quadwork 1.0.16 → 1.0.17
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/bin/quadwork.js +9 -1
- package/out/404.html +1 -1
- package/out/__next.__PAGE__.txt +1 -1
- package/out/__next._full.txt +2 -2
- package/out/__next._head.txt +1 -1
- package/out/__next._index.txt +2 -2
- package/out/__next._tree.txt +2 -2
- package/out/_next/static/chunks/0caq73v0knw_w.js +1 -0
- package/out/_next/static/chunks/10b3c4k.q.yw..css +2 -0
- package/out/_not-found/__next._full.txt +2 -2
- package/out/_not-found/__next._head.txt +1 -1
- package/out/_not-found/__next._index.txt +2 -2
- package/out/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/out/_not-found/__next._not-found.txt +1 -1
- package/out/_not-found/__next._tree.txt +2 -2
- package/out/_not-found.html +1 -1
- package/out/_not-found.txt +2 -2
- package/out/app-shell/__next._full.txt +2 -2
- package/out/app-shell/__next._head.txt +1 -1
- package/out/app-shell/__next._index.txt +2 -2
- package/out/app-shell/__next._tree.txt +2 -2
- package/out/app-shell/__next.app-shell.__PAGE__.txt +1 -1
- package/out/app-shell/__next.app-shell.txt +1 -1
- package/out/app-shell.html +1 -1
- package/out/app-shell.txt +2 -2
- package/out/index.html +1 -1
- package/out/index.txt +2 -2
- package/out/project/_/__next._full.txt +2 -2
- package/out/project/_/__next._head.txt +1 -1
- package/out/project/_/__next._index.txt +2 -2
- package/out/project/_/__next._tree.txt +2 -2
- package/out/project/_/__next.project.$d$id.__PAGE__.txt +1 -1
- package/out/project/_/__next.project.$d$id.txt +1 -1
- package/out/project/_/__next.project.txt +1 -1
- package/out/project/_/memory/__next._full.txt +2 -2
- package/out/project/_/memory/__next._head.txt +1 -1
- package/out/project/_/memory/__next._index.txt +2 -2
- package/out/project/_/memory/__next._tree.txt +2 -2
- package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +1 -1
- package/out/project/_/memory/__next.project.$d$id.memory.txt +1 -1
- package/out/project/_/memory/__next.project.$d$id.txt +1 -1
- package/out/project/_/memory/__next.project.txt +1 -1
- package/out/project/_/memory.html +1 -1
- package/out/project/_/memory.txt +2 -2
- package/out/project/_/queue/__next._full.txt +2 -2
- package/out/project/_/queue/__next._head.txt +1 -1
- package/out/project/_/queue/__next._index.txt +2 -2
- package/out/project/_/queue/__next._tree.txt +2 -2
- package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +1 -1
- package/out/project/_/queue/__next.project.$d$id.queue.txt +1 -1
- package/out/project/_/queue/__next.project.$d$id.txt +1 -1
- package/out/project/_/queue/__next.project.txt +1 -1
- package/out/project/_/queue.html +1 -1
- package/out/project/_/queue.txt +2 -2
- package/out/project/_.html +1 -1
- package/out/project/_.txt +2 -2
- package/out/settings/__next._full.txt +2 -2
- package/out/settings/__next._head.txt +1 -1
- package/out/settings/__next._index.txt +2 -2
- package/out/settings/__next._tree.txt +2 -2
- package/out/settings/__next.settings.__PAGE__.txt +1 -1
- package/out/settings/__next.settings.txt +1 -1
- package/out/settings.html +1 -1
- package/out/settings.txt +2 -2
- package/out/setup/__next._full.txt +3 -3
- package/out/setup/__next._head.txt +1 -1
- package/out/setup/__next._index.txt +2 -2
- package/out/setup/__next._tree.txt +2 -2
- package/out/setup/__next.setup.__PAGE__.txt +2 -2
- package/out/setup/__next.setup.txt +1 -1
- package/out/setup.html +1 -1
- package/out/setup.txt +3 -3
- package/package.json +1 -1
- package/server/index.js +188 -10
- package/server/routes.js +27 -16
- package/out/_next/static/chunks/0ahp74n0wkel0.js +0 -1
- package/out/_next/static/chunks/0s8jbc4nxw6y6.css +0 -2
- /package/out/_next/static/{GOOT2ox5oH-rTFhgq8-MK → TKQFu1hHpaRuo62RWWrUJ}/_buildManifest.js +0 -0
- /package/out/_next/static/{GOOT2ox5oH-rTFhgq8-MK → TKQFu1hHpaRuo62RWWrUJ}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{GOOT2ox5oH-rTFhgq8-MK → TKQFu1hHpaRuo62RWWrUJ}/_ssgManifest.js +0 -0
package/server/index.js
CHANGED
|
@@ -131,22 +131,197 @@ const agentSessions = new Map();
|
|
|
131
131
|
// AgentChattr server processes — per-project (key = projectId)
|
|
132
132
|
const chattrProcesses = new Map();
|
|
133
133
|
|
|
134
|
+
// --- MCP auth proxy for Codex (can't pass headers via -c flag) ---
|
|
135
|
+
// Maps "project/agent" → { server, port }
|
|
136
|
+
const mcpProxies = new Map();
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Start a local HTTP proxy that forwards MCP requests with Bearer token.
|
|
140
|
+
* Returns a Promise that resolves to the proxy URL once listening.
|
|
141
|
+
*/
|
|
142
|
+
function startMcpProxy(projectId, agentId, upstreamUrl, token) {
|
|
143
|
+
const key = `${projectId}/${agentId}`;
|
|
144
|
+
const existing = mcpProxies.get(key);
|
|
145
|
+
if (existing) return Promise.resolve(`http://127.0.0.1:${existing.port}/mcp`);
|
|
146
|
+
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
const proxyServer = http.createServer((req, res) => {
|
|
149
|
+
const parsedUrl = new URL(req.url, `http://127.0.0.1`);
|
|
150
|
+
const targetUrl = `${upstreamUrl}${parsedUrl.pathname}${parsedUrl.search}`;
|
|
151
|
+
const headers = { ...req.headers, host: new URL(upstreamUrl).host };
|
|
152
|
+
if (token) {
|
|
153
|
+
headers["authorization"] = `Bearer ${token}`;
|
|
154
|
+
headers["x-agent-token"] = token;
|
|
155
|
+
}
|
|
156
|
+
delete headers["content-length"];
|
|
157
|
+
|
|
158
|
+
const chunks = [];
|
|
159
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
160
|
+
req.on("end", () => {
|
|
161
|
+
const body = Buffer.concat(chunks);
|
|
162
|
+
const proxyReq = (upstreamUrl.startsWith("https") ? require("https") : http).request(
|
|
163
|
+
targetUrl,
|
|
164
|
+
{ method: req.method, headers: { ...headers, "content-length": body.length } },
|
|
165
|
+
(proxyRes) => {
|
|
166
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
167
|
+
proxyRes.pipe(res);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
proxyReq.on("error", (err) => {
|
|
171
|
+
res.writeHead(502);
|
|
172
|
+
res.end(`Proxy error: ${err.message}`);
|
|
173
|
+
});
|
|
174
|
+
proxyReq.end(body);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
proxyServer.on("error", (err) => reject(err));
|
|
179
|
+
proxyServer.listen(0, "127.0.0.1", () => {
|
|
180
|
+
const port = proxyServer.address().port;
|
|
181
|
+
mcpProxies.set(key, { server: proxyServer, port });
|
|
182
|
+
resolve(`http://127.0.0.1:${port}/mcp`);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function stopMcpProxy(projectId, agentId) {
|
|
188
|
+
const key = `${projectId}/${agentId}`;
|
|
189
|
+
const proxy = mcpProxies.get(key);
|
|
190
|
+
if (proxy) {
|
|
191
|
+
try { proxy.server.close(); } catch {}
|
|
192
|
+
mcpProxies.delete(key);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// --- Permission bypass flags per CLI ---
|
|
197
|
+
const PERMISSION_FLAGS = {
|
|
198
|
+
claude: ["--dangerously-skip-permissions"],
|
|
199
|
+
codex: ["--dangerously-bypass-approvals-and-sandbox"],
|
|
200
|
+
gemini: ["--yolo"],
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// --- MCP config generation & agent launch args ---
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Generate a per-agent MCP config file for Claude (--mcp-config).
|
|
207
|
+
* Returns the absolute path to the written JSON file.
|
|
208
|
+
*/
|
|
209
|
+
function writeMcpConfigFile(projectId, agentId, mcpHttpPort, token) {
|
|
210
|
+
const os = require("os");
|
|
211
|
+
const configDir = path.join(os.homedir(), ".quadwork", projectId);
|
|
212
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
213
|
+
const filePath = path.join(configDir, `mcp-${agentId}.json`);
|
|
214
|
+
const url = `http://127.0.0.1:${mcpHttpPort}/mcp`;
|
|
215
|
+
const config = {
|
|
216
|
+
mcpServers: {
|
|
217
|
+
agentchattr: {
|
|
218
|
+
type: "http",
|
|
219
|
+
url,
|
|
220
|
+
...(token ? { headers: { Authorization: `Bearer ${token}` } } : {}),
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
225
|
+
return filePath;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Build extra launch args for an agent (permission flags + MCP injection).
|
|
230
|
+
* Async because Codex proxy_flag mode needs to await proxy startup.
|
|
231
|
+
*/
|
|
232
|
+
async function buildAgentArgs(projectId, agentId) {
|
|
233
|
+
const cfg = readConfig();
|
|
234
|
+
const project = cfg.projects?.find((p) => p.id === projectId);
|
|
235
|
+
if (!project) return [];
|
|
236
|
+
|
|
237
|
+
const agentCfg = project.agents?.[agentId] || {};
|
|
238
|
+
const command = agentCfg.command || "claude";
|
|
239
|
+
const cliBase = command.split("/").pop().split(" ")[0]; // extract base CLI name
|
|
240
|
+
const args = [];
|
|
241
|
+
|
|
242
|
+
// Permission bypass flags
|
|
243
|
+
if (agentCfg.auto_approve !== false) {
|
|
244
|
+
const flags = PERMISSION_FLAGS[cliBase];
|
|
245
|
+
if (flags) args.push(...flags);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// MCP config injection
|
|
249
|
+
const mcpHttpPort = project.mcp_http_port;
|
|
250
|
+
const token = project.agentchattr_token;
|
|
251
|
+
if (mcpHttpPort) {
|
|
252
|
+
const injectMode = agentCfg.mcp_inject || (cliBase === "codex" ? "proxy_flag" : cliBase === "gemini" ? "env" : "flag");
|
|
253
|
+
if (injectMode === "flag") {
|
|
254
|
+
// Claude/Kimi: write config file, pass --mcp-config
|
|
255
|
+
const mcpConfigPath = writeMcpConfigFile(projectId, agentId, mcpHttpPort, token);
|
|
256
|
+
const flag = agentCfg.mcp_flag || "--mcp-config";
|
|
257
|
+
args.push(flag, mcpConfigPath);
|
|
258
|
+
} else if (injectMode === "proxy_flag") {
|
|
259
|
+
// Codex: start local auth proxy, pass proxy URL via -c flag
|
|
260
|
+
const upstreamUrl = `http://127.0.0.1:${mcpHttpPort}`;
|
|
261
|
+
const proxyUrl = await startMcpProxy(projectId, agentId, upstreamUrl, token);
|
|
262
|
+
if (proxyUrl) {
|
|
263
|
+
args.push("-c", `mcp_servers.agentchattr.url="${proxyUrl}"`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return args;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Build extra env vars for an agent (MCP injection via env for Gemini).
|
|
273
|
+
*/
|
|
274
|
+
function buildAgentEnv(projectId, agentId) {
|
|
275
|
+
const cfg = readConfig();
|
|
276
|
+
const project = cfg.projects?.find((p) => p.id === projectId);
|
|
277
|
+
if (!project) return {};
|
|
278
|
+
|
|
279
|
+
const agentCfg = project.agents?.[agentId] || {};
|
|
280
|
+
const command = agentCfg.command || "claude";
|
|
281
|
+
const cliBase = command.split("/").pop().split(" ")[0];
|
|
282
|
+
const env = {};
|
|
283
|
+
|
|
284
|
+
// Gemini: inject MCP via env var
|
|
285
|
+
if (cliBase === "gemini" && project.mcp_http_port) {
|
|
286
|
+
const os = require("os");
|
|
287
|
+
const configDir = path.join(os.homedir(), ".quadwork", projectId);
|
|
288
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
289
|
+
const settingsPath = path.join(configDir, `mcp-${agentId}-settings.json`);
|
|
290
|
+
const url = `http://127.0.0.1:${project.mcp_http_port}/mcp`;
|
|
291
|
+
const settings = {
|
|
292
|
+
mcpServers: {
|
|
293
|
+
agentchattr: {
|
|
294
|
+
type: "http",
|
|
295
|
+
url,
|
|
296
|
+
...(project.agentchattr_token ? { headers: { Authorization: `Bearer ${project.agentchattr_token}` } } : {}),
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
301
|
+
env.GEMINI_CLI_SYSTEM_SETTINGS_PATH = settingsPath;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return env;
|
|
305
|
+
}
|
|
306
|
+
|
|
134
307
|
// Helper: spawn a PTY for a project/agent and register in agentSessions
|
|
135
|
-
function spawnAgentPty(project, agent) {
|
|
308
|
+
async function spawnAgentPty(project, agent) {
|
|
136
309
|
const key = `${project}/${agent}`;
|
|
137
310
|
|
|
138
311
|
const cwd = resolveAgentCwd(project, agent);
|
|
139
312
|
if (!cwd) return { ok: false, error: `Unknown agent: ${key}` };
|
|
140
313
|
|
|
141
314
|
const command = resolveAgentCommand(project, agent) || (process.env.SHELL || "/bin/zsh");
|
|
315
|
+
const args = await buildAgentArgs(project, agent);
|
|
316
|
+
const extraEnv = buildAgentEnv(project, agent);
|
|
142
317
|
|
|
143
318
|
try {
|
|
144
|
-
const term = pty.spawn(command,
|
|
319
|
+
const term = pty.spawn(command, args, {
|
|
145
320
|
name: "xterm-256color",
|
|
146
321
|
cols: 120,
|
|
147
322
|
rows: 30,
|
|
148
323
|
cwd,
|
|
149
|
-
env: process.env,
|
|
324
|
+
env: { ...process.env, ...extraEnv },
|
|
150
325
|
});
|
|
151
326
|
|
|
152
327
|
const session = { projectId: project, agentId: agent, term, ws: null, state: "running", error: null };
|
|
@@ -190,6 +365,9 @@ function stopAgentSession(key) {
|
|
|
190
365
|
session.ws = null;
|
|
191
366
|
session.state = "stopped";
|
|
192
367
|
session.error = null;
|
|
368
|
+
// Clean up MCP auth proxy if running
|
|
369
|
+
const [projectId, agentId] = key.split("/");
|
|
370
|
+
if (projectId && agentId) stopMcpProxy(projectId, agentId);
|
|
193
371
|
}
|
|
194
372
|
|
|
195
373
|
app.get("/api/agents", (_req, res) => {
|
|
@@ -423,7 +601,7 @@ app.post("/api/agents/:project/reset", async (req, res) => {
|
|
|
423
601
|
|
|
424
602
|
// --- Lifecycle: start spawns PTY (visible in terminal panel) ---
|
|
425
603
|
|
|
426
|
-
app.post("/api/agents/:project/:agent/start", (req, res) => {
|
|
604
|
+
app.post("/api/agents/:project/:agent/start", async (req, res) => {
|
|
427
605
|
const { project, agent } = req.params;
|
|
428
606
|
const key = `${project}/${agent}`;
|
|
429
607
|
|
|
@@ -432,7 +610,7 @@ app.post("/api/agents/:project/:agent/start", (req, res) => {
|
|
|
432
610
|
return res.json({ ok: true, state: "running", message: "Already running" });
|
|
433
611
|
}
|
|
434
612
|
|
|
435
|
-
const result = spawnAgentPty(project, agent);
|
|
613
|
+
const result = await spawnAgentPty(project, agent);
|
|
436
614
|
if (result.ok) {
|
|
437
615
|
res.json({ ok: true, state: "running", pid: result.pid });
|
|
438
616
|
} else {
|
|
@@ -451,14 +629,14 @@ app.post("/api/agents/:project/:agent/stop", (req, res) => {
|
|
|
451
629
|
|
|
452
630
|
// --- Lifecycle: restart ---
|
|
453
631
|
|
|
454
|
-
app.post("/api/agents/:project/:agent/restart", (req, res) => {
|
|
632
|
+
app.post("/api/agents/:project/:agent/restart", async (req, res) => {
|
|
455
633
|
const { project, agent } = req.params;
|
|
456
634
|
const key = `${project}/${agent}`;
|
|
457
635
|
|
|
458
636
|
stopAgentSession(key);
|
|
459
637
|
|
|
460
|
-
setTimeout(() => {
|
|
461
|
-
const result = spawnAgentPty(project, agent);
|
|
638
|
+
setTimeout(async () => {
|
|
639
|
+
const result = await spawnAgentPty(project, agent);
|
|
462
640
|
if (result.ok) {
|
|
463
641
|
res.json({ ok: true, state: "running", pid: result.pid });
|
|
464
642
|
} else {
|
|
@@ -708,7 +886,7 @@ app.use((req, res, next) => {
|
|
|
708
886
|
|
|
709
887
|
const wss = new WebSocketServer({ server, path: "/ws/terminal" });
|
|
710
888
|
|
|
711
|
-
wss.on("connection", (ws, req) => {
|
|
889
|
+
wss.on("connection", async (ws, req) => {
|
|
712
890
|
const params = new URL(req.url, `http://localhost:${PORT}`).searchParams;
|
|
713
891
|
const projectId = params.get("project");
|
|
714
892
|
const agentId = params.get("agent");
|
|
@@ -723,7 +901,7 @@ wss.on("connection", (ws, req) => {
|
|
|
723
901
|
|
|
724
902
|
// If no active PTY, spawn one
|
|
725
903
|
if (!session || !session.term) {
|
|
726
|
-
const result = spawnAgentPty(projectId, agentId);
|
|
904
|
+
const result = await spawnAgentPty(projectId, agentId);
|
|
727
905
|
if (!result.ok) {
|
|
728
906
|
ws.close(1011, "pty-spawn-failed");
|
|
729
907
|
return;
|
package/server/routes.js
CHANGED
|
@@ -590,21 +590,26 @@ router.post("/api/setup", (req, res) => {
|
|
|
590
590
|
const wtDir = path.join(parentDir, `${dirName}-${agent}`);
|
|
591
591
|
if (!fs.existsSync(wtDir)) continue;
|
|
592
592
|
|
|
593
|
-
// AGENTS.md —
|
|
593
|
+
// AGENTS.md — always (re)write from template so role definitions
|
|
594
|
+
// stay in sync with templates/seeds/ on every project (re)creation.
|
|
595
|
+
// Previously this was guarded by `!exists`, so if a worktree already
|
|
596
|
+
// had any AGENTS.md (stale, hand-edited, or empty) it was preserved
|
|
597
|
+
// forever and agents could launch with no/outdated role definition.
|
|
594
598
|
const agentsMd = path.join(wtDir, "AGENTS.md");
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
// Fallback stub if template missing
|
|
604
|
-
fs.writeFileSync(agentsMd, `# ${dirName} — ${agent.charAt(0).toUpperCase() + agent.slice(1)} Agent\n\nRepo: ${body.repo}\nRole: ${agent === "head" ? "Owner" : agent.startsWith("reviewer") ? "Reviewer" : "Builder"}\n`);
|
|
605
|
-
}
|
|
606
|
-
seeded.push(`${agent}/AGENTS.md`);
|
|
599
|
+
const seedSrc = path.join(TEMPLATES_DIR, "seeds", `${agent}.AGENTS.md`);
|
|
600
|
+
if (!fs.existsSync(seedSrc)) {
|
|
601
|
+
// Hard fail: missing seed means role is undefined. Better to surface
|
|
602
|
+
// the error than silently write a generic stub.
|
|
603
|
+
return res.json({
|
|
604
|
+
ok: false,
|
|
605
|
+
error: `Missing seed template: templates/seeds/${agent}.AGENTS.md`,
|
|
606
|
+
});
|
|
607
607
|
}
|
|
608
|
+
let agentsContent = fs.readFileSync(seedSrc, "utf-8");
|
|
609
|
+
agentsContent = agentsContent.replace(/\{\{reviewer_github_user\}\}/g, reviewerUser);
|
|
610
|
+
agentsContent = agentsContent.replace(/\{\{reviewer_token_path\}\}/g, reviewerTokenPath);
|
|
611
|
+
fs.writeFileSync(agentsMd, agentsContent);
|
|
612
|
+
seeded.push(`${agent}/AGENTS.md`);
|
|
608
613
|
|
|
609
614
|
// CLAUDE.md — use template with placeholder substitution (matches CLI)
|
|
610
615
|
const claudeMd = path.join(wtDir, "CLAUDE.md");
|
|
@@ -697,19 +702,25 @@ router.post("/api/setup", (req, res) => {
|
|
|
697
702
|
}
|
|
698
703
|
case "add-config": {
|
|
699
704
|
const { id, name, repo, workingDir, backends } = body;
|
|
705
|
+
const autoApprove = body.auto_approve !== false; // default true
|
|
700
706
|
// Use directory basename for sibling paths (matches CLI wizard)
|
|
701
707
|
const dirName = path.basename(workingDir);
|
|
702
708
|
const parentDir = path.dirname(workingDir);
|
|
703
709
|
let cfg;
|
|
704
710
|
try { cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")); }
|
|
705
|
-
catch { cfg = { port: 8400, agentchattr_url: "http://127.0.0.1:8300", projects: [] }; }
|
|
711
|
+
catch { cfg = { port: 8400, agentchattr_url: "http://127.0.0.1:8300", agentchattr_dir: path.join(os.homedir(), ".quadwork", "agentchattr"), projects: [] }; }
|
|
706
712
|
if (cfg.projects.some((p) => p.id === id)) return res.json({ ok: true, message: "Project already in config" });
|
|
707
|
-
// Match CLI wizard agent structure: { cwd, command }
|
|
713
|
+
// Match CLI wizard agent structure: { cwd, command, auto_approve, mcp_inject }
|
|
708
714
|
const agents = {};
|
|
709
715
|
for (const agentId of ["head", "reviewer1", "reviewer2", "dev"]) {
|
|
716
|
+
const cmd = (backends && backends[agentId]) || "claude";
|
|
717
|
+
const cliBase = cmd.split("/").pop().split(" ")[0];
|
|
718
|
+
const injectMode = cliBase === "codex" ? "proxy_flag" : cliBase === "gemini" ? "env" : "flag";
|
|
710
719
|
agents[agentId] = {
|
|
711
720
|
cwd: path.join(parentDir, `${dirName}-${agentId}`),
|
|
712
|
-
command:
|
|
721
|
+
command: cmd,
|
|
722
|
+
auto_approve: autoApprove,
|
|
723
|
+
mcp_inject: injectMode,
|
|
713
724
|
};
|
|
714
725
|
}
|
|
715
726
|
// Use pre-assigned ports/token from agentchattr-config step if provided,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,64618,e=>{"use strict";var t=e.i(24046),s=e.i(85899),a=e.i(4232),r=e.i(16353);let c=[{id:"name",label:"Project Name",subtitle:"Name your project",status:"active"},{id:"repo",label:"GitHub Repo",subtitle:"Connect a repository",status:"pending"},{id:"models",label:"Agent Models",subtitle:"Configure CLI backends",status:"pending"},{id:"workdir",label:"Working Directory",subtitle:"Set the local path",status:"pending"},{id:"workspaces",label:"Create Workspaces",subtitle:"Worktrees + seed files",status:"pending"},{id:"launch",label:"Ready to Launch",subtitle:"Review & start",status:"pending"}],n=[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex"}],l=[{key:"head",label:"T1 — Head",role:"Owner / Final Guard",desc:"Merges PRs, makes final calls"},{key:"reviewer1",label:"T2a — Reviewer 1",role:"Design Reviewer",desc:"Reviews architecture & design"},{key:"reviewer2",label:"T2b — Reviewer 2",role:"Code Reviewer",desc:"Reviews implementation quality"},{key:"dev",label:"T3 — Developer",role:"Full-Stack Builder",desc:"Implements features & fixes"}];function o({repo:e,workingDir:t,setWorkingDir:r,error:c,onNext:n}){let[l,i]=(0,a.useState)(!0),[d,x]=(0,a.useState)(null),[p,m]=(0,a.useState)(!1),u=e?e.split("/")[1]:"project";return(0,a.useEffect)(()=>{e?fetch(`/api/setup/detect-clone?repo=${encodeURIComponent(e)}`).then(e=>e.ok?e.json():null).then(e=>{x(e),e?.found&&e.path?r(e.path):e?.suggested&&r(e.suggested),i(!1)}).catch(()=>i(!1)):i(!1)},[e,r]),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Where is your project?"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-3",children:"Your project's git repository on your local machine. QuadWork will create 4 agent workspaces next to this directory."}),l&&(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-3",children:"Scanning for existing clone..."}),!l&&d?.found&&(0,s.jsxs)("div",{className:"border border-accent/30 bg-accent/5 p-3 mb-4 text-[11px]",children:[(0,s.jsx)("p",{className:"text-accent font-semibold mb-1",children:"Found existing clone"}),(0,s.jsx)("p",{className:"text-text font-mono",children:d.path}),(0,s.jsxs)("div",{className:"flex gap-2 mt-2",children:[(0,s.jsx)("button",{onClick:n,className:"px-3 py-1 bg-accent text-bg text-[11px] font-semibold hover:bg-accent-dim transition-colors",children:"Use this"}),(0,s.jsx)("button",{onClick:()=>{m(!0),r("")},className:"px-3 py-1 text-[11px] text-text-muted border border-border hover:text-text transition-colors",children:"Choose different path"})]})]}),!l&&!d?.found&&!p&&(0,s.jsxs)("div",{className:"border border-border bg-bg-surface p-3 mb-4 text-[11px]",children:[(0,s.jsxs)("p",{className:"text-text-muted mb-1",children:["No local clone found for ",(0,s.jsx)("span",{className:"text-accent",children:e})]}),(0,s.jsx)("p",{className:"text-text-muted mb-2",children:"Setup will clone it to:"}),(0,s.jsx)("p",{className:"text-text font-mono mb-2",children:d?.suggested||`~/Projects/${u}`}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("button",{onClick:n,disabled:!t.trim(),className:"px-3 py-1 bg-accent text-bg text-[11px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:"Clone here & continue"}),(0,s.jsx)("button",{onClick:()=>m(!0),className:"px-3 py-1 text-[11px] text-text-muted border border-border hover:text-text transition-colors",children:"Choose different path"})]})]}),(p||!l&&!d)&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("input",{value:t,onChange:e=>r(e.target.value),placeholder:`~/Projects/${u}`,className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-2"}),(0,s.jsx)("button",{onClick:n,disabled:!t.trim(),className:"px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:"Next"})]}),c&&(0,s.jsx)("p",{className:"text-[11px] text-error mt-2",children:c}),(0,s.jsxs)("div",{className:"border border-border bg-bg-surface p-3 mt-4 text-[11px] text-text-muted font-mono space-y-0.5",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase tracking-wider text-text-muted mb-1 font-sans",children:"Workspace layout"}),(0,s.jsxs)("p",{className:"text-accent",children:[u,"/ ← your repo"]}),(0,s.jsxs)("p",{children:[u,"-head/ ← Head agent"]}),(0,s.jsxs)("p",{children:[u,"-dev/ ← Dev agent"]}),(0,s.jsxs)("p",{children:[u,"-reviewer1/ ← Reviewer1"]}),(0,s.jsxs)("p",{children:[u,"-reviewer2/ ← Reviewer2"]})]})]})}e.s(["default",0,function(){let e=(0,r.useRouter)(),[i,d]=(0,a.useState)(c),[x,p]=(0,a.useState)(0),[m,u]=(0,a.useState)(""),[h,b]=(0,a.useState)(""),[g,j]=(0,a.useState)(""),[f,v]=(0,a.useState)([]),[N,k]=(0,a.useState)(!1),[y,w]=(0,a.useState)(!1),[C,S]=(0,a.useState)(""),[_,R]=(0,a.useState)(!1),[T,P]=(0,a.useState)({head:"claude",reviewer1:"claude",reviewer2:"claude",dev:"claude"}),[$,q]=(0,a.useState)(!1),[H,I]=(0,a.useState)(""),[A,L]=(0,a.useState)("paste"),[E,F]=(0,a.useState)(""),[U,W]=(0,a.useState)("~/.quadwork/reviewer-token"),[D,G]=(0,a.useState)(""),[O,M]=(0,a.useState)({}),[Y,B]=(0,a.useState)(!1),[z,J]=(0,a.useState)([]),[K,V]=(0,a.useState)("idle"),[X,Q]=(0,a.useState)(!1),[Z,ee]=(0,a.useState)({chattr:0,mcpHttp:0,mcpSse:0}),[et,es]=(0,a.useState)({chattr:0,mcpHttp:0,mcpSse:0}),[ea,er]=(0,a.useState)(null);(0,a.useEffect)(()=>{fetch("/api/cli-status").then(e=>e.json()).then(e=>{er(e);let t=e.claude&&!e.codex?"claude":!e.claude&&e.codex?"codex":null;t?P({head:t,reviewer1:t,reviewer2:t,dev:t}):e.claude&&e.codex&&P({head:"codex",dev:"claude",reviewer1:"codex",reviewer2:"claude"})}).catch(()=>{})},[]),(0,a.useEffect)(()=>{fetch("/api/github/user").then(e=>e.json()).then(e=>{e.login&&S(e.login)}).catch(()=>{})},[]),(0,a.useEffect)(()=>{C&&(k(!0),fetch(`/api/github/repos?owner=${encodeURIComponent(C)}`).then(e=>e.json()).then(e=>{Array.isArray(e)&&v(e)}).catch(()=>{}).finally(()=>k(!1)))},[C]);let ec=(0,a.useCallback)((e,t)=>{d(s=>s.map((s,a)=>a===e?{...s,...t}:s))},[]),en=(0,a.useCallback)(()=>{d(e=>e.map((e,t)=>t===x?{...e,status:"done"}:t===x+1?{...e,status:"active"}:e)),p(e=>e+1)},[x]),el=async(e,t)=>{B(!0);try{let s=await fetch(`/api/setup?step=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),a=await s.json();return B(!1),a}catch{return B(!1),{ok:!1,error:"Request failed"}}},eo=async()=>{let e=await el("verify-repo",{repo:h});e.ok?en():ec(x,{status:"error",error:e.error})},ei=async()=>{if(B(!0),J([]),$&&"paste"===A&&E){J(e=>[...e,"Saving reviewer token..."]);try{let e=await fetch("/api/setup/save-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:E})}),t=await e.json();t.ok&&J(e=>[...e,`Token saved to ${t.path}`])}catch{}}J(e=>[...e,"Creating worktrees..."]);let e=await el("create-worktrees",{workingDir:D,repo:h});if(!e.ok){J(t=>[...t,`Error: ${e.errors?.join(", ")||e.error}`]),ec(x,{status:"error",error:e.errors?.join(", ")||e.error}),B(!1);return}J(e=>[...e,"Worktrees created."]),J(e=>[...e,"Writing seed files..."]);let t=$?"file"===A?U:"~/.quadwork/reviewer-token":"",s=await el("seed-files",{workingDir:D,projectName:m,repo:h,reviewerUser:$?H:"",reviewerTokenPath:t});if(!s.ok){J(e=>[...e,`Error: ${s.error}`]),ec(x,{status:"error",error:s.error}),B(!1);return}J(e=>[...e,"Seed files written."]),J(e=>[...e,"Done."]),B(!1),en()},ed=async()=>{let t,s,a;if(V("running"),X&&Z.chattr>0){t=Z.chattr,s=Z.mcpHttp||Z.chattr-100,a=Z.mcpSse||s+1;let e=[t,s,a];try{let t=(await Promise.all(e.map(e=>fetch(`/api/port-check?port=${e}`).then(e=>e.json())))).filter(e=>!e.free).map(e=>e.port);if(t.length>0){V("error"),ec(x,{status:"error",error:`Port${t.length>1?"s":""} ${t.join(", ")} already in use`});return}}catch{}}else if(et.chattr)t=et.chattr,s=et.mcpHttp,a=et.mcpSse;else try{let e=await fetch("/api/port-check/auto?start=8300&count=1"),r=await e.json(),c=await fetch("/api/port-check/auto?start=8200&count=2"),n=await c.json();t=r.ports?.[0]||8300,s=n.ports?.[0]||8200,a=n.ports?.[1]||8201}catch{t=8300,s=8200,a=8201}let r=await el("agentchattr-config",{workingDir:D,projectName:m,repo:h,backends:T,agentchattr_port:t,mcp_http_port:s,mcp_sse_port:a});r.ok&&M({agentchattr_token:r.agentchattr_token,agentchattr_port:r.agentchattr_port,mcp_http_port:r.mcp_http_port,mcp_sse_port:r.mcp_sse_port});let c=D.split("/").pop()||m.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""),n=await el("add-config",{id:c,name:m,repo:h,workingDir:D,backends:T,...r.ok?{agentchattr_token:r.agentchattr_token,agentchattr_port:r.agentchattr_port,mcp_http_port:r.mcp_http_port,mcp_sse_port:r.mcp_sse_port}:O});n.ok?(V("done"),ec(x,{status:"done"}),setTimeout(()=>e.push(`/project/${c}`),1200)):(V("error"),ec(x,{status:"error",error:n.error}))};(0,a.useEffect)(()=>{i[x]?.id==="launch"&&(async()=>{try{let e=await fetch("/api/port-check/auto?start=8300&count=1"),t=await e.json(),s=await fetch("/api/port-check/auto?start=8200&count=2"),a=await s.json(),r={chattr:t.ports?.[0]||8300,mcpHttp:a.ports?.[0]||8200,mcpSse:a.ports?.[1]||8201};es(r),Z.chattr||ee(r)}catch{}})()},[x,i]);let ex=f.filter(e=>e.name.toLowerCase().includes(g.toLowerCase())),ep=i[x];return(0,s.jsxs)("div",{className:"h-full overflow-y-auto",children:[(0,s.jsxs)("div",{className:"px-6 pt-6 pb-4 border-b border-border",children:[(0,s.jsx)("h1",{className:"text-lg font-semibold text-text tracking-tight",children:"Set Up Your AI Dev Team"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mt-1",children:"Configure agents, connect your repo, and launch a multi-agent development workflow in minutes."})]}),(0,s.jsxs)("div",{className:"flex h-[calc(100%-80px)]",children:[(0,s.jsxs)("div",{className:"flex-1 flex gap-6 p-6 overflow-y-auto",children:[(0,s.jsx)("div",{className:"w-44 shrink-0",children:i.map((e,t)=>(0,s.jsxs)("div",{className:"flex items-start gap-2 py-2",children:[(0,s.jsx)("span",{className:`w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 ${"done"===e.status?"border-accent text-accent":"error"===e.status?"border-error text-error":"active"===e.status?"border-accent text-accent bg-accent/10":"skipped"===e.status?"border-border text-text-muted line-through":"border-border text-text-muted"}`,children:"done"===e.status?"✓":"error"===e.status?"!":t+1}),(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:`text-[11px] block leading-tight ${"active"===e.status?"text-text font-semibold":"done"===e.status?"text-accent":"text-text-muted"}`,children:e.label}),(0,s.jsx)("span",{className:"text-[10px] text-text-muted block",children:e.subtitle})]})]},e.id))}),(0,s.jsxs)("div",{className:"flex-1 border border-border p-5 min-h-0",children:[ep?.id==="name"&&(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Name your project"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-4",children:"This name identifies your project in the dashboard and agent configs."}),(0,s.jsx)("input",{value:m,onChange:e=>u(e.target.value),placeholder:"e.g. My DeFi App",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-4",autoFocus:!0}),(0,s.jsx)("button",{onClick:en,disabled:!m.trim(),className:"px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:"Next"})]}),ep?.id==="repo"&&(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Connect a GitHub repository"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-4",children:"Select an existing repo or enter one manually. Agents will work within this repo."}),!y&&(0,s.jsxs)(s.Fragment,{children:[C&&(0,s.jsxs)("p",{className:"text-[11px] text-text-muted mb-2",children:["Showing repos for ",(0,s.jsx)("span",{className:"text-accent",children:C})]}),(0,s.jsx)("input",{value:g,onChange:e=>j(e.target.value),placeholder:"Search repos...",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-2"}),N&&(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-2",children:"Loading..."}),(0,s.jsxs)("div",{className:"max-h-40 overflow-y-auto border border-border mb-3",children:[ex.map(e=>(0,s.jsxs)("button",{onClick:()=>b(`${C}/${e.name}`),className:`w-full text-left px-3 py-1.5 text-[11px] border-b border-border/50 last:border-b-0 hover:bg-accent/5 transition-colors ${h===`${C}/${e.name}`?"bg-accent/10 text-accent":"text-text"}`,children:[(0,s.jsx)("span",{className:"font-semibold",children:e.name}),e.isPrivate&&(0,s.jsx)("span",{className:"text-[10px] text-text-muted ml-2",children:"private"}),e.description&&(0,s.jsx)("span",{className:"text-[10px] text-text-muted ml-2",children:e.description})]},e.name)),!N&&0===ex.length&&(0,s.jsx)("p",{className:"px-3 py-2 text-[11px] text-text-muted",children:"No repos found."})]}),(0,s.jsx)("button",{onClick:()=>w(!0),className:"text-[11px] text-text-muted hover:text-accent transition-colors mb-3 block",children:"Enter manually instead"})]}),y&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("input",{value:h,onChange:e=>b(e.target.value),placeholder:"owner/repo",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-2"}),(0,s.jsx)("button",{onClick:()=>w(!1),className:"text-[11px] text-text-muted hover:text-accent transition-colors mb-3 block",children:"Back to repo list"})]}),(0,s.jsxs)("label",{className:"flex items-center gap-2 mb-4 cursor-pointer",children:[(0,s.jsx)("input",{type:"checkbox",checked:_,onChange:e=>R(e.target.checked),className:"accent-accent"}),(0,s.jsxs)("span",{className:"text-[11px] text-text-muted",children:["Enable branch protection on ",(0,s.jsx)("code",{className:"text-accent",children:"main"})]})]}),_&&(0,s.jsxs)("div",{className:"border border-border bg-bg-surface p-3 mb-4 text-[11px] space-y-2",children:[(0,s.jsx)("p",{className:"text-text-muted",children:"Run this after setup, or configure in GitHub UI:"}),(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("code",{className:"text-accent flex-1 select-all text-[10px] break-all",children:`gh api repos/${h||"owner/repo"}/branches/main/protection -X PUT -f "required_pull_request_reviews[required_approving_review_count]=1" -f "enforce_admins=false" -f "required_status_checks=null" -f "restrictions=null"`}),(0,s.jsx)("button",{onClick:()=>navigator.clipboard.writeText(`gh api repos/${h}/branches/main/protection -X PUT -f "required_pull_request_reviews[required_approving_review_count]=1" -f "enforce_admins=false" -f "required_status_checks=null" -f "restrictions=null"`),className:"text-[10px] text-text-muted hover:text-accent shrink-0",children:"copy"})]})]}),ep.error&&(0,s.jsx)("p",{className:"text-[11px] text-error mb-2",children:ep.error}),(0,s.jsx)("button",{onClick:eo,disabled:!h||Y,className:"px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:Y?"Verifying...":"Verify & Continue"})]}),ep?.id==="models"&&(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Configure agent CLI backends"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-4",children:"Each agent runs its own CLI instance. Pick the backend for each role."}),ea&&!ea.claude&&ea.codex&&(0,s.jsxs)("div",{className:"border border-accent/20 bg-accent/5 p-3 mb-4 text-[11px]",children:[(0,s.jsx)("p",{className:"text-text",children:"You have Codex CLI installed — great! All 4 agents will use Codex."}),(0,s.jsx)("p",{className:"text-text-muted mt-1.5",children:"Tip: Installing Claude Code too gives your team different AI perspectives, which can improve code review quality. You can add it anytime:"}),(0,s.jsx)("p",{className:"text-accent mt-1 font-mono text-[10px]",children:"npm install -g @anthropic-ai/claude-code"}),(0,s.jsx)("p",{className:"text-text-muted mt-1.5",children:"For now, Codex CLI handles everything perfectly. Let's continue!"})]}),ea&&ea.claude&&!ea.codex&&(0,s.jsxs)("div",{className:"border border-accent/20 bg-accent/5 p-3 mb-4 text-[11px]",children:[(0,s.jsx)("p",{className:"text-text",children:"You have Claude Code installed — great! All 4 agents will use Claude."}),(0,s.jsx)("p",{className:"text-text-muted mt-1.5",children:"Tip: Installing Codex CLI too gives your team different AI perspectives, which can improve code review quality. You can add it anytime:"}),(0,s.jsx)("p",{className:"text-accent mt-1 font-mono text-[10px]",children:"npm install -g codex"}),(0,s.jsx)("p",{className:"text-text-muted mt-1.5",children:"For now, Claude Code handles everything perfectly. Let's continue!"})]}),(0,s.jsx)("div",{className:"border border-border mb-4",children:l.map(e=>(0,s.jsxs)("div",{className:"flex items-center justify-between px-3 py-2 border-b border-border/50 last:border-b-0",children:[(0,s.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,s.jsx)("span",{className:"text-[11px] text-text font-semibold block",children:e.label}),(0,s.jsx)("span",{className:"text-[10px] text-text-muted",children:e.desc})]}),(0,s.jsx)("select",{value:T[e.key],onChange:t=>P({...T,[e.key]:t.target.value}),className:"bg-transparent border border-border px-2 py-0.5 text-[11px] text-text outline-none focus:border-accent cursor-pointer ml-3",children:n.map(e=>(0,s.jsxs)("option",{value:e.value,className:"bg-bg-surface",disabled:!!ea&&!ea[e.value],children:[e.label,ea&&!ea[e.value]?" (not installed)":""]},e.value))})]},e.key))}),(0,s.jsxs)("label",{className:"flex items-center gap-2 mb-3 cursor-pointer",children:[(0,s.jsx)("input",{type:"checkbox",checked:$,onChange:e=>q(e.target.checked),className:"accent-accent"}),(0,s.jsx)("span",{className:"text-[11px] text-text-muted",children:"Configure reviewer credentials (for GitHub PR reviews)"})]}),$&&(0,s.jsxs)("div",{className:"border border-border p-3 mb-4 space-y-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"text-[11px] text-text-muted block mb-1",children:"Reviewer GitHub username"}),(0,s.jsx)("input",{value:H,onChange:e=>I(e.target.value),placeholder:"github-username",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"text-[11px] text-text-muted block mb-2",children:"Token source"}),(0,s.jsxs)("div",{className:"flex gap-4 mb-2",children:[(0,s.jsxs)("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[(0,s.jsx)("input",{type:"radio",name:"tokenMode",checked:"paste"===A,onChange:()=>L("paste"),className:"accent-accent"}),(0,s.jsx)("span",{className:"text-[11px] text-text",children:"Paste token"})]}),(0,s.jsxs)("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[(0,s.jsx)("input",{type:"radio",name:"tokenMode",checked:"file"===A,onChange:()=>L("file"),className:"accent-accent"}),(0,s.jsx)("span",{className:"text-[11px] text-text",children:"Use existing file"})]})]}),"paste"===A?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("input",{value:E,onChange:e=>F(e.target.value),placeholder:"ghp_xxxxxxxxxxxxxxxxxxxx",type:"password",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"}),(0,s.jsxs)("div",{className:"mt-2 text-[10px] text-text-muted leading-relaxed",children:[(0,s.jsxs)("p",{children:["Paste a GitHub ",(0,s.jsx)("span",{className:"text-text",children:"Personal Access Token (classic)"}),"."]}),(0,s.jsxs)("p",{className:"mt-1",children:["Create one at"," ",(0,s.jsx)("a",{href:"https://github.com/settings/tokens",target:"_blank",rel:"noopener noreferrer",className:"text-accent hover:underline",children:"github.com/settings/tokens"})," ","→ Generate new token (classic)"]}),(0,s.jsxs)("p",{className:"mt-1",children:["Required permission: ",(0,s.jsx)("span",{className:"text-accent",children:"repo"})," (Full control of private repositories)",(0,s.jsx)("br",{}),(0,s.jsx)("span",{className:"text-text-muted",children:"Needed for reading PRs, posting reviews, and approving/requesting changes"})]})]})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("input",{value:U,onChange:e=>W(e.target.value),placeholder:"~/.quadwork/reviewer-token",className:"w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent"}),U&&!U.startsWith("~/.quadwork")&&!U.startsWith(String.raw`${t.default.env.HOME}/.quadwork`)&&(0,s.jsx)("p",{className:"text-[10px] text-[#ffcc00] mt-1",children:"This path may be inside a git repository. Consider using the default ~/.quadwork/ location to avoid accidentally committing tokens."})]})]})]}),(0,s.jsx)("button",{onClick:en,className:"px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors",children:"Next"})]}),ep?.id==="workdir"&&(0,s.jsx)(o,{repo:h,workingDir:D,setWorkingDir:G,error:ep.error,onNext:en}),ep?.id==="workspaces"&&(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Create workspaces"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-4",children:"This creates git worktrees for each agent and writes seed configuration files (AGENTS.md, CLAUDE.md) into each workspace."}),ep.error&&(0,s.jsx)("p",{className:"text-[11px] text-error mb-2",children:ep.error}),z.length>0&&(0,s.jsx)("div",{className:"border border-border bg-bg-surface p-3 mb-4 text-[11px] text-text-muted space-y-0.5 font-mono",children:z.map((e,t)=>(0,s.jsx)("p",{children:e},t))}),(0,s.jsx)("button",{onClick:ei,disabled:Y,className:"px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:Y?"Creating...":"Create Worktrees & Seed Files"})]}),ep?.id==="launch"&&(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-text mb-1",children:"Ready to launch"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mb-4",children:"Everything is configured. Review the summary and launch your AI dev team."}),(0,s.jsxs)("div",{className:"border border-border mb-4",children:[(0,s.jsx)("div",{className:"px-3 py-1.5 border-b border-border bg-bg-surface",children:(0,s.jsx)("span",{className:"text-[11px] text-text font-semibold",children:"Team Roster"})}),l.map(e=>(0,s.jsxs)("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-border/50 last:border-b-0",children:[(0,s.jsx)("span",{className:"text-[11px] text-text font-semibold",children:e.label}),(0,s.jsx)("span",{className:"text-[10px] text-text-muted",children:e.role}),(0,s.jsx)("span",{className:"text-[11px] text-accent",children:"claude"===T[e.key]?"Claude Code":"Codex"})]},e.key))]}),(0,s.jsxs)("div",{className:"mb-4",children:[(0,s.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer mb-2",children:[(0,s.jsx)("input",{type:"checkbox",checked:X,onChange:e=>Q(e.target.checked),className:"accent-accent"}),(0,s.jsx)("span",{className:"text-[11px] text-text-muted",children:"Custom ports"})]}),X&&(0,s.jsx)("div",{className:"border border-border p-3 space-y-2",children:(0,s.jsxs)("div",{className:"grid grid-cols-3 gap-3",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,s.jsx)("label",{className:"text-[10px] text-text-muted uppercase tracking-wider",children:"AgentChattr port"}),(0,s.jsx)("input",{type:"number",value:Z.chattr||"",onChange:e=>ee({...Z,chattr:parseInt(e.target.value,10)||0}),placeholder:String(et.chattr||8300),className:"bg-transparent border border-border px-2 py-1 text-[11px] text-text outline-none focus:border-accent"}),et.chattr>0&&(0,s.jsxs)("span",{className:"text-[10px] text-text-muted",children:["auto-detected: ",et.chattr]})]}),(0,s.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,s.jsx)("label",{className:"text-[10px] text-text-muted uppercase tracking-wider",children:"MCP HTTP port"}),(0,s.jsx)("input",{type:"number",value:Z.mcpHttp||"",onChange:e=>ee({...Z,mcpHttp:parseInt(e.target.value,10)||0}),placeholder:String(et.mcpHttp||8200),className:"bg-transparent border border-border px-2 py-1 text-[11px] text-text outline-none focus:border-accent"}),et.mcpHttp>0&&(0,s.jsxs)("span",{className:"text-[10px] text-text-muted",children:["auto-detected: ",et.mcpHttp]})]}),(0,s.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,s.jsx)("label",{className:"text-[10px] text-text-muted uppercase tracking-wider",children:"MCP SSE port"}),(0,s.jsx)("input",{type:"number",value:Z.mcpSse||"",onChange:e=>ee({...Z,mcpSse:parseInt(e.target.value,10)||0}),placeholder:String(et.mcpSse||8201),className:"bg-transparent border border-border px-2 py-1 text-[11px] text-text outline-none focus:border-accent"}),et.mcpSse>0&&(0,s.jsxs)("span",{className:"text-[10px] text-text-muted",children:["auto-detected: ",et.mcpSse]})]})]})})]}),ep.error&&(0,s.jsx)("p",{className:"text-[11px] text-error mb-2",children:ep.error}),"done"===K&&(0,s.jsx)("p",{className:"text-[11px] text-accent mb-2",children:"Project saved. Redirecting to dashboard..."}),(0,s.jsx)("button",{onClick:ed,disabled:"running"===K||"done"===K,className:"px-5 py-2 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50",children:"running"===K?"Launching...":"done"===K?"Launched!":"Launch Project"})]}),x>=i.length&&(0,s.jsxs)("div",{className:"text-center py-8",children:[(0,s.jsx)("p",{className:"text-accent text-sm font-semibold",children:"Setup complete!"}),(0,s.jsx)("p",{className:"text-[11px] text-text-muted mt-2",children:"Redirecting to project dashboard..."})]})]})]}),(0,s.jsxs)("div",{className:"w-64 shrink-0 border-l border-border p-4 overflow-y-auto bg-bg-surface/50",children:[(0,s.jsx)("h3",{className:"text-[11px] font-semibold text-text-muted uppercase tracking-wider mb-3",children:"Configuration Preview"}),(0,s.jsxs)("div",{className:"space-y-3 text-[11px]",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Project"}),(0,s.jsx)("span",{className:"text-text",children:m||"—"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Repository"}),(0,s.jsx)("span",{className:"text-text",children:h||"—"}),_&&(0,s.jsx)("span",{className:"text-[10px] text-accent block",children:"+ branch protection"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Backends"}),Object.entries(T).map(([e,t])=>(0,s.jsxs)("div",{className:"flex justify-between",children:[(0,s.jsx)("span",{className:"text-text capitalize",children:e}),(0,s.jsx)("span",{className:"text-accent",children:t})]},e))]}),$&&H&&(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Reviewer"}),(0,s.jsxs)("span",{className:"text-text",children:["@",H]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Directory"}),(0,s.jsx)("span",{className:"text-text font-mono text-[10px]",children:D||"—"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("span",{className:"text-text-muted block mb-0.5",children:"Status"}),(0,s.jsx)("div",{className:"space-y-0.5",children:i.map(e=>(0,s.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,s.jsx)("span",{className:`text-[10px] ${"done"===e.status?"text-accent":"error"===e.status?"text-error":"active"===e.status?"text-text":"text-text-muted"}`,children:"done"===e.status?"✓":"error"===e.status?"✗":"active"===e.status?"●":"○"}),(0,s.jsx)("span",{className:`text-[10px] ${"active"===e.status?"text-text":"text-text-muted"}`,children:e.label})]},e.id))})]})]})]})]})]})}])}]);
|
|
@@ -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}}}@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-green-500:#00c758;--spacing:.25rem;--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-relaxed:1.625;--radius-sm:.25rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--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-green-500:lab(70.5521% -66.5147 45.8073)}}}@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}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-0\.5{top:calc(var(--spacing) * .5)}.right-0{right:calc(var(--spacing) * 0)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing) * 0)}.left-0\.5{left:calc(var(--spacing) * .5)}.left-4{left:calc(var(--spacing) * 4)}.left-16{left:calc(var(--spacing) * 16)}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.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)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.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-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)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.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-4{height:calc(var(--spacing) * 4)}.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-\[calc\(100\%-80px\)\]{height:calc(100% - 80px)}.h-full{height:100%}.h-px{height:1px}.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)}.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-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-44{width:calc(var(--spacing) * 44)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[140px\]{min-width:140px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.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}.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-center{align-items:center}.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-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-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-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.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-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-border,.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-error,.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\/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)}}.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-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-border{background-color:var(--border)}.bg-error,.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-red-500{background-color:var(--color-red-500)}.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{background-color:var(--text)}.bg-text-muted{background-color:var(--text-muted)}.bg-transparent{background-color:#0000}.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\.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)}.pt-6{padding-top:calc(var(--spacing) * 6)}.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-6{padding-bottom:calc(var(--spacing) * 6)}.pl-4{padding-left:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.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-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.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-bg{color:var(--bg)}.text-error{color:var(--error)}.text-red-400{color:var(--color-red-400)}.text-text{color:var(--text)}.text-text-muted{color:var(--text-muted)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.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}.accent-accent{accent-color:var(--accent)}.opacity-0{opacity:0}.opacity-60{opacity:.6}.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))}.transition-transform{transition-property:transform,translate,scale,rotate;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}@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}@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:hover,.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\: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\:text-accent:hover{color:var(--accent)}.hover\:text-error:hover{color:var(--error)}.hover\:text-text:hover{color:var(--text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-accent:focus{border-color:var(--accent)}.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\:opacity-50:disabled{opacity:.5}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}: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}@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}@keyframes pulse{50%{opacity:.5}}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|