thepopebot 1.2.76-beta.27 → 1.2.76-beta.28
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/api/index.js +1 -10
- package/config/instrumentation.js +29 -1
- package/lib/cron.js +32 -4
- package/lib/triggers.js +38 -1
- package/package.json +1 -1
- package/templates/.github/workflows/rebuild-event-handler.yml +0 -5
package/api/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { dispatchCommand, dispatchPreAuthCommand } from '../lib/channels/command
|
|
|
7
7
|
import { getByChannelChatId, setActiveThread } from '../lib/db/user-channels.js';
|
|
8
8
|
import { chat, chatStream, summarizeAgentJob } from '../lib/ai/index.js';
|
|
9
9
|
import { createNotification } from '../lib/db/notifications.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getFireTriggers } from '../lib/triggers.js';
|
|
11
11
|
import { verifyApiKey } from '../lib/db/api-keys.js';
|
|
12
12
|
import { getConfig } from '../lib/config.js';
|
|
13
13
|
import { parseOAuthState, exchangeCodeForToken } from '../lib/oauth/helper.js';
|
|
@@ -19,8 +19,6 @@ const _refreshLocks = new Map();
|
|
|
19
19
|
// Bot token — resolved from DB/env, can be overridden by /telegram/register
|
|
20
20
|
let telegramBotToken = null;
|
|
21
21
|
|
|
22
|
-
// Cached trigger firing function (initialized on first request)
|
|
23
|
-
let _fireTriggers = null;
|
|
24
22
|
|
|
25
23
|
function getTelegramBotToken() {
|
|
26
24
|
if (!telegramBotToken) {
|
|
@@ -29,13 +27,6 @@ function getTelegramBotToken() {
|
|
|
29
27
|
return telegramBotToken;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
function getFireTriggers() {
|
|
33
|
-
if (!_fireTriggers) {
|
|
34
|
-
const result = loadTriggers();
|
|
35
|
-
_fireTriggers = result.fireTriggers;
|
|
36
|
-
}
|
|
37
|
-
return _fireTriggers;
|
|
38
|
-
}
|
|
39
30
|
|
|
40
31
|
// Routes that have their own authentication
|
|
41
32
|
const PUBLIC_ROUTES = ['/telegram/webhook', '/github/webhook', '/ping', '/oauth/callback'];
|
|
@@ -52,7 +52,7 @@ export async function register() {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// Start cron scheduler
|
|
55
|
-
const { loadCrons } = await import('../lib/cron.js');
|
|
55
|
+
const { loadCrons, reloadCrons } = await import('../lib/cron.js');
|
|
56
56
|
loadCrons();
|
|
57
57
|
|
|
58
58
|
// Start built-in crons (version check)
|
|
@@ -74,5 +74,33 @@ export async function register() {
|
|
|
74
74
|
const { startMaintenanceCron } = await import('../lib/maintenance.js');
|
|
75
75
|
startMaintenanceCron();
|
|
76
76
|
|
|
77
|
+
// Watch config files for hot reload (avoids full pm2 restart on git pull)
|
|
78
|
+
const { reloadTriggers } = await import('../lib/triggers.js');
|
|
79
|
+
const { default: chokidar } = await import('chokidar');
|
|
80
|
+
const { PROJECT_ROOT } = await import('../lib/paths.js');
|
|
81
|
+
const path = await import('path');
|
|
82
|
+
|
|
83
|
+
const cronsPath = path.join(PROJECT_ROOT, 'agent-job/CRONS.json');
|
|
84
|
+
const triggersPath = path.join(PROJECT_ROOT, 'event-handler/TRIGGERS.json');
|
|
85
|
+
|
|
86
|
+
const watcher = chokidar.watch([cronsPath, triggersPath], {
|
|
87
|
+
ignoreInitial: true,
|
|
88
|
+
awaitWriteFinish: { stabilityThreshold: 500 },
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
watcher.on('change', (filePath) => {
|
|
92
|
+
if (filePath.endsWith('CRONS.json')) {
|
|
93
|
+
console.log('[config watch] CRONS.json changed, reloading...');
|
|
94
|
+
reloadCrons();
|
|
95
|
+
} else if (filePath.endsWith('TRIGGERS.json')) {
|
|
96
|
+
console.log('[config watch] TRIGGERS.json changed, reloading...');
|
|
97
|
+
reloadTriggers();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
watcher.on('error', (err) => {
|
|
102
|
+
console.error('[config watch] Watcher error:', err.message);
|
|
103
|
+
});
|
|
104
|
+
|
|
77
105
|
console.log('thepopebot initialized');
|
|
78
106
|
}
|
package/lib/cron.js
CHANGED
|
@@ -4,6 +4,9 @@ import path from 'path';
|
|
|
4
4
|
import { PROJECT_ROOT } from './paths.js';
|
|
5
5
|
import { executeAction } from './actions.js';
|
|
6
6
|
|
|
7
|
+
// Active user cron tasks (module-scoped so reloadCrons can stop them)
|
|
8
|
+
let _cronTasks = [];
|
|
9
|
+
|
|
7
10
|
function getInstalledVersion() {
|
|
8
11
|
const pkgPath = path.join(process.cwd(), 'node_modules', 'thepopebot', 'package.json');
|
|
9
12
|
return JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;
|
|
@@ -228,7 +231,6 @@ function startBuiltinCrons() {
|
|
|
228
231
|
|
|
229
232
|
/**
|
|
230
233
|
* Load and schedule crons from CRONS.json
|
|
231
|
-
* @returns {Array} - Array of scheduled cron tasks
|
|
232
234
|
*/
|
|
233
235
|
function loadCrons() {
|
|
234
236
|
const cronFile = path.join(PROJECT_ROOT, 'agent-job/CRONS.json');
|
|
@@ -238,7 +240,8 @@ function loadCrons() {
|
|
|
238
240
|
if (!fs.existsSync(cronFile)) {
|
|
239
241
|
console.log('No CRONS.json found');
|
|
240
242
|
console.log('-----------------\n');
|
|
241
|
-
|
|
243
|
+
_cronTasks = [];
|
|
244
|
+
return;
|
|
242
245
|
}
|
|
243
246
|
|
|
244
247
|
const crons = JSON.parse(fs.readFileSync(cronFile, 'utf8'));
|
|
@@ -276,7 +279,32 @@ function loadCrons() {
|
|
|
276
279
|
|
|
277
280
|
console.log('-----------------\n');
|
|
278
281
|
|
|
279
|
-
|
|
282
|
+
_cronTasks = tasks;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Stop existing cron tasks and re-load from CRONS.json.
|
|
287
|
+
* If the new file is invalid, keeps existing tasks running.
|
|
288
|
+
*/
|
|
289
|
+
function reloadCrons() {
|
|
290
|
+
const cronFile = path.join(PROJECT_ROOT, 'agent-job/CRONS.json');
|
|
291
|
+
|
|
292
|
+
// Pre-validate before stopping anything
|
|
293
|
+
if (fs.existsSync(cronFile)) {
|
|
294
|
+
try {
|
|
295
|
+
JSON.parse(fs.readFileSync(cronFile, 'utf8'));
|
|
296
|
+
} catch (err) {
|
|
297
|
+
console.error(`[cron reload] Invalid JSON in CRONS.json, keeping existing schedule: ${err.message}`);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
for (const { task } of _cronTasks) {
|
|
303
|
+
task.stop();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
loadCrons();
|
|
307
|
+
console.log('[cron reload] Cron schedule reloaded');
|
|
280
308
|
}
|
|
281
309
|
|
|
282
|
-
export { loadCrons, startBuiltinCrons, getUpdateAvailable, setUpdateAvailable, getInstalledVersion, isPrerelease, runVersionCheck };
|
|
310
|
+
export { loadCrons, reloadCrons, startBuiltinCrons, getUpdateAvailable, setUpdateAvailable, getInstalledVersion, isPrerelease, runVersionCheck };
|
package/lib/triggers.js
CHANGED
|
@@ -3,6 +3,9 @@ import path from 'path';
|
|
|
3
3
|
import { PROJECT_ROOT } from './paths.js';
|
|
4
4
|
import { executeAction } from './actions.js';
|
|
5
5
|
|
|
6
|
+
// Cached fire function (module-scoped so reloadTriggers can reset it)
|
|
7
|
+
let _fireTriggers = null;
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* Replace {{body.field}} templates with values from request context
|
|
8
11
|
* @param {string} template - String with {{body.field}} placeholders
|
|
@@ -102,4 +105,38 @@ function loadTriggers() {
|
|
|
102
105
|
return { triggerMap, fireTriggers };
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Get the cached fire function, loading on first call.
|
|
110
|
+
*/
|
|
111
|
+
function getFireTriggers() {
|
|
112
|
+
if (!_fireTriggers) {
|
|
113
|
+
const result = loadTriggers();
|
|
114
|
+
_fireTriggers = result.fireTriggers;
|
|
115
|
+
}
|
|
116
|
+
return _fireTriggers;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Re-load triggers from TRIGGERS.json.
|
|
121
|
+
* If the new file is invalid, keeps existing triggers.
|
|
122
|
+
*/
|
|
123
|
+
function reloadTriggers() {
|
|
124
|
+
const triggerFile = path.join(PROJECT_ROOT, 'event-handler/TRIGGERS.json');
|
|
125
|
+
|
|
126
|
+
// Pre-validate before discarding anything
|
|
127
|
+
if (fs.existsSync(triggerFile)) {
|
|
128
|
+
try {
|
|
129
|
+
JSON.parse(fs.readFileSync(triggerFile, 'utf8'));
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error(`[trigger reload] Invalid JSON in TRIGGERS.json, keeping existing triggers: ${err.message}`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
_fireTriggers = null;
|
|
137
|
+
// Force re-load immediately so the log output shows
|
|
138
|
+
getFireTriggers();
|
|
139
|
+
console.log('[trigger reload] Triggers reloaded');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { loadTriggers, getFireTriggers, reloadTriggers };
|
package/package.json
CHANGED
|
@@ -68,11 +68,6 @@ jobs:
|
|
|
68
68
|
docker exec thepopebot-event-handler rm -f /tmp/.rebuild-status
|
|
69
69
|
echo "status=$STATUS" >> $GITHUB_OUTPUT
|
|
70
70
|
|
|
71
|
-
- name: Reload (no version change)
|
|
72
|
-
if: steps.pull.outputs.status == 'RELOAD'
|
|
73
|
-
run: |
|
|
74
|
-
docker exec thepopebot-event-handler gosu coding-agent pm2 reload all
|
|
75
|
-
|
|
76
71
|
- name: Pull new image and restart container
|
|
77
72
|
if: steps.pull.outputs.status == 'VERSION_CHANGED'
|
|
78
73
|
run: |
|