thepopebot 1.2.75-beta.7 → 1.2.75-beta.8

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/bin/cli.js CHANGED
@@ -248,6 +248,7 @@ async function init() {
248
248
  const pkg = {
249
249
  name: dirName,
250
250
  private: true,
251
+ type: 'module',
251
252
  scripts: {
252
253
  setup: 'thepopebot setup',
253
254
  'setup-telegram': 'thepopebot setup-telegram',
@@ -260,7 +261,15 @@ async function init() {
260
261
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
261
262
  console.log(' Created package.json');
262
263
  } else {
263
- console.log(' Skipped package.json (already exists)');
264
+ // Ensure "type": "module" is set for ESM support
265
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
266
+ if (!pkg.type) {
267
+ pkg.type = 'module';
268
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
269
+ console.log(' Added "type": "module" to package.json');
270
+ } else {
271
+ console.log(' Skipped package.json (already exists)');
272
+ }
264
273
  }
265
274
 
266
275
  // Create default skill activation symlinks
@@ -70,9 +70,9 @@ export async function register() {
70
70
  const { startClusterRuntime } = await import('../lib/cluster/runtime.js');
71
71
  startClusterRuntime();
72
72
 
73
- // Maintenance cron disabled agent job key cleanup will be redesigned
74
- // const { startMaintenanceCron } = await import('../lib/maintenance.js');
75
- // startMaintenanceCron();
73
+ // Start internal maintenance cron (cleanup orphaned agent job keys, etc.)
74
+ const { startMaintenanceCron } = await import('../lib/maintenance.js');
75
+ startMaintenanceCron();
76
76
 
77
77
  console.log('thepopebot initialized');
78
78
  }
@@ -154,12 +154,12 @@ export function verifyApiKey(rawKey) {
154
154
  }
155
155
 
156
156
  /**
157
- * Create a per-job API key for an agent job container.
158
- * Stored as type 'agent_job_api_key'.
159
- * @param {string} jobId - Agent job or workspace ID (stored as key column for traceability)
157
+ * Create a per-container API key for agent secret access.
158
+ * Stored as type 'agent_job_api_key' with the container name in the key column.
159
+ * @param {string} containerName - Docker container name (used for cleanup)
160
160
  * @returns {{ key: string }} The raw API key to inject into the container
161
161
  */
162
- export function createAgentJobApiKey(jobId) {
162
+ export function createAgentJobApiKey(containerName) {
163
163
  const db = getDb();
164
164
  const key = generateApiKey();
165
165
  const keyHash = hashApiKey(key);
@@ -167,7 +167,7 @@ export function createAgentJobApiKey(jobId) {
167
167
  db.insert(settings).values({
168
168
  id: randomUUID(),
169
169
  type: 'agent_job_api_key',
170
- key: jobId,
170
+ key: containerName,
171
171
  value: JSON.stringify({ key_hash: keyHash }),
172
172
  createdAt: now,
173
173
  updatedAt: now,
@@ -3,36 +3,54 @@ import { eq } from 'drizzle-orm';
3
3
  import { getDb } from './db/index.js';
4
4
  import { settings } from './db/schema.js';
5
5
 
6
- const ONE_HOUR = 60 * 60 * 1000;
6
+ const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000;
7
7
 
8
- function cleanExpiredAgentJobKeys() {
8
+ async function cleanExpiredAgentJobKeys() {
9
9
  try {
10
10
  const db = getDb();
11
- const cutoff = Date.now() - ONE_HOUR;
11
+ const cutoff = Date.now() - TWENTY_FOUR_HOURS;
12
12
  const rows = db
13
- .select({ id: settings.id, lastUsedAt: settings.lastUsedAt, createdAt: settings.createdAt })
13
+ .select({ id: settings.id, key: settings.key, lastUsedAt: settings.lastUsedAt, createdAt: settings.createdAt })
14
14
  .from(settings)
15
15
  .where(eq(settings.type, 'agent_job_api_key'))
16
16
  .all();
17
- const expiredIds = rows
18
- .filter(r => r.lastUsedAt !== null ? r.lastUsedAt < cutoff : r.createdAt < cutoff)
19
- .map(r => r.id);
17
+
18
+ // Filter to candidates not used in the last 24 hours
19
+ const candidates = rows.filter(r =>
20
+ (r.lastUsedAt !== null ? r.lastUsedAt : r.createdAt) < cutoff
21
+ );
22
+
23
+ if (candidates.length === 0) {
24
+ console.log(`[maintenance] No expired agent job keys (${rows.length} active)`);
25
+ return;
26
+ }
27
+
28
+ // Check if the container still exists for each candidate
29
+ const { inspectContainer } = await import('./tools/docker.js');
30
+ const expiredIds = [];
31
+ for (const r of candidates) {
32
+ const info = await inspectContainer(r.key);
33
+ if (!info) {
34
+ expiredIds.push(r.id);
35
+ }
36
+ }
37
+
20
38
  if (expiredIds.length > 0) {
21
39
  for (const id of expiredIds) {
22
40
  db.delete(settings).where(eq(settings.id, id)).run();
23
41
  }
24
- console.log(`[maintenance] Deleted ${expiredIds.length} expired agent job key(s)`);
42
+ console.log(`[maintenance] Deleted ${expiredIds.length} orphaned agent job key(s)`);
25
43
  } else {
26
- console.log(`[maintenance] No expired agent job keys (${rows.length} active)`);
44
+ console.log(`[maintenance] ${candidates.length} candidate(s) checked, all containers still running`);
27
45
  }
28
46
  } catch (err) {
29
47
  console.error('[maintenance] cleanExpiredAgentJobKeys failed:', err);
30
48
  }
31
49
  }
32
50
 
33
- function runMaintenance() {
51
+ async function runMaintenance() {
34
52
  console.log('[maintenance] Running maintenance...');
35
- cleanExpiredAgentJobKeys();
53
+ await cleanExpiredAgentJobKeys();
36
54
  }
37
55
 
38
56
  export function startMaintenanceCron() {
@@ -236,7 +236,7 @@ async function runInteractiveContainer({ containerName, repo, branch, codingAgen
236
236
  }
237
237
  // Create per-container API key for agent-secrets access
238
238
  const { createAgentJobApiKey } = await import('../db/api-keys.js');
239
- const { key: agentJobToken } = createAgentJobApiKey(workspaceId || containerName);
239
+ const { key: agentJobToken } = createAgentJobApiKey(containerName);
240
240
  env.push(`AGENT_JOB_TOKEN=${agentJobToken}`);
241
241
  const appUrl = getConfig('APP_URL');
242
242
  if (appUrl) env.push(`APP_URL=${appUrl}`);
@@ -449,7 +449,7 @@ async function runHeadlessContainer({ containerName, repo, branch, featureBranch
449
449
  }
450
450
  // Create per-container API key for agent-secrets access
451
451
  const { createAgentJobApiKey } = await import('../db/api-keys.js');
452
- const { key: agentJobToken } = createAgentJobApiKey(workspaceId || containerName);
452
+ const { key: agentJobToken } = createAgentJobApiKey(containerName);
453
453
  env.push(`AGENT_JOB_TOKEN=${agentJobToken}`);
454
454
  const appUrl = getConfig('APP_URL');
455
455
  if (appUrl) env.push(`APP_URL=${appUrl}`);
@@ -903,7 +903,7 @@ async function runAgentJobContainer({ agentJobId, repo, branch, title, descripti
903
903
 
904
904
  // Create per-container API key for agent-secrets access
905
905
  const { createAgentJobApiKey } = await import('../db/api-keys.js');
906
- const { key: agentJobToken } = createAgentJobApiKey(agentJobId);
906
+ const { key: agentJobToken } = createAgentJobApiKey(containerName);
907
907
  env.push(`AGENT_JOB_TOKEN=${agentJobToken}`);
908
908
 
909
909
  // Inject agent job secrets (plain secrets as env vars; oauth types are null — agent must fetch via get)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thepopebot",
3
- "version": "1.2.75-beta.7",
3
+ "version": "1.2.75-beta.8",
4
4
  "type": "module",
5
5
  "description": "Create autonomous AI agents with a two-layer architecture: Next.js Event Handler + Docker Agent.",
6
6
  "bin": {
@@ -7,14 +7,14 @@ description: List, get, or update agent secrets. Use get for OAuth credentials (
7
7
 
8
8
  ```bash
9
9
  # List available secrets (null = must fetch, plain = already in env)
10
- node skills/agent-job-secrets/agent-job-secrets.mjs
10
+ node skills/agent-job-secrets/agent-job-secrets.js
11
11
 
12
12
  # Get a secret value (OAuth credentials are auto-refreshed)
13
- node skills/agent-job-secrets/agent-job-secrets.mjs get MY_CREDENTIALS
13
+ node skills/agent-job-secrets/agent-job-secrets.js get MY_CREDENTIALS
14
14
 
15
15
  # Set/update a secret (plain string or piped value)
16
- node skills/agent-job-secrets/agent-job-secrets.mjs set MY_KEY "value"
17
- echo "$UPDATED_CREDENTIALS" | node skills/agent-job-secrets/agent-job-secrets.mjs set MY_KEY
16
+ node skills/agent-job-secrets/agent-job-secrets.js set MY_KEY "value"
17
+ echo "$UPDATED_CREDENTIALS" | node skills/agent-job-secrets/agent-job-secrets.js set MY_KEY
18
18
  ```
19
19
 
20
20
  ## Notes