@drakon-systems/multi-clawd 1.5.3 → 1.5.4
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/README.md +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/scripts/doctor.mjs +27 -2
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ openclaw plugins install (Get-Location).Path
|
|
|
188
188
|
**Or let your agent install it.** Running an OpenClaw assistant or Claude
|
|
189
189
|
Code on the target machine already? Paste it this and go make coffee:
|
|
190
190
|
|
|
191
|
-
> Read https://raw.githubusercontent.com/Drakon-Systems-Ltd/multi-clawd/v1.5.
|
|
191
|
+
> Read https://raw.githubusercontent.com/Drakon-Systems-Ltd/multi-clawd/v1.5.4/SETUP-AGENT.md
|
|
192
192
|
> and follow it to set up multi-clawd on this machine. I own a second
|
|
193
193
|
> Claude account — ask me when you need me to log in.
|
|
194
194
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "multi-clawd",
|
|
3
3
|
"name": "multi-clawd",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.4",
|
|
5
5
|
"description": "Register additional Claude Code logins (Max/Pro accounts) as first-class OpenClaw CLI backends for cross-account failover, keeping the full skills/MCP harness on every account.",
|
|
6
6
|
"cliBackends": [
|
|
7
7
|
"claw1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakon-systems/multi-clawd",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "Multi-account Claude Code failover for OpenClaw — register additional Claude (Max/Pro) logins as first-class CLI backends and keep the full skills/MCP harness across every account.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/scripts/doctor.mjs
CHANGED
|
@@ -182,6 +182,9 @@ console.log("account credentials");
|
|
|
182
182
|
const { checkAccountCredential } = await import(join(EXT_DIR, "dist", "login-health.js")).catch(
|
|
183
183
|
() => import(join(REPO_DIR, "dist", "login-health.js")),
|
|
184
184
|
);
|
|
185
|
+
const { summarizeWindowUsage } = await import(join(EXT_DIR, "dist", "health.js")).catch(() =>
|
|
186
|
+
import(join(REPO_DIR, "dist", "health.js")),
|
|
187
|
+
);
|
|
185
188
|
const io = {
|
|
186
189
|
readFile: (p) => readFileSync(expandHome(p), "utf8"),
|
|
187
190
|
keychainHasClaudeCredentials: () => {
|
|
@@ -218,10 +221,32 @@ for (const account of accounts) {
|
|
|
218
221
|
continue;
|
|
219
222
|
}
|
|
220
223
|
const ageMin = Math.round((Date.now() - (state.updatedAt ?? 0)) / 60000);
|
|
224
|
+
// A window whose own reset has PASSED describes the previous cycle, and the
|
|
225
|
+
// rotation logic already voids it ("a passed reset voids the observation",
|
|
226
|
+
// health.ts). Doctor used to print it raw beside a fresh `(0m old)` stamp,
|
|
227
|
+
// so a five-day-dead `seven_day@96%` read as "96% used right now" when
|
|
228
|
+
// nothing was acting on it. The age stamp is the age of the OBSERVATION,
|
|
229
|
+
// never the window's validity.
|
|
230
|
+
//
|
|
231
|
+
// `summarizeWindowUsage` is the same function `explain` uses, so all three
|
|
232
|
+
// surfaces — rotation, explain, doctor — agree on what counts as live
|
|
233
|
+
// rather than each carrying its own copy of the rule.
|
|
234
|
+
const live = new Set(
|
|
235
|
+
summarizeWindowUsage(state, { staleAfterMs: pluginConfig.pool?.staleAfterMs }, Date.now()).map(
|
|
236
|
+
(u) => u.window,
|
|
237
|
+
),
|
|
238
|
+
);
|
|
221
239
|
const windows = Object.entries(state.windows ?? {})
|
|
222
|
-
.map(([w, d]) =>
|
|
240
|
+
.map(([w, d]) => {
|
|
241
|
+
const hasUtil = typeof d.utilization === "number";
|
|
242
|
+
const util = hasUtil ? `@${Math.round(d.utilization * 100)}%` : "";
|
|
243
|
+
// Only utilization-bearing account windows are summarised; a window
|
|
244
|
+
// carrying a number that did NOT survive is one the pool ignores.
|
|
245
|
+
const stale = hasUtil && !w.startsWith("model:") && !live.has(w);
|
|
246
|
+
return `${w}:${d.status}${util}${stale ? " (expired — ignored)" : ""}`;
|
|
247
|
+
})
|
|
223
248
|
.join(" ");
|
|
224
|
-
ok(`${account.id}: ${windows || "no windows"} (${ageMin}m
|
|
249
|
+
ok(`${account.id}: ${windows || "no windows"} (observed ${ageMin}m ago)`);
|
|
225
250
|
}
|
|
226
251
|
|
|
227
252
|
// ── 6. pool ─────────────────────────────────────────────────────────────────
|