itwillsync 1.6.1 → 1.7.0
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/dist/hub/daemon.js +391 -25
- package/dist/hub/daemon.js.map +1 -1
- package/dist/hub/dashboard/assets/index-CUdWjWFv.css +1 -0
- package/dist/hub/dashboard/assets/index-hWUVy-IH.js +2 -0
- package/dist/hub/dashboard/index.html +62 -5
- package/package.json +1 -1
- package/dist/hub/dashboard/assets/index-C0aiYBkq.js +0 -2
- package/dist/hub/dashboard/assets/index-D6z7Ixhf.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*{margin:0;padding:0;box-sizing:border-box}html,body{height:100%;width:100%;background:#1a1a2e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;color:#e0e0e0;overflow-x:hidden;-webkit-overflow-scrolling:touch}#header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#16213e;border-bottom:1px solid #0f3460;position:sticky;top:0;z-index:10}.header-left{display:flex;align-items:center;gap:10px}.logo{font-size:16px;font-weight:700;color:#e94560;letter-spacing:-.5px}#status-dot{width:8px;height:8px;border-radius:50%;background:#e74c3c;transition:background .3s ease}#status-dot.connected{background:#2ecc71}#status-dot.reconnecting{background:#f39c12;animation:pulse 1s infinite}.header-right{display:flex;align-items:center;gap:12px}#session-count{font-size:13px;color:#a0a0b0}.header-icon-btn{background:none;border:1px solid #2a2a44;border-radius:8px;color:#a0a0b0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:color .15s,border-color .15s}.header-icon-btn:active{color:#e94560;border-color:#e94560}#session-list{padding:12px 12px 80px;display:flex;flex-direction:column;gap:12px}#empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;color:#606080;text-align:center;gap:8px}#empty-state .empty-icon{font-size:48px;margin-bottom:8px;opacity:.5}#empty-state p{font-size:16px}#empty-state .empty-hint{font-size:13px;color:#505070}#empty-state code{background:#252540;padding:2px 8px;border-radius:4px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:12px;color:#e94560}.session-card{background:#16213e;border:1px solid #0f3460;border-radius:12px;padding:14px 16px;cursor:pointer;transition:transform .15s ease,border-color .2s ease;-webkit-tap-highlight-color:transparent}.session-card:active{transform:scale(.98)}.session-card:hover{border-color:#e94560}.session-card.attention{border-color:#e94560;animation:attention-glow 2s ease-in-out infinite}@keyframes attention-glow{0%,to{box-shadow:0 0 #e9456000}50%{box-shadow:0 0 12px 2px #e945604d}}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.card-agent{display:flex;align-items:center;gap:8px}.agent-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.agent-dot.active{background:#2ecc71}.agent-dot.idle{background:#f39c12}.agent-dot.attention{background:#e94560;animation:pulse 1s infinite}.agent-name{font-size:15px;font-weight:600;color:#f0f0f0}.card-uptime{font-size:12px;color:#707090;font-variant-numeric:tabular-nums}.card-cwd{font-size:12px;color:#808098;margin-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.card-preview{background:#112;border-radius:6px;padding:8px 10px;margin-bottom:10px;overflow:hidden;min-height:24px;max-height:90px}.card-preview-text{font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:11px;line-height:1.4;color:#a0a0b0;white-space:pre;overflow:hidden;text-overflow:ellipsis;margin:0}.card-preview-text.empty{color:#505070;font-style:italic}.card-status{display:flex;align-items:center;gap:6px;font-size:12px;color:#a0a0b0}.status-badge{padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500;text-transform:uppercase;letter-spacing:.5px}.status-badge.active{background:#2ecc7126;color:#2ecc71}.status-badge.idle{background:#f39c1226;color:#f39c12}.status-badge.attention{background:#e9456026;color:#e94560}.attention-badge{padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;background:#e9456033;color:#e94560;animation:attention-pulse 2s ease-in-out infinite}@keyframes attention-pulse{0%,to{opacity:1}50%{opacity:.6}}.card-actions{display:flex;gap:6px;margin-top:10px;padding-top:10px;border-top:1px solid #0f3460}.action-btn{flex:1;padding:6px 0;border:1px solid #2a2a44;border-radius:6px;background:#1e1e36;color:#a0a0b0;font-size:12px;font-weight:500;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s,color .15s}.action-btn:active{background:#2a2a44}.action-btn.open{color:#2ecc71;border-color:#2ecc714d}.action-btn.stop{color:#e94560;border-color:#e945604d}.action-btn.stop:active{background:#e9456026}.confirm-overlay{display:flex;align-items:center;justify-content:center;gap:10px;padding:10px;margin-top:8px;background:#2d1810;border:1px solid #e94560;border-radius:8px;animation:fadeIn .15s ease}.confirm-msg{font-size:13px;color:#f0f0f0;flex:1}.confirm-btn{padding:5px 14px;border:none;border-radius:5px;font-size:12px;font-weight:600;font-family:inherit;cursor:pointer}.confirm-btn.yes{background:#e94560;color:#fff}.confirm-btn.no{background:#2a2a44;color:#a0a0b0}.rename-input{background:#112;border:1px solid #e94560;border-radius:4px;color:#f0f0f0;font-size:15px;font-weight:600;font-family:inherit;padding:2px 6px;outline:none;width:120px}.card-metadata{margin-top:8px;padding:8px 10px;background:#112;border-radius:6px;animation:fadeIn .2s ease}.card-metadata.hidden{display:none}.meta-row{display:flex;justify-content:space-between;padding:3px 0;font-size:11px}.meta-label{color:#707090;font-weight:500}.meta-value{color:#c0c0d0;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:11px;text-align:right;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(min-width:768px){#session-list{max-width:600px;margin:0 auto}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.session-card{animation:fadeIn .3s ease}#reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#1a1a2ef2;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:100;color:#e0e0e0;font-size:16px;gap:12px}#reconnect-overlay .spinner{width:32px;height:32px;border:3px solid #0f3460;border-top-color:#e94560;border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}#fab-create{position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;background:#e94560;color:#fff;font-size:28px;font-weight:300;border:none;cursor:pointer;box-shadow:0 4px 16px #e9456066;z-index:20;-webkit-tap-highlight-color:transparent;transition:transform .15s,box-shadow .15s;display:flex;align-items:center;justify-content:center;line-height:1}#fab-create:active{transform:scale(.92)}.modal-overlay{position:fixed;inset:0;background:#0a0a14d9;z-index:50;display:flex;align-items:flex-end;justify-content:center;animation:fadeIn .15s ease}.modal-overlay.hidden{display:none}.modal-content{background:#16213e;border-radius:16px 16px 0 0;width:100%;max-width:480px;max-height:85vh;max-height:85dvh;overflow-y:auto;padding:20px;animation:slideUp .2s ease}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.modal-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px}.modal-title{font-size:18px;font-weight:600;color:#f0f0f0}.modal-close{background:none;border:none;color:#707090;font-size:24px;cursor:pointer;padding:4px 8px;line-height:1}.form-label{display:block;font-size:13px;font-weight:500;color:#a0a0b0;margin-bottom:6px;margin-top:16px}.form-label:first-of-type{margin-top:0}.form-input{width:100%;padding:10px 12px;background:#112;border:1px solid #2a2a44;border-radius:8px;color:#f0f0f0;font-size:15px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;outline:none;transition:border-color .15s}.form-input:focus{border-color:#e94560}.form-input.hidden{display:none}.chip-row{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}.chip{padding:5px 12px;background:#1e1e36;border:1px solid #2a2a44;border-radius:16px;font-size:12px;color:#c0c0d0;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s,border-color .15s;white-space:nowrap;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.chip:active,.chip.selected{background:#e9456026;border-color:#e94560;color:#e94560}.dir-display{padding:10px 12px;background:#112;border:1px solid #2a2a44;border-radius:8px;font-size:13px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;color:#c0c0d0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dir-actions{display:flex;gap:8px;margin-top:10px}.dir-action-btn{flex:1;padding:8px 0;background:#1e1e36;border:1px solid #2a2a44;border-radius:8px;color:#a0a0b0;font-size:13px;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s}.dir-action-btn:active{background:#2a2a44}.btn-create{width:100%;margin-top:20px;padding:14px;background:#e94560;color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:opacity .15s}.btn-create:disabled{opacity:.4;cursor:default}.btn-create:not(:disabled):active{opacity:.8}.create-error{margin-top:12px;padding:8px 12px;background:#e9456026;border-radius:6px;font-size:13px;color:#e94560}.create-error.hidden{display:none}.create-spinner{display:flex;flex-direction:column;align-items:center;gap:12px;padding:32px 0;color:#a0a0b0;font-size:14px}.create-spinner.hidden{display:none}.browse-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.browse-back{background:none;border:none;color:#a0a0b0;font-size:14px;font-family:inherit;cursor:pointer;padding:4px 0}.browse-select{padding:6px 14px;background:#e94560;color:#fff;border:none;border-radius:6px;font-size:13px;font-weight:500;font-family:inherit;cursor:pointer}.browse-breadcrumb{display:flex;gap:4px;align-items:center;margin-bottom:12px;font-size:13px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;color:#808098;flex-wrap:wrap}.breadcrumb-segment{cursor:pointer;color:#a0a0b0;transition:color .15s}.breadcrumb-segment:hover,.breadcrumb-segment:active{color:#e94560}.breadcrumb-sep{color:#505070}.browse-list{display:flex;flex-direction:column;gap:2px;max-height:50vh;max-height:50dvh;overflow-y:auto}.browse-item{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;background:#112;border-radius:6px;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .1s}.browse-item:active{background:#1e1e36}.browse-item-name{font-size:14px;color:#d0d0e0;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.browse-item-arrow{color:#505070;font-size:14px}.browse-empty{text-align:center;padding:24px;color:#505070;font-size:13px}.hidden{display:none!important}.setting-row{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;background:#112;border-radius:10px}.setting-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.setting-icon{font-size:22px;flex-shrink:0}.setting-label{font-size:15px;font-weight:600;color:#f0f0f0}.setting-sublabel{font-size:11px;color:#707090;margin-top:2px}.toggle-btn{width:48px;height:28px;border-radius:14px;background:#2a2a44;border:none;cursor:pointer;position:relative;flex-shrink:0;transition:background .25s ease;-webkit-tap-highlight-color:transparent}.toggle-btn[aria-checked=true]{background:#2ecc71}.toggle-btn:disabled{opacity:.4;cursor:default}.toggle-knob{display:block;width:22px;height:22px;border-radius:50%;background:#707090;position:absolute;top:3px;left:3px;transition:transform .25s ease,background .25s ease}.toggle-btn[aria-checked=true] .toggle-knob{transform:translate(20px);background:#fff}.setting-warning{margin-top:12px;padding:10px 14px;background:#f39c121a;border:1px solid rgba(243,156,18,.25);border-radius:8px;font-size:12px;color:#f39c12;line-height:1.5}.setting-note{margin-top:8px;font-size:11px;color:#505070;text-align:center}.setting-tip{margin-top:10px;padding:8px 12px;background:#0f346066;border-radius:6px;font-size:12px;color:#808098;line-height:1.5}#sleep-password-section{margin-top:16px;padding-top:16px;border-top:1px solid #0f3460}#sleep-password-section .form-label{margin-top:0}.sleep-actions{display:flex;gap:10px;margin-top:14px}.sleep-actions .action-btn{flex:1;padding:12px;font-size:14px}.sleep-actions .btn-create{flex:1;margin-top:0;padding:12px;font-size:14px}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))o(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const c of a.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&o(c)}).observe(document,{childList:!0,subtree:!0});function n(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerPolicy&&(a.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?a.credentials="include":s.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(s){if(s.ep)return;s.ep=!0;const a=n(s);fetch(s.href,a)}})();function Z(e){const t=Math.floor(e/1e3);if(t<60)return`${t}s`;const n=Math.floor(t/60);if(n<60)return`${n}m`;const o=Math.floor(n/60),s=n%60;return`${o}h ${s}m`}function Be(e){const t=e.match(/^\/(?:Users|home)\/[^/]+/)?.[0];return t?"~"+e.slice(t.length):e}function Se(e){return e<1024?`${e} KB`:`${(e/1024).toFixed(1)} MB`}function Ne(e,t,n){const o=document.createElement("div");o.className=`session-card${e.status==="attention"?" attention":""}`,o.dataset.sessionId=e.id;const s=Z(Date.now()-e.connectedAt),a=Be(e.cwd),c=document.createElement("div");c.className="card-header";const i=document.createElement("div");i.className="card-agent";const y=document.createElement("div");y.className=`agent-dot ${e.status}`;const W=document.createElement("span");W.className="agent-name",W.textContent=e.name||e.agent,i.appendChild(y),i.appendChild(W);const _=document.createElement("span");_.className="card-uptime",_.textContent=s,c.appendChild(i),c.appendChild(_);const j=document.createElement("div");j.className="card-cwd",j.textContent=a;const N=document.createElement("div");N.className="card-preview";const K=document.createElement("pre");K.className="card-preview-text",K.textContent="Waiting for output...",N.appendChild(K),N.addEventListener("click",l=>{l.stopPropagation(),n.onOpen(e)});const x=document.createElement("div");x.className="card-status";const P=document.createElement("span");P.className=`status-badge ${e.status}`,P.textContent=e.status,e.status==="attention"&&(P.style.display="none");const $=document.createElement("span");$.className="attention-badge",$.textContent="Needs your attention",e.status!=="attention"&&($.style.display="none"),x.appendChild(P),x.appendChild($);const g=document.createElement("div");g.className="card-actions";const M=document.createElement("button");M.className="action-btn stop",M.textContent="Stop",M.addEventListener("click",l=>{l.stopPropagation(),xe(o,e.id,n.onStop)});const A=document.createElement("button");A.className="action-btn rename",A.textContent="Rename",A.addEventListener("click",l=>{l.stopPropagation(),Pe(o,e.id,n.onRename)});const O=document.createElement("button");O.className="action-btn info",O.textContent="Info",O.addEventListener("click",l=>{l.stopPropagation(),n.onInfo(e.id)});const T=document.createElement("button");T.className="action-btn open",T.textContent="Open",T.addEventListener("click",l=>{l.stopPropagation(),n.onOpen(e)}),g.appendChild(T),g.appendChild(A),g.appendChild(O),g.appendChild(M);const ie=document.createElement("div");return ie.className="card-metadata hidden",o.addEventListener("click",()=>{n.onOpen(e)}),o.appendChild(c),o.appendChild(j),o.appendChild(N),o.appendChild(x),o.appendChild(g),o.appendChild(ie),o}function xe(e,t,n){e.querySelector(".confirm-overlay")?.remove();const o=document.createElement("div");o.className="confirm-overlay";const s=document.createElement("span");s.className="confirm-msg",s.textContent="Stop this session?";const a=document.createElement("button");a.className="confirm-btn yes",a.textContent="Yes",a.addEventListener("click",i=>{i.stopPropagation(),n(t),o.remove()});const c=document.createElement("button");c.className="confirm-btn no",c.textContent="No",c.addEventListener("click",i=>{i.stopPropagation(),o.remove()}),o.addEventListener("click",i=>i.stopPropagation()),o.appendChild(s),o.appendChild(a),o.appendChild(c),e.appendChild(o)}function Pe(e,t,n){const o=e.querySelector(".agent-name");if(!o)return;const s=o.textContent||"",a=document.createElement("input");a.className="rename-input",a.type="text",a.value=s;const c=()=>{const i=a.value.trim();i&&i!==s&&n(t,i),o.textContent=i||s,o.style.display="",a.remove()};a.addEventListener("keydown",i=>{i.stopPropagation(),i.key==="Enter"?c():i.key==="Escape"&&(o.textContent=s,o.style.display="",a.remove())}),a.addEventListener("blur",c),a.addEventListener("click",i=>i.stopPropagation()),o.style.display="none",o.parentElement?.insertBefore(a,o.nextSibling),a.focus(),a.select()}function be(e,t){const n=e.querySelector(".agent-dot"),o=e.querySelector(".status-badge"),s=e.querySelector(".card-uptime"),a=e.querySelector(".agent-name");n&&(n.className=`agent-dot ${t.status}`),o&&(o.className=`status-badge ${t.status}`,o.textContent=t.status),s&&(s.textContent=Z(Date.now()-t.connectedAt)),a&&!a.style.display&&(a.textContent=t.name||t.agent);const c=t.status==="attention";o&&(o.style.display=c?"none":"");const i=e.querySelector(".attention-badge");i&&(i.style.display=c?"":"none"),t.status==="attention"?e.classList.add("attention"):e.classList.remove("attention")}function $e(e,t){const n=e.querySelector(".card-preview-text");n&&(t.length>0?(n.textContent=t.join(`
|
|
2
|
+
`),n.classList.remove("empty")):(n.textContent="Waiting for output...",n.classList.add("empty")))}function Me(e,t){const n=e.querySelector(".card-metadata");if(!n)return;for(;n.firstChild;)n.removeChild(n.firstChild);const o=[["PID",String(t.pid)],["Agent",t.agent],["Port",String(t.port)],["Directory",t.cwd],["Memory",Se(t.memoryKB)],["Uptime",Z(t.uptimeMs)]];for(const[s,a]of o){const c=document.createElement("div");c.className="meta-row";const i=document.createElement("span");i.className="meta-label",i.textContent=s;const y=document.createElement("span");y.className="meta-value",y.textContent=a,c.appendChild(i),c.appendChild(y),n.appendChild(c)}n.classList.toggle("hidden")}let d=null,de=!1;function Ae(){if(!de){de=!0;try{d=new AudioContext,d.state==="suspended"&&d.resume()}catch{}}}function re(){if(!d)return;d.state==="suspended"&&d.resume();const e=d.currentTime,t=d.createOscillator(),n=d.createGain();t.frequency.value=587.33,t.type="sine",n.gain.setValueAtTime(.3,e),n.gain.exponentialRampToValueAtTime(.01,e+.3),t.connect(n),n.connect(d.destination),t.start(e),t.stop(e+.3);const o=d.createOscillator(),s=d.createGain();o.frequency.value=880,o.type="sine",s.gain.setValueAtTime(.3,e+.15),s.gain.exponentialRampToValueAtTime(.01,e+.45),o.connect(s),s.connect(d.destination),o.start(e+.15),o.stop(e+.45)}const le=120*1e3,h=new Map;function me(e){if(h.has(e))return;re();const t=setTimeout(function n(){re();const o=h.get(e);o&&(o.timerId=setTimeout(n,le))},le);h.set(e,{timerId:t})}function Y(e){const t=h.get(e);t&&(clearTimeout(t.timerId),h.delete(e))}function ue(){for(const e of h.values())clearTimeout(e.timerId);h.clear()}let z=null,k,u,I,f,b,D,H,pe;function Oe(e){z=e;const t=document.getElementById("btn-settings");k=document.getElementById("settings-modal");const n=document.getElementById("settings-modal-close");u=document.getElementById("sleep-toggle"),I=document.getElementById("sleep-password-section"),f=document.getElementById("sleep-password"),b=document.getElementById("sleep-error"),D=document.getElementById("sleep-spinner"),H=document.getElementById("sleep-unsupported"),pe=document.getElementById("sleep-enable");const o=document.getElementById("sleep-cancel");t.addEventListener("click",()=>{k.classList.remove("hidden")}),n.addEventListener("click",he),k.addEventListener("click",s=>{s.target===k&&he()}),u.addEventListener("click",()=>{if(u.disabled)return;u.getAttribute("aria-checked")==="true"?z?.({type:"disable-sleep-prevention"}):(I.classList.remove("hidden"),b.classList.add("hidden"),f.value="",f.focus())}),pe.addEventListener("click",fe),f.addEventListener("keydown",s=>{s.key==="Enter"&&(s.preventDefault(),fe())}),o.addEventListener("click",ee)}function ee(){I.classList.add("hidden"),f.value="",b.classList.add("hidden")}function fe(){const e=f.value;if(!e){Ce("Password is required");return}f.value="",b.classList.add("hidden"),I.classList.add("hidden"),D.classList.remove("hidden"),z?.({type:"enable-sleep-prevention",password:e})}function he(){k.classList.add("hidden"),ee()}function Ce(e){b.textContent=e,b.classList.remove("hidden")}function Te(e){if(D.classList.add("hidden"),!e.supported){u.disabled=!0,u.setAttribute("aria-checked","false"),H.classList.remove("hidden");return}H.classList.add("hidden"),u.disabled=!1,u.setAttribute("aria-checked",e.enabled?"true":"false"),ee()}function Re(e){D.classList.add("hidden"),I.classList.remove("hidden"),Ce(e),u.setAttribute("aria-checked","false")}const Ue=new URLSearchParams(window.location.search),V=Ue.get("token");if(!V)throw document.body.textContent="Missing authentication token.",new Error("No token in URL");const qe=window.location.protocol==="https:"?"wss:":"ws:",De=`${qe}//${window.location.host}?token=${V}`,we=window.location.hostname,w=new Map,p=new Map,Ve=document.getElementById("session-list"),X=document.getElementById("empty-state"),Fe=document.getElementById("session-count"),ye=document.getElementById("status-dot");let G=null;function R(){Ae(),document.removeEventListener("click",R),document.removeEventListener("touchstart",R)}document.addEventListener("click",R);document.addEventListener("touchstart",R);function v(e){r&&r.readyState===WebSocket.OPEN&&r.send(JSON.stringify(e))}Oe(v);const We={onOpen(e){const t=w.get(e.id)||e;t.status==="attention"&&(v({type:"clear-attention",sessionId:t.id}),Y(t.id));const n=window.location.href,o=`http://${we}:${t.port}?token=${t.token}&hub=${encodeURIComponent(n)}`;window.location.href=o},onStop(e){v({type:"stop-session",sessionId:e})},onRename(e,t){v({type:"rename-session",sessionId:e,name:t})},onInfo(e){v({type:"get-metadata",sessionId:e})}};function Le(){const e=w.size;Fe.textContent=`${e} session${e!==1?"s":""}`,e===0?X.style.display="flex":X.style.display="none"}function ge(e){w.set(e.id,e);const t=Ne(e,we,We);p.set(e.id,t),Ve.insertBefore(t,X),Le()}function Ee(e){w.delete(e);const t=p.get(e);t&&(t.remove(),p.delete(e)),Le()}function _e(e){w.set(e.id,e);const t=p.get(e.id);t&&be(t,e)}function je(){for(const[e,t]of w){const n=p.get(e);n&&be(n,t)}}const te=document.getElementById("fab-create"),B=document.getElementById("create-modal"),Ke=document.getElementById("modal-close"),C=document.getElementById("tool-input"),ve=document.getElementById("tool-chips"),ke=document.getElementById("dir-selected"),Ge=document.getElementById("btn-browse"),Ie=document.getElementById("btn-create-session"),U=document.getElementById("create-error"),L=document.getElementById("create-form-view"),F=document.getElementById("browse-view"),J=document.getElementById("browse-breadcrumb"),E=document.getElementById("browse-list"),Je=document.getElementById("browse-back"),Ye=document.getElementById("browse-select"),ne=document.getElementById("create-spinner");let S="~",Q="~";function m(e,t,n){const o=document.createElement(e);return o.className=t,o.textContent=n,o}function ze(){B.classList.remove("hidden"),L.classList.remove("hidden"),F.classList.add("hidden"),ne.classList.add("hidden"),U.classList.add("hidden"),C.value="",S="~",ke.textContent="~",se(),He(),C.focus()}function oe(){B.classList.add("hidden")}function se(){Ie.disabled=!C.value.trim()}async function He(){try{const t=await(await fetch(`/api/tool-history?token=${V}`)).json();ve.replaceChildren();for(const n of t.tools.slice(0,6)){const o=m("span","chip",n);o.addEventListener("click",()=>{C.value=n,se()}),ve.appendChild(o)}}catch{}}async function ae(e){Q=e,E.replaceChildren(m("div","browse-empty","Loading..."));try{const n=await(await fetch(`/api/browse?path=${encodeURIComponent(e)}&token=${V}`)).json();if(n.error){E.replaceChildren(m("div","browse-empty",n.error));return}const o=n.path||e;Q=o,Xe(o);const s=n.entries;if(s.length===0){E.replaceChildren(m("div","browse-empty","No subdirectories"));return}E.replaceChildren();for(const a of s){const c=document.createElement("div");c.className="browse-item",c.appendChild(m("span","browse-item-name",a)),c.appendChild(m("span","browse-item-arrow","›")),c.addEventListener("click",()=>ae(`${o}/${a}`)),E.appendChild(c)}}catch{E.replaceChildren(m("div","browse-empty","Failed to load"))}}function Xe(e){J.replaceChildren();const t=e.split("/").filter(Boolean);for(let n=0;n<t.length;n++){n>0&&J.appendChild(m("span","breadcrumb-sep"," / "));const o=m("span","breadcrumb-segment",t[n]),s=t.slice(0,n+1).join("/");o.addEventListener("click",()=>ae(s)),J.appendChild(o)}}function Qe(){const e=C.value.trim();e&&(U.classList.add("hidden"),L.classList.add("hidden"),ne.classList.remove("hidden"),v({type:"create-session",tool:e,cwd:S}))}te.addEventListener("click",ze);Ke.addEventListener("click",oe);B.addEventListener("click",e=>{e.target===B&&oe()});C.addEventListener("input",se);Ie.addEventListener("click",Qe);Ge.addEventListener("click",()=>{L.classList.add("hidden"),F.classList.remove("hidden"),ae(S)});Je.addEventListener("click",()=>{F.classList.add("hidden"),L.classList.remove("hidden")});Ye.addEventListener("click",()=>{S=Q,ke.textContent=S,F.classList.add("hidden"),L.classList.remove("hidden")});let r=null,q=0;const Ze=1e4;function ce(){r=new WebSocket(De),r.onopen=()=>{ye.className="connected",q=0,G&&clearInterval(G),G=setInterval(je,1e4)},r.onmessage=e=>{try{const t=JSON.parse(e.data);switch(t.type){case"sessions":{ue();for(const n of p.keys())Ee(n);for(const n of t.sessions)ge(n),n.status==="attention"&&me(n.id);break}case"session-added":{ge(t.session),B.classList.contains("hidden")||oe();break}case"session-removed":{const n=t.sessionId;Y(n),Ee(n);break}case"session-updated":{const n=t.session;_e(n),n.status==="attention"?me(n.id):Y(n.id);break}case"preview":{const n=p.get(t.sessionId);n&&$e(n,t.lines);break}case"metadata":{const n=p.get(t.sessionId);n&&Me(n,t.metadata);break}case"session-creating":break;case"session-create-error":{ne.classList.add("hidden"),L.classList.remove("hidden"),U.textContent=t.error,U.classList.remove("hidden");break}case"sleep-state":{Te(t.state);break}case"sleep-error":{Re(t.error);break}case"operation-error":{console.warn(`Operation "${t.operation}" failed for session ${t.sessionId}: ${t.error}`);break}}}catch{}},r.onclose=()=>{ye.className="reconnecting",ue(),et()},r.onerror=()=>{r?.close()}}function et(){const e=Math.min(1e3*Math.pow(1.5,q),Ze);q++,setTimeout(ce,e)}document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&r?.readyState!==WebSocket.OPEN&&(q=0,ce())});ce();document.addEventListener("focusin",e=>{const t=e.target;t.matches("input, textarea")&&(te.style.display="none",setTimeout(()=>{t.scrollIntoView({block:"center",behavior:"smooth"})},300))});document.addEventListener("focusout",()=>{te.style.display=""});
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no, interactive-widget=resizes-content" />
|
|
6
6
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
7
7
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
8
8
|
<meta name="theme-color" content="#1a1a2e" />
|
|
9
9
|
<title>itwillsync Dashboard</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-hWUVy-IH.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CUdWjWFv.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<header id="header">
|
|
@@ -16,7 +16,15 @@
|
|
|
16
16
|
<span class="logo">itwillsync</span>
|
|
17
17
|
<span id="status-dot"></span>
|
|
18
18
|
</div>
|
|
19
|
-
<
|
|
19
|
+
<div class="header-right">
|
|
20
|
+
<span id="session-count">0 sessions</span>
|
|
21
|
+
<button id="btn-settings" class="header-icon-btn" aria-label="Settings">
|
|
22
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
23
|
+
<circle cx="12" cy="12" r="3"/>
|
|
24
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
|
25
|
+
</svg>
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
20
28
|
</header>
|
|
21
29
|
|
|
22
30
|
<main id="session-list">
|
|
@@ -41,7 +49,7 @@
|
|
|
41
49
|
<!-- View: Create Form -->
|
|
42
50
|
<div id="create-form-view">
|
|
43
51
|
<label class="form-label">Tool</label>
|
|
44
|
-
<input type="text" id="tool-input" class="form-input" placeholder="e.g. claude, aider, bash" autocomplete="off" autocapitalize="off" />
|
|
52
|
+
<input type="text" id="tool-input" class="form-input" placeholder="e.g. claude, aider, zsh, bash" autocomplete="off" autocapitalize="off" />
|
|
45
53
|
<div id="tool-chips" class="chip-row"></div>
|
|
46
54
|
|
|
47
55
|
<label class="form-label">Working Directory</label>
|
|
@@ -72,5 +80,54 @@
|
|
|
72
80
|
</div>
|
|
73
81
|
</div>
|
|
74
82
|
|
|
83
|
+
<!-- Settings Modal -->
|
|
84
|
+
<div id="settings-modal" class="modal-overlay hidden">
|
|
85
|
+
<div class="modal-content">
|
|
86
|
+
<div class="modal-header">
|
|
87
|
+
<span class="modal-title">Settings</span>
|
|
88
|
+
<button class="modal-close" id="settings-modal-close">×</button>
|
|
89
|
+
</div>
|
|
90
|
+
<div id="settings-body">
|
|
91
|
+
<div class="setting-row">
|
|
92
|
+
<div class="setting-info">
|
|
93
|
+
<span class="setting-icon">☕</span>
|
|
94
|
+
<div>
|
|
95
|
+
<div class="setting-label">Prevent Sleep</div>
|
|
96
|
+
<div class="setting-sublabel">Keep computer awake even with lid closed</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<button id="sleep-toggle" class="toggle-btn" role="switch" aria-checked="false">
|
|
100
|
+
<span class="toggle-knob"></span>
|
|
101
|
+
</button>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<div class="setting-warning">
|
|
105
|
+
⚠️ <strong>Battery warning:</strong> Your laptop may shut down if running on battery. Keep it plugged in.
|
|
106
|
+
</div>
|
|
107
|
+
<div class="setting-note">Requires admin password · Auto-reverts when hub stops</div>
|
|
108
|
+
<div class="setting-tip">💻 Enable this while you're near your laptop — you'll need to type your system password.</div>
|
|
109
|
+
|
|
110
|
+
<div id="sleep-password-section" class="hidden">
|
|
111
|
+
<label class="form-label">System password</label>
|
|
112
|
+
<input type="password" id="sleep-password" class="form-input" placeholder="Enter your password" autocomplete="off" />
|
|
113
|
+
<div id="sleep-error" class="create-error hidden"></div>
|
|
114
|
+
<div class="sleep-actions">
|
|
115
|
+
<button id="sleep-cancel" class="action-btn">Cancel</button>
|
|
116
|
+
<button id="sleep-enable" class="btn-create">Enable</button>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div id="sleep-spinner" class="create-spinner hidden">
|
|
121
|
+
<div class="spinner"></div>
|
|
122
|
+
<span>Applying...</span>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div id="sleep-unsupported" class="setting-note hidden">
|
|
126
|
+
Sleep prevention is not available on this platform.
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
75
132
|
</body>
|
|
76
133
|
</html>
|
package/package.json
CHANGED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))o(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const c of a.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&o(c)}).observe(document,{childList:!0,subtree:!0});function n(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerPolicy&&(a.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?a.credentials="include":s.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(s){if(s.ep)return;s.ep=!0;const a=n(s);fetch(s.href,a)}})();function K(e){const t=Math.floor(e/1e3);if(t<60)return`${t}s`;const n=Math.floor(t/60);if(n<60)return`${n}m`;const o=Math.floor(n/60),s=n%60;return`${o}h ${s}m`}function ue(e){const t=e.match(/^\/(?:Users|home)\/[^/]+/)?.[0];return t?"~"+e.slice(t.length):e}function pe(e){return e<1024?`${e} KB`:`${(e/1024).toFixed(1)} MB`}function fe(e,t,n){const o=document.createElement("div");o.className=`session-card${e.status==="attention"?" attention":""}`,o.dataset.sessionId=e.id;const s=K(Date.now()-e.connectedAt),a=ue(e.cwd),c=document.createElement("div");c.className="card-header";const i=document.createElement("div");i.className="card-agent";const f=document.createElement("div");f.className=`agent-dot ${e.status}`;const R=document.createElement("span");R.className="agent-name",R.textContent=e.name||e.agent,i.appendChild(f),i.appendChild(R);const q=document.createElement("span");q.className="card-uptime",q.textContent=s,c.appendChild(i),c.appendChild(q);const U=document.createElement("div");U.className="card-cwd",U.textContent=a;const L=document.createElement("div");L.className="card-preview";const D=document.createElement("pre");D.className="card-preview-text",D.textContent="Waiting for output...",L.appendChild(D),L.addEventListener("click",l=>{l.stopPropagation(),n.onOpen(e)});const N=document.createElement("div");N.className="card-status";const S=document.createElement("span");S.className=`status-badge ${e.status}`,S.textContent=e.status,e.status==="attention"&&(S.style.display="none");const I=document.createElement("span");I.className="attention-badge",I.textContent="Needs your attention",e.status!=="attention"&&(I.style.display="none"),N.appendChild(S),N.appendChild(I);const h=document.createElement("div");h.className="card-actions";const k=document.createElement("button");k.className="action-btn stop",k.textContent="Stop",k.addEventListener("click",l=>{l.stopPropagation(),he(o,e.id,n.onStop)});const B=document.createElement("button");B.className="action-btn rename",B.textContent="Rename",B.addEventListener("click",l=>{l.stopPropagation(),ye(o,e.id,n.onRename)});const x=document.createElement("button");x.className="action-btn info",x.textContent="Info",x.addEventListener("click",l=>{l.stopPropagation(),n.onInfo(e.id)});const P=document.createElement("button");P.className="action-btn open",P.textContent="Open",P.addEventListener("click",l=>{l.stopPropagation(),n.onOpen(e)}),h.appendChild(P),h.appendChild(B),h.appendChild(x),h.appendChild(k);const X=document.createElement("div");return X.className="card-metadata hidden",o.addEventListener("click",()=>{n.onOpen(e)}),o.appendChild(c),o.appendChild(U),o.appendChild(L),o.appendChild(N),o.appendChild(h),o.appendChild(X),o}function he(e,t,n){e.querySelector(".confirm-overlay")?.remove();const o=document.createElement("div");o.className="confirm-overlay";const s=document.createElement("span");s.className="confirm-msg",s.textContent="Stop this session?";const a=document.createElement("button");a.className="confirm-btn yes",a.textContent="Yes",a.addEventListener("click",i=>{i.stopPropagation(),n(t),o.remove()});const c=document.createElement("button");c.className="confirm-btn no",c.textContent="No",c.addEventListener("click",i=>{i.stopPropagation(),o.remove()}),o.addEventListener("click",i=>i.stopPropagation()),o.appendChild(s),o.appendChild(a),o.appendChild(c),e.appendChild(o)}function ye(e,t,n){const o=e.querySelector(".agent-name");if(!o)return;const s=o.textContent||"",a=document.createElement("input");a.className="rename-input",a.type="text",a.value=s;const c=()=>{const i=a.value.trim();i&&i!==s&&n(t,i),o.textContent=i||s,o.style.display="",a.remove()};a.addEventListener("keydown",i=>{i.stopPropagation(),i.key==="Enter"?c():i.key==="Escape"&&(o.textContent=s,o.style.display="",a.remove())}),a.addEventListener("blur",c),a.addEventListener("click",i=>i.stopPropagation()),o.style.display="none",o.parentElement?.insertBefore(a,o.nextSibling),a.focus(),a.select()}function ie(e,t){const n=e.querySelector(".agent-dot"),o=e.querySelector(".status-badge"),s=e.querySelector(".card-uptime"),a=e.querySelector(".agent-name");n&&(n.className=`agent-dot ${t.status}`),o&&(o.className=`status-badge ${t.status}`,o.textContent=t.status),s&&(s.textContent=K(Date.now()-t.connectedAt)),a&&!a.style.display&&(a.textContent=t.name||t.agent);const c=t.status==="attention";o&&(o.style.display=c?"none":"");const i=e.querySelector(".attention-badge");i&&(i.style.display=c?"":"none"),t.status==="attention"?e.classList.add("attention"):e.classList.remove("attention")}function ge(e,t){const n=e.querySelector(".card-preview-text");n&&(t.length>0?(n.textContent=t.join(`
|
|
2
|
-
`),n.classList.remove("empty")):(n.textContent="Waiting for output...",n.classList.add("empty")))}function Ee(e,t){const n=e.querySelector(".card-metadata");if(!n)return;for(;n.firstChild;)n.removeChild(n.firstChild);const o=[["PID",String(t.pid)],["Agent",t.agent],["Port",String(t.port)],["Directory",t.cwd],["Memory",pe(t.memoryKB)],["Uptime",K(t.uptimeMs)]];for(const[s,a]of o){const c=document.createElement("div");c.className="meta-row";const i=document.createElement("span");i.className="meta-label",i.textContent=s;const f=document.createElement("span");f.className="meta-value",f.textContent=a,c.appendChild(i),c.appendChild(f),n.appendChild(c)}n.classList.toggle("hidden")}let r=null,Q=!1;function ve(){if(!Q){Q=!0;try{r=new AudioContext,r.state==="suspended"&&r.resume()}catch{}}}function Z(){if(!r)return;r.state==="suspended"&&r.resume();const e=r.currentTime,t=r.createOscillator(),n=r.createGain();t.frequency.value=587.33,t.type="sine",n.gain.setValueAtTime(.3,e),n.gain.exponentialRampToValueAtTime(.01,e+.3),t.connect(n),n.connect(r.destination),t.start(e),t.stop(e+.3);const o=r.createOscillator(),s=r.createGain();o.frequency.value=880,o.type="sine",s.gain.setValueAtTime(.3,e+.15),s.gain.exponentialRampToValueAtTime(.01,e+.45),o.connect(s),s.connect(r.destination),o.start(e+.15),o.stop(e+.45)}const ee=120*1e3,p=new Map;function te(e){if(p.has(e))return;Z();const t=setTimeout(function n(){Z();const o=p.get(e);o&&(o.timerId=setTimeout(n,ee))},ee);p.set(e,{timerId:t})}function W(e){const t=p.get(e);t&&(clearTimeout(t.timerId),p.delete(e))}function ne(){for(const e of p.values())clearTimeout(e.timerId);p.clear()}const Ce=new URLSearchParams(window.location.search),O=Ce.get("token");if(!O)throw document.body.textContent="Missing authentication token.",new Error("No token in URL");const be=window.location.protocol==="https:"?"wss:":"ws:",we=`${be}//${window.location.host}?token=${O}`,re=window.location.hostname,E=new Map,u=new Map,Le=document.getElementById("session-list"),_=document.getElementById("empty-state"),Ne=document.getElementById("session-count"),oe=document.getElementById("status-dot");let V=null;function $(){ve(),document.removeEventListener("click",$),document.removeEventListener("touchstart",$)}document.addEventListener("click",$);document.addEventListener("touchstart",$);function C(e){d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(e))}const Se={onOpen(e){const t=E.get(e.id)||e;t.status==="attention"&&(C({type:"clear-attention",sessionId:t.id}),W(t.id));const n=window.location.href,o=`http://${re}:${t.port}?token=${t.token}&hub=${encodeURIComponent(n)}`;window.location.href=o},onStop(e){C({type:"stop-session",sessionId:e})},onRename(e,t){C({type:"rename-session",sessionId:e,name:t})},onInfo(e){C({type:"get-metadata",sessionId:e})}};function de(){const e=E.size;Ne.textContent=`${e} session${e!==1?"s":""}`,e===0?_.style.display="flex":_.style.display="none"}function se(e){E.set(e.id,e);const t=fe(e,re,Se);u.set(e.id,t),Le.insertBefore(t,_),de()}function ae(e){E.delete(e);const t=u.get(e);t&&(t.remove(),u.delete(e)),de()}function Ie(e){E.set(e.id,e);const t=u.get(e.id);t&&ie(t,e)}function ke(){for(const[e,t]of E){const n=u.get(e);n&&ie(n,t)}}const Be=document.getElementById("fab-create"),b=document.getElementById("create-modal"),xe=document.getElementById("modal-close"),g=document.getElementById("tool-input"),ce=document.getElementById("tool-chips"),le=document.getElementById("dir-selected"),Pe=document.getElementById("btn-browse"),me=document.getElementById("btn-create-session"),M=document.getElementById("create-error"),v=document.getElementById("create-form-view"),T=document.getElementById("browse-view"),F=document.getElementById("browse-breadcrumb"),y=document.getElementById("browse-list"),$e=document.getElementById("browse-back"),Me=document.getElementById("browse-select"),G=document.getElementById("create-spinner");let w="~",j="~";function m(e,t,n){const o=document.createElement(e);return o.className=t,o.textContent=n,o}function Ae(){b.classList.remove("hidden"),v.classList.remove("hidden"),T.classList.add("hidden"),G.classList.add("hidden"),M.classList.add("hidden"),g.value="",w="~",le.textContent="~",Y(),Oe(),g.focus()}function J(){b.classList.add("hidden")}function Y(){me.disabled=!g.value.trim()}async function Oe(){try{const t=await(await fetch(`/api/tool-history?token=${O}`)).json();ce.replaceChildren();for(const n of t.tools.slice(0,6)){const o=m("span","chip",n);o.addEventListener("click",()=>{g.value=n,Y()}),ce.appendChild(o)}}catch{}}async function z(e){j=e,y.replaceChildren(m("div","browse-empty","Loading..."));try{const n=await(await fetch(`/api/browse?path=${encodeURIComponent(e)}&token=${O}`)).json();if(n.error){y.replaceChildren(m("div","browse-empty",n.error));return}const o=n.path||e;j=o,Te(o);const s=n.entries;if(s.length===0){y.replaceChildren(m("div","browse-empty","No subdirectories"));return}y.replaceChildren();for(const a of s){const c=document.createElement("div");c.className="browse-item",c.appendChild(m("span","browse-item-name",a)),c.appendChild(m("span","browse-item-arrow","›")),c.addEventListener("click",()=>z(`${o}/${a}`)),y.appendChild(c)}}catch{y.replaceChildren(m("div","browse-empty","Failed to load"))}}function Te(e){F.replaceChildren();const t=e.split("/").filter(Boolean);for(let n=0;n<t.length;n++){n>0&&F.appendChild(m("span","breadcrumb-sep"," / "));const o=m("span","breadcrumb-segment",t[n]),s=t.slice(0,n+1).join("/");o.addEventListener("click",()=>z(s)),F.appendChild(o)}}function Re(){const e=g.value.trim();e&&(M.classList.add("hidden"),v.classList.add("hidden"),G.classList.remove("hidden"),C({type:"create-session",tool:e,cwd:w}))}Be.addEventListener("click",Ae);xe.addEventListener("click",J);b.addEventListener("click",e=>{e.target===b&&J()});g.addEventListener("input",Y);me.addEventListener("click",Re);Pe.addEventListener("click",()=>{v.classList.add("hidden"),T.classList.remove("hidden"),z(w)});$e.addEventListener("click",()=>{T.classList.add("hidden"),v.classList.remove("hidden")});Me.addEventListener("click",()=>{w=j,le.textContent=w,T.classList.add("hidden"),v.classList.remove("hidden")});let d=null,A=0;const qe=1e4;function H(){d=new WebSocket(we),d.onopen=()=>{oe.className="connected",A=0,V&&clearInterval(V),V=setInterval(ke,1e4)},d.onmessage=e=>{try{const t=JSON.parse(e.data);switch(t.type){case"sessions":{ne();for(const n of u.keys())ae(n);for(const n of t.sessions)se(n),n.status==="attention"&&te(n.id);break}case"session-added":{se(t.session),b.classList.contains("hidden")||J();break}case"session-removed":{const n=t.sessionId;W(n),ae(n);break}case"session-updated":{const n=t.session;Ie(n),n.status==="attention"?te(n.id):W(n.id);break}case"preview":{const n=u.get(t.sessionId);n&&ge(n,t.lines);break}case"metadata":{const n=u.get(t.sessionId);n&&Ee(n,t.metadata);break}case"session-creating":break;case"session-create-error":{G.classList.add("hidden"),v.classList.remove("hidden"),M.textContent=t.error,M.classList.remove("hidden");break}case"operation-error":{console.warn(`Operation "${t.operation}" failed for session ${t.sessionId}: ${t.error}`);break}}}catch{}},d.onclose=()=>{oe.className="reconnecting",ne(),Ue()},d.onerror=()=>{d?.close()}}function Ue(){const e=Math.min(1e3*Math.pow(1.5,A),qe);A++,setTimeout(H,e)}document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&d?.readyState!==WebSocket.OPEN&&(A=0,H())});H();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*{margin:0;padding:0;box-sizing:border-box}html,body{height:100%;width:100%;background:#1a1a2e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;color:#e0e0e0;overflow-x:hidden;-webkit-overflow-scrolling:touch}#header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#16213e;border-bottom:1px solid #0f3460;position:sticky;top:0;z-index:10}.header-left{display:flex;align-items:center;gap:10px}.logo{font-size:16px;font-weight:700;color:#e94560;letter-spacing:-.5px}#status-dot{width:8px;height:8px;border-radius:50%;background:#e74c3c;transition:background .3s ease}#status-dot.connected{background:#2ecc71}#status-dot.reconnecting{background:#f39c12;animation:pulse 1s infinite}#session-count{font-size:13px;color:#a0a0b0}#session-list{padding:12px 12px 80px;display:flex;flex-direction:column;gap:12px}#empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;color:#606080;text-align:center;gap:8px}#empty-state .empty-icon{font-size:48px;margin-bottom:8px;opacity:.5}#empty-state p{font-size:16px}#empty-state .empty-hint{font-size:13px;color:#505070}#empty-state code{background:#252540;padding:2px 8px;border-radius:4px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:12px;color:#e94560}.session-card{background:#16213e;border:1px solid #0f3460;border-radius:12px;padding:14px 16px;cursor:pointer;transition:transform .15s ease,border-color .2s ease;-webkit-tap-highlight-color:transparent}.session-card:active{transform:scale(.98)}.session-card:hover{border-color:#e94560}.session-card.attention{border-color:#e94560;animation:attention-glow 2s ease-in-out infinite}@keyframes attention-glow{0%,to{box-shadow:0 0 #e9456000}50%{box-shadow:0 0 12px 2px #e945604d}}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.card-agent{display:flex;align-items:center;gap:8px}.agent-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.agent-dot.active{background:#2ecc71}.agent-dot.idle{background:#f39c12}.agent-dot.attention{background:#e94560;animation:pulse 1s infinite}.agent-name{font-size:15px;font-weight:600;color:#f0f0f0}.card-uptime{font-size:12px;color:#707090;font-variant-numeric:tabular-nums}.card-cwd{font-size:12px;color:#808098;margin-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.card-preview{background:#112;border-radius:6px;padding:8px 10px;margin-bottom:10px;overflow:hidden;min-height:24px;max-height:90px}.card-preview-text{font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:11px;line-height:1.4;color:#a0a0b0;white-space:pre;overflow:hidden;text-overflow:ellipsis;margin:0}.card-preview-text.empty{color:#505070;font-style:italic}.card-status{display:flex;align-items:center;gap:6px;font-size:12px;color:#a0a0b0}.status-badge{padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500;text-transform:uppercase;letter-spacing:.5px}.status-badge.active{background:#2ecc7126;color:#2ecc71}.status-badge.idle{background:#f39c1226;color:#f39c12}.status-badge.attention{background:#e9456026;color:#e94560}.attention-badge{padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;background:#e9456033;color:#e94560;animation:attention-pulse 2s ease-in-out infinite}@keyframes attention-pulse{0%,to{opacity:1}50%{opacity:.6}}.card-actions{display:flex;gap:6px;margin-top:10px;padding-top:10px;border-top:1px solid #0f3460}.action-btn{flex:1;padding:6px 0;border:1px solid #2a2a44;border-radius:6px;background:#1e1e36;color:#a0a0b0;font-size:12px;font-weight:500;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s,color .15s}.action-btn:active{background:#2a2a44}.action-btn.open{color:#2ecc71;border-color:#2ecc714d}.action-btn.stop{color:#e94560;border-color:#e945604d}.action-btn.stop:active{background:#e9456026}.confirm-overlay{display:flex;align-items:center;justify-content:center;gap:10px;padding:10px;margin-top:8px;background:#2d1810;border:1px solid #e94560;border-radius:8px;animation:fadeIn .15s ease}.confirm-msg{font-size:13px;color:#f0f0f0;flex:1}.confirm-btn{padding:5px 14px;border:none;border-radius:5px;font-size:12px;font-weight:600;font-family:inherit;cursor:pointer}.confirm-btn.yes{background:#e94560;color:#fff}.confirm-btn.no{background:#2a2a44;color:#a0a0b0}.rename-input{background:#112;border:1px solid #e94560;border-radius:4px;color:#f0f0f0;font-size:15px;font-weight:600;font-family:inherit;padding:2px 6px;outline:none;width:120px}.card-metadata{margin-top:8px;padding:8px 10px;background:#112;border-radius:6px;animation:fadeIn .2s ease}.card-metadata.hidden{display:none}.meta-row{display:flex;justify-content:space-between;padding:3px 0;font-size:11px}.meta-label{color:#707090;font-weight:500}.meta-value{color:#c0c0d0;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;font-size:11px;text-align:right;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(min-width:768px){#session-list{max-width:600px;margin:0 auto}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.session-card{animation:fadeIn .3s ease}#reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:#1a1a2ef2;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:100;color:#e0e0e0;font-size:16px;gap:12px}#reconnect-overlay .spinner{width:32px;height:32px;border:3px solid #0f3460;border-top-color:#e94560;border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}#fab-create{position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;background:#e94560;color:#fff;font-size:28px;font-weight:300;border:none;cursor:pointer;box-shadow:0 4px 16px #e9456066;z-index:20;-webkit-tap-highlight-color:transparent;transition:transform .15s,box-shadow .15s;display:flex;align-items:center;justify-content:center;line-height:1}#fab-create:active{transform:scale(.92)}.modal-overlay{position:fixed;inset:0;background:#0a0a14d9;z-index:50;display:flex;align-items:flex-end;justify-content:center;animation:fadeIn .15s ease}.modal-overlay.hidden{display:none}.modal-content{background:#16213e;border-radius:16px 16px 0 0;width:100%;max-width:480px;max-height:85vh;overflow-y:auto;padding:20px;animation:slideUp .2s ease}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.modal-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px}.modal-title{font-size:18px;font-weight:600;color:#f0f0f0}.modal-close{background:none;border:none;color:#707090;font-size:24px;cursor:pointer;padding:4px 8px;line-height:1}.form-label{display:block;font-size:13px;font-weight:500;color:#a0a0b0;margin-bottom:6px;margin-top:16px}.form-label:first-of-type{margin-top:0}.form-input{width:100%;padding:10px 12px;background:#112;border:1px solid #2a2a44;border-radius:8px;color:#f0f0f0;font-size:15px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;outline:none;transition:border-color .15s}.form-input:focus{border-color:#e94560}.form-input.hidden{display:none}.chip-row{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}.chip{padding:5px 12px;background:#1e1e36;border:1px solid #2a2a44;border-radius:16px;font-size:12px;color:#c0c0d0;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s,border-color .15s;white-space:nowrap;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.chip:active,.chip.selected{background:#e9456026;border-color:#e94560;color:#e94560}.dir-display{padding:10px 12px;background:#112;border:1px solid #2a2a44;border-radius:8px;font-size:13px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;color:#c0c0d0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dir-actions{display:flex;gap:8px;margin-top:10px}.dir-action-btn{flex:1;padding:8px 0;background:#1e1e36;border:1px solid #2a2a44;border-radius:8px;color:#a0a0b0;font-size:13px;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s}.dir-action-btn:active{background:#2a2a44}.btn-create{width:100%;margin-top:20px;padding:14px;background:#e94560;color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:opacity .15s}.btn-create:disabled{opacity:.4;cursor:default}.btn-create:not(:disabled):active{opacity:.8}.create-error{margin-top:12px;padding:8px 12px;background:#e9456026;border-radius:6px;font-size:13px;color:#e94560}.create-error.hidden{display:none}.create-spinner{display:flex;flex-direction:column;align-items:center;gap:12px;padding:32px 0;color:#a0a0b0;font-size:14px}.create-spinner.hidden{display:none}.browse-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.browse-back{background:none;border:none;color:#a0a0b0;font-size:14px;font-family:inherit;cursor:pointer;padding:4px 0}.browse-select{padding:6px 14px;background:#e94560;color:#fff;border:none;border-radius:6px;font-size:13px;font-weight:500;font-family:inherit;cursor:pointer}.browse-breadcrumb{display:flex;gap:4px;align-items:center;margin-bottom:12px;font-size:13px;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace;color:#808098;flex-wrap:wrap}.breadcrumb-segment{cursor:pointer;color:#a0a0b0;transition:color .15s}.breadcrumb-segment:hover,.breadcrumb-segment:active{color:#e94560}.breadcrumb-sep{color:#505070}.browse-list{display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto}.browse-item{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;background:#112;border-radius:6px;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .1s}.browse-item:active{background:#1e1e36}.browse-item-name{font-size:14px;color:#d0d0e0;font-family:Cascadia Code,Fira Code,JetBrains Mono,monospace}.browse-item-arrow{color:#505070;font-size:14px}.browse-empty{text-align:center;padding:24px;color:#505070;font-size:13px}.hidden{display:none!important}
|