fix: dedupe probe/token base types (#16986) (thanks @iyoda)

This commit is contained in:
Shadow
2026-02-15 11:34:21 -06:00
parent 5c88d3c9f1
commit f1e7e28a8a
23 changed files with 101 additions and 55 deletions

View File

@@ -9,6 +9,7 @@ Docs: https://docs.openclaw.ai
- Subagents: nested sub-agents (sub-sub-agents) with configurable depth. Set `agents.defaults.subagents.maxSpawnDepth: 2` to allow sub-agents to spawn their own children. Includes `maxChildrenPerAgent` limit (default 5), depth-aware tool policy, and proper announce chain routing. (#14447) Thanks @tyler6204.
- Discord: components v2 UI + embeds passthrough + exec approval UX refinements (CV2 containers, button layout, Discord-forwarding skip). Thanks @thewilloftheshadow.
- Slack/Discord/Telegram: add per-channel ack reaction overrides (account/channel-level) to support platform-specific emoji formats. (#17092) Thanks @zerone0x.
- Channels: deduplicate probe/token resolution base types across core + extensions while preserving per-channel error typing. (#16986) Thanks @iyoda and @thewilloftheshadow.
### Fixes

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import { buildBlueBubblesApiUrl, blueBubblesFetchWithTimeout } from "./types.js";
export type BlueBubblesProbe = {
ok: boolean;
export type BlueBubblesProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
};
export type BlueBubblesServerInfo = {

View File

@@ -1,3 +1,4 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import type {
FeishuConfigSchema,
FeishuGroupSchema,
@@ -52,9 +53,7 @@ export type FeishuSendResult = {
chatId: string;
};
export type FeishuProbeResult = {
ok: boolean;
error?: string;
export type FeishuProbeResult = BaseProbeResult<string> & {
appId?: string;
botName?: string;
botOpenId?: string;

View File

@@ -1,3 +1,4 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import type {
BlockStreamingCoalesceConfig,
DmConfig,
@@ -83,12 +84,10 @@ export type IrcInboundMessage = {
isGroup: boolean;
};
export type IrcProbe = {
ok: boolean;
export type IrcProbe = BaseProbeResult<string> & {
host: string;
port: number;
tls: boolean;
nick: string;
latencyMs?: number;
error?: string;
};

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import { createMatrixClient, isBunRuntime } from "./client.js";
export type MatrixProbe = {
ok: boolean;
export type MatrixProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs: number;
userId?: string | null;
};

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import { normalizeMattermostBaseUrl, type MattermostUser } from "./client.js";
export type MattermostProbe = {
ok: boolean;
export type MattermostProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs?: number | null;
bot?: MattermostUser;
};

View File

@@ -1,11 +1,9 @@
import type { MSTeamsConfig } from "openclaw/plugin-sdk";
import type { BaseProbeResult, MSTeamsConfig } from "openclaw/plugin-sdk";
import { formatUnknownError } from "./errors.js";
import { loadMSTeamsSdkWithAuth } from "./sdk.js";
import { resolveMSTeamsCredentials } from "./token.js";
export type ProbeMSTeamsResult = {
ok: boolean;
error?: string;
export type ProbeMSTeamsResult = BaseProbeResult<string> & {
appId?: string;
graph?: {
ok: boolean;

View File

@@ -1,3 +1,4 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import { StaticAuthProvider } from "@twurple/auth";
import { ChatClient } from "@twurple/chat";
import type { TwitchAccountConfig } from "./types.js";
@@ -6,9 +7,7 @@ import { normalizeToken } from "./utils/twitch.js";
/**
* Result of probing a Twitch account
*/
export type ProbeTwitchResult = {
ok: boolean;
error?: string;
export type ProbeTwitchResult = BaseProbeResult<string> & {
username?: string;
elapsedMs: number;
connected?: boolean;

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import { getMe, ZaloApiError, type ZaloBotInfo, type ZaloFetch } from "./api.js";
export type ZaloProbeResult = {
ok: boolean;
export type ZaloProbeResult = BaseProbeResult<string> & {
bot?: ZaloBotInfo;
error?: string;
elapsedMs: number;
};

View File

@@ -1,9 +1,8 @@
import { readFileSync } from "node:fs";
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk";
import { type BaseTokenResolution, DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk";
import type { ZaloConfig } from "./types.js";
export type ZaloTokenResolution = {
token: string;
export type ZaloTokenResolution = BaseTokenResolution & {
source: "env" | "config" | "configFile" | "none";
};

View File

@@ -1,11 +1,10 @@
import type { BaseProbeResult } from "openclaw/plugin-sdk";
import type { ZcaUserInfo } from "./types.js";
import { runZca, parseJsonOutput } from "./zca.js";
export interface ZalouserProbeResult {
ok: boolean;
export type ZalouserProbeResult = BaseProbeResult<string> & {
user?: ZcaUserInfo;
error?: string;
}
};
export async function probeZalouser(
profile: string,

View File

@@ -0,0 +1,46 @@
import { describe, it, expectTypeOf } from "vitest";
import type { DiscordProbe } from "../../discord/probe.js";
import type { DiscordTokenResolution } from "../../discord/token.js";
import type { IMessageProbe } from "../../imessage/probe.js";
import type { LineProbeResult } from "../../line/types.js";
import type { SignalProbe } from "../../signal/probe.js";
import type { SlackProbe } from "../../slack/probe.js";
import type { TelegramProbe } from "../../telegram/probe.js";
import type { TelegramTokenResolution } from "../../telegram/token.js";
import type { BaseProbeResult, BaseTokenResolution } from "./types.js";
describe("BaseProbeResult assignability", () => {
it("TelegramProbe satisfies BaseProbeResult", () => {
expectTypeOf<TelegramProbe>().toMatchTypeOf<BaseProbeResult>();
});
it("DiscordProbe satisfies BaseProbeResult", () => {
expectTypeOf<DiscordProbe>().toMatchTypeOf<BaseProbeResult>();
});
it("SlackProbe satisfies BaseProbeResult", () => {
expectTypeOf<SlackProbe>().toMatchTypeOf<BaseProbeResult>();
});
it("SignalProbe satisfies BaseProbeResult", () => {
expectTypeOf<SignalProbe>().toMatchTypeOf<BaseProbeResult>();
});
it("IMessageProbe satisfies BaseProbeResult", () => {
expectTypeOf<IMessageProbe>().toMatchTypeOf<BaseProbeResult>();
});
it("LineProbeResult satisfies BaseProbeResult", () => {
expectTypeOf<LineProbeResult>().toMatchTypeOf<BaseProbeResult>();
});
});
describe("BaseTokenResolution assignability", () => {
it("TelegramTokenResolution satisfies BaseTokenResolution", () => {
expectTypeOf<TelegramTokenResolution>().toMatchTypeOf<BaseTokenResolution>();
});
it("DiscordTokenResolution satisfies BaseTokenResolution", () => {
expectTypeOf<DiscordTokenResolution>().toMatchTypeOf<BaseTokenResolution>();
});
});

View File

@@ -347,3 +347,15 @@ export type ChannelPollContext = {
silent?: boolean;
isAnonymous?: boolean;
};
/** Minimal base for all channel probe results. Channel-specific probes extend this. */
export type BaseProbeResult<TError = string | null> = {
ok: boolean;
error?: TError;
};
/** Minimal base for token resolution results. */
export type BaseTokenResolution = {
token: string;
source: string;
};

View File

@@ -58,6 +58,8 @@ export type {
ChannelThreadingContext,
ChannelThreadingToolContext,
ChannelToolSend,
BaseProbeResult,
BaseTokenResolution,
} from "./types.core.js";
export type { ChannelPlugin } from "./types.plugin.js";

View File

@@ -1,13 +1,12 @@
import type { BaseProbeResult } from "../channels/plugins/types.js";
import { resolveFetch } from "../infra/fetch.js";
import { fetchWithTimeout } from "../utils/fetch-timeout.js";
import { normalizeDiscordToken } from "./token.js";
const DISCORD_API_BASE = "https://discord.com/api/v10";
export type DiscordProbe = {
ok: boolean;
export type DiscordProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs: number;
bot?: { id?: string | null; username?: string | null };
application?: DiscordApplicationSummary;

View File

@@ -1,10 +1,10 @@
import type { BaseTokenResolution } from "../channels/plugins/types.js";
import type { OpenClawConfig } from "../config/config.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
export type DiscordTokenSource = "env" | "config" | "none";
export type DiscordTokenResolution = {
token: string;
export type DiscordTokenResolution = BaseTokenResolution & {
source: DiscordTokenSource;
};

View File

@@ -1,3 +1,4 @@
import type { BaseProbeResult } from "../channels/plugins/types.js";
import type { RuntimeEnv } from "../runtime.js";
import { detectBinary } from "../commands/onboard-helpers.js";
import { loadConfig } from "../config/config.js";
@@ -8,9 +9,7 @@ import { DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./constants.js";
// Re-export for backwards compatibility
export { DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./constants.js";
export type IMessageProbe = {
ok: boolean;
error?: string | null;
export type IMessageProbe = BaseProbeResult & {
fatal?: boolean;
};

View File

@@ -7,6 +7,7 @@ import type {
StickerMessage,
LocationMessage,
} from "@line/bot-sdk";
import type { BaseProbeResult } from "../channels/plugins/types.js";
export type LineTokenSource = "config" | "env" | "file" | "none";
@@ -86,16 +87,14 @@ export interface LineSendResult {
chatId: string;
}
export interface LineProbeResult {
ok: boolean;
export type LineProbeResult = BaseProbeResult<string> & {
bot?: {
displayName?: string;
userId?: string;
basicId?: string;
pictureUrl?: string;
};
error?: string;
}
};
export type LineFlexMessagePayload = {
altText: string;

View File

@@ -56,6 +56,8 @@ export type {
ChannelThreadingContext,
ChannelThreadingToolContext,
ChannelToolSend,
BaseProbeResult,
BaseTokenResolution,
} from "../channels/plugins/types.js";
export type { ChannelConfigSchema, ChannelPlugin } from "../channels/plugins/types.plugin.js";
export type {

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "../channels/plugins/types.js";
import { signalCheck, signalRpcRequest } from "./client.js";
export type SignalProbe = {
ok: boolean;
export type SignalProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs: number;
version?: string | null;
};

View File

@@ -1,9 +1,8 @@
import type { BaseProbeResult } from "../channels/plugins/types.js";
import { createSlackWebClient } from "./client.js";
export type SlackProbe = {
ok: boolean;
export type SlackProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs?: number | null;
bot?: { id?: string; name?: string };
team?: { id?: string; name?: string };

View File

@@ -1,12 +1,11 @@
import type { BaseProbeResult } from "../channels/plugins/types.js";
import { fetchWithTimeout } from "../utils/fetch-timeout.js";
import { makeProxyFetch } from "./proxy.js";
const TELEGRAM_API_BASE = "https://api.telegram.org";
export type TelegramProbe = {
ok: boolean;
export type TelegramProbe = BaseProbeResult & {
status?: number | null;
error?: string | null;
elapsedMs: number;
bot?: {
id?: number | null;

View File

@@ -1,12 +1,12 @@
import fs from "node:fs";
import type { BaseTokenResolution } from "../channels/plugins/types.js";
import type { OpenClawConfig } from "../config/config.js";
import type { TelegramAccountConfig } from "../config/types.telegram.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
export type TelegramTokenSource = "env" | "tokenFile" | "config" | "none";
export type TelegramTokenResolution = {
token: string;
export type TelegramTokenResolution = BaseTokenResolution & {
source: TelegramTokenSource;
};