termbeam 1.12.5 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/assets/index-BoTisaNy.js +108 -0
- package/public/assets/index-yPsf11Zp.css +32 -0
- package/public/index.html +2 -2
- package/public/sw.js +2 -2
- package/src/cli/client.js +9 -0
- package/src/cli/index.js +11 -1
- package/src/cli/interactive.js +7 -0
- package/src/cli/resume.js +9 -0
- package/src/cli/service.js +10 -0
- package/src/server/auth.js +2 -0
- package/src/server/index.js +6 -0
- package/src/server/preview.js +2 -0
- package/src/server/routes.js +25 -2
- package/src/server/sessions.js +26 -4
- package/src/server/websocket.js +2 -0
- package/src/utils/git.js +3 -0
- package/src/utils/update-check.js +22 -2
- package/src/utils/version.js +23 -4
- package/public/assets/index-DhjvNUWH.js +0 -108
- package/public/assets/index-Lhj5V2mZ.css +0 -32
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
._backdrop_barei_1{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--bg);padding:1rem}._card_barei_10{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:2.5rem 2rem;width:100%;max-width:360px;display:flex;flex-direction:column;align-items:center;gap:1.5rem;animation:_fade-in_barei_1 .3s ease}._logo_barei_24{font-size:1.5rem;font-weight:700;color:var(--text);display:flex;align-items:center;gap:.5rem;-webkit-user-select:none;user-select:none}._logoIcon_barei_34{font-size:1.75rem}._form_barei_38{width:100%;display:flex;flex-direction:column;gap:.75rem}._input_barei_45{width:100%;padding:.65rem .85rem;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:8px;font-size:.95rem;outline:none;transition:border-color .15s;box-sizing:border-box}._input_barei_45:focus{border-color:var(--accent)}._button_barei_62{width:100%;padding:.65rem;background:var(--accent);color:var(--bg);border:none;border-radius:8px;font-size:.95rem;font-weight:600;cursor:pointer;transition:opacity .15s,transform .1s}._button_barei_62:hover:not(:disabled){opacity:.9}._button_barei_62:active:not(:disabled){transform:scale(.98)}._button_barei_62:disabled{opacity:.6;cursor:not-allowed}._error_barei_90{color:var(--danger);font-size:.85rem;text-align:center;margin:0}._banner_1ribv_1{display:flex;align-items:center;justify-content:center;gap:.75rem;padding:.55rem 1rem;background:var(--accent);color:var(--bg);font-size:.82rem;font-weight:500;animation:_slide-down_1ribv_1 .25s ease}._text_1ribv_14{flex:1;text-align:center}._dismiss_1ribv_19{background:transparent;border:none;color:var(--bg);font-size:1rem;cursor:pointer;opacity:.7;padding:.15rem .35rem;border-radius:4px;transition:opacity .15s;line-height:1}._dismiss_1ribv_19:hover{opacity:1}@keyframes _slide-down_1ribv_1{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}._wrapper_18ism_1{position:relative;overflow:hidden;border-radius:12px}._deleteBackground_18ism_7{position:absolute;top:0;right:0;bottom:0;width:80px;background:var(--danger);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;border-radius:0 12px 12px 0;color:#fff;font-size:12px;font-weight:600;-webkit-user-select:none;user-select:none;cursor:pointer;border:none;padding:0;transition:background .15s}._deleteBackground_18ism_7:active{background:#c0392b}._card_18ism_34{position:relative;display:flex;flex-direction:column;gap:8px;padding:16px;background:var(--surface);border:1px solid var(--border);border-radius:12px;touch-action:pan-y;-webkit-user-select:none;user-select:none;z-index:1;transition:border-color .15s}._card_18ism_34:hover{border-color:var(--accent)}._topRow_18ism_54{display:flex;align-items:center;justify-content:space-between;gap:8px}._nameGroup_18ism_61{display:flex;align-items:center;gap:8px;min-width:0}._colorDot_18ism_68{width:10px;height:10px;border-radius:50%;flex-shrink:0}._name_18ism_61{font-size:17px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._pidBadge_18ism_84{font-size:12px;color:var(--text-secondary);background:var(--bg);padding:2px 8px;border-radius:4px;white-space:nowrap;flex-shrink:0}._detailsRow_18ism_95{display:flex;flex-wrap:wrap;gap:6px 16px;font-size:13px;color:var(--text-secondary)}._detailItem_18ism_103{display:inline-flex;align-items:center;gap:4px;white-space:nowrap}._detailItem_18ism_103 svg{flex-shrink:0}._gitRow_18ism_115{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:12px}._gitBadge_18ism_122{display:inline-flex;align-items:center;gap:4px;background:var(--bg);padding:2px 8px;border-radius:4px;color:var(--text-secondary);white-space:nowrap}._gitBadge_18ism_122 svg{flex-shrink:0}._statusClean_18ism_137{color:var(--success)}._statusDirty_18ism_141{color:var(--danger)}._connectBtn_18ism_146{align-self:flex-end;background:var(--accent);color:#fff;border:none;border-radius:8px;padding:8px 20px;font-size:14px;font-weight:600;cursor:pointer;transition:opacity .15s,transform .15s}._connectBtn_18ism_146:hover{opacity:.9}._connectBtn_18ism_146:active{transform:scale(.97)}@media(pointer:coarse){._connectBtn_18ism_146{padding:10px 24px}}._container_tkgsa_1{display:flex;flex-direction:column;min-height:0;flex:1;overflow:hidden}._breadcrumb_tkgsa_9{display:flex;align-items:center;flex-wrap:wrap;gap:.15rem;font-size:.8rem;color:var(--text-secondary);padding:.4rem .6rem;background:var(--bg);border-radius:6px;border:1px solid var(--border-subtle);min-height:2rem;flex-shrink:0}._breadcrumbSegment_tkgsa_24{background:transparent;border:none;color:var(--accent);cursor:pointer;padding:.1rem .2rem;border-radius:3px;font-size:.8rem;transition:background .1s}._breadcrumbSegment_tkgsa_24:hover{background:var(--surface)}._breadcrumbSep_tkgsa_39{color:var(--text-muted);-webkit-user-select:none;user-select:none}._list_tkgsa_44{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px;padding:.25rem;background:var(--bg);border-radius:8px;border:1px solid var(--border-subtle);margin:.5rem 0}._entry_tkgsa_58{display:flex;align-items:center;gap:.5rem;padding:.4rem .6rem;border-radius:6px;border:none;background:transparent;color:var(--text);font-size:.82rem;cursor:pointer;text-align:left;width:100%;transition:background .1s}._entry_tkgsa_58:hover{background:var(--surface)}._entryIcon_tkgsa_78{flex-shrink:0;font-size:.9rem}._entryName_tkgsa_83{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._fileEntry_tkgsa_89{color:var(--text-dim);cursor:default}._fileEntry_tkgsa_89:hover{background:transparent}._actions_tkgsa_98{display:flex;gap:.5rem;justify-content:flex-end;flex-shrink:0;padding-top:.5rem}._selectBtn_tkgsa_106{padding:.45rem 1rem;background:var(--accent);color:var(--bg);border:none;border-radius:8px;font-size:.85rem;font-weight:600;cursor:pointer;transition:opacity .15s}._selectBtn_tkgsa_106:hover{opacity:.9}._selectBtn_tkgsa_106:disabled{opacity:.6;cursor:not-allowed}._cancelBtn_tkgsa_127{padding:.45rem 1rem;background:transparent;color:var(--text-secondary);border:1px solid var(--border);border-radius:8px;font-size:.85rem;cursor:pointer;transition:border-color .15s,color .15s}._cancelBtn_tkgsa_127:hover{border-color:var(--text-secondary);color:var(--text)}._loading_tkgsa_145{display:flex;align-items:center;justify-content:center;padding:2rem;color:var(--text-dim);font-size:.85rem}._error_tkgsa_154{color:var(--danger);font-size:.82rem;text-align:center;padding:1rem}._overlay_qhgrm_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay-bg);z-index:200;animation:_fade-in_qhgrm_1 .15s ease}._content_qhgrm_9{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90%;max-width:440px;max-height:85dvh;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:1.5rem;z-index:201;box-shadow:0 8px 24px #0006;animation:_fade-in_qhgrm_1 .2s ease}._title_qhgrm_27{font-size:1.15rem;font-weight:700;color:var(--text);margin:0 0 1.25rem}._form_qhgrm_34{display:flex;flex-direction:column;gap:1rem}._field_qhgrm_40{display:flex;flex-direction:column;gap:.3rem}._label_qhgrm_46{font-size:.78rem;color:var(--text-secondary);font-weight:500;text-transform:uppercase;letter-spacing:.03em}._input_qhgrm_54{padding:.55rem .75rem;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:8px;font-size:.9rem;outline:none;transition:border-color .15s;width:100%;box-sizing:border-box}._input_qhgrm_54:focus{border-color:var(--accent)}._select_qhgrm_71{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23888' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .6rem center;padding-right:2rem}._dirRow_qhgrm_81{display:flex;gap:.5rem}._dirRow_qhgrm_81 ._input_qhgrm_54{flex:1}._browseBtn_qhgrm_90{padding:.55rem .85rem;background:var(--surface);color:var(--text-secondary);border:1px solid var(--border);border-radius:8px;font-size:.82rem;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}._browseBtn_qhgrm_90:hover{border-color:var(--accent);color:var(--text)}._colorPicker_qhgrm_109{display:flex;gap:.5rem;flex-wrap:wrap}._colorDot_qhgrm_115{width:28px;height:28px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:border-color .15s,transform .1s}._colorDot_qhgrm_115:hover{transform:scale(1.15)}._colorDotActive_qhgrm_130{border-color:var(--text)}._actions_qhgrm_134{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.5rem}._cancelBtn_qhgrm_141{padding:.55rem 1rem;background:transparent;color:var(--text-secondary);border:1px solid var(--border);border-radius:8px;font-size:.88rem;cursor:pointer;transition:border-color .15s,color .15s}._cancelBtn_qhgrm_141:hover{border-color:var(--text-secondary);color:var(--text)}._submitBtn_qhgrm_159{padding:.55rem 1.25rem;background:var(--accent);color:var(--bg);border:none;border-radius:8px;font-size:.88rem;font-weight:600;cursor:pointer;transition:opacity .15s}._submitBtn_qhgrm_159:hover:not(:disabled){opacity:.9}._submitBtn_qhgrm_159:disabled{opacity:.6;cursor:not-allowed}@media(pointer:coarse){._content_qhgrm_9{top:30%;transform:translate(-50%,-30%)}}._page_oq88p_1{min-height:100vh;min-height:100dvh;background:var(--bg);display:flex;flex-direction:column}._header_oq88p_9{position:relative;padding:calc(20px + env(safe-area-inset-top,0px)) 16px 12px;border-bottom:1px solid var(--border);text-align:center}._title_oq88p_16{font-size:22px;font-weight:700;color:var(--text);margin:0}._accent_oq88p_23{color:var(--accent)}._tagline_oq88p_27{font-size:13px;color:var(--text-secondary);margin:4px 0 0}._headerBtn_oq88p_33{position:absolute;top:calc(16px + env(safe-area-inset-top,0px));display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--text-dim);cursor:pointer;transition:border-color .15s,color .15s;padding:0}._headerBtn_oq88p_33:hover{border-color:var(--accent);color:var(--text)}._shareBtn_oq88p_57{right:96px}._refreshBtn_oq88p_61{right:56px}._themeBtn_oq88p_65{position:absolute;top:calc(16px + env(safe-area-inset-top,0px));right:16px}._themePanel_oq88p_71{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:240px;max-height:min(420px,60vh);display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--border);border-radius:12px;z-index:1000;box-shadow:0 12px 40px #0006;animation:_themePickerFadeIn_oq88p_1 .15s ease}._themePanelHeader_oq88p_88{display:flex;align-items:center;justify-content:space-between;padding:.6rem .75rem;border-bottom:1px solid var(--border);flex-shrink:0}._themePanelTitle_oq88p_97{font-size:.85rem;font-weight:600;color:var(--text)}._themePanelClose_oq88p_103{background:none;border:none;color:var(--text-dim);font-size:.85rem;cursor:pointer;padding:.15rem .35rem;border-radius:4px;line-height:1;transition:color .15s,background .15s}._themePanelClose_oq88p_103:hover{color:var(--text);background:var(--border)}._themePanelList_oq88p_122{overflow-y:auto;padding:.35rem;flex:1}@keyframes _themePickerFadeIn_oq88p_1{0%{opacity:0}to{opacity:1}}._themeOption_oq88p_137{display:flex;align-items:center;gap:.5rem;padding:.45rem .6rem;border-radius:6px;border:none;background:transparent;color:var(--text);font-size:.82rem;cursor:pointer;width:100%;text-align:left;transition:background .1s}._themeOption_oq88p_137:hover{background:var(--bg)}._themeOptionActive_oq88p_157{color:var(--accent);font-weight:600}._themeSwatch_oq88p_162{width:14px;height:14px;border-radius:4px;border:1px solid var(--border-subtle, rgba(255, 255, 255, .1));flex-shrink:0}._themeCheck_oq88p_170{margin-left:auto;font-size:.75rem;color:var(--accent)}._content_oq88p_176{flex:1;overflow-y:auto}._sessionsList_oq88p_181{display:flex;flex-direction:column;padding:16px;padding-bottom:calc(80px + env(safe-area-inset-bottom,0px));gap:12px}._emptyState_oq88p_189{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;padding:4rem 1rem;color:var(--text-dim);text-align:center}._emptyIcon_oq88p_200{font-size:2.5rem;opacity:.5}._emptyText_oq88p_205{font-size:.95rem}._emptyHint_oq88p_209{font-size:.82rem;color:var(--text-muted)}._newSessionBtn_oq88p_214{position:fixed;bottom:calc(16px + env(safe-area-inset-bottom,0px));left:calc(16px + env(safe-area-inset-left,0px));right:calc(16px + env(safe-area-inset-right,0px));padding:14px;background:var(--accent);color:#fff;border:none;border-radius:12px;font-size:15px;font-weight:600;cursor:pointer;box-shadow:0 2px 8px #0078d44d;z-index:50;transition:transform .15s,opacity .15s;text-align:center}._newSessionBtn_oq88p_214:hover{opacity:.92}._newSessionBtn_oq88p_214:active{transform:scale(.98)}._refreshSpin_oq88p_243{animation:_spin_oq88p_1 .6s linear}@keyframes _spin_oq88p_1{to{transform:rotate(360deg)}}/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
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}._pane_dc7r7_1{flex:1;position:relative;overflow:hidden;min-height:0}._terminalContainer_dc7r7_8{width:100%;height:100%;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none}._terminalContainer_dc7r7_8 .xterm-screen>*{pointer-events:none}._scrollToBottom_dc7r7_29{position:absolute;bottom:12px;right:12px;width:44px;height:44px;border-radius:50%;border:1px solid var(--border);background:var(--surface);color:var(--text);font-size:20px;cursor:pointer;display:flex;align-items:center;justify-content:center;opacity:.8;transition:opacity .2s;z-index:10}._scrollToBottom_dc7r7_29:hover{opacity:1}._exitOverlay_dc7r7_53{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:var(--overlay-bg, rgba(0, 0, 0, .6));z-index:5}._exitMessage_dc7r7_63{color:var(--text-secondary);font-size:1.1rem;padding:1rem 2rem;background:var(--surface);border-radius:8px;border:1px solid var(--border)}._reconnectingBar_dc7r7_73{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;justify-content:center;gap:.5rem;padding:.35rem 0;background:var(--surface);border-bottom:1px solid var(--border);color:var(--text-secondary);font-size:.85rem;z-index:5;animation:_slideDown_dc7r7_1 .2s ease}@keyframes _slideDown_dc7r7_1{0%{transform:translateY(-100%)}to{transform:translateY(0)}}._reconnectingDot_dc7r7_100{width:8px;height:8px;border-radius:50%;background:var(--text-secondary);animation:_pulse_dc7r7_1 1.2s ease-in-out infinite}@keyframes _pulse_dc7r7_1{0%,to{opacity:.3}50%{opacity:1}}._reconnectOverlay_dc7r7_119{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:var(--overlay-bg, rgba(0, 0, 0, .6));z-index:5;animation:_fadeIn_dc7r7_1 .2s ease}@keyframes _fadeIn_dc7r7_1{0%{opacity:0}to{opacity:1}}._reconnectContent_dc7r7_139{display:flex;flex-direction:column;align-items:center;gap:1rem;padding:1.5rem 2rem;background:var(--surface);border-radius:12px;border:1px solid var(--border)}._reconnectMessage_dc7r7_150{color:var(--text-secondary);font-size:1.1rem}._reconnectActions_dc7r7_155{display:flex;gap:.75rem}._reconnectBtn_dc7r7_160{padding:.5rem 1.25rem;border-radius:8px;border:1px solid var(--border);background:var(--surface);color:var(--text);font-size:.9rem;cursor:pointer;text-decoration:none;transition:background .15s,border-color .15s}._reconnectBtn_dc7r7_160:hover{background:var(--border)}._tabBar_c6cms_1{display:flex;align-items:center;gap:2px;padding:0 8px;height:38px;background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0;overflow:hidden}._tabBarInline_c6cms_13{flex:1;display:flex;align-items:center;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:2px;padding:0 4px;height:100%}._tabBarInline_c6cms_13::-webkit-scrollbar{display:none}@media(max-width:640px){._tabBar_c6cms_1{display:none}}@media(pointer:coarse){._addBtnLabel_c6cms_37{display:none}}._tabScroller_c6cms_42{display:flex;align-items:center;gap:2px;overflow-x:auto;overflow-y:hidden;flex:1;min-width:0;scrollbar-width:none}._tabScroller_c6cms_42::-webkit-scrollbar{display:none}._tab_c6cms_1{position:relative;display:flex;align-items:center;gap:6px;padding:4px 10px;border-radius:6px;cursor:grab;white-space:nowrap;-webkit-user-select:none;user-select:none;font-size:12px;font-weight:500;color:var(--text-dim);transition:background .15s,color .15s;border-left:3px solid transparent;flex-shrink:0;height:30px;-webkit-tap-highlight-color:transparent}._tab_c6cms_1:hover{background:var(--border);color:var(--text)}._tabActive_c6cms_84{color:var(--text);font-weight:600;background:var(--bg)}._tabSplit_c6cms_90{background:#0078d41a;color:var(--text)}._colorDot_c6cms_95{width:8px;height:8px;border-radius:50%;flex-shrink:0}._tabName_c6cms_102{max-width:100px;overflow:hidden;text-overflow:ellipsis}._tabActivity_c6cms_108{font-size:10px;color:var(--text-muted);flex-shrink:0}._closeBtn_c6cms_114{display:none;align-items:center;justify-content:center;background:none;border:none;width:18px;height:18px;border-radius:4px;font-size:14px;line-height:1;color:var(--text-muted);cursor:pointer;padding:0;transition:background .15s,color .15s}._tab_c6cms_1:hover ._closeBtn_c6cms_114,._tabActive_c6cms_84 ._closeBtn_c6cms_114{display:flex}._closeBtn_c6cms_114:hover{color:var(--danger);background:transparent}._addBtn_c6cms_37{display:flex;align-items:center;justify-content:center;gap:4px;padding:0 10px;height:28px;border-radius:6px;font-size:13px;color:var(--text-dim);flex-shrink:0;white-space:nowrap;transition:background .15s,color .15s}._addBtn_c6cms_37:hover{background:var(--bg);color:var(--text)}._statusDot_c6cms_165{width:6px;height:6px;border-radius:50%;flex-shrink:0;margin-left:4px}._unreadDot_c6cms_173{width:6px;height:6px;border-radius:50%;background:var(--accent);flex-shrink:0;animation:_pulse_c6cms_1 1.5s ease-in-out infinite}@keyframes _pulse_c6cms_1{0%,to{opacity:1}50%{opacity:.3}}._preview_pobdq_1{position:absolute;top:100%;left:50%;transform:translate(-50%);z-index:100;margin-top:6px;padding:8px 10px;background:var(--surface);border:1px solid var(--border);border-radius:6px;box-shadow:0 4px 16px #0006;min-width:220px;max-width:360px;pointer-events:none;animation:_fade-in_pobdq_1 .15s ease-out}._lines_pobdq_19{font-family:Cascadia Code,Fira Code,Menlo,Consolas,monospace;font-size:11px;line-height:1.4;color:var(--text-secondary);white-space:pre;overflow:hidden;text-overflow:ellipsis}._empty_pobdq_29{color:var(--text-dim);font-style:italic;font-family:inherit;font-size:12px}._touchBar_g2tvp_1{position:fixed;bottom:0;left:0;right:0;z-index:50;height:calc(80px + env(safe-area-inset-bottom,0px));padding:6px 4px;padding-bottom:calc(6px + env(safe-area-inset-bottom,0px));background:var(--surface);display:flex;flex-direction:column;gap:4px;justify-content:center;user-select:none;-webkit-user-select:none;touch-action:none;overscroll-behavior:none}._row_g2tvp_21{display:grid;grid-template-columns:repeat(8,1fr);gap:4px;padding:0 2px}._keyBtn_g2tvp_28{min-width:0;height:34px;background:var(--key-bg);color:var(--text);border:1px solid var(--key-border);border-radius:6px;font-size:13px;font-weight:500;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 1px 0 var(--key-shadow);-webkit-tap-highlight-color:transparent;font-family:inherit;transition:background .08s}._special_g2tvp_47,._modifier_g2tvp_53{background:var(--key-special-bg);font-size:12px;font-weight:600}._modifier_g2tvp_53._active_g2tvp_59{background:var(--accent, #0078d4);box-shadow:0 1px #0003,0 0 10px #0078d480}._iconBtn_g2tvp_66{font-size:16px}._keyEnter_g2tvp_70{grid-column:span 2;background:var(--accent, #0078d4);color:#fff;font-size:20px}._keyDanger_g2tvp_77{background:#5c2222;color:#f87171}._flash_g2tvp_82{background:var(--accent, #0078d4)!important;color:#fff!important}._micBtn_g2tvp_87{transition:transform .2s ease,border-radius .2s ease,width .2s ease;position:relative}._recording_g2tvp_95{background:#dc2626!important;color:#fff!important;transform:scale(2);border-radius:50%;aspect-ratio:1;z-index:10;animation:_micRipple_g2tvp_1 1s ease-out infinite;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}._micDot_g2tvp_110{display:block;width:6px;height:6px;border-radius:50%;background:#fff;animation:_micDotBlink_g2tvp_1 1s ease-in-out infinite}._lockHint_g2tvp_119{position:absolute;bottom:calc(100% + 6px);left:50%;opacity:.7;animation:_lockHintBounce_g2tvp_1 1.2s ease-in-out infinite;filter:drop-shadow(0 1px 3px rgba(0,0,0,.4))}@keyframes _micDotBlink_g2tvp_1{0%,to{opacity:1}50%{opacity:.3}}@keyframes _lockHintBounce_g2tvp_1{0%,to{transform:translate(-50%) translateY(0);opacity:.5}50%{transform:translate(-50%) translateY(-4px);opacity:1}}._micLocked_g2tvp_150{animation:_micLockedPulse_g2tvp_1 1.5s ease-in-out infinite;transform:scale(2);border-radius:50%;aspect-ratio:1}@keyframes _micRipple_g2tvp_1{0%{box-shadow:0 0 #dc262680}70%{box-shadow:0 0 0 22px #dc262600}to{box-shadow:0 0 #dc262600}}@keyframes _micLockedPulse_g2tvp_1{0%,to{box-shadow:0 0 0 4px #dc26264d}50%{box-shadow:0 0 0 8px #dc262626}}@media(orientation:landscape)and (max-height:500px){._touchBar_g2tvp_1{height:calc(44px + env(safe-area-inset-bottom,0px));padding:4px;padding-bottom:calc(4px + env(safe-area-inset-bottom,0px))}._keyBtn_g2tvp_28{height:28px;font-size:12px}}._searchBar_1su33_1{position:absolute;top:calc(40px + env(safe-area-inset-top,0px));right:0;z-index:50;display:flex;align-items:center;gap:6px;padding:6px 12px;background:var(--surface, #1e1e2e);border-bottom:1px solid var(--border, #333);box-shadow:0 2px 8px #0000004d;animation:_slide-down_1su33_1 .15s ease}._input_1su33_16{flex:1;min-width:0;padding:6px 10px;border:1px solid var(--border, #444);border-radius:4px;background:var(--input-bg, #111);color:var(--text, #ccc);font-size:13px;outline:none;font-family:inherit}._input_1su33_16:focus{border-color:var(--accent, #4a9eff)}._btn_1su33_33{background:none;border:1px solid var(--border, #444);border-radius:4px;color:var(--text, #ccc);cursor:pointer;padding:4px 8px;font-size:13px;line-height:1}._btn_1su33_33:hover{background:var(--border, #333)}._btnActive_1su33_48{background:var(--accent, #4a9eff);color:#fff;border-color:var(--accent, #4a9eff)}._indicator_1su33_54{font-size:12px;color:var(--text-muted, #666);white-space:nowrap}@keyframes _slide-down_1su33_1{0%{transform:translateY(-100%)}to{transform:translateY(0)}}._overlay_153fc_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay-bg);z-index:200;animation:_fadeIn_153fc_1 .15s ease-out}._content_153fc_9{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:24px;width:min(380px,calc(100vw - 32px));max-height:85dvh;overflow-y:auto;z-index:201;animation:_slideUp_153fc_1 .15s ease-out}._title_153fc_25{font-size:1.1rem;font-weight:600;color:var(--text);margin:0 0 8px}._description_153fc_32{font-size:.85rem;color:var(--text-secondary);margin:0 0 20px}._label_153fc_38{display:block;font-size:.8rem;color:var(--text-secondary);margin-bottom:6px}._input_153fc_45{width:100%;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:1rem;font-family:inherit;outline:none;box-sizing:border-box}._input_153fc_45:focus{border-color:var(--accent)}._input_153fc_45::-webkit-inner-spin-button,._input_153fc_45::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}._input_153fc_45[type=number]{-moz-appearance:textfield}._actions_153fc_73{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}._cancelBtn_153fc_80{padding:8px 16px;background:transparent;border:1px solid var(--border);border-radius:6px;color:var(--text-secondary);cursor:pointer;font-size:.9rem;transition:border-color .15s}._cancelBtn_153fc_80:hover{border-color:var(--text-secondary)}._openBtn_153fc_95{padding:8px 20px;background:var(--accent);border:none;border-radius:6px;color:#fff;cursor:pointer;font-size:.9rem;font-weight:500;transition:background .15s}._openBtn_153fc_95:hover:not(:disabled){background:var(--accent-hover)}._openBtn_153fc_95:disabled{opacity:.5;cursor:not-allowed}._close_153fc_116{position:absolute;top:12px;right:12px;background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:1.2rem;line-height:1;padding:4px}._close_153fc_116:hover{color:var(--text)}@media(pointer:coarse){._content_153fc_9{top:30%;transform:translate(-50%,-30%)}}@keyframes _fadeIn_153fc_1{0%{opacity:0}to{opacity:1}}@keyframes _slideUp_153fc_1{0%{opacity:0;transform:translate(-50%,-48%)}to{opacity:1;transform:translate(-50%,-50%)}}._backdrop_1rez3_1{position:fixed;top:0;right:0;bottom:0;left:0;z-index:300;background:#0006}._panel_1rez3_8{position:fixed;top:0;right:-100%;width:min(90vw,300px);height:100%;background:var(--bg, #1e1e2e);border-left:1px solid var(--border, #333);z-index:301;box-shadow:0 8px 24px #0006;display:flex;flex-direction:column;transition:right .25s ease}._panelOpen_1rez3_23{right:0}._header_1rez3_27{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid var(--border, #333)}._title_1rez3_35{font-weight:600;font-size:14px;color:var(--text, #ccc)}._closeBtn_1rez3_41{background:none;border:none;color:var(--text, #999);cursor:pointer;font-size:18px;padding:4px 8px;border-radius:4px;line-height:1}._closeBtn_1rez3_41:hover{background:var(--border, #333)}._body_1rez3_56{overflow-y:auto;flex:1;padding:8px}._section_1rez3_62{margin-bottom:8px}._sectionTitle_1rez3_66{font-size:10px;font-weight:700;color:var(--text-muted, #666);text-transform:uppercase;letter-spacing:1px;padding:6px 10px 4px}._btn_1rez3_75{display:flex;align-items:center;gap:10px;width:100%;background:none;border:none;color:var(--text, #ccc);padding:10px 12px;border-radius:6px;font-size:13px;cursor:pointer;transition:background .15s}._btn_1rez3_75:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}._btn_1rez3_75 svg{width:16px;height:16px;opacity:.7;flex-shrink:0}._themeBackdrop_1rez3_102{position:fixed;top:0;right:0;bottom:0;left:0;z-index:999}._themeFloating_1rez3_108{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:240px;max-height:min(420px,60vh);display:flex;flex-direction:column;background:var(--surface, #252526);border:1px solid var(--border, #333);border-radius:12px;z-index:1000;box-shadow:0 12px 40px #0006}._list_1rez3_124{flex:1;overflow-y:auto;padding:8px}._item_1rez3_130{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:6px;cursor:pointer;color:var(--text, #ccc);font-size:13px;border:none;background:none;width:100%;text-align:left;transition:background .15s}._item_1rez3_130:hover,._item_1rez3_130[data-selected=true],._item_1rez3_130[aria-selected=true]{background:var(--surface-hover, rgba(255, 255, 255, .08))}._backdrop_1df0i_1{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;background:var(--overlay-bg);animation:_fade-in_1df0i_1 .2s ease-out}._backdrop_1df0i_1[data-closing=true]{animation:_fade-out_1df0i_1 .2s ease-in forwards}._panel_1df0i_13{position:fixed;top:0;left:0;bottom:0;z-index:201;width:min(85vw,380px);background:var(--surface);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden;padding-top:env(safe-area-inset-top,0px);padding-left:env(safe-area-inset-left,0px);padding-bottom:env(safe-area-inset-bottom,0px);box-shadow:0 4px 12px #0000004d;animation:_slide-in-left_1df0i_1 .25s ease-out}._panel_1df0i_13[data-closing=true]{animation:_slide-out-left_1df0i_1 .2s ease-in forwards}._header_1df0i_38{display:flex;flex-direction:column;padding:16px 14px 12px;border-bottom:1px solid var(--border);position:relative}._brand_1df0i_46{display:flex;align-items:center;gap:8px;font-size:18px;font-weight:700;letter-spacing:-.02em;color:var(--text)}._brand_1df0i_46 svg{flex-shrink:0;color:var(--accent)}._version_1df0i_61{font-size:11px;color:var(--text-muted);font-weight:400;margin-top:2px;padding-left:28px}._closeBtn_1df0i_69{position:absolute;top:14px;right:10px;background:none;border:none;color:var(--text-dim);width:30px;height:30px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:20px;transition:background .15s,color .15s;-webkit-tap-highlight-color:transparent}._closeBtn_1df0i_69:hover{background:var(--border);color:var(--text)}._sectionTitle_1df0i_97{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);padding:10px 14px 4px}._list_1df0i_108{flex:1 1 0;min-height:0;overflow-y:auto;padding:8px;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:6px}._card_1df0i_121{background:var(--bg);border:1px solid var(--border);border-radius:10px;cursor:pointer;overflow:hidden;flex-shrink:0;transition:background .15s,border-color .15s;-webkit-tap-highlight-color:transparent}._card_1df0i_121:hover{border-color:var(--accent)}._cardActive_1df0i_138{border-color:var(--accent);border-width:2px}._cardHeader_1df0i_145{display:flex;align-items:center;gap:8px;padding:10px 12px 6px}._cardDot_1df0i_152{width:10px;height:10px;border-radius:50%;flex-shrink:0}._cardName_1df0i_159{font-size:13px;font-weight:600;color:var(--text);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._cardStatus_1df0i_169{width:7px;height:7px;border-radius:50%;flex-shrink:0}._cardClose_1df0i_176{background:none;border:none;color:var(--text-muted);width:26px;height:26px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;padding:0;transition:background .15s,color .15s;-webkit-tap-highlight-color:transparent}._cardClose_1df0i_176:hover{background:var(--danger);color:#fff}._cardMeta_1df0i_203{padding:0 12px 4px;font-size:10px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._cardGit_1df0i_214{display:flex;flex-wrap:wrap;gap:3px 6px;padding:0 12px 4px;font-size:10px;color:var(--text-secondary);align-items:center}._gitBadge_1df0i_224{display:inline-flex;align-items:center;gap:3px;background:var(--surface);padding:1px 6px;border-radius:3px}._gitClean_1df0i_233{color:var(--success)}._gitDirty_1df0i_237{color:#fbbf24}._cardPreview_1df0i_243{margin:0 8px 8px;padding:6px 8px;background:var(--surface);border-radius:6px;font-family:NerdFont,JetBrains Mono,monospace;font-size:9px;line-height:1.3;color:var(--text-secondary);white-space:pre;overflow:hidden;max-height:72px;-webkit-text-size-adjust:none}._cardPreviewEmpty_1df0i_258{font-style:italic;color:var(--text-muted);text-align:center;font-family:inherit;font-size:11px;white-space:normal}._footer_1df0i_269{padding:8px;border-top:1px solid var(--border)}._newBtn_1df0i_274{width:100%;padding:10px;border:1px dashed var(--border);border-radius:8px;background:none;color:var(--accent);font-size:14px;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;transition:background .15s}._newBtn_1df0i_274:hover{background:var(--bg)}._newBtn_1df0i_274:active{transform:scale(.98)}._unreadDot_1df0i_299{width:6px;height:6px;border-radius:50%;background:var(--accent);flex-shrink:0;animation:_pulse_1df0i_1 1.5s ease-in-out infinite}@keyframes _pulse_1df0i_1{0%,to{opacity:1}50%{opacity:.3}}@keyframes _slide-in-left_1df0i_1{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes _slide-out-left_1df0i_1{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes _fade-in_1df0i_1{0%{opacity:0}to{opacity:1}}@keyframes _fade-out_1df0i_1{0%{opacity:1}to{opacity:0}}._overlay_h1a26_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay-bg);z-index:200;animation:_fadeIn_h1a26_1 .15s ease-out}._content_h1a26_9{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:24px;width:min(440px,calc(100vw - 32px));max-height:85dvh;overflow-y:auto;z-index:201;box-shadow:0 8px 24px #0006;animation:_slideUp_h1a26_1 .15s ease-out}._title_h1a26_26{font-size:1.1rem;font-weight:600;color:var(--text);margin:0 0 16px}._dropZone_h1a26_33{border:2px dashed var(--border);border-radius:8px;padding:32px 16px;text-align:center;cursor:pointer;transition:border-color .15s,background .15s;color:var(--text-secondary);font-size:.9rem}._dropZone_h1a26_33:hover,._dropZoneDragOver_h1a26_47{border-color:var(--accent);background:#4a9eff14;background:color-mix(in srgb,var(--accent) 8%,transparent)}._fileList_h1a26_53{margin-top:12px;max-height:160px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}._fileInfo_h1a26_62{padding:8px 12px;background:var(--bg);border-radius:6px;font-size:.85rem;color:var(--text);display:flex;justify-content:space-between;align-items:center}._fileName_h1a26_73{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:240px}._fileSize_h1a26_81{color:var(--text-dim);flex-shrink:0;margin-left:8px}._targetDirGroup_h1a26_87{margin-top:16px}._label_h1a26_91{display:block;font-size:.8rem;color:var(--text-secondary);margin-bottom:6px}._targetDirRow_h1a26_98{display:flex;gap:8px}._input_h1a26_103{flex:1;padding:8px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.9rem;font-family:inherit;outline:none}._input_h1a26_103:focus{border-color:var(--accent)}._browseBtn_h1a26_119{padding:8px 14px;background:var(--surface);border:1px solid var(--border);border-radius:6px;color:var(--text);cursor:pointer;font-size:.85rem;white-space:nowrap;transition:border-color .15s}._browseBtn_h1a26_119:hover{border-color:var(--accent)}._hint_h1a26_135{margin-top:8px;font-size:.75rem;color:var(--text-dim)}._actions_h1a26_141{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}._cancelBtn_h1a26_148{padding:8px 16px;background:transparent;border:1px solid var(--border);border-radius:6px;color:var(--text-secondary);cursor:pointer;font-size:.9rem;transition:border-color .15s}._cancelBtn_h1a26_148:hover{border-color:var(--text-secondary)}._uploadBtn_h1a26_163{padding:8px 20px;background:var(--accent);border:none;border-radius:6px;color:#fff;cursor:pointer;font-size:.9rem;font-weight:500;transition:background .15s}._uploadBtn_h1a26_163:hover:not(:disabled){background:var(--accent-hover)}._uploadBtn_h1a26_163:disabled{opacity:.5;cursor:not-allowed}._close_h1a26_184{position:absolute;top:12px;right:12px;background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:1.2rem;line-height:1;padding:4px}._close_h1a26_184:hover{color:var(--text)}._progressWrapper_h1a26_201{margin-top:12px;background:var(--bg);border-radius:6px;height:24px;position:relative;overflow:hidden;border:1px solid var(--border)}._progressBar_h1a26_211{height:100%;background:var(--accent);border-radius:5px;transition:width .15s ease-out;min-width:0}._progressLabel_h1a26_219{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:600;color:var(--text);pointer-events:none}._folderBrowserWrapper_h1a26_231{margin-top:12px;border:1px solid var(--border);border-radius:8px;padding:8px;max-height:280px;display:flex;flex-direction:column;overflow:hidden}@media(pointer:coarse){._content_h1a26_9{top:30%;transform:translate(-50%,-30%)}}@keyframes _fadeIn_h1a26_1{0%{opacity:0}to{opacity:1}}@keyframes _slideUp_h1a26_1{0%{opacity:0;transform:translate(-50%,-48%)}to{opacity:1;transform:translate(-50%,-50%)}}._overlay_1mt11_1{position:fixed;top:0;right:0;bottom:0;left:0;z-index:110;display:flex;flex-direction:column;background:var(--overlay-bg);animation:_fade-in_1mt11_1 .15s ease}._header_1mt11_11{display:flex;align-items:center;justify-content:space-between;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 10px;background:var(--surface, #1e1e2e);border-bottom:1px solid var(--border, #333)}._title_1mt11_20{color:var(--text, #ccc);font-size:14px;font-weight:600}._actions_1mt11_26{display:flex;gap:8px}._btnPrimary_1mt11_31{padding:8px 18px;border:none;border-radius:6px;background:var(--accent, #4a9eff);color:#fff;font-size:14px;cursor:pointer}._btnPrimary_1mt11_31:hover{opacity:.9}._btnSecondary_1mt11_45{padding:8px 18px;border:1px solid var(--border, #444);border-radius:6px;background:transparent;color:var(--text, #ccc);font-size:14px;cursor:pointer}._btnSecondary_1mt11_45:hover{background:var(--border, #333)}._content_1mt11_59{flex:1;overflow:auto;padding:16px 16px calc(12px + env(safe-area-inset-bottom,0px))}._loadMoreBtn_1mt11_65{display:block;width:100%;padding:8px;margin-bottom:8px;border:1px solid var(--border, #444);border-radius:6px;background:var(--surface, #1e1e2e);color:var(--accent, #4a9eff);font-size:13px;cursor:pointer;text-align:center}._loadMoreBtn_1mt11_65:hover{background:var(--border, #333)}._pre_1mt11_83{margin:0;font-family:Cascadia Code,Fira Code,monospace;font-size:13px;color:var(--text, #ccc);white-space:pre;word-break:normal;user-select:text;-webkit-user-select:text}@keyframes _fade-in_1mt11_1{0%{opacity:0}to{opacity:1}}._layout_1qhh9_1{--keyboard-height: 0px;position:relative;height:100vh;height:100dvh;overflow:hidden;background:var(--bg);color:var(--text);overscroll-behavior:none;touch-action:none}._topBar_1qhh9_14{height:calc(40px + env(safe-area-inset-top,0px));padding:0 4px;padding-top:env(safe-area-inset-top,0px);display:flex;align-items:center;background:var(--surface);border-bottom:1px solid var(--border);gap:2px;position:fixed;top:0;left:0;right:0;z-index:60}._left_1qhh9_30{display:flex;align-items:center;gap:4px;flex:1;min-width:0;overflow:hidden}._right_1qhh9_39{display:flex;align-items:center;gap:2px;flex-shrink:0}._barBtn_1qhh9_46{background:none;border:none;color:var(--text-dim);width:30px;height:30px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;text-decoration:none;gap:4px;padding:0;flex-shrink:0;transition:background .15s,color .15s;-webkit-tap-highlight-color:transparent}._barBtn_1qhh9_46:hover{background:var(--border);color:var(--text)}._barBtnWithLabel_1qhh9_72{width:auto;padding:0 10px;gap:3px}._btnLabel_1qhh9_78{font-size:12px;font-weight:600}._stopBtn_1qhh9_83{color:var(--danger);font-size:11px;font-weight:600}._stopBtn_1qhh9_83:hover{background:var(--danger);color:#fff}._stopBtn_1qhh9_83:active{transform:scale(.9)}._statusDot_1qhh9_98{width:8px;height:8px;border-radius:50%;background:var(--danger);flex-shrink:0;transition:background .3s;display:inline-block}._statusConnected_1qhh9_108{background:var(--success)}._sessionName_1qhh9_112{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text);max-width:120px}._statusText_1qhh9_122{font-size:11px;color:var(--text-secondary);white-space:nowrap;flex-shrink:0}._mobileOnly_1qhh9_129{display:none}._connectionBanner_1qhh9_134{position:fixed;top:calc(40px + env(safe-area-inset-top,0px));left:0;right:0;z-index:59;display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 16px;background:var(--danger, #f14c4c);color:#fff;font-size:13px;font-weight:500}._connectionBannerBtn_1qhh9_151{background:#fff3;border:1px solid rgba(255,255,255,.4);color:#fff;border-radius:4px;padding:2px 10px;font-size:12px;cursor:pointer}._connectionBannerBtn_1qhh9_151:hover{background:#ffffff4d}@media(max-width:640px){._desktopOnly_1qhh9_166{display:none!important}._mobileOnly_1qhh9_129{display:flex!important}._sessionName_1qhh9_112{max-width:30vw}._statusText_1qhh9_122{display:none}._connectionBanner_1qhh9_134{top:calc(32px + env(safe-area-inset-top,0px))}}._terminalArea_1qhh9_184{position:absolute;top:calc(40px + env(safe-area-inset-top,0px));bottom:calc(80px + env(safe-area-inset-bottom,0px) + var(--keyboard-height, 0px));left:0;right:0;display:flex;min-height:0}._split_1qhh9_194{flex-direction:row}._paneWrapper_1qhh9_198{flex:1;display:none;min-height:0;min-width:0;flex-direction:column}._visible_1qhh9_206{display:flex}._split_1qhh9_194 ._visible_1qhh9_206+._visible_1qhh9_206{border-left:2px solid var(--accent)}@media(max-width:640px){._split_1qhh9_194{flex-direction:column}._split_1qhh9_194 ._visible_1qhh9_206+._visible_1qhh9_206{border-left:none;border-top:2px solid var(--accent)}}@media(orientation:landscape)and (max-height:500px){._topBar_1qhh9_14{height:calc(32px + env(safe-area-inset-top,0px))}._terminalArea_1qhh9_184{top:calc(32px + env(safe-area-inset-top,0px));bottom:calc(44px + env(safe-area-inset-bottom,0px) + var(--keyboard-height, 0px))}._layout_1qhh9_1[data-keyboard-open] ._terminalArea_1qhh9_184{bottom:calc(env(safe-area-inset-bottom,0px) + var(--keyboard-height, 0px))}}:root{--bg: #1e1e1e;--surface: #252526;--border: #3c3c3c;--border-subtle: #474747;--text: #d4d4d4;--text-secondary: #858585;--text-dim: #6e6e6e;--text-muted: #555555;--accent: #0078d4;--accent-hover: #1a8ae8;--accent-active: #005a9e;--danger: #f14c4c;--danger-hover: #d73a3a;--success: #89d185;--overlay-bg: rgba(0, 0, 0, .85);--key-bg: #4a4a4c;--key-border: #5a5a5c;--key-shadow: rgba(0, 0, 0, .5);--key-special-bg: #333335}[data-theme=light]{--bg: #ffffff;--surface: #f3f3f3;--border: #e0e0e0;--border-subtle: #d0d0d0;--text: #1e1e1e;--text-secondary: #616161;--text-dim: #767676;--text-muted: #a0a0a0;--accent: #0078d4;--accent-hover: #106ebe;--accent-active: #005a9e;--danger: #e51400;--danger-hover: #c20000;--success: #16825d;--overlay-bg: rgba(0, 0, 0, .5);--key-bg: #ffffff;--key-border: #b5b5b5;--key-shadow: rgba(0, 0, 0, .12);--key-special-bg: #adb5bd}[data-theme=monokai]{--bg: #272822;--surface: #1e1f1c;--border: #49483e;--border-subtle: #5c5c4f;--text: #f8f8f2;--text-secondary: #a59f85;--text-dim: #75715e;--text-muted: #5a5854;--accent: #a6e22e;--accent-hover: #b8f53c;--accent-active: #8acc16;--danger: #f92672;--danger-hover: #e0155d;--success: #a6e22e;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #49483e;--key-border: #5c5c4f;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #3e3d32}[data-theme=solarized-dark]{--bg: #002b36;--surface: #073642;--border: #586e75;--border-subtle: #657b83;--text: #839496;--text-secondary: #657b83;--text-dim: #586e75;--text-muted: #4a5a62;--accent: #268bd2;--accent-hover: #379ce3;--accent-active: #1a7abf;--danger: #dc322f;--danger-hover: #c8221f;--success: #859900;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #073642;--key-border: #586e75;--key-shadow: rgba(0, 0, 0, .3);--key-special-bg: #002b36}[data-theme=solarized-light]{--bg: #fdf6e3;--surface: #eee8d5;--border: #93a1a1;--border-subtle: #839496;--text: #657b83;--text-secondary: #93a1a1;--text-dim: #a0a0a0;--text-muted: #b0b0b0;--accent: #268bd2;--accent-hover: #379ce3;--accent-active: #1a7abf;--danger: #dc322f;--danger-hover: #c8221f;--success: #859900;--overlay-bg: rgba(0, 0, 0, .4);--key-bg: #ffffff;--key-border: #b5b5b5;--key-shadow: rgba(0, 0, 0, .12);--key-special-bg: #adb5bd}[data-theme=nord]{--bg: #2e3440;--surface: #3b4252;--border: #434c5e;--border-subtle: #4c566a;--text: #d8dee9;--text-secondary: #b0bac9;--text-dim: #7b88a1;--text-muted: #5c6a85;--accent: #88c0d0;--accent-hover: #9fd4e4;--accent-active: #6aafbf;--danger: #bf616a;--danger-hover: #a84d57;--success: #a3be8c;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #434c5e;--key-border: #4c566a;--key-shadow: rgba(0, 0, 0, .3);--key-special-bg: #3b4252}[data-theme=dracula]{--bg: #282a36;--surface: #343746;--border: #44475a;--border-subtle: #525568;--text: #f8f8f2;--text-secondary: #c1c4d2;--text-dim: #8e92a4;--text-muted: #6272a4;--accent: #bd93f9;--accent-hover: #d0b0ff;--accent-active: #a77de7;--danger: #ff5555;--danger-hover: #e03d3d;--success: #50fa7b;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #44475a;--key-border: #525568;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #343746}[data-theme=github-dark]{--bg: #0d1117;--surface: #161b22;--border: #30363d;--border-subtle: #3d444d;--text: #c9d1d9;--text-secondary: #8b949e;--text-dim: #6e7681;--text-muted: #484f58;--accent: #58a6ff;--accent-hover: #79b8ff;--accent-active: #388bfd;--danger: #f85149;--danger-hover: #da3633;--success: #3fb950;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #161b22;--key-border: #30363d;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #0d1117}[data-theme=one-dark]{--bg: #282c34;--surface: #21252b;--border: #3e4452;--border-subtle: #4b5263;--text: #abb2bf;--text-secondary: #7f848e;--text-dim: #5c6370;--text-muted: #4b5263;--accent: #61afef;--accent-hover: #7dc0ff;--accent-active: #4d9ede;--danger: #e06c75;--danger-hover: #c95c67;--success: #98c379;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #3e4452;--key-border: #4b5263;--key-shadow: rgba(0, 0, 0, .3);--key-special-bg: #21252b}[data-theme=catppuccin]{--bg: #1e1e2e;--surface: #313244;--border: #45475a;--border-subtle: #585b70;--text: #cdd6f4;--text-secondary: #a6adc8;--text-dim: #7f849c;--text-muted: #585b70;--accent: #89b4fa;--accent-hover: #b4d0ff;--accent-active: #5c9de3;--danger: #f38ba8;--danger-hover: #eb7c9d;--success: #a6e3a1;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #45475a;--key-border: #585b70;--key-shadow: rgba(0, 0, 0, .3);--key-special-bg: #313244}[data-theme=gruvbox]{--bg: #282828;--surface: #3c3836;--border: #504945;--border-subtle: #665c54;--text: #ebdbb2;--text-secondary: #d5c4a1;--text-dim: #a89984;--text-muted: #7c6f64;--accent: #83a598;--accent-hover: #9dbfb4;--accent-active: #6a8f8a;--danger: #fb4934;--danger-hover: #e33826;--success: #b8bb26;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #504945;--key-border: #665c54;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #3c3836}[data-theme=night-owl]{--bg: #011627;--surface: #0d2a45;--border: #1d3b53;--border-subtle: #264863;--text: #d6deeb;--text-secondary: #8badc1;--text-dim: #5f7e97;--text-muted: #3f5f7d;--accent: #7fdbca;--accent-hover: #9ff0e0;--accent-active: #62c5b5;--danger: #ef5350;--danger-hover: #d83130;--success: #addb67;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #1d3b53;--key-border: #264863;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #0d2a45}[data-theme=tokyo-night]{--bg: #1a1b26;--surface: #24283b;--border: #3b4261;--border-subtle: #444b6a;--text: #a9b1d6;--text-secondary: #7982a9;--text-dim: #565f89;--text-muted: #414868;--accent: #7aa2f7;--accent-hover: #99b4ff;--accent-active: #5d8af0;--danger: #f7768e;--danger-hover: #e05874;--success: #9ece6a;--overlay-bg: rgba(0, 0, 0, .8);--key-bg: #3b4261;--key-border: #444b6a;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #24283b}[data-theme=rose-pine]{--bg: #191724;--surface: #1f1d2e;--border: #26233a;--border-subtle: #393552;--text: #e0def4;--text-secondary: #908caa;--text-dim: #6e6a86;--text-muted: #524f67;--accent: #c4a7e7;--accent-hover: #d4bef5;--accent-active: #a88fd4;--danger: #eb6f92;--danger-hover: #d4577a;--success: #31748f;--overlay-bg: rgba(0, 0, 0, .8);--key-bg: #26233a;--key-border: #393552;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #1f1d2e}[data-theme=kanagawa]{--bg: #1f1f28;--surface: #2a2a37;--border: #363646;--border-subtle: #454559;--text: #dcd7ba;--text-secondary: #c8c093;--text-dim: #727169;--text-muted: #54546d;--accent: #7e9cd8;--accent-hover: #9bb5e6;--accent-active: #6282c2;--danger: #c34043;--danger-hover: #a8302f;--success: #76946a;--overlay-bg: rgba(0, 0, 0, .8);--key-bg: #363646;--key-border: #454559;--key-shadow: rgba(0, 0, 0, .4);--key-special-bg: #2a2a37}[data-theme=everforest]{--bg: #2d353b;--surface: #343f44;--border: #475258;--border-subtle: #56635a;--text: #d3c6aa;--text-secondary: #a7c080;--text-dim: #859289;--text-muted: #6b7a70;--accent: #a7c080;--accent-hover: #bdd49b;--accent-active: #8faa68;--danger: #e67e80;--danger-hover: #cf6567;--success: #83c092;--overlay-bg: rgba(0, 0, 0, .75);--key-bg: #475258;--key-border: #56635a;--key-shadow: rgba(0, 0, 0, .35);--key-special-bg: #343f44}[data-theme=ayu-dark]{--bg: #0b0e14;--surface: #11151c;--border: #1c2433;--border-subtle: #2d3b4d;--text: #bfbdb6;--text-secondary: #73b8ff;--text-dim: #636a76;--text-muted: #404854;--accent: #e6b450;--accent-hover: #f0c566;--accent-active: #d49e38;--danger: #ea6c73;--danger-hover: #d4525a;--success: #91b362;--overlay-bg: rgba(0, 0, 0, .85);--key-bg: #1c2433;--key-border: #2d3b4d;--key-shadow: rgba(0, 0, 0, .5);--key-special-bg: #11151c}[data-theme=matrix]{--bg: #0a0a0a;--surface: #111111;--border: #003b00;--border-subtle: #005200;--text: #00ff41;--text-secondary: #00cc33;--text-dim: #009926;--text-muted: #006619;--accent: #00ff41;--accent-hover: #33ff66;--accent-active: #00cc33;--danger: #00e639;--danger-hover: #00b32d;--success: #33ff66;--overlay-bg: rgba(0, 0, 0, .9);--key-bg: #003b00;--key-border: #005200;--key-shadow: rgba(0, 255, 65, .15);--key-special-bg: #002200}[data-theme=cyberpunk]{--bg: #0d0221;--surface: #150535;--border: #2a0a4a;--border-subtle: #3d1166;--text: #e0d0ff;--text-secondary: #b49ce0;--text-dim: #7b5ea7;--text-muted: #4a3674;--accent: #ff2a6d;--accent-hover: #ff5588;--accent-active: #d91e5a;--danger: #d300c5;--danger-hover: #a600a0;--success: #05d9e8;--overlay-bg: rgba(13, 2, 33, .9);--key-bg: #2a0a4a;--key-border: #3d1166;--key-shadow: rgba(255, 42, 109, .2);--key-special-bg: #150535}[data-theme=sunset-glow]{--bg: #1a1016;--surface: #261820;--border: #3d2530;--border-subtle: #553545;--text: #e8d5c4;--text-secondary: #c0a090;--text-dim: #8a6a5a;--text-muted: #5a4040;--accent: #ff6b35;--accent-hover: #ff8a55;--accent-active: #e05520;--danger: #ff6b6b;--danger-hover: #e05050;--success: #c3e88d;--overlay-bg: rgba(26, 16, 22, .9);--key-bg: #3d2530;--key-border: #553545;--key-shadow: rgba(255, 107, 53, .2);--key-special-bg: #261820}[data-theme=synthwave]{--bg: #241b2f;--surface: #2e2440;--border: #453558;--border-subtle: #5a4670;--text: #f0e4fc;--text-secondary: #c0b0d8;--text-dim: #7a6a90;--text-muted: #504660;--accent: #ff7edb;--accent-hover: #ff9de6;--accent-active: #e060c0;--danger: #fe4450;--danger-hover: #d83040;--success: #72f1b8;--overlay-bg: rgba(36, 27, 47, .9);--key-bg: #453558;--key-border: #5a4670;--key-shadow: rgba(255, 126, 219, .2);--key-special-bg: #2e2440}[data-theme=aurora]{--bg: #07090f;--surface: #0e1220;--border: #1a2035;--border-subtle: #263050;--text: #c5d1eb;--text-secondary: #8898b8;--text-dim: #506080;--text-muted: #354060;--accent: #5ec796;--accent-hover: #78d8aa;--accent-active: #48b080;--danger: #e06c8a;--danger-hover: #c85575;--success: #88c0d0;--overlay-bg: rgba(7, 9, 15, .9);--key-bg: #1a2035;--key-border: #263050;--key-shadow: rgba(94, 199, 150, .15);--key-special-bg: #0e1220}[data-theme=retro-amber]{--bg: #1a1200;--surface: #221a00;--border: #3d2e00;--border-subtle: #554000;--text: #ffb000;--text-secondary: #cc8800;--text-dim: #886000;--text-muted: #664400;--accent: #ffb000;--accent-hover: #ffc040;--accent-active: #e09900;--danger: #ff8c00;--danger-hover: #e07000;--success: #ffd060;--overlay-bg: rgba(26, 18, 0, .92);--key-bg: #3d2e00;--key-border: #554000;--key-shadow: rgba(255, 176, 0, .15);--key-special-bg: #221a00}[data-theme=deep-ocean]{--bg: #040b14;--surface: #08121e;--border: #122038;--border-subtle: #1a3050;--text: #8ab4f8;--text-secondary: #5a8ac0;--text-dim: #2a5a90;--text-muted: #1a3a5c;--accent: #4fc3f7;--accent-hover: #70d4ff;--accent-active: #38a8e0;--danger: #ff5252;--danger-hover: #d83838;--success: #69f0ae;--overlay-bg: rgba(4, 11, 20, .92);--key-bg: #122038;--key-border: #1a3050;--key-shadow: rgba(79, 195, 247, .15);--key-special-bg: #08121e}[data-theme=neon-noir]{--bg: #0c0c0c;--surface: #161616;--border: #2a2a2a;--border-subtle: #383838;--text: #cccccc;--text-secondary: #999999;--text-dim: #666666;--text-muted: #444444;--accent: #00ff9f;--accent-hover: #33ffb5;--accent-active: #00cc80;--danger: #ff003c;--danger-hover: #cc0030;--success: #00ff9f;--overlay-bg: rgba(12, 12, 12, .92);--key-bg: #2a2a2a;--key-border: #383838;--key-shadow: rgba(0, 255, 159, .12);--key-special-bg: #161616}[data-theme=frost-byte]{--bg: #0a1628;--surface: #10203a;--border: #1a3050;--border-subtle: #254060;--text: #c7dbe6;--text-secondary: #8aaccc;--text-dim: #4a7090;--text-muted: #2a4668;--accent: #6cb6e0;--accent-hover: #88caf0;--accent-active: #50a0cc;--danger: #e87d8a;--danger-hover: #cc6070;--success: #8dc891;--overlay-bg: rgba(10, 22, 40, .9);--key-bg: #1a3050;--key-border: #254060;--key-shadow: rgba(108, 182, 224, .15);--key-special-bg: #10203a}[data-theme=vice-city]{--bg: #0f0326;--surface: #1a0838;--border: #2e1055;--border-subtle: #421870;--text: #f8d0f0;--text-secondary: #c8a0c0;--text-dim: #8a6088;--text-muted: #4a2068;--accent: #ff71ce;--accent-hover: #ff95db;--accent-active: #e050b0;--danger: #ff3a7e;--danger-hover: #d82868;--success: #01cdfe;--overlay-bg: rgba(15, 3, 38, .92);--key-bg: #2e1055;--key-border: #421870;--key-shadow: rgba(255, 113, 206, .2);--key-special-bg: #1a0838}[data-theme=radical]{--bg: #141322;--surface: #1c1b30;--border: #303145;--border-subtle: #40415a;--text: #d1d2d3;--text-secondary: #a8ffdb;--text-dim: #5a5b78;--text-muted: #303145;--accent: #ff428e;--accent-hover: #ff6ea4;--accent-active: #d83070;--danger: #fc28a8;--danger-hover: #d01888;--success: #00e8c6;--overlay-bg: rgba(20, 19, 34, .92);--key-bg: #303145;--key-border: #40415a;--key-shadow: rgba(255, 66, 142, .18);--key-special-bg: #1c1b30}[data-theme=material-ocean]{--bg: #0f111a;--surface: #181a27;--border: #252837;--border-subtle: #333750;--text: #a6accd;--text-secondary: #717cb4;--text-dim: #4b5178;--text-muted: #3b3f51;--accent: #82aaff;--accent-hover: #a0c0ff;--accent-active: #6090e8;--danger: #f07178;--danger-hover: #d05860;--success: #c3e88d;--overlay-bg: rgba(15, 17, 26, .92);--key-bg: #252837;--key-border: #333750;--key-shadow: rgba(130, 170, 255, .12);--key-special-bg: #181a27}[data-theme=sakura]{--bg: #1e1527;--surface: #281e35;--border: #3a2d4a;--border-subtle: #4e3d62;--text: #f0d6e8;--text-secondary: #c8a8c0;--text-dim: #8a6888;--text-muted: #4a3560;--accent: #ff90b3;--accent-hover: #ffa8c5;--accent-active: #e07898;--danger: #ff6b9d;--danger-hover: #d85080;--success: #a8d8a8;--overlay-bg: rgba(30, 21, 39, .92);--key-bg: #3a2d4a;--key-border: #4e3d62;--key-shadow: rgba(255, 144, 179, .18);--key-special-bg: #281e35}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{height:100vh;height:100dvh;overflow:hidden;overscroll-behavior:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;transition:background .3s,color .3s}#root{height:100%;display:flex;flex-direction:column}a{color:var(--accent);text-decoration:none}button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit;font-size:inherit}input,select,textarea{font-family:inherit;font-size:inherit;color:var(--text);background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:8px 12px;outline:none}input:focus,select:focus,textarea:focus{border-color:var(--accent)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--border-subtle)}[data-sonner-toaster]{z-index:9999!important}@keyframes toast-in{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes toast-out{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}@keyframes slide-in-right{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes slide-out-right{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes slide-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes slide-out-left{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-out{0%{opacity:1}to{opacity:0}}@keyframes spin{to{transform:rotate(360deg)}}
|
package/public/index.html
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
const t = localStorage.getItem('termbeam-theme');
|
|
19
19
|
if (t) document.documentElement.setAttribute('data-theme', t);
|
|
20
20
|
</script>
|
|
21
|
-
<script type="module" crossorigin src="/assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/assets/index-BoTisaNy.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="/assets/index-yPsf11Zp.css">
|
|
23
23
|
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="root"></div>
|
package/public/sw.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
try{self["workbox:core:7.3.0"]&&_()}catch{}const Q=(n,...e)=>{let t=n;return e.length>0&&(t+=` :: ${JSON.stringify(e)}`),t},z=Q;class l extends Error{constructor(e,t){const s=z(e,t);super(s),this.name=e,this.details=t}}const d={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:typeof registration<"u"?registration.scope:""},E=n=>[d.prefix,n,d.suffix].filter(e=>e&&e.length>0).join("-"),J=n=>{for(const e of Object.keys(d))n(e)},b={updateDetails:n=>{J(e=>{typeof n[e]=="string"&&(d[e]=n[e])})},getGoogleAnalyticsName:n=>n||E(d.googleAnalytics),getPrecacheName:n=>n||E(d.precache),getPrefix:()=>d.prefix,getRuntimeName:n=>n||E(d.runtime),getSuffix:()=>d.suffix};function K(n,e){const t=e();return n.waitUntil(t),t}try{self["workbox:precaching:7.3.0"]&&_()}catch{}const X="__WB_REVISION__";function Y(n){if(!n)throw new l("add-to-cache-list-unexpected-type",{entry:n});if(typeof n=="string"){const r=new URL(n,location.href);return{cacheKey:r.href,url:r.href}}const{revision:e,url:t}=n;if(!t)throw new l("add-to-cache-list-unexpected-type",{entry:n});if(!e){const r=new URL(t,location.href);return{cacheKey:r.href,url:r.href}}const s=new URL(t,location.href),a=new URL(t,location.href);return s.searchParams.set(X,e),{cacheKey:s.href,url:a.href}}class Z{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:s})=>{if(e.type==="install"&&t&&t.originalRequest&&t.originalRequest instanceof Request){const a=t.originalRequest.url;s?this.notUpdatedURLs.push(a):this.updatedURLs.push(a)}return s}}}class ee{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:t,params:s})=>{const a=(s==null?void 0:s.cacheKey)||this._precacheController.getCacheKeyForURL(t.url);return a?new Request(a,{headers:t.headers}):t},this._precacheController=e}}let m;function te(){if(m===void 0){const n=new Response("");if("body"in n)try{new Response(n.body),m=!0}catch{m=!1}m=!1}return m}async function se(n,e){let t=null;if(n.url&&(t=new URL(n.url).origin),t!==self.location.origin)throw new l("cross-origin-copy-response",{origin:t});const s=n.clone(),r={headers:new Headers(s.headers),status:s.status,statusText:s.statusText},i=te()?s.body:await s.blob();return new Response(i,r)}const ne=n=>new URL(String(n),location.href).href.replace(new RegExp(`^${location.origin}`),"");function S(n,e){const t=new URL(n);for(const s of e)t.searchParams.delete(s);return t.href}async function ae(n,e,t,s){const a=S(e.url,t);if(e.url===a)return n.match(e,s);const r=Object.assign(Object.assign({},s),{ignoreSearch:!0}),i=await n.keys(e,r);for(const c of i){const o=S(c.url,t);if(a===o)return n.match(c,s)}}class re{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}const j=new Set;async function ie(){for(const n of j)await n()}function F(n){return new Promise(e=>setTimeout(e,n))}try{self["workbox:strategies:7.3.0"]&&_()}catch{}function C(n){return typeof n=="string"?new Request(n):n}class ce{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new re,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const s of this._plugins)this._pluginStateMap.set(s,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:t}=this;let s=C(e);if(s.mode==="navigate"&&t instanceof FetchEvent&&t.preloadResponse){const i=await t.preloadResponse;if(i)return i}const a=this.hasCallback("fetchDidFail")?s.clone():null;try{for(const i of this.iterateCallbacks("requestWillFetch"))s=await i({request:s.clone(),event:t})}catch(i){if(i instanceof Error)throw new l("plugin-error-request-will-fetch",{thrownErrorMessage:i.message})}const r=s.clone();try{let i;i=await fetch(s,s.mode==="navigate"?void 0:this._strategy.fetchOptions);for(const c of this.iterateCallbacks("fetchDidSucceed"))i=await c({event:t,request:r,response:i});return i}catch(i){throw a&&await this.runCallbacks("fetchDidFail",{error:i,event:t,originalRequest:a.clone(),request:r.clone()}),i}}async fetchAndCachePut(e){const t=await this.fetch(e),s=t.clone();return this.waitUntil(this.cachePut(e,s)),t}async cacheMatch(e){const t=C(e);let s;const{cacheName:a,matchOptions:r}=this._strategy,i=await this.getCacheKey(t,"read"),c=Object.assign(Object.assign({},r),{cacheName:a});s=await caches.match(i,c);for(const o of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await o({cacheName:a,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(e,t){const s=C(e);await F(0);const a=await this.getCacheKey(s,"write");if(!t)throw new l("cache-put-with-no-response",{url:ne(a.url)});const r=await this._ensureResponseSafeToCache(t);if(!r)return!1;const{cacheName:i,matchOptions:c}=this._strategy,o=await self.caches.open(i),h=this.hasCallback("cacheDidUpdate"),g=h?await ae(o,a.clone(),["__WB_REVISION__"],c):null;try{await o.put(a,h?r.clone():r)}catch(u){if(u instanceof Error)throw u.name==="QuotaExceededError"&&await ie(),u}for(const u of this.iterateCallbacks("cacheDidUpdate"))await u({cacheName:i,oldResponse:g,newResponse:r.clone(),request:a,event:this.event});return!0}async getCacheKey(e,t){const s=`${e.url} | ${t}`;if(!this._cacheKeys[s]){let a=e;for(const r of this.iterateCallbacks("cacheKeyWillBeUsed"))a=C(await r({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[s]=a}return this._cacheKeys[s]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const s of this.iterateCallbacks(e))await s(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if(typeof t[e]=="function"){const s=this._pluginStateMap.get(t);yield r=>{const i=Object.assign(Object.assign({},r),{state:s});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){const e=this._extendLifetimePromises.splice(0),s=(await Promise.allSettled(e)).find(a=>a.status==="rejected");if(s)throw s.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,s=!1;for(const a of this.iterateCallbacks("cacheWillUpdate"))if(t=await a({request:this.request,response:t,event:this.event})||void 0,s=!0,!t)break;return s||t&&t.status!==200&&(t=void 0),t}}class I{constructor(e={}){this.cacheName=b.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,s=typeof e.request=="string"?new Request(e.request):e.request,a="params"in e?e.params:void 0,r=new ce(this,{event:t,request:s,params:a}),i=this._getResponse(r,s,t),c=this._awaitComplete(i,r,s,t);return[i,c]}async _getResponse(e,t,s){await e.runCallbacks("handlerWillStart",{event:s,request:t});let a;try{if(a=await this._handle(t,e),!a||a.type==="error")throw new l("no-response",{url:t.url})}catch(r){if(r instanceof Error){for(const i of e.iterateCallbacks("handlerDidError"))if(a=await i({error:r,event:s,request:t}),a)break}if(!a)throw r}for(const r of e.iterateCallbacks("handlerWillRespond"))a=await r({event:s,request:t,response:a});return a}async _awaitComplete(e,t,s,a){let r,i;try{r=await e}catch{}try{await t.runCallbacks("handlerDidRespond",{event:a,request:s,response:r}),await t.doneWaiting()}catch(c){c instanceof Error&&(i=c)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:s,response:r,error:i}),t.destroy(),i)throw i}}class p extends I{constructor(e={}){e.cacheName=b.getPrecacheName(e.cacheName),super(e),this._fallbackToNetwork=e.fallbackToNetwork!==!1,this.plugins.push(p.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const s=await t.cacheMatch(e);return s||(t.event&&t.event.type==="install"?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,t){let s;const a=t.params||{};if(this._fallbackToNetwork){const r=a.integrity,i=e.integrity,c=!i||i===r;s=await t.fetch(new Request(e,{integrity:e.mode!=="no-cors"?i||r:void 0})),r&&c&&e.mode!=="no-cors"&&(this._useDefaultCacheabilityPluginIfNeeded(),await t.cachePut(e,s.clone()))}else throw new l("missing-precache-entry",{cacheName:this.cacheName,url:e.url});return s}async _handleInstall(e,t){this._useDefaultCacheabilityPluginIfNeeded();const s=await t.fetch(e);if(!await t.cachePut(e,s.clone()))throw new l("bad-precaching-response",{url:e.url,status:s.status});return s}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[s,a]of this.plugins.entries())a!==p.copyRedirectedCacheableResponsesPlugin&&(a===p.defaultPrecacheCacheabilityPlugin&&(e=s),a.cacheWillUpdate&&t++);t===0?this.plugins.push(p.defaultPrecacheCacheabilityPlugin):t>1&&e!==null&&this.plugins.splice(e,1)}}p.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:n}){return!n||n.status>=400?null:n}};p.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:n}){return n.redirected?await se(n):n}};class oe{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:s=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new p({cacheName:b.getPrecacheName(e),plugins:[...t,new ee({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const t=[];for(const s of e){typeof s=="string"?t.push(s):s&&s.revision===void 0&&t.push(s.url);const{cacheKey:a,url:r}=Y(s),i=typeof s!="string"&&s.revision?"reload":"default";if(this._urlsToCacheKeys.has(r)&&this._urlsToCacheKeys.get(r)!==a)throw new l("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(r),secondEntry:a});if(typeof s!="string"&&s.integrity){if(this._cacheKeysToIntegrities.has(a)&&this._cacheKeysToIntegrities.get(a)!==s.integrity)throw new l("add-to-cache-list-conflicting-integrities",{url:r});this._cacheKeysToIntegrities.set(a,s.integrity)}if(this._urlsToCacheKeys.set(r,a),this._urlsToCacheModes.set(r,i),t.length>0){const c=`Workbox is precaching URLs without revision info: ${t.join(", ")}
|
|
2
|
-
This is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(c)}}}install(e){return K(e,async()=>{const t=new Z;this.strategy.plugins.push(t);for(const[r,i]of this._urlsToCacheKeys){const c=this._cacheKeysToIntegrities.get(i),o=this._urlsToCacheModes.get(r),h=new Request(r,{integrity:c,cache:o,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:i},request:h,event:e}))}const{updatedURLs:s,notUpdatedURLs:a}=t;return{updatedURLs:s,notUpdatedURLs:a}})}activate(e){return K(e,async()=>{const t=await self.caches.open(this.strategy.cacheName),s=await t.keys(),a=new Set(this._urlsToCacheKeys.values()),r=[];for(const i of s)a.has(i.url)||(await t.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,s=this.getCacheKeyForURL(t);if(s)return(await self.caches.open(this.strategy.cacheName)).match(s)}createHandlerBoundToURL(e){const t=this.getCacheKeyForURL(e);if(!t)throw new l("non-precached-url",{url:e});return s=>(s.request=new Request(e),s.params=Object.assign({cacheKey:t},s.params),this.strategy.handle(s))}}let D;const q=()=>(D||(D=new oe),D);try{self["workbox:routing:7.3.0"]&&_()}catch{}const H="GET",x=n=>n&&typeof n=="object"?n:{handle:n};class R{constructor(e,t,s=H){this.handler=x(t),this.match=e,this.method=s}setCatchHandler(e){this.catchHandler=x(e)}}class he extends R{constructor(e,t,s){const a=({url:r})=>{const i=e.exec(r.href);if(i&&!(r.origin!==location.origin&&i.index!==0))return i.slice(1)};super(a,t,s)}}class le{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,s=this.handleRequest({request:t,event:e});s&&e.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&e.data.type==="CACHE_URLS"){const{payload:t}=e.data,s=Promise.all(t.urlsToCache.map(a=>{typeof a=="string"&&(a=[a]);const r=new Request(...a);return this.handleRequest({request:r,event:e})}));e.waitUntil(s),e.ports&&e.ports[0]&&s.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){const s=new URL(e.url,location.href);if(!s.protocol.startsWith("http"))return;const a=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:s});let c=i&&i.handler;const o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;let h;try{h=c.handle({url:s,request:e,event:t,params:r})}catch(u){h=Promise.reject(u)}const g=i&&i.catchHandler;return h instanceof Promise&&(this._catchHandler||g)&&(h=h.catch(async u=>{if(g)try{return await g.handle({url:s,request:e,event:t,params:r})}catch(M){M instanceof Error&&(u=M)}if(this._catchHandler)return this._catchHandler.handle({url:s,request:e,event:t});throw u})),h}findMatchingRoute({url:e,sameOrigin:t,request:s,event:a}){const r=this._routes.get(s.method)||[];for(const i of r){let c;const o=i.match({url:e,sameOrigin:t,request:s,event:a});if(o)return c=o,(Array.isArray(c)&&c.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o=="boolean")&&(c=void 0),{route:i,params:c}}return{}}setDefaultHandler(e,t=H){this._defaultHandlerMap.set(t,x(e))}setCatchHandler(e){this._catchHandler=x(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new l("unregister-route-but-not-found-with-method",{method:e.method});const t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new l("unregister-route-route-not-registered")}}let w;const ue=()=>(w||(w=new le,w.addFetchListener(),w.addCacheListener()),w);function N(n,e,t){let s;if(typeof n=="string"){const r=new URL(n,location.href),i=({url:c})=>c.href===r.href;s=new R(i,e,t)}else if(n instanceof RegExp)s=new he(n,e,t);else if(typeof n=="function")s=new R(n,e,t);else if(n instanceof R)s=n;else throw new l("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});return ue().registerRoute(s),s}function de(n,e=[]){for(const t of[...n.searchParams.keys()])e.some(s=>s.test(t))&&n.searchParams.delete(t);return n}function*fe(n,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:t="index.html",cleanURLs:s=!0,urlManipulation:a}={}){const r=new URL(n,location.href);r.hash="",yield r.href;const i=de(r,e);if(yield i.href,t&&i.pathname.endsWith("/")){const c=new URL(i.href);c.pathname+=t,yield c.href}if(s){const c=new URL(i.href);c.pathname+=".html",yield c.href}if(a){const c=a({url:r});for(const o of c)yield o.href}}class pe extends R{constructor(e,t){const s=({request:a})=>{const r=e.getURLsToCacheKeys();for(const i of fe(a.url,t)){const c=r.get(i);if(c){const o=e.getIntegrityForCacheKey(c);return{cacheKey:c,integrity:o}}}};super(s,e.strategy)}}function ge(n){const e=q(),t=new pe(e,n);N(t)}const me="-precache-",we=async(n,e=me)=>{const s=(await self.caches.keys()).filter(a=>a.includes(e)&&a.includes(self.registration.scope)&&a!==n);return await Promise.all(s.map(a=>self.caches.delete(a))),s};function ye(){self.addEventListener("activate",(n=>{const e=b.getPrecacheName();n.waitUntil(we(e).then(t=>{}))}))}function _e(n){q().precache(n)}function Re(n,e){_e(n),ge(e)}class be extends I{async _handle(e,t){let s=await t.cacheMatch(e),a;if(!s)try{s=await t.fetchAndCachePut(e)}catch(r){r instanceof Error&&(a=r)}if(!s)throw new l("no-response",{url:e.url,error:a});return s}}class Ce extends I{constructor(e={}){super(e),this._networkTimeoutSeconds=e.networkTimeoutSeconds||0}async _handle(e,t){let s,a;try{const r=[t.fetch(e)];if(this._networkTimeoutSeconds){const i=F(this._networkTimeoutSeconds*1e3);r.push(i)}if(a=await Promise.race(r),!a)throw new Error(`Timed out the network response after ${this._networkTimeoutSeconds} seconds.`)}catch(r){r instanceof Error&&(s=r)}if(!a)throw new l("no-response",{url:e.url,error:s});return a}}function V(n){n.then(()=>{})}const xe=(n,e)=>e.some(t=>n instanceof t);let A,O;function Ee(){return A||(A=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function De(){return O||(O=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const $=new WeakMap,k=new WeakMap,G=new WeakMap,L=new WeakMap,v=new WeakMap;function Le(n){const e=new Promise((t,s)=>{const a=()=>{n.removeEventListener("success",r),n.removeEventListener("error",i)},r=()=>{t(f(n.result)),a()},i=()=>{s(n.error),a()};n.addEventListener("success",r),n.addEventListener("error",i)});return e.then(t=>{t instanceof IDBCursor&&$.set(t,n)}).catch(()=>{}),v.set(e,n),e}function Te(n){if(k.has(n))return;const e=new Promise((t,s)=>{const a=()=>{n.removeEventListener("complete",r),n.removeEventListener("error",i),n.removeEventListener("abort",i)},r=()=>{t(),a()},i=()=>{s(n.error||new DOMException("AbortError","AbortError")),a()};n.addEventListener("complete",r),n.addEventListener("error",i),n.addEventListener("abort",i)});k.set(n,e)}let P={get(n,e,t){if(n instanceof IDBTransaction){if(e==="done")return k.get(n);if(e==="objectStoreNames")return n.objectStoreNames||G.get(n);if(e==="store")return t.objectStoreNames[1]?void 0:t.objectStore(t.objectStoreNames[0])}return f(n[e])},set(n,e,t){return n[e]=t,!0},has(n,e){return n instanceof IDBTransaction&&(e==="done"||e==="store")?!0:e in n}};function Ue(n){P=n(P)}function ke(n){return n===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(e,...t){const s=n.call(T(this),e,...t);return G.set(s,e.sort?e.sort():[e]),f(s)}:De().includes(n)?function(...e){return n.apply(T(this),e),f($.get(this))}:function(...e){return f(n.apply(T(this),e))}}function Pe(n){return typeof n=="function"?ke(n):(n instanceof IDBTransaction&&Te(n),xe(n,Ee())?new Proxy(n,P):n)}function f(n){if(n instanceof IDBRequest)return Le(n);if(L.has(n))return L.get(n);const e=Pe(n);return e!==n&&(L.set(n,e),v.set(e,n)),e}const T=n=>v.get(n);function Ie(n,e,{blocked:t,upgrade:s,blocking:a,terminated:r}={}){const i=indexedDB.open(n,e),c=f(i);return s&&i.addEventListener("upgradeneeded",o=>{s(f(i.result),o.oldVersion,o.newVersion,f(i.transaction),o)}),t&&i.addEventListener("blocked",o=>t(o.oldVersion,o.newVersion,o)),c.then(o=>{r&&o.addEventListener("close",()=>r()),a&&o.addEventListener("versionchange",h=>a(h.oldVersion,h.newVersion,h))}).catch(()=>{}),c}function Ne(n,{blocked:e}={}){const t=indexedDB.deleteDatabase(n);return e&&t.addEventListener("blocked",s=>e(s.oldVersion,s)),f(t).then(()=>{})}const ve=["get","getKey","getAll","getAllKeys","count"],Me=["put","add","delete","clear"],U=new Map;function W(n,e){if(!(n instanceof IDBDatabase&&!(e in n)&&typeof e=="string"))return;if(U.get(e))return U.get(e);const t=e.replace(/FromIndex$/,""),s=e!==t,a=Me.includes(t);if(!(t in(s?IDBIndex:IDBObjectStore).prototype)||!(a||ve.includes(t)))return;const r=async function(i,...c){const o=this.transaction(i,a?"readwrite":"readonly");let h=o.store;return s&&(h=h.index(c.shift())),(await Promise.all([h[t](...c),a&&o.done]))[0]};return U.set(e,r),r}Ue(n=>({...n,get:(e,t,s)=>W(e,t)||n.get(e,t,s),has:(e,t)=>!!W(e,t)||n.has(e,t)}));try{self["workbox:expiration:7.3.0"]&&_()}catch{}const Ke="workbox-expiration",y="cache-entries",B=n=>{const e=new URL(n,location.href);return e.hash="",e.href};class Se{constructor(e){this._db=null,this._cacheName=e}_upgradeDb(e){const t=e.createObjectStore(y,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&Ne(this._cacheName)}async setTimestamp(e,t){e=B(e);const s={url:e,timestamp:t,cacheName:this._cacheName,id:this._getId(e)},r=(await this.getDb()).transaction(y,"readwrite",{durability:"relaxed"});await r.store.put(s),await r.done}async getTimestamp(e){const s=await(await this.getDb()).get(y,this._getId(e));return s==null?void 0:s.timestamp}async expireEntries(e,t){const s=await this.getDb();let a=await s.transaction(y).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;a;){const o=a.value;o.cacheName===this._cacheName&&(e&&o.timestamp<e||t&&i>=t?r.push(a.value):i++),a=await a.continue()}const c=[];for(const o of r)await s.delete(y,o.id),c.push(o.url);return c}_getId(e){return this._cacheName+"|"+B(e)}async getDb(){return this._db||(this._db=await Ie(Ke,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class Ae{constructor(e,t={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new Se(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const e=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),s=await self.caches.open(this._cacheName);for(const a of t)await s.delete(a,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,V(this.expireEntries()))}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(this._maxAgeSeconds){const t=await this._timestampModel.getTimestamp(e),s=Date.now()-this._maxAgeSeconds*1e3;return t!==void 0?t<s:!0}else return!1}async delete(){this._rerunRequested=!1,await this._timestampModel.expireEntries(1/0)}}function Oe(n){j.add(n)}class We{constructor(e={}){this.cachedResponseWillBeUsed=async({event:t,request:s,cacheName:a,cachedResponse:r})=>{if(!r)return null;const i=this._isResponseDateFresh(r),c=this._getCacheExpiration(a);V(c.expireEntries());const o=c.updateTimestamp(s.url);if(t)try{t.waitUntil(o)}catch{}return i?r:null},this.cacheDidUpdate=async({cacheName:t,request:s})=>{const a=this._getCacheExpiration(t);await a.updateTimestamp(s.url),await a.expireEntries()},this._config=e,this._maxAgeSeconds=e.maxAgeSeconds,this._cacheExpirations=new Map,e.purgeOnQuotaError&&Oe(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(e){if(e===b.getRuntimeName())throw new l("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new Ae(e,this._config),this._cacheExpirations.set(e,t)),t}_isResponseDateFresh(e){if(!this._maxAgeSeconds)return!0;const t=this._getDateHeaderTimestamp(e);if(t===null)return!0;const s=Date.now();return t>=s-this._maxAgeSeconds*1e3}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;const t=e.headers.get("date"),a=new Date(t).getTime();return isNaN(a)?null:a}async deleteCacheAndMetadata(){for(const[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}Re([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"3219a9ee232bd8c7d94eff17be4ade76","url":"index.html"},{"revision":"0f93805414c783a30b72e0ce88f2c7c4","url":"icons/icon.svg"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":null,"url":"assets/index-Lhj5V2mZ.css"},{"revision":null,"url":"assets/index-DhjvNUWH.js"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"964f70d27a7182c01f67415dcc656426","url":"manifest.webmanifest"}]);ye();N(({url:n})=>n.hostname==="cdn.jsdelivr.net"&&n.pathname.endsWith(".ttf"),new be({cacheName:"termbeam-fonts",plugins:[new We({maxEntries:5,maxAgeSeconds:365*24*60*60})]}));N(({url:n})=>n.pathname.startsWith("/api/"),new Ce);self.addEventListener("install",()=>{self.skipWaiting()});self.addEventListener("activate",n=>{n.waitUntil(self.clients.claim())});
|
|
1
|
+
try{self["workbox:core:7.3.0"]&&_()}catch{}const Q=(n,...e)=>{let t=n;return e.length>0&&(t+=` :: ${JSON.stringify(e)}`),t},z=Q;class l extends Error{constructor(e,t){const s=z(e,t);super(s),this.name=e,this.details=t}}const d={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:typeof registration<"u"?registration.scope:""},k=n=>[d.prefix,n,d.suffix].filter(e=>e&&e.length>0).join("-"),J=n=>{for(const e of Object.keys(d))n(e)},b={updateDetails:n=>{J(e=>{typeof n[e]=="string"&&(d[e]=n[e])})},getGoogleAnalyticsName:n=>n||k(d.googleAnalytics),getPrecacheName:n=>n||k(d.precache),getPrefix:()=>d.prefix,getRuntimeName:n=>n||k(d.runtime),getSuffix:()=>d.suffix};function S(n,e){const t=e();return n.waitUntil(t),t}try{self["workbox:precaching:7.3.0"]&&_()}catch{}const X="__WB_REVISION__";function Y(n){if(!n)throw new l("add-to-cache-list-unexpected-type",{entry:n});if(typeof n=="string"){const r=new URL(n,location.href);return{cacheKey:r.href,url:r.href}}const{revision:e,url:t}=n;if(!t)throw new l("add-to-cache-list-unexpected-type",{entry:n});if(!e){const r=new URL(t,location.href);return{cacheKey:r.href,url:r.href}}const s=new URL(t,location.href),a=new URL(t,location.href);return s.searchParams.set(X,e),{cacheKey:s.href,url:a.href}}class Z{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:s})=>{if(e.type==="install"&&t&&t.originalRequest&&t.originalRequest instanceof Request){const a=t.originalRequest.url;s?this.notUpdatedURLs.push(a):this.updatedURLs.push(a)}return s}}}class ee{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:t,params:s})=>{const a=(s==null?void 0:s.cacheKey)||this._precacheController.getCacheKeyForURL(t.url);return a?new Request(a,{headers:t.headers}):t},this._precacheController=e}}let w;function te(){if(w===void 0){const n=new Response("");if("body"in n)try{new Response(n.body),w=!0}catch{w=!1}w=!1}return w}async function se(n,e){let t=null;if(n.url&&(t=new URL(n.url).origin),t!==self.location.origin)throw new l("cross-origin-copy-response",{origin:t});const s=n.clone(),r={headers:new Headers(s.headers),status:s.status,statusText:s.statusText},i=te()?s.body:await s.blob();return new Response(i,r)}const ne=n=>new URL(String(n),location.href).href.replace(new RegExp(`^${location.origin}`),"");function K(n,e){const t=new URL(n);for(const s of e)t.searchParams.delete(s);return t.href}async function ae(n,e,t,s){const a=K(e.url,t);if(e.url===a)return n.match(e,s);const r=Object.assign(Object.assign({},s),{ignoreSearch:!0}),i=await n.keys(e,r);for(const c of i){const o=K(c.url,t);if(a===o)return n.match(c,s)}}class re{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}const j=new Set;async function ie(){for(const n of j)await n()}function F(n){return new Promise(e=>setTimeout(e,n))}try{self["workbox:strategies:7.3.0"]&&_()}catch{}function C(n){return typeof n=="string"?new Request(n):n}class ce{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new re,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const s of this._plugins)this._pluginStateMap.set(s,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:t}=this;let s=C(e);if(s.mode==="navigate"&&t instanceof FetchEvent&&t.preloadResponse){const i=await t.preloadResponse;if(i)return i}const a=this.hasCallback("fetchDidFail")?s.clone():null;try{for(const i of this.iterateCallbacks("requestWillFetch"))s=await i({request:s.clone(),event:t})}catch(i){if(i instanceof Error)throw new l("plugin-error-request-will-fetch",{thrownErrorMessage:i.message})}const r=s.clone();try{let i;i=await fetch(s,s.mode==="navigate"?void 0:this._strategy.fetchOptions);for(const c of this.iterateCallbacks("fetchDidSucceed"))i=await c({event:t,request:r,response:i});return i}catch(i){throw a&&await this.runCallbacks("fetchDidFail",{error:i,event:t,originalRequest:a.clone(),request:r.clone()}),i}}async fetchAndCachePut(e){const t=await this.fetch(e),s=t.clone();return this.waitUntil(this.cachePut(e,s)),t}async cacheMatch(e){const t=C(e);let s;const{cacheName:a,matchOptions:r}=this._strategy,i=await this.getCacheKey(t,"read"),c=Object.assign(Object.assign({},r),{cacheName:a});s=await caches.match(i,c);for(const o of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await o({cacheName:a,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(e,t){const s=C(e);await F(0);const a=await this.getCacheKey(s,"write");if(!t)throw new l("cache-put-with-no-response",{url:ne(a.url)});const r=await this._ensureResponseSafeToCache(t);if(!r)return!1;const{cacheName:i,matchOptions:c}=this._strategy,o=await self.caches.open(i),h=this.hasCallback("cacheDidUpdate"),g=h?await ae(o,a.clone(),["__WB_REVISION__"],c):null;try{await o.put(a,h?r.clone():r)}catch(u){if(u instanceof Error)throw u.name==="QuotaExceededError"&&await ie(),u}for(const u of this.iterateCallbacks("cacheDidUpdate"))await u({cacheName:i,oldResponse:g,newResponse:r.clone(),request:a,event:this.event});return!0}async getCacheKey(e,t){const s=`${e.url} | ${t}`;if(!this._cacheKeys[s]){let a=e;for(const r of this.iterateCallbacks("cacheKeyWillBeUsed"))a=C(await r({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[s]=a}return this._cacheKeys[s]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const s of this.iterateCallbacks(e))await s(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if(typeof t[e]=="function"){const s=this._pluginStateMap.get(t);yield r=>{const i=Object.assign(Object.assign({},r),{state:s});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){const e=this._extendLifetimePromises.splice(0),s=(await Promise.allSettled(e)).find(a=>a.status==="rejected");if(s)throw s.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,s=!1;for(const a of this.iterateCallbacks("cacheWillUpdate"))if(t=await a({request:this.request,response:t,event:this.event})||void 0,s=!0,!t)break;return s||t&&t.status!==200&&(t=void 0),t}}class E{constructor(e={}){this.cacheName=b.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,s=typeof e.request=="string"?new Request(e.request):e.request,a="params"in e?e.params:void 0,r=new ce(this,{event:t,request:s,params:a}),i=this._getResponse(r,s,t),c=this._awaitComplete(i,r,s,t);return[i,c]}async _getResponse(e,t,s){await e.runCallbacks("handlerWillStart",{event:s,request:t});let a;try{if(a=await this._handle(t,e),!a||a.type==="error")throw new l("no-response",{url:t.url})}catch(r){if(r instanceof Error){for(const i of e.iterateCallbacks("handlerDidError"))if(a=await i({error:r,event:s,request:t}),a)break}if(!a)throw r}for(const r of e.iterateCallbacks("handlerWillRespond"))a=await r({event:s,request:t,response:a});return a}async _awaitComplete(e,t,s,a){let r,i;try{r=await e}catch{}try{await t.runCallbacks("handlerDidRespond",{event:a,request:s,response:r}),await t.doneWaiting()}catch(c){c instanceof Error&&(i=c)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:s,response:r,error:i}),t.destroy(),i)throw i}}class p extends E{constructor(e={}){e.cacheName=b.getPrecacheName(e.cacheName),super(e),this._fallbackToNetwork=e.fallbackToNetwork!==!1,this.plugins.push(p.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const s=await t.cacheMatch(e);return s||(t.event&&t.event.type==="install"?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,t){let s;const a=t.params||{};if(this._fallbackToNetwork){const r=a.integrity,i=e.integrity,c=!i||i===r;s=await t.fetch(new Request(e,{integrity:e.mode!=="no-cors"?i||r:void 0})),r&&c&&e.mode!=="no-cors"&&(this._useDefaultCacheabilityPluginIfNeeded(),await t.cachePut(e,s.clone()))}else throw new l("missing-precache-entry",{cacheName:this.cacheName,url:e.url});return s}async _handleInstall(e,t){this._useDefaultCacheabilityPluginIfNeeded();const s=await t.fetch(e);if(!await t.cachePut(e,s.clone()))throw new l("bad-precaching-response",{url:e.url,status:s.status});return s}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[s,a]of this.plugins.entries())a!==p.copyRedirectedCacheableResponsesPlugin&&(a===p.defaultPrecacheCacheabilityPlugin&&(e=s),a.cacheWillUpdate&&t++);t===0?this.plugins.push(p.defaultPrecacheCacheabilityPlugin):t>1&&e!==null&&this.plugins.splice(e,1)}}p.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:n}){return!n||n.status>=400?null:n}};p.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:n}){return n.redirected?await se(n):n}};class oe{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:s=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new p({cacheName:b.getPrecacheName(e),plugins:[...t,new ee({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const t=[];for(const s of e){typeof s=="string"?t.push(s):s&&s.revision===void 0&&t.push(s.url);const{cacheKey:a,url:r}=Y(s),i=typeof s!="string"&&s.revision?"reload":"default";if(this._urlsToCacheKeys.has(r)&&this._urlsToCacheKeys.get(r)!==a)throw new l("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(r),secondEntry:a});if(typeof s!="string"&&s.integrity){if(this._cacheKeysToIntegrities.has(a)&&this._cacheKeysToIntegrities.get(a)!==s.integrity)throw new l("add-to-cache-list-conflicting-integrities",{url:r});this._cacheKeysToIntegrities.set(a,s.integrity)}if(this._urlsToCacheKeys.set(r,a),this._urlsToCacheModes.set(r,i),t.length>0){const c=`Workbox is precaching URLs without revision info: ${t.join(", ")}
|
|
2
|
+
This is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(c)}}}install(e){return S(e,async()=>{const t=new Z;this.strategy.plugins.push(t);for(const[r,i]of this._urlsToCacheKeys){const c=this._cacheKeysToIntegrities.get(i),o=this._urlsToCacheModes.get(r),h=new Request(r,{integrity:c,cache:o,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:i},request:h,event:e}))}const{updatedURLs:s,notUpdatedURLs:a}=t;return{updatedURLs:s,notUpdatedURLs:a}})}activate(e){return S(e,async()=>{const t=await self.caches.open(this.strategy.cacheName),s=await t.keys(),a=new Set(this._urlsToCacheKeys.values()),r=[];for(const i of s)a.has(i.url)||(await t.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,s=this.getCacheKeyForURL(t);if(s)return(await self.caches.open(this.strategy.cacheName)).match(s)}createHandlerBoundToURL(e){const t=this.getCacheKeyForURL(e);if(!t)throw new l("non-precached-url",{url:e});return s=>(s.request=new Request(e),s.params=Object.assign({cacheKey:t},s.params),this.strategy.handle(s))}}let D;const H=()=>(D||(D=new oe),D);try{self["workbox:routing:7.3.0"]&&_()}catch{}const q="GET",x=n=>n&&typeof n=="object"?n:{handle:n};class m{constructor(e,t,s=q){this.handler=x(t),this.match=e,this.method=s}setCatchHandler(e){this.catchHandler=x(e)}}class he extends m{constructor(e,t,s){const a=({url:r})=>{const i=e.exec(r.href);if(i&&!(r.origin!==location.origin&&i.index!==0))return i.slice(1)};super(a,t,s)}}class le{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,s=this.handleRequest({request:t,event:e});s&&e.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&e.data.type==="CACHE_URLS"){const{payload:t}=e.data,s=Promise.all(t.urlsToCache.map(a=>{typeof a=="string"&&(a=[a]);const r=new Request(...a);return this.handleRequest({request:r,event:e})}));e.waitUntil(s),e.ports&&e.ports[0]&&s.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){const s=new URL(e.url,location.href);if(!s.protocol.startsWith("http"))return;const a=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:s});let c=i&&i.handler;const o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;let h;try{h=c.handle({url:s,request:e,event:t,params:r})}catch(u){h=Promise.reject(u)}const g=i&&i.catchHandler;return h instanceof Promise&&(this._catchHandler||g)&&(h=h.catch(async u=>{if(g)try{return await g.handle({url:s,request:e,event:t,params:r})}catch(M){M instanceof Error&&(u=M)}if(this._catchHandler)return this._catchHandler.handle({url:s,request:e,event:t});throw u})),h}findMatchingRoute({url:e,sameOrigin:t,request:s,event:a}){const r=this._routes.get(s.method)||[];for(const i of r){let c;const o=i.match({url:e,sameOrigin:t,request:s,event:a});if(o)return c=o,(Array.isArray(c)&&c.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o=="boolean")&&(c=void 0),{route:i,params:c}}return{}}setDefaultHandler(e,t=q){this._defaultHandlerMap.set(t,x(e))}setCatchHandler(e){this._catchHandler=x(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new l("unregister-route-but-not-found-with-method",{method:e.method});const t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new l("unregister-route-route-not-registered")}}let y;const ue=()=>(y||(y=new le,y.addFetchListener(),y.addCacheListener()),y);function T(n,e,t){let s;if(typeof n=="string"){const r=new URL(n,location.href),i=({url:c})=>c.href===r.href;s=new m(i,e,t)}else if(n instanceof RegExp)s=new he(n,e,t);else if(typeof n=="function")s=new m(n,e,t);else if(n instanceof m)s=n;else throw new l("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});return ue().registerRoute(s),s}function de(n,e=[]){for(const t of[...n.searchParams.keys()])e.some(s=>s.test(t))&&n.searchParams.delete(t);return n}function*fe(n,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:t="index.html",cleanURLs:s=!0,urlManipulation:a}={}){const r=new URL(n,location.href);r.hash="",yield r.href;const i=de(r,e);if(yield i.href,t&&i.pathname.endsWith("/")){const c=new URL(i.href);c.pathname+=t,yield c.href}if(s){const c=new URL(i.href);c.pathname+=".html",yield c.href}if(a){const c=a({url:r});for(const o of c)yield o.href}}class pe extends m{constructor(e,t){const s=({request:a})=>{const r=e.getURLsToCacheKeys();for(const i of fe(a.url,t)){const c=r.get(i);if(c){const o=e.getIntegrityForCacheKey(c);return{cacheKey:c,integrity:o}}}};super(s,e.strategy)}}function me(n){const e=H(),t=new pe(e,n);T(t)}const ge="-precache-",we=async(n,e=ge)=>{const s=(await self.caches.keys()).filter(a=>a.includes(e)&&a.includes(self.registration.scope)&&a!==n);return await Promise.all(s.map(a=>self.caches.delete(a))),s};function ye(){self.addEventListener("activate",(n=>{const e=b.getPrecacheName();n.waitUntil(we(e).then(t=>{}))}))}function _e(n){H().precache(n)}function Re(n,e){_e(n),me(e)}class be extends m{constructor(e,{allowlist:t=[/./],denylist:s=[]}={}){super(a=>this._match(a),e),this._allowlist=t,this._denylist=s}_match({url:e,request:t}){if(t&&t.mode!=="navigate")return!1;const s=e.pathname+e.search;for(const a of this._denylist)if(a.test(s))return!1;return!!this._allowlist.some(a=>a.test(s))}}class Ce extends E{async _handle(e,t){let s=await t.cacheMatch(e),a;if(!s)try{s=await t.fetchAndCachePut(e)}catch(r){r instanceof Error&&(a=r)}if(!s)throw new l("no-response",{url:e.url,error:a});return s}}const xe={cacheWillUpdate:async({response:n})=>n.status===200||n.status===0?n:null};class Ee extends E{constructor(e={}){super(e),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(xe),this._networkTimeoutSeconds=e.networkTimeoutSeconds||0}async _handle(e,t){const s=[],a=[];let r;if(this._networkTimeoutSeconds){const{id:o,promise:h}=this._getTimeoutPromise({request:e,logs:s,handler:t});r=o,a.push(h)}const i=this._getNetworkPromise({timeoutId:r,request:e,logs:s,handler:t});a.push(i);const c=await t.waitUntil((async()=>await t.waitUntil(Promise.race(a))||await i)());if(!c)throw new l("no-response",{url:e.url});return c}_getTimeoutPromise({request:e,logs:t,handler:s}){let a;return{promise:new Promise(i=>{a=setTimeout(async()=>{i(await s.cacheMatch(e))},this._networkTimeoutSeconds*1e3)}),id:a}}async _getNetworkPromise({timeoutId:e,request:t,logs:s,handler:a}){let r,i;try{i=await a.fetchAndCachePut(t)}catch(c){c instanceof Error&&(r=c)}return e&&clearTimeout(e),(r||!i)&&(i=await a.cacheMatch(t)),i}}class Te extends E{constructor(e={}){super(e),this._networkTimeoutSeconds=e.networkTimeoutSeconds||0}async _handle(e,t){let s,a;try{const r=[t.fetch(e)];if(this._networkTimeoutSeconds){const i=F(this._networkTimeoutSeconds*1e3);r.push(i)}if(a=await Promise.race(r),!a)throw new Error(`Timed out the network response after ${this._networkTimeoutSeconds} seconds.`)}catch(r){r instanceof Error&&(s=r)}if(!a)throw new l("no-response",{url:e.url,error:s});return a}}function V(n){n.then(()=>{})}const ke=(n,e)=>e.some(t=>n instanceof t);let A,O;function De(){return A||(A=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function Pe(){return O||(O=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const $=new WeakMap,N=new WeakMap,G=new WeakMap,P=new WeakMap,I=new WeakMap;function Le(n){const e=new Promise((t,s)=>{const a=()=>{n.removeEventListener("success",r),n.removeEventListener("error",i)},r=()=>{t(f(n.result)),a()},i=()=>{s(n.error),a()};n.addEventListener("success",r),n.addEventListener("error",i)});return e.then(t=>{t instanceof IDBCursor&&$.set(t,n)}).catch(()=>{}),I.set(e,n),e}function Ue(n){if(N.has(n))return;const e=new Promise((t,s)=>{const a=()=>{n.removeEventListener("complete",r),n.removeEventListener("error",i),n.removeEventListener("abort",i)},r=()=>{t(),a()},i=()=>{s(n.error||new DOMException("AbortError","AbortError")),a()};n.addEventListener("complete",r),n.addEventListener("error",i),n.addEventListener("abort",i)});N.set(n,e)}let v={get(n,e,t){if(n instanceof IDBTransaction){if(e==="done")return N.get(n);if(e==="objectStoreNames")return n.objectStoreNames||G.get(n);if(e==="store")return t.objectStoreNames[1]?void 0:t.objectStore(t.objectStoreNames[0])}return f(n[e])},set(n,e,t){return n[e]=t,!0},has(n,e){return n instanceof IDBTransaction&&(e==="done"||e==="store")?!0:e in n}};function Ne(n){v=n(v)}function ve(n){return n===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(e,...t){const s=n.call(L(this),e,...t);return G.set(s,e.sort?e.sort():[e]),f(s)}:Pe().includes(n)?function(...e){return n.apply(L(this),e),f($.get(this))}:function(...e){return f(n.apply(L(this),e))}}function Ie(n){return typeof n=="function"?ve(n):(n instanceof IDBTransaction&&Ue(n),ke(n,De())?new Proxy(n,v):n)}function f(n){if(n instanceof IDBRequest)return Le(n);if(P.has(n))return P.get(n);const e=Ie(n);return e!==n&&(P.set(n,e),I.set(e,n)),e}const L=n=>I.get(n);function Me(n,e,{blocked:t,upgrade:s,blocking:a,terminated:r}={}){const i=indexedDB.open(n,e),c=f(i);return s&&i.addEventListener("upgradeneeded",o=>{s(f(i.result),o.oldVersion,o.newVersion,f(i.transaction),o)}),t&&i.addEventListener("blocked",o=>t(o.oldVersion,o.newVersion,o)),c.then(o=>{r&&o.addEventListener("close",()=>r()),a&&o.addEventListener("versionchange",h=>a(h.oldVersion,h.newVersion,h))}).catch(()=>{}),c}function Se(n,{blocked:e}={}){const t=indexedDB.deleteDatabase(n);return e&&t.addEventListener("blocked",s=>e(s.oldVersion,s)),f(t).then(()=>{})}const Ke=["get","getKey","getAll","getAllKeys","count"],Ae=["put","add","delete","clear"],U=new Map;function W(n,e){if(!(n instanceof IDBDatabase&&!(e in n)&&typeof e=="string"))return;if(U.get(e))return U.get(e);const t=e.replace(/FromIndex$/,""),s=e!==t,a=Ae.includes(t);if(!(t in(s?IDBIndex:IDBObjectStore).prototype)||!(a||Ke.includes(t)))return;const r=async function(i,...c){const o=this.transaction(i,a?"readwrite":"readonly");let h=o.store;return s&&(h=h.index(c.shift())),(await Promise.all([h[t](...c),a&&o.done]))[0]};return U.set(e,r),r}Ne(n=>({...n,get:(e,t,s)=>W(e,t)||n.get(e,t,s),has:(e,t)=>!!W(e,t)||n.has(e,t)}));try{self["workbox:expiration:7.3.0"]&&_()}catch{}const Oe="workbox-expiration",R="cache-entries",B=n=>{const e=new URL(n,location.href);return e.hash="",e.href};class We{constructor(e){this._db=null,this._cacheName=e}_upgradeDb(e){const t=e.createObjectStore(R,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&Se(this._cacheName)}async setTimestamp(e,t){e=B(e);const s={url:e,timestamp:t,cacheName:this._cacheName,id:this._getId(e)},r=(await this.getDb()).transaction(R,"readwrite",{durability:"relaxed"});await r.store.put(s),await r.done}async getTimestamp(e){const s=await(await this.getDb()).get(R,this._getId(e));return s==null?void 0:s.timestamp}async expireEntries(e,t){const s=await this.getDb();let a=await s.transaction(R).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;a;){const o=a.value;o.cacheName===this._cacheName&&(e&&o.timestamp<e||t&&i>=t?r.push(a.value):i++),a=await a.continue()}const c=[];for(const o of r)await s.delete(R,o.id),c.push(o.url);return c}_getId(e){return this._cacheName+"|"+B(e)}async getDb(){return this._db||(this._db=await Me(Oe,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class Be{constructor(e,t={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new We(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const e=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),s=await self.caches.open(this._cacheName);for(const a of t)await s.delete(a,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,V(this.expireEntries()))}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(this._maxAgeSeconds){const t=await this._timestampModel.getTimestamp(e),s=Date.now()-this._maxAgeSeconds*1e3;return t!==void 0?t<s:!0}else return!1}async delete(){this._rerunRequested=!1,await this._timestampModel.expireEntries(1/0)}}function je(n){j.add(n)}class Fe{constructor(e={}){this.cachedResponseWillBeUsed=async({event:t,request:s,cacheName:a,cachedResponse:r})=>{if(!r)return null;const i=this._isResponseDateFresh(r),c=this._getCacheExpiration(a);V(c.expireEntries());const o=c.updateTimestamp(s.url);if(t)try{t.waitUntil(o)}catch{}return i?r:null},this.cacheDidUpdate=async({cacheName:t,request:s})=>{const a=this._getCacheExpiration(t);await a.updateTimestamp(s.url),await a.expireEntries()},this._config=e,this._maxAgeSeconds=e.maxAgeSeconds,this._cacheExpirations=new Map,e.purgeOnQuotaError&&je(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(e){if(e===b.getRuntimeName())throw new l("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new Be(e,this._config),this._cacheExpirations.set(e,t)),t}_isResponseDateFresh(e){if(!this._maxAgeSeconds)return!0;const t=this._getDateHeaderTimestamp(e);if(t===null)return!0;const s=Date.now();return t>=s-this._maxAgeSeconds*1e3}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;const t=e.headers.get("date"),a=new Date(t).getTime();return isNaN(a)?null:a}async deleteCacheAndMetadata(){for(const[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}Re([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"71c47e06959e7f925be0ff334fc6da39","url":"index.html"},{"revision":"0f93805414c783a30b72e0ce88f2c7c4","url":"icons/icon.svg"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":null,"url":"assets/index-yPsf11Zp.css"},{"revision":null,"url":"assets/index-BoTisaNy.js"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"964f70d27a7182c01f67415dcc656426","url":"manifest.webmanifest"}]);ye();T(new be(new Ee({cacheName:"termbeam-navigation",networkTimeoutSeconds:5})));T(({url:n})=>n.hostname==="cdn.jsdelivr.net"&&n.pathname.endsWith(".ttf"),new Ce({cacheName:"termbeam-fonts",plugins:[new Fe({maxEntries:5,maxAgeSeconds:365*24*60*60})]}));T(({url:n})=>n.pathname.startsWith("/api/"),new Te);self.addEventListener("install",()=>{self.skipWaiting()});self.addEventListener("activate",n=>{n.waitUntil(self.clients.claim())});
|
package/src/cli/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const WebSocket = require('ws');
|
|
2
|
+
const log = require('../utils/logger');
|
|
2
3
|
|
|
3
4
|
const DETACH_KEY = '\x02'; // Ctrl+B
|
|
4
5
|
|
|
@@ -23,6 +24,7 @@ function createTerminalClient({
|
|
|
23
24
|
detachLabel = 'Ctrl+B',
|
|
24
25
|
}) {
|
|
25
26
|
return new Promise((resolve, reject) => {
|
|
27
|
+
log.debug(`Connecting to ${url}`);
|
|
26
28
|
const ws = new WebSocket(url);
|
|
27
29
|
let cleaned = false;
|
|
28
30
|
let bannerTimer = null;
|
|
@@ -68,6 +70,7 @@ function createTerminalClient({
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
ws.on('open', () => {
|
|
73
|
+
log.debug('WebSocket opened, sending auth');
|
|
71
74
|
if (password) {
|
|
72
75
|
ws.send(JSON.stringify({ type: 'auth', password }));
|
|
73
76
|
} else {
|
|
@@ -89,6 +92,7 @@ function createTerminalClient({
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
if (msg.type === 'attached') {
|
|
95
|
+
log.info(`Attached to session ${sessionId}`);
|
|
92
96
|
// Set terminal title to show we're attached
|
|
93
97
|
process.stdout.write(`\x1b]0;[termbeam] ${sessionName} — ${detachLabel} to detach\x07`);
|
|
94
98
|
|
|
@@ -113,6 +117,7 @@ function createTerminalClient({
|
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
if (msg.type === 'error') {
|
|
120
|
+
log.error(`Server error: ${msg.message}`);
|
|
116
121
|
cleanup(`error: ${msg.message}`);
|
|
117
122
|
return;
|
|
118
123
|
}
|
|
@@ -120,6 +125,7 @@ function createTerminalClient({
|
|
|
120
125
|
|
|
121
126
|
ws.on('error', (err) => {
|
|
122
127
|
if (!cleaned) {
|
|
128
|
+
log.warn('WebSocket error');
|
|
123
129
|
cleaned = true;
|
|
124
130
|
resetTerminal();
|
|
125
131
|
reject(err);
|
|
@@ -127,12 +133,14 @@ function createTerminalClient({
|
|
|
127
133
|
});
|
|
128
134
|
|
|
129
135
|
ws.on('close', () => {
|
|
136
|
+
log.info('WebSocket connection closed');
|
|
130
137
|
cleanup('connection closed');
|
|
131
138
|
});
|
|
132
139
|
});
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
function enterRawMode(ws, detachKey, cleanup, refs) {
|
|
143
|
+
log.debug('Entering raw mode');
|
|
136
144
|
if (process.stdin.isTTY) {
|
|
137
145
|
process.stdin.setRawMode(true);
|
|
138
146
|
}
|
|
@@ -141,6 +149,7 @@ function enterRawMode(ws, detachKey, cleanup, refs) {
|
|
|
141
149
|
refs.onData = (data) => {
|
|
142
150
|
const str = data.toString();
|
|
143
151
|
if (str === detachKey) {
|
|
152
|
+
log.info('User detached (Ctrl+B)');
|
|
144
153
|
cleanup('detached');
|
|
145
154
|
return;
|
|
146
155
|
}
|
package/src/cli/index.js
CHANGED
|
@@ -241,6 +241,7 @@ function parseArgs() {
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
log.setLevel(logLevel);
|
|
244
|
+
log.debug('Parsing CLI arguments');
|
|
244
245
|
|
|
245
246
|
const defaultShell = getDefaultShell();
|
|
246
247
|
const cwd = process.env.TERMBEAM_CWD || process.env.PTY_CWD || process.cwd();
|
|
@@ -318,6 +319,7 @@ function parseArgs() {
|
|
|
318
319
|
|
|
319
320
|
const validLogLevels = ['error', 'warn', 'info', 'debug'];
|
|
320
321
|
if (!validLogLevels.includes(logLevel)) {
|
|
322
|
+
log.error(`Invalid log level: ${logLevel}`);
|
|
321
323
|
console.error(`Error: --log-level must be one of: ${validLogLevels.join(', ')}\n`);
|
|
322
324
|
process.exit(1);
|
|
323
325
|
}
|
|
@@ -334,6 +336,7 @@ function parseArgs() {
|
|
|
334
336
|
if (publicTunnel && !useTunnel) {
|
|
335
337
|
const rd = '\x1b[31m';
|
|
336
338
|
const rs = '\x1b[0m';
|
|
339
|
+
log.error('--public requires a tunnel');
|
|
337
340
|
console.error(
|
|
338
341
|
`${rd}Error: --public requires a tunnel. Remove --no-tunnel or remove --public.${rs}`,
|
|
339
342
|
);
|
|
@@ -344,6 +347,7 @@ function parseArgs() {
|
|
|
344
347
|
if (publicTunnel && !password) {
|
|
345
348
|
const rd = '\x1b[31m';
|
|
346
349
|
const rs = '\x1b[0m';
|
|
350
|
+
log.error('Public tunnels require password authentication');
|
|
347
351
|
console.error(
|
|
348
352
|
`${rd}Error: Public tunnels require password authentication. Remove --no-password or remove --public.${rs}`,
|
|
349
353
|
);
|
|
@@ -356,7 +360,7 @@ function parseArgs() {
|
|
|
356
360
|
const { getVersion } = require('../utils/version');
|
|
357
361
|
const version = getVersion();
|
|
358
362
|
|
|
359
|
-
|
|
363
|
+
const config = {
|
|
360
364
|
port,
|
|
361
365
|
host,
|
|
362
366
|
password,
|
|
@@ -372,6 +376,12 @@ function parseArgs() {
|
|
|
372
376
|
interactive,
|
|
373
377
|
force,
|
|
374
378
|
};
|
|
379
|
+
|
|
380
|
+
log.debug(
|
|
381
|
+
`Config: port=${port}, host=${host}, shell=${shell}, tunnel=${useTunnel}, persisted=${persistedTunnel}, public=${publicTunnel}`,
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
return config;
|
|
375
385
|
}
|
|
376
386
|
|
|
377
387
|
module.exports = { parseArgs, printHelp, isKnownShell, getWindowsAncestors };
|
package/src/cli/interactive.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const crypto = require('crypto');
|
|
2
|
+
const log = require('../utils/logger');
|
|
2
3
|
const {
|
|
3
4
|
green,
|
|
4
5
|
yellow,
|
|
@@ -15,6 +16,7 @@ const {
|
|
|
15
16
|
// ── Interactive Setup Wizard ─────────────────────────────────────────────────
|
|
16
17
|
|
|
17
18
|
async function runInteractiveSetup(baseConfig) {
|
|
19
|
+
log.info('Interactive setup started');
|
|
18
20
|
// Enter alternate screen buffer for a clean wizard (like vim/htop)
|
|
19
21
|
process.stdout.write('\x1b[?1049h');
|
|
20
22
|
const exitAltScreen = () => process.stdout.write('\x1b[?1049l');
|
|
@@ -97,6 +99,7 @@ async function runInteractiveSetup(baseConfig) {
|
|
|
97
99
|
passwordMode = 'none';
|
|
98
100
|
config.password = null;
|
|
99
101
|
}
|
|
102
|
+
log.debug(`Password mode selected: ${passwordMode}`);
|
|
100
103
|
decisions.push({
|
|
101
104
|
label: 'Password',
|
|
102
105
|
value: config.password === null ? yellow('disabled') : '••••••••',
|
|
@@ -107,6 +110,7 @@ async function runInteractiveSetup(baseConfig) {
|
|
|
107
110
|
const portStr = await ask(rl, 'Port:', String(config.port));
|
|
108
111
|
const portNum = parseInt(portStr, 10);
|
|
109
112
|
config.port = portNum >= 1 && portNum <= 65535 ? portNum : 3456;
|
|
113
|
+
log.debug(`Port selected: ${config.port}`);
|
|
110
114
|
decisions.push({ label: 'Port', value: String(config.port) });
|
|
111
115
|
|
|
112
116
|
// Step 3: Access mode
|
|
@@ -190,6 +194,7 @@ async function runInteractiveSetup(baseConfig) {
|
|
|
190
194
|
: config.publicTunnel
|
|
191
195
|
? 'DevTunnel (public)'
|
|
192
196
|
: 'DevTunnel (private)';
|
|
197
|
+
log.debug(`Access mode selected: ${accessLabel}`);
|
|
193
198
|
decisions.push({ label: 'Access', value: accessLabel });
|
|
194
199
|
|
|
195
200
|
// Step 4: Log level
|
|
@@ -259,10 +264,12 @@ async function runInteractiveSetup(baseConfig) {
|
|
|
259
264
|
process.removeListener('exit', exitAltScreen);
|
|
260
265
|
|
|
261
266
|
if (!proceed) {
|
|
267
|
+
log.info('Interactive setup cancelled');
|
|
262
268
|
console.log(dim('Cancelled.'));
|
|
263
269
|
process.exit(0);
|
|
264
270
|
}
|
|
265
271
|
|
|
272
|
+
log.info('Interactive setup completed');
|
|
266
273
|
return config;
|
|
267
274
|
}
|
|
268
275
|
|
package/src/cli/resume.js
CHANGED
|
@@ -2,6 +2,7 @@ const http = require('http');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
+
const log = require('../utils/logger');
|
|
5
6
|
const { createTerminalClient } = require('./client');
|
|
6
7
|
const { bold, dim, red, yellow, choose, createRL, ask } = require('./prompts');
|
|
7
8
|
|
|
@@ -11,6 +12,7 @@ const CONNECTION_FILE = path.join(CONFIG_DIR, 'connection.json');
|
|
|
11
12
|
// ── Connection config ────────────────────────────────────────────────────────
|
|
12
13
|
|
|
13
14
|
function readConnectionConfig() {
|
|
15
|
+
log.debug('Reading connection config');
|
|
14
16
|
try {
|
|
15
17
|
return JSON.parse(fs.readFileSync(CONNECTION_FILE, 'utf8'));
|
|
16
18
|
} catch {
|
|
@@ -19,6 +21,7 @@ function readConnectionConfig() {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
function writeConnectionConfig({ port, host, password }) {
|
|
24
|
+
log.debug('Writing connection config');
|
|
22
25
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
23
26
|
fs.writeFileSync(CONNECTION_FILE, JSON.stringify({ port, host, password }, null, 2) + '\n', {
|
|
24
27
|
mode: 0o600,
|
|
@@ -34,6 +37,7 @@ function writeConnectionConfig({ port, host, password }) {
|
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
function removeConnectionConfig() {
|
|
40
|
+
log.debug('Removing connection config');
|
|
37
41
|
try {
|
|
38
42
|
fs.unlinkSync(CONNECTION_FILE);
|
|
39
43
|
} catch {
|
|
@@ -99,6 +103,7 @@ function httpRequest(urlStr, options = {}) {
|
|
|
99
103
|
method: options.method || 'GET',
|
|
100
104
|
headers: { ...options.headers },
|
|
101
105
|
};
|
|
106
|
+
log.debug(`HTTP ${reqOpts.method} ${url.hostname}:${url.port}${url.pathname}`);
|
|
102
107
|
|
|
103
108
|
const req = http.request(reqOpts, (res) => {
|
|
104
109
|
let body = '';
|
|
@@ -117,6 +122,7 @@ async function fetchSessions(baseUrl, password) {
|
|
|
117
122
|
|
|
118
123
|
const res = await httpRequest(`${baseUrl}/api/sessions`, { headers });
|
|
119
124
|
if (res.status === 401) {
|
|
125
|
+
log.warn('Session fetch unauthorized');
|
|
120
126
|
throw new Error('unauthorized');
|
|
121
127
|
}
|
|
122
128
|
if (res.status >= 400) {
|
|
@@ -284,6 +290,7 @@ async function resume(args) {
|
|
|
284
290
|
const detachKey = opts.detachKey || '\x02';
|
|
285
291
|
|
|
286
292
|
try {
|
|
293
|
+
log.info(`Connecting to session: ${session.name || session.id}`);
|
|
287
294
|
const { reason } = await createTerminalClient({
|
|
288
295
|
url: wsUrl,
|
|
289
296
|
password,
|
|
@@ -302,12 +309,14 @@ async function resume(args) {
|
|
|
302
309
|
console.log(dim(` Disconnected from ${bold(session.name)}.`));
|
|
303
310
|
}
|
|
304
311
|
} catch (err) {
|
|
312
|
+
log.error(`Connection failed: ${err.message}`);
|
|
305
313
|
console.error(red(` Connection failed: ${err.message}`));
|
|
306
314
|
process.exit(1);
|
|
307
315
|
}
|
|
308
316
|
}
|
|
309
317
|
|
|
310
318
|
async function list() {
|
|
319
|
+
log.info('Listing sessions');
|
|
311
320
|
const saved = readConnectionConfig();
|
|
312
321
|
const host = (saved && saved.host) || 'localhost';
|
|
313
322
|
const port = (saved && saved.port) || 3456;
|
package/src/cli/service.js
CHANGED
|
@@ -3,6 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const crypto = require('crypto');
|
|
6
|
+
const log = require('../utils/logger');
|
|
6
7
|
const {
|
|
7
8
|
color,
|
|
8
9
|
green,
|
|
@@ -24,6 +25,7 @@ const DEFAULT_SERVICE_NAME = 'termbeam';
|
|
|
24
25
|
// ── PM2 Detection ────────────────────────────────────────────────────────────
|
|
25
26
|
|
|
26
27
|
function findPm2() {
|
|
28
|
+
log.debug('Searching for PM2...');
|
|
27
29
|
try {
|
|
28
30
|
const cmd = os.platform() === 'win32' ? 'where' : 'which';
|
|
29
31
|
const result = execFileSync(cmd, ['pm2'], {
|
|
@@ -38,6 +40,7 @@ function findPm2() {
|
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
function installPm2Global() {
|
|
43
|
+
log.info('Installing PM2 globally');
|
|
41
44
|
console.log(yellow('\nInstalling PM2 globally...'));
|
|
42
45
|
try {
|
|
43
46
|
execFileSync('npm', ['install', '-g', 'pm2'], {
|
|
@@ -90,6 +93,7 @@ function buildArgs(config) {
|
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
function generateEcosystem(config) {
|
|
96
|
+
log.debug('Generating ecosystem config');
|
|
93
97
|
const entry = require.resolve('../../bin/termbeam.js');
|
|
94
98
|
const args = buildArgs(config);
|
|
95
99
|
const env = {};
|
|
@@ -121,6 +125,7 @@ function writeEcosystem(content) {
|
|
|
121
125
|
// ── PM2 Commands ─────────────────────────────────────────────────────────────
|
|
122
126
|
|
|
123
127
|
function pm2Exec(args, opts = {}) {
|
|
128
|
+
log.debug(`PM2 command: pm2 ${args.join(' ')}`);
|
|
124
129
|
try {
|
|
125
130
|
return execFileSync('pm2', args, {
|
|
126
131
|
encoding: 'utf8',
|
|
@@ -130,6 +135,7 @@ function pm2Exec(args, opts = {}) {
|
|
|
130
135
|
});
|
|
131
136
|
} catch (err) {
|
|
132
137
|
if (opts.silent) return null;
|
|
138
|
+
log.error(`PM2 command failed: ${err.message}`);
|
|
133
139
|
console.error(red(`✗ PM2 command failed: pm2 ${args.join(' ')}`));
|
|
134
140
|
if (err.stderr) console.error(dim(err.stderr.trim()));
|
|
135
141
|
return null;
|
|
@@ -139,6 +145,7 @@ function pm2Exec(args, opts = {}) {
|
|
|
139
145
|
// ── Actions ──────────────────────────────────────────────────────────────────
|
|
140
146
|
|
|
141
147
|
async function actionInstall() {
|
|
148
|
+
log.info('Starting service installation');
|
|
142
149
|
console.log(dim('\nChecking PM2...\n'));
|
|
143
150
|
|
|
144
151
|
// Step 1: Check PM2
|
|
@@ -411,6 +418,7 @@ async function actionInstall() {
|
|
|
411
418
|
}
|
|
412
419
|
|
|
413
420
|
pm2Exec(['save'], { inherit: true });
|
|
421
|
+
log.info('Service started successfully');
|
|
414
422
|
console.log(green('\n✓ TermBeam is now running as a PM2 service!'));
|
|
415
423
|
|
|
416
424
|
// Run pm2 startup if chosen during wizard
|
|
@@ -511,6 +519,7 @@ async function actionUninstall() {
|
|
|
511
519
|
console.log(dim(`Removed ${ECOSYSTEM_FILE}`));
|
|
512
520
|
}
|
|
513
521
|
|
|
522
|
+
log.info('Service stopped');
|
|
514
523
|
console.log(green(`\n✓ TermBeam service "${name}" removed.\n`));
|
|
515
524
|
}
|
|
516
525
|
|
|
@@ -545,6 +554,7 @@ function actionRestart() {
|
|
|
545
554
|
process.exit(1);
|
|
546
555
|
}
|
|
547
556
|
pm2Exec(['restart', DEFAULT_SERVICE_NAME], { inherit: true });
|
|
557
|
+
log.info('Service restarted');
|
|
548
558
|
console.log(green('\n✓ TermBeam service restarted.\n'));
|
|
549
559
|
}
|
|
550
560
|
|