clideck 1.30.0 → 1.30.2
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/agent-presets.json +2 -2
- package/config.js +6 -3
- package/handlers.js +23 -1
- package/package.json +1 -1
- package/plugins/autopilot/index.js +32 -5
- package/public/js/app.js +32 -12
- package/public/js/terminals.js +18 -9
- package/public/tailwind.css +1 -1
- package/sessions.js +8 -2
- package/skills/awesome-lists/DONE.md +48 -0
- package/skills/awesome-lists/SKILL.md +148 -0
- package/skills/research-experiment/SKILL.md +224 -0
- package/skills/research-experiment/agents/openai.yaml +4 -0
- package/skills/template/SKILL.md +6 -0
- package/telemetry-receiver.js +59 -6
package/agent-presets.json
CHANGED
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"presetId": "codex",
|
|
29
29
|
"name": "Codex",
|
|
30
30
|
"icon": "/img/codex.png",
|
|
31
|
-
"command": "codex
|
|
31
|
+
"command": "codex",
|
|
32
32
|
"minVersion": "0.118.0",
|
|
33
33
|
"installCmd": "npm install -g @openai/codex",
|
|
34
34
|
"isAgent": true,
|
|
35
35
|
"canResume": true,
|
|
36
|
-
"resumeCommand": "codex resume {{sessionId}}
|
|
36
|
+
"resumeCommand": "codex resume {{sessionId}}",
|
|
37
37
|
"sessionIdPattern": "Session:\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
|
|
38
38
|
"outputMarker": "\u2022",
|
|
39
39
|
"telemetryConfigPath": "~/.codex/config.toml",
|
package/config.js
CHANGED
|
@@ -129,10 +129,13 @@ function migrate(cfg) {
|
|
|
129
129
|
if (cmd.telemetryStatus === undefined) cmd.telemetryStatus = null;
|
|
130
130
|
// Sync bridge config from preset
|
|
131
131
|
if (preset?.bridge) cmd.bridge = preset.bridge;
|
|
132
|
-
// Codex:
|
|
132
|
+
// Codex: keep shipped default commands aligned with the current preset.
|
|
133
|
+
// Only rewrite the known default strings so custom Codex commands stay intact.
|
|
133
134
|
if (preset?.presetId === 'codex') {
|
|
134
|
-
if (cmd.command === 'codex') cmd.command = preset.command;
|
|
135
|
-
if (cmd.resumeCommand === 'codex resume {{sessionId}}'
|
|
135
|
+
if (cmd.command === 'codex' || cmd.command === 'codex --no-alt-screen') cmd.command = preset.command;
|
|
136
|
+
if (cmd.resumeCommand === 'codex resume {{sessionId}}' || cmd.resumeCommand === 'codex resume {{sessionId}} --no-alt-screen') {
|
|
137
|
+
cmd.resumeCommand = preset.resumeCommand;
|
|
138
|
+
}
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
141
|
// Auto-add any shipped presets not yet in the commands list
|
package/handlers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync, unlinkSync } = require('fs');
|
|
2
2
|
const { join, dirname } = require('path');
|
|
3
|
-
const { execFileSync } = require('child_process');
|
|
3
|
+
const { execFileSync, execFile } = require('child_process');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const config = require('./config');
|
|
6
6
|
const sessions = require('./sessions');
|
|
@@ -397,6 +397,28 @@ function onConnection(ws) {
|
|
|
397
397
|
break;
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
+
case 'project.openPath': {
|
|
401
|
+
const proj = cfg.projects?.find(p => p.id === msg.id);
|
|
402
|
+
if (!proj?.path) {
|
|
403
|
+
ws.send(JSON.stringify({ type: 'project.openPath.result', id: msg.id, success: false, error: 'Project path is not set' }));
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
const cmd = process.platform === 'darwin'
|
|
407
|
+
? 'open'
|
|
408
|
+
: process.platform === 'win32'
|
|
409
|
+
? 'explorer'
|
|
410
|
+
: 'xdg-open';
|
|
411
|
+
execFile(cmd, [proj.path], { shell: process.platform === 'win32' }, (err) => {
|
|
412
|
+
ws.send(JSON.stringify({
|
|
413
|
+
type: 'project.openPath.result',
|
|
414
|
+
id: msg.id,
|
|
415
|
+
success: !err,
|
|
416
|
+
error: err ? err.message : '',
|
|
417
|
+
}));
|
|
418
|
+
});
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
|
|
400
422
|
case 'dirs.list': {
|
|
401
423
|
const target = msg.path || cfg.defaultPath;
|
|
402
424
|
const result = listDirs(target, !!msg.showHidden);
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ const DATA_DIR = join(require('os').homedir(), '.clideck', 'autopilot');
|
|
|
10
10
|
const projects = new Map(); // projectId → Project
|
|
11
11
|
const tokenUsage = new Map(); // projectId → { input, output }
|
|
12
12
|
const menuPending = new Set(); // sessionIds with a menu awaiting auto-approve
|
|
13
|
+
const idleCaptureTimers = new Map(); // sessionId → timeout id for deferred idle capture
|
|
13
14
|
let api = null;
|
|
14
15
|
let piAi = null;
|
|
15
16
|
|
|
@@ -84,6 +85,7 @@ function latestAgentOutput(id) {
|
|
|
84
85
|
// --- Consumed state (persisted per-project: role → boolean) ---
|
|
85
86
|
|
|
86
87
|
function captureIdleOutput(id, pid, proj) {
|
|
88
|
+
idleCaptureTimers.delete(id);
|
|
87
89
|
if (!projects.has(pid)) return;
|
|
88
90
|
if (proj.status.get(id)) return;
|
|
89
91
|
const w = proj.workers.get(id);
|
|
@@ -114,6 +116,19 @@ function captureIdleOutput(id, pid, proj) {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
function clearIdleCaptureTimer(id) {
|
|
120
|
+
const timer = idleCaptureTimers.get(id);
|
|
121
|
+
if (timer) {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
idleCaptureTimers.delete(id);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function scheduleIdleCapture(id, pid, proj) {
|
|
128
|
+
clearIdleCaptureTimer(id);
|
|
129
|
+
idleCaptureTimers.set(id, setTimeout(() => captureIdleOutput(id, pid, proj), 5000));
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
function resetProjectState(pid) {
|
|
118
133
|
try { unlinkSync(kbPath(pid)); } catch {}
|
|
119
134
|
}
|
|
@@ -165,10 +180,14 @@ function workerByRole(proj, role) {
|
|
|
165
180
|
return null;
|
|
166
181
|
}
|
|
167
182
|
|
|
183
|
+
function isAutopilotWorkerSession(s) {
|
|
184
|
+
return s.projectId && s.roleName && s.presetId !== 'shell';
|
|
185
|
+
}
|
|
186
|
+
|
|
168
187
|
function discoverWorkers(pid) {
|
|
169
188
|
const workers = new Map();
|
|
170
189
|
const status = new Map();
|
|
171
|
-
for (const s of api.getSessions().filter(s => s.projectId === pid && s
|
|
190
|
+
for (const s of api.getSessions().filter(s => s.projectId === pid && isAutopilotWorkerSession(s))) {
|
|
172
191
|
workers.set(s.id, { role: s.roleName, name: s.name, presetId: s.presetId });
|
|
173
192
|
// Sessions start idle. Status is tracked by notifyStatus() on every
|
|
174
193
|
// working/idle transition. If s.working is undefined, no transition was
|
|
@@ -182,7 +201,7 @@ function discoverWorkers(pid) {
|
|
|
182
201
|
function refreshWorkers(pid, proj) {
|
|
183
202
|
const live = new Map();
|
|
184
203
|
const liveStatus = new Map();
|
|
185
|
-
for (const s of api.getSessions().filter(s => s.projectId === pid && s
|
|
204
|
+
for (const s of api.getSessions().filter(s => s.projectId === pid && isAutopilotWorkerSession(s))) {
|
|
186
205
|
live.set(s.id, { role: s.roleName, name: s.name, presetId: s.presetId });
|
|
187
206
|
liveStatus.set(s.id, s.working === true);
|
|
188
207
|
}
|
|
@@ -669,6 +688,7 @@ async function start(pid) {
|
|
|
669
688
|
function stop(pid, keepPill) {
|
|
670
689
|
const proj = projects.get(pid);
|
|
671
690
|
if (!proj) return;
|
|
691
|
+
for (const [sid] of proj.workers) clearIdleCaptureTimer(sid);
|
|
672
692
|
for (const [sid] of proj.workers) api.setAutoApproveMenu(sid, false);
|
|
673
693
|
projects.delete(pid);
|
|
674
694
|
// api.log(`Stopped: ${pid}`);
|
|
@@ -710,7 +730,10 @@ module.exports.init = function (pluginApi) {
|
|
|
710
730
|
api.onMenuDetected((id, choices) => {
|
|
711
731
|
if (!choices?.length) return;
|
|
712
732
|
const [pid] = projectFor(id);
|
|
713
|
-
if (pid)
|
|
733
|
+
if (pid) {
|
|
734
|
+
menuPending.add(id);
|
|
735
|
+
clearIdleCaptureTimer(id);
|
|
736
|
+
}
|
|
714
737
|
});
|
|
715
738
|
|
|
716
739
|
// Status change — the main routing trigger (only when ALL workers are idle)
|
|
@@ -721,9 +744,13 @@ module.exports.init = function (pluginApi) {
|
|
|
721
744
|
const w = proj.workers.get(id);
|
|
722
745
|
const role = w?.role || id.slice(0, 8);
|
|
723
746
|
|
|
724
|
-
if (working) {
|
|
747
|
+
if (working) {
|
|
748
|
+
menuPending.delete(id);
|
|
749
|
+
clearIdleCaptureTimer(id);
|
|
750
|
+
}
|
|
725
751
|
|
|
726
752
|
if (!working && menuPending.has(id)) {
|
|
753
|
+
clearIdleCaptureTimer(id);
|
|
727
754
|
menuPending.delete(id);
|
|
728
755
|
// api.log(`[status] ${role} → IDLE (menu pending — suppressed)`);
|
|
729
756
|
return;
|
|
@@ -740,7 +767,7 @@ module.exports.init = function (pluginApi) {
|
|
|
740
767
|
if (!proj.workers.has(id)) return;
|
|
741
768
|
|
|
742
769
|
api.appendPillLog(pillId, `${role} → idle`);
|
|
743
|
-
|
|
770
|
+
scheduleIdleCapture(id, pid, proj);
|
|
744
771
|
});
|
|
745
772
|
|
|
746
773
|
// Frontend queries
|
package/public/js/app.js
CHANGED
|
@@ -15,19 +15,13 @@ import { renderPrompts } from './prompts.js';
|
|
|
15
15
|
import { renderRoles } from './roles.js';
|
|
16
16
|
|
|
17
17
|
const shownAgentHealthToasts = new Set();
|
|
18
|
+
let reconnectReplaySkip = null;
|
|
18
19
|
|
|
19
20
|
function connect() {
|
|
20
21
|
state.ws = new WebSocket(`ws://${location.host}`);
|
|
21
22
|
|
|
22
23
|
state.ws.onopen = () => {
|
|
23
|
-
|
|
24
|
-
state.terms.clear();
|
|
25
|
-
state.pills.clear();
|
|
26
|
-
state.activePill = null;
|
|
27
|
-
document.getElementById('session-list').innerHTML = '';
|
|
28
|
-
document.getElementById('pill-log-panel')?.remove();
|
|
29
|
-
state.active = null;
|
|
30
|
-
document.getElementById('empty').style.display = 'flex';
|
|
24
|
+
reconnectReplaySkip = new Set(state.terms.keys());
|
|
31
25
|
send({ type: 'remote.status' });
|
|
32
26
|
};
|
|
33
27
|
|
|
@@ -64,8 +58,16 @@ function connect() {
|
|
|
64
58
|
renderResumable();
|
|
65
59
|
break;
|
|
66
60
|
case 'sessions':
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
{
|
|
62
|
+
const liveIds = new Set(msg.list.map(s => s.id));
|
|
63
|
+
for (const id of [...state.terms.keys()]) {
|
|
64
|
+
if (!liveIds.has(id)) removeTerminal(id);
|
|
65
|
+
}
|
|
66
|
+
msg.list.forEach(s => addTerminal(s.id, s.name, s.themeId, s.commandId, s.projectId, s.muted, s.lastPreview, s.presetId));
|
|
67
|
+
if (!state.active || !state.terms.has(state.active)) {
|
|
68
|
+
if (msg.list.length) select(msg.list[0].id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
69
71
|
break;
|
|
70
72
|
case 'created':
|
|
71
73
|
if (!state.terms.has(msg.id)) addTerminal(msg.id, msg.name, msg.themeId, msg.commandId, msg.projectId, msg.muted, msg.lastPreview, msg.presetId);
|
|
@@ -75,6 +77,7 @@ function connect() {
|
|
|
75
77
|
break;
|
|
76
78
|
case 'output': {
|
|
77
79
|
const entry = state.terms.get(msg.id);
|
|
80
|
+
if (msg.replay && reconnectReplaySkip?.has(msg.id) && entry) break;
|
|
78
81
|
if (entry && !entry.queue(msg.data)) entry.term.write(msg.data);
|
|
79
82
|
updatePreview(msg.id);
|
|
80
83
|
markUnread(msg.id);
|
|
@@ -104,6 +107,7 @@ function connect() {
|
|
|
104
107
|
}
|
|
105
108
|
case 'session.history': {
|
|
106
109
|
const entry = state.terms.get(msg.id);
|
|
110
|
+
if (msg.replay && reconnectReplaySkip?.has(msg.id) && entry) break;
|
|
107
111
|
if (entry && !entry.queue(msg.text + '\n')) entry.term.write(msg.text + '\n');
|
|
108
112
|
updatePreview(msg.id);
|
|
109
113
|
break;
|
|
@@ -231,6 +235,9 @@ function connect() {
|
|
|
231
235
|
}
|
|
232
236
|
break;
|
|
233
237
|
}
|
|
238
|
+
case 'project.openPath.result':
|
|
239
|
+
if (!msg.success) showToast(msg.error || 'Failed to open project folder', { type: 'error' });
|
|
240
|
+
break;
|
|
234
241
|
case 'sessions.saved':
|
|
235
242
|
flashSaveIndicator();
|
|
236
243
|
break;
|
|
@@ -251,8 +258,16 @@ function connect() {
|
|
|
251
258
|
break;
|
|
252
259
|
}
|
|
253
260
|
case 'pills':
|
|
254
|
-
|
|
255
|
-
|
|
261
|
+
{
|
|
262
|
+
const liveIds = new Set(msg.list.map(p => p.id));
|
|
263
|
+
for (const id of [...state.pills.keys()]) {
|
|
264
|
+
if (!liveIds.has(id)) removePill(id);
|
|
265
|
+
}
|
|
266
|
+
for (const p of msg.list) {
|
|
267
|
+
if (state.pills.has(p.id)) updatePill(p);
|
|
268
|
+
else addPill(p);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
256
271
|
break;
|
|
257
272
|
case 'pill.added':
|
|
258
273
|
addPill(msg.pill);
|
|
@@ -326,6 +341,11 @@ sessionList.addEventListener('click', (e) => {
|
|
|
326
341
|
|
|
327
342
|
// Project header click — toggle collapse (skip if just finished a drag)
|
|
328
343
|
const projHeader = e.target.closest('.project-header');
|
|
344
|
+
if (e.target.closest('.project-path-btn')) {
|
|
345
|
+
const projId = e.target.closest('.project-header')?.dataset.projectId;
|
|
346
|
+
if (projId) send({ type: 'project.openPath', id: projId });
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
329
349
|
if (e.target.closest('.plugin-project-btn')) return; // handled by btn's own click listener
|
|
330
350
|
if (projHeader && !e.target.closest('.project-menu-btn') && !wasDragging()) {
|
|
331
351
|
toggleProjectCollapse(projHeader.dataset.projectId);
|
package/public/js/terminals.js
CHANGED
|
@@ -62,12 +62,14 @@ function startBounce(container) {
|
|
|
62
62
|
return { el: c, x: 10 + i * rand(14, 22), y: floor - rand(0, 15), vx: rand(0.6, 1.3), vy: -rand(2.5, 5), r: radii[i] };
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
let raf;
|
|
66
|
-
function step() {
|
|
65
|
+
let raf, lastFrame = 0;
|
|
66
|
+
function step(now = performance.now()) {
|
|
67
|
+
const dt = lastFrame ? Math.min((now - lastFrame) / 16.67, 4) : 1;
|
|
68
|
+
lastFrame = now;
|
|
67
69
|
balls.forEach(b => {
|
|
68
|
-
b.vy += gravity;
|
|
69
|
-
b.x += b.vx;
|
|
70
|
-
b.y += b.vy;
|
|
70
|
+
b.vy += gravity * dt;
|
|
71
|
+
b.x += b.vx * dt;
|
|
72
|
+
b.y += b.vy * dt;
|
|
71
73
|
if (b.y > floor) { b.y = floor; b.vy *= -restitution; }
|
|
72
74
|
});
|
|
73
75
|
for (let i = 0; i < balls.length; i++) {
|
|
@@ -440,16 +442,19 @@ export function addTerminal(id, name, themeId, commandId, projectId, muted, last
|
|
|
440
442
|
fitRaf = requestAnimationFrame(() => { fitRaf = 0; doFit(); });
|
|
441
443
|
});
|
|
442
444
|
ro.observe(el);
|
|
443
|
-
// Safety: if RO hasn't fired within 500ms,
|
|
444
|
-
//
|
|
445
|
-
//
|
|
445
|
+
// Safety: if RO hasn't fired within 500ms, let visible terminals proceed.
|
|
446
|
+
// For hidden/unmeasured terminals, keep the PTY at a reasonable fallback size
|
|
447
|
+
// but do not flush queued output until a real measured fit happens; replaying
|
|
448
|
+
// buffered output into fake geometry is what leaves the rebuilt terminal messy
|
|
449
|
+
// after refresh/logout/login.
|
|
446
450
|
setTimeout(() => {
|
|
447
451
|
if (!fitted) {
|
|
448
|
-
fitted = true;
|
|
449
452
|
if (!el.offsetWidth) {
|
|
450
453
|
term.resize(120, 30);
|
|
451
454
|
send({ type: 'resize', id, cols: 120, rows: 30 });
|
|
455
|
+
return;
|
|
452
456
|
}
|
|
457
|
+
fitted = true;
|
|
453
458
|
for (const chunk of pending) term.write(chunk);
|
|
454
459
|
pending = null;
|
|
455
460
|
updatePreview(id);
|
|
@@ -781,6 +786,7 @@ export function startProjectRename(projectId) {
|
|
|
781
786
|
// --- Project grouping ---
|
|
782
787
|
|
|
783
788
|
const CHEVRON_SVG = `<svg class="w-3 h-3 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>`;
|
|
789
|
+
const PATH_SVG = `<svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7.5A1.5 1.5 0 0 1 4.5 6h4.379a1.5 1.5 0 0 1 1.06.44l1.122 1.12a1.5 1.5 0 0 0 1.06.44H19.5A1.5 1.5 0 0 1 21 9.5v8A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5v-10Z"/></svg>`;
|
|
784
790
|
|
|
785
791
|
const PROJECT_COLORS = ['#3b82f6', '#8b5cf6', '#ec4899', '#f59e0b', '#10b981', '#ef4444', '#06b6d4', '#84cc16'];
|
|
786
792
|
|
|
@@ -817,6 +823,9 @@ export function regroupSessions() {
|
|
|
817
823
|
<span class="w-2 h-2 rounded-full flex-shrink-0" style="background:${projectColor(proj)}"></span>
|
|
818
824
|
<span class="project-name flex-1 text-[11px] font-semibold uppercase tracking-wider text-slate-500 truncate">${esc(proj.name)}</span>
|
|
819
825
|
<span class="project-count text-[10px] text-slate-600">0</span>
|
|
826
|
+
<button class="project-path-btn opacity-0 group-hover:opacity-100 ${proj.path ? 'text-slate-600 hover:text-slate-300' : 'text-slate-700 cursor-default'} flex-shrink-0 transition-opacity p-0.5" title="${proj.path ? 'Open project folder' : 'Project path not set'}" ${proj.path ? '' : 'disabled'}>
|
|
827
|
+
${PATH_SVG}
|
|
828
|
+
</button>
|
|
820
829
|
<span class="project-plugin-actions"></span>
|
|
821
830
|
<button class="project-menu-btn opacity-0 group-hover:opacity-100 text-slate-600 hover:text-slate-400 flex-shrink-0 transition-opacity p-0.5" title="Project menu">
|
|
822
831
|
<svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5" fill="currentColor"/><circle cx="10" cy="10" r="1.5" fill="currentColor"/><circle cx="10" cy="16" r="1.5" fill="currentColor"/></svg>
|
package/public/tailwind.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-base:#020617;--color-surface:#0f172a;--color-raised:#1e293b;--color-muted:#334155;--color-border:#475569;--color-subtle:#64748b;--color-dim:#94a3b8;--color-soft:#cbd5e1;--color-text:#e2e8f0;--color-bright:#f8fafc;--color-overlay:rgba(0,0,0,.6);--color-shadow:rgba(0,0,0,.5);--color-dialog:#1e293b;--color-stats-bg:rgba(0,0,0,.95);--color-accent-subtle:rgba(59,130,246,.15);--color-rail:#1d1f1f;--color-rail-active:#2a323f;--color-sidebar:#161717;--color-sidebar-input:#0f1010;--color-sidebar-border:#2e2f2f;--color-chat-hover:#2e2f2f;--color-chat-active:#2e2f2f;--color-rail-badge-bg:#5cbd6d;--color-rail-badge-text:#0a0a0a}.light{--color-base:#edeef1;--color-surface:#f7f8fa;--color-raised:#fff;--color-muted:#e4e6ea;--color-border:#d1d5db;--color-subtle:#8b919a;--color-dim:#5f6672;--color-soft:#3d4450;--color-text:#1a1d24;--color-bright:#0c0e12;--color-overlay:rgba(0,0,0,.25);--color-shadow:rgba(0,0,0,.08);--color-dialog:#fff;--color-stats-bg:hsla(0,0%,100%,.92);--color-accent-subtle:rgba(59,130,246,.08);--color-rail:#fcfdfd;--color-rail-active:#eae9e7;--color-sidebar:#f9fafa;--color-sidebar-input:#fff;--color-sidebar-border:#e0deda;--color-chat-hover:#f6f5f5;--color-chat-active:#eff0f0;--color-rail-badge-bg:#51a868;--color-rail-badge-text:#fff}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-1{inset:.25rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-2\.5{left:.625rem}.right-0{right:0}.right-3{right:.75rem}.right-5{right:1.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.z-10{z-index:10}.z-\[200\]{z-index:200}.z-\[250\]{z-index:250}.z-\[260\]{z-index:260}.z-\[300\]{z-index:300}.z-\[400\]{z-index:400}.z-\[500\]{z-index:500}.mx-4{margin-left:1rem;margin-right:1rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mt-2{margin-top:-.5rem}.-mt-px{margin-top:-1px}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.ml-0\.5{margin-left:.125rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[180px\]{height:180px}.h-\[18px\]{height:18px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[160px\]{max-height:160px}.max-h-\[400px\]{max-height:400px}.max-h-\[460px\]{max-height:460px}.min-h-0{min-height:0}.min-h-\[200px\]{min-height:200px}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[180px\]{width:180px}.w-\[18px\]{width:18px}.w-\[340px\]{width:340px}.w-\[354px\]{width:354px}.w-\[360px\]{width:360px}.w-\[420px\]{width:420px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[160px\]{min-width:160px}.min-w-\[16px\]{min-width:16px}.min-w-\[220px\]{min-width:220px}.min-w-\[260px\]{min-width:260px}.min-w-\[354px\]{min-width:354px}.max-w-2xl{max-width:42rem}.max-w-full{max-width:100%}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1px*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400{--tw-border-opacity:1;border-color:rgb(96 165 250/var(--tw-border-opacity,1))}.border-red-500\/30{border-color:rgba(239,68,68,.3)}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-slate-700\/40{border-color:rgba(51,65,85,.4)}.border-slate-700\/50{border-color:rgba(51,65,85,.5)}.border-slate-700\/60{border-color:rgba(51,65,85,.6)}.border-slate-900{--tw-border-opacity:1;border-color:rgb(15 23 42/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/15{background-color:rgba(59,130,246,.15)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-600\/20{background-color:rgba(5,150,105,.2)}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/20{background-color:rgba(220,38,38,.2)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-700\/50{background-color:rgba(51,65,85,.5)}.bg-slate-700\/60{background-color:rgba(51,65,85,.6)}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-800\/30{background-color:rgba(30,41,59,.3)}.bg-slate-800\/40{background-color:rgba(30,41,59,.4)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-800\/60{background-color:rgba(30,41,59,.6)}.bg-slate-800\/80{background-color:rgba(30,41,59,.8)}.bg-slate-800\/95{background-color:rgba(30,41,59,.95)}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/70{background-color:rgba(15,23,42,.7)}.bg-slate-950{--tw-bg-opacity:1;background-color:rgb(2 6 23/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-\[3px\]{padding:3px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-\[5px\]{padding-top:5px;padding-bottom:5px}.py-\[7px\]{padding-top:7px;padding-bottom:7px}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-3\.5{padding-bottom:.875rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-9{padding-left:2.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-3\.5{padding-top:.875rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.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)}.leading-\[1\.45\]{line-height:1.45}.leading-\[1\.4\]{line-height:1.4}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.text-emerald-500\/70{color:rgba(16,185,129,.7)}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-rose-400\/80{color:rgba(251,113,133,.8)}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-slate-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-500::placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.accent-blue-500{accent-color:#3b82f6}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-black\/40{--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/60{--tw-shadow-color:rgba(0,0,0,.6);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-white\/40{--tw-ring-color:hsla(0,0%,100%,.4)}.blur{--tw-blur:blur(8px)}.blur,.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-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-filter{-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,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.bg-slate-950{background-color:var(--color-base)!important}.bg-slate-900{background-color:var(--color-surface)!important}.bg-slate-800{background-color:var(--color-raised)!important}.bg-slate-700{background-color:var(--color-muted)!important}.bg-slate-800\/50{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.bg-slate-800\/30{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.bg-slate-800\/60{background-color:color-mix(in srgb,var(--color-raised) 60%,transparent)!important}.bg-slate-800\/80{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.bg-slate-900\/70{background-color:color-mix(in srgb,var(--color-surface) 70%,transparent)!important}.bg-slate-800\/95{background-color:color-mix(in srgb,var(--color-raised) 95%,transparent)!important}.bg-slate-700\/50{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.bg-slate-700\/60{background-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.hover\:bg-slate-700:hover{background-color:var(--color-muted)!important}.hover\:bg-slate-800:hover{background-color:var(--color-raised)!important}.hover\:bg-slate-800\/50:hover{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.hover\:bg-slate-800\/30:hover{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.hover\:bg-slate-700\/50:hover{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.hover\:bg-slate-700\/70:hover{background-color:color-mix(in srgb,var(--color-muted) 70%,transparent)!important}.text-slate-200{color:var(--color-text)!important}.text-slate-300{color:var(--color-soft)!important}.text-slate-400{color:var(--color-dim)!important}.text-slate-500{color:var(--color-subtle)!important}.text-slate-600{color:var(--color-border)!important}.hover\:text-slate-200:hover{color:var(--color-text)!important}.hover\:text-slate-300:hover{color:var(--color-soft)!important}.hover\:text-slate-400:hover{color:var(--color-dim)!important}.border-slate-600{border-color:var(--color-border)!important}.border-slate-700{border-color:var(--color-muted)!important}.border-slate-700\/50{border-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.border-slate-700\/40{border-color:color-mix(in srgb,var(--color-muted) 40%,transparent)!important}.border-slate-700\/60{border-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.border-slate-600\/60{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.hover\:border-slate-500:hover{border-color:var(--color-subtle)!important}.focus\:border-slate-600\/60:focus{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.focus\:bg-slate-800\/80:focus{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.placeholder-slate-500::-moz-placeholder{color:var(--color-subtle)!important}.placeholder-slate-500::placeholder{color:var(--color-subtle)!important}.placeholder-slate-600::-moz-placeholder{color:var(--color-border)!important}.placeholder-slate-600::placeholder{color:var(--color-border)!important}.ring-slate-500{--tw-ring-color:var(--color-subtle)!important}.bg-black\/60{background-color:var(--color-overlay)!important}.shadow-black\/40,.shadow-black\/50,.shadow-black\/60{--tw-shadow-color:var(--color-shadow)!important}.disabled\:bg-slate-600:disabled{background-color:var(--color-border)!important}.disabled\:text-slate-400:disabled{color:var(--color-dim)!important}:root{--color-preview:#a2a2a2;--color-time:#7c7d7d;--color-time-recent:#5cbd6d;--color-dormant:#555;--color-proj-meta:#7c7d7d;--color-search-bg:#2e2f2f;--color-search-text:#acacac;--color-session-hover:hsla(0,0%,100%,.04);--color-header-icon:#cbd5e1;--color-rail-icon:#a5a6a6}.light{--color-preview:#626262;--color-time:#666;--color-time-recent:#51a868;--color-dormant:#aaa;--color-proj-meta:#666;--color-search-bg:#f6f5f5;--color-search-text:#626262;--color-session-hover:rgba(0,0,0,.04);--color-header-icon:#3d4450;--color-rail-icon:#636261}.session-preview{color:var(--color-preview)!important}.session-time{color:var(--color-time)!important}.session-time.recent{color:var(--color-time-recent)!important}.session-status.dormant{color:var(--color-dormant)!important}.group[data-id]:hover,.pill-row:hover,.resumable-row:hover{background-color:var(--color-session-hover)!important}.project-count,.project-menu-btn{color:var(--color-proj-meta)!important}#search-input{background-color:var(--color-search-bg)!important;color:var(--color-search-text)!important}#search-input::-moz-placeholder{color:var(--color-search-text)!important;opacity:.7}#search-input::placeholder{color:var(--color-search-text)!important;opacity:.7}.relative:has(#search-input)>svg{color:var(--color-search-text)!important}.rail-btn:not(.text-slate-200){color:var(--color-rail-icon)!important}.rail-btn.bg-slate-800{background-color:var(--color-rail-active)!important}.icon-btn{color:var(--color-header-icon)!important;border-color:var(--color-border)!important;font-weight:700}.icon-btn svg{stroke-width:2}:root{--color-separator:#2e2f2f}.light{--color-separator:#d8d3cd}#nav-rail{background-color:var(--color-rail)!important}#sidebar{background-color:var(--color-sidebar)!important;border-right-color:var(--color-separator)!important}#sidebar input[type=text],#sidebar select{background-color:var(--color-sidebar-input)!important;border-color:var(--color-sidebar-border)!important}.group:hover{background-color:var(--color-chat-hover)!important}.group.active-session{background-color:var(--color-chat-active)!important}.theme-toggle{position:relative;width:36px;height:36px}.theme-toggle svg{position:absolute;inset:0;margin:auto;transition:opacity .3s ease,transform .3s ease}.theme-toggle .icon-sun{opacity:0;transform:rotate(-90deg) scale(.5)}.light .theme-toggle .icon-sun,.theme-toggle .icon-moon{opacity:1;transform:rotate(0) scale(1)}.light .theme-toggle .icon-moon{opacity:0;transform:rotate(90deg) scale(.5)}html{transition:color .3s ease,background-color .3s ease}.term-wrap{visibility:hidden;position:absolute;overflow:hidden;top:4px;left:4px;right:4px;bottom:0}.term-wrap.active{visibility:visible}.term-wrap .xterm{height:100%}.save-indicator{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;border:1px solid var(--color-search-text);margin-right:4px;opacity:.35;transition:opacity .4s ease}.save-indicator.saved{opacity:.5}.save-indicator .save-tick{color:var(--color-time-recent);display:block}.save-indicator .save-spin{display:none;color:var(--color-dim);animation:save-rotate 1.5s cubic-bezier(.4,0,.2,1) infinite}.save-indicator.saving .save-tick{display:none}.save-indicator.saving .save-spin{display:block}.save-indicator.saving{opacity:.5}@keyframes save-rotate{to{transform:rotate(1turn)}}.tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.5)}.light .tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.25),0 0 0 1px rgba(0,0,0,.05)}.drop-highlight{border-radius:.25rem;background-color:rgba(59,130,246,.1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(59,130,246,.3)}.project-drop-line{height:2px;margin:.125rem .5rem;border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.plugin-chevron.collapsed,.project-chevron.collapsed svg{transform:rotate(-90deg)}.tmx-scroll{scrollbar-width:thin;scrollbar-color:transparent transparent}.tmx-scroll::-webkit-scrollbar{width:10px}.tmx-scroll::-webkit-scrollbar-track{background:transparent}.tmx-scroll::-webkit-scrollbar-thumb{background:transparent;border:2px solid transparent;border-radius:9999px;-webkit-transition:background-color .2s ease,border-color .2s ease;transition:background-color .2s ease,border-color .2s ease}.tmx-scroll.is-scrolling,.tmx-scroll:hover{scrollbar-color:color-mix(in srgb,var(--color-muted) 78%,transparent) color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-track,.tmx-scroll:hover::-webkit-scrollbar-track{background:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb,.tmx-scroll:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--color-muted) 78%,transparent);border-color:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb:hover,.tmx-scroll:hover::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--color-subtle) 85%,transparent)}.prompt-autocomplete{position:fixed;width:340px;background:var(--color-raised);border:1px solid var(--color-muted);border-radius:10px;box-shadow:0 20px 40px -8px rgba(0,0,0,.5);z-index:100;display:flex;flex-direction:column;overflow:hidden;animation:pa-in .15s ease}@keyframes pa-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.pa-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent)}.pa-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-subtle)}.pa-query{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--color-dim);background:color-mix(in srgb,var(--color-muted) 40%,transparent);padding:2px 6px;border-radius:4px}.pa-list{overflow-y:auto;padding:4px;max-height:184px}.pa-item{padding:8px 10px;border-radius:6px;cursor:pointer;transition:background-color .1s}.pa-item:hover,.pa-selected{background:color-mix(in srgb,var(--color-muted) 40%,transparent)}.pa-name{font-size:13px;font-weight:500;color:var(--color-text)}.pa-name,.pa-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pa-text{font-size:11px;color:var(--color-subtle);margin-top:2px}.pa-item mark{background:rgba(59,130,246,.25);color:inherit;border-radius:2px;padding:0 1px}.pa-footer{display:flex;gap:12px;justify-content:center;padding:6px 12px;border-top:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent);font-size:10px;color:var(--color-subtle)}.pa-footer kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;padding:1px 4px;border-radius:3px;background:color-mix(in srgb,var(--color-muted) 50%,transparent);color:var(--color-dim)}.pa-empty{padding:20px 12px;text-align:center;font-size:13px;color:var(--color-subtle)}.pa-hint{padding:0 12px 12px;text-align:center;font-size:11px;color:var(--color-border)}.pa-hint kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:color-mix(in srgb,var(--color-muted) 50%,transparent);padding:1px 4px;border-radius:3px}.empty\:hidden:empty{display:none}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-slate-500:hover{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity,1))}.hover\:bg-amber-500\/20:hover{background-color:rgba(245,158,11,.2)}.hover\:bg-blue-500:hover{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.hover\:bg-blue-500\/20:hover{background-color:rgba(59,130,246,.2)}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:bg-rose-500\/20:hover{background-color:rgba(244,63,94,.2)}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-700\/50:hover{background-color:rgba(51,65,85,.5)}.hover\:bg-slate-700\/60:hover{background-color:rgba(51,65,85,.6)}.hover\:bg-slate-700\/70:hover{background-color:rgba(51,65,85,.7)}.hover\:bg-slate-800\/30:hover{background-color:rgba(30,41,59,.3)}.hover\:bg-slate-800\/40:hover{background-color:rgba(30,41,59,.4)}.hover\:bg-slate-800\/50:hover{background-color:rgba(30,41,59,.5)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\:text-emerald-300:hover{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.hover\:text-emerald-400:hover{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.hover\:text-indigo-400:hover{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-rose-300:hover{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.hover\:text-slate-200:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.hover\:text-slate-300:hover{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.hover\:ring-2:hover{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:ring-slate-500:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(100 116 139/var(--tw-ring-opacity,1))}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:border-slate-600\/60:focus{border-color:rgba(71,85,105,.6)}.focus\:bg-slate-800\/80:focus{background-color:rgba(30,41,59,.8)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:rgba(59,130,246,.3)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-600:disabled{--tw-bg-opacity:1;background-color:rgb(71 85 105/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100{opacity:1}
|
|
1
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-base:#020617;--color-surface:#0f172a;--color-raised:#1e293b;--color-muted:#334155;--color-border:#475569;--color-subtle:#64748b;--color-dim:#94a3b8;--color-soft:#cbd5e1;--color-text:#e2e8f0;--color-bright:#f8fafc;--color-overlay:rgba(0,0,0,.6);--color-shadow:rgba(0,0,0,.5);--color-dialog:#1e293b;--color-stats-bg:rgba(0,0,0,.95);--color-accent-subtle:rgba(59,130,246,.15);--color-rail:#1d1f1f;--color-rail-active:#2a323f;--color-sidebar:#161717;--color-sidebar-input:#0f1010;--color-sidebar-border:#2e2f2f;--color-chat-hover:#2e2f2f;--color-chat-active:#2e2f2f;--color-rail-badge-bg:#5cbd6d;--color-rail-badge-text:#0a0a0a}.light{--color-base:#edeef1;--color-surface:#f7f8fa;--color-raised:#fff;--color-muted:#e4e6ea;--color-border:#d1d5db;--color-subtle:#8b919a;--color-dim:#5f6672;--color-soft:#3d4450;--color-text:#1a1d24;--color-bright:#0c0e12;--color-overlay:rgba(0,0,0,.25);--color-shadow:rgba(0,0,0,.08);--color-dialog:#fff;--color-stats-bg:hsla(0,0%,100%,.92);--color-accent-subtle:rgba(59,130,246,.08);--color-rail:#fcfdfd;--color-rail-active:#eae9e7;--color-sidebar:#f9fafa;--color-sidebar-input:#fff;--color-sidebar-border:#e0deda;--color-chat-hover:#f6f5f5;--color-chat-active:#eff0f0;--color-rail-badge-bg:#51a868;--color-rail-badge-text:#fff}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-1{inset:.25rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-2\.5{left:.625rem}.right-0{right:0}.right-3{right:.75rem}.right-5{right:1.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.z-10{z-index:10}.z-\[200\]{z-index:200}.z-\[250\]{z-index:250}.z-\[260\]{z-index:260}.z-\[300\]{z-index:300}.z-\[400\]{z-index:400}.z-\[500\]{z-index:500}.mx-4{margin-left:1rem;margin-right:1rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mt-2{margin-top:-.5rem}.-mt-px{margin-top:-1px}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.ml-0\.5{margin-left:.125rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[180px\]{height:180px}.h-\[18px\]{height:18px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[160px\]{max-height:160px}.max-h-\[400px\]{max-height:400px}.max-h-\[460px\]{max-height:460px}.min-h-0{min-height:0}.min-h-\[200px\]{min-height:200px}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[180px\]{width:180px}.w-\[18px\]{width:18px}.w-\[340px\]{width:340px}.w-\[354px\]{width:354px}.w-\[360px\]{width:360px}.w-\[420px\]{width:420px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[160px\]{min-width:160px}.min-w-\[16px\]{min-width:16px}.min-w-\[220px\]{min-width:220px}.min-w-\[260px\]{min-width:260px}.min-w-\[354px\]{min-width:354px}.max-w-2xl{max-width:42rem}.max-w-full{max-width:100%}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1px*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400{--tw-border-opacity:1;border-color:rgb(96 165 250/var(--tw-border-opacity,1))}.border-red-500\/30{border-color:rgba(239,68,68,.3)}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-slate-700\/40{border-color:rgba(51,65,85,.4)}.border-slate-700\/50{border-color:rgba(51,65,85,.5)}.border-slate-700\/60{border-color:rgba(51,65,85,.6)}.border-slate-900{--tw-border-opacity:1;border-color:rgb(15 23 42/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/15{background-color:rgba(59,130,246,.15)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-600\/20{background-color:rgba(5,150,105,.2)}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/20{background-color:rgba(220,38,38,.2)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-700\/50{background-color:rgba(51,65,85,.5)}.bg-slate-700\/60{background-color:rgba(51,65,85,.6)}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-800\/30{background-color:rgba(30,41,59,.3)}.bg-slate-800\/40{background-color:rgba(30,41,59,.4)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-800\/60{background-color:rgba(30,41,59,.6)}.bg-slate-800\/80{background-color:rgba(30,41,59,.8)}.bg-slate-800\/95{background-color:rgba(30,41,59,.95)}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/70{background-color:rgba(15,23,42,.7)}.bg-slate-950{--tw-bg-opacity:1;background-color:rgb(2 6 23/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-\[3px\]{padding:3px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-\[5px\]{padding-top:5px;padding-bottom:5px}.py-\[7px\]{padding-top:7px;padding-bottom:7px}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-3\.5{padding-bottom:.875rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-9{padding-left:2.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-3\.5{padding-top:.875rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.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)}.leading-\[1\.45\]{line-height:1.45}.leading-\[1\.4\]{line-height:1.4}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.text-emerald-500\/70{color:rgba(16,185,129,.7)}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-rose-400\/80{color:rgba(251,113,133,.8)}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-slate-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-500::placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.accent-blue-500{accent-color:#3b82f6}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-black\/40{--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/60{--tw-shadow-color:rgba(0,0,0,.6);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-white\/40{--tw-ring-color:hsla(0,0%,100%,.4)}.blur{--tw-blur:blur(8px)}.blur,.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-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-filter{-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,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.bg-slate-950{background-color:var(--color-base)!important}.bg-slate-900{background-color:var(--color-surface)!important}.bg-slate-800{background-color:var(--color-raised)!important}.bg-slate-700{background-color:var(--color-muted)!important}.bg-slate-800\/50{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.bg-slate-800\/30{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.bg-slate-800\/60{background-color:color-mix(in srgb,var(--color-raised) 60%,transparent)!important}.bg-slate-800\/80{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.bg-slate-900\/70{background-color:color-mix(in srgb,var(--color-surface) 70%,transparent)!important}.bg-slate-800\/95{background-color:color-mix(in srgb,var(--color-raised) 95%,transparent)!important}.bg-slate-700\/50{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.bg-slate-700\/60{background-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.hover\:bg-slate-700:hover{background-color:var(--color-muted)!important}.hover\:bg-slate-800:hover{background-color:var(--color-raised)!important}.hover\:bg-slate-800\/50:hover{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.hover\:bg-slate-800\/30:hover{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.hover\:bg-slate-700\/50:hover{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.hover\:bg-slate-700\/70:hover{background-color:color-mix(in srgb,var(--color-muted) 70%,transparent)!important}.text-slate-200{color:var(--color-text)!important}.text-slate-300{color:var(--color-soft)!important}.text-slate-400{color:var(--color-dim)!important}.text-slate-500{color:var(--color-subtle)!important}.text-slate-600{color:var(--color-border)!important}.hover\:text-slate-200:hover{color:var(--color-text)!important}.hover\:text-slate-300:hover{color:var(--color-soft)!important}.hover\:text-slate-400:hover{color:var(--color-dim)!important}.border-slate-600{border-color:var(--color-border)!important}.border-slate-700{border-color:var(--color-muted)!important}.border-slate-700\/50{border-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.border-slate-700\/40{border-color:color-mix(in srgb,var(--color-muted) 40%,transparent)!important}.border-slate-700\/60{border-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.border-slate-600\/60{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.hover\:border-slate-500:hover{border-color:var(--color-subtle)!important}.focus\:border-slate-600\/60:focus{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.focus\:bg-slate-800\/80:focus{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.placeholder-slate-500::-moz-placeholder{color:var(--color-subtle)!important}.placeholder-slate-500::placeholder{color:var(--color-subtle)!important}.placeholder-slate-600::-moz-placeholder{color:var(--color-border)!important}.placeholder-slate-600::placeholder{color:var(--color-border)!important}.ring-slate-500{--tw-ring-color:var(--color-subtle)!important}.bg-black\/60{background-color:var(--color-overlay)!important}.shadow-black\/40,.shadow-black\/50,.shadow-black\/60{--tw-shadow-color:var(--color-shadow)!important}.disabled\:bg-slate-600:disabled{background-color:var(--color-border)!important}.disabled\:text-slate-400:disabled{color:var(--color-dim)!important}:root{--color-preview:#a2a2a2;--color-time:#7c7d7d;--color-time-recent:#5cbd6d;--color-dormant:#555;--color-proj-meta:#7c7d7d;--color-search-bg:#2e2f2f;--color-search-text:#acacac;--color-session-hover:hsla(0,0%,100%,.04);--color-header-icon:#cbd5e1;--color-rail-icon:#a5a6a6}.light{--color-preview:#626262;--color-time:#666;--color-time-recent:#51a868;--color-dormant:#aaa;--color-proj-meta:#666;--color-search-bg:#f6f5f5;--color-search-text:#626262;--color-session-hover:rgba(0,0,0,.04);--color-header-icon:#3d4450;--color-rail-icon:#636261}.session-preview{color:var(--color-preview)!important}.session-time{color:var(--color-time)!important}.session-time.recent{color:var(--color-time-recent)!important}.session-status.dormant{color:var(--color-dormant)!important}.group[data-id]:hover,.pill-row:hover,.resumable-row:hover{background-color:var(--color-session-hover)!important}.project-count,.project-menu-btn{color:var(--color-proj-meta)!important}#search-input{background-color:var(--color-search-bg)!important;color:var(--color-search-text)!important}#search-input::-moz-placeholder{color:var(--color-search-text)!important;opacity:.7}#search-input::placeholder{color:var(--color-search-text)!important;opacity:.7}.relative:has(#search-input)>svg{color:var(--color-search-text)!important}.rail-btn:not(.text-slate-200){color:var(--color-rail-icon)!important}.rail-btn.bg-slate-800{background-color:var(--color-rail-active)!important}.icon-btn{color:var(--color-header-icon)!important;border-color:var(--color-border)!important;font-weight:700}.icon-btn svg{stroke-width:2}:root{--color-separator:#2e2f2f}.light{--color-separator:#d8d3cd}#nav-rail{background-color:var(--color-rail)!important}#sidebar{background-color:var(--color-sidebar)!important;border-right-color:var(--color-separator)!important}#sidebar input[type=text],#sidebar select{background-color:var(--color-sidebar-input)!important;border-color:var(--color-sidebar-border)!important}.group:hover{background-color:var(--color-chat-hover)!important}.group.active-session{background-color:var(--color-chat-active)!important}.theme-toggle{position:relative;width:36px;height:36px}.theme-toggle svg{position:absolute;inset:0;margin:auto;transition:opacity .3s ease,transform .3s ease}.theme-toggle .icon-sun{opacity:0;transform:rotate(-90deg) scale(.5)}.light .theme-toggle .icon-sun,.theme-toggle .icon-moon{opacity:1;transform:rotate(0) scale(1)}.light .theme-toggle .icon-moon{opacity:0;transform:rotate(90deg) scale(.5)}html{transition:color .3s ease,background-color .3s ease}.term-wrap{visibility:hidden;position:absolute;overflow:hidden;top:4px;left:4px;right:4px;bottom:0}.term-wrap.active{visibility:visible}.term-wrap .xterm{height:100%}.save-indicator{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;border:1px solid var(--color-search-text);margin-right:4px;opacity:.35;transition:opacity .4s ease}.save-indicator.saved{opacity:.5}.save-indicator .save-tick{color:var(--color-time-recent);display:block}.save-indicator .save-spin{display:none;color:var(--color-dim);animation:save-rotate 1.5s cubic-bezier(.4,0,.2,1) infinite}.save-indicator.saving .save-tick{display:none}.save-indicator.saving .save-spin{display:block}.save-indicator.saving{opacity:.5}@keyframes save-rotate{to{transform:rotate(1turn)}}.tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.5)}.light .tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.25),0 0 0 1px rgba(0,0,0,.05)}.drop-highlight{border-radius:.25rem;background-color:rgba(59,130,246,.1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(59,130,246,.3)}.project-drop-line{height:2px;margin:.125rem .5rem;border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.plugin-chevron.collapsed,.project-chevron.collapsed svg{transform:rotate(-90deg)}.tmx-scroll{scrollbar-width:thin;scrollbar-color:transparent transparent}.tmx-scroll::-webkit-scrollbar{width:10px}.tmx-scroll::-webkit-scrollbar-track{background:transparent}.tmx-scroll::-webkit-scrollbar-thumb{background:transparent;border:2px solid transparent;border-radius:9999px;-webkit-transition:background-color .2s ease,border-color .2s ease;transition:background-color .2s ease,border-color .2s ease}.tmx-scroll.is-scrolling,.tmx-scroll:hover{scrollbar-color:color-mix(in srgb,var(--color-muted) 78%,transparent) color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-track,.tmx-scroll:hover::-webkit-scrollbar-track{background:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb,.tmx-scroll:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--color-muted) 78%,transparent);border-color:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb:hover,.tmx-scroll:hover::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--color-subtle) 85%,transparent)}.prompt-autocomplete{position:fixed;width:340px;background:var(--color-raised);border:1px solid var(--color-muted);border-radius:10px;box-shadow:0 20px 40px -8px rgba(0,0,0,.5);z-index:100;display:flex;flex-direction:column;overflow:hidden;animation:pa-in .15s ease}@keyframes pa-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.pa-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent)}.pa-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-subtle)}.pa-query{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--color-dim);background:color-mix(in srgb,var(--color-muted) 40%,transparent);padding:2px 6px;border-radius:4px}.pa-list{overflow-y:auto;padding:4px;max-height:184px}.pa-item{padding:8px 10px;border-radius:6px;cursor:pointer;transition:background-color .1s}.pa-item:hover,.pa-selected{background:color-mix(in srgb,var(--color-muted) 40%,transparent)}.pa-name{font-size:13px;font-weight:500;color:var(--color-text)}.pa-name,.pa-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pa-text{font-size:11px;color:var(--color-subtle);margin-top:2px}.pa-item mark{background:rgba(59,130,246,.25);color:inherit;border-radius:2px;padding:0 1px}.pa-footer{display:flex;gap:12px;justify-content:center;padding:6px 12px;border-top:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent);font-size:10px;color:var(--color-subtle)}.pa-footer kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;padding:1px 4px;border-radius:3px;background:color-mix(in srgb,var(--color-muted) 50%,transparent);color:var(--color-dim)}.pa-empty{padding:20px 12px;text-align:center;font-size:13px;color:var(--color-subtle)}.pa-hint{padding:0 12px 12px;text-align:center;font-size:11px;color:var(--color-border)}.pa-hint kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:color-mix(in srgb,var(--color-muted) 50%,transparent);padding:1px 4px;border-radius:3px}.empty\:hidden:empty{display:none}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-slate-500:hover{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity,1))}.hover\:bg-amber-500\/20:hover{background-color:rgba(245,158,11,.2)}.hover\:bg-blue-500:hover{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.hover\:bg-blue-500\/20:hover{background-color:rgba(59,130,246,.2)}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:bg-rose-500\/20:hover{background-color:rgba(244,63,94,.2)}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-700\/50:hover{background-color:rgba(51,65,85,.5)}.hover\:bg-slate-700\/60:hover{background-color:rgba(51,65,85,.6)}.hover\:bg-slate-700\/70:hover{background-color:rgba(51,65,85,.7)}.hover\:bg-slate-800\/30:hover{background-color:rgba(30,41,59,.3)}.hover\:bg-slate-800\/40:hover{background-color:rgba(30,41,59,.4)}.hover\:bg-slate-800\/50:hover{background-color:rgba(30,41,59,.5)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\:text-emerald-300:hover{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.hover\:text-emerald-400:hover{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.hover\:text-indigo-400:hover{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-rose-300:hover{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.hover\:text-slate-200:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.hover\:text-slate-300:hover{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.hover\:ring-2:hover{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:ring-slate-500:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(100 116 139/var(--tw-ring-opacity,1))}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:border-slate-600\/60:focus{border-color:rgba(71,85,105,.6)}.focus\:bg-slate-800\/80:focus{background-color:rgba(30,41,59,.8)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:rgba(59,130,246,.3)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-600:disabled{--tw-bg-opacity:1;background-color:rgb(71 85 105/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100{opacity:1}
|
package/sessions.js
CHANGED
|
@@ -447,9 +447,15 @@ function sendBuffers(ws) {
|
|
|
447
447
|
for (const [id, s] of sessions) {
|
|
448
448
|
if (['claude-code', 'codex', 'gemini-cli', 'opencode'].includes(s.presetId) && !s.working) {
|
|
449
449
|
const text = transcript.getReplayText(id, s.presetId);
|
|
450
|
-
if (text) {
|
|
450
|
+
if (text) {
|
|
451
|
+
ws.send(JSON.stringify({ type: 'session.history', id, text, replay: true }));
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (s.chunks.length) {
|
|
456
|
+
const data = s.chunks.join('');
|
|
457
|
+
ws.send(JSON.stringify({ type: 'output', id, data, replay: true }));
|
|
451
458
|
}
|
|
452
|
-
if (s.chunks.length) ws.send(JSON.stringify({ type: 'output', id, data: s.chunks.join('') }));
|
|
453
459
|
}
|
|
454
460
|
}
|
|
455
461
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Awesome Lists — Submission Log
|
|
2
|
+
|
|
3
|
+
## Merged
|
|
4
|
+
|
|
5
|
+
| Repo | Stars | Section | Link | Date |
|
|
6
|
+
|------|-------|---------|------|------|
|
|
7
|
+
| Piebald-AI/awesome-gemini-cli | 387 | Agent Orchestration & CLI Tools | [PR #33](https://github.com/Piebald-AI/awesome-gemini-cli/pull/33) | 2026-04-05 |
|
|
8
|
+
| ai-for-developers/awesome-ai-coding-tools | 1.6k | Shell & CLI Assistants | [PR #202](https://github.com/ai-for-developers/awesome-ai-coding-tools/pull/202) | 2026-04-07 |
|
|
9
|
+
|
|
10
|
+
## Open
|
|
11
|
+
|
|
12
|
+
| Repo | Stars | Section | Link | Date |
|
|
13
|
+
|------|-------|---------|------|------|
|
|
14
|
+
| e2b-dev/awesome-ai-agents | 27k | Open-source projects (alphabetical) | [PR #685](https://github.com/e2b-dev/awesome-ai-agents/pull/685) | 2026-04-05 |
|
|
15
|
+
| mahseema/awesome-ai-tools | 4.7k | Code | [PR #1027](https://github.com/mahseema/awesome-ai-tools/pull/1027) | 2026-04-05 |
|
|
16
|
+
| Jenqyang/Awesome-AI-Agents | 1k | Tools | [PR #143](https://github.com/Jenqyang/Awesome-AI-Agents/pull/143) | 2026-04-05 |
|
|
17
|
+
| rohitg00/awesome-claude-code-toolkit | 1k | Companion Apps & GUIs | [PR #211](https://github.com/rohitg00/awesome-claude-code-toolkit/pull/211) | 2026-04-05 |
|
|
18
|
+
| andyrewlee/awesome-agent-orchestrators | 185 | Parallel Agent Runners | [PR #27](https://github.com/andyrewlee/awesome-agent-orchestrators/pull/27) | 2026-04-06 |
|
|
19
|
+
| bradAGI/awesome-cli-coding-agents | 121 | Session managers & parallel runners | [PR #39](https://github.com/bradAGI/awesome-cli-coding-agents/pull/39) | 2026-04-06 |
|
|
20
|
+
| webfuse-com/awesome-claude | 1.3k | Applications > Desktop | [PR #166](https://github.com/webfuse-com/awesome-claude/pull/166) | 2026-04-06 |
|
|
21
|
+
| ikaijua/Awesome-AITools | 5.8k | AI Agent | [PR #431](https://github.com/ikaijua/Awesome-AITools/pull/431) | 2026-04-06 |
|
|
22
|
+
|
|
23
|
+
## Rejected
|
|
24
|
+
|
|
25
|
+
| Repo | Stars | Reason | Link | Date |
|
|
26
|
+
|------|-------|--------|------|------|
|
|
27
|
+
| kyrolabs/awesome-agents | 2.1k | Auto-rejected: brand new repo | [PR #331](https://github.com/kyrolabs/awesome-agents/pull/331) | 2026-04-05 |
|
|
28
|
+
| hesreallyhim/awesome-claude-code | 36.3k | Used gh CLI, requires web form only | [Issue #1366](https://github.com/hesreallyhim/awesome-claude-code/issues/1366) | 2026-04-05 |
|
|
29
|
+
|
|
30
|
+
## Parked (retry later)
|
|
31
|
+
|
|
32
|
+
| Repo | Stars | Requirement | Retry when |
|
|
33
|
+
|------|-------|-------------|------------|
|
|
34
|
+
| hesreallyhim/awesome-claude-code | 36.3k | Web form only, 7-day cooldown | April 12 — submit via [web form](https://github.com/hesreallyhim/awesome-claude-code/issues/new?template=recommend-resource.yml), category: Alternative Clients > General |
|
|
35
|
+
| agarrharr/awesome-cli-apps | 19.2k | 90 days old + 20 stars | After June 1 |
|
|
36
|
+
| alvinunreal/awesome-opensource-ai | 2.3k | 100+ stars for EMERGING.md | When we hit 100 stars |
|
|
37
|
+
| kyrolabs/awesome-agents | 2.1k | Needs repo traction | When we hit ~200 stars |
|
|
38
|
+
|
|
39
|
+
## Skipped
|
|
40
|
+
|
|
41
|
+
| Repo | Stars | Reason |
|
|
42
|
+
|------|-------|--------|
|
|
43
|
+
| sourcegraph/awesome-code-ai | 1.6k | Archived |
|
|
44
|
+
| agamm/awesome-developer-first | 1.6k | Paid products only |
|
|
45
|
+
| slavakurilyak/awesome-ai-agents | 1.3k | YAML data format, complex, lower ROI |
|
|
46
|
+
| VoltAgent/awesome-agent-skills | 14k | Skills list, not tools |
|
|
47
|
+
| heilcheng/awesome-agent-skills | 3.6k | Skills list, not tools |
|
|
48
|
+
| Shubhamsaboo/awesome-llm-apps | 104.6k | LLM app tutorials, not tools — wrong fit |
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: awesome-lists
|
|
3
|
+
description: Publish our open source repo in GitHub awesome lists. Search for relevant lists, evaluate them, craft entries matching each list's format, and submit PRs/issues.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Publish to GitHub Awesome Lists
|
|
7
|
+
|
|
8
|
+
Get our repo listed in popular GitHub awesome lists to drive organic discovery.
|
|
9
|
+
|
|
10
|
+
## Step 1: Craft the entry message
|
|
11
|
+
|
|
12
|
+
Before searching for lists, decide what to say. Read our README.md carefully — match its tone exactly (lowercase, direct, Karpathy-style, no marketing language).
|
|
13
|
+
|
|
14
|
+
Write three versions of the entry description:
|
|
15
|
+
- **Long** (~2 sentences) — for lists that allow detailed entries
|
|
16
|
+
- **Medium** (~1 sentence) — for standard lists
|
|
17
|
+
- **Short** (under 15 words) — for tight table formats
|
|
18
|
+
|
|
19
|
+
Rules:
|
|
20
|
+
- No "your" — it's a marketing trap
|
|
21
|
+
- No adjectives like "powerful", "seamless", "cutting-edge", "revolutionary"
|
|
22
|
+
- Lead with what it looks like to use (e.g. "WhatsApp-like interface") — concrete references everyone understands
|
|
23
|
+
- Highlight the three differentiators: chat-style multi-agent UI, autopilot routing while afk, mobile remote
|
|
24
|
+
- State what it does, not what it "enables" or "empowers"
|
|
25
|
+
|
|
26
|
+
Show the drafts to the user for approval before proceeding.
|
|
27
|
+
|
|
28
|
+
## Step 2: Search for awesome lists
|
|
29
|
+
|
|
30
|
+
Use the internal search tool to find candidate lists:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
(cd /Users/rusty/Projects/temp/gpt-oss-20b-MXFP4-Q8 && npm run search:cli -- '{"queries":[
|
|
34
|
+
"awesome AI coding agents CLI tools github list site:github.com",
|
|
35
|
+
"awesome AI development tools terminal agents github site:github.com",
|
|
36
|
+
"awesome list claude code codex gemini CLI agents site:github.com",
|
|
37
|
+
"awesome open source AI tools agents frameworks github site:github.com",
|
|
38
|
+
"awesome AI code assistants IDE tools github list site:github.com",
|
|
39
|
+
"awesome terminal tools developer productivity AI github site:github.com",
|
|
40
|
+
"awesome AI agents autonomous coding tools curated list site:github.com"
|
|
41
|
+
]}')
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
You can send up to 7 queries at once. Results arrive as JSON with `results[].items[].link` and `.title`.
|
|
45
|
+
|
|
46
|
+
Extract unique GitHub repo URLs from results.
|
|
47
|
+
|
|
48
|
+
## Step 3: Evaluate candidates
|
|
49
|
+
|
|
50
|
+
For each repo found, get the star count:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
gh api "repos/OWNER/REPO" --jq '.stargazers_count'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Run this in a batch for all candidates. Sort by stars descending.
|
|
57
|
+
|
|
58
|
+
**Drop immediately:**
|
|
59
|
+
- Archived repos
|
|
60
|
+
- Repos requiring paid products only
|
|
61
|
+
- Repos that are skill/SKILL.md lists (not tool lists) — unless we have a matching skill to submit
|
|
62
|
+
- Repos where we don't meet minimum star/age requirements
|
|
63
|
+
|
|
64
|
+
**Check our repo stats too:**
|
|
65
|
+
```bash
|
|
66
|
+
gh api repos/rustykuntz/clideck --jq '{stars: .stargazers_count, created: .created_at}'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Compare against each list's requirements (some need 20+ stars, 90+ days, 100+ stars, etc).
|
|
70
|
+
|
|
71
|
+
## Step 4: Read contributing rules for each target
|
|
72
|
+
|
|
73
|
+
For every list we plan to submit to, fetch and read:
|
|
74
|
+
1. `CONTRIBUTING.md` (try main branch, then master)
|
|
75
|
+
2. `.github/PULL_REQUEST_TEMPLATE.md`
|
|
76
|
+
3. The README itself — check the entry format by looking at 2-3 existing entries near where ours would go
|
|
77
|
+
|
|
78
|
+
**Pay attention to:**
|
|
79
|
+
- Submission method: PR vs issue form vs Google Form (some ban PRs — e.g. awesome-claude-code uses issue forms only, PRs = ban)
|
|
80
|
+
- **CLI vs web-only**: some repos (e.g. hesreallyhim/awesome-claude-code) explicitly ban `gh` CLI submissions and require the GitHub web UI form. Check issue templates for "does not allow resource submissions via the `gh` CLI" language. These must be submitted by the user manually — prepare the form field values and hand them over.
|
|
81
|
+
- Entry format: plain markdown list, table rows, HTML details blocks — match exactly
|
|
82
|
+
- Ordering: alphabetical vs bottom-of-section
|
|
83
|
+
- Required elements: stars badges, specific badge styles, checklist items
|
|
84
|
+
- Star/age minimums
|
|
85
|
+
- PR title format (some require exact patterns like "Add APP_NAME")
|
|
86
|
+
- Whether they use data files (YAML/JSON) instead of README edits
|
|
87
|
+
- Auto-reject rules: some repos auto-close PRs from new repos with low stars/short history (e.g. kyrolabs/awesome-agents). Don't submit if we clearly don't meet the bar — it looks bad.
|
|
88
|
+
|
|
89
|
+
**Build a table for the user** summarizing each target: repo, stars, section, format, submission method, blockers.
|
|
90
|
+
|
|
91
|
+
## Step 5: Fork and submit
|
|
92
|
+
|
|
93
|
+
For each target repo:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Fork
|
|
97
|
+
gh repo fork OWNER/REPO --clone=false
|
|
98
|
+
|
|
99
|
+
# Sync fork
|
|
100
|
+
gh repo sync rustykuntz/FORK
|
|
101
|
+
|
|
102
|
+
# Create branch
|
|
103
|
+
SHA=$(gh api repos/rustykuntz/FORK/git/ref/heads/main --jq '.object.sha')
|
|
104
|
+
gh api repos/rustykuntz/FORK/git/refs -f ref=refs/heads/add-clideck -f sha="$SHA"
|
|
105
|
+
|
|
106
|
+
# Get file content and SHA
|
|
107
|
+
gh api -X GET repos/rustykuntz/FORK/contents/README.md --field ref=add-clideck --jq '.sha'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
To edit and upload via API (avoids cloning):
|
|
111
|
+
|
|
112
|
+
1. Download the file content
|
|
113
|
+
2. Insert our entry at the correct position (use python3 for multiline insertions — awk/sed break on complex entries)
|
|
114
|
+
3. Base64 encode the updated content
|
|
115
|
+
4. Push via Contents API:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
gh api repos/rustykuntz/FORK/contents/README.md \
|
|
119
|
+
-X PUT \
|
|
120
|
+
-f message="Add clideck to SECTION_NAME" \
|
|
121
|
+
-f content="$ENCODED" \
|
|
122
|
+
-f sha="$FILE_SHA" \
|
|
123
|
+
-f branch=add-clideck
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
5. **Always verify** the edit before creating the PR:
|
|
127
|
+
```bash
|
|
128
|
+
gh api -X GET repos/rustykuntz/FORK/contents/README.md --field ref=add-clideck --jq '.content' | base64 -d | grep -B2 -A2 "clideck"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
6. Create PR matching the repo's requirements:
|
|
132
|
+
```bash
|
|
133
|
+
gh pr create --repo OWNER/REPO \
|
|
134
|
+
--head rustykuntz:add-clideck \
|
|
135
|
+
--title "TITLE MATCHING THEIR FORMAT" \
|
|
136
|
+
--body "BODY WITH THEIR CHECKLIST/TEMPLATE"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For issue-based submissions (like awesome-claude-code):
|
|
140
|
+
```bash
|
|
141
|
+
gh issue create --repo OWNER/REPO --title "TITLE" --body "BODY"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Step 6: Track results
|
|
145
|
+
|
|
146
|
+
Print a final summary table with all submissions: repo, stars, type (PR/issue), link, and any blockers.
|
|
147
|
+
|
|
148
|
+
Note any lists that are parked (we don't meet requirements yet) with the specific threshold we need to hit and when to retry.
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: research-experiment
|
|
3
|
+
description: Coordinate autonomous research experiments across multiple coding agents using isolated git worktrees. Use when a user wants the main agent to define a goal, constraints, acceptance criteria, and experiment boundaries, then dispatch Codex/Claude/Gemini or other agents to independently search for solutions without touching production code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Research Experiment
|
|
7
|
+
|
|
8
|
+
Use this skill to run parallel, autonomous experiments safely.
|
|
9
|
+
|
|
10
|
+
There are two roles:
|
|
11
|
+
|
|
12
|
+
- Main Agent: owns the research brief, workspace setup, researcher prompts, verification, and merge decision.
|
|
13
|
+
- Experiment Agent: owns independent exploration inside one assigned worktree and must not redefine the experiment.
|
|
14
|
+
|
|
15
|
+
If the user says "you are the main agent", follow the Main Agent Role. If the user says "you are an experiment agent" or "researcher agent", follow the Experiment Agent Role.
|
|
16
|
+
|
|
17
|
+
## Main Agent Role
|
|
18
|
+
|
|
19
|
+
The main agent defines the experiment and coordinates researchers. It must not let each researcher invent different goals or acceptance criteria.
|
|
20
|
+
|
|
21
|
+
## Main Agent Workflow
|
|
22
|
+
|
|
23
|
+
1. Convert the user request into an experiment brief:
|
|
24
|
+
- Goal: the outcome to achieve.
|
|
25
|
+
- Acceptance criteria: exact tests, benchmarks, or review gates.
|
|
26
|
+
- Hard constraints: what must not change.
|
|
27
|
+
- Quality bar: what counts as meaningful progress versus noise.
|
|
28
|
+
- Shared resources: ports, GPUs, model caches, services, datasets, credentials, or external APIs.
|
|
29
|
+
- Stop conditions: when researchers may quit.
|
|
30
|
+
|
|
31
|
+
2. Identify the production repository root:
|
|
32
|
+
- Use `git rev-parse --show-toplevel` when inside a git repo.
|
|
33
|
+
- If the project has nested repos, identify which repo owns the files under experiment.
|
|
34
|
+
- Do not assume the current working directory is the repo root.
|
|
35
|
+
|
|
36
|
+
3. Create per-researcher worktrees inside the project folder, not beside it:
|
|
37
|
+
- Prefer a project-local directory such as `<project>/.research-worktrees/<slug>-<n>`.
|
|
38
|
+
- Keep worktree directories inside the main project folder so agents do not need extra filesystem permissions.
|
|
39
|
+
- Do not create sibling worktrees such as `../project_research_1` unless the user explicitly asks.
|
|
40
|
+
- Never point a researcher at the production checkout for edits.
|
|
41
|
+
- Use unique branches, for example `research/<slug>-1`, `research/<slug>-2`.
|
|
42
|
+
|
|
43
|
+
4. Give every researcher the same goal and rules:
|
|
44
|
+
- Do not assign fixed technical roles unless the user explicitly asks.
|
|
45
|
+
- Let each researcher decide the approach and iterate independently.
|
|
46
|
+
- Include the exact worktree path, branch, allowed edit scope, forbidden files, verification commands, and report format.
|
|
47
|
+
- Save the canonical brief to the experiment folder before dispatching researchers.
|
|
48
|
+
|
|
49
|
+
5. Verify centrally:
|
|
50
|
+
- Researchers may run local checks in their worktree, but the main agent owns authoritative acceptance verification.
|
|
51
|
+
- If benchmarks contend for scarce resources, run final benchmarks sequentially from the main agent.
|
|
52
|
+
- Merge nothing unless it passes acceptance criteria and clears the quality bar.
|
|
53
|
+
|
|
54
|
+
## Experiment Folder
|
|
55
|
+
|
|
56
|
+
The main agent should create one experiment folder under the main project, for example:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
.research-worktrees/<experiment-slug>/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Inside it, create:
|
|
63
|
+
|
|
64
|
+
- `EXPERIMENT.md`: the canonical brief, baseline, quality gate, constraints, assignments, commands, and report format.
|
|
65
|
+
- `<slug>-experiment-1/`: worktree for researcher 1.
|
|
66
|
+
- `<slug>-experiment-2/`: worktree for researcher 2.
|
|
67
|
+
- `<slug>-experiment-3/`: worktree for researcher 3.
|
|
68
|
+
- `<slug>-experiment-1/LOG.md`: progress log for researcher 1.
|
|
69
|
+
- `<slug>-experiment-2/LOG.md`: progress log for researcher 2.
|
|
70
|
+
- `<slug>-experiment-3/LOG.md`: progress log for researcher 3.
|
|
71
|
+
|
|
72
|
+
Researcher prompts should tell agents to read `EXPERIMENT.md` first and then follow only their assigned workspace, branch, log file, and resource values.
|
|
73
|
+
|
|
74
|
+
The main agent may check each researcher log during the experiment to monitor progress without interrupting researchers. Researcher agents should append concise entries after each meaningful experiment loop:
|
|
75
|
+
|
|
76
|
+
- Hypothesis tried.
|
|
77
|
+
- Files changed.
|
|
78
|
+
- Command run.
|
|
79
|
+
- Result versus same-session baseline.
|
|
80
|
+
- Keep/reject decision.
|
|
81
|
+
- Current blocker, if any.
|
|
82
|
+
|
|
83
|
+
## Worktree Setup
|
|
84
|
+
|
|
85
|
+
Use project-local worktrees. The worktree directory must live under the main project folder:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
mkdir -p .research-worktrees
|
|
89
|
+
mkdir -p .research-worktrees/<experiment-slug>
|
|
90
|
+
git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-1 -b research/<slug>-1
|
|
91
|
+
git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-2 -b research/<slug>-2
|
|
92
|
+
git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-3 -b research/<slug>-3
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If a branch already exists, choose a new suffix. Do not delete or overwrite existing worktrees unless the user explicitly asks.
|
|
96
|
+
|
|
97
|
+
When the target files live in a nested repo, run the worktree commands from that nested repo root but still put the worktree folders under the main project folder. Example:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd path/to/nested/repo
|
|
101
|
+
mkdir -p /absolute/path/to/main-project/.research-worktrees
|
|
102
|
+
mkdir -p /absolute/path/to/main-project/.research-worktrees/<experiment-slug>
|
|
103
|
+
git worktree add /absolute/path/to/main-project/.research-worktrees/<experiment-slug>/<slug>-experiment-1 -b research/<slug>-1
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Baseline And Quality Gate
|
|
107
|
+
|
|
108
|
+
Before changing code, each researcher must run the exact benchmark or check command once from their assigned worktree and record it as their same-session baseline.
|
|
109
|
+
|
|
110
|
+
Compare final results against:
|
|
111
|
+
|
|
112
|
+
- The user/main-agent supplied baseline.
|
|
113
|
+
- The researcher’s same-session baseline.
|
|
114
|
+
|
|
115
|
+
The main agent/user defines the quality gate for each experiment. Examples:
|
|
116
|
+
|
|
117
|
+
- Test suite must pass.
|
|
118
|
+
- Benchmark score must not regress.
|
|
119
|
+
- ASR must recover at least N words from generated TTS.
|
|
120
|
+
- Human listening check required.
|
|
121
|
+
|
|
122
|
+
Do not invent or weaken the quality gate. If the gate is unclear, ask the main agent before accepting a result.
|
|
123
|
+
|
|
124
|
+
## Experiment Agent Role
|
|
125
|
+
|
|
126
|
+
The experiment agent executes the fixed brief from the main agent. It uses this skill for discipline and workflow only.
|
|
127
|
+
|
|
128
|
+
Follow only your assigned researcher section from the experiment brief. Do not edit outside your assigned worktree.
|
|
129
|
+
Create any temporary files, profiling scripts, generated outputs, scratch notes, and helper artifacts inside your assigned worktree. Do not use `/tmp`, `/var/tmp`, home-directory scratch folders, or sibling project folders unless the brief explicitly allows it.
|
|
130
|
+
|
|
131
|
+
The experiment agent must not redefine:
|
|
132
|
+
|
|
133
|
+
- Goal.
|
|
134
|
+
- Constraints.
|
|
135
|
+
- Quality gate.
|
|
136
|
+
- Benchmark commands.
|
|
137
|
+
- Acceptance criteria.
|
|
138
|
+
- Assigned workspace or branch.
|
|
139
|
+
|
|
140
|
+
If any of those are missing or ambiguous, ask the main agent for clarification before accepting a result. Do not make up a weaker gate.
|
|
141
|
+
|
|
142
|
+
## Experiment Agent Autonomy
|
|
143
|
+
|
|
144
|
+
DO NOT STOP EXPERIMENTING UNLESS YOU ACHIEVED THE GOALS OR ABSOLUTELY NECESSARY.
|
|
145
|
+
|
|
146
|
+
- Do NOT ask the user if you should continue.
|
|
147
|
+
- The user may be away from the computer and expects the experiment to continue until you achieve the experiment goals, so keep working until the task is naturally complete.
|
|
148
|
+
- You are autonomous. If you are unsure how to proceed, re-read the skill, goals, context, think differently, try different innovative approaches, and continue.
|
|
149
|
+
- Stop only if something out of your control blocks you from continuing. Otherwise continue experimenting until goals are achieved or the useful paths are exhausted.
|
|
150
|
+
|
|
151
|
+
## Researcher Prompt Template
|
|
152
|
+
|
|
153
|
+
Include this block, or an equivalent adapted version, in every researcher prompt:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
You are an autonomous research agent for this experiment.
|
|
157
|
+
|
|
158
|
+
Goal:
|
|
159
|
+
<goal>
|
|
160
|
+
|
|
161
|
+
Experiment rules and boundaries:
|
|
162
|
+
<rules>
|
|
163
|
+
|
|
164
|
+
Assigned workspace:
|
|
165
|
+
<absolute path to your worktree>
|
|
166
|
+
|
|
167
|
+
Canonical experiment brief:
|
|
168
|
+
<absolute path to EXPERIMENT.md>
|
|
169
|
+
|
|
170
|
+
Assigned experiment log:
|
|
171
|
+
<absolute path to your LOG.md>
|
|
172
|
+
|
|
173
|
+
You must work only inside your assigned worktree unless the brief explicitly allows another path. Do not edit, overwrite, or revert files in the production checkout. Do not change benchmark scoring, test fixtures, or acceptance criteria unless the brief explicitly asks for that.
|
|
174
|
+
Read the canonical experiment brief before making changes. Follow only your assigned researcher section. Do not redefine the goal, constraints, quality gate, benchmark commands, acceptance criteria, workspace, branch, port, log path, or resource assignments. Do not edit outside your assigned worktree.
|
|
175
|
+
If you need temp folders, profiling scripts, scratch files, benchmark outputs, or helper artifacts, create them inside your assigned worktree. Do not use `/tmp`, `/var/tmp`, home-directory scratch folders, or sibling project folders unless the brief explicitly allows it.
|
|
176
|
+
|
|
177
|
+
DO NOT STOP EXPERIMENTING UNLESS YOU ACHIEVED THE GOALS OR ABSOLUTELY NECESSARY.
|
|
178
|
+
- Do NOT ask the user if you should continue.
|
|
179
|
+
- The user may be away from the computer and expects the experiment to continue until you achieve the experiment goals, so keep working until the task is naturally complete.
|
|
180
|
+
- You are autonomous. If you are unsure how to proceed, re-read the skill, goals, context, think differently, try different innovative approaches, and continue.
|
|
181
|
+
- Stop only if something out of your control blocks you from continuing. Otherwise continue experimenting until goals are achieved or useful paths are exhausted.
|
|
182
|
+
|
|
183
|
+
Loop:
|
|
184
|
+
1. Inspect the code and constraints.
|
|
185
|
+
2. Form hypotheses.
|
|
186
|
+
3. Try a small, explainable experiment.
|
|
187
|
+
4. Run relevant verification.
|
|
188
|
+
5. Keep, revise, or reject the attempt.
|
|
189
|
+
6. Repeat until the goal is achieved, useful paths are exhausted, or an external blocker prevents progress.
|
|
190
|
+
|
|
191
|
+
Report format:
|
|
192
|
+
- Worktree path and branch.
|
|
193
|
+
- Changed files.
|
|
194
|
+
- Commands run and exact relevant output.
|
|
195
|
+
- Results against acceptance criteria.
|
|
196
|
+
- Failed attempts and why they were rejected.
|
|
197
|
+
- Whether you recommend merging the patch.
|
|
198
|
+
- Any cleanup needed: running servers, ports, PIDs, temp files.
|
|
199
|
+
|
|
200
|
+
Also append concise progress entries to your assigned experiment log after each meaningful experiment loop.
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Shared Resource Rules
|
|
204
|
+
|
|
205
|
+
For resources that can contaminate results or conflict across agents:
|
|
206
|
+
|
|
207
|
+
- Assign unique ports, output directories, cache directories, and branch names.
|
|
208
|
+
- Do not run final GPU/MPS benchmarks concurrently across researchers.
|
|
209
|
+
- Prefer researcher-local smoke tests and main-agent final benchmarks.
|
|
210
|
+
- Require researchers to stop servers they started, or report any still-running process clearly.
|
|
211
|
+
|
|
212
|
+
## Merge Rules
|
|
213
|
+
|
|
214
|
+
The main agent must review researcher diffs before applying them to production.
|
|
215
|
+
|
|
216
|
+
Reject or keep separate any patch that:
|
|
217
|
+
|
|
218
|
+
- Touches production checkout files.
|
|
219
|
+
- Changes tests, benchmarks, fixtures, sample inputs, or scoring without permission.
|
|
220
|
+
- Passes only because the acceptance criteria were weakened.
|
|
221
|
+
- Produces only noisy or marginal improvement below the declared quality bar.
|
|
222
|
+
- Leaves unexplained background processes or shared state.
|
|
223
|
+
|
|
224
|
+
If a researcher accidentally edits the production checkout, preserve pre-existing user changes and move or recreate the experiment in an isolated worktree before continuing.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Research Experiment"
|
|
3
|
+
short_description: "Run parallel autonomous experiments in isolated git worktrees."
|
|
4
|
+
default_prompt: "Use this skill to prepare and coordinate autonomous research agents that experiment in isolated git worktrees without touching production code."
|
package/telemetry-receiver.js
CHANGED
|
@@ -10,9 +10,42 @@ const codexMenuPoll = new Map(); // sessionId → interval (polling for menu aft
|
|
|
10
10
|
const codexPendingStop = new Map(); // sessionId → ts (notify hook arrived; wait for next response.completed)
|
|
11
11
|
const codexOutputDone = new Map(); // sessionId → ts (fallback if notify never fires)
|
|
12
12
|
const codexPendingIdle = new Map(); // sessionId → timer (tiny settle before committing idle)
|
|
13
|
+
const codexToolPhasePending = new Set(); // sessionId set once Codex has announced a tool-call phase, cleared when the phase resolves
|
|
14
|
+
const codexPendingTools = new Map(); // sessionId → Set(callId) for approved Codex tool calls still awaiting a result
|
|
13
15
|
let broadcastFn = null;
|
|
14
16
|
let sessionsFn = null;
|
|
15
17
|
|
|
18
|
+
function getPendingToolSet(id) {
|
|
19
|
+
let set = codexPendingTools.get(id);
|
|
20
|
+
if (!set) { set = new Set(); codexPendingTools.set(id, set); }
|
|
21
|
+
return set;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function clearPendingTools(id) {
|
|
25
|
+
codexPendingTools.delete(id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function addPendingTool(id, callId) {
|
|
29
|
+
if (!callId) return;
|
|
30
|
+
getPendingToolSet(id).add(callId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolvePendingTool(id, callId) {
|
|
34
|
+
if (!callId) return;
|
|
35
|
+
const set = codexPendingTools.get(id);
|
|
36
|
+
if (!set) return;
|
|
37
|
+
set.delete(callId);
|
|
38
|
+
if (!set.size) codexPendingTools.delete(id);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasPendingTools(id) {
|
|
42
|
+
return !!codexPendingTools.get(id)?.size;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hasPendingToolState(id) {
|
|
46
|
+
return codexToolPhasePending.has(id) || hasPendingTools(id);
|
|
47
|
+
}
|
|
48
|
+
|
|
16
49
|
function init(broadcast, getSessions) {
|
|
17
50
|
broadcastFn = broadcast;
|
|
18
51
|
sessionsFn = getSessions;
|
|
@@ -77,11 +110,8 @@ function handleLogs(req, res) {
|
|
|
77
110
|
// Debug telemetry logs — uncomment as needed, do not delete
|
|
78
111
|
// if (serviceName === 'claude-code' && eventName) console.log(`[telemetry:claude] ${eventName}`);
|
|
79
112
|
// if (serviceName === 'codex_cli_rs' && eventName) {
|
|
80
|
-
// const
|
|
81
|
-
//
|
|
82
|
-
// .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
83
|
-
// .join(' ');
|
|
84
|
-
// console.log(`[telemetry:codex] ${eventName} session=${resolvedId.slice(0,8)}${details ? ' ' + details : ''}`);
|
|
113
|
+
// const kind = attrs['event.kind'] ? ` kind=${attrs['event.kind']}` : '';
|
|
114
|
+
// console.log(`[telemetry:codex] ${eventName}${kind} session=${resolvedId.slice(0,8)}`);
|
|
85
115
|
// }
|
|
86
116
|
// if (serviceName === 'gemini-cli' && eventName) console.log(`[telemetry:gemini] ${eventName}`);
|
|
87
117
|
|
|
@@ -100,9 +130,18 @@ function handleLogs(req, res) {
|
|
|
100
130
|
if (eventName === 'codex.user_prompt') {
|
|
101
131
|
codexPendingStop.delete(resolvedId);
|
|
102
132
|
codexOutputDone.delete(resolvedId);
|
|
133
|
+
codexToolPhasePending.delete(resolvedId);
|
|
134
|
+
clearPendingTools(resolvedId);
|
|
103
135
|
broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
|
|
104
136
|
}
|
|
105
137
|
|
|
138
|
+
// Codex can announce a function-call phase before the later tool_decision
|
|
139
|
+
// event carries a call_id. Block idle as soon as the tool phase is known,
|
|
140
|
+
// then refine it to call-specific tracking when tool_decision arrives.
|
|
141
|
+
if (eventName === 'codex.websocket_event' && attrs['event.kind'] === 'response.function_call_arguments.done') {
|
|
142
|
+
codexToolPhasePending.add(resolvedId);
|
|
143
|
+
}
|
|
144
|
+
|
|
106
145
|
// Fallback: when notify does not fire, require an output item to finish
|
|
107
146
|
// before treating the next response.completed as a real end-of-turn.
|
|
108
147
|
if (eventName === 'codex.websocket_event' && attrs['event.kind'] === 'response.output_item.done') {
|
|
@@ -113,7 +152,10 @@ function handleLogs(req, res) {
|
|
|
113
152
|
// Also poll briefly for a visible choice menu.
|
|
114
153
|
if (eventName === 'codex.sse_event' && attrs['event.kind'] === 'response.completed') {
|
|
115
154
|
const pendingStopAt = codexPendingStop.get(resolvedId);
|
|
116
|
-
if (
|
|
155
|
+
if (hasPendingToolState(resolvedId)) {
|
|
156
|
+
// Tool execution is still in-flight; this completion only closed the
|
|
157
|
+
// function-call phase, not the user's full turn.
|
|
158
|
+
} else if (pendingStopAt && Date.now() - pendingStopAt <= 5000) {
|
|
117
159
|
// console.log(`[codex] complete matched pending-stop session=${resolvedId.slice(0,8)} age=${Date.now() - pendingStopAt}ms`);
|
|
118
160
|
codexPendingStop.delete(resolvedId);
|
|
119
161
|
codexOutputDone.delete(resolvedId);
|
|
@@ -134,9 +176,18 @@ function handleLogs(req, res) {
|
|
|
134
176
|
if (eventName === 'codex.tool_decision') {
|
|
135
177
|
codexPendingStop.delete(resolvedId);
|
|
136
178
|
codexOutputDone.delete(resolvedId);
|
|
179
|
+
if ((attrs.decision || '').toLowerCase() !== 'denied') {
|
|
180
|
+
addPendingTool(resolvedId, attrs.call_id || attrs['call.id']);
|
|
181
|
+
} else {
|
|
182
|
+
codexToolPhasePending.delete(resolvedId);
|
|
183
|
+
}
|
|
137
184
|
cancelCodexMenuPoll(resolvedId);
|
|
138
185
|
broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
|
|
139
186
|
}
|
|
187
|
+
if (eventName === 'codex.tool_result') {
|
|
188
|
+
codexToolPhasePending.delete(resolvedId);
|
|
189
|
+
resolvePendingTool(resolvedId, attrs.call_id || attrs['call.id']);
|
|
190
|
+
}
|
|
140
191
|
// Codex: user_prompt or next sse_event cancels menu poll
|
|
141
192
|
if ((eventName === 'codex.user_prompt' || (eventName === 'codex.sse_event' && attrs['event.kind'] !== 'response.completed'))) {
|
|
142
193
|
codexOutputDone.delete(resolvedId);
|
|
@@ -228,6 +279,8 @@ function clear(id) {
|
|
|
228
279
|
cancelCodexPendingIdle(id);
|
|
229
280
|
codexPendingStop.delete(id);
|
|
230
281
|
codexOutputDone.delete(id);
|
|
282
|
+
codexToolPhasePending.delete(id);
|
|
283
|
+
clearPendingTools(id);
|
|
231
284
|
const pending = pendingSetup.get(id);
|
|
232
285
|
if (pending) { clearTimeout(pending.timer); pendingSetup.delete(id); }
|
|
233
286
|
}
|