@quanthermes/hermes-web-ui 0.6.16 → 0.6.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/js/{ChannelsView-C3g3StjL.js → ChannelsView-BwP8wsUV.js} +1 -1
- package/dist/client/assets/js/{ChatView-tIA9-kE6.js → ChatView-Mf_KaepB.js} +1 -1
- package/dist/client/assets/js/{CodingAgentsView-BjVUaZEX.js → CodingAgentsView-C0OyfzpB.js} +1 -1
- package/dist/client/assets/js/{DevicesView-CrHv1Mcc.js → DevicesView-Cfk24oSi.js} +1 -1
- package/dist/client/assets/js/{FileRenameModal-BmQIUMYK.js → FileRenameModal-DhB_Oy1Y.js} +1 -1
- package/dist/client/assets/js/{FilesView-BSJjUAhT.js → FilesView-CL3bT4UM.js} +1 -1
- package/dist/client/assets/js/{GroupChatView-DtWcdFAL.js → GroupChatView-DhNycaZ-.js} +1 -1
- package/dist/client/assets/js/{HistoryMessageList-L-9SSk3K.js → HistoryMessageList-C9ywhLVB.js} +1 -1
- package/dist/client/assets/js/{HistoryView-DWEeHcuC.js → HistoryView-CB4oqwnG.js} +1 -1
- package/dist/client/assets/js/{JobsView-BgofNKg-.js → JobsView-DrZUX1TJ.js} +1 -1
- package/dist/client/assets/js/{KanbanView-QPxTlH-J.js → KanbanView-B-rpBbt3.js} +1 -1
- package/dist/client/assets/js/{LoginView-McUee9pQ.js → LoginView-Ca6fECMY.js} +1 -1
- package/dist/client/assets/js/{LogsView-BT-4Df4G.js → LogsView-IjXDeQ1e.js} +1 -1
- package/dist/client/assets/js/{MarkdownRenderer-Jwbx4dOP.js → MarkdownRenderer-BlxKlSHX.js} +1 -1
- package/dist/client/assets/js/{McpManagerView-DLDPI-_O.js → McpManagerView-D-oJeFHz.js} +1 -1
- package/dist/client/assets/js/{MemoryView-Dq3pEc1S.js → MemoryView-BSlKBKzI.js} +1 -1
- package/dist/client/assets/js/{MessageItem-Dr5idUZb.js → MessageItem-Di7V6T5S.js} +1 -1
- package/dist/client/assets/js/{ModelsView-sfHqVERI.js → ModelsView-qxOq5hFg.js} +1 -1
- package/dist/client/assets/js/{OutlinePanel-BddtVbQw.js → OutlinePanel-D62oj0V9.js} +1 -1
- package/dist/client/assets/js/{PerformanceView-BYMIVkGl.js → PerformanceView-Coa_4sVf.js} +1 -1
- package/dist/client/assets/js/{PluginsView-Be878n_l.js → PluginsView-BHOXiJZv.js} +1 -1
- package/dist/client/assets/js/{ProfilesView-B6TQX72B.js → ProfilesView-DjODeu2z.js} +1 -1
- package/dist/client/assets/js/{SettingRow-vaeYDW5h.js → SettingRow-DWprXoV4.js} +1 -1
- package/dist/client/assets/js/{SettingsView-ClBbruK3.js → SettingsView-D5QX2BHT.js} +1 -1
- package/dist/client/assets/js/{SkillsUsageView-cAHh5inD.js → SkillsUsageView-CgpixSYd.js} +1 -1
- package/dist/client/assets/js/{SkillsView-DFxNT1UO.js → SkillsView-DVA_LzFa.js} +1 -1
- package/dist/client/assets/js/{TerminalPanel-Bwa-6ai-.js → TerminalPanel-DhnPxJTG.js} +1 -1
- package/dist/client/assets/js/{TerminalView-KMAVVfPx.js → TerminalView-tgOY8x6C.js} +1 -1
- package/dist/client/assets/js/{UsageView-DQUEWEZR.js → UsageView-DDvy4JWs.js} +1 -1
- package/dist/client/assets/js/{VersionPreviewView-BD_8pfy6.js → VersionPreviewView-DoYv9yy6.js} +1 -1
- package/dist/client/assets/js/{VirtualMessageList-BNu9wFPU.js → VirtualMessageList-CfXQfWcE.js} +1 -1
- package/dist/client/assets/js/{_plugin-vue_export-helper-uEMLHKI8.js → _plugin-vue_export-helper-CwNymSRn.js} +2 -2
- package/dist/client/assets/js/{index-1yNqMnGv.js → index-DW8M4rjb.js} +1 -1
- package/dist/client/assets/js/{models-B67JDoKt.js → models-BDUkz58x.js} +1 -1
- package/dist/client/assets/js/{session-browser-prefs-BMKJzhU0.js → session-browser-prefs-DjzuPSf7.js} +1 -1
- package/dist/client/assets/js/{skills-oOSUGydJ.js → skills-kS4Wy1_s.js} +1 -1
- package/dist/client/assets/js/{system-ClONwY0c.js → system-DaAaRr9k.js} +1 -1
- package/dist/client/assets/js/{useSttSettings-BAlyngwO.js → useSttSettings-DnVfL8DF.js} +1 -1
- package/dist/client/index.html +3 -3
- package/dist/server/index.js +3 -3
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as y}from"./rolldown-runtime-M0oDzQ_3.js";import{Wn as r,Wt as w,nn as d}from"./ui-vendor-dYn1tJGA.js";import{_ as b,g as C}from"./vue-vendor-DZ4A_GHn.js";import{l as v,u as S}from"./_plugin-vue_export-helper-
|
|
1
|
+
import{n as y}from"./rolldown-runtime-M0oDzQ_3.js";import{Wn as r,Wt as w,nn as d}from"./ui-vendor-dYn1tJGA.js";import{_ as b,g as C}from"./vue-vendor-DZ4A_GHn.js";import{l as v,u as S}from"./_plugin-vue_export-helper-CwNymSRn.js";import{a as W,h as A,n as D,p as F,u as g,y as x}from"./system-DaAaRr9k.js";import{Q as l,X as K,Y as N,Z as Q}from"./index-DW8M4rjb.js";var R,E=y((()=>{b(),w(),g(),S(),Q(),N(),R=C("models",()=>{const t=r([]),f=r([]),o=r(""),i=r(""),n=r(!1),u=r(!1),c=d(()=>t.value.filter(e=>e.provider.startsWith("custom:"))),m=d(()=>t.value.filter(e=>!e.provider.startsWith("custom:"))),p=d(()=>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=K().activeProfileName||"default",a=await W(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()){u.value=!0;try{await F(),await s(),await l().reloadModels()}finally{u.value=!1}}}async function M(e,a){await x({default:e,provider:a}),o.value=e,i.value=a,l().reloadModels()}async function h(e){await D(e),await s(),await l().reloadModels()}async function P(e){await A(e),await s(),await l().reloadModels()}return{providers:t,allProviders:f,defaultModel:o,defaultProvider:i,loading:n,refreshingModelCache:u,customProviders:c,builtinProviders:m,allModels:p,fetchProviders:s,refreshModelCache:_,setDefaultModel:M,addProvider:h,removeProvider:P}})}));export{R as n,E as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as w}from"./rolldown-runtime-M0oDzQ_3.js";import{Mn as I,Wn as l,Wt as E}from"./ui-vendor-dYn1tJGA.js";import{_ as J,g as K}from"./vue-vendor-DZ4A_GHn.js";import{X as p,Y as M}from"./index-
|
|
1
|
+
import{n as w}from"./rolldown-runtime-M0oDzQ_3.js";import{Mn as I,Wn as l,Wt as E}from"./ui-vendor-dYn1tJGA.js";import{_ as J,g as K}from"./vue-vendor-DZ4A_GHn.js";import{X as p,Y as M}from"./index-DW8M4rjb.js";function v(){try{return p().activeProfileName||"default"}catch{return localStorage.getItem("hermes_active_profile_name")||"default"}}function f(n){return`${g}${n}`}function c(n){return`${h}${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 Y(n,e){return n.length===e.length&&n.every((t,u)=>t===e[u])}var g,h,$,W=w((()=>{J(),E(),M(),g="hermes_session_pins_v1_",h="hermes_human_only_v1_",$=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 y(r){o(r)?e.value=e.value.filter(i=>i!==r):e.value=[...e.value,r],s()}function P(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 Y(_,e.value)?!1:(e.value=_,s(),!0)}return I(()=>p().activeProfileName,()=>u()),{profileName:n,pinnedIds:e,humanOnly:t,reload:u,isPinned:o,togglePinned:y,removePinned:P,setHumanOnly:S,pruneMissingSessions:N}})}));export{$ as n,W as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as p}from"./rolldown-runtime-M0oDzQ_3.js";import{a as y,f as t,o as u,s as d,u as k}from"./_plugin-vue_export-helper-
|
|
1
|
+
import{n as p}from"./rolldown-runtime-M0oDzQ_3.js";import{a as y,f as t,o as u,s as d,u as k}from"./_plugin-vue_export-helper-CwNymSRn.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=d(),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((()=>{k()}));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 r}from"./rolldown-runtime-M0oDzQ_3.js";import{f as t,u as s}from"./_plugin-vue_export-helper-
|
|
1
|
+
import{n as r}from"./rolldown-runtime-M0oDzQ_3.js";import{f as t,u as s}from"./_plugin-vue_export-helper-CwNymSRn.js";async function o(){return t("/health")}async function d(){return t("/api/hermes/update",{method:"POST"})}async function c(){return t("/api/hermes/update/status")}async function m(){return t("/api/hermes/update/preview")}async function u(){return t("/api/hermes/update/preview/tags")}async function p(e){return t("/api/hermes/update/preview/prepare",{method:"POST",body:JSON.stringify({tag:e})})}async function h(){return t("/api/hermes/update/preview/install",{method:"POST"})}async function f(e){return t("/api/hermes/update/preview/start",{method:"POST",body:JSON.stringify({tag:e})})}async function l(){return t("/api/hermes/update/preview/stop",{method:"POST"})}async function y(){return t("/api/hermes/available-models")}async function v(e){const a=new URLSearchParams;return a.set("profile",e||"default"),t(`/api/hermes/available-models?${a.toString()}`)}async function P(e){return t("/api/hermes/provider-models",{method:"POST",body:JSON.stringify(e)})}async function S(){return t("/api/hermes/provider-models/cache/refresh",{method:"POST"})}async function g(e){await t("/api/hermes/config/model",{method:"PUT",body:JSON.stringify(e)})}async function w(e){await t("/api/hermes/model-alias",{method:"PUT",body:JSON.stringify(e)})}async function O(e){await t("/api/hermes/config/providers",{method:"POST",body:JSON.stringify(e)})}async function b(e){await t(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"DELETE"})}async function T(e,a){await t(`/api/hermes/config/providers/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(a)})}async function U(e){return t("/api/hermes/model-visibility",{method:"PUT",body:JSON.stringify(e)})}async function M(e){return t("/api/hermes/custom-model",{method:"PUT",body:JSON.stringify(e)})}async function J(e){const a=new URLSearchParams;return a.set("provider",e.provider),a.set("model",e.model),t(`/api/hermes/custom-model?${a.toString()}`,{method:"DELETE"})}var N=r((()=>{s()}));export{T as S,l as _,v as a,w as b,P as c,h as d,p as f,f as g,b as h,y as i,c as l,J as m,O as n,m as o,S as p,o as r,u as s,M as t,N as u,d as v,U as x,g as y};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as Y}from"./rolldown-runtime-M0oDzQ_3.js";import{Mn as he,Wn as s,Wt as ie,nn as Ae}from"./ui-vendor-dYn1tJGA.js";import{f as k,u as se}from"./_plugin-vue_export-helper-
|
|
1
|
+
import{n as Y}from"./rolldown-runtime-M0oDzQ_3.js";import{Mn as he,Wn as s,Wt as ie,nn as Ae}from"./ui-vendor-dYn1tJGA.js";import{f as k,u as se}from"./_plugin-vue_export-helper-CwNymSRn.js";function Je(e={}){const t=s({status:"idle",error:null,startedAt:null,mimeType:null}),o=Ae(()=>t.value.status==="recording");let u=null,V=null,F=[],I=null,h=null,b=null,L=null,_=null,w=null,E=null,U=0;function B(){t.value={status:"idle",error:null,startedAt:null,mimeType:null}}function R(r){const n=be(r);return t.value={status:"error",error:n,startedAt:null,mimeType:t.value.mimeType},n}function Z(){I!==null&&(clearTimeout(I),I=null)}function te(r){if(r)for(const n of r.getTracks())n.stop()}function l({stopStream:r=!0,clearChunks:n=!0}={}){Z(),r&&te(V),u=null,V=null,n&&(F=[])}function re(r){const n=b;h=null,b=null,L=null,n?.(r)}function q(r){const n=L;h=null,b=null,L=null,n?.(r)}function ve(){!b&&!L||re(J(t.value.mimeType??u?.mimeType??null))}function N(r){if(r!==void 0&&r!==_)return;const n=w;_=null,w=null,E=null,n?.()}function fe(r,n){if(n!==void 0&&n!==_)return;const S=E;_=null,w=null,E=null,S?.(r)}function ne(){!w&&!E||N()}function J(r){return new Blob([],{type:r||x})}function ye(){return typeof MediaRecorder>"u"?null:MediaRecorder}function Se(){const r=ye();if(!r||typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw new Error(e.messages?.unsupported||le);return r}function Pe(r,n){const S=n?.length?n:[...ae];return typeof r.isTypeSupported!="function"?S[0]:S.find(O=>r.isTypeSupported(O))}function Te(){if(t.value.status==="recording"||t.value.status==="requesting"||t.value.status==="stopping")return Promise.resolve();try{const r=Se(),n=++U;return t.value={status:"requesting",error:null,startedAt:null,mimeType:null},new Promise((S,O)=>{_=n,w=S,E=O,navigator.mediaDevices.getUserMedia(e.constraints??{audio:!0}).then(a=>{if(n!==U){te(a),N(n);return}const P=Pe(r,e.mimeTypes),D=P?new r(a,{mimeType:P}):new r(a);V=a,u=D,F=[],D.ondataavailable=ee=>{const K=ee.data;K&&K.size>0&&F.push(K)},D.onerror=ee=>{const K=R(ee.error??new Error(e.messages?.recordingFailed||"Microphone recording failed."));l(),q(K)},D.start(),t.value={status:"recording",error:null,startedAt:Date.now(),mimeType:D.mimeType||P||x},I=setTimeout(()=>{oe()},e.maxDurationMs??ue),N(n)}).catch(a=>{if(n!==U){N(n);return}l(),fe(R(a),n)})})}catch(r){return l(),Promise.reject(R(r))}}async function oe(){if(t.value.status==="requesting")return U+=1,ne(),l(),B(),J();const r=u;if(!r){const n=t.value.mimeType;return B(),J(n)}if(h)return h;if(r.state==="inactive"){const n=r.mimeType||t.value.mimeType;return l(),B(),J(n)}return t.value={...t.value,status:"stopping",error:null},Z(),h=new Promise((n,S)=>{b=n,L=S;const O=r.mimeType||t.value.mimeType||x;r.onstop=()=>{const a=new Blob(F,{type:O});l(),B(),re(a)},r.onerror=a=>{const P=R(a.error??new Error(e.messages?.recordingFailed||"Microphone recording failed."));l(),q(P)};try{r.stop()}catch(a){const P=R(a);l(),q(P)}}),h}function Me(){U+=1;const r=u;if(Z(),r&&(r.ondataavailable=null,r.onstop=null,r.onerror=null,r.state!=="inactive"))try{r.stop()}catch{}l(),ne(),ve(),B()}return{state:t,isRecording:o,start:Te,stop:oe,cancel:Me}}function be(e){return e instanceof Error?e:new Error(String(e))}var ae,x,ue,le,xe=Y((()=>{ie(),ae=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/wav"],x="audio/webm",ue=12e4,le="Microphone capture is not supported in this browser."}));async function Ge(e){if(!e.provider)throw new Error("STT provider is required");const t=new FormData;return t.append("audio",e.audio,"speech.webm"),t.append("provider",e.provider),typeof e.language=="string"&&e.language&&t.append("language",e.language),typeof e.prompt=="string"&&e.prompt&&t.append("prompt",e.prompt),k("/api/hermes/stt/transcribe",{method:"POST",body:t})}var We=Y((()=>{se()}));function Le(e){return e==="browser"||e==="openai"||e==="custom"?e:null}function _e(e){if(e&&typeof e=="object"){const t=e,o=Le(t.activeProvider);if(Array.isArray(t.providers))return{providers:t.providers,activeProvider:o};if(Array.isArray(t.settings))return{providers:t.settings,activeProvider:o}}return{providers:[],activeProvider:null}}async function we(){return _e(await k("/api/hermes/stt/settings"))}async function Ye(e,t){const o=await k(`/api/hermes/stt/settings/${e}`,{method:"PUT",body:JSON.stringify(t)});return typeof o=="object"&&o!==null&&"setting"in o?o.setting:o}async function $e(e){return(await k("/api/hermes/stt/settings/active",{method:"PUT",body:JSON.stringify({provider:e})})).activeProvider}async function He(e,t){const o=await k(`/api/hermes/stt/settings/${e}/secret/${t}`,{method:"DELETE"});return o&&typeof o=="object"&&"setting"in o?o.setting??null:o}var Ee=Y((()=>{se()}));function Ue(){if(typeof window>"u")return!1;const e=window;return typeof e.SpeechRecognition<"u"||typeof e.webkitSpeechRecognition<"u"}function ce(){return Ue()?"browser":"openai"}function Be(e){return{provider:e.provider==="browser"||e.provider==="openai"||e.provider==="custom"?e.provider:i.provider,openaiModel:typeof e.openaiModel=="string"&&e.openaiModel.trim()?e.openaiModel:i.openaiModel,openaiLanguage:typeof e.openaiLanguage=="string"?e.openaiLanguage:i.openaiLanguage,openaiPrompt:typeof e.openaiPrompt=="string"?e.openaiPrompt:i.openaiPrompt,customBaseUrl:typeof e.customBaseUrl=="string"?e.customBaseUrl:i.customBaseUrl,customModel:typeof e.customModel=="string"&&e.customModel.trim()?e.customModel:i.customModel,customLanguage:typeof e.customLanguage=="string"?e.customLanguage:i.customLanguage,customPrompt:typeof e.customPrompt=="string"?e.customPrompt:i.customPrompt}}function Re(){try{const e=localStorage.getItem(j);if(e){const t=Be(JSON.parse(e)),o=JSON.stringify(t);return e!==o&&localStorage.setItem(j,o),t}}catch{}return{...i}}function Oe(){return{provider:M.value,openaiModel:p.value,openaiLanguage:m.value,openaiPrompt:g.value,customBaseUrl:d.value,customModel:v.value,customLanguage:f.value,customPrompt:y.value}}function De(){try{localStorage.setItem(j,JSON.stringify(Oe()))}catch(e){console.warn("[useSttSettings] Failed to persist STT settings:",e)}}function pe(){p.value=i.openaiModel,m.value=i.openaiLanguage,g.value=i.openaiPrompt,z.value="",$.value="",H.value=!1,d.value=i.customBaseUrl,A.value=[],v.value=i.customModel,f.value=i.customLanguage,y.value=i.customPrompt,C.value="",X.value="",Q.value=!1}function Ke(){M.value=ce(),p.value=i.openaiModel,m.value=i.openaiLanguage,g.value=i.openaiPrompt,d.value=i.customBaseUrl,A.value=[],v.value=i.customModel,f.value=i.customLanguage,y.value=i.customPrompt}function me(){W+=1,G=!1,T=null,Ke(),pe();try{localStorage.removeItem(j)}catch{}}function ge(e){return Array.isArray(e)?Array.from(new Set(e.filter(t=>typeof t=="string"&&!!t.trim()).map(t=>t.trim()))):[]}function je(e){e.provider==="openai"&&(p.value=typeof e.settings.model=="string"&&e.settings.model.trim()?e.settings.model:p.value,m.value=typeof e.settings.language=="string"?e.settings.language:m.value,g.value=typeof e.settings.prompt=="string"?e.settings.prompt:g.value,$.value=e.secrets.apiKey||"",H.value=!!e.secrets.apiKey,z.value=""),e.provider==="custom"&&(d.value=typeof e.settings.baseUrl=="string"?e.settings.baseUrl:d.value,A.value=ge(e.settings.baseUrlPresets),v.value=typeof e.settings.model=="string"&&e.settings.model.trim()?e.settings.model:v.value,f.value=typeof e.settings.language=="string"?e.settings.language:f.value,y.value=typeof e.settings.prompt=="string"?e.settings.prompt:y.value,X.value=e.secrets.apiKey||"",Q.value=!!e.secrets.apiKey,C.value="")}function de(e,t=!1){t&&pe();const o=Array.isArray(e)?e:e.providers;for(const u of o)je(u);!Array.isArray(e)&&e.activeProvider&&(M.value=e.activeProvider)}async function ze(e=!1){if(G&&!e)return;if(T&&!e)return T;const t=W,o=we().then(u=>{t===W&&(de(u,!0),G=!0)}).finally(()=>{T===o&&(T=null)});return T=o,o}function Xe(){return{provider:M,openaiModel:p,openaiLanguage:m,openaiPrompt:g,openaiApiKey:z,openaiApiKeyPreview:$,openaiHasApiKey:H,customBaseUrl:d,customBaseUrlPresets:A,customModel:v,customLanguage:f,customPrompt:y,customApiKey:C,customApiKeyPreview:X,customHasApiKey:Q,setProvider(e){M.value=e},setOpenaiModel(e){p.value=e},setOpenaiLanguage(e){m.value=e},setOpenaiPrompt(e){g.value=e},setOpenaiApiKey(e){z.value=e},setCustomBaseUrl(e){d.value=e},setCustomBaseUrlPresets(e){A.value=ge(e)},setCustomModel(e){v.value=e},setCustomLanguage(e){f.value=e},setCustomPrompt(e){y.value=e},setCustomApiKey(e){C.value=e},applyServerSttSettings:de,loadServerSttSettings:ze,reset(){me()}}}var j,i,c,M,p,m,g,z,$,H,d,A,v,f,y,C,X,Q,G,T,W,Qe=Y((()=>{ie(),Ee(),j="hermes-stt-settings-v1",i={provider:ce(),openaiModel:"gpt-4o-transcribe",openaiLanguage:"",openaiPrompt:"",customBaseUrl:"",customModel:"gpt-4o-transcribe",customLanguage:"",customPrompt:""},c=Re(),M=s(c.provider),p=s(c.openaiModel),m=s(c.openaiLanguage),g=s(c.openaiPrompt),z=s(""),$=s(""),H=s(!1),d=s(c.customBaseUrl),A=s([]),v=s(c.customModel),f=s(c.customLanguage),y=s(c.customPrompt),C=s(""),X=s(""),Q=s(!1),G=!1,T=null,W=0,typeof window<"u"&&window.addEventListener("hermes-auth-cleared",me),he([M,p,m,g,d,v,f,y],De)}));export{Ee as a,We as c,Je as d,we as i,Ge as l,Xe as n,$e as o,He as r,Ye as s,Qe as t,xe as u};
|
package/dist/client/index.html
CHANGED
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
}
|
|
34
34
|
})();
|
|
35
35
|
</script>
|
|
36
|
-
<script type="module" crossorigin src="/assets/js/index-
|
|
36
|
+
<script type="module" crossorigin src="/assets/js/index-DW8M4rjb.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-dYn1tJGA.js">
|
|
40
40
|
<link rel="modulepreload" crossorigin href="/assets/js/vendor-B1Lfatlz.js">
|
|
41
41
|
<link rel="modulepreload" crossorigin href="/assets/js/vue-vendor-DZ4A_GHn.js">
|
|
42
|
-
<link rel="modulepreload" crossorigin href="/assets/js/_plugin-vue_export-helper-
|
|
43
|
-
<link rel="modulepreload" crossorigin href="/assets/js/system-
|
|
42
|
+
<link rel="modulepreload" crossorigin href="/assets/js/_plugin-vue_export-helper-CwNymSRn.js">
|
|
43
|
+
<link rel="modulepreload" crossorigin href="/assets/js/system-DaAaRr9k.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-C-LxXPm3.css">
|
package/dist/server/index.js
CHANGED
|
@@ -272,7 +272,7 @@ const isVersionPreview = import.meta.env.VITE_HERMES_PREVIEW === '1';`)),l=l.rep
|
|
|
272
272
|
`),b.destroy();return}l.handleUpgrade(e,b,d,n=>{l.emit("connection",n,e)})}})}),l.on("connection",(c,e)=>{let b=e.kanbanBoard||"default",d=Bf({board:b,interval:.5}),Z=!1;xs(c,{type:"connected",board:b});let n=()=>{Z||(Z=!0,d.killed||d.kill())};d.stdout?.on("data",cj(t=>{t.toLowerCase().startsWith("watching kanban events")||xs(c,{type:"event",board:b})})),d.stderr?.on("data",cj(t=>{xs(c,{type:"error",board:b,message:t})})),d.on("error",t=>{V.error(t,"Hermes CLI: kanban watch failed"),xs(c,{type:"error",board:b,message:t.message}),c.readyState===c.OPEN&&c.close()}),d.on("exit",(t,a)=>{xs(c,{type:"stopped",board:b,code:t,signal:a}),c.readyState===c.OPEN&&c.close()}),c.on("close",n),c.on("error",n)}),V.info("WebSocket ready at /api/hermes/kanban/events (kanban watch bridge)")}var sj=C(Fm(),1),xwI=C(Mh(),1),Yj=C(Fm(),1),NQ=C(Mh(),1),Yo=require("url"),Aa=C(aj(),1),hj=C(require("http"),1),pj=C(ol(),1),Nj={NotFound:"not-found"};function LwI(I){return typeof I=="function"?I(Nj):I}var kwI=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,sj.default)(c)(l,G):G()}};function No(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:e}=(0,Aa.pathToRegexp)(I,G);return{regexp:c,keys:e}}function zwI(I,l={}){return(0,Aa.compile)(I,l)}function UwI(I,l){return(0,Aa.parse)(I,l)}function mQ(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 BwI(I){try{return decodeURIComponent(I)}catch{return I}}var Wj=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 e of c){let b=typeof e;if(b!=="function"){let d=this.opts.name||G;throw new Error(`${l.toString()} \`${d}\`: \`middleware\` must be a function, not \`${b}\``)}}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=mQ(this.opts),{regexp:l,keys:G}=No(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[e,b]of l.entries()){let d=this.paramNames[e];if(d&&b&&b.length>0){let Z=d.name;c[Z]=BwI(b)}}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("(.*)",""),e=zwI(c,{encode:encodeURIComponent,...G}),b=this._buildParamReplacements(l,c),d=e(b);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],e=c.at(-1);typeof e=="object"&&e!==null?(G=e,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:b,...d}=l;G={query:b},l=d}}return{params:l,options:G}}_buildParamReplacements(I,l){let{tokens:G}=UwI(l),c=G.some(b=>"name"in b&&b.name),e={};if(Array.isArray(I)){let b=0;for(let d of G)"name"in d&&d.name&&(e[d.name]=String(I[b++]))}else if(c&&typeof I=="object"&&!("query"in I))for(let[b,d]of Object.entries(I))e[b]=String(d);return e}_addQueryString(I,l){let G=(0,Yo.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,Yo.format)(c)}param(I,l){let G=this.stack,c=this.paramNames,e=this._createParamMiddleware(I,l),b=c.map(Z=>Z.name),d=b.indexOf(I);return d!==-1&&this._insertParamMiddleware(G,e,b,d),this}_createParamMiddleware(I,l){let G=((c,e)=>(c._matchedParams||(c._matchedParams=new WeakMap),c._matchedParams.has(l)?e():(c._matchedParams.set(l,!0),l(c.params[I],c,e))));return G.param=I,G._originalFn=l,G}_insertParamMiddleware(I,l,G,c){let e=!1;for(let b=0;b<I.length;b++){let d=I[b];if(!d.param){I.splice(b,0,l),e=!0;break}if(G.indexOf(d.param)>c){I.splice(b,0,l),e=!0;break}}e||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(":"),e=this.opts.pathAsRegExp===!0&&typeof this.path=="string";if(c&&e){let b=this.path;(b===String.raw`(?:\/|$)`||b===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=mQ(this.opts),{regexp:e,keys:b}=No(this.path,c);this.regexp=e,this.paramNames=b,this.opts.pathAsRegExp=!1}else if(l){let c=this.path,e=c.startsWith("^")?c:`^${c}`;this.regexp=this.path instanceof RegExp?this.path:new RegExp(e)}else{let c=mQ(this.opts),{regexp:e,keys:b}=No(this.path,c);this.regexp=e,this.paramNames=b}}};function OwI(){return hj.default.METHODS.map(I=>I.toLowerCase())}var MwI=["get","post","put","patch","delete","del","head","options"];function fwI(I){return I?Array.isArray(I)?I:[I]:[]}function uj(I,l,G){let c=fwI(G);for(let e of c)I.param(l,e)}function jwI(I,l){let G=Object.keys(l);for(let c of G){let e=l[c];uj(I,c,e)}}function mj(I,l={}){if(!I)return!1;let{keys:G}=No(I,l);return G.length>0}function KwI(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 sQ=(0,pj.default)("koa-router"),oj=OwI(),YQ=class{opts;methods;exclusive;params;stack;host;_events=new kwI;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 Wj(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),e=l&&typeof l=="string"&&mj(l,this.opts);for(let b=0;b<c.stack.length;b++){let d=c.stack[b],Z=this._cloneLayer(d);l&&typeof l=="string"&&Z.setPrefix(l),this.opts.prefix&&Z.setPrefix(this.opts.prefix),Z.methods.length===0&&e&&(Z.opts.ignoreCaptures=!1),this.stack.push(Z),c.stack[b]=Z}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];uj(I,G,c)}}_registerMiddleware(I,l,G){let c=mj(this.opts.prefix||"",this.opts),e=(()=>{if(l!==void 0)return l;if(c)return""})(),b=G||l===void 0&&c,{path:d,pathAsRegExp:Z}=KwI(e,c),n=d,t=Z,a=b&&d==="/";b&&typeof d=="string"&&(n=d,t=!1),this.register(n,[],I,{end:a,ignoreCaptures:!b&&!c,pathAsRegExp:t})}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 e=G+"/";(c.path===G||c.path.startsWith(e))&&(c.path=c.path.slice(G.length)||"/")}c.setPrefix(l)}return this}middleware(){let I=function(l,G){if(sQ("%s %s",l.method,l.path),!this.matchHost(l.host))return G();let c=this._getRequestPath(l),e=this.match(c,l.method);if(this._storeMatchedRoutes(l,e),l.router=this,l.routeMatched=e.route,!e.route)return this._events.emit(Nj.NotFound,l,G);let b=e.pathAndMethod;this._setMatchedRouteInfo(l,b);let d=this._buildMiddlewareChain(b,c);return(0,Yj.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(e=>e.methods.length>0);c&&(G._matchedRoute=c.path,c.name&&(G._matchedRouteName=c.name))}_buildMiddlewareChain(I,l){let G;if(this.exclusive){let e;if(this.opts.exclusive==="specificity")for(let b of I)(!e||b.paramNames.length<e.paramNames.length)&&(e=b);else e=I.at(-1);G=e?[e]:[]}else G=I;let c=[];for(let e of G)c.push((b,d)=>{let Z=b;return Z.captures=e.captures(l),Z.request.params=e.params(l,Z.captures||[],Z.params),Z.params=Z.request.params,Z.routerPath=e.path,Z.routerName=e.name||void 0,Z._matchedRoute=e.path,e.name&&(Z._matchedRouteName=e.name),d()},...e.stack);return c}routes(){return this.middleware()}on(I,l){return this._events.register(LwI(I),l),this}allowedMethods(I={}){let l=this.methods;return(G,c)=>{let e=G;return c().then(()=>{if(!this._shouldProcessAllowedMethods(e))return;let b=e.matched||[],d=this._collectAllowedMethods(b),Z=Object.keys(d),n=G.method.toUpperCase();if(!l.includes(n)){this._handleNotImplemented(e,Z,I);return}if(n==="OPTIONS"&&Z.length>0){this._handleOptionsRequest(e,Z);return}Z.length>0&&!d[n]&&this._handleMethodNotAllowed(e,Z,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 NQ.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 NQ.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 e={name:l,pathAsRegExp:G instanceof RegExp};return this.register(G,oj,c,{...this.opts,...e}),this}redirect(I,l,G){let c=I,e=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;e=d}return this.all(c,d=>{d.redirect(e),d.status=G||301})}register(I,l,G,c={}){let e={...this.opts,...c};if(Array.isArray(I))return this._registerMultiplePaths(I,l,G,e);let b=this._createRouteLayer(I,l,G,e);return this.opts.prefix&&b.setPrefix(this.opts.prefix),jwI(b,this.params),this.stack.push(b),sQ("defined route %s %s",b.methods,b.path),b}_registerMultiplePaths(I,l,G,c){for(let e of I)this.register.call(this,e,l,G,c);return this}_createRouteLayer(I,l,G,c){return new Wj(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 e of this.stack)if(sQ("test %s %s",e.path,e.regexp),e.match(I)){G.path.push(e);let b=e.methods.length===0,d=e.methods.includes(c);(b||d)&&(G.pathAndMethod.push(e),e.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,e;if(l.length>=2&&(typeof l[1]=="string"||l[1]instanceof RegExp)?(G=l[0],c=l[1],e=l.slice(2)):(G=void 0,c=l[0],e=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 b={name:G,pathAsRegExp:c instanceof RegExp};return this.register(c,[I],e,{...this.opts,...b}),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)}},SwI=YQ,B=SwI;for(let I of oj)MwI.includes(I)||I in YQ.prototype||Object.defineProperty(YQ.prototype,I,{value:function(...G){return this._registerMethod(I,...G)},writable:!0,configurable:!0,enumerable:!1});Xn();JI();var jd=require("child_process"),Uc=require("fs"),UQ=require("net"),NI=require("path");GI();ac();var EQ=require("timers/promises"),gQ=require("net"),dK=require("os"),ZK=require("url"),JQ=require("path");GI();VI();function RvI(){return process.env.VITEST?process.platform==="win32"?`tcp://127.0.0.1:${28e3+process.pid%1e4}`:`ipc://${(0,JQ.join)((0,dK.tmpdir)(),`hermes-agent-bridge-test-${process.pid}.sock`)}`:process.platform==="win32"?"tcp://127.0.0.1:18765":"ipc:///tmp/hermes-agent-bridge.sock"}var CQ=RvI(),FvI=12e4;function bK(I){let l=process.env[I];if(!l)return;let G=Number(l);return Number.isFinite(G)&&G>0?G:void 0}var wo=class extends Error{response},PI=class{endpoint;timeoutMs;connectRetryMs;lock=Promise.resolve();constructor(l={}){this.endpoint=l.endpoint||process.env.HERMES_AGENT_BRIDGE_ENDPOINT||CQ,this.timeoutMs=l.timeoutMs??bK("HERMES_AGENT_BRIDGE_TIMEOUT_MS")??FvI,this.connectRetryMs=l.connectRetryMs??bK("HERMES_AGENT_BRIDGE_CONNECT_RETRY_MS")??5e3}summarizePayload(l){let c={action:String(l.action||"")};for(let e of["session_id","run_id","request_id","approval_id","profile","worker_key"])l[e]!=null&&(c[e]=l[e]);return Array.isArray(l.conversation_history)&&(c.conversation_history_count=l.conversation_history.length),Array.isArray(l.messages)&&(c.messages_count=l.messages.length),typeof l.message=="string"?c.message_chars=l.message.length:Array.isArray(l.message)&&(c.message_parts=l.message.length),typeof l.command=="string"&&(c.command=l.command),typeof l.text=="string"&&(c.text_chars=l.text.length),typeof l.error=="string"&&(c.error=l.error),l.force_compress===!0&&(c.force_compress=!0),c}summarizeResponse(l){let G={ok:l.ok===!0};for(let c of["session_id","run_id","request_id","status","cursor","event_cursor"])l[c]!=null&&(G[c]=l[c]);return typeof l.delta=="string"&&(G.delta_chars=l.delta.length),typeof l.output=="string"&&(G.output_chars=l.output.length),Array.isArray(l.events)&&(G.events_count=l.events.length),typeof l.error=="string"&&(G.error=l.error),Array.isArray(l.history)&&(G.history_count=l.history.length),G}runtimeContext(l){let G=typeof l.profile=="string"?l.profile.trim():"",c=G||"default";try{G||(c=cI())}catch{}let e={profile:c,cwd:process.cwd()};try{let b=T(c);e.profile_dir=b,e.config_path=(0,JQ.join)(b,"config.yaml")}catch{}return e}async connect(){return this}async close(){}connectSocketOnce(){return new Promise((l,G)=>{let c=this.endpoint,e;if(c.startsWith("ipc://"))e=(0,gQ.createConnection)(c.slice(6));else if(c.startsWith("tcp://")){let n=new ZK.URL(c);e=(0,gQ.createConnection)({host:n.hostname||"127.0.0.1",port:Number(n.port)})}else{G(new Error(`unsupported agent bridge endpoint: ${c}`));return}let b=()=>{e.off("connect",d),e.off("error",Z)},d=()=>{b(),l(e)},Z=n=>{b(),e.destroy(),G(n)};e.once("connect",d),e.once("error",Z)})}isRetryableConnectError(l){let G=String(l?.code||"");return["ECONNREFUSED","ENOENT","ECONNRESET","EPIPE","ETIMEDOUT"].includes(G)}async connectSocket(){let l=Date.now()+Math.max(0,this.connectRetryMs);for(;;)try{return await this.connectSocketOnce()}catch(G){if(!this.isRetryableConnectError(G)||Date.now()>=l)throw G;await(0,EQ.setTimeout)(100)}}readResponse(l,G){return new Promise((c,e)=>{let b="",d=G>0?setTimeout(()=>{Z(),l.destroy(),e(new Error(`Agent bridge request timed out after ${G}ms`))},G):null,Z=()=>{d&&clearTimeout(d),l.off("data",t),l.off("error",a),l.off("end",W),l.off("close",m)},n=s=>{Z(),l.end(),c(s)},t=s=>{b+=s.toString("utf8");let N=b.indexOf(`
|
|
273
273
|
`);N>=0&&n(b.slice(0,N))},a=s=>{Z(),l.destroy(),e(s)},W=()=>{let s=b.trim();s&&n(s)},m=()=>{b.trim()||(Z(),e(new Error("Agent bridge socket closed without a response")))};l.on("data",t),l.once("error",a),l.once("end",W),l.once("close",m)})}async request(l,G={}){let c=async()=>{let b=G.timeoutMs||this.timeoutMs,d=Date.now(),n=String(l.action||"")!=="get_output",t=n?this.runtimeContext(l):void 0;n&&rl.info({endpoint:this.endpoint,timeoutMs:b,runtime:t,request:this.summarizePayload(l)},"[agent-bridge-client] request");try{let a=await this.connectSocket();a.write(`${JSON.stringify(l)}
|
|
274
274
|
`);let W=await this.readResponse(a,b),m=JSON.parse(W);if(!m.ok){let s=new wo(m.error||"Agent bridge request failed");throw s.response=m,rl.warn({durationMs:Date.now()-d,runtime:t,response:this.summarizeResponse(m)},"[agent-bridge-client] request rejected"),s}return n&&rl.info({durationMs:Date.now()-d,runtime:t,response:this.summarizeResponse(m)},"[agent-bridge-client] response"),m}catch(a){throw a instanceof wo||rl.error({durationMs:Date.now()-d,err:{message:a?.message,name:a?.name},runtime:t,request:this.summarizePayload(l)},"[agent-bridge-client] request failed"),a}};if(!G.serialize)return c();let e=this.lock.then(c,c);return this.lock=e.catch(()=>{}),e}ping(){return this.request({action:"ping"})}chat(l,G,c,e,b,d={}){return this.request({action:"chat",session_id:l,message:G,...d.storage_message!==void 0?{storage_message:d.storage_message}:{},...c?{conversation_history:c}:{},...e?{instructions:e}:{},...b?{profile:b}:{},...d.model?{model:d.model}:{},...d.provider?{provider:d.provider}:{},...d.source?{source:d.source}:{},...d.wait?{wait:!0}:{},...d.timeout?{timeout:d.timeout}:{},...d.force_compress?{force_compress:!0}:{},...d.reasoning_effort?{reasoning_effort:d.reasoning_effort}:{}})}contextEstimate(l,G,c,e,b={}){return this.request({action:"context_estimate",session_id:l,messages:G,...c?{instructions:c}:{},...e?{profile:e}:{},...b.model?{model:b.model}:{},...b.provider?{provider:b.provider}:{}})}command(l,G,c){return this.request({action:"command",session_id:l,command:G,...c?{profile:c}:{}})}goalEvaluate(l,G,c){return this.request({action:"goal_evaluate",session_id:l,final_response:G,...c?{profile:c}:{}})}getOutput(l,G=0,c=0,e={}){return this.request({action:"get_output",run_id:l,cursor:G,event_cursor:c},e)}getSessionTitle(l,G,c={}){return this.request({action:"get_session_title",session_id:l,...G?{profile:G}:{}},c)}async*streamOutput(l,G={}){let c=G.intervalMs||100,e=0,b=0;for(;;){let d=await this.getOutput(l,e,b,G);if(e=d.cursor,b=d.event_cursor,(d.delta||d.done||d.events&&d.events.length>0)&&(yield d),d.done)return;await(0,EQ.setTimeout)(c)}}async chatStream(l,G,c,e={}){let b=await this.chat(l,G),d=null;for await(let Z of this.streamOutput(b.run_id,e))d=Z,Z.delta&&await c(Z.delta,Z);if(!d)throw new Error(`Agent bridge run ${b.run_id} produced no output state`);return d}getResult(l,G={}){return this.request({action:"get_result",run_id:l},G)}interrupt(l,G,c){return this.request({action:"interrupt",session_id:l,message:G,...c?{profile:c}:{}})}goalPause(l,G,c){return this.request({action:"goal_pause",session_id:l,reason:G,...c?{profile:c}:{}})}steer(l,G,c){return this.request({action:"steer",session_id:l,text:G,...c?{profile:c}:{}})}approvalRespond(l,G){return this.request({action:"approval_respond",approval_id:l,choice:G})}clarifyRespond(l,G){return this.request({action:"clarify_respond",clarify_id:l,response:G})}compressionRespond(l,G){return this.request({action:"compression_respond",request_id:l,...G},{timeoutMs:this.timeoutMs})}destroyAll(){return this.request({action:"destroy_all"},{serialize:!0})}destroyProfile(l){return this.request({action:"destroy_profile",profile:l},{serialize:!0})}getHistory(l,G){return this.request({action:"get_history",session_id:l,...G?{profile:G}:{}})}status(l,G){return this.request({action:"status",session_id:l,...G?{profile:G}:{}})}statusIfLoaded(l,G,c={}){return this.request({action:"status_if_loaded",session_id:l,...G?{profile:G}:{}},c)}destroy(l,G,c){return this.request({action:"destroy",session_id:l,...G?{profile:G}:{},...c?{worker_key:c}:{}})}list(){return this.request({action:"list"})}shutdown(){return this.request({action:"shutdown"},{serialize:!0})}mcpList(l){return this.request({action:"mcp_list",...l?{profile:l}:{}})}mcpAdd(l,G,c){return this.request({action:"mcp_server_add",name:l,config:G,...c?{profile:c}:{}},{serialize:!0})}mcpUpdate(l,G,c){return this.request({action:"mcp_server_update",name:l,config:G,...c?{profile:c}:{}},{serialize:!0})}mcpRemove(l,G){return this.request({action:"mcp_server_remove",name:l,...G?{profile:G}:{}},{serialize:!0})}mcpTest(l,G){return this.request({action:"mcp_server_test",name:l,...G?{profile:G}:{}},{timeoutMs:18e4})}mcpTools(l,G,c){return this.request({action:"mcp_tools_list",...l?{server:l}:{},...G?{profile:G}:{},...c?{raw:c}:{}})}mcpReload(l,G){return this.request({action:"mcp_reload",...l?{server:l}:{},...G?{profile:G}:{}},{serialize:!0})}};var XvI=12e4,HvI=1e3,QvI=3e4,wvI=5e3,vvI=250,AQ={HERMES_OPENROUTER_APP_REFERER:"https://hermes-studio.ai",HERMES_OPENROUTER_APP_TITLE:"Hermes Studio",HERMES_OPENROUTER_APP_CATEGORIES:"cli-agent,personal-agent"};function Hn(I){let l=process.env[I];if(!l)return;let G=Number(l);return Number.isFinite(G)&&G>0?G:void 0}function yvI(I){let l=I.trim().toLowerCase();return l==="ipc:///tmp/hermes-agent-bridge.sock"||l==="tcp://127.0.0.1:18765"||l==="tcp://localhost:18765"}function EvI(I,l,G){return{...process.env,HERMES_AGENT_BRIDGE_ENDPOINT:I,HERMES_HOME:l,HERMES_OPENROUTER_APP_REFERER:process.env.HERMES_OPENROUTER_APP_REFERER||AQ.HERMES_OPENROUTER_APP_REFERER,HERMES_OPENROUTER_APP_TITLE:process.env.HERMES_OPENROUTER_APP_TITLE||AQ.HERMES_OPENROUTER_APP_TITLE,HERMES_OPENROUTER_APP_CATEGORIES:process.env.HERMES_OPENROUTER_APP_CATEGORIES||AQ.HERMES_OPENROUTER_APP_CATEGORIES,HERMES_AGENT_ROOT:G?.trim()||""}}function gvI(I){return I?process.platform==="win32"?[(0,NI.join)(I,"venv","Scripts","python.exe"),(0,NI.join)(I,"venv","Scripts","python3.exe"),(0,NI.join)(I,".venv","Scripts","python.exe"),(0,NI.join)(I,".venv","Scripts","python3.exe")]:[(0,NI.join)(I,"venv","bin","python3"),(0,NI.join)(I,"venv","bin","python"),(0,NI.join)(I,".venv","bin","python3"),(0,NI.join)(I,".venv","bin","python")]:[]}function JvI(I){return I?[process.env.HERMES_AGENT_BRIDGE_UV,process.env.UV,...process.platform==="win32"?[I?(0,NI.join)(I,"venv","Scripts","uv.exe"):"",I?(0,NI.join)(I,"venv","Scripts","uv.cmd"):"",I?(0,NI.join)(I,".venv","Scripts","uv.exe"):"",I?(0,NI.join)(I,".venv","Scripts","uv.cmd"):""]:[I?(0,NI.join)(I,"venv","bin","uv"):"",I?(0,NI.join)(I,".venv","bin","uv"):""],"uv"].filter(l=>!!l&&l.trim().length>0):[process.env.HERMES_AGENT_BRIDGE_UV,process.env.UV].filter(l=>!!l&&l.trim().length>0)}function BQ(I){let l=I.trim();if(l){if((0,NI.isAbsolute)(l)||l.includes("/")||l.includes("\\"))return(0,Uc.existsSync)(l)?(0,NI.resolve)(l):void 0;try{return(process.platform==="win32"?(0,jd.execFileSync)("where.exe",[l],{encoding:"utf-8",windowsHide:!0}):(0,jd.execFileSync)("which",[l],{encoding:"utf-8"})).split(/\r?\n/).map(c=>c.trim()).find(Boolean)}catch{return}}}function CvI(){let I=BQ(Xs());if(!I)return;let l=(0,NI.dirname)(I),c=[(0,NI.resolve)(l,".."),(0,NI.resolve)(l,"..",".."),(0,NI.resolve)(l,"..","hermes-agent"),(0,NI.resolve)(l,"..","lib","hermes-agent"),(0,NI.resolve)(l,"..","..","hermes-agent")].find(e=>(0,Uc.existsSync)((0,NI.join)(e,"run_agent.py")));if(c)return c;try{let d=(0,Uc.readFileSync)(I,"utf-8").split(/\r?\n/,1)[0].match(/^#!\s*(.+)$/)?.[1]?.trim().split(/\s+/)[0];if(d){let Z=(0,NI.dirname)(d);return[(0,NI.resolve)(Z,"..",".."),(0,NI.resolve)(Z,"..","..","hermes-agent"),(0,NI.resolve)(Z,"..","..","lib","hermes-agent")].find(t=>(0,Uc.existsSync)((0,NI.join)(t,"run_agent.py")))}}catch{}}function AvI(){let I=BQ(Xs());if(I)try{let c=(0,Uc.readFileSync)(I,"utf-8").split(/\r?\n/,1)[0].match(/^#!\s*(.+)$/)?.[1]?.trim().split(/\s+/)[0];return c&&(0,Uc.existsSync)(c)?c:void 0}catch{return}}function LQ(I){for(let l of I){if(!(0,NI.isAbsolute)(l)&&!l.includes("/")&&!l.includes("\\")){let G=BQ(l);if(G)return G;continue}try{if((0,Uc.existsSync)(l))return l}catch{}}}function LvI(I,l=Ld()){return[I,process.env.HERMES_AGENT_ROOT,(0,NI.join)(l,"hermes-agent"),CvI(),process.cwd(),(0,NI.join)(process.cwd(),"hermes-agent"),"/usr/local/lib/hermes-agent","/usr/local/hermes-agent","/opt/hermes/hermes-agent","/opt/hermes-agent"].filter(c=>!!c&&c.trim().length>0).find(c=>(0,Uc.existsSync)((0,NI.join)(c,"run_agent.py")))}function OQ(I={}){let l=I.hermesHome||Ld(),G=LvI(I.agentRoot,l),c=I.python||process.env.HERMES_AGENT_BRIDGE_PYTHON;if(c)return{command:c,argsPrefix:[],agentRoot:G,hermesHome:l};let e=LQ(gvI(G));if(e)return{command:e,argsPrefix:[],agentRoot:G,hermesHome:l};let b=AvI();if(b&&(0,Uc.existsSync)(b))return{command:b,argsPrefix:[],agentRoot:G,hermesHome:l};let d=LQ(JvI(G));if(d){let n=["run"];return G&&n.push("--project",G),n.push("python"),{command:d,argsPrefix:n,agentRoot:G,hermesHome:l}}return{command:LQ([process.env.PYTHON||"",...process.platform==="win32"?["py","python","python3"]:["python3","python"]])||(process.platform==="win32"?"python":"python3"),argsPrefix:[],agentRoot:G,hermesHome:l}}function kvI(){let I=[(0,NI.resolve)(__dirname,"agent-bridge","hermes_bridge.py"),(0,NI.resolve)(__dirname,"services/hermes/agent-bridge/hermes_bridge.py"),(0,NI.resolve)(process.cwd(),"packages/server/src/services/hermes/agent-bridge/hermes_bridge.py")],l=I.find(G=>(0,Uc.existsSync)(G));if(!l)throw new Error(`agent bridge Python script not found. Tried: ${I.join(", ")}`);return l}function tK(I){return I.startsWith("tcp://")}function nK(I){return I.startsWith("ipc://")?"ipc":I.startsWith("tcp://")?"tcp":"unknown"}function vo(I,l){return I.trim()?(l instanceof Error?l.message:typeof l=="string"?l:void 0)?.replace(/^Error:\s*/,"").trim()||"agent bridge is unreachable":"agent bridge endpoint is not configured"}function xvI(I,l){if(I.reachable)return;let G=I.error?.trim(),c=vo(I.endpoint,l);return G&&G!==c?`${G}; start failed: ${c}`:G||c}function zvI(){let I=String(process.env.HERMES_AGENT_BRIDGE_KILL_STALE_IPC||"").trim().toLowerCase();return["1","true","yes","on"].includes(I)}async function xQ(I){let l=new URL(I),G=l.hostname||"127.0.0.1",c=Number(l.port);return!Number.isFinite(c)||c<=0?!1:await new Promise(e=>{let b=(0,UQ.createServer)(),d=Z=>{b.removeAllListeners(),e(Z)};b.once("error",()=>d(!1)),b.listen(c,G,()=>{b.close(()=>d(!0))})})}function UvI(I){if(!tK(I))return;let l=new URL(I),G=Number(l.port);return Number.isFinite(G)&&G>0?G:void 0}function BvI(I){try{let l=(0,jd.execFileSync)("netstat.exe",["-ano","-p","tcp"],{windowsHide:!0}).toString("utf8"),G=new Set;for(let c of l.split(/\r?\n/)){let e=c.trim().split(/\s+/);if(e.length<5)continue;let[b,d,,Z,n]=e;if(b.toUpperCase()!=="TCP"||Z.toUpperCase()!=="LISTENING"||!d.endsWith(`:${I}`))continue;let t=Number(n);Number.isFinite(t)&&t>0&&t!==process.pid&&G.add(t)}return[...G]}catch{return[]}}async function OvI(I,l){let G=Date.now()+l;for(;Date.now()<G;){if(await xQ(I))return!0;await new Promise(c=>setTimeout(c,100))}return xQ(I)}async function MvI(I){let l=UvI(I);if(!l)return;let G=BvI(l);if(G.length){for(let c of G)try{V.warn("[agent-bridge] killing stale process tree pid=%d on bridge port %d",c,l),(0,jd.execFileSync)("taskkill.exe",["/PID",String(c),"/T","/F"],{encoding:"utf-8",windowsHide:!0})}catch(e){V.warn(e,"[agent-bridge] failed to kill stale bridge process pid=%d",c)}await OvI(I,3e3)}}async function fvI(I){let l=I.replace(/^ipc:\/\//,"");if(!l)return;let G=l.includes("hermes-agent-bridge-workers"),c=`${l.replace(/\/[^/]+$/,"")}`.replace(/hermes-agent-bridge-workers$/,"hermes-agent-bridge-workers"),e=[l];if(!G){let d=require("path").join(require("path").dirname(l),"hermes-agent-bridge-workers");try{let Z=await import("fs");for(let n of await Z.promises.readdir(d))e.push(require("path").join(d,n))}catch{}}let b=new Set;for(let d of e)try{let Z=(0,jd.execFileSync)("lsof",["-F","p","-U","--",d],{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim();for(let n of Z.split(`
|
|
275
|
-
`)){let t=Number(n.replace(/^p/,""));Number.isFinite(t)&&t>0&&t!==process.pid&&b.add(t)}}catch{}if(b.size){for(let d of b)try{V.warn("[agent-bridge] killing stale bridge process pid=%d on IPC socket %s",d,l),process.kill(d,"SIGKILL")}catch(Z){V.warn(Z,"[agent-bridge] failed to kill stale bridge process pid=%d",d)}await new Promise(d=>setTimeout(d,500))}}var zQ=class{endpoint;options;explicitEndpoint;child=null;attached=!1;starting=null;recovery=null;ready=!1;stopping=!1;stopGeneration=0;restartTimer=null;restartAttempts=0;constructor(l={}){this.options=l,this.explicitEndpoint=!!(l.endpoint||process.env.HERMES_AGENT_BRIDGE_ENDPOINT),this.endpoint=l.endpoint||process.env.HERMES_AGENT_BRIDGE_ENDPOINT||CQ}get running(){return this.ready&&(this.attached||!!this.child&&!this.child.killed)}getRuntimeState(){return{endpoint:this.endpoint,running:this.running,ready:this.ready,attached:this.attached,pid:this.child?.pid,starting:!!this.starting,stopping:this.stopping,restartScheduled:!!this.restartTimer,restartAttempts:this.restartAttempts}}transientReadiness(l,G){let c=this.getRuntimeState(),e=c.endpoint,b={endpoint:e,endpointKind:nK(e),status:l,reachable:!1,ready:!1,running:!1,attached:c.attached,starting:c.starting,stopping:c.stopping,restartScheduled:c.restartScheduled,restartAttempts:c.restartAttempts,pid:c.pid};return G?{...b,error:G}:b}async waitForPromiseSettlementWithin(l,G){if(!G||G<=0){try{await l}catch{}return!0}return new Promise(c=>{let e=!1,b=setTimeout(()=>{e||(e=!0,c(!1))},G);l.finally(()=>{e||(e=!0,clearTimeout(b),c(!0))}).catch(()=>{})})}async waitForReadinessWithin(l,G){return!G||G<=0?l:new Promise(c=>{let e=!1,b=setTimeout(()=>{e||(e=!0,c(null))},G);l.then(d=>{e||(e=!0,clearTimeout(b),c(d))},d=>{e||(e=!0,clearTimeout(b),c(this.transientReadiness("recovering",vo(this.endpoint,d))))})})}async checkReadinessInternal(l={},G=!1){let c=this.getRuntimeState(),e=c.endpoint,b=nK(e),d={endpoint:e,endpointKind:b,status:"unreachable",reachable:!1,ready:c.ready,running:c.running,attached:c.attached,starting:c.starting,stopping:c.stopping,restartScheduled:c.restartScheduled,restartAttempts:c.restartAttempts,pid:c.pid};if(c.stopping)return{...d,status:"stopping",reachable:!1,ready:!1,running:!1};if(!G&&this.recovery)return{...d,status:"recovering",reachable:!1,ready:!1,running:!1};if(c.starting)return{...d,status:"starting",reachable:!1,ready:!1,running:!1};if(c.restartScheduled)return{...d,status:"restarting",reachable:!1,ready:!1,running:!1};if(!e.trim())return{...d,ready:!1,running:!1,error:vo(e,void 0)};try{return await new PI({endpoint:e,timeoutMs:l.timeoutMs??1e3,connectRetryMs:l.connectRetryMs??0}).ping(),{...d,status:"ready",reachable:!0,ready:!0,running:!0}}catch(Z){return{...d,ready:!1,running:!1,error:vo(e,Z)}}}async checkReadiness(l={}){return this.checkReadinessInternal(l)}async performManagedRecovery(l,G){let c=this.stopGeneration;if(this.ready=!1,!await this.waitForManagedChildExit(l)){let b=`managed child pid=${l.pid} did not exit after SIGTERM/SIGKILL during recovery`,d=await this.checkReadinessInternal({...G,connectRetryMs:0},!0);return{...d,status:"unreachable",reachable:!1,ready:!1,running:!1,error:d.error?`${b}; ${d.error}`:b}}if(this.stopGeneration!==c||this.stopping)return this.checkReadinessInternal({...G,connectRetryMs:0},!0);try{return await this.start(),await this.checkReadinessInternal(G,!0)}catch(b){let d=await this.checkReadinessInternal({...G,connectRetryMs:0},!0),Z=xvI(d,b);return Z?{...d,error:Z}:d}}async ensureReady(l={}){let G=await this.checkReadiness(l);if(G.reachable||l.recover===!1)return G;if(this.recovery)return await this.waitForReadinessWithin(this.recovery,l.timeoutMs)??this.transientReadiness("recovering");if(G.status==="starting"&&this.starting)return await this.waitForPromiseSettlementWithin(this.starting,l.timeoutMs)?this.checkReadiness(l):this.transientReadiness("starting");if(G.status!=="unreachable")return G;let c=this.child;if(!c||this.attached)return this.ready=!1,G;if(yvI(this.endpoint)){this.ready=!1;let d="managed bridge recovery is disabled for legacy global default endpoint; merge endpoint scoping before enabling recovery";return{...G,error:G.error?`${G.error}; ${d}`:d}}let e;return e=this.performManagedRecovery(c,l).finally(()=>{this.recovery===e&&(this.recovery=null)}),this.recovery=e,await this.waitForReadinessWithin(e,l.timeoutMs)??this.transientReadiness("recovering")}async start(){if(!this.running){if(this.starting)return this.starting;this.stopping=!1,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.starting=this.startProcess();try{await this.starting}finally{this.starting=null}}}async waitForManagedChildExit(l){return new Promise(G=>{let c=Hn("HERMES_AGENT_BRIDGE_RECOVERY_EXIT_TIMEOUT_MS")??wvI,e=Hn("HERMES_AGENT_BRIDGE_RECOVERY_SIGKILL_WAIT_MS")??vvI,b=!1,d=null,Z=null,n=()=>{d&&clearTimeout(d),Z&&clearTimeout(Z),l.off("exit",a)},t=m=>{b||(b=!0,n(),G(m))},a=()=>{this.child===l&&(this.child=null),t(!0)},W=m=>{try{(m==="SIGKILL"||!l.killed)&&l.kill(m)}catch(s){V.warn(s,"[agent-bridge] failed to signal managed child pid=%s signal=%s",l.pid,m)}};if(l.exitCode!=null||l.signalCode!=null){a();return}l.once("exit",a),d=setTimeout(()=>{b||(V.warn("[agent-bridge] managed child pid=%s did not exit after SIGTERM within %dms; sending SIGKILL",l.pid,c),W("SIGKILL"),Z=setTimeout(()=>{b||(V.warn("[agent-bridge] managed child pid=%s still has not exited %dms after SIGKILL; not starting a replacement",l.pid,e),t(!1))},e))},c),W("SIGTERM")})}async startProcess(){if(await this.attachExistingBridge())return;let l=kvI(),G=OQ(this.options);await this.prepareEndpoint();let c=[...G.argsPrefix,l,"--endpoint",this.endpoint],e=G.agentRoot,b=G.hermesHome;e&&c.push("--agent-root",e),b&&c.push("--hermes-home",b);let d=EvI(this.endpoint,b,e);V.info("[agent-bridge] starting: %s %s",G.command,c.join(" "));let Z=(0,jd.spawn)(G.command,c,{env:d,cwd:process.cwd(),stdio:["ignore","ignore","ignore"],detached:process.platform!=="win32",windowsHide:!0});this.child=Z,this.attached=!1,this.ready=!1,Z.once("exit",(n,t)=>{if(!(this.child===Z)){V.warn("[agent-bridge] stale managed child exit ignored code=%s signal=%s pid=%s",n,t,Z.pid);return}let W=this.ready&&!this.stopping&&this.autoRestartEnabled();V.warn("[agent-bridge] exited code=%s signal=%s",n,t),this.ready=!1,this.child=null,W&&this.scheduleRestart(n,t)}),await new Promise((n,t)=>{let a=this.options.startupTimeoutMs??Hn("HERMES_AGENT_BRIDGE_STARTUP_TIMEOUT_MS")??XvI,W=setTimeout(()=>{m(),t(new Error(`agent bridge did not become ready within ${a}ms`))},a),m=()=>{clearTimeout(W),Z.off("exit",Y),Z.off("error",N)},s=()=>{u||(this.ready=!0,this.restartAttempts=0,u=!0,m(),n())},N=p=>{m(),t(p)},Y=(p,h)=>{m(),t(new Error(`agent bridge exited before ready code=${p} signal=${h}`))},u=!1;Z.once("error",N),Z.once("exit",Y),(async()=>{let p=new PI({endpoint:this.endpoint,timeoutMs:1e3,connectRetryMs:0});for(;!u&&!Z.killed;)try{await p.ping(),s();return}catch{await new Promise(h=>setTimeout(h,100))}})().catch(N)}),V.info("[agent-bridge] ready at %s",this.endpoint),process.platform!=="win32"&&Z.unref()}async attachExistingBridge(){try{return await new PI({endpoint:this.endpoint,timeoutMs:Hn("HERMES_AGENT_BRIDGE_ATTACH_TIMEOUT_MS")??5e3,connectRetryMs:Hn("HERMES_AGENT_BRIDGE_ATTACH_RETRY_MS")??5e3}).ping(),this.child=null,this.attached=!0,this.ready=!0,this.restartAttempts=0,V.info("[agent-bridge] attached to existing bridge at %s",this.endpoint),!0}catch(l){return V.debug(l,"[agent-bridge] no reusable bridge at %s",this.endpoint),this.attached=!1,this.ready=!1,!1}}async prepareEndpoint(){!this.explicitEndpoint&&process.platform==="win32"&&tK(this.endpoint)&&(await xQ(this.endpoint)||await MvI(this.endpoint)),this.endpoint.startsWith("ipc://")&&process.platform!=="win32"&&zvI()&&await fvI(this.endpoint),process.env.HERMES_AGENT_BRIDGE_ENDPOINT=this.endpoint}autoRestartEnabled(){let l=String(process.env.HERMES_AGENT_BRIDGE_AUTO_RESTART||"").trim().toLowerCase();return!["0","false","no","off"].includes(l)}scheduleRestart(l,G){if(this.restartTimer||this.stopping)return;this.restartAttempts+=1;let c=Hn("HERMES_AGENT_BRIDGE_RESTART_DELAY_MS")??HvI,e=Math.min(QvI,c*Math.max(1,this.restartAttempts));V.warn("[agent-bridge] broker exited unexpectedly code=%s signal=%s; restarting in %dms (attempt %d)",l,G,e,this.restartAttempts),this.restartTimer=setTimeout(()=>{this.restartTimer=null,!this.stopping&&this.start().catch(b=>{V.warn(b,"[agent-bridge] automatic restart failed"),this.stopping||this.scheduleRestart(null,null)})},e)}async stop(){this.stopGeneration+=1,this.stopping=!0,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null);let l=this.child;if(!l){if(this.attached||this.ready)try{await new PI({endpoint:this.endpoint,timeoutMs:Hn("HERMES_AGENT_BRIDGE_SHUTDOWN_TIMEOUT_MS")??5e3,connectRetryMs:0}).shutdown()}catch(G){V.warn(G,"[agent-bridge] failed to request attached bridge shutdown")}this.ready=!1,this.attached=!1,this.stopping=!1;return}this.ready=!1,this.attached=!1,this.child=null,await new Promise(G=>{let c=setTimeout(()=>{try{l.kill("SIGKILL")}catch{}G()},1e4);l.once("exit",()=>{clearTimeout(c),G()}),l.killed||l.kill("SIGTERM")}),this.stopping=!1}},kQ=null;function $e(){return kQ||(kQ=new zQ),kQ}async function MQ(){let I=$e();return await I.start(),I}function Ms(I,l,G="[redacted endpoint]"){if(!I)return I;let c=I,e=l?.trim(),b=new Set;if(e){if(b.add(e),e.startsWith("ipc://")){let d=e.slice(6);d&&b.add(d)}if(e.startsWith("tcp://"))try{let d=new URL(e);d.host&&b.add(d.host)}catch{}}for(let d of b)c=c.split(d).join(G);return c.replace(/ipc:\/\/[^\s),;]+/g,G).replace(/(?:[A-Za-z]:)?[^\s),;]*agent-bridge\.sock/g,G)}var jvI="0.6.16",Qn={latestVersion:"",sourceLabel:y.update.sourceLabel,channel:y.update.channel,packageType:y.update.packageType,strategy:y.update.strategy,detectionSource:"npm-registry"},KvI=es(),Eo=np(jvI),sK=75,aK=1e3,wn=null,yo=null;function NK(){if(ca(y.update))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 WK(){if(!(y.update.packageName&&y.update.registry))return null;let I=y.update.packageName||KvI?.name||"hermes-web-ui",l=y.update.registry||"https://registry.npmjs.org",G=y.update.distTag||"latest",c=encodeURIComponent(I),e=`${l}/${c}`,b=await fetch(e,{signal:AbortSignal.timeout(1e4)});if(!b.ok)throw new Error(`Failed to resolve the latest published version from ${l}: HTTP ${b.status}`);let d=await b.json(),Z=d["dist-tags"]?.[G]||d.version||d["dist-tags"]?.latest||"";return Z?{latestVersion:Z,sourceLabel:y.update.sourceLabel,channel:y.update.channel,packageType:y.update.packageType,strategy:y.update.strategy,detectionSource:"npm-registry"}:null}async function mK(){if(ca(y.update))try{let I=oX(y.update)?await AU(y.update):await WK();I?.latestVersion&&(Qn=I,V0(Eo,I.latestVersion)&&console.log(`Update available: ${Eo} \u2192 ${I.latestVersion}`))}catch{if(!oX(y.update))return;try{let I=await WK();I?.latestVersion&&(Qn=I)}catch{}}}function fQ(){!ca(y.update)||NK()||(setTimeout(mK,5e3),setInterval(mK,1800*1e3))}async function SvI(){let I=Date.now();return wn&&wn.expiresAt>I||(yo||(yo=TvI().finally(()=>{yo=null})),wn)?wn.value:await Promise.race([yo,new Promise(G=>{setTimeout(()=>G({status:"unknown",reachable:!1}),sK)})])}async function TvI(){let I;try{let l=$e();I=typeof l.getRuntimeState=="function"?l.getRuntimeState().endpoint:void 0;let G=await l.checkReadiness({timeoutMs:sK,connectRetryMs:0}),c={status:G.status,reachable:G.reachable,ready:G.ready,running:G.running,attached:G.attached,starting:G.starting,stopping:G.stopping,restart_scheduled:G.restartScheduled,restart_attempts:G.restartAttempts,endpoint_kind:G.endpointKind,pid:G.pid,error:Ms(G.error,G.endpoint)};return wn={value:c,expiresAt:Date.now()+aK},c}catch(l){let G={status:"unknown",reachable:!1,error:Ms(l instanceof Error?l.message:String(l),I)};return wn={value:G,expiresAt:Date.now()+aK},G}}async function YK(I){let G=(await Qo()).split(`
|
|
275
|
+
`)){let t=Number(n.replace(/^p/,""));Number.isFinite(t)&&t>0&&t!==process.pid&&b.add(t)}}catch{}if(b.size){for(let d of b)try{V.warn("[agent-bridge] killing stale bridge process pid=%d on IPC socket %s",d,l),process.kill(d,"SIGKILL")}catch(Z){V.warn(Z,"[agent-bridge] failed to kill stale bridge process pid=%d",d)}await new Promise(d=>setTimeout(d,500))}}var zQ=class{endpoint;options;explicitEndpoint;child=null;attached=!1;starting=null;recovery=null;ready=!1;stopping=!1;stopGeneration=0;restartTimer=null;restartAttempts=0;constructor(l={}){this.options=l,this.explicitEndpoint=!!(l.endpoint||process.env.HERMES_AGENT_BRIDGE_ENDPOINT),this.endpoint=l.endpoint||process.env.HERMES_AGENT_BRIDGE_ENDPOINT||CQ}get running(){return this.ready&&(this.attached||!!this.child&&!this.child.killed)}getRuntimeState(){return{endpoint:this.endpoint,running:this.running,ready:this.ready,attached:this.attached,pid:this.child?.pid,starting:!!this.starting,stopping:this.stopping,restartScheduled:!!this.restartTimer,restartAttempts:this.restartAttempts}}transientReadiness(l,G){let c=this.getRuntimeState(),e=c.endpoint,b={endpoint:e,endpointKind:nK(e),status:l,reachable:!1,ready:!1,running:!1,attached:c.attached,starting:c.starting,stopping:c.stopping,restartScheduled:c.restartScheduled,restartAttempts:c.restartAttempts,pid:c.pid};return G?{...b,error:G}:b}async waitForPromiseSettlementWithin(l,G){if(!G||G<=0){try{await l}catch{}return!0}return new Promise(c=>{let e=!1,b=setTimeout(()=>{e||(e=!0,c(!1))},G);l.finally(()=>{e||(e=!0,clearTimeout(b),c(!0))}).catch(()=>{})})}async waitForReadinessWithin(l,G){return!G||G<=0?l:new Promise(c=>{let e=!1,b=setTimeout(()=>{e||(e=!0,c(null))},G);l.then(d=>{e||(e=!0,clearTimeout(b),c(d))},d=>{e||(e=!0,clearTimeout(b),c(this.transientReadiness("recovering",vo(this.endpoint,d))))})})}async checkReadinessInternal(l={},G=!1){let c=this.getRuntimeState(),e=c.endpoint,b=nK(e),d={endpoint:e,endpointKind:b,status:"unreachable",reachable:!1,ready:c.ready,running:c.running,attached:c.attached,starting:c.starting,stopping:c.stopping,restartScheduled:c.restartScheduled,restartAttempts:c.restartAttempts,pid:c.pid};if(c.stopping)return{...d,status:"stopping",reachable:!1,ready:!1,running:!1};if(!G&&this.recovery)return{...d,status:"recovering",reachable:!1,ready:!1,running:!1};if(c.starting)return{...d,status:"starting",reachable:!1,ready:!1,running:!1};if(c.restartScheduled)return{...d,status:"restarting",reachable:!1,ready:!1,running:!1};if(!e.trim())return{...d,ready:!1,running:!1,error:vo(e,void 0)};try{return await new PI({endpoint:e,timeoutMs:l.timeoutMs??1e3,connectRetryMs:l.connectRetryMs??0}).ping(),{...d,status:"ready",reachable:!0,ready:!0,running:!0}}catch(Z){return{...d,ready:!1,running:!1,error:vo(e,Z)}}}async checkReadiness(l={}){return this.checkReadinessInternal(l)}async performManagedRecovery(l,G){let c=this.stopGeneration;if(this.ready=!1,!await this.waitForManagedChildExit(l)){let b=`managed child pid=${l.pid} did not exit after SIGTERM/SIGKILL during recovery`,d=await this.checkReadinessInternal({...G,connectRetryMs:0},!0);return{...d,status:"unreachable",reachable:!1,ready:!1,running:!1,error:d.error?`${b}; ${d.error}`:b}}if(this.stopGeneration!==c||this.stopping)return this.checkReadinessInternal({...G,connectRetryMs:0},!0);try{return await this.start(),await this.checkReadinessInternal(G,!0)}catch(b){let d=await this.checkReadinessInternal({...G,connectRetryMs:0},!0),Z=xvI(d,b);return Z?{...d,error:Z}:d}}async ensureReady(l={}){let G=await this.checkReadiness(l);if(G.reachable||l.recover===!1)return G;if(this.recovery)return await this.waitForReadinessWithin(this.recovery,l.timeoutMs)??this.transientReadiness("recovering");if(G.status==="starting"&&this.starting)return await this.waitForPromiseSettlementWithin(this.starting,l.timeoutMs)?this.checkReadiness(l):this.transientReadiness("starting");if(G.status!=="unreachable")return G;let c=this.child;if(!c||this.attached)return this.ready=!1,G;if(yvI(this.endpoint)){this.ready=!1;let d="managed bridge recovery is disabled for legacy global default endpoint; merge endpoint scoping before enabling recovery";return{...G,error:G.error?`${G.error}; ${d}`:d}}let e;return e=this.performManagedRecovery(c,l).finally(()=>{this.recovery===e&&(this.recovery=null)}),this.recovery=e,await this.waitForReadinessWithin(e,l.timeoutMs)??this.transientReadiness("recovering")}async start(){if(!this.running){if(this.starting)return this.starting;this.stopping=!1,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.starting=this.startProcess();try{await this.starting}finally{this.starting=null}}}async waitForManagedChildExit(l){return new Promise(G=>{let c=Hn("HERMES_AGENT_BRIDGE_RECOVERY_EXIT_TIMEOUT_MS")??wvI,e=Hn("HERMES_AGENT_BRIDGE_RECOVERY_SIGKILL_WAIT_MS")??vvI,b=!1,d=null,Z=null,n=()=>{d&&clearTimeout(d),Z&&clearTimeout(Z),l.off("exit",a)},t=m=>{b||(b=!0,n(),G(m))},a=()=>{this.child===l&&(this.child=null),t(!0)},W=m=>{try{(m==="SIGKILL"||!l.killed)&&l.kill(m)}catch(s){V.warn(s,"[agent-bridge] failed to signal managed child pid=%s signal=%s",l.pid,m)}};if(l.exitCode!=null||l.signalCode!=null){a();return}l.once("exit",a),d=setTimeout(()=>{b||(V.warn("[agent-bridge] managed child pid=%s did not exit after SIGTERM within %dms; sending SIGKILL",l.pid,c),W("SIGKILL"),Z=setTimeout(()=>{b||(V.warn("[agent-bridge] managed child pid=%s still has not exited %dms after SIGKILL; not starting a replacement",l.pid,e),t(!1))},e))},c),W("SIGTERM")})}async startProcess(){if(await this.attachExistingBridge())return;let l=kvI(),G=OQ(this.options);await this.prepareEndpoint();let c=[...G.argsPrefix,l,"--endpoint",this.endpoint],e=G.agentRoot,b=G.hermesHome;e&&c.push("--agent-root",e),b&&c.push("--hermes-home",b);let d=EvI(this.endpoint,b,e);V.info("[agent-bridge] starting: %s %s",G.command,c.join(" "));let Z=(0,jd.spawn)(G.command,c,{env:d,cwd:process.cwd(),stdio:["ignore","ignore","ignore"],detached:process.platform!=="win32",windowsHide:!0});this.child=Z,this.attached=!1,this.ready=!1,Z.once("exit",(n,t)=>{if(!(this.child===Z)){V.warn("[agent-bridge] stale managed child exit ignored code=%s signal=%s pid=%s",n,t,Z.pid);return}let W=this.ready&&!this.stopping&&this.autoRestartEnabled();V.warn("[agent-bridge] exited code=%s signal=%s",n,t),this.ready=!1,this.child=null,W&&this.scheduleRestart(n,t)}),await new Promise((n,t)=>{let a=this.options.startupTimeoutMs??Hn("HERMES_AGENT_BRIDGE_STARTUP_TIMEOUT_MS")??XvI,W=setTimeout(()=>{m(),t(new Error(`agent bridge did not become ready within ${a}ms`))},a),m=()=>{clearTimeout(W),Z.off("exit",Y),Z.off("error",N)},s=()=>{u||(this.ready=!0,this.restartAttempts=0,u=!0,m(),n())},N=p=>{m(),t(p)},Y=(p,h)=>{m(),t(new Error(`agent bridge exited before ready code=${p} signal=${h}`))},u=!1;Z.once("error",N),Z.once("exit",Y),(async()=>{let p=new PI({endpoint:this.endpoint,timeoutMs:1e3,connectRetryMs:0});for(;!u&&!Z.killed;)try{await p.ping(),s();return}catch{await new Promise(h=>setTimeout(h,100))}})().catch(N)}),V.info("[agent-bridge] ready at %s",this.endpoint),process.platform!=="win32"&&Z.unref()}async attachExistingBridge(){try{return await new PI({endpoint:this.endpoint,timeoutMs:Hn("HERMES_AGENT_BRIDGE_ATTACH_TIMEOUT_MS")??5e3,connectRetryMs:Hn("HERMES_AGENT_BRIDGE_ATTACH_RETRY_MS")??5e3}).ping(),this.child=null,this.attached=!0,this.ready=!0,this.restartAttempts=0,V.info("[agent-bridge] attached to existing bridge at %s",this.endpoint),!0}catch(l){return V.debug(l,"[agent-bridge] no reusable bridge at %s",this.endpoint),this.attached=!1,this.ready=!1,!1}}async prepareEndpoint(){!this.explicitEndpoint&&process.platform==="win32"&&tK(this.endpoint)&&(await xQ(this.endpoint)||await MvI(this.endpoint)),this.endpoint.startsWith("ipc://")&&process.platform!=="win32"&&zvI()&&await fvI(this.endpoint),process.env.HERMES_AGENT_BRIDGE_ENDPOINT=this.endpoint}autoRestartEnabled(){let l=String(process.env.HERMES_AGENT_BRIDGE_AUTO_RESTART||"").trim().toLowerCase();return!["0","false","no","off"].includes(l)}scheduleRestart(l,G){if(this.restartTimer||this.stopping)return;this.restartAttempts+=1;let c=Hn("HERMES_AGENT_BRIDGE_RESTART_DELAY_MS")??HvI,e=Math.min(QvI,c*Math.max(1,this.restartAttempts));V.warn("[agent-bridge] broker exited unexpectedly code=%s signal=%s; restarting in %dms (attempt %d)",l,G,e,this.restartAttempts),this.restartTimer=setTimeout(()=>{this.restartTimer=null,!this.stopping&&this.start().catch(b=>{V.warn(b,"[agent-bridge] automatic restart failed"),this.stopping||this.scheduleRestart(null,null)})},e)}async stop(){this.stopGeneration+=1,this.stopping=!0,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null);let l=this.child;if(!l){if(this.attached||this.ready)try{await new PI({endpoint:this.endpoint,timeoutMs:Hn("HERMES_AGENT_BRIDGE_SHUTDOWN_TIMEOUT_MS")??5e3,connectRetryMs:0}).shutdown()}catch(G){V.warn(G,"[agent-bridge] failed to request attached bridge shutdown")}this.ready=!1,this.attached=!1,this.stopping=!1;return}this.ready=!1,this.attached=!1,this.child=null,await new Promise(G=>{let c=setTimeout(()=>{try{l.kill("SIGKILL")}catch{}G()},1e4);l.once("exit",()=>{clearTimeout(c),G()}),l.killed||l.kill("SIGTERM")}),this.stopping=!1}},kQ=null;function $e(){return kQ||(kQ=new zQ),kQ}async function MQ(){let I=$e();return await I.start(),I}function Ms(I,l,G="[redacted endpoint]"){if(!I)return I;let c=I,e=l?.trim(),b=new Set;if(e){if(b.add(e),e.startsWith("ipc://")){let d=e.slice(6);d&&b.add(d)}if(e.startsWith("tcp://"))try{let d=new URL(e);d.host&&b.add(d.host)}catch{}}for(let d of b)c=c.split(d).join(G);return c.replace(/ipc:\/\/[^\s),;]+/g,G).replace(/(?:[A-Za-z]:)?[^\s),;]*agent-bridge\.sock/g,G)}var jvI="0.6.17",Qn={latestVersion:"",sourceLabel:y.update.sourceLabel,channel:y.update.channel,packageType:y.update.packageType,strategy:y.update.strategy,detectionSource:"npm-registry"},KvI=es(),Eo=np(jvI),sK=75,aK=1e3,wn=null,yo=null;function NK(){if(ca(y.update))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 WK(){if(!(y.update.packageName&&y.update.registry))return null;let I=y.update.packageName||KvI?.name||"hermes-web-ui",l=y.update.registry||"https://registry.npmjs.org",G=y.update.distTag||"latest",c=encodeURIComponent(I),e=`${l}/${c}`,b=await fetch(e,{signal:AbortSignal.timeout(1e4)});if(!b.ok)throw new Error(`Failed to resolve the latest published version from ${l}: HTTP ${b.status}`);let d=await b.json(),Z=d["dist-tags"]?.[G]||d.version||d["dist-tags"]?.latest||"";return Z?{latestVersion:Z,sourceLabel:y.update.sourceLabel,channel:y.update.channel,packageType:y.update.packageType,strategy:y.update.strategy,detectionSource:"npm-registry"}:null}async function mK(){if(ca(y.update))try{let I=oX(y.update)?await AU(y.update):await WK();I?.latestVersion&&(Qn=I,V0(Eo,I.latestVersion)&&console.log(`Update available: ${Eo} \u2192 ${I.latestVersion}`))}catch{if(!oX(y.update))return;try{let I=await WK();I?.latestVersion&&(Qn=I)}catch{}}}function fQ(){!ca(y.update)||NK()||(setTimeout(mK,5e3),setInterval(mK,1800*1e3))}async function SvI(){let I=Date.now();return wn&&wn.expiresAt>I||(yo||(yo=TvI().finally(()=>{yo=null})),wn)?wn.value:await Promise.race([yo,new Promise(G=>{setTimeout(()=>G({status:"unknown",reachable:!1}),sK)})])}async function TvI(){let I;try{let l=$e();I=typeof l.getRuntimeState=="function"?l.getRuntimeState().endpoint:void 0;let G=await l.checkReadiness({timeoutMs:sK,connectRetryMs:0}),c={status:G.status,reachable:G.reachable,ready:G.ready,running:G.running,attached:G.attached,starting:G.starting,stopping:G.stopping,restart_scheduled:G.restartScheduled,restart_attempts:G.restartAttempts,endpoint_kind:G.endpointKind,pid:G.pid,error:Ms(G.error,G.endpoint)};return wn={value:c,expiresAt:Date.now()+aK},c}catch(l){let G={status:"unknown",reachable:!1,error:Ms(l instanceof Error?l.message:String(l),I)};return wn={value:G,expiresAt:Date.now()+aK},G}}async function YK(I){let G=(await Qo()).split(`
|
|
276
276
|
`)[0].replace("Hermes Agent ","")||"",c=Au(y.update),e=ca(y.update),b=NK(),d=await SvI();I.body={status:"ok",platform:"hermes-agent",version:G,gateway:"running",webui_version:Eo,webui_latest:b?"":Qn.latestVersion,webui_update_enabled:c,webui_update_source_label:e?Qn.sourceLabel||y.update.sourceLabel:"",webui_update_channel:e?Qn.channel||y.update.channel:"",webui_update_strategy:e?y.update.strategy:"",webui_update_package_type:e?Qn.packageType||y.update.packageType:"",webui_update_available:b?!1:V0(Eo,Qn.latestVersion),node_version:process.versions.node,agent_bridge:d}}var jQ=new B;jQ.get("/health",YK);GI();async function hK(I){let l=I.request.body;if(!l||!l.event){I.status=400,I.body={error:"Missing event field"};return}V.info("Received webhook event: %s",l.event),I.body={ok:!0}}var KQ=new B;KQ.post("/webhook",hK);var oK=require("crypto"),Jo=require("fs/promises"),rK=require("path");VI();var go=require("path");JI();ac();function PvI(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 uK(I){return(0,go.resolve)((0,go.join)(y.uploadDir,PvI(I)))}var pK=50*1024*1024;function _vI(I){return I.state?.profile?.name||cI()||"default"}async function VK(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=[],e=0;for await(let a of I.req){if(e+=a.length,e>pK){I.status=413,I.body={error:`File too large (max ${pK/1024/1024}MB)`};return}c.push(a)}let b=Buffer.concat(c),d=Buffer.from(G),Z=$vI(b,d),n=[],t=uK(_vI(I));await(0,Jo.mkdir)(t,{recursive:!0});for(let a of Z){let W=a.indexOf(Buffer.from(`\r
|
|
277
277
|
\r
|
|
278
278
|
`));if(W===-1)continue;let s=a.subarray(0,W).toString("utf-8"),N=a.subarray(W+4,a.length-2),Y="",u=s.match(/filename\*=UTF-8''(.+)/i);if(u)Y=decodeURIComponent(u[1]);else{let r=s.match(/filename="([^"]+)"/);if(!r)continue;Y=r[1]}let o=Y.includes(".")?"."+Y.split(".").pop():"",p=(0,oK.randomBytes)(8).toString("hex")+o,h=(0,rK.join)(t,p);await(0,Jo.writeFile)(h,N),n.push({name:Y,path:h})}I.body={files:n}}function $vI(I,l){let G=[],c=0;for(;;){let e=I.indexOf(l,c);if(e===-1)break;c>0&&G.push(I.subarray(c+2,e)),c=e+l.length}return G}var SQ=new B;SQ.post("/upload",VK);var Ib=new B;Ib.post("/api/hermes/update",uB);Ib.get("/api/hermes/update/status",hB);Ib.get("/api/hermes/update/preview",pB);Ib.get("/api/hermes/update/preview/tags",oB);Ib.post("/api/hermes/update/preview/prepare",rB);Ib.post("/api/hermes/update/preview/install",VB);Ib.post("/api/hermes/update/preview/start",iB);Ib.post("/api/hermes/update/preview/stop",RB);VI();async function RK(I){I.body={hasPasswordLogin:!0,hasUsers:Zo()>0}}async function FK(I){let l=I.state.user?.id,G=l?Lc(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===As&&Ls(eo,G.password_hash)}}}var TQ=500*1024;function iK(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>TQ)return{ok:!1,error:`Avatar image is too large (max ${TQ} 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 XK(I){let l=I.state.user?.id;if(!l){I.status=401,I.body={error:"Unauthorized"};return}I.body={avatar:Ea(l)}}async function HK(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>TQ*2){I.status=400,I.body={error:"Avatar string is too large"};return}try{let d=JSON.parse(c),Z=iK(d);if(!Z.ok){I.status=400,I.body={error:Z.error};return}if(!qH(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 e=iK(c);if(!e.ok){I.status=400,I.body={error:e.error};return}if(!qH(l,e.json)){I.status=500,I.body={error:"Failed to save avatar"};return}I.body={success:!0,avatar:e.json}}async function QK(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=RX(I),e=lx(c);if(!e.allowed){I.status=e.status,I.body={error:"Too many login attempts, please try again later"};return}let b=Zo(),d=b===0?uf(l,G):Ne(l);if(!d||d.status!=="active"||b>0&&!Ls(G,d.password_hash)){Gx(c),I.status=401,I.body={error:"Invalid username or password"};return}let Z;try{Z=await Rf(d)}catch(n){I.status=500,I.body={error:n?.message||"Failed to issue login token"};return}cx(c),I.body={token:Z}}async function wK(I){I.status=400,I.body={error:"Password login is managed by user accounts"}}async function vK(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,e=c?Lc(c):null;if(!e||!Ls(l,e.password_hash)){I.status=400,I.body={error:"Current password is incorrect"};return}Wf(e.id,G),I.body={success:!0}}async function yK(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,e=c?Lc(c):null;if(!e||!Ls(l,e.password_hash)){I.status=400,I.body={error:"Current password is incorrect"};return}let b=Ne(G);if(b&&b.id!==e.id){I.status=409,I.body={error:"Username already exists"};return}mf(e.id,G),I.body={success:!0}}async function EK(I){I.status=400,I.body={error:"Password login cannot be removed for user accounts"}}function gK(I){return I==="super_admin"||I==="admin"?I:null}function JK(I){return I==="active"||I==="disabled"?I:null}function CK(I){return Array.isArray(I)?[...new Set(I.map(l=>String(l||"").trim()).filter(Boolean))]:[]}function AK(I){let l=new Set(DI());return I.find(c=>!l.has(c))||null}async function LK(I){I.body={users:ks(),profiles:DI()}}async function kK(I){let l=I.request.body,G=String(l.username||"").trim(),c=String(l.password||""),e=gK(l.role||"admin"),b=JK(l.status||"active"),d=CK(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(!e||!b){I.status=400,I.body={error:"Invalid role or status"};return}if(Ne(G)){I.status=409,I.body={error:"Username already exists"};return}let Z=AK(d);if(Z){I.status=400,I.body={error:`Profile "${Z}" does not exist`};return}let n=sf({username:G,password:c,role:e,status:b,profiles:e==="super_admin"?[]:d,defaultProfile:l.defaultProfile});I.status=201,I.body={user:n,users:ks()}}async function xK(I){let l=Number(I.params.id),G=Number.isInteger(l)?Lc(l):null;if(!G){I.status=404,I.body={error:"User not found"};return}let c=I.request.body,e=c.username==null?void 0:String(c.username).trim(),b=c.password==null?void 0:String(c.password),d=c.role==null?void 0:gK(c.role),Z=c.status==null?void 0:JK(c.status),n=c.profiles==null?void 0:CK(c.profiles);if(e!==void 0&&e.length<2){I.status=400,I.body={error:"Username must be at least 2 characters"};return}if(b!==void 0&&b.length>0&&b.length<6){I.status=400,I.body={error:"Password must be at least 6 characters"};return}if(c.role!=null&&!d||c.status!=null&&!Z){I.status=400,I.body={error:"Invalid role or status"};return}if(e&&e!==G.username){let m=Ne(e);if(m&&m.id!==G.id){I.status=409,I.body={error:"Username already exists"};return}}let t=d||G.role,a=Z||G.status,W=I.state.user?.id;if(G.id===W&&a!=="active"){I.status=400,I.body={error:"You cannot disable your own account"};return}if(G.role==="super_admin"&&G.status==="active"&&(t!=="super_admin"||a!=="active")&&DH(G.id)===0){I.status=400,I.body={error:"At least one active super administrator is required"};return}if(n){let m=AK(n);if(m){I.status=400,I.body={error:`Profile "${m}" does not exist`};return}}Nf({userId:G.id,username:e,password:b||void 0,role:d||void 0,status:Z||void 0,profiles:t==="super_admin"?[]:n,defaultProfile:c.defaultProfile}),I.body={user:Lc(G.id),users:ks()}}async function zK(I){let l=Number(I.params.id),G=Number.isInteger(l)?Lc(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"&&DH(G.id)===0){I.status=400,I.body={error:"At least one active super administrator is required"};return}Yf(G.id),I.body={success:!0,users:ks()}}async function UK(I){let l=XX();I.body={locks:l}}async function BK(I){let l=I.query.ip;if(l){if(!ex(l)){I.status=404,I.body={error:"IP not locked"};return}I.body={success:!0};return}let G=bx();I.body={success:!0,count:G}}var Co=new B;Co.get("/api/auth/status",RK);Co.post("/api/auth/login",QK);var JG=new B;JG.post("/api/auth/setup",wK);JG.get("/api/auth/me",FK);JG.post("/api/auth/change-password",vK);JG.post("/api/auth/change-username",yK);JG.get("/api/auth/avatar",XK);JG.put("/api/auth/avatar",HK);JG.delete("/api/auth/password",EK);JG.get("/api/auth/users",nG,LK);JG.post("/api/auth/users",nG,kK);JG.put("/api/auth/users/:id",nG,xK);JG.delete("/api/auth/users/:id",nG,zK);JG.get("/api/auth/locked-ips",UK);JG.delete("/api/auth/locked-ips",BK);wG();me();var fs=class extends Error{constructor(){super("Duplicate pairing request"),this.name="DuplicateDeviceRequestError"}};function GyI(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 cyI(I){return I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:"none"}function eyI(I){return I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:"none"}function js(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:cyI(I.inbound_status||I.status),outbound_status:eyI(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 Ao(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:GyI(I.last_seen_at),updated_at:G}}function Ks(I){let l=O();return l?(l.prepare(`
|
|
@@ -304,7 +304,7 @@ const isVersionPreview = import.meta.env.VITE_HERMES_PREVIEW === '1';`)),l=l.rep
|
|
|
304
304
|
inbound_history_deleted_at = excluded.inbound_history_deleted_at,
|
|
305
305
|
last_seen_at = excluded.last_seen_at,
|
|
306
306
|
updated_at = excluded.updated_at
|
|
307
|
-
`).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),Bc(I.id)):(bp(nc,I.id,I),js(I))}function Lo(){byI();let I=O();return I?I.prepare(`SELECT * FROM ${nc} ORDER BY updated_at DESC`).all().map(js):Object.values(Gs(nc)).map(js).sort((G,c)=>c.updated_at-G.updated_at)}function Bc(I){let l=O();if(!l){let c=ep(nc,I);return c?js(c):null}let G=l.prepare(`SELECT * FROM ${nc} WHERE id = ?`).get(I);return G?js(G):null}function byI(){let I=O();if(!I){let G=Gs(nc),c=0;for(let[e,b]of Object.entries(G))b.inbound_history_deleted_at!=null&&(cs(nc,e),c+=1);return c}let l=I.prepare(`DELETE FROM ${nc} WHERE inbound_history_deleted_at IS NOT NULL`).run();return Number(l.changes)}function OK(){return Lo().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 MK(I){return Ks(Ao(I,Bc(I.id),Date.now()))}function fK(I){let l=Date.now(),G=Bc(I.id),c=Ao(I,G,l);if(G?.inbound_status==="pending")throw new fs;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),Ks(c)}function jK(I,l,G){let c=G?MK(G):Bc(I);if(!c)throw new Error("Device not found");let e=Date.now(),b=Ao(c,c,e);return b.status=l,b.inbound_status=l,b.decided_at=l==="pending"||l==="none"?null:e,l==="pending"&&!b.requested_at&&(b.requested_at=e),l==="pending"&&(b.inbound_history_deleted_at=null),Ks(b)}function ko(I,l,G){let c=MK(G),e=Date.now(),b=Ao(c,c,e);return b.outbound_status=l,l==="pending"?(b.outbound_requested_at=e,b.outbound_decided_at=null):b.outbound_decided_at=e,Ks(b)}function KK(I){if(!Bc(I))return!1;let G=O();return G?G.prepare(`DELETE FROM ${nc} WHERE id = ?`).run(I).changes>0:(cs(nc,I),!0)}var _Q=C(require("dgram")),DK=require("os");JI();GI();var lb=require("os"),Kd=require("crypto");var za=require("fs/promises"),xo=require("path");JI();Xn();var DQ=(0,xo.resolve)(y.appHome,"device-identity.json"),qQ=null;function zo(){return"0.6.
|
|
307
|
+
`).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),Bc(I.id)):(bp(nc,I.id,I),js(I))}function Lo(){byI();let I=O();return I?I.prepare(`SELECT * FROM ${nc} ORDER BY updated_at DESC`).all().map(js):Object.values(Gs(nc)).map(js).sort((G,c)=>c.updated_at-G.updated_at)}function Bc(I){let l=O();if(!l){let c=ep(nc,I);return c?js(c):null}let G=l.prepare(`SELECT * FROM ${nc} WHERE id = ?`).get(I);return G?js(G):null}function byI(){let I=O();if(!I){let G=Gs(nc),c=0;for(let[e,b]of Object.entries(G))b.inbound_history_deleted_at!=null&&(cs(nc,e),c+=1);return c}let l=I.prepare(`DELETE FROM ${nc} WHERE inbound_history_deleted_at IS NOT NULL`).run();return Number(l.changes)}function OK(){return Lo().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 MK(I){return Ks(Ao(I,Bc(I.id),Date.now()))}function fK(I){let l=Date.now(),G=Bc(I.id),c=Ao(I,G,l);if(G?.inbound_status==="pending")throw new fs;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),Ks(c)}function jK(I,l,G){let c=G?MK(G):Bc(I);if(!c)throw new Error("Device not found");let e=Date.now(),b=Ao(c,c,e);return b.status=l,b.inbound_status=l,b.decided_at=l==="pending"||l==="none"?null:e,l==="pending"&&!b.requested_at&&(b.requested_at=e),l==="pending"&&(b.inbound_history_deleted_at=null),Ks(b)}function ko(I,l,G){let c=MK(G),e=Date.now(),b=Ao(c,c,e);return b.outbound_status=l,l==="pending"?(b.outbound_requested_at=e,b.outbound_decided_at=null):b.outbound_decided_at=e,Ks(b)}function KK(I){if(!Bc(I))return!1;let G=O();return G?G.prepare(`DELETE FROM ${nc} WHERE id = ?`).run(I).changes>0:(cs(nc,I),!0)}var _Q=C(require("dgram")),DK=require("os");JI();GI();var lb=require("os"),Kd=require("crypto");var za=require("fs/promises"),xo=require("path");JI();Xn();var DQ=(0,xo.resolve)(y.appHome,"device-identity.json"),qQ=null;function zo(){return"0.6.17"}function dyI(I){return I.split(`
|
|
308
308
|
`)[0]?.replace(/^Hermes Agent\s+/,"").trim()||""}function ZyI(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 Ua(I){return`hwui_${(0,Kd.createHash)("sha256").update(I).digest("base64url").slice(0,32)}`}async function nyI(){try{let G=JSON.parse(await(0,za.readFile)(DQ,"utf-8"));if(ZyI(G))return G}catch{}let I=(0,Kd.generateKeyPairSync)("ed25519",{publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem"}}),l={device_id:Ua(I.publicKey),device_public_key:I.publicKey,device_private_key:I.privateKey};return await(0,za.mkdir)((0,xo.dirname)(DQ),{recursive:!0}),await(0,za.writeFile)(DQ,JSON.stringify(l,null,2),{encoding:"utf-8",mode:384}),l}function SK(){return qQ||(qQ=nyI()),qQ}function TK(I){return`${I.device_id}.${I.nonce}.${I.timestamp}`}async function Ss(I,l){let G=await SK();return(0,Kd.sign)(null,Buffer.from(TK({device_id:G.device_id,nonce:I,timestamp:l})),G.device_private_key).toString("base64url")}function Ts(I){if(Ua(I.device_public_key)!==I.device_id)return!1;try{return(0,Kd.verify)(null,Buffer.from(TK(I)),I.device_public_key,Buffer.from(I.signature,"base64url"))}catch{return!1}}async function Sd(){let I=dyI(await Qo()),l=await SK();return{device_id:l.device_id,device_public_key:l.device_public_key,computer_name:(0,lb.hostname)(),os:{type:(0,lb.type)(),platform:(0,lb.platform)(),release:(0,lb.release)(),arch:(0,lb.arch)()},hermes_agent_version:I,hermes_web_ui_version:zo()}}var Bo=1,tyI=4e4,ayI=[8648,8748],WyI=1e3,PQ=null,Ba={scanning:!1,last_scanned_at:null,devices:[]},Ds=null,Uo=null;function myI(I){let l=String(process.env[I]||"").trim().toLowerCase();return["0","false","no","off"].includes(l)}function qK(){return!myI("HERMES_LAN_DISCOVERY_ENABLED")}function syI(I){return String(I||"").split(/[\s,]+/).map(l=>Number.parseInt(l,10)).filter(l=>Number.isInteger(l)&&l>0&&l<=65535)}function PK(I){let l=tyI+I;if(l>65535)throw new Error(`HTTP port ${I} cannot be mapped to a UDP discovery port`);return l}function vn(I){return I===8648?"web":I===8748?"desktop":"custom"}function NyI(I=y.port){let l=syI(process.env.HERMES_LAN_DISCOVERY_HTTP_PORTS);return[...new Set([...l.length?l:ayI,I])]}function Oa(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 YyI(I){return[I>>>24&255,I>>>16&255,I>>>8&255,I&255].join(".")}function _K(I){let l=Oa(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 $Q(){try{return Object.values((0,DK.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 hyI(){return new Set(["127.0.0.1",...$Q().map(I=>I.address)])}function uyI(I,l){let G=Oa(I),c=Oa(l);return G===null||c===null?null:YyI((G|~c>>>0)>>>0)}function pyI(I){let l=Oa(I),G=$Q();if(l!==null)for(let c of G){let e=Oa(c.address),b=Oa(c.netmask);if(e!==null&&b!==null&&(e&b)===(l&b))return c.address}return G[0]?.address||"127.0.0.1"}function oyI(){let I=new Set(["255.255.255.255"]);for(let l of $Q()){let G=uyI(l.address,l.netmask);G&&I.add(G)}return[...I]}async function ryI(I){let l=Date.now();if(Uo&&Uo.expiresAt>l)return Uo.value;let G=await I();return Uo={value:G,expiresAt:l+6e4},G}function $K(I){try{return JSON.parse(I.toString("utf8"))}catch{return null}}async function VyI(I,l,G,c){let e=await ryI(c),b=pyI(l);return{type:"hermes.announce",version:Bo,request_id:I.request_id,http_port:G,endpoint_kind:vn(G),url:`http://${b}:${G}`,...e}}function IS(I={}){if(!qK())return null;if(PQ)return PQ;let l=I.httpPort||y.port,G=PK(l),c=I.getSystemInfo||Sd,e=_Q.default.createSocket("udp4");return e.on("message",(b,d)=>{if(!_K(d.address))return;let Z=$K(b);!Z||Z.type!=="hermes.discover"||Z.version!==Bo||VyI(Z,d.address,l,c).then(n=>{let t=Buffer.from(JSON.stringify(n));e.send(t,d.port,d.address)}).catch(n=>V.warn(n,"[lan-discovery] failed to build discovery response"))}),e.on("error",b=>{V.warn(b,"[lan-discovery] UDP responder error")}),e.bind(G,"0.0.0.0",()=>{e.setBroadcast(!0),e.unref(),V.info("[lan-discovery] responder listening on udp://0.0.0.0:%d for http port %d",G,l)}),PQ=e,e}function iyI(I,l,G,c){if(!I||I.type!=="hermes.announce"||I.version!==Bo)return null;let e=Number(I.http_port);if(!Number.isInteger(e)||e<=0||e>65535)return null;let b=typeof I.device_id=="string"&&I.device_id?I.device_id:"",d=typeof I.device_public_key=="string"?I.device_public_key:"";if(!b||!d||Ua(d)!==b)return null;let Z=I.endpoint_kind==="web"||I.endpoint_kind==="desktop"||I.endpoint_kind==="custom"?I.endpoint_kind:vn(e),n=`http://${l}:${e}`;return{id:b,device_id:b,device_public_key:d,ip:l,http_port:e,endpoint_kind:Z,url:n,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 RyI(I,l){return l.has(I.ip)}function qs(){return{scanning:Ba.scanning,last_scanned_at:Ba.last_scanned_at,devices:[...Ba.devices]}}async function Oo(I={}){if(!qK())return qs();if(Ds)return Ds;let l=Math.max(100,Math.min(I.timeoutMs||WyI,5e3)),G=[...new Set(I.httpPorts||NyI())],c=I.targetAddresses||oyI(),e=hyI(),b=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;Ba={...Ba,scanning:!0};let d=Date.now();return Ds=new Promise(Z=>{let n=_Q.default.createSocket("udp4"),t=new Map;n.on("message",(a,W)=>{if(!_K(W.address))return;let m=$K(a);if(m?.request_id&&m.request_id!==b)return;let s=iyI(m,W.address,Date.now()-d,new Date().toISOString());s&&!I.includeSelf&&RyI(s,e)||s&&t.set(s.id,s)}),n.on("error",a=>{V.warn(a,"[lan-discovery] UDP scan error")}),n.bind(0,"0.0.0.0",()=>{n.setBroadcast(!0);let a=Buffer.from(JSON.stringify({type:"hermes.discover",version:Bo,request_id:b}));for(let W of G){let m;try{m=PK(W)}catch{continue}for(let s of c)n.send(a,m,s)}}),setTimeout(()=>{try{n.close()}catch{}Ba={scanning:!1,last_scanned_at:new Date().toISOString(),devices:[...t.values()].sort((a,W)=>a.id.localeCompare(W.id))},Z(qs())},l)}).finally(()=>{Ds=null}),Ds}var yn=require("crypto"),jo=require("fs"),Ps=require("fs"),bS=require("os"),Ko=require("path"),dS=require("child_process");VI();GI();JI();var ew="/api/devices/peer-socket",ZS=300*1e3,Iw=64*1024,FyI=5,XyI=1e3,HyI=3e4,lS=5*1024*1024,QyI=3e4,GS=bw("HERMES_LAN_PEER_MAX_TERMINALS",4,1,32),Mo=bw("HERMES_LAN_PEER_TERMINAL_IDLE_MS",600*1e3,3e4,1440*60*1e3),wyI=bw("HERMES_LAN_PEER_TERMINAL_BUFFER_BYTES",1024*1024,64*1024,16*1024*1024),Gw=null;try{Gw=require("node-pty")}catch(I){V.warn(I,"[lan-peer] node-pty failed to load; peer terminal disabled")}function En(){return Date.now()}function bw(I,l,G,c){let e=Number(process.env[I]);return Number.isFinite(e)?Math.max(G,Math.min(c,Math.floor(e))):l}function vyI(I,l,G,c){let e=En();for(let[d,Z]of I)Z<=e&&I.delete(d);let b=`${l}:${G}`;return I.has(b)?!1:(I.set(b,c+ZS),!0)}function cS(I){return I.split("/").pop()||I}function yyI(){return process.platform==="win32"?"powershell.exe":[process.env.SHELL,"/bin/zsh","/bin/bash"].filter(Boolean).find(l=>(0,Ps.existsSync)(l))||"/bin/bash"}function eS(){let I=(0,Ps.existsSync)(nl())?nl():(0,bS.homedir)(),l=Js().cwd?.trim();if(!l)return I;let G=(0,Ko.isAbsolute)(l)?l:(0,Ko.resolve)(I,l);return(0,Ps.existsSync)(G)?G:I}function EyI(I){let l=I.url.replace(/\/$/,""),G=new URL(l);return G.protocol=G.protocol==="https:"?"wss:":"ws:",G.pathname=ew,G.search="",G.toString()}function gyI(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 fo=class{constructor(l,G,c,e,b,d){this.manager=l;this.ws=G;this.role=c;this.deviceId=e;this.computerName=b;this.url=d;this.ws.on("pong",()=>{this.alive=!0}),this.ws.on("message",Z=>this.handleMessage(Z)),this.ws.on("close",()=>this.close({intentional:!1})),this.ws.on("error",Z=>{V.warn(Z,"[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,yn.randomUUID)();connectedAt=En();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===Ad.OPEN||this.ws.readyState===Ad.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===Ad.OPEN){if(!this.alive){try{this.ws.terminate()}catch{}return}this.alive=!1;try{this.ws.ping()}catch{}}},HyI),this.heartbeatTimer.unref?.()}sendJson(l){this.ws.readyState===Ad.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=En(),this.scheduleTerminalIdleTimeout(l,Mo)}scheduleTerminalIdleTimeout(l,G){l.idleTimer&&clearTimeout(l.idleTimer),l.idleTimer=setTimeout(()=>{let c=this.terminalSessions.get(l.id);if(!c)return;let e=Mo-(En()-c.lastActiveAt);if(e>0){this.scheduleTerminalIdleTimeout(c,e);return}V.info({connectionId:this.id,terminalId:c.id,idleMs:Mo},"[lan-peer] closing idle terminal"),this.disposeTerminalSession(c,{notify:!0,exitCode:0})},G),l.idleTimer.unref?.()}request(l,G,c=["error"],e=3e4){if(this.ws.readyState!==Ad.OPEN)return Promise.reject(new Error("Peer connection is not open"));let b=(0,yn.randomUUID)();return new Promise((d,Z)=>{let n=setTimeout(()=>{this.pendingRequests.delete(b),Z(new Error("Peer request timed out"))},e);n.unref?.(),this.pendingRequests.set(b,{resolve:d,reject:Z,successTypes:new Set(G),errorTypes:new Set(c),timer:n}),this.sendJson({...l,request_id:b})})}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:cS(l.shell),last_active_at:l.lastActiveAt,idle_timeout_ms:Mo}))}}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!==Ad.OPEN)return Promise.reject(new Error("Peer connection is not open"));let c=(0,yn.randomUUID)();return new Promise((e,b)=>{let d=setTimeout(()=>{this.pendingDownloads.delete(c),b(new Error("Peer file download timed out"))},G);d.unref?.(),this.pendingDownloads.set(c,{chunks:[],resolve:e,reject:b,timer:d}),this.sendJson({type:"file.download",transfer_id:c,path:l})})}async uploadFileFromBuffer(l,G,c=6e4){let e=(0,yn.randomUUID)();await this.request({type:"file.upload.start",transfer_id:e,path:l},["file.upload.ready"],["file.error","error"],c);for(let b=0;b<G.length;b+=Iw)this.sendJson({type:"file.upload.chunk",transfer_id:e,data:G.subarray(b,b+Iw).toString("base64")});return await this.request({type:"file.upload.complete",transfer_id:e},["file.upload.complete"],["file.error","error"],c),{path:l,size:G.length}}handleMessage(l){let G=gyI(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>wyI&&G.buffer.length>1;){let e=G.buffer.shift()||"";G.bufferBytes-=Buffer.byteLength(e,"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(!Gw){this.sendJson({type:"terminal.error",request_id:l.request_id,message:"Terminal is not available"});return}if(this.terminalSessions.size>=GS){this.sendJson({type:"terminal.error",request_id:l.request_id,message:`Terminal limit reached (${GS} per peer connection)`});return}let G=l.shell||yyI(),c;try{c=Gw.spawn(G,[],{name:"xterm-color",cols:Math.max(1,l.cols||80),rows:Math.max(1,l.rows||24),cwd:eS()})}catch(d){this.sendJson({type:"terminal.error",request_id:l.request_id,message:d?.message||"Failed to create terminal"});return}let e=(0,yn.randomUUID)(),b={id:e,pty:c,shell:G,pid:c.pid,lastActiveAt:En(),idleTimer:null};this.terminalSessions.set(e,b),this.touchTerminalSession(b),b.pty.onData(d=>{this.terminalSessions.has(e)&&(this.touchTerminalSession(b),this.sendJson({type:"terminal.data",terminal_id:e,data:d}))}),b.pty.onExit(({exitCode:d})=>{this.terminalSessions.has(e)&&(b.idleTimer&&clearTimeout(b.idleTimer),this.terminalSessions.delete(e),this.sendJson({type:"terminal.exit",terminal_id:e,exit_code:d}))}),this.sendJson({type:"terminal.created",request_id:l.request_id,terminal_id:e,pid:b.pid,shell:cS(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(u=>typeof u=="string"):[];if(!G){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:"Missing command"});return}let e=eS();if(l.cwd)try{let u=K(l.cwd);e=(0,Ps.existsSync)(u)?u:e}catch(u){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:u?.message||"Invalid cwd"});return}let b=Math.max(1e3,Math.min(Number(l.timeout_ms)||QyI,600*1e3)),d=[],Z=[],n=0,t=0,a=!1,W=!1,m;try{m=(0,dS.spawn)(G,c,{cwd:e,shell:!1,windowsHide:!0})}catch(u){this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:u?.message||"Failed to start command"});return}let s=u=>{a||(a=!0,clearTimeout(Y),this.sendJson({type:"terminal.exec.result",request_id:l.request_id,stdout:Buffer.concat(d).toString("utf8"),stderr:Buffer.concat(Z).toString("utf8"),exit_code:u,timed_out:W}))},N=(u,o,p)=>{if(o>=lS)return o;let h=lS-o,r=p.subarray(0,h);return u.push(r),o+r.length},Y=setTimeout(()=>{W=!0;try{m.kill()}catch{}s(null)},b);Y.unref?.(),m.stdout?.on("data",u=>{n=N(d,n,Buffer.from(u))}),m.stderr?.on("data",u=>{t=N(Z,t,Buffer.from(u))}),m.on("error",u=>{a||(a=!0,clearTimeout(Y),this.sendJson({type:"terminal.exec.error",request_id:l.request_id,message:u.message}))}),m.on("close",u=>s(u))}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(e){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:e?.message||"Invalid file path"});return}let c=(0,jo.createReadStream)(G,{highWaterMark:Iw});this.sendJson({type:"file.download.started",request_id:l.request_id,transfer_id:l.transfer_id}),c.on("data",e=>{this.sendJson({type:"file.download.chunk",transfer_id:l.transfer_id,data:Buffer.from(e).toString("base64")})}),c.on("error",e=>{this.sendJson({type:"file.error",transfer_id:l.transfer_id,message:e.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(e){this.sendJson({type:"file.error",request_id:l.request_id,transfer_id:l.transfer_id,message:e?.message||"Invalid upload path"});return}let c=(0,jo.createWriteStream)(G);c.on("error",e=>{this.uploads.delete(l.transfer_id),this.sendJson({type:"file.error",transfer_id:l.transfer_id,message:e.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})})}},cw=class{wss=new hn.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(e,b,d)=>{let Z=new URL(e.url||"",`http://${e.headers.host}`);if(Z.pathname!==ew)return;if(Od(e,y.corsOrigins)){ga(b);return}let n=await this.authenticateUpgrade(Z,e);if(!n.ok){b.write(`HTTP/1.1 ${n.status} ${n.message}\r
|
|
309
309
|
\r
|
|
310
310
|
`),b.destroy();return}this.wss.handleUpgrade(e,b,d,t=>{let a=new fo(this,t,"server",n.device.id,n.device.computerName,n.device.url);this.connections.set(a.id,a),this.wss.emit("connection",t,e)})})})}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 e=await this.openClientConnection(l);return c.attempts=0,e.info()}async openClientConnection(l){let G=await Sd(),c=En(),e=(0,yn.randomUUID)(),b=await Ss(e,c),d=new URL(EyI(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",e),d.searchParams.set("signature",b);let Z=new Ad(d);await new Promise((t,a)=>{let W=setTimeout(()=>{Z.close(),a(new Error("Peer socket connection timeout"))},5e3);Z.once("open",()=>{clearTimeout(W),t()}),Z.once("error",m=>{clearTimeout(W),a(m)})});let n=new fo(this,Z,"client",l.id,l.computer_name,l.url);return this.connections.set(n.id,n),n}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>=FyI){V.warn({deviceId:l},"[lan-peer] client reconnect limit reached");return}G.attempts+=1;let c=XyI*2**(G.attempts-1);G.reconnectTimer=setTimeout(()=>{G.reconnectTimer=null,this.openClientConnection(G.device).then(()=>{G.attempts=0}).catch(e=>{V.warn({err:e,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()||"",e=l.searchParams.get("device_public_key")||"",b=Number(l.searchParams.get("timestamp")||""),d=l.searchParams.get("nonce")||"",Z=l.searchParams.get("signature")||"",n=l.searchParams.get("computer_name")||"";if(!c||!e||!Number.isFinite(b)||!d||!Z)return{ok:!1,status:400,message:"Bad Request"};if(Math.abs(En()-b)>ZS)return{ok:!1,status:400,message:"Expired Request"};if(!Ts({device_id:c,device_public_key:e,nonce:d,timestamp:b,signature:Z}))return{ok:!1,status:401,message:"Unauthorized"};if(!vyI(this.seenNonces,c,d,b))return{ok:!1,status:409,message:"Replay Request"};if(Bc(c)?.inbound_status!=="approved")return{ok:!1,status:403,message:"Forbidden"};let a=G.socket.remoteAddress?.startsWith("::ffff:")?G.socket.remoteAddress.slice(7):G.socket.remoteAddress||"";return{ok:!0,device:{id:c,computerName:n,url:a?`ws://${a}`:""}}}},lw=null;function mc(){return lw||(lw=new cw),lw}function nS(){return ew}var So=require("fs/promises");var Zw=class{listConnections(){return mc().listConnections()}disconnect(l){return mc().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,So.writeFile)(G,c),{remote_path:l.remotePath,local_path:G,size:c.length}}async uploadFile(l){let G=K(l.localPath),c=await(0,So.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=mc().getConnection(l);if(!G)throw Object.assign(new Error("Peer connection not found"),{status:404});return G}},dw=null;function Gb(){return dw||(dw=new Zw),dw}var aS=C(require("http")),WS=C(require("https")),To=class extends Error{primaryError;fallbackError;constructor(l,G){super(`fetch failed: ${l.message}; node-http fallback failed: ${G.message}`),this.name="LanJsonPostError",this.primaryError=l,this.fallbackError=G}};function tS(I){return{name:String(I?.name||"Error"),message:String(I?.message||I||"request failed"),code:typeof I?.code=="string"?I.code:void 0,syscall:typeof I?.syscall=="string"?I.syscall:void 0,address:typeof I?.address=="string"?I.address:void 0,port:typeof I?.port=="number"?I.port:void 0}}async function JyI(I,l,G,c){let e=new AbortController,b=setTimeout(()=>e.abort(),c);try{let d=await fetch(I,{method:l,headers:l==="POST"?{"Content-Type":"application/json"}:{Accept:"application/json"},...l==="POST"?{body:JSON.stringify(G)}:{},signal:e.signal}),Z=await d.json().catch(()=>({}));return{ok:d.ok,status:d.status,data:Z,transport:"fetch"}}finally{clearTimeout(b)}}function CyI(I){if(!I)return{};try{let l=JSON.parse(I);return l&&typeof l=="object"&&!Array.isArray(l)?l:{}}catch{return{}}}function AyI(I,l,G,c,e){let b=new URL(I),d=l==="POST"?JSON.stringify(G):"",Z=b.protocol==="https:"?WS.default:aS.default;return new Promise((n,t)=>{let a=Z.request(b,{method:l,headers:{Accept:"application/json",...l==="POST"?{"Content-Type":"application/json","Content-Length":Buffer.byteLength(d)}:{}},timeout:c},W=>{let m=[];W.on("data",s=>m.push(Buffer.isBuffer(s)?s:Buffer.from(s))),W.on("end",()=>{let s=W.statusCode||0;n({ok:s>=200&&s<300,status:s,data:CyI(Buffer.concat(m).toString("utf-8")),transport:"node-http",primaryError:e})})});a.on("timeout",()=>{let W=new Error(`request timed out after ${c}ms`);W.code="ETIMEDOUT",a.destroy(W)}),a.on("error",t),a.end(d||void 0)})}async function mS(I,l,G,c){try{return await JyI(I,l,G,c)}catch(e){let b=tS(e);try{return await AyI(I,l,G,c,b)}catch(d){throw new To(b,tS(d))}}}async function sS(I,l=5e3){return mS(I,"GET",void 0,l)}async function nw(I,l,G=5e3){return mS(I,"POST",l,G)}function tw(I){return I instanceof To?{message:I.message,primary:I.primaryError,fallback:I.fallbackError}:I?{message:String(I?.message||I)}:null}JI();var aw=require("crypto"),Ww=300*1e3,Do=new Map;function NS(I,l,G){let c=Date.now();for(let[b,d]of Do)d<=c&&Do.delete(b);let e=`${I}:${l}`;return Do.has(e)?!1:(Do.set(e,G+Ww),!0)}function YS(I){return I==="none"||I==="pending"||I==="approved"||I==="rejected"||I==="blocked"?I:null}async function LyI(I){let l=Date.now(),G=(0,aw.randomUUID)(),c=await Sd(),e=await Ss(G,l);try{let b=await nw(`${I.url.replace(/\/$/,"")}/api/devices/link-status`,{device_id:c.device_id,device_public_key:c.device_public_key,timestamp:l,nonce:G,signature:e},1500);return b.ok?YS(b.data.status):null}catch{return null}}async function kyI(I){let l=new Map;return await Promise.all(I.map(async G=>{let c=await LyI(G);if(!c)return;l.set(G.id,c);let e=Bc(G.id);c!=="pending"&&(c!=="none"||e?.outbound_status!=="none")&&ko(G.id,c,G)})),l}function hS(I){return{id:I.id,device_id:I.device_id,device_public_key:I.device_public_key,ip:I.ip,http_port:I.http_port,endpoint_kind:I.endpoint_kind,url:I.url,computer_name:I.computer_name,os:I.os,hermes_agent_version:I.hermes_agent_version,hermes_web_ui_version:I.hermes_web_ui_version,response_ms:I.response_ms,last_seen_at:new Date(I.last_seen_at||I.updated_at||Date.now()).toISOString()}}function xyI(I,l){let G=new Map(I.map(c=>[c.id,c]));for(let c of l)G.has(c.id)||c.inbound_status==="none"&&c.outbound_status==="none"||!c.device_public_key||!c.url||!c.http_port||G.set(c.id,hS(c));return[...G.values()]}async function Ma(){let I=qs(),l=Lo(),G=new Set(I.devices.map(Z=>Z.id)),c=xyI(I.devices,l),e=await kyI(c),b=new Map(Lo().map(Z=>[Z.id,Z])),d=c.map(Z=>{let n=b.get(Z.id),t=e.get(Z.id)||n?.outbound_status||"none",a=G.has(Z.id)||e.has(Z.id);return a&&t==="approved"&&mc().connectToDevice(Z).catch(W=>{console.warn("[lan-peer] failed to connect paired device:",W?.message||W)}),{...Z,online:a,inbound_status:n?.inbound_status||"none",outbound_status:t,requested_at:n?.requested_at||0,decided_at:n?.decided_at||null,outbound_requested_at:n?.outbound_requested_at||0,outbound_decided_at:n?.outbound_decided_at||null,updated_at:n?.updated_at||0}});return{scanning:I.scanning,last_scanned_at:I.last_scanned_at,devices:d,requests:OK()}}async function uS(I){I.body=await Ma()}function zyI(I){let l=String(I||"").trim();if(!l)return null;try{let G=new URL(l.includes("://")?l:`http://${l}`);return G.protocol!=="http:"&&G.protocol!=="https:"?null:(G.username="",G.password="",G.pathname="",G.search="",G.hash="",G)}catch{return null}}function UyI(I){return Math.max(0,Date.now()-I)}function ByI(I,l,G){let c=typeof l.device_id=="string"?l.device_id.trim():"",e=typeof l.device_public_key=="string"?l.device_public_key:"";if(!c||!e||Ua(e)!==c)return null;let b=Number(l.http_port)||Number(I.port)||(I.protocol==="https:"?443:80);if(!Number.isInteger(b)||b<=0||b>65535)return null;let d=l.endpoint_kind==="web"||l.endpoint_kind==="desktop"||l.endpoint_kind==="custom"?l.endpoint_kind:vn(b);return{id:c,device_id:c,device_public_key:e,ip:I.hostname,http_port:b,endpoint_kind:d,url:I.origin,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:G,last_seen_at:new Date().toISOString()}}async function OyI(I){let l=Date.now(),G=await sS(`${I.origin}/api/devices/link-info`,5e3);if(!G.ok)throw new Error(`Device info request failed: ${G.status}`);let c=ByI(I,G.data,UyI(l));if(!c)throw new Error("Remote URL did not return valid device info");return c}async function pS(I){let l=Date.now(),G=(0,aw.randomUUID)(),c=await Sd(),e=await Ss(G,l),b={...c,http_port:y.port,endpoint_kind:vn(y.port),timestamp:l,nonce:G,signature:e},d=await nw(`${I.url.replace(/\/$/,"")}/api/devices/link-request`,b,5e3),Z=d.data;if(!d.ok){let n=new Error(typeof Z.error=="string"?Z.error:`Request failed: ${d.status}`);throw n.status=d.status===409?409:502,n}return YS(Z.status)||"pending"}async function oS(I){let l=await Sd();I.body={...l,http_port:y.port,endpoint_kind:vn(y.port)}}async function rS(I){let l=zyI(I.request.body?.url);if(!l){I.status=400,I.body={error:"Invalid device URL"};return}try{let G=await OyI(l),c=await pS(G);c!=="none"&&ko(G.id,c,G),I.body=await Ma()}catch(G){I.status=Number(G?.status)||502,I.body={error:G?.message?`Failed to request device pairing: ${G.message}`:"Failed to request device pairing",detail:tw(G)}}}async function VS(I){await Oo(),I.body=await Ma()}function mw(I){let l=qs().devices.find(c=>c.id===I);if(l)return l;let G=Bc(I);return G?hS(G):null}function MyI(I){let l=String(I.ip||I.request?.ip||"");return l.startsWith("::ffff:")?l.slice(7):l}function fyI(I,l){let G=typeof l?.device_id=="string"?l.device_id.trim():"",c=typeof l?.device_public_key=="string"?l.device_public_key:"",e=Number(l?.http_port);if(!G||!c||!Number.isInteger(e)||e<=0||e>65535)return null;let b=MyI(I),d=l.endpoint_kind==="web"||l.endpoint_kind==="desktop"||l.endpoint_kind==="custom"?l.endpoint_kind:vn(e);return{id:G,device_id:G,device_public_key:c,ip:b,http_port:e,endpoint_kind:d,url:typeof l?.url=="string"&&l.url?l.url:`http://${b}:${e}`,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 iS(I){let l=I.request.body,G=Number(l?.timestamp),c=typeof l?.nonce=="string"?l.nonce:"",e=typeof l?.signature=="string"?l.signature:"",b=fyI(I,l);if(!b||!Number.isFinite(G)||!c||!e){I.status=400,I.body={error:"Invalid device request"};return}if(Math.abs(Date.now()-G)>Ww){I.status=400,I.body={error:"Device request expired"};return}if(!Ts({device_id:b.id,device_public_key:b.device_public_key,nonce:c,timestamp:G,signature:e})){I.status=401,I.body={error:"Invalid device signature"};return}if(!NS(b.id,c,G)){I.status=409,I.body={error:"Device request replayed"};return}try{let d=fK(b);I.body={status:d.inbound_status}}catch(d){if(d instanceof fs){I.status=409,I.body={error:"Duplicate pairing request"};return}throw d}}async function RS(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:"",e=Number(l?.timestamp),b=typeof l?.nonce=="string"?l.nonce:"",d=typeof l?.signature=="string"?l.signature:"";if(!G||!c||!Number.isFinite(e)||!b||!d){I.status=400,I.body={error:"Invalid device status request"};return}if(Math.abs(Date.now()-e)>Ww){I.status=400,I.body={error:"Device status request expired"};return}if(!Ts({device_id:G,device_public_key:c,nonce:b,timestamp:e,signature:d})){I.status=401,I.body={error:"Invalid device signature"};return}if(!NS(G,b,e)){I.status=409,I.body={error:"Device status request replayed"};return}I.body={status:Bc(G)?.inbound_status||"none"}}async function qo(I,l){try{jK(I.params.id,l,mw(I.params.id)||void 0),I.body=await Ma()}catch{I.status=404,I.body={error:"Device not found"}}}async function FS(I){await qo(I,"approved")}async function XS(I){await qo(I,"rejected")}async function HS(I){await qo(I,"blocked")}async function QS(I){await qo(I,"none")}async function wS(I){if(!KK(I.params.id)){I.status=404,I.body={error:"Device request not found"};return}mc().disconnectDevice(I.params.id),I.body=await Ma()}async function vS(I){I.body={connections:mc().listConnections()}}async function yS(I){let l=mw(I.params.id);if(!l){I.status=404,I.body={error:"Device not found"};return}if(Bc(I.params.id)?.outbound_status!=="approved"){I.status=403,I.body={error:"Device pairing has not been approved"};return}try{let c=await mc().connectToDevice(l);I.body={connection:c}}catch(c){I.status=502,I.body={error:c?.message||"Failed to connect peer device"}}}async function ES(I){if(!mc().disconnect(I.params.connectionId)){I.status=404,I.body={error:"Peer connection not found"};return}I.body={connections:mc().listConnections()}}function gn(I,l){let G=Number(I);return Number.isFinite(G)?G:l}function Ub(I,l){I.status=Number(l?.status)||502,I.body={error:l?.message||"Peer operation failed"}}async function gS(I){let l=I.request.body;try{let G=await Gb().createTerminal(I.params.connectionId,{shell:typeof l?.shell=="string"?l.shell:void 0,cols:gn(l?.cols,80),rows:gn(l?.rows,24)});I.body={terminal:G}}catch(G){Ub(I,G)}}async function JS(I){try{I.body={terminals:Gb().listTerminals(I.params.connectionId)}}catch(l){Ub(I,l)}}async function CS(I){let l=I.request.body;try{I.body=Gb().writeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||""),data:String(l?.data||"")})}catch(G){Ub(I,G)}}async function AS(I){let l=I.request.body;try{I.body=Gb().resizeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||""),cols:gn(l?.cols,80),rows:gn(l?.rows,24)})}catch(G){Ub(I,G)}}async function LS(I){try{I.body={terminal:Gb().readTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||"")})}}catch(l){Ub(I,l)}}async function kS(I){try{I.body=Gb().closeTerminal({connectionId:I.params.connectionId,terminalId:String(I.params.terminalId||"")})}catch(l){Ub(I,l)}}async function xS(I){let l=I.request.body;try{let G=await Gb().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:gn(l?.timeout_ms,3e4)});I.body={result:G}}catch(G){Ub(I,G)}}async function zS(I){let l=I.request.body;try{I.body=await Gb().downloadFile({connectionId:I.params.connectionId,remotePath:String(l?.remote_path||l?.path||""),localPath:String(l?.local_path||""),timeoutMs:gn(l?.timeout_ms,6e4)})}catch(G){Ub(I,G)}}async function US(I){let l=I.request.body;try{I.body=await Gb().uploadFile({connectionId:I.params.connectionId,localPath:String(l?.local_path||""),remotePath:String(l?.remote_path||l?.path||""),timeoutMs:gn(l?.timeout_ms,6e4)})}catch(G){Ub(I,G)}}async function BS(I){let l=mw(I.params.id);if(!l){I.status=404,I.body={error:"Device not found"};return}try{let G=await pS(l);G!=="none"&&ko(l.id,G,l),I.body=await Ma()}catch(G){let c=tw(G);I.status=Number(G?.status)||502,I.body={error:G?.message?`Failed to request device pairing: ${G.message}`:"Failed to request device pairing",detail:c}}}var _s=new B,tl=new B;_s.post("/api/devices/link-request",iS);_s.post("/api/devices/link-status",RS);_s.get("/api/devices/link-info",oS);tl.get("/api/devices",uS);tl.post("/api/devices/scan",VS);tl.post("/api/devices/manual-request",rS);tl.post("/api/devices/:id/request",BS);tl.post("/api/devices/:id/approve",FS);tl.post("/api/devices/:id/reject",XS);tl.post("/api/devices/:id/block",HS);tl.post("/api/devices/:id/unblock",QS);tl.delete("/api/devices/:id/request-history",wS);tl.get("/api/devices/peer-connections",vS);tl.post("/api/devices/:id/connect",yS);tl.post("/api/devices/peer-connections/:connectionId/disconnect",ES);tl.post("/api/devices/peer-connections/:connectionId/terminal",gS);tl.get("/api/devices/peer-connections/:connectionId/terminals",JS);tl.get("/api/devices/peer-connections/:connectionId/terminal/:terminalId/read",LS);tl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/input",CS);tl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/resize",AS);tl.post("/api/devices/peer-connections/:connectionId/terminal/:terminalId/close",kS);tl.post("/api/devices/peer-connections/:connectionId/exec",xS);tl.post("/api/devices/peer-connections/:connectionId/download",zS);tl.post("/api/devices/peer-connections/:connectionId/upload",US);var CT=require("child_process"),AT=require("crypto"),sc=require("fs"),WG=require("fs/promises"),dr=require("os"),oI=require("path"),LT=require("util");JI();Sl();var ww=require("stream");JI();function sw(I){let l=String(I||"").trim().replace(/\/+$/,"");if(!l)throw new Error("baseUrl is required");return new URL(l)}function Nw(I){return I.pathname.replace(/\/+$/,"")}function fa(I,l){return`${I.replace(/\/+$/,"")}/${l.replace(/^\/+/,"")}`}function Yw(I,l){return I.toLowerCase().endsWith(`/${l.toLowerCase()}`)}function OS(I){let l=I.toLowerCase(),G=l.split("/").filter(Boolean),c=G[G.length-1]||"";return!!(/^v\d+(?:beta)?$/.test(c)||c==="openai"||/\/api\/paas\/v\d+$/.test(l)||/\/coding\/v\d+$/.test(l)||/\/step_plan\/v\d+$/.test(l))}function KyI(I){let G=I.toLowerCase().split("/").filter(Boolean),c=G[G.length-1]||"";return/^v\d+(?:beta)?$/.test(c)}function $s(I){let l=sw(I),G=Nw(l),c=l.toString().replace(/\/+$/,"");return Yw(G,"chat/completions")?c:OS(G)?fa(c,"chat/completions"):fa(c,"v1/chat/completions")}function ja(I){let l=sw(I),G=Nw(l),c=l.toString().replace(/\/+$/,"");return Yw(G,"responses")?c:OS(G)?fa(c,"responses"):fa(c,"v1/responses")}function Po(I){let l=sw(I),G=Nw(l),c=l.toString().replace(/\/+$/,"");return Yw(G,"messages")?c:KyI(G)?fa(c,"messages"):fa(c,"v1/messages")}function hw(I){let l,G=[];for(let c of I.split(/\r?\n/))if(!(!c||c.startsWith(":"))){if(c.startsWith("event:")){l=c.slice(6).trim();continue}c.startsWith("data:")&&G.push(c.slice(5).trimStart())}return G.length?{event:l,data:G.join(`
|
|
@@ -1215,7 +1215,7 @@ ${G.instructions}`:ce();if(G.session_id){let t=hI(G.session_id)?.workspace||Stri
|
|
|
1215
1215
|
${`[Current working directory: ${t}]`}
|
|
1216
1216
|
${Z}`)}await sdI(this.nsp,l,{...G,instructions:Z},c,this.sessionMap,this.bridge,e,ER,this.dequeueNextQueuedRun.bind(this));return}if(b==="coding_agent"){await hdI(this.nsp,l,G,c,this.sessionMap);return}await _bI(this.nsp,l,G,c,this.sessionMap,e,this.dequeueNextQueuedRun.bind(this))}}async resumeSession(l,G){let c=this.sessionMap.get(G);c||(c=await ER(G,this.sessionMap),this.sessionMap.set(G,c)),await this.reattachBridgeRun(l,G,c);let e=c.isWorking?c.events:(c.events||[]).filter(b=>b?.event==="run.reattach_failed");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:e,inputTokens:c.inputTokens,outputTokens:c.outputTokens,contextTokens:c.contextTokens,queueLength:c.queue?.length||0,queueMessages:this.serializeQueuedMessages(c.queue||[])}),V.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 e=hI(G),b=e?.profile||FMI(l),d;try{let Z=await this.bridge.statusIfLoaded(G,b,{timeoutMs:1e3}),n=Z.running===!0,t=typeof Z.current_run_id=="string"?Z.current_run_id:"";if(!n||!t||(d=`${G}:${t}`,this.bridgeResumePolls.has(d)))return;this.bridgeResumePolls.add(d),c.isWorking=!0,c.isAborting=c.isAborting===!0,c.runId=t,c.activeRunMarker=void 0,c.profile=b,c.source="cli",c.events=[];let a=this.resumeInstructionsForSession(G);NdI(this.nsp,l,{sessionId:G,runId:t,profile:b,instructions:a,model:e?.model,provider:e?.provider},this.sessionMap,this.bridge,this.dequeueNextQueuedRun.bind(this)).finally(()=>{d&&this.bridgeResumePolls.delete(d)}),V.info("[chat-run-socket] reattached running bridge run %s for session %s",t,G)}catch(Z){d&&this.bridgeResumePolls.delete(d),V.warn(Z,"[chat-run-socket] bridge status lookup failed while resuming session %s",G);let n=$e().getRuntimeState?.().endpoint,t=aJ(Z instanceof Error?Z.message:String(Z),n),a={event:"run.reattach_failed",session_id:G,error:t,message:`Unable to confirm Agent Bridge status while resuming: ${t}`,text:`Unable to confirm Agent Bridge status while resuming: ${t}`},W=[...c.events||[]],m=W[W.length-1];(m?.event!=="run.reattach_failed"||m?.data?.error!==t)&&(W.push({event:"run.reattach_failed",data:a}),c.events=W),this.emitToSession(l,G,"run.reattach_failed",a)}}resumeInstructionsForSession(l){let G=ce(),c=hI(l);return c?.workspace&&(G=`
|
|
1217
1217
|
[Current working directory: ${c.workspace}]
|
|
1218
|
-
${G}`),G}dequeueNextQueuedRun(l,G,c="default"){let e=this.sessionMap.get(G);if(!e?.queue.length)return!1;let b=e.queue.shift();return e.isWorking=!0,e.profile=b.profile||c,e.source=b.source,V.info("[chat-run-socket] dequeuing queued run for session %s (remaining: %d)",G,e.queue.length),this.nsp.to(`session:${G}`).emit("run.queued",{event:"run.queued",session_id:G,queue_length:e.queue.length,dequeued_queue_id:b.queue_id,queued_messages:this.serializeQueuedMessages(e.queue)}),this.runQueuedItem(l,G,b,c),!0}runQueuedItem(l,G,c,e="default"){let b=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,workspace:c.workspace,source:c.source,queue_id:c.queue_id,peerExcludeSocketId:c.originSocketId,coding_agent_id:c.codingAgentId,agent_id:c.agentId,mode:c.mode,baseUrl:c.baseUrl,base_url:c.base_url,apiKey:c.apiKey,api_key:c.api_key,apiMode:c.apiMode,api_mode:c.api_mode},c.profile||e,b)}emitExternalEvent(l,G,c){let e={...c,session_id:l},b=this.sessionMap.get(l);b?.isWorking&&(b.events.push({event:G,data:e}),b.events.length>200&&b.events.splice(0,b.events.length-200)),this.nsp.to(`session:${l}`).emit(G,e)}markExternalRunCompleted(l,G){let c=this.sessionMap.get(l);if(c&&(c.isWorking=!1,c.abortController=void 0,c.runId=void 0,c.activeRunMarker=void 0,c.events=[],c.responseRun=void 0,c.profile=void 0,V.info("[chat-run-socket] external run completed for session %s (%s)",l,G),c.queue.length>0)){let e=this.socketForQueuedRun(l,c.queue[0]);e&&this.dequeueNextQueuedRun(e,l)}}socketForQueuedRun(l,G){if(G?.originSocketId){let e=this.nsp.sockets.get(G.originSocketId);if(e)return e}let c=this.nsp.adapter.rooms.get(`session:${l}`);if(c)for(let e of c){let b=this.nsp.sockets.get(e);if(b)return b}return this.nsp.sockets.values().next().value||null}clearClarifyEventState(l,G){let c=this.sessionMap.get(l);if(!c?.events.length)return;let e=c.events.filter(({event:b,data:d})=>b!=="clarify.requested"&&b!=="clarify.resolved"?!0:d?.clarify_id!==G);e.length!==c.events.length&&(c.events=e)}emitToSession(l,G,c,e){let b={...e,session_id:G};this.nsp.to(`session:${G}`).emit(c,b),!this.nsp.adapter.rooms.get(`session:${G}`)?.size&&l.connected&&l.emit(c,b)}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:Ge(G.displayInput??G.input),timestamp:Math.floor(Date.now()/1e3),queued:!0}))}canAccessProfile(l,G){return l.role==="super_admin"||ya(l.id,G)}close(){for(let[l,G]of this.sessionMap.entries())if(G.abortController)try{G.abortController.abort()}catch(c){V.warn(c,"[chat-run-socket] failed to abort controller for session %s",l)}this.sessionMap.clear(),V.info("[chat-run-socket] closed all connections and cleared state")}};var XdI=require("node:fs"),HdI=require("node:os"),LR=require("node:path");JI();Sl();GI();VI();var JZ="hermes-studio",kR="HERMES_WEB_UI_MANAGED_MCP",HMI=new Set(["hermes-lan-peer-mcp","hermes-devices-mcp","hermes-web-ui-mcp","hermes-studio-mcp"]);function QdI(I){return["1","true","yes","on"].includes(String(I||"").trim().toLowerCase())}function QMI(){return QdI(process.env.HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT)}function wMI(){return QdI(process.env.HERMES_WEB_UI_ALLOW_TRANSIENT_MCP_AUTOINJECT)}function FdI(I){return I.replace(/\/+$/,"")+"/"}function vMI(I){let l=FdI(I);return[(0,HdI.tmpdir)(),"/tmp","/private/tmp"].filter(Boolean).map(c=>FdI(c)).some(c=>l.startsWith(c))}function yMI(){return vMI(y.appHome)&&!wMI()}function EMI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function wdI(){return[process.env.HERMES_WEB_UI_MCP_BIN,(0,LR.join)(process.cwd(),"bin/hermes-web-ui-mcp.mjs"),(0,LR.join)(__dirname,"../../bin/hermes-web-ui-mcp.mjs"),(0,LR.join)(__dirname,"../../../../../bin/hermes-web-ui-mcp.mjs")].filter(I=>!!I)}function gMI(){return wdI().find(I=>(0,XdI.existsSync)(I))||null}function JMI(){if(EMI())return{command:"hermes-studio-mcp"};let I=gMI();return I?{command:process.execPath,args:[I]}:(V.warn({candidates:wdI()},"[mcp-autoinject] bundled MCP script not found; falling back to PATH command"),{command:"hermes-web-ui-mcp"})}function CMI(){let I={HERMES_WEB_UI_URL:`http://127.0.0.1:${y.port}`,HERMES_WEB_UI_HOME:y.appHome,HERMES_WEBUI_STATE_DIR:y.appHome,[kR]:"1"};return{...JMI(),env:I,enabled:!0}}function mm(I){return!!I&&typeof I=="object"&&!Array.isArray(I)}function AMI(I){return mm(I)?mm(I.env)&&I.env[kR]==="1"?!0:typeof I.command=="string"&&HMI.has(I.command):!1}function LMI(I,l){let G=Array.isArray(l.args)?l.args:void 0,c=Array.isArray(I.args)?I.args:void 0;return!G&&!c?!0:!G||!c?!1:G.length===c.length&&G.every((e,b)=>c[b]===e)}function kMI(I,l){let G=l.env;return I.command===l.command&&LMI(I,l)&&I.enabled!==!1&&mm(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[kR]===G[kR]}async function xMI(I,l){return await DG(I,G=>{let c=mm(G)?G:{};mm(c.mcp_servers)||(c.mcp_servers={});let e=c.mcp_servers[JZ];return e?AMI(e)?mm(e)&&e.enabled===!1?{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${JZ} MCP server is disabled by user`}}:kMI(e,l)?{data:c,write:!1,result:{profile:I,status:"unchanged"}}:(c.mcp_servers[JZ]=l,{data:c,result:{profile:I,status:"updated"}}):{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${JZ} MCP server is not managed by Hermes Web UI`}}:(c.mcp_servers[JZ]=l,{data:c,result:{profile:I,status:"injected"}})})}async function vdI(){let I=CMI(),l={serverName:JZ,command:String(I.command),targets:[]};if(QMI())return V.info("[mcp-autoinject] disabled by HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT"),l;if(yMI())return V.info({appHome:y.appHome},"[mcp-autoinject] skipped for transient Web UI home"),l;for(let e of DI())l.targets.push(await xMI(e,I));let G=l.targets.filter(e=>e.status==="injected"||e.status==="updated");G.length>0&&V.info({serverName:JZ,command:I.command,targets:G},"[mcp-autoinject] synced bundled MCP server");let c=l.targets.filter(e=>e.status==="skipped");return c.length>0&&V.warn({serverName:JZ,targets:c},"[mcp-autoinject] skipped unmanaged MCP server entries"),l}xa();GI();var UMI="0.6.16";process.on("uncaughtException",I=>{console.error("FATAL: Uncaught exception"),console.error(I),V.fatal(I,"Uncaught exception"),process.exit(1)});process.on("unhandledRejection",I=>{console.error("Unhandled rejection"),console.error(I),V.error(I,"Unhandled rejection")});var BMI=null,CZ=[],xR=null,zR=null;function OMI(I,l,G){return new Promise((c,e)=>{let b=I.listen(l,G);b.once("listening",()=>c(b)),b.once("error",e)})}async function MMI(I,l,G){let c=G||"0.0.0.0";console.log(`[bootstrap] listening on ${c}:${l}`);let e=await OMI(I,l,c);return{primary:e,servers:[e]}}function fMI(){try{return LdI.default.networkInterfaces()}catch{return{}}}function gdI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function xdI(I){let l=String(process.env[I]||"").trim().toLowerCase();return["1","true","yes","on"].includes(l)}function zdI(){return xdI("HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART")}function jMI(){return xdI("HERMES_WEB_UI_DISABLE_SKILL_INJECTION")}async function KMI(){if(zdI())console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART");else try{await wQ(),console.log("[bootstrap] profile gateways checked")}catch(I){V.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}try{zR=await MQ(),console.log("[bootstrap] agent bridge started")}catch(I){V.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I)}}function SMI(){zdI()?console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART"):(async()=>{try{await wQ(),console.log("[bootstrap] profile gateways checked")}catch(I){V.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}})(),(async()=>{try{zR=await MQ(),console.log("[bootstrap] agent bridge started")}catch(I){V.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I);return}})()}function TMI(){let I=IS({httpPort:y.port}),l=!1,G=()=>{l||(l=!0,Oo().catch(c=>V.warn(c,"[lan-discovery] initial scan failed")))};I?(I.once("listening",G),setTimeout(G,500).unref?.()):G()}async function UdI(){if(console.log(`hermes-web-ui v${UMI} starting...`),await(0,WJ.mkdir)(y.uploadDir,{recursive:!0}),D9()&&await(0,WJ.mkdir)(y.dataDir,{recursive:!0}),await dx(),jMI())console.log("[bootstrap] bundled skill injection disabled by HERMES_WEB_UI_DISABLE_SKILL_INJECTION");else try{let m=await new xn().injectMissingSkills();m.injected.length>0&&V.info({injected:[...new Set(m.injected)],targetCount:m.targets.length},"[bootstrap] bundled skills injected"),m.updated.length>0&&V.info({updated:[...new Set(m.updated)],targetCount:m.targets.length},"[bootstrap] bundled skills updated")}catch(W){V.warn(W,"[bootstrap] failed to inject bundled skills"),console.warn("[bootstrap] failed to inject bundled skills:",W instanceof Error?W.message:W)}try{await vdI()}catch(W){V.warn(W,"[bootstrap] failed to inject bundled MCP server"),console.warn("[bootstrap] failed to inject bundled MCP server:",W instanceof Error?W.message:W)}gdI()||await KMI();let I=new dL;await new Promise(W=>setTimeout(W,1e3));let{initAllStores:l}=await Promise.resolve().then(()=>(EdI(),ydI));l(),await new Promise(W=>setTimeout(W,1e3)),console.log("[bootstrap] all stores initialized"),I.use(vf()),I.use((0,JdI.default)({origin:Qf(y.corsOrigins)})),I.use(O3({encoding:"utf-8",jsonLimit:"20mb",formLimit:"20mb",textLimit:"20mb",parsedMethods:["POST","PUT","PATCH","DELETE"]})),console.log("[bootstrap] cors + bodyParser registered");let G=EcI(I,[Xf,Hf]);I.use(G),console.log("[bootstrap] routes registered");let c=(0,kdI.resolve)(__dirname,"..","client");I.use((0,CdI.default)(c)),I.use(async W=>{!W.path.startsWith("/api")&&W.path!=="/health"&&W.path!=="/upload"&&W.path!=="/webhook"&&await(0,AdI.default)(W,"index.html",{root:c})}),console.log("[bootstrap] SPA fallback registered");let e=await MMI(I,y.port,y.host);BMI=e.primary,CZ=e.servers,console.log("[bootstrap] app.listen called"),gf(CZ),ej(CZ),mc().setupServer(CZ),console.log("[bootstrap] terminal + kanban + LAN peer websocket setup");let b=new HR(CZ);UD(b),xR=new AR(b.getIO()),cH(xR),xR.init();let{SessionDeleter:d}=await Promise.resolve().then(()=>(yr(),mq)),Z=d.getInstance(),n=process.env.PROFILE||"default";Z.start(n),console.log("[bootstrap] session deleter started, profile=%s",n),CZ.forEach(W=>{W.on("upgrade",(m,s)=>{let N=new URL(m.url||"",`http://${m.headers.host}`);N.pathname!=="/api/hermes/terminal"&&N.pathname!=="/api/hermes/kanban/events"&&N.pathname!==nS()&&!N.pathname.startsWith("/socket.io/")&&s.destroy()})});let t=fMI(),a=Object.values(t).flat().find(W=>W?.family==="IPv4"&&!W?.internal)?.address||"localhost";console.log(`Server: http://localhost:${y.port} (LAN: http://${a}:${y.port})`),console.log(`Log: ${y.appHome}/logs/server.log`),V.info("Server: http://localhost:%d (LAN: http://%s:%d)",y.port,a,y.port),TMI(),GP("bootstrap"),gdI()&&(zR=$e(),SMI()),b.restoreWhenReady(),CZ.forEach(W=>{W.on("error",m=>{console.error("[bootstrap] server error:",m.code||m.message),V.error({err:m},"Server error")})}),KB(CZ,b,xR,zR),fQ()}UdI().catch(I=>{console.error("FATAL: Failed to start Hermes Web UI"),console.error(I),V.fatal(I,"Fatal error during bootstrap"),process.exit(1)});0&&(module.exports={bootstrap});
|
|
1218
|
+
${G}`),G}dequeueNextQueuedRun(l,G,c="default"){let e=this.sessionMap.get(G);if(!e?.queue.length)return!1;let b=e.queue.shift();return e.isWorking=!0,e.profile=b.profile||c,e.source=b.source,V.info("[chat-run-socket] dequeuing queued run for session %s (remaining: %d)",G,e.queue.length),this.nsp.to(`session:${G}`).emit("run.queued",{event:"run.queued",session_id:G,queue_length:e.queue.length,dequeued_queue_id:b.queue_id,queued_messages:this.serializeQueuedMessages(e.queue)}),this.runQueuedItem(l,G,b,c),!0}runQueuedItem(l,G,c,e="default"){let b=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,workspace:c.workspace,source:c.source,queue_id:c.queue_id,peerExcludeSocketId:c.originSocketId,coding_agent_id:c.codingAgentId,agent_id:c.agentId,mode:c.mode,baseUrl:c.baseUrl,base_url:c.base_url,apiKey:c.apiKey,api_key:c.api_key,apiMode:c.apiMode,api_mode:c.api_mode},c.profile||e,b)}emitExternalEvent(l,G,c){let e={...c,session_id:l},b=this.sessionMap.get(l);b?.isWorking&&(b.events.push({event:G,data:e}),b.events.length>200&&b.events.splice(0,b.events.length-200)),this.nsp.to(`session:${l}`).emit(G,e)}markExternalRunCompleted(l,G){let c=this.sessionMap.get(l);if(c&&(c.isWorking=!1,c.abortController=void 0,c.runId=void 0,c.activeRunMarker=void 0,c.events=[],c.responseRun=void 0,c.profile=void 0,V.info("[chat-run-socket] external run completed for session %s (%s)",l,G),c.queue.length>0)){let e=this.socketForQueuedRun(l,c.queue[0]);e&&this.dequeueNextQueuedRun(e,l)}}socketForQueuedRun(l,G){if(G?.originSocketId){let e=this.nsp.sockets.get(G.originSocketId);if(e)return e}let c=this.nsp.adapter.rooms.get(`session:${l}`);if(c)for(let e of c){let b=this.nsp.sockets.get(e);if(b)return b}return this.nsp.sockets.values().next().value||null}clearClarifyEventState(l,G){let c=this.sessionMap.get(l);if(!c?.events.length)return;let e=c.events.filter(({event:b,data:d})=>b!=="clarify.requested"&&b!=="clarify.resolved"?!0:d?.clarify_id!==G);e.length!==c.events.length&&(c.events=e)}emitToSession(l,G,c,e){let b={...e,session_id:G};this.nsp.to(`session:${G}`).emit(c,b),!this.nsp.adapter.rooms.get(`session:${G}`)?.size&&l.connected&&l.emit(c,b)}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:Ge(G.displayInput??G.input),timestamp:Math.floor(Date.now()/1e3),queued:!0}))}canAccessProfile(l,G){return l.role==="super_admin"||ya(l.id,G)}close(){for(let[l,G]of this.sessionMap.entries())if(G.abortController)try{G.abortController.abort()}catch(c){V.warn(c,"[chat-run-socket] failed to abort controller for session %s",l)}this.sessionMap.clear(),V.info("[chat-run-socket] closed all connections and cleared state")}};var XdI=require("node:fs"),HdI=require("node:os"),LR=require("node:path");JI();Sl();GI();VI();var JZ="hermes-studio",kR="HERMES_WEB_UI_MANAGED_MCP",HMI=new Set(["hermes-lan-peer-mcp","hermes-devices-mcp","hermes-web-ui-mcp","hermes-studio-mcp"]);function QdI(I){return["1","true","yes","on"].includes(String(I||"").trim().toLowerCase())}function QMI(){return QdI(process.env.HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT)}function wMI(){return QdI(process.env.HERMES_WEB_UI_ALLOW_TRANSIENT_MCP_AUTOINJECT)}function FdI(I){return I.replace(/\/+$/,"")+"/"}function vMI(I){let l=FdI(I);return[(0,HdI.tmpdir)(),"/tmp","/private/tmp"].filter(Boolean).map(c=>FdI(c)).some(c=>l.startsWith(c))}function yMI(){return vMI(y.appHome)&&!wMI()}function EMI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function wdI(){return[process.env.HERMES_WEB_UI_MCP_BIN,(0,LR.join)(process.cwd(),"bin/hermes-web-ui-mcp.mjs"),(0,LR.join)(__dirname,"../../bin/hermes-web-ui-mcp.mjs"),(0,LR.join)(__dirname,"../../../../../bin/hermes-web-ui-mcp.mjs")].filter(I=>!!I)}function gMI(){return wdI().find(I=>(0,XdI.existsSync)(I))||null}function JMI(){if(EMI())return{command:"hermes-studio-mcp"};let I=gMI();return I?{command:process.execPath,args:[I]}:(V.warn({candidates:wdI()},"[mcp-autoinject] bundled MCP script not found; falling back to PATH command"),{command:"hermes-web-ui-mcp"})}function CMI(){let I={HERMES_WEB_UI_URL:`http://127.0.0.1:${y.port}`,HERMES_WEB_UI_HOME:y.appHome,HERMES_WEBUI_STATE_DIR:y.appHome,[kR]:"1"};return{...JMI(),env:I,enabled:!0}}function mm(I){return!!I&&typeof I=="object"&&!Array.isArray(I)}function AMI(I){return mm(I)?mm(I.env)&&I.env[kR]==="1"?!0:typeof I.command=="string"&&HMI.has(I.command):!1}function LMI(I,l){let G=Array.isArray(l.args)?l.args:void 0,c=Array.isArray(I.args)?I.args:void 0;return!G&&!c?!0:!G||!c?!1:G.length===c.length&&G.every((e,b)=>c[b]===e)}function kMI(I,l){let G=l.env;return I.command===l.command&&LMI(I,l)&&I.enabled!==!1&&mm(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[kR]===G[kR]}async function xMI(I,l){return await DG(I,G=>{let c=mm(G)?G:{};mm(c.mcp_servers)||(c.mcp_servers={});let e=c.mcp_servers[JZ];return e?AMI(e)?mm(e)&&e.enabled===!1?{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${JZ} MCP server is disabled by user`}}:kMI(e,l)?{data:c,write:!1,result:{profile:I,status:"unchanged"}}:(c.mcp_servers[JZ]=l,{data:c,result:{profile:I,status:"updated"}}):{data:c,write:!1,result:{profile:I,status:"skipped",reason:`existing ${JZ} MCP server is not managed by Hermes Web UI`}}:(c.mcp_servers[JZ]=l,{data:c,result:{profile:I,status:"injected"}})})}async function vdI(){let I=CMI(),l={serverName:JZ,command:String(I.command),targets:[]};if(QMI())return V.info("[mcp-autoinject] disabled by HERMES_WEB_UI_DISABLE_MCP_AUTOINJECT"),l;if(yMI())return V.info({appHome:y.appHome},"[mcp-autoinject] skipped for transient Web UI home"),l;for(let e of DI())l.targets.push(await xMI(e,I));let G=l.targets.filter(e=>e.status==="injected"||e.status==="updated");G.length>0&&V.info({serverName:JZ,command:I.command,targets:G},"[mcp-autoinject] synced bundled MCP server");let c=l.targets.filter(e=>e.status==="skipped");return c.length>0&&V.warn({serverName:JZ,targets:c},"[mcp-autoinject] skipped unmanaged MCP server entries"),l}xa();GI();var UMI="0.6.17";process.on("uncaughtException",I=>{console.error("FATAL: Uncaught exception"),console.error(I),V.fatal(I,"Uncaught exception"),process.exit(1)});process.on("unhandledRejection",I=>{console.error("Unhandled rejection"),console.error(I),V.error(I,"Unhandled rejection")});var BMI=null,CZ=[],xR=null,zR=null;function OMI(I,l,G){return new Promise((c,e)=>{let b=I.listen(l,G);b.once("listening",()=>c(b)),b.once("error",e)})}async function MMI(I,l,G){let c=G||"0.0.0.0";console.log(`[bootstrap] listening on ${c}:${l}`);let e=await OMI(I,l,c);return{primary:e,servers:[e]}}function fMI(){try{return LdI.default.networkInterfaces()}catch{return{}}}function gdI(){return String(process.env.HERMES_DESKTOP||"").trim().toLowerCase()==="true"}function xdI(I){let l=String(process.env[I]||"").trim().toLowerCase();return["1","true","yes","on"].includes(l)}function zdI(){return xdI("HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART")}function jMI(){return xdI("HERMES_WEB_UI_DISABLE_SKILL_INJECTION")}async function KMI(){if(zdI())console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART");else try{await wQ(),console.log("[bootstrap] profile gateways checked")}catch(I){V.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}try{zR=await MQ(),console.log("[bootstrap] agent bridge started")}catch(I){V.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I)}}function SMI(){zdI()?console.log("[bootstrap] profile gateway check disabled by HERMES_WEB_UI_DISABLE_GATEWAY_AUTOSTART"):(async()=>{try{await wQ(),console.log("[bootstrap] profile gateways checked")}catch(I){V.warn(I,"[bootstrap] failed to ensure profile gateways"),console.warn("[bootstrap] failed to ensure profile gateways:",I instanceof Error?I.message:I)}})(),(async()=>{try{zR=await MQ(),console.log("[bootstrap] agent bridge started")}catch(I){V.warn(I,"[bootstrap] agent bridge failed to start"),console.warn("[bootstrap] agent bridge failed to start:",I instanceof Error?I.message:I);return}})()}function TMI(){let I=IS({httpPort:y.port}),l=!1,G=()=>{l||(l=!0,Oo().catch(c=>V.warn(c,"[lan-discovery] initial scan failed")))};I?(I.once("listening",G),setTimeout(G,500).unref?.()):G()}async function UdI(){if(console.log(`hermes-web-ui v${UMI} starting...`),await(0,WJ.mkdir)(y.uploadDir,{recursive:!0}),D9()&&await(0,WJ.mkdir)(y.dataDir,{recursive:!0}),await dx(),jMI())console.log("[bootstrap] bundled skill injection disabled by HERMES_WEB_UI_DISABLE_SKILL_INJECTION");else try{let m=await new xn().injectMissingSkills();m.injected.length>0&&V.info({injected:[...new Set(m.injected)],targetCount:m.targets.length},"[bootstrap] bundled skills injected"),m.updated.length>0&&V.info({updated:[...new Set(m.updated)],targetCount:m.targets.length},"[bootstrap] bundled skills updated")}catch(W){V.warn(W,"[bootstrap] failed to inject bundled skills"),console.warn("[bootstrap] failed to inject bundled skills:",W instanceof Error?W.message:W)}try{await vdI()}catch(W){V.warn(W,"[bootstrap] failed to inject bundled MCP server"),console.warn("[bootstrap] failed to inject bundled MCP server:",W instanceof Error?W.message:W)}gdI()||await KMI();let I=new dL;await new Promise(W=>setTimeout(W,1e3));let{initAllStores:l}=await Promise.resolve().then(()=>(EdI(),ydI));l(),await new Promise(W=>setTimeout(W,1e3)),console.log("[bootstrap] all stores initialized"),I.use(vf()),I.use((0,JdI.default)({origin:Qf(y.corsOrigins)})),I.use(O3({encoding:"utf-8",jsonLimit:"20mb",formLimit:"20mb",textLimit:"20mb",parsedMethods:["POST","PUT","PATCH","DELETE"]})),console.log("[bootstrap] cors + bodyParser registered");let G=EcI(I,[Xf,Hf]);I.use(G),console.log("[bootstrap] routes registered");let c=(0,kdI.resolve)(__dirname,"..","client");I.use((0,CdI.default)(c)),I.use(async W=>{!W.path.startsWith("/api")&&W.path!=="/health"&&W.path!=="/upload"&&W.path!=="/webhook"&&await(0,AdI.default)(W,"index.html",{root:c})}),console.log("[bootstrap] SPA fallback registered");let e=await MMI(I,y.port,y.host);BMI=e.primary,CZ=e.servers,console.log("[bootstrap] app.listen called"),gf(CZ),ej(CZ),mc().setupServer(CZ),console.log("[bootstrap] terminal + kanban + LAN peer websocket setup");let b=new HR(CZ);UD(b),xR=new AR(b.getIO()),cH(xR),xR.init();let{SessionDeleter:d}=await Promise.resolve().then(()=>(yr(),mq)),Z=d.getInstance(),n=process.env.PROFILE||"default";Z.start(n),console.log("[bootstrap] session deleter started, profile=%s",n),CZ.forEach(W=>{W.on("upgrade",(m,s)=>{let N=new URL(m.url||"",`http://${m.headers.host}`);N.pathname!=="/api/hermes/terminal"&&N.pathname!=="/api/hermes/kanban/events"&&N.pathname!==nS()&&!N.pathname.startsWith("/socket.io/")&&s.destroy()})});let t=fMI(),a=Object.values(t).flat().find(W=>W?.family==="IPv4"&&!W?.internal)?.address||"localhost";console.log(`Server: http://localhost:${y.port} (LAN: http://${a}:${y.port})`),console.log(`Log: ${y.appHome}/logs/server.log`),V.info("Server: http://localhost:%d (LAN: http://%s:%d)",y.port,a,y.port),TMI(),GP("bootstrap"),gdI()&&(zR=$e(),SMI()),b.restoreWhenReady(),CZ.forEach(W=>{W.on("error",m=>{console.error("[bootstrap] server error:",m.code||m.message),V.error({err:m},"Server error")})}),KB(CZ,b,xR,zR),fQ()}UdI().catch(I=>{console.error("FATAL: Failed to start Hermes Web UI"),console.error(I),V.fatal(I,"Fatal error during bootstrap"),process.exit(1)});0&&(module.exports={bootstrap});
|
|
1219
1219
|
/*! Bundled license information:
|
|
1220
1220
|
|
|
1221
1221
|
ee-first/index.js:
|
package/package.json
CHANGED