Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

ai-cli-online

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ai-cli-online - npm Package Compare versions

Comparing version
3.0.19
to
3.0.20
+4
server/dist/routes/taskAuto.d.ts
declare const router: import("express-serve-static-core").Router;
export declare function recoverAutoSessions(): void;
export declare function stopAllWatchers(): void;
export default router;
import { Router } from 'express';
import { resolveSession } from '../middleware/auth.js';
import { createAutoSession, getAutoSession, getAllRunningAutoSessions, updateAutoStatus, deleteAutoSession, insertAutoStep, endAutoStep, getAutoSteps, getLastAutoStep, deleteAutoSteps, } from '../db.js';
import { watch, readFileSync, writeFileSync, existsSync } from 'fs';
import { join } from 'path';
const router = Router();
// In-memory watcher map: sessionName → FSWatcher
const watchers = new Map();
function parseSignalFile(taskDir) {
const signalPath = join(taskDir, '.auto-signal');
try {
if (!existsSync(signalPath))
return null;
const raw = readFileSync(signalPath, 'utf-8').trim();
if (!raw)
return null;
return JSON.parse(raw);
}
catch {
return null;
}
}
function formatDuration(startedAt, endedAt) {
const start = new Date(startedAt).getTime();
const end = endedAt ? new Date(endedAt).getTime() : Date.now();
const sec = Math.round((end - start) / 1000);
if (sec < 60)
return `${sec}s`;
const min = Math.floor(sec / 60);
const rem = sec % 60;
if (min < 60)
return rem > 0 ? `${min}m ${rem}s` : `${min}m`;
const hr = Math.floor(min / 60);
const mrem = min % 60;
return mrem > 0 ? `${hr}h ${mrem}m` : `${hr}h`;
}
function formatTime(iso) {
return iso.replace('T', ' ').replace(/\.\d+Z$/, '').replace('Z', '');
}
/** Write .auto-timeline.md to the task directory with the full step history */
function writeTimelineFile(sessionName, taskDir) {
const session = getAutoSession(sessionName);
if (!session)
return;
const steps = getAutoSteps(sessionName);
if (steps.length === 0)
return;
const totalDuration = formatDuration(session.started_at, steps[steps.length - 1].ended_at ?? new Date().toISOString());
const endTime = steps[steps.length - 1].ended_at ?? new Date().toISOString();
const lines = [];
lines.push(`## Execution Timeline`);
lines.push(``);
lines.push(`- **Status**: ${session.status}`);
lines.push(`- **Total Duration**: ${totalDuration} (${formatTime(session.started_at)} → ${formatTime(endTime)})`);
const maxIter = Math.max(...steps.map(s => s.iteration));
if (maxIter > 0)
lines.push(`- **Iterations**: ${maxIter}`);
lines.push(``);
// Table
lines.push(`| # | Phase | Result | Checkpoint | Duration | Started | Ended |`);
lines.push(`|---|-------|--------|------------|----------|---------|-------|`);
for (let i = 0; i < steps.length; i++) {
const s = steps[i];
const dur = s.ended_at ? formatDuration(s.started_at, s.ended_at) : 'running';
const cp = s.checkpoint || '';
const started = formatTime(s.started_at).split(' ')[1] || '';
const ended = s.ended_at ? (formatTime(s.ended_at).split(' ')[1] || '') : '—';
lines.push(`| ${i + 1} | ${s.step} | ${s.result} | ${cp} | ${dur} | ${started} | ${ended} |`);
}
lines.push(``);
// Visual flow — show result only for decision steps (check, merge)
const flow = steps.map(s => {
const dur = s.ended_at ? formatDuration(s.started_at, s.ended_at) : '...';
const showResult = s.step === 'check' || s.step === 'merge';
const label = showResult ? `${s.step}:${s.result}` : s.step;
return `${label}(${dur})`;
}).join(' → ');
lines.push(`**Flow**: ${flow}`);
lines.push(``);
try {
writeFileSync(join(taskDir, '.auto-timeline.md'), lines.join('\n'));
}
catch (err) {
console.error(`[taskAuto] Failed to write .auto-timeline.md:`, err);
}
}
function processSignal(sessionName, signal) {
const lastStep = getLastAutoStep(sessionName);
// If same step+result+checkpoint as last, skip (no transition)
if (lastStep &&
lastStep.step === signal.step &&
lastStep.result === (signal.result || '') &&
lastStep.checkpoint === (signal.checkpoint || '')) {
return;
}
// End previous step if it has no ended_at
if (lastStep && !lastStep.ended_at) {
endAutoStep(lastStep.id);
}
// Insert new step
insertAutoStep(sessionName, signal.step, signal.result || '', signal.next || '', signal.checkpoint || '', signal.iteration ?? 0);
// If next is "(stop)" or "(done)", mark auto session as completed
if (signal.next === '(stop)' || signal.next === '(done)') {
// End the just-inserted step
const newLast = getLastAutoStep(sessionName);
if (newLast && !newLast.ended_at) {
endAutoStep(newLast.id);
}
updateAutoStatus(sessionName, 'completed');
// Write timeline file before stopping
const session = getAutoSession(sessionName);
if (session)
writeTimelineFile(sessionName, session.task_dir);
stopWatcher(sessionName);
}
}
function startWatcher(sessionName, taskDir) {
stopWatcher(sessionName);
try {
const watcher = watch(taskDir, (_eventType, filename) => {
if (filename === '.auto-signal') {
const signal = parseSignalFile(taskDir);
if (signal) {
try {
processSignal(sessionName, signal);
}
catch (err) {
console.error(`[taskAuto:watcher] Error processing signal for ${sessionName}:`, err);
}
}
}
// Detect .auto-stop written by the auto skill itself
if (filename === '.auto-stop') {
const session = getAutoSession(sessionName);
if (session && session.status === 'running') {
const lastStep = getLastAutoStep(sessionName);
if (lastStep && !lastStep.ended_at) {
endAutoStep(lastStep.id);
}
updateAutoStatus(sessionName, 'stopped');
writeTimelineFile(sessionName, session.task_dir);
stopWatcher(sessionName);
}
}
});
watchers.set(sessionName, watcher);
}
catch (err) {
console.error(`[taskAuto] Failed to watch ${taskDir}:`, err);
}
}
function stopWatcher(sessionName) {
const watcher = watchers.get(sessionName);
if (watcher) {
try {
watcher.close();
}
catch { /* ignore */ }
watchers.delete(sessionName);
}
}
// --- REST endpoints ---
// POST: Start auto tracking
router.post('/api/sessions/:sessionId/task-auto', (req, res) => {
const sessionName = resolveSession(req, res);
if (!sessionName)
return;
const { taskDir, maxIterations = 20, timeoutMinutes = 1440 } = req.body || {};
if (!taskDir || typeof taskDir !== 'string') {
res.status(400).json({ error: 'taskDir is required' });
return;
}
// Check if already tracking
const existing = getAutoSession(sessionName);
if (existing && existing.status === 'running') {
res.status(409).json({ error: 'Auto already running for this session' });
return;
}
// Clean up any old data
if (existing) {
deleteAutoSteps(sessionName);
deleteAutoSession(sessionName);
}
try {
createAutoSession(sessionName, taskDir, maxIterations, timeoutMinutes);
// Read initial signal if exists
const signal = parseSignalFile(taskDir);
if (signal) {
processSignal(sessionName, signal);
}
startWatcher(sessionName, taskDir);
res.json({ ok: true });
}
catch (err) {
console.error('[taskAuto:start]', err);
res.status(500).json({ error: 'Failed to start auto tracking' });
}
});
// GET: Get auto status + step history
router.get('/api/sessions/:sessionId/task-auto', (req, res) => {
const sessionName = resolveSession(req, res);
if (!sessionName)
return;
const session = getAutoSession(sessionName);
if (!session) {
res.json(null);
return;
}
const steps = getAutoSteps(sessionName);
const startedAt = new Date(session.started_at);
const elapsedMinutes = (Date.now() - startedAt.getTime()) / 60000;
res.json({
status: session.status,
taskDir: session.task_dir,
maxIterations: session.max_iterations,
timeoutMinutes: session.timeout_minutes,
startedAt: session.started_at,
elapsedMinutes: Math.round(elapsedMinutes * 10) / 10,
steps: steps.map((s) => ({
id: s.id,
step: s.step,
result: s.result,
next: s.next,
checkpoint: s.checkpoint,
iteration: s.iteration,
startedAt: s.started_at,
endedAt: s.ended_at,
})),
});
});
// DELETE: Stop auto tracking
router.delete('/api/sessions/:sessionId/task-auto', (req, res) => {
const sessionName = resolveSession(req, res);
if (!sessionName)
return;
const session = getAutoSession(sessionName);
if (!session) {
res.status(404).json({ error: 'No auto session found' });
return;
}
// If already finished (completed/cancelled/stopped), just clean up records
if (session.status !== 'running') {
deleteAutoSteps(sessionName);
deleteAutoSession(sessionName);
res.json({ ok: true });
return;
}
// Write .auto-stop to signal the auto subprocess to halt
try {
const stopPath = join(session.task_dir, '.auto-stop');
writeFileSync(stopPath, JSON.stringify({ reason: 'user_stop', timestamp: new Date().toISOString() }));
}
catch (err) {
console.error('[taskAuto:stop] Failed to write .auto-stop:', err);
}
// End last step
const lastStep = getLastAutoStep(sessionName);
if (lastStep && !lastStep.ended_at) {
endAutoStep(lastStep.id);
}
updateAutoStatus(sessionName, 'cancelled');
writeTimelineFile(sessionName, session.task_dir);
stopWatcher(sessionName);
res.json({ ok: true });
});
// --- Server restart recovery ---
export function recoverAutoSessions() {
const sessions = getAllRunningAutoSessions();
for (const session of sessions) {
if (existsSync(session.task_dir)) {
console.log(`[taskAuto:recover] Resuming watcher for ${session.session_name}`);
// Process any signals that arrived while server was down
const signal = parseSignalFile(session.task_dir);
if (signal) {
try {
processSignal(session.session_name, signal);
}
catch { /* ignore */ }
}
// Check if still running after processing
const updated = getAutoSession(session.session_name);
if (updated && updated.status === 'running') {
startWatcher(session.session_name, session.task_dir);
}
}
else {
console.log(`[taskAuto:recover] Task dir gone for ${session.session_name}, cleaning up`);
deleteAutoSteps(session.session_name);
deleteAutoSession(session.session_name);
}
}
}
export function stopAllWatchers() {
for (const [, watcher] of watchers) {
try {
watcher.close();
}
catch { /* ignore */ }
}
watchers.clear();
}
export default router;
/**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Bold.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}:root,[data-theme=dark]{--bg-primary: #000000;--bg-secondary: #0c0c0c;--bg-tertiary: #171717;--bg-hover: #1c1c1c;--border: #2d2d2d;--text-primary: #cccccc;--text-secondary: #858585;--text-bright: #e8e8e8;--accent-blue: #569cd6;--accent-purple: #c586c0;--accent-cyan: #4ec9b0;--accent-green: #89d185;--accent-yellow: #cca700;--accent-red: #f44747;--accent-orange: #ce9178;--scrollbar-thumb: rgba(121, 121, 121, .4);--scrollbar-thumb-hover: rgba(121, 121, 121, .7);--selection-bg: rgba(38, 79, 120, .5)}[data-theme=light]{--bg-primary: #ffffff;--bg-secondary: #f6f8fa;--bg-tertiary: #ffffff;--bg-hover: #eff2f5;--border: #d1d9e0;--text-primary: #1f2328;--text-secondary: #59636e;--text-bright: #1f2328;--accent-blue: #0969da;--accent-purple: #8250df;--accent-cyan: #1b7c83;--accent-green: #1a7f37;--accent-yellow: #9a6700;--accent-red: #d1242f;--accent-orange: #bc4c00;--scrollbar-thumb: rgba(31, 35, 40, .15);--scrollbar-thumb-hover: rgba(31, 35, 40, .3);--selection-bg: rgba(9, 105, 218, .2)}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;background-color:var(--bg-primary);font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body.resizing-panes,body.resizing-panes *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.session-sidebar{transition:width .2s ease;overflow:hidden;flex-shrink:0;z-index:10;position:relative}body.resizing-panes-v,body.resizing-panes-v *{cursor:row-resize!important;-webkit-user-select:none!important;user-select:none!important}button{transition:all .15s ease;font-family:inherit}button:hover{filter:brightness(1.2)}button:active{transform:scale(.97)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}::selection{background:var(--selection-bg);color:var(--text-bright)}input:focus-visible,button:focus-visible{outline:1px solid var(--accent-blue);outline-offset:1px}.header-btn{background:none;border:1px solid var(--border);color:var(--accent-blue);padding:3px 10px;border-radius:5px;cursor:pointer;font-size:13px;line-height:1.4;transition:all .15s ease}.header-btn:hover{background:#7aa2f71f;border-color:var(--accent-blue);box-shadow:0 0 8px #7aa2f726}.header-btn--muted{color:var(--text-secondary);font-size:12px}.header-btn--muted:hover{color:var(--text-primary);border-color:var(--text-secondary);background:#565f891a}.pane-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;line-height:1;padding:2px 5px;border-radius:4px;transition:all .15s ease}.pane-btn:hover{color:var(--accent-blue);background:#7aa2f71f}.pane-btn--danger:hover{color:var(--accent-red);background:#f7768e1f}.login-input{transition:border-color .2s ease,box-shadow .2s ease}.login-input:focus{border-color:var(--accent-blue)!important;box-shadow:0 0 0 3px #7aa2f726}.login-card{box-shadow:0 8px 32px #0006,0 0 0 1px #7aa2f714;transition:box-shadow .3s ease}.login-submit{transition:all .2s ease}.login-submit:not(:disabled):hover{filter:brightness(1.1);box-shadow:0 4px 12px #7aa2f74d}.md-editor-textarea{flex:1;min-width:0;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;color:var(--text-primary);background-color:var(--bg-primary);-moz-tab-size:2;tab-size:2}.md-editor-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.md-editor-divider{height:3px;background:var(--border);cursor:row-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.md-editor-divider:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.pane-btn--active{color:var(--accent-blue)}.plan-panel-body{display:flex;flex-direction:row;flex:1;min-height:0;overflow:hidden}.plan-renderer{position:relative;overflow:hidden;padding:0;min-width:0;-webkit-user-select:text;user-select:text}.plan-divider-h{width:2px;background:var(--border);cursor:col-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.plan-divider-h:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.plan-editor-wrap{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.plan-filename-input{background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;width:120px;outline:none;transition:border-color .15s ease}.plan-filename-input:focus{border-color:var(--accent-blue)}body.resizing-panes-h,body.resizing-panes-h *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.md-preview{color:var(--text-primary);font-size:13px;line-height:1.6;word-wrap:break-word}.md-preview h1{color:var(--accent-blue);font-size:1.4em;margin:.6em 0 .3em;padding-bottom:.2em;border-bottom:1px solid var(--border)}.md-preview h2{color:var(--accent-purple);font-size:1.2em;margin:.5em 0 .3em}.md-preview h3{color:var(--accent-cyan);font-size:1.05em;margin:.4em 0 .2em}.md-preview p{margin:.4em 0}.md-preview code{background:var(--bg-tertiary);color:var(--text-bright);padding:1px 4px;border-radius:3px;font-size:.9em;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.md-preview pre{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:4px;padding:10px 12px;overflow-x:auto;margin:.5em 0}.md-preview pre code{background:none;padding:0;border-radius:0}.md-preview blockquote{border-left:3px solid var(--accent-blue);padding:2px 12px;margin:.4em 0;color:var(--text-secondary)}.md-preview ul,.md-preview ol{padding-left:1.5em;margin:.3em 0}.md-preview li{margin:.15em 0}.md-preview table{border-collapse:collapse;width:100%;margin:.5em 0;font-size:12px}.md-preview th,.md-preview td{border:1px solid var(--border);padding:4px 8px;text-align:left}.md-preview th{background:var(--bg-tertiary);color:var(--accent-blue);font-weight:600}.md-preview a{color:var(--accent-blue);text-decoration:none}.md-preview a:hover{text-decoration:underline}.md-preview hr{border:none;border-top:1px solid var(--border);margin:.6em 0}.slash-dropdown{flex-shrink:0;max-height:200px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:13px}.slash-item{display:flex;align-items:center;gap:10px;padding:6px 12px;cursor:pointer;transition:background .12s ease}.slash-item:hover,.slash-item--active{background:var(--bg-hover)}.slash-cmd{color:var(--accent-blue);font-weight:600;min-width:180px;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.slash-desc{color:var(--accent-purple);font-size:11px}.file-dropdown{flex-shrink:0;max-height:180px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.file-item{display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;transition:background .1s ease}.file-item:hover,.file-item--active{background:var(--bg-hover)}.file-loading{color:var(--text-secondary);cursor:default}.file-icon{flex-shrink:0;width:16px;text-align:center;font-size:13px}.file-name{color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-dropdown{flex-shrink:0;max-height:260px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.history-item{display:flex;align-items:flex-start;gap:8px;padding:6px 10px;cursor:pointer;transition:background .1s ease;position:relative}.history-item:hover,.history-item--active{background:var(--bg-hover)}.history-empty{color:var(--text-secondary);cursor:default;justify-content:center;padding:12px}.history-text{flex:1;color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;white-space:pre-wrap;overflow-wrap:break-word;line-height:1.4}.history-time{flex-shrink:0;color:var(--text-secondary);font-size:10px;white-space:nowrap;margin-top:2px}.history-delete{flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:14px;padding:0 2px;line-height:1;opacity:0;transition:opacity .1s ease,color .1s ease}.history-item:hover .history-delete,.history-item--active .history-delete{opacity:1}.history-delete:hover{color:var(--accent-red)}.tab-bar{display:flex;align-items:center;padding:0 10px;height:32px;background:var(--bg-secondary);border-top:1px solid var(--border);flex-shrink:0;overflow-x:auto;gap:3px}.tab-bar::-webkit-scrollbar{height:0}.tab-item{display:flex;align-items:center;gap:6px;padding:4px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap;transition:color .15s ease,border-color .15s ease,background .15s ease,box-shadow .15s ease;border-radius:5px 5px 0 0;-webkit-user-select:none;user-select:none;flex-shrink:0}.tab-item:hover{color:var(--text-primary);background:#7aa2f70f}.tab-item--active{color:var(--text-bright);border-bottom-color:var(--accent-blue);background:#7aa2f71a;box-shadow:inset 0 -1px 0 var(--accent-blue)}.tab-item__name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.tab-item__count{font-size:10px;color:var(--scrollbar-thumb-hover)}.tab-item__close{font-size:14px;line-height:1;color:inherit;opacity:0;background:none;border:none;cursor:pointer;padding:0 2px;border-radius:3px;transition:opacity .1s ease}.tab-item:hover .tab-item__close{opacity:.5}.tab-item__close:hover{opacity:1!important;color:var(--accent-red);background:#f7768e1a}.tab-item__rename-input{background:transparent;border:1px solid var(--accent-blue);color:var(--text-bright);font-size:13px;font-family:inherit;padding:0 6px;border-radius:3px;outline:none;width:100px}.tab-bar-add{background:none;border:1px solid transparent;color:var(--text-secondary);font-size:18px;line-height:1;padding:2px 8px;border-radius:5px;cursor:pointer;margin-left:4px;flex-shrink:0}.tab-bar-add:hover{color:var(--accent-blue);border-color:var(--border);background:#7aa2f71a}.md-editor-actions{display:flex;align-items:center;gap:8px;padding:4px 8px;flex-shrink:0;background:var(--bg-secondary);border-top:1px solid var(--border)}.plan-anno-toolbar{display:flex;align-items:center;gap:6px;padding:3px 10px;height:28px;flex-shrink:0;background:var(--bg-secondary);border-bottom:1px solid var(--border)}.plan-anno-content{-webkit-user-select:text;user-select:text}.plan-insert-zone{position:relative;min-height:12px}.plan-insert-btn{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:20px;height:20px;border-radius:50%;border:1px solid var(--scrollbar-thumb-hover);background:var(--bg-secondary);color:var(--accent-blue);font-size:15px;line-height:1;cursor:pointer;padding:0 0 1px;z-index:2;transition:background .12s ease,border-color .12s ease,transform .12s ease;align-items:center;justify-content:center}.plan-insert-zone:hover .plan-insert-btn{display:flex}.plan-anno-content--editing .plan-insert-zone:hover .plan-insert-btn{display:none}.plan-empty-placeholder{display:flex;align-items:center;justify-content:center;min-height:120px;color:var(--text-secondary);font-size:13px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:center;padding:16px}.plan-empty-placeholder:hover{color:var(--accent-blue)}.plan-insert-btn:hover{background:var(--bg-hover);border-color:var(--accent-blue);transform:translate(-50%,-50%) scale(1.15)}.plan-annotation-card{display:flex;align-items:flex-start;gap:6px;padding:6px 10px;margin:4px 0;background:#e0af681f;border-left:3px solid var(--accent-yellow);border-radius:0 4px 4px 0}.plan-annotation-card--editing{border-left-color:var(--accent-blue);background:#7aa2f70f}.plan-annotation-textarea{flex:1;min-height:36px;max-height:30em;field-sizing:content;resize:vertical;border:1px solid var(--border);border-radius:3px;background:var(--bg-primary);color:var(--text-primary);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;font-size:12px;padding:4px 6px;outline:none;transition:border-color .15s ease}.plan-annotation-textarea:focus{border-color:var(--accent-blue)}.plan-annotation-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-deletion-card{display:flex;align-items:center;gap:6px;padding:2px 8px;margin:2px 0;background:#f7768e0f;border-left:3px solid var(--accent-red);border-radius:0 4px 4px 0;font-size:11px}.plan-selection-float{position:absolute;z-index:1000;display:flex;flex-direction:row;gap:2px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;padding:2px;box-shadow:0 2px 8px #0000004d}.plan-selection-float button{width:24px;height:24px;border-radius:4px;border:none;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;background:transparent;transition:background .15s,transform .1s}.plan-selection-float button:hover{transform:scale(1.1)}.plan-selection-float__delete{color:var(--accent-red)}.plan-selection-float__delete:hover{background:#f7768e33}.plan-selection-float__replace{color:var(--accent-blue)}.plan-selection-float__replace:hover{background:#7aa2f733}.plan-selection-float__comment{color:var(--accent-green)}.plan-selection-float__comment:hover{background:#9ece6a33}.plan-replace-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(122,162,247,.6);background:#7aa2f70a;border-radius:0 4px 4px 0;font-size:11px}.plan-comment-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(158,206,106,.6);background:#9ece6a0a;border-radius:0 4px 4px 0;font-size:11px}.plan-block--deleted{border-left:3px solid rgba(247,118,142,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--replaced{border-left:3px solid rgba(122,162,247,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--commented{border-left:3px solid rgba(158,206,106,.5);padding-left:8px;border-radius:2px;position:relative}.mermaid-diagram{margin:8px 0;padding:12px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;overflow-x:auto}.mermaid-diagram svg{display:block;margin:0 auto;max-width:100%;height:auto}.mermaid-error{border-left:3px solid var(--accent-red);padding-left:8px}.mermaid-error__msg{color:var(--accent-red);font-size:11px;margin-top:4px}.pane-btn--sm{font-size:11px;flex-shrink:0}.plan-file-browser{display:flex;flex-direction:column;height:100%;width:100%;background:var(--bg-secondary);overflow:hidden}.plan-file-browser__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;height:28px;flex-shrink:0;border-bottom:1px solid var(--border)}.plan-file-browser__title{font-size:11px;color:var(--accent-blue);font-weight:600;letter-spacing:.3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;direction:rtl;text-align:left}.plan-file-browser__list{flex:1;overflow-y:auto;overflow-x:hidden;padding:2px 0}.plan-file-browser__status{padding:8px 10px;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-file-browser__item{display:flex;align-items:center;padding:3px 8px;font-size:12px;cursor:pointer;gap:5px;transition:background .1s ease;border-left:2px solid transparent}.plan-file-browser__item:hover{background:var(--bg-tertiary)}.plan-file-browser__item--active{background:#7aa2f71a;border-left-color:var(--accent-blue)}.plan-file-browser__item--active .plan-file-browser__name{color:var(--text-bright)}.plan-file-browser__icon{flex-shrink:0;width:14px;font-size:10px;color:var(--text-secondary);text-align:center}.plan-file-browser__name{flex:1;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.plan-file-browser__size{flex-shrink:1;font-size:9px;color:var(--scrollbar-thumb-hover);white-space:nowrap;overflow:hidden;min-width:0}.plan-file-browser__create{display:flex;align-items:center;gap:4px;padding:4px 6px;border-top:1px solid var(--border);flex-shrink:0}.plan-file-browser__input{flex:1;min-width:0;background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;outline:none;transition:border-color .15s ease}.plan-file-browser__input:focus{border-color:var(--accent-blue)}.plan-file-browser__input::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-overlay-body{display:flex;flex:1;min-height:0;overflow:hidden}.plan-overlay-center{flex:1;min-width:0;overflow:hidden}.plan-anno-counts{display:inline-flex;align-items:center;gap:4px;font-size:10px;margin-left:4px}.plan-anno-counts__unsent{color:var(--accent-yellow)}.plan-anno-counts__sent{color:var(--accent-green)}.plan-anno-dropdown-trigger{display:flex;align-items:center;gap:4px;padding:2px 6px;border:1px solid var(--border);border-radius:3px;cursor:pointer;background:var(--bg-primary);transition:border-color .15s ease,background .15s ease;min-width:0}.plan-anno-dropdown-trigger:hover,.plan-anno-dropdown-trigger--active{border-color:var(--accent-blue);background:var(--bg-hover)}.plan-anno-dropdown-trigger__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:var(--text-secondary)}.plan-anno-dropdown-trigger__arrow{flex-shrink:0;font-size:9px;color:var(--text-secondary);transition:transform .15s ease}.plan-anno-dropdown-trigger--active .plan-anno-dropdown-trigger__arrow{transform:rotate(180deg)}.plan-anno-dropdown{position:absolute;top:100%;right:0;z-index:100;width:320px;max-height:300px;display:flex;flex-direction:column;background:var(--bg-secondary);border:1px solid var(--border);border-radius:4px;box-shadow:0 4px 12px #0000004d;overflow:hidden}.plan-anno-dropdown__header{display:flex;align-items:center;justify-content:center;padding:4px 6px;border-bottom:1px solid var(--border);flex-shrink:0}.plan-anno-dropdown__list{flex:1;overflow-y:auto;padding:2px 0}.plan-anno-dropdown__item{display:flex;align-items:center;gap:4px;padding:3px 6px;font-size:11px;border-bottom:1px solid var(--border-subtle, rgba(128,128,128,.1))}.plan-anno-dropdown__item:last-child{border-bottom:none}.plan-anno-dropdown__item--add{border-left:2px solid var(--accent-yellow)}.plan-anno-dropdown__item--del{border-left:2px solid var(--accent-red)}.plan-anno-dropdown__item--rep{border-left:2px solid var(--accent-blue)}.plan-anno-dropdown__item--com{border-left:2px solid var(--accent-green)}.plan-anno-dropdown__type{flex-shrink:0;width:14px;font-weight:700;text-align:center}.plan-anno-dropdown__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-primary)}.plan-anno-dropdown__badge{flex-shrink:0;font-size:9px;padding:0 4px;border-radius:3px;background:var(--accent-green);color:var(--bg-primary)}.plan-anno-dropdown__empty{padding:8px;text-align:center;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-edit-textarea{width:100%;flex:1;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;line-height:1.6;background:var(--bg-primary);color:var(--text-primary);-moz-tab-size:2;tab-size:2}.plan-edit-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.auto-timeline{display:flex;align-items:center;gap:5px;padding:3px 8px;min-height:26px;overflow:hidden}.auto-divider{color:var(--border);font-size:11px;-webkit-user-select:none;user-select:none;flex-shrink:0}.auto-spin-input{display:inline-flex;align-items:center;height:18px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:3px;overflow:hidden;flex-shrink:0}.auto-spin-input input{width:100%;height:100%;padding:0 2px;font-size:10px;background:transparent;color:var(--text-primary);border:none;outline:none;text-align:left;-moz-appearance:textfield}.auto-spin-input input::-webkit-inner-spin-button,.auto-spin-input input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.auto-spin-btns{display:flex;flex-direction:column;flex-shrink:0;border-left:1px solid var(--border)}.auto-spin-btns button{display:flex;align-items:center;justify-content:center;width:14px;height:9px;font-size:5px;line-height:1;padding:0;background:var(--bg-secondary);color:var(--text-secondary);border:none;cursor:pointer}.auto-spin-btns button:hover{background:var(--bg-tertiary);color:var(--text-primary)}.auto-spin-btns button:first-child{border-bottom:1px solid var(--border)}.auto-step-node{display:flex;flex-direction:column;align-items:center;gap:1px;background:none;border:none;padding:2px 4px;cursor:pointer;min-width:40px;flex-shrink:0}.auto-step-node:disabled{cursor:default;opacity:.5}.auto-step-node:not(:disabled):hover .auto-step-circle{transform:scale(1.3)}.auto-step-circle{width:8px;height:8px;border-radius:50%;transition:transform .15s,background-color .2s;flex-shrink:0}.auto-step-node.completed .auto-step-circle{background-color:var(--accent-green)}.auto-step-node.active .auto-step-circle{background-color:var(--accent-blue);animation:auto-pulse 1.5s ease-in-out infinite}.auto-step-node.pending .auto-step-circle{background-color:var(--text-secondary);opacity:.4}@keyframes auto-pulse{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.4);opacity:.7}}.auto-step-label{font-size:9px;color:var(--text-primary);white-space:nowrap;max-width:50px;overflow:hidden;text-overflow:ellipsis}.auto-step-duration{font-size:8px;color:var(--text-secondary);white-space:nowrap}.auto-connector{width:12px;height:2px;background-color:var(--border);flex-shrink:0;transition:background-color .2s}.auto-connector.completed{background-color:var(--accent-green)}.auto-step-popup{position:absolute;left:0;right:0;bottom:0;top:0;z-index:10;background-color:var(--bg-primary);display:flex;flex-direction:column;border-top:2px solid var(--accent-blue)}

Sorry, the diff of this file is too big to display

+1
-1
{
"name": "ai-cli-online",
"version": "3.0.19",
"version": "3.0.20",
"description": "AI-Cli Online - Web Terminal for Claude Code via xterm.js + tmux",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -13,2 +13,31 @@ export declare function getSetting(tokenHash: string, key: string): string | null;

export declare function cleanupOldAnnotations(maxAgeDays?: number): number;
export interface AutoSession {
session_name: string;
task_dir: string;
status: string;
max_iterations: number;
timeout_minutes: number;
started_at: string;
}
export interface AutoStep {
id: number;
session_name: string;
step: string;
result: string;
next: string;
checkpoint: string;
iteration: number;
started_at: string;
ended_at: string | null;
}
export declare function createAutoSession(sessionName: string, taskDir: string, maxIterations: number, timeoutMinutes: number): void;
export declare function getAutoSession(sessionName: string): AutoSession | null;
export declare function getAllRunningAutoSessions(): AutoSession[];
export declare function updateAutoStatus(sessionName: string, status: string): void;
export declare function deleteAutoSession(sessionName: string): void;
export declare function insertAutoStep(sessionName: string, step: string, result: string, next: string, checkpoint: string, iteration: number): number;
export declare function endAutoStep(stepId: number): void;
export declare function getAutoSteps(sessionName: string): AutoStep[];
export declare function getLastAutoStep(sessionName: string): AutoStep | null;
export declare function deleteAutoSteps(sessionName: string): void;
export declare function closeDb(): void;

@@ -109,4 +109,77 @@ import Database from 'better-sqlite3';

}
// --- Auto mode tables ---
db.exec(`
CREATE TABLE IF NOT EXISTS task_auto (
session_name TEXT PRIMARY KEY,
task_dir TEXT NOT NULL UNIQUE,
status TEXT DEFAULT 'running',
max_iterations INTEGER DEFAULT 20,
timeout_minutes INTEGER DEFAULT 30,
started_at TEXT NOT NULL
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS task_auto_steps (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_name TEXT NOT NULL,
step TEXT NOT NULL,
result TEXT DEFAULT '',
next TEXT DEFAULT '',
checkpoint TEXT DEFAULT '',
iteration INTEGER DEFAULT 0,
started_at TEXT NOT NULL,
ended_at TEXT
)
`);
db.exec('CREATE INDEX IF NOT EXISTS idx_auto_steps_session ON task_auto_steps(session_name)');
// --- Auto mode statements ---
const stmtAutoInsert = db.prepare(`
INSERT INTO task_auto (session_name, task_dir, status, max_iterations, timeout_minutes, started_at)
VALUES (?, ?, 'running', ?, ?, ?)
`);
const stmtAutoGet = db.prepare('SELECT * FROM task_auto WHERE session_name = ?');
const stmtAutoGetAll = db.prepare("SELECT * FROM task_auto WHERE status = 'running'");
const stmtAutoUpdateStatus = db.prepare('UPDATE task_auto SET status = ? WHERE session_name = ?');
const stmtAutoDelete = db.prepare('DELETE FROM task_auto WHERE session_name = ?');
const stmtAutoStepInsert = db.prepare(`
INSERT INTO task_auto_steps (session_name, step, result, next, checkpoint, iteration, started_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
const stmtAutoStepEnd = db.prepare('UPDATE task_auto_steps SET ended_at = ? WHERE id = ?');
const stmtAutoStepGetAll = db.prepare('SELECT * FROM task_auto_steps WHERE session_name = ? ORDER BY id ASC');
const stmtAutoStepGetLast = db.prepare('SELECT * FROM task_auto_steps WHERE session_name = ? ORDER BY id DESC LIMIT 1');
const stmtAutoStepsDelete = db.prepare('DELETE FROM task_auto_steps WHERE session_name = ?');
export function createAutoSession(sessionName, taskDir, maxIterations, timeoutMinutes) {
stmtAutoInsert.run(sessionName, taskDir, maxIterations, timeoutMinutes, new Date().toISOString());
}
export function getAutoSession(sessionName) {
return stmtAutoGet.get(sessionName) ?? null;
}
export function getAllRunningAutoSessions() {
return stmtAutoGetAll.all();
}
export function updateAutoStatus(sessionName, status) {
stmtAutoUpdateStatus.run(status, sessionName);
}
export function deleteAutoSession(sessionName) {
stmtAutoDelete.run(sessionName);
}
export function insertAutoStep(sessionName, step, result, next, checkpoint, iteration) {
const info = stmtAutoStepInsert.run(sessionName, step, result, next, checkpoint, iteration, new Date().toISOString());
return Number(info.lastInsertRowid);
}
export function endAutoStep(stepId) {
stmtAutoStepEnd.run(new Date().toISOString(), stepId);
}
export function getAutoSteps(sessionName) {
return stmtAutoStepGetAll.all(sessionName);
}
export function getLastAutoStep(sessionName) {
return stmtAutoStepGetLast.get(sessionName) ?? null;
}
export function deleteAutoSteps(sessionName) {
stmtAutoStepsDelete.run(sessionName);
}
export function closeDb() {
db.close();
}

@@ -22,2 +22,3 @@ import express from 'express';

import gitRouter from './routes/git.js';
import taskAutoRouter, { recoverAutoSessions, stopAllWatchers } from './routes/taskAuto.js';
const __dirname = dirname(fileURLToPath(import.meta.url));

@@ -105,2 +106,3 @@ config();

app.use(gitRouter);
app.use(taskAutoRouter);
// --- Static files ---

@@ -180,2 +182,8 @@ const webDistPath = join(__dirname, '../../web/dist');

}
try {
recoverAutoSessions();
}
catch (e) {
console.error('[startup:auto-recover]', e);
}
const CLEANUP_INTERVAL = 60 * 60 * 1000;

@@ -207,2 +215,3 @@ const cleanupTimer = setInterval(async () => {

clearWsIntervals();
stopAllWatchers();
if (cleanupTimer)

@@ -209,0 +218,0 @@ clearInterval(cleanupTimer);

import { Router } from 'express';
import { extractToken, checkAuth, resolveSession } from '../middleware/auth.js';
import { listSessions, killSession, buildSessionName, getCwd, getPaneCommand } from '../tmux.js';
import { listSessions, killSession, buildSessionName, getCwd, getPaneCommand, captureScrollback } from '../tmux.js';
import { getActiveSessionNames } from '../websocket.js';

@@ -64,2 +64,16 @@ import { deleteDraft } from '../db.js';

});
// Capture pane scrollback content (for live terminal popup)
router.get('/api/sessions/:sessionId/capture-pane', async (req, res) => {
const sessionName = resolveSession(req, res);
if (!sessionName)
return;
try {
const content = await captureScrollback(sessionName);
res.json({ content });
}
catch (err) {
console.error(`[api:capture-pane] ${sessionName}:`, err);
res.status(500).json({ error: 'Failed to capture pane content' });
}
});
export default router;
{
"name": "ai-cli-online-server",
"version": "3.0.19",
"version": "3.0.20",
"description": "CLI-Online Backend Server",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

{
"name": "ai-cli-online-shared",
"version": "3.0.19",
"version": "3.0.20",
"description": "Shared types for CLI-Online",

@@ -5,0 +5,0 @@ "type": "module",

@@ -13,7 +13,7 @@ <!DOCTYPE html>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@1.7.0/lxgwwenkaimono-bold.css" />
<script type="module" crossorigin src="/assets/index-Kzdpgxcz.js"></script>
<script type="module" crossorigin src="/assets/index-DG0BJZ53.js"></script>
<link rel="modulepreload" crossorigin href="/assets/react-vendor-BCIvbQoU.js">
<link rel="modulepreload" crossorigin href="/assets/terminal-DnNpv9tw.js">
<link rel="modulepreload" crossorigin href="/assets/markdown-CU76q5qk.js">
<link rel="stylesheet" crossorigin href="/assets/index-BI7oV4SU.css">
<link rel="stylesheet" crossorigin href="/assets/index-D7cmVR0X.css">
</head>

@@ -20,0 +20,0 @@ <body>

{
"name": "ai-cli-online-web",
"version": "3.0.19",
"version": "3.0.20",
"description": "CLI-Online Web Frontend",

@@ -5,0 +5,0 @@ "type": "module",

/**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:JetBrains Mono;src:url(/fonts/JetBrainsMono-Bold.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}:root,[data-theme=dark]{--bg-primary: #000000;--bg-secondary: #0c0c0c;--bg-tertiary: #171717;--bg-hover: #1c1c1c;--border: #2d2d2d;--text-primary: #cccccc;--text-secondary: #858585;--text-bright: #e8e8e8;--accent-blue: #569cd6;--accent-purple: #c586c0;--accent-cyan: #4ec9b0;--accent-green: #89d185;--accent-yellow: #cca700;--accent-red: #f44747;--accent-orange: #ce9178;--scrollbar-thumb: rgba(121, 121, 121, .4);--scrollbar-thumb-hover: rgba(121, 121, 121, .7);--selection-bg: rgba(38, 79, 120, .5)}[data-theme=light]{--bg-primary: #ffffff;--bg-secondary: #f6f8fa;--bg-tertiary: #ffffff;--bg-hover: #eff2f5;--border: #d1d9e0;--text-primary: #1f2328;--text-secondary: #59636e;--text-bright: #1f2328;--accent-blue: #0969da;--accent-purple: #8250df;--accent-cyan: #1b7c83;--accent-green: #1a7f37;--accent-yellow: #9a6700;--accent-red: #d1242f;--accent-orange: #bc4c00;--scrollbar-thumb: rgba(31, 35, 40, .15);--scrollbar-thumb-hover: rgba(31, 35, 40, .3);--selection-bg: rgba(9, 105, 218, .2)}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;background-color:var(--bg-primary);font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body.resizing-panes,body.resizing-panes *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.session-sidebar{transition:width .2s ease;overflow:hidden;flex-shrink:0;z-index:10;position:relative}body.resizing-panes-v,body.resizing-panes-v *{cursor:row-resize!important;-webkit-user-select:none!important;user-select:none!important}button{transition:all .15s ease;font-family:inherit}button:hover{filter:brightness(1.2)}button:active{transform:scale(.97)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}::selection{background:var(--selection-bg);color:var(--text-bright)}input:focus-visible,button:focus-visible{outline:1px solid var(--accent-blue);outline-offset:1px}.header-btn{background:none;border:1px solid var(--border);color:var(--accent-blue);padding:3px 10px;border-radius:5px;cursor:pointer;font-size:13px;line-height:1.4;transition:all .15s ease}.header-btn:hover{background:#7aa2f71f;border-color:var(--accent-blue);box-shadow:0 0 8px #7aa2f726}.header-btn--muted{color:var(--text-secondary);font-size:12px}.header-btn--muted:hover{color:var(--text-primary);border-color:var(--text-secondary);background:#565f891a}.pane-btn{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px;line-height:1;padding:2px 5px;border-radius:4px;transition:all .15s ease}.pane-btn:hover{color:var(--accent-blue);background:#7aa2f71f}.pane-btn--danger:hover{color:var(--accent-red);background:#f7768e1f}.login-input{transition:border-color .2s ease,box-shadow .2s ease}.login-input:focus{border-color:var(--accent-blue)!important;box-shadow:0 0 0 3px #7aa2f726}.login-card{box-shadow:0 8px 32px #0006,0 0 0 1px #7aa2f714;transition:box-shadow .3s ease}.login-submit{transition:all .2s ease}.login-submit:not(:disabled):hover{filter:brightness(1.1);box-shadow:0 4px 12px #7aa2f74d}.md-editor-textarea{flex:1;min-width:0;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;color:var(--text-primary);background-color:var(--bg-primary);-moz-tab-size:2;tab-size:2}.md-editor-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.md-editor-divider{height:3px;background:var(--border);cursor:row-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.md-editor-divider:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.pane-btn--active{color:var(--accent-blue)}.plan-panel-body{display:flex;flex-direction:row;flex:1;min-height:0;overflow:hidden}.plan-renderer{position:relative;overflow:hidden;padding:0;min-width:0;-webkit-user-select:text;user-select:text}.plan-divider-h{width:2px;background:var(--border);cursor:col-resize;flex-shrink:0;transition:background .15s ease,box-shadow .15s ease}.plan-divider-h:hover{background:var(--accent-blue);box-shadow:0 0 6px #7aa2f766}.plan-editor-wrap{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.plan-filename-input{background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;width:120px;outline:none;transition:border-color .15s ease}.plan-filename-input:focus{border-color:var(--accent-blue)}body.resizing-panes-h,body.resizing-panes-h *{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}.md-preview{color:var(--text-primary);font-size:13px;line-height:1.6;word-wrap:break-word}.md-preview h1{color:var(--accent-blue);font-size:1.4em;margin:.6em 0 .3em;padding-bottom:.2em;border-bottom:1px solid var(--border)}.md-preview h2{color:var(--accent-purple);font-size:1.2em;margin:.5em 0 .3em}.md-preview h3{color:var(--accent-cyan);font-size:1.05em;margin:.4em 0 .2em}.md-preview p{margin:.4em 0}.md-preview code{background:var(--bg-tertiary);color:var(--text-bright);padding:1px 4px;border-radius:3px;font-size:.9em;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.md-preview pre{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:4px;padding:10px 12px;overflow-x:auto;margin:.5em 0}.md-preview pre code{background:none;padding:0;border-radius:0}.md-preview blockquote{border-left:3px solid var(--accent-blue);padding:2px 12px;margin:.4em 0;color:var(--text-secondary)}.md-preview ul,.md-preview ol{padding-left:1.5em;margin:.3em 0}.md-preview li{margin:.15em 0}.md-preview table{border-collapse:collapse;width:100%;margin:.5em 0;font-size:12px}.md-preview th,.md-preview td{border:1px solid var(--border);padding:4px 8px;text-align:left}.md-preview th{background:var(--bg-tertiary);color:var(--accent-blue);font-weight:600}.md-preview a{color:var(--accent-blue);text-decoration:none}.md-preview a:hover{text-decoration:underline}.md-preview hr{border:none;border-top:1px solid var(--border);margin:.6em 0}.slash-dropdown{flex-shrink:0;max-height:200px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:13px}.slash-item{display:flex;align-items:center;gap:10px;padding:6px 12px;cursor:pointer;transition:background .12s ease}.slash-item:hover,.slash-item--active{background:var(--bg-hover)}.slash-cmd{color:var(--accent-blue);font-weight:600;min-width:180px;font-family:JetBrains Mono,LXGW WenKai Mono,monospace}.slash-desc{color:var(--accent-purple);font-size:11px}.file-dropdown{flex-shrink:0;max-height:180px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.file-item{display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;transition:background .1s ease}.file-item:hover,.file-item--active{background:var(--bg-hover)}.file-loading{color:var(--text-secondary);cursor:default}.file-icon{flex-shrink:0;width:16px;text-align:center;font-size:13px}.file-name{color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-dropdown{flex-shrink:0;max-height:260px;overflow-y:auto;background:var(--bg-secondary);border-bottom:1px solid var(--border);z-index:10;font-size:12px}.history-item{display:flex;align-items:flex-start;gap:8px;padding:6px 10px;cursor:pointer;transition:background .1s ease;position:relative}.history-item:hover,.history-item--active{background:var(--bg-hover)}.history-empty{color:var(--text-secondary);cursor:default;justify-content:center;padding:12px}.history-text{flex:1;color:var(--text-bright);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;white-space:pre-wrap;overflow-wrap:break-word;line-height:1.4}.history-time{flex-shrink:0;color:var(--text-secondary);font-size:10px;white-space:nowrap;margin-top:2px}.history-delete{flex-shrink:0;background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:14px;padding:0 2px;line-height:1;opacity:0;transition:opacity .1s ease,color .1s ease}.history-item:hover .history-delete,.history-item--active .history-delete{opacity:1}.history-delete:hover{color:var(--accent-red)}.tab-bar{display:flex;align-items:center;padding:0 10px;height:32px;background:var(--bg-secondary);border-top:1px solid var(--border);flex-shrink:0;overflow-x:auto;gap:3px}.tab-bar::-webkit-scrollbar{height:0}.tab-item{display:flex;align-items:center;gap:6px;padding:4px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap;transition:color .15s ease,border-color .15s ease,background .15s ease,box-shadow .15s ease;border-radius:5px 5px 0 0;-webkit-user-select:none;user-select:none;flex-shrink:0}.tab-item:hover{color:var(--text-primary);background:#7aa2f70f}.tab-item--active{color:var(--text-bright);border-bottom-color:var(--accent-blue);background:#7aa2f71a;box-shadow:inset 0 -1px 0 var(--accent-blue)}.tab-item__name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.tab-item__count{font-size:10px;color:var(--scrollbar-thumb-hover)}.tab-item__close{font-size:14px;line-height:1;color:inherit;opacity:0;background:none;border:none;cursor:pointer;padding:0 2px;border-radius:3px;transition:opacity .1s ease}.tab-item:hover .tab-item__close{opacity:.5}.tab-item__close:hover{opacity:1!important;color:var(--accent-red);background:#f7768e1a}.tab-item__rename-input{background:transparent;border:1px solid var(--accent-blue);color:var(--text-bright);font-size:13px;font-family:inherit;padding:0 6px;border-radius:3px;outline:none;width:100px}.tab-bar-add{background:none;border:1px solid transparent;color:var(--text-secondary);font-size:18px;line-height:1;padding:2px 8px;border-radius:5px;cursor:pointer;margin-left:4px;flex-shrink:0}.tab-bar-add:hover{color:var(--accent-blue);border-color:var(--border);background:#7aa2f71a}.md-editor-actions{display:flex;align-items:center;gap:8px;padding:4px 8px;flex-shrink:0;background:var(--bg-secondary);border-top:1px solid var(--border)}.plan-anno-toolbar{display:flex;align-items:center;gap:6px;padding:3px 10px;height:28px;flex-shrink:0;background:var(--bg-secondary);border-bottom:1px solid var(--border)}.plan-anno-content{-webkit-user-select:text;user-select:text}.plan-insert-zone{position:relative;min-height:12px}.plan-insert-btn{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:20px;height:20px;border-radius:50%;border:1px solid var(--scrollbar-thumb-hover);background:var(--bg-secondary);color:var(--accent-blue);font-size:15px;line-height:1;cursor:pointer;padding:0 0 1px;z-index:2;transition:background .12s ease,border-color .12s ease,transform .12s ease;align-items:center;justify-content:center}.plan-insert-zone:hover .plan-insert-btn{display:flex}.plan-anno-content--editing .plan-insert-zone:hover .plan-insert-btn{display:none}.plan-empty-placeholder{display:flex;align-items:center;justify-content:center;min-height:120px;color:var(--text-secondary);font-size:13px;font-style:italic;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:center;padding:16px}.plan-empty-placeholder:hover{color:var(--accent-blue)}.plan-insert-btn:hover{background:var(--bg-hover);border-color:var(--accent-blue);transform:translate(-50%,-50%) scale(1.15)}.plan-annotation-card{display:flex;align-items:flex-start;gap:6px;padding:6px 10px;margin:4px 0;background:#e0af681f;border-left:3px solid var(--accent-yellow);border-radius:0 4px 4px 0}.plan-annotation-card--editing{border-left-color:var(--accent-blue);background:#7aa2f70f}.plan-annotation-textarea{flex:1;min-height:36px;max-height:30em;field-sizing:content;resize:vertical;border:1px solid var(--border);border-radius:3px;background:var(--bg-primary);color:var(--text-primary);font-family:JetBrains Mono,LXGW WenKai Mono,monospace;font-size:12px;padding:4px 6px;outline:none;transition:border-color .15s ease}.plan-annotation-textarea:focus{border-color:var(--accent-blue)}.plan-annotation-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-deletion-card{display:flex;align-items:center;gap:6px;padding:2px 8px;margin:2px 0;background:#f7768e0f;border-left:3px solid var(--accent-red);border-radius:0 4px 4px 0;font-size:11px}.plan-selection-float{position:absolute;z-index:1000;display:flex;flex-direction:row;gap:2px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;padding:2px;box-shadow:0 2px 8px #0000004d}.plan-selection-float button{width:24px;height:24px;border-radius:4px;border:none;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;background:transparent;transition:background .15s,transform .1s}.plan-selection-float button:hover{transform:scale(1.1)}.plan-selection-float__delete{color:var(--accent-red)}.plan-selection-float__delete:hover{background:#f7768e33}.plan-selection-float__replace{color:var(--accent-blue)}.plan-selection-float__replace:hover{background:#7aa2f733}.plan-selection-float__comment{color:var(--accent-green)}.plan-selection-float__comment:hover{background:#9ece6a33}.plan-replace-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(122,162,247,.6);background:#7aa2f70a;border-radius:0 4px 4px 0;font-size:11px}.plan-comment-card{display:flex;align-items:flex-start;gap:6px;padding:2px 8px;margin:2px 0;border-left:3px solid rgba(158,206,106,.6);background:#9ece6a0a;border-radius:0 4px 4px 0;font-size:11px}.plan-block--deleted{border-left:3px solid rgba(247,118,142,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--replaced{border-left:3px solid rgba(122,162,247,.5);padding-left:8px;border-radius:2px;position:relative}.plan-block--commented{border-left:3px solid rgba(158,206,106,.5);padding-left:8px;border-radius:2px;position:relative}.mermaid-diagram{margin:8px 0;padding:12px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;overflow-x:auto}.mermaid-diagram svg{display:block;margin:0 auto;max-width:100%;height:auto}.mermaid-error{border-left:3px solid var(--accent-red);padding-left:8px}.mermaid-error__msg{color:var(--accent-red);font-size:11px;margin-top:4px}.pane-btn--sm{font-size:11px;flex-shrink:0}.plan-file-browser{display:flex;flex-direction:column;height:100%;width:100%;background:var(--bg-secondary);overflow:hidden}.plan-file-browser__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;height:28px;flex-shrink:0;border-bottom:1px solid var(--border)}.plan-file-browser__title{font-size:11px;color:var(--accent-blue);font-weight:600;letter-spacing:.3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;direction:rtl;text-align:left}.plan-file-browser__list{flex:1;overflow-y:auto;overflow-x:hidden;padding:2px 0}.plan-file-browser__status{padding:8px 10px;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-file-browser__item{display:flex;align-items:center;padding:3px 8px;font-size:12px;cursor:pointer;gap:5px;transition:background .1s ease;border-left:2px solid transparent}.plan-file-browser__item:hover{background:var(--bg-tertiary)}.plan-file-browser__item--active{background:#7aa2f71a;border-left-color:var(--accent-blue)}.plan-file-browser__item--active .plan-file-browser__name{color:var(--text-bright)}.plan-file-browser__icon{flex-shrink:0;width:14px;font-size:10px;color:var(--text-secondary);text-align:center}.plan-file-browser__name{flex:1;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.plan-file-browser__size{flex-shrink:1;font-size:9px;color:var(--scrollbar-thumb-hover);white-space:nowrap;overflow:hidden;min-width:0}.plan-file-browser__create{display:flex;align-items:center;gap:4px;padding:4px 6px;border-top:1px solid var(--border);flex-shrink:0}.plan-file-browser__input{flex:1;min-width:0;background:var(--bg-primary);border:1px solid var(--border);color:var(--text-primary);padding:2px 6px;border-radius:3px;font-family:inherit;font-size:11px;outline:none;transition:border-color .15s ease}.plan-file-browser__input:focus{border-color:var(--accent-blue)}.plan-file-browser__input::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}.plan-overlay-body{display:flex;flex:1;min-height:0;overflow:hidden}.plan-overlay-center{flex:1;min-width:0;overflow:hidden}.plan-anno-counts{display:inline-flex;align-items:center;gap:4px;font-size:10px;margin-left:4px}.plan-anno-counts__unsent{color:var(--accent-yellow)}.plan-anno-counts__sent{color:var(--accent-green)}.plan-anno-dropdown-trigger{display:flex;align-items:center;gap:4px;padding:2px 6px;border:1px solid var(--border);border-radius:3px;cursor:pointer;background:var(--bg-primary);transition:border-color .15s ease,background .15s ease;min-width:0}.plan-anno-dropdown-trigger:hover,.plan-anno-dropdown-trigger--active{border-color:var(--accent-blue);background:var(--bg-hover)}.plan-anno-dropdown-trigger__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:var(--text-secondary)}.plan-anno-dropdown-trigger__arrow{flex-shrink:0;font-size:9px;color:var(--text-secondary);transition:transform .15s ease}.plan-anno-dropdown-trigger--active .plan-anno-dropdown-trigger__arrow{transform:rotate(180deg)}.plan-anno-dropdown{position:absolute;top:100%;right:0;z-index:100;width:320px;max-height:300px;display:flex;flex-direction:column;background:var(--bg-secondary);border:1px solid var(--border);border-radius:4px;box-shadow:0 4px 12px #0000004d;overflow:hidden}.plan-anno-dropdown__header{display:flex;align-items:center;justify-content:center;padding:4px 6px;border-bottom:1px solid var(--border);flex-shrink:0}.plan-anno-dropdown__list{flex:1;overflow-y:auto;padding:2px 0}.plan-anno-dropdown__item{display:flex;align-items:center;gap:4px;padding:3px 6px;font-size:11px;border-bottom:1px solid var(--border-subtle, rgba(128,128,128,.1))}.plan-anno-dropdown__item:last-child{border-bottom:none}.plan-anno-dropdown__item--add{border-left:2px solid var(--accent-yellow)}.plan-anno-dropdown__item--del{border-left:2px solid var(--accent-red)}.plan-anno-dropdown__item--rep{border-left:2px solid var(--accent-blue)}.plan-anno-dropdown__item--com{border-left:2px solid var(--accent-green)}.plan-anno-dropdown__type{flex-shrink:0;width:14px;font-weight:700;text-align:center}.plan-anno-dropdown__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-primary)}.plan-anno-dropdown__badge{flex-shrink:0;font-size:9px;padding:0 4px;border-radius:3px;background:var(--accent-green);color:var(--bg-primary)}.plan-anno-dropdown__empty{padding:8px;text-align:center;font-size:11px;color:var(--text-secondary);font-style:italic}.plan-edit-textarea{width:100%;flex:1;resize:none;border:none;outline:none;padding:8px 12px;font-family:JetBrains Mono,LXGW WenKai Mono,Menlo,Monaco,Courier New,monospace;line-height:1.6;background:var(--bg-primary);color:var(--text-primary);-moz-tab-size:2;tab-size:2}.plan-edit-textarea::placeholder{color:var(--scrollbar-thumb-hover);font-style:italic}

Sorry, the diff of this file is too big to display