@ouro.bot/cli 0.1.0-alpha.548 → 0.1.0-alpha.549
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/changelog.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.549",
|
|
6
|
+
"changes": [
|
|
7
|
+
"`ouro up` now unloads any already-loaded daemon LaunchAgent before replacing a drifted daemon runtime, preventing launchd KeepAlive from racing the manual replacement and leaving two daemon processes split across the same socket.",
|
|
8
|
+
"`ouro up` now rewrites the daemon boot plist as soon as the daemon is answering, so a degraded sense no longer prevents restart auto-start metadata from being refreshed."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
4
11
|
{
|
|
5
12
|
"version": "0.1.0-alpha.548",
|
|
6
13
|
"changes": [
|
|
@@ -251,6 +251,15 @@ function defaultEnsureDaemonBootPersistence(socketPath) {
|
|
|
251
251
|
envPath: process.env.PATH,
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
|
+
function defaultPrepareDaemonRuntimeReplacement() {
|
|
255
|
+
if (process.platform !== "darwin") {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
(0, launchd_1.bootoutLaunchAgentByLabel)({
|
|
259
|
+
exec: (cmd) => { (0, child_process_1.execSync)(cmd, { stdio: "ignore" }); },
|
|
260
|
+
userUid: process.getuid?.() ?? 0,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
254
263
|
async function defaultPromptInput(question) {
|
|
255
264
|
const readline = await Promise.resolve().then(() => __importStar(require("readline/promises")));
|
|
256
265
|
const rl = readline.createInterface({
|
|
@@ -615,6 +624,7 @@ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SO
|
|
|
615
624
|
syncGlobalOuroBotWrapper: ouro_bot_global_installer_1.syncGlobalOuroBotWrapper,
|
|
616
625
|
pruneDaemonLogs: logs_prune_1.pruneDaemonLogs,
|
|
617
626
|
ensureSkillManagement: skill_management_installer_1.ensureSkillManagement,
|
|
627
|
+
prepareDaemonRuntimeReplacement: defaultPrepareDaemonRuntimeReplacement,
|
|
618
628
|
ensureDaemonBootPersistence: defaultEnsureDaemonBootPersistence,
|
|
619
629
|
/* v8 ignore start -- dev-mode defaults: tests inject mocks for mode detection and binary resolution @preserve */
|
|
620
630
|
detectMode: () => (0, runtime_mode_1.detectRuntimeMode)((0, identity_1.getRepoRoot)()),
|
|
@@ -943,6 +943,7 @@ async function ensureDaemonRunning(deps, options = {}) {
|
|
|
943
943
|
stopDaemon: async () => {
|
|
944
944
|
await deps.sendCommand(deps.socketPath, { kind: "daemon.stop" });
|
|
945
945
|
},
|
|
946
|
+
prepareDaemonRuntimeReplacement: deps.prepareDaemonRuntimeReplacement,
|
|
946
947
|
cleanupStaleSocket: deps.cleanupStaleSocket,
|
|
947
948
|
startDaemonProcess: deps.startDaemonProcess,
|
|
948
949
|
checkSocketAlive: deps.checkSocketAlive,
|
|
@@ -5901,6 +5902,20 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
5901
5902
|
return returnCliFailure(deps, daemonResult.message);
|
|
5902
5903
|
}
|
|
5903
5904
|
progress.completePhase("starting daemon", daemonProgressSummary(daemonResult));
|
|
5905
|
+
if (deps.ensureDaemonBootPersistence) {
|
|
5906
|
+
try {
|
|
5907
|
+
await Promise.resolve(deps.ensureDaemonBootPersistence(deps.socketPath));
|
|
5908
|
+
}
|
|
5909
|
+
catch (error) {
|
|
5910
|
+
(0, runtime_1.emitNervesEvent)({
|
|
5911
|
+
level: "warn",
|
|
5912
|
+
component: "daemon",
|
|
5913
|
+
event: "daemon.system_setup_launchd_error",
|
|
5914
|
+
message: "failed to persist daemon boot startup",
|
|
5915
|
+
meta: { error: error instanceof Error ? error.message : String(error), socketPath: deps.socketPath },
|
|
5916
|
+
});
|
|
5917
|
+
}
|
|
5918
|
+
}
|
|
5904
5919
|
progress.startPhase("provider checks");
|
|
5905
5920
|
const providerDegraded = await checkAlreadyRunningAgentProviders(deps, (msg) => progress.updateDetail(msg));
|
|
5906
5921
|
daemonResult.stability = mergeStartupStability(daemonResult.stability, providerDegraded);
|
|
@@ -6069,23 +6084,6 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
6069
6084
|
const driftAdvisories = await collectAgentDriftAdvisories(deps);
|
|
6070
6085
|
writeDriftAdvisorySummary(deps, driftAdvisories);
|
|
6071
6086
|
}
|
|
6072
|
-
// Persist boot startup AFTER daemon is running — bootstrap is safe now
|
|
6073
|
-
// because the daemon socket exists, so launchd's KeepAlive registers
|
|
6074
|
-
// for crash recovery without starting a competing process.
|
|
6075
|
-
if (deps.ensureDaemonBootPersistence) {
|
|
6076
|
-
try {
|
|
6077
|
-
await Promise.resolve(deps.ensureDaemonBootPersistence(deps.socketPath));
|
|
6078
|
-
}
|
|
6079
|
-
catch (error) {
|
|
6080
|
-
(0, runtime_1.emitNervesEvent)({
|
|
6081
|
-
level: "warn",
|
|
6082
|
-
component: "daemon",
|
|
6083
|
-
event: "daemon.system_setup_launchd_error",
|
|
6084
|
-
message: "failed to persist daemon boot startup",
|
|
6085
|
-
meta: { error: error instanceof Error ? error.message : String(error), socketPath: deps.socketPath },
|
|
6086
|
-
});
|
|
6087
|
-
}
|
|
6088
|
-
}
|
|
6089
6087
|
return daemonResult.message;
|
|
6090
6088
|
}
|
|
6091
6089
|
if (command.kind === "daemon.dev") {
|
|
@@ -107,6 +107,24 @@ async function ensureCurrentDaemonRuntime(deps) {
|
|
|
107
107
|
try {
|
|
108
108
|
deps.onProgress?.("stopping the older background service");
|
|
109
109
|
await deps.stopDaemon();
|
|
110
|
+
if (deps.prepareDaemonRuntimeReplacement) {
|
|
111
|
+
deps.onProgress?.("disabling daemon auto-restart during replacement");
|
|
112
|
+
try {
|
|
113
|
+
await Promise.resolve(deps.prepareDaemonRuntimeReplacement());
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
(0, runtime_1.emitNervesEvent)({
|
|
117
|
+
level: "warn",
|
|
118
|
+
component: "daemon",
|
|
119
|
+
event: "daemon.runtime_sync_replacement_prepare_error",
|
|
120
|
+
message: "daemon runtime replacement preparation failed",
|
|
121
|
+
meta: {
|
|
122
|
+
socketPath: deps.socketPath,
|
|
123
|
+
reason: formatErrorReason(error),
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
110
128
|
}
|
|
111
129
|
catch (error) {
|
|
112
130
|
const reason = formatErrorReason(error);
|
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.DAEMON_PLIST_LABEL = void 0;
|
|
37
|
+
exports.bootoutLaunchAgentByLabel = bootoutLaunchAgentByLabel;
|
|
37
38
|
exports.generateDaemonPlist = generateDaemonPlist;
|
|
38
39
|
exports.writeLaunchAgentPlist = writeLaunchAgentPlist;
|
|
39
40
|
exports.installLaunchAgent = installLaunchAgent;
|
|
@@ -48,6 +49,26 @@ function plistFilePath(homeDir) {
|
|
|
48
49
|
function userLaunchDomain(userUid) {
|
|
49
50
|
return `gui/${userUid}`;
|
|
50
51
|
}
|
|
52
|
+
function bootoutLaunchAgentByLabel(deps) {
|
|
53
|
+
const domain = userLaunchDomain(deps.userUid);
|
|
54
|
+
try {
|
|
55
|
+
deps.exec(`launchctl bootout ${domain}/${exports.DAEMON_PLIST_LABEL}`);
|
|
56
|
+
(0, runtime_1.emitNervesEvent)({
|
|
57
|
+
component: "daemon",
|
|
58
|
+
event: "daemon.launchd_label_bootout",
|
|
59
|
+
message: "booted out daemon launch agent by label",
|
|
60
|
+
meta: { label: exports.DAEMON_PLIST_LABEL, domain },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
(0, runtime_1.emitNervesEvent)({
|
|
65
|
+
component: "daemon",
|
|
66
|
+
event: "daemon.launchd_label_bootout_skipped",
|
|
67
|
+
message: "daemon launch agent label bootout skipped",
|
|
68
|
+
meta: { label: exports.DAEMON_PLIST_LABEL, domain, reason: error instanceof Error ? error.message : String(error) },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
51
72
|
function generateDaemonPlist(options) {
|
|
52
73
|
(0, runtime_1.emitNervesEvent)({
|
|
53
74
|
component: "daemon",
|
|
@@ -145,12 +166,8 @@ function uninstallLaunchAgent(deps) {
|
|
|
145
166
|
meta: {},
|
|
146
167
|
});
|
|
147
168
|
const fullPath = plistFilePath(deps.homeDir);
|
|
148
|
-
|
|
169
|
+
bootoutLaunchAgentByLabel(deps);
|
|
149
170
|
if (deps.existsFile(fullPath)) {
|
|
150
|
-
try {
|
|
151
|
-
deps.exec(`launchctl bootout ${domain} "${fullPath}"`);
|
|
152
|
-
}
|
|
153
|
-
catch { /* best effort */ }
|
|
154
171
|
deps.removeFile(fullPath);
|
|
155
172
|
}
|
|
156
173
|
(0, runtime_1.emitNervesEvent)({
|