quadwork 1.6.2 → 1.7.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 (97) hide show
  1. package/README.md +37 -8
  2. package/bin/quadwork.js +42 -59
  3. package/bridges/discord/discord_bridge.py +3 -3
  4. package/out/404.html +1 -1
  5. package/out/__next.__PAGE__.txt +3 -3
  6. package/out/__next._full.txt +14 -14
  7. package/out/__next._head.txt +4 -4
  8. package/out/__next._index.txt +7 -7
  9. package/out/__next._tree.txt +2 -2
  10. package/out/_next/static/chunks/{0zy-ktdv5zuby.js → 00_f~dht-py.~.js} +1 -1
  11. package/out/_next/static/chunks/{0ksh60pbzmyjf.js → 01keua0t73paf.js} +13 -13
  12. package/out/_next/static/chunks/0ggc226h4xp_6.css +2 -0
  13. package/out/_next/static/chunks/14zyqqpdz2x7j.js +1 -0
  14. package/out/_next/static/chunks/{0o3_.p5ivp5sp.js → 152f2hu-ivy6f.js} +1 -1
  15. package/out/_next/static/jXvlZMZi9MNbHTOZg0eK3/_ssgManifest.js +1 -0
  16. package/out/_next/static/media/favicon.0yjarmrcdsq9k.ico +0 -0
  17. package/out/_not-found/__next._full.txt +13 -13
  18. package/out/_not-found/__next._head.txt +4 -4
  19. package/out/_not-found/__next._index.txt +7 -7
  20. package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
  21. package/out/_not-found/__next._not-found.txt +3 -3
  22. package/out/_not-found/__next._tree.txt +2 -2
  23. package/out/_not-found.html +1 -1
  24. package/out/_not-found.txt +13 -13
  25. package/out/app-shell/__next._full.txt +13 -13
  26. package/out/app-shell/__next._head.txt +4 -4
  27. package/out/app-shell/__next._index.txt +7 -7
  28. package/out/app-shell/__next._tree.txt +2 -2
  29. package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
  30. package/out/app-shell/__next.app-shell.txt +3 -3
  31. package/out/app-shell.html +1 -1
  32. package/out/app-shell.txt +13 -13
  33. package/out/favicon.ico +0 -0
  34. package/out/icon.png +0 -0
  35. package/out/icon.svg +10 -4
  36. package/out/index.html +1 -1
  37. package/out/index.txt +14 -14
  38. package/out/project/_/__next._full.txt +14 -14
  39. package/out/project/_/__next._head.txt +4 -4
  40. package/out/project/_/__next._index.txt +7 -7
  41. package/out/project/_/__next._tree.txt +2 -2
  42. package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
  43. package/out/project/_/__next.project.$d$id.txt +3 -3
  44. package/out/project/_/__next.project.txt +3 -3
  45. package/out/project/_/queue/__next._full.txt +14 -14
  46. package/out/project/_/queue/__next._head.txt +4 -4
  47. package/out/project/_/queue/__next._index.txt +7 -7
  48. package/out/project/_/queue/__next._tree.txt +2 -2
  49. package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
  50. package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
  51. package/out/project/_/queue/__next.project.$d$id.txt +3 -3
  52. package/out/project/_/queue/__next.project.txt +3 -3
  53. package/out/project/_/queue.html +1 -1
  54. package/out/project/_/queue.txt +14 -14
  55. package/out/project/_.html +1 -1
  56. package/out/project/_.txt +14 -14
  57. package/out/quadwork-symbol.svg +14 -0
  58. package/out/settings/__next._full.txt +14 -14
  59. package/out/settings/__next._head.txt +4 -4
  60. package/out/settings/__next._index.txt +7 -7
  61. package/out/settings/__next._tree.txt +2 -2
  62. package/out/settings/__next.settings.__PAGE__.txt +3 -3
  63. package/out/settings/__next.settings.txt +3 -3
  64. package/out/settings.html +1 -1
  65. package/out/settings.txt +14 -14
  66. package/out/setup/__next._full.txt +14 -14
  67. package/out/setup/__next._head.txt +4 -4
  68. package/out/setup/__next._index.txt +7 -7
  69. package/out/setup/__next._tree.txt +2 -2
  70. package/out/setup/__next.setup.__PAGE__.txt +3 -3
  71. package/out/setup/__next.setup.txt +3 -3
  72. package/out/setup.html +1 -1
  73. package/out/setup.txt +14 -14
  74. package/package.json +1 -1
  75. package/server/index.js +27 -15
  76. package/server/routes.discordBridge.test.js +5 -5
  77. package/server/routes.js +69 -206
  78. package/server/routes.telegramBridge.test.js +6 -6
  79. package/templates/config.toml +7 -7
  80. package/out/_next/static/AQ0US7_Pm9gOOelb-ks5q/_ssgManifest.js +0 -1
  81. package/out/_next/static/chunks/0j-zyy6.adwtl.css +0 -2
  82. package/out/_next/static/chunks/0n7b.b.q4nmo..js +0 -1
  83. package/out/_next/static/chunks/0~xrqi87fqraz.js +0 -1
  84. package/out/_next/static/chunks/12i404gkhv7q..js +0 -4
  85. package/out/_next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
  86. package/out/project/_/memory/__next._full.txt +0 -21
  87. package/out/project/_/memory/__next._head.txt +0 -6
  88. package/out/project/_/memory/__next._index.txt +0 -8
  89. package/out/project/_/memory/__next._tree.txt +0 -3
  90. package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +0 -6
  91. package/out/project/_/memory/__next.project.$d$id.memory.txt +0 -5
  92. package/out/project/_/memory/__next.project.$d$id.txt +0 -5
  93. package/out/project/_/memory/__next.project.txt +0 -5
  94. package/out/project/_/memory.html +0 -1
  95. package/out/project/_/memory.txt +0 -21
  96. /package/out/_next/static/{AQ0US7_Pm9gOOelb-ks5q → jXvlZMZi9MNbHTOZg0eK3}/_buildManifest.js +0 -0
  97. /package/out/_next/static/{AQ0US7_Pm9gOOelb-ks5q → jXvlZMZi9MNbHTOZg0eK3}/_clientMiddlewareManifest.js +0 -0
package/server/routes.js CHANGED
@@ -113,18 +113,32 @@ function chatAuthHeaders(token) {
113
113
  }
114
114
 
