@amalgm/shell 0.1.162 → 0.1.164-main.34182640231

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 (144) hide show
  1. package/PURPOSE.md +163 -17
  2. package/README.md +74 -11
  3. package/config/releases/trust/runtime/main.root.json +84 -0
  4. package/config/releases/trust/runtime/preview.root.json +84 -0
  5. package/dist/authorization/recovery-host.d.ts +1 -0
  6. package/dist/authorization/recovery-host.js +2 -3
  7. package/dist/authorization/recovery-host.js.map +1 -1
  8. package/dist/boot.js +28 -20
  9. package/dist/boot.js.map +1 -1
  10. package/dist/cli-arguments.d.ts +8 -0
  11. package/dist/cli-arguments.js +47 -0
  12. package/dist/cli-arguments.js.map +1 -0
  13. package/dist/cli.d.ts +6 -4
  14. package/dist/cli.js +91 -73
  15. package/dist/cli.js.map +1 -1
  16. package/dist/compose.js +4 -3
  17. package/dist/compose.js.map +1 -1
  18. package/dist/content-cache-index.js +2 -2
  19. package/dist/content-cache-index.js.map +1 -1
  20. package/dist/detection/runtime.js +2 -2
  21. package/dist/detection/runtime.js.map +1 -1
  22. package/dist/development/profile.d.ts +27 -0
  23. package/dist/development/profile.js +142 -0
  24. package/dist/development/profile.js.map +1 -0
  25. package/dist/entity-apply-host.js +2 -2
  26. package/dist/entity-apply-host.js.map +1 -1
  27. package/dist/entity-apply-store.d.ts +2 -1
  28. package/dist/entity-apply-store.js +52 -37
  29. package/dist/entity-apply-store.js.map +1 -1
  30. package/dist/files-register-host.d.ts +1 -0
  31. package/dist/files-register-host.js +1 -0
  32. package/dist/files-register-host.js.map +1 -1
  33. package/dist/installation/environment.d.ts +30 -0
  34. package/dist/installation/environment.js +28 -0
  35. package/dist/installation/environment.js.map +1 -0
  36. package/dist/installation/lease.d.ts +6 -0
  37. package/dist/installation/lease.js +28 -0
  38. package/dist/installation/lease.js.map +1 -0
  39. package/dist/installation/ownership.d.ts +30 -0
  40. package/dist/installation/ownership.js +156 -0
  41. package/dist/installation/ownership.js.map +1 -0
  42. package/dist/installation/selection.d.ts +8 -0
  43. package/dist/installation/selection.js +29 -0
  44. package/dist/installation/selection.js.map +1 -0
  45. package/dist/machine-host.d.ts +27 -5
  46. package/dist/machine-host.js +244 -96
  47. package/dist/machine-host.js.map +1 -1
  48. package/dist/main.js +56 -2
  49. package/dist/main.js.map +1 -1
  50. package/dist/platform-product-host.d.ts +9 -9
  51. package/dist/platform-product-host.js +17 -17
  52. package/dist/platform-product-host.js.map +1 -1
  53. package/dist/platform-tools.d.ts +4 -3
  54. package/dist/platform-tools.js +34 -37
  55. package/dist/platform-tools.js.map +1 -1
  56. package/dist/process-lifecycle.d.ts +6 -0
  57. package/dist/process-lifecycle.js +42 -0
  58. package/dist/process-lifecycle.js.map +1 -0
  59. package/dist/pty-host.d.ts +1 -1
  60. package/dist/pty-host.js +70 -21
  61. package/dist/pty-host.js.map +1 -1
  62. package/dist/runtime-command-host.d.ts +7 -0
  63. package/dist/runtime-command-host.js +49 -13
  64. package/dist/runtime-command-host.js.map +1 -1
  65. package/dist/service/adapter.d.ts +36 -0
  66. package/dist/service/adapter.js +24 -0
  67. package/dist/service/adapter.js.map +1 -0
  68. package/dist/service/cli.d.ts +8 -0
  69. package/dist/service/cli.js +237 -0
  70. package/dist/service/cli.js.map +1 -0
  71. package/dist/service/control.d.ts +38 -0
  72. package/dist/service/control.js +68 -0
  73. package/dist/service/control.js.map +1 -0
  74. package/dist/service/index.d.ts +9 -0
  75. package/dist/service/index.js +10 -0
  76. package/dist/service/index.js.map +1 -0
  77. package/dist/service/keepalive.d.ts +18 -0
  78. package/dist/service/keepalive.js +418 -0
  79. package/dist/service/keepalive.js.map +1 -0
  80. package/dist/service/launchd.d.ts +9 -0
  81. package/dist/service/launchd.js +105 -0
  82. package/dist/service/launchd.js.map +1 -0
  83. package/dist/service/owner.d.ts +4 -0
  84. package/dist/service/owner.js +14 -0
  85. package/dist/service/owner.js.map +1 -0
  86. package/dist/service/portable.d.ts +10 -0
  87. package/dist/service/portable.js +32 -0
  88. package/dist/service/portable.js.map +1 -0
  89. package/dist/service/recovery.d.ts +27 -0
  90. package/dist/service/recovery.js +58 -0
  91. package/dist/service/recovery.js.map +1 -0
  92. package/dist/service/registration.d.ts +82 -0
  93. package/dist/service/registration.js +114 -0
  94. package/dist/service/registration.js.map +1 -0
  95. package/dist/service/systemd-unit.d.ts +7 -0
  96. package/dist/service/systemd-unit.js +43 -0
  97. package/dist/service/systemd-unit.js.map +1 -0
  98. package/dist/service/systemd.d.ts +5 -0
  99. package/dist/service/systemd.js +72 -0
  100. package/dist/service/systemd.js.map +1 -0
  101. package/dist/service/windows-action.d.ts +9 -0
  102. package/dist/service/windows-action.js +55 -0
  103. package/dist/service/windows-action.js.map +1 -0
  104. package/dist/service/windows-task.d.ts +9 -0
  105. package/dist/service/windows-task.js +46 -0
  106. package/dist/service/windows-task.js.map +1 -0
  107. package/dist/service/windows.d.ts +2 -0
  108. package/dist/service/windows.js +65 -0
  109. package/dist/service/windows.js.map +1 -0
  110. package/dist/sqlite.d.ts +4 -0
  111. package/dist/sqlite.js +16 -0
  112. package/dist/sqlite.js.map +1 -0
  113. package/dist/updates/artifacts.d.ts +40 -0
  114. package/dist/updates/artifacts.js +299 -0
  115. package/dist/updates/artifacts.js.map +1 -0
  116. package/dist/updates/bootstrap.d.ts +48 -0
  117. package/dist/updates/bootstrap.js +384 -0
  118. package/dist/updates/bootstrap.js.map +1 -0
  119. package/dist/updates/controller.d.ts +66 -0
  120. package/dist/updates/controller.js +322 -0
  121. package/dist/updates/controller.js.map +1 -0
  122. package/dist/updates/isolated-command-lifetime.d.ts +1 -0
  123. package/dist/updates/isolated-command-lifetime.js +63 -0
  124. package/dist/updates/isolated-command-lifetime.js.map +1 -0
  125. package/dist/updates/store.d.ts +41 -0
  126. package/dist/updates/store.js +80 -0
  127. package/dist/updates/store.js.map +1 -0
  128. package/dist/updates/trust.d.ts +20 -0
  129. package/dist/updates/trust.js +138 -0
  130. package/dist/updates/trust.js.map +1 -0
  131. package/dist/user-ground-host.d.ts +4 -1
  132. package/dist/user-ground-host.js +16 -3
  133. package/dist/user-ground-host.js.map +1 -1
  134. package/dist/watching/host.js +4 -2
  135. package/dist/watching/host.js.map +1 -1
  136. package/dist/workspace-add-staging.js +2 -2
  137. package/dist/workspace-add-staging.js.map +1 -1
  138. package/examinations/fixtures/machine-control-plane.js +57 -0
  139. package/examinations/fixtures/private-wire-authority.js +1065 -0
  140. package/examinations/native-service.mjs +92 -0
  141. package/examinations/network-view.mjs +202 -0
  142. package/examinations/runtime-upgrade.native-test.mjs +198 -0
  143. package/npm-shrinkwrap.json +2097 -218
  144. package/package.json +95 -14
