diff --git a/extensions/discord/src/doctor.ts b/extensions/discord/src/doctor.ts index 42a1a8db868..3e8e2b5b7bd 100644 --- a/extensions/discord/src/doctor.ts +++ b/extensions/discord/src/doctor.ts @@ -3,7 +3,7 @@ import { type ChannelDoctorConfigMutation, } from "openclaw/plugin-sdk/channel-contract"; import { type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime"; +import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime-doctor"; import { DISCORD_LEGACY_CONFIG_RULES } from "./doctor-shared.js"; import { resolveDiscordPreviewStreamMode } from "./preview-streaming.js"; diff --git a/extensions/feishu/index.ts b/extensions/feishu/index.ts index 2eae5ce5e68..9469da45972 100644 --- a/extensions/feishu/index.ts +++ b/extensions/feishu/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { registerFeishuBitableTools } from "./src/bitable.js"; import { feishuPlugin } from "./src/channel.js"; import { registerFeishuChatTools } from "./src/chat.js"; diff --git a/extensions/feishu/setup-entry.ts b/extensions/feishu/setup-entry.ts index 1f16bde8bdd..bfdb856e45f 100644 --- a/extensions/feishu/setup-entry.ts +++ b/extensions/feishu/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { feishuPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(feishuPlugin); diff --git a/extensions/googlechat/index.ts b/extensions/googlechat/index.ts index a9bf2fe10a6..16d84588d7a 100644 --- a/extensions/googlechat/index.ts +++ b/extensions/googlechat/index.ts @@ -1,5 +1,5 @@ -import type { ChannelPlugin } from "openclaw/plugin-sdk/core"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { googlechatPlugin } from "./src/channel.js"; import { setGoogleChatRuntime } from "./src/runtime.js"; diff --git a/extensions/googlechat/runtime-api.ts b/extensions/googlechat/runtime-api.ts index df946f8ec4a..f2fd8769d99 100644 --- a/extensions/googlechat/runtime-api.ts +++ b/extensions/googlechat/runtime-api.ts @@ -1,4 +1,62 @@ // Private runtime barrel for the bundled Google Chat extension. -// Keep this barrel thin and aligned with the local extension surface. +// Keep this barrel thin and avoid broad plugin-sdk surfaces during bootstrap. -export * from "openclaw/plugin-sdk/googlechat"; +export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; +export { + createActionGate, + jsonResult, + readNumberParam, + readReactionParams, + readStringParam, +} from "openclaw/plugin-sdk/channel-actions"; +export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives"; +export type { + ChannelMessageActionAdapter, + ChannelMessageActionName, + ChannelStatusIssue, +} from "openclaw/plugin-sdk/channel-contract"; +export { missingTargetError } from "openclaw/plugin-sdk/channel-feedback"; +export { + createAccountStatusSink, + runPassiveAccountLifecycle, +} from "openclaw/plugin-sdk/channel-lifecycle"; +export { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing"; +export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline"; +export { + evaluateGroupRouteAccessForPolicy, + resolveDmGroupAccessWithLists, + resolveSenderScopedGroupPolicy, +} from "openclaw/plugin-sdk/channel-policy"; +export { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status"; +export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking"; +export type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; +export { + GROUP_POLICY_BLOCKED_LABEL, + isDangerousNameMatchingEnabled, + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, + warnMissingProviderGroupPolicyFallbackOnce, +} from "openclaw/plugin-sdk/config-runtime"; +export { fetchRemoteMedia, resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime"; +export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media"; +export type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store"; +export { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime"; +export { + GoogleChatConfigSchema, + type GoogleChatAccountConfig, + type GoogleChatConfig, +} from "openclaw/plugin-sdk/googlechat-runtime-shared"; +export { extractToolSend } from "openclaw/plugin-sdk/tool-send"; +export { resolveMentionGatingWithBypass } from "openclaw/plugin-sdk/channel-inbound"; +export { resolveInboundRouteEnvelopeBuilderWithRuntime } from "openclaw/plugin-sdk/inbound-envelope"; +export { resolveWebhookPath } from "openclaw/plugin-sdk/webhook-path"; +export { + registerWebhookTargetWithPluginRoute, + resolveWebhookTargetWithAuthOrReject, + withResolvedWebhookRequestPipeline, +} from "openclaw/plugin-sdk/webhook-targets"; +export { + createWebhookInFlightLimiter, + readJsonWebhookBodyOrReject, + type WebhookInFlightLimiter, +} from "openclaw/plugin-sdk/webhook-request-guards"; diff --git a/extensions/googlechat/setup-entry.ts b/extensions/googlechat/setup-entry.ts index 44fd1f11fb3..ad5dd6ee283 100644 --- a/extensions/googlechat/setup-entry.ts +++ b/extensions/googlechat/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { googlechatPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(googlechatPlugin); diff --git a/extensions/googlechat/src/accounts.ts b/extensions/googlechat/src/accounts.ts index a729c5302bd..fbba2c67594 100644 --- a/extensions/googlechat/src/accounts.ts +++ b/extensions/googlechat/src/accounts.ts @@ -2,11 +2,12 @@ import { createAccountListHelpers, DEFAULT_ACCOUNT_ID, normalizeAccountId, + type OpenClawConfig, resolveAccountEntry, resolveMergedAccountConfig, } from "openclaw/plugin-sdk/account-resolution"; -import { isSecretRef, type OpenClawConfig } from "openclaw/plugin-sdk/core"; import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared"; +import { isSecretRef } from "openclaw/plugin-sdk/secret-input"; import { z } from "zod"; import type { GoogleChatAccountConfig } from "./types.config.js"; diff --git a/extensions/googlechat/src/channel.deps.runtime.ts b/extensions/googlechat/src/channel.deps.runtime.ts index e8c4adf0880..127a5d848e3 100644 --- a/extensions/googlechat/src/channel.deps.runtime.ts +++ b/extensions/googlechat/src/channel.deps.runtime.ts @@ -4,7 +4,6 @@ export { createAccountStatusSink, DEFAULT_ACCOUNT_ID, fetchRemoteMedia, - getChatChannelMeta, GoogleChatConfigSchema, loadOutboundMediaFromUrl, missingTargetError, diff --git a/extensions/googlechat/src/channel.ts b/extensions/googlechat/src/channel.ts index d53fd338d80..2baba29d1aa 100644 --- a/extensions/googlechat/src/channel.ts +++ b/extensions/googlechat/src/channel.ts @@ -4,13 +4,13 @@ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { composeAccountWarningCollectors, composeWarningCollectors, createAllowlistProviderGroupPolicyWarningCollector, createAllowlistProviderOpenWarningCollector, } from "openclaw/plugin-sdk/channel-policy"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter, listResolvedDirectoryGroupEntriesFromMapKeys, @@ -31,7 +31,6 @@ import { createAccountStatusSink, DEFAULT_ACCOUNT_ID, fetchRemoteMedia, - getChatChannelMeta, GoogleChatConfigSchema, listGoogleChatAccountIds, loadOutboundMediaFromUrl, @@ -57,7 +56,19 @@ import { collectRuntimeConfigAssignments, secretTargetRegistryEntries } from "./ import { googlechatSetupAdapter } from "./setup-core.js"; import { googlechatSetupWizard } from "./setup-surface.js"; -const meta = getChatChannelMeta("googlechat"); +const meta = { + id: "googlechat", + label: "Google Chat", + selectionLabel: "Google Chat (Chat API)", + docsPath: "/channels/googlechat", + docsLabel: "googlechat", + blurb: "Google Workspace Chat app with HTTP webhook.", + aliases: ["gchat", "google-chat"], + order: 55, + detailLabel: "Google Chat", + systemImage: "message.badge", + markdownCapable: true, +}; const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport( () => import("./channel.runtime.js"), diff --git a/extensions/imessage/index.ts b/extensions/imessage/index.ts index 6ed01ad9da4..26bb14c365a 100644 --- a/extensions/imessage/index.ts +++ b/extensions/imessage/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { imessagePlugin } from "./src/channel.js"; import { setIMessageRuntime } from "./src/runtime.js"; diff --git a/extensions/imessage/setup-entry.ts b/extensions/imessage/setup-entry.ts index 7c4c55967a8..1fca32f3e29 100644 --- a/extensions/imessage/setup-entry.ts +++ b/extensions/imessage/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { imessageSetupPlugin } from "./src/channel.setup.js"; export { imessageSetupPlugin } from "./src/channel.setup.js"; diff --git a/extensions/imessage/src/channel.ts b/extensions/imessage/src/channel.ts index 4f3958bafc2..47258bce42f 100644 --- a/extensions/imessage/src/channel.ts +++ b/extensions/imessage/src/channel.ts @@ -1,5 +1,5 @@ import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime"; diff --git a/extensions/irc/index.ts b/extensions/irc/index.ts index 7a746c551cf..9ee429c310f 100644 --- a/extensions/irc/index.ts +++ b/extensions/irc/index.ts @@ -1,5 +1,5 @@ -import type { ChannelPlugin } from "openclaw/plugin-sdk/core"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { ircPlugin } from "./src/channel.js"; import { setIrcRuntime } from "./src/runtime.js"; diff --git a/extensions/irc/setup-entry.ts b/extensions/irc/setup-entry.ts index 3d3d040990c..cb5d208fd0c 100644 --- a/extensions/irc/setup-entry.ts +++ b/extensions/irc/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { ircPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(ircPlugin); diff --git a/extensions/irc/src/accounts.ts b/extensions/irc/src/accounts.ts index d25a57e7a64..f60fc1b8c2c 100644 --- a/extensions/irc/src/accounts.ts +++ b/extensions/irc/src/accounts.ts @@ -1,8 +1,10 @@ import { createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id"; import { resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution"; -import { parseOptionalDelimitedEntries } from "openclaw/plugin-sdk/core"; -import { tryReadSecretFileSync } from "openclaw/plugin-sdk/core"; +import { + parseOptionalDelimitedEntries, + tryReadSecretFileSync, +} from "openclaw/plugin-sdk/channel-core"; import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input"; import type { CoreConfig, IrcAccountConfig, IrcNickServConfig } from "./types.js"; diff --git a/extensions/irc/src/channel-api.ts b/extensions/irc/src/channel-api.ts index e3ac0ee496c..949aece11f9 100644 --- a/extensions/irc/src/channel-api.ts +++ b/extensions/irc/src/channel-api.ts @@ -1,6 +1,6 @@ export { createAccountStatusSink } from "openclaw/plugin-sdk/channel-lifecycle"; +export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; +export type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; export { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status"; export { buildBaseChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers"; -export type { ChannelPlugin } from "openclaw/plugin-sdk/core"; -export { DEFAULT_ACCOUNT_ID, getChatChannelMeta } from "openclaw/plugin-sdk/core"; export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking"; diff --git a/extensions/irc/src/channel.ts b/extensions/irc/src/channel.ts index 4904b6a3faa..376ec08cab2 100644 --- a/extensions/irc/src/channel.ts +++ b/extensions/irc/src/channel.ts @@ -5,12 +5,12 @@ import { createScopedChannelConfigAdapter, createScopedDmSecurityResolver, } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { composeAccountWarningCollectors, composeWarningCollectors, createAllowlistProviderOpenWarningCollector, } from "openclaw/plugin-sdk/channel-policy"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter, createResolvedDirectoryEntriesLister, @@ -32,7 +32,6 @@ import { createAccountStatusSink, chunkTextForOutbound, DEFAULT_ACCOUNT_ID, - getChatChannelMeta, PAIRING_APPROVED_MESSAGE, type ChannelPlugin, } from "./channel-api.js"; @@ -54,7 +53,18 @@ import { ircSetupAdapter } from "./setup-core.js"; import { ircSetupWizard } from "./setup-surface.js"; import type { CoreConfig, IrcProbe } from "./types.js"; -const meta = getChatChannelMeta("irc"); +const meta = { + id: "irc", + label: "IRC", + selectionLabel: "IRC (Server + Nick)", + docsPath: "/channels/irc", + docsLabel: "irc", + blurb: "classic IRC networks; host, nick, channels.", + order: 80, + detailLabel: "IRC", + systemImage: "number", + markdownCapable: true, +}; function normalizePairingTarget(raw: string): string { const normalized = normalizeIrcAllowEntry(raw); diff --git a/extensions/irc/src/runtime-api.ts b/extensions/irc/src/runtime-api.ts index d3258698cd7..fbe2bb4cbea 100644 --- a/extensions/irc/src/runtime-api.ts +++ b/extensions/irc/src/runtime-api.ts @@ -1,12 +1,10 @@ // Private runtime barrel for the bundled IRC extension. // Keep this barrel thin and generic-only. -export type { - BaseProbeResult, - ChannelPlugin, - OpenClawConfig, - PluginRuntime, -} from "openclaw/plugin-sdk/core"; +export type { BaseProbeResult } from "openclaw/plugin-sdk/channel-contract"; +export type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; +export type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; +export type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store"; export type { RuntimeEnv } from "openclaw/plugin-sdk/runtime"; export type { BlockStreamingCoalesceConfig, @@ -18,11 +16,8 @@ export type { MarkdownConfig, } from "openclaw/plugin-sdk/config-runtime"; export type { OutboundReplyPayload } from "openclaw/plugin-sdk/reply-payload"; -export { - DEFAULT_ACCOUNT_ID, - buildChannelConfigSchema, - getChatChannelMeta, -} from "openclaw/plugin-sdk/core"; +export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; +export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives"; export { PAIRING_APPROVED_MESSAGE, buildBaseChannelStatusSummary, @@ -43,9 +38,9 @@ export { } from "openclaw/plugin-sdk/reply-payload"; export { GROUP_POLICY_BLOCKED_LABEL, + isDangerousNameMatchingEnabled, resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce, - isDangerousNameMatchingEnabled, } from "openclaw/plugin-sdk/config-runtime"; export { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound"; diff --git a/extensions/line/index.ts b/extensions/line/index.ts index b6134102503..75a4e2cea35 100644 --- a/extensions/line/index.ts +++ b/extensions/line/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/channel-core"; import { linePlugin } from "./src/channel.js"; import { setLineRuntime } from "./src/runtime.js"; @@ -15,7 +15,7 @@ async function loadLineCardCommand(api: OpenClawPluginApi): Promise void; warn?: (message: string) => void }; }): Promise { + const { createBackupArchive } = await import("openclaw/plugin-sdk/runtime"); const env = params.env ?? process.env; const markerPath = resolveMatrixMigrationSnapshotMarkerPath(env); const existingMarker = loadSnapshotMarker(markerPath); diff --git a/extensions/matrix/src/runtime-api.ts b/extensions/matrix/src/runtime-api.ts index 2771e4a7602..9d2b0be676a 100644 --- a/extensions/matrix/src/runtime-api.ts +++ b/extensions/matrix/src/runtime-api.ts @@ -1,23 +1,18 @@ export { DEFAULT_ACCOUNT_ID, - buildChannelConfigSchema, - createActionGate, - getChatChannelMeta, - jsonResult, normalizeAccountId, + normalizeOptionalAccountId, +} from "openclaw/plugin-sdk/account-id"; +export { + createActionGate, + jsonResult, readNumberParam, readReactionParams, readStringArrayParam, readStringParam, - type PollInput, - type ReplyPayload, -} from "openclaw/plugin-sdk/core"; -export type { - ChannelPlugin, - NormalizedLocation, - PluginRuntime, - RuntimeLogger, -} from "openclaw/plugin-sdk/core"; +} from "openclaw/plugin-sdk/channel-actions"; +export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives"; +export type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; export type { BaseProbeResult, ChannelDirectoryEntry, @@ -31,9 +26,14 @@ export type { ChannelResolveResult, ChannelToolSend, } from "openclaw/plugin-sdk/channel-contract"; -export { formatZonedTimestamp } from "openclaw/plugin-sdk/core"; -export { normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-id"; -export type { ChannelSetupInput } from "openclaw/plugin-sdk/core"; +export { + formatLocationText, + logInboundDrop, + toLocationContext, + type NormalizedLocation, +} from "openclaw/plugin-sdk/channel-inbound"; +export { resolveAckReaction, logTypingFailure } from "openclaw/plugin-sdk/channel-feedback"; +export type { ChannelSetupInput } from "openclaw/plugin-sdk/setup"; export type { OpenClawConfig, ContextVisibilityMode, @@ -41,7 +41,7 @@ export type { GroupPolicy, } from "openclaw/plugin-sdk/config-runtime"; export type { GroupToolPolicyConfig } from "openclaw/plugin-sdk/config-runtime"; -export type { WizardPrompter } from "openclaw/plugin-sdk/core"; +export type { WizardPrompter } from "openclaw/plugin-sdk/matrix-runtime-shared"; export type { SecretInput } from "openclaw/plugin-sdk/secret-input"; export { GROUP_POLICY_BLOCKED_LABEL, @@ -74,7 +74,7 @@ export { dispatchReplyFromConfigWithSettledDispatcher } from "openclaw/plugin-sd export { ensureConfiguredAcpBindingReady, resolveConfiguredAcpBindingRecord, -} from "openclaw/plugin-sdk/core"; +} from "openclaw/plugin-sdk/acp-binding-runtime"; export { buildProbeChannelStatusSummary, collectStatusIssuesFromLastError, @@ -90,8 +90,22 @@ export { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing"; export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking"; export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline"; export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media"; -export { normalizePollInput } from "openclaw/plugin-sdk/media-runtime"; +export { normalizePollInput, type PollInput } from "openclaw/plugin-sdk/media-runtime"; export { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store"; +export { + buildChannelKeyCandidates, + resolveChannelEntryMatch, +} from "openclaw/plugin-sdk/channel-targets"; +export { + evaluateGroupRouteAccessForPolicy, + resolveSenderScopedGroupPolicy, +} from "openclaw/plugin-sdk/channel-policy"; +export { + formatZonedTimestamp, + type PluginRuntime, + type RuntimeLogger, +} from "openclaw/plugin-sdk/matrix-runtime-shared"; +export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime"; // resolveMatrixAccountStringValues already comes from plugin-sdk/matrix. // Re-exporting auth-precedence here makes Jiti try to define the same export twice. diff --git a/extensions/matrix/src/session-route.ts b/extensions/matrix/src/session-route.ts index 2272c81e693..60ac0984060 100644 --- a/extensions/matrix/src/session-route.ts +++ b/extensions/matrix/src/session-route.ts @@ -3,7 +3,7 @@ import { stripChannelTargetPrefix, stripTargetKindPrefix, type ChannelOutboundSessionRouteParams, -} from "openclaw/plugin-sdk/core"; +} from "openclaw/plugin-sdk/channel-core"; export function resolveMatrixOutboundSessionRoute(params: ChannelOutboundSessionRouteParams) { const stripped = stripChannelTargetPrefix(params.target, "matrix"); diff --git a/extensions/mattermost/index.ts b/extensions/mattermost/index.ts index a40971bf850..a6b8999734f 100644 --- a/extensions/mattermost/index.ts +++ b/extensions/mattermost/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { mattermostPlugin } from "./src/channel.js"; import { registerSlashCommandRoute } from "./src/mattermost/slash-state.js"; import { setMattermostRuntime } from "./src/runtime.js"; diff --git a/extensions/mattermost/setup-entry.ts b/extensions/mattermost/setup-entry.ts index 34ce40972e4..2564793aa2c 100644 --- a/extensions/mattermost/setup-entry.ts +++ b/extensions/mattermost/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { mattermostPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(mattermostPlugin); diff --git a/extensions/mattermost/src/channel.ts b/extensions/mattermost/src/channel.ts index d40a110a596..0a05966a960 100644 --- a/extensions/mattermost/src/channel.ts +++ b/extensions/mattermost/src/channel.ts @@ -11,9 +11,9 @@ import type { ChannelMessageActionName, ChannelMessageToolDiscovery, } from "openclaw/plugin-sdk/channel-contract"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createLoggedPairingApprovalNotifier } from "openclaw/plugin-sdk/channel-pairing"; import { createRestrictSendersChannelSecurity } from "openclaw/plugin-sdk/channel-policy"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared"; import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime"; diff --git a/extensions/msteams/index.ts b/extensions/msteams/index.ts index edffd1452f4..86214a6e800 100644 --- a/extensions/msteams/index.ts +++ b/extensions/msteams/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { msteamsPlugin } from "./src/channel.js"; import { setMSTeamsRuntime } from "./src/runtime.js"; diff --git a/extensions/msteams/setup-entry.ts b/extensions/msteams/setup-entry.ts index 6e29414c82e..4a08bd31dd3 100644 --- a/extensions/msteams/setup-entry.ts +++ b/extensions/msteams/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { msteamsPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(msteamsPlugin); diff --git a/extensions/msteams/src/channel.ts b/extensions/msteams/src/channel.ts index 275ee3b86c8..4ec5857dcdd 100644 --- a/extensions/msteams/src/channel.ts +++ b/extensions/msteams/src/channel.ts @@ -6,12 +6,12 @@ import type { ChannelMessageActionAdapter, ChannelMessageToolDiscovery, } from "openclaw/plugin-sdk/channel-contract"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing"; import { createAllowlistProviderGroupPolicyWarningCollector, projectConfigWarningCollector, } from "openclaw/plugin-sdk/channel-policy"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, diff --git a/extensions/nextcloud-talk/index.ts b/extensions/nextcloud-talk/index.ts index 56a398d705b..d5aebc4478f 100644 --- a/extensions/nextcloud-talk/index.ts +++ b/extensions/nextcloud-talk/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { nextcloudTalkPlugin } from "./src/channel.js"; import { setNextcloudTalkRuntime } from "./src/runtime.js"; diff --git a/extensions/nextcloud-talk/setup-entry.ts b/extensions/nextcloud-talk/setup-entry.ts index 88aec7d47e9..6fbfbd20e5d 100644 --- a/extensions/nextcloud-talk/setup-entry.ts +++ b/extensions/nextcloud-talk/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { nextcloudTalkPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(nextcloudTalkPlugin); diff --git a/extensions/nextcloud-talk/src/accounts.ts b/extensions/nextcloud-talk/src/accounts.ts index dffa201d88f..016f155b871 100644 --- a/extensions/nextcloud-talk/src/accounts.ts +++ b/extensions/nextcloud-talk/src/accounts.ts @@ -1,5 +1,5 @@ import { resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution"; -import { tryReadSecretFileSync } from "openclaw/plugin-sdk/core"; +import { tryReadSecretFileSync } from "openclaw/plugin-sdk/channel-core"; import { createAccountListHelpers, DEFAULT_ACCOUNT_ID, diff --git a/extensions/nextcloud-talk/src/channel-api.ts b/extensions/nextcloud-talk/src/channel-api.ts index 5095db8ccee..6aaee922dcc 100644 --- a/extensions/nextcloud-talk/src/channel-api.ts +++ b/extensions/nextcloud-talk/src/channel-api.ts @@ -1,3 +1,5 @@ -export type { ChannelPlugin, OpenClawConfig } from "openclaw/plugin-sdk/core"; -export { clearAccountEntryFields, DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/core"; +export type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; +export type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; +export { clearAccountEntryFields } from "openclaw/plugin-sdk/channel-core"; +export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema"; diff --git a/extensions/nextcloud-talk/src/channel.ts b/extensions/nextcloud-talk/src/channel.ts index ac230f66c94..19b004b7145 100644 --- a/extensions/nextcloud-talk/src/channel.ts +++ b/extensions/nextcloud-talk/src/channel.ts @@ -5,13 +5,13 @@ import { createScopedChannelConfigAdapter, createScopedDmSecurityResolver, } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createAccountStatusSink } from "openclaw/plugin-sdk/channel-lifecycle"; import { createLoggedPairingApprovalNotifier, createPairingPrefixStripper, } from "openclaw/plugin-sdk/channel-pairing"; import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { runStoppablePassiveMonitor } from "openclaw/plugin-sdk/extension-shared"; import { buildWebhookChannelStatusSummary, diff --git a/extensions/nextcloud-talk/src/session-route.ts b/extensions/nextcloud-talk/src/session-route.ts index c469358c70e..7ff7c498b8d 100644 --- a/extensions/nextcloud-talk/src/session-route.ts +++ b/extensions/nextcloud-talk/src/session-route.ts @@ -1,7 +1,7 @@ import { buildChannelOutboundSessionRoute, type ChannelOutboundSessionRouteParams, -} from "openclaw/plugin-sdk/core"; +} from "openclaw/plugin-sdk/channel-core"; import { stripNextcloudTalkTargetPrefix } from "./normalize.js"; export function resolveNextcloudTalkOutboundSessionRoute( diff --git a/extensions/nostr/index.ts b/extensions/nostr/index.ts index 2b891c4f0f2..07ee38d4b43 100644 --- a/extensions/nostr/index.ts +++ b/extensions/nostr/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { nostrPlugin } from "./src/channel.js"; import type { NostrProfile } from "./src/config-schema.js"; import { createNostrProfileHttpHandler } from "./src/nostr-profile-http.js"; diff --git a/extensions/nostr/setup-entry.ts b/extensions/nostr/setup-entry.ts index f2ac263fd0f..769f4c364f2 100644 --- a/extensions/nostr/setup-entry.ts +++ b/extensions/nostr/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { nostrPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(nostrPlugin); diff --git a/extensions/nostr/src/channel.ts b/extensions/nostr/src/channel.ts index b9c89508b1d..e0fddf848f6 100644 --- a/extensions/nostr/src/channel.ts +++ b/extensions/nostr/src/channel.ts @@ -3,9 +3,9 @@ import { createScopedDmSecurityResolver, createTopLevelChannelConfigAdapter, } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing"; import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { buildPassiveChannelStatusSummary, buildTrafficStatusSummary, diff --git a/extensions/qqbot/index.ts b/extensions/qqbot/index.ts index 62ded34412a..cac2e1e5c7a 100644 --- a/extensions/qqbot/index.ts +++ b/extensions/qqbot/index.ts @@ -1,5 +1,9 @@ -import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk/core"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import type { + ChannelPlugin, + OpenClawPluginApi, + PluginCommandContext, +} from "openclaw/plugin-sdk/channel-core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { qqbotPlugin } from "./src/channel.js"; import { resolveQQBotAccount } from "./src/config.js"; import { sendDocument, type MediaTargetContext } from "./src/outbound.js"; @@ -30,7 +34,7 @@ export default defineChannelPluginEntry({ description: cmd.description, requireAuth: true, acceptsArgs: true, - handler: async (ctx) => { + handler: async (ctx: PluginCommandContext) => { // Derive the QQBot message type from ctx.from so that handlers that // inspect SlashCommandContext.type get the correct value. // ctx.from format: "qqbot::" e.g. "qqbot:c2c:" diff --git a/extensions/qqbot/setup-entry.ts b/extensions/qqbot/setup-entry.ts index d3ffb490076..0786409e78d 100644 --- a/extensions/qqbot/setup-entry.ts +++ b/extensions/qqbot/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { qqbotSetupPlugin } from "./src/channel.setup.js"; export { qqbotSetupPlugin } from "./src/channel.setup.js"; diff --git a/extensions/signal/src/channel.ts b/extensions/signal/src/channel.ts index 05ce14a169e..5439bb6daa7 100644 --- a/extensions/signal/src/channel.ts +++ b/extensions/signal/src/channel.ts @@ -1,5 +1,6 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit"; +import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing"; import { attachChannelToResult, @@ -7,7 +8,6 @@ import { } from "openclaw/plugin-sdk/channel-send-result"; import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status"; import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime"; -import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/core"; import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime"; import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; import { chunkText, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking"; diff --git a/extensions/slack/src/doctor.ts b/extensions/slack/src/doctor.ts index a1465d75b11..97da44c4432 100644 --- a/extensions/slack/src/doctor.ts +++ b/extensions/slack/src/doctor.ts @@ -4,7 +4,7 @@ import { type ChannelDoctorLegacyConfigRule, } from "openclaw/plugin-sdk/channel-contract"; import { type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime"; +import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime-doctor"; import { isSlackMutableAllowEntry } from "./security-doctor.js"; import { formatSlackStreamingBooleanMigrationMessage, diff --git a/extensions/synology-chat/index.ts b/extensions/synology-chat/index.ts index 1e51c8f68aa..d48e2abfa84 100644 --- a/extensions/synology-chat/index.ts +++ b/extensions/synology-chat/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { synologyChatPlugin } from "./src/channel.js"; import { setSynologyRuntime } from "./src/runtime.js"; diff --git a/extensions/synology-chat/setup-entry.ts b/extensions/synology-chat/setup-entry.ts index 858696710a8..9d3610a3650 100644 --- a/extensions/synology-chat/setup-entry.ts +++ b/extensions/synology-chat/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { synologyChatPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(synologyChatPlugin); diff --git a/extensions/synology-chat/src/channel.ts b/extensions/synology-chat/src/channel.ts index 9a8fdc2fe65..4785c543b17 100644 --- a/extensions/synology-chat/src/channel.ts +++ b/extensions/synology-chat/src/channel.ts @@ -10,6 +10,7 @@ import { createHybridChannelConfigAdapter, createScopedDmSecurityResolver, } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { waitUntilAbort } from "openclaw/plugin-sdk/channel-lifecycle"; import { composeWarningCollectors, @@ -18,7 +19,6 @@ import { projectAccountWarningCollector, } from "openclaw/plugin-sdk/channel-policy"; import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result"; -import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/core"; import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; import { listAccountIds, resolveAccount } from "./accounts.js"; import { synologyChatApprovalAuth } from "./approval-auth.js"; diff --git a/extensions/telegram/index.ts b/extensions/telegram/index.ts index ec6290914fe..cdbc1d3a8e1 100644 --- a/extensions/telegram/index.ts +++ b/extensions/telegram/index.ts @@ -1,5 +1,5 @@ -import type { ChannelPlugin } from "openclaw/plugin-sdk/core"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { telegramPlugin } from "./src/channel.js"; import { setTelegramRuntime } from "./src/runtime.js"; diff --git a/extensions/telegram/setup-entry.ts b/extensions/telegram/setup-entry.ts index 7b2c02399fa..eb9e5ec4339 100644 --- a/extensions/telegram/setup-entry.ts +++ b/extensions/telegram/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { telegramSetupPlugin } from "./src/channel.setup.js"; export { telegramSetupPlugin } from "./src/channel.setup.js"; diff --git a/extensions/telegram/src/channel.ts b/extensions/telegram/src/channel.ts index 98d4436c830..a0d5330d9c7 100644 --- a/extensions/telegram/src/channel.ts +++ b/extensions/telegram/src/channel.ts @@ -4,6 +4,7 @@ import { createNestedAllowlistOverrideResolver, } from "openclaw/plugin-sdk/allowlist-config-edit"; import type { ChannelMessageActionAdapter } from "openclaw/plugin-sdk/channel-contract"; +import { clearAccountEntryFields, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing"; import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy"; import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result"; @@ -14,8 +15,6 @@ import { resolveConfiguredFromCredentialStatuses, } from "openclaw/plugin-sdk/channel-status"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; -import { clearAccountEntryFields } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; import { resolveOutboundSendDep, diff --git a/extensions/telegram/src/doctor.ts b/extensions/telegram/src/doctor.ts index 9768f253287..e015ec9067b 100644 --- a/extensions/telegram/src/doctor.ts +++ b/extensions/telegram/src/doctor.ts @@ -5,10 +5,6 @@ import { type ChannelDoctorLegacyConfigRule, } from "openclaw/plugin-sdk/channel-contract"; import { type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { - getChannelsCommandSecretTargetIds, - resolveCommandSecretRefsViaGateway, -} from "openclaw/plugin-sdk/runtime"; import { inspectTelegramAccount } from "./account-inspect.js"; import { listTelegramAccountIds, resolveTelegramAccount } from "./accounts.js"; import { isNumericTelegramUserId, normalizeTelegramAllowFromEntry } from "./allow-from.js"; @@ -252,6 +248,9 @@ export async function maybeRepairTelegramAllowFromUsernames(cfg: OpenClawConfig) return { config: cfg, changes: [] }; } + const { getChannelsCommandSecretTargetIds, resolveCommandSecretRefsViaGateway } = + await import("openclaw/plugin-sdk/runtime-secret-resolution"); + const { resolvedConfig } = await resolveCommandSecretRefsViaGateway({ config: cfg, commandName: "doctor --fix", diff --git a/extensions/tlon/index.ts b/extensions/tlon/index.ts index a59c7bcb9f2..6f8c224face 100644 --- a/extensions/tlon/index.ts +++ b/extensions/tlon/index.ts @@ -2,7 +2,7 @@ import { spawn } from "node:child_process"; import { existsSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { tlonPlugin } from "./src/channel.js"; import { setTlonRuntime } from "./src/runtime.js"; diff --git a/extensions/tlon/setup-entry.ts b/extensions/tlon/setup-entry.ts index 6a14ba3bade..de25eaa266e 100644 --- a/extensions/tlon/setup-entry.ts +++ b/extensions/tlon/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { tlonPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(tlonPlugin); diff --git a/extensions/tlon/src/channel.ts b/extensions/tlon/src/channel.ts index ad08ce19e6f..0153772b2a5 100644 --- a/extensions/tlon/src/channel.ts +++ b/extensions/tlon/src/channel.ts @@ -1,8 +1,8 @@ import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers"; import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; import { createHybridChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/core"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { createRuntimeOutboundDelegates } from "openclaw/plugin-sdk/outbound-runtime"; import { @@ -10,6 +10,7 @@ import { createDefaultChannelRuntimeState, } from "openclaw/plugin-sdk/status-helpers"; import { tlonChannelConfigSchema } from "./config-schema.js"; +import { tlonDoctor } from "./doctor.js"; import { resolveTlonOutboundSessionRoute } from "./session-route.js"; import { applyTlonSetupConfig, @@ -17,7 +18,6 @@ import { resolveTlonSetupConfigured, tlonSetupAdapter, } from "./setup-core.js"; -import { tlonDoctor } from "./doctor.js"; import { formatTargetHint, normalizeShip, diff --git a/extensions/twitch/index.ts b/extensions/twitch/index.ts index 1a4ea89185c..3c89063034e 100644 --- a/extensions/twitch/index.ts +++ b/extensions/twitch/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { twitchPlugin } from "./src/plugin.js"; import { setTwitchRuntime } from "./src/runtime.js"; diff --git a/extensions/twitch/src/plugin.ts b/extensions/twitch/src/plugin.ts index 9e22463de85..0650b66715e 100644 --- a/extensions/twitch/src/plugin.ts +++ b/extensions/twitch/src/plugin.ts @@ -6,11 +6,11 @@ */ import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createLoggedPairingApprovalNotifier, createPairingPrefixStripper, } from "openclaw/plugin-sdk/channel-pairing"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared"; import { createComputedAccountStatusAdapter, diff --git a/extensions/whatsapp/index.ts b/extensions/whatsapp/index.ts index de3e6c92706..ecf77d6f544 100644 --- a/extensions/whatsapp/index.ts +++ b/extensions/whatsapp/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { whatsappPlugin } from "./src/channel.js"; import { setWhatsAppRuntime } from "./src/runtime.js"; diff --git a/extensions/whatsapp/setup-entry.ts b/extensions/whatsapp/setup-entry.ts index 16471e34e0f..9fab8788ecb 100644 --- a/extensions/whatsapp/setup-entry.ts +++ b/extensions/whatsapp/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { whatsappSetupPlugin } from "./src/channel.setup.js"; export { whatsappSetupPlugin } from "./src/channel.setup.js"; diff --git a/extensions/whatsapp/src/channel.ts b/extensions/whatsapp/src/channel.ts index 7de26fa5b6b..3a967c96b0e 100644 --- a/extensions/whatsapp/src/channel.ts +++ b/extensions/whatsapp/src/channel.ts @@ -1,6 +1,6 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit"; -import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/core"; +import { createChatChannelPlugin, type ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { createAsyncComputedAccountStatusAdapter, diff --git a/extensions/zalo/index.ts b/extensions/zalo/index.ts index b1391b68c01..13fdb4174da 100644 --- a/extensions/zalo/index.ts +++ b/extensions/zalo/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { zaloPlugin } from "./src/channel.js"; import { setZaloRuntime } from "./src/runtime.js"; diff --git a/extensions/zalo/setup-entry.ts b/extensions/zalo/setup-entry.ts index d26b0f93fe0..1fb1c1714a8 100644 --- a/extensions/zalo/setup-entry.ts +++ b/extensions/zalo/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { zaloPlugin } from "./src/channel.js"; export default defineSetupPluginEntry(zaloPlugin); diff --git a/extensions/zalo/src/channel.ts b/extensions/zalo/src/channel.ts index 9f48b2b4c47..dae8a967769 100644 --- a/extensions/zalo/src/channel.ts +++ b/extensions/zalo/src/channel.ts @@ -8,6 +8,11 @@ import { mapAllowFromEntries, } from "openclaw/plugin-sdk/channel-config-helpers"; import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/channel-contract"; +import { + buildChannelConfigSchema, + createChatChannelPlugin, + type ChannelPlugin, +} from "openclaw/plugin-sdk/channel-core"; import { buildOpenGroupPolicyRestrictSendersWarning, buildOpenGroupPolicyWarning, @@ -20,8 +25,6 @@ import { import { buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/channel-status"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import { createStaticReplyToModeResolver } from "openclaw/plugin-sdk/conversation-runtime"; -import { createChatChannelPlugin, buildChannelConfigSchema } from "openclaw/plugin-sdk/core"; -import type { ChannelPlugin } from "openclaw/plugin-sdk/core"; import { createChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; import { listResolvedDirectoryUserEntriesFromAllowFrom } from "openclaw/plugin-sdk/directory-runtime"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; diff --git a/extensions/zalouser/index.ts b/extensions/zalouser/index.ts index 306527010c4..c5560a70391 100644 --- a/extensions/zalouser/index.ts +++ b/extensions/zalouser/index.ts @@ -1,4 +1,4 @@ -import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { zalouserPlugin } from "./src/channel.js"; import { setZalouserRuntime } from "./src/runtime.js"; import { createZalouserTool } from "./src/tool.js"; diff --git a/extensions/zalouser/setup-entry.ts b/extensions/zalouser/setup-entry.ts index df1681dd12d..def0bdd4862 100644 --- a/extensions/zalouser/setup-entry.ts +++ b/extensions/zalouser/setup-entry.ts @@ -1,4 +1,4 @@ -import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core"; +import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core"; import { zalouserSetupPlugin } from "./src/channel.setup.js"; export { zalouserSetupPlugin } from "./src/channel.setup.js"; diff --git a/extensions/zalouser/src/channel.ts b/extensions/zalouser/src/channel.ts index d3fe444379d..e31d0121645 100644 --- a/extensions/zalouser/src/channel.ts +++ b/extensions/zalouser/src/channel.ts @@ -1,4 +1,5 @@ import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers"; +import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createAccountStatusSink } from "openclaw/plugin-sdk/channel-lifecycle"; import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing"; import { @@ -6,7 +7,6 @@ import { createRawChannelSendResultAdapter, } from "openclaw/plugin-sdk/channel-send-result"; import { createStaticReplyToModeResolver } from "openclaw/plugin-sdk/conversation-runtime"; -import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { diff --git a/extensions/zalouser/src/doctor.ts b/extensions/zalouser/src/doctor.ts index 248a9931857..40c8f5f12c3 100644 --- a/extensions/zalouser/src/doctor.ts +++ b/extensions/zalouser/src/doctor.ts @@ -4,7 +4,7 @@ import type { ChannelDoctorLegacyConfigRule, } from "openclaw/plugin-sdk/channel-contract"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime"; +import { collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime-doctor"; import { isZalouserMutableGroupEntry } from "./security-audit.js"; type ZalouserChannelsConfig = NonNullable; diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index e4b8195fae5..bb12195c970 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -6,7 +6,9 @@ "self-hosted-provider-setup", "routing", "runtime", + "runtime-doctor", "runtime-env", + "runtime-secret-resolution", "setup", "setup-adapter-runtime", "setup-runtime", diff --git a/src/agents/models-config.e2e-harness.ts b/src/agents/models-config.e2e-harness.ts index 9eca2d352d5..1992a2ed7c1 100644 --- a/src/agents/models-config.e2e-harness.ts +++ b/src/agents/models-config.e2e-harness.ts @@ -267,6 +267,15 @@ async function inferImplicitProviderTestPluginIds(params: { providerIds.add(providerId.trim()); } } + const legacyGrokApiKey = + params.config?.tools?.web?.search && + typeof params.config.tools.web.search === "object" && + "grok" in params.config.tools.web.search + ? (params.config.tools.web.search.grok as { apiKey?: unknown } | undefined)?.apiKey + : undefined; + if (legacyGrokApiKey !== undefined && params.config?.plugins?.entries?.xai?.enabled !== false) { + providerIds.add("xai"); + } for (const [envVar, mappedProviderIds] of Object.entries(TEST_PROVIDER_ENV_TO_PROVIDER_IDS)) { if (!params.env[envVar]?.trim()) { continue; diff --git a/src/channels/plugins/bundled.shape-guard.test.ts b/src/channels/plugins/bundled.shape-guard.test.ts index d36f91a070f..5e546181198 100644 --- a/src/channels/plugins/bundled.shape-guard.test.ts +++ b/src/channels/plugins/bundled.shape-guard.test.ts @@ -1,3 +1,5 @@ +import fs from "node:fs"; +import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; import { importFreshModule } from "../../../test/helpers/import-fresh.ts"; @@ -29,4 +31,120 @@ describe("bundled channel entry shape guards", () => { expect(bundled.listBundledChannelPlugins()).toEqual([]); expect(bundled.listBundledChannelSetupPlugins()).toEqual([]); }); + + it("keeps channel entrypoints on the narrow channel-core SDK surface", () => { + const extensionRoot = path.resolve("extensions"); + const offenders: string[] = []; + + for (const extensionId of fs.readdirSync(extensionRoot)) { + const extensionDir = path.join(extensionRoot, extensionId); + if (!fs.statSync(extensionDir).isDirectory()) { + continue; + } + for (const relativePath of ["index.ts", "setup-entry.ts"]) { + const filePath = path.join(extensionDir, relativePath); + if (!fs.existsSync(filePath)) { + continue; + } + const source = fs.readFileSync(filePath, "utf8"); + const usesEntryHelpers = + source.includes("defineChannelPluginEntry") || source.includes("defineSetupPluginEntry"); + if (!usesEntryHelpers) { + continue; + } + if (source.includes('from "openclaw/plugin-sdk/core"')) { + offenders.push(path.relative(process.cwd(), filePath)); + } + } + } + + expect(offenders).toEqual([]); + }); + + it("keeps channel implementations off the broad core SDK surface", () => { + const extensionRoot = path.resolve("extensions"); + const offenders: string[] = []; + + for (const extensionId of fs.readdirSync(extensionRoot)) { + const extensionDir = path.join(extensionRoot, extensionId); + if (!fs.statSync(extensionDir).isDirectory()) { + continue; + } + for (const relativePath of ["src/channel.ts", "src/plugin.ts"]) { + const filePath = path.join(extensionDir, relativePath); + if (!fs.existsSync(filePath)) { + continue; + } + const source = fs.readFileSync(filePath, "utf8"); + if (!source.includes("createChatChannelPlugin")) { + continue; + } + if (source.includes('from "openclaw/plugin-sdk/core"')) { + offenders.push(path.relative(process.cwd(), filePath)); + } + } + } + + expect(offenders).toEqual([]); + }); + + it("keeps plugin-sdk channel-core free of chat metadata bootstrap imports", () => { + const source = fs.readFileSync(path.resolve("src/plugin-sdk/channel-core.ts"), "utf8"); + + expect(source.includes("../channels/chat-meta.js")).toBe(false); + expect(source.includes("getChatChannelMeta")).toBe(false); + }); + + it("keeps bundled hot runtime barrels off the broad core SDK surface", () => { + const offenders = [ + "extensions/googlechat/runtime-api.ts", + "extensions/irc/src/runtime-api.ts", + "extensions/matrix/src/runtime-api.ts", + ].filter((filePath) => + fs.readFileSync(path.resolve(filePath), "utf8").includes("openclaw/plugin-sdk/core"), + ); + + expect(offenders).toEqual([]); + }); + + it("keeps runtime helper surfaces off bootstrap-registry", () => { + const offenders = [ + "src/config/markdown-tables.ts", + "src/config/sessions/group.ts", + "src/channels/plugins/setup-helpers.ts", + "src/plugin-sdk/extension-shared.ts", + ].filter((filePath) => + fs.readFileSync(path.resolve(filePath), "utf8").includes("bootstrap-registry.js"), + ); + + expect(offenders).toEqual([]); + }); + + it("keeps extension-shared off the broad runtime barrel", () => { + const source = fs.readFileSync(path.resolve("src/plugin-sdk/extension-shared.ts"), "utf8"); + + expect(source.includes('from "./runtime.js"')).toBe(false); + }); + + it("keeps nextcloud-talk's private SDK surface off the broad runtime barrel", () => { + const source = fs.readFileSync(path.resolve("src/plugin-sdk/nextcloud-talk.ts"), "utf8"); + + expect(source.includes('from "./runtime.js"')).toBe(false); + }); + + it("keeps bundled doctor surfaces off the broad runtime barrel", () => { + const offenders = [ + "extensions/discord/src/doctor.ts", + "extensions/matrix/src/doctor.ts", + "extensions/slack/src/doctor.ts", + "extensions/telegram/src/doctor.ts", + "extensions/zalouser/src/doctor.ts", + ].filter((filePath) => + fs + .readFileSync(path.resolve(filePath), "utf8") + .includes('from "openclaw/plugin-sdk/runtime"'), + ); + + expect(offenders).toEqual([]); + }); }); diff --git a/src/channels/plugins/bundled.ts b/src/channels/plugins/bundled.ts index 551b7a89a05..b801de61ddf 100644 --- a/src/channels/plugins/bundled.ts +++ b/src/channels/plugins/bundled.ts @@ -242,8 +242,9 @@ function loadGeneratedBundledChannelEntries(): readonly GeneratedBundledChannelE ...(setupEntry ? { setupEntry } : {}), }); } catch (error) { + const detail = error instanceof Error ? error.message : String(error); log.warn( - `[channels] failed to load bundled channel ${manifest.id} from ${candidate.source}: ${String(error)}`, + `[channels] failed to load bundled channel ${manifest.id} from ${candidate.source}: ${detail}`, ); } } diff --git a/src/channels/plugins/setup-helpers.ts b/src/channels/plugins/setup-helpers.ts index cf5760cf202..9c7dc3fe868 100644 --- a/src/channels/plugins/setup-helpers.ts +++ b/src/channels/plugins/setup-helpers.ts @@ -1,7 +1,7 @@ import { z, type ZodType } from "zod"; import type { OpenClawConfig } from "../../config/config.js"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js"; -import { getBootstrapChannelPlugin } from "./bootstrap-registry.js"; +import { getChannelPlugin } from "./registry.js"; import type { ChannelSetupAdapter } from "./types.adapters.js"; import type { ChannelSetupInput } from "./types.core.js"; @@ -417,7 +417,7 @@ type ChannelSetupPromotionSurface = { }; function getChannelSetupPromotionSurface(channelKey: string): ChannelSetupPromotionSurface | null { - const setup = getBootstrapChannelPlugin(channelKey)?.setup; + const setup = getChannelPlugin(channelKey)?.setup; if (!setup || typeof setup !== "object") { return null; } diff --git a/src/config/markdown-tables.ts b/src/config/markdown-tables.ts index 578c1dd135b..3302a7652f6 100644 --- a/src/config/markdown-tables.ts +++ b/src/config/markdown-tables.ts @@ -1,5 +1,6 @@ -import { listBootstrapChannelPlugins } from "../channels/plugins/bootstrap-registry.js"; import { normalizeChannelId } from "../channels/plugins/index.js"; +import { listChannelPlugins } from "../channels/plugins/registry.js"; +import { getActivePluginChannelRegistryVersion } from "../plugins/runtime.js"; import { resolveAccountEntry } from "../routing/account-lookup.js"; import { normalizeAccountId } from "../routing/session-key.js"; import type { OpenClawConfig } from "./config.js"; @@ -17,7 +18,7 @@ type MarkdownConfigSection = MarkdownConfigEntry & { function buildDefaultTableModes(): Map { return new Map( - listBootstrapChannelPlugins() + listChannelPlugins() .flatMap((plugin) => { const defaultMarkdownTableMode = plugin.messaging?.defaultMarkdownTableMode; return defaultMarkdownTableMode ? [[plugin.id, defaultMarkdownTableMode] as const] : []; @@ -27,9 +28,14 @@ function buildDefaultTableModes(): Map { } let cachedDefaultTableModes: Map | null = null; +let cachedDefaultTableModesRegistryVersion: number | null = null; function getDefaultTableModes(): Map { - cachedDefaultTableModes ??= buildDefaultTableModes(); + const registryVersion = getActivePluginChannelRegistryVersion(); + if (!cachedDefaultTableModes || cachedDefaultTableModesRegistryVersion !== registryVersion) { + cachedDefaultTableModes = buildDefaultTableModes(); + cachedDefaultTableModesRegistryVersion = registryVersion; + } return cachedDefaultTableModes; } diff --git a/src/config/sessions/group.ts b/src/config/sessions/group.ts index b690343989c..772b6249198 100644 --- a/src/config/sessions/group.ts +++ b/src/config/sessions/group.ts @@ -1,5 +1,5 @@ import type { MsgContext } from "../../auto-reply/templating.js"; -import { listBootstrapChannelPlugins } from "../../channels/plugins/bootstrap-registry.js"; +import { listChannelPlugins } from "../../channels/plugins/registry.js"; import { normalizeHyphenSlug } from "../../shared/string-normalization.js"; import { listDeliverableMessageChannels } from "../../utils/message-channel.js"; import type { GroupKeyResolution } from "./types.js"; @@ -11,7 +11,7 @@ type LegacyGroupSessionSurface = { }; function resolveLegacyGroupSessionKey(ctx: MsgContext): GroupKeyResolution | null { - for (const plugin of listBootstrapChannelPlugins()) { + for (const plugin of listChannelPlugins()) { const resolved = ( plugin.messaging as LegacyGroupSessionSurface | undefined )?.resolveLegacyGroupSessionKey?.(ctx); diff --git a/src/plugin-sdk/acp-binding-runtime.ts b/src/plugin-sdk/acp-binding-runtime.ts new file mode 100644 index 00000000000..7b08ffe2116 --- /dev/null +++ b/src/plugin-sdk/acp-binding-runtime.ts @@ -0,0 +1,5 @@ +// Narrow ACP binding helpers for plugins that need persistent ACP setup state +// without importing the broad core SDK surface. + +export { ensureConfiguredAcpBindingReady } from "../acp/persistent-bindings.lifecycle.js"; +export { resolveConfiguredAcpBindingRecord } from "../acp/persistent-bindings.resolve.js"; diff --git a/src/plugin-sdk/channel-core.ts b/src/plugin-sdk/channel-core.ts index 99876eba054..cd50b9335b9 100644 --- a/src/plugin-sdk/channel-core.ts +++ b/src/plugin-sdk/channel-core.ts @@ -25,11 +25,16 @@ import type { ReplyToMode } from "../config/types.base.js"; import { buildOutboundBaseSessionKey } from "../infra/outbound/base-session-key.js"; import type { OutboundDeliveryResult } from "../infra/outbound/deliver.js"; import type { PluginRuntime } from "../plugins/runtime/types.js"; -import type { OpenClawPluginApi } from "../plugins/types.js"; +import type { OpenClawPluginApi, PluginCommandContext } from "../plugins/types.js"; export type { ChannelConfigUiHint, ChannelPlugin }; export type { OpenClawConfig }; export type { PluginRuntime }; +export type { OpenClawPluginApi, PluginCommandContext }; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { clearAccountEntryFields } from "../channels/plugins/config-helpers.js"; +export { parseOptionalDelimitedEntries } from "../channels/plugins/helpers.js"; +export { tryReadSecretFileSync } from "../infra/secret-file.js"; export type ChannelOutboundSessionRouteParams = Parameters< NonNullable diff --git a/src/plugin-sdk/channel-policy.ts b/src/plugin-sdk/channel-policy.ts index 4c986768334..8c51f8eab68 100644 --- a/src/plugin-sdk/channel-policy.ts +++ b/src/plugin-sdk/channel-policy.ts @@ -46,6 +46,10 @@ export { resolveDmGroupAccessWithLists, resolveEffectiveAllowFromLists, } from "../security/dm-policy-shared.js"; +export { + evaluateGroupRouteAccessForPolicy, + resolveSenderScopedGroupPolicy, +} from "./group-access.js"; export { createAllowlistProviderRestrictSendersWarningCollector }; export type ChannelMutableAllowlistCandidate = { diff --git a/src/plugin-sdk/extension-shared.ts b/src/plugin-sdk/extension-shared.ts index 346721df023..8ce5337f603 100644 --- a/src/plugin-sdk/extension-shared.ts +++ b/src/plugin-sdk/extension-shared.ts @@ -1,6 +1,6 @@ import type { z } from "zod"; import { runPassiveAccountLifecycle } from "./channel-lifecycle.core.js"; -import { createLoggerBackedRuntime } from "./runtime.js"; +import { createLoggerBackedRuntime } from "./runtime-logger.js"; export { safeParseJsonWithSchema, safeParseWithSchema } from "../utils/zod-parse.js"; type PassiveChannelStatusSnapshot = { diff --git a/src/plugin-sdk/googlechat-runtime-shared.ts b/src/plugin-sdk/googlechat-runtime-shared.ts new file mode 100644 index 00000000000..93cea9e2f29 --- /dev/null +++ b/src/plugin-sdk/googlechat-runtime-shared.ts @@ -0,0 +1,4 @@ +// Narrow Google Chat runtime exports used by the bundled Google Chat plugin. + +export type { GoogleChatAccountConfig, GoogleChatConfig } from "../config/types.js"; +export { GoogleChatConfigSchema } from "../config/zod-schema.providers-core.js"; diff --git a/src/plugin-sdk/nextcloud-talk.ts b/src/plugin-sdk/nextcloud-talk.ts index 19fe60a9d4a..ab400e3f036 100644 --- a/src/plugin-sdk/nextcloud-talk.ts +++ b/src/plugin-sdk/nextcloud-talk.ts @@ -103,7 +103,7 @@ export { resolveOutboundMediaUrls, } from "./reply-payload.js"; export { dispatchInboundReplyWithBase } from "./inbound-reply-dispatch.js"; -export { createLoggerBackedRuntime } from "./runtime.js"; +export { createLoggerBackedRuntime } from "./runtime-logger.js"; export { buildBaseChannelStatusSummary, buildRuntimeAccountStatusSnapshot, diff --git a/src/plugin-sdk/runtime-doctor.ts b/src/plugin-sdk/runtime-doctor.ts new file mode 100644 index 00000000000..6e3352d2be0 --- /dev/null +++ b/src/plugin-sdk/runtime-doctor.ts @@ -0,0 +1,6 @@ +export { collectProviderDangerousNameMatchingScopes } from "../config/dangerous-name-matching.js"; +export { + detectPluginInstallPathIssue, + formatPluginInstallPathIssue, +} from "../infra/plugin-install-path-warnings.js"; +export { removePluginFromConfig } from "../plugins/uninstall.js"; diff --git a/src/plugin-sdk/runtime-logger.ts b/src/plugin-sdk/runtime-logger.ts new file mode 100644 index 00000000000..92b1bfcba71 --- /dev/null +++ b/src/plugin-sdk/runtime-logger.ts @@ -0,0 +1,80 @@ +import { format } from "node:util"; +import type { OutputRuntimeEnv, RuntimeEnv } from "../runtime.js"; + +/** Minimal logger contract accepted by runtime-adapter helpers. */ +type LoggerLike = { + info: (message: string) => void; + error: (message: string) => void; +}; + +/** Adapt a simple logger into the RuntimeEnv contract used by shared plugin SDK helpers. */ +export function createLoggerBackedRuntime(params: { + logger: LoggerLike; + exitError?: (code: number) => Error; +}): OutputRuntimeEnv { + return { + log: (...args) => { + params.logger.info(format(...args)); + }, + error: (...args) => { + params.logger.error(format(...args)); + }, + writeStdout: (value) => { + params.logger.info(value); + }, + writeJson: (value, space = 2) => { + params.logger.info(JSON.stringify(value, null, space > 0 ? space : undefined)); + }, + exit: (code: number): never => { + throw params.exitError?.(code) ?? new Error(`exit ${code}`); + }, + }; +} + +/** Reuse an existing runtime when present, otherwise synthesize one from the provided logger. */ +export function resolveRuntimeEnv(params: { + runtime: RuntimeEnv; + logger: LoggerLike; + exitError?: (code: number) => Error; +}): RuntimeEnv; +export function resolveRuntimeEnv(params: { + runtime?: undefined; + logger: LoggerLike; + exitError?: (code: number) => Error; +}): OutputRuntimeEnv; +export function resolveRuntimeEnv(params: { + runtime?: RuntimeEnv; + logger: LoggerLike; + exitError?: (code: number) => Error; +}): RuntimeEnv | OutputRuntimeEnv { + return params.runtime ?? createLoggerBackedRuntime(params); +} + +/** Resolve a runtime that treats exit requests as unsupported errors instead of process termination. */ +export function resolveRuntimeEnvWithUnavailableExit(params: { + runtime: RuntimeEnv; + logger: LoggerLike; + unavailableMessage?: string; +}): RuntimeEnv; +export function resolveRuntimeEnvWithUnavailableExit(params: { + runtime?: undefined; + logger: LoggerLike; + unavailableMessage?: string; +}): OutputRuntimeEnv; +export function resolveRuntimeEnvWithUnavailableExit(params: { + runtime?: RuntimeEnv; + logger: LoggerLike; + unavailableMessage?: string; +}): RuntimeEnv | OutputRuntimeEnv { + if (params.runtime) { + return resolveRuntimeEnv({ + runtime: params.runtime, + logger: params.logger, + exitError: () => new Error(params.unavailableMessage ?? "Runtime exit not available"), + }); + } + return resolveRuntimeEnv({ + logger: params.logger, + exitError: () => new Error(params.unavailableMessage ?? "Runtime exit not available"), + }); +} diff --git a/src/plugin-sdk/runtime-secret-resolution.ts b/src/plugin-sdk/runtime-secret-resolution.ts new file mode 100644 index 00000000000..d1be75fae8b --- /dev/null +++ b/src/plugin-sdk/runtime-secret-resolution.ts @@ -0,0 +1,2 @@ +export { resolveCommandSecretRefsViaGateway } from "../cli/command-secret-gateway.js"; +export { getChannelsCommandSecretTargetIds } from "../cli/command-secret-targets.js"; diff --git a/src/plugin-sdk/runtime.ts b/src/plugin-sdk/runtime.ts index 84fcb415334..b1b5b823c05 100644 --- a/src/plugin-sdk/runtime.ts +++ b/src/plugin-sdk/runtime.ts @@ -1,9 +1,13 @@ -import { format } from "node:util"; import type { OutputRuntimeEnv, RuntimeEnv } from "../runtime.js"; export type { OutputRuntimeEnv, RuntimeEnv } from "../runtime.js"; export { createNonExitingRuntime, defaultRuntime } from "../runtime.js"; export { resolveCommandSecretRefsViaGateway } from "../cli/command-secret-gateway.js"; export { getChannelsCommandSecretTargetIds } from "../cli/command-secret-targets.js"; +export { + createLoggerBackedRuntime, + resolveRuntimeEnv, + resolveRuntimeEnvWithUnavailableExit, +} from "./runtime-logger.js"; export { danger, info, @@ -27,81 +31,3 @@ export { export { collectProviderDangerousNameMatchingScopes } from "../config/dangerous-name-matching.js"; export { registerUnhandledRejectionHandler } from "../infra/unhandled-rejections.js"; export { removePluginFromConfig } from "../plugins/uninstall.js"; - -/** Minimal logger contract accepted by runtime-adapter helpers. */ -type LoggerLike = { - info: (message: string) => void; - error: (message: string) => void; -}; - -/** Adapt a simple logger into the RuntimeEnv contract used by shared plugin SDK helpers. */ -export function createLoggerBackedRuntime(params: { - logger: LoggerLike; - exitError?: (code: number) => Error; -}): OutputRuntimeEnv { - return { - log: (...args) => { - params.logger.info(format(...args)); - }, - error: (...args) => { - params.logger.error(format(...args)); - }, - writeStdout: (value) => { - params.logger.info(value); - }, - writeJson: (value, space = 2) => { - params.logger.info(JSON.stringify(value, null, space > 0 ? space : undefined)); - }, - exit: (code: number): never => { - throw params.exitError?.(code) ?? new Error(`exit ${code}`); - }, - }; -} - -/** Reuse an existing runtime when present, otherwise synthesize one from the provided logger. */ -export function resolveRuntimeEnv(params: { - runtime: RuntimeEnv; - logger: LoggerLike; - exitError?: (code: number) => Error; -}): RuntimeEnv; -export function resolveRuntimeEnv(params: { - runtime?: undefined; - logger: LoggerLike; - exitError?: (code: number) => Error; -}): OutputRuntimeEnv; -export function resolveRuntimeEnv(params: { - runtime?: RuntimeEnv; - logger: LoggerLike; - exitError?: (code: number) => Error; -}): RuntimeEnv | OutputRuntimeEnv { - return params.runtime ?? createLoggerBackedRuntime(params); -} - -/** Resolve a runtime that treats exit requests as unsupported errors instead of process termination. */ -export function resolveRuntimeEnvWithUnavailableExit(params: { - runtime: RuntimeEnv; - logger: LoggerLike; - unavailableMessage?: string; -}): RuntimeEnv; -export function resolveRuntimeEnvWithUnavailableExit(params: { - runtime?: undefined; - logger: LoggerLike; - unavailableMessage?: string; -}): OutputRuntimeEnv; -export function resolveRuntimeEnvWithUnavailableExit(params: { - runtime?: RuntimeEnv; - logger: LoggerLike; - unavailableMessage?: string; -}): RuntimeEnv | OutputRuntimeEnv { - if (params.runtime) { - return resolveRuntimeEnv({ - runtime: params.runtime, - logger: params.logger, - exitError: () => new Error(params.unavailableMessage ?? "Runtime exit not available"), - }); - } - return resolveRuntimeEnv({ - logger: params.logger, - exitError: () => new Error(params.unavailableMessage ?? "Runtime exit not available"), - }); -} diff --git a/src/plugin-sdk/secret-input.ts b/src/plugin-sdk/secret-input.ts index b1bcdd7c78d..867a9d168e5 100644 --- a/src/plugin-sdk/secret-input.ts +++ b/src/plugin-sdk/secret-input.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { hasConfiguredSecretInput, + isSecretRef, normalizeResolvedSecretInputString, normalizeSecretInputString, } from "../config/types.secrets.js"; @@ -11,6 +12,7 @@ export type { SecretInput } from "../config/types.secrets.js"; export { buildSecretInputSchema, hasConfiguredSecretInput, + isSecretRef, normalizeResolvedSecretInputString, normalizeSecretInput, normalizeSecretInputString,