codex-lens 0.1.34 → 0.1.36

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.
@@ -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: #000000;--bg-secondary: #0A0A0A;--bg-tertiary: #141414;--bg-elevated: #1A1A1A;--bg-surface: #0F0F0F;--text-primary: #F8FAFC;--text-secondary: #94A3B8;--text-muted: #64748B;--border-color: rgba(148, 163, 184, .15);--border-glow: rgba(34, 197, 94, .3);--accent-color: #22C55E;--accent-hover: #16A34A;--accent-glow: rgba(34, 197, 94, .4);--accent-soft: rgba(34, 197, 94, .1);--diff-add-bg: rgba(34, 197, 94, .12);--diff-add-text: #4ADE80;--diff-add-border: #22C55E;--diff-remove-bg: rgba(239, 68, 68, .12);--diff-remove-text: #F87171;--diff-remove-border: #EF4444;--danger-color: #EF4444;--danger-hover: #DC2626;--success-color: #22C55E;--success-hover: #16A34A;--warning-color: #F59E0B;--info-color: #3B82F6;--font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono: "JetBrains Mono", "Fira Code", "SF Mono", "Consolas", monospace;--shadow-xs: 0 1px 2px rgba(0, 0, 0, .2);--shadow-sm: 0 2px 4px rgba(0, 0, 0, .2);--shadow-md: 0 4px 12px rgba(0, 0, 0, .3);--shadow-lg: 0 8px 24px rgba(0, 0, 0, .4);--shadow-xl: 0 16px 48px rgba(0, 0, 0, .5);--shadow-glow: 0 0 24px var(--accent-glow);--shadow-glow-sm: 0 0 12px var(--accent-glow);--radius-xs: 4px;--radius-sm: 6px;--radius-md: 10px;--radius-lg: 14px;--radius-xl: 20px;--transition-fast: .12s ease;--transition-normal: .2s ease;--transition-slow: .3s ease;--blur-sm: 8px;--blur-md: 16px;--blur-lg: 24px}@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: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;flex-direction:column;height:100vh;width:100vw;background:var(--bg-primary)}.top-bar{display:flex;align-items:center;justify-content:space-between;padding:12px 20px;background:linear-gradient(180deg,#1e293bf2,#1e293bd9);-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));border-bottom:1px solid var(--border-color);min-height:52px;position:relative;z-index:100}.top-bar:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--accent-color),transparent);opacity:.3}.top-bar-left,.top-bar-center,.top-bar-right{display:flex;align-items:center;gap:16px}.top-bar-left{width:260px}.top-bar-center{flex:1;justify-content:center}.top-bar-right{width:40%;justify-content:flex-end}.top-bar-title{font-family:var(--font-display);font-weight:600;font-size:13px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:flex;align-items:center;gap:8px}.top-bar-title:before{content:"";display:inline-block;width:3px;height:14px;background:var(--accent-color);border-radius:2px}.main-content{display:flex;flex:1;overflow:hidden;gap:1px;background:var(--border-color)}.panel{display:flex;flex-direction:column;overflow:hidden;background:linear-gradient(180deg,var(--bg-secondary) 0%,rgba(30,41,59,.95) 100%)}.left-panel{width:260px;flex-shrink:0}.middle-panel{flex:1;min-width:300px}.right-panel{width:40%;min-width:300px;max-width:60%}.panel-content{flex:1;overflow:auto;padding:8px}.file-tree{padding:4px}.file-item{padding:8px 12px;cursor:pointer;border-radius:var(--radius-sm);display:flex;align-items:center;gap:10px;transition:all var(--transition-fast);position:relative;margin:2px 0}.file-item:before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:0;background:var(--accent-color);border-radius:0 2px 2px 0;transition:height var(--transition-fast)}.file-item:hover{background:#94a3b814}.file-item:hover:before{height:60%}.file-item:active{transform:scale(.98)}.file-item.active{background:var(--accent-soft);color:var(--text-primary)}.file-item.active:before{height:70%}.file-icon{width:18px;height:18px;display:flex;align-items:center;justify-content:center;font-size:14px;opacity:.9}.file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.diff-line{font-family:var(--font-mono);font-size:13px;padding:3px 16px 3px 20px;white-space:pre;border-left:3px solid transparent;transition:background var(--transition-fast);position:relative}.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:16px;margin-left:-16px;text-align:center;font-weight:600;font-size:12px}.diff-line.added:before{content:"+";color:var(--diff-add-text)}.diff-line.removed:before{content:"-";color:var(--diff-remove-text)}.tab-bar{display:flex;background:#0f172a99;border-bottom:1px solid var(--border-color);overflow-x:auto;min-height:40px;scrollbar-width:none}.tab-bar::-webkit-scrollbar{display:none}.tab{display:flex;align-items:center;gap:8px;padding:10px 16px;background:transparent;border-right:1px solid var(--border-color);cursor:pointer;min-width:100px;max-width:180px;font-size:13px;color:var(--text-muted);transition:all var(--transition-fast);position:relative}.tab:hover{background:#94a3b80d;color:var(--text-secondary)}.tab.active{background:var(--bg-secondary);color:var(--text-primary)}.tab.active:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background: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:16px;cursor:pointer;padding:2px 6px;border-radius:var(--radius-xs);line-height:1;transition:all var(--transition-fast);opacity:.6}.tab-close:hover{background:#ef444433;color:var(--danger-color);opacity:1}.tab.modified .tab-name{color:var(--accent-color)}.tab-modified-mark{color:var(--accent-color);margin-right:4px;font-size:10px}.context-menu{position:fixed;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:6px;min-width:160px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease;-webkit-backdrop-filter:blur(var(--blur-sm));backdrop-filter:blur(var(--blur-sm))}@keyframes contextMenuIn{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.context-menu-item{padding:10px 14px;cursor:pointer;font-size:13px;color:var(--text-primary);border-radius:var(--radius-sm);transition:all var(--transition-fast)}.context-menu-item:hover{background:var(--accent-soft);color:var(--accent-color)}.file-context-menu{position:fixed;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:6px;min-width:200px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease;-webkit-backdrop-filter:blur(var(--blur-sm));backdrop-filter:blur(var(--blur-sm))}.ws-status{display:inline-block;width:8px;height:8px;border-radius:50%;margin-left:8px;transition:all var(--transition-normal)}.ws-status.connected{background:var(--success-color);box-shadow:0 0 8px var(--success-color);animation:pulse 2s infinite}.ws-status.disconnected{background:var(--danger-color);box-shadow:0 0 8px var(--danger-color)}@keyframes pulse{0%,to{opacity:1;box-shadow:0 0 8px var(--success-color)}50%{opacity:.7;box-shadow:0 0 4px var(--success-color)}}.version-info{display:flex;align-items:center;gap:10px}.version-number{font-size:11px;color:var(--text-muted);font-weight:500;font-family:var(--font-mono);padding:3px 8px;background:#94a3b81a;border-radius:var(--radius-xs)}.update-badge{font-size:10px;padding:4px 10px;background:linear-gradient(135deg,var(--warning-color) 0%,#FBBF24 100%);color:var(--bg-primary);border-radius:var(--radius-sm);cursor:pointer;font-weight:600;transition:all var(--transition-fast)}.update-badge:hover{transform:translateY(-1px);box-shadow:0 4px 12px #f59e0b4d}.terminal-wrapper{flex:1;overflow:hidden;min-height:0}.section{margin-bottom:8px}.section-title{padding:10px 12px 6px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px}.empty-state{padding:40px 24px;text-align:center;color:var(--text-muted);font-size:13px;display:flex;flex-direction:column;align-items:center;gap:12px}.empty-state:before{content:"";width:48px;height:48px;background:linear-gradient(135deg,var(--bg-tertiary) 0%,var(--bg-elevated) 100%);border-radius:var(--radius-lg);display:flex;align-items:center;justify-content:center}.code-panel{font-family:var(--font-mono)}.code-viewer-codemirror{height:100%;width:100%;display:flex;min-height:0;min-width:0}.code-viewer-codemirror .cm-theme{flex:1;display:flex;min-height:0;min-width:0}.code-viewer-codemirror .cm-editor{flex:1;min-width:0;min-height:0}.code-viewer-codemirror .cm-scroller{flex:1;overflow:auto!important;min-height:0}.code-content{padding:16px;white-space:pre-wrap;word-break:break-all;line-height:1.7;font-size:13px}.diff-container{font-family:var(--font-mono);font-size:13px;padding:8px 0}.task-btn{padding:8px 18px;border:none;border-radius:var(--radius-sm);font-size:12px;font-weight:600;cursor:pointer;transition:all var(--transition-fast);font-family:var(--font-family);display:inline-flex;align-items:center;gap:6px}.task-btn:hover{transform:translateY(-1px)}.task-btn:active{transform:translateY(0)}.task-btn-clear{background:transparent;color:var(--text-secondary);border:1px solid var(--border-color)}.task-btn-clear:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color);box-shadow:var(--shadow-glow-sm)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}::-webkit-scrollbar-corner{background:transparent}.git-status-bar{display:flex;align-items:center;gap:16px;padding:6px 14px;background:#94a3b814;border-radius:var(--radius-sm);border:1px solid var(--border-color)}.git-branch{display:flex;align-items:center;gap:6px;font-family:var(--font-mono);font-size:12px;font-weight:600;color:var(--accent-color)}.git-branch-icon{font-size:14px;opacity:.8}.git-stats{display:flex;align-items:center;gap:12px}.git-staged,.git-unstaged{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary)}.git-staged-count{font-weight:600;color:var(--success-color)}.git-unstaged-count{font-weight:600;color:var(--warning-color)}.git-changes-btn{padding:4px 10px;font-size:11px;background:transparent;border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.git-changes-btn:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color)}.staged-changes-panel{position:absolute;top:52px;left:0;right:0;max-height:400px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);z-index:99;overflow-y:auto;animation:slideDown .2s ease}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.staged-panel-header{display:flex;justify-content:space-between;align-items:center;padding:10px 16px;background:#0f172a99;border-bottom:1px solid var(--border-color);font-weight:600;font-size:12px;color:var(--text-secondary)}.staged-panel-actions{display:flex;gap:8px;align-items:center}.stage-btn,.unstage-btn{padding:4px 10px;font-size:11px;background:var(--bg-elevated);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.stage-btn:hover,.unstage-btn:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color)}.close-btn{width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:16px;border-radius:var(--radius-xs);transition:all var(--transition-fast)}.close-btn:hover{background:#ef444433;color:var(--danger-color)}.changes-section{padding:8px 0;border-bottom:1px solid var(--border-color)}.changes-section:last-child{border-bottom:none}.changes-section-header{padding:4px 16px}.changes-section-title{font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.changes-list{display:flex;flex-direction:column}.change-item{display:flex;align-items:center;gap:8px;padding:6px 16px;cursor:pointer;transition:background var(--transition-fast)}.change-item:hover{background:#94a3b814}.change-item.staged{background:var(--accent-soft)}.change-icon{width:16px;text-align:center;font-size:12px;color:var(--text-muted)}.change-item.staged .change-icon{color:var(--success-color)}.change-status{width:14px;height:14px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;font-family:var(--font-mono);border-radius:2px}.change-status.M{background:var(--warning-color);color:var(--bg-primary)}.change-status.A{background:var(--success-color);color:var(--bg-primary)}.change-status.D{background:var(--danger-color);color:var(--text-primary)}.change-status.R{background:var(--info-color);color:var(--text-primary)}.change-status.\?{background:var(--text-muted);color:var(--bg-primary)}.change-path{flex:1;font-size:12px;font-family:var(--font-mono);color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.no-changes{padding:24px;text-align:center;color:var(--text-muted);font-size:13px}.commit-section{display:flex;gap:8px;padding:12px 16px;background:#0f172a99;border-top:1px solid var(--border-color)}.commit-input{flex:1;padding:8px 12px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-sm);color:var(--text-primary);font-size:12px;font-family:var(--font-family)}.commit-input:focus{outline:none;border-color:var(--accent-color)}.commit-btn{padding:8px 16px;background:var(--accent-color);border:none;border-radius:var(--radius-sm);color:var(--bg-primary);font-size:12px;font-weight:600;cursor:pointer;transition:all var(--transition-fast)}.commit-btn:hover{background:var(--accent-hover);transform:translateY(-1px)}.file-git-badge{width:14px;height:14px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;font-family:var(--font-mono);border-radius:2px;margin-left:auto;flex-shrink:0}.file-git-badge.staged{background:var(--success-color);color:var(--bg-primary)}.file-git-badge.wt{background:var(--warning-color);color:var(--bg-primary)}@media (max-width: 1024px){.left-panel{width:220px}.right-panel{width:45%;min-width:250px}.top-bar-left{width:220px}}@media (max-width: 768px){.main-content{flex-direction:column}.left-panel,.right-panel{width:100%;max-width:none;min-width:auto}.middle-panel{min-height:300px}.top-bar{flex-wrap:wrap;padding:10px 16px}.top-bar-left,.top-bar-center,.top-bar-right{width:auto}.top-bar-center{order:3;width:100%;justify-content:flex-start;margin-top:8px;padding-top:8px;border-top:1px solid var(--border-color)}}
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: #000000;--bg-secondary: #0A0A0A;--bg-tertiary: #141414;--bg-elevated: #1A1A1A;--bg-surface: #0F0F0F;--text-primary: #F8FAFC;--text-secondary: #94A3B8;--text-muted: #64748B;--border-color: rgba(148, 163, 184, .15);--border-glow: rgba(34, 197, 94, .3);--accent-color: #22C55E;--accent-hover: #16A34A;--accent-glow: rgba(34, 197, 94, .4);--accent-soft: rgba(34, 197, 94, .1);--diff-add-bg: rgba(34, 197, 94, .12);--diff-add-text: #4ADE80;--diff-add-border: #22C55E;--diff-remove-bg: rgba(239, 68, 68, .12);--diff-remove-text: #F87171;--diff-remove-border: #EF4444;--danger-color: #EF4444;--danger-hover: #DC2626;--success-color: #22C55E;--success-hover: #16A34A;--warning-color: #F59E0B;--info-color: #3B82F6;--font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono: "JetBrains Mono", "Fira Code", "SF Mono", "Consolas", monospace;--shadow-xs: 0 1px 2px rgba(0, 0, 0, .2);--shadow-sm: 0 2px 4px rgba(0, 0, 0, .2);--shadow-md: 0 4px 12px rgba(0, 0, 0, .3);--shadow-lg: 0 8px 24px rgba(0, 0, 0, .4);--shadow-xl: 0 16px 48px rgba(0, 0, 0, .5);--shadow-glow: 0 0 24px var(--accent-glow);--shadow-glow-sm: 0 0 12px var(--accent-glow);--radius-xs: 4px;--radius-sm: 6px;--radius-md: 10px;--radius-lg: 14px;--radius-xl: 20px;--transition-fast: .12s ease;--transition-normal: .2s ease;--transition-slow: .3s ease;--blur-sm: 8px;--blur-md: 16px;--blur-lg: 24px}@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: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;flex-direction:column;height:100vh;width:100vw;background:var(--bg-primary)}.top-bar{display:flex;align-items:center;justify-content:space-between;padding:12px 20px;background:linear-gradient(180deg,#1e293bf2,#1e293bd9);-webkit-backdrop-filter:blur(var(--blur-md));backdrop-filter:blur(var(--blur-md));border-bottom:1px solid var(--border-color);min-height:52px;position:relative;z-index:100}.top-bar:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--accent-color),transparent);opacity:.3}.top-bar-left,.top-bar-center,.top-bar-right{display:flex;align-items:center;gap:16px}.top-bar-left{width:260px}.top-bar-center{flex:1;justify-content:center}.top-bar-right{width:40%;justify-content:flex-end}.top-bar-title{font-family:var(--font-display);font-weight:600;font-size:13px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:flex;align-items:center;gap:8px}.top-bar-title:before{content:"";display:inline-block;width:3px;height:14px;background:var(--accent-color);border-radius:2px}.main-content{display:flex;flex:1;overflow:hidden;gap:1px;background:var(--border-color)}.panel{display:flex;flex-direction:column;overflow:hidden;background:linear-gradient(180deg,var(--bg-secondary) 0%,rgba(30,41,59,.95) 100%)}.left-panel{width:260px;flex-shrink:0}.middle-panel{flex:1;min-width:300px}.right-panel{width:40%;min-width:300px;max-width:60%}.panel-content{flex:1;overflow:auto;padding:8px}.file-tree{padding:4px}.file-item{padding:8px 12px;cursor:pointer;border-radius:var(--radius-sm);display:flex;align-items:center;gap:10px;transition:all var(--transition-fast);position:relative;margin:2px 0}.file-item:before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:0;background:var(--accent-color);border-radius:0 2px 2px 0;transition:height var(--transition-fast)}.file-item:hover{background:#94a3b814}.file-item:hover:before{height:60%}.file-item:active{transform:scale(.98)}.file-item.active{background:var(--accent-soft);color:var(--text-primary)}.file-item.active:before{height:70%}.file-icon{width:18px;height:18px;display:flex;align-items:center;justify-content:center;font-size:14px;opacity:.9}.file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.diff-line{font-family:var(--font-mono);font-size:13px;padding:3px 16px 3px 20px;white-space:pre;border-left:3px solid transparent;transition:background var(--transition-fast);position:relative}.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:16px;margin-left:-16px;text-align:center;font-weight:600;font-size:12px}.diff-line.added:before{content:"+";color:var(--diff-add-text)}.diff-line.removed:before{content:"-";color:var(--diff-remove-text)}.tab-bar{display:flex;background:#0f172a99;border-bottom:1px solid var(--border-color);overflow-x:auto;min-height:40px;scrollbar-width:none}.tab-bar::-webkit-scrollbar{display:none}.tab{display:flex;align-items:center;gap:8px;padding:10px 16px;background:transparent;border-right:1px solid var(--border-color);cursor:pointer;min-width:100px;max-width:180px;font-size:13px;color:var(--text-muted);transition:all var(--transition-fast);position:relative}.tab:hover{background:#94a3b80d;color:var(--text-secondary)}.tab.active{background:var(--bg-secondary);color:var(--text-primary)}.tab.active:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background: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:16px;cursor:pointer;padding:2px 6px;border-radius:var(--radius-xs);line-height:1;transition:all var(--transition-fast);opacity:.6}.tab-close:hover{background:#ef444433;color:var(--danger-color);opacity:1}.tab.modified .tab-name{color:var(--accent-color)}.tab-modified-mark{color:var(--accent-color);margin-right:4px;font-size:10px}.context-menu{position:fixed;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:6px;min-width:160px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease;-webkit-backdrop-filter:blur(var(--blur-sm));backdrop-filter:blur(var(--blur-sm))}@keyframes contextMenuIn{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.context-menu-item{padding:10px 14px;cursor:pointer;font-size:13px;color:var(--text-primary);border-radius:var(--radius-sm);transition:all var(--transition-fast)}.context-menu-item:hover{background:var(--accent-soft);color:var(--accent-color)}.file-context-menu{position:fixed;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:6px;min-width:200px;box-shadow:var(--shadow-lg);z-index:1000;animation:contextMenuIn .15s ease;-webkit-backdrop-filter:blur(var(--blur-sm));backdrop-filter:blur(var(--blur-sm))}.ws-status{display:inline-block;width:8px;height:8px;border-radius:50%;margin-left:8px;transition:all var(--transition-normal)}.ws-status.connected{background:var(--success-color);box-shadow:0 0 8px var(--success-color);animation:pulse 2s infinite}.ws-status.disconnected{background:var(--danger-color);box-shadow:0 0 8px var(--danger-color)}@keyframes pulse{0%,to{opacity:1;box-shadow:0 0 8px var(--success-color)}50%{opacity:.7;box-shadow:0 0 4px var(--success-color)}}.version-info{display:flex;align-items:center;gap:10px}.version-number{font-size:11px;color:var(--text-muted);font-weight:500;font-family:var(--font-mono);padding:3px 8px;background:#94a3b81a;border-radius:var(--radius-xs)}.update-badge{font-size:10px;padding:4px 10px;background:linear-gradient(135deg,var(--warning-color) 0%,#FBBF24 100%);color:var(--bg-primary);border-radius:var(--radius-sm);cursor:pointer;font-weight:600;transition:all var(--transition-fast)}.update-badge:hover{transform:translateY(-1px);box-shadow:0 4px 12px #f59e0b4d}.terminal-wrapper{flex:1;overflow:hidden;min-height:0}.section{margin-bottom:8px}.section-title{padding:10px 12px 6px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px}.empty-state{padding:40px 24px;text-align:center;color:var(--text-muted);font-size:13px;display:flex;flex-direction:column;align-items:center;gap:12px}.empty-state:before{content:"";width:48px;height:48px;background:linear-gradient(135deg,var(--bg-tertiary) 0%,var(--bg-elevated) 100%);border-radius:var(--radius-lg);display:flex;align-items:center;justify-content:center}.code-panel{font-family:var(--font-mono)}.code-viewer-codemirror{height:100%;width:100%;display:flex;min-height:0;min-width:0}.code-viewer-codemirror .cm-theme{flex:1;display:flex;min-height:0;min-width:0}.code-viewer-codemirror .cm-editor{flex:1;min-width:0;min-height:0}.code-viewer-codemirror .cm-scroller{flex:1;overflow:auto!important;min-height:0}.code-content{padding:16px;white-space:pre-wrap;word-break:break-all;line-height:1.7;font-size:13px}.diff-container{font-family:var(--font-mono);font-size:13px;padding:8px 0}.task-btn{padding:8px 18px;border:none;border-radius:var(--radius-sm);font-size:12px;font-weight:600;cursor:pointer;transition:all var(--transition-fast);font-family:var(--font-family);display:inline-flex;align-items:center;gap:6px}.task-btn:hover{transform:translateY(-1px)}.task-btn:active{transform:translateY(0)}.task-btn-clear{background:transparent;color:var(--text-secondary);border:1px solid var(--border-color)}.task-btn-clear:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color);box-shadow:var(--shadow-glow-sm)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}::-webkit-scrollbar-corner{background:transparent}.git-status-bar{display:flex;align-items:center;gap:16px;padding:6px 14px;background:#94a3b814;border-radius:var(--radius-sm);border:1px solid var(--border-color)}.git-branch{display:flex;align-items:center;gap:6px;font-family:var(--font-mono);font-size:12px;font-weight:600;color:var(--accent-color)}.git-branch-icon{font-size:14px;opacity:.8}.git-stats{display:flex;align-items:center;gap:12px}.git-staged,.git-unstaged{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary)}.git-staged-count{font-weight:600;color:var(--success-color)}.git-unstaged-count{font-weight:600;color:var(--warning-color)}.git-changes-btn{padding:4px 10px;font-size:11px;background:transparent;border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.git-changes-btn:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color)}.staged-changes-panel{position:absolute;top:52px;left:0;right:0;max-height:400px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:1px solid var(--border-color);z-index:99;overflow-y:auto;animation:slideDown .2s ease}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.staged-panel-header{display:flex;justify-content:space-between;align-items:center;padding:10px 16px;background:#0f172a99;border-bottom:1px solid var(--border-color);font-weight:600;font-size:12px;color:var(--text-secondary)}.staged-panel-actions{display:flex;gap:8px;align-items:center}.stage-btn,.unstage-btn{padding:4px 10px;font-size:11px;background:var(--bg-elevated);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.stage-btn:hover,.unstage-btn:hover{background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color)}.close-btn{width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:16px;border-radius:var(--radius-xs);transition:all var(--transition-fast)}.close-btn:hover{background:#ef444433;color:var(--danger-color)}.changes-section{padding:8px 0;border-bottom:1px solid var(--border-color)}.changes-section:last-child{border-bottom:none}.changes-section-header{padding:4px 16px}.changes-section-title{font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.changes-list{display:flex;flex-direction:column}.change-item{display:flex;align-items:center;gap:8px;padding:6px 16px;cursor:pointer;transition:background var(--transition-fast)}.change-item:hover{background:#94a3b814}.change-item.staged{background:var(--accent-soft)}.change-icon{width:16px;text-align:center;font-size:12px;color:var(--text-muted)}.change-item.staged .change-icon{color:var(--success-color)}.change-status{width:14px;height:14px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;font-family:var(--font-mono);border-radius:2px}.change-status.M{background:var(--warning-color);color:var(--bg-primary)}.change-status.A{background:var(--success-color);color:var(--bg-primary)}.change-status.D{background:var(--danger-color);color:var(--text-primary)}.change-status.R{background:var(--info-color);color:var(--text-primary)}.change-status.\?{background:var(--text-muted);color:var(--bg-primary)}.change-path{flex:1;font-size:12px;font-family:var(--font-mono);color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.no-changes{padding:24px;text-align:center;color:var(--text-muted);font-size:13px}.commit-section{display:flex;gap:8px;padding:12px 16px;background:#0f172a99;border-top:1px solid var(--border-color)}.commit-input{flex:1;padding:8px 12px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-sm);color:var(--text-primary);font-size:12px;font-family:var(--font-family)}.commit-input:focus{outline:none;border-color:var(--accent-color)}.commit-btn{padding:8px 16px;background:var(--accent-color);border:none;border-radius:var(--radius-sm);color:var(--bg-primary);font-size:12px;font-weight:600;cursor:pointer;transition:all var(--transition-fast)}.commit-btn:hover{background:var(--accent-hover);transform:translateY(-1px)}.panel-divider{width:1px;height:20px;background:var(--border-color);margin:0 4px}.git-action-btn{padding:4px 10px;font-size:11px;background:var(--bg-elevated);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-secondary);cursor:pointer;transition:all var(--transition-fast)}.git-action-btn:hover:not(:disabled){background:var(--accent-soft);border-color:var(--accent-color);color:var(--accent-color)}.git-action-btn:disabled{opacity:.5;cursor:not-allowed}.git-push-btn{background:linear-gradient(135deg,rgba(34,197,94,.1) 0%,var(--bg-elevated) 100%);border-color:#22c55e4d;color:var(--success-color)}.git-push-btn:hover:not(:disabled){background:var(--success-color);border-color:var(--success-color);color:var(--bg-primary)}.toast{position:fixed;bottom:24px;right:24px;display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:var(--radius-md);background:var(--bg-elevated);border:1px solid var(--border-color);box-shadow:var(--shadow-lg);z-index:1000;animation:toastIn .2s ease;min-width:240px;max-width:400px}@keyframes toastIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.toast-success{border-color:var(--success-color);background:linear-gradient(135deg,rgba(34,197,94,.15) 0%,var(--bg-elevated) 100%)}.toast-error{border-color:var(--danger-color);background:linear-gradient(135deg,rgba(239,68,68,.15) 0%,var(--bg-elevated) 100%)}.toast-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-size:12px;font-weight:700;flex-shrink:0}.toast-success .toast-icon{background:var(--success-color);color:var(--bg-primary)}.toast-error .toast-icon{background:var(--danger-color);color:var(--text-primary)}.toast-message{flex:1;font-size:13px;color:var(--text-primary)}.toast-close{background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:16px;padding:2px 6px;border-radius:var(--radius-xs);transition:all var(--transition-fast);flex-shrink:0}.toast-close:hover{background:#ffffff1a;color:var(--text-primary)}.file-git-badge{width:16px;height:16px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;font-family:var(--font-mono);border-radius:3px;margin-left:auto;flex-shrink:0}.file-git-badge.staged{background:var(--success-color);color:#000}.file-git-badge.wt{background:var(--warning-color);color:#000}.file-git-badge.untracked{background:var(--text-muted);color:#fff}@media (max-width: 1024px){.left-panel{width:220px}.right-panel{width:45%;min-width:250px}.top-bar-left{width:220px}}@media (max-width: 768px){.main-content{flex-direction:column}.left-panel,.right-panel{width:100%;max-width:none;min-width:auto}.middle-panel{min-height:300px}.top-bar{flex-wrap:wrap;padding:10px 16px}.top-bar-left,.top-bar-center,.top-bar-right{width:auto}.top-bar-center{order:3;width:100%;justify-content:flex-start;margin-top:8px;padding-top:8px;border-top:1px solid var(--border-color)}}
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Codex Lens</title>
7
- <script type="module" crossorigin src="./assets/main-B9zQ2WJ0.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/main-DLXcJXXv.css">
7
+ <script type="module" crossorigin src="./assets/main-C24uyyBG.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/main-gnDZ_a0p.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-lens",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "A visualization tool for Codex that monitors API requests and file system changes",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/aggregator.js CHANGED
@@ -313,6 +313,27 @@ class Aggregator {
313
313
  await this.gitManager.commit(data.message);
314
314
  this.gitManager.broadcastUpdate();
315
315
  }
