grix-connector 4.6.10 → 4.7.1
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/adapter/agy/agy-adapter.js +8 -7
- package/dist/adapter/claude/claude-adapter.js +21 -21
- package/dist/assets/dsh-bridge/grix-dsh-bridge-4.7.1.tgz +0 -0
- package/dist/assets/dsh-bridge/manifest.json +6 -6
- package/dist/audit/raw-capture/capture-relay.js +3 -3
- package/dist/core/installer/npm-registry.js +4 -4
- package/dist/core/runtime/index.js +1 -1
- package/dist/core/runtime/orphan-cleanup.js +2 -0
- package/dist/core/upgrade/npm-upgrader.js +2 -2
- package/dist/grix.js +7 -7
- package/dist/mcp/stream-http/security.js +1 -1
- package/dist/service/legacy-state-heal.js +2 -0
- package/dist/service/platform-adapter.js +5 -5
- package/dist/service/service-manager.js +3 -3
- package/dist/service/service-paths.js +2 -2
- package/package.json +2 -2
- package/dist/assets/dsh-bridge/grix-dsh-bridge-4.6.10.tgz +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createHash as F}from"node:crypto";import h from"node:fs";import b from"node:os";import o from"node:path";import D from"node:process";import{mkdir as w}from"node:fs/promises";import{setTimeout as B}from"node:timers/promises";import{resolveRuntimePaths as S}from"../core/config/paths.js";import{inspectDaemonState as g}from"../runtime/service-state.js";import{isProcessRunning as H,runCommand as m,terminateProcessTree as T,waitForProcessExit as N}from"./process-control.js";import{isLockHolderIdentityVerified as k,readDaemonLock as P}from"../runtime/daemon-lock.js";import{ServiceInstallStore as q}from"./service-install-store.js";import{getPlatformServiceAdapter as M}from"./platform-adapter.js";import{captureLogCursor as v,formatLogDelta as _}from"./log-diagnostics.js";import{LAUNCHER_FILE as z,bootstrapVersionFromPackage as O,compareVersions as A,ensureLauncher as V,launcherPath as I,packagedLauncherPath as G,readLauncherTemplateVersion as J,readPackageVersionAt as E,readPointer as R,switchCurrent as U,versionEntry as C}from"../core/upgrade/version-store.js";import{buildServiceID as y,resolveWindowsServiceRuntimeDir as W,resolveServiceInstallRecordPath as K,resolveServiceStderrPath as Q,resolveServiceStdoutPath as X}from"./service-paths.js";function Y(L){try{return h.realpathSync(L)}catch{return L}}class Dt{adapter;platform;homeDir;uid;nodePath;cliPath;waitForExit;terminateTree;constructor(e){this.platform=e.platform??D.platform,this.homeDir=e.homeDir??b.homedir(),this.uid=e.uid??D.getuid?.()??0,this.nodePath=e.nodePath??D.execPath,this.cliPath=Y(e.cliPath),this.adapter=M(this.platform),this.waitForExit=e.processControl?.waitForExit??N,this.terminateTree=e.processControl?.terminateTree??T}normalizeRootDir(e){return o.resolve(String(e??"").trim())}resolveLocalServiceBaseDir(){if(this.platform==="darwin")return o.join(this.homeDir,"Library","Application Support","grix-connector");if(this.platform==="win32"){const e=String(D.env.LOCALAPPDATA??"").trim();return o.join(e&&o.isAbsolute(e)?e:o.join(this.homeDir,"AppData","Local"),"grix-connector")}return null}resolveServiceRuntimeDir(e){const t=this.resolveLocalServiceBaseDir();return t?this.platform==="win32"?W(this.normalizeRootDir(e),D.env,this.homeDir):o.join(t,"runtime"):null}resolveServiceCliPath(e){const t=this.resolveServiceRuntimeDir(e);return t?I(t):this.cliPath}resolveSourcePackageDir(){return o.dirname(o.dirname(this.cliPath))}async adoptLauncher(e){const t=this.normalizeRootDir(e),r=this.resolveServiceRuntimeDir(t);if(!r)return!1;const s=await this.createStore(t).load();return!s||s.cli_path===this.resolveServiceCliPath(t)&&this.isLauncherStoreUsable(r)?!1:(await this.refreshDescriptor(t,s),!0)}isLauncherStoreUsable(e){if(!h.existsSync(I(e)))return!1;const t=R(e,"current");return!!t&&h.existsSync(C(e,t))}prepareServiceRuntime(e){const t=this.resolveServiceRuntimeDir(e);if(!t)return;const r=this.resolveSourcePackageDir();h.mkdirSync(t,{recursive:!0});const s=E(r);if(!s)throw new Error(`Cannot read package version at ${r} (entry ${this.cliPath}); refusing to install the service`);if(!V(t,r))throw new Error(`Package at ${r} does not ship ${z}; refusing to point the service at it`);const i=R(t,"current");if((!i||!h.existsSync(C(t,i))||A(s,i)>0)&&(O(t,r,s),U(t,s)),this.platform==="win32"||this.platform==="darwin"){const a=o.join(r,"scripts","upgrade-guardian.mjs");if(h.existsSync(a)){const d=o.join(this.normalizeRootDir(e),"bin"),c=o.join(d,"upgrade-guardian.mjs"),n=o.join(d,"upgrade-guardian.fallback.mjs"),l=`${c}.tmp-${D.pid}`;h.mkdirSync(d,{recursive:!0});try{h.copyFileSync(a,l),h.renameSync(l,c),h.copyFileSync(a,n)}finally{h.rmSync(l,{force:!0})}}if(this.platform==="darwin"){const d=o.join(r,"scripts","upgrade-guardian.sh");if(h.existsSync(d)){const c=o.join(this.normalizeRootDir(e),"bin","upgrade-guardian.sh"),n=`${c}.tmp-${D.pid}`;try{h.copyFileSync(d,n),h.chmodSync(n,493),h.renameSync(n,c)}finally{h.rmSync(n,{force:!0})}}}}}buildDescriptor(e,t,r=""){const s=this.normalizeRootDir(e),i=this.resolveServiceCliPath(s);return{schema_version:1,platform:this.platform,service_id:y(s,this.platform),node_path:this.nodePath,cli_path:i,cli_hash:this.computeServiceHash(i)??"",definition_path:r,config_dir:t??"",installed_at:0,updated_at:0}}createStore(e){return new q(K(this.normalizeRootDir(e)))}toAdapterPayload(e,t){return{serviceID:e.service_id,nodePath:e.node_path,cliPath:e.cli_path,configDir:e.config_dir||void 0,rootDir:this.normalizeRootDir(t),environmentPath:this.buildServiceEnvironmentPath()}}async resolveServiceLogPaths(e){const t=this.resolveLocalServiceBaseDir();if(t){const r=o.join(this.platform==="darwin"?o.join(this.homeDir,"Library","Logs","grix-connector"):o.join(t,"logs"),y(this.normalizeRootDir(e),this.platform));return await w(r,{recursive:!0}),{stdoutPath:o.join(r,"daemon.out.log"),stderrPath:o.join(r,"daemon.err.log")}}return await w(o.join(e,"service"),{recursive:!0}),{stdoutPath:X(e),stderrPath:Q(e)}}buildServiceEnvironmentPath(){const e=[o.dirname(this.nodePath),...this.platform==="darwin"?["/opt/homebrew/bin"]:[],"/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"],t=String(D.env.PATH??"").split(o.delimiter).filter(i=>i&&o.isAbsolute(i)).filter(i=>!i.includes("/node_modules/.bin")).filter(i=>!i.includes("/node-gyp-bin")),r=[],s=new Set;for(const i of[...e,...t]){if(s.has(i))continue;if(s.add(i),[...r,i].join(o.delimiter).length>2048)break;r.push(i)}return r.join(o.delimiter)}toStartParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toStopParams(e){return{serviceID:e.service_id,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toRestartParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toUninstallParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}async loadDescriptor(e){const t=this.createStore(e),r=await t.load();if(!r)throw new Error("\u540E\u53F0\u670D\u52A1\u8FD8\u6CA1\u6709\u5B89\u88C5\uFF0C\u8BF7\u5148\u6267\u884C grix-connector start\uFF08\u4F1A\u81EA\u52A8\u5B89\u88C5\u5E76\u542F\u52A8\u670D\u52A1\uFF09\u3002");return{store:t,descriptor:r}}isDescriptorCurrent(e,t){if(t.node_path!==this.nodePath||t.cli_path!==this.resolveServiceCliPath(e)||!t.cli_hash)return!1;const r=this.computeServiceHash(t.cli_path),s=this.computeServiceHash(this.cliPath);return r!==null&&s!==null&&r===t.cli_hash&&s===t.cli_hash}computeFileHash(e){try{const t=h.readFileSync(e);return F("sha256").update(t).digest("hex")}catch{return null}}computeServiceHash(e){return this.resolveLocalServiceBaseDir()?this.computeLauncherHash(e):this.computeFileHash(e)}computeLauncherHash(e){try{const t=this.resolveSourcePackageDir(),r=E(t)??"",s=o.basename(e)===z,i=s?o.dirname(e):null,a=s?e:G(t);if(!a)return null;const d=J(a);if(d<0)return null;let c=!0;if(i){const n=R(i,"current");c=!!n&&h.existsSync(C(i,n))&&A(n,r)>=0}return c?F("sha256").update(`launcher:${d}`).update(`source:${r}`).digest("hex"):null}catch{return null}}computeRuntimeDirHash(e){try{const t=o.dirname(e),r=F("sha256"),s=a=>{const d=h.readdirSync(a,{withFileTypes:!0}).sort((c,n)=>c.name.localeCompare(n.name));for(const c of d){const n=o.join(a,c.name);r.update(o.relative(t,n)),c.isDirectory()?s(n):c.isFile()&&r.update(h.readFileSync(n))}};s(t);const i=o.join(o.dirname(t),"package.json");return h.existsSync(i)&&(r.update("package.json"),r.update(h.readFileSync(i))),r.digest("hex")}catch{return null}}async refreshDescriptor(e,t){const r=this.normalizeRootDir(e);await w(o.join(r,"service"),{recursive:!0}),this.prepareServiceRuntime(r);const s=this.resolveServiceCliPath(r),i={...t,platform:this.platform,service_id:t.service_id||y(r,this.platform),node_path:this.nodePath,cli_path:s,cli_hash:this.computeServiceHash(s)??"",config_dir:t.config_dir},a=await this.resolveServiceLogPaths(r),d=await this.adapter.install({...this.toAdapterPayload(i,r),stdoutPath:a.stdoutPath,stderrPath:a.stderrPath,homeDir:this.homeDir,uid:this.uid,runCommand:m}),c={...i,installed_at:t.installed_at,definition_path:d?.definitionPath||i.definition_path,updated_at:Date.now()};return await this.createStore(r).save(c),c}async resolveActiveDescriptor(e){const{descriptor:t}=await this.loadDescriptor(e);return this.isDescriptorCurrent(e,t)?t:this.refreshDescriptor(e,t)}async discoverConflictingServices(e){const t=this.normalizeRootDir(e),r=y(t,this.platform);return(await this.adapter.discoverServices({homeDir:this.homeDir,runCommand:m})).filter(i=>i.serviceID!==r)}async cleanupConflictingServices(e){const t=await this.discoverConflictingServices(e);if(t.length>0){const s=t.map(i=>i.serviceID).join(", ");console.log(`\u53D1\u73B0 ${t.length} \u4E2A\u6B8B\u7559\u670D\u52A1\uFF0C\u6B63\u5728\u68C0\u67E5: ${s}`)}let r=0;for(const s of t){if(await this.adapter.isServiceLoaded({serviceID:s.serviceID,uid:this.uid,homeDir:this.homeDir,runCommand:m})){console.log(`\u8DF3\u8FC7\u6B63\u5728\u8FD0\u884C\u7684\u670D\u52A1: ${s.serviceID}`);continue}try{await this.adapter.stop({serviceID:s.serviceID,uid:this.uid,homeDir:this.homeDir,runCommand:m})}catch{}try{await this.adapter.uninstall({serviceID:s.serviceID,definitionPath:s.definitionPath,uid:this.uid,homeDir:this.homeDir,runCommand:m}),r++}catch{}}return r}captureDaemonBaseline(e){return{status:g(e.daemonStatusFile),lock:P(e.daemonLockFile)}}isDaemonReady(e,t,r){const s=g(e.daemonStatusFile),i=P(e.daemonLockFile);if(!s.running||s.state!=="running"||s.pid<=0||!i||i.pid!==s.pid||!H(i.pid)||typeof i.root_dir!="string"||o.resolve(i.root_dir)!==o.resolve(e.rootDir)||typeof i.instance_id!="string"||i.instance_id.length===0||s.instance_id!==i.instance_id)return!1;const a=s.pid!==t.status.pid||s.state!==t.status.state||s.updated_at!==t.status.updated_at||s.instance_id!==t.status.instance_id,d=!t.lock||i.pid!==t.lock.pid||i.acquired_at!==t.lock.acquired_at||i.instance_id!==t.lock.instance_id,c=a&&d,n=t.status.state==="starting"&&t.status.instance_id===i.instance_id&&t.lock?.pid===i.pid&&t.lock.instance_id===i.instance_id&&s.instance_id===i.instance_id&&s.updated_at!==t.status.updated_at,l=t.lock?.pid===i.pid&&t.lock.instance_id===i.instance_id&&t.lock.acquired_at===i.acquired_at&&(t.status.pid!==i.pid||t.status.instance_id!==i.instance_id||t.status.state!=="running")&&s.pid===i.pid&&s.instance_id===i.instance_id&&s.state==="running"&&s.updated_at!==t.status.updated_at;return!k(i)&&!c&&!n&&!l?!1:r?c||n||l:!0}canForceTerminateDaemon(e,t){const r=P(e.daemonLockFile);return t>0&&r!==null&&r.pid===t&&typeof r.root_dir=="string"&&o.resolve(r.root_dir)===o.resolve(e.rootDir)&&k(r)}defaultDaemonStartTimeoutMs(){return this.platform==="darwin"?5e4:2e4}async waitForDaemonStarted(e,t={}){const r=t.timeoutMs??this.defaultDaemonStartTimeoutMs(),s=t.baseline??this.captureDaemonBaseline(e),i=t.requireNewDaemon??!1,a=t.stdoutLogFile??e.stdoutLogFile,d=t.stderrLogFile??e.stderrLogFile,c=t.stdoutLogCursor??v(a),n=t.stderrLogCursor??v(d),l=Date.now();for(;Date.now()-l<r;){if(this.isDaemonReady(e,s,i))return;const f=g(e.daemonStatusFile);if(f.state==="failed"&&(s.status.state!=="failed"||f.pid!==s.status.pid||f.updated_at!==s.status.updated_at||f.instance_id!==s.status.instance_id)){const x=P(e.daemonLockFile),$=["daemon start failed",`status=${JSON.stringify(f)}`,`lock=${x?JSON.stringify(x):"missing"}`,_("stderr",d,n),_("stdout",a,c)].filter(Boolean);throw new Error($.join(`
|
|
2
|
-
`))}await B(100)}const p=
|
|
3
|
-
`))}async install(e){const t=this.normalizeRootDir(e.rootDir);await this.cleanupConflictingServices(t),await
|
|
1
|
+
import{createHash as F}from"node:crypto";import l from"node:fs";import T from"node:os";import o from"node:path";import D from"node:process";import{mkdir as _}from"node:fs/promises";import{setTimeout as B}from"node:timers/promises";import{resolveRuntimePaths as P}from"../core/config/paths.js";import{inspectDaemonState as g}from"../runtime/service-state.js";import{isProcessRunning as N,runCommand as m,terminateProcessTree as M,waitForProcessExit as W}from"./process-control.js";import{isLockHolderIdentityVerified as k,readDaemonLock as w}from"../runtime/daemon-lock.js";import{ServiceInstallStore as q}from"./service-install-store.js";import{getPlatformServiceAdapter as O}from"./platform-adapter.js";import{captureLogCursor as v,formatLogDelta as y}from"./log-diagnostics.js";import{LAUNCHER_FILE as x,bootstrapVersionFromPackage as U,compareVersions as j,ensureLauncher as V,launcherPath as z,packagedLauncherPath as G,readLauncherTemplateVersion as J,readPackageVersionAt as A,readPointer as E,switchCurrent as X,versionEntry as I}from"../core/upgrade/version-store.js";import{buildServiceID as S,parseExecStartWords as K,parseProgramArgumentsFromPlistXML as Q,resolveLinuxUserUnitPath as Y,resolveMacOSLaunchAgentPath as Z,resolveWindowsServiceRuntimeDir as tt,resolveServiceInstallRecordPath as et,resolveServiceStderrPath as it,resolveServiceStdoutPath as rt}from"./service-paths.js";import{resolveWindowsStartupShortcutPath as st,resolveWindowsWrapperPath as $}from"./platform-adapter.js";import{readInstalledWrapperTemplate as at}from"./windows-wrapper-migration.js";import{appendLegacyHealLog as ot,isLauncherStoreUsable as b,parseWrapperCliPath as nt,planLegacyStateHeal as ct}from"./legacy-state-heal.js";function dt(L){try{return l.realpathSync(L)}catch{return L}}class jt{adapter;platform;homeDir;uid;nodePath;cliPath;waitForExit;terminateTree;constructor(e){this.platform=e.platform??D.platform,this.homeDir=e.homeDir??T.homedir(),this.uid=e.uid??D.getuid?.()??0,this.nodePath=e.nodePath??D.execPath,this.cliPath=dt(e.cliPath),this.adapter=O(this.platform),this.waitForExit=e.processControl?.waitForExit??W,this.terminateTree=e.processControl?.terminateTree??M}normalizeRootDir(e){return o.resolve(String(e??"").trim())}resolveLocalServiceBaseDir(){if(this.platform==="darwin")return o.join(this.homeDir,"Library","Application Support","grix-connector");if(this.platform==="win32"){const e=String(D.env.LOCALAPPDATA??"").trim();return o.join(e&&o.isAbsolute(e)?e:o.join(this.homeDir,"AppData","Local"),"grix-connector")}return null}resolveServiceRuntimeDir(e){const t=this.resolveLocalServiceBaseDir();return t?this.platform==="win32"?tt(this.normalizeRootDir(e),D.env,this.homeDir):o.join(t,"runtime"):null}resolveServiceCliPath(e){const t=this.resolveServiceRuntimeDir(e);return t?z(t):this.cliPath}resolveSourcePackageDir(){return o.dirname(o.dirname(this.cliPath))}async adoptLauncher(e){const t=this.normalizeRootDir(e),r=this.resolveServiceRuntimeDir(t);if(!r)return!1;const i=await this.createStore(t).load();return!i||i.cli_path===this.resolveServiceCliPath(t)&&b(r)?!1:(await this.refreshDescriptor(t,i),!0)}prepareServiceRuntime(e){const t=this.resolveServiceRuntimeDir(e);if(!t)return;const r=this.resolveSourcePackageDir();l.mkdirSync(t,{recursive:!0});const i=A(r);if(!i)throw new Error(`Cannot read package version at ${r} (entry ${this.cliPath}); refusing to install the service`);if(!V(t,r))throw new Error(`Package at ${r} does not ship ${x}; refusing to point the service at it`);const s=E(t,"current");if((!s||!l.existsSync(I(t,s))||j(i,s)>0)&&(U(t,r,i),X(t,i)),this.platform==="win32"||this.platform==="darwin"){const a=o.join(r,"scripts","upgrade-guardian.mjs");if(l.existsSync(a)){const n=o.join(this.normalizeRootDir(e),"bin"),d=o.join(n,"upgrade-guardian.mjs"),c=o.join(n,"upgrade-guardian.fallback.mjs"),h=`${d}.tmp-${D.pid}`;l.mkdirSync(n,{recursive:!0});try{l.copyFileSync(a,h),l.renameSync(h,d),l.copyFileSync(a,c)}finally{l.rmSync(h,{force:!0})}}if(this.platform==="darwin"){const n=o.join(r,"scripts","upgrade-guardian.sh");if(l.existsSync(n)){const d=o.join(this.normalizeRootDir(e),"bin","upgrade-guardian.sh"),c=`${d}.tmp-${D.pid}`;try{l.copyFileSync(n,c),l.chmodSync(c,493),l.renameSync(c,d)}finally{l.rmSync(c,{force:!0})}}}}}buildDescriptor(e,t,r=""){const i=this.normalizeRootDir(e),s=this.resolveServiceCliPath(i);return{schema_version:1,platform:this.platform,service_id:S(i,this.platform),node_path:this.nodePath,cli_path:s,cli_hash:this.computeServiceHash(s)??"",definition_path:r,config_dir:t??"",installed_at:0,updated_at:0}}createStore(e){return new q(et(this.normalizeRootDir(e)))}toAdapterPayload(e,t){return{serviceID:e.service_id,nodePath:e.node_path,cliPath:e.cli_path,configDir:e.config_dir||void 0,rootDir:this.normalizeRootDir(t),environmentPath:this.buildServiceEnvironmentPath()}}async resolveServiceLogPaths(e){const t=this.resolveLocalServiceBaseDir();if(t){const r=o.join(this.platform==="darwin"?o.join(this.homeDir,"Library","Logs","grix-connector"):o.join(t,"logs"),S(this.normalizeRootDir(e),this.platform));return await _(r,{recursive:!0}),{stdoutPath:o.join(r,"daemon.out.log"),stderrPath:o.join(r,"daemon.err.log")}}return await _(o.join(e,"service"),{recursive:!0}),{stdoutPath:rt(e),stderrPath:it(e)}}buildServiceEnvironmentPath(){const e=[o.dirname(this.nodePath),...this.platform==="darwin"?["/opt/homebrew/bin"]:[],"/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"],t=String(D.env.PATH??"").split(o.delimiter).filter(s=>s&&o.isAbsolute(s)).filter(s=>!s.includes("/node_modules/.bin")).filter(s=>!s.includes("/node-gyp-bin")),r=[],i=new Set;for(const s of[...e,...t]){if(i.has(s))continue;if(i.add(s),[...r,s].join(o.delimiter).length>2048)break;r.push(s)}return r.join(o.delimiter)}toStartParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toStopParams(e){return{serviceID:e.service_id,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toRestartParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}toUninstallParams(e){return{serviceID:e.service_id,definitionPath:e.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:m}}async loadDescriptor(e){const t=this.createStore(e),r=await t.load();if(!r)throw new Error("\u540E\u53F0\u670D\u52A1\u8FD8\u6CA1\u6709\u5B89\u88C5\uFF0C\u8BF7\u5148\u6267\u884C grix-connector start\uFF08\u4F1A\u81EA\u52A8\u5B89\u88C5\u5E76\u542F\u52A8\u670D\u52A1\uFF09\u3002");return{store:t,descriptor:r}}isDescriptorCurrent(e,t){if(t.node_path!==this.nodePath||t.cli_path!==this.resolveServiceCliPath(e)||!t.cli_hash)return!1;const r=this.computeServiceHash(t.cli_path),i=this.computeServiceHash(this.cliPath);return r!==null&&i!==null&&r===t.cli_hash&&i===t.cli_hash}computeFileHash(e){try{const t=l.readFileSync(e);return F("sha256").update(t).digest("hex")}catch{return null}}computeServiceHash(e){return this.resolveLocalServiceBaseDir()?this.computeLauncherHash(e):this.computeFileHash(e)}computeLauncherHash(e){try{const t=this.resolveSourcePackageDir(),r=A(t)??"",i=o.basename(e)===x,s=i?o.dirname(e):null,a=i?e:G(t);if(!a)return null;const n=J(a);if(n<0)return null;let d=!0;if(s){const c=E(s,"current");d=!!c&&l.existsSync(I(s,c))&&j(c,r)>=0}return d?F("sha256").update(`launcher:${n}`).update(`source:${r}`).digest("hex"):null}catch{return null}}computeRuntimeDirHash(e){try{const t=o.dirname(e),r=F("sha256"),i=a=>{const n=l.readdirSync(a,{withFileTypes:!0}).sort((d,c)=>d.name.localeCompare(c.name));for(const d of n){const c=o.join(a,d.name);r.update(o.relative(t,c)),d.isDirectory()?i(c):d.isFile()&&r.update(l.readFileSync(c))}};i(t);const s=o.join(o.dirname(t),"package.json");return l.existsSync(s)&&(r.update("package.json"),r.update(l.readFileSync(s))),r.digest("hex")}catch{return null}}async refreshDescriptor(e,t){const r=this.normalizeRootDir(e);await _(o.join(r,"service"),{recursive:!0}),this.prepareServiceRuntime(r);const i=this.resolveServiceCliPath(r),s={...t,platform:this.platform,service_id:t.service_id||S(r,this.platform),node_path:this.nodePath,cli_path:i,cli_hash:this.computeServiceHash(i)??"",config_dir:t.config_dir},a=await this.resolveServiceLogPaths(r),n=await this.adapter.install({...this.toAdapterPayload(s,r),stdoutPath:a.stdoutPath,stderrPath:a.stderrPath,homeDir:this.homeDir,uid:this.uid,runCommand:m}),d={...s,installed_at:t.installed_at,definition_path:n?.definitionPath||s.definition_path,updated_at:Date.now()};return await this.createStore(r).save(d),d}async resolveActiveDescriptor(e){const{descriptor:t}=await this.loadDescriptor(e);return this.isDescriptorCurrent(e,t)?t:this.refreshDescriptor(e,t)}async discoverConflictingServices(e){const t=this.normalizeRootDir(e),r=S(t,this.platform);return(await this.adapter.discoverServices({homeDir:this.homeDir,runCommand:m})).filter(s=>s.serviceID!==r)}async cleanupConflictingServices(e){const t=await this.discoverConflictingServices(e);if(t.length>0){const i=t.map(s=>s.serviceID).join(", ");console.log(`\u53D1\u73B0 ${t.length} \u4E2A\u6B8B\u7559\u670D\u52A1\uFF0C\u6B63\u5728\u68C0\u67E5: ${i}`)}let r=0;for(const i of t){if(await this.adapter.isServiceLoaded({serviceID:i.serviceID,uid:this.uid,homeDir:this.homeDir,runCommand:m})){console.log(`\u8DF3\u8FC7\u6B63\u5728\u8FD0\u884C\u7684\u670D\u52A1: ${i.serviceID}`);continue}try{await this.adapter.stop({serviceID:i.serviceID,uid:this.uid,homeDir:this.homeDir,runCommand:m})}catch{}try{await this.adapter.uninstall({serviceID:i.serviceID,definitionPath:i.definitionPath,uid:this.uid,homeDir:this.homeDir,runCommand:m}),r++}catch{}}return r}captureDaemonBaseline(e){return{status:g(e.daemonStatusFile),lock:w(e.daemonLockFile)}}isDaemonReady(e,t,r){const i=g(e.daemonStatusFile),s=w(e.daemonLockFile);if(!i.running||i.state!=="running"||i.pid<=0||!s||s.pid!==i.pid||!N(s.pid)||typeof s.root_dir!="string"||o.resolve(s.root_dir)!==o.resolve(e.rootDir)||typeof s.instance_id!="string"||s.instance_id.length===0||i.instance_id!==s.instance_id)return!1;const a=i.pid!==t.status.pid||i.state!==t.status.state||i.updated_at!==t.status.updated_at||i.instance_id!==t.status.instance_id,n=!t.lock||s.pid!==t.lock.pid||s.acquired_at!==t.lock.acquired_at||s.instance_id!==t.lock.instance_id,d=a&&n,c=t.status.state==="starting"&&t.status.instance_id===s.instance_id&&t.lock?.pid===s.pid&&t.lock.instance_id===s.instance_id&&i.instance_id===s.instance_id&&i.updated_at!==t.status.updated_at,h=t.lock?.pid===s.pid&&t.lock.instance_id===s.instance_id&&t.lock.acquired_at===s.acquired_at&&(t.status.pid!==s.pid||t.status.instance_id!==s.instance_id||t.status.state!=="running")&&i.pid===s.pid&&i.instance_id===s.instance_id&&i.state==="running"&&i.updated_at!==t.status.updated_at;return!k(s)&&!d&&!c&&!h?!1:r?d||c||h:!0}canForceTerminateDaemon(e,t){const r=w(e.daemonLockFile);return t>0&&r!==null&&r.pid===t&&typeof r.root_dir=="string"&&o.resolve(r.root_dir)===o.resolve(e.rootDir)&&k(r)}defaultDaemonStartTimeoutMs(){return this.platform==="darwin"?5e4:2e4}async waitForDaemonStarted(e,t={}){const r=t.timeoutMs??this.defaultDaemonStartTimeoutMs(),i=t.baseline??this.captureDaemonBaseline(e),s=t.requireNewDaemon??!1,a=t.stdoutLogFile??e.stdoutLogFile,n=t.stderrLogFile??e.stderrLogFile,d=t.stdoutLogCursor??v(a),c=t.stderrLogCursor??v(n),h=Date.now();for(;Date.now()-h<r;){if(this.isDaemonReady(e,i,s))return;const f=g(e.daemonStatusFile);if(f.state==="failed"&&(i.status.state!=="failed"||f.pid!==i.status.pid||f.updated_at!==i.status.updated_at||f.instance_id!==i.status.instance_id)){const R=w(e.daemonLockFile),H=["daemon start failed",`status=${JSON.stringify(f)}`,`lock=${R?JSON.stringify(R):"missing"}`,y("stderr",n,c),y("stdout",a,d)].filter(Boolean);throw new Error(H.join(`
|
|
2
|
+
`))}await B(100)}const p=w(e.daemonLockFile),u=g(e.daemonStatusFile),C=[`daemon start timeout (${r}ms)`,`status=${JSON.stringify(u)}`,`lock=${p?JSON.stringify(p):"missing"}`,y("stderr",n,c),y("stdout",a,d)].filter(Boolean);throw new Error(C.join(`
|
|
3
|
+
`))}readDefinitionCliPath(e,t){const r=t.service_id||S(e,this.platform),i=s=>{try{return l.readFileSync(s,"utf8")}catch{return null}};if(this.adapter.kind==="launchd"){const s=i(t.definition_path||Z(r,this.homeDir));return s?Q(s)[1]??null:null}if(this.adapter.kind==="systemd-user"){const s=i(t.definition_path||Y(r,this.homeDir));return s?K(s)[1]??null:null}if(this.adapter.kind==="task-scheduler"){const s=i($(r,this.homeDir));return s?nt(s):null}return null}observeLegacyState(e,t){const r=this.resolveServiceRuntimeDir(e),i=t?.service_id||S(e,this.platform);return{platform:this.platform,record:t,expectedLauncherPath:r?z(r):null,launcherStoreUsable:r?b(r):!1,nodePathExists:!!t?.node_path&&l.existsSync(t.node_path),cliPathExists:!!t?.cli_path&&l.existsSync(t.cli_path),definitionCliPath:t?this.readDefinitionCliPath(e,t):null,upgradePending:l.existsSync(o.join(e,"data","upgrade-pending.json")),windowsWrapperTemplate:this.platform==="win32"?at($(i,this.homeDir)):-1,windowsStartupShortcutExists:this.platform==="win32"&&l.existsSync(st(i,this.homeDir))}}async healLegacyState(e){const t=this.normalizeRootDir(e.rootDir),r=this.createStore(t),i=await r.load(),s=ct(this.observeLegacyState(t,i));if(!s.heal||!i)return{healed:!1,reasons:[]};const a=n=>{ot(t,n),console.log(`\u9057\u7559\u72B6\u6001\u81EA\u6108: ${n}`)};for(const n of s.reasons)a(`detected ${n}`);try{await this.stopServiceAndDaemon(t,i),a("stopped the legacy service and daemon")}catch(n){a(`stop failed (continuing): ${n instanceof Error?n.message:n}`)}try{await this.adapter.uninstall(this.toUninstallParams(i)),a("removed the legacy service definition")}catch(n){a(`uninstall failed (continuing): ${n instanceof Error?n.message:n}`)}return await r.clear(),a("cleared the install record; rebuilding via install"),{healed:!0,reasons:s.reasons,configDir:i.config_dir||void 0}}async install(e){const t=this.normalizeRootDir(e.rootDir);await this.cleanupConflictingServices(t),await _(o.join(t,"service"),{recursive:!0}),this.prepareServiceRuntime(t);const r=P(t),i=this.captureDaemonBaseline(r),s=this.buildDescriptor(t,e.configDir),a=await this.resolveServiceLogPaths(t),n=v(a.stdoutPath),d=v(a.stderrPath),c=await this.adapter.isServiceLoaded({serviceID:s.service_id,uid:this.uid,homeDir:this.homeDir,runCommand:m}),h=await this.adapter.install({...this.toAdapterPayload(s,t),stdoutPath:a.stdoutPath,stderrPath:a.stderrPath,homeDir:this.homeDir,uid:this.uid,runCommand:m}),p={...s,definition_path:h?.definitionPath??"",installed_at:Date.now(),updated_at:Date.now()};return await this.createStore(t).save(p),c?await this.adapter.restart(this.toRestartParams(p)):await this.adapter.start(this.toStartParams(p)),await this.waitForDaemonStarted(r,{baseline:i,requireNewDaemon:!0,stdoutLogFile:a.stdoutPath,stderrLogFile:a.stderrPath,stdoutLogCursor:n,stderrLogCursor:d}),this.status({rootDir:t})}async start(e){const t=this.normalizeRootDir(e.rootDir);await this.cleanupConflictingServices(t);const r=P(t),i=this.captureDaemonBaseline(r),s=i.status,a=v(r.stdoutLogFile),n=v(r.stderrLogFile),c=await this.createStore(t).load();if(s.running&&c&&this.isDescriptorCurrent(t,c)){if(s.state==="starting"){const u=i.lock;if(u!==null&&u.pid===s.pid&&typeof u.root_dir=="string"&&o.resolve(u.root_dir)===o.resolve(r.rootDir)&&typeof u.instance_id=="string"&&u.instance_id.length>0&&s.instance_id===u.instance_id&&k(u)){const f=await this.resolveServiceLogPaths(t);return await this.waitForDaemonStarted(r,{baseline:i,stdoutLogFile:f.stdoutPath,stderrLogFile:f.stderrPath,stdoutLogCursor:a,stderrLogCursor:n}),this.status({rootDir:t})}}if(this.isDaemonReady(r,i,!1))return this.status({rootDir:t})}const h=c?this.isDescriptorCurrent(t,c)&&s.running?c:await this.refreshDescriptor(t,c):await this.resolveActiveDescriptor(t),p=await this.resolveServiceLogPaths(t);try{s.running?await this.adapter.restart(this.toRestartParams(h)):await this.adapter.start(this.toStartParams(h))}catch(u){if(u instanceof Error&&u.message.includes("plist missing"))await this.adapter.install({...this.toAdapterPayload(h,t),stdoutPath:p.stdoutPath,stderrPath:p.stderrPath,homeDir:this.homeDir,uid:this.uid,runCommand:m}),await this.adapter.start(this.toStartParams(h));else throw u}return await this.waitForDaemonStarted(r,{baseline:i,requireNewDaemon:!0,stdoutLogFile:p.stdoutPath,stderrLogFile:p.stderrPath,stdoutLogCursor:a,stderrLogCursor:n}),this.status({rootDir:t})}async stopServiceAndDaemon(e,t){const r=P(e),i=g(r.daemonStatusFile);await this.adapter.stop(this.toStopParams(t)),!(!i.running||!i.pid||await this.waitForExit(i.pid,{timeoutMs:5e3}))&&this.canForceTerminateDaemon(r,i.pid)&&(await this.terminateTree(i.pid,{platform:this.platform,runCommandImpl:m}),await this.waitForExit(i.pid,{timeoutMs:5e3}))}async stop(e){const t=this.normalizeRootDir(e.rootDir),{descriptor:r}=await this.loadDescriptor(t);return await this.stopServiceAndDaemon(t,r),this.status({rootDir:t})}async restart(e){const t=this.normalizeRootDir(e.rootDir);await this.cleanupConflictingServices(t);const r=await this.resolveActiveDescriptor(t),i=P(t),s=this.captureDaemonBaseline(i),a=await this.resolveServiceLogPaths(t),n=v(a.stdoutPath),d=v(a.stderrPath);try{await this.adapter.restart(this.toRestartParams(r))}catch(c){if(c instanceof Error&&c.message.includes("plist missing"))await this.adapter.install({...this.toAdapterPayload(r,t),stdoutPath:a.stdoutPath,stderrPath:a.stderrPath,homeDir:this.homeDir,uid:this.uid,runCommand:m}),await this.adapter.start(this.toStartParams(r));else throw c}return await this.waitForDaemonStarted(i,{baseline:s,requireNewDaemon:!0,stdoutLogFile:a.stdoutPath,stderrLogFile:a.stderrPath,stdoutLogCursor:n,stderrLogCursor:d}),this.status({rootDir:t})}async uninstall(e){const t=this.normalizeRootDir(e.rootDir),r=this.createStore(t),i=await r.load();return i&&(await this.adapter.uninstall(this.toUninstallParams(i)),await r.clear()),this.status({rootDir:t})}async status(e){const t=this.normalizeRootDir(e.rootDir),i=await this.createStore(t).load(),s=P(t),a=g(s.daemonStatusFile);return i?{installed:!0,install_state:this.isDescriptorCurrent(t,i)?"current":"stale",service_kind:this.adapter.kind,service_id:i.service_id,definition_path:i.definition_path,root_dir:t,daemon_state:a.state,pid:a.pid,connection_state:a.connection_state,updated_at:a.updated_at,reason:a.reason}:{installed:!1,install_state:"missing",service_kind:this.adapter.kind,root_dir:t,daemon_state:a.state,pid:a.pid,reason:a.reason}}}export{jt as ServiceManager};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createHash as d}from"node:crypto";import a from"node:os";import i from"node:path";import{normalizeString as x}from"../core/util/normalize-string.js";const
|
|
2
|
-
`:
|
|
1
|
+
import{createHash as d}from"node:crypto";import a from"node:os";import i from"node:path";import{normalizeString as x}from"../core/util/normalize-string.js";const f="com.dhfpub.grix-connector.daemon.",p="grix-connector-daemon-",m="GrixConnectorDaemon-";function h(e){return d("sha1").update(x(e)||"default").digest("hex").slice(0,12)}function v(e,r=process.platform){const t=h(e);return r==="win32"?`${m}${t}`:r==="darwin"?`${f}${t}`:`${p}${t}`}function E(e=process.platform){return e==="win32"?m:e==="darwin"?f:p}function j(e,r=process.env,t=a.homedir()){const o=String(r.LOCALAPPDATA??"").trim(),s=o&&i.isAbsolute(o)?o:i.join(t,"AppData","Local");return i.join(s,"grix-connector","runtimes",v(i.resolve(e),"win32"))}function g(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"')}function D(e){const r=[...e.matchAll(/<string>([^<]+)<\/string>/g)].map(t=>g(t[1]));for(let t=0;t<r.length-1;t+=1)if(r[t]==="--config-dir")return r[t+1];return null}function L(e){const r=e.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/);return r?[...r[1].matchAll(/<string>([^<]*)<\/string>/g)].map(t=>g(t[1])):[]}function S(e){const r=e.match(/^ExecStart=(.*)$/m)?.[1];if(!r)return[];const t=[];let o="",s=null,u=!1,c=!1;const l=()=>{c&&(t.push(o.replace(/\$\$/g,"$").replace(/%%/g,"%")),o="",c=!1)};for(const n of r){if(u){o+=n==="n"?`
|
|
2
|
+
`:n==="r"?"\r":n==="t"?" ":n,u=!1,c=!0;continue}if(n==="\\"){u=!0,c=!0;continue}if(s!==null){n===s?s=null:o+=n,c=!0;continue}if(n==="'"||n==='"'){s=n,c=!0;continue}if(/\s/.test(n)){l();continue}o+=n,c=!0}return u&&(o+="\\"),l(),t}function R(e){const r=S(e),t=r.indexOf("--config-dir");return t>=0?r[t+1]??null:null}function b(e){return i.join(e,"daemon-service.json")}function w(e){return i.join(e,"service","daemon.out.log")}function C(e){return i.join(e,"service","daemon.err.log")}function y(e,r){return i.join(r??a.homedir(),"Library","LaunchAgents",`${e}.plist`)}function F(e,r){return i.join(r??a.homedir(),".config","systemd","user",`${e}.service`)}function X(e,r){return i.join(r??a.homedir(),".grix","service",`${e}.bare.json`)}export{f as SERVICE_PREFIX_DARWIN,p as SERVICE_PREFIX_LINUX,m as SERVICE_PREFIX_WIN32,v as buildServiceID,E as getServicePrefix,D as parseConfigDirFromPlistXML,R as parseConfigDirFromSystemdUnit,S as parseExecStartWords,L as parseProgramArgumentsFromPlistXML,X as resolveBareDaemonMarkerPath,F as resolveLinuxUserUnitPath,y as resolveMacOSLaunchAgentPath,b as resolveServiceInstallRecordPath,C as resolveServiceStderrPath,w as resolveServiceStdoutPath,j as resolveWindowsServiceRuntimeDir};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grix-connector",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.1",
|
|
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",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"postinstall": "node scripts/install-guardian.mjs",
|
|
28
28
|
"prepublishOnly": "npm run build:all",
|
|
29
|
-
"build": "npm run check:isolation && node -e \"const fs=require('fs'); for(const dir of ['dist/default-skills','dist/kimi-plugins']) fs.rmSync(dir,{recursive:true,force:true})\" && tsc && node -e \"const fs=require('fs'); for(const dir of ['default-skills','kimi-plugins']) fs.cpSync('src/'+dir,'dist/'+dir,{recursive:true,filter:s=>!s.endsWith('.ts')}); fs.cpSync('src/adapter/deepseek-harness/grix-jsonrpc.cordis.yml','dist/adapter/deepseek-harness/grix-jsonrpc.cordis.yml')\" && node scripts/build-dsh-bridge.mjs && node -e \"require('fs').cpSync('src/core/proxy/hermes-profile-relay.py','dist/core/proxy/hermes-profile-relay.py'); require('fs').cpSync('scripts/launcher.mjs','dist/launcher.mjs')\"",
|
|
29
|
+
"build": "npm run check:isolation && node -e \"const fs=require('fs'); for(const dir of ['dist/default-skills','dist/kimi-plugins']) fs.rmSync(dir,{recursive:true,force:true})\" && tsc && node -e \"const fs=require('fs'); for(const dir of ['default-skills','kimi-plugins']) fs.cpSync('src/'+dir,'dist/'+dir,{recursive:true,filter:s=>!s.endsWith('.ts')}); fs.cpSync('src/adapter/deepseek-harness/grix-jsonrpc.cordis.yml','dist/adapter/deepseek-harness/grix-jsonrpc.cordis.yml')\" && node scripts/build-dsh-bridge.mjs && node -e \"require('fs').cpSync('src/core/proxy/hermes-profile-relay.py','dist/core/proxy/hermes-profile-relay.py'); require('fs').cpSync('scripts/launcher.mjs','dist/launcher.mjs')\" && node scripts/sync-dist-to-runtime.mjs",
|
|
30
30
|
"check:isolation": "node scripts/check-adapter-isolation.mjs",
|
|
31
31
|
"build:plugin": "node scripts/build-plugin.mjs",
|
|
32
32
|
"build:all": "npm run build && node scripts/minify-dist.mjs && npm run build:plugin",
|
|
Binary file
|