diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index c090ccc5de8..7765bfd0d2b 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -0a7db1dbcb8d4a58aa9533164929f08e2ed6ee37bb29bf302590a478c55c363a plugin-sdk-api-baseline.json -f1fb149181511750b30d1ee9638d17a0dc6a332db2e32a9a599cb9aeb40b4e1f plugin-sdk-api-baseline.jsonl +20db3f5afb93db334ad7456d26303c81b2a3eeaa5c1f8846a459eec72be20b96 plugin-sdk-api-baseline.json +d02926e9facb3321a1018804d4c0370d9627963bee5e478942dda469e529c20b plugin-sdk-api-baseline.jsonl diff --git a/src/plugin-sdk/anthropic-cli.ts b/src/plugin-sdk/anthropic-cli.ts index 7a4edcc6d97..89c03cd1c7c 100644 --- a/src/plugin-sdk/anthropic-cli.ts +++ b/src/plugin-sdk/anthropic-cli.ts @@ -1,7 +1,11 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/anthropic/api.js"); import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + CLAUDE_CLI_BACKEND_ID: string; + isClaudeCliProvider: (providerId: string) => boolean; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "anthropic", diff --git a/src/plugin-sdk/anthropic-vertex.ts b/src/plugin-sdk/anthropic-vertex.ts index d283b06f3bb..d67c6c937bf 100644 --- a/src/plugin-sdk/anthropic-vertex.ts +++ b/src/plugin-sdk/anthropic-vertex.ts @@ -1,6 +1,22 @@ -type FacadeModule = typeof import("@openclaw/anthropic-vertex/api.js"); +import type { ModelProviderConfig } from "../config/types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + resolveAnthropicVertexClientRegion: (params?: { + baseUrl?: string; + env?: NodeJS.ProcessEnv; + }) => string; + resolveAnthropicVertexProjectId: (env?: NodeJS.ProcessEnv) => string | undefined; + buildAnthropicVertexProvider: (params?: { env?: NodeJS.ProcessEnv }) => ModelProviderConfig; + resolveImplicitAnthropicVertexProvider: (params?: { + env?: NodeJS.ProcessEnv; + }) => ModelProviderConfig | null; + mergeImplicitAnthropicVertexProvider: (params: { + existing?: ModelProviderConfig; + implicit: ModelProviderConfig; + }) => ModelProviderConfig; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "anthropic-vertex", diff --git a/src/plugin-sdk/bluebubbles-policy.ts b/src/plugin-sdk/bluebubbles-policy.ts index ef2459874dc..ae9dc7976ea 100644 --- a/src/plugin-sdk/bluebubbles-policy.ts +++ b/src/plugin-sdk/bluebubbles-policy.ts @@ -1,7 +1,32 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/bluebubbles/api.js"); +import type { OpenClawConfig } from "../config/types.js"; +import type { GroupToolPolicyConfig } from "../config/types.tools.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type BlueBubblesGroupContext = { + cfg: OpenClawConfig; + accountId?: string | null; + groupId?: string | null; + senderId?: string | null; + senderName?: string | null; + senderUsername?: string | null; + senderE164?: string | null; +}; + +type FacadeModule = { + isAllowedBlueBubblesSender: (params: { + allowFrom: Array; + sender: string; + chatId?: number | null; + chatGuid?: string | null; + chatIdentifier?: string | null; + }) => boolean; + resolveBlueBubblesGroupRequireMention: (params: BlueBubblesGroupContext) => boolean; + resolveBlueBubblesGroupToolPolicy: ( + params: BlueBubblesGroupContext, + ) => GroupToolPolicyConfig | undefined; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "bluebubbles", diff --git a/src/plugin-sdk/feishu-conversation.ts b/src/plugin-sdk/feishu-conversation.ts index 8457967f8be..5472dff00c7 100644 --- a/src/plugin-sdk/feishu-conversation.ts +++ b/src/plugin-sdk/feishu-conversation.ts @@ -1,11 +1,75 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/feishu/contract-api.js"); +import type { OpenClawConfig } from "../config/types.js"; +import type { BindingTargetKind } from "../infra/outbound/session-binding-service.js"; import { createLazyFacadeArrayValue, createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +type FeishuGroupSessionScope = "group" | "group_sender" | "group_topic" | "group_topic_sender"; + +type FeishuThreadBindingRecord = { + accountId: string; + conversationId: string; + parentConversationId?: string; + deliveryTo?: string; + deliveryThreadId?: string; + targetKind: "subagent" | "acp"; + targetSessionKey: string; + agentId?: string; + label?: string; + boundBy?: string; + boundAt: number; + lastActivityAt: number; +}; + +type FeishuThreadBindingManager = { + accountId: string; + getByConversationId: (conversationId: string) => FeishuThreadBindingRecord | undefined; + listBySessionKey: (targetSessionKey: string) => FeishuThreadBindingRecord[]; + bindConversation: (params: { + conversationId: string; + parentConversationId?: string; + targetKind: BindingTargetKind; + targetSessionKey: string; + metadata?: Record; + }) => FeishuThreadBindingRecord | null; + touchConversation: (conversationId: string, at?: number) => FeishuThreadBindingRecord | null; + unbindConversation: (conversationId: string) => FeishuThreadBindingRecord | null; + unbindBySessionKey: (targetSessionKey: string) => FeishuThreadBindingRecord[]; + stop: () => void; +}; + +type FacadeModule = { + buildFeishuConversationId: (params: { + chatId: string; + scope: FeishuGroupSessionScope; + senderOpenId?: string; + topicId?: string; + }) => string; + createFeishuThreadBindingManager: (params: { + accountId?: string; + cfg: OpenClawConfig; + }) => FeishuThreadBindingManager; + feishuSessionBindingAdapterChannels: readonly ["feishu"]; + feishuThreadBindingTesting: { + resetFeishuThreadBindingsForTests: () => void; + }; + parseFeishuDirectConversationId: (raw: unknown) => string | undefined; + parseFeishuConversationId: (params: { + conversationId: string; + parentConversationId?: string; + }) => { + canonicalConversationId: string; + chatId: string; + topicId?: string; + senderOpenId?: string; + scope: FeishuGroupSessionScope; + } | null; + parseFeishuTargetId: (raw: unknown) => string | undefined; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "feishu", diff --git a/src/plugin-sdk/feishu-security.ts b/src/plugin-sdk/feishu-security.ts index 7a804d40c1e..56ca20b643a 100644 --- a/src/plugin-sdk/feishu-security.ts +++ b/src/plugin-sdk/feishu-security.ts @@ -1,7 +1,12 @@ // Manual facade. Keep loader boundary explicit. -type SecuritySurface = typeof import("@openclaw/feishu/security-contract-api.js"); +import type { OpenClawConfig } from "../config/types.js"; +import type { SecurityAuditFinding } from "../security/audit.types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type SecuritySurface = { + collectFeishuSecurityAuditFindings: (params: { cfg: OpenClawConfig }) => SecurityAuditFinding[]; +}; + function loadSecuritySurface(): SecuritySurface { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "feishu", diff --git a/src/plugin-sdk/feishu-setup.ts b/src/plugin-sdk/feishu-setup.ts index a00a8cd111f..ed088127cb1 100644 --- a/src/plugin-sdk/feishu-setup.ts +++ b/src/plugin-sdk/feishu-setup.ts @@ -1,10 +1,16 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/feishu/setup-api.js"); +import type { ChannelSetupWizard } from "../channels/plugins/setup-wizard-types.js"; +import type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +type FacadeModule = { + feishuSetupAdapter: ChannelSetupAdapter; + feishuSetupWizard: ChannelSetupWizard; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "feishu", diff --git a/src/plugin-sdk/github-copilot-login.ts b/src/plugin-sdk/github-copilot-login.ts index 2dac888fdf3..2a42bec9203 100644 --- a/src/plugin-sdk/github-copilot-login.ts +++ b/src/plugin-sdk/github-copilot-login.ts @@ -1,7 +1,14 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/github-copilot/api.js"); +import type { RuntimeEnv } from "../runtime.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + githubCopilotLoginCommand: ( + opts: { profileId?: string; yes?: boolean }, + runtime: RuntimeEnv, + ) => Promise; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "github-copilot", diff --git a/src/plugin-sdk/irc-surface.ts b/src/plugin-sdk/irc-surface.ts index 2e76b37322d..05878b5b445 100644 --- a/src/plugin-sdk/irc-surface.ts +++ b/src/plugin-sdk/irc-surface.ts @@ -1,10 +1,54 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/irc/api.js"); +import type { ChannelSetupWizard } from "../channels/plugins/setup-wizard-types.js"; +import type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js"; +import type { OpenClawConfig } from "../config/types.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +type IrcAccountConfig = { + name?: string; + enabled?: boolean; + host?: string; + port?: number; + tls?: boolean; + nick?: string; + username?: string; + realname?: string; + password?: string; + passwordFile?: string; + channels?: string[]; + groups?: Record; +}; + +type ResolvedIrcAccount = { + accountId: string; + enabled: boolean; + name?: string; + configured: boolean; + host: string; + port: number; + tls: boolean; + nick: string; + username: string; + realname: string; + password: string; + passwordSource: "env" | "passwordFile" | "config" | "none"; + config: IrcAccountConfig; +}; + +type FacadeModule = { + ircSetupAdapter: ChannelSetupAdapter; + ircSetupWizard: ChannelSetupWizard; + listIrcAccountIds: (cfg: OpenClawConfig) => string[]; + resolveDefaultIrcAccountId: (cfg: OpenClawConfig) => string; + resolveIrcAccount: (params: { + cfg: OpenClawConfig; + accountId?: string | null; + }) => ResolvedIrcAccount; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "irc", diff --git a/src/plugin-sdk/line-runtime.ts b/src/plugin-sdk/line-runtime.ts index c682e828208..7a08c15805b 100644 --- a/src/plugin-sdk/line-runtime.ts +++ b/src/plugin-sdk/line-runtime.ts @@ -1,7 +1,64 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/line/runtime-api.js"); +import type { BaseProbeResult } from "../channels/plugins/types.public.js"; import { loadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; +type FacadeFunction = (...args: unknown[]) => unknown; +type FacadeModule = Record< + | "buildTemplateMessageFromPayload" + | "cancelDefaultRichMenu" + | "createActionCard" + | "createAgendaCard" + | "createAppleTvRemoteCard" + | "createCarousel" + | "createDefaultMenuConfig" + | "createDeviceControlCard" + | "createEventCard" + | "createGridLayout" + | "createImageCard" + | "createInfoCard" + | "createListCard" + | "createMediaPlayerCard" + | "createNotificationBubble" + | "createQuickReplyItems" + | "createReceiptCard" + | "createRichMenu" + | "createRichMenuAlias" + | "datetimePickerAction" + | "deleteRichMenu" + | "deleteRichMenuAlias" + | "downloadLineMedia" + | "firstDefined" + | "getDefaultRichMenuId" + | "getRichMenu" + | "getRichMenuIdOfUser" + | "getRichMenuList" + | "hasLineDirectives" + | "isSenderAllowed" + | "linkRichMenuToUser" + | "linkRichMenuToUsers" + | "messageAction" + | "monitorLineProvider" + | "normalizeAllowFrom" + | "normalizeDmAllowFromWithStore" + | "parseLineDirectives" + | "postbackAction" + | "probeLineBot" + | "pushFlexMessage" + | "pushLocationMessage" + | "pushMessageLine" + | "pushMessagesLine" + | "pushTemplateMessage" + | "pushTextMessageWithQuickReplies" + | "sendMessageLine" + | "setDefaultRichMenu" + | "toFlexMessage" + | "unlinkRichMenuFromUser" + | "unlinkRichMenuFromUsers" + | "uploadRichMenuImage" + | "uriAction", + FacadeFunction +>; + function loadFacadeModule(): FacadeModule { return loadActivatedBundledPluginPublicSurfaceModuleSync({ dirName: "line", @@ -134,24 +191,123 @@ export const uploadRichMenuImage: FacadeModule["uploadRichMenuImage"] = ((...arg loadFacadeModule()["uploadRichMenuImage"](...args)) as FacadeModule["uploadRichMenuImage"]; export const uriAction: FacadeModule["uriAction"] = ((...args) => loadFacadeModule()["uriAction"](...args)) as FacadeModule["uriAction"]; -export type Action = import("@openclaw/line/runtime-api.js").Action; -export type CardAction = import("@openclaw/line/runtime-api.js").CardAction; -export type CreateRichMenuParams = import("@openclaw/line/runtime-api.js").CreateRichMenuParams; -export type FlexBox = import("@openclaw/line/runtime-api.js").FlexBox; -export type FlexBubble = import("@openclaw/line/runtime-api.js").FlexBubble; -export type FlexButton = import("@openclaw/line/runtime-api.js").FlexButton; -export type FlexCarousel = import("@openclaw/line/runtime-api.js").FlexCarousel; -export type FlexComponent = import("@openclaw/line/runtime-api.js").FlexComponent; -export type FlexContainer = import("@openclaw/line/runtime-api.js").FlexContainer; -export type FlexImage = import("@openclaw/line/runtime-api.js").FlexImage; -export type FlexText = import("@openclaw/line/runtime-api.js").FlexText; -export type LineChannelData = import("@openclaw/line/runtime-api.js").LineChannelData; -export type LineConfig = import("@openclaw/line/runtime-api.js").LineConfig; -export type LineProbeResult = import("@openclaw/line/runtime-api.js").LineProbeResult; -export type ListItem = import("@openclaw/line/runtime-api.js").ListItem; -export type ResolvedLineAccount = import("@openclaw/line/runtime-api.js").ResolvedLineAccount; -export type RichMenuArea = import("@openclaw/line/runtime-api.js").RichMenuArea; -export type RichMenuAreaRequest = import("@openclaw/line/runtime-api.js").RichMenuAreaRequest; -export type RichMenuRequest = import("@openclaw/line/runtime-api.js").RichMenuRequest; -export type RichMenuResponse = import("@openclaw/line/runtime-api.js").RichMenuResponse; -export type RichMenuSize = import("@openclaw/line/runtime-api.js").RichMenuSize; +export type Action = Record; +export type FlexBox = Record; +export type FlexBubble = Record; +export type FlexButton = Record; +export type FlexCarousel = Record; +export type FlexComponent = Record; +export type FlexContainer = Record; +export type FlexImage = Record; +export type FlexText = Record; + +export interface ListItem { + title: string; + subtitle?: string; + action?: Action; +} + +export interface CardAction { + label: string; + action: Action; +} + +export interface LineThreadBindingsConfig { + enabled?: boolean; + idleHours?: number; + maxAgeHours?: number; + spawnSubagentSessions?: boolean; + spawnAcpSessions?: boolean; +} + +interface LineAccountBaseConfig { + enabled?: boolean; + channelAccessToken?: string; + channelSecret?: string; + tokenFile?: string; + secretFile?: string; + name?: string; + allowFrom?: Array; + groupAllowFrom?: Array; + dmPolicy?: "open" | "allowlist" | "pairing" | "disabled"; + groupPolicy?: "open" | "allowlist" | "disabled"; + responsePrefix?: string; + mediaMaxMb?: number; + webhookPath?: string; + threadBindings?: LineThreadBindingsConfig; + groups?: Record; +} + +export interface LineConfig extends LineAccountBaseConfig { + accounts?: Record; + defaultAccount?: string; +} + +export interface LineGroupConfig { + enabled?: boolean; + allowFrom?: Array; + requireMention?: boolean; + systemPrompt?: string; + skills?: string[]; +} + +export interface ResolvedLineAccount { + accountId: string; + name?: string; + enabled: boolean; + channelAccessToken: string; + channelSecret: string; + tokenSource: "config" | "env" | "file" | "none"; + config: LineConfig & LineAccountBaseConfig; +} + +export type LineProbeResult = BaseProbeResult & { + bot?: { + displayName?: string; + userId?: string; + basicId?: string; + pictureUrl?: string; + }; +}; + +export type LineChannelData = { + quickReplies?: string[]; + location?: { + title: string; + address: string; + latitude: number; + longitude: number; + }; + flexMessage?: { + altText: string; + contents: unknown; + }; + templateMessage?: unknown; +}; + +export interface RichMenuSize { + width: 2500; + height: 1686 | 843; +} + +export interface RichMenuAreaRequest { + bounds: { + x: number; + y: number; + width: number; + height: number; + }; + action: Action; +} + +export interface CreateRichMenuParams { + size: RichMenuSize; + selected?: boolean; + name: string; + chatBarText: string; + areas: RichMenuAreaRequest[]; +} + +export type RichMenuArea = RichMenuAreaRequest; +export type RichMenuRequest = Record; +export type RichMenuResponse = Record; diff --git a/src/plugin-sdk/line-surface.ts b/src/plugin-sdk/line-surface.ts index 410b00e6dd6..8c2bf19347b 100644 --- a/src/plugin-sdk/line-surface.ts +++ b/src/plugin-sdk/line-surface.ts @@ -1,10 +1,33 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/line/runtime-api.js"); +import type { BaseProbeResult } from "../channels/plugins/types.public.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +type FacadeFunction = (...args: unknown[]) => unknown; +type FacadeModule = Record< + | "createActionCard" + | "createAgendaCard" + | "createAppleTvRemoteCard" + | "createDeviceControlCard" + | "createEventCard" + | "createImageCard" + | "createInfoCard" + | "createListCard" + | "createMediaPlayerCard" + | "createReceiptCard" + | "listLineAccountIds" + | "normalizeAccountId" + | "processLineMessage" + | "resolveDefaultLineAccountId" + | "resolveExactLineGroupConfigKey" + | "resolveLineAccount", + FacadeFunction +> & { + LineConfigSchema: object; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "line", @@ -36,8 +59,8 @@ export const createMediaPlayerCard: FacadeModule["createMediaPlayerCard"] = ((.. export const createReceiptCard: FacadeModule["createReceiptCard"] = ((...args) => loadFacadeModule()["createReceiptCard"](...args)) as FacadeModule["createReceiptCard"]; export const LineConfigSchema: FacadeModule["LineConfigSchema"] = createLazyFacadeObjectValue( - () => loadFacadeModule()["LineConfigSchema"] as object, -) as FacadeModule["LineConfigSchema"]; + () => loadFacadeModule()["LineConfigSchema"], +); export const listLineAccountIds: FacadeModule["listLineAccountIds"] = ((...args) => loadFacadeModule()["listLineAccountIds"](...args)) as FacadeModule["listLineAccountIds"]; export const normalizeAccountId: FacadeModule["normalizeAccountId"] = ((...args) => @@ -58,9 +81,88 @@ export const resolveExactLineGroupConfigKey: FacadeModule["resolveExactLineGroup )) as FacadeModule["resolveExactLineGroupConfigKey"]; export const resolveLineAccount: FacadeModule["resolveLineAccount"] = ((...args) => loadFacadeModule()["resolveLineAccount"](...args)) as FacadeModule["resolveLineAccount"]; -export type CardAction = import("@openclaw/line/runtime-api.js").CardAction; -export type LineChannelData = import("@openclaw/line/runtime-api.js").LineChannelData; -export type LineConfig = import("@openclaw/line/runtime-api.js").LineConfig; -export type LineProbeResult = import("@openclaw/line/runtime-api.js").LineProbeResult; -export type ListItem = import("@openclaw/line/runtime-api.js").ListItem; -export type ResolvedLineAccount = import("@openclaw/line/runtime-api.js").ResolvedLineAccount; +export type Action = Record; + +export interface ListItem { + title: string; + subtitle?: string; + action?: Action; +} + +export interface CardAction { + label: string; + action: Action; +} + +export interface LineThreadBindingsConfig { + enabled?: boolean; + idleHours?: number; + maxAgeHours?: number; + spawnSubagentSessions?: boolean; + spawnAcpSessions?: boolean; +} + +interface LineAccountBaseConfig { + enabled?: boolean; + channelAccessToken?: string; + channelSecret?: string; + tokenFile?: string; + secretFile?: string; + name?: string; + allowFrom?: Array; + groupAllowFrom?: Array; + dmPolicy?: "open" | "allowlist" | "pairing" | "disabled"; + groupPolicy?: "open" | "allowlist" | "disabled"; + responsePrefix?: string; + mediaMaxMb?: number; + webhookPath?: string; + threadBindings?: LineThreadBindingsConfig; + groups?: Record; +} + +export interface LineConfig extends LineAccountBaseConfig { + accounts?: Record; + defaultAccount?: string; +} + +export interface LineGroupConfig { + enabled?: boolean; + allowFrom?: Array; + requireMention?: boolean; + systemPrompt?: string; + skills?: string[]; +} + +export interface ResolvedLineAccount { + accountId: string; + name?: string; + enabled: boolean; + channelAccessToken: string; + channelSecret: string; + tokenSource: "config" | "env" | "file" | "none"; + config: LineConfig & LineAccountBaseConfig; +} + +export type LineProbeResult = BaseProbeResult & { + bot?: { + displayName?: string; + userId?: string; + basicId?: string; + pictureUrl?: string; + }; +}; + +export type LineChannelData = { + quickReplies?: string[]; + location?: { + title: string; + address: string; + latitude: number; + longitude: number; + }; + flexMessage?: { + altText: string; + contents: unknown; + }; + templateMessage?: unknown; +}; diff --git a/src/plugin-sdk/litellm.ts b/src/plugin-sdk/litellm.ts index bbb01bbecfe..7fcecf484b7 100644 --- a/src/plugin-sdk/litellm.ts +++ b/src/plugin-sdk/litellm.ts @@ -1,7 +1,16 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/litellm/api.js"); +import type { ModelDefinitionConfig, OpenClawConfig } from "../config/types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + applyLitellmConfig: (cfg: OpenClawConfig) => OpenClawConfig; + applyLitellmProviderConfig: (cfg: OpenClawConfig) => OpenClawConfig; + buildLitellmModelDefinition: () => ModelDefinitionConfig; + LITELLM_BASE_URL: string; + LITELLM_DEFAULT_MODEL_ID: string; + LITELLM_DEFAULT_MODEL_REF: string; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "litellm", diff --git a/src/plugin-sdk/lmstudio-runtime.ts b/src/plugin-sdk/lmstudio-runtime.ts index 10e743b8cff..99d0ed73192 100644 --- a/src/plugin-sdk/lmstudio-runtime.ts +++ b/src/plugin-sdk/lmstudio-runtime.ts @@ -1,7 +1,103 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/lmstudio/runtime-api.js"); +import type { + ModelDefinitionConfig, + ModelProviderConfig, + OpenClawConfig, +} from "../config/types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; +type LmstudioReasoningCapabilityWire = { + allowed_options?: unknown; + default?: unknown; +}; + +export type LmstudioModelWire = { + type?: "llm" | "embedding"; + key?: string; + display_name?: string; + max_context_length?: number; + format?: "gguf" | "mlx" | null; + capabilities?: { + vision?: boolean; + trained_for_tool_use?: boolean; + reasoning?: LmstudioReasoningCapabilityWire; + }; + loaded_instances?: Array<{ + id?: string; + config?: { + context_length?: number; + } | null; + } | null>; +}; + +export type LmstudioModelBase = { + id: string; + displayName: string; + format: "gguf" | "mlx" | null; + vision: boolean; + trainedForToolUse: boolean; + loaded: boolean; + reasoning: boolean; + input: ModelDefinitionConfig["input"]; + cost: ModelDefinitionConfig["cost"]; + contextWindow: number; + contextTokens: number; + maxTokens: number; +}; + +type FacadeModule = { + LMSTUDIO_DEFAULT_BASE_URL: string; + LMSTUDIO_DEFAULT_INFERENCE_BASE_URL: string; + LMSTUDIO_DEFAULT_EMBEDDING_MODEL: string; + LMSTUDIO_PROVIDER_LABEL: string; + LMSTUDIO_DEFAULT_API_KEY_ENV_VAR: string; + LMSTUDIO_LOCAL_API_KEY_PLACEHOLDER: string; + LMSTUDIO_MODEL_PLACEHOLDER: string; + LMSTUDIO_DEFAULT_LOAD_CONTEXT_LENGTH: number; + LMSTUDIO_DEFAULT_MODEL_ID: string; + LMSTUDIO_PROVIDER_ID: string; + resolveLmstudioReasoningCapability: (entry: Pick) => boolean; + resolveLoadedContextWindow: (entry: Pick) => number | null; + resolveLmstudioServerBase: (configuredBaseUrl?: string) => string; + resolveLmstudioInferenceBase: (configuredBaseUrl?: string) => string; + normalizeLmstudioProviderConfig: (provider: ModelProviderConfig) => ModelProviderConfig; + fetchLmstudioModels: (params?: { + baseUrl?: string; + apiKey?: string; + headers?: Record; + }) => Promise; + mapLmstudioWireEntry: (entry: LmstudioModelWire) => LmstudioModelBase | null; + discoverLmstudioModels: (params?: { + config?: OpenClawConfig; + baseUrl?: string; + apiKey?: string; + headers?: Record; + }) => Promise; + ensureLmstudioModelLoaded: (params: Record) => Promise; + buildLmstudioAuthHeaders: (params: { + apiKey?: string; + json?: boolean; + headers?: Record; + }) => Record | undefined; + resolveLmstudioConfiguredApiKey: (params: { + config?: OpenClawConfig; + env?: NodeJS.ProcessEnv; + path?: string; + }) => Promise; + resolveLmstudioProviderHeaders: (params: { + config?: OpenClawConfig; + env?: NodeJS.ProcessEnv; + headers?: unknown; + path?: string; + }) => Promise | undefined>; + resolveLmstudioRuntimeApiKey: (params: { + config?: OpenClawConfig; + agentDir?: string; + env?: NodeJS.ProcessEnv; + headers?: unknown; + }) => Promise; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "lmstudio", @@ -9,9 +105,6 @@ function loadFacadeModule(): FacadeModule { }); } -export type LmstudioModelWire = Parameters[0]; -export type LmstudioModelBase = Exclude, null>; - // Keep defaults inline so importing the runtime facade stays cold until a helper // is actually used. These values are part of the public LM Studio contract. export const LMSTUDIO_DEFAULT_BASE_URL: FacadeModule["LMSTUDIO_DEFAULT_BASE_URL"] = diff --git a/src/plugin-sdk/lmstudio.ts b/src/plugin-sdk/lmstudio.ts index 4b102b08606..e4224d5ebae 100644 --- a/src/plugin-sdk/lmstudio.ts +++ b/src/plugin-sdk/lmstudio.ts @@ -1,3 +1,13 @@ +import type { OpenClawConfig } from "../config/types.js"; +import type { + ProviderAuthMethodNonInteractiveContext, + ProviderAuthResult, + ProviderCatalogContext, + ProviderPrepareDynamicModelContext, + ProviderRuntimeModel, +} from "../plugins/types.js"; +import type { WizardPrompter } from "../wizard/prompts.js"; + export type { OpenClawPluginApi, ProviderAuthContext, @@ -8,7 +18,6 @@ export type { ProviderPrepareDynamicModelContext, ProviderRuntimeModel, } from "../plugins/types.js"; - export type { LmstudioModelBase, LmstudioModelWire } from "./lmstudio-runtime.js"; export { LMSTUDIO_DEFAULT_API_KEY_ENV_VAR, @@ -36,9 +45,37 @@ export { resolveLmstudioServerBase, } from "./lmstudio-runtime.js"; -type FacadeModule = typeof import("@openclaw/lmstudio/api.js"); import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; +type LmstudioInteractiveParams = { + config: OpenClawConfig; + prompter?: WizardPrompter; + secretInputMode?: unknown; + allowSecretRefPrompt?: boolean; + promptText?: (params: { + message: string; + initialValue?: string; + placeholder?: string; + validate?: (value: string | undefined) => string | undefined; + }) => Promise; + note?: (message: string, title?: string) => Promise | void; +}; + +type FacadeModule = { + promptAndConfigureLmstudioInteractive: ( + params: LmstudioInteractiveParams, + ) => Promise; + configureLmstudioNonInteractive: ( + ctx: ProviderAuthMethodNonInteractiveContext, + ) => Promise; + discoverLmstudioProvider: ( + ctx: ProviderCatalogContext, + ) => Promise<{ provider: import("../config/types.js").ModelProviderConfig } | null>; + prepareLmstudioDynamicModels: ( + ctx: ProviderPrepareDynamicModelContext, + ) => Promise; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "lmstudio", diff --git a/src/plugin-sdk/matrix-deps.ts b/src/plugin-sdk/matrix-deps.ts index d2ab4d44ef6..488998a3284 100644 --- a/src/plugin-sdk/matrix-deps.ts +++ b/src/plugin-sdk/matrix-deps.ts @@ -1,7 +1,15 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/matrix/runtime-api.js"); +import type { RuntimeEnv } from "../runtime.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + ensureMatrixSdkInstalled: (params: { + runtime: RuntimeEnv; + confirm?: (message: string) => Promise; + }) => Promise; + isMatrixSdkAvailable: () => boolean; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "matrix", diff --git a/src/plugin-sdk/matrix-helper.ts b/src/plugin-sdk/matrix-helper.ts index a9329feb379..9c2d8419e1a 100644 --- a/src/plugin-sdk/matrix-helper.ts +++ b/src/plugin-sdk/matrix-helper.ts @@ -1,7 +1,50 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/matrix/api.js"); +import type { OpenClawConfig } from "../config/config.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +export type MatrixScopedEnvVarNames = { + homeserver: string; + userId: string; + accessToken: string; + password: string; + deviceId: string; + deviceName: string; +}; + +export type MatrixAccountStorageRoot = { + rootDir: string; + accountKey: string; + tokenHash: string; +}; + +export type MatrixLegacyFlatStoragePaths = { + rootDir: string; + storagePath: string; + cryptoPath: string; +}; + +type FacadeModule = { + findMatrixAccountEntry: ( + cfg: OpenClawConfig, + accountId: string, + ) => Record | null; + getMatrixScopedEnvVarNames: (accountId: string) => MatrixScopedEnvVarNames; + requiresExplicitMatrixDefaultAccount: (cfg: OpenClawConfig, env?: NodeJS.ProcessEnv) => boolean; + resolveConfiguredMatrixAccountIds: (cfg: OpenClawConfig, env?: NodeJS.ProcessEnv) => string[]; + resolveMatrixAccountStorageRoot: (params: { + stateDir: string; + homeserver: string; + userId: string; + accessToken: string; + accountId?: string | null; + }) => MatrixAccountStorageRoot; + resolveMatrixChannelConfig: (cfg: OpenClawConfig) => Record | null; + resolveMatrixCredentialsDir: (stateDir: string) => string; + resolveMatrixCredentialsPath: (params: { stateDir: string; accountId?: string | null }) => string; + resolveMatrixDefaultOrOnlyAccountId: (cfg: OpenClawConfig, env?: NodeJS.ProcessEnv) => string; + resolveMatrixLegacyFlatStoragePaths: (stateDir: string) => MatrixLegacyFlatStoragePaths; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "matrix", diff --git a/src/plugin-sdk/matrix-runtime-surface.ts b/src/plugin-sdk/matrix-runtime-surface.ts index 6c70f278ffa..be75a2956a8 100644 --- a/src/plugin-sdk/matrix-runtime-surface.ts +++ b/src/plugin-sdk/matrix-runtime-surface.ts @@ -1,7 +1,30 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/matrix/runtime-api.js"); +import type { PluginRuntime } from "../plugins/runtime/types.js"; import { loadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; +export type MatrixResolvedStringField = + | "homeserver" + | "userId" + | "accessToken" + | "password" + | "deviceId" + | "deviceName"; + +export type MatrixResolvedStringValues = Record; + +type MatrixStringSourceMap = Partial>; + +type FacadeModule = { + resolveMatrixAccountStringValues: (params: { + accountId: string; + account?: MatrixStringSourceMap; + scopedEnv?: MatrixStringSourceMap; + channel?: MatrixStringSourceMap; + globalEnv?: MatrixStringSourceMap; + }) => MatrixResolvedStringValues; + setMatrixRuntime: (runtime: PluginRuntime) => void; +}; + function loadFacadeModule(): FacadeModule { return loadActivatedBundledPluginPublicSurfaceModuleSync({ dirName: "matrix", diff --git a/src/plugin-sdk/matrix-surface.ts b/src/plugin-sdk/matrix-surface.ts index ed4fa7d57ea..aac8a6266ab 100644 --- a/src/plugin-sdk/matrix-surface.ts +++ b/src/plugin-sdk/matrix-surface.ts @@ -1,10 +1,108 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/matrix/api.js"); +import type { + BindingTargetKind, + SessionBindingRecord, +} from "../infra/outbound/session-binding-service.js"; import { createLazyFacadeArrayValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +export type MatrixFacadeAuth = { + accountId: string; + homeserver: string; + userId: string; + accessToken: string; + password?: string; + deviceId?: string; + deviceName?: string; + initialSyncLimit?: number; + encryption?: boolean; + allowPrivateNetwork?: boolean; + ssrfPolicy?: unknown; + dispatcherPolicy?: unknown; +}; + +export type MatrixThreadBindingTargetKind = "subagent" | "acp"; + +export type MatrixThreadBindingRecord = { + accountId: string; + conversationId: string; + parentConversationId?: string; + targetKind: MatrixThreadBindingTargetKind; + targetSessionKey: string; + agentId?: string; + label?: string; + boundBy?: string; + boundAt: number; + lastActivityAt: number; + idleTimeoutMs?: number; + maxAgeMs?: number; +}; + +export type MatrixThreadBindingManager = { + accountId: string; + getIdleTimeoutMs: () => number; + getMaxAgeMs: () => number; + getByConversation: (params: { + conversationId: string; + parentConversationId?: string; + }) => MatrixThreadBindingRecord | undefined; + listBySessionKey: (targetSessionKey: string) => MatrixThreadBindingRecord[]; + listBindings: () => MatrixThreadBindingRecord[]; + touchBinding: (bindingId: string, at?: number) => MatrixThreadBindingRecord | null; + setIdleTimeoutBySessionKey: (params: { + targetSessionKey: string; + idleTimeoutMs: number; + }) => MatrixThreadBindingRecord[]; + setMaxAgeBySessionKey: (params: { + targetSessionKey: string; + maxAgeMs: number; + }) => MatrixThreadBindingRecord[]; + persist: () => Promise; + stop: () => void; +}; + +type MatrixThreadBindingManagerFactory = (params: { + accountId: string; + auth: MatrixFacadeAuth; + client: unknown; + env?: NodeJS.ProcessEnv; + stateDir?: string; + idleTimeoutMs: number; + maxAgeMs: number; + enableSweeper?: boolean; + logVerboseMessage?: (message: string) => void; +}) => Promise; + +type FacadeModule = { + createMatrixThreadBindingManager: MatrixThreadBindingManagerFactory; + matrixSessionBindingAdapterChannels: readonly ["matrix"]; + resetMatrixThreadBindingsForTests: () => void; +}; + +export type MatrixSessionBindingTimeoutParams = { + accountId: string; + targetSessionKey: string; + idleTimeoutMs: number; +}; + +export type MatrixSessionBindingMaxAgeParams = { + accountId: string; + targetSessionKey: string; + maxAgeMs: number; +}; + +export type MatrixSessionBindingTimeoutSetter = ( + params: MatrixSessionBindingTimeoutParams, +) => SessionBindingRecord[]; + +export type MatrixSessionBindingMaxAgeSetter = ( + params: MatrixSessionBindingMaxAgeParams, +) => SessionBindingRecord[]; + +export type MatrixSessionBindingTargetKind = BindingTargetKind; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "matrix", diff --git a/src/plugin-sdk/matrix-thread-bindings.ts b/src/plugin-sdk/matrix-thread-bindings.ts index 6e453e58917..1c0ec479bca 100644 --- a/src/plugin-sdk/matrix-thread-bindings.ts +++ b/src/plugin-sdk/matrix-thread-bindings.ts @@ -1,7 +1,20 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/matrix/api.js"); +import type { SessionBindingRecord } from "../infra/outbound/session-binding-service.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + setMatrixThreadBindingIdleTimeoutBySessionKey: (params: { + accountId: string; + targetSessionKey: string; + idleTimeoutMs: number; + }) => SessionBindingRecord[]; + setMatrixThreadBindingMaxAgeBySessionKey: (params: { + accountId: string; + targetSessionKey: string; + maxAgeMs: number; + }) => SessionBindingRecord[]; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "matrix", diff --git a/src/plugin-sdk/matrix.ts b/src/plugin-sdk/matrix.ts index e63901659db..d5915c9538a 100644 --- a/src/plugin-sdk/matrix.ts +++ b/src/plugin-sdk/matrix.ts @@ -7,7 +7,11 @@ import { loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; -type MatrixFacadeModule = typeof import("@openclaw/matrix/contract-api.js"); +type MatrixFacadeModule = { + singleAccountKeysToMove: readonly string[]; + namedAccountPromotionKeys: readonly string[]; + resolveSingleAccountPromotionTarget: (params: { channel: Record }) => string; +}; function loadMatrixFacadeModule(): MatrixFacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ diff --git a/src/plugin-sdk/memory-core-bundled-runtime.ts b/src/plugin-sdk/memory-core-bundled-runtime.ts index aa73f399120..9d7324871f2 100644 --- a/src/plugin-sdk/memory-core-bundled-runtime.ts +++ b/src/plugin-sdk/memory-core-bundled-runtime.ts @@ -1,7 +1,96 @@ -// Manual facade. Keep loader boundary explicit. -type ApiFacadeModule = typeof import("@openclaw/memory-core/api.js"); -type RuntimeFacadeModule = typeof import("@openclaw/memory-core/runtime-api.js"); import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +// Manual facade. Keep loader boundary explicit. +import type { + MemoryEmbeddingProvider, + MemoryEmbeddingProviderAdapter, + MemoryEmbeddingProviderCreateOptions, + MemoryEmbeddingProviderRuntime, +} from "./memory-core-host-engine-embeddings.js"; + +type EmbeddingProviderResult = { + provider: MemoryEmbeddingProvider | null; + requestedProvider: string; + fallbackFrom?: string; + fallbackReason?: string; + providerUnavailableReason?: string; + runtime?: MemoryEmbeddingProviderRuntime; +}; + +type RuntimeFacadeModule = { + createEmbeddingProvider: ( + options: MemoryEmbeddingProviderCreateOptions & { + provider: string; + fallback: string; + }, + ) => Promise; + registerBuiltInMemoryEmbeddingProviders: (register: { + registerMemoryEmbeddingProvider: (adapter: MemoryEmbeddingProviderAdapter) => void; + }) => void; + removeGroundedShortTermCandidates: (params: { + workspaceDir: string; + }) => Promise<{ removed: number; storePath: string }>; + repairDreamingArtifacts: (params: { + workspaceDir: string; + archiveDiary?: boolean; + now?: Date; + }) => Promise; +}; + +type GroundedRemPreviewItem = { + text: string; + refs: string[]; +}; + +type GroundedRemCandidate = GroundedRemPreviewItem & { + lean: "likely_durable" | "unclear" | "likely_situational"; +}; + +type GroundedRemFilePreview = { + path: string; + facts: GroundedRemPreviewItem[]; + reflections: GroundedRemPreviewItem[]; + memoryImplications: GroundedRemPreviewItem[]; + candidates: GroundedRemCandidate[]; + renderedMarkdown: string; +}; + +type GroundedRemPreviewResult = { + workspaceDir: string; + scannedFiles: number; + files: GroundedRemFilePreview[]; +}; + +type ApiFacadeModule = { + previewGroundedRemMarkdown: (params: { + workspaceDir: string; + inputPaths: string[]; + }) => Promise; + dedupeDreamDiaryEntries: (params: { + workspaceDir: string; + }) => Promise<{ dreamsPath: string; removed: number; kept: number }>; + writeBackfillDiaryEntries: (params: { + workspaceDir: string; + entries: Array<{ + isoDay: string; + bodyLines: string[]; + sourcePath?: string; + }>; + timezone?: string; + }) => Promise<{ dreamsPath: string; written: number; replaced: number }>; + removeBackfillDiaryEntries: (params: { + workspaceDir: string; + }) => Promise<{ dreamsPath: string; removed: number }>; +}; + +type RepairDreamingArtifactsResult = { + changed: boolean; + archiveDir?: string; + archivedDreamsDiary: boolean; + archivedSessionCorpus: boolean; + archivedSessionIngestion: boolean; + archivedPaths: string[]; + warnings: string[]; +}; function loadApiFacadeModule(): ApiFacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ diff --git a/src/plugin-sdk/memory-core-engine-runtime.ts b/src/plugin-sdk/memory-core-engine-runtime.ts index 603b993e608..3756f49accc 100644 --- a/src/plugin-sdk/memory-core-engine-runtime.ts +++ b/src/plugin-sdk/memory-core-engine-runtime.ts @@ -1,9 +1,135 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/memory-core/runtime-api.js"); +import type { OpenClawConfig } from "../config/types.js"; import { createLazyFacadeObjectValue, loadActivatedBundledPluginPublicSurfaceModuleSync, } from "./facade-runtime.js"; +import type { MemorySearchManager } from "./memory-core-host-engine-storage.js"; + +export type BuiltinMemoryEmbeddingProviderDoctorMetadata = { + providerId: string; + authProviderId: string; + envVars: string[]; + transport: "local" | "remote"; + autoSelectPriority?: number; +}; + +export type DreamingArtifactsAuditIssue = { + severity: "warn" | "error"; + code: + | "dreaming-session-corpus-unreadable" + | "dreaming-session-corpus-self-ingested" + | "dreaming-session-ingestion-unreadable" + | "dreaming-diary-unreadable"; + message: string; + fixable: boolean; +}; + +export type DreamingArtifactsAuditSummary = { + dreamsPath?: string; + sessionCorpusDir: string; + sessionCorpusFileCount: number; + suspiciousSessionCorpusFileCount: number; + suspiciousSessionCorpusLineCount: number; + sessionIngestionPath: string; + sessionIngestionExists: boolean; + issues: DreamingArtifactsAuditIssue[]; +}; + +export type RepairDreamingArtifactsResult = { + changed: boolean; + archiveDir?: string; + archivedDreamsDiary: boolean; + archivedSessionCorpus: boolean; + archivedSessionIngestion: boolean; + archivedPaths: string[]; + warnings: string[]; +}; + +export type ShortTermAuditIssue = { + severity: "warn" | "error"; + code: + | "recall-store-unreadable" + | "recall-store-empty" + | "recall-store-invalid" + | "recall-lock-stale" + | "recall-lock-unreadable" + | "qmd-index-missing" + | "qmd-index-empty" + | "qmd-collections-empty"; + message: string; + fixable: boolean; +}; + +export type ShortTermAuditSummary = { + storePath: string; + lockPath: string; + updatedAt?: string; + exists: boolean; + entryCount: number; + promotedCount: number; + spacedEntryCount: number; + conceptTaggedEntryCount: number; + conceptTagScripts?: Record; + invalidEntryCount: number; + issues: ShortTermAuditIssue[]; + qmd?: + | { + dbPath?: string; + collections?: number; + dbBytes?: number; + } + | undefined; +}; + +export type RepairShortTermPromotionArtifactsResult = { + changed: boolean; + removedInvalidEntries: number; + rewroteStore: boolean; + removedStaleLock: boolean; +}; + +type MemoryIndexManagerFacade = { + get(params: { + cfg: OpenClawConfig; + agentId: string; + purpose?: "default" | "status"; + }): Promise; +}; + +type FacadeModule = { + auditShortTermPromotionArtifacts: (params: { + workspaceDir: string; + qmd?: { + dbPath?: string; + collections?: number; + }; + }) => Promise; + auditDreamingArtifacts: (params: { + workspaceDir: string; + }) => Promise; + getBuiltinMemoryEmbeddingProviderDoctorMetadata: ( + providerId: string, + ) => BuiltinMemoryEmbeddingProviderDoctorMetadata | null; + getMemorySearchManager: (params: { + cfg: OpenClawConfig; + agentId: string; + purpose?: "default" | "status"; + }) => Promise<{ + manager: MemorySearchManager | null; + error?: string; + }>; + listBuiltinAutoSelectMemoryEmbeddingProviderDoctorMetadata: () => Array; + MemoryIndexManager: MemoryIndexManagerFacade; + repairShortTermPromotionArtifacts: (params: { + workspaceDir: string; + }) => Promise; + repairDreamingArtifacts: (params: { + workspaceDir: string; + archiveDiary?: boolean; + now?: Date; + }) => Promise; +}; function loadFacadeModule(): FacadeModule { return loadActivatedBundledPluginPublicSurfaceModuleSync({ @@ -43,13 +169,3 @@ export const repairDreamingArtifacts: FacadeModule["repairDreamingArtifacts"] = loadFacadeModule()["repairDreamingArtifacts"]( ...args, )) as FacadeModule["repairDreamingArtifacts"]; -export type BuiltinMemoryEmbeddingProviderDoctorMetadata = - import("@openclaw/memory-core/runtime-api.js").BuiltinMemoryEmbeddingProviderDoctorMetadata; -export type DreamingArtifactsAuditSummary = - import("@openclaw/memory-core/runtime-api.js").DreamingArtifactsAuditSummary; -export type RepairDreamingArtifactsResult = - import("@openclaw/memory-core/runtime-api.js").RepairDreamingArtifactsResult; -export type RepairShortTermPromotionArtifactsResult = - import("@openclaw/memory-core/runtime-api.js").RepairShortTermPromotionArtifactsResult; -export type ShortTermAuditSummary = - import("@openclaw/memory-core/runtime-api.js").ShortTermAuditSummary; diff --git a/src/plugin-sdk/openrouter.ts b/src/plugin-sdk/openrouter.ts index 6828e99119b..09ebe6ad91e 100644 --- a/src/plugin-sdk/openrouter.ts +++ b/src/plugin-sdk/openrouter.ts @@ -1,7 +1,14 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/openrouter/api.js"); +import type { ModelProviderConfig, OpenClawConfig } from "../config/types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + applyOpenrouterConfig: (cfg: OpenClawConfig) => OpenClawConfig; + applyOpenrouterProviderConfig: (cfg: OpenClawConfig) => OpenClawConfig; + buildOpenrouterProvider: () => ModelProviderConfig; + OPENROUTER_DEFAULT_MODEL_REF: string; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "openrouter", diff --git a/src/plugin-sdk/qa-channel.ts b/src/plugin-sdk/qa-channel.ts index 613545cda4a..e6a9ac293c9 100644 --- a/src/plugin-sdk/qa-channel.ts +++ b/src/plugin-sdk/qa-channel.ts @@ -1,10 +1,256 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/qa-channel/api.js"); +import type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +export type QaBusConversationKind = "direct" | "channel"; + +export type QaBusConversation = { + id: string; + kind: QaBusConversationKind; + title?: string; +}; + +export type QaBusAttachment = { + id: string; + kind: "image" | "video" | "audio" | "file"; + mimeType: string; + fileName?: string; + inline?: boolean; + url?: string; + contentBase64?: string; + width?: number; + height?: number; + durationMs?: number; + altText?: string; + transcript?: string; +}; + +export type QaBusMessage = { + id: string; + accountId: string; + direction: "inbound" | "outbound"; + conversation: QaBusConversation; + senderId: string; + senderName?: string; + text: string; + timestamp: number; + threadId?: string; + threadTitle?: string; + replyToId?: string; + deleted?: boolean; + editedAt?: number; + attachments?: QaBusAttachment[]; + reactions: Array<{ + emoji: string; + senderId: string; + timestamp: number; + }>; +}; + +export type QaBusThread = { + id: string; + accountId: string; + conversationId: string; + title: string; + createdAt: number; + createdBy: string; +}; + +export type QaBusEvent = + | { cursor: number; kind: "inbound-message"; accountId: string; message: QaBusMessage } + | { cursor: number; kind: "outbound-message"; accountId: string; message: QaBusMessage } + | { cursor: number; kind: "thread-created"; accountId: string; thread: QaBusThread } + | { cursor: number; kind: "message-edited"; accountId: string; message: QaBusMessage } + | { cursor: number; kind: "message-deleted"; accountId: string; message: QaBusMessage } + | { + cursor: number; + kind: "reaction-added"; + accountId: string; + message: QaBusMessage; + emoji: string; + senderId: string; + }; + +export type QaBusInboundMessageInput = { + accountId?: string; + conversation: QaBusConversation; + senderId: string; + senderName?: string; + text: string; + timestamp?: number; + threadId?: string; + threadTitle?: string; + replyToId?: string; + attachments?: QaBusAttachment[]; +}; + +export type QaBusOutboundMessageInput = { + accountId?: string; + to: string; + senderId?: string; + senderName?: string; + text: string; + timestamp?: number; + threadId?: string; + replyToId?: string; + attachments?: QaBusAttachment[]; +}; + +export type QaBusCreateThreadInput = { + accountId?: string; + conversationId: string; + title: string; + createdBy?: string; + timestamp?: number; +}; + +export type QaBusReactToMessageInput = { + accountId?: string; + messageId: string; + emoji: string; + senderId?: string; + timestamp?: number; +}; + +export type QaBusEditMessageInput = { + accountId?: string; + messageId: string; + text: string; + timestamp?: number; +}; + +export type QaBusDeleteMessageInput = { + accountId?: string; + messageId: string; + timestamp?: number; +}; + +export type QaBusSearchMessagesInput = { + accountId?: string; + query?: string; + conversationId?: string; + threadId?: string; + limit?: number; +}; + +export type QaBusReadMessageInput = { + accountId?: string; + messageId: string; +}; + +export type QaBusPollInput = { + accountId?: string; + cursor?: number; + timeoutMs?: number; + limit?: number; +}; + +export type QaBusPollResult = { + cursor: number; + events: QaBusEvent[]; +}; + +export type QaBusStateSnapshot = { + cursor: number; + conversations: QaBusConversation[]; + threads: QaBusThread[]; + messages: QaBusMessage[]; + events: QaBusEvent[]; +}; + +export type QaBusWaitForInput = + | { + timeoutMs?: number; + kind: "event-kind"; + eventKind: QaBusEvent["kind"]; + } + | { + timeoutMs?: number; + kind: "message-text"; + textIncludes: string; + direction?: QaBusMessage["direction"]; + } + | { + timeoutMs?: number; + kind: "thread-id"; + threadId: string; + }; + +type QaTargetParts = { + chatType: "direct" | "channel"; + conversationId: string; + threadId?: string; +}; + +type FacadeModule = { + buildQaTarget: (params: QaTargetParts & { threadId?: string | null }) => string; + formatQaTarget: (params: QaTargetParts & { threadId?: string | null }) => string; + createQaBusThread: (params: { + baseUrl: string; + accountId: string; + conversationId: string; + title: string; + createdBy?: string; + }) => Promise<{ thread: QaBusThread }>; + deleteQaBusMessage: (params: { + baseUrl: string; + accountId: string; + messageId: string; + }) => Promise<{ message: QaBusMessage }>; + editQaBusMessage: (params: { + baseUrl: string; + accountId: string; + messageId: string; + text: string; + }) => Promise<{ message: QaBusMessage }>; + getQaBusState: (baseUrl: string) => Promise; + injectQaBusInboundMessage: (params: { + baseUrl: string; + input: QaBusInboundMessageInput; + }) => Promise<{ message: QaBusMessage }>; + normalizeQaTarget: (raw: string) => string | undefined; + parseQaTarget: (raw: string) => QaTargetParts; + pollQaBus: (params: { + baseUrl: string; + accountId: string; + cursor: number; + timeoutMs: number; + signal?: AbortSignal; + }) => Promise; + qaChannelPlugin: ChannelPlugin; + reactToQaBusMessage: (params: { + baseUrl: string; + accountId: string; + messageId: string; + emoji: string; + senderId?: string; + }) => Promise<{ message: QaBusMessage }>; + readQaBusMessage: (params: { + baseUrl: string; + accountId: string; + messageId: string; + }) => Promise<{ message: QaBusMessage }>; + searchQaBusMessages: (params: { + baseUrl: string; + input: QaBusSearchMessagesInput; + }) => Promise<{ messages: QaBusMessage[] }>; + sendQaBusMessage: (params: { + baseUrl: string; + accountId: string; + to: string; + text: string; + senderId?: string; + senderName?: string; + threadId?: string; + replyToId?: string; + attachments?: QaBusAttachment[]; + }) => Promise<{ message: QaBusMessage }>; + setQaChannelRuntime: (runtime: unknown) => void; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "qa-channel", @@ -62,26 +308,3 @@ export const sendQaBusMessage: FacadeModule["sendQaBusMessage"] = ((...args) => export const setQaChannelRuntime: FacadeModule["setQaChannelRuntime"] = ((...args) => loadFacadeModule().setQaChannelRuntime(...args)) as FacadeModule["setQaChannelRuntime"]; - -export type QaBusAttachment = import("@openclaw/qa-channel/api.js").QaBusAttachment; -export type QaBusConversation = import("@openclaw/qa-channel/api.js").QaBusConversation; -export type QaBusConversationKind = import("@openclaw/qa-channel/api.js").QaBusConversationKind; -export type QaBusCreateThreadInput = import("@openclaw/qa-channel/api.js").QaBusCreateThreadInput; -export type QaBusDeleteMessageInput = import("@openclaw/qa-channel/api.js").QaBusDeleteMessageInput; -export type QaBusEditMessageInput = import("@openclaw/qa-channel/api.js").QaBusEditMessageInput; -export type QaBusEvent = import("@openclaw/qa-channel/api.js").QaBusEvent; -export type QaBusInboundMessageInput = - import("@openclaw/qa-channel/api.js").QaBusInboundMessageInput; -export type QaBusMessage = import("@openclaw/qa-channel/api.js").QaBusMessage; -export type QaBusOutboundMessageInput = - import("@openclaw/qa-channel/api.js").QaBusOutboundMessageInput; -export type QaBusPollInput = import("@openclaw/qa-channel/api.js").QaBusPollInput; -export type QaBusPollResult = import("@openclaw/qa-channel/api.js").QaBusPollResult; -export type QaBusReactToMessageInput = - import("@openclaw/qa-channel/api.js").QaBusReactToMessageInput; -export type QaBusReadMessageInput = import("@openclaw/qa-channel/api.js").QaBusReadMessageInput; -export type QaBusSearchMessagesInput = - import("@openclaw/qa-channel/api.js").QaBusSearchMessagesInput; -export type QaBusStateSnapshot = import("@openclaw/qa-channel/api.js").QaBusStateSnapshot; -export type QaBusThread = import("@openclaw/qa-channel/api.js").QaBusThread; -export type QaBusWaitForInput = import("@openclaw/qa-channel/api.js").QaBusWaitForInput; diff --git a/src/plugin-sdk/synology-chat.ts b/src/plugin-sdk/synology-chat.ts index 33cdfccb207..4447ee7110b 100644 --- a/src/plugin-sdk/synology-chat.ts +++ b/src/plugin-sdk/synology-chat.ts @@ -1,7 +1,19 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/synology-chat/contract-api.js"); +import type { SecurityAuditFinding } from "../security/audit.types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + collectSynologyChatSecurityAuditFindings: (params: { + accountId?: string | null; + account: { + accountId?: string; + dangerouslyAllowNameMatching?: boolean; + }; + orderedAccountIds: string[]; + hasExplicitAccountPath: boolean; + }) => SecurityAuditFinding[]; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "synology-chat", diff --git a/src/plugin-sdk/vercel-ai-gateway.ts b/src/plugin-sdk/vercel-ai-gateway.ts index 0b2edbbf0a8..f7740af6553 100644 --- a/src/plugin-sdk/vercel-ai-gateway.ts +++ b/src/plugin-sdk/vercel-ai-gateway.ts @@ -1,10 +1,25 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/vercel-ai-gateway/api.js"); +import type { ModelDefinitionConfig, ModelProviderConfig } from "../config/types.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +type ModelCost = ModelDefinitionConfig["cost"]; + +type FacadeModule = { + buildVercelAiGatewayProvider: () => Promise; + discoverVercelAiGatewayModels: () => Promise; + getStaticVercelAiGatewayModelCatalog: () => ModelDefinitionConfig[]; + VERCEL_AI_GATEWAY_BASE_URL: string; + VERCEL_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW: number; + VERCEL_AI_GATEWAY_DEFAULT_COST: ModelCost; + VERCEL_AI_GATEWAY_DEFAULT_MAX_TOKENS: number; + VERCEL_AI_GATEWAY_DEFAULT_MODEL_ID: string; + VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF: string; + VERCEL_AI_GATEWAY_PROVIDER_ID: string; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "vercel-ai-gateway", diff --git a/src/plugin-sdk/xiaomi.ts b/src/plugin-sdk/xiaomi.ts index b9a40f1335c..40070f49f3f 100644 --- a/src/plugin-sdk/xiaomi.ts +++ b/src/plugin-sdk/xiaomi.ts @@ -1,7 +1,15 @@ // Manual facade. Keep loader boundary explicit. -type FacadeModule = typeof import("@openclaw/xiaomi/api.js"); +import type { ModelProviderConfig, OpenClawConfig } from "../config/types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + applyXiaomiConfig: (cfg: OpenClawConfig) => OpenClawConfig; + applyXiaomiProviderConfig: (cfg: OpenClawConfig) => OpenClawConfig; + buildXiaomiProvider: () => ModelProviderConfig; + XIAOMI_DEFAULT_MODEL_ID: string; + XIAOMI_DEFAULT_MODEL_REF: string; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "xiaomi", diff --git a/src/plugin-sdk/zalo-setup.ts b/src/plugin-sdk/zalo-setup.ts index 8912c285c2b..165e6052027 100644 --- a/src/plugin-sdk/zalo-setup.ts +++ b/src/plugin-sdk/zalo-setup.ts @@ -1,10 +1,37 @@ // Manual facade. Keep loader boundaries explicit and narrow. -type SetupFacadeModule = typeof import("@openclaw/zalo/setup-api.js"); -type GroupAccessFacadeModule = typeof import("@openclaw/zalo/contract-api.js"); +import type { ChannelSetupWizard } from "../channels/plugins/setup-wizard-types.js"; +import type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js"; +import type { GroupPolicy } from "../config/types.base.js"; import { createLazyFacadeObjectValue, loadBundledPluginPublicSurfaceModuleSync, } from "./facade-loader.js"; +import type { SenderGroupAccessDecision } from "./group-access.js"; + +type ZaloRuntimeGroupPolicyResult = { + groupPolicy: GroupPolicy; + providerMissingFallbackApplied: boolean; +}; + +type SetupFacadeModule = { + zaloSetupAdapter: ChannelSetupAdapter; + zaloSetupWizard: ChannelSetupWizard; +}; + +type GroupAccessFacadeModule = { + evaluateZaloGroupAccess: (params: { + providerConfigPresent: boolean; + configuredGroupPolicy?: GroupPolicy; + defaultGroupPolicy?: GroupPolicy; + groupAllowFrom: string[]; + senderId: string; + }) => SenderGroupAccessDecision; + resolveZaloRuntimeGroupPolicy: (params: { + providerConfigPresent: boolean; + groupPolicy?: GroupPolicy; + defaultGroupPolicy?: GroupPolicy; + }) => ZaloRuntimeGroupPolicyResult; +}; function loadSetupFacadeModule(): SetupFacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ diff --git a/src/plugin-sdk/zalouser.ts b/src/plugin-sdk/zalouser.ts index 9bd997fac31..c476090fcff 100644 --- a/src/plugin-sdk/zalouser.ts +++ b/src/plugin-sdk/zalouser.ts @@ -82,9 +82,24 @@ export { formatResolvedUnresolvedNote } from "./resolution-notes.js"; export { buildBaseAccountStatusSnapshot } from "./status-helpers.js"; export { chunkTextForOutbound } from "./text-chunking.js"; -type FacadeModule = typeof import("@openclaw/zalouser/contract-api.js"); +import type { SecurityAuditFinding } from "../security/audit.types.js"; import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-loader.js"; +type FacadeModule = { + collectZalouserSecurityAuditFindings: (params: { + accountId?: string | null; + account: { + accountId?: string; + config?: { + groups?: Record; + dangerouslyAllowNameMatching?: boolean; + }; + }; + orderedAccountIds: string[]; + hasExplicitAccountPath: boolean; + }) => SecurityAuditFinding[]; +}; + function loadFacadeModule(): FacadeModule { return loadBundledPluginPublicSurfaceModuleSync({ dirName: "zalouser", diff --git a/src/plugins/contracts/provider-vitest-registry.ts b/src/plugins/contracts/provider-vitest-registry.ts index 75e48540785..061a786be10 100644 --- a/src/plugins/contracts/provider-vitest-registry.ts +++ b/src/plugins/contracts/provider-vitest-registry.ts @@ -8,9 +8,12 @@ export type ProviderContractEntry = { let providerContractRegistryCache: ProviderContractEntry[] | null = null; -type AnthropicApiSurface = typeof import("../../../extensions/anthropic/api.js"); -type GoogleApiSurface = typeof import("../../../extensions/google/api.js"); -type OpenAIApiSurface = typeof import("../../../extensions/openai/api.js"); +type ProviderApiSurface = Record ProviderPlugin>; +type AnthropicApiSurface = ProviderApiSurface<"buildAnthropicProvider">; +type GoogleApiSurface = ProviderApiSurface<"buildGoogleProvider" | "buildGoogleGeminiCliProvider">; +type OpenAIApiSurface = ProviderApiSurface< + "buildOpenAIProvider" | "buildOpenAICodexProviderPlugin" +>; export function loadVitestProviderContractRegistry(): ProviderContractEntry[] { const anthropicApi = loadBundledPluginApiSync("anthropic"); diff --git a/src/plugins/contracts/web-provider-vitest-registry.ts b/src/plugins/contracts/web-provider-vitest-registry.ts index 501b62eb12a..416513ba520 100644 --- a/src/plugins/contracts/web-provider-vitest-registry.ts +++ b/src/plugins/contracts/web-provider-vitest-registry.ts @@ -9,8 +9,9 @@ export type WebSearchProviderContractEntry = { let webSearchProviderContractRegistryCache: WebSearchProviderContractEntry[] | null = null; -type GoogleWebSearchContractApiSurface = - typeof import("../../../extensions/google/web-search-contract-api.js"); +type GoogleWebSearchContractApiSurface = { + createGeminiWebSearchProvider: () => WebSearchProviderPlugin; +}; export function loadVitestWebSearchProviderContractRegistry(): WebSearchProviderContractEntry[] { const googleWebSearchContractApi = diff --git a/src/security/audit-channel-discord-command-findings.test.ts b/src/security/audit-channel-discord-command-findings.test.ts index c438b6d1789..0744a39c50d 100644 --- a/src/security/audit-channel-discord-command-findings.test.ts +++ b/src/security/audit-channel-discord-command-findings.test.ts @@ -53,7 +53,7 @@ describe("security audit discord command findings", () => { discord: DiscordAccountConfig; }; }, - account: createDiscordAccount(cfg.channels!.discord!), + account: createDiscordAccount(cfg.channels!.discord), accountId: "default", orderedAccountIds: ["default"], hasExplicitAccountPath: false, diff --git a/test/helpers/channels/channel-media-roots-contract.ts b/test/helpers/channels/channel-media-roots-contract.ts index ca03c65a31d..33378e6cd4f 100644 --- a/test/helpers/channels/channel-media-roots-contract.ts +++ b/test/helpers/channels/channel-media-roots-contract.ts @@ -1,6 +1,10 @@ import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type IMessageContractSurface = typeof import("@openclaw/imessage/contract-api.js"); +type IMessageContractSurface = { + DEFAULT_IMESSAGE_ATTACHMENT_ROOTS: string[]; + resolveIMessageAttachmentRoots: (params: unknown) => string[]; + resolveIMessageRemoteAttachmentRoots: (params: unknown) => string[]; +}; const { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, diff --git a/test/helpers/channels/command-contract.ts b/test/helpers/channels/command-contract.ts index b1d33001818..f77b3883449 100644 --- a/test/helpers/channels/command-contract.ts +++ b/test/helpers/channels/command-contract.ts @@ -3,11 +3,14 @@ import { loadBundledPluginContractApiSync, } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type TelegramContractSurface = typeof import("@openclaw/telegram/contract-api.js"); -type WhatsAppApiSurface = Pick< - typeof import("@openclaw/whatsapp/api.js"), - "isWhatsAppGroupJid" | "normalizeWhatsAppTarget" | "whatsappCommandPolicy" ->; +type TelegramContractSurface = { + buildTelegramModelsProviderChannelData: (...args: unknown[]) => unknown; +}; +type WhatsAppApiSurface = { + isWhatsAppGroupJid: (...args: unknown[]) => boolean; + normalizeWhatsAppTarget: (...args: unknown[]) => string | null; + whatsappCommandPolicy: Record; +}; let telegramContractSurface: TelegramContractSurface | undefined; let whatsappApiSurface: WhatsAppApiSurface | undefined; diff --git a/test/helpers/channels/dm-policy-contract.ts b/test/helpers/channels/dm-policy-contract.ts index 5f34da9ea40..81a6da6d594 100644 --- a/test/helpers/channels/dm-policy-contract.ts +++ b/test/helpers/channels/dm-policy-contract.ts @@ -1,10 +1,16 @@ -import type { SignalSender } from "@openclaw/signal/contract-api.js"; import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type SignalContractApiSurface = Pick< - typeof import("@openclaw/signal/contract-api.js"), - "isSignalSenderAllowed" ->; +export type SignalSender = { + kind: string; + raw: string; + e164?: string; + uuid?: string; + username?: string; +}; + +type SignalContractApiSurface = { + isSignalSenderAllowed: (...args: unknown[]) => boolean; +}; let signalContractSurface: Promise | undefined; @@ -18,4 +24,3 @@ export function getSignalContractSurface(): Promise { ) as Promise; return signalContractSurface; } -export type { SignalSender }; diff --git a/test/helpers/channels/inbound-contract.slack.ts b/test/helpers/channels/inbound-contract.slack.ts index a6a6ce72bfe..cf3340dbbea 100644 --- a/test/helpers/channels/inbound-contract.slack.ts +++ b/test/helpers/channels/inbound-contract.slack.ts @@ -5,7 +5,21 @@ import type { OpenClawConfig } from "../../../src/config/config.js"; import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; import { withTempHome } from "../temp-home.js"; -type ResolvedSlackAccount = import("@openclaw/slack/api.js").ResolvedSlackAccount; +type ResolvedSlackAccount = { + accountId: string; + enabled: boolean; + botTokenSource: string; + appTokenSource: string; + userTokenSource: string; + config: { + replyToMode?: unknown; + replyToModeByChatType?: unknown; + dm?: unknown; + }; + replyToMode?: unknown; + replyToModeByChatType?: unknown; + dm?: unknown; +}; type SlackMessageEvent = { channel: string; diff --git a/test/helpers/channels/interactive-contract.ts b/test/helpers/channels/interactive-contract.ts index 414c75f8728..f4fe4a41692 100644 --- a/test/helpers/channels/interactive-contract.ts +++ b/test/helpers/channels/interactive-contract.ts @@ -1,12 +1,78 @@ -export type { - DiscordInteractiveHandlerContext, - DiscordInteractiveHandlerRegistration, -} from "@openclaw/discord/contract-api.js"; -export type { - SlackInteractiveHandlerContext, - SlackInteractiveHandlerRegistration, -} from "@openclaw/slack/contract-api.js"; -export type { - TelegramInteractiveHandlerContext, - TelegramInteractiveHandlerRegistration, -} from "@openclaw/telegram/contract-api.js"; +type ConversationBindingHelpers = { + requestConversationBinding: (...args: unknown[]) => unknown; + detachConversationBinding: (...args: unknown[]) => unknown; + getCurrentConversationBinding: (...args: unknown[]) => unknown; +}; + +type InteractiveHandlerRegistration< + TChannel extends string, + TContext, +> = ConversationBindingHelpers & { + channel: TChannel; + namespace: string; + handler: (ctx: TContext) => unknown; +}; + +type BaseInteractiveContext = ConversationBindingHelpers & { + channel: TChannel; + accountId: string; + conversationId: string; + parentConversationId?: string; + senderId: string; + senderUsername?: string; + auth?: unknown; +}; + +export type TelegramInteractiveHandlerContext = BaseInteractiveContext<"telegram"> & { + callbackId: string; + senderUsername?: string; + threadId?: number; + isGroup?: boolean; + isForum?: boolean; + callback: { + data: string; + namespace: string; + payload: string; + messageId: number; + chatId: string; + messageText?: string; + }; + respond: Record unknown>; +}; + +export type DiscordInteractiveHandlerContext = BaseInteractiveContext<"discord"> & { + interactionId: string; + guildId?: string; + interaction: { + data: string; + namespace: string; + payload: string; + [key: string]: unknown; + }; + respond: Record unknown>; +}; + +export type SlackInteractiveHandlerContext = BaseInteractiveContext<"slack"> & { + interactionId: string; + threadId?: string; + interaction: { + data: string; + namespace: string; + payload: string; + [key: string]: unknown; + }; + respond: Record unknown>; +}; + +export type TelegramInteractiveHandlerRegistration = InteractiveHandlerRegistration< + "telegram", + TelegramInteractiveHandlerContext +>; +export type DiscordInteractiveHandlerRegistration = InteractiveHandlerRegistration< + "discord", + DiscordInteractiveHandlerContext +>; +export type SlackInteractiveHandlerRegistration = InteractiveHandlerRegistration< + "slack", + SlackInteractiveHandlerContext +>; diff --git a/test/helpers/channels/matrix-setup-contract.ts b/test/helpers/channels/matrix-setup-contract.ts index 9e229fc7970..c6c4c8b7d95 100644 --- a/test/helpers/channels/matrix-setup-contract.ts +++ b/test/helpers/channels/matrix-setup-contract.ts @@ -1,6 +1,9 @@ import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type MatrixContractSurface = typeof import("@openclaw/matrix/contract-api.js"); +type MatrixContractSurface = { + matrixSetupAdapter: Record; + matrixSetupWizard: Record; +}; let matrixContractSurface: MatrixContractSurface | undefined; diff --git a/test/helpers/channels/plugins-core-extension-contract.ts b/test/helpers/channels/plugins-core-extension-contract.ts index 99a18bb4f83..6f84cdd372e 100644 --- a/test/helpers/channels/plugins-core-extension-contract.ts +++ b/test/helpers/channels/plugins-core-extension-contract.ts @@ -9,29 +9,29 @@ import type { LineProbeResult } from "../../../src/plugin-sdk/line.js"; import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js"; import { withEnvAsync } from "../../../src/test-utils/env.js"; -type DiscordDirectoryContractApiSurface = Pick< - typeof import("@openclaw/discord/directory-contract-api.js"), - "listDiscordDirectoryPeersFromConfig" | "listDiscordDirectoryGroupsFromConfig" ->; -type DiscordProbe = import("@openclaw/discord/api.js").DiscordProbe; -type DiscordTokenResolution = import("@openclaw/discord/api.js").DiscordTokenResolution; -type IMessageProbe = import("@openclaw/imessage/runtime-api.js").IMessageProbe; -type SignalProbe = import("@openclaw/signal/api.js").SignalProbe; -type SlackDirectoryContractApiSurface = Pick< - typeof import("@openclaw/slack/directory-contract-api.js"), - "listSlackDirectoryPeersFromConfig" | "listSlackDirectoryGroupsFromConfig" ->; -type SlackProbe = import("@openclaw/slack/api.js").SlackProbe; -type TelegramDirectoryContractApiSurface = Pick< - typeof import("@openclaw/telegram/directory-contract-api.js"), - "listTelegramDirectoryPeersFromConfig" | "listTelegramDirectoryGroupsFromConfig" ->; -type TelegramProbe = import("@openclaw/telegram/api.js").TelegramProbe; -type TelegramTokenResolution = import("@openclaw/telegram/api.js").TelegramTokenResolution; -type WhatsAppDirectoryContractApiSurface = Pick< - typeof import("@openclaw/whatsapp/directory-contract-api.js"), - "listWhatsAppDirectoryPeersFromConfig" | "listWhatsAppDirectoryGroupsFromConfig" ->; +type DiscordDirectoryContractApiSurface = { + listDiscordDirectoryPeersFromConfig: DirectoryListFn; + listDiscordDirectoryGroupsFromConfig: DirectoryListFn; +}; +type DiscordProbe = BaseProbeResult; +type DiscordTokenResolution = BaseTokenResolution; +type IMessageProbe = BaseProbeResult; +type SignalProbe = BaseProbeResult; +type SlackDirectoryContractApiSurface = { + listSlackDirectoryPeersFromConfig: DirectoryListFn; + listSlackDirectoryGroupsFromConfig: DirectoryListFn; +}; +type SlackProbe = BaseProbeResult; +type TelegramDirectoryContractApiSurface = { + listTelegramDirectoryPeersFromConfig: DirectoryListFn; + listTelegramDirectoryGroupsFromConfig: DirectoryListFn; +}; +type TelegramProbe = BaseProbeResult; +type TelegramTokenResolution = BaseTokenResolution; +type WhatsAppDirectoryContractApiSurface = { + listWhatsAppDirectoryPeersFromConfig: DirectoryListFn; + listWhatsAppDirectoryGroupsFromConfig: DirectoryListFn; +}; let discordDirectoryContractApi: Promise | undefined; let slackDirectoryContractApi: Promise | undefined; diff --git a/test/helpers/channels/security-audit-contract.ts b/test/helpers/channels/security-audit-contract.ts index ad0a67c57c1..6d04bf47f30 100644 --- a/test/helpers/channels/security-audit-contract.ts +++ b/test/helpers/channels/security-audit-contract.ts @@ -1,15 +1,54 @@ +import type { OpenClawConfig } from "../../../src/config/config.js"; +import type { SecurityAuditFinding } from "../../../src/security/audit.types.js"; import { loadBundledPluginPublicSurfaceSync, resolveRelativeBundledPluginPublicModuleId, } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type DiscordSecurityAuditSurface = - typeof import("@openclaw/discord/security-audit-contract-api.js"); -type FeishuSecuritySurface = typeof import("@openclaw/feishu/security-contract-api.js"); -type SlackSecuritySurface = typeof import("@openclaw/slack/security-contract-api.js"); -type SynologyChatSecuritySurface = typeof import("@openclaw/synology-chat/contract-api.js"); -type TelegramSecuritySurface = typeof import("@openclaw/telegram/security-audit-contract-api.js"); -type ZalouserSecuritySurface = typeof import("@openclaw/zalouser/contract-api.js"); +type SecurityAuditAccount = { + accountId: string; + enabled?: boolean; + token?: unknown; + tokenSource?: string; + config?: Record; + [key: string]: unknown; +}; +type FlexibleSecurityAuditParams = { + cfg?: OpenClawConfig; + sourceConfig?: OpenClawConfig; + account: SecurityAuditAccount; + accountId?: string | null; + orderedAccountIds?: string[]; + hasExplicitAccountPath?: boolean; +}; +type ConfigSecurityAuditParams = { + cfg: OpenClawConfig; +}; +type AsyncChannelSecurityAuditCollector = ( + params: FlexibleSecurityAuditParams, +) => Promise; +type SyncChannelSecurityAuditCollector = ( + params: FlexibleSecurityAuditParams, +) => SecurityAuditFinding[]; +type ConfigSecurityAuditCollector = (params: ConfigSecurityAuditParams) => SecurityAuditFinding[]; +type DiscordSecurityAuditSurface = { + collectDiscordSecurityAuditFindings: AsyncChannelSecurityAuditCollector; +}; +type FeishuSecuritySurface = { + collectFeishuSecurityAuditFindings: ConfigSecurityAuditCollector; +}; +type SlackSecuritySurface = { + collectSlackSecurityAuditFindings: AsyncChannelSecurityAuditCollector; +}; +type SynologyChatSecuritySurface = { + collectSynologyChatSecurityAuditFindings: SyncChannelSecurityAuditCollector; +}; +type TelegramSecuritySurface = { + collectTelegramSecurityAuditFindings: AsyncChannelSecurityAuditCollector; +}; +type ZalouserSecuritySurface = { + collectZalouserSecurityAuditFindings: SyncChannelSecurityAuditCollector; +}; const discordSecurityAuditModuleId = resolveRelativeBundledPluginPublicModuleId({ fromModuleUrl: import.meta.url, diff --git a/test/helpers/providers/anthropic-contract.ts b/test/helpers/providers/anthropic-contract.ts index 728c22f2a84..ffd5380dec9 100644 --- a/test/helpers/providers/anthropic-contract.ts +++ b/test/helpers/providers/anthropic-contract.ts @@ -1,6 +1,13 @@ import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js"; -type AnthropicContractSurface = typeof import("@openclaw/anthropic/contract-api.js"); +type AnthropicContractSurface = { + createAnthropicBetaHeadersWrapper: (...args: unknown[]) => unknown; + createAnthropicFastModeWrapper: (...args: unknown[]) => unknown; + createAnthropicServiceTierWrapper: (...args: unknown[]) => unknown; + resolveAnthropicBetas: (...args: unknown[]) => unknown; + resolveAnthropicFastMode: (...args: unknown[]) => unknown; + resolveAnthropicServiceTier: (...args: unknown[]) => unknown; +}; let anthropicContractSurface: AnthropicContractSurface | undefined;