@0xmaxma/claude-gateway 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 (192) hide show
  1. package/README.md +791 -0
  2. package/config.template.json +87 -0
  3. package/dist/agent/context-isolation.d.ts +28 -0
  4. package/dist/agent/context-isolation.d.ts.map +1 -0
  5. package/dist/agent/context-isolation.js +80 -0
  6. package/dist/agent/context-isolation.js.map +1 -0
  7. package/dist/agent/runner.d.ts +211 -0
  8. package/dist/agent/runner.d.ts.map +1 -0
  9. package/dist/agent/runner.js +1802 -0
  10. package/dist/agent/runner.js.map +1 -0
  11. package/dist/agent/workspace-loader.d.ts +31 -0
  12. package/dist/agent/workspace-loader.d.ts.map +1 -0
  13. package/dist/agent/workspace-loader.js +207 -0
  14. package/dist/agent/workspace-loader.js.map +1 -0
  15. package/dist/api/auth.d.ts +25 -0
  16. package/dist/api/auth.d.ts.map +1 -0
  17. package/dist/api/auth.js +77 -0
  18. package/dist/api/auth.js.map +1 -0
  19. package/dist/api/cron-router.d.ts +22 -0
  20. package/dist/api/cron-router.d.ts.map +1 -0
  21. package/dist/api/cron-router.js +197 -0
  22. package/dist/api/cron-router.js.map +1 -0
  23. package/dist/api/gateway-router.d.ts +52 -0
  24. package/dist/api/gateway-router.d.ts.map +1 -0
  25. package/dist/api/gateway-router.js +215 -0
  26. package/dist/api/gateway-router.js.map +1 -0
  27. package/dist/api/router.d.ts +5 -0
  28. package/dist/api/router.d.ts.map +1 -0
  29. package/dist/api/router.js +1098 -0
  30. package/dist/api/router.js.map +1 -0
  31. package/dist/api/skills-router.d.ts +5 -0
  32. package/dist/api/skills-router.d.ts.map +1 -0
  33. package/dist/api/skills-router.js +424 -0
  34. package/dist/api/skills-router.js.map +1 -0
  35. package/dist/api/workspace-router.d.ts +4 -0
  36. package/dist/api/workspace-router.d.ts.map +1 -0
  37. package/dist/api/workspace-router.js +149 -0
  38. package/dist/api/workspace-router.js.map +1 -0
  39. package/dist/config/loader.d.ts +16 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +235 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/migrator.d.ts +70 -0
  44. package/dist/config/migrator.d.ts.map +1 -0
  45. package/dist/config/migrator.js +343 -0
  46. package/dist/config/migrator.js.map +1 -0
  47. package/dist/config/watcher.d.ts +30 -0
  48. package/dist/config/watcher.d.ts.map +1 -0
  49. package/dist/config/watcher.js +170 -0
  50. package/dist/config/watcher.js.map +1 -0
  51. package/dist/cron/manager.d.ts +48 -0
  52. package/dist/cron/manager.d.ts.map +1 -0
  53. package/dist/cron/manager.js +580 -0
  54. package/dist/cron/manager.js.map +1 -0
  55. package/dist/cron/scheduler.d.ts +50 -0
  56. package/dist/cron/scheduler.d.ts.map +1 -0
  57. package/dist/cron/scheduler.js +231 -0
  58. package/dist/cron/scheduler.js.map +1 -0
  59. package/dist/discord/receiver.d.ts +17 -0
  60. package/dist/discord/receiver.d.ts.map +1 -0
  61. package/dist/discord/receiver.js +108 -0
  62. package/dist/discord/receiver.js.map +1 -0
  63. package/dist/heartbeat/history.d.ts +24 -0
  64. package/dist/heartbeat/history.d.ts.map +1 -0
  65. package/dist/heartbeat/history.js +50 -0
  66. package/dist/heartbeat/history.js.map +1 -0
  67. package/dist/heartbeat/parser.d.ts +26 -0
  68. package/dist/heartbeat/parser.d.ts.map +1 -0
  69. package/dist/heartbeat/parser.js +283 -0
  70. package/dist/heartbeat/parser.js.map +1 -0
  71. package/dist/history/cleanup.d.ts +21 -0
  72. package/dist/history/cleanup.d.ts.map +1 -0
  73. package/dist/history/cleanup.js +171 -0
  74. package/dist/history/cleanup.js.map +1 -0
  75. package/dist/history/db.d.ts +27 -0
  76. package/dist/history/db.d.ts.map +1 -0
  77. package/dist/history/db.js +323 -0
  78. package/dist/history/db.js.map +1 -0
  79. package/dist/history/media-store.d.ts +27 -0
  80. package/dist/history/media-store.d.ts.map +1 -0
  81. package/dist/history/media-store.js +158 -0
  82. package/dist/history/media-store.js.map +1 -0
  83. package/dist/history/types.d.ts +62 -0
  84. package/dist/history/types.d.ts.map +1 -0
  85. package/dist/history/types.js +3 -0
  86. package/dist/history/types.js.map +1 -0
  87. package/dist/index.d.ts +3 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +483 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/logger.d.ts +3 -0
  92. package/dist/logger.d.ts.map +1 -0
  93. package/dist/logger.js +81 -0
  94. package/dist/logger.js.map +1 -0
  95. package/dist/memory/manager.d.ts +45 -0
  96. package/dist/memory/manager.d.ts.map +1 -0
  97. package/dist/memory/manager.js +178 -0
  98. package/dist/memory/manager.js.map +1 -0
  99. package/dist/session/compactor.d.ts +22 -0
  100. package/dist/session/compactor.d.ts.map +1 -0
  101. package/dist/session/compactor.js +151 -0
  102. package/dist/session/compactor.js.map +1 -0
  103. package/dist/session/process.d.ts +76 -0
  104. package/dist/session/process.d.ts.map +1 -0
  105. package/dist/session/process.js +729 -0
  106. package/dist/session/process.js.map +1 -0
  107. package/dist/session/store.d.ts +102 -0
  108. package/dist/session/store.d.ts.map +1 -0
  109. package/dist/session/store.js +533 -0
  110. package/dist/session/store.js.map +1 -0
  111. package/dist/skills/index.d.ts +9 -0
  112. package/dist/skills/index.d.ts.map +1 -0
  113. package/dist/skills/index.js +15 -0
  114. package/dist/skills/index.js.map +1 -0
  115. package/dist/skills/invoker.d.ts +16 -0
  116. package/dist/skills/invoker.d.ts.map +1 -0
  117. package/dist/skills/invoker.js +36 -0
  118. package/dist/skills/invoker.js.map +1 -0
  119. package/dist/skills/loader.d.ts +23 -0
  120. package/dist/skills/loader.d.ts.map +1 -0
  121. package/dist/skills/loader.js +183 -0
  122. package/dist/skills/loader.js.map +1 -0
  123. package/dist/skills/parser.d.ts +55 -0
  124. package/dist/skills/parser.d.ts.map +1 -0
  125. package/dist/skills/parser.js +178 -0
  126. package/dist/skills/parser.js.map +1 -0
  127. package/dist/skills/sync.d.ts +10 -0
  128. package/dist/skills/sync.d.ts.map +1 -0
  129. package/dist/skills/sync.js +130 -0
  130. package/dist/skills/sync.js.map +1 -0
  131. package/dist/skills/watcher.d.ts +16 -0
  132. package/dist/skills/watcher.d.ts.map +1 -0
  133. package/dist/skills/watcher.js +25 -0
  134. package/dist/skills/watcher.js.map +1 -0
  135. package/dist/telegram/markdown.d.ts +25 -0
  136. package/dist/telegram/markdown.d.ts.map +1 -0
  137. package/dist/telegram/markdown.js +237 -0
  138. package/dist/telegram/markdown.js.map +1 -0
  139. package/dist/telegram/receiver.d.ts +17 -0
  140. package/dist/telegram/receiver.d.ts.map +1 -0
  141. package/dist/telegram/receiver.js +104 -0
  142. package/dist/telegram/receiver.js.map +1 -0
  143. package/dist/types.d.ts +224 -0
  144. package/dist/types.d.ts.map +1 -0
  145. package/dist/types.js +3 -0
  146. package/dist/types.js.map +1 -0
  147. package/dist/ui/web-ui.d.ts +6 -0
  148. package/dist/ui/web-ui.d.ts.map +1 -0
  149. package/dist/ui/web-ui.js +227 -0
  150. package/dist/ui/web-ui.js.map +1 -0
  151. package/dist/watch/factory.d.ts +26 -0
  152. package/dist/watch/factory.d.ts.map +1 -0
  153. package/dist/watch/factory.js +43 -0
  154. package/dist/watch/factory.js.map +1 -0
  155. package/dist/webhook/manager.d.ts +34 -0
  156. package/dist/webhook/manager.d.ts.map +1 -0
  157. package/dist/webhook/manager.js +120 -0
  158. package/dist/webhook/manager.js.map +1 -0
  159. package/mcp/bun.lock +264 -0
  160. package/mcp/channel-manager.ts +115 -0
  161. package/mcp/package.json +15 -0
  162. package/mcp/router.ts +69 -0
  163. package/mcp/server.ts +129 -0
  164. package/mcp/tools/agent/handlers.ts +578 -0
  165. package/mcp/tools/agent/module.ts +163 -0
  166. package/mcp/tools/browser/module.ts +321 -0
  167. package/mcp/tools/browser/skills/open-browser/SKILL.md +89 -0
  168. package/mcp/tools/cron/client.ts +65 -0
  169. package/mcp/tools/cron/module.ts +158 -0
  170. package/mcp/tools/cron/skills/cron/SKILL.md +46 -0
  171. package/mcp/tools/discord/access.ts +197 -0
  172. package/mcp/tools/discord/client.ts +31 -0
  173. package/mcp/tools/discord/commands.ts +48 -0
  174. package/mcp/tools/discord/inbound.ts +53 -0
  175. package/mcp/tools/discord/module.ts +442 -0
  176. package/mcp/tools/discord/outbound.ts +90 -0
  177. package/mcp/tools/discord/receiver-server.ts +58 -0
  178. package/mcp/tools/discord/skills/access/SKILL.md +86 -0
  179. package/mcp/tools/discord/skills/configure/SKILL.md +53 -0
  180. package/mcp/tools/discord/threading.ts +37 -0
  181. package/mcp/tools/discord/types.ts +106 -0
  182. package/mcp/tools/skills/handlers.ts +196 -0
  183. package/mcp/tools/skills/module.ts +163 -0
  184. package/mcp/tools/telegram/module.ts +454 -0
  185. package/mcp/tools/telegram/pure.ts +224 -0
  186. package/mcp/tools/telegram/receiver-server.ts +1656 -0
  187. package/mcp/tools/telegram/skills/access/SKILL.md +169 -0
  188. package/mcp/tools/telegram/skills/configure/SKILL.md +118 -0
  189. package/mcp/tools/telegram/typing.ts +327 -0
  190. package/mcp/types.ts +128 -0
  191. package/package.json +62 -0
  192. package/resource/claude_gateway.svg +112 -0
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MissingScheduleError = exports.AmbiguousScheduleError = exports.MissingNameError = exports.MissingPromptError = exports.InvalidIntervalError = exports.InvalidCronError = void 0;
37
+ exports.intervalToCron = intervalToCron;
38
+ exports.parseHeartbeat = parseHeartbeat;
39
+ const yaml = __importStar(require("js-yaml"));
40
+ // ---------- Error classes ----------
41
+ class InvalidCronError extends Error {
42
+ constructor(taskName, expr) {
43
+ super(`Task "${taskName}": invalid cron expression "${expr}"`);
44
+ this.name = 'InvalidCronError';
45
+ }
46
+ }
47
+ exports.InvalidCronError = InvalidCronError;
48
+ class InvalidIntervalError extends Error {
49
+ constructor(taskName, interval) {
50
+ super(`Task "${taskName}": invalid interval "${interval}"`);
51
+ this.name = 'InvalidIntervalError';
52
+ }
53
+ }
54
+ exports.InvalidIntervalError = InvalidIntervalError;
55
+ class MissingPromptError extends Error {
56
+ constructor(taskName) {
57
+ super(`Task "${taskName}" is missing required field "prompt"`);
58
+ this.name = 'MissingPromptError';
59
+ }
60
+ }
61
+ exports.MissingPromptError = MissingPromptError;
62
+ class MissingNameError extends Error {
63
+ constructor(index) {
64
+ super(`Task at index ${index} is missing required field "name"`);
65
+ this.name = 'MissingNameError';
66
+ }
67
+ }
68
+ exports.MissingNameError = MissingNameError;
69
+ class AmbiguousScheduleError extends Error {
70
+ constructor(taskName) {
71
+ super(`Task "${taskName}" specifies both "cron" and "interval" — use exactly one`);
72
+ this.name = 'AmbiguousScheduleError';
73
+ }
74
+ }
75
+ exports.AmbiguousScheduleError = AmbiguousScheduleError;
76
+ class MissingScheduleError extends Error {
77
+ constructor(taskName) {
78
+ super(`Task "${taskName}" must specify either "cron" or "interval"`);
79
+ this.name = 'MissingScheduleError';
80
+ }
81
+ }
82
+ exports.MissingScheduleError = MissingScheduleError;
83
+ // ---------- Cron validation ----------
84
+ /**
85
+ * Validate a 5-field cron expression.
86
+ * Fields: minute hour day-of-month month day-of-week
87
+ */
88
+ function validateCron(expr) {
89
+ // Allow common step/range/wildcard patterns but reject obviously invalid values
90
+ const fields = expr.trim().split(/\s+/);
91
+ if (fields.length !== 5)
92
+ return false;
93
+ // Ranges for each field: [min, max]
94
+ const ranges = [
95
+ [0, 59], // minute
96
+ [0, 23], // hour
97
+ [1, 31], // day-of-month
98
+ [1, 12], // month
99
+ [0, 7], // day-of-week (0 and 7 both = Sunday)
100
+ ];
101
+ for (let i = 0; i < 5; i++) {
102
+ const field = fields[i];
103
+ const [min, max] = ranges[i];
104
+ if (!validateCronField(field, min, max)) {
105
+ return false;
106
+ }
107
+ }
108
+ return true;
109
+ }
110
+ function validateCronField(field, min, max) {
111
+ if (field === '*')
112
+ return true;
113
+ // Step: */N or N/N
114
+ if (field.includes('/')) {
115
+ const parts = field.split('/');
116
+ if (parts.length !== 2)
117
+ return false;
118
+ const [base, step] = parts;
119
+ const stepNum = parseInt(step, 10);
120
+ if (isNaN(stepNum) || stepNum < 1)
121
+ return false;
122
+ if (base !== '*') {
123
+ const baseNum = parseInt(base, 10);
124
+ if (isNaN(baseNum) || baseNum < min || baseNum > max)
125
+ return false;
126
+ }
127
+ return true;
128
+ }
129
+ // Range: N-M
130
+ if (field.includes('-')) {
131
+ const parts = field.split('-');
132
+ if (parts.length !== 2)
133
+ return false;
134
+ const lo = parseInt(parts[0], 10);
135
+ const hi = parseInt(parts[1], 10);
136
+ if (isNaN(lo) || isNaN(hi))
137
+ return false;
138
+ if (lo < min || hi > max || lo > hi)
139
+ return false;
140
+ return true;
141
+ }
142
+ // List: N,M,...
143
+ if (field.includes(',')) {
144
+ const parts = field.split(',');
145
+ for (const p of parts) {
146
+ const num = parseInt(p, 10);
147
+ if (isNaN(num) || num < min || num > max)
148
+ return false;
149
+ }
150
+ return true;
151
+ }
152
+ // Plain number
153
+ const num = parseInt(field, 10);
154
+ if (isNaN(num) || num < min || num > max)
155
+ return false;
156
+ return true;
157
+ }
158
+ // ---------- Interval conversion ----------
159
+ /**
160
+ * Convert an interval string to a 5-field cron expression.
161
+ * Supported: 30m, 2h, 1d, 1w
162
+ */
163
+ function intervalToCron(interval) {
164
+ const match = interval.match(/^(\d+)([mhdw])$/);
165
+ if (!match) {
166
+ return ''; // signal invalid
167
+ }
168
+ const value = parseInt(match[1], 10);
169
+ const unit = match[2];
170
+ switch (unit) {
171
+ case 'm':
172
+ if (value < 1 || value > 59)
173
+ return '';
174
+ return `*/${value} * * * *`;
175
+ case 'h':
176
+ if (value < 1 || value > 23)
177
+ return '';
178
+ return `0 */${value} * * *`;
179
+ case 'd':
180
+ if (value !== 1)
181
+ return '';
182
+ return `0 0 * * *`;
183
+ case 'w':
184
+ if (value !== 1)
185
+ return '';
186
+ return `0 0 * * 0`;
187
+ default:
188
+ return '';
189
+ }
190
+ }
191
+ // ---------- YAML extraction ----------
192
+ /**
193
+ * Extract the YAML block from a heartbeat.md content string.
194
+ * The YAML block is everything before the first markdown heading (`#`) line
195
+ * that appears after the YAML content starts.
196
+ *
197
+ * Strategy: find the `tasks:` key, collect lines until we hit a line that
198
+ * starts with `#` (markdown heading) that is NOT inside a YAML string.
199
+ */
200
+ function extractYamlBlock(content) {
201
+ const lines = content.split('\n');
202
+ const yamlLines = [];
203
+ let inYaml = false;
204
+ for (const line of lines) {
205
+ // Detect start of YAML (tasks: key at root level)
206
+ if (!inYaml && /^tasks\s*:/.test(line)) {
207
+ inYaml = true;
208
+ }
209
+ if (inYaml) {
210
+ // Stop at a markdown heading that is at column 0 and not part of YAML value
211
+ // A line starting with `#` that is NOT indented signals end of YAML block
212
+ if (/^#/.test(line)) {
213
+ break;
214
+ }
215
+ yamlLines.push(line);
216
+ }
217
+ }
218
+ return yamlLines.join('\n');
219
+ }
220
+ // ---------- Main parser ----------
221
+ function parseHeartbeat(content) {
222
+ const yamlBlock = extractYamlBlock(content);
223
+ if (!yamlBlock.trim()) {
224
+ return [];
225
+ }
226
+ let parsed;
227
+ try {
228
+ parsed = yaml.load(yamlBlock);
229
+ }
230
+ catch {
231
+ return [];
232
+ }
233
+ if (!parsed || typeof parsed !== 'object') {
234
+ return [];
235
+ }
236
+ const root = parsed;
237
+ if (!Array.isArray(root.tasks)) {
238
+ return [];
239
+ }
240
+ const rawTasks = root.tasks;
241
+ if (rawTasks.length === 0) {
242
+ return [];
243
+ }
244
+ const tasks = [];
245
+ for (let i = 0; i < rawTasks.length; i++) {
246
+ const raw = rawTasks[i];
247
+ // Validate name
248
+ if (!raw.name || typeof raw.name !== 'string' || !raw.name.trim()) {
249
+ throw new MissingNameError(i);
250
+ }
251
+ const name = raw.name.trim();
252
+ // Validate prompt
253
+ if (!raw.prompt || typeof raw.prompt !== 'string' || !raw.prompt.trim()) {
254
+ throw new MissingPromptError(name);
255
+ }
256
+ const prompt = raw.prompt.trim();
257
+ const hasCron = 'cron' in raw && raw.cron !== undefined && raw.cron !== null;
258
+ const hasInterval = 'interval' in raw && raw.interval !== undefined && raw.interval !== null;
259
+ if (hasCron && hasInterval) {
260
+ throw new AmbiguousScheduleError(name);
261
+ }
262
+ if (!hasCron && !hasInterval) {
263
+ throw new MissingScheduleError(name);
264
+ }
265
+ let cronExpr;
266
+ if (hasCron) {
267
+ cronExpr = String(raw.cron).trim();
268
+ if (!validateCron(cronExpr)) {
269
+ throw new InvalidCronError(name, cronExpr);
270
+ }
271
+ }
272
+ else {
273
+ const intervalStr = String(raw.interval).trim();
274
+ cronExpr = intervalToCron(intervalStr);
275
+ if (!cronExpr) {
276
+ throw new InvalidIntervalError(name, intervalStr);
277
+ }
278
+ }
279
+ tasks.push({ name, cron: cronExpr, prompt });
280
+ }
281
+ return tasks;
282
+ }
283
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/heartbeat/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { HistoryDB } from './db';
2
+ export interface CleanupOptions {
3
+ db: HistoryDB;
4
+ agentMediaRoot: string;
5
+ logPath: string;
6
+ retentionDays: number;
7
+ cleanupHour: number;
8
+ cleanupTimezone: string;
9
+ }
10
+ /**
11
+ * Compute milliseconds until the next occurrence of `hour` in `timezone`.
12
+ * If the current hour already matches and no minutes have passed, fires in 24h.
13
+ */
14
+ export declare function msUntilNextHour(hour: number, timezone: string, now?: Date): number;
15
+ /**
16
+ * Schedule daily cleanup at cleanupHour in cleanupTimezone.
17
+ * Returns a cancel function that stops the timer.
18
+ */
19
+ export declare function scheduleCleanup(opts: CleanupOptions): () => void;
20
+ export declare function resolveRetentionDays(agentRetention?: number, globalRetention?: number): number;
21
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/history/cleanup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAIjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,SAAS,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AA0BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,MAAM,CAyBxF;AAuDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,IAAI,CAmBhE;AAED,wBAAgB,oBAAoB,CAClC,cAAc,CAAC,EAAE,MAAM,EACvB,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CAIR"}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.msUntilNextHour = msUntilNextHour;
37
+ exports.scheduleCleanup = scheduleCleanup;
38
+ exports.resolveRetentionDays = resolveRetentionDays;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const DEFAULT_RETENTION_DAYS = 60;
42
+ const MAX_LOG_BYTES = 1 * 1024 * 1024; // 1 MB
43
+ const MAX_LOG_LINES_KEPT = 400;
44
+ function appendLog(logPath, line) {
45
+ const ts = new Date().toISOString();
46
+ const entry = `[${ts}] ${line}\n`;
47
+ try {
48
+ // Rotate: keep last N lines when file exceeds size cap
49
+ try {
50
+ const stat = fs.statSync(logPath);
51
+ if (stat.size > MAX_LOG_BYTES) {
52
+ const content = fs.readFileSync(logPath, 'utf8');
53
+ const kept = content.split('\n').filter(Boolean).slice(-MAX_LOG_LINES_KEPT).join('\n') + '\n';
54
+ fs.writeFileSync(logPath, kept);
55
+ }
56
+ }
57
+ catch {
58
+ // file may not exist yet — that's fine
59
+ }
60
+ fs.appendFileSync(logPath, entry);
61
+ }
62
+ catch {
63
+ // log write failure is non-fatal
64
+ }
65
+ }
66
+ /**
67
+ * Compute milliseconds until the next occurrence of `hour` in `timezone`.
68
+ * If the current hour already matches and no minutes have passed, fires in 24h.
69
+ */
70
+ function msUntilNextHour(hour, timezone, now = new Date()) {
71
+ const hourFormatter = new Intl.DateTimeFormat('en-US', {
72
+ timeZone: timezone,
73
+ hour: 'numeric',
74
+ hour12: false,
75
+ });
76
+ const currentHour = parseInt(hourFormatter.format(now), 10);
77
+ let hoursUntil = hour - currentHour;
78
+ if (hoursUntil <= 0)
79
+ hoursUntil += 24;
80
+ // Compute ms elapsed since start of current hour in the target timezone.
81
+ // Using formatToParts so we handle half-hour/45-min offset timezones correctly.
82
+ const minSecFormatter = new Intl.DateTimeFormat('en-US', {
83
+ timeZone: timezone,
84
+ minute: '2-digit',
85
+ second: '2-digit',
86
+ });
87
+ const parts = minSecFormatter.formatToParts(now);
88
+ const minutes = parseInt(parts.find((p) => p.type === 'minute')?.value ?? '0', 10);
89
+ const seconds = parseInt(parts.find((p) => p.type === 'second')?.value ?? '0', 10);
90
+ const msIntoCurrentHour = (minutes * 60 + seconds) * 1000 + (now.getTime() % 1000);
91
+ const msPerHour = 60 * 60 * 1000;
92
+ return hoursUntil * msPerHour - msIntoCurrentHour;
93
+ }
94
+ function doCleanup(opts) {
95
+ const { db, agentMediaRoot, logPath, retentionDays } = opts;
96
+ if (retentionDays === 0)
97
+ return;
98
+ const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
99
+ let mediaPaths;
100
+ try {
101
+ mediaPaths = db.pruneOlderThan(cutoffMs);
102
+ }
103
+ catch (err) {
104
+ appendLog(logPath, `ERROR pruneOlderThan failed: ${err.message}`);
105
+ return;
106
+ }
107
+ let deletedFiles = 0;
108
+ const dirsToCheck = new Set();
109
+ for (const relPath of mediaPaths) {
110
+ // Strip leading "media/" prefix if present
111
+ const withoutPrefix = relPath.startsWith('media/') ? relPath.slice(6) : relPath;
112
+ const absPath = path.resolve(agentMediaRoot, withoutPrefix);
113
+ // Path traversal guard: resolved path must stay inside agentMediaRoot
114
+ if (!absPath.startsWith(agentMediaRoot + path.sep) && absPath !== agentMediaRoot)
115
+ continue;
116
+ try {
117
+ if (fs.existsSync(absPath)) {
118
+ fs.unlinkSync(absPath);
119
+ deletedFiles++;
120
+ dirsToCheck.add(path.dirname(absPath));
121
+ }
122
+ }
123
+ catch (err) {
124
+ appendLog(logPath, `WARN failed to delete ${absPath}: ${err.message}`);
125
+ }
126
+ }
127
+ // Remove empty parent directories (within agentMediaRoot only)
128
+ for (const dir of dirsToCheck) {
129
+ if (!dir.startsWith(agentMediaRoot + path.sep))
130
+ continue;
131
+ try {
132
+ const entries = fs.readdirSync(dir);
133
+ if (entries.length === 0)
134
+ fs.rmdirSync(dir);
135
+ }
136
+ catch {
137
+ // non-fatal
138
+ }
139
+ }
140
+ appendLog(logPath, `cleanup done: retentionDays=${retentionDays} cutoff=${new Date(cutoffMs).toISOString()} deletedFiles=${deletedFiles}`);
141
+ }
142
+ /**
143
+ * Schedule daily cleanup at cleanupHour in cleanupTimezone.
144
+ * Returns a cancel function that stops the timer.
145
+ */
146
+ function scheduleCleanup(opts) {
147
+ if (opts.retentionDays === 0)
148
+ return () => { };
149
+ let timer;
150
+ const schedule = () => {
151
+ const delay = msUntilNextHour(opts.cleanupHour, opts.cleanupTimezone);
152
+ timer = setTimeout(() => {
153
+ doCleanup(opts);
154
+ schedule(); // reschedule for next day
155
+ }, delay);
156
+ // Don't hold the event loop open just for a cleanup timer
157
+ if (typeof timer.unref === 'function') {
158
+ timer.unref();
159
+ }
160
+ };
161
+ schedule();
162
+ return () => clearTimeout(timer);
163
+ }
164
+ function resolveRetentionDays(agentRetention, globalRetention) {
165
+ if (agentRetention !== undefined)
166
+ return agentRetention;
167
+ if (globalRetention !== undefined)
168
+ return globalRetention;
169
+ return DEFAULT_RETENTION_DAYS;
170
+ }
171
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/history/cleanup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { ChatSummary, HistoryMessage, MessagePage, PaginationOpts, SearchOpts, SearchPage, SessionSummary } from './types';
2
+ export declare class HistoryDB {
3
+ private readonly db;
4
+ private readonly insertStmt;
5
+ private readonly agentId;
6
+ private constructor();
7
+ static forAgent(agentsBaseDir: string, agentId: string): HistoryDB;
8
+ static forDir(agentDir: string, agentId: string): HistoryDB;
9
+ static evict(agentsBaseDir: string, agentId: string): void;
10
+ static evictDir(agentDir: string, agentId: string): void;
11
+ private _initSchema;
12
+ insertMessage(msg: HistoryMessage): void;
13
+ listChats(): ChatSummary[];
14
+ getMessages(chatId: string, opts?: PaginationOpts): MessagePage;
15
+ searchMessages(chatId: string, query: string, opts?: SearchOpts): SearchPage;
16
+ listSessions(): SessionSummary[];
17
+ clearChat(chatId: string): void;
18
+ clearSession(chatId: string, sessionId: string): string[];
19
+ /**
20
+ * Delete all messages older than cutoffMs (Unix ms timestamp).
21
+ * Returns relative media_files paths from deleted rows for disk cleanup.
22
+ * FTS5 index stays consistent via the AFTER DELETE trigger.
23
+ */
24
+ pruneOlderThan(cutoffMs: number): string[];
25
+ private _rowToMessage;
26
+ }
27
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/history/db.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,cAAc,EAEd,WAAW,EAEX,cAAc,EACd,UAAU,EACV,UAAU,EAEV,cAAc,EACf,MAAM,SAAS,CAAC;AASjB,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO;IAcP,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS;IAWlE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS;IAS3D,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1D,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIxD,OAAO,CAAC,WAAW;IAyCnB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAoBxC,SAAS,IAAI,WAAW,EAAE;IAqC1B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,WAAW;IAyCnE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,UAAU;IAgDhF,YAAY,IAAI,cAAc,EAAE;IAqChC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAYzD;;;;OAIG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAoB1C,OAAO,CAAC,aAAa;CAuBtB"}