grix-connector 4.6.7 → 4.6.9

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.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "bridgeVersion": "4.6.7",
4
- "tarball": "grix-dsh-bridge-4.6.7.tgz",
3
+ "bridgeVersion": "4.6.9",
4
+ "tarball": "grix-dsh-bridge-4.6.9.tgz",
5
5
  "size": 23091,
6
6
  "unpackedSize": 92668,
7
- "shasum": "3f4850cd8bf049b0ae74e903c7f6b490df2546d7",
8
- "integrity": "sha512-13RZFWVRBcXfgG53K5jL0KvDeZ/p0hPWGUraqAr754AX1b0x2GT1En2i7mUsj1qLWnkd/5jvAsohngJoAagodA=="
7
+ "shasum": "689c038f63bf0e004e1db914f1a3572848a9413c",
8
+ "integrity": "sha512-tJPtUS4lO/bVn6nJBBVZwZCrM8pf1/zpmlLS18ZQYGsuaogGY0NPXCllZZcm/uD27CO4n8xuBgkmwVxiwst1RQ=="
9
9
  }
@@ -1 +1 @@
1
- function a(o){const e=new Set([`http://127.0.0.1:${o.serverPort}`,`http://localhost:${o.serverPort}`,...o.allowedOrigins]),t=new Set([`127.0.0.1:${o.serverPort}`,`localhost:${o.serverPort}`,...o.allowedHosts]);return{validateRequest(s){const r=i(s,e);if(!r.ok)return r;const n=l(s,t);return n.ok?{ok:!0}:n}}}function i(o,e){const t=o.headers.origin;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${t}`}:{ok:!0}}function l(o,e){const t=o.headers.host;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${t}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
1
+ function a(e){const t=new Set([`http://127.0.0.1:${e.serverPort}`,`http://localhost:${e.serverPort}`,...e.allowedOrigins]),o=new Set([`127.0.0.1:${e.serverPort}`,`localhost:${e.serverPort}`,...e.allowedHosts]);return{validateRequest(s){const r=i(s,t);if(!r.ok)return r;const n=l(s,o);return n.ok?{ok:!0}:n}}}function i(e,t){const o=e.headers.origin;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${o}`}:{ok:!0}}function l(e,t){const o=e.headers.host;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${o}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
@@ -1,4 +1,4 @@
1
- import{existsSync as b,readFileSync as U}from"node:fs";import{mkdir as k,readdir as F,readFile as S,rm as y,stat as Y,writeFile as $}from"node:fs/promises";import d from"node:os";import c from"node:path";import{GRIX_HOME_ENV as C}from"../core/config/paths.js";import{isProcessRunning as I,runCommand as f,spawnDetached as L,isWindowsElevated as tt,killProcessesByCommandLine as G}from"./process-control.js";import{getServicePrefix as D,parseConfigDirFromPlistXML as et,parseConfigDirFromSystemdUnit as nt,resolveBareDaemonMarkerPath as P,resolveLinuxUserUnitPath as rt,resolveMacOSLaunchAgentPath as it}from"./service-paths.js";function g(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function R(t){return`'${String(t??"").replace(/'/g,"'\\''")}'`}function H(t){return String(t??"").replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}function at(t){return`"${H(t).replace(/%/g,"%%")}"`}function _(t){return String(t??"").replace(/%/g,"%%")}function ot(t){return`"${H(t).replace(/\$/g,()=>"$$").replace(/%/g,"%%")}"`}function j(t=process.env){const e=[];for(const n of["GRIX_HEALTH_PORT","GRIX_ADMIN_PORT"]){const r=String(t[n]??"").trim();/^\d{2,5}$/.test(r)&&e.push([n,r])}return e}function V(t){return[t.nodePath,t.cliPath,...t.configDir?["--config-dir",t.configDir]:[]]}function st(t){const e=V(t);return`<?xml version="1.0" encoding="UTF-8"?>
1
+ import{existsSync as b,readFileSync as U}from"node:fs";import{mkdir as k,readdir as F,readFile as P,rm as y,stat as tt,writeFile as $}from"node:fs/promises";import m from"node:os";import c from"node:path";import{GRIX_HOME_ENV as v}from"../core/config/paths.js";import{isProcessRunning as I,runCommand as f,spawnDetached as L,isWindowsElevated as et,killProcessesByCommandLine as G}from"./process-control.js";import{getServicePrefix as D,parseConfigDirFromPlistXML as nt,parseConfigDirFromSystemdUnit as rt,resolveBareDaemonMarkerPath as S,resolveLinuxUserUnitPath as it,resolveMacOSLaunchAgentPath as ot}from"./service-paths.js";function g(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function R(t){return`'${String(t??"").replace(/'/g,"'\\''")}'`}function H(t){return String(t??"").replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}function V(t){return`"${H(t).replace(/%/g,"%%")}"`}function _(t){return String(t??"").replace(/%/g,"%%")}function at(t){return`"${H(t).replace(/\$/g,()=>"$$").replace(/%/g,"%%")}"`}function j(t=process.env){const e=[];for(const n of["GRIX_HEALTH_PORT","GRIX_ADMIN_PORT"]){const r=String(t[n]??"").trim();/^\d{2,5}$/.test(r)&&e.push([n,r])}return e}function X(t){return[t.nodePath,t.cliPath,...t.configDir?["--config-dir",t.configDir]:[]]}function st(t){const e=X(t);return`<?xml version="1.0" encoding="UTF-8"?>
2
2
  <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
3
  <plist version="1.0">
4
4
  <dict>
@@ -20,7 +20,7 @@ ${e.map(n=>` <string>${g(n)}</string>`).join(`
20
20
  <string>${g(c.dirname(t.cliPath))}</string>
21
21
  <key>EnvironmentVariables</key>
22
22
  <dict>
23
- <key>${C}</key>
23
+ <key>${v}</key>
24
24
  <string>${g(t.rootDir)}</string>
25
25
  ${j().map(([n,r])=>` <key>${n}</key>
26
26
  <string>${r}</string>
@@ -33,7 +33,7 @@ ${j().map(([n,r])=>` <key>${n}</key>
33
33
  <string>${g(t.stderrPath)}</string>
34
34
  </dict>
35
35
  </plist>
36
- `}function ct(t){const e=V(t).map(n=>ot(n)).join(" ");return`[Unit]
36
+ `}function ct(t){const e=X(t).map(n=>at(n)).join(" ");return`[Unit]
37
37
  Description=grix-connector daemon (${t.serviceID})
38
38
  After=network.target
39
39
 
@@ -41,9 +41,10 @@ After=network.target
41
41
  Type=simple
42
42
  ExecStart=${e}
43
43
  WorkingDirectory=${_(c.dirname(t.cliPath))}
44
- Environment=${at(`${C}=${t.rootDir}`)}
44
+ Environment=${V(`${v}=${t.rootDir}`)}
45
45
  ${j().map(([n,r])=>`Environment=${n}=${r}
46
- `).join("")}
46
+ `).join("")}${t.environmentPath?`Environment=${V(`PATH=${t.environmentPath}`)}
47
+ `:""}
47
48
  Restart=always
48
49
  RestartSec=30
49
50
  StandardOutput=append:${_(t.stdoutPath)}
@@ -51,8 +52,8 @@ StandardError=append:${_(t.stderrPath)}
51
52
 
52
53
  [Install]
53
54
  WantedBy=default.target
54
- `}function x(t,e){const n=t.replace(/[^a-zA-Z0-9._-]/g,"_");return c.join(e,".grix",`${n}-wrapper.vbs`)}function M(t,e){const n=t.replace(/[^a-zA-Z0-9._-]/g,"_"),r=c.join(e,"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup");return c.join(r,`${n}.lnk`)}function p(t){return String(t??"").replace(/"/g,'""')}function A(t){return`'${String(t??"").replace(/'/g,"''")}'`}function lt(t,e){const n=c.join(c.dirname(t),c.basename(e).replace(/\.lnk$/,"-create.vbs")),r=["Option Explicit","Dim shell, shortcut",'Set shell = CreateObject("WScript.Shell")',`Set shortcut = shell.CreateShortcut("${p(e)}")`,'shortcut.TargetPath = "wscript.exe"',`shortcut.Arguments = "//B //NoLogo \\"${p(t)}\\""`,"shortcut.WindowStyle = 7","shortcut.Save",""].join(`\r
55
- `);return{path:n,content:r}}async function ut(t){const{wrapperPath:e,shortcutPath:n,runCommand:r}=t,i=lt(e,n);for(let a=1;a<=3;a+=1){try{await $(i.path,i.content,"utf8"),await r("wscript.exe",[i.path,"//B","//NoLogo"])}catch{}finally{await y(i.path,{force:!0}).catch(()=>{})}if(b(n))return!0}return console.warn(`Warning: failed to create Windows logon-autostart shortcut at ${n}. The daemon will NOT start automatically after the next reboot/logon. Check Controlled Folder Access / antivirus blocking writes to the Startup folder, or create the shortcut manually.`),!1}async function dt(t){try{const e=await t("whoami",["/user","/fo","csv","/nh"],{allowFailure:!0}),n=String(e?.stdout??"").match(/"(S-1-[0-9-]+)"/);if(n)return n[1]}catch{}return null}function mt(t){const e=`//B //NoLogo "${t.wrapperPath}"`;return`<?xml version="1.0" encoding="UTF-16"?>
55
+ `}function x(t,e){const n=t.replace(/[^a-zA-Z0-9._-]/g,"_");return c.join(e,".grix",`${n}-wrapper.vbs`)}function M(t,e){const n=t.replace(/[^a-zA-Z0-9._-]/g,"_"),r=c.join(e,"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup");return c.join(r,`${n}.lnk`)}function h(t){return String(t??"").replace(/"/g,'""')}function A(t){return`'${String(t??"").replace(/'/g,"''")}'`}function lt(t,e){const n=c.join(c.dirname(t),c.basename(e).replace(/\.lnk$/,"-create.vbs")),r=["Option Explicit","Dim shell, shortcut",'Set shell = CreateObject("WScript.Shell")',`Set shortcut = shell.CreateShortcut("${h(e)}")`,'shortcut.TargetPath = "wscript.exe"',`shortcut.Arguments = "//B //NoLogo \\"${h(t)}\\""`,"shortcut.WindowStyle = 7","shortcut.Save",""].join(`\r
56
+ `);return{path:n,content:r}}async function ut(t){const{wrapperPath:e,shortcutPath:n,runCommand:r}=t,i=lt(e,n);for(let o=1;o<=3;o+=1){try{await $(i.path,i.content,"utf8"),await r("wscript.exe",[i.path,"//B","//NoLogo"])}catch{}finally{await y(i.path,{force:!0}).catch(()=>{})}if(b(n))return!0}return console.warn(`Warning: failed to create Windows logon-autostart shortcut at ${n}. The daemon will NOT start automatically after the next reboot/logon. Check Controlled Folder Access / antivirus blocking writes to the Startup folder, or create the shortcut manually.`),!1}async function dt(t){try{const e=await t("whoami",["/user","/fo","csv","/nh"],{allowFailure:!0}),n=String(e?.stdout??"").match(/"(S-1-[0-9-]+)"/);if(n)return n[1]}catch{}return null}function mt(t){const e=`//B //NoLogo "${t.wrapperPath}"`;return`<?xml version="1.0" encoding="UTF-16"?>
56
57
  <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
