@slock-ai/computer 0.0.6 → 0.0.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.
- package/dist/index.js +105 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -304,6 +304,13 @@ function upgradeStagingDir(slockHome, version) {
|
|
|
304
304
|
function upgradeSnapshotPath(slockHome) {
|
|
305
305
|
return path.join(computerDir(slockHome), "upgrade-snapshot.json");
|
|
306
306
|
}
|
|
307
|
+
function upgradeLogPath(slockHome) {
|
|
308
|
+
return path.join(computerDir(slockHome), "upgrade.log");
|
|
309
|
+
}
|
|
310
|
+
function formatUpgradeLogTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
311
|
+
const iso = date.toISOString();
|
|
312
|
+
return iso.replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
|
|
313
|
+
}
|
|
307
314
|
|
|
308
315
|
// src/output.ts
|
|
309
316
|
var CliExit = class extends Error {
|
|
@@ -1411,6 +1418,44 @@ async function runResident(serverId, deps = {}) {
|
|
|
1411
1418
|
}
|
|
1412
1419
|
var RECONCILE_INTERVAL_MS = 5e3;
|
|
1413
1420
|
var CHILD_RESTART_BACKOFF_MS = 2e3;
|
|
1421
|
+
var START_ENSURE_TIMEOUT_MS = 15e3;
|
|
1422
|
+
var START_ENSURE_POLL_INTERVAL_MS = 100;
|
|
1423
|
+
async function waitForManagedDaemonPids(slockHome, serverIds, deps) {
|
|
1424
|
+
const readPidfile = deps.readPidfile ?? readPidfileAt;
|
|
1425
|
+
const isAlive = deps.isProcessAlive ?? isProcessAlive2;
|
|
1426
|
+
const sleep2 = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1427
|
+
const timeoutMs = deps.ensureTimeoutMs ?? START_ENSURE_TIMEOUT_MS;
|
|
1428
|
+
const pollIntervalMs = deps.ensurePollIntervalMs ?? START_ENSURE_POLL_INTERVAL_MS;
|
|
1429
|
+
const deadline = Date.now() + timeoutMs;
|
|
1430
|
+
const ready = /* @__PURE__ */ new Map();
|
|
1431
|
+
while (ready.size < serverIds.length) {
|
|
1432
|
+
for (const serverId of serverIds) {
|
|
1433
|
+
if (ready.has(serverId)) continue;
|
|
1434
|
+
const pid = await readPidfile(serverDaemonPidPath(slockHome, serverId));
|
|
1435
|
+
if (pid && isAlive(pid)) ready.set(serverId, pid);
|
|
1436
|
+
}
|
|
1437
|
+
if (ready.size === serverIds.length) return ready;
|
|
1438
|
+
const remaining = deadline - Date.now();
|
|
1439
|
+
if (remaining <= 0) return ready;
|
|
1440
|
+
await sleep2(Math.min(pollIntervalMs, remaining));
|
|
1441
|
+
}
|
|
1442
|
+
return ready;
|
|
1443
|
+
}
|
|
1444
|
+
function formatReadySummary(ready, serverIds, opts) {
|
|
1445
|
+
if (opts.serverId && serverIds.length === 1) {
|
|
1446
|
+
const pid = ready.get(opts.serverId);
|
|
1447
|
+
return `Daemon for server ${opts.serverLabel ?? opts.serverId} is running${pid ? ` (pid ${pid})` : ""}.`;
|
|
1448
|
+
}
|
|
1449
|
+
return `Daemons for ${serverIds.length} managed server(s) are running.`;
|
|
1450
|
+
}
|
|
1451
|
+
function failStartEnsureTimeout(slockHome, serverIds, ready, opts) {
|
|
1452
|
+
const missing = serverIds.filter((id) => !ready.has(id));
|
|
1453
|
+
const target = opts.serverId && missing.length === 1 ? `${opts.serverLabel ?? opts.serverId}` : `${missing.length} daemon(s): ${missing.join(", ")}`;
|
|
1454
|
+
fail(
|
|
1455
|
+
"START_DAEMON_TIMEOUT",
|
|
1456
|
+
`Timed out waiting for ${target} to start. Run \`slock-computer status\` and inspect ${supervisorLogPath(slockHome)} plus per-server daemon logs under ~/.slock/computer/servers/<serverId>/daemon.log.`
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1414
1459
|
async function runSupervisorStartupRecovery(slockHome) {
|
|
1415
1460
|
const parentHoldsLock = process.env[PARENT_LOCK_HELD_ENV_VAR] === "1";
|
|
1416
1461
|
try {
|
|
@@ -1592,7 +1637,7 @@ async function runSupervise() {
|
|
|
1592
1637
|
await new Promise(() => {
|
|
1593
1638
|
});
|
|
1594
1639
|
}
|
|
1595
|
-
async function runStart(opts = {},
|
|
1640
|
+
async function runStart(opts = {}, deps = {}) {
|
|
1596
1641
|
const slockHome = resolveSlockHome();
|
|
1597
1642
|
const attached = await listAttachedServerIds(slockHome);
|
|
1598
1643
|
if (attached.length === 0) {
|
|
@@ -1614,9 +1659,11 @@ async function runStart(opts = {}, _deps = {}) {
|
|
|
1614
1659
|
const existing = await readPidfileAt(supervisorPidPath(slockHome));
|
|
1615
1660
|
if (existing && isProcessAlive2(existing)) {
|
|
1616
1661
|
info(`Supervisor already running (pid ${existing}).`);
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1662
|
+
const ready2 = await waitForManagedDaemonPids(slockHome, managedTargets, deps);
|
|
1663
|
+
if (ready2.size !== managedTargets.length) {
|
|
1664
|
+
failStartEnsureTimeout(slockHome, managedTargets, ready2, opts);
|
|
1665
|
+
}
|
|
1666
|
+
info(formatReadySummary(ready2, managedTargets, opts));
|
|
1620
1667
|
return;
|
|
1621
1668
|
}
|
|
1622
1669
|
if (opts.foreground) {
|
|
@@ -1628,12 +1675,17 @@ async function runStart(opts = {}, _deps = {}) {
|
|
|
1628
1675
|
}
|
|
1629
1676
|
let pid;
|
|
1630
1677
|
try {
|
|
1631
|
-
pid = await spawnDetachedSupervisor(slockHome);
|
|
1678
|
+
pid = await (deps.spawnDetachedSupervisor ?? spawnDetachedSupervisor)(slockHome);
|
|
1632
1679
|
} catch (err) {
|
|
1633
1680
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1634
1681
|
fail("SUPERVISOR_SPAWN_FAILED", msg);
|
|
1635
1682
|
}
|
|
1636
1683
|
info(`Supervisor started (pid ${pid}); keeps running after this terminal closes.`);
|
|
1684
|
+
const ready = await waitForManagedDaemonPids(slockHome, managedTargets, deps);
|
|
1685
|
+
if (ready.size !== managedTargets.length) {
|
|
1686
|
+
failStartEnsureTimeout(slockHome, managedTargets, ready, opts);
|
|
1687
|
+
}
|
|
1688
|
+
info(formatReadySummary(ready, managedTargets, opts));
|
|
1637
1689
|
info(
|
|
1638
1690
|
`Managing ${managedTargets.length} of ${attached.length} attached server(s). Logs: ${supervisorLogPath(slockHome)}`
|
|
1639
1691
|
);
|
|
@@ -3298,6 +3350,26 @@ async function locateStagedTarball(stagedPath) {
|
|
|
3298
3350
|
return join6(stagedPath, tgz);
|
|
3299
3351
|
}
|
|
3300
3352
|
|
|
3353
|
+
// src/upgradeLog.ts
|
|
3354
|
+
import { chmod as chmod5, mkdir as mkdir12, open as open2 } from "fs/promises";
|
|
3355
|
+
var FILE_MODE = 384;
|
|
3356
|
+
async function appendUpgradeLogEntry(slockHome, entry) {
|
|
3357
|
+
await mkdir12(computerDir(slockHome), { recursive: true });
|
|
3358
|
+
const path2 = upgradeLogPath(slockHome);
|
|
3359
|
+
const at = entry.at ?? formatUpgradeLogTimestamp();
|
|
3360
|
+
const fullEntry = { ...entry, at };
|
|
3361
|
+
const line = JSON.stringify(fullEntry) + "\n";
|
|
3362
|
+
const handle = await open2(path2, "a", FILE_MODE);
|
|
3363
|
+
try {
|
|
3364
|
+
await handle.write(line);
|
|
3365
|
+
} finally {
|
|
3366
|
+
await handle.close();
|
|
3367
|
+
}
|
|
3368
|
+
if (process.platform !== "win32") {
|
|
3369
|
+
await chmod5(path2, FILE_MODE);
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3301
3373
|
// src/upgradeCli.ts
|
|
3302
3374
|
async function defaultSpawnFreshSupervisor(slockHome) {
|
|
3303
3375
|
await spawnDetachedSupervisor(slockHome);
|
|
@@ -3400,14 +3472,35 @@ async function runUpgradeCli(slockHome, opts, deps = {}) {
|
|
|
3400
3472
|
spawnFreshSupervisor: () => spawnFreshSupervisor(slockHome)
|
|
3401
3473
|
}
|
|
3402
3474
|
});
|
|
3475
|
+
const bundle = (version) => ({
|
|
3476
|
+
computerVersion: version
|
|
3477
|
+
});
|
|
3478
|
+
const logTrigger = opts.trigger ?? "cli";
|
|
3403
3479
|
if (outcome.ok) {
|
|
3404
3480
|
info(
|
|
3405
3481
|
`Upgrade ${fromVersion} \u2192 ${targetVersion} succeeded (health-OK in ${outcome.restart?.healthAfterMs ?? 0}ms).`
|
|
3406
3482
|
);
|
|
3483
|
+
await appendUpgradeLogEntry(slockHome, {
|
|
3484
|
+
fromBundle: bundle(fromVersion),
|
|
3485
|
+
toBundle: bundle(targetVersion),
|
|
3486
|
+
channel: channel2,
|
|
3487
|
+
trigger: logTrigger,
|
|
3488
|
+
outcome: "ok"
|
|
3489
|
+
}).catch(() => {
|
|
3490
|
+
});
|
|
3407
3491
|
return;
|
|
3408
3492
|
}
|
|
3409
3493
|
const code = mapFailurePhaseToCode(outcome);
|
|
3410
3494
|
const rolledBack = outcome.rolledBack === true ? " (swap rolled back)" : "";
|
|
3495
|
+
await appendUpgradeLogEntry(slockHome, {
|
|
3496
|
+
fromBundle: bundle(fromVersion),
|
|
3497
|
+
toBundle: bundle(targetVersion),
|
|
3498
|
+
channel: channel2,
|
|
3499
|
+
trigger: logTrigger,
|
|
3500
|
+
outcome: "err",
|
|
3501
|
+
errorCode: code
|
|
3502
|
+
}).catch(() => {
|
|
3503
|
+
});
|
|
3411
3504
|
fail(
|
|
3412
3505
|
code,
|
|
3413
3506
|
`Upgrade failed at phase=${outcome.phase}: ${outcome.reason ?? "unknown"}${rolledBack}.`
|
|
@@ -3473,7 +3566,7 @@ async function defaultCurrentVersion() {
|
|
|
3473
3566
|
}
|
|
3474
3567
|
|
|
3475
3568
|
// src/upgradeTestHarness.ts
|
|
3476
|
-
import { mkdir as
|
|
3569
|
+
import { mkdir as mkdir13, readdir as readdir4, stat as stat3, writeFile as writeFile10 } from "fs/promises";
|
|
3477
3570
|
import { join as join8 } from "path";
|
|
3478
3571
|
import { createHash as createHash4 } from "crypto";
|
|
3479
3572
|
var PHASES = /* @__PURE__ */ new Set([
|
|
@@ -3544,7 +3637,7 @@ function buildSimulatedDeps(slockHome, opts) {
|
|
|
3544
3637
|
if (opts.simulateFail === "extract") {
|
|
3545
3638
|
return { exitCode: 1, stderr: "simulated extract failure" };
|
|
3546
3639
|
}
|
|
3547
|
-
await
|
|
3640
|
+
await mkdir13(join8(destDir, "package"), { recursive: true });
|
|
3548
3641
|
await writeFile10(join8(destDir, "package", "marker.txt"), `NEW@${targetVersion}`);
|
|
3549
3642
|
return { exitCode: 0, stderr: "" };
|
|
3550
3643
|
},
|
|
@@ -3605,7 +3698,7 @@ function buildSimulatedDeps(slockHome, opts) {
|
|
|
3605
3698
|
}
|
|
3606
3699
|
async function arrangeSnapshotFailure(slockHome) {
|
|
3607
3700
|
const snapshotPath = join8(slockHome, "computer", "upgrade-snapshot.json");
|
|
3608
|
-
await
|
|
3701
|
+
await mkdir13(snapshotPath, { recursive: true });
|
|
3609
3702
|
}
|
|
3610
3703
|
async function pathInfo(path2) {
|
|
3611
3704
|
try {
|
|
@@ -3660,12 +3753,12 @@ async function runUpgradeTestHarness(slockHome, opts, writer = (s) => process.st
|
|
|
3660
3753
|
process.exitCode = 1;
|
|
3661
3754
|
return;
|
|
3662
3755
|
}
|
|
3663
|
-
await
|
|
3756
|
+
await mkdir13(slockHome, { recursive: true });
|
|
3664
3757
|
if (opts.simulateFail === "snapshot") {
|
|
3665
3758
|
await arrangeSnapshotFailure(slockHome);
|
|
3666
3759
|
}
|
|
3667
3760
|
const { opts: upgradeOpts } = buildSimulatedDeps(slockHome, opts);
|
|
3668
|
-
await
|
|
3761
|
+
await mkdir13(upgradeOpts.currentBinaryDir, { recursive: true });
|
|
3669
3762
|
let outcome;
|
|
3670
3763
|
try {
|
|
3671
3764
|
outcome = await runUpgrade(slockHome, upgradeOpts);
|
|
@@ -3702,7 +3795,7 @@ async function runUpgradeTestHarness(slockHome, opts, writer = (s) => process.st
|
|
|
3702
3795
|
}
|
|
3703
3796
|
|
|
3704
3797
|
// src/upgradeInstallSmoke.ts
|
|
3705
|
-
import { copyFile, mkdir as
|
|
3798
|
+
import { copyFile, mkdir as mkdir14, readFile as readFile13 } from "fs/promises";
|
|
3706
3799
|
import { createHash as createHash5 } from "crypto";
|
|
3707
3800
|
import { dirname as dirname11, isAbsolute, join as join9, resolve as pathResolve } from "path";
|
|
3708
3801
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -3725,7 +3818,7 @@ async function runUpgradeInstallSmoke(slockHome, opts, deps = {}) {
|
|
|
3725
3818
|
const spawnFreshSupervisor = deps.spawnFreshSupervisor ?? (async (h) => {
|
|
3726
3819
|
await spawnDetachedSupervisor(h);
|
|
3727
3820
|
});
|
|
3728
|
-
await
|
|
3821
|
+
await mkdir14(slockHome, { recursive: true });
|
|
3729
3822
|
const outcome = await runUpgrade(slockHome, {
|
|
3730
3823
|
targetVersion: opts.targetVersion,
|
|
3731
3824
|
fromVersion,
|
package/package.json
CHANGED