botmux 1.0.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 (202) hide show
  1. package/.env.example +24 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +267 -0
  4. package/README.md +267 -0
  5. package/dist/adapters/backend/pty-backend.d.ts +13 -0
  6. package/dist/adapters/backend/pty-backend.d.ts.map +1 -0
  7. package/dist/adapters/backend/pty-backend.js +39 -0
  8. package/dist/adapters/backend/pty-backend.js.map +1 -0
  9. package/dist/adapters/backend/tmux-backend.d.ts +20 -0
  10. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -0
  11. package/dist/adapters/backend/tmux-backend.js +30 -0
  12. package/dist/adapters/backend/tmux-backend.js.map +1 -0
  13. package/dist/adapters/backend/types.d.ts +19 -0
  14. package/dist/adapters/backend/types.d.ts.map +1 -0
  15. package/dist/adapters/backend/types.js +2 -0
  16. package/dist/adapters/backend/types.js.map +1 -0
  17. package/dist/adapters/cli/aiden.d.ts +4 -0
  18. package/dist/adapters/cli/aiden.d.ts.map +1 -0
  19. package/dist/adapters/cli/aiden.js +63 -0
  20. package/dist/adapters/cli/aiden.js.map +1 -0
  21. package/dist/adapters/cli/claude-code.d.ts +4 -0
  22. package/dist/adapters/cli/claude-code.d.ts.map +1 -0
  23. package/dist/adapters/cli/claude-code.js +59 -0
  24. package/dist/adapters/cli/claude-code.js.map +1 -0
  25. package/dist/adapters/cli/coco.d.ts +4 -0
  26. package/dist/adapters/cli/coco.d.ts.map +1 -0
  27. package/dist/adapters/cli/coco.js +46 -0
  28. package/dist/adapters/cli/coco.js.map +1 -0
  29. package/dist/adapters/cli/codex.d.ts +4 -0
  30. package/dist/adapters/cli/codex.d.ts.map +1 -0
  31. package/dist/adapters/cli/codex.js +47 -0
  32. package/dist/adapters/cli/codex.js.map +1 -0
  33. package/dist/adapters/cli/registry.d.ts +13 -0
  34. package/dist/adapters/cli/registry.d.ts.map +1 -0
  35. package/dist/adapters/cli/registry.js +42 -0
  36. package/dist/adapters/cli/registry.js.map +1 -0
  37. package/dist/adapters/cli/types.d.ts +39 -0
  38. package/dist/adapters/cli/types.d.ts.map +1 -0
  39. package/dist/adapters/cli/types.js +2 -0
  40. package/dist/adapters/cli/types.js.map +1 -0
  41. package/dist/cli.d.ts +3 -0
  42. package/dist/cli.d.ts.map +1 -0
  43. package/dist/cli.js +245 -0
  44. package/dist/cli.js.map +1 -0
  45. package/dist/config.d.ts +24 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +39 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/core/command-handler.d.ts +11 -0
  50. package/dist/core/command-handler.d.ts.map +1 -0
  51. package/dist/core/command-handler.js +322 -0
  52. package/dist/core/command-handler.js.map +1 -0
  53. package/dist/core/cost-calculator.d.ts +12 -0
  54. package/dist/core/cost-calculator.d.ts.map +1 -0
  55. package/dist/core/cost-calculator.js +61 -0
  56. package/dist/core/cost-calculator.js.map +1 -0
  57. package/dist/core/scheduler.d.ts +38 -0
  58. package/dist/core/scheduler.d.ts.map +1 -0
  59. package/dist/core/scheduler.js +221 -0
  60. package/dist/core/scheduler.js.map +1 -0
  61. package/dist/core/session-manager.d.ts +13 -0
  62. package/dist/core/session-manager.d.ts.map +1 -0
  63. package/dist/core/session-manager.js +125 -0
  64. package/dist/core/session-manager.js.map +1 -0
  65. package/dist/core/types.d.ts +29 -0
  66. package/dist/core/types.d.ts.map +1 -0
  67. package/dist/core/types.js +2 -0
  68. package/dist/core/types.js.map +1 -0
  69. package/dist/core/worker-pool.d.ts +26 -0
  70. package/dist/core/worker-pool.d.ts.map +1 -0
  71. package/dist/core/worker-pool.js +261 -0
  72. package/dist/core/worker-pool.js.map +1 -0
  73. package/dist/daemon.d.ts +3 -0
  74. package/dist/daemon.d.ts.map +1 -0
  75. package/dist/daemon.js +344 -0
  76. package/dist/daemon.js.map +1 -0
  77. package/dist/im/lark/card-builder.d.ts +18 -0
  78. package/dist/im/lark/card-builder.d.ts.map +1 -0
  79. package/dist/im/lark/card-builder.js +194 -0
  80. package/dist/im/lark/card-builder.js.map +1 -0
  81. package/dist/im/lark/card-handler.d.ts +9 -0
  82. package/dist/im/lark/card-handler.d.ts.map +1 -0
  83. package/dist/im/lark/card-handler.js +131 -0
  84. package/dist/im/lark/card-handler.js.map +1 -0
  85. package/dist/im/lark/client.d.ts +23 -0
  86. package/dist/im/lark/client.d.ts.map +1 -0
  87. package/dist/im/lark/client.js +259 -0
  88. package/dist/im/lark/client.js.map +1 -0
  89. package/dist/im/lark/event-dispatcher.d.ts +34 -0
  90. package/dist/im/lark/event-dispatcher.d.ts.map +1 -0
  91. package/dist/im/lark/event-dispatcher.js +195 -0
  92. package/dist/im/lark/event-dispatcher.js.map +1 -0
  93. package/dist/im/lark/message-parser.d.ts +45 -0
  94. package/dist/im/lark/message-parser.d.ts.map +1 -0
  95. package/dist/im/lark/message-parser.js +132 -0
  96. package/dist/im/lark/message-parser.js.map +1 -0
  97. package/dist/im/types.d.ts +78 -0
  98. package/dist/im/types.d.ts.map +1 -0
  99. package/dist/im/types.js +2 -0
  100. package/dist/im/types.js.map +1 -0
  101. package/dist/index-daemon.d.ts +3 -0
  102. package/dist/index-daemon.d.ts.map +1 -0
  103. package/dist/index-daemon.js +21 -0
  104. package/dist/index-daemon.js.map +1 -0
  105. package/dist/index.d.ts +3 -0
  106. package/dist/index.d.ts.map +1 -0
  107. package/dist/index.js +16 -0
  108. package/dist/index.js.map +1 -0
  109. package/dist/scheduler.d.ts +38 -0
  110. package/dist/scheduler.d.ts.map +1 -0
  111. package/dist/scheduler.js +221 -0
  112. package/dist/scheduler.js.map +1 -0
  113. package/dist/server.d.ts +3 -0
  114. package/dist/server.d.ts.map +1 -0
  115. package/dist/server.js +23 -0
  116. package/dist/server.js.map +1 -0
  117. package/dist/services/lark-client.d.ts +22 -0
  118. package/dist/services/lark-client.d.ts.map +1 -0
  119. package/dist/services/lark-client.js +238 -0
  120. package/dist/services/lark-client.js.map +1 -0
  121. package/dist/services/lark-ws.d.ts +5 -0
  122. package/dist/services/lark-ws.d.ts.map +1 -0
  123. package/dist/services/lark-ws.js +79 -0
  124. package/dist/services/lark-ws.js.map +1 -0
  125. package/dist/services/message-queue.d.ts +9 -0
  126. package/dist/services/message-queue.d.ts.map +1 -0
  127. package/dist/services/message-queue.js +77 -0
  128. package/dist/services/message-queue.js.map +1 -0
  129. package/dist/services/message-router.d.ts +8 -0
  130. package/dist/services/message-router.d.ts.map +1 -0
  131. package/dist/services/message-router.js +73 -0
  132. package/dist/services/message-router.js.map +1 -0
  133. package/dist/services/project-scanner.d.ts +12 -0
  134. package/dist/services/project-scanner.d.ts.map +1 -0
  135. package/dist/services/project-scanner.js +109 -0
  136. package/dist/services/project-scanner.js.map +1 -0
  137. package/dist/services/schedule-store.d.ts +14 -0
  138. package/dist/services/schedule-store.d.ts.map +1 -0
  139. package/dist/services/schedule-store.js +89 -0
  140. package/dist/services/schedule-store.js.map +1 -0
  141. package/dist/services/session-store.d.ts +8 -0
  142. package/dist/services/session-store.d.ts.map +1 -0
  143. package/dist/services/session-store.js +93 -0
  144. package/dist/services/session-store.js.map +1 -0
  145. package/dist/tools/close-session.d.ts +22 -0
  146. package/dist/tools/close-session.d.ts.map +1 -0
  147. package/dist/tools/close-session.js +38 -0
  148. package/dist/tools/close-session.js.map +1 -0
  149. package/dist/tools/create-session.d.ts +28 -0
  150. package/dist/tools/create-session.d.ts.map +1 -0
  151. package/dist/tools/create-session.js +40 -0
  152. package/dist/tools/create-session.js.map +1 -0
  153. package/dist/tools/get-thread-messages.d.ts +26 -0
  154. package/dist/tools/get-thread-messages.d.ts.map +1 -0
  155. package/dist/tools/get-thread-messages.js +33 -0
  156. package/dist/tools/get-thread-messages.js.map +1 -0
  157. package/dist/tools/index.d.ts +9 -0
  158. package/dist/tools/index.d.ts.map +1 -0
  159. package/dist/tools/index.js +10 -0
  160. package/dist/tools/index.js.map +1 -0
  161. package/dist/tools/react-to-message.d.ts +41 -0
  162. package/dist/tools/react-to-message.d.ts.map +1 -0
  163. package/dist/tools/react-to-message.js +30 -0
  164. package/dist/tools/react-to-message.js.map +1 -0
  165. package/dist/tools/send-to-thread.d.ts +24 -0
  166. package/dist/tools/send-to-thread.d.ts.map +1 -0
  167. package/dist/tools/send-to-thread.js +83 -0
  168. package/dist/tools/send-to-thread.js.map +1 -0
  169. package/dist/tools/wait-for-reply.d.ts +17 -0
  170. package/dist/tools/wait-for-reply.d.ts.map +1 -0
  171. package/dist/tools/wait-for-reply.js +65 -0
  172. package/dist/tools/wait-for-reply.js.map +1 -0
  173. package/dist/types.d.ts +85 -0
  174. package/dist/types.d.ts.map +1 -0
  175. package/dist/types.js +6 -0
  176. package/dist/types.js.map +1 -0
  177. package/dist/utils/card-builder.d.ts +16 -0
  178. package/dist/utils/card-builder.d.ts.map +1 -0
  179. package/dist/utils/card-builder.js +183 -0
  180. package/dist/utils/card-builder.js.map +1 -0
  181. package/dist/utils/idle-detector.d.ts +21 -0
  182. package/dist/utils/idle-detector.d.ts.map +1 -0
  183. package/dist/utils/idle-detector.js +95 -0
  184. package/dist/utils/idle-detector.js.map +1 -0
  185. package/dist/utils/logger.d.ts +7 -0
  186. package/dist/utils/logger.d.ts.map +1 -0
  187. package/dist/utils/logger.js +22 -0
  188. package/dist/utils/logger.js.map +1 -0
  189. package/dist/utils/message-parser.d.ts +45 -0
  190. package/dist/utils/message-parser.d.ts.map +1 -0
  191. package/dist/utils/message-parser.js +132 -0
  192. package/dist/utils/message-parser.js.map +1 -0
  193. package/dist/utils/terminal-renderer.d.ts +39 -0
  194. package/dist/utils/terminal-renderer.d.ts.map +1 -0
  195. package/dist/utils/terminal-renderer.js +186 -0
  196. package/dist/utils/terminal-renderer.js.map +1 -0
  197. package/dist/worker.d.ts +3 -0
  198. package/dist/worker.d.ts.map +1 -0
  199. package/dist/worker.js +411 -0
  200. package/dist/worker.js.map +1 -0
  201. package/ecosystem.config.cjs +15 -0
  202. package/package.json +60 -0