@@ -0,0 +1,418 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
3
+ import { closeSync, fstatSync, openSync, renameSync, rmSync, writeSync } from 'node:fs';
4
+ import { createServer } from 'node:http';
5
+ import { join } from 'node:path';
6
+ import { CHILD_HEALTH_POLICY, CHILD_RESTART_POLICY, readyDeadlineMs } from '@amalgm/core/supervision';
7
+ import { runtimeBindingsMatch } from '@amalgm/core/binding';
8
+ import { atomicJson, ensurePrivateDir } from '../filesystem.js';
9
+ import { acquireProcessLease } from '../installation/lease.js';
10
+ import { currentLauncher, readRegistration } from './registration.js';
11
+ import { controllerLeaseFile, controllerStateFile } from './control.js';
12
+ import { RuntimeRecovery } from './recovery.js';
13
+ import { RuntimeUpdates } from '../updates/controller.js';
14
+ export const STOP_GRACE_MS = 25_000;
15
+ export const LOG_LIMIT_BYTES = 8 * 1024 * 1024;
16
+ /** One leased controller supervises one runtime over IPC. The optional policy
17
+ * lets process examinations use short clocks; the CLI always uses Core defaults. */
18
+ export async function runKeepalive(identity, policy = {}) {
19
+ const registration = readRegistration(identity);
20
+ if (!registration)
21
+ throw new Error('This environment has no runtime service registration.');
22
+ ensurePrivateDir(identity.serviceDir);
23
+ const lease = acquireProcessLease(controllerLeaseFile(identity));
24
+ if (!lease)
25
+ return 0; // A concurrent start binds to the existing owner.
26
+ try {
27
+ return await runOwnedController(identity, registration, policy);
28
+ }
29
+ finally {
30
+ lease.close();
31
+ }
32
+ }
33
+ async function runOwnedController(identity, registration, policy) {
34
+ const restartPolicy = policy.restart ?? CHILD_RESTART_POLICY;
35
+ const healthPolicy = policy.health ?? CHILD_HEALTH_POLICY;
36
+ const recovery = new RuntimeRecovery(identity, restartPolicy);
37
+ let log;
38
+ try {
39
+ log = openRotatingLog(join(identity.serviceDir, 'service.log'), LOG_LIMIT_BYTES);
40
+ }
41
+ catch (error) {
42
+ recovery.close();
43
+ throw error;
44
+ }
45
+ let child = null;
46
+ let stopping = false;
47
+ let wake = null;
48
+ let killTimer;
49
+ let closeMonitor = () => { };
50
+ let updates = null;
51
+ let runtimePaused = false;
52
+ let runtimeReady = false;
53
+ let starts = 0;
54
+ let replacing = false;
55
+ let state = {
56
+ binding: identity.binding, user: identity.user, instanceId: randomUUID(), pid: process.pid,
57
+ bootstrapPid: process.connected ? process.ppid : null,
58
+ port: 0, token: randomBytes(32).toString('base64url'), childPid: null, restarts: 0,
59
+ phase: 'starting', recovery: recovery.state,
60
+ };
61
+ const publish = (patch) => {
62
+ state = { ...state, ...patch, recovery: recovery.state, update: updates?.status ?? null };
63
+ atomicJson(controllerStateFile(identity), state);
64
+ };
65
+ const drainChild = () => {
66
+ if (child && child.exitCode === null && child.signalCode === null) {
67
+ const owned = child;
68
+ if (owned.connected)
69
+ owned.send({ type: 'amalgm-shutdown' }, () => { });
70
+ else
71
+ owned.kill('SIGTERM');
72
+ if (killTimer)
73
+ return;
74
+ killTimer = setTimeout(() => {
75
+ if (owned.exitCode === null && owned.signalCode === null)
76
+ owned.kill('SIGKILL');
77
+ }, policy.stopGraceMs ?? STOP_GRACE_MS);
78
+ killTimer.unref();
79
+ }
80
+ };
81
+ const stop = () => {
82
+ if (stopping)
83
+ return;
84
+ stopping = true;
85
+ drainChild();
86
+ wake?.();
87
+ };
88
+ const parentMessage = (value) => {
89
+ if (!value || typeof value !== 'object')
90
+ return;
91
+ const message = value;
92
+ if (message.type === 'amalgm-shutdown')
93
+ stop();
94
+ else if (message.type === 'amalgm-health' && typeof message.nonce === 'string' && !stopping) {
95
+ process.send?.({ type: 'amalgm-health', nonce: message.nonce }, () => { });
96
+ }
97
+ };
98
+ const server = createServer((request, response) => {
99
+ const actual = Buffer.from(request.headers.authorization || '');
100
+ const expected = Buffer.from(`Bearer ${state.token}`);
101
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
102
+ response.writeHead(401).end();
103
+ return;
104
+ }
105
+ if (request.method === 'GET' && request.url === '/status'
106
+ || request.method === 'POST' && (request.url === '/stop' || request.url === '/retry')) {
107
+ // A valid token proves access to this endpoint, not that the caller
108
+ // selected this owner. Mutation admission must prove both before effects.
109
+ if (request.method === 'POST') {
110
+ let expectedIdentity;
111
+ try {
112
+ expectedIdentity = JSON.parse(String(request.headers['x-amalgm-controller-identity'] || ''));
113
+ }
114
+ catch {
115
+ response.writeHead(409).end();
116
+ return;
117
+ }
118
+ if (expectedIdentity?.instanceId !== state.instanceId || expectedIdentity?.user !== state.user
119
+ || !runtimeBindingsMatch(expectedIdentity?.binding, state.binding)) {
120
+ response.writeHead(409).end();
121
+ return;
122
+ }
123
+ }
124
+ if (request.url === '/retry' && !stopping && recovery.state.parked) {
125
+ recovery.retry();
126
+ publish({ phase: 'starting' });
127
+ wake?.();
128
+ }
129
+ response.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' });
130
+ response.end(JSON.stringify({ ...state, token: '' }));
131
+ if (request.url === '/stop')
132
+ stop();
133
+ return;
134
+ }
135
+ response.writeHead(404).end();
136
+ });
137
+ process.once('SIGTERM', stop);
138
+ process.once('SIGINT', stop);
139
+ process.once('disconnect', stop);
140
+ process.on('message', parentMessage);
141
+ const wait = (milliseconds) => new Promise((resolve) => {
142
+ const timer = milliseconds === undefined ? undefined : setTimeout(resolve, milliseconds);
143
+ wake = () => { clearTimeout(timer); resolve(); };
144
+ }).finally(() => { wake = null; });
145
+ try {
146
+ await new Promise((resolve, reject) => {
147
+ server.once('error', reject);
148
+ server.listen(0, '127.0.0.1', resolve);
149
+ });
150
+ const address = server.address();
151
+ if (!address || typeof address === 'string')
152
+ throw new Error('The controller did not receive a local address.');
153
+ publish({ port: address.port });
154
+ if (RuntimeUpdates.enabled(identity)) {
155
+ updates = new RuntimeUpdates(identity, {
156
+ packageRoot: currentLauncher().packageRoot,
157
+ pause: async () => {
158
+ runtimePaused = true;
159
+ if (child) {
160
+ const draining = childExit(child);
161
+ drainChild();
162
+ await draining;
163
+ }
164
+ runtimeReady = false;
165
+ },
166
+ start: async () => {
167
+ const before = starts;
168
+ runtimePaused = false;
169
+ if (recovery.state.parked)
170
+ recovery.retry(); // Core already authorized this distinct update generation.
171
+ wake?.();
172
+ const deadline = Date.now() + recovery.delayMs + readyDeadlineMs(healthPolicy);
173
+ while (!runtimeReady) {
174
+ if (stopping || Date.now() >= deadline || starts > before && child === null)
175
+ throw new Error('The authorized runtime generation did not become ready');
176
+ await new Promise(resolve => setTimeout(resolve, 50));
177
+ }
178
+ },
179
+ probe: async () => {
180
+ if (!child || !runtimeReady)
181
+ throw new Error('The authorized runtime generation is not running');
182
+ await probeRuntime(child, healthPolicy.timeoutMs);
183
+ },
184
+ replace: () => { replacing = true; stop(); },
185
+ changed: () => { publish({}); wake?.(); },
186
+ log: reason => log.write(`${JSON.stringify({ event: 'runtime-update', reason })}\n`),
187
+ });
188
+ runtimePaused = !updates.permitsOrdinaryRuntime;
189
+ updates.start();
190
+ }
191
+ process.send?.({ type: 'amalgm-ready' }, () => { });
192
+ while (!stopping) {
193
+ if (runtimePaused) {
194
+ publish({ phase: 'parked' });
195
+ await wait();
196
+ continue;
197
+ }
198
+ if (recovery.state.parked) {
199
+ publish({ phase: 'parked' });
200
+ await wait();
201
+ continue;
202
+ }
203
+ const delayMs = recovery.delayMs;
204
+ if (delayMs > 0) {
205
+ publish({ phase: 'backoff' });
206
+ const retryAt = Date.now() + delayMs;
207
+ while (!stopping && !runtimePaused && Date.now() < retryAt)
208
+ await wait(retryAt - Date.now());
209
+ if (stopping)
210
+ break;
211
+ if (runtimePaused || recovery.state.parked)
212
+ continue;
213
+ }
214
+ const generation = randomUUID();
215
+ recovery.begin(generation);
216
+ starts++;
217
+ publish({ phase: 'starting' });
218
+ const launcher = updates ? currentLauncher() : registration;
219
+ child = spawn(launcher.node, [launcher.bin, ...registration.run_args], {
220
+ cwd: identity.home, env: process.env,
221
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'], windowsHide: true,
222
+ });
223
+ const exiting = childExit(child);
224
+ child.stdout?.on('data', (chunk) => log.write(chunk));
225
+ child.stderr?.on('data', (chunk) => log.write(chunk));
226
+ publish({ childPid: child.pid ?? null });
227
+ let failure = null;
228
+ const monitored = monitorRuntime(child, healthPolicy, restartPolicy.stableAfterMs, {
229
+ ready: () => { if (!stopping) {
230
+ runtimeReady = true;
231
+ publish({ phase: 'running' });
232
+ } },
233
+ healthy: () => { if (!stopping) {
234
+ recovery.healthy(generation);
235
+ publish({});
236
+ } },
237
+ failed: (reason) => { if (!stopping) {
238
+ failure = reason;
239
+ drainChild();
240
+ } },
241
+ });
242
+ closeMonitor = monitored.close;
243
+ const outcome = await exiting;
244
+ closeMonitor();
245
+ child = null;
246
+ runtimeReady = false;
247
+ if (updates && !updates.permitsOrdinaryRuntime)
248
+ runtimePaused = true;
249
+ if (killTimer)
250
+ clearTimeout(killTimer);
251
+ killTimer = undefined;
252
+ recovery.exited(generation, stopping ? null : failure ?? outcome.error ?? `Runtime exited (${outcome.signal ?? outcome.code})`);
253
+ publish({ childPid: null, phase: stopping ? 'stopping' : recovery.state.parked ? 'parked' : 'backoff' });
254
+ if (stopping)
255
+ break;
256
+ publish({ restarts: state.restarts + 1 });
257
+ log.write(`${JSON.stringify({ event: 'runtime-exited', ...outcome, recovery: recovery.state })}\n`);
258
+ }
259
+ return 0;
260
+ }
261
+ finally {
262
+ const requestedStop = stopping;
263
+ closeMonitor();
264
+ stop();
265
+ if (child && child.exitCode === null && child.signalCode === null)
266
+ await childExit(child);
267
+ await updates?.close();
268
+ if (killTimer)
269
+ clearTimeout(killTimer);
270
+ process.off('SIGTERM', stop);
271
+ process.off('SIGINT', stop);
272
+ process.off('disconnect', stop);
273
+ process.off('message', parentMessage);
274
+ server.closeAllConnections();
275
+ await new Promise((resolve) => { if (server.listening)
276
+ server.close(() => resolve());
277
+ else
278
+ resolve(); });
279
+ rmSync(controllerStateFile(identity), { force: true });
280
+ try {
281
+ log.close();
282
+ }
283
+ finally {
284
+ recovery.close();
285
+ }
286
+ if (requestedStop && process.connected)
287
+ process.send?.({ type: replacing ? 'amalgm-controller-replace' : 'amalgm-controller-stop' }, () => { });
288
+ }
289
+ }
290
+ /** A fresh generation-owned challenge supplies probation evidence; an old
291
+ * cached status or controller heartbeat cannot prove runtime health. */
292
+ function probeRuntime(child, timeoutMs) {
293
+ return new Promise((resolve, reject) => {
294
+ const nonce = randomUUID();
295
+ const close = () => { clearTimeout(timer); child.off('message', message); child.off('exit', exited); };
296
+ const exited = () => { close(); reject(new Error('Runtime exited during its health examination')); };
297
+ const message = (value) => {
298
+ const reply = value;
299
+ if (reply?.type === 'amalgm-health' && reply.nonce === nonce) {
300
+ close();
301
+ resolve();
302
+ }
303
+ };
304
+ const timer = setTimeout(() => { close(); reject(new Error('Runtime probation health timed out')); }, timeoutMs);
305
+ child.on('message', message);
306
+ child.once('exit', exited);
307
+ if (child.connected)
308
+ child.send({ type: 'amalgm-health', nonce }, () => { });
309
+ else
310
+ exited();
311
+ });
312
+ }
313
+ function childExit(child) {
314
+ if (child.exitCode !== null || child.signalCode !== null)
315
+ return Promise.resolve({ code: child.exitCode, signal: child.signalCode });
316
+ return new Promise((resolve) => {
317
+ // Only a failed spawn has no process to drain. A later IPC/kill error is
318
+ // not evidence of exit and cannot authorize a replacement beside the child.
319
+ const error = (cause) => {
320
+ if (child.pid === undefined) {
321
+ child.off('exit', exited);
322
+ child.off('error', error);
323
+ resolve({ code: 1, signal: null, error: cause.message });
324
+ }
325
+ };
326
+ const exited = (code, signal) => { child.off('error', error); resolve({ code, signal }); };
327
+ child.on('error', error);
328
+ child.once('exit', exited);
329
+ });
330
+ }
331
+ /** Probe only the owned IPC channel, with one outstanding request. Ready plus
332
+ * sustained responses earns a fresh allowance; uptime alone never does. */
333
+ function monitorRuntime(child, health, stableAfterMs, effects) {
334
+ let ready = false;
335
+ let closed = false;
336
+ let stable = false;
337
+ let healthySince = null;
338
+ let failures = 0;
339
+ let nonce = null;
340
+ let probeTimer;
341
+ let timeout;
342
+ const startup = setTimeout(() => fail('Runtime did not become ready before its startup deadline'), readyDeadlineMs(health));
343
+ const close = () => {
344
+ closed = true;
345
+ clearTimeout(startup);
346
+ clearTimeout(probeTimer);
347
+ clearTimeout(timeout);
348
+ child.off('message', message);
349
+ };
350
+ const fail = (reason) => { if (!closed) {
351
+ close();
352
+ effects.failed(reason);
353
+ } };
354
+ const probe = () => {
355
+ if (closed)
356
+ return;
357
+ nonce = randomUUID();
358
+ timeout = setTimeout(() => {
359
+ nonce = null;
360
+ healthySince = null;
361
+ if (++failures >= health.maxFailures)
362
+ fail('Runtime IPC health checks stopped responding');
363
+ else
364
+ probeTimer = setTimeout(probe, health.intervalMs);
365
+ }, health.timeoutMs);
366
+ if (child.connected)
367
+ child.send({ type: 'amalgm-health', nonce }, () => { });
368
+ };
369
+ const message = (value) => {
370
+ if (closed || !value || typeof value !== 'object')
371
+ return;
372
+ const reply = value;
373
+ if (reply.type === 'amalgm-ready' && !ready) {
374
+ ready = true;
375
+ clearTimeout(startup);
376
+ effects.ready();
377
+ probe();
378
+ }
379
+ else if (reply.type === 'amalgm-health' && nonce && reply.nonce === nonce) {
380
+ clearTimeout(timeout);
381
+ nonce = null;
382
+ failures = 0;
383
+ healthySince ??= performance.now();
384
+ if (!stable && performance.now() - healthySince >= stableAfterMs) {
385
+ stable = true;
386
+ effects.healthy();
387
+ }
388
+ probeTimer = setTimeout(probe, health.intervalMs);
389
+ }
390
+ };
391
+ child.on('message', message);
392
+ return { close };
393
+ }
394
+ /** Two bounded log files; even a single oversized write obeys the limit. */
395
+ export function openRotatingLog(file, limitBytes) {
396
+ let fd = openSync(file, 'a');
397
+ let size = fstatSync(fd).size;
398
+ return {
399
+ write(chunk) {
400
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
401
+ for (let offset = 0; offset < bytes.length;) {
402
+ if (size >= limitBytes) {
403
+ closeSync(fd);
404
+ rmSync(`${file}.1`, { force: true });
405
+ renameSync(file, `${file}.1`);
406
+ fd = openSync(file, 'a');
407
+ size = 0;
408
+ }
409
+ const count = Math.min(bytes.length - offset, limitBytes - size);
410
+ writeSync(fd, bytes, offset, count);
411
+ offset += count;
412
+ size += count;
413
+ }
414
+ },
415
+ close() { closeSync(fd); },
416
+ };
417
+ }
418
+ //# sourceMappingURL=keepalive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keepalive.js","sourceRoot":"","sources":["../../src/service/keepalive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type ServiceOwner } from "./adapter.js";
2
+ export declare function renderLaunchdPlist(input: {
3
+ readonly label: string;
4
+ readonly command: readonly string[];
5
+ readonly environment: Readonly<Record<string, string>>;
6
+ readonly workingDirectory: string;
7
+ readonly logPath: string;
8
+ }): string;
9
+ export declare const launchdOwner: ServiceOwner;
@@ -0,0 +1,105 @@
1
+ import { stopKeepalive } from "./control.js";
2
+ /**
3
+ * macOS: a LaunchAgent in the user's `gui/<uid>` domain. launchd starts it
4
+ * at login, restarts it whenever it exits non-zero, and stops it at logout.
5
+ * Every knob is written out, so the policy is the file, not a default.
6
+ */
7
+ import { existsSync, rmSync } from "node:fs";
8
+ import { dirname } from "node:path";
9
+ import { launchdPlistPath, plistEscape } from "@amalgm/core/supervision";
10
+ import { atomicWrite, ensureUserDir } from "../filesystem.js";
11
+ import { keepaliveCommand, osCommand, serviceEnvironment } from "./adapter.js";
12
+ /** launchd's own default, stated: a non-zero exit is retried after 10s. */
13
+ const THROTTLE_INTERVAL_S = 10;
14
+ /** SIGTERM, then SIGKILL after this; the keepalive stops its child within 25s. */
15
+ const EXIT_TIMEOUT_S = 30;
16
+ export function renderLaunchdPlist(input) {
17
+ const args = input.command.map((part) => ` <string>${plistEscape(part)}</string>`).join("\n");
18
+ const env = Object.entries(input.environment)
19
+ .map(([key, value]) => ` <key>${plistEscape(key)}</key>\n <string>${plistEscape(value)}</string>`)
20
+ .join("\n");
21
+ return `<?xml version="1.0" encoding="UTF-8"?>
22
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
23
+ <plist version="1.0">
24
+ <dict>
25
+ <key>Label</key>
26
+ <string>${plistEscape(input.label)}</string>
27
+ <key>ProgramArguments</key>
28
+ <array>
29
+ ${args}
30
+ </array>
31
+ <key>EnvironmentVariables</key>
32
+ <dict>
33
+ ${env}
34
+ </dict>
35
+ <key>WorkingDirectory</key>
36
+ <string>${plistEscape(input.workingDirectory)}</string>
37
+ <key>RunAtLoad</key>
38
+ <true/>
39
+ <key>KeepAlive</key>
40
+ <dict>
41
+ <key>SuccessfulExit</key>
42
+ <false/>
43
+ </dict>
44
+ <key>ThrottleInterval</key>
45
+ <integer>${THROTTLE_INTERVAL_S}</integer>
46
+ <key>ExitTimeOut</key>
47
+ <integer>${EXIT_TIMEOUT_S}</integer>
48
+ <key>StandardOutPath</key>
49
+ <string>${plistEscape(input.logPath)}</string>
50
+ <key>StandardErrorPath</key>
51
+ <string>${plistEscape(input.logPath)}</string>
52
+ </dict>
53
+ </plist>
54
+ `;
55
+ }
56
+ function domain() {
57
+ return `gui/${process.getuid?.() ?? 0}`;
58
+ }
59
+ function plist(identity) {
60
+ return launchdPlistPath(identity.home, identity.label);
61
+ }
62
+ function launchctl(args, tolerate = false) {
63
+ return osCommand("launchctl", args, { tolerate });
64
+ }
65
+ export const launchdOwner = {
66
+ backend: "launchd",
67
+ files: (identity) => ({ plist: plist(identity) }),
68
+ async install(identity, launcher, keepaliveArgs) {
69
+ await stopKeepalive(identity);
70
+ const file = plist(identity);
71
+ ensureUserDir(dirname(file));
72
+ atomicWrite(file, renderLaunchdPlist({
73
+ label: identity.label,
74
+ command: keepaliveCommand(launcher, keepaliveArgs),
75
+ environment: serviceEnvironment(identity),
76
+ workingDirectory: identity.home,
77
+ logPath: `${identity.serviceDir}/launchd.log`,
78
+ }), 0o644);
79
+ launchctl(["bootout", `${domain()}/${identity.label}`], true);
80
+ launchctl(["bootstrap", domain(), file]);
81
+ launchctl(["enable", `${domain()}/${identity.label}`]);
82
+ },
83
+ start(identity) {
84
+ launchctl(["bootstrap", domain(), plist(identity)], true);
85
+ launchctl(["enable", `${domain()}/${identity.label}`], true);
86
+ launchctl(["kickstart", `${domain()}/${identity.label}`]);
87
+ },
88
+ async stop(identity) {
89
+ await stopKeepalive(identity);
90
+ launchctl(["bootout", `${domain()}/${identity.label}`], true);
91
+ },
92
+ status(identity) {
93
+ const registered = existsSync(plist(identity));
94
+ const print = launchctl(["print", `${domain()}/${identity.label}`], true);
95
+ const state = /^\s*state = (\S+)/m.exec(print.stdout)?.[1] ?? null;
96
+ const pid = /^\s*pid = (\d+)/m.exec(print.stdout)?.[1];
97
+ return { registered, loaded: print.ok, state, pid: pid ? Number(pid) : null };
98
+ },
99
+ async uninstall(identity) {
100
+ await stopKeepalive(identity);
101
+ launchctl(["bootout", `${domain()}/${identity.label}`], true);
102
+ rmSync(plist(identity), { force: true });
103
+ },
104
+ };
105
+ //# sourceMappingURL=launchd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launchd.js","sourceRoot":"","sources":["../../src/service/launchd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Select one OS adapter; the adapters depend only on adapter.ts. */
2
+ import type { Backend } from './registration.js';
3
+ import type { ServiceOwner } from './adapter.js';
4
+ export declare function ownerFor(backend: Backend): ServiceOwner;
@@ -0,0 +1,14 @@
1
+ import { launchdOwner } from './launchd.js';
2
+ import { systemdOwner } from './systemd.js';
3
+ import { windowsOwner } from './windows.js';
4
+ import { portableOwner } from './portable.js';
5
+ const OWNERS = {
6
+ launchd: launchdOwner,
7
+ systemd: systemdOwner,
8
+ windows: windowsOwner,
9
+ portable: portableOwner,
10
+ };
11
+ export function ownerFor(backend) {
12
+ return OWNERS[backend];
13
+ }
14
+ //# sourceMappingURL=owner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner.js","sourceRoot":"","sources":["../../src/service/owner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,MAAM,GAA4C;IACtD,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;CACxB,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Portable: no OS owner. Containers and hosts without a user service
3
+ * manager run the keepalive themselves as the foreground workload — the
4
+ * Daytona lesson: be the declared process, never a detached one. Install
5
+ * only records the service; start prints the command to run.
6
+ */
7
+ import type { ServiceIdentity } from "./registration.js";
8
+ import type { ServiceOwner } from "./adapter.js";
9
+ export declare function portableEntrypoint(identity: ServiceIdentity, keepaliveArgs: readonly string[]): string;
10
+ export declare const portableOwner: ServiceOwner;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Portable: no OS owner. Containers and hosts without a user service
3
+ * manager run the keepalive themselves as the foreground workload — the
4
+ * Daytona lesson: be the declared process, never a detached one. Install
5
+ * only records the service; start prints the command to run.
6
+ */
7
+ import { keepaliveStatus, stopKeepalive } from "./control.js";
8
+ import { shellQuote } from "@amalgm/core/supervision";
9
+ export function portableEntrypoint(identity, keepaliveArgs) {
10
+ return ["amalgm", ...keepaliveArgs].map(shellQuote).join(" ");
11
+ }
12
+ export const portableOwner = {
13
+ backend: "portable",
14
+ files: () => ({}),
15
+ install() {
16
+ // Nothing to write: the registration record is the whole install.
17
+ },
18
+ start(identity, registration) {
19
+ throw new Error(`Portable mode has no OS owner. Run this in the foreground as your entrypoint:\n ${portableEntrypoint(identity, registration.keepalive_args)}`);
20
+ },
21
+ async stop(identity) {
22
+ await stopKeepalive(identity);
23
+ },
24
+ async status(identity) {
25
+ const keepalive = await keepaliveStatus(identity);
26
+ return { registered: true, loaded: null, state: keepalive?.alive ? "running" : "stopped", pid: keepalive?.alive ? keepalive.pid : null };
27
+ },
28
+ async uninstall(identity) {
29
+ await stopKeepalive(identity);
30
+ },
31
+ };
32
+ //# sourceMappingURL=portable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portable.js","sourceRoot":"","sources":["../../src/service/portable.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAItD,MAAM,UAAU,kBAAkB,CAAC,QAAyB,EAAE,aAAgC;IAC5F,OAAO,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IACjB,OAAO;QACL,kEAAkE;IACpE,CAAC;IACD,KAAK,CAAC,QAAQ,EAAE,YAAY;QAC1B,MAAM,IAAI,KAAK,CACb,oFAAoF,kBAAkB,CAAC,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,EAAE,CAChJ,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,QAAQ;QACjB,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,QAAQ;QACnB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3I,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,QAAQ;QACtB,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;CACF,CAAC"}