57
58
  <RegistrationInfo>
58
59
  <Description>grix-connector daemon autostart</Description>
@@ -95,13 +96,13 @@ WantedBy=default.target
95
96
  </Exec>
96
97
  </Actions>
97
98
  </Task>
98
- `}async function ft(t){const{serviceID:e,wrapperPath:n,runCommand:r}=t,i=await dt(r)??d.userInfo().username,a=c.join(c.dirname(n),`${e}-task.xml`);try{const o=mt({userId:i,wrapperPath:n});return await $(a,"\uFEFF"+o,"utf16le"),await r("schtasks",["/Create","/TN",e,"/XML",a,"/F"]),!0}catch{return!1}finally{await y(a,{force:!0}).catch(()=>{})}}const pt=3,ht="grix-wrapper-template:";function gt(t){const e=c.join(t.rootDir,"data","upgrade-wrapper-child.json"),n=[`"${t.cliPath}"`,...t.configDir?["--config-dir",`"${t.configDir}"`]:[]],r=["$ErrorActionPreference = 'Stop'",`$recordPath = ${A(e)}`,"$exitCode = 1","try {"," [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($recordPath)) | Out-Null",` $p = Start-Process -FilePath ${A(t.nodePath)} -ArgumentList @(${n.map(A).join(", ")}) -WindowStyle Hidden -PassThru`,` $record = @{ pid = $p.Id; launched_at = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds(); boot_time = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() - [Environment]::TickCount64; cli_path = ${A(t.cliPath)} }`," $utf8NoBom = New-Object System.Text.UTF8Encoding($false)"," try {"," [IO.File]::WriteAllText($recordPath, ($record | ConvertTo-Json -Compress), $utf8NoBom)"," } catch {",' & "$env:SystemRoot\\System32\\taskkill.exe" /PID $p.Id /T /F 2>$null | Out-Null'," $p.WaitForExit()"," throw"," }"," $p.WaitForExit()"," $exitCode = $p.ExitCode","} finally {"," Remove-Item -LiteralPath $recordPath -Force -ErrorAction SilentlyContinue","}","exit $exitCode"].join(`
99
- `),i=Buffer.from(r,"utf16le").toString("base64"),l=`"${c.join(process.env.SystemRoot||"C:\\Windows","System32","WindowsPowerShell","v1.0","powershell.exe")}" -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${i}`,o=c.join(t.rootDir,"bin","upgrade-guardian.mjs"),s=c.join(t.rootDir,"bin","upgrade-guardian.fallback.mjs"),u=c.join(t.rootDir,"data","upgrade-wrapper.pause.json"),m=c.join(t.rootDir,"data","upgrade-pending.json"),h=[`"${p(t.nodePath)}"`,`"${p(o)}"`,"activate","--root",`"${p(t.rootDir)}"`].join(" "),w=`${h} --wrapper-handoff`,O=[`"${p(t.nodePath)}"`,`"${p(s)}"`,"activate","--root",`"${p(t.rootDir)}"`].join(" "),T=`${O} --wrapper-handoff`;return[`' ${ht} ${pt}`,"Option Explicit","Dim shell, processEnv, fso, command, guardianCommand, handoffGuardianCommand, guardianFallbackCommand, handoffGuardianFallbackCommand, guardianPath, guardianFallbackPath, maintenanceFile, pendingFile, delayMs, rapidCount, guardianExit",`command = "${p(l)}"`,`guardianCommand = "${p(h)}"`,`handoffGuardianCommand = "${p(w)}"`,`guardianFallbackCommand = "${p(O)}"`,`handoffGuardianFallbackCommand = "${p(T)}"`,`guardianPath = "${p(o)}"`,`guardianFallbackPath = "${p(s)}"`,`maintenanceFile = "${p(u)}"`,`pendingFile = "${p(m)}"`,'Set shell = CreateObject("WScript.Shell")','Set processEnv = shell.Environment("Process")','Set fso = CreateObject("Scripting.FileSystemObject")',`processEnv("${C}") = "${p(t.rootDir)}"`,'processEnv("GRIX_WRAPPER_SUPERVISED") = "1"',...j().map(([K,Z])=>`processEnv("${K}") = "${Z}"`),"delayMs = 5000","rapidCount = 0","Do"," Do While fso.FileExists(maintenanceFile)"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(guardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(guardianFallbackCommand, 0, True)"," Else"," On Error Resume Next"," fso.DeleteFile maintenanceFile, True"," On Error GoTo 0"," WScript.Sleep 1000"," End If"," If fso.FileExists(maintenanceFile) Then WScript.Sleep 3000"," Loop"," If fso.FileExists(pendingFile) Then"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(guardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(guardianFallbackCommand, 0, True)"," End If"," End If"," shell.Run command, 0, True"," If fso.FileExists(pendingFile) Then"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(handoffGuardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(handoffGuardianFallbackCommand, 0, True)"," End If"," End If"," If fso.FileExists(pendingFile) And Not PendingIsTerminal() Then"," rapidCount = 0"," WScript.Sleep delayMs"," ElseIf fso.FileExists(maintenanceFile) Then"," rapidCount = 0"," Else"," rapidCount = rapidCount + 1"," If rapidCount >= 10 Then"," WScript.Sleep 300000"," rapidCount = 0"," Else"," WScript.Sleep delayMs"," End If"," End If","Loop","","Function PendingIsTerminal()"," Dim stream, text"," PendingIsTerminal = False"," On Error Resume Next"," Set stream = fso.OpenTextFile(pendingFile, 1)"," If Err.Number <> 0 Then"," Err.Clear"," On Error GoTo 0"," Exit Function"," End If"," text = stream.ReadAll"," stream.Close"," If Err.Number <> 0 Then"," Err.Clear"," On Error GoTo 0"," Exit Function"," End If"," On Error GoTo 0",' text = Replace(Replace(Replace(text, " ", ""), vbCr, ""), vbLf, "")',' If InStr(text, """phase"":""failed""") > 0 Then PendingIsTerminal = True',' If InStr(text, """phase"":""finalizing""") > 0 Then PendingIsTerminal = True',"End Function",""].join(`\r
100
- `)}function v(t){return`gui/${t??0}`}function B(t){const e=String(t?.stdout??"").trim();return String(t?.stderr??"").trim()||e||`exit=${Number(t?.exitCode??-1)}`}function N(t,e,n,r){if(t?.trim())return c.resolve(t);const i=e||n;return i?c.resolve(c.dirname(c.dirname(i))):c.join(r,".grix")}async function X(t){try{await Y(t)}catch{throw new Error(`launchd plist missing: ${t}`)}}async function Q(t){const{serviceID:e,domain:n,runCommand:r}=t,i=`${n}/${e}`,a=await r("launchctl",["bootout",i],{allowFailure:!0});if(Number(a?.exitCode??-1)!==0){const l=await r("launchctl",["print",i],{allowFailure:!0});if(Number(l?.exitCode??1)===0){await new Promise(s=>setTimeout(s,250));const o=await r("launchctl",["print",i],{allowFailure:!0});if(Number(o?.exitCode??1)===0)throw new Error(`launchctl bootout ${i}: ${B(a)}`)}return}for(let l=0;l<20;l+=1){const o=await r("launchctl",["print",i],{allowFailure:!0});if(Number(o?.exitCode??1)!==0)return;await new Promise(s=>setTimeout(s,250))}throw new Error(`launchctl bootout ${i}: service remains loaded`)}async function z(t){const{serviceID:e,domain:n,definitionPath:r,runCommand:i}=t,a=`${n}/${e}`,l=await i("launchctl",["bootstrap",n,r],{allowFailure:!0});if(Number(l?.exitCode??-1)===0)return;const o=await i("launchctl",["print",a],{allowFailure:!0});Number(o?.exitCode??1)===0&&await Q(t);const s=await i("launchctl",["bootstrap",n,r],{allowFailure:!0});if(Number(s?.exitCode??-1)!==0)throw new Error(`launchctl bootstrap ${n} failed: initial=${B(l)}; retry=${B(s)}`)}function wt(){return{platform:"darwin",kind:"launchd",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:a,stderrPath:l,environmentPath:o="",homeDir:s=d.homedir()}){const u=it(t,s),m=N(i,a,l,s);return await k(c.dirname(u),{recursive:!0}),await $(u,st({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:m,stdoutPath:a,stderrPath:l,environmentPath:o}),{encoding:"utf8",mode:384}),{definitionPath:u}},async start({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=v(r);await X(e),await z({serviceID:t,domain:i,definitionPath:e,runCommand:n})},async stop({serviceID:t,runCommand:e=f,uid:n=process.getuid?.()??0}){const r=v(n);await e("launchctl",["bootout",`${r}/${t}`],{allowFailure:!0})},async restart({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=v(r),a={serviceID:t,domain:i,definitionPath:e,runCommand:n};await X(e),await Q(a),await z(a)},async uninstall({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=v(r);await n("launchctl",["bootout",`${i}/${t}`],{allowFailure:!0}),await y(e,{force:!0})},async discoverServices({homeDir:t=d.homedir()}={}){const e=c.join(t,"Library","LaunchAgents"),n=await F(e).catch(()=>[]),r=D("darwin"),i=[];for(const a of n){if(!a.startsWith(r)||!a.endsWith(".plist"))continue;const l=a.slice(0,-6),o=c.join(e,a);let s=null;try{const u=await S(o,"utf8");s=et(u)}catch{}i.push({serviceID:l,definitionPath:o,configDir:s})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f,uid:n=process.getuid?.()??0}){const r=v(n),i=await e("launchctl",["print",`${r}/${t}`],{allowFailure:!0});return Number(i?.exitCode??1)===0}}}function yt(){return{platform:"win32",kind:"task-scheduler",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:a,stderrPath:l,runCommand:o=f,homeDir:s=d.homedir()}){const u=x(t,s),m=N(i,a,l,s);await k(c.dirname(u),{recursive:!0}),await $(u,gt({nodePath:e,cliPath:n,configDir:r,rootDir:m}),"utf8");let h=!1;tt()&&(h=await ft({serviceID:t,wrapperPath:u,runCommand:o}));const w=M(t,s);return h?await y(w,{force:!0}).catch(()=>{}):await ut({wrapperPath:u,shortcutPath:w,runCommand:o}),{definitionPath:h?`task:${t}`:`startup:${t}`}},async start({serviceID:t,definitionPath:e,runCommand:n=f,homeDir:r=d.homedir()}){const i=x(t,r);if(e.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}L("wscript.exe",["//B","//NoLogo",i])},async stop({serviceID:t,runCommand:e=f,homeDir:n=d.homedir()}){await e("schtasks",["/End","/TN",t],{allowFailure:!0});const r=`${t}-wrapper.vbs`;await G(r,{platform:"win32"})},async restart({serviceID:t,definitionPath:e,runCommand:n=f,homeDir:r=d.homedir()}){await n("schtasks",["/End","/TN",t],{allowFailure:!0});const i=`${t}-wrapper.vbs`;await G(i,{platform:"win32"});const a=x(t,r);if(e?.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}L("wscript.exe",["//B","//NoLogo",a])},async uninstall({serviceID:t,runCommand:e=f,homeDir:n=d.homedir()}){await e("schtasks",["/Delete","/TN",t,"/F"],{allowFailure:!0});const r=x(t,n);await y(r,{force:!0});const i=M(t,n);await y(i,{force:!0})},async discoverServices({homeDir:t=d.homedir(),runCommand:e=f}={}){const n=D("win32"),r=await e("schtasks",["/Query","/FO","CSV","/NH"],{allowFailure:!0}),i=[];if(Number(r?.exitCode??-1)===0){const o=String(r.stdout??"").split(/\r?\n/);for(const s of o){const u=s.match(/^"([^"]+)"/);if(!u)continue;const m=u[1];if(!m.startsWith(n))continue;let h=null;try{const w=x(m,t),T=(await S(w,"utf8")).match(/--config-dir\s+""([^""]+)""/);T&&(h=T[1])}catch{}i.push({serviceID:m,definitionPath:`task:${m}`,configDir:h})}}const a=c.join(t,"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),l=await F(a).catch(()=>[]);for(const o of l){if(!o.startsWith(n)||!o.endsWith(".lnk"))continue;const s=o.slice(0,-4);if(i.some(m=>m.serviceID===s))continue;let u=null;try{const m=x(s,t),w=(await S(m,"utf8")).match(/--config-dir\s+""([^""]+)""/);w&&(u=w[1])}catch{}i.push({serviceID:s,definitionPath:`startup:${s}`,configDir:u})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f,homeDir:n=d.homedir()}){const r=await e("schtasks",["/Query","/TN",t,"/NH"],{allowFailure:!0});return Number(r?.exitCode??1)===0?!0:b(M(t,n))}}}function $t(){return{platform:"linux",kind:"systemd-user",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:a,stderrPath:l,homeDir:o=d.homedir(),runCommand:s=f}){const u=rt(t,o),m=N(i,a,l,o);return await k(c.dirname(u),{recursive:!0}),await $(u,ct({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:m,stdoutPath:a,stderrPath:l}),{encoding:"utf8",mode:384}),await s("systemctl",["--user","daemon-reload"]),await s("systemctl",["--user","enable",`${t}.service`]),{definitionPath:u}},async start({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","start",`${t}.service`])},async stop({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0})},async restart({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","restart",`${t}.service`])},async uninstall({serviceID:t,definitionPath:e,runCommand:n=f}){await n("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0}),await n("systemctl",["--user","disable",`${t}.service`],{allowFailure:!0}),await y(e,{force:!0}),await n("systemctl",["--user","daemon-reload"])},async discoverServices({homeDir:t=d.homedir()}={}){const e=c.join(t,".config","systemd","user"),n=await F(e).catch(()=>[]),r=D("linux"),i=[];for(const a of n){if(!a.startsWith(r)||!a.endsWith(".service"))continue;const l=a.slice(0,-8),o=c.join(e,a);let s=null;try{const u=await S(o,"utf8");s=nt(u)}catch{}i.push({serviceID:l,definitionPath:o,configDir:s})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f}){const n=await e("systemctl",["--user","is-active",`${t}.service`],{allowFailure:!0});return String(n?.stdout??"").trim()==="active"}}}function E(t){try{const e=U(t,"utf8"),n=JSON.parse(e);if(n&&typeof n.service_id=="string"&&typeof n.node_path=="string"&&typeof n.cli_path=="string"&&typeof n.root_dir=="string")return n}catch{}return null}function St(t){return c.join(t,"daemon.lock.json")}function W(t){const e=St(t);try{const n=U(e,"utf8"),r=JSON.parse(n);if(typeof r?.pid=="number")return r.pid}catch{}return 0}function J(t){return c.join(t,".profile")}function Pt(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function xt(t){const e=[R(t.nodePath),R(t.cliPath)];t.configDir&&e.push("--config-dir",R(t.configDir));const n=`env ${C}=${R(t.rootDir)} ${e.join(" ")}`;return`${n} status >/dev/null 2>&1 || (nohup ${n} start >/dev/null 2>&1 &)`}function Et(t,e){return`# >>> grix-connector autostart [${t}] >>>
99
+ `}async function ft(t){const{serviceID:e,wrapperPath:n,runCommand:r}=t,i=await dt(r)??m.userInfo().username,o=c.join(c.dirname(n),`${e}-task.xml`);try{const a=mt({userId:i,wrapperPath:n});return await $(o,"\uFEFF"+a,"utf16le"),await r("schtasks",["/Create","/TN",e,"/XML",o,"/F"]),!0}catch{return!1}finally{await y(o,{force:!0}).catch(()=>{})}}const ht=3,pt="grix-wrapper-template:";function gt(t){const e=c.join(t.rootDir,"data","upgrade-wrapper-child.json"),n=[`"${t.cliPath}"`,...t.configDir?["--config-dir",`"${t.configDir}"`]:[]],r=["$ErrorActionPreference = 'Stop'",`$recordPath = ${A(e)}`,"$exitCode = 1","try {"," [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($recordPath)) | Out-Null",` $p = Start-Process -FilePath ${A(t.nodePath)} -ArgumentList @(${n.map(A).join(", ")}) -WindowStyle Hidden -PassThru`,` $record = @{ pid = $p.Id; launched_at = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds(); boot_time = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() - [Environment]::TickCount64; cli_path = ${A(t.cliPath)} }`," $utf8NoBom = New-Object System.Text.UTF8Encoding($false)"," try {"," [IO.File]::WriteAllText($recordPath, ($record | ConvertTo-Json -Compress), $utf8NoBom)"," } catch {",' & "$env:SystemRoot\\System32\\taskkill.exe" /PID $p.Id /T /F 2>$null | Out-Null'," $p.WaitForExit()"," throw"," }"," $p.WaitForExit()"," $exitCode = $p.ExitCode","} finally {"," Remove-Item -LiteralPath $recordPath -Force -ErrorAction SilentlyContinue","}","exit $exitCode"].join(`
100
+ `),i=Buffer.from(r,"utf16le").toString("base64"),l=`"${c.join(process.env.SystemRoot||"C:\\Windows","System32","WindowsPowerShell","v1.0","powershell.exe")}" -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${i}`,a=c.join(t.rootDir,"bin","upgrade-guardian.mjs"),s=c.join(t.rootDir,"bin","upgrade-guardian.fallback.mjs"),u=c.join(t.rootDir,"data","upgrade-wrapper.pause.json"),d=c.join(t.rootDir,"data","upgrade-pending.json"),p=[`"${h(t.nodePath)}"`,`"${h(a)}"`,"activate","--root",`"${h(t.rootDir)}"`].join(" "),w=`${p} --wrapper-handoff`,O=[`"${h(t.nodePath)}"`,`"${h(s)}"`,"activate","--root",`"${h(t.rootDir)}"`].join(" "),T=`${O} --wrapper-handoff`;return[`' ${pt} ${ht}`,"Option Explicit","Dim shell, processEnv, fso, command, guardianCommand, handoffGuardianCommand, guardianFallbackCommand, handoffGuardianFallbackCommand, guardianPath, guardianFallbackPath, maintenanceFile, pendingFile, delayMs, rapidCount, guardianExit",`command = "${h(l)}"`,`guardianCommand = "${h(p)}"`,`handoffGuardianCommand = "${h(w)}"`,`guardianFallbackCommand = "${h(O)}"`,`handoffGuardianFallbackCommand = "${h(T)}"`,`guardianPath = "${h(a)}"`,`guardianFallbackPath = "${h(s)}"`,`maintenanceFile = "${h(u)}"`,`pendingFile = "${h(d)}"`,'Set shell = CreateObject("WScript.Shell")','Set processEnv = shell.Environment("Process")','Set fso = CreateObject("Scripting.FileSystemObject")',`processEnv("${v}") = "${h(t.rootDir)}"`,'processEnv("GRIX_WRAPPER_SUPERVISED") = "1"',...j().map(([Z,Y])=>`processEnv("${Z}") = "${Y}"`),"delayMs = 5000","rapidCount = 0","Do"," Do While fso.FileExists(maintenanceFile)"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(guardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(guardianFallbackCommand, 0, True)"," Else"," On Error Resume Next"," fso.DeleteFile maintenanceFile, True"," On Error GoTo 0"," WScript.Sleep 1000"," End If"," If fso.FileExists(maintenanceFile) Then WScript.Sleep 3000"," Loop"," If fso.FileExists(pendingFile) Then"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(guardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(guardianFallbackCommand, 0, True)"," End If"," End If"," shell.Run command, 0, True"," If fso.FileExists(pendingFile) Then"," If fso.FileExists(guardianPath) Then"," guardianExit = shell.Run(handoffGuardianCommand, 0, True)"," ElseIf fso.FileExists(guardianFallbackPath) Then"," guardianExit = shell.Run(handoffGuardianFallbackCommand, 0, True)"," End If"," End If"," If fso.FileExists(pendingFile) And Not PendingIsTerminal() Then"," rapidCount = 0"," WScript.Sleep delayMs"," ElseIf fso.FileExists(maintenanceFile) Then"," rapidCount = 0"," Else"," rapidCount = rapidCount + 1"," If rapidCount >= 10 Then"," WScript.Sleep 300000"," rapidCount = 0"," Else"," WScript.Sleep delayMs"," End If"," End If","Loop","","Function PendingIsTerminal()"," Dim stream, text"," PendingIsTerminal = False"," On Error Resume Next"," Set stream = fso.OpenTextFile(pendingFile, 1)"," If Err.Number <> 0 Then"," Err.Clear"," On Error GoTo 0"," Exit Function"," End If"," text = stream.ReadAll"," stream.Close"," If Err.Number <> 0 Then"," Err.Clear"," On Error GoTo 0"," Exit Function"," End If"," On Error GoTo 0",' text = Replace(Replace(Replace(text, " ", ""), vbCr, ""), vbLf, "")',' If InStr(text, """phase"":""failed""") > 0 Then PendingIsTerminal = True',' If InStr(text, """phase"":""finalizing""") > 0 Then PendingIsTerminal = True',"End Function",""].join(`\r
101
+ `)}function C(t){return`gui/${t??0}`}function B(t){const e=String(t?.stdout??"").trim();return String(t?.stderr??"").trim()||e||`exit=${Number(t?.exitCode??-1)}`}function N(t,e,n,r){if(t?.trim())return c.resolve(t);const i=e||n;return i?c.resolve(c.dirname(c.dirname(i))):c.join(r,".grix")}async function Q(t){try{await tt(t)}catch{throw new Error(`launchd plist missing: ${t}`)}}async function z(t){const{serviceID:e,domain:n,runCommand:r}=t,i=`${n}/${e}`,o=await r("launchctl",["bootout",i],{allowFailure:!0});if(Number(o?.exitCode??-1)!==0){const l=await r("launchctl",["print",i],{allowFailure:!0});if(Number(l?.exitCode??1)===0){await new Promise(s=>setTimeout(s,250));const a=await r("launchctl",["print",i],{allowFailure:!0});if(Number(a?.exitCode??1)===0)throw new Error(`launchctl bootout ${i}: ${B(o)}`)}return}for(let l=0;l<20;l+=1){const a=await r("launchctl",["print",i],{allowFailure:!0});if(Number(a?.exitCode??1)!==0)return;await new Promise(s=>setTimeout(s,250))}throw new Error(`launchctl bootout ${i}: service remains loaded`)}async function J(t){const{serviceID:e,domain:n,definitionPath:r,runCommand:i}=t,o=`${n}/${e}`,l=await i("launchctl",["bootstrap",n,r],{allowFailure:!0});if(Number(l?.exitCode??-1)===0)return;const a=await i("launchctl",["print",o],{allowFailure:!0});Number(a?.exitCode??1)===0&&await z(t);const s=await i("launchctl",["bootstrap",n,r],{allowFailure:!0});if(Number(s?.exitCode??-1)!==0)throw new Error(`launchctl bootstrap ${n} failed: initial=${B(l)}; retry=${B(s)}`)}function wt(){return{platform:"darwin",kind:"launchd",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:o,stderrPath:l,environmentPath:a="",homeDir:s=m.homedir()}){const u=ot(t,s),d=N(i,o,l,s);return await k(c.dirname(u),{recursive:!0}),await $(u,st({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:d,stdoutPath:o,stderrPath:l,environmentPath:a}),{encoding:"utf8",mode:384}),{definitionPath:u}},async start({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=C(r);await Q(e),await J({serviceID:t,domain:i,definitionPath:e,runCommand:n})},async stop({serviceID:t,runCommand:e=f,uid:n=process.getuid?.()??0}){const r=C(n);await e("launchctl",["bootout",`${r}/${t}`],{allowFailure:!0})},async restart({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=C(r),o={serviceID:t,domain:i,definitionPath:e,runCommand:n};await Q(e),await z(o),await J(o)},async uninstall({serviceID:t,definitionPath:e,runCommand:n=f,uid:r=process.getuid?.()??0}){const i=C(r);await n("launchctl",["bootout",`${i}/${t}`],{allowFailure:!0}),await y(e,{force:!0})},async discoverServices({homeDir:t=m.homedir()}={}){const e=c.join(t,"Library","LaunchAgents"),n=await F(e).catch(()=>[]),r=D("darwin"),i=[];for(const o of n){if(!o.startsWith(r)||!o.endsWith(".plist"))continue;const l=o.slice(0,-6),a=c.join(e,o);let s=null;try{const u=await P(a,"utf8");s=nt(u)}catch{}i.push({serviceID:l,definitionPath:a,configDir:s})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f,uid:n=process.getuid?.()??0}){const r=C(n),i=await e("launchctl",["print",`${r}/${t}`],{allowFailure:!0});return Number(i?.exitCode??1)===0}}}function yt(){return{platform:"win32",kind:"task-scheduler",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:o,stderrPath:l,runCommand:a=f,homeDir:s=m.homedir()}){const u=x(t,s),d=N(i,o,l,s);await k(c.dirname(u),{recursive:!0}),await $(u,gt({nodePath:e,cliPath:n,configDir:r,rootDir:d}),"utf8");let p=!1;et()&&(p=await ft({serviceID:t,wrapperPath:u,runCommand:a}));const w=M(t,s);return p?await y(w,{force:!0}).catch(()=>{}):await ut({wrapperPath:u,shortcutPath:w,runCommand:a}),{definitionPath:p?`task:${t}`:`startup:${t}`}},async start({serviceID:t,definitionPath:e,runCommand:n=f,homeDir:r=m.homedir()}){const i=x(t,r);if(e.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}L("wscript.exe",["//B","//NoLogo",i])},async stop({serviceID:t,runCommand:e=f,homeDir:n=m.homedir()}){await e("schtasks",["/End","/TN",t],{allowFailure:!0});const r=`${t}-wrapper.vbs`;await G(r,{platform:"win32"})},async restart({serviceID:t,definitionPath:e,runCommand:n=f,homeDir:r=m.homedir()}){await n("schtasks",["/End","/TN",t],{allowFailure:!0});const i=`${t}-wrapper.vbs`;await G(i,{platform:"win32"});const o=x(t,r);if(e?.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}L("wscript.exe",["//B","//NoLogo",o])},async uninstall({serviceID:t,runCommand:e=f,homeDir:n=m.homedir()}){await e("schtasks",["/Delete","/TN",t,"/F"],{allowFailure:!0});const r=x(t,n);await y(r,{force:!0});const i=M(t,n);await y(i,{force:!0})},async discoverServices({homeDir:t=m.homedir(),runCommand:e=f}={}){const n=D("win32"),r=await e("schtasks",["/Query","/FO","CSV","/NH"],{allowFailure:!0}),i=[];if(Number(r?.exitCode??-1)===0){const a=String(r.stdout??"").split(/\r?\n/);for(const s of a){const u=s.match(/^"([^"]+)"/);if(!u)continue;const d=u[1];if(!d.startsWith(n))continue;let p=null;try{const w=x(d,t),T=(await P(w,"utf8")).match(/--config-dir\s+""([^""]+)""/);T&&(p=T[1])}catch{}i.push({serviceID:d,definitionPath:`task:${d}`,configDir:p})}}const o=c.join(t,"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),l=await F(o).catch(()=>[]);for(const a of l){if(!a.startsWith(n)||!a.endsWith(".lnk"))continue;const s=a.slice(0,-4);if(i.some(d=>d.serviceID===s))continue;let u=null;try{const d=x(s,t),w=(await P(d,"utf8")).match(/--config-dir\s+""([^""]+)""/);w&&(u=w[1])}catch{}i.push({serviceID:s,definitionPath:`startup:${s}`,configDir:u})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f,homeDir:n=m.homedir()}){const r=await e("schtasks",["/Query","/TN",t,"/NH"],{allowFailure:!0});return Number(r?.exitCode??1)===0?!0:b(M(t,n))}}}function $t(){return{platform:"linux",kind:"systemd-user",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:o,stderrPath:l,environmentPath:a="",homeDir:s=m.homedir(),runCommand:u=f}){const d=it(t,s),p=N(i,o,l,s);return await k(c.dirname(d),{recursive:!0}),await $(d,ct({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:p,stdoutPath:o,stderrPath:l,environmentPath:a}),{encoding:"utf8",mode:384}),await u("systemctl",["--user","daemon-reload"]),await u("systemctl",["--user","enable",`${t}.service`]),{definitionPath:d}},async start({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","start",`${t}.service`])},async stop({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0})},async restart({serviceID:t,runCommand:e=f}){await e("systemctl",["--user","restart",`${t}.service`])},async uninstall({serviceID:t,definitionPath:e,runCommand:n=f}){await n("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0}),await n("systemctl",["--user","disable",`${t}.service`],{allowFailure:!0}),await y(e,{force:!0}),await n("systemctl",["--user","daemon-reload"])},async discoverServices({homeDir:t=m.homedir()}={}){const e=c.join(t,".config","systemd","user"),n=await F(e).catch(()=>[]),r=D("linux"),i=[];for(const o of n){if(!o.startsWith(r)||!o.endsWith(".service"))continue;const l=o.slice(0,-8),a=c.join(e,o);let s=null;try{const u=await P(a,"utf8");s=rt(u)}catch{}i.push({serviceID:l,definitionPath:a,configDir:s})}return i},async isServiceLoaded({serviceID:t,runCommand:e=f}){const n=await e("systemctl",["--user","is-active",`${t}.service`],{allowFailure:!0});return String(n?.stdout??"").trim()==="active"}}}function E(t){try{const e=U(t,"utf8"),n=JSON.parse(e);if(n&&typeof n.service_id=="string"&&typeof n.node_path=="string"&&typeof n.cli_path=="string"&&typeof n.root_dir=="string")return n}catch{}return null}function Pt(t){return c.join(t,"daemon.lock.json")}function W(t){const e=Pt(t);try{const n=U(e,"utf8"),r=JSON.parse(n);if(typeof r?.pid=="number")return r.pid}catch{}return 0}function q(t){return c.join(t,".profile")}function St(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function xt(t){const e=[R(t.nodePath),R(t.cliPath)];t.configDir&&e.push("--config-dir",R(t.configDir));const n=`env ${v}=${R(t.rootDir)} ${e.join(" ")}`;return`${n} status >/dev/null 2>&1 || (nohup ${n} start >/dev/null 2>&1 &)`}function Et(t,e){return`# >>> grix-connector autostart [${t}] >>>
101
102
  ${e}
