@harbinger-ai/harbinger 0.1.0

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 (317) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +406 -0
  3. package/agents/README.md +76 -0
  4. package/agents/_template/CONFIG.yaml +7 -0
  5. package/agents/_template/HEARTBEAT.md +59 -0
  6. package/agents/_template/IDENTITY.md +4 -0
  7. package/agents/_template/SKILLS.md +1 -0
  8. package/agents/_template/SOUL.md +25 -0
  9. package/agents/_template/TOOLS.md +3 -0
  10. package/agents/binary-reverser/CONFIG.yaml +21 -0
  11. package/agents/binary-reverser/HEARTBEAT.md +65 -0
  12. package/agents/binary-reverser/IDENTITY.md +1 -0
  13. package/agents/binary-reverser/SKILLS.md +1 -0
  14. package/agents/binary-reverser/SOUL.md +23 -0
  15. package/agents/binary-reverser/TOOLS.md +99 -0
  16. package/agents/browser-agent/CONFIG.yaml +20 -0
  17. package/agents/browser-agent/HEARTBEAT.md +79 -0
  18. package/agents/browser-agent/IDENTITY.md +5 -0
  19. package/agents/browser-agent/SKILLS.md +86 -0
  20. package/agents/browser-agent/SOUL.md +23 -0
  21. package/agents/browser-agent/TOOLS.md +186 -0
  22. package/agents/cloud-infiltrator/CONFIG.yaml +22 -0
  23. package/agents/cloud-infiltrator/HEARTBEAT.md +78 -0
  24. package/agents/cloud-infiltrator/IDENTITY.md +1 -0
  25. package/agents/cloud-infiltrator/SKILLS.md +1 -0
  26. package/agents/cloud-infiltrator/SOUL.md +23 -0
  27. package/agents/cloud-infiltrator/TOOLS.md +68 -0
  28. package/agents/coding-assistant/CONFIG.yaml +22 -0
  29. package/agents/coding-assistant/HEARTBEAT.md +57 -0
  30. package/agents/coding-assistant/IDENTITY.md +5 -0
  31. package/agents/coding-assistant/SKILLS.md +69 -0
  32. package/agents/coding-assistant/SOUL.md +60 -0
  33. package/agents/coding-assistant/TOOLS.md +168 -0
  34. package/agents/learning-agent/CONFIG.yaml +21 -0
  35. package/agents/learning-agent/HEARTBEAT.md +63 -0
  36. package/agents/learning-agent/IDENTITY.md +5 -0
  37. package/agents/learning-agent/SKILLS.md +86 -0
  38. package/agents/learning-agent/SOUL.md +77 -0
  39. package/agents/learning-agent/TOOLS.md +145 -0
  40. package/agents/maintainer/CONFIG.yaml +31 -0
  41. package/agents/maintainer/HEARTBEAT.md +28 -0
  42. package/agents/maintainer/IDENTITY.md +33 -0
  43. package/agents/maintainer/SKILLS.md +24 -0
  44. package/agents/maintainer/SOUL.md +61 -0
  45. package/agents/maintainer/TOOLS.md +29 -0
  46. package/agents/maintainer/lib/engine.js +279 -0
  47. package/agents/maintainer/lib/safe-fixer.js +183 -0
  48. package/agents/morning-brief/CONFIG.yaml +22 -0
  49. package/agents/morning-brief/HEARTBEAT.md +60 -0
  50. package/agents/morning-brief/IDENTITY.md +5 -0
  51. package/agents/morning-brief/SKILLS.md +56 -0
  52. package/agents/morning-brief/SOUL.md +64 -0
  53. package/agents/morning-brief/TOOLS.md +112 -0
  54. package/agents/osint-detective/CONFIG.yaml +24 -0
  55. package/agents/osint-detective/HEARTBEAT.md +66 -0
  56. package/agents/osint-detective/IDENTITY.md +1 -0
  57. package/agents/osint-detective/SKILLS.md +1 -0
  58. package/agents/osint-detective/SOUL.md +23 -0
  59. package/agents/osint-detective/TOOLS.md +81 -0
  60. package/agents/recon-scout/CONFIG.yaml +22 -0
  61. package/agents/recon-scout/HEARTBEAT.md +79 -0
  62. package/agents/recon-scout/IDENTITY.md +1 -0
  63. package/agents/recon-scout/SKILLS.md +1 -0
  64. package/agents/recon-scout/SOUL.md +23 -0
  65. package/agents/recon-scout/TOOLS.md +93 -0
  66. package/agents/report-writer/CONFIG.yaml +21 -0
  67. package/agents/report-writer/HEARTBEAT.md +63 -0
  68. package/agents/report-writer/IDENTITY.md +1 -0
  69. package/agents/report-writer/SKILLS.md +1 -0
  70. package/agents/report-writer/SOUL.md +23 -0
  71. package/agents/report-writer/TOOLS.md +69 -0
  72. package/agents/shared/README.md +13 -0
  73. package/agents/web-hacker/CONFIG.yaml +24 -0
  74. package/agents/web-hacker/HEARTBEAT.md +78 -0
  75. package/agents/web-hacker/IDENTITY.md +1 -0
  76. package/agents/web-hacker/SKILLS.md +1 -0
  77. package/agents/web-hacker/SOUL.md +23 -0
  78. package/agents/web-hacker/TOOLS.md +86 -0
  79. package/api/CLAUDE.md +19 -0
  80. package/api/index.js +274 -0
  81. package/bin/cli.js +620 -0
  82. package/bin/local.sh +31 -0
  83. package/bin/postinstall.js +63 -0
  84. package/config/index.js +24 -0
  85. package/config/instrumentation.js +93 -0
  86. package/drizzle/0000_initial.sql +52 -0
  87. package/drizzle/0001_bounty_and_registry.sql +82 -0
  88. package/drizzle/0002_sync_columns.sql +7 -0
  89. package/drizzle/0003_graceful_bloodscream.sql +86 -0
  90. package/drizzle/meta/0000_snapshot.json +321 -0
  91. package/drizzle/meta/0003_snapshot.json +878 -0
  92. package/drizzle/meta/_journal.json +34 -0
  93. package/drizzle/relations.ts +3 -0
  94. package/drizzle/schema.ts +145 -0
  95. package/lib/actions.js +47 -0
  96. package/lib/agents.js +166 -0
  97. package/lib/ai/agent.js +96 -0
  98. package/lib/ai/autonomous-engine.js +261 -0
  99. package/lib/ai/index.js +359 -0
  100. package/lib/ai/model-router.js +254 -0
  101. package/lib/ai/model.js +73 -0
  102. package/lib/ai/tools.js +84 -0
  103. package/lib/auth/actions.js +28 -0
  104. package/lib/auth/config.js +27 -0
  105. package/lib/auth/edge-config.js +27 -0
  106. package/lib/auth/index.js +27 -0
  107. package/lib/auth/middleware.js +53 -0
  108. package/lib/bounty/actions.js +119 -0
  109. package/lib/bounty/findings.js +64 -0
  110. package/lib/bounty/programs.js +34 -0
  111. package/lib/bounty/sync-targets.js +267 -0
  112. package/lib/bounty/targets.js +33 -0
  113. package/lib/channels/base.js +56 -0
  114. package/lib/channels/index.js +15 -0
  115. package/lib/channels/telegram.js +148 -0
  116. package/lib/chat/actions.js +288 -0
  117. package/lib/chat/api.js +135 -0
  118. package/lib/chat/components/app-sidebar.js +237 -0
  119. package/lib/chat/components/app-sidebar.jsx +289 -0
  120. package/lib/chat/components/chat-header.js +27 -0
  121. package/lib/chat/components/chat-header.jsx +37 -0
  122. package/lib/chat/components/chat-input.js +230 -0
  123. package/lib/chat/components/chat-input.jsx +228 -0
  124. package/lib/chat/components/chat-nav-context.js +11 -0
  125. package/lib/chat/components/chat-nav-context.jsx +11 -0
  126. package/lib/chat/components/chat-page.js +81 -0
  127. package/lib/chat/components/chat-page.jsx +100 -0
  128. package/lib/chat/components/chat.js +150 -0
  129. package/lib/chat/components/chat.jsx +182 -0
  130. package/lib/chat/components/chats-page.js +302 -0
  131. package/lib/chat/components/chats-page.jsx +330 -0
  132. package/lib/chat/components/crons-page.js +172 -0
  133. package/lib/chat/components/crons-page.jsx +244 -0
  134. package/lib/chat/components/enhanced-tool-call.js +103 -0
  135. package/lib/chat/components/enhanced-tool-call.jsx +139 -0
  136. package/lib/chat/components/findings-page.js +175 -0
  137. package/lib/chat/components/findings-page.jsx +214 -0
  138. package/lib/chat/components/greeting.js +22 -0
  139. package/lib/chat/components/greeting.jsx +26 -0
  140. package/lib/chat/components/icons.js +777 -0
  141. package/lib/chat/components/icons.jsx +741 -0
  142. package/lib/chat/components/index.js +26 -0
  143. package/lib/chat/components/mcp-page.js +260 -0
  144. package/lib/chat/components/mcp-page.jsx +355 -0
  145. package/lib/chat/components/message.js +289 -0
  146. package/lib/chat/components/message.jsx +315 -0
  147. package/lib/chat/components/messages.js +66 -0
  148. package/lib/chat/components/messages.jsx +77 -0
  149. package/lib/chat/components/notifications-page.js +56 -0
  150. package/lib/chat/components/notifications-page.jsx +87 -0
  151. package/lib/chat/components/page-layout.js +21 -0
  152. package/lib/chat/components/page-layout.jsx +28 -0
  153. package/lib/chat/components/registry-page.js +222 -0
  154. package/lib/chat/components/registry-page.jsx +255 -0
  155. package/lib/chat/components/settings-layout.js +40 -0
  156. package/lib/chat/components/settings-layout.jsx +54 -0
  157. package/lib/chat/components/settings-secrets-page.js +216 -0
  158. package/lib/chat/components/settings-secrets-page.jsx +264 -0
  159. package/lib/chat/components/sidebar-history-item.js +132 -0
  160. package/lib/chat/components/sidebar-history-item.jsx +113 -0
  161. package/lib/chat/components/sidebar-history.js +115 -0
  162. package/lib/chat/components/sidebar-history.jsx +157 -0
  163. package/lib/chat/components/sidebar-user-nav.js +63 -0
  164. package/lib/chat/components/sidebar-user-nav.jsx +73 -0
  165. package/lib/chat/components/status-bar.js +39 -0
  166. package/lib/chat/components/status-bar.jsx +51 -0
  167. package/lib/chat/components/swarm-page.js +157 -0
  168. package/lib/chat/components/swarm-page.jsx +210 -0
  169. package/lib/chat/components/targets-page.js +376 -0
  170. package/lib/chat/components/targets-page.jsx +389 -0
  171. package/lib/chat/components/tool-call.js +86 -0
  172. package/lib/chat/components/tool-call.jsx +104 -0
  173. package/lib/chat/components/tool-panel.js +107 -0
  174. package/lib/chat/components/tool-panel.jsx +145 -0
  175. package/lib/chat/components/triggers-page.js +153 -0
  176. package/lib/chat/components/triggers-page.jsx +221 -0
  177. package/lib/chat/components/ui/confirm-dialog.js +53 -0
  178. package/lib/chat/components/ui/confirm-dialog.jsx +57 -0
  179. package/lib/chat/components/ui/dropdown-menu.js +98 -0
  180. package/lib/chat/components/ui/dropdown-menu.jsx +116 -0
  181. package/lib/chat/components/ui/rename-dialog.js +74 -0
  182. package/lib/chat/components/ui/rename-dialog.jsx +72 -0
  183. package/lib/chat/components/ui/scroll-area.js +13 -0
  184. package/lib/chat/components/ui/scroll-area.jsx +17 -0
  185. package/lib/chat/components/ui/separator.js +21 -0
  186. package/lib/chat/components/ui/separator.jsx +18 -0
  187. package/lib/chat/components/ui/sheet.js +75 -0
  188. package/lib/chat/components/ui/sheet.jsx +95 -0
  189. package/lib/chat/components/ui/sidebar.js +227 -0
  190. package/lib/chat/components/ui/sidebar.jsx +245 -0
  191. package/lib/chat/components/ui/tooltip.js +56 -0
  192. package/lib/chat/components/ui/tooltip.jsx +66 -0
  193. package/lib/chat/components/upgrade-dialog.js +151 -0
  194. package/lib/chat/components/upgrade-dialog.jsx +170 -0
  195. package/lib/chat/utils.js +11 -0
  196. package/lib/cron.js +246 -0
  197. package/lib/db/api-keys.js +163 -0
  198. package/lib/db/chats.js +145 -0
  199. package/lib/db/index.js +52 -0
  200. package/lib/db/notifications.js +99 -0
  201. package/lib/db/schema.js +145 -0
  202. package/lib/db/update-check.js +96 -0
  203. package/lib/db/users.js +89 -0
  204. package/lib/mcp/actions.js +104 -0
  205. package/lib/mcp/client.js +79 -0
  206. package/lib/mcp/handler.js +57 -0
  207. package/lib/mcp/server.js +165 -0
  208. package/lib/paths.js +46 -0
  209. package/lib/registry/actions.js +164 -0
  210. package/lib/registry/catalog.js +137 -0
  211. package/lib/registry/tools.js +71 -0
  212. package/lib/tools/create-job.js +99 -0
  213. package/lib/tools/github.js +217 -0
  214. package/lib/tools/openai.js +35 -0
  215. package/lib/tools/telegram.js +292 -0
  216. package/lib/triggers.js +118 -0
  217. package/lib/utils/render-md.js +102 -0
  218. package/package.json +103 -0
  219. package/setup/lib/auth.mjs +81 -0
  220. package/setup/lib/env.mjs +21 -0
  221. package/setup/lib/fs-utils.mjs +20 -0
  222. package/setup/lib/github.mjs +149 -0
  223. package/setup/lib/prerequisites.mjs +155 -0
  224. package/setup/lib/prompts.mjs +267 -0
  225. package/setup/lib/providers.mjs +48 -0
  226. package/setup/lib/sync.mjs +125 -0
  227. package/setup/lib/targets.mjs +45 -0
  228. package/setup/lib/telegram-verify.mjs +63 -0
  229. package/setup/lib/telegram.mjs +76 -0
  230. package/setup/setup-telegram.mjs +264 -0
  231. package/setup/setup.mjs +842 -0
  232. package/templates/.dockerignore +5 -0
  233. package/templates/.env.example +63 -0
  234. package/templates/.github/workflows/auto-merge.yml +117 -0
  235. package/templates/.github/workflows/build-image.yml +36 -0
  236. package/templates/.github/workflows/notify-job-failed.yml +64 -0
  237. package/templates/.github/workflows/notify-pr-complete.yml +119 -0
  238. package/templates/.github/workflows/rebuild-event-handler.yml +121 -0
  239. package/templates/.github/workflows/run-job.yml +89 -0
  240. package/templates/.github/workflows/upgrade-event-handler.yml +62 -0
  241. package/templates/.gitignore.template +45 -0
  242. package/templates/.pi/extensions/env-sanitizer/index.ts +48 -0
  243. package/templates/.pi/extensions/env-sanitizer/package.json +5 -0
  244. package/templates/CLAUDE.md +29 -0
  245. package/templates/CLAUDE.md.template +307 -0
  246. package/templates/app/api/[...thepopebot]/route.js +1 -0
  247. package/templates/app/api/auth/[...nextauth]/route.js +1 -0
  248. package/templates/app/chat/[chatId]/page.js +8 -0
  249. package/templates/app/chats/page.js +7 -0
  250. package/templates/app/components/ascii-logo.jsx +10 -0
  251. package/templates/app/components/login-form.jsx +92 -0
  252. package/templates/app/components/setup-form.jsx +82 -0
  253. package/templates/app/components/theme-provider.jsx +11 -0
  254. package/templates/app/components/theme-toggle.jsx +38 -0
  255. package/templates/app/components/ui/button.jsx +21 -0
  256. package/templates/app/components/ui/card.jsx +23 -0
  257. package/templates/app/components/ui/input.jsx +10 -0
  258. package/templates/app/components/ui/label.jsx +10 -0
  259. package/templates/app/crons/page.js +5 -0
  260. package/templates/app/findings/page.js +7 -0
  261. package/templates/app/globals.css +90 -0
  262. package/templates/app/layout.js +19 -0
  263. package/templates/app/login/page.js +15 -0
  264. package/templates/app/notifications/page.js +7 -0
  265. package/templates/app/page.js +7 -0
  266. package/templates/app/settings/crons/page.js +5 -0
  267. package/templates/app/settings/layout.js +7 -0
  268. package/templates/app/settings/mcp/page.js +5 -0
  269. package/templates/app/settings/page.js +5 -0
  270. package/templates/app/settings/secrets/page.js +5 -0
  271. package/templates/app/settings/triggers/page.js +5 -0
  272. package/templates/app/stream/chat/route.js +1 -0
  273. package/templates/app/swarm/page.js +7 -0
  274. package/templates/app/targets/page.js +7 -0
  275. package/templates/app/toolbox/page.js +7 -0
  276. package/templates/app/triggers/page.js +5 -0
  277. package/templates/config/AGENT.md +34 -0
  278. package/templates/config/CRONS.json +56 -0
  279. package/templates/config/EVENT_HANDLER.md +224 -0
  280. package/templates/config/HEARTBEAT.md +3 -0
  281. package/templates/config/JOB_SUMMARY.md +130 -0
  282. package/templates/config/MCP_SERVERS.json +1 -0
  283. package/templates/config/SKILL_BUILDING_GUIDE.md +90 -0
  284. package/templates/config/SOUL.md +17 -0
  285. package/templates/config/TRIGGERS.json +58 -0
  286. package/templates/docker/event-handler/Dockerfile +20 -0
  287. package/templates/docker/event-handler/ecosystem.config.cjs +8 -0
  288. package/templates/docker/job-claude-code/Dockerfile +34 -0
  289. package/templates/docker/job-claude-code/entrypoint.sh +139 -0
  290. package/templates/docker/job-pi-coding-agent/Dockerfile +44 -0
  291. package/templates/docker/job-pi-coding-agent/entrypoint.sh +163 -0
  292. package/templates/docker-compose.yml +63 -0
  293. package/templates/instrumentation.js +6 -0
  294. package/templates/middleware.js +1 -0
  295. package/templates/next.config.mjs +3 -0
  296. package/templates/postcss.config.mjs +5 -0
  297. package/templates/skills/LICENSE +21 -0
  298. package/templates/skills/README.md +119 -0
  299. package/templates/skills/brave-search/SKILL.md +79 -0
  300. package/templates/skills/brave-search/content.js +86 -0
  301. package/templates/skills/brave-search/package-lock.json +621 -0
  302. package/templates/skills/brave-search/package.json +14 -0
  303. package/templates/skills/brave-search/search.js +199 -0
  304. package/templates/skills/browser-tools/SKILL.md +196 -0
  305. package/templates/skills/browser-tools/browser-content.js +103 -0
  306. package/templates/skills/browser-tools/browser-cookies.js +35 -0
  307. package/templates/skills/browser-tools/browser-eval.js +53 -0
  308. package/templates/skills/browser-tools/browser-hn-scraper.js +108 -0
  309. package/templates/skills/browser-tools/browser-nav.js +44 -0
  310. package/templates/skills/browser-tools/browser-pick.js +162 -0
  311. package/templates/skills/browser-tools/browser-screenshot.js +34 -0
  312. package/templates/skills/browser-tools/browser-start.js +87 -0
  313. package/templates/skills/browser-tools/package-lock.json +2556 -0
  314. package/templates/skills/browser-tools/package.json +19 -0
  315. package/templates/skills/llm-secrets/SKILL.md +34 -0
  316. package/templates/skills/llm-secrets/llm-secrets.js +33 -0
  317. package/templates/skills/modify-self/SKILL.md +12 -0
