@ouro.bot/cli 0.1.0-alpha.379 → 0.1.0-alpha.380
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,14 @@
|
|
|
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.380",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Daemon startup now supplements pidfile cleanup with the scoped orphan-process scan, so a partial stale pidfile cannot leave an older daemon process alive after `ouro up` replaces the runtime.",
|
|
8
|
+
"`ouro status` now keeps vault runtime/config failures compact in sense rows, replacing multi-line vault-lock explanations with a direct `ouro vault unlock --agent <agent>` hint.",
|
|
9
|
+
"`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the daemon/status polish release."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.379",
|
|
6
14
|
"changes": [
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.OuroDaemon = void 0;
|
|
37
37
|
exports.parseOrphanPidsFromPs = parseOrphanPidsFromPs;
|
|
38
38
|
exports.filterPidfilePidsToActualOrphans = filterPidfilePidsToActualOrphans;
|
|
39
|
+
exports.mergeUniqueOrphanPids = mergeUniqueOrphanPids;
|
|
39
40
|
exports.killOrphanProcesses = killOrphanProcesses;
|
|
40
41
|
exports.writePidfile = writePidfile;
|
|
41
42
|
exports.handleAgentSenseTurn = handleAgentSenseTurn;
|
|
@@ -162,6 +163,19 @@ function filterPidfilePidsToActualOrphans(candidatePids, psRunner = runPsCheck)
|
|
|
162
163
|
}
|
|
163
164
|
return survivingOrphans;
|
|
164
165
|
}
|
|
166
|
+
function mergeUniqueOrphanPids(...sources) {
|
|
167
|
+
const merged = [];
|
|
168
|
+
const seen = new Set();
|
|
169
|
+
for (const source of sources) {
|
|
170
|
+
for (const pid of source) {
|
|
171
|
+
if (seen.has(pid))
|
|
172
|
+
continue;
|
|
173
|
+
seen.add(pid);
|
|
174
|
+
merged.push(pid);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return merged;
|
|
178
|
+
}
|
|
165
179
|
/* v8 ignore start -- shells out to ps; covered by filterPidfilePidsToActualOrphans unit tests via injected runner @preserve */
|
|
166
180
|
function runPsCheck(pids) {
|
|
167
181
|
try {
|
|
@@ -203,7 +217,8 @@ function killOrphanProcesses() {
|
|
|
203
217
|
return;
|
|
204
218
|
}
|
|
205
219
|
try {
|
|
206
|
-
let
|
|
220
|
+
let pidfileOrphans = [];
|
|
221
|
+
let scanOrphans = [];
|
|
207
222
|
// Primary: read pidfile from previous daemon
|
|
208
223
|
try {
|
|
209
224
|
const raw = fs.readFileSync(PIDFILE_PATH, "utf-8");
|
|
@@ -212,19 +227,21 @@ function killOrphanProcesses() {
|
|
|
212
227
|
.filter((n) => !isNaN(n) && n !== process.pid);
|
|
213
228
|
// Verify each candidate is an actual live orphan before killing. See
|
|
214
229
|
// docstring above for why this matters.
|
|
215
|
-
|
|
230
|
+
pidfileOrphans = filterPidfilePidsToActualOrphans(candidates);
|
|
216
231
|
fs.unlinkSync(PIDFILE_PATH);
|
|
217
232
|
}
|
|
218
233
|
catch {
|
|
219
|
-
// No pidfile —
|
|
234
|
+
// No pidfile — the ps scan below still covers true orphans.
|
|
220
235
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
236
|
+
// Always supplement the pidfile with the scoped ps scan. A stale or
|
|
237
|
+
// partial pidfile can otherwise kill one old daemon while leaving a
|
|
238
|
+
// sibling PPID=1 daemon alive without a socket.
|
|
239
|
+
try {
|
|
240
|
+
const result = (0, child_process_1.execSync)("ps -eo pid,ppid,command", { encoding: "utf-8", timeout: 5000 });
|
|
241
|
+
scanOrphans = parseOrphanPidsFromPs(result, process.pid);
|
|
227
242
|
}
|
|
243
|
+
catch { /* ps failed — best effort */ }
|
|
244
|
+
const pidsToKill = mergeUniqueOrphanPids(pidfileOrphans, scanOrphans);
|
|
228
245
|
if (pidsToKill.length > 0) {
|
|
229
246
|
for (const pid of pidsToKill) {
|
|
230
247
|
try {
|
|
@@ -96,6 +96,20 @@ function numberField(record, key, fallback) {
|
|
|
96
96
|
const value = record?.[key];
|
|
97
97
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
98
98
|
}
|
|
99
|
+
function compactRuntimeConfigError(agent, error) {
|
|
100
|
+
const compact = error.replace(/\s+/g, " ").trim();
|
|
101
|
+
if (/credential vault is locked|vault locked|vault is locked/i.test(compact)) {
|
|
102
|
+
return `vault locked; run 'ouro vault unlock --agent ${agent}'`;
|
|
103
|
+
}
|
|
104
|
+
return compact || "unavailable";
|
|
105
|
+
}
|
|
106
|
+
function runtimeConfigUnavailableDetail(agent, runtimeConfig) {
|
|
107
|
+
if (runtimeConfig.ok)
|
|
108
|
+
return "";
|
|
109
|
+
if (runtimeConfig.reason === "missing")
|
|
110
|
+
return `missing vault runtime/config (${agent})`;
|
|
111
|
+
return `vault runtime/config unavailable (${compactRuntimeConfigError(agent, runtimeConfig.error)})`;
|
|
112
|
+
}
|
|
99
113
|
function senseFactsFromRuntimeConfig(agent, senses, runtimeConfig) {
|
|
100
114
|
const base = {
|
|
101
115
|
cli: { configured: true, detail: "local interactive terminal" },
|
|
@@ -103,11 +117,7 @@ function senseFactsFromRuntimeConfig(agent, senses, runtimeConfig) {
|
|
|
103
117
|
bluebubbles: { configured: false, detail: "not enabled in agent.json" },
|
|
104
118
|
};
|
|
105
119
|
const payload = runtimeConfig.ok ? runtimeConfig.config : {};
|
|
106
|
-
const unavailableDetail = runtimeConfig
|
|
107
|
-
? ""
|
|
108
|
-
: runtimeConfig.reason === "missing"
|
|
109
|
-
? `missing vault runtime/config (${agent})`
|
|
110
|
-
: `vault runtime/config unavailable (${runtimeConfig.error})`;
|
|
120
|
+
const unavailableDetail = runtimeConfigUnavailableDetail(agent, runtimeConfig);
|
|
111
121
|
const teams = payload.teams;
|
|
112
122
|
const teamsChannel = payload.teamsChannel;
|
|
113
123
|
const bluebubbles = payload.bluebubbles;
|