thepopebot 1.2.76-beta.0 → 1.2.76-beta.11

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 (74) hide show
  1. package/api/index.js +56 -18
  2. package/bin/cli.js +16 -26
  3. package/drizzle/0021_coding_agent_workspace.sql +1 -0
  4. package/drizzle/0022_organic_apocalypse.sql +16 -0
  5. package/drizzle/meta/0021_snapshot.json +639 -0
  6. package/drizzle/meta/0022_snapshot.json +743 -0
  7. package/drizzle/meta/_journal.json +14 -0
  8. package/lib/ai/index.js +41 -23
  9. package/lib/ai/scope.js +26 -0
  10. package/lib/ai/sdk-adapters/CLAUDE.md +113 -0
  11. package/lib/ai/sdk-adapters/claude-code.js +100 -8
  12. package/lib/ai/system-prompt.js +19 -0
  13. package/lib/ai/tools.js +15 -2
  14. package/lib/ai/workspace-setup.js +18 -35
  15. package/lib/channels/CLAUDE.md +2 -2
  16. package/lib/channels/base.js +6 -2
  17. package/lib/channels/commands/index.js +42 -0
  18. package/lib/channels/commands/session.js +53 -0
  19. package/lib/channels/commands/verify.js +18 -0
  20. package/lib/channels/telegram.js +70 -19
  21. package/lib/chat/actions.js +208 -26
  22. package/lib/chat/api.js +153 -16
  23. package/lib/chat/components/chat-input.js +78 -33
  24. package/lib/chat/components/chat-input.jsx +74 -23
  25. package/lib/chat/components/chat.js +47 -8
  26. package/lib/chat/components/chat.jsx +50 -5
  27. package/lib/chat/components/code-mode-toggle.js +110 -14
  28. package/lib/chat/components/code-mode-toggle.jsx +104 -13
  29. package/lib/chat/components/index.js +1 -1
  30. package/lib/chat/components/message.js +3 -3
  31. package/lib/chat/components/message.jsx +3 -3
  32. package/lib/chat/components/profile-page.js +182 -4
  33. package/lib/chat/components/profile-page.jsx +196 -1
  34. package/lib/chat/components/scope-picker.js +21 -0
  35. package/lib/chat/components/scope-picker.jsx +27 -0
  36. package/lib/chat/components/settings-secrets-page.js +180 -75
  37. package/lib/chat/components/settings-secrets-page.jsx +212 -66
  38. package/lib/chat/components/ui/combobox.js +18 -2
  39. package/lib/chat/components/ui/combobox.jsx +17 -1
  40. package/lib/chat/telegram-profile.js +33 -0
  41. package/lib/code/actions.js +26 -6
  42. package/lib/code/terminal-view.js +36 -9
  43. package/lib/code/terminal-view.jsx +42 -10
  44. package/lib/config.js +7 -2
  45. package/lib/db/chats.js +9 -17
  46. package/lib/db/code-workspaces.js +6 -2
  47. package/lib/db/config.js +0 -1
  48. package/lib/db/schema.js +23 -1
  49. package/lib/db/user-channels.js +129 -0
  50. package/lib/maintenance.js +31 -21
  51. package/lib/tools/docker.js +30 -9
  52. package/lib/tools/github.js +16 -0
  53. package/lib/tools/telegram.js +106 -0
  54. package/lib/utils/render-md.js +44 -18
  55. package/package.json +3 -2
  56. package/setup/lib/targets.mjs +0 -2
  57. package/setup/lib/telegram.mjs +8 -69
  58. package/setup/setup-telegram.mjs +5 -36
  59. package/templates/.env.example +0 -7
  60. package/templates/.github/workflows/rebuild-event-handler.yml +1 -1
  61. package/templates/.gitignore.template +1 -3
  62. package/templates/CLAUDE.md +1 -1
  63. package/templates/CLAUDE.md.template +3 -2
  64. package/templates/agent-job/CLAUDE.md.template +1 -2
  65. package/templates/agent-job/SYSTEM.md +6 -6
  66. package/templates/coding-workspace/CLAUDE.md.template +7 -0
  67. package/templates/docker-compose.yml +1 -0
  68. package/templates/skills/CLAUDE.md.template +16 -23
  69. package/templates/skills/{library/agent-job-secrets → agent-job-secrets}/SKILL.md +2 -2
  70. package/setup/lib/telegram-verify.mjs +0 -63
  71. package/templates/agent-job/SOUL.md +0 -17
  72. /package/templates/{skills/active/.gitkeep → coding-workspace/SYSTEM.md} +0 -0
  73. /package/templates/skills/{library/agent-job-secrets → agent-job-secrets}/agent-job-secrets.js +0 -0
  74. /package/templates/skills/{library/playwright-cli → playwright-cli}/SKILL.md +0 -0
