mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-23 07:01:40 +00:00
refactor: share webhook channel status helpers
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
export {
|
||||
createAccountListHelpers,
|
||||
describeAccountSnapshot,
|
||||
describeWebhookAccountSnapshot,
|
||||
mergeAccountConfig,
|
||||
resolveMergedAccountConfig,
|
||||
} from "../channels/plugins/account-helpers.js";
|
||||
|
||||
@@ -6,8 +6,10 @@ import {
|
||||
buildComputedAccountStatusSnapshot,
|
||||
buildRuntimeAccountStatusSnapshot,
|
||||
createComputedAccountStatusAdapter,
|
||||
buildWebhookChannelStatusSummary,
|
||||
buildTokenChannelStatusSummary,
|
||||
collectStatusIssuesFromLastError,
|
||||
createDependentCredentialStatusIssueCollector,
|
||||
createDefaultChannelRuntimeState,
|
||||
} from "./status-helpers.js";
|
||||
|
||||
@@ -351,6 +353,62 @@ describe("buildTokenChannelStatusSummary", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildWebhookChannelStatusSummary", () => {
|
||||
it("defaults mode to webhook and keeps supplied extras", () => {
|
||||
expect(
|
||||
buildWebhookChannelStatusSummary(
|
||||
{
|
||||
configured: true,
|
||||
running: true,
|
||||
},
|
||||
{
|
||||
secretSource: "env",
|
||||
},
|
||||
),
|
||||
).toEqual({
|
||||
configured: true,
|
||||
running: true,
|
||||
lastStartAt: null,
|
||||
lastStopAt: null,
|
||||
lastError: null,
|
||||
mode: "webhook",
|
||||
secretSource: "env",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("createDependentCredentialStatusIssueCollector", () => {
|
||||
it("uses source metadata from sanitized snapshots to pick the missing field", () => {
|
||||
const collect = createDependentCredentialStatusIssueCollector({
|
||||
channel: "line",
|
||||
dependencySourceKey: "tokenSource",
|
||||
missingPrimaryMessage: "LINE channel access token not configured",
|
||||
missingDependentMessage: "LINE channel secret not configured",
|
||||
});
|
||||
|
||||
expect(
|
||||
collect([
|
||||
{ accountId: "default", configured: false, tokenSource: "none" },
|
||||
{ accountId: "work", configured: false, tokenSource: "env" },
|
||||
{ accountId: "ok", configured: true, tokenSource: "env" },
|
||||
]),
|
||||
).toEqual([
|
||||
{
|
||||
channel: "line",
|
||||
accountId: "default",
|
||||
kind: "config",
|
||||
message: "LINE channel access token not configured",
|
||||
},
|
||||
{
|
||||
channel: "line",
|
||||
accountId: "work",
|
||||
kind: "config",
|
||||
message: "LINE channel secret not configured",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("collectStatusIssuesFromLastError", () => {
|
||||
it("returns runtime issues only for non-empty string lastError values", () => {
|
||||
expect(
|
||||
|
||||
@@ -40,6 +40,11 @@ type ComputedAccountStatusAdapterParams<ResolvedAccount, Probe, Audit> = {
|
||||
type ComputedAccountStatusSnapshot<TExtra extends StatusSnapshotExtra = StatusSnapshotExtra> =
|
||||
ComputedAccountStatusBase & { extra?: TExtra };
|
||||
|
||||
type ConfigIssueAccount = {
|
||||
accountId?: string | null;
|
||||
configured?: boolean | null;
|
||||
} & Record<string, unknown>;
|
||||
|
||||
/** Create the baseline runtime snapshot shape used by channel/account status stores. */
|
||||
export function createDefaultChannelRuntimeState<T extends Record<string, unknown>>(
|
||||
accountId: string,
|
||||
@@ -102,6 +107,24 @@ export function buildProbeChannelStatusSummary<TExtra extends Record<string, unk
|
||||
};
|
||||
}
|
||||
|
||||
/** Build webhook channel summaries with a stable default mode. */
|
||||
export function buildWebhookChannelStatusSummary<TExtra extends StatusSnapshotExtra>(
|
||||
snapshot: {
|
||||
configured?: boolean | null;
|
||||
mode?: string | null;
|
||||
running?: boolean | null;
|
||||
lastStartAt?: number | null;
|
||||
lastStopAt?: number | null;
|
||||
lastError?: string | null;
|
||||
},
|
||||
extra?: TExtra,
|
||||
) {
|
||||
return buildBaseChannelStatusSummary(snapshot, {
|
||||
mode: snapshot.mode ?? "webhook",
|
||||
...(extra ?? ({} as TExtra)),
|
||||
});
|
||||
}
|
||||
|
||||
/** Build the standard per-account status payload from config metadata plus runtime state. */
|
||||
export function buildBaseAccountStatusSnapshot<TExtra extends StatusSnapshotExtra>(
|
||||
params: {
|
||||
@@ -290,6 +313,36 @@ export function buildTokenChannelStatusSummary(
|
||||
};
|
||||
}
|
||||
|
||||
/** Build a config-issue collector from snapshot-safe source metadata only. */
|
||||
export function createDependentCredentialStatusIssueCollector(options: {
|
||||
channel: string;
|
||||
dependencySourceKey: string;
|
||||
missingPrimaryMessage: string;
|
||||
missingDependentMessage: string;
|
||||
isDependencyConfigured?: ((value: unknown) => boolean) | undefined;
|
||||
}) {
|
||||
const isDependencyConfigured =
|
||||
options.isDependencyConfigured ??
|
||||
((value: unknown) => typeof value === "string" && value.trim().length > 0 && value !== "none");
|
||||
|
||||
return (accounts: ConfigIssueAccount[]): ChannelStatusIssue[] =>
|
||||
accounts.flatMap((account) => {
|
||||
if (account.configured !== false) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
channel: options.channel,
|
||||
accountId: account.accountId ?? "",
|
||||
kind: "config",
|
||||
message: isDependencyConfigured(account[options.dependencySourceKey])
|
||||
? options.missingDependentMessage
|
||||
: options.missingPrimaryMessage,
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/** Convert account runtime errors into the generic channel status issue format. */
|
||||
export function collectStatusIssuesFromLastError(
|
||||
channel: string,
|
||||
|
||||
Reference in New Issue
Block a user