@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.
- package/README.md +791 -0
- package/config.template.json +87 -0
- package/dist/agent/context-isolation.d.ts +28 -0
- package/dist/agent/context-isolation.d.ts.map +1 -0
- package/dist/agent/context-isolation.js +80 -0
- package/dist/agent/context-isolation.js.map +1 -0
- package/dist/agent/runner.d.ts +211 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +1802 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/workspace-loader.d.ts +31 -0
- package/dist/agent/workspace-loader.d.ts.map +1 -0
- package/dist/agent/workspace-loader.js +207 -0
- package/dist/agent/workspace-loader.js.map +1 -0
- package/dist/api/auth.d.ts +25 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +77 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/cron-router.d.ts +22 -0
- package/dist/api/cron-router.d.ts.map +1 -0
- package/dist/api/cron-router.js +197 -0
- package/dist/api/cron-router.js.map +1 -0
- package/dist/api/gateway-router.d.ts +52 -0
- package/dist/api/gateway-router.d.ts.map +1 -0
- package/dist/api/gateway-router.js +215 -0
- package/dist/api/gateway-router.js.map +1 -0
- package/dist/api/router.d.ts +5 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +1098 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/skills-router.d.ts +5 -0
- package/dist/api/skills-router.d.ts.map +1 -0
- package/dist/api/skills-router.js +424 -0
- package/dist/api/skills-router.js.map +1 -0
- package/dist/api/workspace-router.d.ts +4 -0
- package/dist/api/workspace-router.d.ts.map +1 -0
- package/dist/api/workspace-router.js +149 -0
- package/dist/api/workspace-router.js.map +1 -0
- package/dist/config/loader.d.ts +16 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +235 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/migrator.d.ts +70 -0
- package/dist/config/migrator.d.ts.map +1 -0
- package/dist/config/migrator.js +343 -0
- package/dist/config/migrator.js.map +1 -0
- package/dist/config/watcher.d.ts +30 -0
- package/dist/config/watcher.d.ts.map +1 -0
- package/dist/config/watcher.js +170 -0
- package/dist/config/watcher.js.map +1 -0
- package/dist/cron/manager.d.ts +48 -0
- package/dist/cron/manager.d.ts.map +1 -0
- package/dist/cron/manager.js +580 -0
- package/dist/cron/manager.js.map +1 -0
- package/dist/cron/scheduler.d.ts +50 -0
- package/dist/cron/scheduler.d.ts.map +1 -0
- package/dist/cron/scheduler.js +231 -0
- package/dist/cron/scheduler.js.map +1 -0
- package/dist/discord/receiver.d.ts +17 -0
- package/dist/discord/receiver.d.ts.map +1 -0
- package/dist/discord/receiver.js +108 -0
- package/dist/discord/receiver.js.map +1 -0
- package/dist/heartbeat/history.d.ts +24 -0
- package/dist/heartbeat/history.d.ts.map +1 -0
- package/dist/heartbeat/history.js +50 -0
- package/dist/heartbeat/history.js.map +1 -0
- package/dist/heartbeat/parser.d.ts +26 -0
- package/dist/heartbeat/parser.d.ts.map +1 -0
- package/dist/heartbeat/parser.js +283 -0
- package/dist/heartbeat/parser.js.map +1 -0
- package/dist/history/cleanup.d.ts +21 -0
- package/dist/history/cleanup.d.ts.map +1 -0
- package/dist/history/cleanup.js +171 -0
- package/dist/history/cleanup.js.map +1 -0
- package/dist/history/db.d.ts +27 -0
- package/dist/history/db.d.ts.map +1 -0
- package/dist/history/db.js +323 -0
- package/dist/history/db.js.map +1 -0
- package/dist/history/media-store.d.ts +27 -0
- package/dist/history/media-store.d.ts.map +1 -0
- package/dist/history/media-store.js +158 -0
- package/dist/history/media-store.js.map +1 -0
- package/dist/history/types.d.ts +62 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +3 -0
- package/dist/history/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +483 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +81 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/manager.d.ts +45 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +178 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/session/compactor.d.ts +22 -0
- package/dist/session/compactor.d.ts.map +1 -0
- package/dist/session/compactor.js +151 -0
- package/dist/session/compactor.js.map +1 -0
- package/dist/session/process.d.ts +76 -0
- package/dist/session/process.d.ts.map +1 -0
- package/dist/session/process.js +729 -0
- package/dist/session/process.js.map +1 -0
- package/dist/session/store.d.ts +102 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +533 -0
- package/dist/session/store.js.map +1 -0
- package/dist/skills/index.d.ts +9 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +15 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/invoker.d.ts +16 -0
- package/dist/skills/invoker.d.ts.map +1 -0
- package/dist/skills/invoker.js +36 -0
- package/dist/skills/invoker.js.map +1 -0
- package/dist/skills/loader.d.ts +23 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +183 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/parser.d.ts +55 -0
- package/dist/skills/parser.d.ts.map +1 -0
- package/dist/skills/parser.js +178 -0
- package/dist/skills/parser.js.map +1 -0
- package/dist/skills/sync.d.ts +10 -0
- package/dist/skills/sync.d.ts.map +1 -0
- package/dist/skills/sync.js +130 -0
- package/dist/skills/sync.js.map +1 -0
- package/dist/skills/watcher.d.ts +16 -0
- package/dist/skills/watcher.d.ts.map +1 -0
- package/dist/skills/watcher.js +25 -0
- package/dist/skills/watcher.js.map +1 -0
- package/dist/telegram/markdown.d.ts +25 -0
- package/dist/telegram/markdown.d.ts.map +1 -0
- package/dist/telegram/markdown.js +237 -0
- package/dist/telegram/markdown.js.map +1 -0
- package/dist/telegram/receiver.d.ts +17 -0
- package/dist/telegram/receiver.d.ts.map +1 -0
- package/dist/telegram/receiver.js +104 -0
- package/dist/telegram/receiver.js.map +1 -0
- package/dist/types.d.ts +224 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/web-ui.d.ts +6 -0
- package/dist/ui/web-ui.d.ts.map +1 -0
- package/dist/ui/web-ui.js +227 -0
- package/dist/ui/web-ui.js.map +1 -0
- package/dist/watch/factory.d.ts +26 -0
- package/dist/watch/factory.d.ts.map +1 -0
- package/dist/watch/factory.js +43 -0
- package/dist/watch/factory.js.map +1 -0
- package/dist/webhook/manager.d.ts +34 -0
- package/dist/webhook/manager.d.ts.map +1 -0
- package/dist/webhook/manager.js +120 -0
- package/dist/webhook/manager.js.map +1 -0
- package/mcp/bun.lock +264 -0
- package/mcp/channel-manager.ts +115 -0
- package/mcp/package.json +15 -0
- package/mcp/router.ts +69 -0
- package/mcp/server.ts +129 -0
- package/mcp/tools/agent/handlers.ts +578 -0
- package/mcp/tools/agent/module.ts +163 -0
- package/mcp/tools/browser/module.ts +321 -0
- package/mcp/tools/browser/skills/open-browser/SKILL.md +89 -0
- package/mcp/tools/cron/client.ts +65 -0
- package/mcp/tools/cron/module.ts +158 -0
- package/mcp/tools/cron/skills/cron/SKILL.md +46 -0
- package/mcp/tools/discord/access.ts +197 -0
- package/mcp/tools/discord/client.ts +31 -0
- package/mcp/tools/discord/commands.ts +48 -0
- package/mcp/tools/discord/inbound.ts +53 -0
- package/mcp/tools/discord/module.ts +442 -0
- package/mcp/tools/discord/outbound.ts +90 -0
- package/mcp/tools/discord/receiver-server.ts +58 -0
- package/mcp/tools/discord/skills/access/SKILL.md +86 -0
- package/mcp/tools/discord/skills/configure/SKILL.md +53 -0
- package/mcp/tools/discord/threading.ts +37 -0
- package/mcp/tools/discord/types.ts +106 -0
- package/mcp/tools/skills/handlers.ts +196 -0
- package/mcp/tools/skills/module.ts +163 -0
- package/mcp/tools/telegram/module.ts +454 -0
- package/mcp/tools/telegram/pure.ts +224 -0
- package/mcp/tools/telegram/receiver-server.ts +1656 -0
- package/mcp/tools/telegram/skills/access/SKILL.md +169 -0
- package/mcp/tools/telegram/skills/configure/SKILL.md +118 -0
- package/mcp/tools/telegram/typing.ts +327 -0
- package/mcp/types.ts +128 -0
- package/package.json +62 -0
- 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"}
|