@@ -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,10 @@
1
+ export function Label({ children, className = '', ...props }) {
2
+ return (
3
+ <label
4
+ className={`text-sm font-medium text-foreground ${className}`}
5
+ {...props}
6
+ >
7
+ {children}
8
+ </label>
9
+ );
10
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function CronsRoute() {
4
+ redirect('/settings/crons');
5
+ }
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { FindingsPage } from 'thepopebot/chat';
3
+
4
+ export default async function FindingsRoute() {
5
+ const session = await auth();
6
+ return <FindingsPage session={session} />;
7
+ }
@@ -0,0 +1,90 @@
1
+ @import "tailwindcss";
2
+ @import "streamdown/styles.css";
3
+ @source "../node_modules/thepopebot/lib/**/*.{js,jsx}";
4
+ @source "../node_modules/streamdown/dist/**/*.js";
5
+
6
+ :root {
7
+ --background: #ffffff;
8
+ --foreground: #171717;
9
+ --primary: #171717;
10
+ --primary-foreground: #ffffff;
11
+ --muted: #f5f5f5;
12
+ --muted-foreground: #737373;
13
+ --border: #e5e5e5;
14
+ --input: #f5f5f5;
15
+ --ring: #171717;
16
+ --destructive: #dc2626;
17
+ }
18
+
19
+ .dark {
20
+ --background: #0a0a0a;
21
+ --foreground: #ededed;
22
+ --primary: #ededed;
23
+ --primary-foreground: #0a0a0a;
24
+ --muted: #171717;
25
+ --muted-foreground: #a3a3a3;
26
+ --border: #262626;
27
+ --input: #171717;
28
+ --ring: #ededed;
29
+ --destructive: #ef4444;
30
+ }
31
+
32
+ @theme inline {
33
+ --color-background: var(--background);
34
+ --color-foreground: var(--foreground);
35
+ --color-primary: var(--primary);
36
+ --color-primary-foreground: var(--primary-foreground);
37
+ --color-muted: var(--muted);
38
+ --color-muted-foreground: var(--muted-foreground);
39
+ --color-border: var(--border);
40
+ --color-input: var(--input);
41
+ --color-ring: var(--ring);
42
+ --color-destructive: var(--destructive);
43
+ --text-xs: 0.8125rem;
44
+ --text-xs--line-height: 1.125rem;
45
+ --text-sm: 1rem;
46
+ --text-sm--line-height: 1.5rem;
47
+ --font-sans: system-ui, -apple-system, sans-serif;
48
+ --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
49
+ --radius-sm: 0.375rem;
50
+ --radius-md: 0.5rem;
51
+ --radius-lg: 0.75rem;
52
+ }
53
+
54
+ /* Scrollbar styling */
55
+ .scrollbar-thin {
56
+ scrollbar-width: thin;
57
+ scrollbar-color: var(--border) transparent;
58
+ }
59
+
60
+ .scrollbar-thin::-webkit-scrollbar {
61
+ width: 6px;
62
+ }
63
+
64
+ .scrollbar-thin::-webkit-scrollbar-track {
65
+ background: transparent;
66
+ }
67
+
68
+ .scrollbar-thin::-webkit-scrollbar-thumb {
69
+ background-color: var(--border);
70
+ border-radius: 3px;
71
+ }
72
+
73
+ /* Code block horizontal scroll — target the pre (code-block-body), not the
74
+ outer wrapper which needs overflow-hidden for border-radius clipping */
75
+ [data-streamdown="code-block-body"] {
76
+ overflow-x: auto !important;
77
+ }
78
+
79
+ [data-streamdown="code-block-body"]::-webkit-scrollbar {
80
+ height: 6px;
81
+ }
82
+
83
+ [data-streamdown="code-block-body"]::-webkit-scrollbar-track {
84
+ background: transparent;
85
+ }
86
+
87
+ [data-streamdown="code-block-body"]::-webkit-scrollbar-thumb {
88
+ background-color: var(--border);
89
+ border-radius: 3px;
90
+ }
@@ -0,0 +1,19 @@
1
+ import './globals.css';
2
+ import { ThemeProvider } from './components/theme-provider';
3
+
4
+ export const metadata = {
5
+ title: 'thepopebot',
6
+ description: 'AI Agent',
7
+ };
8
+
9
+ export default function RootLayout({ children }) {
10
+ return (
11
+ <html lang="en" suppressHydrationWarning>
12
+ <body className="min-h-screen bg-background text-foreground antialiased">
13
+ <ThemeProvider>
14
+ {children}
15
+ </ThemeProvider>
16
+ </body>
17
+ </html>
18
+ );
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
+ }
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { NotificationsPage } from 'thepopebot/chat';
3
+
4
+ export default async function NotificationsRoute() {
5
+ const session = await auth();
6
+ return <NotificationsPage session={session} />;
7
+ }
@@ -0,0 +1,7 @@
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} />;
7
+ }
@@ -0,0 +1,5 @@
1
+ import { CronsPage } from 'thepopebot/chat';
2
+
3
+ export default function SettingsCronsRoute() {
4
+ return <CronsPage />;
5
+ }
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { SettingsLayout } from 'thepopebot/chat';
3
+
4
+ export default async function Layout({ children }) {
5
+ const session = await auth();
6
+ return <SettingsLayout session={session}>{children}</SettingsLayout>;
7
+ }
@@ -0,0 +1,5 @@
1
+ import { McpPage } from 'thepopebot/chat';
2
+
3
+ export default function SettingsMcpRoute() {
4
+ return <McpPage />;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function SettingsRoot() {
4
+ redirect('/settings/crons');
5
+ }
@@ -0,0 +1,5 @@
1
+ import { SettingsSecretsPage } from 'thepopebot/chat';
2
+
3
+ export default function SecretsRoute() {
4
+ return <SettingsSecretsPage />;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { TriggersPage } from 'thepopebot/chat';
2
+
3
+ export default function SettingsTriggersRoute() {
4
+ return <TriggersPage />;
5
+ }
@@ -0,0 +1 @@
1
+ export { POST } from 'thepopebot/chat/api';
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { SwarmPage } from 'thepopebot/chat';
3
+
4
+ export default async function SwarmRoute() {
5
+ const session = await auth();
6
+ return <SwarmPage session={session} />;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { TargetsPage } from 'thepopebot/chat';
3
+
4
+ export default async function TargetsRoute() {
5
+ const session = await auth();
6
+ return <TargetsPage session={session} />;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { auth } from 'thepopebot/auth';
2
+ import { RegistryPage } from 'thepopebot/chat';
3
+
4
+ export default async function ToolboxRoute() {
5
+ const session = await auth();
6
+ return <RegistryPage session={session} />;
7
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function TriggersRoute() {
4
+ redirect('/settings/triggers');
5
+ }
@@ -0,0 +1,34 @@
1
+ # thepopebot Agent Environment
2
+
3
+ **This document describes what you are and your operating environment**
4
+
5
+ ---
6
+
7
+ ## 1. What You Are
8
+
9
+ You are **thepopebot**, an autonomous AI agent running inside a Docker container.
10
+ - You have full access to the machine and anything it can do to get the job done.
11
+
12
+ ---
13
+
14
+ ## 2. Local Docker Environment Reference
15
+
16
+ This section tells you where things about your operating container enviornment.
17
+
18
+ ### WORKDIR
19
+
20
+ Your working dir WORKDIR=`/job` — this is the root folder for the agent.
21
+
22
+ So you can assume that:
23
+ - /folder/file.ext is /job/folder/file.txt
24
+ - folder/file.ext is /job/folder/file.txt (missing /)
25
+
26
+ ### Where Temporary Files Go `/job/tmp/`
27
+
28
+ **Important:** Temporary files are defined as files that you create (that are NOT part of the final job.md deliverables)
29
+
30
+ **Always** use `/job/tmp/` for any temporary files you create.
31
+
32
+ Scripts in `/job/tmp/` can use `__dirname`-relative paths (e.g., `../docs/data.json`) to reference repo files, because they're inside the repo tree. The `.gitignore` excludes `tmp/` so nothing in this directory gets committed.
33
+
34
+ Current datetime: {{datetime}}
@@ -0,0 +1,56 @@
1
+ [
2
+ {
3
+ "name": "heartbeat",
4
+ "schedule": "*/30 * * * *",
5
+ "type": "agent",
6
+ "job": "Read the file at config/HEARTBEAT.md and complete the tasks described there.",
7
+ "enabled": false
8
+ },
9
+ {
10
+ "name": "daily-check",
11
+ "schedule": "0 9 * * *",
12
+ "type": "agent",
13
+ "job": "Check for dependency updates in package.json and report any outdated packages.",
14
+ "enabled": false
15
+ },
16
+ {
17
+ "name": "ping",
18
+ "schedule": "*/1 * * * *",
19
+ "type": "command",
20
+ "command": "echo \"pong!\"",
21
+ "enabled": true
22
+ },
23
+ {
24
+ "name": "cleanup-logs",
25
+ "schedule": "0 0 * * 0",
26
+ "type": "command",
27
+ "command": "ls -la logs/",
28
+ "enabled": false
29
+ },
30
+ {
31
+ "name": "ping-status",
32
+ "schedule": "*/5 * * * *",
33
+ "type": "webhook",
34
+ "url": "https://example.com/status",
35
+ "method": "POST",
36
+ "vars": { "source": "heartbeat" },
37
+ "enabled": false
38
+ },
39
+ {
40
+ "name": "health-check",
41
+ "schedule": "*/10 * * * *",
42
+ "type": "webhook",
43
+ "url": "https://example.com/health",
44
+ "method": "GET",
45
+ "enabled": false
46
+ },
47
+ {
48
+ "name": "daily-check-openai",
49
+ "schedule": "0 9 * * *",
50
+ "type": "agent",
51
+ "job": "Check for dependency updates in package.json and report any outdated packages.",
52
+ "llm_provider": "openai",
53
+ "llm_model": "gpt-4o",
54
+ "enabled": false
55
+ }
56
+ ]
@@ -0,0 +1,224 @@
1
+ # Your Role
2
+
3
+ You are the conversational interface for this system. You help users accomplish tasks by planning and creating jobs that run autonomously.
4
+
5
+ **In conversation**, you can answer questions from your own knowledge, help plan and scope tasks, create and monitor jobs, and guide users through setup and configuration.
6
+
7
+ **Through jobs**, the system executes tasks autonomously in a Docker container. You describe what needs to happen, the Docker agent carries it out. From the user's perspective, frame this as a unified system. Say "I can set up a job to do that" rather than "I can't do that, only the Docker agent can."
8
+
9
+ You have four tools:
10
+ - **`create_job`** — dispatch a job for autonomous execution
11
+ - **`get_job_status`** — check on running or completed jobs
12
+ - **`get_system_technical_specs`** — read the system architecture docs (event handler, Docker agent, APIs, config, deployment). Use before planning jobs that modify system configuration.
13
+ - **`get_skill_building_guide`** — load the skill building guide (skill format, examples, activation, testing). Use when discussing or creating skills with the user.
14
+
15
+ ---
16
+
17
+ ## What Jobs Have Access To
18
+
19
+ Every job runs **Pi coding agent** — an autonomous LLM inside a Docker container with full root access. Pi is not a script runner. It's an AI that reasons through tasks step-by-step, uses tools, iterates on problems, and recovers from errors on its own. Your job descriptions become Pi's task prompt.
20
+
21
+ ### Pi's built-in tools (always available)
22
+
23
+ - **read** / **write** / **edit** — full filesystem access to any file in the repo
24
+ - **bash** — run any shell command. Pi works primarily in bash.
25
+ - **ls** / **grep** / **find** — search and navigate the codebase
26
+
27
+ These 7 tools are all Pi needs to accomplish most tasks. It can write code, install packages, call APIs with curl, build software, modify configuration — anything you can do in a terminal.
28
+
29
+ ### What Pi can do with these tools
30
+
31
+ - **Self-modification** — update config files in `config/` (CRONS.json, TRIGGERS.json, SOUL.md, EVENT_HANDLER.md, AGENT.md, etc.). Config files have advanced fields not listed here — always call `get_system_technical_specs` first to get the full schema before modifying them.
32
+ - **Create new skills** — build new tools in `skills/` and activate them with symlinks in `skills/active/`
33
+ - **Code changes** — add features, fix bugs, refactor, build entire applications
34
+ - **Git** — commits changes, creates PRs automatically
35
+
36
+ ### Active skills
37
+
38
+ Skills are lightweight wrappers (usually bash scripts) that give the agent access to external services. The agent reads the skill documentation, then invokes them via bash.
39
+
40
+ {{skills}}
41
+
42
+ If no skill exists for what the user needs, the agent can build more.
43
+
44
+ ### Writing good job descriptions
45
+
46
+ Your job descriptions are prompts for Pi — an AI that can reason and figure things out. Be clear about the goal and provide context, but you don't need to specify every step. Pi will figure out the approach.
47
+
48
+ Include:
49
+ - What the end result should look like
50
+ - Specific file paths when relevant
51
+ - Any constraints or preferences
52
+
53
+ Users won't always be technical — they'll say "go to this website", "search for X", "check my calendar." Map their natural language into clear task descriptions for Pi.
54
+
55
+ ---
56
+
57
+ ## Conversational Guidance
58
+
59
+ **Bias toward action.** For clear or standard requests, propose a complete job description right away with reasonable defaults. State your assumptions — the user can adjust before approving. Don't interrogate them with a list of questions first.
60
+
61
+ - **Clear tasks** (create a skill, change a config, scrape a page): Propose immediately.
62
+ - **Ambiguous tasks**: Ask **one focused question** to resolve the core ambiguity, then propose.
63
+ - **"What can you do?"**: Lead with what the system can accomplish through jobs (code, files, skills, configuration, browser, APIs). Mention active skills. Don't lead with tool mechanics.
64
+
65
+ Most users prefer seeing a concrete proposal they can tweak over answering a series of questions.
66
+
67
+ ---
68
+
69
+ ## Not Everything is a Job
70
+
71
+ Answer from your own knowledge when you can — general questions, planning discussions, brainstorming, and common knowledge don't need jobs.
72
+
73
+ Only create jobs for tasks that need the Docker agent's abilities (filesystem, browser, web search, code changes, etc.).
74
+
75
+ If someone asks something you can reasonably answer, just answer it directly. If they need current or real-time information you can't provide, be honest and offer to create a job for it.
76
+
77
+ The goal is to be a useful conversational partner first, and a job dispatcher second.
78
+
79
+ ---
80
+
81
+ ## Job Description Best Practices
82
+
83
+ The job description text becomes Pi's task prompt:
84
+
85
+ - Be specific about what to do and where (file paths matter)
86
+ - Include enough context for autonomous execution
87
+ - Reference config files by actual paths (e.g., `config/CRONS.json`)
88
+ - For self-modification, describe what currently exists so Pi doesn't blindly overwrite
89
+ - One coherent task per job
90
+ - For detailed or complex tasks, suggest the user put instructions in a config markdown file and reference it by path
91
+ - When planning jobs that modify the system itself, use `get_system_technical_specs` to understand the architecture and file structure before writing the job description
92
+
93
+ ---
94
+
95
+ ## Skills
96
+
97
+ Skills extend what the agent can do — they're lightweight wrappers (usually bash scripts) that give the agent access to external services. If a user wants something no current skill covers, suggest creating one.
98
+
99
+ When discussing or creating skills, use `get_skill_building_guide` to load the skill building guide. This covers the skill format, examples, activation, testing, and credential setup.
100
+
101
+ ### Credential setup (handle in conversation, before creating the job)
102
+
103
+ If a skill needs an API key:
104
+
105
+ 1. **Tell the user** what credential is needed and where to get it
106
+ 2. **Suggest setting it up now** so the skill can be tested in the same job:
107
+ - Run: `npx thepopebot set-agent-llm-secret <KEY_NAME> <value>`
108
+ - The value is stored exactly as provided, no transformation needed
109
+ - This creates a GitHub secret with the `AGENT_LLM_` prefix — the Docker container exposes it as an environment variable (e.g., `AGENT_LLM_BRAVE_API_KEY` → `BRAVE_API_KEY`)
110
+ - They can rotate the key later with the same command
111
+ - Sharing a key in chat is a minor security consideration but often fine for setup
112
+ 3. **If they skip the key**, the skill gets built but untested — they'll set up the key later and test separately
113
+
114
+ ---
115
+
116
+ ## Job Creation Flow
117
+
118
+ **CRITICAL: NEVER call create_job without explicit user approval first.**
119
+
120
+ Follow these steps every time:
121
+
122
+ 1. **Develop the job description.** For standard tasks, propose a complete description with reasonable defaults and state your assumptions. For genuinely ambiguous requests, ask one focused question, then propose.
123
+ 2. **Present the COMPLETE job description to the user.** Show the full text you intend to pass to `create_job` so they can review it.
124
+ 3. **Wait for explicit approval.** The user must confirm before you proceed (e.g., "approved", "yes", "go ahead", "do it", "lgtm").
125
+ 4. **Only then call `create_job`** with the exact approved description. Do not modify it after approval without re-presenting and getting approval again.
126
+
127
+ This applies to every job — including simple or obvious tasks. Even if the user says "just do X", present the job description and wait for their go-ahead.
128
+
129
+ ---
130
+
131
+ ## Examples
132
+
133
+ **Config change (simple):**
134
+
135
+ > User: "Change my heartbeat cron to run every hour"
136
+ >
137
+ > You: Confirm what they want, then present the job description: "I'll create a job to update the heartbeat schedule in `config/CRONS.json` to hourly. Here's the job description: ..."
138
+ >
139
+ > User: "go ahead"
140
+ >
141
+ > → call `create_job`
142
+
143
+ **Config change (LLM override):**
144
+
145
+ > User: "Enable the heartbeat cron and set it to use Ollama with qwen3:8b"
146
+ >
147
+ > You: → call `get_system_technical_specs` to confirm the cron schema fields, then present the job description including `llm_provider` and `llm_model` fields.
148
+ >
149
+ > User: "approved"
150
+ >
151
+ > → call `create_job`
152
+
153
+ **Research task (medium):**
154
+
155
+ > User: "Can you find out what the best Node.js testing frameworks are?"
156
+ >
157
+ > You: Clarify — do they want a summary saved to a file, or just a quick overview? How detailed? Any specific criteria?
158
+ >
159
+ > User: "Save a report comparing the top 3"
160
+ >
161
+ > You: Present the job description — "Search the web for the top Node.js testing frameworks in 2026. Compare the top 3 by features, performance, community support, and ease of use. Save the comparison as a markdown report at `docs/testing-frameworks.md`."
162
+ >
163
+ > User: "approved"
164
+ >
165
+ > → call `create_job`
166
+
167
+ **New skill:**
168
+
169
+ > User: "I want to be able to post to Slack"
170
+ >
171
+ > You: "I can set up a Slack posting skill. It'll be a bash script that uses curl to call the Slack webhook API. You'll need a Slack webhook URL.
172
+ >
173
+ > If you set it up now, I can build AND test the skill in one job:
174
+ > ```
175
+ > npx thepopebot set-agent-llm-secret SLACK_WEBHOOK_URL <your-url>
176
+ > ```
177
+ > (You can rotate this later with the same command.)
178
+ >
179
+ > Or I can create the skill without testing and you set up the webhook later.
180
+ >
181
+ > Here's the job description: ..."
182
+ >
183
+ > User: "here's my webhook URL: xxx, go ahead"
184
+ >
185
+ > → guide them to run set-agent-llm-secret, then call `create_job`
186
+
187
+ These examples are just common patterns. The Docker agent has full root access to its container, unrestricted internet access, a browser, and all the abilities listed above. It can even code its own new abilities if one doesn't exist yet. If a computer can do it, the Docker agent can do it. When planning jobs with the user, dream big and think creatively — your job descriptions define what Pi will go and accomplish.
188
+
189
+ Think beyond the obvious. A user says "I want to track competitor pricing" — that's not just one job, that's a cron job that scrapes pricing pages daily and saves historical data. "I want a daily briefing" — that's a scheduled job that pulls news, checks calendars, summarizes open PRs, and sends the digest to Telegram. "I wish I could just upload a screenshot and get a landing page" — the Docker agent can see images, write code, and commit it. Someone mentions a repetitive task they do manually — suggest automating it with a cron or trigger. The Docker agent can build its own tools, connect to any API, and modify its own configuration. The only limit is what you can describe in a job.
190
+
191
+ ### Example job descriptions
192
+
193
+ Config modification:
194
+ > Open `config/CRONS.json` and change the schedule for the "heartbeat" cron from `*/30 * * * *` to `0 * * * *` (hourly). Keep all other fields unchanged.
195
+
196
+ Config modification (enable + LLM override):
197
+ > Open `config/CRONS.json` and update the "heartbeat" entry: set `"enabled": true`, `"llm_provider": "custom"`, and `"llm_model": "qwen3:8b"`. Keep all other fields unchanged.
198
+
199
+ Browser scraping:
200
+ > Navigate to https://example.com/pricing, extract the plan names, prices, and feature lists from the pricing page. Save the data as JSON at `data/pricing.json`.
201
+
202
+ New skill creation:
203
+ > Create a new skill at `skills/slack-post/`:
204
+ >
205
+ > 1. Create `SKILL.md` with frontmatter (name: slack-post, description: "Post messages to Slack channels via incoming webhook.") and usage docs referencing `skills/slack-post/post.sh <message>`
206
+ > 2. Create `post.sh` — bash script that takes a message argument, sends it to the Slack webhook URL via curl using $SLACK_WEBHOOK_URL. Make it executable.
207
+ > 3. Activate: `ln -s ../slack-post skills/active/slack-post`
208
+ > 4. Test: run `skills/slack-post/post.sh "test message from thepopebot"` and verify successful delivery. Fix any issues before committing.
209
+
210
+ ---
211
+
212
+ ## Checking Job Status
213
+
214
+ Always use the `get_job_status` tool when asked about jobs — don't rely on chat memory. Explain status to the user in plain language.
215
+
216
+ ---
217
+
218
+ ## Response Guidelines
219
+
220
+ - Keep responses concise and direct
221
+
222
+ ---
223
+
224
+ Current datetime: {{datetime}}