102
103
  # <<< grix-connector autostart [${t}] <<<
103
- `}function q(t){const e=Pt(t);return new RegExp(`(?:^|\\n)# >>> grix-connector autostart \\[${e}\\] >>>\\n[\\s\\S]*?\\n# <<< grix-connector autostart \\[${e}\\] <<<\\n?`,"m")}async function kt(t,e,n){let r="";try{r=await S(t,"utf8")}catch{}const i=Et(e,n),a=q(e);let l;if(a.test(r))l=r.replace(a,`
104
- ${i}`).replace(/^\n+/,"");else{const o=r.length===0||r.endsWith(`
104
+ `}function K(t){const e=St(t);return new RegExp(`(?:^|\\n)# >>> grix-connector autostart \\[${e}\\] >>>\\n[\\s\\S]*?\\n# <<< grix-connector autostart \\[${e}\\] <<<\\n?`,"m")}async function kt(t,e,n){let r="";try{r=await P(t,"utf8")}catch{}const i=Et(e,n),o=K(e);let l;if(o.test(r))l=r.replace(o,`
105
+ ${i}`).replace(/^\n+/,"");else{const a=r.length===0||r.endsWith(`
105
106
  `)?"":`
106
- `;l=`${r}${o}${i}`}l!==r&&(await k(c.dirname(t),{recursive:!0}),await $(t,l,{encoding:"utf8"}))}async function Ct(t,e){let n="";try{n=await S(t,"utf8")}catch{return}const r=q(e);if(!r.test(n))return;const i=n.replace(r,"").replace(/^\n+/,"");await $(t,i,{encoding:"utf8"})}function vt(){return{platform:"linux",kind:"bare-daemon",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:a,stderrPath:l,homeDir:o=d.homedir()}){const s=P(t,o);await k(c.dirname(s),{recursive:!0});const u=N(i,a,l,o),m={schema_version:1,service_id:t,node_path:e,cli_path:n,config_dir:r??"",root_dir:u,stdout_path:a,stderr_path:l,installed_at:Date.now()};await $(s,`${JSON.stringify(m,null,2)}
107
- `,{encoding:"utf8",mode:384});const h=xt({nodePath:e,cliPath:n,configDir:r??"",rootDir:u});return await kt(J(o),t,h),{definitionPath:s}},async start({serviceID:t,homeDir:e=d.homedir()}){const n=P(t,e),r=E(n);if(!r)throw new Error(`bare-daemon marker missing: ${n}`);const i=[r.cli_path];r.config_dir&&i.push("--config-dir",r.config_dir),L(r.node_path,i,{env:{...process.env,[C]:r.root_dir}})},async stop({serviceID:t,homeDir:e=d.homedir()}){const n=P(t,e),r=E(n);if(!r)return;const i=W(r.root_dir);if(i>0&&I(i))try{process.kill(i,"SIGTERM")}catch{}},async restart(t){await this.stop(t);const e=Date.now()+5e3,n=P(t.serviceID,t.homeDir??d.homedir()),r=E(n);for(;r&&Date.now()<e;){const i=W(r.root_dir);if(i<=0||!I(i))break;await new Promise(a=>setTimeout(a,100))}await this.start(t)},async uninstall({serviceID:t,homeDir:e=d.homedir()}){const n=P(t,e),r=E(n);if(r){const i=W(r.root_dir);if(i>0&&I(i))try{process.kill(i,"SIGTERM")}catch{}}await y(n,{force:!0}),await Ct(J(e),t)},async discoverServices({homeDir:t=d.homedir()}={}){const e=c.join(t,".grix","service"),n=await F(e).catch(()=>[]),r=D("linux"),i=[];for(const a of n){if(!a.startsWith(r)||!a.endsWith(".bare.json"))continue;const l=a.slice(0,-10),o=c.join(e,a),s=E(o);i.push({serviceID:l,definitionPath:o,configDir:s?.config_dir||null})}return i},async isServiceLoaded({serviceID:t,homeDir:e=d.homedir()}){const n=P(t,e),r=E(n);if(!r)return!1;const i=W(r.root_dir);return i>0&&I(i)}}}function Tt(t=process.getuid?.()??0){if(process.env.GRIX_FORCE_BARE_DAEMON==="1")return!1;const e=process.env.XDG_RUNTIME_DIR;return!!(e&&b(c.join(e,"bus"))||b(`/run/user/${t}/bus`))}function Wt(t=process.platform,e={}){return t==="darwin"?wt():t==="win32"?yt():e.systemdUserAvailable??Tt()?$t():vt()}export{ht as WINDOWS_WRAPPER_TEMPLATE_MARKER,pt as WINDOWS_WRAPPER_TEMPLATE_VERSION,gt as buildWindowsWrapperScript,j as collectServicePortEnv,Wt as getPlatformServiceAdapter,Tt as isSystemdUserBusAvailable,Ct as removeProfileAutostart,x as resolveWindowsWrapperPath,kt as upsertProfileAutostart};
107
+ `;l=`${r}${a}${i}`}l!==r&&(await k(c.dirname(t),{recursive:!0}),await $(t,l,{encoding:"utf8"}))}async function vt(t,e){let n="";try{n=await P(t,"utf8")}catch{return}const r=K(e);if(!r.test(n))return;const i=n.replace(r,"").replace(/^\n+/,"");await $(t,i,{encoding:"utf8"})}function Ct(){return{platform:"linux",kind:"bare-daemon",async install({serviceID:t,nodePath:e,cliPath:n,configDir:r,rootDir:i,stdoutPath:o,stderrPath:l,homeDir:a=m.homedir()}){const s=S(t,a);await k(c.dirname(s),{recursive:!0});const u=N(i,o,l,a),d={schema_version:1,service_id:t,node_path:e,cli_path:n,config_dir:r??"",root_dir:u,stdout_path:o,stderr_path:l,installed_at:Date.now()};await $(s,`${JSON.stringify(d,null,2)}
108
+ `,{encoding:"utf8",mode:384});const p=xt({nodePath:e,cliPath:n,configDir:r??"",rootDir:u});return await kt(q(a),t,p),{definitionPath:s}},async start({serviceID:t,homeDir:e=m.homedir()}){const n=S(t,e),r=E(n);if(!r)throw new Error(`bare-daemon marker missing: ${n}`);const i=[r.cli_path];r.config_dir&&i.push("--config-dir",r.config_dir),L(r.node_path,i,{env:{...process.env,[v]:r.root_dir}})},async stop({serviceID:t,homeDir:e=m.homedir()}){const n=S(t,e),r=E(n);if(!r)return;const i=W(r.root_dir);if(i>0&&I(i))try{process.kill(i,"SIGTERM")}catch{}},async restart(t){await this.stop(t);const e=Date.now()+5e3,n=S(t.serviceID,t.homeDir??m.homedir()),r=E(n);for(;r&&Date.now()<e;){const i=W(r.root_dir);if(i<=0||!I(i))break;await new Promise(o=>setTimeout(o,100))}await this.start(t)},async uninstall({serviceID:t,homeDir:e=m.homedir()}){const n=S(t,e),r=E(n);if(r){const i=W(r.root_dir);if(i>0&&I(i))try{process.kill(i,"SIGTERM")}catch{}}await y(n,{force:!0}),await vt(q(e),t)},async discoverServices({homeDir:t=m.homedir()}={}){const e=c.join(t,".grix","service"),n=await F(e).catch(()=>[]),r=D("linux"),i=[];for(const o of n){if(!o.startsWith(r)||!o.endsWith(".bare.json"))continue;const l=o.slice(0,-10),a=c.join(e,o),s=E(a);i.push({serviceID:l,definitionPath:a,configDir:s?.config_dir||null})}return i},async isServiceLoaded({serviceID:t,homeDir:e=m.homedir()}){const n=S(t,e),r=E(n);if(!r)return!1;const i=W(r.root_dir);return i>0&&I(i)}}}function Tt(t=process.getuid?.()??0){if(process.env.GRIX_FORCE_BARE_DAEMON==="1")return!1;const e=process.env.XDG_RUNTIME_DIR;return!!(e&&b(c.join(e,"bus"))||b(`/run/user/${t}/bus`))}function Wt(t=process.platform,e={}){return t==="darwin"?wt():t==="win32"?yt():e.systemdUserAvailable??Tt()?$t():Ct()}export{pt as WINDOWS_WRAPPER_TEMPLATE_MARKER,ht as WINDOWS_WRAPPER_TEMPLATE_VERSION,gt as buildWindowsWrapperScript,j as collectServicePortEnv,Wt as getPlatformServiceAdapter,Tt as isSystemdUserBusAvailable,vt as removeProfileAutostart,x as resolveWindowsWrapperPath,kt as upsertProfileAutostart};
@@ -14656,19 +14656,19 @@ var plugin = {
14656
14656
  register(api) {
14657
14657
  setAibotRuntime(api.runtime);
14658
14658
  api.registerChannel({ plugin: aibotPlugin });
14659
- api.registerTool((ctx) => createGrixQueryTool(api, ctx), { optional: true });
14660
- api.registerTool((ctx) => createGrixAuditDataTool(api, ctx), { optional: true });
14661
- api.registerTool((ctx) => createGrixGroupTool(api, ctx), { optional: true });
14662
- api.registerTool((ctx) => createGrixAdminTool(api, ctx), { optional: true });
14663
- api.registerTool((ctx) => createGrixEggTool(api, ctx), { optional: true });
14664
- api.registerTool((ctx) => createGrixEggSearchTool(api, ctx), { optional: true });
14665
- api.registerTool((ctx) => createGrixEggGetTool(api, ctx), { optional: true });
14666
- api.registerTool((ctx) => createGrixRegisterTool(api, ctx), { optional: true });
14667
- api.registerTool((ctx) => createGrixUpdateTool(api, ctx), { optional: true });
14668
- api.registerTool((ctx) => createGrixMessageSendTool(api, ctx), { optional: true });
14669
- api.registerTool((ctx) => createGrixMessageUnsendTool(api, ctx), { optional: true });
14670
- api.registerTool((ctx) => createGrixFileLinkTool(api, ctx), { optional: true });
14671
- api.registerTool((ctx) => createOpenClawMemorySetupTool(api, ctx), { optional: true });
14659
+ api.registerTool((ctx) => createGrixQueryTool(api, ctx));
14660
+ api.registerTool((ctx) => createGrixAuditDataTool(api, ctx));
14661
+ api.registerTool((ctx) => createGrixGroupTool(api, ctx));
14662
+ api.registerTool((ctx) => createGrixAdminTool(api, ctx));
14663
+ api.registerTool((ctx) => createGrixEggTool(api, ctx));
14664
+ api.registerTool((ctx) => createGrixEggSearchTool(api, ctx));
14665
+ api.registerTool((ctx) => createGrixEggGetTool(api, ctx));
14666
+ api.registerTool((ctx) => createGrixRegisterTool(api, ctx));
14667
+ api.registerTool((ctx) => createGrixUpdateTool(api, ctx));
14668
+ api.registerTool((ctx) => createGrixMessageSendTool(api, ctx));
14669
+ api.registerTool((ctx) => createGrixMessageUnsendTool(api, ctx));
14670
+ api.registerTool((ctx) => createGrixFileLinkTool(api, ctx));
14671
+ api.registerTool((ctx) => createOpenClawMemorySetupTool(api, ctx));
14672
14672
  api.registerCli(({ program }) => registerGrixAdminCli({ api, program }), {
14673
14673
  commands: ["grix"]
14674
14674
  });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "grix",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "skills": [
5
5
  "./openclaw-plugin/skills"
6
6
  ],
@@ -14,6 +14,8 @@
14
14
  "grix_group",
15
15
  "grix_admin",
16
16
  "grix_egg",
17
+ "grix_egg_search",
18
+ "grix_egg_get",
17
19
  "grix_register",
18
20
  "grix_update",
19
21
  "grix_message_send",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grix-connector",
3
- "version": "4.6.7",
3
+ "version": "4.6.9",
4
4
  "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",