aicodeman 0.9.5 → 0.9.6
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/web/public/api-client.3adebdc2.js.gz +0 -0
- package/dist/web/public/app.c860ea08.js.gz +0 -0
- package/dist/web/public/constants.5b68d2de.js.gz +0 -0
- package/dist/web/public/image-input.7cade6a8.js.gz +0 -0
- package/dist/web/public/index.html +1 -1
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.88082175.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.cdfd8c04.js.gz +0 -0
- package/dist/web/public/mobile-handlers.1e2a8ef8.js.gz +0 -0
- package/dist/web/public/mobile.26dc30d6.css.gz +0 -0
- package/dist/web/public/notification-manager.9c984ac2.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/panels-ui.5192a2c0.js.gz +0 -0
- package/dist/web/public/ralph-panel.61076370.js.gz +0 -0
- package/dist/web/public/ralph-wizard.52d533d2.js.gz +0 -0
- package/dist/web/public/respawn-ui.5377f958.js.gz +0 -0
- package/dist/web/public/session-ui.3e0cf024.js.gz +0 -0
- package/dist/web/public/{settings-ui.da0621e1.js → settings-ui.2b70e2c8.js} +1 -1
- package/dist/web/public/settings-ui.2b70e2c8.js.br +0 -0
- package/dist/web/public/settings-ui.2b70e2c8.js.gz +0 -0
- package/dist/web/public/styles.e87cb785.css.gz +0 -0
- package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.37caa926.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/package.json +1 -1
- package/dist/web/public/settings-ui.da0621e1.js.br +0 -0
- package/dist/web/public/settings-ui.da0621e1.js.gz +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1845,7 +1845,7 @@
|
|
|
1845
1845
|
<script defer src="respawn-ui.5377f958.js"></script>
|
|
1846
1846
|
<script defer src="ralph-panel.61076370.js"></script>
|
|
1847
1847
|
<script defer src="orchestrator-panel.js"></script>
|
|
1848
|
-
<script defer src="settings-ui.
|
|
1848
|
+
<script defer src="settings-ui.2b70e2c8.js"></script>
|
|
1849
1849
|
<script defer src="panels-ui.5192a2c0.js"></script>
|
|
1850
1850
|
<script defer src="session-ui.3e0cf024.js"></script>
|
|
1851
1851
|
<script defer src="ralph-wizard.52d533d2.js"></script>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.assign(CodemanApp.prototype,{_onHookIdlePrompt(e){e.sessionId&&this.setPendingHook(e.sessionId,"idle_prompt"),this._notifySession(e.sessionId,"warning","hook-idle","Waiting for Input",e.message||"Claude is idle and waiting for a prompt")},_onHookPermissionPrompt(e){e.sessionId&&this.setPendingHook(e.sessionId,"permission_prompt");const t=e.tool?`${e.tool}${e.command?": "+e.command:e.file?": "+e.file:""}`:"";this._notifySession(e.sessionId,"critical","hook-permission","Permission Required",t||"Claude needs tool approval to continue")},_onHookElicitationDialog(e){e.sessionId&&this.setPendingHook(e.sessionId,"elicitation_dialog"),this._notifySession(e.sessionId,"critical","hook-elicitation","Question Asked",e.question||"Claude is asking a question and waiting for your answer")},_onHookStop(e){e.sessionId&&this.clearPendingHooks(e.sessionId),this._notifySession(e.sessionId,"info","hook-stop","Response Complete",e.reason||"Claude has finished responding")},_onHookTeammateIdle(e){const t=this.sessions.get(e.sessionId);this._notifySession(e.sessionId,"warning","hook-teammate-idle","Teammate Idle",`A teammate is idle in ${t?.name||e.sessionId}`)},_onHookTaskCompleted(e){const t=this.sessions.get(e.sessionId);this._notifySession(e.sessionId,"info","hook-task-completed","Task Completed",`A team task completed in ${t?.name||e.sessionId}`)},_onTunnelStarted(e){console.log("[Tunnel] Started:",e.url),this._tunnelUrl=e.url,this._dismissTunnelConnecting(),this._updateTunnelUrlDisplay(e.url),this._updateTunnelIndicator(!0),document.getElementById("welcomeOverlay")?.classList.contains("visible")?(this._updateWelcomeTunnelBtn(!0,e.url,!0),this.showToast("Tunnel active","success")):(this._updateWelcomeTunnelBtn(!0,e.url),this.showToast(`Tunnel active: ${e.url}`,"success"),this.showTunnelQR())},_onTunnelStopped(){console.log("[Tunnel] Stopped"),this._tunnelUrl=null,this._dismissTunnelConnecting(),this._updateTunnelUrlDisplay(null),this._updateWelcomeTunnelBtn(!1),this._updateTunnelIndicator(!1),this.closeTunnelPanel(),this.closeTunnelQR()},_onTunnelProgress(e){console.log("[Tunnel] Progress:",e.message);const t=document.getElementById("tunnelConnectingToast");t&&(t.innerHTML=`<span class="tunnel-spinner"></span> ${e.message}`);const n=document.getElementById("welcomeTunnelBtn");n?.classList.contains("connecting")&&(n.innerHTML=`<span class="tunnel-spinner"></span> ${e.message}`)},_onTunnelError(e){console.warn("[Tunnel] Error:",e.message),this._dismissTunnelConnecting(),this.showToast(`Tunnel error: ${e.message}`,"error");const t=document.getElementById("welcomeTunnelBtn");t&&(t.disabled=!1,t.classList.remove("connecting"))},_onTunnelQrRotated(e){if(e.svg){const t=document.getElementById("tunnelQrContainer");t&&(t.innerHTML=e.svg);const n=document.getElementById("welcomeQrInner");n&&(n.innerHTML=e.svg)}else this._refreshTunnelQrFromApi();this._resetQrCountdown()},_onTunnelQrRegenerated(e){if(e.svg){const t=document.getElementById("tunnelQrContainer");t&&(t.innerHTML=e.svg);const n=document.getElementById("welcomeQrInner");n&&(n.innerHTML=e.svg)}else this._refreshTunnelQrFromApi();this._resetQrCountdown()},_onTunnelQrAuthUsed(e){const n=(e.ua||"Unknown device").match(/Chrome|Firefox|Safari|Edge|Mobile/)?.[0]||"Browser";this.showToast(`Device authenticated via QR (${n}, ${e.ip}). Not you?`,"warning",{duration:1e4,action:{label:"Revoke All",onClick:()=>{fetch("/api/auth/revoke",{method:"POST",headers:{"Content-Type":"application/json"},body:"{}"}).then(()=>this.showToast("All sessions revoked","success")).catch(()=>this.showToast("Failed to revoke sessions","error"))}}})},registerServiceWorker(){"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(e=>{this._swRegistration=e,navigator.serviceWorker.addEventListener("message",t=>{if(t.data?.type==="notification-click"){const{sessionId:n}=t.data;n&&this.sessions.has(n)&&this.selectSession(n),window.focus()}}),e.pushManager.getSubscription().then(t=>{t&&(this._pushSubscription=t,this._updatePushUI(!0))})}).catch(()=>{})},async subscribeToPush(){if(!this._swRegistration){this.showToast("Service worker not available. HTTPS or localhost required.","error");return}try{const e=await this._apiJson("/api/push/vapid-key");if(!e?.success)throw new Error("Failed to get VAPID key");const t=urlBase64ToUint8Array(e.data.publicKey),n=await this._swRegistration.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:t}),s=n.toJSON(),o=await this._apiJson("/api/push/subscribe",{method:"POST",body:{endpoint:s.endpoint,keys:s.keys,userAgent:navigator.userAgent,pushPreferences:this._buildPushPreferences()}});if(!o?.success)throw new Error("Failed to register subscription");this._pushSubscription=n,this._pushSubscriptionId=o.data.id,localStorage.setItem("codeman-push-subscription-id",o.data.id),this._updatePushUI(!0),this.showToast("Push notifications enabled","success")}catch(e){this.showToast("Push subscription failed: "+(e.message||e),"error")}},async unsubscribeFromPush(){try{this._pushSubscription&&await this._pushSubscription.unsubscribe();const e=this._pushSubscriptionId||localStorage.getItem("codeman-push-subscription-id");e&&await fetch(`/api/push/subscribe/${e}`,{method:"DELETE"}).catch(()=>{}),this._pushSubscription=null,this._pushSubscriptionId=null,localStorage.removeItem("codeman-push-subscription-id"),this._updatePushUI(!1),this.showToast("Push notifications disabled","success")}catch(e){this.showToast("Failed to unsubscribe: "+(e.message||e),"error")}},async togglePushSubscription(){this._pushSubscription?await this.unsubscribeFromPush():await this.subscribeToPush()},async _syncPushPreferences(){const e=this._pushSubscriptionId||localStorage.getItem("codeman-push-subscription-id");if(e)try{await fetch(`/api/push/subscribe/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({pushPreferences:this._buildPushPreferences()})})}catch{}},_buildPushPreferences(){const e={},t={"hook:permission_prompt":"eventPermissionPush","hook:elicitation_dialog":"eventQuestionPush","hook:idle_prompt":"eventIdlePush","hook:stop":"eventStopPush","respawn:blocked":"eventRespawnPush","session:ralphCompletionDetected":"eventRalphPush"};for(const[n,s]of Object.entries(t)){const o=document.getElementById(s);e[n]=o?o.checked:!0}return e["session:error"]=!0,e},_updatePushUI(e){const t=document.getElementById("pushSubscribeBtn"),n=document.getElementById("pushSubscriptionStatus");t&&(t.textContent=e?"Unsubscribe":"Subscribe"),n&&(n.textContent=e?"active":"off",n.classList.remove("granted","denied"),e&&n.classList.add("granted"))},openAppSettings(){const e=this.loadAppSettingsFromStorage();document.getElementById("appSettingsClaudeMdPath").value=e.defaultClaudeMdPath||"",document.getElementById("appSettingsDefaultDir").value=e.defaultWorkingDir||"";const t=this.getDefaultSettings();document.getElementById("appSettingsRalphEnabled").checked=e.ralphTrackerEnabled??t.ralphTrackerEnabled??!1,document.getElementById("appSettingsShowFontControls").checked=e.showFontControls??t.showFontControls??!1,document.getElementById("appSettingsShowSystemStats").checked=e.showSystemStats??t.showSystemStats??!0,document.getElementById("appSettingsShowTokenCount").checked=e.showTokenCount??t.showTokenCount??!0,document.getElementById("appSettingsShowCost").checked=e.showCost??t.showCost??!1,document.getElementById("appSettingsShowLifecycleLog").checked=e.showLifecycleLog??t.showLifecycleLog??!0,document.getElementById("appSettingsShowMonitor").checked=e.showMonitor??t.showMonitor??!0,document.getElementById("appSettingsShowProjectInsights").checked=e.showProjectInsights??t.showProjectInsights??!1,document.getElementById("appSettingsShowFileBrowser").checked=e.showFileBrowser??t.showFileBrowser??!1,document.getElementById("appSettingsShowSubagents").checked=e.showSubagents??t.showSubagents??!1,document.getElementById("appSettingsShowMultiMonitorButton").checked=e.showMultiMonitorButton??t.showMultiMonitorButton??!1;const n=document.getElementById("appSettingsGestureControlItem");n&&(n.style.display=window.__codemanGestureAvailable?"":"none"),document.getElementById("appSettingsGestureControl").checked=e.gestureControlEnabled??t.gestureControlEnabled??!1,document.getElementById("appSettingsSubagentTracking").checked=e.subagentTrackingEnabled??t.subagentTrackingEnabled??!0,document.getElementById("appSettingsSubagentActiveTabOnly").checked=e.subagentActiveTabOnly??t.subagentActiveTabOnly??!0,document.getElementById("appSettingsImageWatcherEnabled").checked=e.imageWatcherEnabled??t.imageWatcherEnabled??!1,document.getElementById("appSettingsTunnelEnabled").checked=e.tunnelEnabled??!1,this.loadTunnelStatus(),document.getElementById("appSettingsLocalEcho").checked=e.localEchoEnabled??MobileDetection.isTouchDevice(),document.getElementById("appSettingsCjkInput").checked=e.cjkInputEnabled??!1,document.getElementById("appSettingsExtendedKeyboardBar").checked=e.extendedKeyboardBar??!1,document.getElementById("appSettingsTabTwoRows").checked=e.tabTwoRows??t.tabTwoRows??!1;const s=document.getElementById("appSettingsClaudeMode"),o=document.getElementById("allowedToolsRow");s.value=e.claudeMode||"dangerously-skip-permissions",document.getElementById("appSettingsAllowedTools").value=e.allowedTools||"",o.style.display=s.value==="allowedTools"?"":"none",s.onchange=()=>{o.style.display=s.value==="allowedTools"?"":"none"},document.getElementById("appSettingsAgentTeams").checked=e.agentTeamsEnabled??!1,document.getElementById("appSettingsOpusContext1m").checked=e.opusContext1mEnabled??!1,document.getElementById("appSettingsThinkingEffort").value=e.thinkingEffort??"";const i=e.nice||{};document.getElementById("appSettingsNiceEnabled").checked=i.enabled??!1,document.getElementById("appSettingsNiceValue").value=i.niceValue??10,this.loadModelConfigForSettings();const a=this.notificationManager?.preferences||{};document.getElementById("appSettingsNotifEnabled").checked=a.enabled??!0,document.getElementById("appSettingsNotifBrowser").checked=a.browserNotifications??!1,document.getElementById("appSettingsNotifAudio").checked=a.audioAlerts??!1,document.getElementById("appSettingsNotifStuckMins").value=Math.round((a.stuckThresholdMs||6e5)/6e4),document.getElementById("appSettingsNotifCritical").checked=!a.muteCritical,document.getElementById("appSettingsNotifWarning").checked=!a.muteWarning,document.getElementById("appSettingsNotifInfo").checked=!a.muteInfo,document.getElementById("appSettingsPushEnabled").checked=!!this._pushSubscription,this._updatePushUI(!!this._pushSubscription);const l=a.eventTypes||{},c=l.permission_prompt||{};document.getElementById("eventPermissionEnabled").checked=c.enabled??!0,document.getElementById("eventPermissionBrowser").checked=c.browser??!0,document.getElementById("eventPermissionPush").checked=c.push??!1,document.getElementById("eventPermissionAudio").checked=c.audio??!0;const d=l.elicitation_dialog||{};document.getElementById("eventQuestionEnabled").checked=d.enabled??!0,document.getElementById("eventQuestionBrowser").checked=d.browser??!0,document.getElementById("eventQuestionPush").checked=d.push??!1,document.getElementById("eventQuestionAudio").checked=d.audio??!0;const r=l.idle_prompt||{};document.getElementById("eventIdleEnabled").checked=r.enabled??!0,document.getElementById("eventIdleBrowser").checked=r.browser??!0,document.getElementById("eventIdlePush").checked=r.push??!1,document.getElementById("eventIdleAudio").checked=r.audio??!1;const u=l.stop||{};document.getElementById("eventStopEnabled").checked=u.enabled??!0,document.getElementById("eventStopBrowser").checked=u.browser??!1,document.getElementById("eventStopPush").checked=u.push??!1,document.getElementById("eventStopAudio").checked=u.audio??!1;const p=l.respawn_cycle||{};document.getElementById("eventRespawnEnabled").checked=p.enabled??!0,document.getElementById("eventRespawnBrowser").checked=p.browser??!1,document.getElementById("eventRespawnPush").checked=p.push??!1,document.getElementById("eventRespawnAudio").checked=p.audio??!1;const m=l.ralph_complete||{};document.getElementById("eventRalphEnabled").checked=m.enabled??!0,document.getElementById("eventRalphBrowser").checked=m.browser??!0,document.getElementById("eventRalphPush").checked=m.push??!1,document.getElementById("eventRalphAudio").checked=m.audio??!0;const h=l.subagent_spawn||{};document.getElementById("eventSubagentEnabled").checked=h.enabled??!1,document.getElementById("eventSubagentBrowser").checked=h.browser??!1,document.getElementById("eventSubagentPush").checked=h.push??!1,document.getElementById("eventSubagentAudio").checked=h.audio??!1;const f=document.getElementById("notifPermissionStatus");if(f&&typeof Notification<"u"){const g=Notification.permission;f.textContent=g==="granted"?"\u2713":g==="denied"?"\u2717":"?",f.classList.remove("granted","denied"),g==="granted"?f.classList.add("granted"):g==="denied"&&f.classList.add("denied")}const y=VoiceInput._getDeepgramConfig();document.getElementById("voiceDeepgramKey").value=y.apiKey||"",document.getElementById("voiceLanguage").value=y.language||"en-US",document.getElementById("voiceKeyterms").value=y.keyterms||"refactor, endpoint, middleware, callback, async, regex, TypeScript, npm, API, deploy, config, linter, env, webhook, schema, CLI, JSON, CSS, DOM, SSE, backend, frontend, localhost, dependencies, repository, merge, rebase, diff, commit, com",document.getElementById("voiceInsertMode").value=y.insertMode||"direct";const S=document.getElementById("voiceDeepgramKey");S.type="password",document.getElementById("voiceKeyToggleBtn").textContent="Show";const w=VoiceInput.getActiveProviderName(),v=document.getElementById("voiceProviderStatus");v.textContent=w,v.className="voice-provider-status"+(w.startsWith("Deepgram")?" active":""),this._initUpdatesSection(),this.switchSettingsTab("settings-display");const b=document.getElementById("appSettingsModal");b.querySelectorAll(".modal-tabs .modal-tab-btn").forEach(g=>{g.onclick=()=>this.switchSettingsTab(g.dataset.tab)}),b.classList.add("active"),this.activeFocusTrap=new FocusTrap(b),this.activeFocusTrap.activate()},switchSettingsTab(e){const t=document.getElementById("appSettingsModal");t.querySelectorAll(".modal-tabs .modal-tab-btn").forEach(n=>{n.classList.toggle("active",n.dataset.tab===e)}),t.querySelectorAll(".modal-tab-content").forEach(n=>{n.classList.toggle("hidden",n.id!==e)})},closeAppSettings(){document.getElementById("appSettingsModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},_updatePhaseText(e){return{queued:"Queued\u2026",preparing:"Preparing\u2026",stashing:"Stashing local changes\u2026",fetching:"Fetching release\u2026",checkout:"Checking out release\u2026",installing:"Installing dependencies\u2026",building:"Building\u2026",restarting:"Restarting Codeman\u2026"}[e]||e},_initUpdatesSection(){const e=this.$("updateCurrentVersion");e&&(e.textContent=(this.$("versionDisplay")?.textContent||"").trim()||"\u2014");for(const t of["updateResult","updateActionRow","updateNotes","updateProgress"]){const n=this.$(t);n&&(n.style.display="none")}this._updateCheck=null},_setUpdateResult(e){const t=this.$("updateResult");t&&(t.style.display="block",t.innerHTML=e)},_setUpdateProgress(e){const t=this.$("updateProgress");t&&(t.style.display="block",t.innerHTML=e)},async checkForUpdate(){const e=this.$("updateCheckBtn");e&&(e.disabled=!0,e.textContent="Checking\u2026");const t=await this._apiJson("/api/system/update/check");e&&(e.disabled=!1,e.textContent="Check now");const n=this.$("updateActionRow"),s=this.$("updateNotes");if(n&&(n.style.display="none"),s&&(s.style.display="none"),!t){this._setUpdateResult("Could not check for updates. Try again later.");return}this._updateCheck=t;const o=this.$("updateCurrentVersion");if(o&&t.currentVersion&&(o.textContent=`v${t.currentVersion}`),t.installKind&&t.installKind!=="git"){this._setUpdateResult(`This install can't update itself (${escapeHtml(t.installKind)}). Update with <code>npm i -g aicodeman@latest</code>.`);return}if(t.selfUpdateEnabled===!1){this._setUpdateResult("In-app updates are disabled on this server (CODEMAN_DISABLE_SELF_UPDATE=1).");return}if(t.error&&!t.updateAvailable){this._setUpdateResult(escapeHtml(t.error));return}if(t.updateAvailable&&t.latestVersion){this._setUpdateResult(`Update available: <strong>v${escapeHtml(t.latestVersion)}</strong> (current v${escapeHtml(t.currentVersion||"")})`);const i=this.$("updateActionLabel");i&&(i.textContent=`Update to v${t.latestVersion}`),n&&(n.style.display="flex");const a=this.$("updateNowBtn");a&&(a.disabled=!1,a.textContent="Update now"),s&&t.notes&&(s.style.display="block",s.textContent=t.notes)}else this._setUpdateResult(`You're up to date (v${escapeHtml(t.currentVersion||"")}).`)},async startSelfUpdate(){const e=this._updateCheck?.latestVersion?`v${this._updateCheck.latestVersion}`:"the latest release";if(!confirm(`Update Codeman to ${e}? The server will restart and this page will reload.`))return;const t=this.$("updateNowBtn");t&&(t.disabled=!0,t.textContent="Starting\u2026");const n=await this._apiPost("/api/system/update",{});if(!n||!n.ok){let i="Failed to start the update.";try{const a=await n.json();a?.error?.message&&(i=a.error.message)}catch{}this._setUpdateProgress(`<span style="color:var(--danger,#e5534b)">${escapeHtml(i)}</span>`),t&&(t.disabled=!1,t.textContent="Update now");return}const s=this.$("updateActionRow");s&&(s.style.display="none");const o=this.$("updateNotes");o&&(o.style.display="none"),this._setUpdateProgress("Starting update\u2026"),this._pollUpdateStatus()},_stopUpdatePolling(){this._updatePollTimer&&(clearInterval(this._updatePollTimer),this._updatePollTimer=null)},_pollUpdateStatus(){this._stopUpdatePolling();const e=new Set(["completed","completed-needs-manual-restart","failed","idle"]),t=async()=>{let n=null;try{const s=await fetch("/api/system/update/status");s.ok&&(n=await s.json())}catch{}if(!n){this._setUpdateProgress("\u21BB Restarting Codeman\u2026");return}if(!e.has(n.phase)){this._setUpdateProgress(`\u21BB ${escapeHtml(this._updatePhaseText(n.phase))}`);return}if(this._stopUpdatePolling(),n.phase==="completed"){let s=`<span style="color:var(--success,#3fb950)">\u2713 Updated to v${escapeHtml(n.toVersion||"")}. Reloading\u2026</span>`;n.stashRef&&(s+=`<br><span style="color:var(--text-secondary)">Local changes stashed as <code>${escapeHtml(n.stashRef)}</code> \u2014 run <code>git stash pop</code> to restore.</span>`),this._setUpdateProgress(s),setTimeout(()=>location.reload(),2500)}else if(n.phase==="completed-needs-manual-restart")this._setUpdateProgress(`Update staged. Restart Codeman to apply:<br><code>${escapeHtml(n.manualRestartCommand||"restart codeman web")}</code>`);else if(n.phase==="failed"){let s=`<span style="color:var(--danger,#e5534b)">\u2717 ${escapeHtml(n.message||"Update failed")}.</span>`;n.error&&(s+=`<br><span style="color:var(--text-secondary)">${escapeHtml(n.error)}</span>`),s+='<br><span style="color:var(--text-secondary)">The previous version is still running.</span>',n.stashRef&&(s+=`<br><span style="color:var(--text-secondary)">Local changes stashed as <code>${escapeHtml(n.stashRef)}</code>.</span>`),this._setUpdateProgress(s);const o=this.$("updateNowBtn"),i=this.$("updateActionRow");o&&(o.disabled=!1,o.textContent="Try again"),i&&(i.style.display="flex")}};t(),this._updatePollTimer=setInterval(t,1500)},async loadTunnelStatus(){try{const t=await(await fetch("/api/tunnel/status")).json(),n=t.running&&t.url;this._tunnelUrl=n?t.url:null,this._updateTunnelUrlDisplay(this._tunnelUrl),this._updateWelcomeTunnelBtn(!!n,this._tunnelUrl),this._updateTunnelIndicator(!!n)}catch{this._tunnelUrl=null,this._updateTunnelUrlDisplay(null),this._updateWelcomeTunnelBtn(!1),this._updateTunnelIndicator(!1)}},_updateTunnelUrlRow(e,t,n,s=""){const o=document.getElementById(e),i=document.getElementById(t);if(!(!o||!i))if(n){const a=n+s;o.style.display="",i.textContent=a,i.onclick=()=>{navigator.clipboard.writeText(a).then(()=>{this.showToast(`${s?"Upload":"Tunnel"} URL copied`,"success")})}}else o.style.display="none",i.textContent="",i.onclick=null},_updateTunnelUrlDisplay(e){this._updateTunnelUrlRow("tunnelUrlRow","tunnelUrlDisplay",e),this._updateTunnelUrlRow("tunnelUploadUrlRow","tunnelUploadUrlDisplay",e,"/upload.html")},showTunnelQR(){this.closeTunnelQR();const e=document.createElement("div");e.id="tunnelQrOverlay",e.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,0.7);z-index:5000;display:flex;align-items:center;justify-content:center;cursor:pointer",e.onclick=n=>{n.target===e&&this.closeTunnelQR()};const t=document.createElement("div");t.style.cssText="background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:24px;text-align:center;max-width:340px;width:90vw;box-shadow:var(--shadow-lg);cursor:default",t.innerHTML=`
|
|
1
|
+
"use strict";Object.assign(CodemanApp.prototype,{_onHookIdlePrompt(e){e.sessionId&&this.setPendingHook(e.sessionId,"idle_prompt"),this._notifySession(e.sessionId,"warning","hook-idle","Waiting for Input",e.message||"Claude is idle and waiting for a prompt")},_onHookPermissionPrompt(e){e.sessionId&&this.setPendingHook(e.sessionId,"permission_prompt");const t=e.tool?`${e.tool}${e.command?": "+e.command:e.file?": "+e.file:""}`:"";this._notifySession(e.sessionId,"critical","hook-permission","Permission Required",t||"Claude needs tool approval to continue")},_onHookElicitationDialog(e){e.sessionId&&this.setPendingHook(e.sessionId,"elicitation_dialog"),this._notifySession(e.sessionId,"critical","hook-elicitation","Question Asked",e.question||"Claude is asking a question and waiting for your answer")},_onHookStop(e){e.sessionId&&this.clearPendingHooks(e.sessionId),this._notifySession(e.sessionId,"info","hook-stop","Response Complete",e.reason||"Claude has finished responding")},_onHookTeammateIdle(e){const t=this.sessions.get(e.sessionId);this._notifySession(e.sessionId,"warning","hook-teammate-idle","Teammate Idle",`A teammate is idle in ${t?.name||e.sessionId}`)},_onHookTaskCompleted(e){const t=this.sessions.get(e.sessionId);this._notifySession(e.sessionId,"info","hook-task-completed","Task Completed",`A team task completed in ${t?.name||e.sessionId}`)},_onTunnelStarted(e){console.log("[Tunnel] Started:",e.url),this._tunnelUrl=e.url,this._dismissTunnelConnecting(),this._updateTunnelUrlDisplay(e.url),this._updateTunnelIndicator(!0),document.getElementById("welcomeOverlay")?.classList.contains("visible")?(this._updateWelcomeTunnelBtn(!0,e.url,!0),this.showToast("Tunnel active","success")):(this._updateWelcomeTunnelBtn(!0,e.url),this.showToast(`Tunnel active: ${e.url}`,"success"),this.showTunnelQR())},_onTunnelStopped(){console.log("[Tunnel] Stopped"),this._tunnelUrl=null,this._dismissTunnelConnecting(),this._updateTunnelUrlDisplay(null),this._updateWelcomeTunnelBtn(!1),this._updateTunnelIndicator(!1),this.closeTunnelPanel(),this.closeTunnelQR()},_onTunnelProgress(e){console.log("[Tunnel] Progress:",e.message);const t=document.getElementById("tunnelConnectingToast");t&&(t.innerHTML=`<span class="tunnel-spinner"></span> ${e.message}`);const n=document.getElementById("welcomeTunnelBtn");n?.classList.contains("connecting")&&(n.innerHTML=`<span class="tunnel-spinner"></span> ${e.message}`)},_onTunnelError(e){console.warn("[Tunnel] Error:",e.message),this._dismissTunnelConnecting(),this.showToast(`Tunnel error: ${e.message}`,"error");const t=document.getElementById("welcomeTunnelBtn");t&&(t.disabled=!1,t.classList.remove("connecting"))},_onTunnelQrRotated(e){if(e.svg){const t=document.getElementById("tunnelQrContainer");t&&(t.innerHTML=e.svg);const n=document.getElementById("welcomeQrInner");n&&(n.innerHTML=e.svg)}else this._refreshTunnelQrFromApi();this._resetQrCountdown()},_onTunnelQrRegenerated(e){if(e.svg){const t=document.getElementById("tunnelQrContainer");t&&(t.innerHTML=e.svg);const n=document.getElementById("welcomeQrInner");n&&(n.innerHTML=e.svg)}else this._refreshTunnelQrFromApi();this._resetQrCountdown()},_onTunnelQrAuthUsed(e){const n=(e.ua||"Unknown device").match(/Chrome|Firefox|Safari|Edge|Mobile/)?.[0]||"Browser";this.showToast(`Device authenticated via QR (${n}, ${e.ip}). Not you?`,"warning",{duration:1e4,action:{label:"Revoke All",onClick:()=>{fetch("/api/auth/revoke",{method:"POST",headers:{"Content-Type":"application/json"},body:"{}"}).then(()=>this.showToast("All sessions revoked","success")).catch(()=>this.showToast("Failed to revoke sessions","error"))}}})},registerServiceWorker(){"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then(e=>{this._swRegistration=e,navigator.serviceWorker.addEventListener("message",t=>{if(t.data?.type==="notification-click"){const{sessionId:n}=t.data;n&&this.sessions.has(n)&&this.selectSession(n),window.focus()}}),e.pushManager.getSubscription().then(t=>{t&&(this._pushSubscription=t,this._updatePushUI(!0))})}).catch(()=>{})},async subscribeToPush(){if(!this._swRegistration){this.showToast("Service worker not available. HTTPS or localhost required.","error");return}try{const e=await this._apiJson("/api/push/vapid-key");if(!e?.success)throw new Error("Failed to get VAPID key");const t=urlBase64ToUint8Array(e.data.publicKey),n=await this._swRegistration.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:t}),s=n.toJSON(),o=await this._apiJson("/api/push/subscribe",{method:"POST",body:{endpoint:s.endpoint,keys:s.keys,userAgent:navigator.userAgent,pushPreferences:this._buildPushPreferences()}});if(!o?.success)throw new Error("Failed to register subscription");this._pushSubscription=n,this._pushSubscriptionId=o.data.id,localStorage.setItem("codeman-push-subscription-id",o.data.id),this._updatePushUI(!0),this.showToast("Push notifications enabled","success")}catch(e){this.showToast("Push subscription failed: "+(e.message||e),"error")}},async unsubscribeFromPush(){try{this._pushSubscription&&await this._pushSubscription.unsubscribe();const e=this._pushSubscriptionId||localStorage.getItem("codeman-push-subscription-id");e&&await fetch(`/api/push/subscribe/${e}`,{method:"DELETE"}).catch(()=>{}),this._pushSubscription=null,this._pushSubscriptionId=null,localStorage.removeItem("codeman-push-subscription-id"),this._updatePushUI(!1),this.showToast("Push notifications disabled","success")}catch(e){this.showToast("Failed to unsubscribe: "+(e.message||e),"error")}},async togglePushSubscription(){this._pushSubscription?await this.unsubscribeFromPush():await this.subscribeToPush()},async _syncPushPreferences(){const e=this._pushSubscriptionId||localStorage.getItem("codeman-push-subscription-id");if(e)try{await fetch(`/api/push/subscribe/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({pushPreferences:this._buildPushPreferences()})})}catch{}},_buildPushPreferences(){const e={},t={"hook:permission_prompt":"eventPermissionPush","hook:elicitation_dialog":"eventQuestionPush","hook:idle_prompt":"eventIdlePush","hook:stop":"eventStopPush","respawn:blocked":"eventRespawnPush","session:ralphCompletionDetected":"eventRalphPush"};for(const[n,s]of Object.entries(t)){const o=document.getElementById(s);e[n]=o?o.checked:!0}return e["session:error"]=!0,e},_updatePushUI(e){const t=document.getElementById("pushSubscribeBtn"),n=document.getElementById("pushSubscriptionStatus");t&&(t.textContent=e?"Unsubscribe":"Subscribe"),n&&(n.textContent=e?"active":"off",n.classList.remove("granted","denied"),e&&n.classList.add("granted"))},openAppSettings(){const e=this.loadAppSettingsFromStorage();document.getElementById("appSettingsClaudeMdPath").value=e.defaultClaudeMdPath||"",document.getElementById("appSettingsDefaultDir").value=e.defaultWorkingDir||"";const t=this.getDefaultSettings();document.getElementById("appSettingsRalphEnabled").checked=e.ralphTrackerEnabled??t.ralphTrackerEnabled??!1,document.getElementById("appSettingsShowFontControls").checked=e.showFontControls??t.showFontControls??!1,document.getElementById("appSettingsShowSystemStats").checked=e.showSystemStats??t.showSystemStats??!0,document.getElementById("appSettingsShowTokenCount").checked=e.showTokenCount??t.showTokenCount??!0,document.getElementById("appSettingsShowCost").checked=e.showCost??t.showCost??!1,document.getElementById("appSettingsShowLifecycleLog").checked=e.showLifecycleLog??t.showLifecycleLog??!0,document.getElementById("appSettingsShowMonitor").checked=e.showMonitor??t.showMonitor??!0,document.getElementById("appSettingsShowProjectInsights").checked=e.showProjectInsights??t.showProjectInsights??!1,document.getElementById("appSettingsShowFileBrowser").checked=e.showFileBrowser??t.showFileBrowser??!1,document.getElementById("appSettingsShowSubagents").checked=e.showSubagents??t.showSubagents??!1,document.getElementById("appSettingsShowMultiMonitorButton").checked=e.showMultiMonitorButton??t.showMultiMonitorButton??!1;const n=document.getElementById("appSettingsGestureControlItem");n&&(n.style.display=window.__codemanGestureAvailable?"":"none"),document.getElementById("appSettingsGestureControl").checked=e.gestureControlEnabled??t.gestureControlEnabled??!1,document.getElementById("appSettingsSubagentTracking").checked=e.subagentTrackingEnabled??t.subagentTrackingEnabled??!0,document.getElementById("appSettingsSubagentActiveTabOnly").checked=e.subagentActiveTabOnly??t.subagentActiveTabOnly??!0,document.getElementById("appSettingsImageWatcherEnabled").checked=e.imageWatcherEnabled??t.imageWatcherEnabled??!1,document.getElementById("appSettingsTunnelEnabled").checked=e.tunnelEnabled??!1,this.loadTunnelStatus(),document.getElementById("appSettingsLocalEcho").checked=e.localEchoEnabled??MobileDetection.isTouchDevice(),document.getElementById("appSettingsCjkInput").checked=e.cjkInputEnabled??!1,document.getElementById("appSettingsExtendedKeyboardBar").checked=e.extendedKeyboardBar??!1,document.getElementById("appSettingsTabTwoRows").checked=e.tabTwoRows??t.tabTwoRows??!1;const s=document.getElementById("appSettingsClaudeMode"),o=document.getElementById("allowedToolsRow");s.value=e.claudeMode||"dangerously-skip-permissions",document.getElementById("appSettingsAllowedTools").value=e.allowedTools||"",o.style.display=s.value==="allowedTools"?"":"none",s.onchange=()=>{o.style.display=s.value==="allowedTools"?"":"none"},document.getElementById("appSettingsAgentTeams").checked=e.agentTeamsEnabled??!1,document.getElementById("appSettingsOpusContext1m").checked=e.opusContext1mEnabled??!1,document.getElementById("appSettingsThinkingEffort").value=e.thinkingEffort??"";const i=e.nice||{};document.getElementById("appSettingsNiceEnabled").checked=i.enabled??!1,document.getElementById("appSettingsNiceValue").value=i.niceValue??10,this.loadModelConfigForSettings();const a=this.notificationManager?.preferences||{};document.getElementById("appSettingsNotifEnabled").checked=a.enabled??!0,document.getElementById("appSettingsNotifBrowser").checked=a.browserNotifications??!1,document.getElementById("appSettingsNotifAudio").checked=a.audioAlerts??!1,document.getElementById("appSettingsNotifStuckMins").value=Math.round((a.stuckThresholdMs||6e5)/6e4),document.getElementById("appSettingsNotifCritical").checked=!a.muteCritical,document.getElementById("appSettingsNotifWarning").checked=!a.muteWarning,document.getElementById("appSettingsNotifInfo").checked=!a.muteInfo,document.getElementById("appSettingsPushEnabled").checked=!!this._pushSubscription,this._updatePushUI(!!this._pushSubscription);const l=a.eventTypes||{},c=l.permission_prompt||{};document.getElementById("eventPermissionEnabled").checked=c.enabled??!0,document.getElementById("eventPermissionBrowser").checked=c.browser??!0,document.getElementById("eventPermissionPush").checked=c.push??!1,document.getElementById("eventPermissionAudio").checked=c.audio??!0;const d=l.elicitation_dialog||{};document.getElementById("eventQuestionEnabled").checked=d.enabled??!0,document.getElementById("eventQuestionBrowser").checked=d.browser??!0,document.getElementById("eventQuestionPush").checked=d.push??!1,document.getElementById("eventQuestionAudio").checked=d.audio??!0;const r=l.idle_prompt||{};document.getElementById("eventIdleEnabled").checked=r.enabled??!0,document.getElementById("eventIdleBrowser").checked=r.browser??!0,document.getElementById("eventIdlePush").checked=r.push??!1,document.getElementById("eventIdleAudio").checked=r.audio??!1;const u=l.stop||{};document.getElementById("eventStopEnabled").checked=u.enabled??!0,document.getElementById("eventStopBrowser").checked=u.browser??!1,document.getElementById("eventStopPush").checked=u.push??!1,document.getElementById("eventStopAudio").checked=u.audio??!1;const p=l.respawn_cycle||{};document.getElementById("eventRespawnEnabled").checked=p.enabled??!0,document.getElementById("eventRespawnBrowser").checked=p.browser??!1,document.getElementById("eventRespawnPush").checked=p.push??!1,document.getElementById("eventRespawnAudio").checked=p.audio??!1;const m=l.ralph_complete||{};document.getElementById("eventRalphEnabled").checked=m.enabled??!0,document.getElementById("eventRalphBrowser").checked=m.browser??!0,document.getElementById("eventRalphPush").checked=m.push??!1,document.getElementById("eventRalphAudio").checked=m.audio??!0;const h=l.subagent_spawn||{};document.getElementById("eventSubagentEnabled").checked=h.enabled??!1,document.getElementById("eventSubagentBrowser").checked=h.browser??!1,document.getElementById("eventSubagentPush").checked=h.push??!1,document.getElementById("eventSubagentAudio").checked=h.audio??!1;const f=document.getElementById("notifPermissionStatus");if(f&&typeof Notification<"u"){const g=Notification.permission;f.textContent=g==="granted"?"\u2713":g==="denied"?"\u2717":"?",f.classList.remove("granted","denied"),g==="granted"?f.classList.add("granted"):g==="denied"&&f.classList.add("denied")}const y=VoiceInput._getDeepgramConfig();document.getElementById("voiceDeepgramKey").value=y.apiKey||"",document.getElementById("voiceLanguage").value=y.language||"en-US",document.getElementById("voiceKeyterms").value=y.keyterms||"refactor, endpoint, middleware, callback, async, regex, TypeScript, npm, API, deploy, config, linter, env, webhook, schema, CLI, JSON, CSS, DOM, SSE, backend, frontend, localhost, dependencies, repository, merge, rebase, diff, commit, com",document.getElementById("voiceInsertMode").value=y.insertMode||"direct";const S=document.getElementById("voiceDeepgramKey");S.type="password",document.getElementById("voiceKeyToggleBtn").textContent="Show";const w=VoiceInput.getActiveProviderName(),v=document.getElementById("voiceProviderStatus");v.textContent=w,v.className="voice-provider-status"+(w.startsWith("Deepgram")?" active":""),this._initUpdatesSection(),this.switchSettingsTab("settings-display");const b=document.getElementById("appSettingsModal");b.querySelectorAll(".modal-tabs .modal-tab-btn").forEach(g=>{g.onclick=()=>this.switchSettingsTab(g.dataset.tab)}),b.classList.add("active"),this.activeFocusTrap=new FocusTrap(b),this.activeFocusTrap.activate()},switchSettingsTab(e){const t=document.getElementById("appSettingsModal");t.querySelectorAll(".modal-tabs .modal-tab-btn").forEach(n=>{n.classList.toggle("active",n.dataset.tab===e)}),t.querySelectorAll(".modal-tab-content").forEach(n=>{n.classList.toggle("hidden",n.id!==e)})},closeAppSettings(){document.getElementById("appSettingsModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},_updatePhaseText(e){return{queued:"Queued\u2026",preparing:"Preparing\u2026",stashing:"Stashing local changes\u2026",fetching:"Fetching release\u2026",checkout:"Checking out release\u2026",installing:"Installing dependencies\u2026",building:"Building\u2026",restarting:"Restarting Codeman\u2026"}[e]||e},_initUpdatesSection(){const e=this.$("updateCurrentVersion");e&&(e.textContent=(this.$("versionDisplay")?.textContent||"").trim()||"\u2014");for(const t of["updateResult","updateActionRow","updateNotes","updateProgress"]){const n=this.$(t);n&&(n.style.display="none")}this._updateCheck=null},_setUpdateResult(e){const t=this.$("updateResult");t&&(t.style.display="block",t.innerHTML=e)},_setUpdateProgress(e){const t=this.$("updateProgress");t&&(t.style.display="block",t.innerHTML=e)},async checkForUpdate(){const e=this.$("updateCheckBtn");e&&(e.disabled=!0,e.textContent="Checking\u2026");const t=await this._apiJson("/api/system/update/check");e&&(e.disabled=!1,e.textContent="Check now");const n=this.$("updateActionRow"),s=this.$("updateNotes");if(n&&(n.style.display="none"),s&&(s.style.display="none"),!t){this._setUpdateResult("Could not check for updates. Try again later.");return}this._updateCheck=t;const o=this.$("updateCurrentVersion");if(o&&t.currentVersion&&(o.textContent=`v${t.currentVersion}`),t.installKind&&t.installKind!=="git"){this._setUpdateResult(`This install can't update itself (${escapeHtml(t.installKind)}). Update with <code>npm i -g aicodeman@latest</code>.`);return}if(t.selfUpdateEnabled===!1){this._setUpdateResult("In-app updates are disabled on this server (CODEMAN_DISABLE_SELF_UPDATE=1).");return}if(t.error&&!t.updateAvailable){this._setUpdateResult(escapeHtml(t.error));return}if(t.updateAvailable&&t.latestVersion){this._setUpdateResult(`Update available: <strong>v${escapeHtml(t.latestVersion)}</strong> (current v${escapeHtml(t.currentVersion||"")})`);const i=this.$("updateActionLabel");i&&(i.textContent=`Update to v${t.latestVersion}`),n&&(n.style.display="flex");const a=this.$("updateNowBtn");a&&(a.disabled=!1,a.textContent="Update now"),s&&t.notes&&(s.style.display="block",s.textContent=t.notes)}else this._setUpdateResult(`You're up to date (v${escapeHtml(t.currentVersion||"")}).`)},async startSelfUpdate(){const e=this._updateCheck?.latestVersion?`v${this._updateCheck.latestVersion}`:"the latest release";if(!confirm(`Update Codeman to ${e}? The server will restart and this page will reload.`))return;const t=this.$("updateNowBtn");t&&(t.disabled=!0,t.textContent="Starting\u2026");const n=await this._apiPost("/api/system/update",{});if(!n||!n.ok){let i="Failed to start the update.";try{const a=await n.json();a?.error?.message&&(i=a.error.message)}catch{}this._setUpdateProgress(`<span style="color:var(--danger,#e5534b)">${escapeHtml(i)}</span>`),t&&(t.disabled=!1,t.textContent="Update now");return}const s=this.$("updateActionRow");s&&(s.style.display="none");const o=this.$("updateNotes");o&&(o.style.display="none"),this._setUpdateProgress("Starting update\u2026"),this._pollUpdateStatus()},_stopUpdatePolling(){this._updatePollTimer&&(clearInterval(this._updatePollTimer),this._updatePollTimer=null)},_pollUpdateStatus(){this._stopUpdatePolling();const e=new Set(["completed","completed-needs-manual-restart","failed","idle"]),t=async()=>{let n=null;try{const s=await fetch("/api/system/update/status");s.ok&&(n=await s.json())}catch{}if(!n){this._setUpdateProgress("\u21BB Restarting Codeman\u2026");return}if(!e.has(n.phase)){const s=n.message&&n.message.trim()?n.message.trim():this._updatePhaseText(n.phase);let o="";n.startedAt&&(o=` <span style="color:var(--text-secondary)">\xB7 ${Math.max(0,Math.round((Date.now()-n.startedAt)/1e3))}s</span>`),this._setUpdateProgress(`<span class="tunnel-spinner"></span> ${escapeHtml(s)}${o}`);return}if(this._stopUpdatePolling(),n.phase==="completed"){let s=`<span style="color:var(--success,#3fb950)">\u2713 Updated to v${escapeHtml(n.toVersion||"")}. Reloading\u2026</span>`;n.stashRef&&(s+=`<br><span style="color:var(--text-secondary)">Local changes stashed as <code>${escapeHtml(n.stashRef)}</code> \u2014 run <code>git stash pop</code> to restore.</span>`),this._setUpdateProgress(s),setTimeout(()=>location.reload(),2500)}else if(n.phase==="completed-needs-manual-restart")this._setUpdateProgress(`Update staged. Restart Codeman to apply:<br><code>${escapeHtml(n.manualRestartCommand||"restart codeman web")}</code>`);else if(n.phase==="failed"){let s=`<span style="color:var(--danger,#e5534b)">\u2717 ${escapeHtml(n.message||"Update failed")}.</span>`;n.error&&(s+=`<br><span style="color:var(--text-secondary)">${escapeHtml(n.error)}</span>`),s+='<br><span style="color:var(--text-secondary)">The previous version is still running.</span>',n.stashRef&&(s+=`<br><span style="color:var(--text-secondary)">Local changes stashed as <code>${escapeHtml(n.stashRef)}</code>.</span>`),this._setUpdateProgress(s);const o=this.$("updateNowBtn"),i=this.$("updateActionRow");o&&(o.disabled=!1,o.textContent="Try again"),i&&(i.style.display="flex")}};t(),this._updatePollTimer=setInterval(t,1500)},async loadTunnelStatus(){try{const t=await(await fetch("/api/tunnel/status")).json(),n=t.running&&t.url;this._tunnelUrl=n?t.url:null,this._updateTunnelUrlDisplay(this._tunnelUrl),this._updateWelcomeTunnelBtn(!!n,this._tunnelUrl),this._updateTunnelIndicator(!!n)}catch{this._tunnelUrl=null,this._updateTunnelUrlDisplay(null),this._updateWelcomeTunnelBtn(!1),this._updateTunnelIndicator(!1)}},_updateTunnelUrlRow(e,t,n,s=""){const o=document.getElementById(e),i=document.getElementById(t);if(!(!o||!i))if(n){const a=n+s;o.style.display="",i.textContent=a,i.onclick=()=>{navigator.clipboard.writeText(a).then(()=>{this.showToast(`${s?"Upload":"Tunnel"} URL copied`,"success")})}}else o.style.display="none",i.textContent="",i.onclick=null},_updateTunnelUrlDisplay(e){this._updateTunnelUrlRow("tunnelUrlRow","tunnelUrlDisplay",e),this._updateTunnelUrlRow("tunnelUploadUrlRow","tunnelUploadUrlDisplay",e,"/upload.html")},showTunnelQR(){this.closeTunnelQR();const e=document.createElement("div");e.id="tunnelQrOverlay",e.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,0.7);z-index:5000;display:flex;align-items:center;justify-content:center;cursor:pointer",e.onclick=n=>{n.target===e&&this.closeTunnelQR()};const t=document.createElement("div");t.style.cssText="background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:24px;text-align:center;max-width:340px;width:90vw;box-shadow:var(--shadow-lg);cursor:default",t.innerHTML=`
|
|
2
2
|
<div style="font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:16px">Scan to connect</div>
|
|
3
3
|
<div id="tunnelQrContainer" style="background:#fff;border-radius:8px;padding:16px;display:inline-block">
|
|
4
4
|
<div style="color:#666;font-size:12px">Loading...</div>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/web/public/sw.js.gz
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|