@quanthermes/hermes-web-ui 0.6.12 → 0.6.13

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.
Files changed (41) hide show
  1. package/bin/hermes-web-ui.mjs +7 -0
  2. package/dist/client/assets/js/{ChannelsView-BAbGxkKW.js → ChannelsView-BduiL1-M.js} +1 -1
  3. package/dist/client/assets/js/{ChatView-hdWG7dhS.js → ChatView-C-84i0a3.js} +1 -1
  4. package/dist/client/assets/js/{CodingAgentsView-BB79rLb_.js → CodingAgentsView-Cu5bfdCo.js} +1 -1
  5. package/dist/client/assets/js/{DevicesView-DEdHwkrV.js → DevicesView-BwVqTyuH.js} +1 -1
  6. package/dist/client/assets/js/{FileRenameModal-CdKXqr0a.js → FileRenameModal-DMqVjoLN.js} +1 -1
  7. package/dist/client/assets/js/{FilesView-C49jsfxy.js → FilesView-Ce30F1_8.js} +1 -1
  8. package/dist/client/assets/js/{GroupChatView-DwL-zIjT.js → GroupChatView-BQqM5noE.js} +1 -1
  9. package/dist/client/assets/js/{HistoryMessageList-B1ORl6-d.js → HistoryMessageList-B3TsU-9g.js} +1 -1
  10. package/dist/client/assets/js/{HistoryView-CdlRAUh5.js → HistoryView-qhTXEU5G.js} +1 -1
  11. package/dist/client/assets/js/{JobsView-BPZ4Wv0y.js → JobsView-BszCmau_.js} +1 -1
  12. package/dist/client/assets/js/{KanbanView-UHzayv3c.js → KanbanView-BMa_FMqS.js} +1 -1
  13. package/dist/client/assets/js/{LoginView-BYrZGFRC.js → LoginView-v4Lvgu2R.js} +1 -1
  14. package/dist/client/assets/js/{LogsView-CyfCeIeY.js → LogsView-CuwioOCX.js} +1 -1
  15. package/dist/client/assets/js/{MarkdownRenderer-D-IgakCO.js → MarkdownRenderer-2bwbBjlK.js} +1 -1
  16. package/dist/client/assets/js/{McpManagerView-DMbmKtiH.js → McpManagerView-BDJSjkHx.js} +1 -1
  17. package/dist/client/assets/js/{MemoryView-iYE-K13x.js → MemoryView-rYoZbfMb.js} +1 -1
  18. package/dist/client/assets/js/{MessageItem-Be7fqF3P.js → MessageItem-OSBjfS2l.js} +1 -1
  19. package/dist/client/assets/js/{ModelsView-XRIIk2f7.js → ModelsView-DGPA2heM.js} +1 -1
  20. package/dist/client/assets/js/{OutlinePanel-BSPx9YaI.js → OutlinePanel-CN0TVZ0B.js} +1 -1
  21. package/dist/client/assets/js/{PerformanceView-m3deuRba.js → PerformanceView-0GmZ2GXR.js} +1 -1
  22. package/dist/client/assets/js/{PluginsView-BBrFPfSn.js → PluginsView-D6XEulKx.js} +1 -1
  23. package/dist/client/assets/js/{ProfilesView-G_eYB34O.js → ProfilesView-CCPI-DaB.js} +1 -1
  24. package/dist/client/assets/js/{SettingRow-wqcLQ0FL.js → SettingRow-B0WJ-Iqa.js} +1 -1
  25. package/dist/client/assets/js/{SettingsView-DMOWr41T.js → SettingsView-BaZ_P8Wu.js} +1 -1
  26. package/dist/client/assets/js/{SkillsUsageView-fn3jivrH.js → SkillsUsageView-BJVHpo4D.js} +1 -1
  27. package/dist/client/assets/js/{SkillsView-CXDdZj7R.js → SkillsView-vhxQVIz8.js} +1 -1
  28. package/dist/client/assets/js/{TerminalPanel-CqIASgSb.js → TerminalPanel-C50X3--t.js} +1 -1
  29. package/dist/client/assets/js/{TerminalView-ycEOrgth.js → TerminalView-1qIvfZKj.js} +1 -1
  30. package/dist/client/assets/js/{UsageView-BhNclgOH.js → UsageView-CLUP9AqF.js} +1 -1
  31. package/dist/client/assets/js/{VersionPreviewView-DoG0hdD2.js → VersionPreviewView-C9I3ZH13.js} +1 -1
  32. package/dist/client/assets/js/{VirtualMessageList-B_teFrlt.js → VirtualMessageList-D6BvQLbe.js} +1 -1
  33. package/dist/client/assets/js/{_plugin-vue_export-helper-D4mtpdbl.js → _plugin-vue_export-helper-CtZk2OSc.js} +2 -2
  34. package/dist/client/assets/js/{index-BHU-82RO.js → index-DyLZQAQu.js} +1 -1
  35. package/dist/client/assets/js/{models-BX7pr_Gd.js → models-CjHxxDse.js} +1 -1
  36. package/dist/client/assets/js/{session-browser-prefs-OR-qaA1z.js → session-browser-prefs-kGpZZDQo.js} +1 -1
  37. package/dist/client/assets/js/{skills-fBzB8FGc.js → skills-CDjYTDMo.js} +1 -1
  38. package/dist/client/assets/js/{system-vQTkarwT.js → system-Pg8JEuA6.js} +1 -1
  39. package/dist/client/index.html +3 -3
  40. package/dist/server/index.js +3 -3
  41. package/package.json +1 -1
@@ -1 +1 @@
1
- import{n as y}from"./rolldown-runtime-M0oDzQ_3.js";import{Bn as r,Bt as w,Qt as u}from"./ui-vendor-DNWaqYj5.js";import{_ as b,g as C}from"./vue-vendor-VX6KvV1_.js";import{c as v,l as S}from"./_plugin-vue_export-helper-D4mtpdbl.js";import{a as A,f as D,l as B,m as F,n as Q,v as W}from"./system-vQTkarwT.js";import{Q as l,X as x,Y as K,Z as N}from"./index-BHU-82RO.js";var X,G=y((()=>{b(),w(),B(),S(),N(),K(),X=C("models",()=>{const t=r([]),f=r([]),o=r(""),i=r(""),n=r(!1),d=r(!1),c=u(()=>t.value.filter(e=>e.provider.startsWith("custom:"))),m=u(()=>t.value.filter(e=>!e.provider.startsWith("custom:"))),p=u(()=>t.value.flatMap(e=>e.models.map(a=>({id:a,provider:e.provider,label:e.label,base_url:e.base_url,isDefault:a===o.value&&e.provider===i.value}))));async function s(){if(v()){n.value=!0;try{const e=x().activeProfileName||"default",a=await A(e);t.value=a.groups,f.value=a.allProviders,o.value=a.default,i.value=a.default_provider||""}catch(e){console.error("Failed to fetch providers:",e)}finally{n.value=!1}}}async function _(){if(v()){d.value=!0;try{await D(),await s(),await l().reloadModels()}finally{d.value=!1}}}async function M(e,a){await W({default:e,provider:a}),o.value=e,i.value=a,l().reloadModels()}async function P(e){await Q(e),await s(),await l().reloadModels()}async function h(e){await F(e),await s(),await l().reloadModels()}return{providers:t,allProviders:f,defaultModel:o,defaultProvider:i,loading:n,refreshingModelCache:d,customProviders:c,builtinProviders:m,allModels:p,fetchProviders:s,refreshModelCache:_,setDefaultModel:M,addProvider:P,removeProvider:h}})}));export{X as n,G as t};
1
+ import{n as y}from"./rolldown-runtime-M0oDzQ_3.js";import{Bn as r,Bt as w,Qt as u}from"./ui-vendor-DNWaqYj5.js";import{_ as b,g as C}from"./vue-vendor-VX6KvV1_.js";import{c as v,l as S}from"./_plugin-vue_export-helper-CtZk2OSc.js";import{a as A,f as D,l as B,m as F,n as Q,v as W}from"./system-Pg8JEuA6.js";import{Q as l,X as x,Y as K,Z as N}from"./index-DyLZQAQu.js";var X,G=y((()=>{b(),w(),B(),S(),N(),K(),X=C("models",()=>{const t=r([]),f=r([]),o=r(""),i=r(""),n=r(!1),d=r(!1),c=u(()=>t.value.filter(e=>e.provider.startsWith("custom:"))),m=u(()=>t.value.filter(e=>!e.provider.startsWith("custom:"))),p=u(()=>t.value.flatMap(e=>e.models.map(a=>({id:a,provider:e.provider,label:e.label,base_url:e.base_url,isDefault:a===o.value&&e.provider===i.value}))));async function s(){if(v()){n.value=!0;try{const e=x().activeProfileName||"default",a=await A(e);t.value=a.groups,f.value=a.allProviders,o.value=a.default,i.value=a.default_provider||""}catch(e){console.error("Failed to fetch providers:",e)}finally{n.value=!1}}}async function _(){if(v()){d.value=!0;try{await D(),await s(),await l().reloadModels()}finally{d.value=!1}}}async function M(e,a){await W({default:e,provider:a}),o.value=e,i.value=a,l().reloadModels()}async function P(e){await Q(e),await s(),await l().reloadModels()}async function h(e){await F(e),await s(),await l().reloadModels()}return{providers:t,allProviders:f,defaultModel:o,defaultProvider:i,loading:n,refreshingModelCache:d,customProviders:c,builtinProviders:m,allModels:p,fetchProviders:s,refreshModelCache:_,setDefaultModel:M,addProvider:P,removeProvider:h}})}));export{X as n,G as t};
@@ -1 +1 @@
1
- import{n as w}from"./rolldown-runtime-M0oDzQ_3.js";import{Bn as l,Bt as I,On as E}from"./ui-vendor-DNWaqYj5.js";import{_ as J,g as K}from"./vue-vendor-VX6KvV1_.js";import{X as p,Y}from"./index-BHU-82RO.js";function v(){try{return p().activeProfileName||"default"}catch{return localStorage.getItem("hermes_active_profile_name")||"default"}}function f(n){return`${h}${n}`}function c(n){return`${P}${n}`}function a(n,e){try{const t=localStorage.getItem(n);return t?JSON.parse(t):e}catch{return e}}function m(n,e){try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function $(n,e){return n.length===e.length&&n.every((t,u)=>t===e[u])}var h,P,b,R=w((()=>{J(),I(),Y(),h="hermes_session_pins_v1_",P="hermes_human_only_v1_",b=K("session-browser-prefs",()=>{const n=l(v()),e=l(a(f(n.value),[])),t=l(a(c(n.value),!0));function u(){n.value=v(),e.value=a(f(n.value),[]),t.value=a(c(n.value),!0)}function s(){m(f(n.value),e.value)}function d(){m(c(n.value),t.value)}function o(r){return e.value.includes(r)}function g(r){o(r)?e.value=e.value.filter(i=>i!==r):e.value=[...e.value,r],s()}function y(r){return o(r)?(e.value=e.value.filter(i=>i!==r),s(),!0):!1}function S(r){t.value!==r&&(t.value=r,d())}function N(r){if(r.length===0)return!1;const i=new Set(r),_=e.value.filter(O=>i.has(O));return $(_,e.value)?!1:(e.value=_,s(),!0)}return E(()=>p().activeProfileName,()=>u()),{profileName:n,pinnedIds:e,humanOnly:t,reload:u,isPinned:o,togglePinned:g,removePinned:y,setHumanOnly:S,pruneMissingSessions:N}})}));export{b as n,R as t};
1
+ import{n as w}from"./rolldown-runtime-M0oDzQ_3.js";import{Bn as l,Bt as I,On as E}from"./ui-vendor-DNWaqYj5.js";import{_ as J,g as K}from"./vue-vendor-VX6KvV1_.js";import{X as p,Y}from"./index-DyLZQAQu.js";function v(){try{return p().activeProfileName||"default"}catch{return localStorage.getItem("hermes_active_profile_name")||"default"}}function f(n){return`${h}${n}`}function c(n){return`${P}${n}`}function a(n,e){try{const t=localStorage.getItem(n);return t?JSON.parse(t):e}catch{return e}}function m(n,e){try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function $(n,e){return n.length===e.length&&n.every((t,u)=>t===e[u])}var h,P,b,R=w((()=>{J(),I(),Y(),h="hermes_session_pins_v1_",P="hermes_human_only_v1_",b=K("session-browser-prefs",()=>{const n=l(v()),e=l(a(f(n.value),[])),t=l(a(c(n.value),!0));function u(){n.value=v(),e.value=a(f(n.value),[]),t.value=a(c(n.value),!0)}function s(){m(f(n.value),e.value)}function d(){m(c(n.value),t.value)}function o(r){return e.value.includes(r)}function g(r){o(r)?e.value=e.value.filter(i=>i!==r):e.value=[...e.value,r],s()}function y(r){return o(r)?(e.value=e.value.filter(i=>i!==r),s(),!0):!1}function S(r){t.value!==r&&(t.value=r,d())}function N(r){if(r.length===0)return!1;const i=new Set(r),_=e.value.filter(O=>i.has(O));return $(_,e.value)?!1:(e.value=_,s(),!0)}return E(()=>p().activeProfileName,()=>u()),{profileName:n,pinnedIds:e,humanOnly:t,reload:u,isPinned:o,togglePinned:g,removePinned:y,setHumanOnly:S,pruneMissingSessions:N}})}));export{b as n,R as t};
@@ -1 +1 @@
1
- import{n as p}from"./rolldown-runtime-M0oDzQ_3.js";import{a as y,d as t,l as d,o as u,s as k}from"./_plugin-vue_export-helper-D4mtpdbl.js";async function w(){const e=await t("/api/hermes/skills");return{categories:e.categories,archived:e.archived??[],paths:e.paths}}async function P(e=7){return t(`/api/hermes/skills/usage/stats?${new URLSearchParams({days:String(e)})}`)}async function U(e){return(await t(`/api/hermes/skills/${e}`)).content}async function $(e,s){return(await t(`/api/hermes/skills/${e}/${s}/files`)).files}async function b(){return t("/api/hermes/memory")}async function v(e,s){await t("/api/hermes/memory",{method:"POST",body:JSON.stringify({section:e,content:s})})}async function x(e,s){await t("/api/hermes/skills/toggle",{method:"PUT",body:JSON.stringify({name:e,enabled:s})})}async function O(e,s){await t("/api/hermes/skills/pin",{method:"PUT",body:JSON.stringify({name:e,pinned:s})})}async function E(){return(await t("/api/hermes/skills/external-dirs")).dirs??[]}async function N(e){await t("/api/hermes/skills/external-dirs",{method:"PUT",body:JSON.stringify({dirs:e})})}async function T(e,s){await t(`/api/hermes/skills/${encodeURIComponent(e)}/${encodeURIComponent(s)}`,{method:"DELETE"})}async function A(e,s){const m=k(),c=u(),a={};c&&(a.Authorization=`Bearer ${c}`);const f=y();f&&(a["X-Hermes-Profile"]=f);const i=new FormData;for(const l of e){const h=l.webkitRelativePath||l.name;i.append("file",l,h)}s&&i.append("category",s);const n=await fetch(`${m}/api/hermes/skills/import`,{method:"POST",headers:a,body:i}),r=await n.text();let o=null;try{o=r?JSON.parse(r):null}catch{}if(!n.ok)throw new Error(o?.error||r||`Import failed (${n.status})`);return o||{name:""}}var D=p((()=>{d()}));export{$ as a,A as c,N as d,v as f,U as i,D as l,E as n,P as o,x as p,b as r,w as s,T as t,O as u};
1
+ import{n as p}from"./rolldown-runtime-M0oDzQ_3.js";import{a as y,d as t,l as d,o as u,s as k}from"./_plugin-vue_export-helper-CtZk2OSc.js";async function w(){const e=await t("/api/hermes/skills");return{categories:e.categories,archived:e.archived??[],paths:e.paths}}async function P(e=7){return t(`/api/hermes/skills/usage/stats?${new URLSearchParams({days:String(e)})}`)}async function U(e){return(await t(`/api/hermes/skills/${e}`)).content}async function $(e,s){return(await t(`/api/hermes/skills/${e}/${s}/files`)).files}async function b(){return t("/api/hermes/memory")}async function v(e,s){await t("/api/hermes/memory",{method:"POST",body:JSON.stringify({section:e,content:s})})}async function x(e,s){await t("/api/hermes/skills/toggle",{method:"PUT",body:JSON.stringify({name:e,enabled:s})})}async function O(e,s){await t("/api/hermes/skills/pin",{method:"PUT",body:JSON.stringify({name:e,pinned:s})})}async function E(){return(await t("/api/hermes/skills/external-dirs")).dirs??[]}async function N(e){await t("/api/hermes/skills/external-dirs",{method:"PUT",body:JSON.stringify({dirs:e})})}async function T(e,s){await t(`/api/hermes/skills/${encodeURIComponent(e)}/${encodeURIComponent(s)}`,{method:"DELETE"})}async function A(e,s){const m=k(),c=u(),a={};c&&(a.Authorization=`Bearer ${c}`);const f=y();f&&(a["X-Hermes-Profile"]=f);const i=new FormData;for(const l of e){const h=l.webkitRelativePath||l.name;i.append("file",l,h)}s&&i.append("category",s);const n=await fetch(`${m}/api/hermes/skills/import`,{method:"POST",headers:a,body:i}),r=await n.text();let o=null;try{o=r?JSON.parse(r):null}catch{}if(!n.ok)throw new Error(o?.error||r||`Import failed (${n.status})`);return o||{name:""}}var D=p((()=>{d()}));export{$ as a,A as c,N as d,v as f,U as i,D as l,E as n,P as o,x as p,b as r,w as s,T as t,O as u};
@@ -1 +1 @@
1
- import{n as t}from"./rolldown-runtime-M0oDzQ_3.js";import{d as r,l as i}from"./_plugin-vue_export-helper-D4mtpdbl.js";async function n(){return r("/health")}async function d(){return r("/api/hermes/update",{method:"POST"})}async function m(){return r("/api/hermes/update/preview")}async function c(){return r("/api/hermes/update/preview/tags")}async function p(e){return r("/api/hermes/update/preview/prepare",{method:"POST",body:JSON.stringify({tag:e})})}async function u(){return r("/api/hermes/update/preview/install",{method:"POST"})}async function h(e){return r("/api/hermes/update/preview/start",{method:"POST",body:JSON.stringify({tag:e})})}async function f(){return r("/api/hermes/update/preview/stop",{method:"POST"})}async function l(){return r("/api/hermes/available-models")}async function y(e){const a=new URLSearchParams;return a.set("profile",e||"default"),r(`/api/hermes/available-models?${a.toString()}`)}async function v(e){return r("/api/hermes/provider-models",{method:"POST",body:JSON.stringify(e)})}async function P(){return r("/api/hermes/provider-models/cache/refresh",{method:"POST"})}async function S(e){await r("/api/hermes/config/model",{method:"PUT",body:JSON.stringify(e)})}async function g(e){await r("/api/hermes/model-alias",{method:"PUT",body:JSON.stringify(e)})}async function w(e){await r("/api/hermes/config/providers",{method:"POST",body:JSON.stringify(e)})}async function O(e){await r(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"DELETE"})}async function b(e,a){await r(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(a)})}async function T(e){return r("/api/hermes/model-visibility",{method:"PUT",body:JSON.stringify(e)})}async function M(e){return r("/api/hermes/custom-model",{method:"PUT",body:JSON.stringify(e)})}async function U(e){const a=new URLSearchParams;return a.set("provider",e.provider),a.set("model",e.model),r(`/api/hermes/custom-model?${a.toString()}`,{method:"DELETE"})}var J=t((()=>{i()}));export{d as _,y as a,T as b,v as c,p as d,P as f,f as g,h,l as i,J as l,O as m,w as n,m as o,U as p,n as r,c as s,M as t,u,S as v,b as x,g as y};
1
+ import{n as t}from"./rolldown-runtime-M0oDzQ_3.js";import{d as r,l as i}from"./_plugin-vue_export-helper-CtZk2OSc.js";async function n(){return r("/health")}async function d(){return r("/api/hermes/update",{method:"POST"})}async function m(){return r("/api/hermes/update/preview")}async function c(){return r("/api/hermes/update/preview/tags")}async function p(e){return r("/api/hermes/update/preview/prepare",{method:"POST",body:JSON.stringify({tag:e})})}async function u(){return r("/api/hermes/update/preview/install",{method:"POST"})}async function h(e){return r("/api/hermes/update/preview/start",{method:"POST",body:JSON.stringify({tag:e})})}async function f(){return r("/api/hermes/update/preview/stop",{method:"POST"})}async function l(){return r("/api/hermes/available-models")}async function y(e){const a=new URLSearchParams;return a.set("profile",e||"default"),r(`/api/hermes/available-models?${a.toString()}`)}async function v(e){return r("/api/hermes/provider-models",{method:"POST",body:JSON.stringify(e)})}async function P(){return r("/api/hermes/provider-models/cache/refresh",{method:"POST"})}async function S(e){await r("/api/hermes/config/model",{method:"PUT",body:JSON.stringify(e)})}async function g(e){await r("/api/hermes/model-alias",{method:"PUT",body:JSON.stringify(e)})}async function w(e){await r("/api/hermes/config/providers",{method:"POST",body:JSON.stringify(e)})}async function O(e){await r(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"DELETE"})}async function b(e,a){await r(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(a)})}async function T(e){return r("/api/hermes/model-visibility",{method:"PUT",body:JSON.stringify(e)})}async function M(e){return r("/api/hermes/custom-model",{method:"PUT",body:JSON.stringify(e)})}async function U(e){const a=new URLSearchParams;return a.set("provider",e.provider),a.set("model",e.model),r(`/api/hermes/custom-model?${a.toString()}`,{method:"DELETE"})}var J=t((()=>{i()}));export{d as _,y as a,T as b,v as c,p as d,P as f,f as g,h,l as i,J as l,O as m,w as n,m as o,U as p,n as r,c as s,M as t,u,S as v,b as x,g as y};
@@ -33,14 +33,14 @@
33
33
  }