115
115
  router.get("/api/chat", async (req, res) => {
116
+ const projectId = req.query.project;
116
117
  const apiPath = req.query.path || "/api/messages";
117
- const { url: base, token } = getChattrConfig(req.query.project);
118
+ const { url: base, token } = getChattrConfig(projectId);
118
119
 
119
- const fwd = new URLSearchParams();
120
- for (const [k, v] of Object.entries(req.query)) {
121
- if (k !== "path") fwd.set(k, String(v));
122
- }
123
- if (token) fwd.set("token", token);
120
+ const buildUrl = (tok) => {
121
+ const fwd = new URLSearchParams();
122
+ for (const [k, v] of Object.entries(req.query)) {
123
+ if (k !== "path") fwd.set(k, String(v));
124
+ }
125
+ if (tok) fwd.set("token", tok);
126
+ return `${base}${apiPath}?${fwd.toString()}`;
127
+ };
124
128
 
125
- const url = `${base}${apiPath}?${fwd.toString()}`;
126
129
  try {
127
- const r = await fetch(url, { headers: chatAuthHeaders(token) });
130
+ const r = await fetch(buildUrl(token), { headers: chatAuthHeaders(token) });
131
+ // #448: on 401/403, re-sync the session token from AC and retry
132
+ // once. The stored token may be stale after an AC restart.
133
+ if ((r.status === 401 || r.status === 403) && projectId) {
134
+ try { await syncChattrToken(projectId); } catch {}
135
+ const { token: refreshed } = getChattrConfig(projectId);
136
+ if (refreshed && refreshed !== token) {
137
+ const retry = await fetch(buildUrl(refreshed), { headers: chatAuthHeaders(refreshed) });
138
+ if (!retry.ok) return res.status(retry.status).json({ error: `AgentChattr returned ${retry.status}` });
139
+ return res.json(await retry.json());
140
+ }
141
+ }
128
142
  if (!r.ok) return res.status(r.status).json({ error: `AgentChattr returned ${r.status}` });
129
143
  res.json(await r.json());
130
144
  } catch (err) {
@@ -1674,184 +1688,7 @@ router.get("/api/batch-progress", async (req, res) => {
1674
1688
  res.json(data);
1675
1689
  });
1676
1690
 
1677
- // ─── Memory ────────────────────────────────────────────────────────────────
1678
-
1679
- function getProject(projectId) {
1680
- try {
1681
- const cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
1682
- return cfg.projects?.find((p) => p.id === projectId) || null;
1683
- } catch {
1684
- return null;
1685
- }
1686
- }
1687
-
1688
- function getMemoryPaths(project) {
1689
- const workDir = project.working_dir || "";
1690
- return {
1691
- cardsDir: project.memory_cards_dir || path.join(workDir, "..", "agent-memory", "archive", "v2", "cards"),
1692
- sharedMemoryPath: project.shared_memory_path || path.join(workDir, "..", "agent-memory", "central", "short-term", "agent-os.md"),
1693
- butlerDir: project.butler_scripts_dir || path.join(workDir, "..", "agent-memory", "scripts"),
1694
- };
1695
- }
1696
-
1697
- function findMdFiles(dir) {
1698
- const results = [];
1699
- if (!fs.existsSync(dir)) return results;
1700
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1701
- const full = path.join(dir, entry.name);
1702
- if (entry.isDirectory()) results.push(...findMdFiles(full));
1703
- else if (entry.name.endsWith(".md")) results.push(full);
1704
- }
1705
- return results;
1706
- }
1707
-
1708
- function parseFrontmatter(content) {
1709
- const fm = {};
1710
- const match = content.match(/^---\n([\s\S]*?)\n---/);
1711
- if (!match) return fm;
1712
- for (const line of match[1].split("\n")) {
1713
- const idx = line.indexOf(":");
1714
- if (idx > 0) {
1715
- const key = line.slice(0, idx).trim();
1716
- let val = line.slice(idx + 1).trim();
1717
- if (val.startsWith("[") && val.endsWith("]")) val = val.slice(1, -1).trim();
1718
- fm[key] = val;
1719
- }
1720
- }
1721
- return fm;
1722
- }
1723
-
1724
- router.get("/api/memory", (req, res) => {
1725
- const projectId = req.query.project || "";
1726
- const action = req.query.action || "cards";
1727
- const project = getProject(projectId);
1728
- if (!project) return res.status(404).json({ error: "Project not found" });
1729
-
1730
- const paths = getMemoryPaths(project);
1731
-
1732
- if (action === "cards") {
1733
- const search = req.query.search || "";
1734
- try {
1735
- const files = findMdFiles(paths.cardsDir);
1736
- const cards = files.map((fullPath) => {
1737
- const content = fs.readFileSync(fullPath, "utf-8");
1738
- const fm = parseFrontmatter(content);
1739
- const relPath = path.relative(paths.cardsDir, fullPath);
1740
- const body = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
1741
- const firstLine = body.split("\n")[0]?.replace(/^#\s*/, "").trim();
1742
- return {
1743
- file: relPath,
1744
- title: firstLine || fm.id || path.basename(fullPath, ".md"),
1745
- date: fm.at || "",
1746
- agent: fm.by || "",
1747
- tags: fm.tags || "",
1748
- content: body,
1749
- };
1750
- });
1751
- cards.sort((a, b) => b.date.localeCompare(a.date));
1752
- if (search) {
1753
- const q = search.toLowerCase();
1754
- return res.json(cards.filter((c) =>
1755
- c.title.toLowerCase().includes(q) || c.agent.toLowerCase().includes(q) || c.tags.toLowerCase().includes(q) || c.content.toLowerCase().includes(q)
1756
- ));
1757
- }
1758
- return res.json(cards);
1759
- } catch {
1760
- return res.json([]);
1761
- }
1762
- }
1763
-
1764
- if (action === "status") {
1765
- const agents = project.agents || {};
1766
- const status = {};
1767
- for (const [id, agent] of Object.entries(agents)) {
1768
- const targetPath = path.join(agent.cwd || "", "shared-memory.md");
1769
- if (fs.existsSync(targetPath)) {
1770
- const stat = fs.statSync(targetPath);
1771
- status[id] = { injected: true, lastModified: stat.mtime.toISOString() };
1772
- } else {
1773
- status[id] = { injected: false, lastModified: null };
1774
- }
1775
- }
1776
- const sourceExists = fs.existsSync(paths.sharedMemoryPath);
1777
- return res.json({ agents: status, sourceExists });
1778
- }
1779
-
1780
- if (action === "shared-memory") {
1781
- try {
1782
- const content = fs.readFileSync(paths.sharedMemoryPath, "utf-8");
1783
- return res.json({ content, path: paths.sharedMemoryPath });
1784
- } catch {
1785
- return res.json({ content: "", path: paths.sharedMemoryPath });
1786
- }
1787
- }
1788
-
1789
- if (action === "settings") {
1790
- return res.json({
1791
- memory_cards_dir: project.memory_cards_dir || "",
1792
- shared_memory_path: project.shared_memory_path || "",
1793
- butler_scripts_dir: project.butler_scripts_dir || "",
1794
- });
1795
- }
1796
-
1797
- res.status(400).json({ error: "Unknown action" });
1798
- });
1799
-
1800
- router.post("/api/memory", (req, res) => {
1801
- const projectId = req.query.project || "";
1802
- const action = req.query.action || "";
1803
- const project = getProject(projectId);
1804
- if (!project) return res.status(404).json({ error: "Project not found" });
1805
-
1806
- const paths = getMemoryPaths(project);
1807
-
1808
- if (action === "butler") {
1809
- const allowed = ["butler-scan.sh", "butler-consolidate.sh", "inject.sh"];
1810
- const command = req.body.command;
1811
- if (!allowed.includes(command)) return res.json({ ok: false, error: `Unknown command: ${command}` });
1812
- const scriptPath = path.join(paths.butlerDir, command);
1813
- if (!fs.existsSync(scriptPath)) return res.json({ ok: false, error: `Script not found: ${scriptPath}` });
1814
- try {
1815
- const output = execFileSync("bash", [scriptPath], {
1816
- encoding: "utf-8",
1817
- timeout: 30000,
1818
- cwd: path.dirname(paths.butlerDir),
1819
- });
1820
- return res.json({ ok: true, output });
1821
- } catch (err) {
1822
- return res.json({ ok: false, error: err.message });
1823
- }
1824
- }
1825
-
1826
- if (action === "save-memory") {
1827
- try {
1828
- const dir = path.dirname(paths.sharedMemoryPath);
1829
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
1830
- fs.writeFileSync(paths.sharedMemoryPath, req.body.content);
1831
- return res.json({ ok: true });
1832
- } catch (err) {
1833
- return res.json({ ok: false, error: err.message });
1834
- }
1835
- }
1836
-
1837
- if (action === "save-settings") {
1838
- try {
1839
- const cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
1840
- const proj = cfg.projects?.find((p) => p.id === projectId);
1841
- if (!proj) return res.json({ ok: false, error: "Project not found" });
1842
- const s = req.body;
1843
- if (s.memory_cards_dir !== undefined) proj.memory_cards_dir = s.memory_cards_dir || undefined;
1844
- if (s.shared_memory_path !== undefined) proj.shared_memory_path = s.shared_memory_path || undefined;
1845
- if (s.butler_scripts_dir !== undefined) proj.butler_scripts_dir = s.butler_scripts_dir || undefined;
1846
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
1847
- return res.json({ ok: true });
1848
- } catch (err) {
1849
- return res.json({ ok: false, error: err.message });
1850
- }
1851
- }
1852
-
1853
- res.status(400).json({ error: "Unknown action" });
1854
- });
1691
+ // #445: Memory section (agent-memory butler integration) removed.
1855
1692
 
1856
1693
  // ─── Setup ─────────────────────────────────────────────────────────────────
1857
1694
 
@@ -2378,9 +2215,12 @@ router.post("/api/rename", (req, res) => {
2378
2215
  // ─── Telegram ──────────────────────────────────────────────────────────────
2379
2216
 
2380
2217
  const BRIDGE_DIR = path.join(CONFIG_DIR, "agentchattr-telegram");
2218
+ // #444: pin agentchattr-telegram to a known commit (same pattern as
2219
+ // AGENTCHATTR_PIN in bin/quadwork.js for bcurts/agentchattr).
2220
+ const AGENTCHATTR_TELEGRAM_PIN = "4a6b45f1794c612328b9d5ee6d6fcb3f77015abc";
2381
2221
 
2382
2222
  function telegramPidFile(projectId) {
2383
- return path.join(CONFIG_DIR, `telegram-bridge-${projectId}.pid`);
2223
+ return path.join(CONFIG_DIR, `tg-bridge-${projectId}.pid`);
2384
2224
  }
2385
2225
 
2386
2226
  function telegramConfigToml(projectId) {
@@ -2388,7 +2228,7 @@ function telegramConfigToml(projectId) {
2388
2228
  }
2389
2229
 
2390
2230
  // #383: path to a project's AgentChattr config.toml. The install
2391
- // handler patches this file to declare the `telegram-bridge` agent
2231
+ // handler patches this file to declare the `tg` agent
2392
2232
  // so AC's registry accepts the bridge's register call.
2393
2233
  function projectAgentchattrConfigPath(projectId) {
2394
2234
  return path.join(CONFIG_DIR, projectId, "agentchattr", "config.toml");
@@ -2415,7 +2255,12 @@ function resolveProjectAgentchattrUrl(cfg, project) {
2415
2255
  // AC message IDs advances the cursor past the other project's range,
2416
2256
  // silently killing AC→TG forwarding for that project.
2417
2257
  function buildTelegramBridgeToml(tg, projectId) {
2418
- const cursorFile = path.join(CONFIG_DIR, `telegram-bridge-cursor-${projectId}.json`);
2258
+ const cursorFile = path.join(CONFIG_DIR, `tg-bridge-cursor-${projectId}.json`);
2259
+ // #439: migrate old cursor file so the bridge doesn't replay history
2260
+ const oldCursor = path.join(CONFIG_DIR, `telegram-bridge-cursor-${projectId}.json`);
2261
+ if (!fs.existsSync(cursorFile) && fs.existsSync(oldCursor)) {
2262
+ fs.renameSync(oldCursor, cursorFile);
2263
+ }
2419
2264
  return (
2420
2265
  `[telegram]\n` +
2421
2266
  `bot_token = "${tg.bot_token}"\n` +
@@ -2427,14 +2272,18 @@ function buildTelegramBridgeToml(tg, projectId) {
2427
2272
 
2428
2273
  // #383 Bug 3: AC's registry rejects any base name not pre-declared
2429
2274
  // in config.toml with `400 unknown base`. The bridge registers as
2430
- // `telegram-bridge`, so every per-project AC config must declare it.
2431
- // Idempotent: only appends if the section is not already present.
2275
+ // `tg` (#439: renamed from `telegram-bridge`), so every per-project
2276
+ // AC config must declare it. Idempotent: only appends if the section
2277
+ // is not already present. Also migrates old `[agents.telegram-bridge]`.
2432
2278
  function patchAgentchattrConfigForTelegramBridge(tomlText) {
2433
- if (/^\[agents\.telegram-bridge\]\s*$/m.test(tomlText)) {
2434
- return { text: tomlText, changed: false };
2279
+ // #439: migrate old slug if present
2280
+ const original = tomlText;
2281
+ tomlText = tomlText.replace(/^\[agents\.telegram-bridge\]\s*$/m, "[agents.tg]");
2282
+ if (/^\[agents\.tg\]\s*$/m.test(tomlText)) {
2283
+ return { text: tomlText, changed: tomlText !== original };
2435
2284
  }
2436
2285
  const sep = tomlText.length === 0 || tomlText.endsWith("\n") ? "" : "\n";
2437
- const block = `\n[agents.telegram-bridge]\nlabel = "Telegram Bridge"\n`;
2286
+ const block = `\n[agents.tg]\nlabel = "Telegram Bridge"\n`;
2438
2287
  return { text: tomlText + sep + block, changed: true };
2439
2288
  }
2440
2289
 
@@ -2456,7 +2305,7 @@ function buildTelegramBridgeSpawnEnv(parentEnv) {
2456
2305
  // config parse, auth failure) are recoverable instead of
2457
2306
  // /dev/null'd by `stdio: "ignore"`.
2458
2307
  function telegramBridgeLog(projectId) {
2459
- return path.join(CONFIG_DIR, `telegram-bridge-${projectId}.log`);
2308
+ return path.join(CONFIG_DIR, `tg-bridge-${projectId}.log`);
2460
2309
  }
2461
2310
 
2462
2311
  // Tail the last N lines of a file without reading the whole thing
@@ -2676,6 +2525,12 @@ router.post("/api/telegram", async (req, res) => {
2676
2525
  try {
2677
2526
  if (!fs.existsSync(BRIDGE_DIR)) {
2678
2527
  execFileSync("gh", ["repo", "clone", "realproject7/agentchattr-telegram", BRIDGE_DIR], { encoding: "utf-8", timeout: 30000 });
2528
+ // #444: pin to a known commit after clone
2529
+ try {
2530
+ execFileSync("git", ["-C", BRIDGE_DIR, "checkout", "-B", "pinned", AGENTCHATTR_TELEGRAM_PIN], { encoding: "utf-8", timeout: 30000 });
2531
+ } catch {
2532
+ console.warn(`[telegram] WARNING: could not check out agentchattr-telegram pin ${AGENTCHATTR_TELEGRAM_PIN}; falling back to default branch.`);
2533
+ }
2679
2534
  }
2680
2535
  // #380: create the dedicated venv if missing. `python3 -m venv`
2681
2536
  // builds a fresh isolated environment that bypasses PEP 668
@@ -2706,7 +2561,7 @@ router.post("/api/telegram", async (req, res) => {
2706
2561
  });
2707
2562
  }
2708
2563
  // #383 Bug 3: ensure every known project's AC config declares
2709
- // the `telegram-bridge` agent. Without this, AC's registry
2564
+ // the `tg` agent. Without this, AC's registry
2710
2565
  // rejects the bridge's register call with `400 unknown base`
2711
2566
  // and the bridge enters an infinite re-register loop.
2712
2567
  // Idempotent — append-only, skips configs that already have
@@ -2855,7 +2710,7 @@ router.post("/api/telegram", async (req, res) => {
2855
2710
  const acUrl = resolveProjectAgentchattrUrl(cfg, project);
2856
2711
  if (acUrl) {
2857
2712
  const acPort = new URL(acUrl).port || "8300";
2858
- await fetch(`http://127.0.0.1:${acPort}/api/deregister/telegram-bridge`, {
2713
+ await fetch(`http://127.0.0.1:${acPort}/api/deregister/tg`, {
2859
2714
  method: "POST",
2860
2715
  signal: AbortSignal.timeout(3000),
2861
2716
  }).catch(() => {});
@@ -2938,7 +2793,7 @@ const DISCORD_BRIDGE_SRC = path.join(__dirname, "..", "bridges", "discord");
2938
2793
  const DISCORD_BRIDGE_DIR = path.join(CONFIG_DIR, "agentchattr-discord");
2939
2794
 
2940
2795
  function discordPidFile(projectId) {
2941
- return path.join(CONFIG_DIR, `discord-bridge-${projectId}.pid`);
2796
+ return path.join(CONFIG_DIR, `dc-bridge-${projectId}.pid`);
2942
2797
  }
2943
2798
 
2944
2799
  function discordConfigToml(projectId) {
@@ -2946,11 +2801,16 @@ function discordConfigToml(projectId) {
2946
2801
  }
2947
2802
 
2948
2803
  function discordBridgeLog(projectId) {
2949
- return path.join(CONFIG_DIR, `discord-bridge-${projectId}.log`);
2804
+ return path.join(CONFIG_DIR, `dc-bridge-${projectId}.log`);
2950
2805
  }
2951
2806
 
2952
2807
  function buildDiscordBridgeToml(dc, projectId) {
2953
- const cursorFile = path.join(CONFIG_DIR, `discord-bridge-cursor-${projectId}.json`);
2808
+ const cursorFile = path.join(CONFIG_DIR, `dc-bridge-cursor-${projectId}.json`);
2809
+ // #439: migrate old cursor file so the bridge doesn't replay history
2810
+ const oldCursor = path.join(CONFIG_DIR, `discord-bridge-cursor-${projectId}.json`);
2811
+ if (!fs.existsSync(cursorFile) && fs.existsSync(oldCursor)) {
2812
+ fs.renameSync(oldCursor, cursorFile);
2813
+ }
2954
2814
  return (
2955
2815
  `[discord]\n` +
2956
2816
  `bot_token = "${dc.bot_token}"\n` +
@@ -2961,11 +2821,14 @@ function buildDiscordBridgeToml(dc, projectId) {
2961
2821
  }
2962
2822
 
2963
2823
  function patchAgentchattrConfigForDiscordBridge(tomlText) {
2964
- if (/^\[agents\.discord-bridge\]\s*$/m.test(tomlText)) {
2965
- return { text: tomlText, changed: false };
2824
+ // #439: migrate old slug if present
2825
+ const original = tomlText;
2826
+ tomlText = tomlText.replace(/^\[agents\.discord-bridge\]\s*$/m, "[agents.dc]");
2827
+ if (/^\[agents\.dc\]\s*$/m.test(tomlText)) {
2828
+ return { text: tomlText, changed: tomlText !== original };
2966
2829
  }
2967
2830
  const sep = tomlText.length === 0 || tomlText.endsWith("\n") ? "" : "\n";
2968
- const block = `\n[agents.discord-bridge]\nlabel = "Discord Bridge"\n`;
2831
+ const block = `\n[agents.dc]\nlabel = "Discord Bridge"\n`;
2969
2832
  return { text: tomlText + sep + block, changed: true };
2970
2833
  }
2971
2834
 
@@ -3147,7 +3010,7 @@ router.post("/api/discord", async (req, res) => {
3147
3010
  `pip output tail:\n${pipOutput.split("\n").slice(-10).join("\n")}`,
3148
3011
  });
3149
3012
  }
3150
- // Patch all project AC configs with [agents.discord-bridge]
3013
+ // Patch all project AC configs with [agents.dc]
3151
3014
  const patched = [];
3152
3015
  try {
3153
3016
  const cfgAll = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
@@ -3246,7 +3109,7 @@ router.post("/api/discord", async (req, res) => {
3246
3109
  const acUrl = resolveProjectAgentchattrUrl(cfg, project);
3247
3110
  if (acUrl) {
3248
3111
  const acPort = new URL(acUrl).port || "8300";
3249
- await fetch(`http://127.0.0.1:${acPort}/api/deregister/discord-bridge`, {
3112
+ await fetch(`http://127.0.0.1:${acPort}/api/deregister/dc`, {
3250
3113
  method: "POST",
3251
3114
  signal: AbortSignal.timeout(3000),
3252
3115
  }).catch(() => {});
@@ -3374,7 +3237,7 @@ module.exports.parseActiveBatch = parseActiveBatch;
3374
3237
  // summarizeItems for the batch-progress fixture test.
3375
3238
  module.exports.buildNoPrRow = buildNoPrRow;
3376
3239
  module.exports.summarizeItems = summarizeItems;
3377
- // #353: expose readLastLines for the telegram-bridge test.
3240
+ // #353: expose readLastLines for the tg-bridge test.
3378
3241
  module.exports.readLastLines = readLastLines;
3379
3242
  // #380: expose checkTelegramBridgePythonDeps so the bridge test can
3380
3243
  // exercise the venv-path interpreter argument round trip.
@@ -183,7 +183,7 @@ try {
183
183
  assert.match(toml13, /agentchattr_url = "http:\/\/127\.0\.0\.1:8301"/);
184
184
  // #404: cursor_file must be per-project so multiple bridges
185
185
  // don't clobber each other's position.
186
- assert.match(toml13, /cursor_file = ".*telegram-bridge-cursor-testproject\.json"/);
186
+ assert.match(toml13, /cursor_file = ".*tg-bridge-cursor-testproject\.json"/);
187
187
  // Must NOT emit a separate [agentchattr] section — the bridge
188
188
  // would silently ignore it.
189
189
  assert.equal(toml13.includes("\n[agentchattr]\n"), false);
@@ -196,19 +196,19 @@ try {
196
196
  "[agents.head]\nlabel = \"Head\"\n\n[agents.dev]\nlabel = \"Dev\"\n";
197
197
  const first = patchAgentchattrConfigForTelegramBridge(baseConfig);
198
198
  assert.equal(first.changed, true);
199
- assert.match(first.text, /^\[agents\.telegram-bridge\]$/m);
199
+ assert.match(first.text, /^\[agents\.tg\]$/m);
200
200
  assert.match(first.text, /label = "Telegram Bridge"/);
201
201
  // Running a second time is a no-op.
202
202
  const second = patchAgentchattrConfigForTelegramBridge(first.text);
203
203
  assert.equal(second.changed, false);
204
204
  assert.equal(second.text, first.text);
205
- // A config that was hand-patched during diagnosis is recognized
206
- // as already-correct do not clobber the operator's edit.
205
+ // #439: a config with old slug [agents.telegram-bridge] is migrated
206
+ // to [agents.tg] and flagged as changed.
207
207
  const handPatched =
208
208
  baseConfig + "\n[agents.telegram-bridge]\nlabel = \"Telegram Bridge\"\n";
209
209
  const third = patchAgentchattrConfigForTelegramBridge(handPatched);
210
- assert.equal(third.changed, false);
211
- assert.equal(third.text, handPatched);
210
+ assert.equal(third.changed, true);
211
+ assert.match(third.text, /^\[agents\.tg\]$/m);
212
212
 
213
213
  // 15) #383 Bug 4: buildTelegramBridgeSpawnEnv strips the three
214
214
  // env vars the upstream bridge treats as higher-precedence
@@ -38,15 +38,15 @@ color = "#da7756"
38
38
  label = "Builder"
39
39
 
40
40
  # #383: AC's registry rejects bases not declared in config.toml.
41
- # The Telegram bridge registers as `telegram-bridge`, so every
42
- # per-project AC config must declare it. The bridge has no
43
- # command/cwd of its own — it is a long-running external client
44
- # that posts to AC's HTTP API.
45
- [agents.telegram-bridge]
41
+ # The Telegram bridge registers as `tg` (#439: renamed from
42
+ # `telegram-bridge`), so every per-project AC config must declare
43
+ # it. The bridge has no command/cwd of its own — it is a long-running
44
+ # external client that posts to AC's HTTP API.
45
+ [agents.tg]
46
46
  label = "Telegram Bridge"
47
47
 
48
- # #399: Discord bridge registers as `discord-bridge`.
49
- [agents.discord-bridge]
48
+ # #399/#439: Discord bridge registers as `dc` (renamed from `discord-bridge`).
49
+ [agents.dc]
50
50
  label = "Discord Bridge"
51
51
 
52
52
  [routing]
@@ -1 +0,0 @@
1
- self.__SSG_MANIFEST=new Set(["\u002Fproject\u002F[id]","\u002Fproject\u002F[id]\u002Fmemory","\u002Fproject\u002F[id]\u002Fqueue"]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
@@ -1,2 +0,0 @@
1
- @font-face{font-family:Geist Mono;font-style:normal;font-weight:100 900;font-display:swap;src:url(../media/4fa387ec64143e14-s.0q3udbd2bu5yp.woff2)format("woff2");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Geist Mono;font-style:normal;font-weight:100 900;font-display:swap;src:url(../media/bbc41e54d2fcbd21-s.0gw~uztddq1df.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Geist Mono;font-style:normal;font-weight:100 900;font-display:swap;src:url(../media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Geist Mono Fallback;src:local(Arial);ascent-override:74.67%;descent-override:21.92%;line-gap-override:0.0%;size-adjust:134.59%}.geist_mono_8d43a2aa-module__8Li5zG__className{font-family:Geist Mono,Geist Mono Fallback;font-style:normal}.geist_mono_8d43a2aa-module__8Li5zG__variable{--font-geist-mono:"Geist Mono", "Geist Mono Fallback"}
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--color-red-400:#ff6568;--color-red-500:#fb2c36;--color-red-700:#bf000f;--color-red-900:#82181a;--color-amber-200:#fee685;--color-amber-300:#ffd236;--color-amber-400:#fcbb00;--color-amber-500:#f99c00;--color-green-500:#00c758;--color-blue-300:#90c5ff;--color-blue-400:#54a2ff;--color-neutral-200:#e5e5e5;--color-neutral-300:#d4d4d4;--color-neutral-400:#a1a1a1;--color-neutral-500:#737373;--color-neutral-600:#525252;--color-neutral-700:#404040;--color-neutral-900:#171717;--color-neutral-950:#0a0a0a;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-3xl:48rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-lg:.5rem;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-geist-mono)}@supports (color:lab(0% 0 0)){:root,:host{--color-red-400:lab(63.7053% 60.745 31.3109);--color-red-500:lab(55.4814% 75.0732 48.8528);--color-red-700:lab(40.4273% 67.2623 53.7441);--color-red-900:lab(28.5139% 44.5539 29.0463);--color-amber-200:lab(91.7203% -.505269 49.9084);--color-amber-300:lab(86.4156% 6.13147 78.3961);--color-amber-400:lab(80.1641% 16.6016 99.2089);--color-amber-500:lab(72.7183% 31.8672 97.9407);--color-green-500:lab(70.5521% -66.5147 45.8073);--color-blue-300:lab(77.5052% -6.4629 -36.42);--color-blue-400:lab(65.0361% -1.42065 -56.9802);--color-neutral-200:lab(90.952% 0 -.0000119209);--color-neutral-300:lab(84.92% 0 -.0000119209);--color-neutral-400:lab(66.128% -.0000298023 .0000119209);--color-neutral-500:lab(48.496% 0 0);--color-neutral-600:lab(34.924% 0 0);--color-neutral-700:lab(27.036% 0 0);--color-neutral-900:lab(7.78201% -.0000149012 0);--color-neutral-950:lab(2.75381% 0 0)}}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-5{top:calc(var(--spacing) * 5)}.top-6{top:calc(var(--spacing) * 6)}.right-0{right:calc(var(--spacing) * 0)}.right-3{right:calc(var(--spacing) * 3)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-5{bottom:calc(var(--spacing) * 5)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing) * 0)}.left-16{left:calc(var(--spacing) * 16)}.left-\[14px\]{left:14px}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.mx-4{margin-inline:calc(var(--spacing) * 4)}.my-2{margin-block:calc(var(--spacing) * 2)}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.list-item{display:list-item}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-\[12px\]{height:12px}.h-\[80vh\]{height:80vh}.h-\[calc\(100\%-80px\)\]{height:calc(100% - 80px)}.h-full{height:100%}.h-px{height:1px}.max-h-28{max-height:calc(var(--spacing) * 28)}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-60{max-height:calc(var(--spacing) * 60)}.max-h-\[90vh\]{max-height:90vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[88px\]{min-height:88px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-44{width:calc(var(--spacing) * 44)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-\[1px\]{width:1px}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-\[60\%\]{max-width:60%}.max-w-\[520px\]{max-width:520px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[140px\]{min-width:140px}.min-w-\[220px\]{min-width:220px}.min-w-\[280px\]{min-width:280px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.cursor-col-resize{cursor:col-resize}.cursor-move{cursor:move}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-flow-col{grid-auto-flow:column}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[\#ffcc00\]\/40{border-color:#fc06;border-color:lab(84.7597% 8.24091 84.7906/.4)}.border-accent,.border-accent\/20{border-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.border-accent\/20{border-color:color-mix(in oklab, var(--accent) 20%, transparent)}}.border-accent\/30{border-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.border-accent\/30{border-color:color-mix(in oklab, var(--accent) 30%, transparent)}}.border-accent\/40{border-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.border-accent\/40{border-color:color-mix(in oklab, var(--accent) 40%, transparent)}}.border-accent\/50{border-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.border-accent\/50{border-color:color-mix(in oklab, var(--accent) 50%, transparent)}}.border-amber-500\/40{border-color:#f99c0066}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/40{border-color:color-mix(in oklab, var(--color-amber-500) 40%, transparent)}}.border-border,.border-border\/30{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/30{border-color:color-mix(in oklab, var(--border) 30%, transparent)}}.border-border\/40{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/40{border-color:color-mix(in oklab, var(--border) 40%, transparent)}}.border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/50{border-color:color-mix(in oklab, var(--border) 50%, transparent)}}.border-border\/60{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/60{border-color:color-mix(in oklab, var(--border) 60%, transparent)}}.border-error,.border-error\/30{border-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.border-error\/30{border-color:color-mix(in oklab, var(--error) 30%, transparent)}}.border-error\/40{border-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.border-error\/40{border-color:color-mix(in oklab, var(--error) 40%, transparent)}}.border-error\/60{border-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.border-error\/60{border-color:color-mix(in oklab, var(--error) 60%, transparent)}}.border-red-700\/40{border-color:#bf000f66}@supports (color:color-mix(in lab, red, red)){.border-red-700\/40{border-color:color-mix(in oklab, var(--color-red-700) 40%, transparent)}}.border-red-700\/50{border-color:#bf000f80}@supports (color:color-mix(in lab, red, red)){.border-red-700\/50{border-color:color-mix(in oklab, var(--color-red-700) 50%, transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.bg-\[\#1a1a1a\]{background-color:#1a1a1a}.bg-\[\#ffcc00\]{background-color:#fc0}.bg-accent,.bg-accent\/5{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/5{background-color:color-mix(in oklab, var(--accent) 5%, transparent)}}.bg-accent\/10{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/10{background-color:color-mix(in oklab, var(--accent) 10%, transparent)}}.bg-accent\/30{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.bg-accent\/30{background-color:color-mix(in oklab, var(--accent) 30%, transparent)}}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/5{background-color:color-mix(in oklab, var(--color-amber-500) 5%, transparent)}}.bg-bg{background-color:var(--bg)}.bg-bg-surface,.bg-bg-surface\/50{background-color:var(--bg-surface)}@supports (color:color-mix(in lab, red, red)){.bg-bg-surface\/50{background-color:color-mix(in oklab, var(--bg-surface) 50%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-border{background-color:var(--border)}.bg-error,.bg-error\/5{background-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.bg-error\/5{background-color:color-mix(in oklab, var(--error) 5%, transparent)}}.bg-error\/10{background-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.bg-error\/10{background-color:color-mix(in oklab, var(--error) 10%, transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-neutral-400{background-color:var(--color-neutral-400)}.bg-neutral-900{background-color:var(--color-neutral-900)}.bg-neutral-950{background-color:var(--color-neutral-950)}.bg-neutral-950\/90{background-color:#0a0a0ae6}@supports (color:color-mix(in lab, red, red)){.bg-neutral-950\/90{background-color:color-mix(in oklab, var(--color-neutral-950) 90%, transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-900\/20{background-color:#82181a33}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/20{background-color:color-mix(in oklab, var(--color-red-900) 20%, transparent)}}.bg-red-900\/30{background-color:#82181a4d}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/30{background-color:color-mix(in oklab, var(--color-red-900) 30%, transparent)}}.bg-text-muted{background-color:var(--text-muted)}.bg-transparent{background-color:#0000}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.bg-white\/5{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-\[1px\]{padding-block:1px}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-5{padding-bottom:calc(var(--spacing) * 5)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-6{padding-left:calc(var(--spacing) * 6)}.pl-10{padding-left:calc(var(--spacing) * 10)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-geist-mono)}.font-sans{font-family:var(--font-sans)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[16px\]{font-size:16px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#ffcc00\]{color:#fc0}.text-accent,.text-accent\/70{color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.text-accent\/70{color:color-mix(in oklab, var(--accent) 70%, transparent)}}.text-amber-200\/90{color:#fee685e6}@supports (color:color-mix(in lab, red, red)){.text-amber-200\/90{color:color-mix(in oklab, var(--color-amber-200) 90%, transparent)}}.text-amber-300{color:var(--color-amber-300)}.text-amber-400{color:var(--color-amber-400)}.text-bg{color:var(--bg)}.text-blue-400{color:var(--color-blue-400)}.text-error{color:var(--error)}.text-neutral-200{color:var(--color-neutral-200)}.text-neutral-300{color:var(--color-neutral-300)}.text-neutral-400{color:var(--color-neutral-400)}.text-neutral-500{color:var(--color-neutral-500)}.text-neutral-600{color:var(--color-neutral-600)}.text-neutral-700{color:var(--color-neutral-700)}.text-red-400{color:var(--color-red-400)}.text-text{color:var(--text)}.text-text-muted,.text-text-muted\/60{color:var(--text-muted)}@supports (color:color-mix(in lab, red, red)){.text-text-muted\/60{color:color-mix(in oklab, var(--text-muted) 60%, transparent)}}.text-text-muted\/80{color:var(--text-muted)}@supports (color:color-mix(in lab, red, red)){.text-text-muted\/80{color:color-mix(in oklab, var(--text-muted) 80%, transparent)}}.text-white{color:var(--color-white)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.accent-accent{accent-color:var(--accent)}.opacity-0{opacity:0}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\:block:is(:where(.group):hover *){display:block}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\:text-text-muted::placeholder{color:var(--text-muted)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.last\:pb-0:last-child{padding-bottom:calc(var(--spacing) * 0)}@media (hover:hover){.hover\:border-accent:hover,.hover\:border-accent\/40:hover{border-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:border-accent\/40:hover{border-color:color-mix(in oklab, var(--accent) 40%, transparent)}}.hover\:border-error\/40:hover{border-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.hover\:border-error\/40:hover{border-color:color-mix(in oklab, var(--error) 40%, transparent)}}.hover\:border-text-muted:hover{border-color:var(--text-muted)}.hover\:border-white\/40:hover{border-color:#fff6}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/40:hover{border-color:color-mix(in oklab, var(--color-white) 40%, transparent)}}.hover\:bg-\[\#1a1a1a\]:hover{background-color:#1a1a1a}.hover\:bg-accent-dim:hover{background-color:var(--accent-dim)}.hover\:bg-accent\/5:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/5:hover{background-color:color-mix(in oklab, var(--accent) 5%, transparent)}}.hover\:bg-accent\/10:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/10:hover{background-color:color-mix(in oklab, var(--accent) 10%, transparent)}}.hover\:bg-accent\/20:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/20:hover{background-color:color-mix(in oklab, var(--accent) 20%, transparent)}}.hover\:bg-error\/20:hover{background-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-error\/20:hover{background-color:color-mix(in oklab, var(--error) 20%, transparent)}}.hover\:bg-white\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/5:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:text-accent:hover{color:var(--accent)}.hover\:text-accent-dim:hover{color:var(--accent-dim)}.hover\:text-blue-300:hover{color:var(--color-blue-300)}.hover\:text-blue-400:hover{color:var(--color-blue-400)}.hover\:text-error:hover{color:var(--error)}.hover\:text-text:hover{color:var(--text)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:border-accent:focus{border-color:var(--accent)}.focus\:opacity-100:focus{opacity:1}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-accent:focus{--tw-ring-color:var(--accent)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:inline{display:inline}.sm\:inline-flex{display:inline-flex}}@media (min-width:48rem){.md\:flex{display:flex}.md\:h-auto{height:auto}.md\:w-px{width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-start{align-items:flex-start}.md\:gap-6{gap:calc(var(--spacing) * 6)}.md\:self-stretch{align-self:stretch}.md\:border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.md\:bg-border{background-color:var(--border)}}@media (min-width:64rem){.lg\:block{display:block}.lg\:min-h-0{min-height:calc(var(--spacing) * 0)}.lg\:min-w-\[280px\]{min-width:280px}.lg\:flex-1{flex:1}.lg\:flex-row{flex-direction:row}.lg\:overflow-hidden{overflow:hidden}.lg\:overflow-y-auto{overflow-y:auto}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.\[\&_a\]\:text-accent a{color:var(--accent)}.\[\&_a\]\:underline a{text-decoration-line:underline}.\[\&_blockquote\]\:border-l-2 blockquote{border-left-style:var(--tw-border-style);border-left-width:2px}.\[\&_blockquote\]\:border-border blockquote{border-color:var(--border)}.\[\&_blockquote\]\:pl-2 blockquote{padding-left:calc(var(--spacing) * 2)}.\[\&_blockquote\]\:text-text-muted blockquote{color:var(--text-muted)}.\[\&_code\]\:rounded code{border-radius:.25rem}.\[\&_code\]\:bg-bg-surface code{background-color:var(--bg-surface)}.\[\&_code\]\:px-1 code{padding-inline:calc(var(--spacing) * 1)}.\[\&_code\]\:text-\[11px\] code{font-size:11px}.\[\&_h1\]\:mt-3 h1{margin-top:calc(var(--spacing) * 3)}.\[\&_h1\]\:mb-2 h1{margin-bottom:calc(var(--spacing) * 2)}.\[\&_h1\]\:text-\[14px\] h1{font-size:14px}.\[\&_h1\]\:font-semibold h1{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.\[\&_h2\]\:mt-3 h2{margin-top:calc(var(--spacing) * 3)}.\[\&_h2\]\:mb-1\.5 h2{margin-bottom:calc(var(--spacing) * 1.5)}.\[\&_h2\]\:text-\[13px\] h2{font-size:13px}.\[\&_h2\]\:font-semibold h2{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.\[\&_h3\]\:mt-2 h3{margin-top:calc(var(--spacing) * 2)}.\[\&_h3\]\:mb-1 h3{margin-bottom:calc(var(--spacing) * 1)}.\[\&_h3\]\:text-\[12px\] h3{font-size:12px}.\[\&_h3\]\:font-semibold h3{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.\[\&_hr\]\:my-3 hr{margin-block:calc(var(--spacing) * 3)}.\[\&_hr\]\:border-border hr{border-color:var(--border)}.\[\&_li\]\:my-0\.5 li{margin-block:calc(var(--spacing) * .5)}.\[\&_ol\]\:my-1\.5 ol{margin-block:calc(var(--spacing) * 1.5)}.\[\&_ol\]\:list-decimal ol{list-style-type:decimal}.\[\&_ol\]\:pl-4 ol{padding-left:calc(var(--spacing) * 4)}.\[\&_p\]\:my-1\.5 p{margin-block:calc(var(--spacing) * 1.5)}.\[\&_strong\]\:text-text strong{color:var(--text)}.\[\&_ul\]\:my-1\.5 ul{margin-block:calc(var(--spacing) * 1.5)}.\[\&_ul\]\:list-disc ul{list-style-type:disc}.\[\&_ul\]\:pl-4 ul{padding-left:calc(var(--spacing) * 4)}}:root{--bg:#0a0a0a;--bg-surface:#111;--text:#e0e0e0;--text-muted:#737373;--accent:#0f8;--accent-dim:#00cc6a;--border:#2a2a2a;--error:#f44}::selection{background:var(--accent);color:var(--bg)}body{background:var(--bg);color:var(--text);font-family:var(--font-geist-mono), ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1,h2,h3,h4,h5,h6{font-family:var(--font-geist-mono), ui-monospace, monospace;letter-spacing:-.01em}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:0}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}:focus-visible{outline:1px solid var(--accent);outline-offset:1px}@keyframes qw-blink{0%,50%{opacity:1}51%,to{opacity:0}}.animate-qw-blink{animation:1s steps(2,start) infinite qw-blink}@keyframes qw-name-shimmer{0%,to{color:var(--accent)}50%{color:color-mix(in srgb, var(--accent) 55%, #e0e0e0)}}.animate-name-shimmer{animation:1.6s ease-in-out infinite qw-name-shimmer}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,78759,e=>{"use strict";var t=e.i(43476),s=e.i(71645);let r=[{title:"You assign a task in the chat",body:"Tell @head what to build. Be as specific or as vague as you like."},{title:"Head creates a GitHub issue",body:"Head opens an issue, adds it to the queue, and waits for your trigger."},{title:"Dev writes the code",body:"Dev clones a branch, implements the change, and opens a pull request."},{title:"Reviewers check the work",body:"RE1 and RE2 each review the PR independently. Both must approve before the PR is mergeable."},{title:"Head merges and continues",body:"Head merges the approved PR and assigns the next ticket from the queue. The cycle continues all night while you sleep."}];e.s(["default",0,function({open:e,onClose:a}){return((0,s.useEffect)(()=>{if(!e)return;let t=e=>{"Escape"===e.key&&a()};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e,a]),e)?(0,t.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm",onClick:a,role:"dialog","aria-modal":"true","aria-labelledby":"how-to-work-title",children:(0,t.jsxs)("div",{className:"relative mx-4 max-w-xl w-full max-h-[90vh] overflow-auto rounded-lg border border-white/10 bg-neutral-950 p-6 shadow-2xl",onClick:e=>e.stopPropagation(),children:[(0,t.jsx)("button",{type:"button",onClick:a,"aria-label":"Close",className:"absolute right-3 top-3 rounded p-1 text-neutral-400 hover:bg-white/5 hover:text-white",children:(0,t.jsx)("svg",{width:"18",height:"18",viewBox:"0 0 20 20",fill:"none",stroke:"currentColor",strokeWidth:"1.8",children:(0,t.jsx)("path",{d:"M4 4l12 12M16 4L4 16",strokeLinecap:"round"})})}),(0,t.jsx)("h2",{id:"how-to-work-title",className:"text-base font-semibold text-white",children:"How QuadWork builds your code"}),(0,t.jsx)("p",{className:"mt-2 text-[12px] text-neutral-400",children:"Five steps from your one-line request to a merged pull request."}),(0,t.jsxs)("ol",{className:"mt-5 relative",children:[(0,t.jsx)("span",{"aria-hidden":!0,className:"absolute left-[14px] top-3 bottom-3 w-px bg-accent/30"}),r.map((e,s)=>(0,t.jsxs)("li",{className:"relative pl-10 pb-5 last:pb-0",children:[(0,t.jsx)("span",{className:"absolute left-0 top-0 inline-flex items-center justify-center w-7 h-7 rounded-full border border-accent bg-neutral-950 text-accent text-[12px] font-semibold tabular-nums","aria-hidden":!0,children:s+1}),(0,t.jsx)("div",{className:"text-[13px] font-semibold text-white",children:e.title}),(0,t.jsx)("div",{className:"mt-1 text-[12px] leading-relaxed text-neutral-400",children:e.body})]},s))]})]})}):null}])},54338,e=>{"use strict";var t=e.i(43476),s=e.i(71645),r=e.i(22016),a=e.i(78759);function l({hasProjects:e}){let[i,o]=(0,s.useState)(!1);return(0,t.jsxs)("div",{className:"flex flex-col items-center justify-center text-center px-6 py-12 border border-border bg-bg-surface",children:[(0,t.jsxs)("svg",{width:"64",height:"64",viewBox:"0 0 64 64",fill:"none","aria-hidden":!0,className:"text-accent",children:[(0,t.jsx)("rect",{x:"6",y:"14",width:"18",height:"22",rx:"2",stroke:"currentColor",strokeWidth:"2"}),(0,t.jsx)("rect",{x:"40",y:"14",width:"18",height:"22",rx:"2",stroke:"currentColor",strokeWidth:"2"}),(0,t.jsx)("rect",{x:"6",y:"42",width:"18",height:"14",rx:"2",stroke:"currentColor",strokeWidth:"2"}),(0,t.jsx)("rect",{x:"40",y:"42",width:"18",height:"14",rx:"2",stroke:"currentColor",strokeWidth:"2"}),(0,t.jsx)("circle",{cx:"15",cy:"25",r:"2",fill:"currentColor"}),(0,t.jsx)("circle",{cx:"49",cy:"25",r:"2",fill:"currentColor"}),(0,t.jsx)("circle",{cx:"15",cy:"49",r:"2",fill:"currentColor"}),(0,t.jsx)("circle",{cx:"49",cy:"49",r:"2",fill:"currentColor"}),(0,t.jsx)("path",{d:"M24 25 L40 25 M24 49 L40 49 M15 36 L15 42 M49 36 L49 42",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]}),(0,t.jsx)("h1",{className:"mt-5 text-lg font-semibold text-text max-w-md",children:e?"Pick a project from the sidebar to start working":"Welcome to QuadWork — let's set up your first AI dev team"}),(0,t.jsx)("p",{className:"mt-2 text-[12px] text-text-muted leading-relaxed max-w-md",children:e?"Each project has its own 4-agent team and chat. Click any chip in the left sidebar to open one.":"QuadWork runs Head, Dev, and two Reviewers as a team. They open issues, write code, review PRs, and merge — while you sleep."}),(0,t.jsxs)("div",{className:"mt-5 flex items-center gap-3",children:[e?(0,t.jsx)("span",{className:"text-[11px] text-text-muted italic",children:"← look at the left sidebar"}):(0,t.jsx)(r.default,{href:"/setup",className:"px-4 py-2 text-[12px] font-semibold text-bg bg-accent hover:bg-accent-dim transition-colors",children:"Add Your First Project →"}),(0,t.jsx)("button",{type:"button",onClick:()=>o(!0),className:"px-4 py-2 text-[12px] text-text-muted border border-border hover:text-text hover:border-text-muted transition-colors",children:"How to Work"})]}),(0,t.jsx)(a.default,{open:i,onClose:()=>o(!1)})]})}e.s(["default",0,function(){let[e,a]=(0,s.useState)([]),[i,o]=(0,s.useState)([]),[c,n]=(0,s.useState)("loading");return(0,s.useEffect)(()=>{fetch("/api/projects").then(e=>{if(!e.ok)throw Error(`${e.status}`);return e.json()}).then(e=>{e.projects&&Array.isArray(e.projects)&&a(e.projects.filter(e=>!e.archived)),e.recentEvents&&Array.isArray(e.recentEvents)&&o(e.recentEvents),n("loaded")}).catch(()=>{n("error")})},[]),(0,t.jsxs)("div",{className:"h-full overflow-y-auto p-6",children:["loaded"===c&&(0,t.jsx)("div",{className:"mb-6",children:(0,t.jsx)(l,{hasProjects:e.length>0})}),"error"===c&&(0,t.jsx)("div",{className:"mb-6 border border-error/30 bg-error/5 text-error text-[11px] px-3 py-2",children:"Could not load projects from /api/projects. The dashboard may be out of date — check the server logs and reload."}),(0,t.jsxs)("div",{className:"mb-6",children:[(0,t.jsx)("h1",{className:"text-lg font-semibold text-text tracking-tight",children:"Projects"}),(0,t.jsxs)("p",{className:"text-xs text-text-muted mt-1",children:[e.length," configured project",1!==e.length?"s":""]})]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3 mb-8",children:[e.map(e=>(0,t.jsxs)(r.default,{href:`/project/${e.id}`,className:"block border border-border bg-bg-surface p-4 hover:bg-[#1a1a1a] transition-colors group",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:`w-1.5 h-1.5 rounded-full ${"active"===e.state?"bg-accent":"bg-text-muted"}`}),(0,t.jsx)("span",{className:"text-sm font-semibold text-text",children:e.name}),(0,t.jsx)("span",{className:"text-[10px] text-text-muted",children:e.state})]}),(0,t.jsx)("span",{className:"text-[10px] text-text-muted opacity-0 group-hover:opacity-100 transition-opacity",children:"open →"})]}),(0,t.jsxs)("div",{className:"flex gap-4 text-[11px] mb-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-text-muted",children:"agents"}),(0,t.jsx)("span",{className:"ml-1.5 text-text",children:e.agentCount})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-text-muted",children:"PRs"}),(0,t.jsx)("span",{className:"ml-1.5 text-text",children:e.openPrs})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-text-muted",children:"repo"}),(0,t.jsx)("span",{className:"ml-1.5 text-text",children:e.repo})]})]}),e.lastActivity&&(0,t.jsxs)("div",{className:"text-[10px] text-text-muted",children:["last activity: ",function(e){let t=Math.floor((Date.now()-new Date(e).getTime())/6e4);if(t<1)return"just now";if(t<60)return`${t}m ago`;let s=Math.floor(t/60);if(s<24)return`${s}h ago`;let r=Math.floor(s/24);return`${r}d ago`}(e.lastActivity)]})]},e.id)),(0,t.jsx)(r.default,{href:"/setup",className:"border border-dashed border-border p-4 flex items-center justify-center text-text-muted hover:text-text hover:border-text-muted transition-colors min-h-[88px]",children:(0,t.jsx)("span",{className:"text-sm",children:"+ New Project"})})]}),(0,t.jsxs)("div",{className:"mb-6",children:[(0,t.jsx)("h2",{className:"text-xs text-text-muted uppercase tracking-wider mb-3",children:"Recent Activity"}),(0,t.jsxs)("div",{className:"border border-border bg-bg-surface",children:[0===i.length&&(0,t.jsx)("div",{className:"px-3 py-3 text-[11px] text-text-muted",children:"No recent activity"}),i.map((e,s)=>(0,t.jsxs)("div",{className:"flex gap-3 px-3 py-1.5 border-b border-border/50 last:border-b-0 text-[11px]",children:[(0,t.jsx)("span",{className:"text-text-muted shrink-0 w-10 text-right tabular-nums",children:e.time?.slice(0,5)||""}),(0,t.jsx)("span",{className:"text-accent shrink-0 font-semibold w-12",children:e.projectName}),(0,t.jsx)("span",{className:"text-[#ffcc00] shrink-0 font-semibold w-12",children:e.actor}),(0,t.jsx)("span",{className:"text-text truncate min-w-0",children:e.text})]},`${e.time}-${s}`))]})]})]})}],54338)}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,67585,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"BailoutToCSR",{enumerable:!0,get:function(){return l}});let r=e.r(32061);function l({reason:e,children:t}){if("u"<typeof window)throw Object.defineProperty(new r.BailoutToCSRError(e),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return t}},9885,(e,t,n)=>{"use strict";function r(e){return e.split("/").map(e=>encodeURIComponent(e)).join("/")}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"encodeURIPath",{enumerable:!0,get:function(){return r}})},52157,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"PreloadChunks",{enumerable:!0,get:function(){return i}});let r=e.r(43476),l=e.r(74080),o=e.r(63599),u=e.r(9885),a=e.r(43369);function i({moduleIds:e}){if("u">typeof window)return null;let t=o.workAsyncStorage.getStore();if(void 0===t)return null;let n=[];if(t.reactLoadableManifest&&e){let r=t.reactLoadableManifest;for(let t of e){if(!r[t])continue;let e=r[t].files;n.push(...e)}}if(0===n.length)return null;let s=(0,a.getAssetTokenQuery)();return(0,r.jsx)(r.Fragment,{children:n.map(e=>{let n=`${t.assetPrefix}/_next/${(0,u.encodeURIPath)(e)}${s}`;return e.endsWith(".css")?(0,r.jsx)("link",{precedence:"dynamic",href:n,rel:"stylesheet",as:"style",nonce:t.nonce},e):((0,l.preload)(n,{as:"script",fetchPriority:"low",nonce:t.nonce}),null)})})}},69093,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return s}});let r=e.r(43476),l=e.r(71645),o=e.r(67585),u=e.r(52157);function a(e){return{default:e&&"default"in e?e.default:e}}let i={loader:()=>Promise.resolve(a(()=>null)),loading:null,ssr:!0},s=function(e){let t={...i,...e},n=(0,l.lazy)(()=>t.loader().then(a)),s=t.loading;function d(e){let a=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,i=!t.ssr||!!t.loading,d=i?l.Suspense:l.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:["u"<typeof window?(0,r.jsx)(u.PreloadChunks,{moduleIds:t.modules}):null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(o.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(d,{...i?{fallback:a}:{},children:c})}return d.displayName="LoadableComponent",d}},70703,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return l}});let r=e.r(55682)._(e.r(69093));function l(e,t){let n={};"function"==typeof e&&(n.loader=e);let l={...n,...t};return(0,r.default)({...l,modules:l.loadableGenerated?.modules})}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},5964,e=>{"use strict";var t=e.i(43476),n=e.i(70703),r=e.i(18566);let l=(0,n.default)(()=>e.A(93116),{loadableGenerated:{modules:[43200]},ssr:!1});e.s(["default",0,function(){let e=(0,r.usePathname)().split("/")[2]||"";return e&&"_"!==e?(0,t.jsx)(l,{projectId:e}):null}])},93116,e=>{e.v(t=>Promise.all(["static/chunks/12i404gkhv7q..js"].map(t=>e.l(t))).then(()=>t(43200)))}]);
@@ -1,4 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,72035,e=>{"use strict";var t=e.i(43476),s=e.i(71645);e.s(["default",0,function({projectId:e}){let[a,r]=(0,s.useState)([]),[n,o]=(0,s.useState)(""),[c,l]=(0,s.useState)(null),[d,i]=(0,s.useState)({}),[x,m]=(0,s.useState)(""),[p,h]=(0,s.useState)(""),[b,u]=(0,s.useState)(!1),[f,j]=(0,s.useState)(!1),[g,y]=(0,s.useState)(!1),[v,N]=(0,s.useState)("cards"),[S,C]=(0,s.useState)({memory_cards_dir:"",shared_memory_path:"",butler_scripts_dir:""}),[_,k]=(0,s.useState)(!1),[$,T]=(0,s.useState)(!1),w=(0,s.useCallback)(()=>{fetch(`/api/memory?project=${encodeURIComponent(e)}&action=cards&search=${encodeURIComponent(n)}`).then(e=>e.ok?e.json():[]).then(r).catch(()=>{})},[e,n]);(0,s.useEffect)(()=>{w()},[w]),(0,s.useEffect)(()=>{fetch(`/api/memory?project=${encodeURIComponent(e)}&action=status`).then(e=>e.ok?e.json():{agents:{}}).then(e=>i(e.agents||{})).catch(()=>{})},[e]),(0,s.useEffect)(()=>{fetch(`/api/memory?project=${encodeURIComponent(e)}&action=shared-memory`).then(e=>e.ok?e.json():{content:""}).then(e=>m(e.content)).catch(()=>{})},[e]),(0,s.useEffect)(()=>{fetch(`/api/memory?project=${encodeURIComponent(e)}&action=settings`).then(e=>e.ok?e.json():{}).then(e=>C({memory_cards_dir:e.memory_cards_dir||"",shared_memory_path:e.shared_memory_path||"",butler_scripts_dir:e.butler_scripts_dir||""})).catch(()=>{})},[e]);let R=t=>{u(!0),h(e=>e+`
2
- > ${t}
3
- `),fetch(`/api/memory?project=${encodeURIComponent(e)}&action=butler`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({command:t})}).then(e=>e.json()).then(s=>{h(e=>e+(s.ok?s.output:`Error: ${s.error}`)+"\n"),"inject.sh"===t&&fetch(`/api/memory?project=${encodeURIComponent(e)}&action=status`).then(e=>e.ok?e.json():{agents:{}}).then(e=>i(e.agents||{})).catch(()=>{}),("butler-scan.sh"===t||"butler-consolidate.sh"===t)&&w()}).catch(e=>h(t=>t+`Error: ${e.message}
4
- `)).finally(()=>u(!1))};return(0,t.jsxs)("div",{className:"h-full flex flex-col p-6 max-w-5xl",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,t.jsx)("h1",{className:"text-lg font-semibold text-text tracking-tight",children:"Shared Memory"}),(0,t.jsxs)("div",{className:"flex items-center gap-1 border border-border",children:[(0,t.jsx)("button",{onClick:()=>N("cards"),className:`px-3 py-1 text-[11px] ${"cards"===v?"bg-accent text-bg":"text-text-muted hover:text-text"}`,children:"Cards"}),(0,t.jsx)("button",{onClick:()=>N("editor"),className:`px-3 py-1 text-[11px] ${"editor"===v?"bg-accent text-bg":"text-text-muted hover:text-text"}`,children:"Editor"}),(0,t.jsx)("button",{onClick:()=>N("settings"),className:`px-3 py-1 text-[11px] ${"settings"===v?"bg-accent text-bg":"text-text-muted hover:text-text"}`,children:"Settings"})]})]}),(0,t.jsx)("div",{className:"flex items-center gap-4 mb-4 text-[11px]",children:Object.entries(d).map(([e,s])=>(0,t.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,t.jsx)("span",{className:`w-1.5 h-1.5 rounded-full ${s.injected?"bg-accent":"bg-text-muted"}`}),(0,t.jsx)("span",{className:"text-text-muted",children:e.toUpperCase()}),s.lastModified&&(0,t.jsx)("span",{className:"text-text-muted text-[10px]",children:new Date(s.lastModified).toLocaleTimeString()})]},e))}),(0,t.jsxs)("div",{className:"flex items-center gap-2 mb-4",children:[(0,t.jsx)("button",{onClick:()=>R("butler-scan.sh"),disabled:b,className:"px-3 py-1 text-[11px] border border-border text-text-muted hover:text-text hover:border-accent transition-colors disabled:opacity-50",children:"Scan"}),(0,t.jsx)("button",{onClick:()=>R("butler-consolidate.sh"),disabled:b,className:"px-3 py-1 text-[11px] border border-border text-text-muted hover:text-text hover:border-accent transition-colors disabled:opacity-50",children:"Consolidate"}),(0,t.jsx)("button",{onClick:()=>R("inject.sh"),disabled:b,className:"px-3 py-1 text-[11px] border border-border text-text-muted hover:text-text hover:border-accent transition-colors disabled:opacity-50",children:"Inject"}),b&&(0,t.jsx)("span",{className:"text-[10px] text-text-muted",children:"Running..."})]}),p&&(0,t.jsx)("div",{className:"mb-4 border border-border bg-bg-surface max-h-32 overflow-y-auto",children:(0,t.jsx)("pre",{className:"p-2 text-[10px] text-text-muted whitespace-pre-wrap",children:p.trim()})}),"cards"===v&&(0,t.jsxs)("div",{className:"flex-1 min-h-0 flex flex-col",children:[(0,t.jsx)("input",{value:n,onChange:e=>o(e.target.value),placeholder:"Search cards...",className:"mb-3 bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"}),(0,t.jsxs)("div",{className:"flex-1 overflow-y-auto border border-border",children:[0===a.length&&(0,t.jsx)("div",{className:"p-3 text-[11px] text-text-muted",children:"No memory cards found"}),a.map(e=>(0,t.jsxs)("div",{className:"border-b border-border/50 last:border-b-0",children:[(0,t.jsxs)("button",{onClick:()=>l(c===e.file?null:e.file),className:"w-full flex items-center gap-3 px-3 py-1.5 hover:bg-[#1a1a1a] transition-colors text-left",children:[(0,t.jsx)("span",{className:"text-[11px] text-text flex-1 truncate",children:e.title}),(0,t.jsx)("span",{className:"text-[10px] text-text-muted shrink-0",children:e.agent}),(0,t.jsx)("span",{className:"text-[10px] text-text-muted shrink-0",children:e.date}),e.tags&&(0,t.jsx)("span",{className:"text-[10px] text-accent shrink-0",children:e.tags})]}),c===e.file&&(0,t.jsx)("div",{className:"px-3 pb-2 bg-bg-surface",children:(0,t.jsx)("pre",{className:"text-[11px] text-text whitespace-pre-wrap",children:e.content})})]},e.file))]})]}),"editor"===v&&(0,t.jsxs)("div",{className:"flex-1 min-h-0 flex flex-col",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-2",children:[(0,t.jsx)("span",{className:"text-[11px] text-text-muted",children:"shared-memory.md"}),(0,t.jsx)("button",{onClick:()=>{j(!0),fetch(`/api/memory?project=${encodeURIComponent(e)}&action=save-memory`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:x})}).then(e=>e.json()).then(e=>{e.ok&&(y(!0),setTimeout(()=>y(!1),2e3))}).catch(()=>{}).finally(()=>j(!1))},disabled:f,className:"px-4 py-1 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:f?"Saving...":g?"Saved":"Save"})]}),(0,t.jsx)("textarea",{value:x,onChange:e=>m(e.target.value),className:"flex-1 bg-bg-surface border border-border p-3 text-[12px] text-text outline-none focus:border-accent resize-none"})]}),"settings"===v&&(0,t.jsxs)("div",{className:"flex-1 min-h-0 flex flex-col gap-4",children:[(0,t.jsx)("p",{className:"text-[11px] text-text-muted",children:"Override default paths for this project. Leave blank to use defaults."}),(0,t.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,t.jsx)("span",{className:"text-[11px] text-text-muted",children:"Memory Cards Directory"}),(0,t.jsx)("input",{value:S.memory_cards_dir,onChange:e=>C({...S,memory_cards_dir:e.target.value}),placeholder:"../agent-memory/archive/v2/cards",className:"bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"})]}),(0,t.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,t.jsx)("span",{className:"text-[11px] text-text-muted",children:"Shared Memory Path"}),(0,t.jsx)("input",{value:S.shared_memory_path,onChange:e=>C({...S,shared_memory_path:e.target.value}),placeholder:"../agent-memory/central/short-term/agent-os.md",className:"bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"})]}),(0,t.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,t.jsx)("span",{className:"text-[11px] text-text-muted",children:"Butler Scripts Directory"}),(0,t.jsx)("input",{value:S.butler_scripts_dir,onChange:e=>C({...S,butler_scripts_dir:e.target.value}),placeholder:"../agent-memory/scripts",className:"bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"})]}),(0,t.jsx)("div",{children:(0,t.jsx)("button",{onClick:()=>{k(!0),fetch(`/api/memory?project=${encodeURIComponent(e)}&action=save-settings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(S)}).then(e=>e.json()).then(e=>{e.ok&&(T(!0),setTimeout(()=>T(!1),2e3))}).catch(()=>{}).finally(()=>k(!1))},disabled:_,className:"px-4 py-1 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:_?"Saving...":$?"Saved":"Save Settings"})})]})]})}])},43200,e=>{e.n(e.i(72035))}]);