nextclaw 0.6.10 → 0.6.11
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/dist/cli/index.js +54 -5
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1788,6 +1788,23 @@ import { resolve as resolve6 } from "path";
|
|
|
1788
1788
|
import { getDataDir as getDataDir4 } from "@nextclaw/core";
|
|
1789
1789
|
var RESTART_SENTINEL_FILENAME = "restart-sentinel.json";
|
|
1790
1790
|
var PENDING_SYSTEM_EVENTS_KEY = "pending_system_events";
|
|
1791
|
+
var RESTART_REASON_MAX_CHARS = 240;
|
|
1792
|
+
var RESTART_NOTE_MAX_CHARS = 600;
|
|
1793
|
+
var RESTART_OUTBOUND_MAX_CHARS = 1200;
|
|
1794
|
+
function trimTo(value, maxChars) {
|
|
1795
|
+
const text = value.trim();
|
|
1796
|
+
if (!text) {
|
|
1797
|
+
return "";
|
|
1798
|
+
}
|
|
1799
|
+
if (text.length <= maxChars) {
|
|
1800
|
+
return text;
|
|
1801
|
+
}
|
|
1802
|
+
return `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
|
|
1803
|
+
}
|
|
1804
|
+
function normalizeLine(value, maxChars) {
|
|
1805
|
+
const trimmed = trimTo(value, maxChars);
|
|
1806
|
+
return trimmed ? trimmed : null;
|
|
1807
|
+
}
|
|
1791
1808
|
function resolveRestartSentinelPath() {
|
|
1792
1809
|
return resolve6(getDataDir4(), "run", RESTART_SENTINEL_FILENAME);
|
|
1793
1810
|
}
|
|
@@ -1822,7 +1839,7 @@ async function consumeRestartSentinel() {
|
|
|
1822
1839
|
}
|
|
1823
1840
|
}
|
|
1824
1841
|
function summarizeRestartSentinel(payload) {
|
|
1825
|
-
const reason = payload.stats?.reason
|
|
1842
|
+
const reason = normalizeLine(payload.stats?.reason ?? "", RESTART_REASON_MAX_CHARS);
|
|
1826
1843
|
if (payload.kind === "update.run") {
|
|
1827
1844
|
return payload.status === "ok" ? "\u2705 NextClaw update completed and service restarted." : "\u26A0\uFE0F NextClaw update finished with issues.";
|
|
1828
1845
|
}
|
|
@@ -1836,15 +1853,16 @@ function summarizeRestartSentinel(payload) {
|
|
|
1836
1853
|
}
|
|
1837
1854
|
function formatRestartSentinelMessage(payload) {
|
|
1838
1855
|
const lines = [summarizeRestartSentinel(payload)];
|
|
1839
|
-
const note = payload.message
|
|
1856
|
+
const note = normalizeLine(payload.message ?? "", RESTART_NOTE_MAX_CHARS);
|
|
1840
1857
|
if (note) {
|
|
1841
1858
|
lines.push(note);
|
|
1842
1859
|
}
|
|
1843
|
-
const reason = payload.stats?.reason
|
|
1860
|
+
const reason = normalizeLine(payload.stats?.reason ?? "", RESTART_REASON_MAX_CHARS);
|
|
1844
1861
|
if (reason && !lines.some((line) => line.includes(reason))) {
|
|
1845
1862
|
lines.push(`Reason: ${reason}`);
|
|
1846
1863
|
}
|
|
1847
|
-
|
|
1864
|
+
const message = lines.join("\n").trim();
|
|
1865
|
+
return trimTo(message, RESTART_OUTBOUND_MAX_CHARS);
|
|
1848
1866
|
}
|
|
1849
1867
|
function parseSessionKey(sessionKey) {
|
|
1850
1868
|
const value = sessionKey?.trim();
|
|
@@ -2498,6 +2516,32 @@ var ServiceCommands = class {
|
|
|
2498
2516
|
async sleep(ms) {
|
|
2499
2517
|
await new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
2500
2518
|
}
|
|
2519
|
+
resolveMostRecentRoutableSessionKey(sessionManager) {
|
|
2520
|
+
const sessions = sessionManager.listSessions();
|
|
2521
|
+
let best = null;
|
|
2522
|
+
for (const session of sessions) {
|
|
2523
|
+
const key = this.normalizeOptionalString(session.key);
|
|
2524
|
+
if (!key || key.startsWith("cli:")) {
|
|
2525
|
+
continue;
|
|
2526
|
+
}
|
|
2527
|
+
const metadataRaw = session.metadata;
|
|
2528
|
+
const metadata = metadataRaw && typeof metadataRaw === "object" && !Array.isArray(metadataRaw) ? metadataRaw : {};
|
|
2529
|
+
const contextRaw = metadata.last_delivery_context;
|
|
2530
|
+
const context = contextRaw && typeof contextRaw === "object" && !Array.isArray(contextRaw) ? contextRaw : {};
|
|
2531
|
+
const hasRoute = Boolean(this.normalizeOptionalString(context.channel)) && Boolean(this.normalizeOptionalString(context.chatId));
|
|
2532
|
+
const hasFallbackRoute = Boolean(this.normalizeOptionalString(metadata.last_channel)) && Boolean(this.normalizeOptionalString(metadata.last_to));
|
|
2533
|
+
if (!hasRoute && !hasFallbackRoute) {
|
|
2534
|
+
continue;
|
|
2535
|
+
}
|
|
2536
|
+
const updatedAtRaw = this.normalizeOptionalString(session.updated_at);
|
|
2537
|
+
const updatedAt = updatedAtRaw ? Date.parse(updatedAtRaw) : Number.NaN;
|
|
2538
|
+
const score = Number.isFinite(updatedAt) ? updatedAt : 0;
|
|
2539
|
+
if (!best || score >= best.updatedAt) {
|
|
2540
|
+
best = { key, updatedAt: score };
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return best?.key;
|
|
2544
|
+
}
|
|
2501
2545
|
async sendRestartSentinelNotice(params) {
|
|
2502
2546
|
const outboundBase = {
|
|
2503
2547
|
channel: params.channel,
|
|
@@ -2543,7 +2587,12 @@ var ServiceCommands = class {
|
|
|
2543
2587
|
await new Promise((resolve10) => setTimeout(resolve10, 750));
|
|
2544
2588
|
const payload = sentinel.payload;
|
|
2545
2589
|
const message = formatRestartSentinelMessage(payload);
|
|
2546
|
-
const
|
|
2590
|
+
const sentinelSessionKey = this.normalizeOptionalString(payload.sessionKey);
|
|
2591
|
+
const fallbackSessionKey = sentinelSessionKey ? void 0 : this.resolveMostRecentRoutableSessionKey(params.sessionManager);
|
|
2592
|
+
if (!sentinelSessionKey && fallbackSessionKey) {
|
|
2593
|
+
console.warn(`Warning: restart sentinel missing sessionKey; fallback to ${fallbackSessionKey}.`);
|
|
2594
|
+
}
|
|
2595
|
+
const sessionKey = sentinelSessionKey ?? fallbackSessionKey ?? "cli:default";
|
|
2547
2596
|
const parsedSession = parseSessionKey(sessionKey);
|
|
2548
2597
|
const context = payload.deliveryContext;
|
|
2549
2598
|
const channel = this.normalizeOptionalString(context?.channel) ?? parsedSession?.channel ?? this.normalizeOptionalString((params.sessionManager.getIfExists(sessionKey)?.metadata ?? {}).last_channel);
|