palmier 0.8.6 → 0.8.7

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.
@@ -133,6 +133,17 @@ function runLaunchctl(args, opts = {}) {
133
133
  console.error(`launchctl ${args[0]} failed: ${e.stderr || err}`);
134
134
  }
135
135
  }
136
+ /**
137
+ * Reload a LaunchAgent plist. The `enable` call is essential: after `bootout`
138
+ * macOS can leave the service in a *disabled* state (tracked in
139
+ * /var/db/com.apple.xpc.launchd/disabled.<uid>.plist). A subsequent bootstrap
140
+ * then fails with "Bootstrap failed: 5: Input/output error".
141
+ */
142
+ function reloadAgent(domain, label, plistPath) {
143
+ runLaunchctl(["bootout", `${domain}/${label}`], { ignoreFailure: true });
144
+ runLaunchctl(["enable", `${domain}/${label}`], { ignoreFailure: true });
145
+ runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
146
+ }
136
147
  export class MacOsPlatform {
137
148
  installDaemon(config) {
138
149
  fs.mkdirSync(AGENT_DIR, { recursive: true });
@@ -155,8 +166,7 @@ export class MacOsPlatform {
155
166
  fs.writeFileSync(plistPath, plist, "utf-8");
156
167
  console.log("LaunchAgent installed at:", plistPath);
157
168
  const domain = guiDomain();
158
- runLaunchctl(["bootout", `${domain}/${DAEMON_LABEL}`], { ignoreFailure: true });
159
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
169
+ reloadAgent(domain, DAEMON_LABEL, plistPath);
160
170
  runLaunchctl(["kickstart", "-k", `${domain}/${DAEMON_LABEL}`]);
161
171
  console.log("Palmier host LaunchAgent loaded and started.");
162
172
  console.log("Note: LaunchAgents only run while you are logged into the GUI session. " +
@@ -195,8 +205,7 @@ export class MacOsPlatform {
195
205
  const updated = content.replace(/(<key>PATH<\/key>\s*\n\s*<string>)[^<]*(<\/string>)/, `$1${escapeXml(userPath)}$2`);
196
206
  if (updated !== content) {
197
207
  fs.writeFileSync(plistPath, updated, "utf-8");
198
- runLaunchctl(["bootout", `${domain}/${DAEMON_LABEL}`], { ignoreFailure: true });
199
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
208
+ reloadAgent(domain, DAEMON_LABEL, plistPath);
200
209
  }
201
210
  }
202
211
  runLaunchctl(["kickstart", "-k", `${domain}/${DAEMON_LABEL}`]);
@@ -239,8 +248,7 @@ export class MacOsPlatform {
239
248
  }
240
249
  fs.writeFileSync(plistPath, buildPlist(dict), "utf-8");
241
250
  const domain = guiDomain();
242
- runLaunchctl(["bootout", `${domain}/${label}`], { ignoreFailure: true });
243
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
251
+ reloadAgent(domain, label, plistPath);
244
252
  }
245
253
  removeTaskTimer(taskId) {
246
254
  const domain = guiDomain();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "palmier",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "description": "Palmier host CLI - provisions, executes tasks, and serves NATS RPC",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Hongxu Cai",
@@ -140,6 +140,18 @@ function runLaunchctl(args: string[], opts: { ignoreFailure?: boolean } = {}): v
140
140
  }
141
141
  }
142
142
 
143
+ /**
144
+ * Reload a LaunchAgent plist. The `enable` call is essential: after `bootout`
145
+ * macOS can leave the service in a *disabled* state (tracked in
146
+ * /var/db/com.apple.xpc.launchd/disabled.<uid>.plist). A subsequent bootstrap
147
+ * then fails with "Bootstrap failed: 5: Input/output error".
148
+ */
149
+ function reloadAgent(domain: string, label: string, plistPath: string): void {
150
+ runLaunchctl(["bootout", `${domain}/${label}`], { ignoreFailure: true });
151
+ runLaunchctl(["enable", `${domain}/${label}`], { ignoreFailure: true });
152
+ runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
153
+ }
154
+
143
155
  export class MacOsPlatform implements PlatformService {
144
156
  installDaemon(config: HostConfig): void {
145
157
  fs.mkdirSync(AGENT_DIR, { recursive: true });
@@ -166,8 +178,7 @@ export class MacOsPlatform implements PlatformService {
166
178
  console.log("LaunchAgent installed at:", plistPath);
167
179
 
168
180
  const domain = guiDomain();
169
- runLaunchctl(["bootout", `${domain}/${DAEMON_LABEL}`], { ignoreFailure: true });
170
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
181
+ reloadAgent(domain, DAEMON_LABEL, plistPath);
171
182
  runLaunchctl(["kickstart", "-k", `${domain}/${DAEMON_LABEL}`]);
172
183
 
173
184
  console.log("Palmier host LaunchAgent loaded and started.");
@@ -212,8 +223,7 @@ export class MacOsPlatform implements PlatformService {
212
223
  );
213
224
  if (updated !== content) {
214
225
  fs.writeFileSync(plistPath, updated, "utf-8");
215
- runLaunchctl(["bootout", `${domain}/${DAEMON_LABEL}`], { ignoreFailure: true });
216
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
226
+ reloadAgent(domain, DAEMON_LABEL, plistPath);
217
227
  }
218
228
  }
219
229
 
@@ -263,8 +273,7 @@ export class MacOsPlatform implements PlatformService {
263
273
  fs.writeFileSync(plistPath, buildPlist(dict), "utf-8");
264
274
 
265
275
  const domain = guiDomain();
266
- runLaunchctl(["bootout", `${domain}/${label}`], { ignoreFailure: true });
267
- runLaunchctl(["bootstrap", domain, `"${plistPath}"`]);
276
+ reloadAgent(domain, label, plistPath);
268
277
  }
269
278
 
270
279
  removeTaskTimer(taskId: string): void {