@surenkid/acli-hub 1.0.7 → 1.0.9

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.
@@ -1 +1 @@
1
- :root{--bg-primary: #0f172a;--bg-secondary: #1e293b;--bg-tertiary: #334155;--bg-card: #1e293b;--bg-card-hover: #334155;--border-color: #334155;--border-color-hover: #475569;--text-primary: #f8fafc;--text-secondary: #94a3b8;--text-tertiary: #64748b;--accent-primary: #3b82f6;--accent-hover: #2563eb;--accent-dim: rgba(59, 130, 246, .15);--success: #10b981;--warning: #f59e0b;--danger: #ef4444;--sidebar-width: 260px;--sidebar-collapsed-width: 0px;--toolbar-height: 56px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1)}*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol;background:var(--bg-primary);color:var(--text-primary);overflow:hidden;height:100vh;font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}#app{height:100vh;display:flex;flex-direction:column}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-tertiary);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-tertiary)}.glass{background:#1e293bb3;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--border-color)}.btn{display:inline-flex;align-items:center;justify-content:center;padding:8px 16px;border-radius:var(--radius-md);font-weight:500;cursor:pointer;transition:all .2s;border:1px solid transparent;outline:none}.btn-primary{background:var(--accent-primary);color:#fff}.btn-primary:hover{background:var(--accent-hover)}input{background:var(--bg-primary);border:1px solid var(--border-color);color:var(--text-primary);padding:8px 12px;border-radius:var(--radius-md);outline:none;transition:border-color .2s}input:focus{border-color:var(--accent-primary)}.session-card[data-v-0e38e5ff]{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:var(--radius-md);cursor:pointer;transition:all .2s;border:1px solid transparent;color:var(--text-secondary)}.session-card[data-v-0e38e5ff]:hover{background:var(--bg-card-hover);color:var(--text-primary)}.session-card.active[data-v-0e38e5ff]{background:var(--bg-tertiary);color:var(--text-primary);border-color:var(--border-color)}.status-indicator[data-v-0e38e5ff]{width:8px;height:8px;border-radius:50%;background:var(--text-tertiary);flex-shrink:0}.status-indicator.running[data-v-0e38e5ff]{background:var(--success);box-shadow:0 0 8px #10b98166}.status-indicator.running.output-active[data-v-0e38e5ff]{background:var(--warning);box-shadow:0 0 8px #f59e0b66}.card-content[data-v-0e38e5ff]{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.card-top[data-v-0e38e5ff]{display:flex;align-items:center;gap:4px}.session-name[data-v-0e38e5ff]{font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;display:flex;align-items:baseline;gap:6px}.alias-text[data-v-0e38e5ff]{overflow:hidden;text-overflow:ellipsis}.real-name[data-v-0e38e5ff]{flex-shrink:1;max-width:45%;overflow:hidden;text-overflow:ellipsis;font-size:11px;font-weight:400;color:var(--text-tertiary)}.alias-input[data-v-0e38e5ff]{flex:1;min-width:0;padding:2px 6px;font-size:13px;color:var(--text-primary);background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;outline:none}.alias-input[data-v-0e38e5ff]:focus{border-color:var(--accent-primary, #3b82f6)}.close-btn[data-v-0e38e5ff]{display:none;align-items:center;justify-content:center;background:none;border:none;color:var(--text-tertiary);cursor:pointer;padding:2px;border-radius:4px;flex-shrink:0}.session-card:hover .close-btn[data-v-0e38e5ff]{display:flex}.close-btn[data-v-0e38e5ff]:hover{background:var(--bg-tertiary);color:var(--danger)}.session-info[data-v-0e38e5ff]{display:flex;align-items:baseline;gap:8px;font-size:11px;color:var(--text-tertiary)}.pane-title[data-v-0e38e5ff]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.confirm-bar[data-v-0e38e5ff]{display:flex;align-items:center;gap:6px;font-size:12px}.confirm-text[data-v-0e38e5ff]{color:var(--danger);font-weight:500}.confirm-yes[data-v-0e38e5ff],.confirm-no[data-v-0e38e5ff]{background:none;border:1px solid var(--border-color);border-radius:4px;padding:1px 8px;font-size:11px;cursor:pointer;color:var(--text-secondary)}.confirm-yes[data-v-0e38e5ff]:hover{background:var(--danger);border-color:var(--danger);color:#fff}.confirm-no[data-v-0e38e5ff]:hover{background:var(--bg-tertiary);color:var(--text-primary)}.session-card.collapsed[data-v-0e38e5ff]{justify-content:center;padding:12px}.session-card.collapsed .status-indicator[data-v-0e38e5ff]{width:10px;height:10px}li[data-v-5c068d88]{list-style:none}.tree-row[data-v-5c068d88]{display:flex;align-items:center;gap:5px;min-height:31px;padding:2px 6px;cursor:pointer;border-radius:3px;outline-offset:-2px}.tree-row[data-v-5c068d88]:hover,.tree-row[data-v-5c068d88]:focus-visible{background:var(--bg-tertiary)}.chevron[data-v-5c068d88]{flex:0 0 10px;color:var(--text-secondary)}.file-icon[data-v-5c068d88]{color:var(--text-secondary);font-size:18px;width:15px}.filename[data-v-5c068d88]{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1;font-size:13px}.dotfile[data-v-5c068d88]{opacity:.55}.deleted[data-v-5c068d88]{text-decoration:line-through;opacity:.65}.row-end[data-v-5c068d88]{position:relative;flex:0 0 20px;height:24px}.git-badge[data-v-5c068d88],.git-dot[data-v-5c068d88]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.git-badge[data-v-5c068d88]{font:600 11px/1.5 ui-monospace,monospace}.git-M[data-v-5c068d88],.git-dot[data-v-5c068d88]{color:#e5b45c}.git-A[data-v-5c068d88],.git-U[data-v-5c068d88]{color:#71c993}.git-D[data-v-5c068d88],.git-C[data-v-5c068d88]{color:#f08080}.git-R[data-v-5c068d88]{color:#79b8ff}.git-dot[data-v-5c068d88]{font-size:7px}.more[data-v-5c068d88]{position:absolute;inset:0;width:100%;background:var(--bg-tertiary);color:var(--text-secondary);border:none;border-radius:3px;cursor:pointer;padding:0;font-size:18px;opacity:0;pointer-events:none}.tree-row:hover .more[data-v-5c068d88],.tree-row:focus-within .more[data-v-5c068d88]{opacity:1;pointer-events:auto}.tree-row:hover .has-menu .git-badge[data-v-5c068d88],.tree-row:hover .has-menu .git-dot[data-v-5c068d88],.tree-row:focus-within .has-menu .git-badge[data-v-5c068d88],.tree-row:focus-within .has-menu .git-dot[data-v-5c068d88]{opacity:0}.tree-children[data-v-5c068d88]{margin-left:14px;padding-left:5px;border-left:1px solid var(--border-color)}.tree-status[data-v-5c068d88]{padding:5px 10px;color:var(--text-secondary);font-size:12px;overflow-wrap:anywhere}.tree-status button[data-v-5c068d88]{background:none;color:var(--text-primary);border:none;cursor:pointer;text-decoration:underline}.error[data-v-5c068d88]{color:var(--danger)}@media(hover:none){.more[data-v-5c068d88]{pointer-events:auto}.row-end:not(.has-status) .more[data-v-5c068d88]{opacity:1;background:transparent}}.file-dialog[data-v-5ceee09a]{margin:auto;width:min(480px,calc(100vw - 32px));max-height:calc(100dvh - 40px);overflow:auto;padding:24px;background:var(--bg-secondary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-lg)}.file-dialog[data-v-5ceee09a]::backdrop{background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}p[data-v-5ceee09a]{margin:12px 0;color:var(--text-secondary)}.operation-path[data-v-5ceee09a]{overflow-wrap:anywhere;font:12px/1.6 monospace}label[data-v-5ceee09a]{display:flex;flex-direction:column;gap:8px}.dialog-actions[data-v-5ceee09a]{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.btn[data-v-5ceee09a]{background:var(--bg-tertiary);color:var(--text-primary)}.btn-primary[data-v-5ceee09a]{background:var(--accent-primary)}.delete-btn[data-v-5ceee09a]{background:var(--danger);color:#fff}.error[data-v-5ceee09a]{color:var(--danger)}button[data-v-5ceee09a]:disabled{opacity:.5;cursor:default}.clipboard-overlay[data-v-317cb3e2]{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.clipboard-dialog[data-v-317cb3e2]{width:min(520px,calc(100vw - 32px));padding:20px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md)}h3[data-v-317cb3e2]{font-size:16px}p[data-v-317cb3e2]{margin:12px 0;color:var(--text-secondary)}textarea[data-v-317cb3e2]{width:100%;height:180px;resize:vertical;padding:12px;background:var(--bg-primary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);font:13px/1.5 monospace}textarea[data-v-317cb3e2]:focus{outline:2px solid var(--accent-primary);outline-offset:2px}.clipboard-actions[data-v-317cb3e2]{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button[type=button][data-v-317cb3e2]{color:var(--text-primary);background:var(--bg-tertiary)}button[data-v-317cb3e2]:disabled{opacity:.5;cursor:default}.file-panel[data-v-771bf310]{display:flex;flex-direction:column;min-height:0;flex:1}.file-toolbar[data-v-771bf310]{display:flex;align-items:center;gap:4px;padding:10px 12px 4px}.project-name[data-v-771bf310]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:600}.file-toolbar button[data-v-771bf310],.panel-hint button[data-v-771bf310]{border:none;background:transparent;color:var(--text-secondary);padding:3px 5px;cursor:pointer;font-size:17px}.file-toolbar button[data-v-771bf310]:hover{background:var(--bg-tertiary);border-radius:4px}button[data-v-771bf310]:disabled{opacity:.4;cursor:default}.root-path[data-v-771bf310]{color:var(--text-secondary);font:11px/1.6 monospace;overflow-wrap:anywhere;padding:0 12px 10px;border-bottom:1px solid var(--border-color)}.file-tree[data-v-771bf310]{overflow:auto;padding:6px;flex:1;min-height:0}.panel-hint[data-v-771bf310]{padding:12px;color:var(--text-secondary);font-size:12px;list-style:none;overflow-wrap:anywhere}.error[data-v-771bf310]{color:var(--danger)}.git-warning[data-v-771bf310]{color:#e5b45c}.file-menu[data-v-771bf310]{position:fixed;z-index:110;width:min(230px,calc(100vw - 16px));padding:6px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-md)}.file-menu button[data-v-771bf310]{display:flex;justify-content:space-between;width:100%;text-align:left;padding:8px 10px;background:none;color:var(--text-primary);border:none;border-radius:4px;cursor:pointer}.file-menu button[data-v-771bf310]:hover:not(:disabled),.file-menu button[data-v-771bf310]:focus-visible{background:var(--bg-tertiary)}.file-menu span[data-v-771bf310]{color:var(--text-secondary)}.file-menu .danger[data-v-771bf310]{color:var(--danger)}.sidebar[data-v-b8faf56e]{width:var(--sidebar-width);border-right:1px solid var(--border-color);background:var(--bg-secondary);display:flex;flex-direction:column;flex-shrink:0;transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden;height:100%;z-index:20}.sidebar.collapsed[data-v-b8faf56e]{width:72px}.sidebar-tabs[data-v-b8faf56e]{display:flex;flex-shrink:0;border-bottom:1px solid var(--border-color)}.sidebar-tabs button[data-v-b8faf56e]{flex:1;padding:12px 4px;border:none;border-bottom:2px solid transparent;background:none;color:var(--text-secondary);cursor:pointer;font:inherit;font-size:12px}.sidebar-tabs button[aria-selected=true][data-v-b8faf56e]{border-bottom-color:var(--accent-primary);color:var(--text-primary);background:var(--bg-primary)}.sessions-panel[data-v-b8faf56e],.files-panel[data-v-b8faf56e]{display:flex;flex-direction:column;min-height:0;flex:1}.sidebar-header[data-v-b8faf56e]{padding:16px;border-bottom:1px solid var(--border-color);display:flex;flex-direction:column;gap:12px}.sidebar-title[data-v-b8faf56e]{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-tertiary);font-weight:600}.new-session-btn[data-v-b8faf56e]{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;background:var(--accent-primary);color:#fff;border:none;border-radius:var(--radius-md);padding:10px;cursor:pointer;font-weight:500;transition:all .2s}.new-session-btn[data-v-b8faf56e]:hover{background:var(--accent-hover)}.sidebar.collapsed .new-session-btn[data-v-b8faf56e]{padding:10px 0}.session-list[data-v-b8faf56e]{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:4px}.empty-hint[data-v-b8faf56e]{text-align:center;padding:40px 10px;color:var(--text-tertiary)}.empty-hint p[data-v-b8faf56e]{font-size:14px;margin-bottom:4px}.empty-hint .sub-hint[data-v-b8faf56e]{font-size:12px;opacity:.7}@media(max-width:768px){.sidebar[data-v-b8faf56e]{position:fixed;top:0;left:0;bottom:0;width:var(--sidebar-width);transform:translate(0);box-shadow:var(--shadow-md);z-index:50}.sidebar.collapsed[data-v-b8faf56e]{transform:translate(-100%);width:var(--sidebar-width)}}.brand-mark[data-v-f54af403]{display:block;flex-shrink:0;object-fit:contain}.terminal-area[data-v-95819edf]{flex:1;display:flex;flex-direction:column;overflow:hidden;background:#000;position:relative}.terminal-frame[data-v-95819edf]{flex:1;width:100%;min-height:0;border:none;background:#000}.terminal-tools[data-v-95819edf]{display:flex;align-items:center;flex-shrink:0;gap:8px;padding:6px 12px;background:var(--bg-primary);border-bottom:1px solid var(--border-color);flex-wrap:wrap}.upload-progress[data-v-95819edf]{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-secondary)}.upload-progress progress[data-v-95819edf]{width:64px;height:4px;accent-color:var(--accent-primary)}.clipboard-btn[data-v-95819edf]{padding:4px 10px;background:var(--bg-secondary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-sm);cursor:pointer}.clipboard-btn[data-v-95819edf]:hover:not(:disabled){background:var(--bg-tertiary)}.clipboard-btn[data-v-95819edf]:disabled,.clipboard-menu button[data-v-95819edf]:disabled{opacity:.45;cursor:default}.selection-hint[data-v-95819edf]{color:var(--text-secondary);font-size:12px}.clipboard-menu[data-v-95819edf]{position:fixed;z-index:100;width:min(280px,calc(100vw - 16px));padding:6px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-md)}.clipboard-menu button[data-v-95819edf]{display:flex;justify-content:space-between;width:100%;padding:8px 10px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--text-primary);text-align:left;cursor:pointer}.clipboard-menu button[data-v-95819edf]:hover:not(:disabled),.clipboard-menu button[data-v-95819edf]:focus-visible{background:var(--bg-tertiary)}.clipboard-menu span[data-v-95819edf],.clipboard-menu p[data-v-95819edf]{color:var(--text-secondary);font-size:12px}.clipboard-menu p[data-v-95819edf]{padding:8px 10px 4px;border-top:1px solid var(--border-color)}@media(max-width:600px){.selection-hint[data-v-95819edf]{display:none}}.welcome__container[data-v-95819edf]{flex:1;display:flex;align-items:center;justify-content:center;background:var(--bg-primary);background-image:radial-gradient(circle at center,var(--bg-secondary) 0%,var(--bg-primary) 100%)}.welcome__content[data-v-95819edf]{text-align:center;max-width:400px;padding:40px}.welcome-brand[data-v-95819edf]{display:flex;flex-direction:column;align-items:center;gap:12px;margin-bottom:24px}.logo-text[data-v-95819edf]{font-size:32px;font-weight:700;color:var(--text-primary);letter-spacing:-1px}.welcome__text[data-v-95819edf]{color:var(--text-secondary);font-size:16px;margin-bottom:24px}.highlight[data-v-95819edf]{color:var(--text-primary);font-weight:600}.sub-text[data-v-95819edf]{color:var(--text-tertiary);font-size:14px}.modal-overlay[data-v-f9ae44fb]{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn-f9ae44fb .2s ease}.modal-content[data-v-f9ae44fb]{width:100%;max-width:400px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);margin:16px;overflow:hidden;animation:slideUp-f9ae44fb .3s cubic-bezier(.16,1,.3,1)}.modal-header[data-v-f9ae44fb]{padding:16px 20px;border-bottom:1px solid var(--border-color);display:flex;justify-content:space-between;align-items:center}.modal-header h3[data-v-f9ae44fb]{font-size:16px;font-weight:600;color:var(--text-primary)}.close-btn[data-v-f9ae44fb]{background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:18px;padding:4px;border-radius:4px}.close-btn[data-v-f9ae44fb]:hover{background:var(--bg-tertiary);color:var(--text-primary)}.modal-body[data-v-f9ae44fb]{padding:20px;display:flex;flex-direction:column;gap:16px}.form-group[data-v-f9ae44fb]{display:flex;flex-direction:column;gap:8px}.label-text[data-v-f9ae44fb]{font-size:13px;font-weight:500;color:var(--text-secondary)}select[data-v-f9ae44fb],input[data-v-f9ae44fb]{width:100%;background:var(--bg-primary);border:1px solid var(--border-color);color:var(--text-primary);padding:10px;border-radius:var(--radius-md);outline:none;font-size:14px;appearance:none}select[data-v-f9ae44fb]:focus,input[data-v-f9ae44fb]:focus{border-color:var(--accent-primary);box-shadow:0 0 0 2px var(--accent-dim)}.modal-footer[data-v-f9ae44fb]{padding:16px 20px;background:var(--bg-primary);border-top:1px solid var(--border-color);display:flex;justify-content:flex-end;gap:12px}@keyframes fadeIn-f9ae44fb{0%{opacity:0}to{opacity:1}}@keyframes slideUp-f9ae44fb{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.login-screen[data-v-86b6b672]{height:100vh;display:flex;align-items:center;justify-content:center;background:var(--bg-primary)}.login-card[data-v-86b6b672]{width:min(360px,calc(100vw - 48px));padding:32px;display:flex;flex-direction:column;align-items:center;gap:12px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md)}.login-logo[data-v-86b6b672]{display:flex;align-items:center;justify-content:center;width:72px;height:72px}h1[data-v-86b6b672]{font-size:22px;font-weight:600;color:var(--text-primary);letter-spacing:-.5px}.login-hint[data-v-86b6b672]{margin:-4px 0 8px;font-size:13px;color:var(--text-secondary)}input[data-v-86b6b672]{width:100%;padding:10px 12px;font-size:14px;color:var(--text-primary);background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);outline:none}input[data-v-86b6b672]:focus{border-color:var(--accent-primary, #3b82f6)}.login-error[data-v-86b6b672]{width:100%;margin:0;font-size:13px;color:var(--danger)}.login-btn[data-v-86b6b672]{width:100%;margin-top:4px;padding:10px 12px;font-size:14px;font-weight:500;color:#fff;background:var(--accent-primary, #3b82f6);border:none;border-radius:var(--radius-md);cursor:pointer}.login-btn[data-v-86b6b672]:disabled{opacity:.5;cursor:default}.login-btn[data-v-86b6b672]:not(:disabled):hover{filter:brightness(1.1)}.toast-container[data-v-6bea03ca]{position:fixed;top:60px;right:16px;z-index:200;display:flex;flex-direction:column;gap:8px;max-width:min(520px,calc(100vw - 32px));max-height:calc(100vh - 80px);overflow:auto}.toast[data-v-6bea03ca]{padding:10px 16px;border-radius:8px;font-size:13px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);min-width:200px;background:var(--bg-secondary);display:flex;align-items:flex-start;gap:12px}.toast-message[data-v-6bea03ca]{white-space:pre-wrap;overflow-wrap:anywhere;max-height:35vh;overflow:auto;flex:1}.toast-actions[data-v-6bea03ca]{display:flex;gap:8px;flex-shrink:0}.toast-actions button[data-v-6bea03ca]{border:none;background:transparent;color:inherit;cursor:pointer;font:inherit}.toast.info[data-v-6bea03ca]{background:var(--bg-secondary);color:var(--text-primary)}.toast.error[data-v-6bea03ca]{background:var(--bg-secondary);color:var(--danger)}.toast.success[data-v-6bea03ca]{background:#4ade8026;color:#4ade80}.toast-enter-active[data-v-6bea03ca]{animation:slideIn-6bea03ca .3s ease}.toast-leave-active[data-v-6bea03ca]{animation:slideOut-6bea03ca .3s ease}@keyframes slideIn-6bea03ca{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideOut-6bea03ca{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:0}}.app-layout[data-v-1baffbd3]{height:100vh;display:flex;flex-direction:column}.toolbar[data-v-1baffbd3]{height:var(--toolbar-height);display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid var(--border-color);flex-shrink:0;z-index:30;background:var(--bg-primary)}.toolbar-left[data-v-1baffbd3]{display:flex;align-items:center;gap:12px}.toggle-btn[data-v-1baffbd3]{background:transparent;border:none;color:var(--text-secondary);cursor:pointer;padding:4px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center}.toggle-btn[data-v-1baffbd3]:hover{color:var(--text-primary);background:var(--bg-tertiary)}.logo-wrapper[data-v-1baffbd3]{display:flex;align-items:center;justify-content:center;flex-shrink:0}.toolbar-title[data-v-1baffbd3]{font-size:16px;font-weight:600;color:var(--text-primary);letter-spacing:-.5px}.main-area[data-v-1baffbd3]{flex:1;display:flex;overflow:hidden;position:relative}.sidebar-overlay[data-v-1baffbd3]{display:none;position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:15;opacity:0;transition:opacity .3s ease;pointer-events:none}@media(max-width:768px){.sidebar-overlay[data-v-1baffbd3]{display:block}.sidebar-overlay.show[data-v-1baffbd3]{opacity:1;pointer-events:auto}}
1
+ :root{--bg-primary: #0f172a;--bg-secondary: #1e293b;--bg-tertiary: #334155;--bg-card: #1e293b;--bg-card-hover: #334155;--border-color: #334155;--border-color-hover: #475569;--text-primary: #f8fafc;--text-secondary: #94a3b8;--text-tertiary: #64748b;--accent-primary: #3b82f6;--accent-hover: #2563eb;--accent-dim: rgba(59, 130, 246, .15);--success: #10b981;--warning: #f59e0b;--danger: #ef4444;--sidebar-width: 260px;--sidebar-collapsed-width: 0px;--toolbar-height: 56px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1)}*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol;background:var(--bg-primary);color:var(--text-primary);overflow:hidden;height:100vh;font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}#app{height:100vh;display:flex;flex-direction:column}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-tertiary);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-tertiary)}.glass{background:#1e293bb3;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--border-color)}.btn{display:inline-flex;align-items:center;justify-content:center;padding:8px 16px;border-radius:var(--radius-md);font-weight:500;cursor:pointer;transition:all .2s;border:1px solid transparent;outline:none}.btn-primary{background:var(--accent-primary);color:#fff}.btn-primary:hover{background:var(--accent-hover)}input{background:var(--bg-primary);border:1px solid var(--border-color);color:var(--text-primary);padding:8px 12px;border-radius:var(--radius-md);outline:none;transition:border-color .2s}input:focus{border-color:var(--accent-primary)}.session-card[data-v-0e38e5ff]{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:var(--radius-md);cursor:pointer;transition:all .2s;border:1px solid transparent;color:var(--text-secondary)}.session-card[data-v-0e38e5ff]:hover{background:var(--bg-card-hover);color:var(--text-primary)}.session-card.active[data-v-0e38e5ff]{background:var(--bg-tertiary);color:var(--text-primary);border-color:var(--border-color)}.status-indicator[data-v-0e38e5ff]{width:8px;height:8px;border-radius:50%;background:var(--text-tertiary);flex-shrink:0}.status-indicator.running[data-v-0e38e5ff]{background:var(--success);box-shadow:0 0 8px #10b98166}.status-indicator.running.output-active[data-v-0e38e5ff]{background:var(--warning);box-shadow:0 0 8px #f59e0b66}.card-content[data-v-0e38e5ff]{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.card-top[data-v-0e38e5ff]{display:flex;align-items:center;gap:4px}.session-name[data-v-0e38e5ff]{font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;display:flex;align-items:baseline;gap:6px}.alias-text[data-v-0e38e5ff]{overflow:hidden;text-overflow:ellipsis}.real-name[data-v-0e38e5ff]{flex-shrink:1;max-width:45%;overflow:hidden;text-overflow:ellipsis;font-size:11px;font-weight:400;color:var(--text-tertiary)}.alias-input[data-v-0e38e5ff]{flex:1;min-width:0;padding:2px 6px;font-size:13px;color:var(--text-primary);background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;outline:none}.alias-input[data-v-0e38e5ff]:focus{border-color:var(--accent-primary, #3b82f6)}.close-btn[data-v-0e38e5ff]{display:none;align-items:center;justify-content:center;background:none;border:none;color:var(--text-tertiary);cursor:pointer;padding:2px;border-radius:4px;flex-shrink:0}.session-card:hover .close-btn[data-v-0e38e5ff]{display:flex}.close-btn[data-v-0e38e5ff]:hover{background:var(--bg-tertiary);color:var(--danger)}.session-info[data-v-0e38e5ff]{display:flex;align-items:baseline;gap:8px;font-size:11px;color:var(--text-tertiary)}.pane-title[data-v-0e38e5ff]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.confirm-bar[data-v-0e38e5ff]{display:flex;align-items:center;gap:6px;font-size:12px}.confirm-text[data-v-0e38e5ff]{color:var(--danger);font-weight:500}.confirm-yes[data-v-0e38e5ff],.confirm-no[data-v-0e38e5ff]{background:none;border:1px solid var(--border-color);border-radius:4px;padding:1px 8px;font-size:11px;cursor:pointer;color:var(--text-secondary)}.confirm-yes[data-v-0e38e5ff]:hover{background:var(--danger);border-color:var(--danger);color:#fff}.confirm-no[data-v-0e38e5ff]:hover{background:var(--bg-tertiary);color:var(--text-primary)}.session-card.collapsed[data-v-0e38e5ff]{justify-content:center;padding:12px}.session-card.collapsed .status-indicator[data-v-0e38e5ff]{width:10px;height:10px}li[data-v-5c068d88]{list-style:none}.tree-row[data-v-5c068d88]{display:flex;align-items:center;gap:5px;min-height:31px;padding:2px 6px;cursor:pointer;border-radius:3px;outline-offset:-2px}.tree-row[data-v-5c068d88]:hover,.tree-row[data-v-5c068d88]:focus-visible{background:var(--bg-tertiary)}.chevron[data-v-5c068d88]{flex:0 0 10px;color:var(--text-secondary)}.file-icon[data-v-5c068d88]{color:var(--text-secondary);font-size:18px;width:15px}.filename[data-v-5c068d88]{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1;font-size:13px}.dotfile[data-v-5c068d88]{opacity:.55}.deleted[data-v-5c068d88]{text-decoration:line-through;opacity:.65}.row-end[data-v-5c068d88]{position:relative;flex:0 0 20px;height:24px}.git-badge[data-v-5c068d88],.git-dot[data-v-5c068d88]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.git-badge[data-v-5c068d88]{font:600 11px/1.5 ui-monospace,monospace}.git-M[data-v-5c068d88],.git-dot[data-v-5c068d88]{color:#e5b45c}.git-A[data-v-5c068d88],.git-U[data-v-5c068d88]{color:#71c993}.git-D[data-v-5c068d88],.git-C[data-v-5c068d88]{color:#f08080}.git-R[data-v-5c068d88]{color:#79b8ff}.git-dot[data-v-5c068d88]{font-size:7px}.more[data-v-5c068d88]{position:absolute;inset:0;width:100%;background:var(--bg-tertiary);color:var(--text-secondary);border:none;border-radius:3px;cursor:pointer;padding:0;font-size:18px;opacity:0;pointer-events:none}.tree-row:hover .more[data-v-5c068d88],.tree-row:focus-within .more[data-v-5c068d88]{opacity:1;pointer-events:auto}.tree-row:hover .has-menu .git-badge[data-v-5c068d88],.tree-row:hover .has-menu .git-dot[data-v-5c068d88],.tree-row:focus-within .has-menu .git-badge[data-v-5c068d88],.tree-row:focus-within .has-menu .git-dot[data-v-5c068d88]{opacity:0}.tree-children[data-v-5c068d88]{margin-left:14px;padding-left:5px;border-left:1px solid var(--border-color)}.tree-status[data-v-5c068d88]{padding:5px 10px;color:var(--text-secondary);font-size:12px;overflow-wrap:anywhere}.tree-status button[data-v-5c068d88]{background:none;color:var(--text-primary);border:none;cursor:pointer;text-decoration:underline}.error[data-v-5c068d88]{color:var(--danger)}@media(hover:none){.more[data-v-5c068d88]{pointer-events:auto}.row-end:not(.has-status) .more[data-v-5c068d88]{opacity:1;background:transparent}}.file-dialog[data-v-5ceee09a]{margin:auto;width:min(480px,calc(100vw - 32px));max-height:calc(100dvh - 40px);overflow:auto;padding:24px;background:var(--bg-secondary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-lg)}.file-dialog[data-v-5ceee09a]::backdrop{background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}p[data-v-5ceee09a]{margin:12px 0;color:var(--text-secondary)}.operation-path[data-v-5ceee09a]{overflow-wrap:anywhere;font:12px/1.6 monospace}label[data-v-5ceee09a]{display:flex;flex-direction:column;gap:8px}.dialog-actions[data-v-5ceee09a]{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.btn[data-v-5ceee09a]{background:var(--bg-tertiary);color:var(--text-primary)}.btn-primary[data-v-5ceee09a]{background:var(--accent-primary)}.delete-btn[data-v-5ceee09a]{background:var(--danger);color:#fff}.error[data-v-5ceee09a]{color:var(--danger)}button[data-v-5ceee09a]:disabled{opacity:.5;cursor:default}.clipboard-overlay[data-v-317cb3e2]{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.clipboard-dialog[data-v-317cb3e2]{width:min(520px,calc(100vw - 32px));padding:20px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md)}h3[data-v-317cb3e2]{font-size:16px}p[data-v-317cb3e2]{margin:12px 0;color:var(--text-secondary)}textarea[data-v-317cb3e2]{width:100%;height:180px;resize:vertical;padding:12px;background:var(--bg-primary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);font:13px/1.5 monospace}textarea[data-v-317cb3e2]:focus{outline:2px solid var(--accent-primary);outline-offset:2px}.clipboard-actions[data-v-317cb3e2]{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button[type=button][data-v-317cb3e2]{color:var(--text-primary);background:var(--bg-tertiary)}button[data-v-317cb3e2]:disabled{opacity:.5;cursor:default}.file-panel[data-v-771bf310]{display:flex;flex-direction:column;min-height:0;flex:1}.file-toolbar[data-v-771bf310]{display:flex;align-items:center;gap:4px;padding:10px 12px 4px}.project-name[data-v-771bf310]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:600}.file-toolbar button[data-v-771bf310],.panel-hint button[data-v-771bf310]{border:none;background:transparent;color:var(--text-secondary);padding:3px 5px;cursor:pointer;font-size:17px}.file-toolbar button[data-v-771bf310]:hover{background:var(--bg-tertiary);border-radius:4px}button[data-v-771bf310]:disabled{opacity:.4;cursor:default}.root-path[data-v-771bf310]{color:var(--text-secondary);font:11px/1.6 monospace;overflow-wrap:anywhere;padding:0 12px 10px;border-bottom:1px solid var(--border-color)}.file-tree[data-v-771bf310]{overflow:auto;padding:6px;flex:1;min-height:0}.panel-hint[data-v-771bf310]{padding:12px;color:var(--text-secondary);font-size:12px;list-style:none;overflow-wrap:anywhere}.error[data-v-771bf310]{color:var(--danger)}.git-warning[data-v-771bf310]{color:#e5b45c}.file-menu[data-v-771bf310]{position:fixed;z-index:110;width:min(230px,calc(100vw - 16px));padding:6px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-md)}.file-menu button[data-v-771bf310]{display:flex;justify-content:space-between;width:100%;text-align:left;padding:8px 10px;background:none;color:var(--text-primary);border:none;border-radius:4px;cursor:pointer}.file-menu button[data-v-771bf310]:hover:not(:disabled),.file-menu button[data-v-771bf310]:focus-visible{background:var(--bg-tertiary)}.file-menu span[data-v-771bf310]{color:var(--text-secondary)}.file-menu .danger[data-v-771bf310]{color:var(--danger)}.sidebar[data-v-b8faf56e]{width:var(--sidebar-width);border-right:1px solid var(--border-color);background:var(--bg-secondary);display:flex;flex-direction:column;flex-shrink:0;transition:all .3s cubic-bezier(.4,0,.2,1);overflow:hidden;height:100%;z-index:20}.sidebar.collapsed[data-v-b8faf56e]{width:72px}.sidebar-tabs[data-v-b8faf56e]{display:flex;flex-shrink:0;border-bottom:1px solid var(--border-color)}.sidebar-tabs button[data-v-b8faf56e]{flex:1;padding:12px 4px;border:none;border-bottom:2px solid transparent;background:none;color:var(--text-secondary);cursor:pointer;font:inherit;font-size:12px}.sidebar-tabs button[aria-selected=true][data-v-b8faf56e]{border-bottom-color:var(--accent-primary);color:var(--text-primary);background:var(--bg-primary)}.sessions-panel[data-v-b8faf56e],.files-panel[data-v-b8faf56e]{display:flex;flex-direction:column;min-height:0;flex:1}.sidebar-header[data-v-b8faf56e]{padding:16px;border-bottom:1px solid var(--border-color);display:flex;flex-direction:column;gap:12px}.sidebar-title[data-v-b8faf56e]{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-tertiary);font-weight:600}.new-session-btn[data-v-b8faf56e]{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;background:var(--accent-primary);color:#fff;border:none;border-radius:var(--radius-md);padding:10px;cursor:pointer;font-weight:500;transition:all .2s}.new-session-btn[data-v-b8faf56e]:hover{background:var(--accent-hover)}.sidebar.collapsed .new-session-btn[data-v-b8faf56e]{padding:10px 0}.session-list[data-v-b8faf56e]{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:4px}.empty-hint[data-v-b8faf56e]{text-align:center;padding:40px 10px;color:var(--text-tertiary)}.empty-hint p[data-v-b8faf56e]{font-size:14px;margin-bottom:4px}.empty-hint .sub-hint[data-v-b8faf56e]{font-size:12px;opacity:.7}@media(max-width:768px){.sidebar[data-v-b8faf56e]{position:fixed;top:0;left:0;bottom:0;width:var(--sidebar-width);transform:translate(0);box-shadow:var(--shadow-md);z-index:50}.sidebar.collapsed[data-v-b8faf56e]{transform:translate(-100%);width:var(--sidebar-width)}}.brand-mark[data-v-f54af403]{display:block;flex-shrink:0;object-fit:contain}.terminal-area[data-v-95819edf]{flex:1;display:flex;flex-direction:column;overflow:hidden;background:#000;position:relative}.terminal-frame[data-v-95819edf]{flex:1;width:100%;min-height:0;border:none;background:#000}.terminal-tools[data-v-95819edf]{display:flex;align-items:center;flex-shrink:0;gap:8px;padding:6px 12px;background:var(--bg-primary);border-bottom:1px solid var(--border-color);flex-wrap:wrap}.upload-progress[data-v-95819edf]{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-secondary)}.upload-progress progress[data-v-95819edf]{width:64px;height:4px;accent-color:var(--accent-primary)}.clipboard-btn[data-v-95819edf]{padding:4px 10px;background:var(--bg-secondary);color:var(--text-primary);border:1px solid var(--border-color);border-radius:var(--radius-sm);cursor:pointer}.clipboard-btn[data-v-95819edf]:hover:not(:disabled){background:var(--bg-tertiary)}.clipboard-btn[data-v-95819edf]:disabled,.clipboard-menu button[data-v-95819edf]:disabled{opacity:.45;cursor:default}.selection-hint[data-v-95819edf]{color:var(--text-secondary);font-size:12px}.clipboard-menu[data-v-95819edf]{position:fixed;z-index:100;width:min(280px,calc(100vw - 16px));padding:6px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-md)}.clipboard-menu button[data-v-95819edf]{display:flex;justify-content:space-between;width:100%;padding:8px 10px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--text-primary);text-align:left;cursor:pointer}.clipboard-menu button[data-v-95819edf]:hover:not(:disabled),.clipboard-menu button[data-v-95819edf]:focus-visible{background:var(--bg-tertiary)}.clipboard-menu span[data-v-95819edf],.clipboard-menu p[data-v-95819edf]{color:var(--text-secondary);font-size:12px}.clipboard-menu p[data-v-95819edf]{padding:8px 10px 4px;border-top:1px solid var(--border-color)}@media(max-width:600px){.selection-hint[data-v-95819edf]{display:none}}.welcome__container[data-v-95819edf]{flex:1;display:flex;align-items:center;justify-content:center;background:var(--bg-primary);background-image:radial-gradient(circle at center,var(--bg-secondary) 0%,var(--bg-primary) 100%)}.welcome__content[data-v-95819edf]{text-align:center;max-width:400px;padding:40px}.welcome-brand[data-v-95819edf]{display:flex;flex-direction:column;align-items:center;gap:12px;margin-bottom:24px}.logo-text[data-v-95819edf]{font-size:32px;font-weight:700;color:var(--text-primary);letter-spacing:-1px}.welcome__text[data-v-95819edf]{color:var(--text-secondary);font-size:16px;margin-bottom:24px}.highlight[data-v-95819edf]{color:var(--text-primary);font-weight:600}.sub-text[data-v-95819edf]{color:var(--text-tertiary);font-size:14px}.modal-overlay[data-v-ef0ce732]{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn-ef0ce732 .2s ease}.modal-content[data-v-ef0ce732]{width:100%;max-width:400px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);margin:16px;overflow:hidden;animation:slideUp-ef0ce732 .3s cubic-bezier(.16,1,.3,1)}.modal-header[data-v-ef0ce732]{padding:16px 20px;border-bottom:1px solid var(--border-color);display:flex;justify-content:space-between;align-items:center}.modal-header h3[data-v-ef0ce732]{font-size:16px;font-weight:600;color:var(--text-primary)}.close-btn[data-v-ef0ce732]{background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:18px;padding:4px;border-radius:4px}.close-btn[data-v-ef0ce732]:hover{background:var(--bg-tertiary);color:var(--text-primary)}.modal-body[data-v-ef0ce732]{padding:20px;display:flex;flex-direction:column;gap:16px}.form-group[data-v-ef0ce732]{display:flex;flex-direction:column;gap:8px}.label-text[data-v-ef0ce732]{font-size:13px;font-weight:500;color:var(--text-secondary)}select[data-v-ef0ce732]{width:100%;background:var(--bg-primary);border:1px solid var(--border-color);color:var(--text-primary);padding:10px;border-radius:var(--radius-md);outline:none;font-size:14px;appearance:none}select[data-v-ef0ce732]:focus{border-color:var(--accent-primary);box-shadow:0 0 0 2px var(--accent-dim)}.modal-footer[data-v-ef0ce732]{padding:16px 20px;background:var(--bg-primary);border-top:1px solid var(--border-color);display:flex;justify-content:flex-end;gap:12px}@keyframes fadeIn-ef0ce732{0%{opacity:0}to{opacity:1}}@keyframes slideUp-ef0ce732{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.login-screen[data-v-86b6b672]{height:100vh;display:flex;align-items:center;justify-content:center;background:var(--bg-primary)}.login-card[data-v-86b6b672]{width:min(360px,calc(100vw - 48px));padding:32px;display:flex;flex-direction:column;align-items:center;gap:12px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);box-shadow:var(--shadow-md)}.login-logo[data-v-86b6b672]{display:flex;align-items:center;justify-content:center;width:72px;height:72px}h1[data-v-86b6b672]{font-size:22px;font-weight:600;color:var(--text-primary);letter-spacing:-.5px}.login-hint[data-v-86b6b672]{margin:-4px 0 8px;font-size:13px;color:var(--text-secondary)}input[data-v-86b6b672]{width:100%;padding:10px 12px;font-size:14px;color:var(--text-primary);background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);outline:none}input[data-v-86b6b672]:focus{border-color:var(--accent-primary, #3b82f6)}.login-error[data-v-86b6b672]{width:100%;margin:0;font-size:13px;color:var(--danger)}.login-btn[data-v-86b6b672]{width:100%;margin-top:4px;padding:10px 12px;font-size:14px;font-weight:500;color:#fff;background:var(--accent-primary, #3b82f6);border:none;border-radius:var(--radius-md);cursor:pointer}.login-btn[data-v-86b6b672]:disabled{opacity:.5;cursor:default}.login-btn[data-v-86b6b672]:not(:disabled):hover{filter:brightness(1.1)}.toast-container[data-v-6bea03ca]{position:fixed;top:60px;right:16px;z-index:200;display:flex;flex-direction:column;gap:8px;max-width:min(520px,calc(100vw - 32px));max-height:calc(100vh - 80px);overflow:auto}.toast[data-v-6bea03ca]{padding:10px 16px;border-radius:8px;font-size:13px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);min-width:200px;background:var(--bg-secondary);display:flex;align-items:flex-start;gap:12px}.toast-message[data-v-6bea03ca]{white-space:pre-wrap;overflow-wrap:anywhere;max-height:35vh;overflow:auto;flex:1}.toast-actions[data-v-6bea03ca]{display:flex;gap:8px;flex-shrink:0}.toast-actions button[data-v-6bea03ca]{border:none;background:transparent;color:inherit;cursor:pointer;font:inherit}.toast.info[data-v-6bea03ca]{background:var(--bg-secondary);color:var(--text-primary)}.toast.error[data-v-6bea03ca]{background:var(--bg-secondary);color:var(--danger)}.toast.success[data-v-6bea03ca]{background:#4ade8026;color:#4ade80}.toast-enter-active[data-v-6bea03ca]{animation:slideIn-6bea03ca .3s ease}.toast-leave-active[data-v-6bea03ca]{animation:slideOut-6bea03ca .3s ease}@keyframes slideIn-6bea03ca{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideOut-6bea03ca{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:0}}.app-layout[data-v-cfab805f]{height:100vh;display:flex;flex-direction:column}.toolbar[data-v-cfab805f]{height:var(--toolbar-height);display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-bottom:1px solid var(--border-color);flex-shrink:0;z-index:30;background:var(--bg-primary)}.toolbar-left[data-v-cfab805f]{display:flex;align-items:center;gap:12px}.toggle-btn[data-v-cfab805f]{background:transparent;border:none;color:var(--text-secondary);cursor:pointer;padding:4px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center}.toggle-btn[data-v-cfab805f]:hover{color:var(--text-primary);background:var(--bg-tertiary)}.logo-wrapper[data-v-cfab805f]{display:flex;align-items:center;justify-content:center;flex-shrink:0}.toolbar-title[data-v-cfab805f]{font-size:16px;font-weight:600;color:var(--text-primary);letter-spacing:-.5px}.main-area[data-v-cfab805f]{flex:1;display:flex;overflow:hidden;position:relative}.sidebar-overlay[data-v-cfab805f]{display:none;position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:15;opacity:0;transition:opacity .3s ease;pointer-events:none}@media(max-width:768px){.sidebar-overlay[data-v-cfab805f]{display:block}.sidebar-overlay.show[data-v-cfab805f]{opacity:1;pointer-events:auto}}
@@ -10,8 +10,8 @@
10
10
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
11
11
  <link rel="manifest" href="/site.webmanifest" />
12
12
  <title>ACLI Hub</title>
13
- <script type="module" crossorigin src="/assets/index-CGMIO8Dh.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-B-BHzxof.css">
13
+ <script type="module" crossorigin src="/assets/index-DlR3k_jH.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-xnjgJSWe.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="app"></div>
@@ -1,13 +1,20 @@
1
1
  const express = require('express');
2
+ const os = require('os');
2
3
  const { sessionCookie, clearCookie, sessionTokenFromRequest } = require('../services/auth');
3
4
 
4
- module.exports = function (auth) {
5
+ module.exports = function (auth, { name = process.env.ACLI_HUB_NAME, hostname = os.hostname() } = {}) {
5
6
  const router = express.Router();
7
+ const normalizeName = value => (typeof value === 'string' ? value : '')
8
+ .replace(/[\s\u0000-\u001f\u007f]+/g, ' ').trim().slice(0, 100);
9
+ const instanceName = normalizeName(name) || normalizeName(hostname) || 'localhost';
6
10
 
7
11
  router.get('/status', (req, res) => {
8
12
  const authRequired = auth.isEnabled();
9
13
  const authenticated = !authRequired || auth.validateSession(sessionTokenFromRequest(req));
10
- res.json({ authRequired, authenticated });
14
+ // The login page needs the same tab identity as an authenticated page.
15
+ // Return only the chosen display name, not the hostname behind an alias.
16
+ res.set('Cache-Control', 'no-store');
17
+ res.json({ authRequired, authenticated, instance: { name: instanceName } });
11
18
  });
12
19
 
13
20
  router.post('/login', (req, res) => {
@@ -0,0 +1,71 @@
1
+ const test = require('node:test');
2
+ const assert = require('node:assert/strict');
3
+ const http = require('node:http');
4
+ const express = require('express');
5
+ const { AuthService } = require('../services/auth');
6
+ const authRoute = require('./auth');
7
+
8
+ async function serve(t, auth, identity) {
9
+ const app = express();
10
+ app.use(express.json());
11
+ app.use('/api/auth', authRoute(auth, identity));
12
+ const server = http.createServer(app);
13
+ await new Promise((resolve, reject) => {
14
+ server.once('error', reject);
15
+ server.listen(0, '127.0.0.1', resolve);
16
+ });
17
+ t.after(async () => {
18
+ server.closeAllConnections();
19
+ await new Promise(resolve => server.close(resolve));
20
+ });
21
+ const base = `http://127.0.0.1:${server.address().port}/api/auth`;
22
+ return (path, options) => fetch(`${base}${path}`, options);
23
+ }
24
+
25
+ test('hostname identity is available without authentication and status is never cached', async t => {
26
+ const request = await serve(t, new AuthService(), { name: '', hostname: 'dev-server' });
27
+ const response = await request('/status');
28
+ assert.equal(response.status, 200);
29
+ assert.equal(response.headers.get('cache-control'), 'no-store');
30
+ assert.deepEqual(await response.json(), {
31
+ authRequired: false, authenticated: true, instance: { name: 'dev-server' },
32
+ });
33
+ });
34
+
35
+ test('custom names are public before login, hide the hostname and survive login/logout unchanged', async t => {
36
+ const identity = { name: ' 东京\t开发机\n🚀 ', hostname: 'private.internal.example' };
37
+ const request = await serve(t, new AuthService('fixture-password'), identity);
38
+ identity.name = 'Not the startup name';
39
+ let response = await request('/status');
40
+ let data = await response.json();
41
+ assert.deepEqual(data, {
42
+ authRequired: true, authenticated: false, instance: { name: '东京 开发机 🚀' },
43
+ });
44
+ assert.ok(!JSON.stringify(data).includes(identity.hostname));
45
+
46
+ response = await request('/login', {
47
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify({ password: 'fixture-password' }),
49
+ });
50
+ assert.equal(response.status, 200);
51
+ const cookie = response.headers.get('set-cookie').split(';')[0];
52
+ data = await (await request('/status', { headers: { Cookie: cookie } })).json();
53
+ assert.equal(data.authenticated, true);
54
+ assert.deepEqual(data.instance, { name: '东京 开发机 🚀' });
55
+
56
+ await request('/logout', { method: 'POST', headers: { Cookie: cookie } });
57
+ data = await (await request('/status', { headers: { Cookie: cookie } })).json();
58
+ assert.equal(data.authenticated, false);
59
+ assert.deepEqual(data.instance, { name: '东京 开发机 🚀' });
60
+ });
61
+
62
+ test('empty/invalid names fall back safely, control characters are removed and names are bounded', async t => {
63
+ for (const name of ['', ' \t\n\0 ', null, 123]) {
64
+ const request = await serve(t, new AuthService(), { name, hostname: 'host-fallback' });
65
+ assert.deepEqual((await (await request('/status')).json()).instance, { name: 'host-fallback' });
66
+ }
67
+ const long = await serve(t, new AuthService(), { name: 'a'.repeat(200), hostname: 'host' });
68
+ assert.equal((await (await long('/status')).json()).instance.name, 'a'.repeat(100));
69
+ const empty = await serve(t, new AuthService(), { name: '', hostname: '' });
70
+ assert.equal((await (await empty('/status')).json()).instance.name, 'localhost');
71
+ });
@@ -0,0 +1,23 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const path = require('path');
4
+
5
+ function ensureUserConfig({ env = process.env, home = os.homedir(), warn = console.warn } = {}) {
6
+ const directory = path.join(env.XDG_CONFIG_HOME || path.join(home, '.config'), 'acli-hub');
7
+ const example = path.join(directory, '.env.example');
8
+ try {
9
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
10
+ try {
11
+ fs.copyFileSync(path.join(__dirname, '..', '..', '.env.example'), example, fs.constants.COPYFILE_EXCL);
12
+ } catch (err) {
13
+ // Preserve existing templates, including symlinks, without following them.
14
+ if (err.code !== 'EEXIST') throw err;
15
+ }
16
+ } catch (err) {
17
+ // A missing template must not prevent environment-only/read-only deployments.
18
+ warn(`WARNING: Could not create config template at ${example}: ${err.message}`);
19
+ }
20
+ return directory;
21
+ }
22
+
23
+ module.exports = { ensureUserConfig };
@@ -0,0 +1,87 @@
1
+ const test = require('node:test');
2
+ const assert = require('node:assert/strict');
3
+ const fs = require('node:fs');
4
+ const os = require('node:os');
5
+ const path = require('node:path');
6
+ const { ensureUserConfig } = require('./user-config');
7
+
8
+ function fixture(t) {
9
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'hub-user-config-'));
10
+ t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
11
+ const warnings = [];
12
+ return { directory, options: { env: {}, home: directory, warn: message => warnings.push(message) }, warnings };
13
+ }
14
+
15
+ const template = () => fs.readFileSync(path.join(__dirname, '..', '..', '.env.example'), 'utf8');
16
+
17
+ test('first startup creates the user config directory and packaged example, not an active .env', t => {
18
+ const { directory, options, warnings } = fixture(t);
19
+ const config = ensureUserConfig(options);
20
+ assert.equal(config, path.join(directory, '.config', 'acli-hub'));
21
+ assert.equal(fs.readFileSync(path.join(config, '.env.example'), 'utf8'), template());
22
+ assert.equal(fs.existsSync(path.join(config, '.env')), false);
23
+ if (process.platform !== 'win32') assert.equal(fs.statSync(config).mode & 0o777, 0o700);
24
+ assert.deepEqual(warnings, []);
25
+ });
26
+
27
+ test('XDG_CONFIG_HOME redirects initialization without creating the default config directory', t => {
28
+ const { directory, options, warnings } = fixture(t);
29
+ options.env.XDG_CONFIG_HOME = path.join(directory, 'custom config', '配置');
30
+ const config = ensureUserConfig(options);
31
+ assert.equal(config, path.join(options.env.XDG_CONFIG_HOME, 'acli-hub'));
32
+ assert.equal(fs.readFileSync(path.join(config, '.env.example'), 'utf8'), template());
33
+ assert.equal(fs.existsSync(path.join(directory, '.config')), false);
34
+ assert.deepEqual(warnings, []);
35
+ });
36
+
37
+ test('repeated startups preserve an existing template and active configuration', t => {
38
+ const { options, warnings } = fixture(t);
39
+ const config = ensureUserConfig(options);
40
+ const example = path.join(config, '.env.example');
41
+ const active = path.join(config, '.env');
42
+ fs.writeFileSync(example, '# user-maintained example\n');
43
+ fs.writeFileSync(active, 'ACLI_HUB_PORT=4321\n');
44
+ const before = fs.statSync(example);
45
+ ensureUserConfig(options);
46
+ ensureUserConfig(options);
47
+ assert.equal(fs.readFileSync(example, 'utf8'), '# user-maintained example\n');
48
+ assert.equal(fs.readFileSync(active, 'utf8'), 'ACLI_HUB_PORT=4321\n');
49
+ assert.equal(fs.statSync(example).mtimeMs, before.mtimeMs);
50
+ assert.deepEqual(warnings, []);
51
+ });
52
+
53
+ test('an existing directory receives a missing example without modifying its .env', t => {
54
+ const { directory, options, warnings } = fixture(t);
55
+ const config = path.join(directory, '.config', 'acli-hub');
56
+ fs.mkdirSync(config, { recursive: true });
57
+ fs.writeFileSync(path.join(config, '.env'), 'ACLI_HUB_NAME=东京开发机\n');
58
+ ensureUserConfig(options);
59
+ assert.equal(fs.readFileSync(path.join(config, '.env.example'), 'utf8'), template());
60
+ assert.equal(fs.readFileSync(path.join(config, '.env'), 'utf8'), 'ACLI_HUB_NAME=东京开发机\n');
61
+ assert.deepEqual(warnings, []);
62
+ });
63
+
64
+ test('an existing example symlink is preserved and its target is never overwritten', t => {
65
+ const { directory, options, warnings } = fixture(t);
66
+ const config = path.join(directory, '.config', 'acli-hub');
67
+ fs.mkdirSync(config, { recursive: true });
68
+ const target = path.join(directory, 'external-example');
69
+ fs.writeFileSync(target, 'keep this file');
70
+ const example = path.join(config, '.env.example');
71
+ fs.symlinkSync(target, example);
72
+ ensureUserConfig(options);
73
+ assert.equal(fs.readlinkSync(example), target);
74
+ assert.equal(fs.readFileSync(target, 'utf8'), 'keep this file');
75
+ assert.deepEqual(warnings, []);
76
+ });
77
+
78
+ test('unwritable config locations warn instead of blocking startup', t => {
79
+ const { directory, options, warnings } = fixture(t);
80
+ const blocked = path.join(directory, 'not-a-directory');
81
+ fs.writeFileSync(blocked, 'keep this file');
82
+ options.env.XDG_CONFIG_HOME = blocked;
83
+ assert.equal(ensureUserConfig(options), path.join(blocked, 'acli-hub'));
84
+ assert.equal(fs.readFileSync(blocked, 'utf8'), 'keep this file');
85
+ assert.equal(warnings.length, 1);
86
+ assert.match(warnings[0], /WARNING: Could not create config template/);
87
+ });