thepopebot 1.1.2 → 1.2.3
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 +1 -1
- package/api/index.js +72 -165
- package/bin/cli.js +36 -6
- package/bin/local.sh +31 -0
- package/bin/postinstall.js +6 -2
- package/config/index.js +2 -11
- package/config/instrumentation.js +17 -5
- package/lib/actions.js +7 -6
- package/lib/ai/agent.js +36 -0
- package/lib/ai/index.js +274 -0
- package/lib/ai/model.js +67 -0
- package/lib/ai/tools.js +49 -0
- package/lib/auth/actions.js +28 -0
- package/lib/auth/config.js +45 -0
- package/lib/auth/index.js +27 -0
- package/lib/auth/middleware.js +30 -0
- package/lib/channels/base.js +56 -0
- package/lib/channels/index.js +15 -0
- package/lib/channels/telegram.js +146 -0
- package/lib/chat/actions.js +239 -0
- package/lib/chat/api.js +103 -0
- package/lib/chat/components/app-sidebar.js +161 -0
- package/lib/chat/components/app-sidebar.jsx +214 -0
- package/lib/chat/components/chat-header.js +9 -0
- package/lib/chat/components/chat-header.jsx +14 -0
- package/lib/chat/components/chat-input.js +230 -0
- package/lib/chat/components/chat-input.jsx +232 -0
- package/lib/chat/components/chat-nav-context.js +11 -0
- package/lib/chat/components/chat-nav-context.jsx +11 -0
- package/lib/chat/components/chat-page.js +70 -0
- package/lib/chat/components/chat-page.jsx +89 -0
- package/lib/chat/components/chat.js +78 -0
- package/lib/chat/components/chat.jsx +91 -0
- package/lib/chat/components/chats-page.js +170 -0
- package/lib/chat/components/chats-page.jsx +203 -0
- package/lib/chat/components/crons-page.js +144 -0
- package/lib/chat/components/crons-page.jsx +204 -0
- package/lib/chat/components/greeting.js +11 -0
- package/lib/chat/components/greeting.jsx +14 -0
- package/lib/chat/components/icons.js +518 -0
- package/lib/chat/components/icons.jsx +482 -0
- package/lib/chat/components/index.js +19 -0
- package/lib/chat/components/message.js +66 -0
- package/lib/chat/components/message.jsx +92 -0
- package/lib/chat/components/messages.js +63 -0
- package/lib/chat/components/messages.jsx +72 -0
- package/lib/chat/components/notifications-page.js +54 -0
- package/lib/chat/components/notifications-page.jsx +83 -0
- package/lib/chat/components/page-layout.js +21 -0
- package/lib/chat/components/page-layout.jsx +28 -0
- package/lib/chat/components/settings-layout.js +37 -0
- package/lib/chat/components/settings-layout.jsx +51 -0
- package/lib/chat/components/settings-secrets-page.js +216 -0
- package/lib/chat/components/settings-secrets-page.jsx +264 -0
- package/lib/chat/components/sidebar-history-item.js +54 -0
- package/lib/chat/components/sidebar-history-item.jsx +50 -0
- package/lib/chat/components/sidebar-history.js +92 -0
- package/lib/chat/components/sidebar-history.jsx +132 -0
- package/lib/chat/components/sidebar-user-nav.js +59 -0
- package/lib/chat/components/sidebar-user-nav.jsx +69 -0
- package/lib/chat/components/swarm-page.js +250 -0
- package/lib/chat/components/swarm-page.jsx +356 -0
- package/lib/chat/components/triggers-page.js +121 -0
- package/lib/chat/components/triggers-page.jsx +177 -0
- package/lib/chat/components/ui/dropdown-menu.js +98 -0
- package/lib/chat/components/ui/dropdown-menu.jsx +116 -0
- package/lib/chat/components/ui/scroll-area.js +13 -0
- package/lib/chat/components/ui/scroll-area.jsx +17 -0
- package/lib/chat/components/ui/separator.js +21 -0
- package/lib/chat/components/ui/separator.jsx +18 -0
- package/lib/chat/components/ui/sheet.js +75 -0
- package/lib/chat/components/ui/sheet.jsx +95 -0
- package/lib/chat/components/ui/sidebar.js +227 -0
- package/lib/chat/components/ui/sidebar.jsx +245 -0
- package/lib/chat/components/ui/tooltip.js +56 -0
- package/lib/chat/components/ui/tooltip.jsx +66 -0
- package/lib/chat/utils.js +11 -0
- package/lib/cron.js +7 -8
- package/lib/db/api-keys.js +160 -0
- package/lib/db/chats.js +129 -0
- package/lib/db/index.js +106 -0
- package/lib/db/notifications.js +99 -0
- package/lib/db/schema.js +51 -0
- package/lib/db/users.js +89 -0
- package/lib/paths.js +23 -17
- package/lib/tools/create-job.js +3 -3
- package/lib/tools/github.js +145 -1
- package/lib/tools/openai.js +1 -1
- package/lib/tools/telegram.js +4 -3
- package/lib/triggers.js +6 -7
- package/lib/utils/render-md.js +6 -6
- package/package.json +43 -6
- package/setup/lib/auth.mjs +22 -9
- package/setup/lib/prerequisites.mjs +10 -3
- package/setup/lib/telegram-verify.mjs +3 -16
- package/setup/setup-telegram.mjs +31 -62
- package/setup/setup.mjs +58 -98
- package/templates/.dockerignore +5 -0
- package/templates/.env.example +18 -2
- package/templates/.github/workflows/auto-merge.yml +1 -1
- package/templates/.github/workflows/build-image.yml +6 -4
- package/templates/.github/workflows/notify-job-failed.yml +2 -2
- package/templates/.github/workflows/notify-pr-complete.yml +2 -2
- package/templates/.github/workflows/run-job.yml +24 -10
- package/templates/CLAUDE.md +5 -3
- package/templates/app/api/auth/[...nextauth]/route.js +1 -0
- package/templates/app/api/chat/route.js +1 -0
- package/templates/app/chat/[chatId]/page.js +8 -0
- package/templates/app/chats/page.js +7 -0
- package/templates/app/components/ascii-logo.jsx +10 -0
- package/templates/app/components/login-form.jsx +81 -0
- package/templates/app/components/setup-form.jsx +82 -0
- package/templates/app/components/theme-provider.jsx +11 -0
- package/templates/app/components/theme-toggle.jsx +38 -0
- package/templates/app/components/ui/button.jsx +21 -0
- package/templates/app/components/ui/card.jsx +23 -0
- package/templates/app/components/ui/input.jsx +10 -0
- package/templates/app/components/ui/label.jsx +10 -0
- package/templates/app/crons/page.js +7 -0
- package/templates/app/globals.css +66 -0
- package/templates/app/layout.js +9 -2
- package/templates/app/login/page.js +15 -0
- package/templates/app/notifications/page.js +7 -0
- package/templates/app/page.js +6 -30
- package/templates/app/settings/layout.js +7 -0
- package/templates/app/settings/page.js +5 -0
- package/templates/app/settings/secrets/page.js +5 -0
- package/templates/app/swarm/page.js +7 -0
- package/templates/app/triggers/page.js +7 -0
- package/templates/config/CRONS.json +2 -2
- package/templates/config/TRIGGERS.json +2 -2
- package/templates/docker/event_handler/Dockerfile +19 -0
- package/templates/docker/{entrypoint.sh → job/entrypoint.sh} +4 -4
- package/templates/docker/runner/Dockerfile +38 -0
- package/templates/docker/runner/entrypoint.sh +41 -0
- package/templates/docker-compose.yml +52 -0
- package/templates/instrumentation.js +6 -1
- package/templates/middleware.js +1 -0
- package/templates/postcss.config.mjs +5 -0
- package/lib/claude/conversation.js +0 -76
- package/lib/claude/index.js +0 -142
- package/lib/claude/tools.js +0 -54
- /package/templates/docker/{Dockerfile → job/Dockerfile} +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { Button } from './ui/button';
|
|
6
|
+
import { Input } from './ui/input';
|
|
7
|
+
import { Label } from './ui/label';
|
|
8
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from './ui/card';
|
|
9
|
+
import { setupAdmin } from 'thepopebot/auth/actions';
|
|
10
|
+
|
|
11
|
+
export function SetupForm() {
|
|
12
|
+
const router = useRouter();
|
|
13
|
+
const [email, setEmail] = useState('');
|
|
14
|
+
const [password, setPassword] = useState('');
|
|
15
|
+
const [error, setError] = useState('');
|
|
16
|
+
const [loading, setLoading] = useState(false);
|
|
17
|
+
|
|
18
|
+
async function handleSubmit(e) {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
setError('');
|
|
21
|
+
setLoading(true);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const result = await setupAdmin(email, password);
|
|
25
|
+
|
|
26
|
+
if (result.error) {
|
|
27
|
+
setError(result.error);
|
|
28
|
+
setLoading(false);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Redirect to login — admin must authenticate through the normal flow
|
|
33
|
+
router.push('/login');
|
|
34
|
+
} catch {
|
|
35
|
+
setError('Something went wrong. Please try again.');
|
|
36
|
+
} finally {
|
|
37
|
+
setLoading(false);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Card className="w-full max-w-sm">
|
|
43
|
+
<CardHeader>
|
|
44
|
+
<CardTitle>Create Admin Account</CardTitle>
|
|
45
|
+
<CardDescription>Set up your first admin account to get started.</CardDescription>
|
|
46
|
+
</CardHeader>
|
|
47
|
+
<CardContent>
|
|
48
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
49
|
+
<div className="space-y-2">
|
|
50
|
+
<Label htmlFor="email">Email</Label>
|
|
51
|
+
<Input
|
|
52
|
+
id="email"
|
|
53
|
+
type="email"
|
|
54
|
+
placeholder="admin@example.com"
|
|
55
|
+
value={email}
|
|
56
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
57
|
+
required
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
<div className="space-y-2">
|
|
61
|
+
<Label htmlFor="password">Password</Label>
|
|
62
|
+
<Input
|
|
63
|
+
id="password"
|
|
64
|
+
type="password"
|
|
65
|
+
placeholder="Min 8 characters"
|
|
66
|
+
value={password}
|
|
67
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
68
|
+
required
|
|
69
|
+
minLength={8}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
{error && (
|
|
73
|
+
<p className="text-sm text-destructive">{error}</p>
|
|
74
|
+
)}
|
|
75
|
+
<Button type="submit" className="w-full" disabled={loading}>
|
|
76
|
+
{loading ? 'Creating...' : 'Create Account'}
|
|
77
|
+
</Button>
|
|
78
|
+
</form>
|
|
79
|
+
</CardContent>
|
|
80
|
+
</Card>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
|
4
|
+
|
|
5
|
+
export function ThemeProvider({ children }) {
|
|
6
|
+
return (
|
|
7
|
+
<NextThemesProvider attribute="class" defaultTheme="system" enableSystem>
|
|
8
|
+
{children}
|
|
9
|
+
</NextThemesProvider>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useTheme } from 'next-themes';
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
export function ThemeToggle() {
|
|
7
|
+
const { theme, setTheme } = useTheme();
|
|
8
|
+
const [mounted, setMounted] = useState(false);
|
|
9
|
+
|
|
10
|
+
useEffect(() => setMounted(true), []);
|
|
11
|
+
|
|
12
|
+
if (!mounted) return <div className="h-[34px] w-[106px]" />;
|
|
13
|
+
|
|
14
|
+
const options = [
|
|
15
|
+
{ value: 'light', label: '☀️' },
|
|
16
|
+
{ value: 'dark', label: '🌙' },
|
|
17
|
+
{ value: 'system', label: '💻' },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="flex items-center gap-1 rounded-md border border-border bg-muted p-1">
|
|
22
|
+
{options.map((opt) => (
|
|
23
|
+
<button
|
|
24
|
+
key={opt.value}
|
|
25
|
+
onClick={() => setTheme(opt.value)}
|
|
26
|
+
className={`rounded px-2 py-1 text-sm transition-colors ${
|
|
27
|
+
theme === opt.value
|
|
28
|
+
? 'bg-background text-foreground shadow-sm'
|
|
29
|
+
: 'text-muted-foreground hover:text-foreground'
|
|
30
|
+
}`}
|
|
31
|
+
title={opt.value.charAt(0).toUpperCase() + opt.value.slice(1)}
|
|
32
|
+
>
|
|
33
|
+
{opt.label}
|
|
34
|
+
</button>
|
|
35
|
+
))}
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
export function Button({ children, variant = 'default', className = '', disabled, ...props }) {
|
|
4
|
+
const base = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 px-4 py-2';
|
|
5
|
+
|
|
6
|
+
const variants = {
|
|
7
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
8
|
+
outline: 'border border-border bg-transparent text-foreground hover:bg-muted',
|
|
9
|
+
ghost: 'text-foreground hover:bg-muted',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<button
|
|
14
|
+
className={`${base} ${variants[variant] || variants.default} ${className}`}
|
|
15
|
+
disabled={disabled}
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</button>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function Card({ children, className = '' }) {
|
|
2
|
+
return (
|
|
3
|
+
<div className={`rounded-lg border border-border bg-muted p-6 ${className}`}>
|
|
4
|
+
{children}
|
|
5
|
+
</div>
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function CardHeader({ children, className = '' }) {
|
|
10
|
+
return <div className={`mb-4 ${className}`}>{children}</div>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function CardTitle({ children, className = '' }) {
|
|
14
|
+
return <h2 className={`text-lg font-semibold text-foreground ${className}`}>{children}</h2>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function CardDescription({ children, className = '' }) {
|
|
18
|
+
return <p className={`text-sm text-muted-foreground ${className}`}>{children}</p>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function CardContent({ children, className = '' }) {
|
|
22
|
+
return <div className={className}>{children}</div>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
export function Input({ className = '', ...props }) {
|
|
4
|
+
return (
|
|
5
|
+
<input
|
|
6
|
+
className={`flex h-10 w-full rounded-md border border-border bg-input px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${className}`}
|
|
7
|
+
{...props}
|
|
8
|
+
/>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "streamdown/styles.css";
|
|
3
|
+
@source "../node_modules/thepopebot/lib/**/*.{js,jsx}";
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--background: #ffffff;
|
|
7
|
+
--foreground: #171717;
|
|
8
|
+
--primary: #171717;
|
|
9
|
+
--primary-foreground: #ffffff;
|
|
10
|
+
--muted: #f5f5f5;
|
|
11
|
+
--muted-foreground: #737373;
|
|
12
|
+
--border: #e5e5e5;
|
|
13
|
+
--input: #f5f5f5;
|
|
14
|
+
--ring: #171717;
|
|
15
|
+
--destructive: #dc2626;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.dark {
|
|
19
|
+
--background: #0a0a0a;
|
|
20
|
+
--foreground: #ededed;
|
|
21
|
+
--primary: #ededed;
|
|
22
|
+
--primary-foreground: #0a0a0a;
|
|
23
|
+
--muted: #171717;
|
|
24
|
+
--muted-foreground: #a3a3a3;
|
|
25
|
+
--border: #262626;
|
|
26
|
+
--input: #171717;
|
|
27
|
+
--ring: #ededed;
|
|
28
|
+
--destructive: #ef4444;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@theme inline {
|
|
32
|
+
--color-background: var(--background);
|
|
33
|
+
--color-foreground: var(--foreground);
|
|
34
|
+
--color-primary: var(--primary);
|
|
35
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
36
|
+
--color-muted: var(--muted);
|
|
37
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
38
|
+
--color-border: var(--border);
|
|
39
|
+
--color-input: var(--input);
|
|
40
|
+
--color-ring: var(--ring);
|
|
41
|
+
--color-destructive: var(--destructive);
|
|
42
|
+
--font-sans: system-ui, -apple-system, sans-serif;
|
|
43
|
+
--font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
|
|
44
|
+
--radius-sm: 0.375rem;
|
|
45
|
+
--radius-md: 0.5rem;
|
|
46
|
+
--radius-lg: 0.75rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Scrollbar styling */
|
|
50
|
+
.scrollbar-thin {
|
|
51
|
+
scrollbar-width: thin;
|
|
52
|
+
scrollbar-color: var(--border) transparent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.scrollbar-thin::-webkit-scrollbar {
|
|
56
|
+
width: 6px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.scrollbar-thin::-webkit-scrollbar-track {
|
|
60
|
+
background: transparent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.scrollbar-thin::-webkit-scrollbar-thumb {
|
|
64
|
+
background-color: var(--border);
|
|
65
|
+
border-radius: 3px;
|
|
66
|
+
}
|
package/templates/app/layout.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import './globals.css';
|
|
2
|
+
import { ThemeProvider } from './components/theme-provider';
|
|
3
|
+
|
|
1
4
|
export const metadata = {
|
|
2
5
|
title: 'thepopebot',
|
|
3
6
|
description: 'AI Agent',
|
|
@@ -5,8 +8,12 @@ export const metadata = {
|
|
|
5
8
|
|
|
6
9
|
export default function RootLayout({ children }) {
|
|
7
10
|
return (
|
|
8
|
-
<html lang="en">
|
|
9
|
-
<body
|
|
11
|
+
<html lang="en" suppressHydrationWarning>
|
|
12
|
+
<body className="min-h-screen bg-background text-foreground antialiased">
|
|
13
|
+
<ThemeProvider>
|
|
14
|
+
{children}
|
|
15
|
+
</ThemeProvider>
|
|
16
|
+
</body>
|
|
10
17
|
</html>
|
|
11
18
|
);
|
|
12
19
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getPageAuthState } from 'thepopebot/auth';
|
|
2
|
+
import { AsciiLogo } from '../components/ascii-logo';
|
|
3
|
+
import { SetupForm } from '../components/setup-form';
|
|
4
|
+
import { LoginForm } from '../components/login-form';
|
|
5
|
+
|
|
6
|
+
export default async function LoginPage() {
|
|
7
|
+
const { needsSetup } = await getPageAuthState();
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<main className="min-h-screen flex flex-col items-center justify-center p-8">
|
|
11
|
+
<AsciiLogo />
|
|
12
|
+
{needsSetup ? <SetupForm /> : <LoginForm />}
|
|
13
|
+
</main>
|
|
14
|
+
);
|
|
15
|
+
}
|
package/templates/app/page.js
CHANGED
|
@@ -1,31 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
display: 'flex',
|
|
8
|
-
flexDirection: 'column',
|
|
9
|
-
alignItems: 'center',
|
|
10
|
-
justifyContent: 'center',
|
|
11
|
-
fontFamily: 'system-ui, sans-serif',
|
|
12
|
-
padding: '2rem',
|
|
13
|
-
}}>
|
|
14
|
-
<pre style={{
|
|
15
|
-
color: '#00e5ff',
|
|
16
|
-
fontSize: 'clamp(0.45rem, 1.5vw, 0.85rem)',
|
|
17
|
-
lineHeight: 1.3,
|
|
18
|
-
textAlign: 'left',
|
|
19
|
-
marginBottom: '2rem',
|
|
20
|
-
}}>{` _____ _ ____ ____ _
|
|
21
|
-
|_ _| |__ ___| _ \\ ___ _ __ ___| __ ) ___ | |_
|
|
22
|
-
| | | '_ \\ / _ \\ |_) / _ \\| '_ \\ / _ \\ _ \\ / _ \\| __|
|
|
23
|
-
| | | | | | __/ __/ (_) | |_) | __/ |_) | (_) | |_
|
|
24
|
-
|_| |_| |_|\\___|_| \\___/| .__/ \\___|____/ \\___/ \\__|
|
|
25
|
-
|_|`}</pre>
|
|
26
|
-
<p style={{ color: '#888', fontSize: '1rem' }}>
|
|
27
|
-
Your AI agent is running.
|
|
28
|
-
</p>
|
|
29
|
-
</main>
|
|
30
|
-
);
|
|
1
|
+
import { auth } from 'thepopebot/auth';
|
|
2
|
+
import { ChatPage } from 'thepopebot/chat';
|
|
3
|
+
|
|
4
|
+
export default async function Home() {
|
|
5
|
+
const session = await auth();
|
|
6
|
+
return <ChatPage session={session} needsSetup={false} />;
|
|
31
7
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
{
|
|
31
31
|
"name": "ping-status",
|
|
32
32
|
"schedule": "*/5 * * * *",
|
|
33
|
-
"type": "
|
|
33
|
+
"type": "webhook",
|
|
34
34
|
"url": "https://example.com/status",
|
|
35
35
|
"method": "POST",
|
|
36
36
|
"vars": { "source": "heartbeat" },
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
{
|
|
40
40
|
"name": "health-check",
|
|
41
41
|
"schedule": "*/10 * * * *",
|
|
42
|
-
"type": "
|
|
42
|
+
"type": "webhook",
|
|
43
43
|
"url": "https://example.com/health",
|
|
44
44
|
"method": "GET",
|
|
45
45
|
"enabled": false
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"name": "forward-github",
|
|
36
36
|
"watch_path": "/github/webhook",
|
|
37
37
|
"actions": [
|
|
38
|
-
{ "type": "
|
|
38
|
+
{ "type": "webhook", "url": "https://example.com/hook", "method": "POST", "vars": { "source": "github" } }
|
|
39
39
|
],
|
|
40
40
|
"enabled": false
|
|
41
41
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"name": "forward-webhook",
|
|
44
44
|
"watch_path": "/webhook",
|
|
45
45
|
"actions": [
|
|
46
|
-
{ "type": "
|
|
46
|
+
{ "type": "webhook", "url": "https://example.com/hook", "method": "POST", "vars": { "source": "webhook" } }
|
|
47
47
|
],
|
|
48
48
|
"enabled": false
|
|
49
49
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
FROM node:22-bookworm-slim
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get install -y \
|
|
4
|
+
curl \
|
|
5
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY package.json package-lock.json* ./
|
|
10
|
+
|
|
11
|
+
RUN npm install --omit=dev
|
|
12
|
+
|
|
13
|
+
COPY . .
|
|
14
|
+
|
|
15
|
+
RUN npm run build
|
|
16
|
+
|
|
17
|
+
EXPOSE 80
|
|
18
|
+
|
|
19
|
+
CMD ["npx", "next", "start", "-p", "80"]
|
|
@@ -73,11 +73,11 @@ PROMPT="
|
|
|
73
73
|
|
|
74
74
|
$(cat /job/logs/${JOB_ID}/job.md)"
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
LLM_PROVIDER="${LLM_PROVIDER:-anthropic}"
|
|
77
77
|
|
|
78
|
-
MODEL_FLAGS="--provider $
|
|
79
|
-
if [ -n "$
|
|
80
|
-
MODEL_FLAGS="$MODEL_FLAGS --model $
|
|
78
|
+
MODEL_FLAGS="--provider $LLM_PROVIDER"
|
|
79
|
+
if [ -n "$LLM_MODEL" ]; then
|
|
80
|
+
MODEL_FLAGS="$MODEL_FLAGS --model $LLM_MODEL"
|
|
81
81
|
fi
|
|
82
82
|
|
|
83
83
|
# Copy custom models.json to PI's global config if present in repo
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
FROM ubuntu:24.04
|
|
2
|
+
|
|
3
|
+
ARG RUNNER_VERSION=2.321.0
|
|
4
|
+
ARG RUNNER_ARCH=x64
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y \
|
|
7
|
+
curl \
|
|
8
|
+
jq \
|
|
9
|
+
git \
|
|
10
|
+
ca-certificates \
|
|
11
|
+
gnupg \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
14
|
+
# Install Docker CLI (talks to host daemon via socket)
|
|
15
|
+
RUN install -m 0755 -d /etc/apt/keyrings \
|
|
16
|
+
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
|
17
|
+
&& chmod a+r /etc/apt/keyrings/docker.gpg \
|
|
18
|
+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list \
|
|
19
|
+
&& apt-get update && apt-get install -y docker-ce-cli \
|
|
20
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
21
|
+
|
|
22
|
+
# Create non-root runner user
|
|
23
|
+
RUN useradd -m -s /bin/bash runner \
|
|
24
|
+
&& usermod -aG root runner
|
|
25
|
+
|
|
26
|
+
# Download and extract GitHub Actions runner
|
|
27
|
+
WORKDIR /home/runner
|
|
28
|
+
RUN curl -fsSL "https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz" \
|
|
29
|
+
| tar xz \
|
|
30
|
+
&& ./bin/installdependencies.sh \
|
|
31
|
+
&& chown -R runner:runner /home/runner
|
|
32
|
+
|
|
33
|
+
COPY entrypoint.sh /entrypoint.sh
|
|
34
|
+
RUN chmod +x /entrypoint.sh
|
|
35
|
+
|
|
36
|
+
USER runner
|
|
37
|
+
|
|
38
|
+
ENTRYPOINT ["/entrypoint.sh"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Required environment variables
|
|
5
|
+
: "${REPO_URL:?REPO_URL is required}"
|
|
6
|
+
: "${ACCESS_TOKEN:?ACCESS_TOKEN is required}"
|
|
7
|
+
|
|
8
|
+
RUNNER_NAME="${RUNNER_NAME:-thepopebot-runner}"
|
|
9
|
+
LABELS="${LABELS:-self-hosted,thepopebot}"
|
|
10
|
+
|
|
11
|
+
# Generate a registration token from the PAT
|
|
12
|
+
REG_TOKEN=$(curl -s -X POST \
|
|
13
|
+
-H "Authorization: token ${ACCESS_TOKEN}" \
|
|
14
|
+
-H "Accept: application/vnd.github.v3+json" \
|
|
15
|
+
"${REPO_URL/github.com/api.github.com/repos}/actions/runners/registration-token" \
|
|
16
|
+
| jq -r '.token')
|
|
17
|
+
|
|
18
|
+
if [ "$REG_TOKEN" = "null" ] || [ -z "$REG_TOKEN" ]; then
|
|
19
|
+
echo "Failed to get registration token. Check ACCESS_TOKEN permissions."
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Configure the runner
|
|
24
|
+
./config.sh \
|
|
25
|
+
--url "$REPO_URL" \
|
|
26
|
+
--token "$REG_TOKEN" \
|
|
27
|
+
--name "$RUNNER_NAME" \
|
|
28
|
+
--labels "$LABELS" \
|
|
29
|
+
--unattended \
|
|
30
|
+
--replace
|
|
31
|
+
|
|
32
|
+
# Deregister on shutdown
|
|
33
|
+
cleanup() {
|
|
34
|
+
echo "Removing runner..."
|
|
35
|
+
./config.sh remove --token "$REG_TOKEN" 2>/dev/null || true
|
|
36
|
+
}
|
|
37
|
+
trap cleanup SIGTERM SIGINT
|
|
38
|
+
|
|
39
|
+
# Start the runner (blocks until stopped)
|
|
40
|
+
./run.sh &
|
|
41
|
+
wait $!
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
services:
|
|
2
|
+
traefik:
|
|
3
|
+
image: traefik:v3
|
|
4
|
+
command:
|
|
5
|
+
- --providers.docker=true
|
|
6
|
+
- --providers.docker.exposedByDefault=false
|
|
7
|
+
- --entrypoints.web.address=:80
|
|
8
|
+
- --entrypoints.websecure.address=:443
|
|
9
|
+
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
|
10
|
+
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
|
11
|
+
- --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL:-}
|
|
12
|
+
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
|
|
13
|
+
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
|
|
14
|
+
ports:
|
|
15
|
+
- "80:80"
|
|
16
|
+
- "443:443"
|
|
17
|
+
volumes:
|
|
18
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
19
|
+
- traefik_certs:/letsencrypt
|
|
20
|
+
restart: unless-stopped
|
|
21
|
+
|
|
22
|
+
event_handler:
|
|
23
|
+
image: ${EVENT_HANDLER_IMAGE_URL:-stephengpope/thepopebot-event-handler:latest}
|
|
24
|
+
volumes:
|
|
25
|
+
- ./.env:/app/.env
|
|
26
|
+
- ./config:/app/config
|
|
27
|
+
- ./data:/app/data
|
|
28
|
+
- ./cron:/app/cron
|
|
29
|
+
- ./triggers:/app/triggers
|
|
30
|
+
- ./logs:/app/logs
|
|
31
|
+
labels:
|
|
32
|
+
- traefik.enable=true
|
|
33
|
+
# Set APP_HOSTNAME in .env to the domain from APP_URL (e.g., mybot.example.com)
|
|
34
|
+
- traefik.http.routers.event_handler.rule=Host(`${APP_HOSTNAME}`)
|
|
35
|
+
- traefik.http.routers.event_handler.entrypoints=websecure
|
|
36
|
+
- traefik.http.routers.event_handler.tls.certresolver=letsencrypt
|
|
37
|
+
- traefik.http.services.event_handler.loadbalancer.server.port=80
|
|
38
|
+
restart: unless-stopped
|
|
39
|
+
|
|
40
|
+
runner:
|
|
41
|
+
image: ${RUNNER_IMAGE_URL:-stephengpope/thepopebot-runner:latest}
|
|
42
|
+
environment:
|
|
43
|
+
REPO_URL: https://github.com/${GH_OWNER}/${GH_REPO}
|
|
44
|
+
ACCESS_TOKEN: ${GH_TOKEN}
|
|
45
|
+
RUNNER_SCOPE: repo
|
|
46
|
+
LABELS: self-hosted,thepopebot
|
|
47
|
+
volumes:
|
|
48
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
49
|
+
restart: unless-stopped
|
|
50
|
+
|
|
51
|
+
volumes:
|
|
52
|
+
traefik_certs:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { middleware, config } from 'thepopebot/middleware';
|