UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

429 lines (428 loc) 16.2 kB
import { P as timestampMsToIsoString } from "./number-coercion-CJQ8TR--.js"; import { t as createLazyImportLoader } from "./lazy-promise-BONnzNfb.js"; import { t as sanitizeTerminalText } from "./safe-text-BkQYdJi1.js"; import { c as normalizePairingConnectRequestId, d as readConnectPairingRequiredMessage, f as readPairingConnectErrorDetails } from "./connect-error-details-BXqba0zp.js"; import { o as readRestartSentinel } from "./restart-sentinel-BFAG1Tav.js"; import { r as withProgress } from "./progress-CN3xUiCO.js"; import { t as logGatewayConnectionDetails } from "./status.gateway-connection-BhoLn6II.js"; import { a as resolveStatusRuntimeSnapshot, c as resolveStatusUsageSummary, f as buildStatusOverviewSurfaceFromScan, o as resolveStatusSecurityAudit, r as resolveStatusGatewayHealth, t as loadStatusProviderUsageModule } from "./status-runtime-shared-D72cMRcz.js"; import { C as buildStatusSystemEventsRows, S as buildStatusSessionsRows, T as statusHealthColumns, _ as buildStatusHealthRows, b as buildStatusPluginCompatibilityLines, c as buildStatusOverviewSection, d as buildStatusUsageSection, g as buildStatusFooterLines, h as buildStatusCommandOverviewRows, l as buildStatusSessionsSection, o as buildStatusChannelsTableSection, p as formatUpdateRestartStatusValue, s as buildStatusHealthSection, t as appendStatusReportSections, u as buildStatusSystemEventsSection, v as buildStatusModelSelectionLines, w as buildStatusSystemEventsTrailer, x as buildStatusSecurityAuditLines, y as buildStatusPairingRecoveryLines } from "./text-report-C_U929Hv.js"; import { n as statusChannelsTableColumns, t as buildStatusChannelsTableRows } from "./channels-table-DxFNivs3.js"; import { t as runStatusJsonCommand } from "./status-json-command-BAUu0Czz.js"; //#region src/commands/status.command-report-data.ts /** Builds all table rows, section lines, and footer data needed by the status report renderer. */ async function buildStatusCommandReportData(params) { const overviewRows = buildStatusCommandOverviewRows({ opts: params.opts, surface: params.surface, osLabel: params.osSummary.label, summary: params.summary, health: params.health, lastHeartbeat: params.lastHeartbeat, agentStatus: params.agentStatus, memory: params.memory, memoryPlugin: params.memoryPlugin, pluginCompatibility: params.pluginCompatibility, ok: params.ok, warn: params.warn, muted: params.muted, formatTimeAgo: params.formatTimeAgo, formatKTokens: params.formatKTokens, resolveMemoryVectorState: params.resolveMemoryVectorState, resolveMemoryFtsState: params.resolveMemoryFtsState, resolveMemoryCacheSummary: params.resolveMemoryCacheSummary, updateValue: params.updateValue, updateRestartValue: params.updateRestartValue }); const sessionsColumns = [ { key: "Key", header: "Key", minWidth: 20, flex: true }, { key: "Kind", header: "Kind", minWidth: 6 }, { key: "Age", header: "Age", minWidth: 9 }, { key: "Model", header: "Model", minWidth: 14 }, { key: "Runtime", header: "Runtime", minWidth: 14 }, { key: "Tokens", header: "Tokens", minWidth: 16 }, ...params.opts.verbose ? [{ key: "Cache", header: "Cache", minWidth: 16, flex: true }] : [] ]; const securityAuditLines = params.securityAudit ? buildStatusSecurityAuditLines({ securityAudit: params.securityAudit, theme: params.theme, shortenText: params.shortenText, formatCliCommand: params.formatCliCommand }) : [params.theme.muted(`Skipped in fast status. Full report: ${params.formatCliCommand("openclaw security audit")}`), params.theme.muted(`Deep probe: ${params.formatCliCommand("openclaw status --deep")}`)]; const retainedLost = params.summary.taskAuditRetainedLost; const retainedLostLine = (params.opts.deep || params.opts.verbose) && retainedLost && retainedLost.count > 0 ? params.theme.muted(`${retainedLost.count} lost task${retainedLost.count === 1 ? "" : "s"} retained until ${timestampMsToIsoString(retainedLost.nextCleanupAfter) ?? "cleanupAfter"}`) : null; return { heading: params.theme.heading, muted: params.theme.muted, renderTable: params.renderTable, width: params.tableWidth, overviewRows, showTaskMaintenanceHint: params.summary.taskAudit.errors > 0, taskMaintenanceHint: `Task maintenance: ${params.formatCliCommand("openclaw tasks maintenance --apply")}`, retainedLostTaskLine: retainedLostLine, pluginCompatibilityLines: buildStatusPluginCompatibilityLines({ notices: params.pluginCompatibility, formatNotice: params.formatPluginCompatibilityNotice, warn: params.theme.warn, muted: params.theme.muted }), pairingRecoveryLines: buildStatusPairingRecoveryLines({ pairingRecovery: params.pairingRecovery, warn: params.theme.warn, muted: params.theme.muted, formatCliCommand: params.formatCliCommand }), modelSelectionLines: buildStatusModelSelectionLines({ recent: params.summary.sessions.recent, shortenText: params.shortenText, warn: params.theme.warn, muted: params.theme.muted }), securityAuditLines, channelsColumns: statusChannelsTableColumns, channelsRows: buildStatusChannelsTableRows({ rows: params.channels.rows, channelIssues: params.channelIssues, ok: params.ok, warn: params.warn, muted: params.muted, accentDim: params.accentDim, formatIssueMessage: (message) => params.shortenText(message, 84) }), sessionsColumns, sessionsRows: buildStatusSessionsRows({ recent: params.summary.sessions.recent, verbose: params.opts.verbose, shortenText: params.shortenText, formatTimeAgo: params.formatTimeAgo, formatTokensCompact: params.formatTokensCompact, formatPromptCacheCompact: params.formatPromptCacheCompact, muted: params.muted }), systemEventsRows: buildStatusSystemEventsRows({ queuedSystemEvents: params.summary.queuedSystemEvents }), systemEventsTrailer: buildStatusSystemEventsTrailer({ queuedSystemEvents: params.summary.queuedSystemEvents, muted: params.muted }), healthColumns: params.health ? statusHealthColumns : void 0, healthRows: params.health ? buildStatusHealthRows({ health: params.health, formatHealthChannelLines: params.formatHealthChannelLines, ok: params.ok, warn: params.warn, muted: params.muted }) : void 0, usageLines: params.usageLines, footerLines: buildStatusFooterLines({ updateHint: params.formatUpdateAvailableHint(params.surface.update), warn: params.theme.warn, formatCliCommand: params.formatCliCommand, nodeOnlyGateway: params.surface.nodeOnlyGateway, gatewayReachable: params.surface.gatewayReachable }) }; } //#endregion //#region src/commands/status.command-report.ts /** Builds terminal lines for the standard status report. */ async function buildStatusCommandReportLines(params) { const lines = []; lines.push(params.heading("OpenClaw status")); appendStatusReportSections({ lines, heading: params.heading, sections: [ { ...buildStatusOverviewSection({ width: params.width, renderTable: params.renderTable, rows: params.overviewRows }) }, { kind: "raw", body: params.showTaskMaintenanceHint || params.retainedLostTaskLine ? [ "", ...params.showTaskMaintenanceHint ? [params.muted(params.taskMaintenanceHint)] : [], ...params.retainedLostTaskLine ? [params.retainedLostTaskLine] : [] ] : [], skipIfEmpty: true }, { kind: "lines", title: "Plugin compatibility", body: params.pluginCompatibilityLines, skipIfEmpty: true }, { kind: "raw", body: params.pairingRecoveryLines.length > 0 ? ["", ...params.pairingRecoveryLines] : [], skipIfEmpty: true }, { kind: "lines", title: "Model selection", body: params.modelSelectionLines, skipIfEmpty: true }, { kind: "lines", title: "Security audit", body: params.securityAuditLines }, params.channelsRows.length === 0 ? { kind: "lines", title: "Channels", body: [params.muted("No channels configured")] } : { ...buildStatusChannelsTableSection({ width: params.width, renderTable: params.renderTable, columns: params.channelsColumns, rows: params.channelsRows }) }, params.sessionsRows.length === 0 ? { kind: "lines", title: "Sessions", body: [params.muted("No sessions")] } : { ...buildStatusSessionsSection({ width: params.width, renderTable: params.renderTable, columns: params.sessionsColumns, rows: params.sessionsRows }) }, { ...buildStatusSystemEventsSection({ width: params.width, renderTable: params.renderTable, rows: params.systemEventsRows, trailer: params.systemEventsTrailer }) }, { ...buildStatusHealthSection({ width: params.width, renderTable: params.renderTable, columns: params.healthColumns, rows: params.healthRows }) }, { ...buildStatusUsageSection({ usageLines: params.usageLines }) }, { kind: "raw", body: ["", ...params.footerLines] } ] }); return lines; } //#endregion //#region src/commands/status.command.ts const statusScanModuleLoader = createLazyImportLoader(() => import("./status.scan-D2nVHgAl.js")); const statusScanFastJsonModuleLoader = createLazyImportLoader(() => import("./status.scan.fast-json-Bnh-xH8A.js")); const statusAllModuleLoader = createLazyImportLoader(() => import("./status-all-CV2bCStk.js")); const statusCommandTextRuntimeLoader = createLazyImportLoader(() => import("./status.command.text-runtime-B6mbB3mJ.js")); const statusNodeModeModuleLoader = createLazyImportLoader(() => import("./status.node-mode-DnPsbBfq.js")); function loadStatusScanModule() { return statusScanModuleLoader.load(); } function loadStatusScanFastJsonModule() { return statusScanFastJsonModuleLoader.load(); } function loadStatusAllModule() { return statusAllModuleLoader.load(); } function loadStatusCommandTextRuntime() { return statusCommandTextRuntimeLoader.load(); } function loadStatusNodeModeModule() { return statusNodeModeModuleLoader.load(); } /** Extracts device-pairing recovery context from structured gateway errors or legacy message text. */ function resolvePairingRecoveryContext(params) { const structured = readPairingConnectErrorDetails(params.details); if (structured) return { requestId: normalizePairingConnectRequestId(structured.requestId) ?? null, reason: structured.reason ?? null, remediationHint: structured.remediationHint ? sanitizeTerminalText(structured.remediationHint) : null }; const pairing = readConnectPairingRequiredMessage([params.error, params.closeReason].filter((part) => typeof part === "string" && part.trim().length > 0).join(" ")); if (!pairing) return null; return { requestId: normalizePairingConnectRequestId(pairing.requestId) ?? null, reason: pairing.reason ?? null, remediationHint: null }; } /** Runs `openclaw status`, including JSON/all routing and optional deep probes. */ async function statusCommand(opts, runtime) { if (opts.all && !opts.json) { await loadStatusAllModule().then(({ statusAllCommand }) => statusAllCommand(runtime, { timeoutMs: opts.timeoutMs })); return; } if (opts.json) { await runStatusJsonCommand({ opts, runtime, includeSecurityAudit: opts.all === true, includePluginCompatibility: true, suppressHealthErrors: true, scanStatusJsonFast: async (scanOpts, runtimeForScan) => await loadStatusScanFastJsonModule().then(({ scanStatusJsonFast }) => scanStatusJsonFast(scanOpts, runtimeForScan)) }); return; } const scan = await loadStatusScanModule().then(({ scanStatus }) => scanStatus({ json: false, timeoutMs: opts.timeoutMs, all: opts.all, deep: opts.deep }, runtime)); const { cfg, osSummary, tailscaleMode, tailscaleDns, tailscaleHttpsUrl, update, gatewayConnection, remoteUrlMissing, gatewayMode, gatewayProbeAuth, gatewayProbeAuthWarning, gatewayProbe, gatewayReachable, gatewaySelf, channelIssues, agentStatus, channels, summary, secretDiagnostics, memory, memoryPlugin, pluginCompatibility } = scan; const { securityAudit, usage, health, lastHeartbeat, gatewayService: daemon, nodeService: nodeDaemon } = await resolveStatusRuntimeSnapshot({ config: scan.cfg, sourceConfig: scan.sourceConfig, timeoutMs: opts.timeoutMs, usage: opts.usage, deep: opts.deep, gatewayReachable, includeSecurityAudit: opts.all === true || opts.deep === true, resolveSecurityAudit: async (input) => await withProgress({ label: "Running security audit…", indeterminate: true, enabled: true }, async () => await resolveStatusSecurityAudit(input)), resolveUsage: async (input) => await withProgress({ label: "Fetching usage snapshot…", indeterminate: true, enabled: opts.json !== true }, async () => await resolveStatusUsageSummary(input)), resolveHealth: async (input) => await withProgress({ label: "Checking gateway health…", indeterminate: true, enabled: opts.json !== true }, async () => await resolveStatusGatewayHealth(input)) }); const { buildStatusUpdateSurface, formatCliCommand, formatHealthChannelLines, formatKTokens, formatPromptCacheCompact, formatPluginCompatibilityNotice, formatTimeAgo, formatTokensCompact, formatUpdateAvailableHint, getTerminalTableWidth, info, renderTable, resolveMemoryCacheSummary, resolveMemoryFtsState, resolveMemoryVectorState, shortenText, theme } = await loadStatusCommandTextRuntime(); const muted = (value) => theme.muted(value); const ok = (value) => theme.success(value); const warn = (value) => theme.warn(value); const updateSurface = buildStatusUpdateSurface({ updateConfigChannel: cfg.update?.channel, update }); if (opts.verbose) { const { buildGatewayConnectionDetails } = await import("./call-BEl78mhZ.js"); logGatewayConnectionDetails({ runtime, info, message: buildGatewayConnectionDetails({ config: scan.cfg }).message, trailingBlankLine: true }); } const tableWidth = getTerminalTableWidth(); if (secretDiagnostics.length > 0) { runtime.log(theme.warn("Secret diagnostics:")); for (const entry of secretDiagnostics) runtime.log(`- ${entry}`); runtime.log(""); } const nodeOnlyGateway = await loadStatusNodeModeModule().then(({ resolveNodeOnlyGatewayInfo }) => resolveNodeOnlyGatewayInfo({ daemon, node: nodeDaemon })); const pairingRecovery = resolvePairingRecoveryContext({ error: gatewayProbe?.error ?? null, closeReason: gatewayProbe?.close?.reason ?? null, details: gatewayProbe?.connectErrorDetails }); const usageLines = usage ? await loadStatusProviderUsageModule().then(({ formatUsageReportLines }) => formatUsageReportLines(usage)) : void 0; const overviewSurface = buildStatusOverviewSurfaceFromScan({ scan: { cfg, update, tailscaleMode, tailscaleDns, tailscaleHttpsUrl, gatewayMode, remoteUrlMissing, gatewayConnection, gatewayReachable, gatewayProbe, gatewayProbeAuth, gatewayProbeAuthWarning, gatewaySelf }, gatewayService: daemon, nodeService: nodeDaemon, nodeOnlyGateway }); const updateRestartValue = formatUpdateRestartStatusValue((await readRestartSentinel().catch(() => null))?.payload, { ok, warn, muted, formatTimeAgo }); const lines = await buildStatusCommandReportLines(await buildStatusCommandReportData({ opts, surface: overviewSurface, osSummary, summary, securityAudit, health, usageLines, lastHeartbeat, agentStatus, channels, channelIssues, memory, memoryPlugin, pluginCompatibility, pairingRecovery, tableWidth, ok, warn, muted, shortenText, formatCliCommand, formatTimeAgo, formatKTokens, formatTokensCompact, formatPromptCacheCompact, formatHealthChannelLines, formatPluginCompatibilityNotice, formatUpdateAvailableHint, resolveMemoryVectorState, resolveMemoryFtsState, resolveMemoryCacheSummary, accentDim: theme.accentDim, theme, renderTable, updateValue: updateSurface.updateAvailable ? warn(`available · ${updateSurface.updateLine}`) : updateSurface.updateLine, updateRestartValue })); for (const line of lines) runtime.log(line); } //#endregion export { statusCommand as n, resolvePairingRecoveryContext as t };