herdr-remote 0.3.34 → 0.3.36
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/README.md +4 -0
- package/README.zh-CN.md +2 -0
- package/dist/chunks/{MHS44P3Y.js → 37NKZLLR.js} +1 -1
- package/dist/chunks/{6M7I477E.js → 4CO2WAXZ.js} +1 -1
- package/dist/chunks/{IRV2W3ZL.js → 54QMQDOL.js} +1 -1
- package/dist/chunks/{S57VTPH5.js → 5RGV2MW6.js} +1 -1
- package/dist/chunks/67FHQKXM.js +6 -0
- package/dist/chunks/{UK7XZS2G.js → B6LZOIKD.js} +1 -1
- package/dist/chunks/{QXMBBOKS.js → CUXGXJMW.js} +1 -1
- package/dist/chunks/{WDPLLWBV.js → D3LUHIKR.js} +1 -1
- package/dist/chunks/{72JMGTAK.js → ETEPTJGZ.js} +2 -2
- package/dist/chunks/GZIFCN7B.js +3 -0
- package/dist/chunks/{FN6VM2O7.js → HDHNFESR.js} +1 -1
- package/dist/chunks/{MLSLOPR7.js → HRFNURKU.js} +1 -1
- package/dist/chunks/{S3V2O6BK.js → IONXNA5T.js} +1 -1
- package/dist/chunks/KEUAW3VO.js +3 -0
- package/dist/chunks/{TSP3KNDA.js → KUDVTWG4.js} +1 -1
- package/dist/chunks/N3C7MVSO.js +3 -0
- package/dist/chunks/{MRXHG2UD.js → NYAKZHLQ.js} +1 -1
- package/dist/chunks/ODOBBR6N.js +9 -0
- package/dist/chunks/{2IM3AVNW.js → PDOEV4QJ.js} +1 -1
- package/dist/chunks/{2RUREFQO.js → QL4I7VLD.js} +1 -1
- package/dist/chunks/{42KARAL4.js → QOPTXTL7.js} +6 -6
- package/dist/chunks/{NY3SVG3W.js → QP6NLV4R.js} +2 -2
- package/dist/chunks/{I6K6O3EE.js → S4TW5MHM.js} +1 -1
- package/dist/chunks/SWVUDSHP.js +3 -0
- package/dist/chunks/{Y5CEFDIU.js → VSBBDPSE.js} +1 -1
- package/dist/chunks/{QRQJLJWT.js → W2FYGFNZ.js} +1 -1
- package/dist/chunks/{ZZOEVJ3V.js → ZAAEQP3M.js} +1 -1
- package/dist/chunks/{W24FRSKQ.js → ZUTRSLCH.js} +1 -1
- package/dist/cli.js +13 -13
- package/dist/connector/admin-broker.js +1 -1
- package/dist/connector/main.js +14 -14
- package/herdr-plugin.toml +2 -2
- package/node_modules/herdr-remote-relay/bin/herdr-remote-relay.js +11 -11
- package/node_modules/herdr-remote-relay/package.json +1 -1
- package/node_modules/herdr-remote-relay/web/dist/assets/{index-CnRQXj8k.js → index-DMbkU5R6.js} +11 -11
- package/node_modules/herdr-remote-relay/web/dist/index.html +1 -1
- package/package.json +2 -2
- package/dist/chunks/3FQAXVGC.js +0 -3
- package/dist/chunks/J427SPKK.js +0 -3
- package/dist/chunks/NKDFWWLU.js +0 -3
- package/dist/chunks/W27D73NQ.js +0 -3
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire as __herdrCreateRequire } from 'node:module';
|
|
2
2
|
const require = __herdrCreateRequire(import.meta.url);
|
|
3
|
-
import{a as y,b as A}from"./chunks/
|
|
3
|
+
import{a as y,b as A}from"./chunks/KEUAW3VO.js";import{f as S,h as w}from"./chunks/5RGV2MW6.js";import"./chunks/U6QAYG3E.js";import{f as m,l as v,n as $,o as k}from"./chunks/37NKZLLR.js";import"./chunks/KRVF37OW.js";import"./chunks/QRGNEKME.js";import"./chunks/SWVUDSHP.js";import{a as d,c as h,d as g}from"./chunks/TNLCNVA2.js";import"./chunks/I6NRCYLI.js";import U from"node:fs";import P from"node:os";import u from"node:path";var j=JSON.parse(U.readFileSync(u.join(d,"package.json"),"utf8")).version,f=`herdr-remote ${j} \u2014 browser access to Herdr workspaces
|
|
4
4
|
|
|
5
5
|
Usage: herdr-remote [command] [options]
|
|
6
6
|
|
|
@@ -26,21 +26,21 @@ Options:
|
|
|
26
26
|
-v, --version Show version
|
|
27
27
|
|
|
28
28
|
Self-hosting: docs/self-hosted-relay.md
|
|
29
|
-
`;function E(
|
|
30
|
-
`)}function b(
|
|
31
|
-
`)}async function B(
|
|
29
|
+
`;function E(r){let s=[],t={};for(let l=0;l<r.length;l+=1){let n=r[l];if(n==="--json"){t.json=!0;continue}if(n==="--daemon"){t.daemon=!0;continue}if(n==="--elevated"){t.elevated=!0;continue}if(n==="--help"||n==="-h"){t.help=!0;continue}if(n==="--version"||n==="-v"){t.version=!0;continue}if(n==="--lang"){t.lang=r[l+1],l+=1;continue}if(n.startsWith("--lang=")){t.lang=n.slice(7);continue}if(n.startsWith("-")){t.unknown=n;continue}s.push(n)}return{positional:s,flags:t}}function o(r){process.stdout.write(`${JSON.stringify(r,null,2)}
|
|
30
|
+
`)}function b(r,s){let t=[];if(t.push(`${s("overview.mode")}: ${s(`mode.${r.mode}`)}`),r.relay.local?t.push(`${s("overview.relay")}: ${r.relay.alive?s("common.running"):s("common.stopped")} (${r.relay.bind}:${r.relay.port})`):t.push(`${s("overview.relay")}: ${r.relay.remoteUrl}`),t.push(`${s("overview.host")}: ${r.host.alive?s("common.running"):s("common.stopped")}`),t.push(`${s("overview.socket")}: ${r.host.socketPath}${r.host.socketExists?"":` (${s("overview.socketMissing")})`}`),t.push(`${s("overview.webUrl")}: ${r.publicUrl}`),r.keepalive){let l=r.keepalive.active?s("common.running"):r.keepalive.installed?s("common.installed"):s("common.notInstalled");t.push(`${s("overview.keepalive")}: ${r.keepalive.manager} \u2014 ${l}`)}return r.relay.health&&r.relay.health.ok===!1&&t.push(`${s("overview.relay")}: ${s("overview.unreachable",{message:r.relay.health.message??""})}`),t.join(`
|
|
31
|
+
`)}async function B(r){let{startTui:s}=await import("./chunks/QP6NLV4R.js");await s(r)}async function O(r=process.argv.slice(2)){if(r[0]==="open-link"){let{runLinkShim:e}=await import("./chunks/67FHQKXM.js");process.exitCode=await e(r.slice(1));return}let{positional:s,flags:t}=E(r);if(process.platform==="win32"){let e=u.relative(d,process.cwd());(e===""||e!==".."&&!e.startsWith(`..${u.sep}`)&&!u.isAbsolute(e))&&process.chdir(P.homedir())}let l=s[0]||null;if(t.help){process.stdout.write(f);return}if(t.version){process.stdout.write(`${j}
|
|
32
32
|
`);return}if(t.unknown){process.stderr.write(`herdr-remote: unknown option "${t.unknown}"
|
|
33
33
|
|
|
34
|
-
${f}`),process.exitCode=2;return}$(),await(await import("./chunks/
|
|
35
|
-
${b(await c.fullStatus(
|
|
36
|
-
`);return}case"stop":{let e=c.stopAll(
|
|
37
|
-
`);return}case"restart":{let e=c.restartAll(
|
|
38
|
-
`);return}case"status":{let e=await c.fullStatus(
|
|
39
|
-
`);return}case"pair":{let e=await
|
|
34
|
+
${f}`),process.exitCode=2;return}$(),await(await import("./chunks/S4TW5MHM.js")).captureTerminalPalette(),(await import("./chunks/CUXGXJMW.js")).captureTerminalFont();let n=k(),C=t.lang&&v.includes(t.lang)?t.lang:n.ui.language,a=A(y({preference:C})),c=await import("./chunks/N3C7MVSO.js"),T=await import("./chunks/GZIFCN7B.js");switch(l){case null:{if(process.stdin.isTTY&&process.stdout.isTTY){await B({language:t.lang||null});return}o(await c.fullStatus(n));return}case"start":{let e=c.startAll(n);t.json?o(e):process.stdout.write(`${a("services.started")}
|
|
35
|
+
${b(await c.fullStatus(n),a)}
|
|
36
|
+
`);return}case"stop":{let e=c.stopAll(n);t.json?o(e):process.stdout.write(`${a("services.stopped")}
|
|
37
|
+
`);return}case"restart":{let e=c.restartAll(n);t.json?o(e):process.stdout.write(`${a("services.restarted")}
|
|
38
|
+
`);return}case"status":{let e=await c.fullStatus(n);t.json?o(e):process.stdout.write(`${b(e,a)}
|
|
39
|
+
`);return}case"pair":{let e=await T.pair();if(t.json){o(e);return}let i=S(e),p=e.pairUrl||`${m(n,w())}/?pairCode=${encodeURIComponent(i)}`,x=`${Math.round((n.auth.pairingTtlMs||6e5)/6e4)}m`;process.stdout.write(`${a("pair.code")}: ${i}
|
|
40
40
|
${a("pair.url")}: ${p}
|
|
41
41
|
${a("pair.expires",{minutes:x,time:new Date(e.expiresAt).toLocaleTimeString()})}
|
|
42
|
-
`);return}case"url":{process.stdout.write(`${m(
|
|
43
|
-
`);return}case"update":{let{runUpdate:e}=await import("./chunks/
|
|
42
|
+
`);return}case"url":{process.stdout.write(`${m(n,w())}
|
|
43
|
+
`);return}case"update":{let{runUpdate:e}=await import("./chunks/VSBBDPSE.js"),i=await e(a,{config:n,...t.json?{report:()=>{}}:{}});t.json&&o(i),i.ok||(process.exitCode=1);return}case"run":{let{runForeground:e}=await import("./chunks/54QMQDOL.js");await e({logToFiles:!!t.daemon});return}case"admin-broker":{let e=await import("./connector/admin-broker.js"),i=s[1]||"status";if(i==="install")e.installAdminBroker(a),o({installed:!0,available:await e.waitForAdminBroker()});else if(i==="uninstall")e.uninstallAdminBroker(a),o({installed:!1});else if(i==="restart"){if(await e.stopAdminBroker()==="busy")throw new Error(a("adminBroker.busy"));e.startAdminBrokerTask(a),o({available:await e.waitForAdminBroker()})}else if(i==="status")o({available:await e.adminBrokerStatus()});else throw new Error(`unknown administrator broker action: ${i}`);return}case"admin-shell":{let{runAdminShell:e}=await import("./chunks/KUDVTWG4.js");process.exitCode=await e(a);return}case"keepalive":{let e=await import("./chunks/NYAKZHLQ.js"),i=s[1]||"status";if(i==="install"&&t.elevated){let{completeServiceInstall:p}=await import("./chunks/D3LUHIKR.js");process.exitCode=await p(a)}else if(i==="install")o(await e.install(n));else if(i==="uninstall")o(await e.uninstall(n));else if(i==="restart")o(e.restart(n));else if(i==="status")o(e.status(n));else throw new Error(`unknown keepalive action: ${i}`);return}case"plugin":{let e=await import("./chunks/ZUTRSLCH.js"),i=s[1]||"status";if(i==="link")o(e.register());else if(i==="unlink")o(e.unregister());else if(i==="status")o(e.registrationStatus());else throw new Error(`unknown plugin action: ${i}`);return}case"config":{o({configPath:g(),stateDir:h(),config:n});return}default:process.stderr.write(`herdr-remote: unknown command "${l}"
|
|
44
44
|
|
|
45
|
-
${f}`),process.exitCode=2}}function M(){O().catch(
|
|
45
|
+
${f}`),process.exitCode=2}}function M(){O().catch(r=>{process.stderr.write(`herdr-remote: ${r.message}
|
|
46
46
|
`),process.exitCode=1})}export{b as describeStatus,E as parseArgs,M as run};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { createRequire as __herdrCreateRequire } from 'node:module';
|
|
2
2
|
const require = __herdrCreateRequire(import.meta.url);
|
|
3
|
-
import{e as a,f as b,g as c,h as d,i as e,j as f,k as g,l as h}from"../chunks/
|
|
3
|
+
import{e as a,f as b,g as c,h as d,i as e,j as f,k as g,l as h}from"../chunks/QOPTXTL7.js";import"../chunks/TNLCNVA2.js";import"../chunks/I6NRCYLI.js";export{d as adminBrokerStatus,a as adminBrokerTaskScript,b as installAdminBroker,h as serveAdminBroker,f as startAdminBrokerTask,e as stopAdminBroker,c as uninstallAdminBroker,g as waitForAdminBroker};
|
package/dist/connector/main.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { createRequire as __herdrCreateRequire } from 'node:module';
|
|
2
2
|
const require = __herdrCreateRequire(import.meta.url);
|
|
3
|
-
import"../chunks/C2UUZY6J.js";import{a as
|
|
4
|
-
`)}this.send({type:"terminal_font",terminalFont:this.publicFont()})}sendChunk(e,t){let r=this.subsetChunk(t.sha256,t.index)||be(this.font,t.sha256,t.index);if(!r){this.send({type:"error",clientId:e,code:"host_font_unavailable",message:
|
|
5
|
-
`),r}catch(r){if(r.code!=="EEXIST")throw r;let n=
|
|
6
|
-
`).find(r=>r.startsWith("0::"));return t!==void 0&&/\.service$/.test(t.trim())}catch{return!1}}function
|
|
7
|
-
${
|
|
8
|
-
`)}start(e){let t=
|
|
9
|
-
`),this.sendError(t,"herdr_not_found",r);return}let n=
|
|
3
|
+
import{c as Se}from"../chunks/ODOBBR6N.js";import"../chunks/C2UUZY6J.js";import{a as Ee,b as ke,d as Ie}from"../chunks/HDHNFESR.js";import"../chunks/KEUAW3VO.js";import{a as _}from"../chunks/QOPTXTL7.js";import{a as u}from"../chunks/7SMZ43LI.js";import{a as pe,b as ye,c as ge,d as I}from"../chunks/JJGEV4EZ.js";import{a as _e,d as M,e as be,i as we}from"../chunks/IONXNA5T.js";import{m as Te}from"../chunks/ZAAEQP3M.js";import"../chunks/U6QAYG3E.js";import"../chunks/HRFNURKU.js";import{b as ae,e as ce,g as T,h as le,i as he,n as de,o as ue,p as k,q as fe,r as me}from"../chunks/ETEPTJGZ.js";import{h as te,i as re,o as se}from"../chunks/37NKZLLR.js";import{b as ie,c as oe}from"../chunks/KRVF37OW.js";import{a as g,d as ne}from"../chunks/QRGNEKME.js";import{a as Y,b as W,c as X,i as q,k as y,l as j,m as J,n as Q,o as Z,p as ee}from"../chunks/SWVUDSHP.js";import{a as G,c as p}from"../chunks/TNLCNVA2.js";import"../chunks/I6NRCYLI.js";import Ut from"node:os";import Be from"node:path";import ve from"node:crypto";import b from"node:fs";import N from"node:path";var Xe=20,qe=50*1024*1024,je=1440*60*1e3;function Ae(){let s=N.join(p(),"pasted");return g(s),s}function v({dir:s=Ae(),maxFiles:e=Xe,maxBytes:t=qe,maxAgeMs:r=je,now:n=Date.now()}={}){let i;try{i=b.readdirSync(s,{withFileTypes:!0})}catch{return}let o=[];for(let h of i){if(!h.isFile())continue;let l=N.join(s,h.name);try{let c=b.statSync(l);if(n-c.mtimeMs>r){try{b.unlinkSync(l)}catch{}continue}o.push({path:l,size:c.size,mtimeMs:c.mtimeMs})}catch{}}o.sort((h,l)=>h.mtimeMs-l.mtimeMs);let a=o.reduce((h,l)=>h+l.size,0);for(;o.length>e||a>t;){let h=o.shift();if(!h)break;try{b.unlinkSync(h.path),a-=h.size}catch{}}}function He({mime:s,dataBase64:e,name:t,dir:r=Ae()}){let n=Z(s)?s:null;if(!n&&s!==j)throw new Error(`unsupported MIME type: ${s}`);if(typeof e!="string")throw new Error("missing or invalid dataBase64 payload");let i=Buffer.from(e,"base64");if(i.length>3145728)throw new Error(`file size (${i.length} bytes) exceeds maximum limit of 3 MB`);if(i.length===0)throw new Error("file payload is empty");if(n&&!ee(n,i))throw new Error(`file magic bytes do not match declared MIME type ${s}`);v({dir:r});let o=n?`${ve.randomUUID()}${Q[n]}`:`${ve.randomUUID()}-${J(t)}`,a=N.join(r,o);b.writeFileSync(a,i,{mode:384,flag:"wx"});try{b.chmodSync(a,384)}catch{}return v({dir:r}),a}var S=["blocked","done","working","idle","unknown"];function Pe(s,e=48){if(typeof s!="string")return null;let t=s.replace(/[\u0000-\u001F\u007F-\u009F]/g," ").replace(/\s+/g," ").trim();return t?t.length>e?t.slice(0,e):t:null}function Je(s){return S.includes(s)?s:"unknown"}function Qe(){return Object.fromEntries(S.map(s=>[s,0]))}function Fe(s){let e=Array.isArray(s?.agents)?s.agents:[],t=Array.isArray(s?.panes)?s.panes:[],r=typeof s?.focused_pane_id=="string"&&s.focused_pane_id?s.focused_pane_id:null,n=(r?t.find(c=>c?.pane_id===r):t.find(c=>c?.focused===!0))||null,i=(r?e.find(c=>c?.pane_id===r):e.find(c=>c?.focused===!0))||null,o=r||(typeof n?.pane_id=="string"?n.pane_id:null)||(typeof i?.pane_id=="string"?i.pane_id:null),a=typeof n?.agent=="string"?n.agent:typeof i?.agent=="string"?i.agent:null,h=Qe(),l=[];for(let c of e){if(!c||typeof c.pane_id!="string")continue;let d=Je(c.agent_status);h[d]+=1,l.push({paneId:c.pane_id,workspaceId:typeof c.workspace_id=="string"?c.workspace_id:null,agent:Pe(c.display_agent||c.agent,24),title:Pe(c.terminal_title_stripped||c.terminal_title),status:d,focused:c.focused===!0})}return l.sort((c,d)=>S.indexOf(c.status)-S.indexOf(d.status)),{focusedPaneId:o,focusedAgent:a,counts:h,total:l.length,agents:l.slice(0,16)}}function Oe(s,e){if(!s||!e)return s===e;if(s.focusedPaneId!==e.focusedPaneId||s.focusedAgent!==e.focusedAgent||s.total!==e.total)return!1;for(let t of S)if((s.counts?.[t]||0)!==(e.counts?.[t]||0))return!1;return s.agents.length!==e.agents.length?!1:s.agents.every((t,r)=>{let n=e.agents[r];return n&&t.paneId===n.paneId&&t.status===n.status&&t.agent===n.agent&&t.title===n.title})}var Ze=5e3,et=150,tt=[{type:"pane.focused"},{type:"tab.focused"},{type:"workspace.focused"},{type:"pane.agent_detected"}],A=class{socketPath;request;subscribe;send;pollTimer=null;debounceTimer=null;subscription=null;pending=!1;stale=!1;lastSummary=null;constructor(e,t){this.socketPath=e.socketPath,this.request=e.requestHerdr||Ee,this.subscribe=e.subscribeHerdr||ke,this.send=t}start(){if(!this.pollTimer){this.pollTimer=setInterval(()=>this.read(),Ze),this.pollTimer.unref?.();try{this.subscription=this.subscribe(this.socketPath,tt,()=>this.scheduleRead(),{onStarted:()=>this.scheduleRead()})}catch{}this.read()}}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null),this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.subscription&&(this.subscription.close(),this.subscription=null),this.stale=!1,this.lastSummary=null}scheduleRead(){this.pollTimer&&(this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.read()},et),this.debounceTimer.unref?.())}async read(){if(!this.pollTimer)return;if(this.pending){this.stale=!0;return}this.pending=!0,this.stale=!1;let e;try{let r=await this.request(this.socketPath,"session.snapshot",{});e=r?.snapshot||r}catch{return}finally{this.pending=!1,this.stale&&this.scheduleRead()}if(!this.pollTimer)return;let t=Fe(e);Oe(this.lastSummary,t)||(this.lastSummary=t,this.send({type:"agent_status",...t}))}};import ct from"node:crypto";import lt from"node:fs";import{createRequire as rt}from"node:module";import D from"node:fs";import st from"node:path";var nt=6e4,it=16384,ot=1,R=null;function at(){if(!R){let s=st.join(G,"dist","harfbuzz-subset.wasm"),e=D.existsSync(s)?s:rt(import.meta.url).resolve("harfbuzzjs/dist/harfbuzz-subset.wasm");R=new WebAssembly.Module(D.readFileSync(e))}return R}var H=class{idleMs;instance=null;faces=new Map;idleTimer=null;constructor({idleMs:e=nt}={}){this.idleMs=e}exports(){return this.instance||(this.instance=new WebAssembly.Instance(at(),{}).exports,this.instance._initialize()),this.instance}face(e){let t=`${e.path}\0${e.index||0}`,r=this.faces.get(t);if(r)return r.face;let n=this.exports(),i=D.readFileSync(e.path),o=n.malloc(i.length);if(!o)throw new Error("out of memory loading font");new Uint8Array(n.memory.buffer).set(i,o);let a=n.hb_blob_create(o,i.length,ot,0,0),h=n.hb_face_create(a,e.index||0);return n.hb_blob_destroy(a),this.faces.set(t,{pointer:o,face:h}),h}subset(e,t){let r=this.exports(),n=this.face(e),i=r.hb_subset_input_create_or_fail();if(!i)throw new Error("font subsetting is unavailable");let o=0,a=0;try{let h=r.hb_subset_input_unicode_set(i);for(let d of t.slice(0,it))r.hb_set_add(h,d);if(a=r.hb_subset_or_fail(n,i),!a)throw new Error("the font could not be subset");o=r.hb_face_reference_blob(a);let l=r.hb_blob_get_length(o),c=r.hb_blob_get_data(o,0);return Buffer.from(new Uint8Array(r.memory.buffer,c,l))}finally{o&&r.hb_blob_destroy(o),a&&r.hb_face_destroy(a),r.hb_subset_input_destroy(i),this.scheduleRelease()}}scheduleRelease(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>this.release(),this.idleMs),this.idleTimer.unref?.()}release(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=null,this.faces.clear(),this.instance=null}};var ht=48*1024*1024,Le="The terminal font changed or is no longer on this workstation",F=class{font;load;subsetter;subsets=new Map;send;constructor(e,t){this.load=e.loadTerminalFont||we,this.font=e.terminalFont!==void 0?e.terminalFont:this.load(),this.subsetter=e.fontSubsetter||new H,this.send=t}publicFont(){return M(this.font)}pickUp(){if(this.font)return;let e=null;try{e=this.load()}catch{return}e&&(this.font=e,this.send({type:"terminal_font",terminalFont:M(e)}))}refresh(){try{let e=this.load({refresh:!0});e&&(this.font=e)}catch(e){process.stderr.write(`herdr-remote host connector: could not read the terminal font: ${e.message}
|
|
4
|
+
`)}this.send({type:"terminal_font",terminalFont:this.publicFont()})}sendChunk(e,t){let r=this.subsetChunk(t.sha256,t.index)||be(this.font,t.sha256,t.index);if(!r){this.send({type:"error",clientId:e,code:"host_font_unavailable",message:Le});return}this.send({type:"host_font_chunk",clientId:e,sha256:t.sha256,index:t.index,total:r.total,dataBase64:r.data.toString("base64")})}sendSubset(e,t){let r=(l,c)=>this.send({type:"error",clientId:e,code:l,message:c}),n=this.font?.subsets?.find(l=>l.sha256===t.sha256);if(!n||!this.unchanged(n)){r("host_font_unavailable",Le);return}let i=[...new Set(Array.from(String(t.text||""),l=>l.codePointAt(0)))],o;try{o=this.subsetter.subset(n,i)}catch(l){r("host_font_subset_failed",l.message||"The font could not be subset");return}let a=ct.createHash("sha256").update(o).digest("hex"),h={type:"host_font_subset_ready",clientId:e,requestId:t.requestId,sha256:n.sha256,subsetSha:a,bytes:o.length};o.length<=262144?h.dataBase64=o.toString("base64"):this.hold(a,o),this.send(h)}unchanged(e){try{let t=lt.statSync(e.path);return t.size===e.bytes&&t.mtimeMs===e.mtimeMs}catch{return!1}}hold(e,t){this.subsets.delete(e),this.subsets.set(e,t);let r=[...this.subsets.values()].reduce((n,i)=>n+i.length,0);for(let[n,i]of this.subsets){if(r<=ht||n===e)break;this.subsets.delete(n),r-=i.length}}subsetChunk(e,t){let r=this.subsets.get(e);if(!r)return null;let n=Math.ceil(r.length/262144);if(!Number.isInteger(t)||t<0||t>=n)return null;let i=t*262144;return{data:r.subarray(i,i+262144),total:n}}};import ft from"node:os";import dt from"node:fs";var Ce=["ctrl+b"];function xe(s=process.env,e=process.platform){let t;try{t=dt.readFileSync(pe(s,e),"utf8")}catch{return[...Ce]}let r=_e(t)["keys.prefix"];return q(typeof r=="string"?[r]:r)??[...Ce]}function Me(s){return{type:"host_hello",protocol:1,hostId:s.hostId,token:s.token,password:s.password||null,hostname:ft.hostname(),platform:process.platform,...process.platform==="win32"&&(process.env.MSYSTEM||/(?:^|[\\/])(?:bash|sh)(?:\.exe)?$/i.test(process.env.SHELL||""))?{shellProfile:"git-bash"}:{},arch:process.arch,version:s.version,terminalPalette:s.terminalPalette||null,terminalFont:s.terminalFont,herdrPrefixKeys:xe(),capabilities:[y.hostHandoff,y.idleHeartbeat,y.binaryFrameV2,y.pasteAnyFile,...process.platform==="win32"?[y.adminTabs]:[]]}}import w from"node:fs";import mt from"node:path";function Re(s){try{return JSON.parse(w.readFileSync(s,"utf8"))}catch{return null}}function Ne(s,e){let t=new Error(s);return t.code=e,t}function De(s,e){g(mt.dirname(s));for(let t=0;t<2;t+=1)try{let r=w.openSync(s,"wx",384);return w.writeFileSync(r,`${JSON.stringify({pid:process.pid,processStart:ie(process.pid),hostId:e,startedAt:new Date().toISOString()})}
|
|
5
|
+
`),r}catch(r){if(r.code!=="EEXIST")throw r;let n=Re(s);if(n&&oe([n]).length>0)throw Ne(`another host connector is already running (pid ${n.pid})`,"HOST_ALREADY_RUNNING");try{w.rmSync(s,{force:!0})}catch{}}throw Ne("could not acquire host connector lock","HOST_LOCK_FAILED")}function Ue(s,e){try{w.closeSync(e)}catch{}let t=Re(s);if(!(t&&t.pid!==process.pid))try{w.rmSync(s,{force:!0})}catch{}}import O from"node:fs";import pt from"node:net";import yt from"node:path";import{spawn as gt,spawnSync as _t}from"node:child_process";var bt=1e3,wt=2e4,Tt=200,St=["EPERM","EACCES"],Et="0.9.4",kt=/S-1-16-(?:12288|16384)\b/;function It(s,e){return e!=="win32"||!St.includes(s.code||"")?{state:"unavailable",reason:s.message}:{state:"unavailable",elevated:!0,reason:`Herdr is running as administrator and refuses clients that are not. Start Herdr from an ordinary terminal, or set allow_unelevated_clients = true under [server] in its config.toml and restart its server. (${s.message})`}}function U(s,{connect:e=pt.connect,timeout:t=bt,platform:r=process.platform}={}){let n=I(s);return n.ok?new Promise(i=>{let o,a=l=>{clearTimeout(h),o&&(o.removeAllListeners(),o.on("error",()=>{}),o.destroy()),i(l)},h=setTimeout(()=>a({state:"running"}),t);typeof h.unref=="function"&&h.unref(),o=e(ye(s,r)),o.once("connect",()=>a({state:"running"})),o.once("error",l=>a(l.code==="ECONNREFUSED"||l.code==="ENOENT"?{state:"stopped",stale:!0}:It(l,r)))}):Promise.resolve(n.missing?{state:"stopped"}:{state:"unavailable",reason:n.reason})}function vt({platform:s=process.platform,readCgroup:e=()=>O.readFileSync("/proc/self/cgroup","utf8")}={}){if(s!=="linux")return!1;try{let t=e().split(`
|
|
6
|
+
`).find(r=>r.startsWith("0::"));return t!==void 0&&/\.service$/.test(t.trim())}catch{return!1}}function At({platform:s=process.platform,whoamiGroups:e=()=>_t("whoami",["/groups","/fo","csv","/nh"],{encoding:"utf8",windowsHide:!0}).stdout||""}={}){if(s!=="win32")return!1;try{return kt.test(e())}catch{return!1}}function Ht(s,e=At()){if(!e)return!1;let{version:t}=k({command:s});return t!==null&&T(t,Et)>=0}function Pt(s,e=process.env){let t={...e};for(let r of Object.keys(t))r.startsWith("HERDR_")&&delete t[r];return s&&(t.HERDR_SOCKET_PATH=s),t}function Ft({command:s,args:e=[],inService:t=vt(),allowUnelevated:r=!1}){let n=[s,...e,"server",...r?["--allow-unelevated-clients"]:[]];return t?{file:"systemd-run",args:["--user","--scope","--quiet","--collect","--description=Herdr server started by herdr-remote","--",...n]}:{file:n[0],args:n.slice(1)}}function Ot({command:s,args:e=[],socketPath:t,cwd:r,logPath:n,spawnProcess:i=gt,inService:o,allowUnelevated:a=Ht(s)}){let{file:h,args:l}=Ft({command:s,args:e,inService:o,allowUnelevated:a});g(yt.dirname(n));let c=O.openSync(n,"a"),d;try{d=i(h,l,{cwd:r,env:Pt(t),detached:!0,windowsHide:!0,stdio:["ignore",c,c]})}finally{O.closeSync(c)}return d.on("error",()=>{}),d.unref(),d}function Lt(s,e=2e3){try{return O.readFileSync(s,"utf8").slice(-e).trim()}catch{return""}}async function $e({command:s,args:e=[],socketPath:t,cwd:r,logPath:n,probe:i=U,launch:o=Ot,timeout:a=wt,interval:h=Tt}){let l=await i(t);if(l.state==="running")return{started:!1};if(l.state==="unavailable")throw new Error(`Herdr socket at ${t} cannot be used: ${l.reason}`);let c=o({command:s,args:e,socketPath:t,cwd:r,logPath:n}),d=null;c.once("exit",(z,E)=>{d={code:z,signal:E}});let Ge=Date.now()+a;for(;;){if(await new Promise(Ye=>setTimeout(Ye,h)),(await i(t)).state==="running")return{started:!0};let E=Lt(n),K=E?`
|
|
7
|
+
${E}`:"";if(d)throw new Error(`Herdr server exited (${d.signal||`code ${d.code}`}) before opening ${t}.${K}`);if(Date.now()>=Ge)throw new Error(`Herdr server did not open ${t} within ${Math.round(a/1e3)}s.${K}`)}}function m(s,e){s&&s.readyState===u.default.OPEN&&s.send(JSON.stringify(e))}function Ve(s,e="host connector stopping"){if(!(!s||s.readyState===u.default.CLOSED||s.readyState===u.default.CLOSING))try{s.close(1e3,e)}catch{}}function $(s){if(!s||s.readyState===u.default.CLOSED)return;let e=s;try{typeof e.terminate=="function"?e.terminate():typeof e.destroy=="function"?e.destroy():e.close?.()}catch{}}function f(s){let e=s.clientId||s.streamId;return typeof e=="string"&&e?e:null}var xt=1500,Mt=4,Nt=3,L=class{byStream=new Map;streamIndexToId=new Map;waitingForHerdr=new Map;probingStarts=new Map;herdrLaunch=null;herdrVersionWarned=!1;fastFailures=0;herdrCommand;herdrArgs;socketPath;cwd;herdrLookup;herdrLogPath;readHerdrVersion;Pty;probeHerdr;ensureHerdr;clientEnv;link;constructor(e,t){this.socketPath=e.socketPath,this.herdrLookup=e.herdrLookup||{},this.herdrCommand=e.herdrCommand||de(this.herdrLookup),this.herdrArgs=e.herdrArgs,this.cwd=e.cwd,this.herdrLogPath=e.herdrLogPath,this.readHerdrVersion=e.readHerdrVersion||k,this.Pty=e.PtySession||_,this.probeHerdr=e.probeHerdr||U,this.ensureHerdr=e.ensureHerdr||$e,this.clientEnv=e.clientEnv||(()=>({})),this.link=t}sendError(e,t,r){this.link.send({type:"error",clientId:e,code:t,message:r})}ensureHerdrCommand(){let e=ue(this.herdrCommand,this.herdrLookup);return e.found?(this.herdrCommand=e.command,this.warnIfHerdrOutdated(),null):me(this.herdrLookup)}warnIfHerdrOutdated(){if(this.herdrVersionWarned)return;let e=this.readHerdrVersion({command:this.herdrCommand});if(e.supported){e.version&&(this.herdrVersionWarned=!0);return}this.herdrVersionWarned=!0,process.stderr.write(`herdr-remote host connector: ${fe(e.version)}
|
|
8
|
+
`)}start(e){let t=f(e);if(!t)return;this.stop(t);let r=this.ensureHerdrCommand();if(r){process.stderr.write(`herdr-remote host connector: ${r}
|
|
9
|
+
`),this.sendError(t,"herdr_not_found",r);return}let n=I(this.socketPath);if(!n.ok&&!n.missing){this.sendError(t,"herdr_socket_unavailable",n.reason);return}if(!n.ok){this.waitForHerdr(t,e);return}let i={message:e};return this.probingStarts.set(t,i),this.probeHerdr(this.socketPath).then(o=>{this.probingStarts.get(t)===i&&(this.probingStarts.delete(t),o.state==="running"?this.spawn(i.message):o.state==="stopped"?this.waitForHerdr(t,i.message):this.sendError(t,o.elevated?"herdr_elevated":"herdr_socket_unavailable",o.reason))})}waitForHerdr(e,t){this.waitingForHerdr.set(e,t),this.sendError(e,"herdr_not_running",`Herdr is not running on this workstation (${this.socketPath}).`)}startHerdr(){return this.herdrLaunch||(this.herdrLaunch=Promise.resolve().then(()=>{let e=this.ensureHerdrCommand();if(e)throw new Error(e);return this.ensureHerdr({command:this.herdrCommand,args:this.herdrArgs,socketPath:this.socketPath,cwd:this.cwd,logPath:this.herdrLogPath})}).finally(()=>{this.herdrLaunch=null})),this.herdrLaunch}async startHerdrFor(e){try{(await this.startHerdr()).started&&process.stderr.write(`herdr-remote host connector: started Herdr at a browser's request
|
|
10
10
|
`)}catch(r){let{message:n}=r;process.stderr.write(`herdr-remote host connector: could not start Herdr: ${n}
|
|
11
|
-
`),e&&this.sendError(e,"herdr_start_failed",n);return}let t=[...this.waitingForHerdr.values()];this.waitingForHerdr.clear();for(let r of t)this.spawn(r)}spawn(e){let t=
|
|
12
|
-
`),this.sendError(r,"herdr_start_failed",o)}write(e,t){let r=e.streamIndex!==void 0?this.streamIndexToId.get(e.streamIndex):e.streamId;r&&this.byStream.get(r)?.pty.write(t)}resize(e){let t=
|
|
13
|
-
`)})}stop(){this.stopping=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,m(this.ws,{type:"host_shutdown"}),this.disconnected()
|
|
11
|
+
`),e&&this.sendError(e,"herdr_start_failed",n);return}let t=[...this.waitingForHerdr.values()];this.waitingForHerdr.clear();for(let r of t)this.spawn(r)}spawn(e){let t=f(e),r=typeof e.streamIndex=="number"?e.streamIndex:null,n=new this.Pty({command:this.herdrCommand,args:this.herdrArgs,cwd:this.cwd,socketPath:this.socketPath,env:this.clientEnv(t)}),i={id:t,streamIndex:r,pty:n,cols:Number(e.cols)||_.DEFAULT_COLS,rows:Number(e.rows)||_.DEFAULT_ROWS,createdAt:new Date().toISOString(),startedAtMs:Date.now(),pendingOutput:[],flushImmediate:null,flushTimeout:null},o=()=>{if(i.flushImmediate&&(clearImmediate(i.flushImmediate),i.flushImmediate=null),i.flushTimeout&&(clearTimeout(i.flushTimeout),i.flushTimeout=null),i.pendingOutput.length===0)return;let a=Buffer.concat(i.pendingOutput);i.pendingOutput=[],this.link.sendFrame(i.streamIndex!==null?W(0,i.streamIndex,a):Y("output",t,a))};try{n.start({cols:i.cols,rows:i.rows,onData:a=>{let h=Buffer.isBuffer(a)?a:Buffer.from(a,"utf8");h.length!==0&&(i.pendingOutput.push(h),!i.flushImmediate&&!i.flushTimeout&&(process.platform==="win32"?i.flushTimeout=setTimeout(o,Mt):i.flushImmediate=setImmediate(o)))},onExit:({exitCode:a})=>{this.byStream.get(t)===i&&(this.forget(i),this.reportExit(i,a),this.link.changed())}})}catch(a){V(i),this.sendError(t,"pty_start_failed",a.message),n.kill();return}this.byStream.set(t,i),r!==null&&this.streamIndexToId.set(r,t),this.link.send({type:"session_ready",clientId:t}),this.link.changed()}reportExit(e,t){let r=e.id,n=Date.now()-e.startedAtMs,i=t!==0&&n<xt;if(this.fastFailures=i?this.fastFailures+1:0,this.fastFailures<Nt){this.link.send({type:"session_exit",clientId:r,code:t});return}let o=`"${this.herdrCommand}" exited immediately with code ${t} on ${this.fastFailures} attempts in a row. Check that it runs from a terminal, and see the host connector log for what it printed.`;process.stderr.write(`herdr-remote host connector: ${o}
|
|
12
|
+
`),this.sendError(r,"herdr_start_failed",o)}write(e,t){let r=e.streamIndex!==void 0?this.streamIndexToId.get(e.streamIndex):e.streamId;r&&this.byStream.get(r)?.pty.write(t)}resize(e){let t=f(e);if(!t)return;let r=this.waitingForHerdr.get(t)||this.probingStarts.get(t)?.message;r&&(Number.isInteger(e.cols)&&(r.cols=e.cols),Number.isInteger(e.rows)&&(r.rows=e.rows));let n=this.byStream.get(t);n&&(Number.isInteger(e.cols)&&(n.cols=_.clampDimension(e.cols,0)),Number.isInteger(e.rows)&&(n.rows=_.clampDimension(e.rows,0)),n.pty.resize(n.cols,n.rows))}stop(e){this.waitingForHerdr.delete(e),this.probingStarts.delete(e);let t=this.byStream.get(e);t&&(this.forget(t),t.pty.kill(),this.link.changed())}stopAll(){for(let e of this.byStream.values())V(e),e.pty.kill();this.byStream.clear(),this.streamIndexToId.clear(),this.waitingForHerdr.clear(),this.probingStarts.clear()}summaries(){return[...this.byStream.values()].map(e=>({id:e.id,pid:e.pty.terminal?.pid||null,command:e.pty.command,cols:e.cols,rows:e.rows,cwd:e.pty.cwd,createdAt:e.createdAt,activeClients:1}))}forget(e){this.byStream.delete(e.id),e.streamIndex!==null&&this.streamIndexToId.delete(e.streamIndex),V(e)}};function V(s){s.flushImmediate&&(clearImmediate(s.flushImmediate),s.flushImmediate=null),s.flushTimeout&&(clearTimeout(s.flushTimeout),s.flushTimeout=null),s.pendingOutput=[]}var Rt=6e4,C=class{checkUpdate;readInstalledVersion;runningVersion;send;checkedAt=0;pending=null;constructor(e,t){this.checkUpdate=e.checkUpdate!==void 0?e.checkUpdate:ce()?le:null,this.readInstalledVersion=e.readInstalledVersion||he,this.runningVersion=e.runningVersion||ae(),this.send=t}report({now:e=Date.now()}={}){let t=this.checkUpdate;return!t||this.pending?this.pending:e-this.checkedAt<Rt?null:(this.checkedAt=e,this.pending=Promise.resolve().then(()=>t()).then(r=>{if(!r?.ok||!r.latest)return;let n=this.runningVersion,i=this.readInstalledVersion()||n;this.send({type:"update_status",current:n,installed:i,latest:r.latest,updateAvailable:T(r.latest,n)>0,restartPending:T(i,n)>0,updateCommand:!0})}).catch(()=>{}).finally(()=>{this.pending=null}),this.pending)}};var $t=["relay_password_required","host_auth_failed","invalid_host_credentials"],x=class{config;relayUrl;hostId;hostToken;relayPassword;socketPath;terminalPalette;sessions;font;agents;updates;links;ws=null;reconnectTimer=null;heartbeatTimer=null;keepaliveTimer=null;reconnectAttempts=0;clientCount=0;legacyHeartbeat=!1;authFailure=!1;stopping=!1;lockPath;lockFd=null;onFatal;constructor(e={}){let t=e.config||se();this.config=t,this.relayUrl=e.relayUrl||(process.env.RELAY_URL?re(process.env.RELAY_URL):te(t)),this.hostId=e.hostId||process.env.RELAY_HOST_ID||`host-${ne(9)}`,this.hostToken=e.hostToken||process.env.RELAY_HOST_TOKEN||"",this.relayPassword=e.relayPassword??process.env.RELAY_PASSWORD??"",this.socketPath=e.socketPath||ge(t.herdr.socketPath),this.terminalPalette=e.terminalPalette!==void 0?e.terminalPalette:Te();let r=n=>m(this.ws,n);this.sessions=new L({...e,socketPath:this.socketPath,herdrArgs:e.herdrArgs||t.herdr.args,cwd:e.cwd||t.herdr.cwd,herdrLogPath:e.herdrLogPath||Be.join(p(),"herdr-server.log"),clientEnv:n=>this.links.env(n)},{send:r,sendFrame:n=>{this.ws?.readyState===u.default.OPEN&&this.ws.send(n)},changed:()=>this.sendHeartbeat()}),this.font=new F(e,r),this.agents=new A({...e,socketPath:this.socketPath},r),this.updates=new C(e,r),this.links=new Se({directory:p(),...e.links},r,n=>this.sessions.byStream.has(n)),this.lockPath=e.lockPath||process.env.HERDR_REMOTE_HOST_LOCK||Be.join(p(),"host-connector.lock"),this.onFatal=e.onFatal||(n=>process.exit(n));try{v()}catch{}}acquireLock(){this.lockFd===null&&(this.lockFd=De(this.lockPath,this.hostId))}releaseLock(){this.lockFd!==null&&(Ue(this.lockPath,this.lockFd),this.lockFd=null)}start(){if(!this.hostToken)throw new Error("RELAY_HOST_TOKEN is required");this.acquireLock(),this.stopping=!1,this.connect(),this.config.herdr?.autoStart&&this.sessions.startHerdr().catch(e=>{process.stderr.write(`herdr-remote host connector: could not start Herdr: ${e.message}
|
|
13
|
+
`)})}stop(){this.stopping=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,m(this.ws,{type:"host_shutdown"}),this.disconnected(),Ve(this.ws,"host_shutdown"),this.ws=null,this.links.stop(),this.releaseLock()}disconnected(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,this.stopKeepalive(),this.agents.stop(),this.clientCount=0,this.legacyHeartbeat=!1,this.links.setRelayCapabilities(void 0),this.sessions.stopAll()}connect(){if(this.stopping||this.ws?.readyState===u.default.OPEN||this.ws?.readyState===u.default.CONNECTING)return;this.stopKeepalive();let e;try{e=new u.default(this.relayUrl)}catch(t){this.scheduleReconnect(t);return}this.ws=e,e.isAlive=!0,e.on("open",()=>{try{e._socket?.setNoDelay(!0)}catch{}e.isAlive=!0,this.authFailure=!1,m(e,Me({hostId:this.hostId,token:this.hostToken,password:this.relayPassword,version:this.updates.runningVersion,terminalPalette:this.terminalPalette,terminalFont:this.font.publicFont()}))}),e.on("pong",()=>{e.isAlive=!0}),e.on("message",(t,r)=>this.handleMessage(t,r)),e.on("close",(t,r)=>{if(this.ws!==e)return;if(this.ws=null,this.disconnected(),(r?r.toString():"")==="host_replaced"){process.stderr.write(`herdr-remote host connector: another instance took over this workstation; exiting
|
|
14
14
|
`),this.stop(),this.onFatal(12);return}if(this.authFailure){this.stopping=!0,process.stderr.write(`herdr-remote host connector: authentication failed; update relay credentials and restart the service
|
|
15
15
|
`),this.releaseLock(),this.onFatal(13);return}this.scheduleReconnect()}),e.on("error",t=>{process.stderr.write(`herdr-remote host connector: ${t.message}
|
|
16
16
|
`)})}scheduleReconnect(e=null){if(this.stopping||this.reconnectTimer)return;e&&process.stderr.write(`herdr-remote host connector: ${e.message}
|
|
17
|
-
`);let t=Math.min(3e4,500*1.5**this.reconnectAttempts+Math.floor(Math.random()*250));this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},t)}handleMessage(e,t=!1){if(t){this.handleFrame(e);return}let r;try{r=JSON.parse(typeof e=="string"?e:e.toString("utf8"))}catch{return}switch(r.type){case"error":if(r.clientId)return;this.authFailure
|
|
18
|
-
`);return;case"host_ready":this.hostReady(r);return;case"client_count":this.setClientCount(r.clientCount);return;case"session_start":return this.startSession(r);case"herdr_start":return this.sessions.startHerdrFor(
|
|
19
|
-
`);return}t.type==="input"&&this.sessions.write(t.version===2?{streamIndex:t.streamIndex}:{streamId:t.streamId},t.payload)}hostReady(e){if(this.reconnectAttempts=0,this.startKeepalive(),Object.hasOwn(e,"clientCount")){this.legacyHeartbeat=!1,this.setClientCount(e.clientCount);return}this.legacyHeartbeat=!0,this.sendHeartbeat(!0),this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.config.cleanup.heartbeatIntervalMs)}startSession(e){if(
|
|
20
|
-
`),process.exitCode=e==="HOST_ALREADY_RUNNING"?12:1}var
|
|
17
|
+
`);let t=Math.min(3e4,500*1.5**this.reconnectAttempts+Math.floor(Math.random()*250));this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},t)}handleMessage(e,t=!1){if(t){this.handleFrame(e);return}let r;try{r=JSON.parse(typeof e=="string"?e:e.toString("utf8"))}catch{return}switch(r.type){case"error":if(r.clientId)return;this.authFailure=$t.includes(r.code),process.stderr.write(`herdr-remote host connector: relay rejected the connection: ${r.message||r.code}
|
|
18
|
+
`);return;case"host_ready":this.hostReady(r);return;case"client_count":this.setClientCount(r.clientCount);return;case"session_start":return this.startSession(r);case"herdr_start":return this.sessions.startHerdrFor(f(r));case"admin_tab_open":return Ie(f(r),{socketPath:this.socketPath,language:this.config.ui?.language,send:n=>m(this.ws,n)});case"session_stop":{let n=f(r);n&&this.sessions.stop(n);return}case"resize":this.sessions.resize(r);return;case"paste_file":this.savePaste(f(r),r);return;case"host_font_chunk_request":this.font.sendChunk(f(r),r);return;case"host_font_subset_request":this.font.sendSubset(f(r),r);return;case"host_font_refresh":this.font.refresh();return;default:return}}handleFrame(e){let t;try{t=X(e)}catch(r){process.stderr.write(`herdr-remote host connector: invalid relay frame: ${r.message}
|
|
19
|
+
`);return}t.type==="input"&&this.sessions.write(t.version===2?{streamIndex:t.streamIndex}:{streamId:t.streamId},t.payload)}hostReady(e){if(this.reconnectAttempts=0,this.startKeepalive(),this.links.setRelayCapabilities(e.capabilities),Object.hasOwn(e,"clientCount")){this.legacyHeartbeat=!1,this.setClientCount(e.clientCount);return}this.legacyHeartbeat=!0,this.sendHeartbeat(!0),this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.config.cleanup.heartbeatIntervalMs)}startSession(e){if(f(e))return this.updates.report(),this.font.pickUp(),this.sessions.start(e)}savePaste(e,t){try{let r=He({mime:t.mime,dataBase64:t.dataBase64,name:t.name});m(this.ws,{type:"paste_file_ready",clientId:e,path:r})}catch(r){m(this.ws,{type:"error",clientId:e,code:"paste_file_write_failed",message:r.message||"Failed to save pasted file"})}}startKeepalive(){if(this.stopKeepalive(),!this.ws||this.stopping)return;this.ws.isAlive=!0;let e=this.config?.cleanup?.heartbeatIntervalMs||3e4;this.keepaliveTimer=setInterval(()=>this.tickKeepalive(),e)}stopKeepalive(){this.keepaliveTimer&&(clearInterval(this.keepaliveTimer),this.keepaliveTimer=null)}tickKeepalive(){let e=this.ws;if(!(!e||this.stopping)){if(e.readyState===u.default.CLOSING){$(e);return}if(e.readyState===u.default.OPEN){if(!e.isAlive){$(e);return}e.isAlive=!1;try{typeof e.ping=="function"&&e.ping()}catch{}this.clientCount<=0&&!this.legacyHeartbeat&&m(e,{type:"heartbeat",load:{},ptys:[]})}}}setClientCount(e){let t=Number.isInteger(e)?Math.max(0,e):0;if(t===this.clientCount&&(t===0||this.heartbeatTimer))return;let r=this.clientCount>0;this.clientCount=t,this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null,t>0?(this.sendHeartbeat(!0),this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.config.cleanup.heartbeatIntervalMs)):r&&this.sendHeartbeat(!0),t>0&&!this.stopping?this.agents.start():this.agents.stop()}sendHeartbeat(e=!1){if(!e&&this.clientCount<=0&&!this.legacyHeartbeat)return;let t=process.memoryUsage(),r=Ut.loadavg();m(this.ws,{type:"heartbeat",load:{load1m:r[0]||0,load5m:r[1]||0,load15m:r[2]||0,rssBytes:t.rss,heapUsedBytes:t.heapUsed},ptys:this.sessions.summaries()})}};var ze=new x({onFatal:s=>process.exit(s)});try{ze.start()}catch(s){let{code:e,message:t}=s;process.stderr.write(`herdr-remote host connector failed: ${t}
|
|
20
|
+
`),process.exitCode=e==="HOST_ALREADY_RUNNING"?12:1}var Ke=()=>{ze.stop(),process.exit(0)};process.once("SIGINT",Ke);process.once("SIGTERM",Ke);
|
package/herdr-plugin.toml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
id = "herdr.remote.web"
|
|
2
2
|
name = "Herdr Remote Web"
|
|
3
|
-
version = "0.3.
|
|
4
|
-
min_herdr_version = "0.9.
|
|
3
|
+
version = "0.3.36"
|
|
4
|
+
min_herdr_version = "0.9.5"
|
|
5
5
|
description = "Browser access to Herdr workspaces via local or self-hosted relay"
|
|
6
6
|
platforms = ["linux", "macos", "windows"]
|
|
7
7
|
|