316
+ } else if (data.type === 'git_push') {
317
+ if (this.gitManager?.isGitRepo()) {
318
+ const result = await this.gitManager.push();
319
+ this.broadcast({ type: 'git_operation_result', operation: 'push', success: result.success, message: result.message });
320
+ if (result.success) {
321
+ this.gitManager.broadcastUpdate();
322
+ }
323
+ }
324
+ } else if (data.type === 'git_pull') {
325
+ if (this.gitManager?.isGitRepo()) {
326
+ const result = await this.gitManager.pull();
327
+ this.broadcast({ type: 'git_operation_result', operation: 'pull', success: result.success, message: result.message });
328
+ if (result.success) {
329
+ this.gitManager.broadcastUpdate();
330
+ }
331
+ }
332
+ } else if (data.type === 'git_fetch') {
333
+ if (this.gitManager?.isGitRepo()) {
334
+ const result = await this.gitManager.fetch();
335
+ this.broadcast({ type: 'git_operation_result', operation: 'fetch', success: result.success, message: result.message });
336
+ }
316
337
  }
317
338
  }
318
339
 
@@ -21,6 +21,9 @@ export function App() {
21
21
  unstagedCount: 0
22
22
  });
23
23
  const [showStagedPanel, setShowStagedPanel] = useState(false);
