yingclaw 2.5.4 → 2.5.5

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.
Files changed (2) hide show
  1. package/lib/autostart.js +43 -5
  2. package/package.json +1 -1
package/lib/autostart.js CHANGED
@@ -63,6 +63,35 @@ function runLaunchctl(runner, args, options = {}) {
63
63
  return result;
64
64
  }
65
65
 
66
+ function sleepSync(ms) {
67
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
68
+ }
69
+
70
+ function getLaunchAgentRuntimeStatus(runner, service) {
71
+ const result = runner('launchctl', ['print', service], { encoding: 'utf8', stdio: 'pipe' });
72
+ const output = `${result.stdout || ''}\n${result.stderr || ''}`;
73
+ return {
74
+ loaded: result.status === 0,
75
+ running: result.status === 0 && /state\s*=\s*running/i.test(output),
76
+ };
77
+ }
78
+
79
+ function waitForLaunchAgentUnload(runner, service, options = {}) {
80
+ const timeoutMs = options.timeoutMs == null ? 1500 : options.timeoutMs;
81
+ const intervalMs = options.intervalMs == null ? 100 : options.intervalMs;
82
+ const deadline = Date.now() + timeoutMs;
83
+
84
+ do {
85
+ if (!getLaunchAgentRuntimeStatus(runner, service).loaded) {
86
+ return true;
87
+ }
88
+ if (Date.now() >= deadline) {
89
+ return false;
90
+ }
91
+ sleepSync(intervalMs);
92
+ } while (true);
93
+ }
94
+
66
95
  function installGatewayAutostart(options = {}) {
67
96
  const platform = options.platform || process.platform;
68
97
  if (platform !== 'darwin') {
@@ -84,8 +113,18 @@ function installGatewayAutostart(options = {}) {
84
113
  const domain = `gui/${uid}`;
85
114
  const service = `${domain}/${GATEWAY_LAUNCH_AGENT_LABEL}`;
86
115
 
87
- runLaunchctl(runner, ['bootout', domain, GATEWAY_LAUNCH_AGENT_LABEL], { optional: true });
88
- runLaunchctl(runner, ['bootstrap', domain, file]);
116
+ const bootout = runLaunchctl(runner, ['bootout', service], { optional: true });
117
+ if (bootout.status === 0) {
118
+ waitForLaunchAgentUnload(runner, service, {
119
+ timeoutMs: options.unloadTimeoutMs,
120
+ intervalMs: options.unloadPollIntervalMs,
121
+ });
122
+ }
123
+ const bootstrap = runLaunchctl(runner, ['bootstrap', domain, file], { optional: true });
124
+ if (bootstrap.status !== 0 && !getLaunchAgentRuntimeStatus(runner, service).loaded) {
125
+ const stderr = String(bootstrap.stderr || '').trim();
126
+ throw new Error(`launchctl bootstrap ${domain} ${file} 失败${stderr ? `: ${stderr}` : ''}`);
127
+ }
89
128
  runLaunchctl(runner, ['enable', service]);
90
129
  runLaunchctl(runner, ['kickstart', '-k', service]);
91
130
 
@@ -111,12 +150,11 @@ function getGatewayAutostartStatus(options = {}) {
111
150
  }
112
151
 
113
152
  const runner = options.runner || spawnSync;
114
- const result = runner('launchctl', ['print', `gui/${uid}/${GATEWAY_LAUNCH_AGENT_LABEL}`], { encoding: 'utf8', stdio: 'pipe' });
115
- const output = `${result.stdout || ''}\n${result.stderr || ''}`;
153
+ const runtimeStatus = getLaunchAgentRuntimeStatus(runner, `gui/${uid}/${GATEWAY_LAUNCH_AGENT_LABEL}`);
116
154
  return {
117
155
  supported: true,
118
156
  installed: true,
119
- running: result.status === 0 && /state\s*=\s*running/i.test(output),
157
+ running: runtimeStatus.running,
120
158
  file,
121
159
  };
122
160
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yingclaw",
3
- "version": "2.5.4",
3
+ "version": "2.5.5",
4
4
  "description": "Claude Code × 国产大模型一键接入:DeepSeek、Kimi、Qwen、MiniMax、GLM、MiMo",
5
5
  "main": "index.js",
6
6
  "bin": {