@deksden-com/dd-flow-cli 0.9.0-beta.29 → 0.9.0-beta.30
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.md
CHANGED
package/dist/build-info.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cli_package": "@deksden-com/dd-flow-cli",
|
|
3
|
-
"cli_version": "0.9.0-beta.
|
|
4
|
-
"cli_commit": "
|
|
5
|
-
"built_at": "2026-09-
|
|
3
|
+
"cli_version": "0.9.0-beta.30",
|
|
4
|
+
"cli_commit": "88b1f0f37ffa205a7ed21b56054849d083707501",
|
|
5
|
+
"built_at": "2026-09-07T14:11:41.176Z",
|
|
6
6
|
"built_with_canon": {
|
|
7
7
|
"version": "4.0.6",
|
|
8
8
|
"commit": "c6fc50cb3b5526ea0162ee4454d1ee36f17be2da",
|
|
@@ -3,7 +3,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
3
3
|
import { appendFile, chmod, lstat, mkdir, open, readFile, realpath, rename, unlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import net from "node:net";
|
|
6
|
-
import {
|
|
6
|
+
import { ObservationClock } from "./observation-clock.mjs";
|
|
7
7
|
import { durableDaemonDispatch } from "./daemon-operations.mjs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { observeModel } from "./model-observations.mjs";
|
|
@@ -74,25 +74,33 @@ async function prepare(paths, config) {
|
|
|
74
74
|
export async function callDaemon(stateDir, operation, params = {}, timeoutMs = 30_000) {
|
|
75
75
|
const paths = locations(stateDir), request = { schema_id: REQUEST_SCHEMA, id: process.env.DD_EVAL_OPERATION_ID ?? randomUUID(), operation, params };
|
|
76
76
|
return await new Promise((resolve, reject) => {
|
|
77
|
-
const client = net.createConnection(paths.socket); let buffer = "", settled = false, timer, lastActivity = Date.now();
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
77
|
+
const client = net.createConnection(paths.socket); let buffer = "", settled = false, timer, checking = false, lastActivity = Date.now();
|
|
78
|
+
const clock = new ObservationClock({ timeoutMs, onGap: gap => { void appendFile(paths.journal, `${JSON.stringify({ kind: "observation_gap", payload: { ...gap, operation_id: request.id } })}\n`, { mode: 0o600 }).catch(() => {}); } });
|
|
79
|
+
const finish = (error, result) => { if (settled) return; settled = true; if (timer) clearInterval(timer); client.destroy(); error ? reject(error) : resolve(result); };
|
|
80
|
+
const poll = Math.min(5_000, Math.max(25, Math.floor(timeoutMs / 20)));
|
|
81
|
+
timer = setInterval(async () => {
|
|
82
|
+
if (settled || checking) return;
|
|
83
|
+
checking = true;
|
|
84
84
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
if (operation !== "session.prompt") {
|
|
86
|
+
if (clock.sample()) finish(new DaemonError("daemon_timeout", `${operation} timed out`, true));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
let status = null;
|
|
90
|
+
try { status = await callDaemon(stateDir, "daemon.status", {}, Math.min(timeoutMs, 5_000)); }
|
|
91
|
+
catch { /* The original RPC retains the authoritative failure. */ }
|
|
92
|
+
const observed = Date.parse(status?.last_activity_at ?? "");
|
|
93
|
+
const progressed = status?.active_tree === true && Number.isFinite(observed) && observed > lastActivity;
|
|
94
|
+
if (progressed) lastActivity = observed;
|
|
95
|
+
if (!clock.sample(progressed ? lastActivity : undefined)) return;
|
|
96
|
+
finish(new DaemonError(status?.active_tree ? "subject_liveness_timeout" : "operation_observation_lost", `${operation} has no recent productive provider activity`, true, {
|
|
97
|
+
operation_id: request.id,
|
|
98
|
+
last_activity_at: status?.last_activity_at ?? null,
|
|
99
|
+
active_tree: status?.active_tree === true
|
|
100
|
+
}));
|
|
101
|
+
} finally { checking = false; }
|
|
102
|
+
}, poll);
|
|
103
|
+
client.setEncoding("utf8"); client.on("connect", () => client.write(`${JSON.stringify(request)}\n`)); client.on("data", chunk => { buffer += chunk; const index = buffer.indexOf("\n"); if (index < 0) return; try { const response = JSON.parse(buffer.slice(0, index)); response.ok ? finish(null, response.result) : finish(new DaemonError(response.error.code, response.error.message, response.error.retryable, response.error.details)); } catch (error) { finish(new DaemonError("daemon_protocol_mismatch", error.message)); } }); client.on("error", error => finish(new DaemonError("daemon_not_running", error.message, true))); client.on("end", () => finish(new DaemonError("daemon_connection_closed", `${operation} connection closed before a response`, true))); client.on("close", () => finish(new DaemonError("daemon_connection_closed", `${operation} connection closed before a response`, true)));
|
|
96
104
|
});
|
|
97
105
|
}
|
|
98
106
|
|