mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-23 19:08:22 -06:00
fix(cli): read node liveness from the recorded node.list fact and drop dead nodes-CLI guards (#124348)
Four nodes-CLI repairs at their owners:
- nodes status --last-connected joined a second pairing-scoped RPC
(node.pair.list) to reconstruct last-connection times the gateway already
records on every node.list row (lastConnectedAtMs, max of stored pairing
history and live connection, since 2dcd47d4f4). The client-side join also
preferred stored history over a live connection instead of taking the max,
and made the command fail for callers whose auth grants operator.read but
not operator.pairing. The filter now reads the recorded fact;
connectedAtMs covers gateways predating it.
- nodes list --connected blanked pending rows and then printed "Pending: 0"
while requests waited — asserting a fact it never checked. Pending rows
carry no connection state to filter on; they now always show.
- nodes remove/rename carried unreachable !nodeId guards (resolveCliNodeId
throws "node required" on blank input and every parse layer drops id-less
rows) whose dead text pointed at the wrong command (nodes pending targets
pairing requests, not paired nodes). Guards deleted; the reachable empty
--name branch now hints at nodes list.
- status.node-mode derived node-service liveness from the formatted
runtimeShort display string — parsing a fact back out of its own
projection, dead in all first-party call paths (both callers pass the
runtime object it is derived from). Field and branch deleted.
e2e test updated to pin the single-RPC shape (asserts node.pair.list is NOT
called); node-mode fixtures now use the production shape.
This commit is contained in:
committed by
GitHub
parent
df2b83f7ae
commit
ca849506f3
@@ -358,25 +358,23 @@ describe("cli program (nodes basics)", () => {
|
||||
expect(output).toContain("Catalog Only");
|
||||
});
|
||||
|
||||
it("runs nodes status --last-connected and filters by age", async () => {
|
||||
it("runs nodes status --last-connected using the recorded node.list fact", async () => {
|
||||
const now = Date.now();
|
||||
const methods: string[] = [];
|
||||
programGatewayCallMock.mockImplementation(async (...args: unknown[]) => {
|
||||
const opts = (args[0] ?? {}) as { method?: string };
|
||||
methods.push(opts.method ?? "");
|
||||
if (opts.method === "node.list") {
|
||||
return {
|
||||
ts: now,
|
||||
nodes: [
|
||||
{ nodeId: "n1", displayName: "One", connected: false },
|
||||
{ nodeId: "n2", displayName: "Two", connected: false },
|
||||
],
|
||||
};
|
||||
}
|
||||
if (opts.method === "node.pair.list") {
|
||||
return {
|
||||
pending: [],
|
||||
paired: [
|
||||
{ nodeId: "n1", lastConnectedAtMs: now - 1_000 },
|
||||
{ nodeId: "n2", lastConnectedAtMs: now - 2 * 24 * 60 * 60 * 1000 },
|
||||
{ nodeId: "n1", displayName: "One", connected: false, lastConnectedAtMs: now - 1_000 },
|
||||
{
|
||||
nodeId: "n2",
|
||||
displayName: "Two",
|
||||
connected: false,
|
||||
lastConnectedAtMs: now - 2 * 24 * 60 * 60 * 1000,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -384,7 +382,9 @@ describe("cli program (nodes basics)", () => {
|
||||
});
|
||||
await runProgram(["nodes", "status", "--last-connected", "24h"]);
|
||||
|
||||
expectGatewayRequest("node.pair.list", {});
|
||||
// The gateway records lastConnectedAtMs on node.list rows; re-joining
|
||||
// node.pair.list broke --last-connected for read-scoped callers.
|
||||
expect(methods).not.toContain("node.pair.list");
|
||||
const output = getRuntimeOutput();
|
||||
expect(output).toContain("One");
|
||||
expect(output).not.toContain("Two");
|
||||
|
||||
Reference in New Issue
Block a user