package/api/index.js CHANGED
@@ -1,9 +1,11 @@
1
- import { createHash, timingSafeEqual } from 'crypto';
1
+ import { createHash, timingSafeEqual, randomUUID } from 'crypto';
2
2
  import { createAgentJob } from '../lib/tools/create-agent-job.js';
3
3
  import { setWebhook } from '../lib/tools/telegram.js';
4
4
  import { getAgentJobStatus, fetchAgentJobLog } from '../lib/tools/github.js';
5
5
  import { getTelegramAdapter } from '../lib/channels/index.js';
6
- import { chat, summarizeAgentJob } from '../lib/ai/index.js';
6
+ import { dispatchCommand, dispatchPreAuthCommand } from '../lib/channels/commands/index.js';
7
+ import { getByChannelChatId, setActiveThread } from '../lib/db/user-channels.js';
8
+ import { chat, chatStream, summarizeAgentJob } from '../lib/ai/index.js';
7
9
  import { createNotification } from '../lib/db/notifications.js';
8
10
  import { loadTriggers } from '../lib/triggers.js';
9
11
  import { verifyApiKey } from '../lib/db/api-keys.js';
@@ -209,29 +211,65 @@ async function handleTelegramWebhook(request) {
209
211
  }
210
212
 
211
213
  /**
212
- * Process a normalized message through the AI layer with channel UX.
213
- * Message persistence is handled centrally by the AI layer.
214
+ * Resolve the incoming channel message to a user, dispatch any slash command,
215
+ * and otherwise stream the message through the AI layer using the user's
216
+ * active session.
214
217
  */
