amalgm 0.1.145 → 0.1.146
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/lib/service.js +1 -1
- package/lib/supervisor.js +37 -19
- package/package.json +1 -1
- package/runtime/scripts/amalgm-mcp/events/desktop-release-runner.js +12 -56
- package/runtime/scripts/amalgm-mcp/lib/email-embeds.js +1 -1
- package/runtime/scripts/amalgm-mcp/lib/email-md.js +1 -1
- package/runtime/scripts/amalgm-mcp/lib/generated/email-render.json +1 -1
- package/runtime/scripts/amalgm-mcp/tests/desktop-release-runner.test.js +1 -28
- package/runtime/scripts/amalgm-mcp/tests/email-render.test.js +1 -1
- package/runtime/scripts/runtime-auth.js +0 -1
package/lib/service.js
CHANGED
|
@@ -248,7 +248,7 @@ function runningInContainer() {
|
|
|
248
248
|
if (fs.existsSync('/.dockerenv') || fs.existsSync('/run/.containerenv')) return true;
|
|
249
249
|
try {
|
|
250
250
|
const cgroup = fs.readFileSync('/proc/1/cgroup', 'utf8');
|
|
251
|
-
return /docker|kubepods|containerd|libpod|lxc|
|
|
251
|
+
return /docker|kubepods|containerd|libpod|lxc|e2b/i.test(cgroup);
|
|
252
252
|
} catch {
|
|
253
253
|
return false;
|
|
254
254
|
}
|
package/lib/supervisor.js
CHANGED
|
@@ -86,6 +86,11 @@ const CHILD_HEALTH_POLICY = {
|
|
|
86
86
|
maxFailures: 3,
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
const CHAT_SERVER_HEALTH_POLICY = {
|
|
90
|
+
timeoutMs: 15000,
|
|
91
|
+
maxFailures: 6,
|
|
92
|
+
};
|
|
93
|
+
|
|
89
94
|
const AUTO_UPDATE_POLICY = {
|
|
90
95
|
checkIntervalMs: 15 * 60_000,
|
|
91
96
|
initialDelayMs: 60_000,
|
|
@@ -289,19 +294,30 @@ function baseRuntimeEnv(record, ports, options = {}) {
|
|
|
289
294
|
|
|
290
295
|
function serviceSpecs(record, ports, options = {}) {
|
|
291
296
|
const env = baseRuntimeEnv(record, ports, options);
|
|
292
|
-
return runtimeLaunchServices().map((service) =>
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
297
|
+
return runtimeLaunchServices().map((service) => {
|
|
298
|
+
const healthPolicy = healthPolicyForService(service.name);
|
|
299
|
+
return {
|
|
300
|
+
name: service.name,
|
|
301
|
+
command: process.execPath,
|
|
302
|
+
args: [runtimeEntry(service.script), RUNTIME_INSTANCE_ARG],
|
|
303
|
+
env: service.name === 'port-monitor' ? { ...env, PORT: process.env.PORT || '0' } : env,
|
|
304
|
+
port: ports[service.portKey],
|
|
305
|
+
healthPath: '/healthz',
|
|
306
|
+
expectedRuntimeInstanceId: AMALGM_RUNTIME_INSTANCE_ID,
|
|
307
|
+
expectedService: service.name,
|
|
308
|
+
healthPolicy,
|
|
309
|
+
healthHeaders: env.AMALGM_RUNTIME_TOKEN
|
|
310
|
+
? { 'x-amalgm-runtime-token': env.AMALGM_RUNTIME_TOKEN }
|
|
311
|
+
: {},
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function healthPolicyForService(serviceName) {
|
|
317
|
+
return {
|
|
318
|
+
...CHILD_HEALTH_POLICY,
|
|
319
|
+
...(serviceName === 'chat-server' ? CHAT_SERVER_HEALTH_POLICY : {}),
|
|
320
|
+
};
|
|
305
321
|
}
|
|
306
322
|
|
|
307
323
|
function isPortFree(port, host = '127.0.0.1') {
|
|
@@ -983,6 +999,7 @@ function checkServiceHealth(spec, timeoutMs = CHILD_HEALTH_POLICY.timeoutMs) {
|
|
|
983
999
|
|
|
984
1000
|
function createManagedProcess(spec, options) {
|
|
985
1001
|
const { stream } = openServiceLog(spec.name);
|
|
1002
|
+
const healthPolicy = { ...CHILD_HEALTH_POLICY, ...(spec.healthPolicy || {}) };
|
|
986
1003
|
let child = null;
|
|
987
1004
|
let stopped = false;
|
|
988
1005
|
let restartTimer = null;
|
|
@@ -1026,12 +1043,12 @@ function createManagedProcess(spec, options) {
|
|
|
1026
1043
|
};
|
|
1027
1044
|
|
|
1028
1045
|
const scheduleHealthCheck = () => {
|
|
1029
|
-
const delayMs = state === 'running' ?
|
|
1046
|
+
const delayMs = state === 'running' ? healthPolicy.intervalMs : 500;
|
|
1030
1047
|
clearHealthTimer();
|
|
1031
1048
|
if (stopped) return;
|
|
1032
1049
|
healthTimer = setTimeout(async () => {
|
|
1033
1050
|
if (stopped || !child) return;
|
|
1034
|
-
const ok = await checkServiceHealth(spec);
|
|
1051
|
+
const ok = await checkServiceHealth(spec, healthPolicy.timeoutMs);
|
|
1035
1052
|
if (stopped || !child) return;
|
|
1036
1053
|
if (ok) {
|
|
1037
1054
|
healthFailures = 0;
|
|
@@ -1040,7 +1057,7 @@ function createManagedProcess(spec, options) {
|
|
|
1040
1057
|
settleReady();
|
|
1041
1058
|
}
|
|
1042
1059
|
} else {
|
|
1043
|
-
if (Date.now() - startedAt <
|
|
1060
|
+
if (Date.now() - startedAt < healthPolicy.graceMs) {
|
|
1044
1061
|
scheduleHealthCheck();
|
|
1045
1062
|
return;
|
|
1046
1063
|
}
|
|
@@ -1048,10 +1065,10 @@ function createManagedProcess(spec, options) {
|
|
|
1048
1065
|
writePrefixed(
|
|
1049
1066
|
stream,
|
|
1050
1067
|
spec.name,
|
|
1051
|
-
`health check failed (${healthFailures}/${
|
|
1068
|
+
`health check failed (${healthFailures}/${healthPolicy.maxFailures})\n`,
|
|
1052
1069
|
options.foreground ? process.stderr : null,
|
|
1053
1070
|
);
|
|
1054
|
-
if (healthFailures >=
|
|
1071
|
+
if (healthFailures >= healthPolicy.maxFailures) {
|
|
1055
1072
|
setState('restarting', { reason: 'health_check_failed' });
|
|
1056
1073
|
try {
|
|
1057
1074
|
child.kill('SIGTERM');
|
|
@@ -1105,7 +1122,7 @@ function createManagedProcess(spec, options) {
|
|
|
1105
1122
|
if (readyTimer) clearTimeout(readyTimer);
|
|
1106
1123
|
readyTimer = setTimeout(() => {
|
|
1107
1124
|
settleReady(new Error(`${spec.name} did not become healthy on port ${spec.port}`));
|
|
1108
|
-
},
|
|
1125
|
+
}, healthPolicy.graceMs + ((healthPolicy.intervalMs + healthPolicy.timeoutMs) * healthPolicy.maxFailures));
|
|
1109
1126
|
}
|
|
1110
1127
|
child = spawn(spec.command, spec.args, {
|
|
1111
1128
|
cwd: RUNTIME_DIR,
|
|
@@ -1333,6 +1350,7 @@ async function startSupervisor(options = {}) {
|
|
|
1333
1350
|
module.exports = {
|
|
1334
1351
|
startSupervisor,
|
|
1335
1352
|
_test: {
|
|
1353
|
+
healthPolicyForService,
|
|
1336
1354
|
liveDeclaredRuntimePorts,
|
|
1337
1355
|
runtimeStateFilesUnder,
|
|
1338
1356
|
runtimeStateSearchRoots,
|
package/package.json
CHANGED
|
@@ -719,12 +719,9 @@ function envForBuild(
|
|
|
719
719
|
...baseEnv,
|
|
720
720
|
DESKTOP_RELEASE_LANE: request.lane,
|
|
721
721
|
DESKTOP_RELEASE_CHANNEL: request.lane === 'preview' ? 'preview' : 'latest',
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
...(desktopRendererDelivery(baseEnv) === 'bundled-next' ? {
|
|
726
|
-
NEXT_IMAGE_UNOPTIMIZED: '1',
|
|
727
|
-
} : {}),
|
|
722
|
+
AMALGM_DESKTOP_RENDERER_DELIVERY: 'bundled-next',
|
|
723
|
+
AMALGM_DESKTOP_RUNTIME_DELIVERY: 'npm',
|
|
724
|
+
NEXT_IMAGE_UNOPTIMIZED: '1',
|
|
728
725
|
AMALGM_RUNTIME_LABEL: request.lane === 'preview' ? 'preview' : 'main',
|
|
729
726
|
AMALGM_BRANCH: request.lane,
|
|
730
727
|
ELECTRON_VERSION: version,
|
|
@@ -770,33 +767,6 @@ function envForBuild(
|
|
|
770
767
|
return env;
|
|
771
768
|
}
|
|
772
769
|
|
|
773
|
-
function desktopThinRuntimeBuildEnabled(env = process.env) {
|
|
774
|
-
const raw = cleanString(env.AMALGM_DESKTOP_THIN || env.DESKTOP_THIN_BUILD).toLowerCase();
|
|
775
|
-
if (!raw) return true;
|
|
776
|
-
if (['1', 'true', 'yes', 'on'].includes(raw)) return true;
|
|
777
|
-
if (['0', 'false', 'no', 'off'].includes(raw)) return false;
|
|
778
|
-
throw new Error(`Unsupported AMALGM_DESKTOP_THIN value: ${raw}`);
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
function desktopRendererDelivery(env = process.env) {
|
|
782
|
-
const raw = cleanString(
|
|
783
|
-
env.AMALGM_DESKTOP_RENDERER_DELIVERY
|
|
784
|
-
|| env.AMALGM_DESKTOP_UI_DELIVERY
|
|
785
|
-
|| (cleanString(env.AMALGM_DESKTOP_UI_MODE).toLowerCase() === 'local' ? 'bundled-next' : ''),
|
|
786
|
-
).toLowerCase();
|
|
787
|
-
if (!raw) return desktopThinRuntimeBuildEnabled(env) ? 'hosted' : 'bundled-next';
|
|
788
|
-
if (['hosted', 'remote', 'web'].includes(raw)) return 'hosted';
|
|
789
|
-
if (['bundled-next', 'bundled', 'local', 'next', 'local-next'].includes(raw)) return 'bundled-next';
|
|
790
|
-
throw new Error(`Unsupported AMALGM_DESKTOP_RENDERER_DELIVERY value: ${raw}`);
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
function desktopRuntimeDelivery(env = process.env) {
|
|
794
|
-
const raw = cleanString(env.AMALGM_DESKTOP_RUNTIME_DELIVERY).toLowerCase();
|
|
795
|
-
if (!raw) return desktopThinRuntimeBuildEnabled(env) ? 'npm' : 'bundled-with-npm-handoff';
|
|
796
|
-
if (['npm', 'managed-npm'].includes(raw)) return 'npm';
|
|
797
|
-
if (['bundled-with-npm-handoff', 'bundled', 'local', 'embedded'].includes(raw)) return 'bundled-with-npm-handoff';
|
|
798
|
-
throw new Error(`Unsupported AMALGM_DESKTOP_RUNTIME_DELIVERY value: ${raw}`);
|
|
799
|
-
}
|
|
800
770
|
|
|
801
771
|
function appOriginForLane(lane, env = process.env) {
|
|
802
772
|
if (lane === 'preview') {
|
|
@@ -1802,29 +1772,15 @@ function publishDesktopRelease(request, options = {}) {
|
|
|
1802
1772
|
run('git', ['push', 'origin', `refs/tags/v${version}`, '--force'], { cwd: engineDir });
|
|
1803
1773
|
run('npm', ['version', '--no-git-tag-version', '--allow-same-version', version], { cwd: engineDir, env: releaseEnv });
|
|
1804
1774
|
run('npm', ['run', 'compile'], { cwd: engineDir, env: releaseEnv });
|
|
1805
|
-
|
|
1806
|
-
const
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
appOrigin = writeBundledWebEnv(engineDir, request.lane, releaseEnv);
|
|
1815
|
-
run('npm', ['run', 'build:next'], {
|
|
1816
|
-
cwd: engineDir,
|
|
1817
|
-
env: {
|
|
1818
|
-
...releaseEnv,
|
|
1819
|
-
NEXT_IMAGE_UNOPTIMIZED: '1',
|
|
1820
|
-
},
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
if (npmRuntime) {
|
|
1824
|
-
console.log('Building desktop shell with managed npm runtime; skipping bundled engine runtime payload.');
|
|
1825
|
-
} else {
|
|
1826
|
-
run('npm', ['run', 'npm:sync'], { cwd: engineDir, env: releaseEnv });
|
|
1827
|
-
}
|
|
1775
|
+
copyUiIntoEngine(uiDir, engineDir);
|
|
1776
|
+
const appOrigin = writeBundledWebEnv(engineDir, request.lane, releaseEnv);
|
|
1777
|
+
run('npm', ['run', 'build:next'], {
|
|
1778
|
+
cwd: engineDir,
|
|
1779
|
+
env: {
|
|
1780
|
+
...releaseEnv,
|
|
1781
|
+
NEXT_IMAGE_UNOPTIMIZED: '1',
|
|
1782
|
+
},
|
|
1783
|
+
});
|
|
1828
1784
|
if (request.lane === 'preview') run('npm', ['run', 'assets:preview-icon'], { cwd: engineDir, env: releaseEnv });
|
|
1829
1785
|
|
|
1830
1786
|
const buildEnv = envForBuild(releaseEnv, request, sourcePackageVersion, version, refs, shas, appOrigin, releaseRepository, publishTarget);
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
// GENERATED tokens/chrome — serialized from lib/rendering/tokens.ts and
|
|
19
|
-
// chromeTokens.ts by scripts/
|
|
19
|
+
// chromeTokens.ts by scripts/email-render/generate-email-render-assets.mts.
|
|
20
20
|
// No hand-mirrored values here: change the canonical file and regenerate.
|
|
21
21
|
const RENDER_ASSETS = require('./generated/email-render.json');
|
|
22
22
|
const TOKENS = RENDER_ASSETS.tokens;
|
|
@@ -21,7 +21,7 @@ const embeds = require('./email-embeds');
|
|
|
21
21
|
const { buildEmailRenderContext, normalizeEmailLink } = require('./email-deeplinks');
|
|
22
22
|
|
|
23
23
|
// GENERATED from lib/rendering/tokens.ts by
|
|
24
|
-
// scripts/
|
|
24
|
+
// scripts/email-render/generate-email-render-assets.mts — the deterministic
|
|
25
25
|
// adapter. There is no hand-mirrored token copy anymore; change tokens.ts
|
|
26
26
|
// (or Citation.tsx for the templates below) and regenerate.
|
|
27
27
|
const RENDER_ASSETS = require('./generated/email-render.json');
|
|
@@ -246,40 +246,13 @@ test('desktop release runner uses electron-builder compatible signing identity n
|
|
|
246
246
|
assert.equal(env.AMALGM_DESKTOP_RELEASE_UPLOAD_URL, 'https://amalgm-desktop-releases.fly.dev/');
|
|
247
247
|
assert.equal(env.AMALGM_DESKTOP_RELEASE_FLY_APP, 'amalgm-desktop-releases');
|
|
248
248
|
assert.equal(env.AMALGM_DESKTOP_RELEASE_FLY_ROOT, '/data');
|
|
249
|
-
assert.equal(env.AMALGM_DESKTOP_THIN, '1');
|
|
250
249
|
assert.equal(env.AMALGM_DESKTOP_NOTARIZE, 'off');
|
|
251
250
|
});
|
|
252
251
|
|
|
253
|
-
test('desktop release runner
|
|
252
|
+
test('desktop release runner always builds bundled UI with npm runtime', () => {
|
|
254
253
|
const env = envForBuild(
|
|
255
254
|
{
|
|
256
255
|
GH_TOKEN: 'token',
|
|
257
|
-
AMALGM_DESKTOP_THIN: '0',
|
|
258
|
-
NEXT_PUBLIC_SUPABASE_URL: 'https://example.supabase.co',
|
|
259
|
-
NEXT_PUBLIC_SUPABASE_ANON_KEY: 'anon-key',
|
|
260
|
-
},
|
|
261
|
-
{ lane: 'main', delivery: 'delivery-id' },
|
|
262
|
-
'0.1.124',
|
|
263
|
-
'0.1.124000001',
|
|
264
|
-
{ engineRef: 'engine', uiRef: 'ui' },
|
|
265
|
-
{ engineSha: 'engine-sha', uiSha: 'ui-sha' },
|
|
266
|
-
'https://amalgm.ai',
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
assert.equal(env.AMALGM_DESKTOP_THIN, '0');
|
|
270
|
-
assert.equal(env.AMALGM_DESKTOP_RENDERER_DELIVERY, 'bundled-next');
|
|
271
|
-
assert.equal(env.AMALGM_DESKTOP_RUNTIME_DELIVERY, 'bundled-with-npm-handoff');
|
|
272
|
-
assert.equal(env.NEXT_IMAGE_UNOPTIMIZED, '1');
|
|
273
|
-
assert.equal(env.NEXT_PUBLIC_SUPABASE_URL, 'https://example.supabase.co');
|
|
274
|
-
assert.equal(env.NEXT_PUBLIC_SUPABASE_ANON_KEY, 'anon-key');
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
test('desktop release runner supports bundled UI with npm runtime', () => {
|
|
278
|
-
const env = envForBuild(
|
|
279
|
-
{
|
|
280
|
-
GH_TOKEN: 'token',
|
|
281
|
-
AMALGM_DESKTOP_RENDERER_DELIVERY: 'bundled-next',
|
|
282
|
-
AMALGM_DESKTOP_RUNTIME_DELIVERY: 'npm',
|
|
283
256
|
NEXT_PUBLIC_SUPABASE_URL: 'https://example.supabase.co',
|
|
284
257
|
NEXT_PUBLIC_SUPABASE_ANON_KEY: 'anon-key',
|
|
285
258
|
},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* email-render-goldens/. The full notification shell is covered once.
|
|
9
9
|
*
|
|
10
10
|
* When output changes on purpose (tokens, chrome, templates, renderer):
|
|
11
|
-
* UPDATE_GOLDENS=1 node --test scripts/
|
|
11
|
+
* UPDATE_GOLDENS=1 node --test scripts/email-render/tests/email-render.test.js
|
|
12
12
|
* then review the golden diff like any code change.
|
|
13
13
|
*/
|
|
14
14
|
|