24
+ const [gitOperationLoading, setGitOperationLoading] = useState(false);
25
+ const [gitOperationType, setGitOperationType] = useState(null);
26
+ const [toast, setToast] = useState(null);
24
27
  const wsRef = useRef(null);
25
28
 
26
29
  useEffect(() => {
@@ -139,6 +142,11 @@ export function App() {
139
142
  unstagedCount: msg.data.unstagedCount
140
143
  });
141
144
  break;
145
+ case 'git_operation_result':
146
+ setGitOperationLoading(false);
147
+ setGitOperationType(null);
148
+ setToast({ type: msg.success ? 'success' : 'error', message: msg.message });
149
+ break;
142
150
  case 'connected':
143
151
  console.log('Server confirmed connection');
144
152
  break;
@@ -165,6 +173,12 @@ export function App() {
165
173
  sendGitCommand('git_commit', { message });
166
174
  }
167
175
 
176
+ function handleGitOperation(operationType) {
177
+ setGitOperationLoading(true);
178
+ setGitOperationType(operationType);
179
+ sendGitCommand(`git_${operationType}`, {});
180
+ }
181
+
168
182
  function openFileInTab(data) {
169
183
  const fileName = data.path.split(/[/\\]/).pop();
170
184
 
@@ -521,9 +535,15 @@ export function App() {
521
535
  onStage={handleStage}
522
536
  onUnstage={handleUnstage}
523
537
  onCommit={handleCommit}
538
+ onPush={() => handleGitOperation('push')}
539
+ onPull={() => handleGitOperation('pull')}
540
+ onFetch={() => handleGitOperation('fetch')}
541
+ operationLoading={gitOperationLoading}
542
+ operationType={gitOperationType}
524
543
  onClose={() => setShowStagedPanel(false)}
525
544
  />
526
545
  )}
546
+ <Toast toast={toast} onClose={() => setToast(null)} />
527
547
  <div className="panel right-panel">
528
548
  <div className="terminal-wrapper">
529
549
  <TerminalPanel />
@@ -585,7 +605,28 @@ function ContextMenu({ x, y, tab, tabs, saving, onClose, onCloseTab, onCloseOthe
585
605
  );
586
606
  }
587
607
 
588
- function StagedChangesPanel({ gitInfo, onStage, onUnstage, onCommit, onClose }) {
608
+ function Toast({ toast, onClose }) {
609
+ const timerRef = useRef(null);
610
+
611
+ useEffect(() => {
612
+ if (toast) {
613
+ timerRef.current = setTimeout(onClose, 4000);
614
+ }
615
+ return () => clearTimeout(timerRef.current);
616
+ }, [toast, onClose]);
617
+
618
+ if (!toast) return null;
619
+
620
+ return (
621
+ <div className={`toast toast-${toast.type}`}>
622
+ <span className="toast-icon">{toast.type === 'success' ? '✓' : '✗'}</span>
623
+ <span className="toast-message">{toast.message}</span>
624
+ <button className="toast-close" onClick={onClose}>×</button>
625
+ </div>
626
+ );
627
+ }
628
+
629
+ function StagedChangesPanel({ gitInfo, onStage, onUnstage, onCommit, onPush, onPull, onFetch, operationLoading, operationType, onClose }) {
589
630
  if (!gitInfo.isRepo || !gitInfo.status) return null;
590
631
 
591
632
  const { staged, unstaged, untracked } = gitInfo.status;
@@ -595,6 +636,16 @@ function StagedChangesPanel({ gitInfo, onStage, onUnstage, onCommit, onClose })
595
636
  <div className="staged-panel-header">
596
637
  <span>Git 变更</span>
597
638
  <div className="staged-panel-actions">
639
+ <button onClick={onFetch} className="git-action-btn" disabled={operationLoading} title="Fetch from remote">
640
+ {operationLoading && operationType === 'fetch' ? '...' : 'Fetch'}
641
+ </button>
642
+ <button onClick={onPull} className="git-action-btn" disabled={operationLoading} title="Pull from remote">
643
+ {operationLoading && operationType === 'pull' ? '...' : 'Pull'}
644
+ </button>
645
+ <button onClick={onPush} className="git-action-btn git-push-btn" disabled={operationLoading} title="Push to remote">
646
+ {operationLoading && operationType === 'push' ? '...' : 'Push'}
647
+ </button>
648
+ <span className="panel-divider"></span>
598
649
  <button onClick={() => onStage(null)} className="stage-btn">Stage All</button>
599
650
  <button onClick={() => onUnstage(null)} className="unstage-btn">Unstage All</button>
600
651
  <button onClick={onClose} className="close-btn">×</button>
@@ -744,8 +795,8 @@ function LeftPanel({ files, activeFile, onFileClick, gitInfo }) {
744
795
  </span>
745
796
  <span className="file-name">{item.name}</span>
746
797
  {fileGitStatus && (
747
- <span className={`file-git-badge ${fileGitStatus.indexStatus !== '?' ? 'staged' : 'wt'}`}>
748
- {fileGitStatus.indexStatus !== '?' ? fileGitStatus.indexStatus : fileGitStatus.workTreeStatus}
798
+ <span className={`file-git-badge ${getGitBadgeClass(fileGitStatus)}`}>
799
+ {getGitBadgeText(fileGitStatus)}
749
800
  </span>
750
801
  )}
751
802
  </div>
@@ -807,3 +858,28 @@ function getFileIcon(type) {
807
858
  };
808
859
  return icons[type] || icons['default'];
809
860
  }
861
+
862
+ function getGitBadgeClass(fileGitStatus) {
863
+ // indexStatus === '?' means untracked
864
+ if (fileGitStatus.indexStatus === '?' && fileGitStatus.workTreeStatus === '?') {
865
+ return 'untracked';
866
+ }
867
+ // Staged: indexStatus is not ' ' and not '?'
868
+ if (fileGitStatus.indexStatus !== ' ' && fileGitStatus.indexStatus !== '?') {
869
+ return 'staged';
870
+ }
871
+ // Otherwise (working tree changes)
872
+ return 'wt';
873
+ }
874
+
875
+ function getGitBadgeText(fileGitStatus) {
876
+ // For untracked, show 'U'
877
+ if (fileGitStatus.indexStatus === '?' && fileGitStatus.workTreeStatus === '?') {
878
+ return 'U';
879
+ }
880
+ // Show index status for staged, workTree status for unstaged
881
+ if (fileGitStatus.indexStatus !== ' ' && fileGitStatus.indexStatus !== '?') {
882
+ return fileGitStatus.indexStatus;
883
+ }
884
+ return fileGitStatus.workTreeStatus;
885
+ }
@@ -138,6 +138,18 @@ class GitManager {
138
138
  return this.getStatus();
139
139
  }
140
140
 
141
+ async runRemoteOperation(operation, args, successMsg) {
142
+ const result = await this.runGitCommand(args);
143
+ return {
144
+ success: result.code === 0,
145
+ message: result.code === 0 ? successMsg : (result.stderr || `${operation} 失败`),
146
+ };
147
+ }
148
+
149
+ async push() { return this.runRemoteOperation('Push', ['push'], 'Push 成功'); }
150
+ async pull() { return this.runRemoteOperation('Pull', ['pull'], 'Pull 成功'); }
151
+ async fetch() { return this.runRemoteOperation('Fetch', ['fetch', '--all'], 'Fetch 成功'); }
152
+
141
153
  async broadcastUpdate() {
142
154
  const branch = await this.getCurrentBranch();
143
155
  const status = await this.getStatus();
package/src/global.css CHANGED
@@ -923,29 +923,161 @@ body {
923
923
  transform: translateY(-1px);
924
924
  }
925
925
 
926
+ /* ==================== Git Remote Action Buttons ==================== */
927
+ .panel-divider {
928
+ width: 1px;
929
+ height: 20px;
930
+ background: var(--border-color);
931
+ margin: 0 4px;
932
+ }
933
+
934
+ .git-action-btn {
935
+ padding: 4px 10px;
936
+ font-size: 11px;
937
+ background: var(--bg-elevated);
938
+ border: 1px solid var(--border-color);
939
+ border-radius: var(--radius-xs);
940
+ color: var(--text-secondary);
941
+ cursor: pointer;
942
+ transition: all var(--transition-fast);
943
+ }
944
+
945
+ .git-action-btn:hover:not(:disabled) {
946
+ background: var(--accent-soft);
947
+ border-color: var(--accent-color);
948
+ color: var(--accent-color);
949
+ }
950
+
951
+ .git-action-btn:disabled {
952
+ opacity: 0.5;
953
+ cursor: not-allowed;
954
+ }
955
+
956
+ .git-push-btn {
957
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.1) 0%, var(--bg-elevated) 100%);
958
+ border-color: rgba(34, 197, 94, 0.3);
959
+ color: var(--success-color);
960
+ }
961
+
962
+ .git-push-btn:hover:not(:disabled) {
963
+ background: var(--success-color);
964
+ border-color: var(--success-color);
965
+ color: var(--bg-primary);
966
+ }
967
+
968
+ /* ==================== Toast Notifications ==================== */
969
+ .toast {
970
+ position: fixed;
971
+ bottom: 24px;
972
+ right: 24px;
973
+ display: flex;
974
+ align-items: center;
975
+ gap: 10px;
976
+ padding: 12px 16px;
977
+ border-radius: var(--radius-md);
978
+ background: var(--bg-elevated);
979
+ border: 1px solid var(--border-color);
980
+ box-shadow: var(--shadow-lg);
981
+ z-index: 1000;
982
+ animation: toastIn 0.2s ease;
983
+ min-width: 240px;
984
+ max-width: 400px;
985
+ }
986
+
987
+ @keyframes toastIn {
988
+ from {
989
+ opacity: 0;
990
+ transform: translateY(8px);
991
+ }
992
+ to {
993
+ opacity: 1;
994
+ transform: translateY(0);
995
+ }
996
+ }
997
+
998
+ .toast-success {
999
+ border-color: var(--success-color);
1000
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.15) 0%, var(--bg-elevated) 100%);
1001
+ }
1002
+
1003
+ .toast-error {
1004
+ border-color: var(--danger-color);
1005
+ background: linear-gradient(135deg, rgba(239, 68, 68, 0.15) 0%, var(--bg-elevated) 100%);
1006
+ }
1007
+
1008
+ .toast-icon {
1009
+ width: 20px;
1010
+ height: 20px;
1011
+ display: flex;
1012
+ align-items: center;
1013
+ justify-content: center;
1014
+ border-radius: 50%;
1015
+ font-size: 12px;
1016
+ font-weight: bold;
1017
+ flex-shrink: 0;
1018
+ }
1019
+
1020
+ .toast-success .toast-icon {
1021
+ background: var(--success-color);
1022
+ color: var(--bg-primary);
1023
+ }
1024
+
1025
+ .toast-error .toast-icon {
1026
+ background: var(--danger-color);
1027
+ color: var(--text-primary);
1028
+ }
1029
+
1030
+ .toast-message {
1031
+ flex: 1;
1032
+ font-size: 13px;
1033
+ color: var(--text-primary);
1034
+ }
1035
+
1036
+ .toast-close {
1037
+ background: none;
1038
+ border: none;
1039
+ color: var(--text-muted);
1040
+ cursor: pointer;
1041
+ font-size: 16px;
1042
+ padding: 2px 6px;
1043
+ border-radius: var(--radius-xs);
1044
+ transition: all var(--transition-fast);
1045
+ flex-shrink: 0;
1046
+ }
1047
+
1048
+ .toast-close:hover {
1049
+ background: rgba(255, 255, 255, 0.1);
1050
+ color: var(--text-primary);
1051
+ }
1052
+
926
1053
  /* ==================== File Tree Git Badges ==================== */
927
1054
  .file-git-badge {
928
- width: 14px;
929
- height: 14px;
1055
+ width: 16px;
1056
+ height: 16px;
930
1057
  display: flex;
931
1058
  align-items: center;
932
1059
  justify-content: center;
933
- font-size: 9px;
1060
+ font-size: 10px;
934
1061
  font-weight: 700;
935
1062
  font-family: var(--font-mono);
936
- border-radius: 2px;
1063
+ border-radius: 3px;
937
1064
  margin-left: auto;
938
1065
  flex-shrink: 0;
939
1066
  }
940
1067
 
941
1068
  .file-git-badge.staged {
942
1069
  background: var(--success-color);
943
- color: var(--bg-primary);
1070
+ color: #000;
944
1071
  }
945
1072
 
946
1073
  .file-git-badge.wt {
947
1074
  background: var(--warning-color);
948
- color: var(--bg-primary);
1075
+ color: #000;
1076
+ }
1077
+
1078
+ .file-git-badge.untracked {
1079
+ background: var(--text-muted);
1080
+ color: #fff;
949
1081
  }
950
1082
 
951
1083
  @media (max-width: 1024px) {