the-campfire 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 (180) hide show
  1. package/bin/cli.ts +182 -0
  2. package/dist/apple-touch-icon.png +0 -0
  3. package/dist/assets/MermaidDiagram-By1J3Whj.js +2 -0
  4. package/dist/assets/_basePickBy-Dq6gnD-p.js +1 -0
  5. package/dist/assets/_baseUniq-SpgN6cGc.js +1 -0
  6. package/dist/assets/arc-D9SEA8dX.js +1 -0
  7. package/dist/assets/architectureDiagram-VXUJARFQ-CoTcwLeR.js +36 -0
  8. package/dist/assets/blockDiagram-VD42YOAC-Dvc63voV.js +122 -0
  9. package/dist/assets/c4Diagram-YG6GDRKO-tuDcG4_4.js +10 -0
  10. package/dist/assets/channel-CxhcHn7S.js +1 -0
  11. package/dist/assets/chunk-4BX2VUAB-x1hChYu9.js +1 -0
  12. package/dist/assets/chunk-55IACEB6-BX6HWnWP.js +1 -0
  13. package/dist/assets/chunk-B4BG7PRW-B4IlF03G.js +165 -0
  14. package/dist/assets/chunk-DI55MBZ5-TpYb5rLg.js +220 -0
  15. package/dist/assets/chunk-FMBD7UC4-DZX4LUPx.js +15 -0
  16. package/dist/assets/chunk-QN33PNHL-CuQs0NDY.js +1 -0
  17. package/dist/assets/chunk-QZHKN3VN-CygWwVx8.js +1 -0
  18. package/dist/assets/chunk-TZMSLE5B-CtI-IdKV.js +1 -0
  19. package/dist/assets/classDiagram-2ON5EDUG-BM0LptJF.js +1 -0
  20. package/dist/assets/classDiagram-v2-WZHVMYZB-BM0LptJF.js +1 -0
  21. package/dist/assets/clone-C6kt1rE7.js +1 -0
  22. package/dist/assets/cose-bilkent-S5V4N54A-PdySs991.js +1 -0
  23. package/dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
  24. package/dist/assets/dagre-6UL2VRFP-J0SxEiEu.js +4 -0
  25. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  26. package/dist/assets/diagram-PSM6KHXK-CW0HLXaH.js +24 -0
  27. package/dist/assets/diagram-QEK2KX5R-DADHF-k4.js +43 -0
  28. package/dist/assets/diagram-S2PKOQOG-9S0-PC3S.js +24 -0
  29. package/dist/assets/erDiagram-Q2GNP2WA-BEHAiY_q.js +60 -0
  30. package/dist/assets/flowDiagram-NV44I4VS-Cu6n9Xnd.js +162 -0
  31. package/dist/assets/ganttDiagram-JELNMOA3-Cr_BHryu.js +267 -0
  32. package/dist/assets/gitGraphDiagram-V2S2FVAM-D5pT35v5.js +65 -0
  33. package/dist/assets/graph-DKRbrxcs.js +1 -0
  34. package/dist/assets/index-Byjg9zgI.css +32 -0
  35. package/dist/assets/index-Cwj3m0hT.js +284 -0
  36. package/dist/assets/infoDiagram-HS3SLOUP-BaJlrgKV.js +2 -0
  37. package/dist/assets/init-Gi6I4Gst.js +1 -0
  38. package/dist/assets/journeyDiagram-XKPGCS4Q-CXC4-DJv.js +139 -0
  39. package/dist/assets/kanban-definition-3W4ZIXB7-BtHBu9cx.js +89 -0
  40. package/dist/assets/katex-BlHpptmG.js +261 -0
  41. package/dist/assets/layout-DnxSwLDJ.js +1 -0
  42. package/dist/assets/linear-CWbbIT8l.js +1 -0
  43. package/dist/assets/mermaid.core-DXn1cFAK.js +256 -0
  44. package/dist/assets/mindmap-definition-VGOIOE7T-BR8br1hs.js +68 -0
  45. package/dist/assets/ordinal-BENe2yWM.js +1 -0
  46. package/dist/assets/pieDiagram-ADFJNKIX-B7RmXV7I.js +30 -0
  47. package/dist/assets/quadrantDiagram-AYHSOK5B-DK0FhyV_.js +7 -0
  48. package/dist/assets/requirementDiagram-UZGBJVZJ-3zAGxSpL.js +64 -0
  49. package/dist/assets/sankeyDiagram-TZEHDZUN-DZppKtjc.js +10 -0
  50. package/dist/assets/sequenceDiagram-WL72ISMW-D1x3r3wV.js +145 -0
  51. package/dist/assets/stateDiagram-FKZM4ZOC-2ByD08Vq.js +1 -0
  52. package/dist/assets/stateDiagram-v2-4FDKWEC3-Vm1cYjgV.js +1 -0
  53. package/dist/assets/timeline-definition-IT6M3QCI-l5S35biR.js +61 -0
  54. package/dist/assets/treemap-GDKQZRPO-DIPadPiF.js +162 -0
  55. package/dist/assets/xychartDiagram-PRI3JC2R-9GUvwS2b.js +7 -0
  56. package/dist/favicon.svg +3 -0
  57. package/dist/fonts/Geist-Variable.woff2 +0 -0
  58. package/dist/fonts/GeistMono-Variable.woff2 +0 -0
  59. package/dist/icon-192.png +0 -0
  60. package/dist/icon-512.png +0 -0
  61. package/dist/index.html +33 -0
  62. package/dist/logo-codex.svg +14 -0
  63. package/dist/logo.svg +3 -0
  64. package/dist/manifest.json +26 -0
  65. package/dist/og-image.png +0 -0
  66. package/dist/sw.js +130 -0
  67. package/package.json +92 -0
  68. package/server/ADAPTERS.md +121 -0
  69. package/server/adapter-registry-types.ts +28 -0
  70. package/server/adapter-registry.ts +293 -0
  71. package/server/adapter-types.ts +51 -0
  72. package/server/agent-executor.ts +249 -0
  73. package/server/agent-mcp-bridge.ts +148 -0
  74. package/server/agent-mcp-stdio.ts +171 -0
  75. package/server/agent-mcp-tools.ts +76 -0
  76. package/server/agent-store.ts +183 -0
  77. package/server/agent-types.ts +79 -0
  78. package/server/aider-adapter.ts +525 -0
  79. package/server/auth.ts +153 -0
  80. package/server/auto-namer.ts +132 -0
  81. package/server/capability-discovery.ts +431 -0
  82. package/server/claude-container-auth.ts +40 -0
  83. package/server/claude-stdio-adapter.ts +452 -0
  84. package/server/clawhub-export.ts +218 -0
  85. package/server/cli-launcher.ts +1613 -0
  86. package/server/codex-adapter.ts +1987 -0
  87. package/server/codex-container-auth.ts +40 -0
  88. package/server/codex-home.ts +26 -0
  89. package/server/collective-intelligence.ts +401 -0
  90. package/server/commands-discovery.ts +160 -0
  91. package/server/constants.ts +5 -0
  92. package/server/container-manager.ts +328 -0
  93. package/server/cron-scheduler.ts +243 -0
  94. package/server/cron-store.ts +149 -0
  95. package/server/cron-types.ts +63 -0
  96. package/server/deliberation-engine.ts +323 -0
  97. package/server/embedding.ts +89 -0
  98. package/server/env-manager.ts +146 -0
  99. package/server/environment-detector.ts +106 -0
  100. package/server/environment-rules.ts +106 -0
  101. package/server/gallery-store.ts +216 -0
  102. package/server/gallery-types.ts +52 -0
  103. package/server/gallery-votes.ts +101 -0
  104. package/server/git-utils.ts +384 -0
  105. package/server/github-pr.ts +379 -0
  106. package/server/goose-adapter.ts +929 -0
  107. package/server/image-pull-manager.ts +144 -0
  108. package/server/index.ts +363 -0
  109. package/server/linear-project-manager.ts +78 -0
  110. package/server/moltbook-client.ts +160 -0
  111. package/server/openclaw-adapter.ts +916 -0
  112. package/server/openclaw-channel/channel.ts +188 -0
  113. package/server/openclaw-channel/index.ts +68 -0
  114. package/server/openclaw-channel/package.json +19 -0
  115. package/server/openclaw-channel/types.ts +93 -0
  116. package/server/opencode-adapter.ts +951 -0
  117. package/server/openhands-adapter.ts +775 -0
  118. package/server/orchestrator-executor.ts +184 -0
  119. package/server/orchestrator-store.ts +106 -0
  120. package/server/orchestrator-types.ts +86 -0
  121. package/server/path-resolver.ts +168 -0
  122. package/server/pr-poller.ts +162 -0
  123. package/server/proactive-keepalive.ts +121 -0
  124. package/server/prompt-manager.ts +103 -0
  125. package/server/protocol-monitor.ts +197 -0
  126. package/server/race-controller.ts +295 -0
  127. package/server/race-store.ts +82 -0
  128. package/server/recorder.ts +359 -0
  129. package/server/recording-hub/compat-validator.ts +122 -0
  130. package/server/recording-hub/diagnostics.ts +289 -0
  131. package/server/recording-hub/hub-routes.ts +146 -0
  132. package/server/recording-hub/hub-store.ts +224 -0
  133. package/server/replay.ts +78 -0
  134. package/server/routes/adapter-routes.ts +31 -0
  135. package/server/routes/agent-mcp-routes.ts +35 -0
  136. package/server/routes/agent-routes.ts +185 -0
  137. package/server/routes/auth-routes.ts +101 -0
  138. package/server/routes/ci-routes.ts +165 -0
  139. package/server/routes/commands-routes.ts +94 -0
  140. package/server/routes/cron-routes.ts +100 -0
  141. package/server/routes/env-routes.ts +50 -0
  142. package/server/routes/folder-routes.ts +56 -0
  143. package/server/routes/fs-routes.ts +403 -0
  144. package/server/routes/gallery-routes.ts +410 -0
  145. package/server/routes/git-routes.ts +108 -0
  146. package/server/routes/index.ts +62 -0
  147. package/server/routes/linear-routes.ts +254 -0
  148. package/server/routes/monitor-routes.ts +11 -0
  149. package/server/routes/orchestrator-routes.ts +210 -0
  150. package/server/routes/prompt-routes.ts +47 -0
  151. package/server/routes/race-routes.ts +103 -0
  152. package/server/routes/recording-routes.ts +101 -0
  153. package/server/routes/route-deps.ts +32 -0
  154. package/server/routes/session-routes.ts +560 -0
  155. package/server/routes/settings-routes.ts +108 -0
  156. package/server/routes/skills-routes.ts +52 -0
  157. package/server/routes/system-routes.ts +243 -0
  158. package/server/routes/webhook-routes.ts +135 -0
  159. package/server/routes.ts +44 -0
  160. package/server/security-middleware.ts +100 -0
  161. package/server/semantic-memory.ts +389 -0
  162. package/server/service.ts +733 -0
  163. package/server/session-folders.ts +107 -0
  164. package/server/session-git-info.ts +89 -0
  165. package/server/session-linear-issues.ts +94 -0
  166. package/server/session-names.ts +67 -0
  167. package/server/session-store.ts +169 -0
  168. package/server/session-types.ts +415 -0
  169. package/server/settings-manager.ts +120 -0
  170. package/server/shared-context.ts +401 -0
  171. package/server/skills-manager.ts +250 -0
  172. package/server/sub-session-manager.ts +263 -0
  173. package/server/terminal-manager.ts +185 -0
  174. package/server/update-checker.ts +114 -0
  175. package/server/usage-limits.ts +192 -0
  176. package/server/webhook-manager.ts +228 -0
  177. package/server/webhook-store.ts +168 -0
  178. package/server/webhook-types.ts +66 -0
  179. package/server/worktree-tracker.ts +84 -0
  180. package/server/ws-bridge.ts +2322 -0
