grix-connector 4.4.2-beta.1 → 4.4.2-beta.2
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/assets/dsh-bridge/{grix-dsh-bridge-4.4.2-beta.1.tgz → grix-dsh-bridge-4.4.2-beta.2.tgz}
RENAMED
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"bridgeVersion": "4.4.2-beta.
|
|
4
|
-
"tarball": "grix-dsh-bridge-4.4.2-beta.
|
|
5
|
-
"size":
|
|
3
|
+
"bridgeVersion": "4.4.2-beta.2",
|
|
4
|
+
"tarball": "grix-dsh-bridge-4.4.2-beta.2.tgz",
|
|
5
|
+
"size": 22636,
|
|
6
6
|
"unpackedSize": 90343,
|
|
7
|
-
"shasum": "
|
|
8
|
-
"integrity": "sha512-
|
|
7
|
+
"shasum": "086f2d649887e8be03eedce3dc7d5486e4bb2746",
|
|
8
|
+
"integrity": "sha512-d5G5Xu9IypdO1rZkcz0J+dWmscTyDGbYnLSNydzd3ggkY7pU03hlrYzfclvTZ/njP5DycmR6WxaDhRRymxJ5MA=="
|
|
9
9
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as
|
|
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 _,isWindowsElevated as tt,killProcessesByCommandLine as G}from"./process-control.js";import{getServicePrefix as D,parseConfigDirFromPlistXML as et,parseConfigDirFromSystemdUnit as nt,resolveBareDaemonMarkerPath as x,resolveLinuxUserUnitPath as rt,resolveMacOSLaunchAgentPath as it}from"./service-paths.js";function g(t){return String(t??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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 A(t){return`"${H(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 V(t){return[t.nodePath,t.cliPath,...t.configDir?["--config-dir",t.configDir]:[]]}function ot(t){const e=V(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>
|
|
@@ -22,7 +22,9 @@ ${e.map(n=>` <string>${g(n)}</string>`).join(`
|
|
|
22
22
|
<dict>
|
|
23
23
|
<key>${C}</key>
|
|
24
24
|
<string>${g(t.rootDir)}</string>
|
|
25
|
-
${
|
|
25
|
+
${j().map(([n,r])=>` <key>${n}</key>
|
|
26
|
+
<string>${r}</string>
|
|
27
|
+
`).join("")}${t.environmentPath?` <key>PATH</key>
|
|
26
28
|
<string>${g(t.environmentPath)}</string>
|
|
27
29
|
`:""} </dict>
|
|
28
30
|
<key>StandardOutPath</key>
|
|
@@ -31,24 +33,26 @@ ${t.environmentPath?` <key>PATH</key>
|
|
|
31
33
|
<string>${g(t.stderrPath)}</string>
|
|
32
34
|
</dict>
|
|
33
35
|
</plist>
|
|
34
|
-
`}function
|
|
36
|
+
`}function st(t){const e=V(t).map(n=>at(n)).join(" ");return`[Unit]
|
|
35
37
|
Description=grix-connector daemon (${t.serviceID})
|
|
36
38
|
After=network.target
|
|
37
39
|
|
|
38
40
|
[Service]
|
|
39
41
|
Type=simple
|
|
40
42
|
ExecStart=${e}
|
|
41
|
-
WorkingDirectory=${
|
|
42
|
-
Environment=${
|
|
43
|
+
WorkingDirectory=${A(c.dirname(t.cliPath))}
|
|
44
|
+
Environment=${A(`${C}=${t.rootDir}`)}
|
|
45
|
+
${j().map(([n,r])=>`Environment=${n}=${r}
|
|
46
|
+
`).join("")}
|
|
43
47
|
Restart=always
|
|
44
48
|
RestartSec=30
|
|
45
|
-
StandardOutput=${
|
|
46
|
-
StandardError=${
|
|
49
|
+
StandardOutput=${A(`append:${t.stdoutPath}`)}
|
|
50
|
+
StandardError=${A(`append:${t.stderrPath}`)}
|
|
47
51
|
|
|
48
52
|
[Install]
|
|
49
53
|
WantedBy=default.target
|
|
50
|
-
`}function P(t,e){const n=t.replace(/[^a-zA-Z0-9._-]/g,"_");return c.join(e,".grix",`${n}-wrapper.vbs`)}function
|
|
51
|
-
`);return{path:n,content:r}}async function
|
|
54
|
+
`}function P(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 N(t){return`'${String(t??"").replace(/'/g,"''")}'`}function ct(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 lt(t){const{wrapperPath:e,shortcutPath:n,runCommand:r}=t,i=ct(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 ut(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 dt(t){const e=`//B //NoLogo "${t.wrapperPath}"`;return`<?xml version="1.0" encoding="UTF-16"?>
|
|
52
56
|
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
53
57
|
<RegistrationInfo>
|
|
54
58
|
<Description>grix-connector daemon autostart</Description>
|
|
@@ -91,13 +95,13 @@ WantedBy=default.target
|
|
|
91
95
|
</Exec>
|
|
92
96
|
</Actions>
|
|
93
97
|
</Task>
|
|
94
|
-
`}async function
|
|
95
|
-
`),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"),
|
|
96
|
-
`)}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 W(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
|
|
98
|
+
`}async function mt(t){const{serviceID:e,wrapperPath:n,runCommand:r}=t,i=await ut(r)??d.userInfo().username,a=c.join(c.dirname(n),`${e}-task.xml`);try{const o=dt({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 ft=3,pt="grix-wrapper-template:";function ht(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 = ${N(e)}`,"$exitCode = 1","try {"," [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($recordPath)) | Out-Null",` $p = Start-Process -FilePath ${N(t.nodePath)} -ArgumentList @(${n.map(N).join(", ")}) -WindowStyle Hidden -PassThru`,` $record = @{ pid = $p.Id; launched_at = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds(); boot_time = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() - [Environment]::TickCount64; cli_path = ${N(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`,L=[`"${p(t.nodePath)}"`,`"${p(s)}"`,"activate","--root",`"${p(t.rootDir)}"`].join(" "),T=`${L} --wrapper-handoff`;return[`' ${pt} ${ft}`,"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(L)}"`,`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 W(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 gt(){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=W(i,a,l,s);return await k(c.dirname(u),{recursive:!0}),await $(u,ot({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 wt(){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=P(t,s),m=W(i,a,l,s);await k(c.dirname(u),{recursive:!0}),await $(u,ht({nodePath:e,cliPath:n,configDir:r,rootDir:m}),"utf8");let h=!1;tt()&&(h=await mt({serviceID:t,wrapperPath:u,runCommand:o}));const w=M(t,s);return h?await y(w,{force:!0}).catch(()=>{}):await lt({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=P(t,r);if(e.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}_("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=P(t,r);if(e?.startsWith("task:"))try{await n("schtasks",["/Run","/TN",t]);return}catch{}_("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=P(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=P(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=P(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 yt(){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=W(i,a,l,o);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}),{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 $t(t){return c.join(t,"daemon.lock.json")}function O(t){const e=$t(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 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 ${C}=${R(t.rootDir)} ${e.join(" ")}`;return`${n} status >/dev/null 2>&1 || (nohup ${n} start >/dev/null 2>&1 &)`}function Pt(t,e){return`# >>> grix-connector autostart [${t}] >>>
|
|
97
101
|
${e}
|
|
98
102
|
# <<< grix-connector autostart [${t}] <<<
|
|
99
|
-
`}function
|
|
103
|
+
`}function q(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 Et(t,e,n){let r="";try{r=await S(t,"utf8")}catch{}const i=Pt(e,n),a=q(e);let l;if(a.test(r))l=r.replace(a,`
|
|
100
104
|
${i}`).replace(/^\n+/,"");else{const o=r.length===0||r.endsWith(`
|
|
101
105
|
`)?"":`
|
|
102
|
-
`;l=`${r}${o}${i}`}l!==r&&(await k(c.dirname(t),{recursive:!0}),await $(t,l,{encoding:"utf8"}))}async function
|
|
103
|
-
`,{encoding:"utf8",mode:384});const
|
|
106
|
+
`;l=`${r}${o}${i}`}l!==r&&(await k(c.dirname(t),{recursive:!0}),await $(t,l,{encoding:"utf8"}))}async function kt(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 Ct(){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=x(t,o);await k(c.dirname(s),{recursive:!0});const u=W(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 Et(J(o),t,h),{definitionPath:s}},async start({serviceID:t,homeDir:e=d.homedir()}){const n=x(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),_(r.node_path,i,{env:{...process.env,[C]:r.root_dir}})},async stop({serviceID:t,homeDir:e=d.homedir()}){const n=x(t,e),r=E(n);if(!r)return;const i=O(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=x(t.serviceID,t.homeDir??d.homedir()),r=E(n);for(;r&&Date.now()<e;){const i=O(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=x(t,e),r=E(n);if(r){const i=O(r.root_dir);if(i>0&&I(i))try{process.kill(i,"SIGTERM")}catch{}}await y(n,{force:!0}),await kt(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=x(t,e),r=E(n);if(!r)return!1;const i=O(r.root_dir);return i>0&&I(i)}}}function vt(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 Nt(t=process.platform,e={}){return t==="darwin"?gt():t==="win32"?wt():e.systemdUserAvailable??vt()?yt():Ct()}export{pt as WINDOWS_WRAPPER_TEMPLATE_MARKER,ft as WINDOWS_WRAPPER_TEMPLATE_VERSION,ht as buildWindowsWrapperScript,j as collectServicePortEnv,Nt as getPlatformServiceAdapter,vt as isSystemdUserBusAvailable,kt as removeProfileAutostart,P as resolveWindowsWrapperPath,Et as upsertProfileAutostart};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grix-connector",
|
|
3
|
-
"version": "4.4.2-beta.
|
|
3
|
+
"version": "4.4.2-beta.2",
|
|
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",
|