@songsid/agend 2.2.0-beta.8 → 2.2.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/README.md +40 -24
- package/README.zh-TW.md +40 -24
- package/dist/agent-endpoint.js +3 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.js +7 -1
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.d.ts +3 -1
- package/dist/auth-api.js +15 -1
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +33 -0
- package/dist/backend/antigravity.js +126 -18
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +3 -0
- package/dist/backend/claude-code.js +9 -0
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +33 -0
- package/dist/backend/codex-metadata.js +122 -18
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex.d.ts +3 -0
- package/dist/backend/codex.js +17 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +37 -1
- package/dist/backend/effort-metadata.js +86 -15
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.d.ts +4 -0
- package/dist/backend/grok.js +14 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +18 -1
- package/dist/backend/kiro.js +35 -8
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +61 -0
- package/dist/backend/launch-effort.js +170 -0
- package/dist/backend/launch-effort.js.map +1 -0
- package/dist/backend/muse.d.ts +17 -0
- package/dist/backend/muse.js +86 -16
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +40 -1
- package/dist/backend/types.js +12 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-command.d.ts +91 -0
- package/dist/backend-command.js +122 -0
- package/dist/backend-command.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +12 -0
- package/dist/channel/adapters/discord.js +49 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +18 -0
- package/dist/channel/adapters/telegram.js +24 -3
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +2 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.d.ts +2 -0
- package/dist/channel/tool-router.js +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +16 -0
- package/dist/cli.js +124 -24
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +2 -2
- package/dist/command-table.js +5 -2
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.d.ts +86 -0
- package/dist/compact-watch.js +288 -0
- package/dist/compact-watch.js.map +1 -0
- package/dist/config-validator.js +39 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +13 -1
- package/dist/daemon.js +160 -13
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +8 -1
- package/dist/delivery-outbox.js +6 -2
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/doctor.js +7 -0
- package/dist/doctor.js.map +1 -1
- package/dist/fleet-context.d.ts +7 -0
- package/dist/fleet-manager.d.ts +160 -10
- package/dist/fleet-manager.js +837 -121
- package/dist/fleet-manager.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +4 -3
- package/dist/forged-envelope-scan.js +4 -3
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +4 -1
- package/dist/install-lock.d.ts +18 -1
- package/dist/install-lock.js +30 -3
- package/dist/install-lock.js.map +1 -1
- package/dist/instance-avatar.d.ts +5 -4
- package/dist/instance-avatar.js +12 -8
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-lifecycle.js +3 -1
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.js +2 -2
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.d.ts +38 -0
- package/dist/kiro-compact-pane.js +57 -0
- package/dist/kiro-compact-pane.js.map +1 -0
- package/dist/kiro-log-gate.d.ts +42 -0
- package/dist/kiro-log-gate.js +39 -0
- package/dist/kiro-log-gate.js.map +1 -0
- package/dist/launchd-handoff.d.ts +43 -0
- package/dist/launchd-handoff.js +56 -0
- package/dist/launchd-handoff.js.map +1 -0
- package/dist/locale.js +202 -30
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js +10 -2
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +26 -0
- package/dist/log-steps.js +215 -3
- package/dist/log-steps.js.map +1 -1
- package/dist/login-shell.d.ts +21 -0
- package/dist/login-shell.js +98 -0
- package/dist/login-shell.js.map +1 -0
- package/dist/outbound-handlers.d.ts +27 -0
- package/dist/outbound-handlers.js +120 -36
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +12 -0
- package/dist/outbound-schemas.js +15 -4
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/provider-probe.d.ts +29 -0
- package/dist/provider-probe.js +198 -2
- package/dist/provider-probe.js.map +1 -1
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +11 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/quickstart-api.d.ts +1 -1
- package/dist/quickstart-api.js +8 -6
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +12 -0
- package/dist/quickstart.js +36 -6
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +86 -5
- package/dist/reply-buttons-controller.js +271 -7
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-buttons.d.ts +48 -3
- package/dist/reply-buttons.js +105 -10
- package/dist/reply-buttons.js.map +1 -1
- package/dist/reply-polls.d.ts +85 -0
- package/dist/reply-polls.js +154 -0
- package/dist/reply-polls.js.map +1 -0
- package/dist/restart-guard.d.ts +6 -3
- package/dist/restart-guard.js +6 -3
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +0 -2
- package/dist/restart-progress.js +0 -2
- package/dist/restart-progress.js.map +1 -1
- package/dist/sd-notify.d.ts +22 -1
- package/dist/sd-notify.js +63 -10
- package/dist/sd-notify.js.map +1 -1
- package/dist/service-activation.d.ts +15 -7
- package/dist/service-activation.js +42 -26
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +24 -0
- package/dist/service-installer.js +49 -1
- package/dist/service-installer.js.map +1 -1
- package/dist/service-plan.d.ts +11 -0
- package/dist/service-plan.js +23 -0
- package/dist/service-plan.js.map +1 -1
- package/dist/systemd-peer-bus.d.ts +95 -0
- package/dist/systemd-peer-bus.js +430 -0
- package/dist/systemd-peer-bus.js.map +1 -0
- package/dist/systemd-runtime.d.ts +27 -1
- package/dist/systemd-runtime.js +69 -7
- package/dist/systemd-runtime.js.map +1 -1
- package/dist/tool-permissions.js +3 -3
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +68 -2
- package/dist/topic-commands.js +141 -27
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-jsonl.d.ts +7 -2
- package/dist/transcript-jsonl.js +13 -7
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-sources.js +6 -1
- package/dist/transcript-sources.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/ui/chat-commands.js +1 -0
- package/dist/ui/chat-render.js +55 -10
- package/dist/ui/chat-store.js +69 -5
- package/dist/ui/chat-strings.js +28 -16
- package/dist/ui/chat-thread.js +132 -14
- package/dist/ui/chat-tour.js +17 -14
- package/dist/ui/panel-chat.js +16 -10
- package/dist/ui/panel-fleet.js +15 -2
- package/dist/ui/panel-log.js +55 -15
- package/dist/ui/panel-needs.js +10 -7
- package/dist/ui/panel-settings.js +58 -7
- package/dist/ui/settings-dialogs.js +11 -6
- package/dist/ui/settings-model.js +3 -1
- package/dist/ui/settings-strings.js +24 -10
- package/dist/ui/settings-token.js +7 -0
- package/dist/ui/settings-wizard.js +5 -3
- package/dist/ui/shared/app-i18n.js +1 -1
- package/dist/ui/shared/app-stream.js +4 -1
- package/dist/ui/shared/app.css +52 -10
- package/dist/ui/shared/header-tools.js +34 -14
- package/dist/ui/shared/instance-switch.js +5 -2
- package/dist/ui/shared/panel-view.js +15 -4
- package/dist/ui/shared/signin.js +15 -9
- package/dist/ui/shared/ui-icons.js +1 -0
- package/dist/ui/shared/view-strings.js +10 -2
- package/dist/ui/signin.html +8 -3
- package/dist/unrecognised-prompt.js +2 -2
- package/dist/unrecognised-prompt.js.map +1 -1
- package/dist/update-check.d.ts +31 -0
- package/dist/update-check.js +47 -0
- package/dist/update-check.js.map +1 -1
- package/dist/update-launch.d.ts +48 -1
- package/dist/update-launch.js +159 -5
- package/dist/update-launch.js.map +1 -1
- package/dist/usage/providers.d.ts +28 -8
- package/dist/usage/providers.js +96 -41
- package/dist/usage/providers.js.map +1 -1
- package/dist/view-api.js +26 -9
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +44 -2
- package/dist/web-api.js +265 -57
- package/dist/web-api.js.map +1 -1
- package/dist/web-chat-history.d.ts +26 -1
- package/dist/web-chat-history.js +47 -8
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +39 -3
- package/dist/web-commands.js +22 -5
- package/dist/web-commands.js.map +1 -1
- package/dist/web-login.d.ts +14 -0
- package/dist/web-login.js +4 -2
- package/dist/web-login.js.map +1 -1
- package/dist/web-prefs.d.ts +18 -0
- package/dist/web-prefs.js +36 -4
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-profile.d.ts +32 -0
- package/dist/web-profile.js +132 -0
- package/dist/web-profile.js.map +1 -0
- package/dist/web-session.d.ts +14 -0
- package/dist/web-session.js +10 -0
- package/dist/web-session.js.map +1 -1
- package/dist/web-upload.d.ts +119 -4
- package/dist/web-upload.js +252 -39
- package/dist/web-upload.js.map +1 -1
- package/launcher/install-admission.cjs +61 -6
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -16,14 +16,14 @@ import { Command } from "commander";
|
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { SchedulerDb } from "./scheduler/db.js";
|
|
18
18
|
import { Cron } from "croner";
|
|
19
|
-
import { existsSync, readFileSync, writeFileSync, appendFileSync, unlinkSync, mkdirSync, chmodSync, readdirSync, rmSync, statSync, realpathSync, } from "node:fs";
|
|
19
|
+
import { existsSync, readFileSync, writeFileSync, appendFileSync, unlinkSync, mkdirSync, chmodSync, readdirSync, rmSync, statSync, realpathSync, openSync, writeSync, closeSync, } from "node:fs";
|
|
20
20
|
import { homedir, totalmem, freemem, userInfo } from "node:os";
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import { spawn, spawnSync, execSync, execFileSync } from "node:child_process";
|
|
23
23
|
import { getAgendHome, getTmuxSocketName, isDefaultAgendHome } from "./paths.js";
|
|
24
24
|
import { hasPausedMarker } from "./pause-marker.js";
|
|
25
25
|
import { COMPLETION_SHELLS, completionScript } from "./completion.js";
|
|
26
|
-
import { getUpdateSelector, isExactVersion, isUnrequestedDowngrade, lookupTargetVersion, reportUpdateRestart, shouldSkipUpdate, runningFleetPredatesInstall, processStartMs, } from "./update-check.js";
|
|
26
|
+
import { getUpdateSelector, isExactVersion, isUnrequestedDowngrade, lookupTargetVersion, reportUpdateRestart, shouldSkipUpdate, runningFleetPredatesInstall, fleetProvenStopped, readFleetPidEvidence, pidAlive, processStartMs, } from "./update-check.js";
|
|
27
27
|
import { clearUpdateMarker, markUpdateInProgress, setUpdateProgressStage } from "./update-marker.js";
|
|
28
28
|
import { describeSignalSource, forceAllowed, gateFleetControl, recordInstanceControl, withOrigin } from "./fleet-control-audit.js";
|
|
29
29
|
import { FLEET_STOP_TIMEOUT_MS, stopDetachedOwner, systemdStopTimeoutMs, detachedProcessStart, detachedProcessExited } from "./fleet-stop-budget.js";
|
|
@@ -38,6 +38,7 @@ import { DeliveryStatusArgs } from "./outbound-schemas.js";
|
|
|
38
38
|
import { requestCpuProfile } from "./profile-control.js";
|
|
39
39
|
import { requestSettingsConfirmation } from "./settings-control.js";
|
|
40
40
|
import { canonicalCliEntry, selfCommand } from "./cli-entry.js";
|
|
41
|
+
import { handOff, shouldHandOff } from "./launchd-handoff.js";
|
|
41
42
|
/** Prefix tmux args with -L when socket isolation is active. */
|
|
42
43
|
function tmuxArgs(args) {
|
|
43
44
|
const socket = getTmuxSocketName();
|
|
@@ -79,6 +80,28 @@ function planDeps() {
|
|
|
79
80
|
now: () => new Date(),
|
|
80
81
|
};
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* #1871: hand this command to a detached copy that outlives the fleet's stop (see launchd-handoff.ts). True when it
|
|
85
|
+
* did; false to carry on here (not an agent session, or the copy could not be started — said so).
|
|
86
|
+
*/
|
|
87
|
+
async function handOffLaunchdActivation(action) {
|
|
88
|
+
if (!shouldHandOff(process.env))
|
|
89
|
+
return false;
|
|
90
|
+
const handed = await handOff({ agendHome: DATA_DIR, self: selfCommand(process.argv.slice(2)), env: process.env, action }, {
|
|
91
|
+
open: path => openSync(path, "a", 0o600),
|
|
92
|
+
write: (fd, text) => writeSync(fd, text),
|
|
93
|
+
close: fd => closeSync(fd),
|
|
94
|
+
spawn: (command, args, options) => spawn(command, args, options),
|
|
95
|
+
now: () => new Date(),
|
|
96
|
+
});
|
|
97
|
+
if (handed.ok) {
|
|
98
|
+
console.log(` ↪ This session belongs to the fleet that launchd is about to stop, so \`agend ${action}\` goes on in the background.`);
|
|
99
|
+
console.log(` Its output: ${handed.log}`);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
console.log(` ⚠ Could not continue in the background (${handed.reason}); going on in this session.`);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
82
105
|
const FLEET_CONFIG_PATH = join(DATA_DIR, "fleet.yaml");
|
|
83
106
|
// CLI commands run outside FleetManager. Honor an explicit fleet locale while
|
|
84
107
|
// keeping the historical English CLI default when config is missing/unset.
|
|
@@ -1446,6 +1469,12 @@ program
|
|
|
1446
1469
|
}
|
|
1447
1470
|
if (!gateFleetControl(DATA_DIR, "update", { yes: opts.yes }))
|
|
1448
1471
|
process.exit(1);
|
|
1472
|
+
// #1871: on launchd the activation boots out the fleet this agent session runs in; the update must outlive that.
|
|
1473
|
+
{
|
|
1474
|
+
const { getServicePath, getSystemServicePath, detectPlatform } = await import("./service-installer.js");
|
|
1475
|
+
if (detectPlatform() === "macos" && !getSystemServicePath() && getServicePath() && await handOffLaunchdActivation("update"))
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1449
1478
|
const { spawnSync } = await import("node:child_process");
|
|
1450
1479
|
// The channel follows the version being replaced — this CLI's own package — so an alpha or beta stays on its channel.
|
|
1451
1480
|
const tag = getUpdateSelector(opts, pkgVersion);
|
|
@@ -1495,7 +1524,7 @@ program
|
|
|
1495
1524
|
const { newAgendInvocation, retireSystemCopy, activationSettled } = await import("./update-install.js");
|
|
1496
1525
|
// What the restart came to — carried, never inferred from the exit code (pending ≠ restarted).
|
|
1497
1526
|
let restartResult = null;
|
|
1498
|
-
const { activateService } = await import("./service-activation.js");
|
|
1527
|
+
const { activateService, systemdPeerBus } = await import("./service-activation.js");
|
|
1499
1528
|
const { getServicePath, getSystemServicePath, detectPlatform } = await import("./service-installer.js");
|
|
1500
1529
|
const { accessSync, constants } = await import("node:fs");
|
|
1501
1530
|
const newAgend = newAgendInvocation({ viaNvm, nvmSh }, verified.agendPath);
|
|
@@ -1579,6 +1608,7 @@ program
|
|
|
1579
1608
|
log: message => console.log(message),
|
|
1580
1609
|
restorePackage,
|
|
1581
1610
|
systemdRecovery: restoreChecked ? { restorePackage: restoreChecked } : undefined,
|
|
1611
|
+
peerBus: systemdPeerBus,
|
|
1582
1612
|
});
|
|
1583
1613
|
// Settled: after a success only this transition's preimage is kept (for a repair); a failure consumed it.
|
|
1584
1614
|
if (activationSettled(outcome, restartResult) && rollback)
|
|
@@ -1666,15 +1696,9 @@ program
|
|
|
1666
1696
|
installedAtMs = statSync(fileURLToPath(import.meta.url)).mtimeMs;
|
|
1667
1697
|
}
|
|
1668
1698
|
catch { /* unknown */ }
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
processStartMs: pid => processStartMs(pid),
|
|
1673
|
-
isFleetProcess: pid => isFleetStartCommandLine(readProcessCommandLine(pid)),
|
|
1674
|
-
})) {
|
|
1675
|
-
console.log(`\n v${pkgVersion} is installed, but the running fleet started before it was — verifying it before restarting onto it.`);
|
|
1676
|
-
// The earlier update may have stopped exactly because this install failed verification (#1449 review): a
|
|
1677
|
-
// second `agend update` must not restart onto it unchecked.
|
|
1699
|
+
// The earlier update may have stopped exactly because this install failed verification (#1449 review): a
|
|
1700
|
+
// second `agend update` must not restart onto it — nor call it up to date — unchecked.
|
|
1701
|
+
const verifyInstalled = async () => {
|
|
1678
1702
|
const { verifyInstalledPackage } = await import("./update-install.js");
|
|
1679
1703
|
const verified = verifyInstalledPackage({ pkg: `@songsid/agend@${pkgVersion}`, targetVersion: pkgVersion, viaNvm: false, nvmSh }, {
|
|
1680
1704
|
run: (command, args, options = {}) => {
|
|
@@ -1688,13 +1712,42 @@ program
|
|
|
1688
1712
|
console.error(message);
|
|
1689
1713
|
setUpdateProgressStage(DATA_DIR, "failed", { error: message.trim() });
|
|
1690
1714
|
process.exitCode = 1;
|
|
1691
|
-
return;
|
|
1692
1715
|
}
|
|
1716
|
+
return verified;
|
|
1717
|
+
};
|
|
1718
|
+
if (runningFleetPredatesInstall({
|
|
1719
|
+
pid: fleetPid,
|
|
1720
|
+
installedAtMs,
|
|
1721
|
+
processStartMs: pid => processStartMs(pid),
|
|
1722
|
+
isFleetProcess: pid => isFleetStartCommandLine(readProcessCommandLine(pid)),
|
|
1723
|
+
})) {
|
|
1724
|
+
console.log(`\n v${pkgVersion} is installed, but the running fleet started before it was — verifying it before restarting onto it.`);
|
|
1725
|
+
const verified = await verifyInstalled();
|
|
1726
|
+
if (!verified.ok)
|
|
1727
|
+
return;
|
|
1693
1728
|
console.log(` ✓ v${pkgVersion} verified — restarting the fleet onto it.\n`);
|
|
1694
1729
|
markUpdateInProgress(DATA_DIR);
|
|
1695
1730
|
await activateVerified(verified, false);
|
|
1696
1731
|
return;
|
|
1697
1732
|
}
|
|
1733
|
+
// #1829 ⑥: installed, but no fleet runs (a restart that never finished, a stopped service): not "up to date".
|
|
1734
|
+
// Verified first, then the exact next step — never started from here, so nothing bypasses `agend start`'s checks.
|
|
1735
|
+
// Only a fleet.pid that is missing, or names a pid proven gone / not a fleet, says so (review: unreadable,
|
|
1736
|
+
// empty or malformed is unknown, and keeps the old answer).
|
|
1737
|
+
const pidEvidence = readFleetPidEvidence(join(DATA_DIR, "fleet.pid"));
|
|
1738
|
+
if (pidEvidence.kind !== "unknown" && fleetProvenStopped({
|
|
1739
|
+
pid: pidEvidence.kind === "valid" ? pidEvidence.pid : null,
|
|
1740
|
+
alive: pid => pidAlive(pid),
|
|
1741
|
+
commandLine: pid => readProcessCommandLine(pid),
|
|
1742
|
+
isFleetProcess: line => isFleetStartCommandLine(line),
|
|
1743
|
+
})) {
|
|
1744
|
+
const verified = await verifyInstalled();
|
|
1745
|
+
if (!verified.ok)
|
|
1746
|
+
return;
|
|
1747
|
+
console.error(`\n ✗ AgEnD v${pkgVersion} is installed but the fleet is not running — run: agend start\n`);
|
|
1748
|
+
process.exitCode = 1;
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1698
1751
|
console.log(`\n ✓ Already up to date (v${pkgVersion})\n`);
|
|
1699
1752
|
setUpdateProgressStage(DATA_DIR, "complete", { version: pkgVersion });
|
|
1700
1753
|
return;
|
|
@@ -1800,7 +1853,7 @@ program
|
|
|
1800
1853
|
: {}),
|
|
1801
1854
|
lock: prefix => {
|
|
1802
1855
|
const lock = acquireInstallLock(prefix, { spec: pkg, agendHome: DATA_DIR }, {
|
|
1803
|
-
pid: process.pid, processStart: admission.processStart, newToken: () => randomBytes(16).toString("hex"),
|
|
1856
|
+
pid: process.pid, processStart: admission.processStart, startTicks: admission.startTicks, bootId: admission.bootId, newToken: () => randomBytes(16).toString("hex"),
|
|
1804
1857
|
now: () => new Date(), log: message => console.log(message),
|
|
1805
1858
|
});
|
|
1806
1859
|
if (!lock.ok)
|
|
@@ -1913,6 +1966,25 @@ program
|
|
|
1913
1966
|
console.log(` ${outcome.message}`);
|
|
1914
1967
|
return;
|
|
1915
1968
|
}
|
|
1969
|
+
// #1884: a legacy system unit is the service a root fleet runs under; the refresh brings its ExecStart to this
|
|
1970
|
+
// install's selection too, or `agend restart` refuses it after an update (see refreshSystemUnitExecStart).
|
|
1971
|
+
const systemUnit = opts.activate === false && detectPlatform() !== "macos" ? getSystemServicePath() : null;
|
|
1972
|
+
if (systemUnit) {
|
|
1973
|
+
const { refreshSystemUnitExecStart } = await import("./service-installer.js");
|
|
1974
|
+
try {
|
|
1975
|
+
const refreshed = refreshSystemUnitExecStart(systemUnit, serviceVars, dirname(dirname(execPath)));
|
|
1976
|
+
if (refreshed.kind === "updated")
|
|
1977
|
+
console.log(` ✓ ${systemUnit}: ExecStart=${refreshed.execStart}`);
|
|
1978
|
+
else if (refreshed.kind === "foreign")
|
|
1979
|
+
console.log(` ℹ ${systemUnit} left as it is: ${refreshed.reason}.`);
|
|
1980
|
+
else if (refreshed.kind === "unreadable")
|
|
1981
|
+
console.log(` ⚠ ${systemUnit} could not be read; left as it is.`);
|
|
1982
|
+
}
|
|
1983
|
+
catch (err) {
|
|
1984
|
+
console.error(` ✗ ${systemUnit} could not be updated (${err.message}); \`agend restart\` will refuse until its ExecStart starts this install. Run the update as root, or: sudo agend install --no-activate`);
|
|
1985
|
+
process.exitCode = 1;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1916
1988
|
const svcPath = installService(serviceVars);
|
|
1917
1989
|
console.log(t("install.path", svcPath));
|
|
1918
1990
|
if (opts.activate !== false) {
|
|
@@ -2283,7 +2355,8 @@ program
|
|
|
2283
2355
|
}
|
|
2284
2356
|
if (filterCustom)
|
|
2285
2357
|
console.log(` ⚠ ${unitPath} sets its own CoredumpFilter; left as is. CoredumpFilter=0 keeps crash dumps to a few KB (#1113).`);
|
|
2286
|
-
|
|
2358
|
+
const { systemdPeerBus } = await import("./service-activation.js");
|
|
2359
|
+
if (expectation.ok && refuses(guard.guardSystemd(captureRun, systemdTarget.user, systemdTarget.unit, expectation.expected, guardDeps, systemdPeerBus)))
|
|
2287
2360
|
return;
|
|
2288
2361
|
// Clears the failed state AND the start-limit counter (#1113:
|
|
2289
2362
|
// StartLimitBurst=4 in 30min) for whichever unit this restart targets,
|
|
@@ -2322,8 +2395,13 @@ program
|
|
|
2322
2395
|
if (printed.status === 0) {
|
|
2323
2396
|
const plistPath = getServicePath() ?? join(homedir(), "Library", "LaunchAgents", `${label}.plist`);
|
|
2324
2397
|
// Path 2 (#1450 C6): a proven new plist waits on disk with its plan — exactly one bootout + bootstrap.
|
|
2325
|
-
const { readPlan, admitPlan, planPath } = await import("./service-plan.js");
|
|
2326
|
-
const
|
|
2398
|
+
const { readPlan, admitPlan, planPath, planCarriedOut } = await import("./service-plan.js");
|
|
2399
|
+
const recorded = opts.force ? null : readPlan(DATA_DIR, deps);
|
|
2400
|
+
// #1871: an interrupted update's plan whose job launchd already runs (after `agend start`) is done: restart that
|
|
2401
|
+
// job as an unchanged one (path 1) instead of refusing it for its new pid.
|
|
2402
|
+
const plan = recorded && planCarriedOut(recorded, target, deps) ? null : recorded;
|
|
2403
|
+
if (recorded && !plan)
|
|
2404
|
+
console.log(" ℹ launchd already runs the job an interrupted update planned; restarting it as it is.");
|
|
2327
2405
|
if (plan && expectation.ok) {
|
|
2328
2406
|
const pkgDir = dirname(dirname(expectation.expected.entry));
|
|
2329
2407
|
const admitted = admitPlan(plan, { target, expected: expectation.expected, pkgDir }, deps);
|
|
@@ -2332,6 +2410,8 @@ program
|
|
|
2332
2410
|
process.exitCode = 1;
|
|
2333
2411
|
return;
|
|
2334
2412
|
}
|
|
2413
|
+
if (await handOffLaunchdActivation("restart"))
|
|
2414
|
+
return;
|
|
2335
2415
|
const { activateService } = await import("./service-activation.js");
|
|
2336
2416
|
const outcome = activateService({ kind: "launchd", label, plistPath: plan.plistPath, domain: `gui/${uid}` }, { bin: expectation.expected.entry, entry: expectation.expected.entry, node: expectation.expected.node, dir: pkgDir }, {
|
|
2337
2417
|
...deps,
|
|
@@ -2605,6 +2685,16 @@ program
|
|
|
2605
2685
|
const { runSetupWizard } = await import("./setup-wizard.js");
|
|
2606
2686
|
await runSetupWizard();
|
|
2607
2687
|
});
|
|
2688
|
+
// The opener is optional (a server or WSL without xdg-open): a spawn failure is an `error` event, and unhandled it
|
|
2689
|
+
// crashed the command after the link was already printed (#1854). The printed link still works, so say so instead.
|
|
2690
|
+
function openInBrowser(url) {
|
|
2691
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
|
|
2692
|
+
const child = spawn(cmd, [url], { detached: true, stdio: "ignore" });
|
|
2693
|
+
child.on("error", (err) => {
|
|
2694
|
+
console.error(`Could not open a browser (${cmd}: ${err.code ?? err.message}). Open the link above yourself.`);
|
|
2695
|
+
});
|
|
2696
|
+
child.unref();
|
|
2697
|
+
}
|
|
2608
2698
|
program
|
|
2609
2699
|
.command("web")
|
|
2610
2700
|
.description("Open the Web UI sign-in page in your browser and print a one-time sign-in code")
|
|
@@ -2647,9 +2737,7 @@ program
|
|
|
2647
2737
|
console.log(`Code: ${code} (works once, valid ~${minutes} min)`);
|
|
2648
2738
|
if (opts.code)
|
|
2649
2739
|
return;
|
|
2650
|
-
|
|
2651
|
-
const child = spawn(cmd, [signin], { detached: true, stdio: "ignore" });
|
|
2652
|
-
child.unref();
|
|
2740
|
+
openInBrowser(signin);
|
|
2653
2741
|
});
|
|
2654
2742
|
program
|
|
2655
2743
|
.command("web-token")
|
|
@@ -2679,9 +2767,7 @@ program
|
|
|
2679
2767
|
const port = fleet.health_port ?? 19280;
|
|
2680
2768
|
const url = `http://localhost:${port}/view`;
|
|
2681
2769
|
console.log(`Opening ${url}`);
|
|
2682
|
-
|
|
2683
|
-
const child = spawn(cmd, [url], { detached: true, stdio: "ignore" });
|
|
2684
|
-
child.unref();
|
|
2770
|
+
openInBrowser(url);
|
|
2685
2771
|
});
|
|
2686
2772
|
program
|
|
2687
2773
|
.command("validate")
|
|
@@ -2990,7 +3076,21 @@ async function fuzzyMatch(query, names) {
|
|
|
2990
3076
|
return null;
|
|
2991
3077
|
}
|
|
2992
3078
|
async function resolveInstance(query, config) {
|
|
2993
|
-
const
|
|
3079
|
+
const namesRaw = await listInstanceNames(config);
|
|
3080
|
+
const names = [...new Set(namesRaw)]; // P3-3: deduplicate (a classicBot instanceName can equal a fleet name)
|
|
3081
|
+
const { resolveName } = await import("./topic-commands.js");
|
|
3082
|
+
const entries = names.map((name) => ({
|
|
3083
|
+
name,
|
|
3084
|
+
displayName: config.instances[name]?.display_name,
|
|
3085
|
+
}));
|
|
3086
|
+
const result = resolveName(query, entries);
|
|
3087
|
+
if (result.kind === "name")
|
|
3088
|
+
return result.realName;
|
|
3089
|
+
if (result.kind === "ambiguous") {
|
|
3090
|
+
console.error(`"${query}" matches multiple instances: ${result.realNames.join(", ")}. Use the real name.`);
|
|
3091
|
+
process.exit(1);
|
|
3092
|
+
}
|
|
3093
|
+
// Fall through to the original fuzzy match on real names.
|
|
2994
3094
|
const match = await fuzzyMatch(query, names);
|
|
2995
3095
|
if (!match) {
|
|
2996
3096
|
console.error(`No instance matching "${query}". Available: ${names.join(", ")}`);
|