Josh Avant 0e4245063f
CLI: make read-only SecretRef status flows degrade safely (#37023)
* CLI: add read-only SecretRef inspection

* CLI: fix read-only SecretRef status regressions

* CLI: preserve read-only SecretRef status fallbacks

* Docs: document read-only channel inspection hook

* CLI: preserve audit coverage for read-only SecretRefs

* CLI: fix read-only status account selection

* CLI: fix targeted gateway fallback analysis

* CLI: fix Slack HTTP read-only inspection

* CLI: align audit credential status checks

* CLI: restore Telegram read-only fallback semantics
2026-03-05 23:07:13 -06:00

72 lines
2.4 KiB
TypeScript

import { type ChannelId, getChannelPlugin } from "../../channels/plugins/index.js";
import {
type CommandSecretResolutionMode,
resolveCommandSecretRefsViaGateway,
} from "../../cli/command-secret-gateway.js";
import { getChannelsCommandSecretTargetIds } from "../../cli/command-secret-targets.js";
import type { OpenClawConfig } from "../../config/config.js";
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
import { defaultRuntime, type RuntimeEnv } from "../../runtime.js";
import { requireValidConfigSnapshot } from "../config-validation.js";
export type ChatChannel = ChannelId;
export { requireValidConfigSnapshot };
export async function requireValidConfig(
runtime: RuntimeEnv = defaultRuntime,
secretResolution?: {
commandName?: string;
mode?: CommandSecretResolutionMode;
},
): Promise<OpenClawConfig | null> {
const cfg = await requireValidConfigSnapshot(runtime);
if (!cfg) {
return null;
}
const { resolvedConfig, diagnostics } = await resolveCommandSecretRefsViaGateway({
config: cfg,
commandName: secretResolution?.commandName ?? "channels",
targetIds: getChannelsCommandSecretTargetIds(),
mode: secretResolution?.mode,
});
for (const entry of diagnostics) {
runtime.log(`[secrets] ${entry}`);
}
return resolvedConfig;
}
export function formatAccountLabel(params: { accountId: string; name?: string }) {
const base = params.accountId || DEFAULT_ACCOUNT_ID;
if (params.name?.trim()) {
return `${base} (${params.name.trim()})`;
}
return base;
}
export const channelLabel = (channel: ChatChannel) => {
const plugin = getChannelPlugin(channel);
return plugin?.meta.label ?? channel;
};
export function formatChannelAccountLabel(params: {
channel: ChatChannel;
accountId: string;
name?: string;
channelStyle?: (value: string) => string;
accountStyle?: (value: string) => string;
}): string {
const channelText = channelLabel(params.channel);
const accountText = formatAccountLabel({
accountId: params.accountId,
name: params.name,
});
const styledChannel = params.channelStyle ? params.channelStyle(channelText) : channelText;
const styledAccount = params.accountStyle ? params.accountStyle(accountText) : accountText;
return `${styledChannel} ${styledAccount}`;
}
export function shouldUseWizard(params?: { hasFlags?: boolean }) {
return params?.hasFlags === false;
}