thepopebot 1.2.78-beta.1 → 1.2.78-beta.2

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 CHANGED
@@ -109,14 +109,31 @@ the agent already knows what you were just talking about.
109
109
 
110
110
  ### Two steps
111
111
 
112
+ **1. Scaffold the project.**
113
+
112
114
  ```bash
113
115
  mkdir my-agent && cd my-agent
114
- npx thepopebot@latest init # scaffold project
115
- npm run setup # interactive wizard
116
+ npx thepopebot@latest init
117
+ ```
118
+
119
+ **2. Run the interactive setup wizard.**
120
+
121
+ ```bash
122
+ npm run setup
116
123
  ```
117
124
 
118
125
  The wizard checks prerequisites, creates a GitHub repo, generates a PAT, configures your URL, and starts Docker. Visit your APP_URL when it finishes.
119
126
 
127
+ ### After setup
128
+
129
+ Sign in at your APP_URL and configure these three, in order, before you can chat or run agent jobs:
130
+
131
+ 1. **Providers** — `/admin/event-handler/llms`. Add API keys for the LLM providers you want to use (Anthropic, OpenAI, Google, etc.). Everything else pulls from these credentials.
132
+ 2. **Helper LLM** — `/admin/event-handler/helper-llm`. Pick provider + model for one-shot calls (chat titles, agent-job titles, PR-merge summaries). Only providers with keys from step 1 appear here.
133
+ 3. **Coding agent** — `/admin/event-handler/coding-agents`. Pick which agent (Claude Code, Pi, Codex, Gemini, OpenCode, Kimi) drives live chat, code workspaces, and background agent jobs, and configure its model.
134
+
135
+ Optional: connect Telegram at `/admin/event-handler/telegram` to talk to your bot from your phone.
136
+
120
137
  > **Local installs**: your server needs to be reachable from the internet for GitHub webhooks and Telegram. Use [ngrok](https://ngrok.com) (`ngrok http 80`). If your ngrok URL changes, run `npx thepopebot set-var APP_URL <new-url>` and re-register the Telegram webhook from `/admin/event-handler/telegram`.
121
138
 
122
139
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thepopebot",
3
- "version": "1.2.78-beta.1",
3
+ "version": "1.2.78-beta.2",
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": {
package/setup/setup.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { execSync } from 'child_process';
4
- import http from 'http';
5
4
  import fs from 'fs';
6
5
  import path from 'path';
7
6
  import chalk from 'chalk';
@@ -436,86 +435,15 @@ async function main() {
436
435
  // ─── Step 5: Start Server ─────────────────────────────────────────────
437
436
  clack.log.step(`[${++currentStep}/${TOTAL_STEPS}] Start Server`);
438
437
 
439
- // Probe /login (not /api/ping) to confirm Next.js can actually render
440
- // the page, not just answer API routes. /login serves SetupForm on a
441
- // fresh install; LoginForm once a user exists. Either way it's HTML.
442
- // Traefik routes by Host(`${APP_HOSTNAME}`), so a bare localhost:80
443
- // request hits Traefik's default 404 — set the Host header to match.
444
- // node:http is used (not fetch) because undici silently strips Host.
445
- const appHostname = collected.APP_HOSTNAME;
446
- function isLoginPageReady(timeoutMs = 2000) {
447
- return new Promise((resolve) => {
448
- const req = http.request(
449
- {
450
- host: '127.0.0.1',
451
- port: 80,
452
- method: 'GET',
453
- path: '/login',
454
- headers: { Host: appHostname },
455
- timeout: timeoutMs,
456
- },
457
- (res) => {
458
- const ok = res.statusCode === 200 && (res.headers['content-type'] || '').includes('text/html');
459
- res.resume();
460
- resolve(ok);
461
- }
462
- );
463
- req.on('error', () => resolve(false));
464
- req.on('timeout', () => { req.destroy(); resolve(false); });
465
- req.end();
466
- });
467
- }
468
-
469
- let serverUp = await isLoginPageReady(3000);
470
-
471
- if (serverUp) {
472
- if (await confirm('Server is already running. Restart?')) {
473
- clack.log.info('Restarting server...');
474
- try {
475
- execSync('docker compose down && docker compose up -d', { stdio: 'inherit' });
476
- clack.log.success('Server restarted');
477
- serverUp = false; // Need to wait for it to come back up
478
- } catch (err) {
479
- const output = (err.stderr || err.stdout || err.message || '').toString().trim();
480
- clack.log.warn('Failed to restart.');
481
- if (output) clack.log.error(output);
482
- clack.log.info('Fix the issue above, then run: docker compose down && docker compose up -d');
483
- }
484
- }
485
- } else {
486
- clack.log.info('Starting server...');
487
- try {
488
- execSync('docker compose up -d', { stdio: 'inherit' });
489
- clack.log.success('Server started');
490
- } catch (err) {
491
- const output = (err.stderr || err.stdout || err.message || '').toString().trim();
492
- clack.log.warn('Failed to start.');
493
- if (output) clack.log.error(output);
494
- clack.log.info('Fix the issue above, then run: docker compose up -d');
495
- }
496
- }
497
-
498
- // Poll for the server to come up (max 60 seconds)
499
- if (!serverUp) {
500
- const pollSpinner = clack.spinner();
501
- pollSpinner.start('Waiting for server to come up...');
502
-
503
- const startTime = Date.now();
504
- const timeout = 60_000;
505
-
506
- while (Date.now() - startTime < timeout) {
507
- if (await isLoginPageReady()) {
508
- serverUp = true;
509
- break;
510
- }
511
- await new Promise((r) => setTimeout(r, 2000));
512
- }
513
-
514
- if (serverUp) {
515
- pollSpinner.stop('Server is up!');
516
- } else {
517
- pollSpinner.stop('Could not detect the server after 60 seconds.');
518
- }
438
+ clack.log.info('Starting server...');
439
+ try {
440
+ execSync('docker compose up -d', { stdio: 'inherit' });
441
+ clack.log.success('Server started');
442
+ } catch (err) {
443
+ const output = (err.stderr || err.stdout || err.message || '').toString().trim();
444
+ clack.log.warn('Failed to start.');
445
+ if (output) clack.log.error(output);
446
+ clack.log.info('Fix the issue above, then run: docker compose up -d');
519
447
  }
520
448
 
521
449
  // ─── Done ─────────────────────────────────────────────────────────────
@@ -527,23 +455,16 @@ async function main() {
527
455
 
528
456
  clack.note(summary, 'Configuration');
529
457
 
530
- // Only offer the link once the server is actually serving the login page.
531
- // /admin would 401 — a fresh install has no users yet, so the root sends
532
- // them to /login where the first-user setup form is shown.
533
- if (serverUp) {
534
- clack.log.info('Create your admin account, then configure your LLM provider, API keys, and agent settings under Admin.');
535
-
536
- if (canOpenBrowser()) {
537
- const open = (await import('open')).default;
538
- const shouldOpen = await confirm(`Open ${appUrl} in your browser?`, true);
539
- if (shouldOpen) {
540
- await open(appUrl);
541
- }
542
- } else {
543
- clack.log.info(`Visit ${appUrl} to create your admin account.`);
458
+ clack.log.info('Create your admin account, then configure your LLM provider, API keys, and agent settings under Admin.');
459
+
460
+ if (canOpenBrowser()) {
461
+ const open = (await import('open')).default;
462
+ const shouldOpen = await confirm(`Open ${appUrl} in your browser?`, true);
463
+ if (shouldOpen) {
464
+ await open(appUrl);
544
465
  }
545
466
  } else {
546
- clack.log.warn(`Server didn't respond. Check docker logs, then visit ${appUrl} to create your admin account.`);
467
+ clack.log.info(`Visit ${appUrl} to create your admin account.`);
547
468
  }
548
469
 
549
470
  clack.outro('Setup complete!');