@ouro.bot/cli 0.1.0-alpha.646 → 0.1.0-alpha.648
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,18 @@
|
|
|
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.648",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Daemon restart state truth: stale exits from a child intentionally replaced during restart are ignored, preventing provider refresh from reporting success while a later SIGTERM from the old worker clears the replacement pid and leaves status stuck at `starting`."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.0-alpha.647",
|
|
12
|
+
"changes": [
|
|
13
|
+
"Provider refresh restart hardening: provider-refresh restarts now skip redundant vault config checks after credentials are already refreshed, and the Bitwarden cross-process lock wait outlasts a single `bw` child timeout so concurrent vault users survive normal holder cleanup instead of failing at the same 30s boundary."
|
|
14
|
+
]
|
|
15
|
+
},
|
|
4
16
|
{
|
|
5
17
|
"version": "0.1.0-alpha.646",
|
|
6
18
|
"changes": [
|
|
@@ -2001,14 +2001,16 @@ async function storeRuntimeConfigKey(input) {
|
|
|
2001
2001
|
function readRuntimeApplyWorker(payload, agent) {
|
|
2002
2002
|
return payload.workers.find((worker) => worker.agent === agent) ?? null;
|
|
2003
2003
|
}
|
|
2004
|
-
async function applyRuntimeChangeToRunningAgent(agent, deps, onProgress) {
|
|
2004
|
+
async function applyRuntimeChangeToRunningAgent(agent, deps, onProgress, options = {}) {
|
|
2005
2005
|
try {
|
|
2006
2006
|
onProgress?.("checking whether Ouro is already running");
|
|
2007
2007
|
const alive = await deps.checkSocketAlive(deps.socketPath);
|
|
2008
2008
|
if (!alive)
|
|
2009
2009
|
return "daemon is not running; next `ouro up` will load the change";
|
|
2010
2010
|
onProgress?.(`asking Ouro to reload ${agent}`);
|
|
2011
|
-
const response = await withCliTimeout(DEFAULT_AGENT_RESTART_TIMEOUT_MS, "daemon restart request timed out", () => deps.sendCommand(deps.socketPath,
|
|
2011
|
+
const response = await withCliTimeout(DEFAULT_AGENT_RESTART_TIMEOUT_MS, "daemon restart request timed out", () => deps.sendCommand(deps.socketPath, options.skipRestartConfigCheck
|
|
2012
|
+
? { kind: "agent.restart", agent, skipConfigCheck: true }
|
|
2013
|
+
: { kind: "agent.restart", agent }));
|
|
2012
2014
|
if (!response.ok)
|
|
2013
2015
|
return `daemon restart skipped: ${response.error ?? response.message ?? "unknown daemon error"}`;
|
|
2014
2016
|
const deadline = cliNowMs(deps) + DEFAULT_RUNTIME_APPLY_TIMEOUT_MS;
|
|
@@ -4716,7 +4718,7 @@ async function executeProviderRefresh(command, deps) {
|
|
|
4716
4718
|
deps.writeStdout(message);
|
|
4717
4719
|
return message;
|
|
4718
4720
|
}
|
|
4719
|
-
const reload = await runCommandProgressPhase(progress, `applying change to running ${command.agent}`, () => applyRuntimeChangeToRunningAgent(command.agent, deps, (message) => progress.updateDetail(message)), (result) => result);
|
|
4721
|
+
const reload = await runCommandProgressPhase(progress, `applying change to running ${command.agent}`, () => applyRuntimeChangeToRunningAgent(command.agent, deps, (message) => progress.updateDetail(message), { skipRestartConfigCheck: true }), (result) => result);
|
|
4720
4722
|
progress.end();
|
|
4721
4723
|
lines.push(`running agent: ${reload}`);
|
|
4722
4724
|
const message = lines.join("\n");
|
|
@@ -1177,7 +1177,10 @@ class OuroDaemon {
|
|
|
1177
1177
|
if (!managed) {
|
|
1178
1178
|
return { ok: false, error: `Unknown managed agent '${command.agent}'.` };
|
|
1179
1179
|
}
|
|
1180
|
-
|
|
1180
|
+
const restartWork = command.skipConfigCheck === true
|
|
1181
|
+
? this.processManager.restartAgent(command.agent, { skipConfigCheck: true })
|
|
1182
|
+
: this.processManager.restartAgent(command.agent);
|
|
1183
|
+
void restartWork.catch((error) => {
|
|
1181
1184
|
(0, runtime_1.emitNervesEvent)({
|
|
1182
1185
|
level: "error",
|
|
1183
1186
|
component: "daemon",
|
|
@@ -203,7 +203,7 @@ class DaemonProcessManager {
|
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
-
async startAgent(agent) {
|
|
206
|
+
async startAgent(agent, options = {}) {
|
|
207
207
|
const state = this.requireAgent(agent);
|
|
208
208
|
if (state.process || state.startInFlight)
|
|
209
209
|
return;
|
|
@@ -215,7 +215,7 @@ class DaemonProcessManager {
|
|
|
215
215
|
this.clearRestartTimer(state);
|
|
216
216
|
state.stopRequested = false;
|
|
217
217
|
state.snapshot.status = "starting";
|
|
218
|
-
if (this.configCheckFn) {
|
|
218
|
+
if (this.configCheckFn && options.skipConfigCheck !== true) {
|
|
219
219
|
let result;
|
|
220
220
|
try {
|
|
221
221
|
result = await this.configCheckFn(agent);
|
|
@@ -260,6 +260,10 @@ class DaemonProcessManager {
|
|
|
260
260
|
state.snapshot.errorReason = null;
|
|
261
261
|
state.snapshot.fixHint = null;
|
|
262
262
|
}
|
|
263
|
+
if (options.skipConfigCheck === true) {
|
|
264
|
+
state.snapshot.errorReason = null;
|
|
265
|
+
state.snapshot.fixHint = null;
|
|
266
|
+
}
|
|
263
267
|
const runCwd = (0, identity_1.getRepoRoot)();
|
|
264
268
|
const entryScript = path.join((0, identity_1.getRepoRoot)(), "dist", state.config.entry);
|
|
265
269
|
if (this.existsSyncFn && !this.existsSyncFn(entryScript)) {
|
|
@@ -392,7 +396,7 @@ class DaemonProcessManager {
|
|
|
392
396
|
});
|
|
393
397
|
/* v8 ignore stop */
|
|
394
398
|
child.once("exit", (code, signal) => {
|
|
395
|
-
this.onExit(state, code, signal);
|
|
399
|
+
this.onExit(state, child, code, signal);
|
|
396
400
|
});
|
|
397
401
|
}
|
|
398
402
|
finally {
|
|
@@ -437,7 +441,7 @@ class DaemonProcessManager {
|
|
|
437
441
|
}
|
|
438
442
|
this.notifySnapshotChange(state.snapshot);
|
|
439
443
|
}
|
|
440
|
-
async restartAgent(agent) {
|
|
444
|
+
async restartAgent(agent, options = {}) {
|
|
441
445
|
const state = this.requireAgent(agent);
|
|
442
446
|
// Respawn-loop guard: prune timestamps outside the window, then check
|
|
443
447
|
// whether we've already restarted this agent too many times in it.
|
|
@@ -519,7 +523,7 @@ class DaemonProcessManager {
|
|
|
519
523
|
state.startAttemptedAtMs = null;
|
|
520
524
|
}
|
|
521
525
|
await this.stopAgent(agent);
|
|
522
|
-
await this.startAgent(agent);
|
|
526
|
+
await this.startAgent(agent, options);
|
|
523
527
|
}
|
|
524
528
|
async stopAll() {
|
|
525
529
|
for (const state of this.agents.values()) {
|
|
@@ -575,8 +579,8 @@ class DaemonProcessManager {
|
|
|
575
579
|
listAgentSnapshots() {
|
|
576
580
|
return [...this.agents.values()].map((state) => state.snapshot);
|
|
577
581
|
}
|
|
578
|
-
onExit(state, code, signal) {
|
|
579
|
-
if (
|
|
582
|
+
onExit(state, child, code, signal) {
|
|
583
|
+
if (state.process !== child)
|
|
580
584
|
return;
|
|
581
585
|
state.process = null;
|
|
582
586
|
state.startInFlight = false;
|
|
@@ -168,7 +168,8 @@ function isBwItemNotFoundError(error) {
|
|
|
168
168
|
// detection serializes across processes.
|
|
169
169
|
// ---------------------------------------------------------------------------
|
|
170
170
|
const BW_LOCK_FILENAME = ".ouro-bw.lock";
|
|
171
|
-
const
|
|
171
|
+
const BW_COMMAND_TIMEOUT_MS = 30_000;
|
|
172
|
+
const BW_LOCK_TIMEOUT_MS = 75_000;
|
|
172
173
|
const BW_LOCK_POLL_MS = 100;
|
|
173
174
|
const BW_LOCK_DEAD_CHILD_GRACE_MS = 2_000;
|
|
174
175
|
const BW_LOCK_STALE_MS = BW_LOCK_TIMEOUT_MS * 2;
|
|
@@ -344,7 +345,7 @@ function execBw(args, sessionToken, appDataDir, stdin, bwBinaryPath = "bw", extr
|
|
|
344
345
|
...extraEnv,
|
|
345
346
|
};
|
|
346
347
|
const runCommand = (lock) => new Promise((resolve, reject) => {
|
|
347
|
-
const child = (0, node_child_process_1.execFile)(bwBinaryPath, args, { timeout:
|
|
348
|
+
const child = (0, node_child_process_1.execFile)(bwBinaryPath, args, { timeout: BW_COMMAND_TIMEOUT_MS, env }, (err, stdout, stderr) => {
|
|
348
349
|
if (err) {
|
|
349
350
|
if (isBwNotInstalled(err)) {
|
|
350
351
|
reject(new Error("bw CLI not found. Install from https://bitwarden.com/help/cli/"));
|