@@ -0,0 +1,94 @@
1
+ import type { Hono } from "hono";
2
+ import type { RouteDeps } from "./route-deps.js";
3
+ import { discoverCommandsAndSkills, readCommandContent } from "../commands-discovery.js";
4
+
5
+ // Cache for CLI-reported slash commands (populated on first request)
6
+ let cachedCliCommands: string[] | null = null;
7
+ let fetchingCliCommands = false;
8
+
9
+ function findCommandsFromSessions(wsBridge: RouteDeps["wsBridge"]): string[] | null {
10
+ const sessions = wsBridge.getAllSessions();
11
+ for (const session of sessions) {
12
+ if (session.slash_commands && session.slash_commands.length > 0) {
13
+ return session.slash_commands;
14
+ }
15
+ }
16
+ return null;
17
+ }
18
+
19
+ async function fetchCommandsViaTempSession(launcher: RouteDeps["launcher"], wsBridge: RouteDeps["wsBridge"]): Promise<string[]> {
20
+ const tempSession = launcher.launch({
21
+ permissionMode: "default",
22
+ cwd: process.cwd(),
23
+ backendType: "claude",
24
+ });
25
+
26
+ const startTime = Date.now();
27
+ let commands: string[] = [];
28
+ while (Date.now() - startTime < 30_000) {
29
+ await new Promise((r) => setTimeout(r, 500));
30
+ const allSessions = wsBridge.getAllSessions();
31
+ const tempState = allSessions.find((s) => s.session_id === tempSession.sessionId);
32
+ if (tempState?.slash_commands && tempState.slash_commands.length > 0) {
33
+ commands = tempState.slash_commands;
34
+ break;
35
+ }
36
+ }
37
+
38
+ await launcher.kill(tempSession.sessionId).catch(() => {});
39
+ return commands;
40
+ }
41
+
42
+ export function registerCommandsRoutes(api: Hono, deps: RouteDeps): void {
43
+ const { launcher, wsBridge } = deps;
44
+
45
+ // Discover custom commands and skills for a given working directory
46
+ api.get("/commands", (c) => {
47
+ const cwd = c.req.query("cwd") || undefined;
48
+ return c.json(discoverCommandsAndSkills(cwd));
49
+ });
50
+
51
+ // Read a specific command's full content
52
+ api.get("/commands/read", (c) => {
53
+ const path = c.req.query("path");
54
+ if (!path) return c.json({ error: "path is required" }, 400);
55
+ const content = readCommandContent(path);
56
+ if (content === null) return c.json({ error: "File not found" }, 404);
57
+ return c.json({ path, content });
58
+ });
59
+
60
+ // Get slash commands from the CLI (dynamic, not hardcoded).
61
+ // Tries existing sessions first, then spins up a temporary one.
62
+ api.get("/commands/slash", async (c) => {
63
+ // 1. Try existing sessions
64
+ const fromSession = findCommandsFromSessions(wsBridge);
65
+ if (fromSession) {
66
+ cachedCliCommands = fromSession;
67
+ return c.json({ commands: fromSession, source: "session" });
68
+ }
69
+
70
+ // 2. Return cache
71
+ if (cachedCliCommands) return c.json({ commands: cachedCliCommands, source: "cache" });
72
+
73
+ // 3. Wait if another request is already fetching
74
+ if (fetchingCliCommands) {
75
+ for (let i = 0; i < 60; i++) {
76
+ await new Promise((r) => setTimeout(r, 500));
77
+ if (cachedCliCommands) return c.json({ commands: cachedCliCommands, source: "cache" });
78
+ }
79
+ return c.json({ commands: [], source: "timeout" });
80
+ }
81
+
82
+ // 4. Spin up temp session
83
+ fetchingCliCommands = true;
84
+ try {
85
+ const commands = await fetchCommandsViaTempSession(launcher, wsBridge);
86
+ if (commands.length > 0) cachedCliCommands = commands;
87
+ return c.json({ commands, source: commands.length > 0 ? "fetched" : "empty" });
88
+ } catch {
89
+ return c.json({ commands: [], source: "error" });
90
+ } finally {
91
+ fetchingCliCommands = false;
92
+ }
93
+ });
94
+ }
@@ -0,0 +1,100 @@
1
+ import type { Hono } from "hono";
2
+ import type { RouteDeps } from "./route-deps.js";
3
+ import * as cronStore from "../cron-store.js";
4
+
5
+ export function registerCronRoutes(api: Hono, deps: RouteDeps): void {
6
+ const { cronScheduler } = deps;
7
+
8
+ api.get("/cron/jobs", (c) => {
9
+ const jobs = cronStore.listJobs();
10
+ const enriched = jobs.map((j) => ({
11
+ ...j,
12
+ nextRunAt: cronScheduler?.getNextRunTime(j.id)?.getTime() ?? null,
13
+ }));
14
+ return c.json(enriched);
15
+ });
16
+
17
+ api.get("/cron/jobs/:id", (c) => {
18
+ const job = cronStore.getJob(c.req.param("id"));
19
+ if (!job) return c.json({ error: "Job not found" }, 404);
20
+ return c.json({
21
+ ...job,
22
+ nextRunAt: cronScheduler?.getNextRunTime(job.id)?.getTime() ?? null,
23
+ });
24
+ });
25
+
26
+ api.post("/cron/jobs", async (c) => {
27
+ const body = await c.req.json().catch(() => ({}));
28
+ try {
29
+ const job = cronStore.createJob({
30
+ name: body.name || "",
31
+ prompt: body.prompt || "",
32
+ schedule: body.schedule || "",
33
+ recurring: body.recurring ?? true,
34
+ backendType: body.backendType || "claude",
35
+ model: body.model || "",
36
+ cwd: body.cwd || "",
37
+ envSlug: body.envSlug,
38
+ enabled: body.enabled ?? true,
39
+ permissionMode: body.permissionMode || "bypassPermissions",
40
+ codexInternetAccess: body.codexInternetAccess,
41
+ });
42
+ if (job.enabled) cronScheduler?.scheduleJob(job);
43
+ return c.json(job, 201);
44
+ } catch (e: unknown) {
45
+ return c.json({ error: e instanceof Error ? e.message : String(e) }, 400);
46
+ }
47
+ });
48
+
49
+ api.put("/cron/jobs/:id", async (c) => {
50
+ const id = c.req.param("id");
51
+ const body = await c.req.json().catch(() => ({}));
52
+ try {
53
+ const allowed: Record<string, unknown> = {};
54
+ for (const key of ["name", "prompt", "schedule", "recurring", "backendType", "model", "cwd", "envSlug", "enabled", "permissionMode", "codexInternetAccess"] as const) {
55
+ if (key in body) allowed[key] = body[key];
56
+ }
57
+ const job = cronStore.updateJob(id, allowed);
58
+ if (!job) return c.json({ error: "Job not found" }, 404);
59
+ if (job.id !== id) cronScheduler?.stopJob(id);
60
+ cronScheduler?.scheduleJob(job);
61
+ return c.json(job);
62
+ } catch (e: unknown) {
63
+ return c.json({ error: e instanceof Error ? e.message : String(e) }, 400);
64
+ }
65
+ });
66
+
67
+ api.delete("/cron/jobs/:id", (c) => {
68
+ const id = c.req.param("id");
69
+ cronScheduler?.stopJob(id);
70
+ const deleted = cronStore.deleteJob(id);
71
+ if (!deleted) return c.json({ error: "Job not found" }, 404);
72
+ return c.json({ ok: true });
73
+ });
74
+
75
+ api.post("/cron/jobs/:id/toggle", (c) => {
76
+ const id = c.req.param("id");
77
+ const job = cronStore.getJob(id);
78
+ if (!job) return c.json({ error: "Job not found" }, 404);
79
+ const updated = cronStore.updateJob(id, { enabled: !job.enabled });
80
+ if (updated?.enabled) {
81
+ cronScheduler?.scheduleJob(updated);
82
+ } else {
83
+ cronScheduler?.stopJob(id);
84
+ }
85
+ return c.json(updated);
86
+ });
87
+
88
+ api.post("/cron/jobs/:id/run", (c) => {
89
+ const id = c.req.param("id");
90
+ const job = cronStore.getJob(id);
91
+ if (!job) return c.json({ error: "Job not found" }, 404);
92
+ cronScheduler?.executeJobManually(id);
93
+ return c.json({ ok: true, message: "Job triggered" });
94
+ });
95
+
96
+ api.get("/cron/jobs/:id/executions", (c) => {
97
+ const id = c.req.param("id");
98
+ return c.json(cronScheduler?.getExecutions(id) ?? []);
99
+ });
100
+ }
@@ -0,0 +1,50 @@
1
+ import type { Hono } from "hono";
2
+ import type { RouteDeps } from "./route-deps.js";
3
+ import * as envManager from "../env-manager.js";
4
+
5
+ export function registerEnvRoutes(api: Hono, _deps: RouteDeps): void {
6
+ api.get("/envs", (c) => {
7
+ try {
8
+ return c.json(envManager.listEnvs());
9
+ } catch (e: unknown) {
10
+ return c.json({ error: e instanceof Error ? e.message : String(e) }, 500);
11
+ }
12
+ });
13
+
14
+ api.get("/envs/:slug", (c) => {
15
+ const env = envManager.getEnv(c.req.param("slug"));
16
+ if (!env) return c.json({ error: "Environment not found" }, 404);
17
+ return c.json(env);
18
+ });
19
+
20
+ api.post("/envs", async (c) => {
21
+ const body = await c.req.json().catch(() => ({}));
22
+ try {
23
+ const env = envManager.createEnv(body.name, body.variables || {});
24
+ return c.json(env, 201);
25
+ } catch (e: unknown) {
26
+ return c.json({ error: e instanceof Error ? e.message : String(e) }, 400);
27
+ }
28
+ });
29
+
30
+ api.put("/envs/:slug", async (c) => {
31
+ const slug = c.req.param("slug");
32
+ const body = await c.req.json().catch(() => ({}));
33
+ try {
34
+ const env = envManager.updateEnv(slug, {
35
+ name: body.name,
36
+ variables: body.variables,
37
+ });
38
+ if (!env) return c.json({ error: "Environment not found" }, 404);
39
+ return c.json(env);
40
+ } catch (e: unknown) {
41
+ return c.json({ error: e instanceof Error ? e.message : String(e) }, 400);
42
+ }
43
+ });
44
+
45
+ api.delete("/envs/:slug", (c) => {
46
+ const deleted = envManager.deleteEnv(c.req.param("slug"));
47
+ if (!deleted) return c.json({ error: "Environment not found" }, 404);
48
+ return c.json({ ok: true });
49
+ });
50
+ }
@@ -0,0 +1,56 @@
1
+ import type { Hono } from "hono";
2
+ import type { RouteDeps } from "./route-deps.js";
3
+ import * as sessionFolders from "../session-folders.js";
4
+
5
+ export function registerFolderRoutes(api: Hono, _deps: RouteDeps): void {
6
+ // List all folders
7
+ api.get("/folders", (c) => {
8
+ return c.json(sessionFolders.listFolders());
9
+ });
10
+
11
+ // Create a folder
12
+ api.post("/folders", async (c) => {
13
+ const body = await c.req.json().catch(() => ({}));
14
+ if (!body.name || typeof body.name !== "string") {
15
+ return c.json({ error: "name is required" }, 400);
16
+ }
17
+ const folder = sessionFolders.createFolder(body.name.trim(), body.color);
18
+ return c.json(folder);
19
+ });
20
+
21
+ // Update a folder
22
+ api.patch("/folders/:id", async (c) => {
23
+ const id = c.req.param("id");
24
+ const body = await c.req.json().catch(() => ({}));
25
+ const folder = sessionFolders.updateFolder(id, {
26
+ name: body.name,
27
+ color: body.color,
28
+ });
29
+ if (!folder) return c.json({ error: "Folder not found" }, 404);
30
+ return c.json(folder);
31
+ });
32
+
33
+ // Delete a folder
34
+ api.delete("/folders/:id", (c) => {
35
+ const id = c.req.param("id");
36
+ const ok = sessionFolders.deleteFolder(id);
37
+ if (!ok) return c.json({ error: "Folder not found" }, 404);
38
+ return c.json({ ok: true });
39
+ });
40
+
41
+ // Add session to folder
42
+ api.post("/folders/:id/sessions/:sessionId", (c) => {
43
+ const folderId = c.req.param("id");
44
+ const sessionId = c.req.param("sessionId");
45
+ const ok = sessionFolders.addSessionToFolder(folderId, sessionId);
46
+ if (!ok) return c.json({ error: "Folder not found" }, 404);
47
+ return c.json({ ok: true });
48
+ });
49
+
50
+ // Remove session from any folder
51
+ api.delete("/folders/sessions/:sessionId", (c) => {
52
+ const sessionId = c.req.param("sessionId");
53
+ sessionFolders.removeSessionFromFolder(sessionId);
54
+ return c.json({ ok: true });
55
+ });
56
+ }