34
34
  })();
35
35
  </script>
36
- <script type="module" crossorigin src="/assets/js/index-BHU-82RO.js"></script>
36
+ <script type="module" crossorigin src="/assets/js/index-DyLZQAQu.js"></script>
37
37
  <link rel="modulepreload" crossorigin href="/assets/js/rolldown-runtime-M0oDzQ_3.js">
38
38
  <link rel="modulepreload" crossorigin href="/assets/js/mermaid-CWQI515T.js">
39
39
  <link rel="modulepreload" crossorigin href="/assets/js/ui-vendor-DNWaqYj5.js">
40
40
  <link rel="modulepreload" crossorigin href="/assets/js/vendor-B1Lfatlz.js">
41
41
  <link rel="modulepreload" crossorigin href="/assets/js/vue-vendor-VX6KvV1_.js">
42
- <link rel="modulepreload" crossorigin href="/assets/js/_plugin-vue_export-helper-D4mtpdbl.js">
43
- <link rel="modulepreload" crossorigin href="/assets/js/system-vQTkarwT.js">
42
+ <link rel="modulepreload" crossorigin href="/assets/js/_plugin-vue_export-helper-CtZk2OSc.js">
43
+ <link rel="modulepreload" crossorigin href="/assets/js/system-Pg8JEuA6.js">
44
44
  <link rel="stylesheet" crossorigin href="/assets/css/vendor-DX3NCGtF.css">
45
45
  <link rel="stylesheet" crossorigin href="/assets/css/vue-vendor-WE_HbAyV.css">
46
46
  <link rel="stylesheet" crossorigin href="/assets/css/index-C56zktda.css">