215
218
  async function processChannelMessage(adapter, normalized) {
216
- await adapter.acknowledge(normalized.metadata);
217
- const stopIndicator = adapter.startProcessingIndicator(normalized.metadata);
219
+ const { channel, channelChatId, metadata } = normalized;
220
+ const binding = getByChannelChatId(channel, channelChatId);
221
+
222
+ // Unbound chat → only /verify is accepted; everything else is silently ignored.
223
+ if (!binding || !binding.verifiedAt) {
224
+ const result = await dispatchPreAuthCommand(normalized, { channel, channelChatId });
225
+ if (result?.handled) {
226
+ await adapter.sendResponse(channelChatId, result.reply, metadata);
227
+ }
228
+ return;
229
+ }
230
+
231
+ const ctx = { channel, channelChatId, userId: binding.userId };
232
+
233
+ // Post-auth slash commands short-circuit the AI path.
234
+ const cmd = await dispatchCommand(normalized, ctx);
235
+ if (cmd?.handled) {
236
+ await adapter.sendResponse(channelChatId, cmd.reply, metadata);
237
+ return;
238
+ }
239
+
240
+ await adapter.acknowledge(metadata);
241
+ const stopIndicator = adapter.startProcessingIndicator(metadata);
218
242
 
219
243
  try {
220
- const response = await chat(
221
- normalized.threadId,
222
- normalized.text,
223
- normalized.attachments,
224
- { userId: 'telegram', chatTitle: 'Telegram' }
225
- );
226
- await adapter.sendResponse(normalized.threadId, response, normalized.metadata);
244
+ let threadId = binding.activeThreadId;
245
+ if (!threadId) {
246
+ threadId = randomUUID();
247
+ setActiveThread(binding.userId, channel, threadId);
248
+ }
249
+
250
+ const envRepo = process.env.GH_OWNER && process.env.GH_REPO
251
+ ? `${process.env.GH_OWNER}/${process.env.GH_REPO}`
252
+ : '';
253
+ const streamOptions = {
254
+ userId: binding.userId,
255
+ chatTitle: 'Telegram',
256
+ repo: envRepo,
257
+ branch: 'main',
258
+ codeMode: false,
259
+ codeModeType: 'code',
260
+ };
261
+
262
+ if (adapter.streamChatResponse) {
263
+ const chunks = chatStream(threadId, normalized.text, normalized.attachments, streamOptions);
264
+ await adapter.streamChatResponse(channelChatId, chunks);
265
+ } else {
266
+ const response = await chat(threadId, normalized.text, normalized.attachments, streamOptions);
267
+ await adapter.sendResponse(channelChatId, response, metadata);
268
+ }
227
269
  } catch (err) {
228
270
  console.error('Failed to process message with AI:', err);
229
271
  await adapter
230
- .sendResponse(
231
- normalized.threadId,
232
- 'Sorry, I encountered an error processing your message.',
233
- normalized.metadata
234
- )
272
+ .sendResponse(channelChatId, 'Sorry, I encountered an error processing your message.', metadata)
235
273
  .catch(() => {});
236
274
  } finally {
237
275
  stopIndicator();
package/bin/cli.js CHANGED
@@ -277,33 +277,23 @@ async function init() {
277
277
  }
278
278
  }
279
279
 
280
- // Create default skill activation symlinks
281
- const defaultSkills = [];
282
- const activeDir = path.join(cwd, 'skills', 'active');
283
- fs.mkdirSync(activeDir, { recursive: true });
284
- for (const skill of defaultSkills) {
285
- const symlink = path.join(activeDir, skill);
286
- if (!fs.existsSync(symlink)) {
287
- createDirLink(`../library/${skill}`, symlink);
288
- console.log(` Created skills/active/${skill} ../library/${skill}`);
280
+ // Create agent skill bridge symlinks (point to ../skills)
281
+ const skillBridges = [
282
+ { dir: '.pi', name: 'Pi' },
283
+ { dir: '.claude', name: 'Claude' },
284
+ { dir: '.codex', name: 'Codex' },
285
+ { dir: '.gemini', name: 'Gemini' },
286
+ { dir: '.kimi', name: 'Kimi' },
287
+ ];
288
+ for (const { dir, name } of skillBridges) {
289
+ const link = path.join(cwd, dir, 'skills');
290
+ if (!fs.existsSync(link)) {
291
+ fs.mkdirSync(path.dirname(link), { recursive: true });
292
+ createDirLink('../skills', link);
293
+ console.log(` Created ${dir}/skills → ../skills`);
289
294
  }
290
295
  }
291
296
 
292
- // Create .pi/skills → ../skills/active symlink
293
- const piSkillsLink = path.join(cwd, '.pi', 'skills');
294
- if (!fs.existsSync(piSkillsLink)) {
295
- fs.mkdirSync(path.dirname(piSkillsLink), { recursive: true });
296
- createDirLink('../skills/active', piSkillsLink);
297
- console.log(' Created .pi/skills → ../skills/active');
298
- }
299
-
300
- // Create .claude/skills → ../skills/active symlink
301
- const claudeSkillsLink = path.join(cwd, '.claude', 'skills');
302
- if (!fs.existsSync(claudeSkillsLink)) {
303
- fs.mkdirSync(path.dirname(claudeSkillsLink), { recursive: true });
304
- createDirLink('../skills/active', claudeSkillsLink);
305
- console.log(' Created .claude/skills → ../skills/active');
306
- }
307
297
 
308
298
  // Report backed-up files
309
299
  if (backedUp.length > 0) {
@@ -420,7 +410,7 @@ function reset(filePath) {
420
410
  console.log(` ${destPath(file)}`);
421
411
  }
422
412
  console.log('\nUsage: thepopebot reset <file>');
423
- console.log('Example: thepopebot reset agent-job/SOUL.md\n');
413
+ console.log('Example: thepopebot reset agent-job/SYSTEM.md\n');
424
414
  return;
425
415
  }
426
416
 
@@ -502,7 +492,7 @@ function diff(filePath) {
502
492
  console.log(' All files match package templates.');
503
493
  }
504
494
  console.log('\nUsage: thepopebot diff <file>');
505
- console.log('Example: thepopebot diff agent-job/SOUL.md\n');
495
+ console.log('Example: thepopebot diff agent-job/SYSTEM.md\n');
506
496
  return;
507
497
  }
508
498
 
@@ -0,0 +1 @@
1
+ ALTER TABLE `code_workspaces` ADD `coding_agent` text;
@@ -0,0 +1,16 @@
1
+ CREATE TABLE `user_channels` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `user_id` text NOT NULL,
4
+ `channel` text NOT NULL,
5
+ `channel_chat_id` text,
6
+ `code` text,
7
+ `code_expires_at` integer,
8
+ `verified_at` integer,
9
+ `active_thread_id` text,
10
+ `created_at` integer NOT NULL,
11
+ `updated_at` integer NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE UNIQUE INDEX `user_channels_user_channel_unique` ON `user_channels` (`user_id`,`channel`);--> statement-breakpoint
15
+ CREATE UNIQUE INDEX `user_channels_channel_chat_id_unique` ON `user_channels` (`channel`,`channel_chat_id`);--> statement-breakpoint
16
+ CREATE INDEX `user_channels_code_lookup` ON `user_channels` (`code`);