@amalgm/core 0.1.0
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/PURPOSE.md +94 -0
- package/README.md +30 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +11 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/identity/auth-records.d.ts +147 -0
- package/dist/identity/auth-records.d.ts.map +1 -0
- package/dist/identity/auth-records.js +354 -0
- package/dist/identity/auth-records.js.map +1 -0
- package/dist/identity/ids.d.ts +57 -0
- package/dist/identity/ids.d.ts.map +1 -0
- package/dist/identity/ids.js +80 -0
- package/dist/identity/ids.js.map +1 -0
- package/dist/identity/index.d.ts +14 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +14 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/labels.d.ts +115 -0
- package/dist/identity/labels.d.ts.map +1 -0
- package/dist/identity/labels.js +154 -0
- package/dist/identity/labels.js.map +1 -0
- package/dist/identity/layout.d.ts +188 -0
- package/dist/identity/layout.d.ts.map +1 -0
- package/dist/identity/layout.js +233 -0
- package/dist/identity/layout.js.map +1 -0
- package/dist/identity/ports.d.ts +31 -0
- package/dist/identity/ports.d.ts.map +1 -0
- package/dist/identity/ports.js +9 -0
- package/dist/identity/ports.js.map +1 -0
- package/dist/identity/product-state.d.ts +49 -0
- package/dist/identity/product-state.d.ts.map +1 -0
- package/dist/identity/product-state.js +55 -0
- package/dist/identity/product-state.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/supervision/app-health.d.ts +148 -0
- package/dist/supervision/app-health.d.ts.map +1 -0
- package/dist/supervision/app-health.js +165 -0
- package/dist/supervision/app-health.js.map +1 -0
- package/dist/supervision/app-restart.d.ts +105 -0
- package/dist/supervision/app-restart.d.ts.map +1 -0
- package/dist/supervision/app-restart.js +97 -0
- package/dist/supervision/app-restart.js.map +1 -0
- package/dist/supervision/health.d.ts +218 -0
- package/dist/supervision/health.d.ts.map +1 -0
- package/dist/supervision/health.js +227 -0
- package/dist/supervision/health.js.map +1 -0
- package/dist/supervision/index.d.ts +17 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +17 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/supervision/service-registration.d.ts +343 -0
- package/dist/supervision/service-registration.d.ts.map +1 -0
- package/dist/supervision/service-registration.js +543 -0
- package/dist/supervision/service-registration.js.map +1 -0
- package/dist/supervision/update.d.ts +231 -0
- package/dist/supervision/update.d.ts.map +1 -0
- package/dist/supervision/update.js +336 -0
- package/dist/supervision/update.js.map +1 -0
- package/dist/transport/admission.d.ts +235 -0
- package/dist/transport/admission.d.ts.map +1 -0
- package/dist/transport/admission.js +313 -0
- package/dist/transport/admission.js.map +1 -0
- package/dist/transport/auth.d.ts +232 -0
- package/dist/transport/auth.d.ts.map +1 -0
- package/dist/transport/auth.js +266 -0
- package/dist/transport/auth.js.map +1 -0
- package/dist/transport/index.d.ts +21 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +21 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/ingress.d.ts +94 -0
- package/dist/transport/ingress.d.ts.map +1 -0
- package/dist/transport/ingress.js +171 -0
- package/dist/transport/ingress.js.map +1 -0
- package/dist/transport/routing.d.ts +235 -0
- package/dist/transport/routing.d.ts.map +1 -0
- package/dist/transport/routing.js +288 -0
- package/dist/transport/routing.js.map +1 -0
- package/dist/transport/shipped-routes.d.ts +21 -0
- package/dist/transport/shipped-routes.d.ts.map +1 -0
- package/dist/transport/shipped-routes.js +53 -0
- package/dist/transport/shipped-routes.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host launcher registration laws — how the runtime enrolls itself with
|
|
3
|
+
* launchd, systemd, a Windows startup script, or the portable watchdog,
|
|
4
|
+
* and how it recognizes its own processes and state afterwards.
|
|
5
|
+
*
|
|
6
|
+
* Axiom 6: a host supplies its own effects. Every function here is a pure
|
|
7
|
+
* name builder, string template, or decision over injected inputs (home
|
|
8
|
+
* directory, pids, env maps, command lines); the host performs the writes,
|
|
9
|
+
* spawns, and `launchctl`/`systemctl` calls. Axiom 8: labels, file names,
|
|
10
|
+
* template bodies, and error strings are byte-exact with the engine.
|
|
11
|
+
*
|
|
12
|
+
* Engine sources (production until cutover, axiom 9):
|
|
13
|
+
* `packages/amalgm/lib/service.js`, `runtime/lib/runtime-manifest.js`,
|
|
14
|
+
* `runtime/scripts/amalgm-mcp/runtime-owner.js`, and
|
|
15
|
+
* `packages/amalgm/lib/process-cleanup.js`.
|
|
16
|
+
*/
|
|
17
|
+
import { compareVersions as defaultCompareVersions } from './update.js';
|
|
18
|
+
/* ------------------------------------------------------------------ *
|
|
19
|
+
* Labels and artifact names (engine service.js:31-33, 591-649).
|
|
20
|
+
* ------------------------------------------------------------------ */
|
|
21
|
+
/**
|
|
22
|
+
* Engine `service.js:31-32`: `${userScope}.${label}` with every character
|
|
23
|
+
* outside `[A-Za-z0-9_.-]` replaced by `_`. One label per user per branch —
|
|
24
|
+
* identity is one story (axiom 2); the scope inputs come from the identity
|
|
25
|
+
* module.
|
|
26
|
+
*/
|
|
27
|
+
export function serviceLabelScope(userScope, runtimeLabel) {
|
|
28
|
+
return `${userScope}.${runtimeLabel}`.replace(/[^A-Za-z0-9_.-]/g, '_');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Engine `service.js:33`: `ai.amalgm.runtime.${scope}`. The engine honors
|
|
32
|
+
* an `AMALGM_SERVICE_LABEL` env override; reading env is the host's job.
|
|
33
|
+
*/
|
|
34
|
+
export function serviceLabel(labelScope) {
|
|
35
|
+
return `ai.amalgm.runtime.${labelScope}`;
|
|
36
|
+
}
|
|
37
|
+
/** Engine `service.js:591-593`: `~/Library/LaunchAgents/<label>.plist`. Home is injected. */
|
|
38
|
+
export function launchdPlistPath(home, label) {
|
|
39
|
+
return `${home}/Library/LaunchAgents/${label}.plist`;
|
|
40
|
+
}
|
|
41
|
+
/** Engine `service.js:637-639`: `~/.config/systemd/user/<label>.service`. */
|
|
42
|
+
export function systemdUnitPath(home, label) {
|
|
43
|
+
return `${home}/.config/systemd/user/${label}.service`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Engine `service.js:641-649`: the per-user Startup folder script,
|
|
47
|
+
* `Amalgm-<labelScope>.vbs`. `appData` is the host's `%APPDATA%` when set;
|
|
48
|
+
* otherwise `<home>/AppData/Roaming`. Joined with `/` — a name contract,
|
|
49
|
+
* not a filesystem call site.
|
|
50
|
+
*/
|
|
51
|
+
export function windowsStartupScriptPath(labelScope, options) {
|
|
52
|
+
const appData = String(options.appData || '').trim();
|
|
53
|
+
const roaming = appData || `${options.home}/AppData/Roaming`;
|
|
54
|
+
return `${roaming}/Microsoft/Windows/Start Menu/Programs/Startup/Amalgm-${labelScope}.vbs`;
|
|
55
|
+
}
|
|
56
|
+
/* ------------------------------------------------------------------ *
|
|
57
|
+
* Escapers (engine service.js:131-146, 651-653).
|
|
58
|
+
* ------------------------------------------------------------------ */
|
|
59
|
+
/** Engine `service.js:131-133`: POSIX single-quote escaping. */
|
|
60
|
+
export function shellQuote(value) {
|
|
61
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
62
|
+
}
|
|
63
|
+
/** Engine `service.js:135-142`: the five XML entities, in engine order (`&` first). */
|
|
64
|
+
export function plistEscape(value) {
|
|
65
|
+
return String(value)
|
|
66
|
+
.replace(/&/g, '&')
|
|
67
|
+
.replace(/</g, '<')
|
|
68
|
+
.replace(/>/g, '>')
|
|
69
|
+
.replace(/"/g, '"')
|
|
70
|
+
.replace(/'/g, ''');
|
|
71
|
+
}
|
|
72
|
+
/** Engine `service.js:144-146`: systemd double-quote escaping (backslash, then quote). */
|
|
73
|
+
export function systemdQuote(value) {
|
|
74
|
+
return `"${String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
75
|
+
}
|
|
76
|
+
/** Engine `service.js:651-653`: VBScript string literal — doubled quotes. */
|
|
77
|
+
export function vbsString(value) {
|
|
78
|
+
return `"${String(value).replace(/"/g, '""')}"`;
|
|
79
|
+
}
|
|
80
|
+
/* ------------------------------------------------------------------ *
|
|
81
|
+
* Ownership and mode decisions (engine service.js:148-263, 749-780).
|
|
82
|
+
* ------------------------------------------------------------------ */
|
|
83
|
+
/**
|
|
84
|
+
* Engine `service.js:148-150`: does a path point inside a desktop app
|
|
85
|
+
* bundle (`Foo.app/Contents/Resources/cli` or `Foo.app/Contents/MacOS`)?
|
|
86
|
+
* Backslashes are normalized first. A service registration pointing at the
|
|
87
|
+
* bundle is the auto-update bundle loop: npm updates `~/.npm-global` but
|
|
88
|
+
* launchd reboots the frozen bundled copy forever.
|
|
89
|
+
*/
|
|
90
|
+
export function pathLooksLikeDesktopBundle(value) {
|
|
91
|
+
return /(?:^|\/)[^/]+\.app\/Contents\/(?:Resources\/cli|MacOS)(?:\/|$)/.test(String(value || '').replace(/\\/g, '/'));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Engine `service.js:152-167`: a registration may own the runtime unless it
|
|
95
|
+
* points at a desktop bundle (any of its paths), or explicitly declares an
|
|
96
|
+
* electron host. `runtime_host: 'node'` always may; an absent
|
|
97
|
+
* `runtime_host` is trusted (older installs, axiom 7).
|
|
98
|
+
*/
|
|
99
|
+
export function serviceStateCanOwnRuntime(state) {
|
|
100
|
+
if (!state)
|
|
101
|
+
return false;
|
|
102
|
+
const pointsAtDesktopBundle = [
|
|
103
|
+
state.package_root,
|
|
104
|
+
state.node,
|
|
105
|
+
state.bin,
|
|
106
|
+
state.files?.plist,
|
|
107
|
+
state.files?.unit,
|
|
108
|
+
state.files?.script,
|
|
109
|
+
state.files?.nodeScript,
|
|
110
|
+
].some(pathLooksLikeDesktopBundle);
|
|
111
|
+
if (pointsAtDesktopBundle)
|
|
112
|
+
return false;
|
|
113
|
+
if (state.runtime_host === 'node')
|
|
114
|
+
return true;
|
|
115
|
+
if (state.runtime_host === 'electron')
|
|
116
|
+
return false;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Engine `service.js:179-184`: a lock file names another live owner. The
|
|
121
|
+
* liveness probe is injected.
|
|
122
|
+
*/
|
|
123
|
+
export function lockOwnedByAnother(existingPid, currentPid, pidRunning) {
|
|
124
|
+
return Number.isInteger(existingPid)
|
|
125
|
+
&& existingPid > 0
|
|
126
|
+
&& existingPid !== currentPid
|
|
127
|
+
&& pidRunning(existingPid);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Engine `service.js:257-263`: mode normalization. Empty/absent → `auto`;
|
|
131
|
+
* the legacy `watchdog` alias → `portable`; anything else throws the exact
|
|
132
|
+
* engine error.
|
|
133
|
+
*/
|
|
134
|
+
export function normalizeMode(mode) {
|
|
135
|
+
const value = String(mode || 'auto').trim().toLowerCase();
|
|
136
|
+
if (!value || value === 'auto')
|
|
137
|
+
return 'auto';
|
|
138
|
+
if (value === 'watchdog')
|
|
139
|
+
return 'portable';
|
|
140
|
+
if (['portable', 'systemd', 'launchd', 'windows'].includes(value))
|
|
141
|
+
return value;
|
|
142
|
+
throw new Error(`Unsupported service mode "${mode}". Use auto, systemd, launchd, windows, or portable.`);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Engine `service.js:222-224`: `systemctl` output that means systemd is not
|
|
146
|
+
* actually available (containers, ssh sessions without a user bus, ...).
|
|
147
|
+
*/
|
|
148
|
+
export function systemdUnavailableOutput(output) {
|
|
149
|
+
return /systemd"? is not running|Failed to connect to bus|No medium found|Host is down|Connection refused/i.test(String(output || ''));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Engine `service.js:749-762`: an existing registration satisfies the
|
|
153
|
+
* request only when it points at THIS package root and version, matches
|
|
154
|
+
* the local-only flag, and matches the requested backend (with `auto`
|
|
155
|
+
* resolved to what detection would choose — the detected backend is
|
|
156
|
+
* injected, detection itself is effectful).
|
|
157
|
+
*/
|
|
158
|
+
export function stateMatchesRequest(state, options, context) {
|
|
159
|
+
if (!state)
|
|
160
|
+
return false;
|
|
161
|
+
if (state.package_root !== context.packageRoot)
|
|
162
|
+
return false;
|
|
163
|
+
if (state.package_version !== context.packageVersion)
|
|
164
|
+
return false;
|
|
165
|
+
if (!!state.local_only !== !!options.localOnly)
|
|
166
|
+
return false;
|
|
167
|
+
const requested = normalizeMode(options.mode || 'auto');
|
|
168
|
+
if (requested === 'auto') {
|
|
169
|
+
if (context.autoBackend !== state.backend)
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
else if (requested !== state.backend) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Engine `service.js:770-780`. A service registration owned by an
|
|
179
|
+
* equal-or-newer install of this package must not be replaced by an older
|
|
180
|
+
* caller (e.g. the CLI bundled inside the desktop app re-registering the
|
|
181
|
+
* service over the auto-updated npm install). Re-pointing the service at an
|
|
182
|
+
* older tree makes the auto-updater restart-loop: it installs the newer
|
|
183
|
+
* version, restarts, and boots the older tree again. Explicit
|
|
184
|
+
* `amalgm service install` still takes over. `binExists` is the injected
|
|
185
|
+
* existence probe for `state.bin`.
|
|
186
|
+
*/
|
|
187
|
+
export function deferToExistingInstall(state, options, context) {
|
|
188
|
+
if (!state || !state.backend || !state.bin || !state.package_version)
|
|
189
|
+
return false;
|
|
190
|
+
if (!serviceStateCanOwnRuntime(state))
|
|
191
|
+
return false;
|
|
192
|
+
if (state.package_root === context.packageRoot)
|
|
193
|
+
return false;
|
|
194
|
+
if (!!state.local_only !== !!options.localOnly)
|
|
195
|
+
return false;
|
|
196
|
+
const requested = normalizeMode(options.mode || 'auto');
|
|
197
|
+
if (requested !== 'auto' && requested !== state.backend)
|
|
198
|
+
return false;
|
|
199
|
+
const compare = context.compare ?? defaultCompareVersions;
|
|
200
|
+
if (compare(state.package_version, context.packageVersion) < 0)
|
|
201
|
+
return false;
|
|
202
|
+
if (!context.binExists(state.bin))
|
|
203
|
+
return false;
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
/* ------------------------------------------------------------------ *
|
|
207
|
+
* Launcher artifact bodies (engine service.js:603-632, 683-700, 655-667).
|
|
208
|
+
* ------------------------------------------------------------------ */
|
|
209
|
+
/**
|
|
210
|
+
* The launchd plist body (engine `service.js:603-632`), byte-exact:
|
|
211
|
+
* KeepAlive and RunAtLoad true, both stdio streams appended to the daemon
|
|
212
|
+
* log, program arguments `node amalgm.js run --amalgm-runtime-id=<id>`.
|
|
213
|
+
* Env entries render in the injected map's insertion order.
|
|
214
|
+
*/
|
|
215
|
+
export function buildLaunchdPlist(input) {
|
|
216
|
+
const envXml = Object.entries(input.env)
|
|
217
|
+
.map(([key, value]) => ` <key>${plistEscape(key)}</key>\n <string>${plistEscape(value)}</string>`)
|
|
218
|
+
.join('\n');
|
|
219
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
220
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
221
|
+
<plist version="1.0">
|
|
222
|
+
<dict>
|
|
223
|
+
<key>Label</key>
|
|
224
|
+
<string>${plistEscape(input.label)}</string>
|
|
225
|
+
<key>ProgramArguments</key>
|
|
226
|
+
<array>
|
|
227
|
+
<string>${plistEscape(input.execPath)}</string>
|
|
228
|
+
<string>${plistEscape(input.binPath)}</string>
|
|
229
|
+
<string>run</string>
|
|
230
|
+
<string>${plistEscape(input.runtimeInstanceArg)}</string>
|
|
231
|
+
</array>
|
|
232
|
+
<key>EnvironmentVariables</key>
|
|
233
|
+
<dict>
|
|
234
|
+
${envXml}
|
|
235
|
+
</dict>
|
|
236
|
+
<key>WorkingDirectory</key>
|
|
237
|
+
<string>${plistEscape(input.workingDirectory)}</string>
|
|
238
|
+
<key>KeepAlive</key>
|
|
239
|
+
<true/>
|
|
240
|
+
<key>RunAtLoad</key>
|
|
241
|
+
<true/>
|
|
242
|
+
<key>StandardOutPath</key>
|
|
243
|
+
<string>${plistEscape(input.daemonLogPath)}</string>
|
|
244
|
+
<key>StandardErrorPath</key>
|
|
245
|
+
<string>${plistEscape(input.daemonLogPath)}</string>
|
|
246
|
+
</dict>
|
|
247
|
+
</plist>
|
|
248
|
+
`;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The systemd user unit body (engine `service.js:683-700`), byte-exact:
|
|
252
|
+
* `Restart=always`, `RestartSec=5`, `KillSignal=SIGTERM`,
|
|
253
|
+
* `TimeoutStopSec=20`, `WantedBy=default.target`, both stdio streams
|
|
254
|
+
* appended to the daemon log via the quoted `ExecStart` shell line. The
|
|
255
|
+
* engine appends `AMALGM_NODE`/`AMALGM_BIN`/`AMALGM_DAEMON_LOG`/
|
|
256
|
+
* `AMALGM_RUNTIME_INSTANCE_ARG` after the service env; this builder does
|
|
257
|
+
* the same, so entry order matches. Note `WorkingDirectory` is rendered
|
|
258
|
+
* unescaped — engine parity.
|
|
259
|
+
*/
|
|
260
|
+
export function buildSystemdUnit(input) {
|
|
261
|
+
const env = {
|
|
262
|
+
...input.env,
|
|
263
|
+
AMALGM_NODE: input.execPath,
|
|
264
|
+
AMALGM_BIN: input.binPath,
|
|
265
|
+
AMALGM_DAEMON_LOG: input.daemonLogPath,
|
|
266
|
+
AMALGM_RUNTIME_INSTANCE_ARG: input.runtimeInstanceArg,
|
|
267
|
+
};
|
|
268
|
+
const envLines = Object.entries(env)
|
|
269
|
+
.map(([key, value]) => `Environment=${systemdQuote(`${key}=${value}`)}`)
|
|
270
|
+
.join('\n');
|
|
271
|
+
return `[Unit]
|
|
272
|
+
Description=Amalgm local runtime
|
|
273
|
+
After=network-online.target
|
|
274
|
+
Wants=network-online.target
|
|
275
|
+
|
|
276
|
+
[Service]
|
|
277
|
+
Type=simple
|
|
278
|
+
WorkingDirectory=${input.workingDirectory}
|
|
279
|
+
${envLines}
|
|
280
|
+
ExecStart=/bin/sh -lc ${systemdQuote('exec "$AMALGM_NODE" "$AMALGM_BIN" run "$AMALGM_RUNTIME_INSTANCE_ARG" >> "$AMALGM_DAEMON_LOG" 2>&1')}
|
|
281
|
+
Restart=always
|
|
282
|
+
RestartSec=5
|
|
283
|
+
KillSignal=SIGTERM
|
|
284
|
+
TimeoutStopSec=20
|
|
285
|
+
|
|
286
|
+
[Install]
|
|
287
|
+
WantedBy=default.target
|
|
288
|
+
`;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The Windows startup VBScript body (engine `service.js:655-667`): launch
|
|
292
|
+
* the portable watchdog hidden (window style 0), don't wait. CRLF line
|
|
293
|
+
* endings, trailing CRLF.
|
|
294
|
+
*/
|
|
295
|
+
export function buildWindowsStartupScript(input) {
|
|
296
|
+
const command = `"${input.execPath}" "${input.watchdogPath}"`;
|
|
297
|
+
return [
|
|
298
|
+
'Set AmalgmShell = CreateObject("WScript.Shell")',
|
|
299
|
+
`AmalgmShell.Run ${vbsString(command)}, 0, False`,
|
|
300
|
+
'',
|
|
301
|
+
].join('\r\n');
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* The runtime's own service registration (engine
|
|
305
|
+
* `runtime-manifest.js:3-40`). This constant is the RUNTIME'S declaration,
|
|
306
|
+
* not core's: core defines the `ServiceDeclaration` shape and the laws over
|
|
307
|
+
* it; the runtime is simply the first registrant, pinned here for parity
|
|
308
|
+
* tests and for hosts that supervise the shipped runtime. Launch order:
|
|
309
|
+
* port-monitor (10) → chat-server (30) → amalgm-mcp (40) → local-gateway (50).
|
|
310
|
+
*/
|
|
311
|
+
export const shippedRuntimeServices = [
|
|
312
|
+
{
|
|
313
|
+
name: 'local-gateway',
|
|
314
|
+
script: 'scripts/local-gateway.js',
|
|
315
|
+
portKey: 'gateway',
|
|
316
|
+
envName: 'AMALGM_GATEWAY_PORT',
|
|
317
|
+
stateKey: 'gateway',
|
|
318
|
+
defaultPort: 28781,
|
|
319
|
+
launchOrder: 50,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
name: 'port-monitor',
|
|
323
|
+
script: 'scripts/port-monitor.js',
|
|
324
|
+
portKey: 'portMonitor',
|
|
325
|
+
envName: 'PORT_MONITOR_PORT',
|
|
326
|
+
stateKey: 'port_monitor',
|
|
327
|
+
defaultPort: 8081,
|
|
328
|
+
launchOrder: 10,
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: 'amalgm-mcp',
|
|
332
|
+
script: 'scripts/amalgm-mcp/index.js',
|
|
333
|
+
portKey: 'amalgmMcp',
|
|
334
|
+
envName: 'AMALGM_MCP_PORT',
|
|
335
|
+
stateKey: 'amalgm_mcp',
|
|
336
|
+
defaultPort: 8083,
|
|
337
|
+
launchOrder: 40,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: 'chat-server',
|
|
341
|
+
script: 'scripts/chat-server.js',
|
|
342
|
+
portKey: 'chatServer',
|
|
343
|
+
envName: 'CHAT_SERVER_PORT',
|
|
344
|
+
stateKey: 'chat_server',
|
|
345
|
+
defaultPort: 8084,
|
|
346
|
+
launchOrder: 30,
|
|
347
|
+
},
|
|
348
|
+
];
|
|
349
|
+
/** Every runtime service answers liveness on this path (engine `runtime-manifest.js:140`). */
|
|
350
|
+
export const RUNTIME_HEALTH_PATH = '/healthz';
|
|
351
|
+
/**
|
|
352
|
+
* Engine `runtime-manifest.js:50-54`: a port is an integer in 1..65535,
|
|
353
|
+
* parsed base-10 from anything stringifiable; everything else is the
|
|
354
|
+
* fallback.
|
|
355
|
+
*/
|
|
356
|
+
export function parsePort(value, fallback = null) {
|
|
357
|
+
const port = Number.parseInt(String(value ?? ''), 10);
|
|
358
|
+
if (Number.isInteger(port) && port > 0 && port <= 65535)
|
|
359
|
+
return port;
|
|
360
|
+
return fallback;
|
|
361
|
+
}
|
|
362
|
+
/** Engine `runtime-manifest.js:60-62`: services sorted by launch order. */
|
|
363
|
+
export function runtimeLaunchServices(services = shippedRuntimeServices) {
|
|
364
|
+
return [...services].sort((left, right) => left.launchOrder - right.launchOrder);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Engine `runtime-manifest.js:96-108`: read service ports back out of
|
|
368
|
+
* runtime-state.json — the gateway from the hoisted `gateway_port` key,
|
|
369
|
+
* everything else from `ports[stateKey]`.
|
|
370
|
+
*/
|
|
371
|
+
export function runtimePortsFromState(state, services = shippedRuntimeServices) {
|
|
372
|
+
const statePorts = state?.ports || {};
|
|
373
|
+
const values = {};
|
|
374
|
+
for (const service of services) {
|
|
375
|
+
if (service.stateKey === 'gateway' && parsePort(state?.gateway_port)) {
|
|
376
|
+
values[service.name] = parsePort(state?.gateway_port);
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const port = parsePort(statePorts[service.stateKey]);
|
|
380
|
+
if (port)
|
|
381
|
+
values[service.name] = port;
|
|
382
|
+
}
|
|
383
|
+
return values;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Engine `runtime-manifest.js:126-143`: the runtime-state.json shape for
|
|
387
|
+
* allocated ports — `gateway_port` + `gateway_url` hoisted, the rest under
|
|
388
|
+
* `ports` by state key, plus a `services` list with `health_path:
|
|
389
|
+
* '/healthz'` per entry.
|
|
390
|
+
*/
|
|
391
|
+
export function runtimePortsState(ports, services = shippedRuntimeServices) {
|
|
392
|
+
const statePorts = {};
|
|
393
|
+
for (const service of services) {
|
|
394
|
+
const port = parsePort(ports?.[service.portKey]);
|
|
395
|
+
if (!port)
|
|
396
|
+
continue;
|
|
397
|
+
if (service.stateKey !== 'gateway')
|
|
398
|
+
statePorts[service.stateKey] = port;
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
gateway_port: parsePort(ports?.['gateway']) || undefined,
|
|
402
|
+
gateway_url: ports?.['gateway'] ? `http://127.0.0.1:${ports['gateway']}` : undefined,
|
|
403
|
+
ports: statePorts,
|
|
404
|
+
services: services.map((service) => ({
|
|
405
|
+
name: service.name,
|
|
406
|
+
port: parsePort(ports?.[service.portKey]),
|
|
407
|
+
health_path: RUNTIME_HEALTH_PATH,
|
|
408
|
+
})),
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* One user-state directory has one runtime owner (engine
|
|
413
|
+
* `runtime-owner.js:34-61`, decision half). The lock file is created
|
|
414
|
+
* exclusively; a live PID refuses a second owner; a dead PID is replaced.
|
|
415
|
+
* The liveness answer is injected — the host already probed
|
|
416
|
+
* `existing.pid`.
|
|
417
|
+
*/
|
|
418
|
+
export function decideOwnership(input) {
|
|
419
|
+
if (!input.existing)
|
|
420
|
+
return { action: 'acquire' };
|
|
421
|
+
if (input.pidAlive) {
|
|
422
|
+
return {
|
|
423
|
+
action: 'refuse',
|
|
424
|
+
code: 'AMALGM_RUNTIME_ALREADY_RUNNING',
|
|
425
|
+
message: `runtime state is already owned by pid ${input.existing.pid}: ${input.directory}`,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
return { action: 'replace-dead', stale: input.existing };
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Engine `runtime-owner.js:64-74`: a release only removes the lock it
|
|
432
|
+
* wrote — the pid AND token must both match, so an old process cannot
|
|
433
|
+
* remove a successor's lock during shutdown.
|
|
434
|
+
*/
|
|
435
|
+
export function releaseAllowed(owner, pid, token) {
|
|
436
|
+
return owner?.pid === pid && owner?.token === token;
|
|
437
|
+
}
|
|
438
|
+
/* ------------------------------------------------------------------ *
|
|
439
|
+
* Process identification (engine process-cleanup.js:24,118-133,157-200).
|
|
440
|
+
* ------------------------------------------------------------------ */
|
|
441
|
+
/**
|
|
442
|
+
* Engine `process-cleanup.js:24`: every supervised process carries its
|
|
443
|
+
* runtime instance id on the command line so orphans can be identified
|
|
444
|
+
* without reading `/proc` environments.
|
|
445
|
+
*/
|
|
446
|
+
export function runtimeInstanceArg(runtimeInstanceId) {
|
|
447
|
+
return `--amalgm-runtime-id=${runtimeInstanceId}`;
|
|
448
|
+
}
|
|
449
|
+
/** Engine `process-cleanup.js:165`: extract the instance id from a command line. */
|
|
450
|
+
export const RUNTIME_INSTANCE_ARG_PATTERN = /(?:^|\s)--amalgm-runtime-id(?:=|\s+)([^\s]+)/;
|
|
451
|
+
/** Engine `process-cleanup.js:163-167` (over a backslash-normalized command). */
|
|
452
|
+
export function commandRuntimeInstanceId(command) {
|
|
453
|
+
const normalized = String(command || '').replace(/\\/g, '/');
|
|
454
|
+
const match = normalized.match(RUNTIME_INSTANCE_ARG_PATTERN);
|
|
455
|
+
return match ? match[1] : '';
|
|
456
|
+
}
|
|
457
|
+
/** The suffix any supervisor command line carries (engine `process-cleanup.js:23`). */
|
|
458
|
+
export const SUPERVISOR_COMMAND_SUFFIX = '/bin/amalgm.js';
|
|
459
|
+
/** Marker paths for the runtime services, absolute under the injected runtime dir. */
|
|
460
|
+
export function runtimeServiceMarkers(runtimeDir, services = shippedRuntimeServices) {
|
|
461
|
+
return services.map((service) => `${runtimeDir}/${service.script}`.replace(/\\/g, '/'));
|
|
462
|
+
}
|
|
463
|
+
/** Relative marker suffixes (`runtime/<script>`) matching any install location. */
|
|
464
|
+
export function runtimeServiceSuffixes(services = shippedRuntimeServices) {
|
|
465
|
+
return services.map((service) => `runtime/${service.script}`.replace(/\\/g, '/'));
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Engine `process-cleanup.js:157-161`: does a process env belong to this
|
|
469
|
+
* runtime? An `AMALGM_RUNTIME_INSTANCE_ID` answers definitively; an absent
|
|
470
|
+
* `AMALGM_DIR` is trusted; otherwise the dirs must match. The engine
|
|
471
|
+
* resolves both paths — this SDK compares injected, already-resolved
|
|
472
|
+
* strings.
|
|
473
|
+
*/
|
|
474
|
+
export function envMatchesAmalgmDir(env, context) {
|
|
475
|
+
if (env?.['AMALGM_RUNTIME_INSTANCE_ID']) {
|
|
476
|
+
return env['AMALGM_RUNTIME_INSTANCE_ID'] === context.runtimeInstanceId;
|
|
477
|
+
}
|
|
478
|
+
if (!env || !env['AMALGM_DIR'])
|
|
479
|
+
return true;
|
|
480
|
+
return env['AMALGM_DIR'] === context.amalgmDir;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Engine `process-cleanup.js:175-188`: is this command line one of OUR
|
|
484
|
+
* runtime services? Marker/suffix match first; an instance-id arg answers
|
|
485
|
+
* definitively; a readable env decides next; otherwise only an absolute
|
|
486
|
+
* marker match may count, and foreign orphans need `includeOrphanedForeign`
|
|
487
|
+
* plus a parent that is not any supervisor.
|
|
488
|
+
*/
|
|
489
|
+
export function commandLooksLikeRuntimeService(command, context) {
|
|
490
|
+
const normalized = String(command || '').replace(/\\/g, '/');
|
|
491
|
+
const absoluteMatch = context.markers.some((marker) => normalized.includes(marker));
|
|
492
|
+
const suffixMatch = context.suffixes.some((marker) => normalized.includes(marker));
|
|
493
|
+
if (!absoluteMatch && !suffixMatch)
|
|
494
|
+
return false;
|
|
495
|
+
const instanceId = commandRuntimeInstanceId(normalized);
|
|
496
|
+
if (instanceId)
|
|
497
|
+
return instanceId === context.runtimeInstanceId;
|
|
498
|
+
const item = context.item;
|
|
499
|
+
if (item?.env && envMatchesAmalgmDir(item.env, context))
|
|
500
|
+
return true;
|
|
501
|
+
if (item?.env)
|
|
502
|
+
return false;
|
|
503
|
+
if (!absoluteMatch)
|
|
504
|
+
return false;
|
|
505
|
+
if (!context.includeOrphanedForeign)
|
|
506
|
+
return false;
|
|
507
|
+
const parent = String(item?.parentCommand || '').replace(/\\/g, '/');
|
|
508
|
+
return !commandLooksLikeAnySupervisor(parent);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Engine `process-cleanup.js:190-195`: OUR supervisor — the absolute
|
|
512
|
+
* `bin/amalgm.js` marker, a `run` word, and a definitively matching
|
|
513
|
+
* instance-id arg.
|
|
514
|
+
*/
|
|
515
|
+
export function commandLooksLikeSupervisor(command, context) {
|
|
516
|
+
const normalized = String(command || '').replace(/\\/g, '/');
|
|
517
|
+
if (!normalized.includes(context.supervisorMarker) || !/\brun\b/.test(normalized))
|
|
518
|
+
return false;
|
|
519
|
+
const instanceId = commandRuntimeInstanceId(normalized);
|
|
520
|
+
return instanceId !== '' && instanceId === context.runtimeInstanceId;
|
|
521
|
+
}
|
|
522
|
+
/** Engine `process-cleanup.js:197-200`: ANY amalgm supervisor, ours or not. */
|
|
523
|
+
export function commandLooksLikeAnySupervisor(command) {
|
|
524
|
+
const normalized = String(command || '').replace(/\\/g, '/');
|
|
525
|
+
return normalized.includes(SUPERVISOR_COMMAND_SUFFIX) && /\brun\b/.test(normalized);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Engine `process-cleanup.js:120`: one `ps -eo pid=,ppid=,command=` line —
|
|
529
|
+
* `/^(\d+)\s+(\d+)\s+(.+)$/` over the trimmed line.
|
|
530
|
+
*/
|
|
531
|
+
export const PS_LINE_PATTERN = /^(\d+)\s+(\d+)\s+(.+)$/;
|
|
532
|
+
/** Parse one ps line (engine `process-cleanup.js:117-129`); null when it doesn't match. */
|
|
533
|
+
export function parsePsLine(line) {
|
|
534
|
+
const match = line.trim().match(PS_LINE_PATTERN);
|
|
535
|
+
if (!match)
|
|
536
|
+
return null;
|
|
537
|
+
return {
|
|
538
|
+
pid: Number(match[1]),
|
|
539
|
+
ppid: Number(match[2]),
|
|
540
|
+
command: match[3],
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=service-registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-registration.js","sourceRoot":"","sources":["../../src/supervision/service-registration.ts"],"names":[],"mappings":"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"}
|