fix: break bundled channel bootstrap cycles

This commit is contained in:
Peter Steinberger
2026-04-05 14:12:48 +01:00
parent 4fedc5c105
commit 89e8c8672c
87 changed files with 476 additions and 212 deletions

View File

@@ -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";

View File

@@ -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<ChannelMessagingAdapter["resolveOutboundSessionRoute"]>

View File

@@ -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 = {

View File

@@ -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 = {

View File

@@ -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";

View File

@@ -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,

View File

@@ -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";

View File

@@ -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"),
});
}

View File

@@ -0,0 +1,2 @@
export { resolveCommandSecretRefsViaGateway } from "../cli/command-secret-gateway.js";
export { getChannelsCommandSecretTargetIds } from "../cli/command-secret-targets.js";

View File

@@ -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"),
});
}

View File

@@ -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,