codex-lens 0.1.12 → 0.1.14
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/build.js +6 -2
- package/dist/aggregator.js +0 -100
- package/dist/public/assets/{main-DA0U-HuE.css → main-0MulWSMb.css} +1 -1
- package/dist/public/assets/{main-4W6-SFMa.js → main-gWFaVAuJ.js} +15 -15
- package/dist/public/index.html +2 -2
- package/package.json +1 -1
- package/src/aggregator.js +0 -116
- package/src/components/App.jsx +79 -193
- package/src/global.css +5 -37
- package/dist/snapshot-manager.js +0 -208
- package/src/snapshot-manager.js +0 -230
package/build.js
CHANGED
|
@@ -20,7 +20,6 @@ async function buildAll() {
|
|
|
20
20
|
'src/aggregator.js',
|
|
21
21
|
'src/watcher.js',
|
|
22
22
|
'src/pty-manager.js',
|
|
23
|
-
'src/snapshot-manager.js',
|
|
24
23
|
'src/lib/sse-parser.js',
|
|
25
24
|
'src/lib/diff-builder.js',
|
|
26
25
|
'src/lib/log-manager.js',
|
|
@@ -28,9 +27,14 @@ async function buildAll() {
|
|
|
28
27
|
];
|
|
29
28
|
|
|
30
29
|
for (const file of backendFiles) {
|
|
30
|
+
const fullPath = resolve(__dirname, file);
|
|
31
|
+
if (!existsSync(fullPath)) {
|
|
32
|
+
console.log(`Skipping (not found): ${file}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
31
35
|
try {
|
|
32
36
|
await esbuildBuild({
|
|
33
|
-
entryPoints: [
|
|
37
|
+
entryPoints: [fullPath],
|
|
34
38
|
outfile: resolve(__dirname, file.replace('src/', 'dist/')),
|
|
35
39
|
bundle: false,
|
|
36
40
|
platform: 'node',
|
package/dist/aggregator.js
CHANGED
|
@@ -8,7 +8,6 @@ import { createProxyServer } from "./proxy.js";
|
|
|
8
8
|
import { FileWatcher, scanDirectory } from "./watcher.js";
|
|
9
9
|
import { createLogger } from "./lib/logger.js";
|
|
10
10
|
import { spawnCodex, writeToPty, resizePty, killPty, onPtyData, onPtyExit, getPtyState, getOutputBuffer } from "./pty-manager.js";
|
|
11
|
-
import { SnapshotManager } from "./snapshot-manager.js";
|
|
12
11
|
import path from "path";
|
|
13
12
|
import { fileURLToPath } from "url";
|
|
14
13
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -51,9 +50,6 @@ class Aggregator {
|
|
|
51
50
|
this.proxyServer = null;
|
|
52
51
|
this.fileWatcher = null;
|
|
53
52
|
this.ptyProcess = null;
|
|
54
|
-
this.snapshotManager = new SnapshotManager();
|
|
55
|
-
this.currentTaskId = null;
|
|
56
|
-
this.taskStatus = "idle";
|
|
57
53
|
}
|
|
58
54
|
async start(proxyPort) {
|
|
59
55
|
await fetchLatestVersion();
|
|
@@ -214,103 +210,7 @@ class Aggregator {
|
|
|
214
210
|
}
|
|
215
211
|
}));
|
|
216
212
|
}
|
|
217
|
-
} else if (data.type === "start_task") {
|
|
218
|
-
this.handleStartTask(ws);
|
|
219
|
-
} else if (data.type === "rollback_task") {
|
|
220
|
-
this.handleRollbackTask(ws);
|
|
221
|
-
} else if (data.type === "complete_task") {
|
|
222
|
-
this.handleCompleteTask(ws);
|
|
223
|
-
} else if (data.type === "get_task_status") {
|
|
224
|
-
ws.send(JSON.stringify({
|
|
225
|
-
type: "task_status",
|
|
226
|
-
data: {
|
|
227
|
-
status: this.taskStatus,
|
|
228
|
-
taskId: this.currentTaskId
|
|
229
|
-
}
|
|
230
|
-
}));
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
async handleStartTask(ws) {
|
|
234
|
-
if (this.taskStatus === "running") {
|
|
235
|
-
ws.send(JSON.stringify({ type: "error", message: "Task already running" }));
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
this.currentTaskId = Date.now().toString();
|
|
239
|
-
this.taskStatus = "running";
|
|
240
|
-
const result = await this.snapshotManager.createSnapshot(this.projectRoot, this.currentTaskId);
|
|
241
|
-
if (result.success) {
|
|
242
|
-
logger.info(`Task started: ${this.currentTaskId}, ${result.filesCount} files snapshotted`);
|
|
243
|
-
this.broadcast({
|
|
244
|
-
type: "task_status",
|
|
245
|
-
data: {
|
|
246
|
-
status: this.taskStatus,
|
|
247
|
-
taskId: this.currentTaskId,
|
|
248
|
-
filesCount: result.filesCount
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
ws.send(JSON.stringify({
|
|
252
|
-
type: "task_started",
|
|
253
|
-
data: {
|
|
254
|
-
taskId: this.currentTaskId,
|
|
255
|
-
filesCount: result.filesCount
|
|
256
|
-
}
|
|
257
|
-
}));
|
|
258
|
-
} else {
|
|
259
|
-
this.taskStatus = "idle";
|
|
260
|
-
this.currentTaskId = null;
|
|
261
|
-
ws.send(JSON.stringify({ type: "error", message: "Failed to create snapshot: " + result.error }));
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
async handleRollbackTask(ws) {
|
|
265
|
-
if (!this.currentTaskId || this.taskStatus !== "running") {
|
|
266
|
-
ws.send(JSON.stringify({ type: "error", message: "No active task to rollback" }));
|
|
267
|
-
return;
|
|
268
213
|
}
|
|
269
|
-
const taskId = this.currentTaskId;
|
|
270
|
-
const result = await this.snapshotManager.restoreSnapshot(taskId);
|
|
271
|
-
if (result.success) {
|
|
272
|
-
await this.snapshotManager.deleteSnapshot(taskId);
|
|
273
|
-
logger.info(`Task rolled back: ${taskId}, ${result.restoredCount} files restored`);
|
|
274
|
-
this.taskStatus = "idle";
|
|
275
|
-
this.currentTaskId = null;
|
|
276
|
-
this.broadcast({
|
|
277
|
-
type: "task_status",
|
|
278
|
-
data: {
|
|
279
|
-
status: this.taskStatus,
|
|
280
|
-
taskId: null
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
ws.send(JSON.stringify({
|
|
284
|
-
type: "task_rolled_back",
|
|
285
|
-
data: {
|
|
286
|
-
restoredCount: result.restoredCount
|
|
287
|
-
}
|
|
288
|
-
}));
|
|
289
|
-
} else {
|
|
290
|
-
ws.send(JSON.stringify({ type: "error", message: "Failed to rollback: " + result.error }));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async handleCompleteTask(ws) {
|
|
294
|
-
if (!this.currentTaskId || this.taskStatus !== "running") {
|
|
295
|
-
ws.send(JSON.stringify({ type: "error", message: "No active task to complete" }));
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const taskId = this.currentTaskId;
|
|
299
|
-
await this.snapshotManager.deleteSnapshot(taskId);
|
|
300
|
-
logger.info(`Task completed: ${taskId}`);
|
|
301
|
-
this.taskStatus = "idle";
|
|
302
|
-
this.currentTaskId = null;
|
|
303
|
-
this.broadcast({
|
|
304
|
-
type: "task_status",
|
|
305
|
-
data: {
|
|
306
|
-
status: this.taskStatus,
|
|
307
|
-
taskId: null
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
ws.send(JSON.stringify({
|
|
311
|
-
type: "task_completed",
|
|
312
|
-
data: {}
|
|
313
|
-
}));
|
|
314
214
|
}
|
|
315
215
|
broadcast(event) {
|
|
316
216
|
const message = JSON.stringify(event);
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
* The original design remains. The terminal itself
|
|
30
30
|
* has been extended to include xterm CSI codes, among
|
|
31
31
|
* other features.
|
|
32
|
-
*/.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 .xterm-scroll-area{visibility:hidden}.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{-webkit-user-select:text;user-select:text;white-space:pre}.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}:root{--bg-primary: #0F172A;--bg-secondary: #1E293B;--bg-tertiary: #334155;--text-primary: #F8FAFC;--text-secondary: #94A3B8;--text-muted: #64748B;--border-color: #475569;--accent-color: #22C55E;--accent-hover: #16A34A;--accent-glow: rgba(34, 197, 94, .3);--diff-add-bg: rgba(34, 197, 94, .15);--diff-add-text: #4ADE80;--diff-add-border: #22C55E;--diff-remove-bg: rgba(239, 68, 68, .15);--diff-remove-text: #F87171;--diff-remove-border: #EF4444;--danger-color: #EF4444;--danger-hover: #DC2626;--success-color: #22C55E;--success-hover: #16A34A;--warning-color: #F59E0B;--font-family: "Fira Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono: "Fira Code", "SF Mono", "Consolas", "Monaco", monospace;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--shadow-lg: 0 8px 32px rgba(0, 0, 0, .5);--shadow-glow: 0 0 20px var(--accent-glow);--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--transition-fast: .15s ease;--transition-normal: .2s ease;--transition-slow: .3s ease}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{height:100%;width:100%;overflow:hidden}body{font-family:var(--font-family);background-color:var(--bg-primary);color:var(--text-primary);font-size:14px;line-height:1.6;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.app-container{display:flex;height:100vh;width:100vw}.panel{display:flex;flex-direction:column;overflow:hidden;background:var(--bg-secondary);border-right:1px solid var(--border-color)}.panel:last-child{border-right:none}.panel-header{padding:12px 16px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-secondary);display:flex;align-items:center;gap:8px}.panel-content{flex:1;overflow:auto}.file-tree{padding:8px}.file-item{padding:6px 12px;cursor:pointer;border-radius:var(--radius-sm);display:flex;align-items:center;gap:8px;transition:background var(--transition-fast),transform var(--transition-fast)}.file-item:hover{background:var(--bg-tertiary)}.file-item:active{transform:scale(.98)}.file-item.active{background:var(--accent-color);color:var(--text-primary);box-shadow:var(--shadow-glow)}.file-icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;font-size:14px}.file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-line{font-family:var(--font-mono);font-size:13px;padding:2px 16px;white-space:pre;border-left:3px solid transparent;transition:background var(--transition-fast)}.diff-line.added{background:var(--diff-add-bg);color:var(--diff-add-text);border-left-color:var(--diff-add-border)}.diff-line.removed{background:var(--diff-remove-bg);color:var(--diff-remove-text);border-left-color:var(--diff-remove-border)}.diff-line:before{display:inline-block;width:20px;margin-right:8px;text-align:center;font-weight:600}.diff-line.added:before{content:"+";color:var(--diff-add-text)}.diff-line.removed:before{content:"-";color:var(--diff-remove-text)}.chat-message{padding:12px 16px;margin:8px 12px;border-radius:var(--radius-lg);max-width:85%;line-height:1.5}.chat-message.user{background:var(--accent-color);color:#fff;margin-left:auto;box-shadow:var(--shadow-md)}.chat-message.codex{background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-color)}.chat-input-container{padding:12px;border-top:1px solid var(--border-color);background:var(--bg-secondary)}.chat-input{width:100%;padding:10px 14px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);font-family:var(--font-family);font-size:14px;resize:none;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.chat-input:focus{outline:none;border-color:var(--accent-color);box-shadow:var(--shadow-glow)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.ws-status{display:inline-block;width:8px;height:8px;border-radius:50%;margin-left:8px;transition:background var(--transition-normal),box-shadow var(--transition-normal)}.ws-status.connected{background:var(--success-color);box-shadow:0 0 8px var(--success-color)}.ws-status.disconnected{background:var(--danger-color);box-shadow:0 0 8px var(--danger-color)}.version-info{display:flex;align-items:center;gap:8px;margin-left:auto}.version-number{font-size:11px;color:var(--text-muted);font-weight:500;font-family:var(--font-mono)}.update-badge{font-size:10px;padding:3px 8px;background:var(--warning-color);color:var(--bg-primary);border-radius:var(--radius-sm);cursor:pointer;font-weight:600;transition:background var(--transition-fast),transform var(--transition-fast)}.update-badge:hover{background:#fbbf24;transform:translateY(-1px)}.terminal-wrapper{flex:1;overflow:hidden;min-height:0}.left-panel{width:260px;flex-shrink:0}.middle-panel{flex:1;min-width:300px}.right-panel{width:40%;min-width:300px;max-width:60%}.section{margin-bottom:16px}.section-title{padding:12px 16px 8px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.empty-state{padding:32px;text-align:center;color:var(--text-muted);font-size:13px;display:flex;flex-direction:column;align-items:center;gap:8px}.empty-state:before{content:"📄";font-size:32px;opacity:.5}.code-panel{font-family:var(--font-mono)}.code-content{padding:16px;white-space:pre-wrap;word-break:break-all;line-height:1.7}.diff-container{font-family:var(--font-mono);font-size:13px;padding:8px 0}.tab-bar{display:flex;background:var(--bg-primary);border-bottom:1px solid var(--border-color);overflow-x:auto;min-height:40px}.tab{display:flex;align-items:center;gap:8px;padding:10px 16px;background:var(--bg-secondary);border-right:1px solid var(--border-color);cursor:pointer;min-width:100px;max-width:200px;font-size:13px;color:var(--text-secondary);transition:background var(--transition-fast),color var(--transition-fast)}.tab:hover{background:var(--bg-tertiary);color:var(--text-primary)}.tab.active{background:var(--bg-primary);color:var(--text-primary);border-bottom:2px solid var(--accent-color)}.tab-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-close{background:none;border:none;color:var(--text-muted);font-size:14px;cursor:pointer;padding:2px 4px;border-radius:var(--radius-sm);line-height:1;transition:background var(--transition-fast),color var(--transition-fast)}.tab-close:hover{background:#ffffff1a;color:var(--text-primary)}.context-menu{position:fixed;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:4px 0;min-width:160px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease}@keyframes contextMenuIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.context-menu-item{padding:10px 16px;cursor:pointer;font-size:13px;color:var(--text-primary);transition:background var(--transition-fast),color var(--transition-fast)}.context-menu-item:hover{background:var(--accent-color);color:#fff}.file-context-menu{position:fixed;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:4px 0;min-width:180px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease}.task-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);min-height:48px}.task-status{display:flex;align-items:center;gap:10px;font-size:13px;font-weight:500}.task-status.idle{color:var(--text-muted)}.task-status.running{color:var(--accent-color)}.task-status:before{content:"";display:inline-block;width:8px;height:8px;border-radius:50%}.task-status.idle:before{background:var(--text-muted)}.task-status.running:before{background:var(--accent-color);box-shadow:0 0 8px var(--accent-color);animation:pulse 1.5s infinite}@keyframes pulse{0%,to{opacity:1;box-shadow:0 0 8px var(--accent-color)}50%{opacity:.6;box-shadow:0 0 4px var(--accent-color)}}.task-buttons{display:flex;gap:8px}.task-btn{padding:8px 16px;border:none;border-radius:var(--radius-sm);font-size:12px;font-weight:600;cursor:pointer;transition:background var(--transition-fast),transform var(--transition-fast),box-shadow var(--transition-fast);font-family:var(--font-family)}.task-btn:hover{transform:translateY(-1px)}.task-btn:active{transform:translateY(0)}.task-btn-start{background:var(--accent-color);color:#fff;box-shadow:var(--shadow-sm)}.task-btn-start:hover{background:var(--accent-hover);box-shadow:var(--shadow-glow)}.task-btn-start:disabled{background:var(--bg-tertiary);color:var(--text-muted);cursor:not-allowed;box-shadow:none}.task-btn-start:disabled:hover{transform:none}.task-btn-rollback{background:var(--danger-color);color:#fff}.task-btn-rollback:hover{background:var(--danger-hover);box-shadow:0 4px 12px #ef44444d}.task-btn-complete{background:var(--success-color);color:#fff}.task-btn-complete:hover{background:var(--success-hover);box-shadow:0 4px 12px #22c55e4d}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:2000;animation:modalOverlayIn .2s ease}@keyframes modalOverlayIn{0%{opacity:0}to{opacity:1}}.modal-content{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:24px;min-width:340px;max-width:420px;box-shadow:var(--shadow-lg);animation:modalContentIn .2s ease}@keyframes modalContentIn{0%{opacity:0;transform:scale(.95) translateY(-10px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-title{font-size:18px;font-weight:600;margin-bottom:12px;color:var(--text-primary)}.modal-body{font-size:14px;color:var(--text-secondary);margin-bottom:24px;line-height:1.7}.modal-buttons{display:flex;justify-content:flex-end;gap:12px}.modal-btn{padding:10px 20px;border:none;border-radius:var(--radius-sm);font-size:13px;font-weight:600;cursor:pointer;transition:background var(--transition-fast),transform var(--transition-fast);font-family:var(--font-family)}.modal-btn:hover{transform:translateY(-1px)}.modal-btn:active{transform:translateY(0)}.modal-btn-cancel{background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-color)}.modal-btn-cancel:hover{background:var(--border-color)}.modal-btn-danger{background:var(--danger-color);color:#fff}.modal-btn-danger:hover{background:var(--danger-hover);box-shadow:0 4px 12px #ef44444d}@media (max-width: 768px){.left-panel{width:200px}.right-panel{width:50%;min-width:200px}}@media (max-width: 480px){.app-container{flex-direction:column}.left-panel,.right-panel{width:100%;max-width:none;min-width:auto}.middle-panel{min-height:300px}}
|
|
32
|
+
*/.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 .xterm-scroll-area{visibility:hidden}.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{-webkit-user-select:text;user-select:text;white-space:pre}.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}:root{--bg-primary: #0F172A;--bg-secondary: #1E293B;--bg-tertiary: #334155;--text-primary: #F8FAFC;--text-secondary: #94A3B8;--text-muted: #64748B;--border-color: #475569;--accent-color: #22C55E;--accent-hover: #16A34A;--accent-glow: rgba(34, 197, 94, .3);--diff-add-bg: rgba(34, 197, 94, .15);--diff-add-text: #4ADE80;--diff-add-border: #22C55E;--diff-remove-bg: rgba(239, 68, 68, .15);--diff-remove-text: #F87171;--diff-remove-border: #EF4444;--danger-color: #EF4444;--danger-hover: #DC2626;--success-color: #22C55E;--success-hover: #16A34A;--warning-color: #F59E0B;--font-family: "Fira Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono: "Fira Code", "SF Mono", "Consolas", "Monaco", monospace;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--shadow-lg: 0 8px 32px rgba(0, 0, 0, .5);--shadow-glow: 0 0 20px var(--accent-glow);--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--transition-fast: .15s ease;--transition-normal: .2s ease;--transition-slow: .3s ease}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{height:100%;width:100%;overflow:hidden}body{font-family:var(--font-family);background-color:var(--bg-primary);color:var(--text-primary);font-size:14px;line-height:1.6;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.app-container{display:flex;height:100vh;width:100vw}.panel{display:flex;flex-direction:column;overflow:hidden;background:var(--bg-secondary);border-right:1px solid var(--border-color)}.panel:last-child{border-right:none}.panel-header{padding:12px 16px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-secondary);display:flex;align-items:center;gap:8px}.panel-content{flex:1;overflow:auto}.file-tree{padding:8px}.file-item{padding:6px 12px;cursor:pointer;border-radius:var(--radius-sm);display:flex;align-items:center;gap:8px;transition:background var(--transition-fast),transform var(--transition-fast)}.file-item:hover{background:var(--bg-tertiary)}.file-item:active{transform:scale(.98)}.file-item.active{background:var(--accent-color);color:var(--text-primary);box-shadow:var(--shadow-glow)}.file-icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;font-size:14px}.file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-line{font-family:var(--font-mono);font-size:13px;padding:2px 16px;white-space:pre;border-left:3px solid transparent;transition:background var(--transition-fast)}.diff-line.added{background:var(--diff-add-bg);color:var(--diff-add-text);border-left-color:var(--diff-add-border)}.diff-line.removed{background:var(--diff-remove-bg);color:var(--diff-remove-text);border-left-color:var(--diff-remove-border)}.diff-line:before{display:inline-block;width:20px;margin-right:8px;text-align:center;font-weight:600}.diff-line.added:before{content:"+";color:var(--diff-add-text)}.diff-line.removed:before{content:"-";color:var(--diff-remove-text)}.chat-message{padding:12px 16px;margin:8px 12px;border-radius:var(--radius-lg);max-width:85%;line-height:1.5}.chat-message.user{background:var(--accent-color);color:#fff;margin-left:auto;box-shadow:var(--shadow-md)}.chat-message.codex{background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-color)}.chat-input-container{padding:12px;border-top:1px solid var(--border-color);background:var(--bg-secondary)}.chat-input{width:100%;padding:10px 14px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);font-family:var(--font-family);font-size:14px;resize:none;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.chat-input:focus{outline:none;border-color:var(--accent-color);box-shadow:var(--shadow-glow)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.ws-status{display:inline-block;width:8px;height:8px;border-radius:50%;margin-left:8px;transition:background var(--transition-normal),box-shadow var(--transition-normal)}.ws-status.connected{background:var(--success-color);box-shadow:0 0 8px var(--success-color)}.ws-status.disconnected{background:var(--danger-color);box-shadow:0 0 8px var(--danger-color)}.version-info{display:flex;align-items:center;gap:8px;margin-left:auto}.version-number{font-size:11px;color:var(--text-muted);font-weight:500;font-family:var(--font-mono)}.update-badge{font-size:10px;padding:3px 8px;background:var(--warning-color);color:var(--bg-primary);border-radius:var(--radius-sm);cursor:pointer;font-weight:600;transition:background var(--transition-fast),transform var(--transition-fast)}.update-badge:hover{background:#fbbf24;transform:translateY(-1px)}.terminal-wrapper{flex:1;overflow:hidden;min-height:0}.left-panel{width:260px;flex-shrink:0}.middle-panel{flex:1;min-width:300px}.right-panel{width:40%;min-width:300px;max-width:60%}.section{margin-bottom:16px}.section-title{padding:12px 16px 8px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.empty-state{padding:32px;text-align:center;color:var(--text-muted);font-size:13px;display:flex;flex-direction:column;align-items:center;gap:8px}.empty-state:before{content:"📄";font-size:32px;opacity:.5}.code-panel{font-family:var(--font-mono)}.code-content{padding:16px;white-space:pre-wrap;word-break:break-all;line-height:1.7}.diff-container{font-family:var(--font-mono);font-size:13px;padding:8px 0}.tab-bar{display:flex;background:var(--bg-primary);border-bottom:1px solid var(--border-color);overflow-x:auto;min-height:40px}.tab{display:flex;align-items:center;gap:8px;padding:10px 16px;background:var(--bg-secondary);border-right:1px solid var(--border-color);cursor:pointer;min-width:100px;max-width:200px;font-size:13px;color:var(--text-secondary);transition:background var(--transition-fast),color var(--transition-fast)}.tab:hover{background:var(--bg-tertiary);color:var(--text-primary)}.tab.active{background:var(--bg-primary);color:var(--text-primary);border-bottom:2px solid var(--accent-color)}.tab-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-close{background:none;border:none;color:var(--text-muted);font-size:14px;cursor:pointer;padding:2px 4px;border-radius:var(--radius-sm);line-height:1;transition:background var(--transition-fast),color var(--transition-fast)}.tab-close:hover{background:#ffffff1a;color:var(--text-primary)}.context-menu{position:fixed;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:4px 0;min-width:160px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease}@keyframes contextMenuIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.context-menu-item{padding:10px 16px;cursor:pointer;font-size:13px;color:var(--text-primary);transition:background var(--transition-fast),color var(--transition-fast)}.context-menu-item:hover{background:var(--accent-color);color:#fff}.file-context-menu{position:fixed;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:4px 0;min-width:180px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease}.task-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);min-height:48px}.task-status{display:flex;align-items:center;gap:10px;font-size:13px;font-weight:500}.task-status.idle{color:var(--text-muted)}.task-status.running{color:var(--accent-color)}.task-status:before{content:"";display:inline-block;width:8px;height:8px;border-radius:50%}.task-status.idle:before{background:var(--text-muted)}.task-status.running:before{background:var(--accent-color);box-shadow:0 0 8px var(--accent-color);animation:pulse 1.5s infinite}@keyframes pulse{0%,to{opacity:1;box-shadow:0 0 8px var(--accent-color)}50%{opacity:.6;box-shadow:0 0 4px var(--accent-color)}}.task-buttons{display:flex;gap:8px}.task-btn{padding:8px 16px;border:none;border-radius:var(--radius-sm);font-size:12px;font-weight:600;cursor:pointer;transition:background var(--transition-fast),transform var(--transition-fast),box-shadow var(--transition-fast);font-family:var(--font-family)}.task-btn:hover{transform:translateY(-1px)}.task-btn:active{transform:translateY(0)}.task-btn-clear{background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-color)}.task-btn-clear:hover{background:var(--border-color)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:2000;animation:modalOverlayIn .2s ease}@keyframes modalOverlayIn{0%{opacity:0}to{opacity:1}}.modal-content{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:24px;min-width:340px;max-width:420px;box-shadow:var(--shadow-lg);animation:modalContentIn .2s ease}@keyframes modalContentIn{0%{opacity:0;transform:scale(.95) translateY(-10px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-title{font-size:18px;font-weight:600;margin-bottom:12px;color:var(--text-primary)}.modal-body{font-size:14px;color:var(--text-secondary);margin-bottom:24px;line-height:1.7}.modal-buttons{display:flex;justify-content:flex-end;gap:12px}.modal-btn{padding:10px 20px;border:none;border-radius:var(--radius-sm);font-size:13px;font-weight:600;cursor:pointer;transition:background var(--transition-fast),transform var(--transition-fast);font-family:var(--font-family)}.modal-btn:hover{transform:translateY(-1px)}.modal-btn:active{transform:translateY(0)}.modal-btn-cancel{background:var(--bg-tertiary);color:var(--text-primary);border:1px solid var(--border-color)}.modal-btn-cancel:hover{background:var(--border-color)}.modal-btn-danger{background:var(--danger-color);color:#fff}.modal-btn-danger:hover{background:var(--danger-hover);box-shadow:0 4px 12px #ef44444d}@media (max-width: 768px){.left-panel{width:200px}.right-panel{width:50%;min-width:200px}}@media (max-width: 480px){.app-container{flex-direction:column}.left-panel,.right-panel{width:100%;max-width:none;min-width:auto}.middle-panel{min-height:300px}}
|