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.
- package/README.md +37 -8
- package/bin/quadwork.js +42 -59
- package/bridges/discord/discord_bridge.py +3 -3
- package/out/404.html +1 -1
- package/out/__next.__PAGE__.txt +3 -3
- package/out/__next._full.txt +14 -14
- package/out/__next._head.txt +4 -4
- package/out/__next._index.txt +7 -7
- package/out/__next._tree.txt +2 -2
- package/out/_next/static/chunks/{0zy-ktdv5zuby.js → 00_f~dht-py.~.js} +1 -1
- package/out/_next/static/chunks/{0ksh60pbzmyjf.js → 01keua0t73paf.js} +13 -13
- package/out/_next/static/chunks/0ggc226h4xp_6.css +2 -0
- package/out/_next/static/chunks/14zyqqpdz2x7j.js +1 -0
- package/out/_next/static/chunks/{0o3_.p5ivp5sp.js → 152f2hu-ivy6f.js} +1 -1
- package/out/_next/static/jXvlZMZi9MNbHTOZg0eK3/_ssgManifest.js +1 -0
- package/out/_next/static/media/favicon.0yjarmrcdsq9k.ico +0 -0
- package/out/_not-found/__next._full.txt +13 -13
- package/out/_not-found/__next._head.txt +4 -4
- package/out/_not-found/__next._index.txt +7 -7
- package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/out/_not-found/__next._not-found.txt +3 -3
- package/out/_not-found/__next._tree.txt +2 -2
- package/out/_not-found.html +1 -1
- package/out/_not-found.txt +13 -13
- package/out/app-shell/__next._full.txt +13 -13
- package/out/app-shell/__next._head.txt +4 -4
- package/out/app-shell/__next._index.txt +7 -7
- package/out/app-shell/__next._tree.txt +2 -2
- package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
- package/out/app-shell/__next.app-shell.txt +3 -3
- package/out/app-shell.html +1 -1
- package/out/app-shell.txt +13 -13
- package/out/favicon.ico +0 -0
- package/out/icon.png +0 -0
- package/out/icon.svg +10 -4
- package/out/index.html +1 -1
- package/out/index.txt +14 -14
- package/out/project/_/__next._full.txt +14 -14
- package/out/project/_/__next._head.txt +4 -4
- package/out/project/_/__next._index.txt +7 -7
- package/out/project/_/__next._tree.txt +2 -2
- package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
- package/out/project/_/__next.project.$d$id.txt +3 -3
- package/out/project/_/__next.project.txt +3 -3
- package/out/project/_/queue/__next._full.txt +14 -14
- package/out/project/_/queue/__next._head.txt +4 -4
- package/out/project/_/queue/__next._index.txt +7 -7
- package/out/project/_/queue/__next._tree.txt +2 -2
- package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
- package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
- package/out/project/_/queue/__next.project.$d$id.txt +3 -3
- package/out/project/_/queue/__next.project.txt +3 -3
- package/out/project/_/queue.html +1 -1
- package/out/project/_/queue.txt +14 -14
- package/out/project/_.html +1 -1
- package/out/project/_.txt +14 -14
- package/out/quadwork-symbol.svg +14 -0
- package/out/settings/__next._full.txt +14 -14
- package/out/settings/__next._head.txt +4 -4
- package/out/settings/__next._index.txt +7 -7
- package/out/settings/__next._tree.txt +2 -2
- package/out/settings/__next.settings.__PAGE__.txt +3 -3
- package/out/settings/__next.settings.txt +3 -3
- package/out/settings.html +1 -1
- package/out/settings.txt +14 -14
- package/out/setup/__next._full.txt +14 -14
- package/out/setup/__next._head.txt +4 -4
- package/out/setup/__next._index.txt +7 -7
- package/out/setup/__next._tree.txt +2 -2
- package/out/setup/__next.setup.__PAGE__.txt +3 -3
- package/out/setup/__next.setup.txt +3 -3
- package/out/setup.html +1 -1
- package/out/setup.txt +14 -14
- package/package.json +1 -1
- package/server/index.js +27 -15
- package/server/routes.discordBridge.test.js +5 -5
- package/server/routes.js +69 -206
- package/server/routes.telegramBridge.test.js +6 -6
- package/templates/config.toml +7 -7
- package/out/_next/static/AQ0US7_Pm9gOOelb-ks5q/_ssgManifest.js +0 -1
- package/out/_next/static/chunks/0j-zyy6.adwtl.css +0 -2
- package/out/_next/static/chunks/0n7b.b.q4nmo..js +0 -1
- package/out/_next/static/chunks/0~xrqi87fqraz.js +0 -1
- package/out/_next/static/chunks/12i404gkhv7q..js +0 -4
- package/out/_next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
- package/out/project/_/memory/__next._full.txt +0 -21
- package/out/project/_/memory/__next._head.txt +0 -6
- package/out/project/_/memory/__next._index.txt +0 -8
- package/out/project/_/memory/__next._tree.txt +0 -3
- package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +0 -6
- package/out/project/_/memory/__next.project.$d$id.memory.txt +0 -5
- package/out/project/_/memory/__next.project.$d$id.txt +0 -5
- package/out/project/_/memory/__next.project.txt +0 -5
- package/out/project/_/memory.html +0 -1
- package/out/project/_/memory.txt +0 -21
- /package/out/_next/static/{AQ0US7_Pm9gOOelb-ks5q → jXvlZMZi9MNbHTOZg0eK3}/_buildManifest.js +0 -0
- /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(
|
|
118
|
+
const { url: base, token } = getChattrConfig(projectId);
|
|
118
119
|
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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(
|
|
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
|
-
//
|
|
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, `
|
|
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 `
|
|
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, `
|
|
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
|
|
2431
|
-
// Idempotent: only appends if the section
|
|
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
|
|
2434
|
-
|
|
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.
|
|
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, `
|
|
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 `
|
|
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/
|
|
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, `
|
|
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, `
|
|
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, `
|
|
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
|
|
2965
|
-
|
|
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.
|
|
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.
|
|
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/
|
|
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
|
|
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 = ".*
|
|
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\.
|
|
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
|
-
//
|
|
206
|
-
//
|
|
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,
|
|
211
|
-
assert.
|
|
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
|
package/templates/config.toml
CHANGED
|
@@ -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 `
|
|
42
|
-
# per-project AC config must declare
|
|
43
|
-
# command/cwd of its own — it is a long-running
|
|
44
|
-
# that posts to AC's HTTP API.
|
|
45
|
-
[agents.
|
|
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.
|
|
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))}]);
|
|
Binary file
|