@@ -0,0 +1,109 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { readdirSync, statSync } from 'node:fs';
3
+ import { join, basename } from 'node:path';
4
+ import { logger } from '../utils/logger.js';
5
+ function getGitBranch(dir) {
6
+ try {
7
+ return execSync('git rev-parse --abbrev-ref HEAD', { cwd: dir, timeout: 5000, encoding: 'utf-8' }).trim();
8
+ }
9
+ catch {
10
+ return 'unknown';
11
+ }
12
+ }
13
+ function getWorktrees(repoPath) {
14
+ try {
15
+ const output = execSync('git worktree list --porcelain', { cwd: repoPath, timeout: 5000, encoding: 'utf-8' });
16
+ const worktrees = [];
17
+ let currentPath = '';
18
+ let currentBranch = '';
19
+ for (const line of output.split('\n')) {
20
+ if (line.startsWith('worktree ')) {
21
+ currentPath = line.slice('worktree '.length);
22
+ }
23
+ else if (line.startsWith('branch ')) {
24
+ currentBranch = line.slice('branch '.length).replace('refs/heads/', '');
25
+ }
26
+ else if (line === '') {
27
+ // End of a worktree entry — skip the main worktree (same as repoPath)
28
+ if (currentPath && currentPath !== repoPath) {
29
+ worktrees.push({
30
+ name: `${basename(repoPath)}/${basename(currentPath)}`,
31
+ path: currentPath,
32
+ type: 'worktree',
33
+ branch: currentBranch || 'unknown',
34
+ });
35
+ }
36
+ currentPath = '';
37
+ currentBranch = '';
38
+ }
39
+ }
40
+ return worktrees;
41
+ }
42
+ catch {
43
+ return [];
44
+ }
45
+ }
46
+ /**
47
+ * Scan a directory for git repositories and their worktrees.
48
+ * Returns a flat list of all projects found.
49
+ */
50
+ export function scanProjects(baseDir, maxDepth = 3) {
51
+ const projects = [];
52
+ const seen = new Set();
53
+ function walk(dir, depth) {
54
+ if (depth > maxDepth)
55
+ return;
56
+ let entries;
57
+ try {
58
+ entries = readdirSync(dir);
59
+ }
60
+ catch {
61
+ return;
62
+ }
63
+ // Check if this directory is a git repo
64
+ if (entries.includes('.git')) {
65
+ const realPath = dir;
66
+ if (!seen.has(realPath)) {
67
+ seen.add(realPath);
68
+ projects.push({
69
+ name: basename(realPath),
70
+ path: realPath,
71
+ type: 'repo',
72
+ branch: getGitBranch(realPath),
73
+ });
74
+ // Also scan for worktrees
75
+ for (const wt of getWorktrees(realPath)) {
76
+ if (!seen.has(wt.path)) {
77
+ seen.add(wt.path);
78
+ projects.push(wt);
79
+ }
80
+ }
81
+ }
82
+ return; // Don't recurse into git repos
83
+ }
84
+ // Recurse into subdirectories
85
+ for (const entry of entries) {
86
+ if (entry.startsWith('.') || entry === 'node_modules' || entry === 'vendor' || entry === 'dist')
87
+ continue;
88
+ const fullPath = join(dir, entry);
89
+ try {
90
+ if (statSync(fullPath).isDirectory()) {
91
+ walk(fullPath, depth + 1);
92
+ }
93
+ }
94
+ catch {
95
+ // Permission denied or broken symlink
96
+ }
97
+ }
98
+ }
99
+ walk(baseDir, 0);
100
+ // Sort: repos first, then worktrees, alphabetically within each group
101
+ projects.sort((a, b) => {
102
+ if (a.type !== b.type)
103
+ return a.type === 'repo' ? -1 : 1;
104
+ return a.name.localeCompare(b.name);
105
+ });
106
+ logger.info(`Scanned ${baseDir}: found ${projects.length} project(s)`);
107
+ return projects;
108
+ }
109
+ //# sourceMappingURL=project-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-scanner.js","sourceRoot":"","sources":["../../src/services/project-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ScheduledTask } from '../types.js';
2
+ export declare function createTask(params: {
3
+ name: string;
4
+ type: ScheduledTask['type'];
5
+ schedule: string;
6
+ prompt: string;
7
+ workingDir: string;
8
+ chatId: string;
9
+ }): ScheduledTask;
10
+ export declare function getTask(id: string): ScheduledTask | undefined;
11
+ export declare function removeTask(id: string): boolean;
12
+ export declare function updateTask(id: string, updates: Partial<Pick<ScheduledTask, 'enabled' | 'lastRunAt'>>): void;
13
+ export declare function listTasks(): ScheduledTask[];
14
+ //# sourceMappingURL=schedule-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-store.d.ts","sourceRoot":"","sources":["../../src/services/schedule-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA6CjD,wBAAgB,UAAU,CAAC,MAAM,EAAE;IACjC,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,CAiBhB;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAG7D;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAQ9C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,WAAW,CAAC,CAAC,GAAG,IAAI,CAO3G;AAED,wBAAgB,SAAS,IAAI,aAAa,EAAE,CAG3C"}
@@ -0,0 +1,89 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { config } from '../config.js';
5
+ import { logger } from '../utils/logger.js';
6
+ let tasks = new Map();
7
+ let loaded = false;
8
+ function getFilePath() {
9
+ return join(config.session.dataDir, 'schedules.json');
10
+ }
11
+ function ensureDir() {
12
+ const dir = dirname(getFilePath());
13
+ if (!existsSync(dir)) {
14
+ mkdirSync(dir, { recursive: true });
15
+ }
16
+ }
17
+ function load() {
18
+ if (loaded)
19
+ return;
20
+ ensureDir();
21
+ const fp = getFilePath();
22
+ if (existsSync(fp)) {
23
+ try {
24
+ const data = JSON.parse(readFileSync(fp, 'utf-8'));
25
+ tasks = new Map(Object.entries(data));
26
+ logger.info(`Loaded ${tasks.size} scheduled tasks from ${fp}`);
27
+ }
28
+ catch (err) {
29
+ logger.error(`Failed to load schedules: ${err}`);
30
+ tasks = new Map();
31
+ }
32
+ }
33
+ loaded = true;
34
+ }
35
+ function save() {
36
+ ensureDir();
37
+ const fp = getFilePath();
38
+ const tmpFp = fp + '.tmp';
39
+ const obj = {};
40
+ for (const [k, v] of tasks) {
41
+ obj[k] = v;
42
+ }
43
+ writeFileSync(tmpFp, JSON.stringify(obj, null, 2), 'utf-8');
44
+ renameSync(tmpFp, fp);
45
+ }
46
+ export function createTask(params) {
47
+ load();
48
+ const task = {
49
+ id: randomUUID().substring(0, 8),
50
+ name: params.name,
51
+ type: params.type,
52
+ schedule: params.schedule,
53
+ prompt: params.prompt,
54
+ workingDir: params.workingDir,
55
+ chatId: params.chatId,
56
+ enabled: true,
57
+ createdAt: new Date().toISOString(),
58
+ };
59
+ tasks.set(task.id, task);
60
+ save();
61
+ logger.info(`Created scheduled task ${task.id}: "${task.name}" (${task.type}: ${task.schedule})`);
62
+ return task;
63
+ }
64
+ export function getTask(id) {
65
+ load();
66
+ return tasks.get(id);
67
+ }
68
+ export function removeTask(id) {
69
+ load();
70
+ const existed = tasks.delete(id);
71
+ if (existed) {
72
+ save();
73
+ logger.info(`Removed scheduled task ${id}`);
74
+ }
75
+ return existed;
76
+ }
77
+ export function updateTask(id, updates) {
78
+ load();
79
+ const task = tasks.get(id);
80
+ if (task) {
81
+ Object.assign(task, updates);
82
+ save();
83
+ }
84
+ }
85
+ export function listTasks() {
86
+ load();
87
+ return [...tasks.values()];
88
+ }
89
+ //# sourceMappingURL=schedule-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-store.js","sourceRoot":"","sources":["../../src/services/schedule-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Session } from '../types.js';
2
+ export declare function createSession(chatId: string, rootMessageId: string, title: string, chatType?: 'group' | 'p2p'): Session;
3
+ export declare function getSession(sessionId: string): Session | undefined;
4
+ export declare function closeSession(sessionId: string): void;
5
+ export declare function updateSessionPid(sessionId: string, pid: number | null): void;
6
+ export declare function updateSession(session: Session): void;
7
+ export declare function listSessions(): Session[];
8
+ //# sourceMappingURL=session-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/services/session-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA6C3C,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAevH;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAGjE;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CASpD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAO5E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAIpD;AAED,wBAAgB,YAAY,IAAI,OAAO,EAAE,CAGxC"}
@@ -0,0 +1,93 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { config } from '../config.js';
5
+ import { logger } from '../utils/logger.js';
6
+ let sessions = new Map();
7
+ let loaded = false;
8
+ function getFilePath() {
9
+ return join(config.session.dataDir, 'sessions.json');
10
+ }
11
+ function ensureDir() {
12
+ const dir = dirname(getFilePath());
13
+ if (!existsSync(dir)) {
14
+ mkdirSync(dir, { recursive: true });
15
+ }
16
+ }
17
+ function load() {
18
+ if (loaded)
19
+ return;
20
+ ensureDir();
21
+ const fp = getFilePath();
22
+ if (existsSync(fp)) {
23
+ try {
24
+ const data = JSON.parse(readFileSync(fp, 'utf-8'));
25
+ sessions = new Map(Object.entries(data));
26
+ logger.info(`Loaded ${sessions.size} sessions from ${fp}`);
27
+ }
28
+ catch (err) {
29
+ logger.error(`Failed to load sessions: ${err}`);
30
+ sessions = new Map();
31
+ }
32
+ }
33
+ loaded = true;
34
+ }
35
+ function save() {
36
+ ensureDir();
37
+ const fp = getFilePath();
38
+ const tmpFp = fp + '.tmp';
39
+ const obj = {};
40
+ for (const [k, v] of sessions) {
41
+ obj[k] = v;
42
+ }
43
+ writeFileSync(tmpFp, JSON.stringify(obj, null, 2), 'utf-8');
44
+ renameSync(tmpFp, fp);
45
+ }
46
+ export function createSession(chatId, rootMessageId, title, chatType) {
47
+ load();
48
+ const session = {
49
+ sessionId: randomUUID(),
50
+ chatId,
51
+ chatType,
52
+ rootMessageId,
53
+ title,
54
+ status: 'active',
55
+ createdAt: new Date().toISOString(),
56
+ };
57
+ sessions.set(session.sessionId, session);
58
+ save();
59
+ logger.info(`Created session ${session.sessionId} (thread: ${rootMessageId})`);
60
+ return session;
61
+ }
62
+ export function getSession(sessionId) {
63
+ load();
64
+ return sessions.get(sessionId);
65
+ }
66
+ export function closeSession(sessionId) {
67
+ load();
68
+ const session = sessions.get(sessionId);
69
+ if (session) {
70
+ session.status = 'closed';
71
+ session.closedAt = new Date().toISOString();
72
+ save();
73
+ logger.info(`Closed session ${sessionId}`);
74
+ }
75
+ }
76
+ export function updateSessionPid(sessionId, pid) {
77
+ load();
78
+ const session = sessions.get(sessionId);
79
+ if (session) {
80
+ session.pid = pid ?? undefined;
81
+ save();
82
+ }
83
+ }
84
+ export function updateSession(session) {
85
+ load();
86
+ sessions.set(session.sessionId, session);
87
+ save();
88
+ }
89
+ export function listSessions() {
90
+ load();
91
+ return [...sessions.values()];
92
+ }
93
+ //# sourceMappingURL=session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/services/session-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ export declare const schema: z.ZodObject<{
3
+ session_id: z.ZodString;
4
+ closing_message: z.ZodOptional<z.ZodString>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ session_id: string;
7
+ closing_message?: string | undefined;
8
+ }, {
9
+ session_id: string;
10
+ closing_message?: string | undefined;
11
+ }>;
12
+ export declare const description = "Close a session and stop listening for messages in the associated thread.";
13
+ export declare function execute(args: z.infer<typeof schema>): Promise<{
14
+ error: string;
15
+ success?: undefined;
16
+ sessionId?: undefined;
17
+ } | {
18
+ success: boolean;
19
+ sessionId: string;
20
+ error?: undefined;
21
+ }>;
22
+ //# sourceMappingURL=close-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-session.d.ts","sourceRoot":"","sources":["../../src/tools/close-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,MAAM;;;;;;;;;EAGjB,CAAC;AAEH,eAAO,MAAM,WAAW,8EAA8E,CAAC;AAEvG,wBAAsB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC;;;;;;;;GA6BzD"}
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ import { replyMessage } from '../services/lark-client.js';
3
+ import * as sessionStore from '../services/session-store.js';
4
+ import * as messageRouter from '../services/message-router.js';
5
+ import { logger } from '../utils/logger.js';
6
+ export const schema = z.object({
7
+ session_id: z.string().describe('Session ID for the active session'),
8
+ closing_message: z.string().optional().describe('Optional closing message to send before closing'),
9
+ });
10
+ export const description = 'Close a session and stop listening for messages in the associated thread.';
11
+ export async function execute(args) {
12
+ const session = sessionStore.getSession(args.session_id);
13
+ if (!session) {
14
+ return { error: `Session ${args.session_id} not found` };
15
+ }
16
+ if (session.status === 'closed') {
17
+ return { error: `Session ${args.session_id} is already closed` };
18
+ }
19
+ try {
20
+ // Send closing message if provided
21
+ const closingMsg = args.closing_message ?? '🔚 Session closed.';
22
+ await replyMessage(session.rootMessageId, closingMsg);
23
+ // Unregister from message router
24
+ messageRouter.unregister(session.rootMessageId);
25
+ // Mark session as closed
26
+ sessionStore.closeSession(args.session_id);
27
+ logger.info(`Session ${args.session_id} closed`);
28
+ return {
29
+ success: true,
30
+ sessionId: args.session_id,
31
+ };
32
+ }
33
+ catch (err) {
34
+ logger.error(`Failed to close session: ${err.message}`);
35
+ return { error: `Failed to close session: ${err.message}` };
36
+ }
37
+ }
38
+ //# sourceMappingURL=close-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-session.js","sourceRoot":"","sources":["../../src/tools/close-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,YAAY,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,aAAa,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;CACnG,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,2EAA2E,CAAC;AAEvG,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAA4B;IACxD,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC,UAAU,YAAY,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC,UAAU,oBAAoB,EAAE,CAAC;IACnE,CAAC;IAED,IAAI,CAAC;QACH,mCAAmC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,IAAI,oBAAoB,CAAC;QAChE,MAAM,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAEtD,iCAAiC;QACjC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAEhD,yBAAyB;QACzB,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE3C,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,SAAS,CAAC,CAAC;QACjD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,4BAA4B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,OAAO,EAAE,KAAK,EAAE,4BAA4B,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ export declare const schema: z.ZodObject<{
3
+ title: z.ZodString;
4
+ chat_id: z.ZodOptional<z.ZodString>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ title: string;
7
+ chat_id?: string | undefined;
8
+ }, {
9
+ title: string;
10
+ chat_id?: string | undefined;
11
+ }>;
12
+ export declare const description = "Create a new session by starting a thread in the Lark topic group. Returns session ID and thread info.";
13
+ export declare function execute(args: z.infer<typeof schema>): Promise<{
14
+ error: string;
15
+ sessionId?: undefined;
16
+ threadId?: undefined;
17
+ chatId?: undefined;
18
+ title?: undefined;
19
+ status?: undefined;
20
+ } | {
21
+ sessionId: string;
22
+ threadId: string;
23
+ chatId: string;
24
+ title: string;
25
+ status: string;
26
+ error?: undefined;
27
+ }>;
28
+ //# sourceMappingURL=create-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-session.d.ts","sourceRoot":"","sources":["../../src/tools/create-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,MAAM;;;;;;;;;EAGjB,CAAC;AAEH,eAAO,MAAM,WAAW,2GAA2G,CAAC;AAEpI,wBAAsB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC;;;;;;;;;;;;;;GAgCzD"}
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ import { config } from '../config.js';
3
+ import { sendMessage, replyMessage } from '../services/lark-client.js';
4
+ import * as sessionStore from '../services/session-store.js';
5
+ import * as messageRouter from '../services/message-router.js';
6
+ import { logger } from '../utils/logger.js';
7
+ export const schema = z.object({
8
+ title: z.string().describe('Title for the thread/session'),
9
+ chat_id: z.string().optional().describe('Chat ID of the topic group. Defaults to LARK_DEFAULT_CHAT_ID'),
10
+ });
11
+ export const description = 'Create a new session by starting a thread in the Lark topic group. Returns session ID and thread info.';
12
+ export async function execute(args) {
13
+ const chatId = args.chat_id || config.lark.defaultChatId;
14
+ if (!chatId) {
15
+ return { error: 'No chat_id provided and LARK_DEFAULT_CHAT_ID not set' };
16
+ }
17
+ try {
18
+ // Send root message to create the thread
19
+ const rootMessageId = await sendMessage(chatId, `🤖 ${args.title}`);
20
+ // Reply to root message to initialize the thread
21
+ await replyMessage(rootMessageId, `Session started. Claude Code is connected.`);
22
+ // Register in message router for real-time message reception
23
+ messageRouter.register(rootMessageId);
24
+ // Persist session
25
+ const session = sessionStore.createSession(chatId, rootMessageId, args.title);
26
+ logger.info(`Session created: ${session.sessionId}, thread root: ${rootMessageId}`);
27
+ return {
28
+ sessionId: session.sessionId,
29
+ threadId: rootMessageId,
30
+ chatId,
31
+ title: args.title,
32
+ status: 'active',
33
+ };
34
+ }
35
+ catch (err) {
36
+ logger.error(`Failed to create session: ${err.message}`);
37
+ return { error: `Failed to create session: ${err.message}` };
38
+ }
39
+ }
40
+ //# sourceMappingURL=create-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-session.js","sourceRoot":"","sources":["../../src/tools/create-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,YAAY,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,aAAa,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IAC1D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;CACxG,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,wGAAwG,CAAC;AAEpI,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAA4B;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;IACzD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,sDAAsD,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,CAAC;QACH,yCAAyC;QACzC,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAEpE,iDAAiD;QACjD,MAAM,YAAY,CAAC,aAAa,EAAE,4CAA4C,CAAC,CAAC;QAEhF,6DAA6D;QAC7D,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEtC,kBAAkB;QAClB,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAE9E,MAAM,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,SAAS,kBAAkB,aAAa,EAAE,CAAC,CAAC;QAEpF,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,aAAa;YACvB,MAAM;YACN,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,6BAA6B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzD,OAAO,EAAE,KAAK,EAAE,6BAA6B,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;IAC/D,CAAC;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ export declare const schema: z.ZodObject<{
3
+ session_id: z.ZodString;
4
+ limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ session_id: string;
7
+ limit: number;
8
+ }, {
9
+ session_id: string;
10
+ limit?: number | undefined;
11
+ }>;
12
+ export declare const description = "Get message history from the Lark thread associated with a session.";
13
+ export declare function execute(args: z.infer<typeof schema>): Promise<{
14
+ error: string;
15
+ sessionId?: undefined;
16
+ threadId?: undefined;
17
+ messages?: undefined;
18
+ total?: undefined;
19
+ } | {
20
+ sessionId: string;
21
+ threadId: string;
22
+ messages: import("../types.js").LarkMessage[];
23
+ total: number;
24
+ error?: undefined;
25
+ }>;
26
+ //# sourceMappingURL=get-thread-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-thread-messages.d.ts","sourceRoot":"","sources":["../../src/tools/get-thread-messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,MAAM;;;;;;;;;EAGjB,CAAC;AAEH,eAAO,MAAM,WAAW,wEAAwE,CAAC;AAEjG,wBAAsB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC;;;;;;;;;;;;GAsBzD"}
@@ -0,0 +1,33 @@
1
+ import { z } from 'zod';
2
+ import * as sessionStore from '../services/session-store.js';
3
+ import { listThreadMessages } from '../im/lark/client.js';
4
+ import { parseApiMessage } from '../im/lark/message-parser.js';
5
+ import { logger } from '../utils/logger.js';
6
+ export const schema = z.object({
7
+ session_id: z.string().describe('Session ID for the active session'),
8
+ limit: z.number().optional().default(50).describe('Max number of messages to return (default 50)'),
9
+ });
10
+ export const description = 'Get message history from the Lark thread associated with a session.';
11
+ export async function execute(args) {
12
+ const session = sessionStore.getSession(args.session_id);
13
+ if (!session) {
14
+ return { error: `Session ${args.session_id} not found` };
15
+ }
16
+ try {
17
+ // List chat messages and filter by root_id to get thread messages
18
+ const rawMessages = await listThreadMessages(session.chatId, session.rootMessageId, args.limit);
19
+ const messages = rawMessages.map(parseApiMessage);
20
+ logger.info(`Retrieved ${messages.length} messages for session ${args.session_id}`);
21
+ return {
22
+ sessionId: args.session_id,
23
+ threadId: session.rootMessageId,
24
+ messages,
25
+ total: messages.length,
26
+ };
27
+ }
28
+ catch (err) {
29
+ logger.error(`Failed to get thread messages: ${err.message}`);
30
+ return { error: `Failed to get messages: ${err.message}` };
31
+ }
32
+ }
33
+ //# sourceMappingURL=get-thread-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-thread-messages.js","sourceRoot":"","sources":["../../src/tools/get-thread-messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,YAAY,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,+CAA+C,CAAC;CACnG,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,qEAAqE,CAAC;AAEjG,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAA4B;IACxD,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC,UAAU,YAAY,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,CAAC;QACH,kEAAkE;QAClE,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAElD,MAAM,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,MAAM,yBAAyB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACpF,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,QAAQ,EAAE,OAAO,CAAC,aAAa;YAC/B,QAAQ;YACR,KAAK,EAAE,QAAQ,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,kCAAkC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,OAAO,EAAE,KAAK,EAAE,2BAA2B,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;IAC7D,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import * as sendToThread from './send-to-thread.js';
2
+ import * as getThreadMessages from './get-thread-messages.js';
3
+ import * as reactToMessage from './react-to-message.js';
4
+ export declare const tools: {
5
+ readonly send_to_thread: typeof sendToThread;
6
+ readonly get_thread_messages: typeof getThreadMessages;
7
+ readonly react_to_message: typeof reactToMessage;
8
+ };
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AAExD,eAAO,MAAM,KAAK;;;;CAIR,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { TOOL_NAMES } from '../types.js';
2
+ import * as sendToThread from './send-to-thread.js';
3
+ import * as getThreadMessages from './get-thread-messages.js';
4
+ import * as reactToMessage from './react-to-message.js';
5
+ export const tools = {
6
+ [TOOL_NAMES.SEND_TO_THREAD]: sendToThread,
7
+ [TOOL_NAMES.GET_THREAD_MESSAGES]: getThreadMessages,
8
+ [TOOL_NAMES.REACT_TO_MESSAGE]: reactToMessage,
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AAExD,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,YAAY;IACzC,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,iBAAiB;IACnD,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,cAAc;CACrC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ export declare const schema: z.ZodObject<{
3
+ message_id: z.ZodString;
4
+ emoji_type: z.ZodDefault<z.ZodString>;
5
+ action: z.ZodDefault<z.ZodEnum<["add", "remove"]>>;
6
+ reaction_id: z.ZodOptional<z.ZodString>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ action: "add" | "remove";
9
+ message_id: string;
10
+ emoji_type: string;
11
+ reaction_id?: string | undefined;
12
+ }, {
13
+ message_id: string;
14
+ action?: "add" | "remove" | undefined;
15
+ emoji_type?: string | undefined;
16
+ reaction_id?: string | undefined;
17
+ }>;
18
+ export declare const description = "Add or remove an emoji reaction on a message. Use \"add\" with OnIt when starting to process, then \"remove\" after responding.";
19
+ export declare function execute(args: z.infer<typeof schema>): Promise<{
20
+ success: boolean;
21
+ reactionId: string;
22
+ messageId: string;
23
+ emoji: string;
24
+ error?: undefined;
25
+ removed?: undefined;
26
+ } | {
27
+ error: string;
28
+ success?: undefined;
29
+ reactionId?: undefined;
30
+ messageId?: undefined;
31
+ emoji?: undefined;
32
+ removed?: undefined;
33
+ } | {
34
+ success: boolean;
35
+ messageId: string;
36
+ removed: string;
37
+ reactionId?: undefined;
38
+ emoji?: undefined;
39
+ error?: undefined;
40
+ }>;
41
+ //# sourceMappingURL=react-to-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-to-message.d.ts","sourceRoot":"","sources":["../../src/tools/react-to-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;EAKjB,CAAC;AAEH,eAAO,MAAM,WAAW,oIAAgI,CAAC;AAEzJ,wBAAsB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;GAgBzD"}