remoat 0.2.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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +297 -0
  3. package/dist/bin/cli.d.ts +2 -0
  4. package/dist/bin/cli.js +80 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/bin/commands/doctor.d.ts +1 -0
  7. package/dist/bin/commands/doctor.js +211 -0
  8. package/dist/bin/commands/doctor.js.map +1 -0
  9. package/dist/bin/commands/open.d.ts +1 -0
  10. package/dist/bin/commands/open.js +187 -0
  11. package/dist/bin/commands/open.js.map +1 -0
  12. package/dist/bin/commands/setup.d.ts +1 -0
  13. package/dist/bin/commands/setup.js +267 -0
  14. package/dist/bin/commands/setup.js.map +1 -0
  15. package/dist/bin/commands/start.d.ts +2 -0
  16. package/dist/bin/commands/start.js +39 -0
  17. package/dist/bin/commands/start.js.map +1 -0
  18. package/dist/bot/index.d.ts +2 -0
  19. package/dist/bot/index.js +1393 -0
  20. package/dist/bot/index.js.map +1 -0
  21. package/dist/commands/chatCommandHandler.d.ts +20 -0
  22. package/dist/commands/chatCommandHandler.js +30 -0
  23. package/dist/commands/chatCommandHandler.js.map +1 -0
  24. package/dist/commands/cleanupCommandHandler.d.ts +21 -0
  25. package/dist/commands/cleanupCommandHandler.js +40 -0
  26. package/dist/commands/cleanupCommandHandler.js.map +1 -0
  27. package/dist/commands/joinCommandHandler.d.ts +19 -0
  28. package/dist/commands/joinCommandHandler.js +27 -0
  29. package/dist/commands/joinCommandHandler.js.map +1 -0
  30. package/dist/commands/messageParser.d.ts +7 -0
  31. package/dist/commands/messageParser.js +29 -0
  32. package/dist/commands/messageParser.js.map +1 -0
  33. package/dist/commands/slashCommandHandler.d.ts +21 -0
  34. package/dist/commands/slashCommandHandler.js +105 -0
  35. package/dist/commands/slashCommandHandler.js.map +1 -0
  36. package/dist/commands/workspaceCommandHandler.d.ts +16 -0
  37. package/dist/commands/workspaceCommandHandler.js +29 -0
  38. package/dist/commands/workspaceCommandHandler.js.map +1 -0
  39. package/dist/database/chatSessionRepository.d.ts +59 -0
  40. package/dist/database/chatSessionRepository.js +110 -0
  41. package/dist/database/chatSessionRepository.js.map +1 -0
  42. package/dist/database/scheduleRepository.d.ts +60 -0
  43. package/dist/database/scheduleRepository.js +106 -0
  44. package/dist/database/scheduleRepository.js.map +1 -0
  45. package/dist/database/templateRepository.d.ts +51 -0
  46. package/dist/database/templateRepository.js +90 -0
  47. package/dist/database/templateRepository.js.map +1 -0
  48. package/dist/database/workspaceBindingRepository.d.ts +48 -0
  49. package/dist/database/workspaceBindingRepository.js +92 -0
  50. package/dist/database/workspaceBindingRepository.js.map +1 -0
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +11 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/middleware/auth.d.ts +5 -0
  55. package/dist/middleware/auth.js +14 -0
  56. package/dist/middleware/auth.js.map +1 -0
  57. package/dist/middleware/sanitize.d.ts +1 -0
  58. package/dist/middleware/sanitize.js +18 -0
  59. package/dist/middleware/sanitize.js.map +1 -0
  60. package/dist/services/antigravityLauncher.d.ts +7 -0
  61. package/dist/services/antigravityLauncher.js +94 -0
  62. package/dist/services/antigravityLauncher.js.map +1 -0
  63. package/dist/services/approvalDetector.d.ts +97 -0
  64. package/dist/services/approvalDetector.js +394 -0
  65. package/dist/services/approvalDetector.js.map +1 -0
  66. package/dist/services/assistantDomExtractor.d.ts +49 -0
  67. package/dist/services/assistantDomExtractor.js +340 -0
  68. package/dist/services/assistantDomExtractor.js.map +1 -0
  69. package/dist/services/autoAcceptService.d.ts +14 -0
  70. package/dist/services/autoAcceptService.js +81 -0
  71. package/dist/services/autoAcceptService.js.map +1 -0
  72. package/dist/services/cdpBridgeManager.d.ts +50 -0
  73. package/dist/services/cdpBridgeManager.js +355 -0
  74. package/dist/services/cdpBridgeManager.js.map +1 -0
  75. package/dist/services/cdpConnectionPool.d.ts +88 -0
  76. package/dist/services/cdpConnectionPool.js +235 -0
  77. package/dist/services/cdpConnectionPool.js.map +1 -0
  78. package/dist/services/cdpService.d.ts +214 -0
  79. package/dist/services/cdpService.js +1423 -0
  80. package/dist/services/cdpService.js.map +1 -0
  81. package/dist/services/chatSessionService.d.ts +89 -0
  82. package/dist/services/chatSessionService.js +738 -0
  83. package/dist/services/chatSessionService.js.map +1 -0
  84. package/dist/services/errorPopupDetector.d.ts +89 -0
  85. package/dist/services/errorPopupDetector.js +274 -0
  86. package/dist/services/errorPopupDetector.js.map +1 -0
  87. package/dist/services/modeService.d.ts +44 -0
  88. package/dist/services/modeService.js +74 -0
  89. package/dist/services/modeService.js.map +1 -0
  90. package/dist/services/modelService.d.ts +36 -0
  91. package/dist/services/modelService.js +64 -0
  92. package/dist/services/modelService.js.map +1 -0
  93. package/dist/services/planningDetector.d.ts +87 -0
  94. package/dist/services/planningDetector.js +321 -0
  95. package/dist/services/planningDetector.js.map +1 -0
  96. package/dist/services/processManager.d.ts +18 -0
  97. package/dist/services/processManager.js +62 -0
  98. package/dist/services/processManager.js.map +1 -0
  99. package/dist/services/progressSender.d.ts +20 -0
  100. package/dist/services/progressSender.js +65 -0
  101. package/dist/services/progressSender.js.map +1 -0
  102. package/dist/services/promptDispatcher.d.ts +38 -0
  103. package/dist/services/promptDispatcher.js +42 -0
  104. package/dist/services/promptDispatcher.js.map +1 -0
  105. package/dist/services/quotaService.d.ts +21 -0
  106. package/dist/services/quotaService.js +191 -0
  107. package/dist/services/quotaService.js.map +1 -0
  108. package/dist/services/responseMonitor.d.ts +129 -0
  109. package/dist/services/responseMonitor.js +996 -0
  110. package/dist/services/responseMonitor.js.map +1 -0
  111. package/dist/services/scheduleService.d.ts +58 -0
  112. package/dist/services/scheduleService.js +135 -0
  113. package/dist/services/scheduleService.js.map +1 -0
  114. package/dist/services/screenshotService.d.ts +55 -0
  115. package/dist/services/screenshotService.js +86 -0
  116. package/dist/services/screenshotService.js.map +1 -0
  117. package/dist/services/telegramTopicManager.d.ts +40 -0
  118. package/dist/services/telegramTopicManager.js +103 -0
  119. package/dist/services/telegramTopicManager.js.map +1 -0
  120. package/dist/services/titleGeneratorService.d.ts +32 -0
  121. package/dist/services/titleGeneratorService.js +114 -0
  122. package/dist/services/titleGeneratorService.js.map +1 -0
  123. package/dist/services/updateCheckService.d.ts +16 -0
  124. package/dist/services/updateCheckService.js +148 -0
  125. package/dist/services/updateCheckService.js.map +1 -0
  126. package/dist/services/userMessageDetector.d.ts +57 -0
  127. package/dist/services/userMessageDetector.js +222 -0
  128. package/dist/services/userMessageDetector.js.map +1 -0
  129. package/dist/services/workspaceService.d.ts +33 -0
  130. package/dist/services/workspaceService.js +65 -0
  131. package/dist/services/workspaceService.js.map +1 -0
  132. package/dist/ui/autoAcceptUi.d.ts +6 -0
  133. package/dist/ui/autoAcceptUi.js +22 -0
  134. package/dist/ui/autoAcceptUi.js.map +1 -0
  135. package/dist/ui/modeUi.d.ts +12 -0
  136. package/dist/ui/modeUi.js +40 -0
  137. package/dist/ui/modeUi.js.map +1 -0
  138. package/dist/ui/modelsUi.d.ts +12 -0
  139. package/dist/ui/modelsUi.js +101 -0
  140. package/dist/ui/modelsUi.js.map +1 -0
  141. package/dist/ui/projectListUi.d.ts +11 -0
  142. package/dist/ui/projectListUi.js +59 -0
  143. package/dist/ui/projectListUi.js.map +1 -0
  144. package/dist/ui/screenshotUi.d.ts +6 -0
  145. package/dist/ui/screenshotUi.js +28 -0
  146. package/dist/ui/screenshotUi.js.map +1 -0
  147. package/dist/ui/sessionPickerUi.d.ts +8 -0
  148. package/dist/ui/sessionPickerUi.js +32 -0
  149. package/dist/ui/sessionPickerUi.js.map +1 -0
  150. package/dist/ui/templateUi.d.ts +5 -0
  151. package/dist/ui/templateUi.js +44 -0
  152. package/dist/ui/templateUi.js.map +1 -0
  153. package/dist/utils/cdpPorts.d.ts +2 -0
  154. package/dist/utils/cdpPorts.js +6 -0
  155. package/dist/utils/cdpPorts.js.map +1 -0
  156. package/dist/utils/config.d.ts +14 -0
  157. package/dist/utils/config.js +12 -0
  158. package/dist/utils/config.js.map +1 -0
  159. package/dist/utils/configLoader.d.ts +23 -0
  160. package/dist/utils/configLoader.js +153 -0
  161. package/dist/utils/configLoader.js.map +1 -0
  162. package/dist/utils/htmlToTelegramMarkdown.d.ts +6 -0
  163. package/dist/utils/htmlToTelegramMarkdown.js +189 -0
  164. package/dist/utils/htmlToTelegramMarkdown.js.map +1 -0
  165. package/dist/utils/i18n.d.ts +3 -0
  166. package/dist/utils/i18n.js +78 -0
  167. package/dist/utils/i18n.js.map +1 -0
  168. package/dist/utils/imageHandler.d.ts +35 -0
  169. package/dist/utils/imageHandler.js +155 -0
  170. package/dist/utils/imageHandler.js.map +1 -0
  171. package/dist/utils/lockfile.d.ts +7 -0
  172. package/dist/utils/lockfile.js +117 -0
  173. package/dist/utils/lockfile.js.map +1 -0
  174. package/dist/utils/logger.d.ts +23 -0
  175. package/dist/utils/logger.js +85 -0
  176. package/dist/utils/logger.js.map +1 -0
  177. package/dist/utils/logo.d.ts +1 -0
  178. package/dist/utils/logo.js +14 -0
  179. package/dist/utils/logo.js.map +1 -0
  180. package/dist/utils/metadataExtractor.d.ts +5 -0
  181. package/dist/utils/metadataExtractor.js +16 -0
  182. package/dist/utils/metadataExtractor.js.map +1 -0
  183. package/dist/utils/pathUtils.d.ts +23 -0
  184. package/dist/utils/pathUtils.js +58 -0
  185. package/dist/utils/pathUtils.js.map +1 -0
  186. package/dist/utils/processLogBuffer.d.ts +17 -0
  187. package/dist/utils/processLogBuffer.js +108 -0
  188. package/dist/utils/processLogBuffer.js.map +1 -0
  189. package/dist/utils/streamMessageFormatter.d.ts +18 -0
  190. package/dist/utils/streamMessageFormatter.js +91 -0
  191. package/dist/utils/streamMessageFormatter.js.map +1 -0
  192. package/dist/utils/telegramFormatter.d.ts +37 -0
  193. package/dist/utils/telegramFormatter.js +445 -0
  194. package/dist/utils/telegramFormatter.js.map +1 -0
  195. package/dist/utils/voiceHandler.d.ts +23 -0
  196. package/dist/utils/voiceHandler.js +169 -0
  197. package/dist/utils/voiceHandler.js.map +1 -0
  198. package/locales/en.json +85 -0
  199. package/locales/ja.json +109 -0
  200. package/package.json +84 -0
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChatSessionRepository = void 0;
4
+ /**
5
+ * Repository for persisting chat-to-session mapping in SQLite.
6
+ * One session per channel (UNIQUE constraint).
7
+ */
8
+ class ChatSessionRepository {
9
+ db;
10
+ // Cached prepared statements
11
+ stmtCreate;
12
+ stmtFindByChannelId;
13
+ stmtFindByCategoryId;
14
+ stmtGetNextSessionNumber;
15
+ stmtUpdateDisplayName;
16
+ stmtFindByDisplayName;
17
+ stmtDeleteByChannelId;
18
+ constructor(db) {
19
+ this.db = db;
20
+ this.initialize();
21
+ this.stmtCreate = this.db.prepare('INSERT INTO chat_sessions (channel_id, category_id, workspace_path, session_number, guild_id) VALUES (?, ?, ?, ?, ?)');
22
+ this.stmtFindByChannelId = this.db.prepare('SELECT * FROM chat_sessions WHERE channel_id = ?');
23
+ this.stmtFindByCategoryId = this.db.prepare('SELECT * FROM chat_sessions WHERE category_id = ? ORDER BY session_number ASC');
24
+ this.stmtGetNextSessionNumber = this.db.prepare('SELECT MAX(session_number) as max_num FROM chat_sessions WHERE category_id = ?');
25
+ this.stmtUpdateDisplayName = this.db.prepare('UPDATE chat_sessions SET display_name = ?, is_renamed = 1 WHERE channel_id = ?');
26
+ this.stmtFindByDisplayName = this.db.prepare('SELECT * FROM chat_sessions WHERE workspace_path = ? AND display_name = ? ORDER BY id DESC LIMIT 1');
27
+ this.stmtDeleteByChannelId = this.db.prepare('DELETE FROM chat_sessions WHERE channel_id = ?');
28
+ }
29
+ initialize() {
30
+ this.db.exec(`
31
+ CREATE TABLE IF NOT EXISTS chat_sessions (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ channel_id TEXT NOT NULL UNIQUE,
34
+ category_id TEXT NOT NULL,
35
+ workspace_path TEXT NOT NULL,
36
+ session_number INTEGER NOT NULL,
37
+ display_name TEXT,
38
+ is_renamed INTEGER NOT NULL DEFAULT 0,
39
+ guild_id TEXT NOT NULL,
40
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
41
+ )
42
+ `);
43
+ }
44
+ create(input) {
45
+ const result = this.stmtCreate.run(input.channelId, input.categoryId, input.workspacePath, input.sessionNumber, input.guildId);
46
+ return {
47
+ id: result.lastInsertRowid,
48
+ channelId: input.channelId,
49
+ categoryId: input.categoryId,
50
+ workspacePath: input.workspacePath,
51
+ sessionNumber: input.sessionNumber,
52
+ displayName: null,
53
+ isRenamed: false,
54
+ guildId: input.guildId,
55
+ };
56
+ }
57
+ findByChannelId(channelId) {
58
+ const row = this.stmtFindByChannelId.get(channelId);
59
+ if (!row)
60
+ return undefined;
61
+ return this.mapRow(row);
62
+ }
63
+ findByCategoryId(categoryId) {
64
+ const rows = this.stmtFindByCategoryId.all(categoryId);
65
+ return rows.map(row => this.mapRow(row));
66
+ }
67
+ /**
68
+ * Get the next session number within a category (MAX + 1, or 1 if none)
69
+ */
70
+ getNextSessionNumber(categoryId) {
71
+ const row = this.stmtGetNextSessionNumber.get(categoryId);
72
+ return (row?.max_num ?? 0) + 1;
73
+ }
74
+ /**
75
+ * Update session display name and set is_renamed to true
76
+ */
77
+ updateDisplayName(channelId, displayName) {
78
+ const result = this.stmtUpdateDisplayName.run(displayName, channelId);
79
+ return result.changes > 0;
80
+ }
81
+ /**
82
+ * Find a session by display name within a workspace.
83
+ * Returns the first match (most recent).
84
+ */
85
+ findByDisplayName(workspacePath, displayName) {
86
+ const row = this.stmtFindByDisplayName.get(workspacePath, displayName);
87
+ if (!row)
88
+ return undefined;
89
+ return this.mapRow(row);
90
+ }
91
+ deleteByChannelId(channelId) {
92
+ const result = this.stmtDeleteByChannelId.run(channelId);
93
+ return result.changes > 0;
94
+ }
95
+ mapRow(row) {
96
+ return {
97
+ id: row.id,
98
+ channelId: row.channel_id,
99
+ categoryId: row.category_id,
100
+ workspacePath: row.workspace_path,
101
+ sessionNumber: row.session_number,
102
+ displayName: row.display_name,
103
+ isRenamed: row.is_renamed === 1,
104
+ guildId: row.guild_id,
105
+ createdAt: row.created_at,
106
+ };
107
+ }
108
+ }
109
+ exports.ChatSessionRepository = ChatSessionRepository;
110
+ //# sourceMappingURL=chatSessionRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatSessionRepository.js","sourceRoot":"","sources":["../../src/database/chatSessionRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import Database from 'better-sqlite3';
2
+ /**
3
+ * Schedule record type definition
4
+ */
5
+ export interface ScheduleRecord {
6
+ /** Unique ID (auto-increment) */
7
+ id: number;
8
+ /** Cron expression (e.g. "0 9 * * *") */
9
+ cronExpression: string;
10
+ /** Prompt to execute */
11
+ prompt: string;
12
+ /** Target workspace path */
13
+ workspacePath: string;
14
+ /** Enabled/disabled */
15
+ enabled: boolean;
16
+ /** Creation timestamp (ISO string) */
17
+ createdAt?: string;
18
+ }
19
+ /**
20
+ * Input type for schedule creation
21
+ */
22
+ export interface CreateScheduleInput {
23
+ cronExpression: string;
24
+ prompt: string;
25
+ workspacePath: string;
26
+ enabled: boolean;
27
+ }
28
+ /**
29
+ * Input type for schedule update (partial update)
30
+ */
31
+ export interface UpdateScheduleInput {
32
+ cronExpression?: string;
33
+ prompt?: string;
34
+ workspacePath?: string;
35
+ enabled?: boolean;
36
+ }
37
+ /**
38
+ * Repository class for SQLite persistence of scheduled jobs.
39
+ * Handles saving, retrieving, updating, and deleting cron expressions and prompts.
40
+ */
41
+ export declare class ScheduleRepository {
42
+ private readonly db;
43
+ private readonly stmtCreate;
44
+ private readonly stmtFindAll;
45
+ private readonly stmtFindById;
46
+ private readonly stmtFindEnabled;
47
+ private readonly stmtDelete;
48
+ constructor(db: Database.Database);
49
+ private initialize;
50
+ create(input: CreateScheduleInput): ScheduleRecord;
51
+ findAll(): ScheduleRecord[];
52
+ findById(id: number): ScheduleRecord | undefined;
53
+ findEnabled(): ScheduleRecord[];
54
+ delete(id: number): boolean;
55
+ /**
56
+ * Partially update a schedule
57
+ */
58
+ update(id: number, input: UpdateScheduleInput): boolean;
59
+ private mapRow;
60
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScheduleRepository = void 0;
4
+ /**
5
+ * Repository class for SQLite persistence of scheduled jobs.
6
+ * Handles saving, retrieving, updating, and deleting cron expressions and prompts.
7
+ */
8
+ class ScheduleRepository {
9
+ db;
10
+ // Cached prepared statements
11
+ stmtCreate;
12
+ stmtFindAll;
13
+ stmtFindById;
14
+ stmtFindEnabled;
15
+ stmtDelete;
16
+ constructor(db) {
17
+ this.db = db;
18
+ this.initialize();
19
+ this.stmtCreate = this.db.prepare('INSERT INTO schedules (cron_expression, prompt, workspace_path, enabled) VALUES (?, ?, ?, ?)');
20
+ this.stmtFindAll = this.db.prepare('SELECT * FROM schedules ORDER BY id ASC');
21
+ this.stmtFindById = this.db.prepare('SELECT * FROM schedules WHERE id = ?');
22
+ this.stmtFindEnabled = this.db.prepare('SELECT * FROM schedules WHERE enabled = 1 ORDER BY id ASC');
23
+ this.stmtDelete = this.db.prepare('DELETE FROM schedules WHERE id = ?');
24
+ }
25
+ initialize() {
26
+ this.db.exec(`
27
+ CREATE TABLE IF NOT EXISTS schedules (
28
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
29
+ cron_expression TEXT NOT NULL,
30
+ prompt TEXT NOT NULL,
31
+ workspace_path TEXT NOT NULL,
32
+ enabled INTEGER NOT NULL DEFAULT 1,
33
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
34
+ )
35
+ `);
36
+ }
37
+ create(input) {
38
+ const result = this.stmtCreate.run(input.cronExpression, input.prompt, input.workspacePath, input.enabled ? 1 : 0);
39
+ return {
40
+ id: result.lastInsertRowid,
41
+ cronExpression: input.cronExpression,
42
+ prompt: input.prompt,
43
+ workspacePath: input.workspacePath,
44
+ enabled: input.enabled,
45
+ };
46
+ }
47
+ findAll() {
48
+ const rows = this.stmtFindAll.all();
49
+ return rows.map(this.mapRow);
50
+ }
51
+ findById(id) {
52
+ const row = this.stmtFindById.get(id);
53
+ if (!row)
54
+ return undefined;
55
+ return this.mapRow(row);
56
+ }
57
+ findEnabled() {
58
+ const rows = this.stmtFindEnabled.all();
59
+ return rows.map(this.mapRow);
60
+ }
61
+ delete(id) {
62
+ const result = this.stmtDelete.run(id);
63
+ return result.changes > 0;
64
+ }
65
+ /**
66
+ * Partially update a schedule
67
+ */
68
+ update(id, input) {
69
+ const sets = [];
70
+ const values = [];
71
+ if (input.cronExpression !== undefined) {
72
+ sets.push('cron_expression = ?');
73
+ values.push(input.cronExpression);
74
+ }
75
+ if (input.prompt !== undefined) {
76
+ sets.push('prompt = ?');
77
+ values.push(input.prompt);
78
+ }
79
+ if (input.workspacePath !== undefined) {
80
+ sets.push('workspace_path = ?');
81
+ values.push(input.workspacePath);
82
+ }
83
+ if (input.enabled !== undefined) {
84
+ sets.push('enabled = ?');
85
+ values.push(input.enabled ? 1 : 0);
86
+ }
87
+ if (sets.length === 0)
88
+ return false;
89
+ values.push(id);
90
+ const sql = `UPDATE schedules SET ${sets.join(', ')} WHERE id = ?`;
91
+ const result = this.db.prepare(sql).run(...values);
92
+ return result.changes > 0;
93
+ }
94
+ mapRow(row) {
95
+ return {
96
+ id: row.id,
97
+ cronExpression: row.cron_expression,
98
+ prompt: row.prompt,
99
+ workspacePath: row.workspace_path,
100
+ enabled: row.enabled === 1,
101
+ createdAt: row.created_at,
102
+ };
103
+ }
104
+ }
105
+ exports.ScheduleRepository = ScheduleRepository;
106
+ //# sourceMappingURL=scheduleRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduleRepository.js","sourceRoot":"","sources":["../../src/database/scheduleRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import Database from 'better-sqlite3';
2
+ /**
3
+ * Template record type definition
4
+ */
5
+ export interface TemplateRecord {
6
+ /** Unique ID (auto-increment) */
7
+ id: number;
8
+ /** Template name (unique) */
9
+ name: string;
10
+ /** Prompt to execute */
11
+ prompt: string;
12
+ /** Creation timestamp (ISO string) */
13
+ createdAt?: string;
14
+ }
15
+ /**
16
+ * Input type for template creation
17
+ */
18
+ export interface CreateTemplateInput {
19
+ name: string;
20
+ prompt: string;
21
+ }
22
+ /**
23
+ * Input type for template update (partial update)
24
+ */
25
+ export interface UpdateTemplateInput {
26
+ prompt?: string;
27
+ }
28
+ /**
29
+ * Repository class for SQLite persistence of frequently used prompt templates.
30
+ * Handles template creation, retrieval, updating, and deletion.
31
+ */
32
+ export declare class TemplateRepository {
33
+ private readonly db;
34
+ private readonly stmtCreate;
35
+ private readonly stmtFindAll;
36
+ private readonly stmtFindById;
37
+ private readonly stmtFindByName;
38
+ private readonly stmtDeleteByName;
39
+ constructor(db: Database.Database);
40
+ private initialize;
41
+ create(input: CreateTemplateInput): TemplateRecord;
42
+ findAll(): TemplateRecord[];
43
+ findById(id: number): TemplateRecord | undefined;
44
+ findByName(name: string): TemplateRecord | undefined;
45
+ deleteByName(name: string): boolean;
46
+ /**
47
+ * Partially update by template name
48
+ */
49
+ updateByName(name: string, input: UpdateTemplateInput): boolean;
50
+ private mapRow;
51
+ }
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TemplateRepository = void 0;
4
+ /**
5
+ * Repository class for SQLite persistence of frequently used prompt templates.
6
+ * Handles template creation, retrieval, updating, and deletion.
7
+ */
8
+ class TemplateRepository {
9
+ db;
10
+ // Cached prepared statements
11
+ stmtCreate;
12
+ stmtFindAll;
13
+ stmtFindById;
14
+ stmtFindByName;
15
+ stmtDeleteByName;
16
+ constructor(db) {
17
+ this.db = db;
18
+ this.initialize();
19
+ this.stmtCreate = this.db.prepare('INSERT INTO templates (name, prompt) VALUES (?, ?)');
20
+ this.stmtFindAll = this.db.prepare('SELECT * FROM templates ORDER BY id ASC');
21
+ this.stmtFindById = this.db.prepare('SELECT * FROM templates WHERE id = ?');
22
+ this.stmtFindByName = this.db.prepare('SELECT * FROM templates WHERE name = ?');
23
+ this.stmtDeleteByName = this.db.prepare('DELETE FROM templates WHERE name = ?');
24
+ }
25
+ initialize() {
26
+ this.db.exec(`
27
+ CREATE TABLE IF NOT EXISTS templates (
28
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
29
+ name TEXT NOT NULL UNIQUE,
30
+ prompt TEXT NOT NULL,
31
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
32
+ )
33
+ `);
34
+ }
35
+ create(input) {
36
+ const result = this.stmtCreate.run(input.name, input.prompt);
37
+ return {
38
+ id: result.lastInsertRowid,
39
+ name: input.name,
40
+ prompt: input.prompt,
41
+ };
42
+ }
43
+ findAll() {
44
+ const rows = this.stmtFindAll.all();
45
+ return rows.map(this.mapRow);
46
+ }
47
+ findById(id) {
48
+ const row = this.stmtFindById.get(id);
49
+ if (!row)
50
+ return undefined;
51
+ return this.mapRow(row);
52
+ }
53
+ findByName(name) {
54
+ const row = this.stmtFindByName.get(name);
55
+ if (!row)
56
+ return undefined;
57
+ return this.mapRow(row);
58
+ }
59
+ deleteByName(name) {
60
+ const result = this.stmtDeleteByName.run(name);
61
+ return result.changes > 0;
62
+ }
63
+ /**
64
+ * Partially update by template name
65
+ */
66
+ updateByName(name, input) {
67
+ const sets = [];
68
+ const values = [];
69
+ if (input.prompt !== undefined) {
70
+ sets.push('prompt = ?');
71
+ values.push(input.prompt);
72
+ }
73
+ if (sets.length === 0)
74
+ return false;
75
+ values.push(name);
76
+ const sql = `UPDATE templates SET ${sets.join(', ')} WHERE name = ?`;
77
+ const result = this.db.prepare(sql).run(...values);
78
+ return result.changes > 0;
79
+ }
80
+ mapRow(row) {
81
+ return {
82
+ id: row.id,
83
+ name: row.name,
84
+ prompt: row.prompt,
85
+ createdAt: row.created_at,
86
+ };
87
+ }
88
+ }
89
+ exports.TemplateRepository = TemplateRepository;
90
+ //# sourceMappingURL=templateRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateRepository.js","sourceRoot":"","sources":["../../src/database/templateRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import Database from 'better-sqlite3';
2
+ /**
3
+ * Workspace binding record type definition
4
+ */
5
+ export interface WorkspaceBindingRecord {
6
+ /** Unique ID (auto-increment) */
7
+ id: number;
8
+ /** Channel / topic ID (unique) */
9
+ channelId: string;
10
+ /** Workspace relative path */
11
+ workspacePath: string;
12
+ /** Chat / group ID */
13
+ guildId: string;
14
+ /** Creation timestamp (ISO string) */
15
+ createdAt?: string;
16
+ }
17
+ /**
18
+ * Input type for binding creation
19
+ */
20
+ export interface CreateWorkspaceBindingInput {
21
+ channelId: string;
22
+ workspacePath: string;
23
+ guildId: string;
24
+ }
25
+ /**
26
+ * Repository for persisting channel/topic to workspace directory bindings in SQLite.
27
+ * Only one workspace can be bound per channel (UNIQUE constraint).
28
+ */
29
+ export declare class WorkspaceBindingRepository {
30
+ private readonly db;
31
+ private readonly stmtCreate;
32
+ private readonly stmtFindByChannelId;
33
+ private readonly stmtFindByWorkspacePathAndGuildId;
34
+ private readonly stmtFindByGuildId;
35
+ private readonly stmtFindAll;
36
+ private readonly stmtDeleteByChannelId;
37
+ private readonly stmtUpsert;
38
+ constructor(db: Database.Database);
39
+ private initialize;
40
+ create(input: CreateWorkspaceBindingInput): WorkspaceBindingRecord;
41
+ findByChannelId(channelId: string): WorkspaceBindingRecord | undefined;
42
+ findByWorkspacePathAndGuildId(workspacePath: string, guildId: string): WorkspaceBindingRecord[];
43
+ findByGuildId(guildId: string): WorkspaceBindingRecord[];
44
+ findAll(): WorkspaceBindingRecord[];
45
+ deleteByChannelId(channelId: string): boolean;
46
+ upsert(input: CreateWorkspaceBindingInput): WorkspaceBindingRecord;
47
+ private mapRow;
48
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkspaceBindingRepository = void 0;
4
+ /**
5
+ * Repository for persisting channel/topic to workspace directory bindings in SQLite.
6
+ * Only one workspace can be bound per channel (UNIQUE constraint).
7
+ */
8
+ class WorkspaceBindingRepository {
9
+ db;
10
+ // Cached prepared statements
11
+ stmtCreate;
12
+ stmtFindByChannelId;
13
+ stmtFindByWorkspacePathAndGuildId;
14
+ stmtFindByGuildId;
15
+ stmtFindAll;
16
+ stmtDeleteByChannelId;
17
+ stmtUpsert;
18
+ constructor(db) {
19
+ this.db = db;
20
+ this.initialize();
21
+ this.stmtCreate = this.db.prepare('INSERT INTO workspace_bindings (channel_id, workspace_path, guild_id) VALUES (?, ?, ?)');
22
+ this.stmtFindByChannelId = this.db.prepare('SELECT * FROM workspace_bindings WHERE channel_id = ?');
23
+ this.stmtFindByWorkspacePathAndGuildId = this.db.prepare('SELECT * FROM workspace_bindings WHERE workspace_path = ? AND guild_id = ? ORDER BY id ASC');
24
+ this.stmtFindByGuildId = this.db.prepare('SELECT * FROM workspace_bindings WHERE guild_id = ? ORDER BY id ASC');
25
+ this.stmtFindAll = this.db.prepare('SELECT * FROM workspace_bindings ORDER BY id ASC');
26
+ this.stmtDeleteByChannelId = this.db.prepare('DELETE FROM workspace_bindings WHERE channel_id = ?');
27
+ this.stmtUpsert = this.db.prepare(`
28
+ INSERT INTO workspace_bindings (channel_id, workspace_path, guild_id)
29
+ VALUES (?, ?, ?)
30
+ ON CONFLICT(channel_id) DO UPDATE SET
31
+ workspace_path = excluded.workspace_path,
32
+ guild_id = excluded.guild_id
33
+ `);
34
+ }
35
+ initialize() {
36
+ this.db.exec(`
37
+ CREATE TABLE IF NOT EXISTS workspace_bindings (
38
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
39
+ channel_id TEXT NOT NULL UNIQUE,
40
+ workspace_path TEXT NOT NULL,
41
+ guild_id TEXT NOT NULL,
42
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
43
+ )
44
+ `);
45
+ }
46
+ create(input) {
47
+ const result = this.stmtCreate.run(input.channelId, input.workspacePath, input.guildId);
48
+ return {
49
+ id: result.lastInsertRowid,
50
+ channelId: input.channelId,
51
+ workspacePath: input.workspacePath,
52
+ guildId: input.guildId,
53
+ };
54
+ }
55
+ findByChannelId(channelId) {
56
+ const row = this.stmtFindByChannelId.get(channelId);
57
+ if (!row)
58
+ return undefined;
59
+ return this.mapRow(row);
60
+ }
61
+ findByWorkspacePathAndGuildId(workspacePath, guildId) {
62
+ const rows = this.stmtFindByWorkspacePathAndGuildId.all(workspacePath, guildId);
63
+ return rows.map(this.mapRow);
64
+ }
65
+ findByGuildId(guildId) {
66
+ const rows = this.stmtFindByGuildId.all(guildId);
67
+ return rows.map(this.mapRow);
68
+ }
69
+ findAll() {
70
+ const rows = this.stmtFindAll.all();
71
+ return rows.map(this.mapRow);
72
+ }
73
+ deleteByChannelId(channelId) {
74
+ const result = this.stmtDeleteByChannelId.run(channelId);
75
+ return result.changes > 0;
76
+ }
77
+ upsert(input) {
78
+ this.stmtUpsert.run(input.channelId, input.workspacePath, input.guildId);
79
+ return this.findByChannelId(input.channelId);
80
+ }
81
+ mapRow(row) {
82
+ return {
83
+ id: row.id,
84
+ channelId: row.channel_id,
85
+ workspacePath: row.workspace_path,
86
+ guildId: row.guild_id,
87
+ createdAt: row.created_at,
88
+ };
89
+ }
90
+ }
91
+ exports.WorkspaceBindingRepository = WorkspaceBindingRepository;
92
+ //# sourceMappingURL=workspaceBindingRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceBindingRepository.js","sourceRoot":"","sources":["../../src/database/workspaceBindingRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const logger_1 = require("./utils/logger");
4
+ const bot_1 = require("./bot");
5
+ const lockfile_1 = require("./utils/lockfile");
6
+ const logo_1 = require("./utils/logo");
7
+ console.log(logo_1.LOGO);
8
+ // Prevent duplicate launch: exit immediately if bot is already running
9
+ (0, lockfile_1.acquireLock)();
10
+ (0, bot_1.startBot)().catch(logger_1.logger.error);
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,2CAAwC;AACxC,+BAAiC;AACjC,+CAA+C;AAC/C,uCAAoC;AAEpC,OAAO,CAAC,GAAG,CAAC,WAAI,CAAC,CAAC;AAElB,uEAAuE;AACvE,IAAA,sBAAW,GAAE,CAAC;AAEd,IAAA,cAAQ,GAAE,CAAC,KAAK,CAAC,eAAM,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @deprecated Not used by the bot (grammy middleware handles auth).
3
+ * Kept for backwards compatibility with tests.
4
+ */
5
+ export declare const withAuth: (userId: string, allowedUserIds: string[], next: () => void) => void;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withAuth = void 0;
4
+ /**
5
+ * @deprecated Not used by the bot (grammy middleware handles auth).
6
+ * Kept for backwards compatibility with tests.
7
+ */
8
+ const withAuth = (userId, allowedUserIds, next) => {
9
+ if (allowedUserIds.includes(userId)) {
10
+ next();
11
+ }
12
+ };
13
+ exports.withAuth = withAuth;
14
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACI,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,cAAwB,EAAE,IAAgB,EAAQ,EAAE;IACzF,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,IAAI,EAAE,CAAC;IACX,CAAC;AACL,CAAC,CAAC;AAJW,QAAA,QAAQ,YAInB"}
@@ -0,0 +1 @@
1
+ export declare const resolveSafePath: (inputPath: string, baseDir: string) => string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveSafePath = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const resolveSafePath = (inputPath, baseDir) => {
9
+ const resolvedPath = path_1.default.resolve(baseDir, inputPath);
10
+ const normalizedBaseDir = path_1.default.resolve(baseDir);
11
+ const relative = path_1.default.relative(normalizedBaseDir, resolvedPath);
12
+ if (relative && (relative.startsWith('..' + path_1.default.sep) || relative === '..')) {
13
+ throw new Error('Path traversal detected');
14
+ }
15
+ return resolvedPath;
16
+ };
17
+ exports.resolveSafePath = resolveSafePath;
18
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/middleware/sanitize.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAEjB,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAE,OAAe,EAAU,EAAE;IAC1E,MAAM,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,cAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;IAEhE,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,cAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,YAAY,CAAC;AACxB,CAAC,CAAC;AAXW,QAAA,eAAe,mBAW1B"}