@@ -265,7 +265,7 @@ const isVersionPreview = import.meta.env.VITE_HERMES_PREVIEW === '1';`)),l=l.rep
265
265
  \r
266
266
  `),Z.destroy();return}b.kanbanProfile=W||void 0}try{b.kanbanBoard=Kd(e.searchParams.get("board"))}catch{Z.write(`HTTP/1.1 400 Bad Request\r
267
267
  \r
268
- `),Z.destroy();return}l.handleUpgrade(b,Z,d,a=>{l.emit("connection",a,b)})}})}),l.on("connection",(c,b)=>{let Z=b.kanbanBoard||"default",d=Y9({board:Z,interval:.5}),e=!1;Wt(c,{type:"connected",board:Z});let a=()=>{e||(e=!0,d.killed||d.kill())};d.stdout?.on("data",E9(n=>{n.toLowerCase().startsWith("watching kanban events")||Wt(c,{type:"event",board:Z})})),d.stderr?.on("data",E9(n=>{Wt(c,{type:"error",board:Z,message:n})})),d.on("error",n=>{i.error(n,"Hermes CLI: kanban watch failed"),Wt(c,{type:"error",board:Z,message:n.message}),c.readyState===c.OPEN&&c.close()}),d.on("exit",(n,W)=>{Wt(c,{type:"stopped",board:Z,code:n,signal:W}),c.readyState===c.OPEN&&c.close()}),c.on("close",a),c.on("error",a)}),i.info("WebSocket ready at /api/hermes/kanban/events (kanban watch bridge)")}var B9=z(dW(),1),muI=z(kN(),1),M9=z(dW(),1),pi=z(kN(),1),UY=require("url"),ka=z(x9(),1),f9=z(require("http"),1),K9=z(ml(),1),O9={NotFound:"not-found"};function WuI(I){return typeof I=="function"?I(O9):I}var tuI=class{_handlers=new Map;register(I,l){let G=this._handlers.get(I)??[];G.push(l),this._handlers.set(I,G)}emit(I,l,G){let c=this._handlers.get(I);return c&&c.length>0?(0,B9.default)(c)(l,G):G()}};function zY(I,l={}){let G={...l};"strict"in G&&!("trailing"in G)&&(G.trailing=G.strict!==!0,delete G.strict),delete G.pathAsRegExp,delete G.ignoreCaptures,delete G.prefix;let{regexp:c,keys:b}=(0,ka.pathToRegexp)(I,G);return{regexp:c,keys:b}}function NuI(I,l={}){return(0,ka.compile)(I,l)}function suI(I,l){return(0,ka.parse)(I,l)}function Vi(I={}){let l={sensitive:I.sensitive,end:I.end,strict:I.strict,trailing:I.trailing};"strict"in l&&!("trailing"in l)&&(l.trailing=l.strict!==!0,delete l.strict);for(let G of Object.keys(l))l[G]===void 0&&delete l[G];return l}function YuI(I){try{return decodeURIComponent(I)}catch{return I}}var z9=class{opts;name;methods;paramNames;stack;path;regexp;constructor(I,l,G,c={}){this.opts=c,this.name=this.opts.name||void 0,this.methods=this._normalizeHttpMethods(l),this.stack=this._normalizeAndValidateMiddleware(G,l,I),this.path=I,this.paramNames=[],this._configurePathMatching()}_normalizeHttpMethods(I){let l=[];for(let G of I){let c=G.toUpperCase();l.push(c),c==="GET"&&l.unshift("HEAD")}return l}_normalizeAndValidateMiddleware(I,l,G){let c=Array.isArray(I)?I:[I];for(let b of c){let Z=typeof b;if(Z!=="function"){let d=this.opts.name||G;throw new Error(`${l.toString()} \`${d}\`: \`middleware\` must be a function, not \`${Z}\``)}}return c}_configurePathMatching(){this.opts.pathAsRegExp===!0?this.regexp=this.path instanceof RegExp?this.path:new RegExp(this.path):this.path&&this._configurePathToRegexp()}_configurePathToRegexp(){let I=Vi(this.opts),{regexp:l,keys:G}=zY(this.path,I);this.regexp=l,this.paramNames=G}match(I){return this.regexp.test(I)}params(I,l,G={}){let c={...G};for(let[b,Z]of l.entries()){let d=this.paramNames[b];if(d&&Z&&Z.length>0){let e=d.name;c[e]=YuI(Z)}}return c}captures(I){if(this.opts.ignoreCaptures)return[];let l=I.match(this.regexp);return l?l.slice(1):[]}url(...I){if(this.path instanceof RegExp)throw new TypeError("Cannot generate URL for routes defined with RegExp paths. Use string paths with named parameters instead.");let{params:l,options:G}=this._parseUrlArguments(I),c=this.path.replaceAll("(.*)",""),b=NuI(c,{encode:encodeURIComponent,...G}),Z=this._buildParamReplacements(l,c),d=b(Z);return G&&G.query?this._addQueryString(d,G.query):d}_parseUrlArguments(I){let l=I[0]??{},G=I[1];if(typeof l!="object"||l===null){let c=[...I],b=c.at(-1);typeof b=="object"&&b!==null?(G=b,l=c.slice(0,-1)):l=c}else if(l&&!G){let c=Object.keys(l);if(c.length===1&&c[0]==="query")G=l,l={};else if("query"in l&&l.query){let{query:Z,...d}=l;G={query:Z},l=d}}return{params:l,options:G}}_buildParamReplacements(I,l){let{tokens:G}=suI(l),c=G.some(Z=>"name"in Z&&Z.name),b={};if(Array.isArray(I)){let Z=0;for(let d of G)"name"in d&&d.name&&(b[d.name]=String(I[Z++]))}else if(c&&typeof I=="object"&&!("query"in I))for(let[Z,d]of Object.entries(I))b[Z]=String(d);return b}_addQueryString(I,l){let G=(0,UY.parse)(I),c={...G,query:G.query??void 0};return typeof l=="string"?(c.search=l,c.query=void 0):(c.search=void 0,c.query=l),(0,UY.format)(c)}param(I,l){let G=this.stack,c=this.paramNames,b=this._createParamMiddleware(I,l),Z=c.map(e=>e.name),d=Z.indexOf(I);return d!==-1&&this._insertParamMiddleware(G,b,Z,d),this}_createParamMiddleware(I,l){let G=((c,b)=>(c._matchedParams||(c._matchedParams=new WeakMap),c._matchedParams.has(l)?b():(c._matchedParams.set(l,!0),l(c.params[I],c,b))));return G.param=I,G._originalFn=l,G}_insertParamMiddleware(I,l,G,c){let b=!1;for(let Z=0;Z<I.length;Z++){let d=I[Z];if(!d.param){I.splice(Z,0,l),b=!0;break}if(G.indexOf(d.param)>c){I.splice(Z,0,l),b=!0;break}}b||I.push(l)}setPrefix(I){return this.path?this.path instanceof RegExp?this:(this.path=this._applyPrefix(I),this._reconfigurePathMatching(I),this):this}_applyPrefix(I){let l=this.path==="/",G=this.opts.strict===!0,c=I.includes(":"),b=this.opts.pathAsRegExp===!0&&typeof this.path=="string";if(c&&b){let Z=this.path;(Z===String.raw`(?:\/|$)`||Z===String.raw`(?:\\\/|$)`)&&(this.path="{/*rest}",this.opts.pathAsRegExp=!1)}return l&&!G?I:`${I}${this.path}`}_reconfigurePathMatching(I){let l=this.opts.pathAsRegExp===!0;if(I&&I.includes(":")&&l){let c=Vi(this.opts),{regexp:b,keys:Z}=zY(this.path,c);this.regexp=b,this.paramNames=Z,this.opts.pathAsRegExp=!1}else if(l){let c=this.path,b=c.startsWith("^")?c:`^${c}`;this.regexp=this.path instanceof RegExp?this.path:new RegExp(b)}else{let c=Vi(this.opts),{regexp:b,keys:Z}=zY(this.path,c);this.regexp=b,this.paramNames=Z}}};function VuI(){return f9.default.METHODS.map(I=>I.toLowerCase())}var huI=["get","post","put","patch","delete","del","head","options"];function puI(I){return I?Array.isArray(I)?I:[I]:[]}function j9(I,l,G){let c=puI(G);for(let b of c)I.param(l,b)}function uuI(I,l){let G=Object.keys(l);for(let c of G){let b=l[c];j9(I,c,b)}}function U9(I,l={}){if(!I)return!1;let{keys:G}=zY(I,l);return G.length>0}function ouI(I,l){return I!==void 0?typeof I=="string"?I===""?{path:"{/*rest}",pathAsRegExp:!1}:I==="/"?{path:"/",pathAsRegExp:!1}:{path:I,pathAsRegExp:!1}:{path:I,pathAsRegExp:!0}:l?{path:"{/*rest}",pathAsRegExp:!1}:{path:String.raw`(?:\/|$)`,pathAsRegExp:!0}}var hi=(0,K9.default)("koa-router"),S9=VuI(),ui=class{opts;methods;exclusive;params;stack;host;_events=new tuI;constructor(I={}){this.opts=I,this.methods=this.opts.methods||["HEAD","OPTIONS","GET","PUT","PATCH","POST","DELETE"],this.exclusive=!!this.opts.exclusive,this.params={},this.stack=[],this.host=this.opts.host}static url(I,...l){return new z9(I,[],()=>{}).url(...l)}use(...I){let l;if(this._isPathArray(I[0]))return this._useWithPathArray(I);let G=this._hasExplicitPath(I[0]);if(G&&(l=I.shift()),I.length===0)throw new Error("You must provide at least one middleware function to router.use()");for(let c of I)this._isNestedRouter(c)?this._mountNestedRouter(c,l):this._registerMiddleware(c,l,G);return this}_isPathArray(I){return Array.isArray(I)&&I.length>0&&I.every(l=>typeof l=="string")}_hasExplicitPath(I){return typeof I=="string"||I instanceof RegExp}_isNestedRouter(I){return typeof I=="function"&&"router"in I&&I.router!==void 0}_useWithPathArray(I){let l=I[0],G=I.slice(1);for(let c of l)Reflect.apply(this.use,this,[c,...G]);return this}_mountNestedRouter(I,l){let G=I.router,c=this._cloneRouter(G),b=l&&typeof l=="string"&&U9(l,this.opts);for(let Z=0;Z<c.stack.length;Z++){let d=c.stack[Z],e=this._cloneLayer(d);l&&typeof l=="string"&&e.setPrefix(l),this.opts.prefix&&e.setPrefix(this.opts.prefix),e.methods.length===0&&b&&(e.opts.ignoreCaptures=!1),this.stack.push(e),c.stack[Z]=e}this.params&&this._applyParamMiddlewareToRouter(c)}_cloneRouter(I){return Object.assign(Object.create(Object.getPrototypeOf(I)),I,{stack:[...I.stack]})}_cloneLayer(I){return Object.assign(Object.create(Object.getPrototypeOf(I)),I,{stack:[...I.stack],methods:[...I.methods],paramNames:[...I.paramNames],opts:{...I.opts}})}_applyParamMiddlewareToRouter(I){let l=Object.keys(this.params);for(let G of l){let c=this.params[G];j9(I,G,c)}}_registerMiddleware(I,l,G){let c=U9(this.opts.prefix||"",this.opts),b=(()=>{if(l!==void 0)return l;if(c)return""})(),Z=G||l===void 0&&c,{path:d,pathAsRegExp:e}=ouI(b,c),a=d,n=e,W=Z&&d==="/";Z&&typeof d=="string"&&(a=d,n=!1),this.register(a,[],I,{end:W,ignoreCaptures:!Z&&!c,pathAsRegExp:n})}prefix(I){let l=I.replace(/\/$/,""),G=this.opts.prefix||"";this.opts.prefix=l;for(let c of this.stack){if(typeof c.path=="string"&&G){let b=G+"/";(c.path===G||c.path.startsWith(b))&&(c.path=c.path.slice(G.length)||"/")}c.setPrefix(l)}return this}middleware(){let I=function(l,G){if(hi("%s %s",l.method,l.path),!this.matchHost(l.host))return G();let c=this._getRequestPath(l),b=this.match(c,l.method);if(this._storeMatchedRoutes(l,b),l.router=this,l.routeMatched=b.route,!b.route)return this._events.emit(O9.NotFound,l,G);let Z=b.pathAndMethod;this._setMatchedRouteInfo(l,Z);let d=this._buildMiddlewareChain(Z,c);return(0,M9.default)(d)(l,G)}.bind(this);return I.router=this,I}_getRequestPath(I){let l=I;return this.opts.routerPath||l.newRouterPath||l.path||l.routerPath||""}_storeMatchedRoutes(I,l){let G=I;G.matched?G.matched.push(...l.path):G.matched=l.path}_setMatchedRouteInfo(I,l){let G=I,c=l.toReversed().find(b=>b.methods.length>0);c&&(G._matchedRoute=c.path,c.name&&(G._matchedRouteName=c.name))}_buildMiddlewareChain(I,l){let G;if(this.exclusive){let b;if(this.opts.exclusive==="specificity")for(let Z of I)(!b||Z.paramNames.length<b.paramNames.length)&&(b=Z);else b=I.at(-1);G=b?[b]:[]}else G=I;let c=[];for(let b of G)c.push((Z,d)=>{let e=Z;return e.captures=b.captures(l),e.request.params=b.params(l,e.captures||[],e.params),e.params=e.request.params,e.routerPath=b.path,e.routerName=b.name||void 0,e._matchedRoute=b.path,b.name&&(e._matchedRouteName=b.name),d()},...b.stack);return c}routes(){return this.middleware()}on(I,l){return this._events.register(WuI(I),l),this}allowedMethods(I={}){let l=this.methods;return(G,c)=>{let b=G;return c().then(()=>{if(!this._shouldProcessAllowedMethods(b))return;let Z=b.matched||[],d=this._collectAllowedMethods(Z),e=Object.keys(d),a=G.method.toUpperCase();if(!l.includes(a)){this._handleNotImplemented(b,e,I);return}if(a==="OPTIONS"&&e.length>0){this._handleOptionsRequest(b,e);return}e.length>0&&!d[a]&&this._handleMethodNotAllowed(b,e,I)})}}_shouldProcessAllowedMethods(I){return!!(I.matched&&(!I.status||I.status===404))}_collectAllowedMethods(I){let l={};for(let G of I)for(let c of G.methods)l[c]=c;return l}_handleNotImplemented(I,l,G){if(G.throw)throw typeof G.notImplemented=="function"?G.notImplemented():new pi.default.NotImplemented;I.status=501,I.set("Allow",l.join(", "))}_handleOptionsRequest(I,l){I.status=200,I.body="",I.set("Allow",l.join(", "))}_handleMethodNotAllowed(I,l,G){if(G.throw)throw typeof G.methodNotAllowed=="function"?G.methodNotAllowed():new pi.default.MethodNotAllowed;I.status=405,I.set("Allow",l.join(", "))}all(...I){let l,G,c;if(I.length>=2&&(typeof I[1]=="string"||I[1]instanceof RegExp)?(l=I[0],G=I[1],c=I.slice(2)):(l=void 0,G=I[0],c=I.slice(1)),typeof G!="string"&&!(G instanceof RegExp)&&(!Array.isArray(G)||G.length===0))throw new Error("You have to provide a path when adding an all handler");let b={name:l,pathAsRegExp:G instanceof RegExp};return this.register(G,S9,c,{...this.opts,...b}),this}redirect(I,l,G){let c=I,b=l;if(typeof I=="symbol"||typeof I=="string"&&I[0]!=="/"){let d=this.url(I);if(d instanceof Error)throw d;c=d}if(typeof l=="symbol"||typeof l=="string"&&l[0]!=="/"&&!l.includes("://")){let d=this.url(l);if(d instanceof Error)throw d;b=d}return this.all(c,d=>{d.redirect(b),d.status=G||301})}register(I,l,G,c={}){let b={...this.opts,...c};if(Array.isArray(I))return this._registerMultiplePaths(I,l,G,b);let Z=this._createRouteLayer(I,l,G,b);return this.opts.prefix&&Z.setPrefix(this.opts.prefix),uuI(Z,this.params),this.stack.push(Z),hi("defined route %s %s",Z.methods,Z.path),Z}_registerMultiplePaths(I,l,G,c){for(let b of I)this.register.call(this,b,l,G,c);return this}_createRouteLayer(I,l,G,c){return new z9(I,l,G,{end:c.end===!1?c.end:!0,name:c.name,sensitive:c.sensitive||!1,strict:c.strict||!1,prefix:c.prefix||"",ignoreCaptures:c.ignoreCaptures,pathAsRegExp:c.pathAsRegExp})}route(I){return this.stack.find(G=>G.name===I)||!1}url(I,...l){let G=this.route(I);return G?G.url(...l):new Error(`No route found for name: ${String(I)}`)}match(I,l){let G={path:[],pathAndMethod:[],route:!1},c=l.toUpperCase();for(let b of this.stack)if(hi("test %s %s",b.path,b.regexp),b.match(I)){G.path.push(b);let Z=b.methods.length===0,d=b.methods.includes(c);(Z||d)&&(G.pathAndMethod.push(b),b.methods.length>0&&(G.route=!0))}return G}matchHost(I){let{host:l}=this;return l?I?typeof l=="string"?I===l:Array.isArray(l)?l.includes(I):l instanceof RegExp?l.test(I):!1:!1:!0}param(I,l){this.params[I]||(this.params[I]=[]),Array.isArray(this.params[I])||(this.params[I]=[this.params[I]]),this.params[I].push(l);for(let G of this.stack)G.param(I,l);return this}_registerMethod(I,...l){let G,c,b;if(l.length>=2&&(typeof l[1]=="string"||l[1]instanceof RegExp)?(G=l[0],c=l[1],b=l.slice(2)):(G=void 0,c=l[0],b=l.slice(1)),typeof c!="string"&&!(c instanceof RegExp)&&(!Array.isArray(c)||c.length===0))throw new Error(`You have to provide a path when adding a ${I} handler`);let Z={name:G,pathAsRegExp:c instanceof RegExp};return this.register(c,[I],b,{...this.opts,...Z}),this}get(...I){return this._registerMethod("get",...I)}post(...I){return this._registerMethod("post",...I)}put(...I){return this._registerMethod("put",...I)}patch(...I){return this._registerMethod("patch",...I)}delete(...I){return this._registerMethod("delete",...I)}del(...I){return this.delete.apply(this,I)}head(...I){return this._registerMethod("head",...I)}options(...I){return this._registerMethod("options",...I)}},RuI=ui,O=RuI;for(let I of S9)huI.includes(I)||I in ui.prototype||Object.defineProperty(ui.prototype,I,{value:function(...G){return this._registerMethod(I,...G)},writable:!0,configurable:!0,enumerable:!1});var IV=require("fs"),$Y=require("path");qd();xI();var PuI="0.6.12",Ba="";function _uI(){let I=[(0,$Y.resolve)(__dirname,"../../package.json"),(0,$Y.resolve)(__dirname,"../../../../package.json"),(0,$Y.resolve)(process.cwd(),"package.json")];for(let l of I)if((0,IV.existsSync)(l))try{let G=JSON.parse((0,IV.readFileSync)(l,"utf-8"));if(G?.name&&G?.version)return{name:String(G.name),version:String(G.version)}}catch{}return null}var Cx=_uI(),Oa=PuI||Cx?.version||"";function lV(){return!!(x.update.enabled&&x.update.packageName&&x.update.registry&&x.update.cliBin)}function Ax(){if(lV())return!1;let I=(process.env.HERMES_WEB_UI_DISABLE_UPDATE_CHECK||"").trim().toLowerCase();return I==="true"||I==="1"||I==="on"||I==="yes"}async function Jx(){if(lV())try{let I=x.update.packageName||Cx?.name||"hermes-web-ui",l=x.update.registry||"https://registry.npmjs.org",G=x.update.distTag||"latest",c=encodeURIComponent(I),b=`${l}/${c}`,Z=await fetch(b,{signal:AbortSignal.timeout(1e4)});if(Z.ok){let d=await Z.json(),e=d["dist-tags"]?.[G]||d.version||d["dist-tags"]?.latest;e&&(Ba=e,Oa&&Ba!==Oa&&console.log(`Update available: ${Oa} \u2192 ${Ba}`))}}catch{}}function Ai(){!lV()||Ax()||(setTimeout(Jx,5e3),setInterval(Jx,1800*1e3))}async function Lx(I){let G=(await _Y()).split(`
268
+ `),Z.destroy();return}l.handleUpgrade(b,Z,d,a=>{l.emit("connection",a,b)})}})}),l.on("connection",(c,b)=>{let Z=b.kanbanBoard||"default",d=Y9({board:Z,interval:.5}),e=!1;Wt(c,{type:"connected",board:Z});let a=()=>{e||(e=!0,d.killed||d.kill())};d.stdout?.on("data",E9(n=>{n.toLowerCase().startsWith("watching kanban events")||Wt(c,{type:"event",board:Z})})),d.stderr?.on("data",E9(n=>{Wt(c,{type:"error",board:Z,message:n})})),d.on("error",n=>{i.error(n,"Hermes CLI: kanban watch failed"),Wt(c,{type:"error",board:Z,message:n.message}),c.readyState===c.OPEN&&c.close()}),d.on("exit",(n,W)=>{Wt(c,{type:"stopped",board:Z,code:n,signal:W}),c.readyState===c.OPEN&&c.close()}),c.on("close",a),c.on("error",a)}),i.info("WebSocket ready at /api/hermes/kanban/events (kanban watch bridge)")}var B9=z(dW(),1),muI=z(kN(),1),M9=z(dW(),1),pi=z(kN(),1),UY=require("url"),ka=z(x9(),1),f9=z(require("http"),1),K9=z(ml(),1),O9={NotFound:"not-found"};function WuI(I){return typeof I=="function"?I(O9):I}var tuI=class{_handlers=new Map;register(I,l){let G=this._handlers.get(I)??[];G.push(l),this._handlers.set(I,G)}emit(I,l,G){let c=this._handlers.get(I);return c&&c.length>0?(0,B9.default)(c)(l,G):G()}};function zY(I,l={}){let G={...l};"strict"in G&&!("trailing"in G)&&(G.trailing=G.strict!==!0,delete G.strict),delete G.pathAsRegExp,delete G.ignoreCaptures,delete G.prefix;let{regexp:c,keys:b}=(0,ka.pathToRegexp)(I,G);return{regexp:c,keys:b}}function NuI(I,l={}){return(0,ka.compile)(I,l)}function suI(I,l){return(0,ka.parse)(I,l)}function Vi(I={}){let l={sensitive:I.sensitive,end:I.end,strict:I.strict,trailing:I.trailing};"strict"in l&&!("trailing"in l)&&(l.trailing=l.strict!==!0,delete l.strict);for(let G of Object.keys(l))l[G]===void 0&&delete l[G];return l}function YuI(I){try{return decodeURIComponent(I)}catch{return I}}var z9=class{opts;name;methods;paramNames;stack;path;regexp;constructor(I,l,G,c={}){this.opts=c,this.name=this.opts.name||void 0,this.methods=this._normalizeHttpMethods(l),this.stack=this._normalizeAndValidateMiddleware(G,l,I),this.path=I,this.paramNames=[],this._configurePathMatching()}_normalizeHttpMethods(I){let l=[];for(let G of I){let c=G.toUpperCase();l.push(c),c==="GET"&&l.unshift("HEAD")}return l}_normalizeAndValidateMiddleware(I,l,G){let c=Array.isArray(I)?I:[I];for(let b of c){let Z=typeof b;if(Z!=="function"){let d=this.opts.name||G;throw new Error(`${l.toString()} \`${d}\`: \`middleware\` must be a function, not \`${Z}\``)}}return c}_configurePathMatching(){this.opts.pathAsRegExp===!0?this.regexp=this.path instanceof RegExp?this.path:new RegExp(this.path):this.path&&this._configurePathToRegexp()}_configurePathToRegexp(){let I=Vi(this.opts),{regexp:l,keys:G}=zY(this.path,I);this.regexp=l,this.paramNames=G}match(I){return this.regexp.test(I)}params(I,l,G={}){let c={...G};for(let[b,Z]of l.entries()){let d=this.paramNames[b];if(d&&Z&&Z.length>0){let e=d.name;c[e]=YuI(Z)}}return c}captures(I){if(this.opts.ignoreCaptures)return[];let l=I.match(this.regexp);return l?l.slice(1):[]}url(...I){if(this.path instanceof RegExp)throw new TypeError("Cannot generate URL for routes defined with RegExp paths. Use string paths with named parameters instead.");let{params:l,options:G}=this._parseUrlArguments(I),c=this.path.replaceAll("(.*)",""),b=NuI(c,{encode:encodeURIComponent,...G}),Z=this._buildParamReplacements(l,c),d=b(Z);return G&&G.query?this._addQueryString(d,G.query):d}_parseUrlArguments(I){let l=I[0]??{},G=I[1];if(typeof l!="object"||l===null){let c=[...I],b=c.at(-1);typeof b=="object"&&b!==null?(G=b,l=c.slice(0,-1)):l=c}else if(l&&!G){let c=Object.keys(l);if(c.length===1&&c[0]==="query")G=l,l={};else if("query"in l&&l.query){let{query:Z,...d}=l;G={query:Z},l=d}}return{params:l,options:G}}_buildParamReplacements(I,l){let{tokens:G}=suI(l),c=G.some(Z=>"name"in Z&&Z.name),b={};if(Array.isArray(I)){let Z=0;for(let d of G)"name"in d&&d.name&&(b[d.name]=String(I[Z++]))}else if(c&&typeof I=="object"&&!("query"in I))for(let[Z,d]of Object.entries(I))b[Z]=String(d);return b}_addQueryString(I,l){let G=(0,UY.parse)(I),c={...G,query:G.query??void 0};return typeof l=="string"?(c.search=l,c.query=void 0):(c.search=void 0,c.query=l),(0,UY.format)(c)}param(I,l){let G=this.stack,c=this.paramNames,b=this._createParamMiddleware(I,l),Z=c.map(e=>e.name),d=Z.indexOf(I);return d!==-1&&this._insertParamMiddleware(G,b,Z,d),this}_createParamMiddleware(I,l){let G=((c,b)=>(c._matchedParams||(c._matchedParams=new WeakMap),c._matchedParams.has(l)?b():(c._matchedParams.set(l,!0),l(c.params[I],c,b))));return G.param=I,G._originalFn=l,G}_insertParamMiddleware(I,l,G,c){let b=!1;for(let Z=0;Z<I.length;Z++){let d=I[Z];if(!d.param){I.splice(Z,0,l),b=!0;break}if(G.indexOf(d.param)>c){I.splice(Z,0,l),b=!0;break}}b||I.push(l)}setPrefix(I){return this.path?this.path instanceof RegExp?this:(this.path=this._applyPrefix(I),this._reconfigurePathMatching(I),this):this}_applyPrefix(I){let l=this.path==="/",G=this.opts.strict===!0,c=I.includes(":"),b=this.opts.pathAsRegExp===!0&&typeof this.path=="string";if(c&&b){let Z=this.path;(Z===String.raw`(?:\/|$)`||Z===String.raw`(?:\\\/|$)`)&&(this.path="{/*rest}",this.opts.pathAsRegExp=!1)}return l&&!G?I:`${I}${this.path}`}_reconfigurePathMatching(I){let l=this.opts.pathAsRegExp===!0;if(I&&I.includes(":")&&l){let c=Vi(this.opts),{regexp:b,keys:Z}=zY(this.path,c);this.regexp=b,this.paramNames=Z,this.opts.pathAsRegExp=!1}else if(l){let c=this.path,b=c.startsWith("^")?c:`^${c}`;this.regexp=this.path instanceof RegExp?this.path:new RegExp(b)}else{let c=Vi(this.opts),{regexp:b,keys:Z}=zY(this.path,c);this.regexp=b,this.paramNames=Z}}};function VuI(){return f9.default.METHODS.map(I=>I.toLowerCase())}var huI=["get","post","put","patch","delete","del","head","options"];function puI(I){return I?Array.isArray(I)?I:[I]:[]}function j9(I,l,G){let c=puI(G);for(let b of c)I.param(l,b)}function uuI(I,l){let G=Object.keys(l);for(let c of G){let b=l[c];j9(I,c,b)}}function U9(I,l={}){if(!I)return!1;let{keys:G}=zY(I,l);return G.length>0}function ouI(I,l){return I!==void 0?typeof I=="string"?I===""?{path:"{/*rest}",pathAsRegExp:!1}:I==="/"?{path:"/",pathAsRegExp:!1}:{path:I,pathAsRegExp:!1}:{path:I,pathAsRegExp:!0}:l?{path:"{/*rest}",pathAsRegExp:!1}:{path:String.raw`(?:\/|$)`,pathAsRegExp:!0}}var hi=(0,K9.default)("koa-router"),S9=VuI(),ui=class{opts;methods;exclusive;params;stack;host;_events=new tuI;constructor(I={}){this.opts=I,this.methods=this.opts.methods||["HEAD","OPTIONS","GET","PUT","PATCH","POST","DELETE"],this.exclusive=!!this.opts.exclusive,this.params={},this.stack=[],this.host=this.opts.host}static url(I,...l){return new z9(I,[],()=>{}).url(...l)}use(...I){let l;if(this._isPathArray(I[0]))return this._useWithPathArray(I);let G=this._hasExplicitPath(I[0]);if(G&&(l=I.shift()),I.length===0)throw new Error("You must provide at least one middleware function to router.use()");for(let c of I)this._isNestedRouter(c)?this._mountNestedRouter(c,l):this._registerMiddleware(c,l,G);return this}_isPathArray(I){return Array.isArray(I)&&I.length>0&&I.every(l=>typeof l=="string")}_hasExplicitPath(I){return typeof I=="string"||I instanceof RegExp}_isNestedRouter(I){return typeof I=="function"&&"router"in I&&I.router!==void 0}_useWithPathArray(I){let l=I[0],G=I.slice(1);for(let c of l)Reflect.apply(this.use,this,[c,...G]);return this}_mountNestedRouter(I,l){let G=I.router,c=this._cloneRouter(G),b=l&&typeof l=="string"&&U9(l,this.opts);for(let Z=0;Z<c.stack.length;Z++){let d=c.stack[Z],e=this._cloneLayer(d);l&&typeof l=="string"&&e.setPrefix(l),this.opts.prefix&&e.setPrefix(this.opts.prefix),e.methods.length===0&&b&&(e.opts.ignoreCaptures=!1),this.stack.push(e),c.stack[Z]=e}this.params&&this._applyParamMiddlewareToRouter(c)}_cloneRouter(I){return Object.assign(Object.create(Object.getPrototypeOf(I)),I,{stack:[...I.stack]})}_cloneLayer(I){return Object.assign(Object.create(Object.getPrototypeOf(I)),I,{stack:[...I.stack],methods:[...I.methods],paramNames:[...I.paramNames],opts:{...I.opts}})}_applyParamMiddlewareToRouter(I){let l=Object.keys(this.params);for(let G of l){let c=this.params[G];j9(I,G,c)}}_registerMiddleware(I,l,G){let c=U9(this.opts.prefix||"",this.opts),b=(()=>{if(l!==void 0)return l;if(c)return""})(),Z=G||l===void 0&&c,{path:d,pathAsRegExp:e}=ouI(b,c),a=d,n=e,W=Z&&d==="/";Z&&typeof d=="string"&&(a=d,n=!1),this.register(a,[],I,{end:W,ignoreCaptures:!Z&&!c,pathAsRegExp:n})}prefix(I){let l=I.replace(/\/$/,""),G=this.opts.prefix||"";this.opts.prefix=l;for(let c of this.stack){if(typeof c.path=="string"&&G){let b=G+"/";(c.path===G||c.path.startsWith(b))&&(c.path=c.path.slice(G.length)||"/")}c.setPrefix(l)}return this}middleware(){let I=function(l,G){if(hi("%s %s",l.method,l.path),!this.matchHost(l.host))return G();let c=this._getRequestPath(l),b=this.match(c,l.method);if(this._storeMatchedRoutes(l,b),l.router=this,l.routeMatched=b.route,!b.route)return this._events.emit(O9.NotFound,l,G);let Z=b.pathAndMethod;this._setMatchedRouteInfo(l,Z);let d=this._buildMiddlewareChain(Z,c);return(0,M9.default)(d)(l,G)}.bind(this);return I.router=this,I}_getRequestPath(I){let l=I;return this.opts.routerPath||l.newRouterPath||l.path||l.routerPath||""}_storeMatchedRoutes(I,l){let G=I;G.matched?G.matched.push(...l.path):G.matched=l.path}_setMatchedRouteInfo(I,l){let G=I,c=l.toReversed().find(b=>b.methods.length>0);c&&(G._matchedRoute=c.path,c.name&&(G._matchedRouteName=c.name))}_buildMiddlewareChain(I,l){let G;if(this.exclusive){let b;if(this.opts.exclusive==="specificity")for(let Z of I)(!b||Z.paramNames.length<b.paramNames.length)&&(b=Z);else b=I.at(-1);G=b?[b]:[]}else G=I;let c=[];for(let b of G)c.push((Z,d)=>{let e=Z;return e.captures=b.captures(l),e.request.params=b.params(l,e.captures||[],e.params),e.params=e.request.params,e.routerPath=b.path,e.routerName=b.name||void 0,e._matchedRoute=b.path,b.name&&(e._matchedRouteName=b.name),d()},...b.stack);return c}routes(){return this.middleware()}on(I,l){return this._events.register(WuI(I),l),this}allowedMethods(I={}){let l=this.methods;return(G,c)=>{let b=G;return c().then(()=>{if(!this._shouldProcessAllowedMethods(b))return;let Z=b.matched||[],d=this._collectAllowedMethods(Z),e=Object.keys(d),a=G.method.toUpperCase();if(!l.includes(a)){this._handleNotImplemented(b,e,I);return}if(a==="OPTIONS"&&e.length>0){this._handleOptionsRequest(b,e);return}e.length>0&&!d[a]&&this._handleMethodNotAllowed(b,e,I)})}}_shouldProcessAllowedMethods(I){return!!(I.matched&&(!I.status||I.status===404))}_collectAllowedMethods(I){let l={};for(let G of I)for(let c of G.methods)l[c]=c;return l}_handleNotImplemented(I,l,G){if(G.throw)throw typeof G.notImplemented=="function"?G.notImplemented():new pi.default.NotImplemented;I.status=501,I.set("Allow",l.join(", "))}_handleOptionsRequest(I,l){I.status=200,I.body="",I.set("Allow",l.join(", "))}_handleMethodNotAllowed(I,l,G){if(G.throw)throw typeof G.methodNotAllowed=="function"?G.methodNotAllowed():new pi.default.MethodNotAllowed;I.status=405,I.set("Allow",l.join(", "))}all(...I){let l,G,c;if(I.length>=2&&(typeof I[1]=="string"||I[1]instanceof RegExp)?(l=I[0],G=I[1],c=I.slice(2)):(l=void 0,G=I[0],c=I.slice(1)),typeof G!="string"&&!(G instanceof RegExp)&&(!Array.isArray(G)||G.length===0))throw new Error("You have to provide a path when adding an all handler");let b={name:l,pathAsRegExp:G instanceof RegExp};return this.register(G,S9,c,{...this.opts,...b}),this}redirect(I,l,G){let c=I,b=l;if(typeof I=="symbol"||typeof I=="string"&&I[0]!=="/"){let d=this.url(I);if(d instanceof Error)throw d;c=d}if(typeof l=="symbol"||typeof l=="string"&&l[0]!=="/"&&!l.includes("://")){let d=this.url(l);if(d instanceof Error)throw d;b=d}return this.all(c,d=>{d.redirect(b),d.status=G||301})}register(I,l,G,c={}){let b={...this.opts,...c};if(Array.isArray(I))return this._registerMultiplePaths(I,l,G,b);let Z=this._createRouteLayer(I,l,G,b);return this.opts.prefix&&Z.setPrefix(this.opts.prefix),uuI(Z,this.params),this.stack.push(Z),hi("defined route %s %s",Z.methods,Z.path),Z}_registerMultiplePaths(I,l,G,c){for(let b of I)this.register.call(this,b,l,G,c);return this}_createRouteLayer(I,l,G,c){return new z9(I,l,G,{end:c.end===!1?c.end:!0,name:c.name,sensitive:c.sensitive||!1,strict:c.strict||!1,prefix:c.prefix||"",ignoreCaptures:c.ignoreCaptures,pathAsRegExp:c.pathAsRegExp})}route(I){return this.stack.find(G=>G.name===I)||!1}url(I,...l){let G=this.route(I);return G?G.url(...l):new Error(`No route found for name: ${String(I)}`)}match(I,l){let G={path:[],pathAndMethod:[],route:!1},c=l.toUpperCase();for(let b of this.stack)if(hi("test %s %s",b.path,b.regexp),b.match(I)){G.path.push(b);let Z=b.methods.length===0,d=b.methods.includes(c);(Z||d)&&(G.pathAndMethod.push(b),b.methods.length>0&&(G.route=!0))}return G}matchHost(I){let{host:l}=this;return l?I?typeof l=="string"?I===l:Array.isArray(l)?l.includes(I):l instanceof RegExp?l.test(I):!1:!1:!0}param(I,l){this.params[I]||(this.params[I]=[]),Array.isArray(this.params[I])||(this.params[I]=[this.params[I]]),this.params[I].push(l);for(let G of this.stack)G.param(I,l);return this}_registerMethod(I,...l){let G,c,b;if(l.length>=2&&(typeof l[1]=="string"||l[1]instanceof RegExp)?(G=l[0],c=l[1],b=l.slice(2)):(G=void 0,c=l[0],b=l.slice(1)),typeof c!="string"&&!(c instanceof RegExp)&&(!Array.isArray(c)||c.length===0))throw new Error(`You have to provide a path when adding a ${I} handler`);let Z={name:G,pathAsRegExp:c instanceof RegExp};return this.register(c,[I],b,{...this.opts,...Z}),this}get(...I){return this._registerMethod("get",...I)}post(...I){return this._registerMethod("post",...I)}put(...I){return this._registerMethod("put",...I)}patch(...I){return this._registerMethod("patch",...I)}delete(...I){return this._registerMethod("delete",...I)}del(...I){return this.delete.apply(this,I)}head(...I){return this._registerMethod("head",...I)}options(...I){return this._registerMethod("options",...I)}},RuI=ui,O=RuI;for(let I of S9)huI.includes(I)||I in ui.prototype||Object.defineProperty(ui.prototype,I,{value:function(...G){return this._registerMethod(I,...G)},writable:!0,configurable:!0,enumerable:!1});var IV=require("fs"),$Y=require("path");qd();xI();var PuI="0.6.13",Ba="";function _uI(){let I=[(0,$Y.resolve)(__dirname,"../../package.json"),(0,$Y.resolve)(__dirname,"../../../../package.json"),(0,$Y.resolve)(process.cwd(),"package.json")];for(let l of I)if((0,IV.existsSync)(l))try{let G=JSON.parse((0,IV.readFileSync)(l,"utf-8"));if(G?.name&&G?.version)return{name:String(G.name),version:String(G.version)}}catch{}return null}var Cx=_uI(),Oa=PuI||Cx?.version||"";function lV(){return!!(x.update.enabled&&x.update.packageName&&x.update.registry&&x.update.cliBin)}function Ax(){if(lV())return!1;let I=(process.env.HERMES_WEB_UI_DISABLE_UPDATE_CHECK||"").trim().toLowerCase();return I==="true"||I==="1"||I==="on"||I==="yes"}async function Jx(){if(lV())try{let I=x.update.packageName||Cx?.name||"hermes-web-ui",l=x.update.registry||"https://registry.npmjs.org",G=x.update.distTag||"latest",c=encodeURIComponent(I),b=`${l}/${c}`,Z=await fetch(b,{signal:AbortSignal.timeout(1e4)});if(Z.ok){let d=await Z.json(),e=d["dist-tags"]?.[G]||d.version||d["dist-tags"]?.latest;e&&(Ba=e,Oa&&Ba!==Oa&&console.log(`Update available: ${Oa} \u2192 ${Ba}`))}}catch{}}function Ai(){!lV()||Ax()||(setTimeout(Jx,5e3),setInterval(Jx,1800*1e3))}async function Lx(I){let G=(await _Y()).split(`
269
269
  `)[0].replace("Hermes Agent ","")||"",c=lV(),b=Ax();I.body={status:"ok",platform:"hermes-agent",version:G,gateway:"running",webui_version:Oa,webui_latest:b?"":Ba,webui_update_enabled:c,webui_update_source_label:c?x.update.sourceLabel:"",webui_update_available:b?!1:!!(Oa&&Ba&&Ba!==Oa),node_version:process.versions.node}}var Li=new O;Li.get("/health",Lx);GI();async function kx(I){let l=I.request.body;if(!l||!l.event){I.status=400,I.body={error:"Missing event field"};return}i.info("Received webhook event: %s",l.event),I.body={ok:!0}}var ki=new O;ki.post("/webhook",kx);var Ux=require("crypto"),cV=require("fs/promises"),Bx=require("path");hI();var GV=require("path");xI();CG();function loI(I){let l=(I||"default").trim()||"default";if(l.includes("/")||l.includes("\\")||l.includes(".."))throw Object.assign(new Error("Invalid profile name"),{code:"invalid_profile"});return l}function xx(I){return(0,GV.resolve)((0,GV.join)(x.uploadDir,loI(I)))}var zx=50*1024*1024;function GoI(I){return I.state?.profile?.name||lI()||"default"}async function Ox(I){let l=I.get("content-type")||"";if(!l.startsWith("multipart/form-data")){I.status=400,I.body={error:"Expected multipart/form-data"};return}let G="--"+l.split("boundary=")[1];if(!G||G==="--undefined"){I.status=400,I.body={error:"Missing boundary"};return}let c=[],b=0;for await(let W of I.req){if(b+=W.length,b>zx){I.status=413,I.body={error:`File too large (max ${zx/1024/1024}MB)`};return}c.push(W)}let Z=Buffer.concat(c),d=Buffer.from(G),e=coI(Z,d),a=[],n=xx(GoI(I));await(0,cV.mkdir)(n,{recursive:!0});for(let W of e){let t=W.indexOf(Buffer.from(`\r
270
270
  \r
271
271
  `));if(t===-1)continue;let N=W.subarray(0,t).toString("utf-8"),s=W.subarray(t+4,W.length-2),Y="",h=N.match(/filename\*=UTF-8''(.+)/i);if(h)Y=decodeURIComponent(h[1]);else{let u=N.match(/filename="([^"]+)"/);if(!u)continue;Y=u[1]}let o=Y.includes(".")?"."+Y.split(".").pop():"",p=(0,Ux.randomBytes)(8).toString("hex")+o,V=(0,Bx.join)(n,p);await(0,cV.writeFile)(V,s),a.push({name:Y,path:V})}I.body={files:a}}function coI(I,l){let G=[],c=0;for(;;){let b=I.indexOf(l,c);if(b===-1)break;c>0&&G.push(I.subarray(c+2,b)),c=b+l.length}return G}var xi=new O;xi.post("/upload",Ox);var Mb=new O;Mb.post("/api/hermes/update",NL);Mb.get("/api/hermes/update/preview",sL);Mb.get("/api/hermes/update/preview/tags",YL);Mb.post("/api/hermes/update/preview/prepare",VL);Mb.post("/api/hermes/update/preview/install",hL);Mb.post("/api/hermes/update/preview/start",pL);Mb.post("/api/hermes/update/preview/stop",uL);hI();async function fx(I){I.body={hasPasswordLogin:!0,hasUsers:gY()>0}}async function jx(I){let l=I.state.user?.id,G=l?bc(l):null;if(!G){I.status=404,I.body={error:"User not found"};return}I.body={user:{id:G.id,username:G.username,role:G.role,status:G.status,created_at:G.created_at,updated_at:G.updated_at,last_login_at:G.last_login_at,avatar:G.avatar||"",requiresCredentialChange:process.env.HERMES_DESKTOP==="true"?!1:G.username===et&&at(yY,G.password_hash)}}}var zi=500*1024;function Mx(I){if(!I||typeof I!="object")return{ok:!1,error:"Invalid avatar payload"};let l=I,G=l.type;if(G!=="image"&&G!=="default")return{ok:!1,error:'Avatar type must be "image" or "default"'};if(G==="image"){if(typeof l.dataUrl!="string"||!l.dataUrl.startsWith("data:image/"))return{ok:!1,error:"Image avatar must include a dataUrl"};if(l.dataUrl.length>zi)return{ok:!1,error:`Avatar image is too large (max ${zi} bytes)`}}return l.seed!=null&&typeof l.seed!="string"?{ok:!1,error:"Avatar seed must be a string"}:{ok:!0,json:JSON.stringify(I)}}async function Kx(I){let l=I.state.user?.id;if(!l){I.status=401,I.body={error:"Unauthorized"};return}I.body={avatar:Ja(l)}}async function Sx(I){let l=I.state.user?.id;if(!l){I.status=401,I.body={error:"Unauthorized"};return}let G=I.request.body,c=G&&Object.prototype.hasOwnProperty.call(G,"avatar")?G.avatar:G;if(typeof c=="string"){if(c.length>zi*2){I.status=400,I.body={error:"Avatar string is too large"};return}try{let d=JSON.parse(c),e=Mx(d);if(!e.ok){I.status=400,I.body={error:e.error};return}if(!Ii(l,c)){I.status=500,I.body={error:"Failed to save avatar"};return}I.body={success:!0,avatar:c};return}catch{I.status=400,I.body={error:"Avatar string is not valid JSON"};return}}let b=Mx(c);if(!b.ok){I.status=400,I.body={error:b.error};return}if(!Ii(l,b.json)){I.status=500,I.body={error:"Failed to save avatar"};return}I.body={success:!0,avatar:b.json}}async function Tx(I){let{username:l,password:G}=I.request.body;if(!l||!G){I.status=400,I.body={error:"Username and password are required"};return}let c=SR(I),b=iC(c);if(!b.allowed){I.status=b.status,I.body={error:"Too many login attempts, please try again later"};return}let Z=gY(),d=Z===0?K3(l,G):yc(l);if(!d||d.status!=="active"||Z>0&&!at(G,d.password_hash)){FC(c),I.status=401,I.body={error:"Invalid username or password"};return}let e;try{e=await P3(d)}catch(a){I.status=500,I.body={error:a?.message||"Failed to issue login token"};return}XC(c),I.body={token:e}}async function Dx(I){I.status=400,I.body={error:"Password login is managed by user accounts"}}async function qx(I){let{currentPassword:l,newPassword:G}=I.request.body;if(!l||!G){I.status=400,I.body={error:"Current password and new password are required"};return}if(G.length<6){I.status=400,I.body={error:"New password must be at least 6 characters"};return}let c=I.state.user?.id,b=c?bc(c):null;if(!b||!at(l,b.password_hash)){I.status=400,I.body={error:"Current password is incorrect"};return}U3(b.id,G),I.body={success:!0}}async function Px(I){let{currentPassword:l,newUsername:G}=I.request.body;if(!l||!G){I.status=400,I.body={error:"Current password and new username are required"};return}if(G.length<2){I.status=400,I.body={error:"Username must be at least 2 characters"};return}let c=I.state.user?.id,b=c?bc(c):null;if(!b||!at(l,b.password_hash)){I.status=400,I.body={error:"Current password is incorrect"};return}let Z=yc(G);if(Z&&Z.id!==b.id){I.status=409,I.body={error:"Username already exists"};return}B3(b.id,G),I.body={success:!0}}async function _x(I){I.status=400,I.body={error:"Password login cannot be removed for user accounts"}}function $x(I){return I==="super_admin"||I==="admin"?I:null}function Iz(I){return I==="active"||I==="disabled"?I:null}function lz(I){return Array.isArray(I)?[...new Set(I.map(l=>String(l||"").trim()).filter(Boolean))]:[]}function Gz(I){let l=new Set(BI());return I.find(c=>!l.has(c))||null}async function cz(I){I.body={users:nt(),profiles:BI()}}async function bz(I){let l=I.request.body,G=String(l.username||"").trim(),c=String(l.password||""),b=$x(l.role||"admin"),Z=Iz(l.status||"active"),d=lz(l.profiles);if(G.length<2){I.status=400,I.body={error:"Username must be at least 2 characters"};return}if(c.length<6){I.status=400,I.body={error:"Password must be at least 6 characters"};return}if(!b||!Z){I.status=400,I.body={error:"Invalid role or status"};return}if(yc(G)){I.status=409,I.body={error:"Username already exists"};return}let e=Gz(d);if(e){I.status=400,I.body={error:`Profile "${e}" does not exist`};return}let a=O3({username:G,password:c,role:b,status:Z,profiles:b==="super_admin"?[]:d,defaultProfile:l.defaultProfile});I.status=201,I.body={user:a,users:nt()}}async function Zz(I){let l=Number(I.params.id),G=Number.isInteger(l)?bc(l):null;if(!G){I.status=404,I.body={error:"User not found"};return}let c=I.request.body,b=c.username==null?void 0:String(c.username).trim(),Z=c.password==null?void 0:String(c.password),d=c.role==null?void 0:$x(c.role),e=c.status==null?void 0:Iz(c.status),a=c.profiles==null?void 0:lz(c.profiles);if(b!==void 0&&b.length<2){I.status=400,I.body={error:"Username must be at least 2 characters"};return}if(Z!==void 0&&Z.length>0&&Z.length<6){I.status=400,I.body={error:"Password must be at least 6 characters"};return}if(c.role!=null&&!d||c.status!=null&&!e){I.status=400,I.body={error:"Invalid role or status"};return}if(b&&b!==G.username){let m=yc(b);if(m&&m.id!==G.id){I.status=409,I.body={error:"Username already exists"};return}}let n=d||G.role,W=e||G.status,t=I.state.user?.id;if(G.id===t&&W!=="active"){I.status=400,I.body={error:"You cannot disable your own account"};return}if(G.role==="super_admin"&&G.status==="active"&&(n!=="super_admin"||W!=="active")&&$r(G.id)===0){I.status=400,I.body={error:"At least one active super administrator is required"};return}if(a){let m=Gz(a);if(m){I.status=400,I.body={error:`Profile "${m}" does not exist`};return}}M3({userId:G.id,username:b,password:Z||void 0,role:d||void 0,status:e||void 0,profiles:n==="super_admin"?[]:a,defaultProfile:c.defaultProfile}),I.body={user:bc(G.id),users:nt()}}async function dz(I){let l=Number(I.params.id),G=Number.isInteger(l)?bc(l):null;if(!G){I.status=404,I.body={error:"User not found"};return}if(I.state.user?.id===G.id){I.status=400,I.body={error:"You cannot delete your own account"};return}if(G.role==="super_admin"&&G.status==="active"&&$r(G.id)===0){I.status=400,I.body={error:"At least one active super administrator is required"};return}f3(G.id),I.body={success:!0,users:nt()}}async function ez(I){let l=DR();I.body={locks:l}}async function az(I){let l=I.query.ip;if(l){if(!HC(l)){I.status=404,I.body={error:"IP not locked"};return}I.body={success:!0};return}let G=QC();I.body={success:!0,count:G}}var bV=new O;bV.get("/api/auth/status",fx);bV.post("/api/auth/login",Tx);var eG=new O;eG.post("/api/auth/setup",Dx);eG.get("/api/auth/me",jx);eG.post("/api/auth/change-password",qx);eG.post("/api/auth/change-username",Px);eG.get("/api/auth/avatar",Kx);eG.put("/api/auth/avatar",Sx);eG.delete("/api/auth/password",_x);eG.get("/api/auth/users",Bb,cz);eG.post("/api/auth/users",Bb,bz);eG.put("/api/auth/users/:id",Bb,Zz);eG.delete("/api/auth/users/:id",Bb,dz);eG.get("/api/auth/locked-ips",ez);eG.delete("/api/auth/locked-ips",az);gG();Ub();var Yt=class extends Error{constructor(){super("Duplicate pairing request"),this.name="DuplicateDeviceRequestError"}};function doI(I){if(typeof I=="number")return I;if(!I)return Date.now();let l=Date.parse(I);return Number.isNaN(l)?Date.now():l}function eoI(I){return I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:"none"}function aoI(I){return I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:"none"}function Vt(I){let l={type:"",platform:"",release:"",arch:""};try{l=JSON.parse(String(I.os_json||"{}"))}catch{}return{id:String(I.id),device_id:String(I.id),inbound_status:eoI(I.inbound_status||I.status),outbound_status:aoI(I.outbound_status),device_public_key:String(I.device_public_key||""),computer_name:String(I.computer_name||""),endpoint_kind:I.endpoint_kind==="web"||I.endpoint_kind==="desktop"?I.endpoint_kind:"custom",ip:String(I.ip||""),http_port:Number(I.http_port||0),url:String(I.url||""),os:l,hermes_agent_version:String(I.hermes_agent_version||""),hermes_web_ui_version:String(I.hermes_web_ui_version||""),response_ms:Number(I.response_ms||0),requested_at:Number(I.requested_at||0),decided_at:I.decided_at==null?null:Number(I.decided_at),outbound_requested_at:Number(I.outbound_requested_at||0),outbound_decided_at:I.outbound_decided_at==null?null:Number(I.outbound_decided_at),inbound_history_deleted_at:I.inbound_history_deleted_at==null?null:Number(I.inbound_history_deleted_at),last_seen_at:Number(I.last_seen_at||0),updated_at:Number(I.updated_at||0)}}function ZV(I,l,G){return{id:I.id,status:l?.inbound_status||"none",inbound_status:l?.inbound_status||"none",outbound_status:l?.outbound_status||"none",device_public_key:I.device_public_key,computer_name:I.computer_name,endpoint_kind:I.endpoint_kind,ip:I.ip,http_port:I.http_port,url:I.url,os_json:JSON.stringify(I.os||{}),hermes_agent_version:I.hermes_agent_version,hermes_web_ui_version:I.hermes_web_ui_version,response_ms:I.response_ms,requested_at:l?.requested_at||0,decided_at:l?.decided_at||null,outbound_requested_at:l?.outbound_requested_at||0,outbound_decided_at:l?.outbound_decided_at||null,inbound_history_deleted_at:l?.inbound_history_deleted_at||null,last_seen_at:doI(I.last_seen_at),updated_at:G}}function ht(I){let l=f();return l?(l.prepare(`
@@ -297,7 +297,7 @@ const isVersionPreview = import.meta.env.VITE_HERMES_PREVIEW === '1';`)),l=l.rep
297
297
  inbound_history_deleted_at = excluded.inbound_history_deleted_at,
298
298
  last_seen_at = excluded.last_seen_at,
299
299
  updated_at = excluded.updated_at
300
- `).run(I.id,I.status||I.inbound_status||"none",I.inbound_status||"none",I.outbound_status||"none",I.computer_name,I.endpoint_kind,I.ip,I.http_port,I.url,I.os_json,I.hermes_agent_version,I.hermes_web_ui_version,I.response_ms,I.device_public_key,I.requested_at,I.decided_at,I.outbound_requested_at||0,I.outbound_decided_at||null,I.inbound_history_deleted_at||null,I.last_seen_at,I.updated_at),Cc(I.id)):(Ps(AG,I.id,I),Vt(I))}function Ui(){noI();let I=f();return I?I.prepare(`SELECT * FROM ${AG} ORDER BY updated_at DESC`).all().map(Vt):Object.values(kW(AG)).map(Vt).sort((G,c)=>c.updated_at-G.updated_at)}function Cc(I){let l=f();if(!l){let c=qs(AG,I);return c?Vt(c):null}let G=l.prepare(`SELECT * FROM ${AG} WHERE id = ?`).get(I);return G?Vt(G):null}function noI(){let I=f();if(!I){let G=kW(AG),c=0;for(let[b,Z]of Object.entries(G))Z.inbound_history_deleted_at!=null&&(xW(AG,b),c+=1);return c}let l=I.prepare(`DELETE FROM ${AG} WHERE inbound_history_deleted_at IS NOT NULL`).run();return Number(l.changes)}function nz(){return Ui().filter(I=>I.inbound_status!=="none"&&I.inbound_history_deleted_at==null).sort((I,l)=>(l.requested_at||l.updated_at)-(I.requested_at||I.updated_at))}function Wz(I){return ht(ZV(I,Cc(I.id),Date.now()))}function tz(I){let l=Date.now(),G=Cc(I.id),c=ZV(I,G,l);if(G?.inbound_status==="pending")throw new Yt;return G?.inbound_status==="blocked"||G?.inbound_status==="approved"||(c.status="pending",c.inbound_status="pending",c.requested_at=l,c.decided_at=null,c.inbound_history_deleted_at=null),ht(c)}function mz(I,l,G){let c=G?Wz(G):Cc(I);if(!c)throw new Error("Device not found");let b=Date.now(),Z=ZV(c,c,b);return Z.status=l,Z.inbound_status=l,Z.decided_at=l==="pending"||l==="none"?null:b,l==="pending"&&!Z.requested_at&&(Z.requested_at=b),l==="pending"&&(Z.inbound_history_deleted_at=null),ht(Z)}function Bi(I,l,G){let c=Wz(G),b=Date.now(),Z=ZV(c,c,b);return Z.outbound_status=l,l==="pending"?(Z.outbound_requested_at=b,Z.outbound_decided_at=null):Z.outbound_decided_at=b,ht(Z)}function Nz(I){if(!Cc(I))return!1;let G=f();return G?G.prepare(`DELETE FROM ${AG} WHERE id = ?`).run(I).changes>0:(xW(AG,I),!0)}var ji=z(require("dgram")),Vz=require("os");xI();GI();var Wb=require("os"),kZ=require("crypto");var Ma=require("fs/promises"),dV=require("path");xI();qd();var Oi=(0,dV.resolve)(x.appHome,"device-identity.json"),Mi=null;function WoI(){return"0.6.12"}function toI(I){return I.split(`
300
+ `).run(I.id,I.status||I.inbound_status||"none",I.inbound_status||"none",I.outbound_status||"none",I.computer_name,I.endpoint_kind,I.ip,I.http_port,I.url,I.os_json,I.hermes_agent_version,I.hermes_web_ui_version,I.response_ms,I.device_public_key,I.requested_at,I.decided_at,I.outbound_requested_at||0,I.outbound_decided_at||null,I.inbound_history_deleted_at||null,I.last_seen_at,I.updated_at),Cc(I.id)):(Ps(AG,I.id,I),Vt(I))}function Ui(){noI();let I=f();return I?I.prepare(`SELECT * FROM ${AG} ORDER BY updated_at DESC`).all().map(Vt):Object.values(kW(AG)).map(Vt).sort((G,c)=>c.updated_at-G.updated_at)}function Cc(I){let l=f();if(!l){let c=qs(AG,I);return c?Vt(c):null}let G=l.prepare(`SELECT * FROM ${AG} WHERE id = ?`).get(I);return G?Vt(G):null}function noI(){let I=f();if(!I){let G=kW(AG),c=0;for(let[b,Z]of Object.entries(G))Z.inbound_history_deleted_at!=null&&(xW(AG,b),c+=1);return c}let l=I.prepare(`DELETE FROM ${AG} WHERE inbound_history_deleted_at IS NOT NULL`).run();return Number(l.changes)}function nz(){return Ui().filter(I=>I.inbound_status!=="none"&&I.inbound_history_deleted_at==null).sort((I,l)=>(l.requested_at||l.updated_at)-(I.requested_at||I.updated_at))}function Wz(I){return ht(ZV(I,Cc(I.id),Date.now()))}function tz(I){let l=Date.now(),G=Cc(I.id),c=ZV(I,G,l);if(G?.inbound_status==="pending")throw new Yt;return G?.inbound_status==="blocked"||G?.inbound_status==="approved"||(c.status="pending",c.inbound_status="pending",c.requested_at=l,c.decided_at=null,c.inbound_history_deleted_at=null),ht(c)}function mz(I,l,G){let c=G?Wz(G):Cc(I);if(!c)throw new Error("Device not found");let b=Date.now(),Z=ZV(c,c,b);return Z.status=l,Z.inbound_status=l,Z.decided_at=l==="pending"||l==="none"?null:b,l==="pending"&&!Z.requested_at&&(Z.requested_at=b),l==="pending"&&(Z.inbound_history_deleted_at=null),ht(Z)}function Bi(I,l,G){let c=Wz(G),b=Date.now(),Z=ZV(c,c,b);return Z.outbound_status=l,l==="pending"?(Z.outbound_requested_at=b,Z.outbound_decided_at=null):Z.outbound_decided_at=b,ht(Z)}function Nz(I){if(!Cc(I))return!1;let G=f();return G?G.prepare(`DELETE FROM ${AG} WHERE id = ?`).run(I).changes>0:(xW(AG,I),!0)}var ji=z(require("dgram")),Vz=require("os");xI();GI();var Wb=require("os"),kZ=require("crypto");var Ma=require("fs/promises"),dV=require("path");xI();qd();var Oi=(0,dV.resolve)(x.appHome,"device-identity.json"),Mi=null;function WoI(){return"0.6.13"}function toI(I){return I.split(`
301
301
  `)[0]?.replace(/^Hermes Agent\s+/,"").trim()||""}function moI(I){return typeof I?.device_id=="string"&&I.device_id.length>=16&&typeof I?.device_public_key=="string"&&I.device_public_key.includes("PUBLIC KEY")&&typeof I?.device_private_key=="string"&&I.device_private_key.includes("PRIVATE KEY")}function eV(I){return`hwui_${(0,kZ.createHash)("sha256").update(I).digest("base64url").slice(0,32)}`}async function NoI(){try{let G=JSON.parse(await(0,Ma.readFile)(Oi,"utf-8"));if(moI(G))return G}catch{}let I=(0,kZ.generateKeyPairSync)("ed25519",{publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem"}}),l={device_id:eV(I.publicKey),device_public_key:I.publicKey,device_private_key:I.privateKey};return await(0,Ma.mkdir)((0,dV.dirname)(Oi),{recursive:!0}),await(0,Ma.writeFile)(Oi,JSON.stringify(l,null,2),{encoding:"utf-8",mode:384}),l}function sz(){return Mi||(Mi=NoI()),Mi}function Yz(I){return`${I.device_id}.${I.nonce}.${I.timestamp}`}async function pt(I,l){let G=await sz();return(0,kZ.sign)(null,Buffer.from(Yz({device_id:G.device_id,nonce:I,timestamp:l})),G.device_private_key).toString("base64url")}function ut(I){if(eV(I.device_public_key)!==I.device_id)return!1;try{return(0,kZ.verify)(null,Buffer.from(Yz(I)),I.device_public_key,Buffer.from(I.signature,"base64url"))}catch{return!1}}async function Pd(){let I=toI(await _Y()),l=await sz();return{device_id:l.device_id,device_public_key:l.device_public_key,computer_name:(0,Wb.hostname)(),os:{type:(0,Wb.type)(),platform:(0,Wb.platform)(),release:(0,Wb.release)(),arch:(0,Wb.arch)()},hermes_agent_version:I,hermes_web_ui_version:WoI()}}var nV=1,soI=4e4,YoI=[8648,8748],VoI=1e3,fi=null,fa={scanning:!1,last_scanned_at:null,devices:[]},ot=null,aV=null;function hoI(I){let l=String(process.env[I]||"").trim().toLowerCase();return["0","false","no","off"].includes(l)}function hz(){return!hoI("HERMES_LAN_DISCOVERY_ENABLED")}function poI(I){return String(I||"").split(/[\s,]+/).map(l=>Number.parseInt(l,10)).filter(l=>Number.isInteger(l)&&l>0&&l<=65535)}function pz(I){let l=soI+I;if(l>65535)throw new Error(`HTTP port ${I} cannot be mapped to a UDP discovery port`);return l}function rt(I){return I===8648?"web":I===8748?"desktop":"custom"}function uoI(I=x.port){let l=poI(process.env.HERMES_LAN_DISCOVERY_HTTP_PORTS);return[...new Set([...l.length?l:YoI,I])]}function ja(I){let l=I.split(".").map(G=>Number.parseInt(G,10));return l.length!==4||l.some(G=>!Number.isInteger(G)||G<0||G>255)?null:(l[0]<<24>>>0)+(l[1]<<16)+(l[2]<<8)+l[3]>>>0}function ooI(I){return[I>>>24&255,I>>>16&255,I>>>8&255,I&255].join(".")}function uz(I){let l=ja(I);if(l===null)return!1;let G=l>>>24&255,c=l>>>16&255;return G===10||G===127||G===172&&c>=16&&c<=31||G===192&&c===168||G===169&&c===254}function Ki(){try{return Object.values((0,Vz.networkInterfaces)()).flat().filter(I=>I&&I.family==="IPv4"&&!I.internal&&I.address&&I.netmask).map(I=>({address:I.address,netmask:I.netmask}))}catch{return[]}}function RoI(){return new Set(["127.0.0.1",...Ki().map(I=>I.address)])}function roI(I,l){let G=ja(I),c=ja(l);return G===null||c===null?null:ooI((G|~c>>>0)>>>0)}function ioI(I){let l=ja(I),G=Ki();if(l!==null)for(let c of G){let b=ja(c.address),Z=ja(c.netmask);if(b!==null&&Z!==null&&(b&Z)===(l&Z))return c.address}return G[0]?.address||"127.0.0.1"}function FoI(){let I=new Set(["255.255.255.255"]);for(let l of Ki()){let G=roI(l.address,l.netmask);G&&I.add(G)}return[...I]}async function XoI(I){let l=Date.now();if(aV&&aV.expiresAt>l)return aV.value;let G=await I();return aV={value:G,expiresAt:l+6e4},G}function oz(I){try{return JSON.parse(I.toString("utf8"))}catch{return null}}async function HoI(I,l,G,c){let b=await XoI(c),Z=ioI(l);return{type:"hermes.announce",version:nV,request_id:I.request_id,http_port:G,endpoint_kind:rt(G),url:`http://${Z}:${G}`,...b}}function Rz(I={}){if(!hz())return null;if(fi)return fi;let l=I.httpPort||x.port,G=pz(l),c=I.getSystemInfo||Pd,b=ji.default.createSocket("udp4");return b.on("message",(Z,d)=>{if(!uz(d.address))return;let e=oz(Z);!e||e.type!=="hermes.discover"||e.version!==nV||HoI(e,d.address,l,c).then(a=>{let n=Buffer.from(JSON.stringify(a));b.send(n,d.port,d.address)}).catch(a=>i.warn(a,"[lan-discovery] failed to build discovery response"))}),b.on("error",Z=>{i.warn(Z,"[lan-discovery] UDP responder error")}),b.bind(G,"0.0.0.0",()=>{b.setBroadcast(!0),b.unref(),i.info("[lan-discovery] responder listening on udp://0.0.0.0:%d for http port %d",G,l)}),fi=b,b}function QoI(I,l,G,c){if(!I||I.type!=="hermes.announce"||I.version!==nV)return null;let b=Number(I.http_port);if(!Number.isInteger(b)||b<=0||b>65535)return null;let Z=typeof I.device_id=="string"&&I.device_id?I.device_id:"",d=typeof I.device_public_key=="string"?I.device_public_key:"";if(!Z||!d||eV(d)!==Z)return null;let e=I.endpoint_kind==="web"||I.endpoint_kind==="desktop"||I.endpoint_kind==="custom"?I.endpoint_kind:rt(b),a=`http://${l}:${b}`;return{id:Z,device_id:Z,device_public_key:d,ip:l,http_port:b,endpoint_kind:e,url:a,computer_name:String(I.computer_name||""),os:{type:String(I.os?.type||""),platform:String(I.os?.platform||""),release:String(I.os?.release||""),arch:String(I.os?.arch||"")},hermes_agent_version:String(I.hermes_agent_version||""),hermes_web_ui_version:String(I.hermes_web_ui_version||""),response_ms:G,last_seen_at:c}}function woI(I,l){return l.has(I.ip)}function Rt(){return{scanning:fa.scanning,last_scanned_at:fa.last_scanned_at,devices:[...fa.devices]}}async function WV(I={}){if(!hz())return Rt();if(ot)return ot;let l=Math.max(100,Math.min(I.timeoutMs||VoI,5e3)),G=[...new Set(I.httpPorts||uoI())],c=I.targetAddresses||FoI(),b=RoI(),Z=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;fa={...fa,scanning:!0};let d=Date.now();return ot=new Promise(e=>{let a=ji.default.createSocket("udp4"),n=new Map;a.on("message",(W,t)=>{if(!uz(t.address))return;let m=oz(W);if(m?.request_id&&m.request_id!==Z)return;let N=QoI(m,t.address,Date.now()-d,new Date().toISOString());N&&!I.includeSelf&&woI(N,b)||N&&n.set(N.id,N)}),a.on("error",W=>{i.warn(W,"[lan-discovery] UDP scan error")}),a.bind(0,"0.0.0.0",()=>{a.setBroadcast(!0);let W=Buffer.from(JSON.stringify({type:"hermes.discover",version:nV,request_id:Z}));for(let t of G){let m;try{m=pz(t)}catch{continue}for(let N of c)a.send(W,m,N)}}),setTimeout(()=>{try{a.close()}catch{}fa={scanning:!1,last_scanned_at:new Date().toISOString(),devices:[...n.values()].sort((W,t)=>W.id.localeCompare(t.id))},e(Rt())},l)}).finally(()=>{ot=null}),ot}var _d=require("crypto"),NV=require("fs"),it=require("fs"),Hz=require("os"),sV=require("path"),Qz=require("child_process");hI();GI();xI();var Pi="/api/devices/peer-socket",wz=300*1e3,Si=64*1024,voI=5,yoI=1e3,EoI=3e4,rz=5*1024*1024,goI=3e4,iz=_i("HERMES_LAN_PEER_MAX_TERMINALS",4,1,32),tV=_i("HERMES_LAN_PEER_TERMINAL_IDLE_MS",600*1e3,3e4,1440*60*1e3),JoI=_i("HERMES_LAN_PEER_TERMINAL_BUFFER_BYTES",1024*1024,64*1024,16*1024*1024),Di=null;try{Di=require("node-pty")}catch(I){i.warn(I,"[lan-peer] node-pty failed to load; peer terminal disabled")}function $d(){return Date.now()}function _i(I,l,G,c){let b=Number(process.env[I]);return Number.isFinite(b)?Math.max(G,Math.min(c,Math.floor(b))):l}function CoI(I,l,G,c){let b=$d();for(let[d,e]of I)e<=b&&I.delete(d);let Z=`${l}:${G}`;return I.has(Z)?!1:(I.set(Z,c+wz),!0)}function Fz(I){return I.split("/").pop()||I}function AoI(){return process.platform==="win32"?"powershell.exe":[process.env.SHELL,"/bin/zsh","/bin/bash"].filter(Boolean).find(l=>(0,it.existsSync)(l))||"/bin/bash"}function Xz(){let I=(0,it.existsSync)(_I())?_I():(0,Hz.homedir)(),l=ct().cwd?.trim();if(!l)return I;let G=(0,sV.isAbsolute)(l)?l:(0,sV.resolve)(I,l);return(0,it.existsSync)(G)?G:I}function LoI(I){let l=I.url.replace(/\/$/,""),G=new URL(l);return G.protocol=G.protocol==="https:"?"wss:":"ws:",G.pathname=Pi,G.search="",G.toString()}function koI(I){let l=Buffer.isBuffer(I)?I.toString("utf8"):String(I);if(!l||l.charCodeAt(0)!==123)return null;try{return JSON.parse(l)}catch{return null}}var mV=class{constructor(l,G,c,b,Z,d){this.manager=l;this.ws=G;this.role=c;this.deviceId=b;this.computerName=Z;this.url=d;this.ws.on("pong",()=>{this.alive=!0}),this.ws.on("message",e=>this.handleMessage(e)),this.ws.on("close",()=>this.close({intentional:!1})),this.ws.on("error",e=>{i.warn(e,"[lan-peer] websocket error"),this.close({intentional:!1})}),this.startHeartbeat(),this.sendJson({type:"peer.ready",connection_id:this.id,device_id:this.deviceId,role:this.role})}manager;ws;role;deviceId;computerName;url;id=(0,_d.randomUUID)();connectedAt=$d();terminalSessions=new Map;remoteTerminals=new Map;uploads=new Map;pendingRequests=new Map;pendingDownloads=new Map;heartbeatTimer=null;alive=!0;closed=!1;info(){return{id:this.id,role:this.role,device_id:this.deviceId,computer_name:this.computerName,url:this.url,connected_at:this.connectedAt,local_terminal_sessions:this.terminalSessions.size,remote_terminal_sessions:this.remoteTerminals.size,reconnect_attempts:this.role==="client"?this.manager.getReconnectAttempts(this.deviceId):void 0}}close(l={}){if(!this.closed){this.closed=!0,this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null);for(let G of this.terminalSessions.values())this.disposeTerminalSession(G,{notify:!1});this.terminalSessions.clear(),this.remoteTerminals.clear();for(let G of this.uploads.values())try{G.stream.destroy()}catch{}this.uploads.clear();for(let G of this.pendingRequests.values())clearTimeout(G.timer),G.reject(new Error("Peer connection closed"));this.pendingRequests.clear();for(let G of this.pendingDownloads.values())clearTimeout(G.timer),G.reject(new Error("Peer connection closed"));if(this.pendingDownloads.clear(),this.ws.readyState===QZ.OPEN||this.ws.readyState===QZ.CONNECTING)try{this.ws.close()}catch{}this.manager.removeConnection(this.id),this.role==="client"&&!l.intentional&&this.manager.scheduleReconnect(this.deviceId)}}startHeartbeat(){this.heartbeatTimer=setInterval(()=>{if(this.ws.readyState===QZ.OPEN){if(!this.alive){try{this.ws.terminate()}catch{}return}this.alive=!1;try{this.ws.ping()}catch{}}},EoI),this.heartbeatTimer.unref?.()}sendJson(l){this.ws.readyState===QZ.OPEN&&this.ws.send(JSON.stringify(l))}disposeTerminalSession(l,G={}){l.idleTimer&&(clearTimeout(l.idleTimer),l.idleTimer=null),this.terminalSessions.delete(l.id);try{l.pty.kill()}catch{}G.notify&&this.sendJson({type:"terminal.exit",terminal_id:l.id,exit_code:G.exitCode??0})}touchTerminalSession(l){l.lastActiveAt=$d(),this.scheduleTerminalIdleTimeout(l,tV)}scheduleTerminalIdleTimeout(l,G){l.idleTimer&&clearTimeout(l.idleTimer),l.idleTimer=setTimeout(()=>{let c=this.terminalSessions.get(l.id);if(!c)return;let b=tV-($d()-c.lastActiveAt);if(b>0){this.scheduleTerminalIdleTimeout(c,b);return}i.info({connectionId:this.id,terminalId:c.id,idleMs:tV},"[lan-peer] closing idle terminal"),this.disposeTerminalSession(c,{notify:!0,exitCode:0})},G),l.idleTimer.unref?.()}request(l,G,c=["error"],b=3e4){if(this.ws.readyState!==QZ.OPEN)return Promise.reject(new Error("Peer connection is not open"));let Z=(0,_d.randomUUID)();return new Promise((d,e)=>{let a=setTimeout(()=>{this.pendingRequests.delete(Z),e(new Error("Peer request timed out"))},b);a.unref?.(),this.pendingRequests.set(Z,{resolve:d,reject:e,successTypes:new Set(G),errorTypes:new Set(c),timer:a}),this.sendJson({...l,request_id:Z})})}async createRemoteTerminal(l={}){let G=await this.request({type:"terminal.create",shell:l.shell,cols:l.cols,rows:l.rows},["terminal.created"],["terminal.error","error"]),c=G.terminal_id||"";if(!c)throw new Error("Peer did not return a terminal id");return this.remoteTerminals.set(c,{id:c,buffer:[],bufferBytes:0,exitCode:null}),{terminal_id:c,pid:Number(G.pid||0),shell:String(G.shell||"")}}listTerminals(){return{remote_terminals:[...this.remoteTerminals.values()].map(l=>({terminal_id:l.id,buffered_bytes:l.bufferBytes,buffered_chunks:l.buffer.length,exited:l.exitCode!==null,exit_code:l.exitCode})),local_terminal_sessions:[...this.terminalSessions.values()].map(l=>({terminal_id:l.id,pid:l.pid,shell:Fz(l.shell),last_active_at:l.lastActiveAt,idle_timeout_ms:tV}))}}writeRemoteTerminal(l,G){if(!this.remoteTerminals.has(l))throw new Error("Remote terminal not found");this.sendJson({type:"terminal.input",terminal_id:l,data:G})}resizeRemoteTerminal(l,G,c){if(!this.remoteTerminals.has(l))throw new Error("Remote terminal not found");this.sendJson({type:"terminal.resize",terminal_id:l,cols:G,rows:c})}closeRemoteTerminal(l){if(!this.remoteTerminals.has(l))throw new Error("Remote terminal not found");this.sendJson({type:"terminal.close",terminal_id:l}),this.remoteTerminals.delete(l)}readRemoteTerminal(l){let G=this.remoteTerminals.get(l);if(!G)throw new Error("Remote terminal not found");let c=G.buffer.join("");return G.buffer.length=0,G.bufferBytes=0,{terminal_id:l,data:c,exited:G.exitCode!==null,exit_code:G.exitCode}}async execRemoteCommand(l){let G=await this.request({type:"terminal.exec",command:l.command,args:l.args||[],cwd:l.cwd,timeout_ms:l.timeoutMs},["terminal.exec.result"],["terminal.exec.error","error"],Math.max(1e3,(l.timeoutMs||3e4)+1e3));return{stdout:String(G.stdout||""),stderr:String(G.stderr||""),exit_code:typeof G.exit_code=="number"?G.exit_code:null,timed_out:!!G.timed_out}}downloadFileToBuffer(l,G=6e4){if(this.ws.readyState!==QZ.OPEN)return Promise.reject(new Error("Peer connection is not open"));let c=(0,_d.randomUUID)();return new Promise((b,Z)=>{let d=setTimeout(()=>{this.pendingDownloads.delete(c),Z(new Error("Peer file download timed out"))},G);d.unref?.(),this.pendingDownloads.set(c,{chunks:[],resolve:b,reject:Z,timer:d}),this.sendJson({type:"file.download",transfer_id:c,path:l})})}async uploadFileFromBuffer(l,G,c=6e4){let b=(0,_d.randomUUID)();await this.request({type:"file.upload.start",transfer_id:b,path:l},["file.upload.ready"],["file.error","error"],c);for(let Z=0;Z<G.length;Z+=Si)this.sendJson({type:"file.upload.chunk",transfer_id:b,data:G.subarray(Z,Z+Si).toString("base64")});return await this.request({type:"file.upload.complete",transfer_id:b},["file.upload.complete"],["file.error","error"],c),{path:l,size:G.length}}handleMessage(l){let G=koI(l);if(!G?.type){this.sendJson({type:"error",message:"Invalid peer message"});return}if(!this.handlePendingMessage(G))switch(G.type){case"terminal.data":this.bufferRemoteTerminalData(G);break;case"terminal.exit":this.markRemoteTerminalExit(G);break;case"terminal.create":this.createTerminal(G);break;case"terminal.input":this.writeTerminal(G);break;case"terminal.resize":this.resizeTerminal(G);break;case"terminal.close":this.closeTerminal(G);break;case"terminal.exec":this.execCommand(G);break;case"file.download":this.downloadFile(G);break;case"file.download.started":break;case"file.download.chunk":case"file.download.complete":case"file.error":this.handleFileTransferMessage(G);break;case"file.upload.start":this.startUpload(G);break;case"file.upload.chunk":this.writeUploadChunk(G);break;case"file.upload.complete":this.completeUpload(G);break;default:this.sendJson({type:"error",request_id:G.request_id,message:`Unsupported peer message: ${G.type}`})}}handlePendingMessage(l){if(l.request_id){let G=this.pendingRequests.get(l.request_id);if(G){if(G.successTypes.has(l.type||""))return clearTimeout(G.timer),this.pendingRequests.delete(l.request_id),G.resolve(l),!0;if(G.errorTypes.has(l.type||""))return clearTimeout(G.timer),this.pendingRequests.delete(l.request_id),G.reject(new Error(l.message||`Peer request failed: ${l.type}`)),!0}}return!1}bufferRemoteTerminalData(l){let G=l.terminal_id?this.remoteTerminals.get(l.terminal_id):null;if(!G||typeof l.data!="string")return;let c=Buffer.byteLength(l.data,"utf8");for(G.buffer.push(l.data),G.bufferBytes+=c;G.bufferBytes>JoI&&G.buffer.length>1;){let b=G.buffer.shift()||"";G.bufferBytes-=Buffer.byteLength(b,"utf8")}}markRemoteTerminalExit(l){let G=l.terminal_id?this.remoteTerminals.get(l.terminal_id):null;G&&(G.exitCode=typeof l.exit_code=="number"?l.exit_code:0)}handleFileTransferMessage(l){let G=l.transfer_id?this.pendingDownloads.get(l.transfer_id):null;return G?l.type==="file.download.chunk"&&typeof l.data=="string"?(G.chunks.push(Buffer.from(l.data,"base64")),!0):l.type==="file.download.complete"?(clearTimeout(G.timer),this.pendingDownloads.delete(l.transfer_id),G.resolve(Buffer.concat(G.chunks)),!0):l.type==="file.error"?(clearTimeout(G.timer),this.pendingDownloads.delete(l.transfer_id),G.reject(new Error(l.message||"Peer file transfer failed")),!0):!1:!1}createTerminal(l){if(!Di){this.sendJson({type:"terminal.error",request_id:l.request_id,message:"Terminal is not available"});return}if(this.terminalSessions.size>=iz){this.sendJson({type:"terminal.error",request_id:l.request_id,message:`Terminal limit reached (${iz} per peer connection)`});return}let G=l.shell||AoI(),c;try{c=Di.spawn(G,[],{name:"xterm-color",cols:Math.max(1,l.cols||80),rows:Math.max(1,l.rows||24),cwd:Xz()})}catch(d){this.sendJson({type:"terminal.error",request_id:l.request_id,message:d?.message||"Failed to create terminal"});return}let b=(0,_d.randomUUID)(),Z={id:b,pty:c,shell:G,pid:c.pid,lastActiveAt:$d(),idleTimer:null};this.terminalSessions.set(b,Z),this.touchTerminalSession(Z),Z.pty.onData(d=>{this.terminalSessions.has(b)&&(this.touchTerminalSession(Z),this.sendJson({type:"terminal.data",terminal_id:b,data:d}))}),Z.pty.onExit(({exitCode:d})=>{this.terminalSessions.has(b)&&(Z.idleTimer&&clearTimeout(Z.idleTimer),this.terminalSessions.delete(b),this.sendJson({type:"terminal.exit",terminal_id:b,exit_code:d}))}),this.sendJson({type:"terminal.created",request_id:l.request_id,terminal_id:b,pid:Z.pid,shell:Fz(G)})}writeTerminal(l){let G=l.terminal_id?this.terminalSessions.get(l.terminal_id):null;!G||typeof l.data!="string"||(this.touchTerminalSession(G),G.pty.write(l.data))}resizeTerminal(l){let G=l.terminal_id?this.terminalSessions.get(l.terminal_id):null;if(G){this.touchTerminalSession(G);try{G.pty.resize(Math.max(1,l.cols||80),Math.max(1,l.rows||24))}catch{}}}closeTerminal(l){let G=l.terminal_id?this.terminalSessions.get(l.terminal_id):null;G&&this.disposeTerminalSession(G,{notify:!1})}execCommand(l){let G=typeof l.command=="string"?l.command.trim():"",c=Array.isArray(l.args)?l.args.filter(h=>typeof h=="string"):[];if(!G){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:"Missing command"});return}let b=Xz();if(l.cwd)try{let h=K(l.cwd);b=(0,it.existsSync)(h)?h:b}catch(h){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:h?.message||"Invalid cwd"});return}let Z=Math.max(1e3,Math.min(Number(l.timeout_ms)||goI,600*1e3)),d=[],e=[],a=0,n=0,W=!1,t=!1,m;try{m=(0,Qz.spawn)(G,c,{cwd:b,shell:!1,windowsHide:!0})}catch(h){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:h?.message||"Failed to start command"});return}let N=h=>{W||(W=!0,clearTimeout(Y),this.sendJson({type:"terminal.exec.result",request_id:l.request_id,stdout:Buffer.concat(d).toString("utf8"),stderr:Buffer.concat(e).toString("utf8"),exit_code:h,timed_out:t}))},s=(h,o,p)=>{if(o>=rz)return o;let V=rz-o,u=p.subarray(0,V);return h.push(u),o+u.length},Y=setTimeout(()=>{t=!0;try{m.kill()}catch{}N(null)},Z);Y.unref?.(),m.stdout?.on("data",h=>{a=s(d,a,Buffer.from(h))}),m.stderr?.on("data",h=>{n=s(e,n,Buffer.from(h))}),m.on("error",h=>{W||(W=!0,clearTimeout(Y),this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:h.message}))}),m.on("close",h=>N(h))}downloadFile(l){if(!l.transfer_id||!l.path){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:"Missing file path"});return}let G;try{G=K(l.path)}catch(b){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:b?.message||"Invalid file path"});return}let c=(0,NV.createReadStream)(G,{highWaterMark:Si});this.sendJson({type:"file.download.started",request_id:l.request_id,transfer_id:l.transfer_id}),c.on("data",b=>{this.sendJson({type:"file.download.chunk",transfer_id:l.transfer_id,data:Buffer.from(b).toString("base64")})}),c.on("error",b=>{this.sendJson({type:"file.error",transfer_id:l.transfer_id,message:b.message})}),c.on("end",()=>{this.sendJson({type:"file.download.complete",transfer_id:l.transfer_id})})}startUpload(l){if(!l.transfer_id||!l.path){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:"Missing upload path"});return}let G;try{G=K(l.path)}catch(b){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:b?.message||"Invalid upload path"});return}let c=(0,NV.createWriteStream)(G);c.on("error",b=>{this.uploads.delete(l.transfer_id),this.sendJson({type:"file.error",transfer_id:l.transfer_id,message:b.message})}),this.uploads.set(l.transfer_id,{id:l.transfer_id,path:G,stream:c}),this.sendJson({type:"file.upload.ready",request_id:l.request_id,transfer_id:l.transfer_id})}writeUploadChunk(l){let G=l.transfer_id?this.uploads.get(l.transfer_id):null;!G||typeof l.data!="string"||G.stream.write(Buffer.from(l.data,"base64"))}completeUpload(l){let G=l.transfer_id?this.uploads.get(l.transfer_id):null;G&&G.stream.end(()=>{this.uploads.delete(G.id),this.sendJson({type:"file.upload.complete",request_id:l.request_id,transfer_id:G.id,path:G.path})})}},qi=class{wss=new Ud.default({noServer:!0});connections=new Map;clientTargets=new Map;seenNonces=new Map;setupDone=!1;setupServer(l){if(this.setupDone)return;this.setupDone=!0,(Array.isArray(l)?l:[l]).forEach(c=>{c.on("upgrade",async(b,Z,d)=>{let e=new URL(b.url||"",`http://${b.headers.host}`);if(e.pathname!==Pi)return;if(CZ(b,x.corsOrigins)){Ca(Z);return}let a=await this.authenticateUpgrade(e,b);if(!a.ok){Z.write(`HTTP/1.1 ${a.status} ${a.message}\r
302
302
  \r
303
303
  `),Z.destroy();return}this.wss.handleUpgrade(b,Z,d,n=>{let W=new mV(this,n,"server",a.device.id,a.device.computerName,a.device.url);this.connections.set(W.id,W),this.wss.emit("connection",n,b)})})})}async connectToDevice(l){let G=this.findConnectionByDevice(l.id,"client");if(G)return G.info();let c=this.getOrCreateClientTarget(l);c.device=l,c.disabled=!1,c.reconnectTimer&&(clearTimeout(c.reconnectTimer),c.reconnectTimer=null);let b=await this.openClientConnection(l);return c.attempts=0,b.info()}async openClientConnection(l){let G=await Pd(),c=$d(),b=(0,_d.randomUUID)(),Z=await pt(b,c),d=new URL(LoI(l));d.searchParams.set("device_id",G.device_id),d.searchParams.set("device_public_key",G.device_public_key),d.searchParams.set("computer_name",G.computer_name),d.searchParams.set("timestamp",String(c)),d.searchParams.set("nonce",b),d.searchParams.set("signature",Z);let e=new QZ(d);await new Promise((n,W)=>{let t=setTimeout(()=>{e.close(),W(new Error("Peer socket connection timeout"))},5e3);e.once("open",()=>{clearTimeout(t),n()}),e.once("error",m=>{clearTimeout(t),W(m)})});let a=new mV(this,e,"client",l.id,l.computer_name,l.url);return this.connections.set(a.id,a),a}listConnections(){return[...this.connections.values()].map(l=>l.info()).sort((l,G)=>G.connected_at-l.connected_at)}getConnection(l){return this.connections.get(l)||null}disconnect(l){let G=this.connections.get(l);return G?(G.role==="client"&&this.disableClientReconnect(G.deviceId),G.close({intentional:!0}),!0):!1}disconnectDevice(l){this.disableClientReconnect(l);let G=[...this.connections.values()].filter(c=>c.deviceId===l);return G.forEach(c=>c.close({intentional:!0})),G.length}removeConnection(l){this.connections.delete(l)}getReconnectAttempts(l){return this.clientTargets.get(l)?.attempts||0}scheduleReconnect(l){let G=this.clientTargets.get(l);if(!G||G.disabled||this.findConnectionByDevice(l,"client")||G.reconnectTimer)return;if(G.attempts>=voI){i.warn({deviceId:l},"[lan-peer] client reconnect limit reached");return}G.attempts+=1;let c=yoI*2**(G.attempts-1);G.reconnectTimer=setTimeout(()=>{G.reconnectTimer=null,this.openClientConnection(G.device).then(()=>{G.attempts=0}).catch(b=>{i.warn({err:b,deviceId:l,attempt:G.attempts},"[lan-peer] client reconnect failed"),this.scheduleReconnect(l)})},c),G.reconnectTimer.unref?.()}getOrCreateClientTarget(l){let G=this.clientTargets.get(l.id);return G||(G={device:l,attempts:0,reconnectTimer:null,disabled:!1},this.clientTargets.set(l.id,G)),G}disableClientReconnect(l){let G=this.clientTargets.get(l);G&&(G.disabled=!0,G.reconnectTimer&&(clearTimeout(G.reconnectTimer),G.reconnectTimer=null))}findConnectionByDevice(l,G){return[...this.connections.values()].find(c=>c.deviceId===l&&(!G||c.role===G))||null}async authenticateUpgrade(l,G){let c=l.searchParams.get("device_id")?.trim()||"",b=l.searchParams.get("device_public_key")||"",Z=Number(l.searchParams.get("timestamp")||""),d=l.searchParams.get("nonce")||"",e=l.searchParams.get("signature")||"",a=l.searchParams.get("computer_name")||"";if(!c||!b||!Number.isFinite(Z)||!d||!e)return{ok:!1,status:400,message:"Bad Request"};if(Math.abs($d()-Z)>wz)return{ok:!1,status:400,message:"Expired Request"};if(!ut({device_id:c,device_public_key:b,nonce:d,timestamp:Z,signature:e}))return{ok:!1,status:401,message:"Unauthorized"};if(!CoI(this.seenNonces,c,d,Z))return{ok:!1,status:409,message:"Replay Request"};if(Cc(c)?.inbound_status!=="approved")return{ok:!1,status:403,message:"Forbidden"};let W=G.socket.remoteAddress?.startsWith("::ffff:")?G.socket.remoteAddress.slice(7):G.socket.remoteAddress||"";return{ok:!0,device:{id:c,computerName:a,url:W?`ws://${W}`:""}}}},Ti=null;function kG(){return Ti||(Ti=new qi),Ti}function vz(){return Pi}var YV=require("fs/promises");var IF=class{listConnections(){return kG().listConnections()}disconnect(l){return kG().disconnect(l)}async createTerminal(l,G={}){return this.requireConnection(l).createRemoteTerminal(G)}listTerminals(l){return this.requireConnection(l).listTerminals()}writeTerminal(l){return this.requireConnection(l.connectionId).writeRemoteTerminal(l.terminalId,l.data),{ok:!0}}resizeTerminal(l){return this.requireConnection(l.connectionId).resizeRemoteTerminal(l.terminalId,l.cols,l.rows),{ok:!0}}closeTerminal(l){return this.requireConnection(l.connectionId).closeRemoteTerminal(l.terminalId),{ok:!0}}readTerminal(l){return this.requireConnection(l.connectionId).readRemoteTerminal(l.terminalId)}exec(l){return this.requireConnection(l.connectionId).execRemoteCommand({command:l.command,args:l.args,cwd:l.cwd,timeoutMs:l.timeoutMs})}async downloadFile(l){let G=K(l.localPath),c=await this.requireConnection(l.connectionId).downloadFileToBuffer(l.remotePath,l.timeoutMs);return await(0,YV.writeFile)(G,c),{remote_path:l.remotePath,local_path:G,size:c.length}}async uploadFile(l){let G=K(l.localPath),c=await(0,YV.readFile)(G);return{...await this.requireConnection(l.connectionId).uploadFileFromBuffer(l.remotePath,c,l.timeoutMs),local_path:G,remote_path:l.remotePath}}requireConnection(l){let G=kG().getConnection(l);if(!G)throw Object.assign(new Error("Peer connection not found"),{status:404});return G}},$i=null;function tb(){return $i||($i=new IF),$i}xI();var lF=require("crypto"),GF=300*1e3,VV=new Map;function yz(I,l,G){let c=Date.now();for(let[Z,d]of VV)d<=c&&VV.delete(Z);let b=`${I}:${l}`;return VV.has(b)?!1:(VV.set(b,G+GF),!0)}function Ez(I){return I==="none"||I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:null}async function xoI(I){let l=Date.now(),G=(0,lF.randomUUID)(),c=await Pd(),b=await pt(G,l),Z=new AbortController,d=setTimeout(()=>Z.abort(),1500);try{let e=await fetch(`${I.url.replace(/\/$/,"")}/api/devices/link-status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_id:c.device_id,device_public_key:c.device_public_key,timestamp:l,nonce:G,signature:b}),signal:Z.signal}),a=await e.json().catch(()=>({}));return e.ok?Ez(a.status):null}catch{return null}finally{clearTimeout(d)}}async function zoI(I){let l=new Map;return await Promise.all(I.map(async G=>{let c=await xoI(G);if(!c)return;l.set(G.id,c);let b=Cc(G.id);c!=="pending"&&(c!=="none"||b?.outbound_status!=="none")&&Bi(G.id,c,G)})),l}async function Ft(){let I=Rt(),l=await zoI(I.devices),G=new Map(Ui().map(b=>[b.id,b])),c=I.devices.map(b=>{let Z=G.get(b.id),d=l.get(b.id)||Z?.outbound_status||"none";return d==="approved"&&kG().connectToDevice(b).catch(e=>{console.warn("[lan-peer] failed to connect paired device:",e?.message||e)}),{...b,inbound_status:Z?.inbound_status||"none",outbound_status:d,requested_at:Z?.requested_at||0,decided_at:Z?.decided_at||null,outbound_requested_at:Z?.outbound_requested_at||0,outbound_decided_at:Z?.outbound_decided_at||null,updated_at:Z?.updated_at||0}});return{scanning:I.scanning,last_scanned_at:I.last_scanned_at,devices:c,requests:nz()}}async function gz(I){I.body=await Ft()}async function Jz(I){await WV(),I.body=await Ft()}function cF(I){return Rt().devices.find(l=>l.id===I)||null}function UoI(I){let l=String(I.ip||I.request?.ip||"");return l.startsWith("::ffff:")?l.slice(7):l}function BoI(I,l){let G=typeof l?.device_id=="string"?l.device_id.trim():"",c=typeof l?.device_public_key=="string"?l.device_public_key:"",b=Number(l?.http_port);if(!G||!c||!Number.isInteger(b)||b<=0||b>65535)return null;let Z=UoI(I),d=l.endpoint_kind==="web"||l.endpoint_kind==="desktop"||l.endpoint_kind==="custom"?l.endpoint_kind:rt(b);return{id:G,device_id:G,device_public_key:c,ip:Z,http_port:b,endpoint_kind:d,url:typeof l?.url=="string"&&l.url?l.url:`http://${Z}:${b}`,computer_name:String(l?.computer_name||""),os:{type:String(l?.os?.type||""),platform:String(l?.os?.platform||""),release:String(l?.os?.release||""),arch:String(l?.os?.arch||"")},hermes_agent_version:String(l?.hermes_agent_version||""),hermes_web_ui_version:String(l?.hermes_web_ui_version||""),response_ms:0,last_seen_at:new Date().toISOString()}}async function Cz(I){let l=I.request.body,G=Number(l?.timestamp),c=typeof l?.nonce=="string"?l.nonce:"",b=typeof l?.signature=="string"?l.signature:"",Z=BoI(I,l);if(!Z||!Number.isFinite(G)||!c||!b){I.status=400,I.body={error:"Invalid device request"};return}if(Math.abs(Date.now()-G)>GF){I.status=400,I.body={error:"Device request expired"};return}if(!ut({device_id:Z.id,device_public_key:Z.device_public_key,nonce:c,timestamp:G,signature:b})){I.status=401,I.body={error:"Invalid device signature"};return}if(!yz(Z.id,c,G)){I.status=409,I.body={error:"Device request replayed"};return}try{let d=tz(Z);I.body={status:d.inbound_status}}catch(d){if(d instanceof Yt){I.status=409,I.body={error:"Duplicate pairing request"};return}throw d}}async function Az(I){let l=I.request.body,G=typeof l?.device_id=="string"?l.device_id.trim():"",c=typeof l?.device_public_key=="string"?l.device_public_key:"",b=Number(l?.timestamp),Z=typeof l?.nonce=="string"?l.nonce:"",d=typeof l?.signature=="string"?l.signature:"";if(!G||!c||!Number.isFinite(b)||!Z||!d){I.status=400,I.body={error:"Invalid device status request"};return}if(Math.abs(Date.now()-b)>GF){I.status=400,I.body={error:"Device status request expired"};return}if(!ut({device_id:G,device_public_key:c,nonce:Z,timestamp:b,signature:d})){I.status=401,I.body={error:"Invalid device signature"};return}if(!yz(G,Z,b)){I.status=409,I.body={error:"Device status request replayed"};return}I.body={status:Cc(G)?.inbound_status||"none"}}async function hV(I,l){try{mz(I.params.id,l,cF(I.params.id)||void 0),I.body=await Ft()}catch{I.status=404,I.body={error:"Device not found"}}}async function Lz(I){await hV(I,"approved")}async function kz(I){await hV(I,"rejected")}async function xz(I){await hV(I,"blocked")}async function zz(I){await hV(I,"none")}async function Uz(I){if(!Nz(I.params.id)){I.status=404,I.body={error:"Device request not found"};return}kG().disconnectDevice(I.params.id),I.body=await Ft()}async function Bz(I){I.body={connections:kG().listConnections()}}async function Oz(I){let l=cF(I.params.id);if(!l){I.status=404,I.body={error:"Device not found"};return}if(Cc(I.params.id)?.outbound_status!=="approved"){I.status=403,I.body={error:"Device pairing has not been approved"};return}try{let c=await kG().connectToDevice(l);I.body={connection:c}}catch(c){I.status=502,I.body={error:c?.message||"Failed to connect peer device"}}}async function Mz(I){if(!kG().disconnect(I.params.connectionId)){I.status=404,I.body={error:"Peer connection not found"};return}I.body={connections:kG().listConnections()}}function Ie(I,l){let G=Number(I);return Number.isFinite(G)?G:l}function fb(I,l){I.status=Number(l?.status)||502,I.body={error:l?.message||"Peer operation failed"}}async function fz(I){let l=I.request.body;try{let G=await tb().createTerminal(I.params.connectionId,{shell:typeof l?.shell=="string"?l.shell:void 0,cols:Ie(l?.cols,80),rows:Ie(l?.rows,24)});I.body={terminal:G}}catch(G){fb(I,G)}}async function jz(I){try{I.body={terminals:tb().listTerminals(I.params.connectionId)}}catch(l){fb(I,l)}}async function Kz(I){let l=I.request.body;try{I.body=tb().writeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||""),data:String(l?.data||"")})}catch(G){fb(I,G)}}async function Sz(I){let l=I.request.body;try{I.body=tb().resizeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||""),cols:Ie(l?.cols,80),rows:Ie(l?.rows,24)})}catch(G){fb(I,G)}}async function Tz(I){try{I.body={terminal:tb().readTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||"")})}}catch(l){fb(I,l)}}async function Dz(I){try{I.body=tb().closeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||"")})}catch(l){fb(I,l)}}async function qz(I){let l=I.request.body;try{let G=await tb().exec({connectionId:I.params.connectionId,command:String(l?.command||""),args:Array.isArray(l?.args)?l.args.map(String):[],cwd:typeof l?.cwd=="string"?l.cwd:void 0,timeoutMs:Ie(l?.timeout_ms,3e4)});I.body={result:G}}catch(G){fb(I,G)}}async function Pz(I){let l=I.request.body;try{I.body=await tb().downloadFile({connectionId:I.params.connectionId,remotePath:String(l?.remote_path||l?.path||""),localPath:String(l?.local_path||""),timeoutMs:Ie(l?.timeout_ms,6e4)})}catch(G){fb(I,G)}}async function _z(I){let l=I.request.body;try{I.body=await tb().uploadFile({connectionId:I.params.connectionId,localPath:String(l?.local_path||""),remotePath:String(l?.remote_path||l?.path||""),timeoutMs:Ie(l?.timeout_ms,6e4)})}catch(G){fb(I,G)}}async function $z(I){let l=cF(I.params.id);if(!l){I.status=404,I.body={error:"Device not found"};return}let G=Date.now(),c=(0,lF.randomUUID)(),b=await Pd(),Z=await pt(c,G),d={...b,http_port:x.port,endpoint_kind:rt(x.port),timestamp:G,nonce:c,signature:Z},e=new AbortController,a=setTimeout(()=>e.abort(),5e3);try{let n=await fetch(`${l.url.replace(/\/$/,"")}/api/devices/link-request`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(d),signal:e.signal}),W=await n.json().catch(()=>({}));if(!n.ok){I.status=n.status===409?409:502,I.body={error:typeof W.error=="string"?W.error:`Request failed: ${n.status}`};return}let t=Ez(W.status)||"pending";t!=="none"&&Bi(l.id,t,l),I.body=await Ft()}catch(n){I.status=502,I.body={error:n?.message||"Failed to request device pairing"}}finally{clearTimeout(a)}}var pV=new O,dl=new O;pV.post("/api/devices/link-request",Cz);pV.post("/api/devices/link-status",Az);dl.get("/api/devices",gz);dl.post("/api/devices/scan",Jz);dl.post("/api/devices/:id/request",$z);dl.post("/api/devices/:id/approve",Lz);dl.post("/api/devices/:id/reject",kz);dl.post("/api/devices/:id/block",xz);dl.post("/api/devices/:id/unblock",zz);dl.delete("/api/devices/:id/request-history",Uz);dl.get("/api/devices/peer-connections",Bz);dl.post("/api/devices/:id/connect",Oz);dl.post("/api/devices/peer-connections/:connectionId/disconnect",Mz);dl.post("/api/devices/peer-connections/:connectionId/terminal",fz);dl.get("/api/devices/peer-connections/:connectionId/terminals",jz);dl.get("/api/devices/peer-connections/:connectionId/terminal/:terminalId/read",Tz);dl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/input",Kz);dl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/resize",Sz);dl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/close",Dz);dl.post("/api/devices/peer-connections/:connectionId/exec",qz);dl.post("/api/devices/peer-connections/:connectionId/download",Pz);dl.post("/api/devices/peer-connections/:connectionId/upload",_z);var BU=require("child_process"),xG=require("fs"),FG=require("fs/promises"),yV=require("os"),YI=require("path"),OU=require("util");xI();var IU=require("crypto"),uV=require("stream");xI();var bF=new Map,MoI=["claude-haiku-4-5","claude-sonnet-4-6","claude-opus-4-7"];function lU(I,l,G,c){return`${I}\0${l}\0${G}\0${c}`}function foI(I,l,G,c){return Buffer.from(lU(I,l,G,c),"utf-8").toString("base64url")}function joI(I){return`http://127.0.0.1:${x.port}/api/claude-code-proxy/${I}`}function GU(I){let l=I.provider.trim(),G=I.model.trim(),c=I.baseUrl.replace(/\/+$/,""),b=I.apiMode||"chat_completions",Z=lU(l,G,b,c),d=bF.get(Z),e=d?.routeKey||foI(l,G,b,c),a=d?.token||`hwui_${(0,IU.randomBytes)(24).toString("base64url")}`;return bF.set(Z,{...I,provider:l,model:G,baseUrl:c,apiMode:b,key:Z,routeKey:e,token:a,updatedAt:Date.now()}),{baseUrl:joI(e),token:a,routeKey:e}}function KoI(I){for(let l of bF.values())if(l.routeKey===I)return l;return null}function SoI(I){let l=I.get("x-api-key").trim();return l||I.get("authorization").trim().match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||""}function cU(I){let l=KoI(String(I.params.key||""));return l?SoI(I)!==l.token?(I.status=401,I.body={type:"error",error:{type:"authentication_error",message:"Invalid Claude proxy token"}},null):l:(I.status=404,I.body={type:"error",error:{type:"not_found_error",message:"Claude proxy target not found"}},null)}function Ka(I){return typeof I=="string"?I:Array.isArray(I)?I.map(l=>typeof l=="string"?l:l&&typeof l=="object"&&"text"in l?String(l.text||""):JSON.stringify(l)).filter(Boolean).join(`
@@ -1191,7 +1191,7 @@ ${G.instructions}`:rc();if(G.session_id){let e=RI(G.session_id);e?.workspace&&(d
1191
1191
  ${`[Current working directory: ${e.workspace}]`}
1192
1192
  ${d}`)}await c_(this.nsp,l,{...G,instructions:d},c,this.sessionMap,this.bridge,b,cu,this.dequeueNextQueuedRun.bind(this));return}await OP(this.nsp,l,G,c,this.sessionMap,b,this.dequeueNextQueuedRun.bind(this))}}async resumeSession(l,G){let c=this.sessionMap.get(G);c||(c=await cu(G,this.sessionMap),this.sessionMap.set(G,c)),await this.reattachBridgeRun(l,G,c),l.emit("resumed",{session_id:G,messages:c.messages,messageTotal:c.messageTotal,messageLoadedCount:c.messageLoadedCount,messagePageLimit:c.messagePageLimit,hasMoreBefore:c.hasMoreBefore,isWorking:c.isWorking,isAborting:c.isAborting||!1,events:c.isWorking?c.events:[],inputTokens:c.inputTokens,outputTokens:c.outputTokens,contextTokens:c.contextTokens,queueLength:c.queue?.length||0,queueMessages:this.serializeQueuedMessages(c.queue||[])}),i.info("[chat-run-socket] socket %s resumed session %s (working: %s, messages: %d)",l.id,G,c.isWorking,c.messages.length)}async reattachBridgeRun(l,G,c){if(c.runId&&c.isWorking)return;let b=RI(G),Z=b?.profile||KgI(l);try{let d=await this.bridge.statusIfLoaded(G,Z),e=d.running===!0,a=typeof d.current_run_id=="string"?d.current_run_id:"";if(!e||!a)return;c.isWorking=!0,c.isAborting=c.isAborting===!0,c.runId=a,c.profile=Z,c.source="cli",c.events=[];let n=`${G}:${a}`;if(this.bridgeResumePolls.has(n))return;this.bridgeResumePolls.add(n);let W=this.resumeInstructionsForSession(G);b_(this.nsp,l,{sessionId:G,runId:a,profile:Z,instructions:W,model:b?.model,provider:b?.provider},this.sessionMap,this.bridge,this.dequeueNextQueuedRun.bind(this)).finally(()=>{this.bridgeResumePolls.delete(n)}),i.info("[chat-run-socket] reattached running bridge run %s for session %s",a,G)}catch(d){i.warn(d,"[chat-run-socket] bridge status lookup failed while resuming session %s",G)}}resumeInstructionsForSession(l){let G=rc(),c=RI(l);return c?.workspace&&(G=`
1193
1193
  [Current working directory: ${c.workspace}]
1194
- ${G}`),G}dequeueNextQueuedRun(l,G,c="default"){let b=this.sessionMap.get(G);if(!b?.queue.length)return!1;let Z=b.queue.shift();return i.info("[chat-run-socket] dequeuing queued run for session %s (remaining: %d)",G,b.queue.length),this.nsp.to(`session:${G}`).emit("run.queued",{event:"run.queued",session_id:G,queue_length:b.queue.length,dequeued_queue_id:Z.queue_id,queued_messages:this.serializeQueuedMessages(b.queue)}),this.runQueuedItem(l,G,Z,c),!0}runQueuedItem(l,G,c,b="default"){let Z=c.displayInput===null;this.handleRun(l,{input:c.input,display_input:c.displayInput,display_role:c.displayRole,storage_message:c.storageMessage,session_id:G,model:c.model,provider:c.provider,model_groups:c.model_groups,instructions:c.instructions,source:c.source,queue_id:c.queue_id,peerExcludeSocketId:c.originSocketId},c.profile||b,Z)}clearClarifyEventState(l,G){let c=this.sessionMap.get(l);if(!c?.events.length)return;let b=c.events.filter(({event:Z,data:d})=>Z!=="clarify.requested"&&Z!=="clarify.resolved"?!0:d?.clarify_id!==G);b.length!==c.events.length&&(c.events=b)}emitToSession(l,G,c,b){let Z={...b,session_id:G};this.nsp.to(`session:${G}`).emit(c,Z),!this.nsp.adapter.rooms.get(`session:${G}`)?.size&&l.connected&&l.emit(c,Z)}serializeQueuedMessages(l){return l.filter(G=>G.displayInput!==null).map(G=>({id:G.queue_id,role:G.displayRole||(typeof G.displayInput=="string"&&G.displayInput.trim().startsWith("/")?"command":"user"),content:Rb(G.displayInput??G.input),timestamp:Math.floor(Date.now()/1e3),queued:!0}))}canAccessProfile(l,G){return l.role==="super_admin"||ga(l.id,G)}close(){for(let[l,G]of this.sessionMap.entries())if(G.abortController)try{G.abortController.abort()}catch(c){i.warn(c,"[chat-run-socket] failed to abort controller for session %s",l)}this.sessionMap.clear(),i.info("[chat-run-socket] closed all connections and cleared state")}};xI();Ml();GI();hI();var Ce="hermes-studio",au="HERMES_WEB_UI_MANAGED_MCP",SgI=new Set(["hermes-lan-peer-mcp","hermes-devices-mcp","hermes-web-ui-mcp","hermes-studio-mcp"]);function TgI(){let I=String(process.env.HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT||"").trim().toLowerCase();return["1","true","yes","on"].includes(I)}function DgI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function qgI(){return DgI()?"hermes-studio-mcp":"hermes-web-ui-mcp"}function PgI(){let I={HERMES_WEB_UI_URL:`http://127.0.0.1:${x.port}`,HERMES_WEB_UI_HOME:x.appHome,HERMES_WEBUI_STATE_DIR:x.appHome,[au]:"1"};return{command:qgI(),env:I,enabled:!0}}function lN(I){return!!I&&typeof I=="object"&&!Array.isArray(I)}function _gI(I){return lN(I)?lN(I.env)&&I.env[au]==="1"?!0:typeof I.command=="string"&&SgI.has(I.command):!1}function $gI(I,l){let G=l.env;return I.command===l.command&&I.enabled!==!1&&lN(I.env)&&I.env.HERMES_WEB_UI_URL===G.HERMES_WEB_UI_URL&&I.env.HERMES_WEB_UI_HOME===G.HERMES_WEB_UI_HOME&&I.env.HERMES_WEBUI_STATE_DIR===G.HERMES_WEBUI_STATE_DIR&&I.env.HERMES_WEB_UI_TOKEN===void 0&&I.env[au]===G[au]}async function IJI(I,l){return await RG(I,G=>{let c=lN(G)?G:{};lN(c.mcp_servers)||(c.mcp_servers={});let b=c.mcp_servers[Ce];return b?_gI(b)?$gI(b,l)?{data:c,write:!1,result:{profile:I,status:"unchanged"}}:(c.mcp_servers[Ce]=l,{data:c,result:{profile:I,status:"updated"}}):{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${Ce} MCP server is not managed by Hermes Web UI`}}:(c.mcp_servers[Ce]=l,{data:c,result:{profile:I,status:"injected"}})})}async function N_(){let I=PgI(),l={serverName:Ce,command:String(I.command),targets:[]};if(TgI())return i.info("[mcp-autoinject] disabled by HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT"),l;for(let b of BI())l.targets.push(await IJI(b,I));let G=l.targets.filter(b=>b.status==="injected"||b.status==="updated");G.length>0&&i.info({serverName:Ce,command:I.command,targets:G},"[mcp-autoinject] synced bundled MCP server");let c=l.targets.filter(b=>b.status==="skipped");return c.length>0&&i.warn({serverName:Ce,targets:c},"[mcp-autoinject] skipped unmanaged MCP server entries"),l}Ua();GI();var GJI="0.6.12";process.on("uncaughtException",I=>{console.error("FATAL: Uncaught exception"),console.error(I),i.fatal(I,"Uncaught exception"),process.exit(1)});process.on("unhandledRejection",I=>{console.error("Unhandled rejection"),console.error(I),i.error(I,"Unhandled rejection")});var cJI=null,ed=[],nu=null,Wu=null;function bJI(I,l,G){return new Promise((c,b)=>{let Z=I.listen(l,G);Z.once("listening",()=>c(Z)),Z.once("error",b)})}async function ZJI(I,l,G){let c=G||"0.0.0.0";console.log(`[bootstrap] listening on ${c}:${l}`);let b=await bJI(I,l,c);return{primary:b,servers:[b]}}function dJI(){try{return o_.default.networkInterfaces()}catch{return{}}}function V_(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function r_(I){let l=String(process.env[I]||"").trim().toLowerCase();return["1","true","yes","on"].includes(l)}function i_(){return r_("HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART")}function eJI(){return r_("HERMES_WEB_UI_DISABLE_SKILL_INJECTION")}async function aJI(){if(i_())console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART");else try{await gi(),console.log("[bootstrap] profile gateways checked")}catch(I){i.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}try{Wu=await jF(),console.log("[bootstrap] agent bridge started")}catch(I){i.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I)}}function nJI(){i_()?console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART"):(async()=>{try{await gi(),console.log("[bootstrap] profile gateways checked")}catch(I){i.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}})(),(async()=>{try{Wu=await jF(),console.log("[bootstrap] agent bridge started")}catch(I){i.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I);return}})()}function WJI(){let I=Rz({httpPort:x.port}),l=!1,G=()=>{l||(l=!0,WV().catch(c=>i.warn(c,"[lan-discovery] initial scan failed")))};I?(I.once("listening",G),setTimeout(G,500).unref?.()):G()}async function F_(){if(console.log(`hermes-web-ui v${GJI} starting...`),await(0,LQ.mkdir)(x.uploadDir,{recursive:!0}),hC()&&await(0,LQ.mkdir)(x.dataDir,{recursive:!0}),await wC(),eJI())console.log("[bootstrap] bundled skill injection disabled by HERMES_WEB_UI_DISABLE_SKILL_INJECTION");else try{let m=await new de().injectMissingSkills();m.injected.length>0&&i.info({injected:[...new Set(m.injected)],targetCount:m.targets.length},"[bootstrap] bundled skills injected"),m.updated.length>0&&i.info({updated:[...new Set(m.updated)],targetCount:m.targets.length},"[bootstrap] bundled skills updated")}catch(t){i.warn(t,"[bootstrap] failed to inject bundled skills"),console.warn("[bootstrap] failed to inject bundled skills:",t instanceof Error?t.message:t)}try{await N_()}catch(t){i.warn(t,"[bootstrap] failed to inject bundled MCP server"),console.warn("[bootstrap] failed to inject bundled MCP server:",t instanceof Error?t.message:t)}V_()||await aJI();let I=new g1;await new Promise(t=>setTimeout(t,1e3));let{initAllStores:l}=await Promise.resolve().then(()=>(Y_(),s_));l(),await new Promise(t=>setTimeout(t,1e3)),console.log("[bootstrap] all stores initialized"),I.use(c9()),I.use((0,h_.default)({origin:l9(x.corsOrigins)})),I.use(s5({encoding:"utf-8",jsonLimit:"20mb",formLimit:"20mb",textLimit:"20mb"})),console.log("[bootstrap] cors + bodyParser registered");let G=hq(I,[$3,I9]);I.use(G),console.log("[bootstrap] routes registered");let c=(0,R_.resolve)(__dirname,"..","client");I.use((0,p_.default)(c)),I.use(async t=>{!t.path.startsWith("/api")&&t.path!=="/health"&&t.path!=="/upload"&&t.path!=="/webhook"&&await(0,u_.default)(t,"index.html",{root:c})}),console.log("[bootstrap] SPA fallback registered");let b=await ZJI(I,x.port,x.host);cJI=b.primary,ed=b.servers,console.log("[bootstrap] app.listen called"),d9(ed),g9(ed),kG().setupServer(ed),console.log("[bootstrap] terminal + kanban + LAN peer websocket setup");let Z=new qp(ed);SB(Z),nu=new eu(Z.getIO()),pq(nu),nu.init();let{SessionDeleter:d}=await Promise.resolve().then(()=>(Ih(),pO)),e=d.getInstance(),a=process.env.PROFILE||"default";e.start(a),console.log("[bootstrap] session deleter started, profile=%s",a),ed.forEach(t=>{t.on("upgrade",(m,N)=>{let s=new URL(m.url||"",`http://${m.headers.host}`);s.pathname!=="/api/hermes/terminal"&&s.pathname!=="/api/hermes/kanban/events"&&s.pathname!==vz()&&!s.pathname.startsWith("/socket.io/")&&N.destroy()})});let n=dJI(),W=Object.values(n).flat().find(t=>t?.family==="IPv4"&&!t?.internal)?.address||"localhost";console.log(`Server: http://localhost:${x.port} (LAN: http://${W}:${x.port})`),console.log(`Log: ${x.appHome}/logs/server.log`),i.info("Server: http://localhost:%d (LAN: http://%s:%d)",x.port,W,x.port),WJI(),df("bootstrap"),V_()&&(Wu=xt(),nJI()),Z.restoreWhenReady(),ed.forEach(t=>{t.on("error",m=>{console.error("[bootstrap] server error:",m.code||m.message),i.error({err:m},"Server error")})}),oL(ed,Z,nu,Wu),Ai()}F_().catch(I=>{console.error("FATAL: Failed to start Hermes Web UI"),console.error(I),i.fatal(I,"Fatal error during bootstrap"),process.exit(1)});0&&(module.exports={bootstrap});
1194
+ ${G}`),G}dequeueNextQueuedRun(l,G,c="default"){let b=this.sessionMap.get(G);if(!b?.queue.length)return!1;let Z=b.queue.shift();return i.info("[chat-run-socket] dequeuing queued run for session %s (remaining: %d)",G,b.queue.length),this.nsp.to(`session:${G}`).emit("run.queued",{event:"run.queued",session_id:G,queue_length:b.queue.length,dequeued_queue_id:Z.queue_id,queued_messages:this.serializeQueuedMessages(b.queue)}),this.runQueuedItem(l,G,Z,c),!0}runQueuedItem(l,G,c,b="default"){let Z=c.displayInput===null;this.handleRun(l,{input:c.input,display_input:c.displayInput,display_role:c.displayRole,storage_message:c.storageMessage,session_id:G,model:c.model,provider:c.provider,model_groups:c.model_groups,instructions:c.instructions,source:c.source,queue_id:c.queue_id,peerExcludeSocketId:c.originSocketId},c.profile||b,Z)}clearClarifyEventState(l,G){let c=this.sessionMap.get(l);if(!c?.events.length)return;let b=c.events.filter(({event:Z,data:d})=>Z!=="clarify.requested"&&Z!=="clarify.resolved"?!0:d?.clarify_id!==G);b.length!==c.events.length&&(c.events=b)}emitToSession(l,G,c,b){let Z={...b,session_id:G};this.nsp.to(`session:${G}`).emit(c,Z),!this.nsp.adapter.rooms.get(`session:${G}`)?.size&&l.connected&&l.emit(c,Z)}serializeQueuedMessages(l){return l.filter(G=>G.displayInput!==null).map(G=>({id:G.queue_id,role:G.displayRole||(typeof G.displayInput=="string"&&G.displayInput.trim().startsWith("/")?"command":"user"),content:Rb(G.displayInput??G.input),timestamp:Math.floor(Date.now()/1e3),queued:!0}))}canAccessProfile(l,G){return l.role==="super_admin"||ga(l.id,G)}close(){for(let[l,G]of this.sessionMap.entries())if(G.abortController)try{G.abortController.abort()}catch(c){i.warn(c,"[chat-run-socket] failed to abort controller for session %s",l)}this.sessionMap.clear(),i.info("[chat-run-socket] closed all connections and cleared state")}};xI();Ml();GI();hI();var Ce="hermes-studio",au="HERMES_WEB_UI_MANAGED_MCP",SgI=new Set(["hermes-lan-peer-mcp","hermes-devices-mcp","hermes-web-ui-mcp","hermes-studio-mcp"]);function TgI(){let I=String(process.env.HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT||"").trim().toLowerCase();return["1","true","yes","on"].includes(I)}function DgI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function qgI(){return DgI()?"hermes-studio-mcp":"hermes-web-ui-mcp"}function PgI(){let I={HERMES_WEB_UI_URL:`http://127.0.0.1:${x.port}`,HERMES_WEB_UI_HOME:x.appHome,HERMES_WEBUI_STATE_DIR:x.appHome,[au]:"1"};return{command:qgI(),env:I,enabled:!0}}function lN(I){return!!I&&typeof I=="object"&&!Array.isArray(I)}function _gI(I){return lN(I)?lN(I.env)&&I.env[au]==="1"?!0:typeof I.command=="string"&&SgI.has(I.command):!1}function $gI(I,l){let G=l.env;return I.command===l.command&&I.enabled!==!1&&lN(I.env)&&I.env.HERMES_WEB_UI_URL===G.HERMES_WEB_UI_URL&&I.env.HERMES_WEB_UI_HOME===G.HERMES_WEB_UI_HOME&&I.env.HERMES_WEBUI_STATE_DIR===G.HERMES_WEBUI_STATE_DIR&&I.env.HERMES_WEB_UI_TOKEN===void 0&&I.env[au]===G[au]}async function IJI(I,l){return await RG(I,G=>{let c=lN(G)?G:{};lN(c.mcp_servers)||(c.mcp_servers={});let b=c.mcp_servers[Ce];return b?_gI(b)?$gI(b,l)?{data:c,write:!1,result:{profile:I,status:"unchanged"}}:(c.mcp_servers[Ce]=l,{data:c,result:{profile:I,status:"updated"}}):{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${Ce} MCP server is not managed by Hermes Web UI`}}:(c.mcp_servers[Ce]=l,{data:c,result:{profile:I,status:"injected"}})})}async function N_(){let I=PgI(),l={serverName:Ce,command:String(I.command),targets:[]};if(TgI())return i.info("[mcp-autoinject] disabled by HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT"),l;for(let b of BI())l.targets.push(await IJI(b,I));let G=l.targets.filter(b=>b.status==="injected"||b.status==="updated");G.length>0&&i.info({serverName:Ce,command:I.command,targets:G},"[mcp-autoinject] synced bundled MCP server");let c=l.targets.filter(b=>b.status==="skipped");return c.length>0&&i.warn({serverName:Ce,targets:c},"[mcp-autoinject] skipped unmanaged MCP server entries"),l}Ua();GI();var GJI="0.6.13";process.on("uncaughtException",I=>{console.error("FATAL: Uncaught exception"),console.error(I),i.fatal(I,"Uncaught exception"),process.exit(1)});process.on("unhandledRejection",I=>{console.error("Unhandled rejection"),console.error(I),i.error(I,"Unhandled rejection")});var cJI=null,ed=[],nu=null,Wu=null;function bJI(I,l,G){return new Promise((c,b)=>{let Z=I.listen(l,G);Z.once("listening",()=>c(Z)),Z.once("error",b)})}async function ZJI(I,l,G){let c=G||"0.0.0.0";console.log(`[bootstrap] listening on ${c}:${l}`);let b=await bJI(I,l,c);return{primary:b,servers:[b]}}function dJI(){try{return o_.default.networkInterfaces()}catch{return{}}}function V_(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function r_(I){let l=String(process.env[I]||"").trim().toLowerCase();return["1","true","yes","on"].includes(l)}function i_(){return r_("HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART")}function eJI(){return r_("HERMES_WEB_UI_DISABLE_SKILL_INJECTION")}async function aJI(){if(i_())console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART");else try{await gi(),console.log("[bootstrap] profile gateways checked")}catch(I){i.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}try{Wu=await jF(),console.log("[bootstrap] agent bridge started")}catch(I){i.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I)}}function nJI(){i_()?console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART"):(async()=>{try{await gi(),console.log("[bootstrap] profile gateways checked")}catch(I){i.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}})(),(async()=>{try{Wu=await jF(),console.log("[bootstrap] agent bridge started")}catch(I){i.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I);return}})()}function WJI(){let I=Rz({httpPort:x.port}),l=!1,G=()=>{l||(l=!0,WV().catch(c=>i.warn(c,"[lan-discovery] initial scan failed")))};I?(I.once("listening",G),setTimeout(G,500).unref?.()):G()}async function F_(){if(console.log(`hermes-web-ui v${GJI} starting...`),await(0,LQ.mkdir)(x.uploadDir,{recursive:!0}),hC()&&await(0,LQ.mkdir)(x.dataDir,{recursive:!0}),await wC(),eJI())console.log("[bootstrap] bundled skill injection disabled by HERMES_WEB_UI_DISABLE_SKILL_INJECTION");else try{let m=await new de().injectMissingSkills();m.injected.length>0&&i.info({injected:[...new Set(m.injected)],targetCount:m.targets.length},"[bootstrap] bundled skills injected"),m.updated.length>0&&i.info({updated:[...new Set(m.updated)],targetCount:m.targets.length},"[bootstrap] bundled skills updated")}catch(t){i.warn(t,"[bootstrap] failed to inject bundled skills"),console.warn("[bootstrap] failed to inject bundled skills:",t instanceof Error?t.message:t)}try{await N_()}catch(t){i.warn(t,"[bootstrap] failed to inject bundled MCP server"),console.warn("[bootstrap] failed to inject bundled MCP server:",t instanceof Error?t.message:t)}V_()||await aJI();let I=new g1;await new Promise(t=>setTimeout(t,1e3));let{initAllStores:l}=await Promise.resolve().then(()=>(Y_(),s_));l(),await new Promise(t=>setTimeout(t,1e3)),console.log("[bootstrap] all stores initialized"),I.use(c9()),I.use((0,h_.default)({origin:l9(x.corsOrigins)})),I.use(s5({encoding:"utf-8",jsonLimit:"20mb",formLimit:"20mb",textLimit:"20mb"})),console.log("[bootstrap] cors + bodyParser registered");let G=hq(I,[$3,I9]);I.use(G),console.log("[bootstrap] routes registered");let c=(0,R_.resolve)(__dirname,"..","client");I.use((0,p_.default)(c)),I.use(async t=>{!t.path.startsWith("/api")&&t.path!=="/health"&&t.path!=="/upload"&&t.path!=="/webhook"&&await(0,u_.default)(t,"index.html",{root:c})}),console.log("[bootstrap] SPA fallback registered");let b=await ZJI(I,x.port,x.host);cJI=b.primary,ed=b.servers,console.log("[bootstrap] app.listen called"),d9(ed),g9(ed),kG().setupServer(ed),console.log("[bootstrap] terminal + kanban + LAN peer websocket setup");let Z=new qp(ed);SB(Z),nu=new eu(Z.getIO()),pq(nu),nu.init();let{SessionDeleter:d}=await Promise.resolve().then(()=>(Ih(),pO)),e=d.getInstance(),a=process.env.PROFILE||"default";e.start(a),console.log("[bootstrap] session deleter started, profile=%s",a),ed.forEach(t=>{t.on("upgrade",(m,N)=>{let s=new URL(m.url||"",`http://${m.headers.host}`);s.pathname!=="/api/hermes/terminal"&&s.pathname!=="/api/hermes/kanban/events"&&s.pathname!==vz()&&!s.pathname.startsWith("/socket.io/")&&N.destroy()})});let n=dJI(),W=Object.values(n).flat().find(t=>t?.family==="IPv4"&&!t?.internal)?.address||"localhost";console.log(`Server: http://localhost:${x.port} (LAN: http://${W}:${x.port})`),console.log(`Log: ${x.appHome}/logs/server.log`),i.info("Server: http://localhost:%d (LAN: http://%s:%d)",x.port,W,x.port),WJI(),df("bootstrap"),V_()&&(Wu=xt(),nJI()),Z.restoreWhenReady(),ed.forEach(t=>{t.on("error",m=>{console.error("[bootstrap] server error:",m.code||m.message),i.error({err:m},"Server error")})}),oL(ed,Z,nu,Wu),Ai()}F_().catch(I=>{console.error("FATAL: Failed to start Hermes Web UI"),console.error(I),i.fatal(I,"Fatal error during bootstrap"),process.exit(1)});0&&(module.exports={bootstrap});
1195
1195
  /*! Bundled license information:
1196
1196
 
1197
1197
  ee-first/index.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quanthermes/hermes-web-ui",
3
- "version": "0.6.12",
3
+ "version": "0.6.13",
4
4
  "description": "Self-hosted AI chat dashboard for Hermes Agent — multi-model web UI with multi-platform integration",
5
5
  "repository": {
6
6
  "type": "git",