refactor: burn export name collision debt (#121767)

* refactor(tasks): disambiguate lifecycle helpers

* refactor(channels): clarify account and id helpers

* refactor(media): separate SDK facades from cores

* refactor(auto-reply): consolidate command helpers

* refactor(cli): disambiguate registration helpers

* refactor(gateway): clarify runtime and test helpers

* chore(scripts): burn resolved collision debt

* fix(refactor): update remaining core callers

* fix(refactor): update remaining UI callers

* chore(plugin-sdk): refresh API baseline
This commit is contained in:
Peter Steinberger
2026-08-10 18:17:13 -07:00
committed by GitHub
parent 1e1f1b1d54
commit dd2aedf08f
154 changed files with 753 additions and 1071 deletions
+17 -17
View File
@@ -53,7 +53,7 @@
{"closureHash":"ff3c4616cd6212a6d698831a8b287ad87e3968c8663f4090d095bb30ec40fc1c","declaration":"export function abortAndDrainAgentHarnessRun(params: { sessionId: string; sessionKey?: string; settleMs?: number; forceClear?: boolean; reason?: string; }): Promise<AbortAndDrainEmbeddedAgentRunResult>;","entrypoint":"agent-harness","exportName":"abortAndDrainAgentHarnessRun","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"58989e3fa91eecf2e05202e36548e6e64a3b9219e83154bd99866c851604e34e","declaration":"export function createAgentToolResultMiddlewareRunner(ctx: AgentToolResultMiddlewareContext, handlers?: AgentToolResultMiddleware[]): { applyToolResultMiddleware(event: AgentToolResultMiddlewareEvent): Promise<OpenClawAgentToolResult>; };","entrypoint":"agent-harness","exportName":"createAgentToolResultMiddlewareRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"b8f6355d7ad1700aceecddaa6e9ccf43091a792d5b481a1ee3f55294a881a67d","declaration":"export function createCodexAppServerToolResultExtensionRunner(ctx: CodexAppServerExtensionContext, factories?: CodexAppServerExtensionFactory[]): { applyToolResultExtensions(event: CodexAppServerToolResultEvent): Promise<AgentToolResult<unknown>>; };","entrypoint":"agent-harness","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"b1fbc2d6c6a6725072af0ec97151814e998d59e19536f2567dbdcc42cd12765a","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"9cfaaa0bb0d08eb8d47932492a7874fb138705087508d7b361b049da2c2e350b","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"13649ee853485319e7449fda25c106b3f3f53d3090e53cdbb28e220a8529eb80","declaration":"export function disposeRegisteredAgentHarnesses(): Promise<void>;","entrypoint":"agent-harness","exportName":"disposeRegisteredAgentHarnesses","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"f255a91162ece4c239bb8fa745efa14a1054bc024a291e9954f75f239b2b87c3","declaration":"export function resolveActiveEmbeddedRunSessionId(sessionKey: string): string | undefined;","entrypoint":"agent-harness","exportName":"resolveActiveEmbeddedRunSessionId","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
{"closureHash":"27d9f61df9ccf68615cb2002a6da891e36ab0c07623bc37c4d07aa980b446881","declaration":"export function resolveWebSearchToolPolicy(params: WebSearchToolPolicyParams): WebSearchToolPolicyResolution;","entrypoint":"agent-harness","exportName":"resolveWebSearchToolPolicy","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"}
@@ -1097,7 +1097,7 @@
{"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"}
{"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"}
{"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-message","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"}
{"closureHash":"5236937315f09d137a86caad72e09219503aa2d4b2d66fa004e18c51455cabe7","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"}
{"closureHash":"d420856f586028947a5239f5f44c78f13d611039f1e5292438eae0b5e1f4133e","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"}
{"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-message","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"}
{"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-message","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"}
{"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-message","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"}
@@ -1226,7 +1226,7 @@
{"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"}
{"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"}
{"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-outbound","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"}
{"closureHash":"5236937315f09d137a86caad72e09219503aa2d4b2d66fa004e18c51455cabe7","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"}
{"closureHash":"d420856f586028947a5239f5f44c78f13d611039f1e5292438eae0b5e1f4133e","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"}
{"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-outbound","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"}
{"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-outbound","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"}
{"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-outbound","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"}
@@ -2354,7 +2354,7 @@
{"closureHash":"98e0cc16352b7dfcceb4957f8cd2acfe3c2b3acb223c42a5cfb885e088fcb04c","declaration":"export function resolveInboundReplyDispatchCounts(result: ChannelTurnDispatchResultLike): Record<ReplyDispatchKind, number>;","entrypoint":"inbound-reply-dispatch","exportName":"resolveInboundReplyDispatchCounts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"}
{"closureHash":"9d503d05e408ddd1a1c373e3c4485b1f9acff4c240fdc241840a2cfa8b55c3a7","declaration":"export function runChannelInboundEvent<TRaw, TDispatchResult = DispatchFromConfigResult>(params: RunChannelTurnParams<TRaw, TDispatchResult, ChannelProviderOwnedMessageSendingDeliveryAdapter>): Promise<ChannelTurnResult<TDispatchResult>>;\nexport function runChannelInboundEvent<TRaw, TDispatchResult = DispatchFromConfigResult>(params: ChannelInboundEventRunnerParams<TRaw, TDispatchResult>): Promise<ChannelTurnResult<TDispatchResult>>;","entrypoint":"inbound-reply-dispatch","exportName":"runChannelInboundEvent","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"}
{"closureHash":"2c68496a174872b31aaf1ac8fad2789deb79d490c5ffbcb157325f1c95d1b51f","declaration":"export function runPreparedInboundReply<TDispatchResult>(params: PreparedChannelTurn<TDispatchResult>): Promise<ChannelTurnResult<TDispatchResult>>;","entrypoint":"inbound-reply-dispatch","exportName":"runPreparedInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"}
{"closureHash":"5236937315f09d137a86caad72e09219503aa2d4b2d66fa004e18c51455cabe7","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"}
{"closureHash":"d420856f586028947a5239f5f44c78f13d611039f1e5292438eae0b5e1f4133e","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"}
{"closureHash":"278dc8a410230012ddbc3552ec621a224e6f7c5dd4cd3904c943ac98dd4259e4","declaration":"export type AssembledInboundReply = AssembledChannelTurn;","entrypoint":"inbound-reply-dispatch","exportName":"AssembledInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"}
{"closureHash":"3de0d6d1bb8f9a83bd1c6e57aa8618e3fea71054236cd530c555e348bd0b7702","declaration":"export type ChannelBotLoopProtectionFacts = ChannelBotLoopProtectionFacts;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelBotLoopProtectionFacts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"}
{"closureHash":"f0da845bbdf49b30f6718a4b7ff012a0536deb98f65418583555dc90825797ca","declaration":"export type ChannelInboundDroppedHistoryOptions = ChannelTurnDroppedHistoryOptions;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelInboundDroppedHistoryOptions","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"}
@@ -3189,19 +3189,19 @@
{"closureHash":"50394942e0a454c742e80a4f3c8739c80258b387ade498eb5aed66df887108be","declaration":"export function callMeetingBrowserProxyOnNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; } & MeetingBrowserRequestParams): Promise<unknown>;","entrypoint":"meeting-runtime","exportName":"callMeetingBrowserProxyOnNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"c5fcd1d157edcb4773235adfaf8051e3ec7ca428cb7916b6d55f2511affab56c","declaration":"export function convertMeetingBridgeAudioForStt(audio: Buffer, audioFormat: MeetingRealtimeAudioFormat): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingBridgeAudioForStt","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"aa9063c27c5ff714d3653571c4a2a71e9d2eea5609b161f03e4738e15411358b","declaration":"export function convertMeetingTtsAudioForBridge(audio: Buffer, sampleRate: number, audioFormat: MeetingRealtimeAudioFormat, outputFormat?: string, platformName?: string): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingTtsAudioForBridge","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"848a8280cc071320c1e62520382920bd4d3653b315d3e8b19df6d7aa787aa1b3","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"c70707c4e2171a912f22899350eea3d71a5969eacd50dc1d59f06f3bb86acbd9","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"9cb63eefd2e5a70aea960bf17fcf570ef02a2d7b5afd5ad9451802964c653fcf","declaration":"export function createMeetingBrowserNodeCaller(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; }): MeetingBrowserRequestCaller;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeCaller","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"f244ca8c47f556c9f388953cf9a7581c7d4d413af93e0dfa1462779e6a687a7c","declaration":"export function createMeetingBrowserNodeInvokePolicy(options: MeetingBrowserNodePolicyOptions): OpenClawPluginNodeInvokePolicy;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeInvokePolicy","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"1aa4e3ff39a2cbe162421c62b1fa4a362973381d4d9ff15c671249b1ebd566bc","declaration":"export function createMeetingNodeHost(options: MeetingNodeHostOptions): { handleCommand(paramsJSON?: string | null): Promise<string>; };","entrypoint":"meeting-runtime","exportName":"createMeetingNodeHost","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"4932698dbb72134c12cabaae29be0fa82328cd46bd61d8aa3f087c78768486fd","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise<void>; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"70a5384f9a5e217338410ae45f1b93bb431ccb0c2b9c1a40bc5e50bc68a2449b","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise<void>; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"9124db05923060c467edb149bd8abdc8be1d00d00f867cf84600972923a58489","declaration":"export function createMeetingSession<TTransport extends string, TMode extends string, TToolPolicy extends string>(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { provider?: string; voiceProvider?: string; transcriptionProvider?: string; model?: string; toolPolicy: TToolPolicy; }; }; resolved: MeetingResolvedJoin<TTransport, TMode>; createdAt: string; }): MeetingSessionRecord<TTransport, TMode, { enabled: boolean; strategy: string; provider: string | undefined; model: string | undefined; transcriptionProvider: string | undefined; toolPolicy: TToolPolicy; }>;","entrypoint":"meeting-runtime","exportName":"createMeetingSession","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"fb276e07e395ab19177b3d7967fd0a8fcda79130883f15092a4a306b826481b9","declaration":"export function createMeetingSetupStatus(checks: MeetingSetupCheck[]): MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"createMeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"93c4bb70429a2739151e6f900e67bed81f3cd8f597811220e790341edb0d6008","declaration":"export function createMeetingVoiceCallGateway(params: { config: MeetingVoiceCallConfig; runtime: PluginRuntime; surface: MeetingVoiceCallSurface; connectClient: (params: { config: MeetingVoiceCallConfig; surface: MeetingVoiceCallSurface; }) => Promise<MeetingVoiceCallGatewayClient>; }): MeetingVoiceCallGateway;","entrypoint":"meeting-runtime","exportName":"createMeetingVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"8390fe7fe0b6ab44150cccce3a11b05207fe2253f5b955d2fb3d7aa6588acffe","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"bc1315a8130ef57fe62d31d54f35b7a9d3085ae5bae65a5dc23a83a66c36436a","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"c0987b15a391a92d53d3e4e12b61eb122f9547fcf4f45478cdd3c5a8973a3e52","declaration":"export function endMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise<void>;","entrypoint":"meeting-runtime","exportName":"endMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"b3ebc10fe7ab372e1317eaa8f78621cf277bba1e33fda57acf2254f6759d1e9d","declaration":"export function getMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise<MeetingVoiceCallStatusResult>;","entrypoint":"meeting-runtime","exportName":"getMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"aac088df8e80d9ce89c45feccdb04ace3ae4417b3fcdd0f058410ddf25c96b46","declaration":"export function isMeetingVoiceCallMissingError(error: unknown): boolean;","entrypoint":"meeting-runtime","exportName":"isMeetingVoiceCallMissingError","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"e14386402c25ad496352bcf803e17218ed648e6b5f34514c7f07c9091f2466dd","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise<MeetingVoiceCallJoinResult>;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"6f5d639ae00dcc0d07499c27d21bf1f865139a81ddaa315468991d7ba2f35c7f","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise<MeetingVoiceCallJoinResult>;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"bac9621cd025754fbcd4c21409b06eb0503405db81f35cac993aaf0b881ab3e1","declaration":"export function leaveMeetingWithBrowser<Session, Mode extends string, Health extends MeetingBrowserHealth, Transcript extends MeetingTranscriptSnapshot>(params: { adapter: BrowserAdapter<Session, Mode, Health, Transcript>; callBrowser: MeetingBrowserRequestCaller; launch: boolean; meetingSessionId?: string; meetingUrl: string; tab: MeetingBrowserTab; timeoutMs: number; }): Promise<{ left: boolean; note: string; }>;","entrypoint":"meeting-runtime","exportName":"leaveMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"c7b1aeac134b2070d053adf33026d876998b852ccd65cd2c9667119b1a1abee2","declaration":"export function openMeetingWithBrowser<Session extends MeetingBrowserJoinSession<Mode>, Mode extends string, Health extends MeetingBrowserHealth & { browserTitle?: string; browserUrl?: string; notes?: string[]; }, Transcript extends MeetingTranscriptSnapshot>(params: { adapter: BrowserAdapter<Session, Mode, Health, Transcript>; callBrowser: MeetingBrowserRequestCaller; config: MeetingBrowserControllerConfig; session: Session; }): Promise<{ launched: boolean; browser?: Health; tab?: MeetingBrowserTab; }>;","entrypoint":"meeting-runtime","exportName":"openMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"34858979bd248799c2215d9c7bdd5d4a6b27660c9173bfca2e50dd4373ac27db","declaration":"export function readMeetingBrowserTab(result: unknown): MeetingBrowserCandidateTab | undefined;","entrypoint":"meeting-runtime","exportName":"readMeetingBrowserTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
@@ -3212,8 +3212,8 @@
{"closureHash":"56874c5b2ced5af647b1dff296c931f0d8b85b1318e98c741aa88b58a9c5c606","declaration":"export function resolveMeetingBrowserNodeInfo(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise<MeetingBrowserNodeInfo>;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNodeInfo","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"f21196c9ea8ab90248ffdcdef3e942f1247ee2b9064ddb9757fffe352362c779","declaration":"export function resolveMeetingRealtimeAudioFormat(audioFormat: MeetingRealtimeAudioFormat): RealtimeVoiceAudioFormat;","entrypoint":"meeting-runtime","exportName":"resolveMeetingRealtimeAudioFormat","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"521dc5c262524a709cdd27cdc88e95004073da8223537bcbc73d5d423172dc2b","declaration":"export function speakMeetingViaVoiceCallGateway(params: { gateway: MeetingVoiceCallGateway; callId: string; message: string; }): Promise<void>;","entrypoint":"meeting-runtime","exportName":"speakMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"795a6bda2c41fecbb0f7d5e500d6ce18ddb062a1667f9be0f769d5aba14c5f91","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise<MeetingRealtimeAudioEngineHandle>;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"a350254ea889399f103718694e4c16eb3246849e288e18c115cd60dba78d6a63","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise<void>; }): Promise<MeetingRealtimeAudioEngineHandle>;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"0e660fb72f507995ee218f6cb63a392ddac22e9fcb98b4a5b9b577d6afbd2377","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise<MeetingRealtimeAudioEngineHandle>;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"690d10ea23a39c93ded9782825b020ebffa20d7a979ea5274773ef414d867529","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise<void>; }): Promise<MeetingRealtimeAudioEngineHandle>;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"}
{"closureHash":"663b9c77231b21af697efd5042e22d1c33e9ee972adeb312ad86d81a2b2e36f7","declaration":"export type MeetingAgentConsultParams = MeetingAgentConsultParams;","entrypoint":"meeting-runtime","exportName":"MeetingAgentConsultParams","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"adf0745c611bf737fc28978d766fc2a25b7104e71b6b2fed4e9b95e519c7b115","declaration":"export type MeetingBrowserCandidateTab = MeetingBrowserCandidateTab;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserCandidateTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"59b1526172b7491b85f14f13c1ee26d8d6726f33093770748580c767b1689a17","declaration":"export type MeetingBrowserControllerConfig = MeetingBrowserControllerConfig;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserControllerConfig","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
@@ -3245,7 +3245,7 @@
{"closureHash":"8244b408803f57cf2004157e96f2ce11bb036cdf864123b15ba2fac7f03b5d43","declaration":"export type MeetingSessionRuntimeHandles<THealth extends MeetingBrowserHealth> = MeetingSessionRuntimeHandles<THealth>;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeHandles","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"aa8054fc2c442891197e89bdad61e79999ea15d813c4b127fb6150607b9e67e7","declaration":"export type MeetingSessionRuntimeJoinContext<TSession extends MeetingSessionRecord<TTransport, TMode>, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab> = MeetingSessionRuntimeJoinContext<TSession, TTransport, TMode, THealth, TTab>;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeJoinContext","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"325241724edd38da439c5df03d225e2a7cb8e56d817e98ed7c37850656d3744b","declaration":"export type MeetingSessionRuntimeMessages<TSpeechBlockedReason extends string> = MeetingSessionRuntimeMessages<TSpeechBlockedReason>;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeMessages","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"358a20ffa7f1ac9cde7431a628c546817df5212955b9cb634699e9c9a065c246","declaration":"export type MeetingSessionRuntimeOptions<TSession extends MeetingSessionRecord<TTransport, TMode>, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth<TManualReason, TSpeechBlockedReason>, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions<TSession, TRequest, TTransport, TMode, THealth, TTab, TManualReason, TSpeechBlockedReason>;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"d5cfb8ce0591d2c56f9c7d2962a3c103affaa560f066b3a9ec19e96104883458","declaration":"export type MeetingSessionRuntimeOptions<TSession extends MeetingSessionRecord<TTransport, TMode>, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth<TManualReason, TSpeechBlockedReason>, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions<TSession, TRequest, TTransport, TMode, THealth, TTab, TManualReason, TSpeechBlockedReason>;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"d3c730cba02d30512c4cdae6e2367c662982e2c25671833ecd8701283924c642","declaration":"export type MeetingSessionState = MeetingSessionState;","entrypoint":"meeting-runtime","exportName":"MeetingSessionState","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"2496931157bf64fdb16013172ab9c023e60c5f85b98f46a3ee9532ce58d636d6","declaration":"export type MeetingSetupCheck = MeetingSetupCheck;","entrypoint":"meeting-runtime","exportName":"MeetingSetupCheck","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"f0aed6f7955a43fc387d8bbc072cb6276b0f2d18e7f829441a2ad45974bb3831","declaration":"export type MeetingSetupStatus = MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"MeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
@@ -3259,9 +3259,9 @@
{"closureHash":"20c70a94483aeddda4d1500cfcc5e71fab844b474ba4061c55d6c8693d40821b","declaration":"export type MeetingVoiceCallJoinResult = MeetingVoiceCallJoinResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallJoinResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"4fb2c5928aa6f809dd4c604d71c5c99cdfe3e98b6e9c1662601c9b4ad9738162","declaration":"export type MeetingVoiceCallStatusResult = MeetingVoiceCallStatusResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallStatusResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"5ef812397b6409a4ca228943dd1080661365959477b42e705a9aaa219757d14f","declaration":"export type MeetingVoiceCallSurface = MeetingVoiceCallSurface;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallSurface","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"}
{"closureHash":"b981b84a269682560b6ca79bf62628f44d1cd30584c6703263b427f2f8592737","declaration":"export interface MeetingPlatformAdapter<Session, Mode extends string, Health extends MeetingBrowserHealth, Transcript extends MeetingTranscriptSnapshot, CreateParams = never, CreateResult = never, DialInParams = never, DialInPlan = never> extends MeetingPlatformAdapterContract<Session, Mode, Health, Transcript, CreateParams, CreateResult, DialInParams, DialInPlan> {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"}
{"closureHash":"9b3952af9ca74d74b0ec98824cdc759023b134dacef29117fb907f7c5d5c7d1a","declaration":"export interface MeetingPlatformAdapter<Session, Mode extends string, Health extends MeetingBrowserHealth, Transcript extends MeetingTranscriptSnapshot, CreateParams = never, CreateResult = never, DialInParams = never, DialInPlan = never> extends MeetingPlatformAdapterContract<Session, Mode, Health, Transcript, CreateParams, CreateResult, DialInParams, DialInPlan> {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"}
{"closureHash":"79884bd1df1ea0d07d5ceb4c62d93c1ee744b75d31c94c988845869c0f3cbd2d","declaration":"export interface MeetingRealtimeAudioTransport {\n onFatal(handler: () => void): void;\n startInput(onAudio: (audio: Buffer) => void): void;\n beginOutput?(): void;\n stop(): Promise<void>;\n writeOutput(audio: Buffer): Promise<void>;\n clearOutput(): Promise<void>;\n dispose(): Promise<void>;\n getHealth?(): MeetingRealtimeAudioTransportHealth;\n startBargeInMonitor?(onBargeIn: (audio: Buffer) => boolean): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"}
{"closureHash":"74889426bdb2a90f11a40de44ec7399fb82d942d84eda3568aa23644c18dcfe1","declaration":"export class MeetingSessionRuntime<TSession extends MeetingSessionRecord<TTransport, TMode>, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth<TManualReason, TSpeechBlockedReason>, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map<string, TSession>;\n readonly #sessionLeaves: Map<string, Promise<MeetingSessionLeaveResult<TSession>>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map<string, () => Promise<void>>;\n readonly #sessionSpeakers: Map<string, (instructions?: string) => void>;\n readonly #sessionHealth: Map<string, () => Partial<THealth>>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts<TSession>;\n readonly #transcriptStore: MeetingSessionTranscriptStore<TSession>;\n constructor(private readonly options: MeetingSessionRuntimeOptions<TSession, TRequest, TTransport, TMode, THealth, TTab, TManualReason, TSpeechBlockedReason>);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise<TranscriptsStartResult>;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise<TranscriptsStopResult>;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin<TTransport, TMode>): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise<boolean>;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise<void>;\n async refreshCaptionHealth(session: TSession): Promise<void>;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin<TTransport, TMode>): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise<boolean>;\n async #rollbackFailedJoinSession(session: TSession): Promise<void>;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise<void>;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles<THealth>): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"}
{"closureHash":"1e14a81a141e1f34fc747e106e98538c67f53fe5e221883ce512f6863a6b53e3","declaration":"export class MeetingSessionRuntime<TSession extends MeetingSessionRecord<TTransport, TMode>, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth<TManualReason, TSpeechBlockedReason>, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map<string, TSession>;\n readonly #sessionLeaves: Map<string, Promise<MeetingSessionLeaveResult<TSession>>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map<string, () => Promise<void>>;\n readonly #sessionSpeakers: Map<string, (instructions?: string) => void>;\n readonly #sessionHealth: Map<string, () => Partial<THealth>>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts<TSession>;\n readonly #transcriptStore: MeetingSessionTranscriptStore<TSession>;\n constructor(private readonly options: MeetingSessionRuntimeOptions<TSession, TRequest, TTransport, TMode, THealth, TTab, TManualReason, TSpeechBlockedReason>);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise<TranscriptsStartResult>;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise<TranscriptsStopResult>;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin<TTransport, TMode>): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise<boolean>;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise<void>;\n async refreshCaptionHealth(session: TSession): Promise<void>;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin<TTransport, TMode>): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise<MeetingSessionLeaveResult<TSession>>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise<boolean>;\n async #rollbackFailedJoinSession(session: TSession): Promise<void>;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise<void>;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles<THealth>): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"}
{"category":null,"entrypoint":"memory-core-host-engine-foundation","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","recordType":"module"}
{"closureHash":"e2df8d235401aebf58eb71652fbeaedb42ca00aaa5042a76909ff2c48ba6fd54","declaration":"export function createSubsystemLogger(subsystem: string): SubsystemLogger;","entrypoint":"memory-core-host-engine-foundation","exportName":"createSubsystemLogger","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"}
{"closureHash":null,"declaration":"export function isPathInside(root: string, target: string): boolean;","entrypoint":"memory-core-host-engine-foundation","exportName":"isPathInside","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"}
@@ -3655,10 +3655,10 @@
{"closureHash":"e66adcb55dec79be73a52bc76594b7e9210fd93c69a85b56098fbb58cecbb354","declaration":"export type WriteOAuthCredentialsOptions = WriteOAuthCredentialsOptions;","entrypoint":"provider-auth","exportName":"WriteOAuthCredentialsOptions","importSpecifier":"openclaw/plugin-sdk/provider-auth","kind":"type","recordType":"export"}
{"category":null,"entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","recordType":"module"}
{"closureHash":"b5665596a3f011454a5614681513516acd50b6c749536c43842d811980cf7ad3","declaration":"export function augmentModelCatalogWithProviderPlugins(params: { config?: OpenClawConfig; workspaceDir?: string; env?: NodeJS.ProcessEnv; metadataSnapshot?: PluginMetadataSnapshot; context: ProviderAugmentModelCatalogContext; }): Promise<ModelCatalogEntry[]>;","entrypoint":"provider-catalog-runtime","exportName":"augmentModelCatalogWithProviderPlugins","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"92f24d657fc620b3d47cb3d8b2f05a1ac5d9eb3ee65ee897d2767175a0fc6a34","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters<typeof resolvePluginProviders>[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"492e70830dc8040252f35c457233a9563f79938b163975b2ed1d8c9b1cec118a","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"ca3d898386ceb6c1e7d8a8be80cfcf93fc99cd9f9bb2bbf8ba0a844f9624cccf","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick<PluginMetadataSnapshot, \"owners\" | \"manifestRegistry\" | \"byPluginId\">; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"355e8319052cdc2e9e1e553f8dd58efaef3f8af710f855d0988dc165958e589b","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"21ecb9d9b55785897a3abb0fd07613d0e06cb323c2d9e5066d66e64821e2acd5","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters<typeof resolvePluginProviders>[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"a81a0603b2a5f136ec58ccf6b0963f15dcecec57506ca2f58a3aff2cc4ec903c","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"61d926974cc9b13df361c3fefa7b7ec570ecda663126f0847c77211d1b710058","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick<PluginMetadataSnapshot, \"owners\" | \"manifestRegistry\" | \"byPluginId\">; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"closureHash":"beaaa1633f55d6f9d1dc5c49da4a297d73e5c35756162302ed4dc72cfc291d90","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"}
{"category":null,"entrypoint":"proxy-capture","importSpecifier":"openclaw/plugin-sdk/proxy-capture","recordType":"module"}
{"closureHash":"d0e4e026d736bc00b1758d1089c44c3c5f3a09c7254291584de8cb297365804c","declaration":"export function acquireDebugProxyCaptureStore(dbPath: string, blobDir: string): { store: LegacyDebugProxyCaptureStore; release: () => void; };\nexport function acquireDebugProxyCaptureStore(options?: DebugProxyCaptureStoreOptions): { store: SharedDebugProxyCaptureStore; release: () => void; };","entrypoint":"proxy-capture","exportName":"acquireDebugProxyCaptureStore","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"}
{"closureHash":"d41cbb9de51b7aee1c6cf8c713b0bc44f27ac926fbb6422c05726f196d11964e","declaration":"export function captureHttpExchange(params: { url: string; method: string; requestHeaders?: Headers | Record<string, string> | undefined; requestBody?: BodyInit | Buffer | string | null; response: Response; transport?: \"http\" | \"sse\"; flowId?: string; meta?: Record<string, unknown>; }, resolved?: DebugProxySettings, deps?: DebugProxyCaptureRuntimeDeps): void;","entrypoint":"proxy-capture","exportName":"captureHttpExchange","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"}
@@ -51,13 +51,6 @@
"src/gateway/server-methods/__mocks__/tools-effective.runtime.ts"
]
},
{
"name": "buildChannelAccountSnapshot",
"files": [
"src/channels/account-summary.ts",
"src/channels/plugins/status.ts"
]
},
{
"name": "buildPluginDiagnosticsReport",
"files": [
@@ -124,13 +117,6 @@
],
"sdk": true
},
{
"name": "cancelDetachedTaskRunById",
"files": [
"src/tasks/task-executor-cancel.runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "classifySessionKind",
"files": [
@@ -183,13 +169,6 @@
"src/agents/embedded-agent-runner/compact.ts"
]
},
{
"name": "completeTaskRunByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "containsConfigIncludeDirective",
"files": [
@@ -240,20 +219,6 @@
"src/plugins/logger.ts"
]
},
{
"name": "createQueuedTaskRun",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "createRunningTaskRun",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "createSessionId",
"files": [
@@ -276,13 +241,6 @@
],
"sdk": true
},
{
"name": "DEFAULT_TIMEOUT_MS",
"files": [
"src/infra/provider-usage.shared.ts",
"src/infra/update-runner-command.ts"
]
},
{
"name": "defaultRuntime",
"files": [
@@ -299,38 +257,6 @@
],
"sdk": true
},
{
"name": "describeImagesWithModel",
"files": [
"src/media-understanding/image-runtime.ts",
"src/media-understanding/image.ts"
],
"sdk": true
},
{
"name": "describeImagesWithModelPayloadTransform",
"files": [
"src/media-understanding/image-runtime.ts",
"src/media-understanding/image.ts"
],
"sdk": true
},
{
"name": "describeImageWithModel",
"files": [
"src/media-understanding/image-runtime.ts",
"src/media-understanding/image.ts"
],
"sdk": true
},
{
"name": "describeImageWithModelPayloadTransform",
"files": [
"src/media-understanding/image-runtime.ts",
"src/media-understanding/image.ts"
],
"sdk": true
},
{
"name": "dispatchReplyWithBufferedBlockDispatcher",
"files": [
@@ -371,13 +297,6 @@
],
"sdk": true
},
{
"name": "ensureConfigReady",
"files": [
"src/cli/program.test-mocks.ts",
"src/cli/program/config-guard.ts"
]
},
{
"name": "ensureConfiguredAcpBindingReady",
"files": [
@@ -415,13 +334,6 @@
"src/gateway/session-transcript-readers.ts"
]
},
{
"name": "failTaskRunByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "fileExists",
"files": [
@@ -431,13 +343,6 @@
],
"sdk": true
},
{
"name": "finalizeTaskRunByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-registry-record-api.ts"
]
},
{
"name": "formatConfigPath",
"files": [
@@ -507,13 +412,6 @@
],
"sdk": true
},
{
"name": "getFreeGatewayPort",
"files": [
"src/gateway/gateway-cli-backend.live-helpers.ts",
"src/gateway/test-helpers.e2e.ts"
]
},
{
"name": "getFreePort",
"files": [
@@ -856,14 +754,6 @@
"src/infra/state-migrations.session-store.ts"
]
},
{
"name": "normalizeChannelId",
"files": [
"src/channels/plugins/registry.ts",
"src/channels/registry.ts"
],
"sdk": true
},
{
"name": "normalizeContainerPath",
"files": [
@@ -900,13 +790,6 @@
"src/cron/run-diagnostics-normalize.ts"
]
},
{
"name": "notifyGatewayPluginMetadataChanged",
"files": [
"src/cli/plugins-cli-test-helpers.ts",
"src/cli/plugins-update-gateway-signal.ts"
]
},
{
"name": "optimizeImageToJpeg",
"files": [
@@ -1012,27 +895,6 @@
"src/plugins/uninstall.ts"
]
},
{
"name": "preserveConfigSnapshotAsClobbered",
"files": [
"src/config/io.observe-recovery.ts",
"src/config/io.runtime.ts"
]
},
{
"name": "promoteConfigSnapshotToLastKnownGood",
"files": [
"src/config/io.observe-recovery.ts",
"src/config/io.runtime.ts"
]
},
{
"name": "promptYesNo",
"files": [
"src/cli/plugins-cli-test-helpers.ts",
"src/cli/prompt.ts"
]
},
{
"name": "readAmbientTranscriptWatermark",
"files": [
@@ -1064,13 +926,6 @@
],
"sdk": true
},
{
"name": "readLatestSessionUsageFromTranscriptAsync",
"files": [
"src/gateway/session-transcript-readers.ts",
"src/gateway/session-utils.fs.ts"
]
},
{
"name": "readPersistedInstalledPluginIndex",
"files": [
@@ -1115,20 +970,6 @@
"src/plugins/installs.ts"
]
},
{
"name": "recordTaskRunProgressByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "recoverConfigFromLastKnownGood",
"files": [
"src/config/io.observe-recovery.ts",
"src/config/io.runtime.ts"
]
},
{
"name": "redactSecrets",
"files": [
@@ -1144,27 +985,6 @@
"src/plugins/plugin-registry-snapshot.ts"
]
},
{
"name": "registerPluginsCli",
"files": [
"src/cli/plugins-cli-test-helpers.ts",
"src/cli/plugins-cli.ts"
]
},
{
"name": "registerSubCliByName",
"files": [
"src/cli/program/register.subclis-core.ts",
"src/cli/program/register.subclis.ts"
]
},
{
"name": "registerSubCliCommands",
"files": [
"src/cli/program/register.subclis-core.ts",
"src/cli/program/register.subclis.ts"
]
},
{
"name": "replaceConfigFile",
"files": [
@@ -1209,14 +1029,6 @@
"src/gateway/test-helpers.assertions.ts"
]
},
{
"name": "resetPreparedModelCatalogForTest",
"files": [
"src/gateway/server-model-catalog.ts",
"src/gateway/server-start.ts",
"src/gateway/server.ts"
]
},
{
"name": "resolveAdvertisedLanHost",
"files": [
@@ -1319,13 +1131,6 @@
"src/plugins/config-state.ts"
]
},
{
"name": "resolveMissingPluginCommandMessage",
"files": [
"src/cli/run-main-policy.ts",
"src/cli/run-main.ts"
]
},
{
"name": "resolveNode",
"files": [
@@ -1361,14 +1166,6 @@
"src/plugins/provider-thinking.ts"
]
},
{
"name": "resolveProviderUsageDisplayName",
"files": [
"src/infra/provider-usage.admin.ts",
"src/infra/provider-usage.shared.ts"
],
"sdk": true
},
{
"name": "resolveSecretInputString",
"files": [
@@ -1415,13 +1212,6 @@
],
"sdk": true
},
{
"name": "resolveThinkingDefaultForModel",
"files": [
"src/auto-reply/thinking.shared.ts",
"src/auto-reply/thinking.ts"
]
},
{
"name": "restorePersistedInstalledPluginIndexIfCurrent",
"files": [
@@ -1459,13 +1249,6 @@
"src/commands/system-agent-with-inference.ts"
]
},
{
"name": "runtimeLogs",
"files": [
"src/cli/daemon-cli/test-helpers/lifecycle-core-harness.ts",
"src/cli/plugins-cli-test-helpers.ts"
]
},
{
"name": "runTui",
"files": [
@@ -1497,13 +1280,6 @@
],
"sdk": true
},
{
"name": "setDetachedTaskDeliveryStatusByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "setupCommand",
"files": [
@@ -1526,28 +1302,6 @@
],
"sdk": true
},
{
"name": "startGatewayServer",
"files": [
"src/gateway/server-start.ts",
"src/gateway/server.ts",
"src/gateway/test-helpers.server.ts"
]
},
{
"name": "startTaskRunByRunId",
"files": [
"src/tasks/detached-task-runtime.ts",
"src/tasks/task-executor.ts"
]
},
{
"name": "stopWithText",
"files": [
"src/auto-reply/reply/commands-acp/shared.ts",
"src/auto-reply/reply/commands-subagents/shared.ts"
]
},
{
"name": "stripTargetKindPrefix",
"files": [
@@ -1609,13 +1363,6 @@
],
"sdk": true
},
{
"name": "tryDispatchAcpReply",
"files": [
"src/auto-reply/reply/dispatch-acp.runtime.ts",
"src/auto-reply/reply/dispatch-acp.ts"
]
},
{
"name": "updateNpmInstalledHookPacks",
"files": [
@@ -253,27 +253,12 @@
"wrapped": "src/plugin-sdk/boolean-param.ts",
"wrapper": "src/infra/outbound/message-action-params.ts"
},
{
"name": "readLatestSessionUsageFromTranscriptAsync",
"wrapped": "src/gateway/session-utils.fs.ts",
"wrapper": "src/gateway/session-transcript-readers.ts"
},
{
"name": "readSessionTranscriptVisibleMessageDelta",
"wrapped": "src/config/sessions/session-accessor.sqlite-active-events.ts",
"wrapper": "src/plugin-sdk/session-transcript-runtime.ts",
"via": "src/config/sessions/session-accessor.ts"
},
{
"name": "registerSubCliByName",
"wrapped": "src/cli/program/register.subclis-core.ts",
"wrapper": "src/cli/program/register.subclis.ts"
},
{
"name": "registerSubCliCommands",
"wrapped": "src/cli/program/register.subclis-core.ts",
"wrapper": "src/cli/program/register.subclis.ts"
},
{
"name": "replaceRuntimeAuthProfileStoreSnapshots",
"wrapped": "src/agents/auth-profiles/runtime-snapshots.ts",
@@ -305,11 +290,6 @@
"wrapped": "src/auto-reply/heartbeat.ts",
"wrapper": "src/infra/heartbeat-runner-config.ts"
},
{
"name": "resolveMissingPluginCommandMessage",
"wrapped": "src/cli/run-main-policy.ts",
"wrapper": "src/cli/run-main.ts"
},
{
"name": "resolvePluginProviders",
"wrapped": "src/plugins/providers.runtime.ts",
@@ -350,11 +330,6 @@
"wrapped": "src/config/sessions/paths.ts",
"wrapper": "src/plugin-sdk/session-store-runtime.ts"
},
{
"name": "resolveThinkingDefaultForModel",
"wrapped": "src/auto-reply/thinking.shared.ts",
"wrapper": "src/auto-reply/thinking.ts"
},
{
"name": "runProviderModelSelectedHook",
"wrapped": "src/plugins/provider-wizard.ts",
@@ -15,7 +15,7 @@ import { startGatewayServer } from "../gateway/server.js";
import {
connectGatewayClient,
disconnectGatewayClient,
getFreeGatewayPort,
getGatewayE2ePortBlock,
} from "../gateway/test-helpers.e2e.js";
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../gateway/test-helpers.env.js";
import { captureEnv, setTestEnvValue } from "../test-utils/env.js";
@@ -68,7 +68,7 @@ describe("gateway-hosted exec approvals", () => {
const workspaceDir = path.join(tempHome, "workspace");
await fs.mkdir(workspaceDir, { recursive: true });
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const token = "exec-approval-e2e-token";
const configPath = path.join(stateDir, "openclaw.json");
await fs.mkdir(stateDir, { recursive: true });
@@ -9,7 +9,7 @@ import { enqueueCommandInLane, markGatewayDraining } from "../../process/command
import * as commandQueueModule from "../../process/command-queue.js";
import { resetCommandQueueStateForTest } from "../../process/command-queue.test-support.js";
import { onSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
import { createQueuedTaskRun as createQueuedTaskRunOrNull } from "../../tasks/task-executor.js";
import { createQueuedTaskRunCore as createQueuedTaskRunOrNull } from "../../tasks/task-executor.js";
import { getTaskFlowById } from "../../tasks/task-flow-registry.js";
import { getTaskById, listTasksForOwnerKey } from "../../tasks/task-registry.js";
import type { TaskRecord } from "../../tasks/task-registry.types.js";
@@ -39,7 +39,9 @@ let createDeferredTurnMaintenanceAbortSignal: typeof import("./context-engine-ma
let resetDeferredTurnMaintenanceStateForTest: typeof import("./context-engine-maintenance.test-support.js").resetDeferredTurnMaintenanceStateForTest;
let waitForDeferredTurnMaintenanceForSession: typeof import("./context-engine-maintenance.js").waitForDeferredTurnMaintenanceForSession;
function createQueuedTaskRun(params: Parameters<typeof createQueuedTaskRunOrNull>[0]): TaskRecord {
function createQueuedTaskRunCore(
params: Parameters<typeof createQueuedTaskRunOrNull>[0],
): TaskRecord {
// Task creation can legally return null for invalid inputs; tests here always
// need a concrete queued task record.
const task = createQueuedTaskRunOrNull(params);
@@ -997,7 +999,7 @@ describe("runContextEngineMaintenance", () => {
resetTaskFlowRegistryForTests({ persist: false });
const sessionKey = "agent:main:session-legacy";
const legacyTask = createQueuedTaskRun({
const legacyTask = createQueuedTaskRunCore({
runtime: "acp",
taskKind: TURN_MAINTENANCE_TASK_KIND,
sourceId: TURN_MAINTENANCE_TASK_KIND,
+1 -1
View File
@@ -8,7 +8,7 @@ import {
normalizeChannelId as normalizeAnyChannelId,
} from "../../channels/plugins/index.js";
import { resolveSessionConversationRef } from "../../channels/plugins/session-conversation.js";
import { normalizeChannelId as normalizeChatChannelId } from "../../channels/registry.js";
import { normalizeChatChannelId } from "../../channels/registry.js";
import { parseSessionDeliveryRoute } from "../../sessions/session-key-utils.js";
import { ANNOUNCE_SKIP_TOKEN, REPLY_SKIP_TOKEN } from "./sessions-send-tokens.js";
export {
+2 -2
View File
@@ -7,7 +7,7 @@ import { resolveFastModeState } from "../../agents/fast-mode.js";
import { normalizeChatType } from "../../channels/chat-type.js";
import { getChannelPlugin } from "../../channels/plugins/index.js";
import type { ChannelId } from "../../channels/plugins/types.public.js";
import { normalizeAnyChannelId, normalizeChannelId } from "../../channels/registry.js";
import { normalizeAnyChannelId, normalizeChatChannelId } from "../../channels/registry.js";
import type { InternalChannelThreadingToolContext } from "../../channels/threading-tool-context-internal.js";
import { resolveCommandSecretRefsViaGateway } from "../../cli/command-secret-gateway.js";
import {
@@ -144,7 +144,7 @@ export function buildThreadingToolContext(params: {
currentSourceTurnId,
};
}
const provider = normalizeChannelId(rawProvider) ?? normalizeAnyChannelId(rawProvider);
const provider = normalizeChatChannelId(rawProvider) ?? normalizeAnyChannelId(rawProvider);
// Fallback for unrecognized/plugin channels (e.g., iMessage before plugin registry init)
const threading = provider ? getChannelPlugin(provider)?.threading : undefined;
if (!threading?.buildToolContext) {
+2 -2
View File
@@ -162,7 +162,7 @@ const { testing: acpResetTargetTesting } = await import("./acp-reset-target.test
const { createTaskRecord } = await import("../../tasks/task-registry.js");
const { resetTaskRegistryForTests } = await import("../../tasks/task-runtime.test-helpers.js");
const { configureTaskRegistryRuntime } = await import("../../tasks/task-registry.store.js");
const { failTaskRunByRunId } = await import("../../tasks/task-executor.js");
const { failTaskRunByRunIdCore } = await import("../../tasks/task-executor.js");
function configureInMemoryTaskRegistryStoreForTests(): void {
configureTaskRegistryRuntime({
@@ -2126,7 +2126,7 @@ describe("/acp command", () => {
task: "Inspect ACP backlog",
status: "running",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "acp-run-1",
endedAt: Date.now(),
error: [
+2 -3
View File
@@ -1,13 +1,12 @@
// Implements ACP session commands and runtime status formatting.
import { logVerbose } from "../../globals.js";
import { createLazyImportLoader } from "../../shared/lazy-promise.js";
import { rejectNonOwnerCommand, requireGatewayClientScope } from "./command-gates.js";
import { commandReply, rejectNonOwnerCommand, requireGatewayClientScope } from "./command-gates.js";
import {
COMMAND,
type AcpAction,
resolveAcpAction,
resolveAcpHelpText,
stopWithText,
} from "./commands-acp/shared.js";
import type {
CommandHandler,
@@ -101,7 +100,7 @@ export const handleAcpCommand: CommandHandler = async (params, _allowTextCommand
const tokens = rest.split(/\s+/).filter(Boolean);
const action = resolveAcpAction(tokens);
if (action === "help") {
return stopWithText(resolveAcpHelpText());
return commandReply(resolveAcpHelpText());
}
if (ACP_OWNER_REQUIRED_ACTIONS.has(action)) {
@@ -10,6 +10,7 @@ import { listAcpSessionEntries, readAcpSessionEntry } from "../../../acp/runtime
import type { SessionEntry } from "../../../config/sessions/types.js";
import type { SessionAcpMeta } from "../../../config/sessions/types.js";
import { getSessionBindingService } from "../../../infra/outbound/session-binding-service.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult, HandleCommandsParams } from "../commands-types.js";
import { resolveAcpCommandBindingContext } from "./context.js";
import { resolveAcpInstallCommandHint } from "./install-hints.js";
@@ -18,7 +19,6 @@ import {
ACP_INSTALL_USAGE,
ACP_SESSIONS_USAGE,
formatAcpCapabilitiesText,
stopWithText,
} from "./shared.js";
import { resolveBoundAcpThreadSessionKey } from "./targets.js";
@@ -44,7 +44,7 @@ export async function handleAcpDoctorAction(
restTokens: string[],
): Promise<CommandHandlerResult> {
if (restTokens.length > 0) {
return stopWithText(`⚠️ ${ACP_DOCTOR_USAGE}`);
return commandReply(`⚠️ ${ACP_DOCTOR_USAGE}`);
}
const backendId = normalizeOptionalString(params.cfg.acp?.backend) ?? "acpx";
@@ -117,7 +117,7 @@ export async function handleAcpDoctorAction(
if ((capabilities.configOptionKeys?.length ?? 0) > 0) {
lines.push(`configKeys: ${capabilities.configOptionKeys?.join(", ")}`);
}
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
} catch (error) {
const acpError = toAcpRuntimeError({
error,
@@ -134,7 +134,7 @@ export async function handleAcpDoctorAction(
if (normalizeLowercaseStringOrEmpty(backendId) === "acpx") {
lines.push("next: verify acpx is installed (`acpx --help`).");
}
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
}
}
@@ -143,7 +143,7 @@ export function handleAcpInstallAction(
restTokens: string[],
): CommandHandlerResult {
if (restTokens.length > 0) {
return stopWithText(`⚠️ ${ACP_INSTALL_USAGE}`);
return commandReply(`⚠️ ${ACP_INSTALL_USAGE}`);
}
const backendId = normalizeOptionalString(params.cfg.acp?.backend) ?? "acpx";
const installHint = resolveAcpInstallCommandHint(params.cfg);
@@ -155,7 +155,7 @@ export function handleAcpInstallAction(
`then: openclaw config set plugins.entries.${backendId}.enabled true`,
"then: /acp doctor",
];
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
}
function formatAcpSessionLine(params: {
@@ -177,12 +177,12 @@ export async function handleAcpSessionsAction(
restTokens: string[],
): Promise<CommandHandlerResult> {
if (restTokens.length > 0) {
return stopWithText(ACP_SESSIONS_USAGE);
return commandReply(ACP_SESSIONS_USAGE);
}
const currentSessionKey = resolveBoundAcpThreadSessionKey(params) || params.sessionKey;
if (!currentSessionKey) {
return stopWithText("⚠️ Missing session key.");
return commandReply("⚠️ Missing session key.");
}
const bindingContext = resolveAcpCommandBindingContext(params);
@@ -223,8 +223,8 @@ export async function handleAcpSessionsAction(
.filter(Boolean);
if (rows.length === 0) {
return stopWithText("ACP sessions:\n-----\n(none)");
return commandReply("ACP sessions:\n-----\n(none)");
}
return stopWithText(["ACP sessions:", "-----", ...rows].join("\n"));
return commandReply(["ACP sessions:", "-----", ...rows].join("\n"));
}
+21 -21
View File
@@ -28,6 +28,7 @@ import {
getSessionBindingService,
type SessionBindingRecord,
} from "../../../infra/outbound/session-binding-service.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult, HandleCommandsParams } from "../commands-types.js";
import {
resolveAcpBindingLabelNoun,
@@ -42,7 +43,6 @@ import {
parseSpawnInput,
parseSteerInput,
resolveCommandRequestId,
stopWithText,
withAcpCommandErrorBoundary,
} from "./shared.js";
import { resolveAcpTargetSessionKey } from "./targets.js";
@@ -107,12 +107,12 @@ export async function handleAcpSpawnAction(
restTokens: string[],
): Promise<CommandHandlerResult> {
if (!isAcpEnabledByPolicy(params.cfg)) {
return stopWithText("ACP is disabled by policy (`acp.enabled=false`).");
return commandReply("ACP is disabled by policy (`acp.enabled=false`).");
}
const parsed = parseSpawnInput(params, restTokens);
if (!parsed.ok) {
return stopWithText(`⚠️ ${parsed.error}`);
return commandReply(`⚠️ ${parsed.error}`);
}
const spawn = parsed.value;
@@ -121,11 +121,11 @@ export async function handleAcpSpawnAction(
requesterSessionKey: params.sessionKey,
});
if (runtimePolicyError) {
return stopWithText(`⚠️ ${runtimePolicyError}`);
return commandReply(`⚠️ ${runtimePolicyError}`);
}
const agentPolicyError = resolveAcpAgentPolicyError(params.cfg, spawn.agentId);
if (agentPolicyError) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error: agentPolicyError,
fallbackCode: "ACP_SESSION_INIT_FAILED",
@@ -149,7 +149,7 @@ export async function handleAcpSpawnAction(
explicitCwd: spawn.cwd,
});
} catch (error) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error,
fallbackCode: "ACP_SESSION_INIT_FAILED",
@@ -176,7 +176,7 @@ export async function handleAcpSpawnAction(
initializedBackend = initialized.handle.backend || initialized.meta.backend;
initializedMeta = initialized.meta;
} catch (err) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error: err,
fallbackCode: "ACP_SESSION_INIT_FAILED",
@@ -202,7 +202,7 @@ export async function handleAcpSpawnAction(
shouldDeleteSession: true,
initializedRuntime,
});
return stopWithText(`⚠️ ${bound.error}`);
return commandReply(`⚠️ ${bound.error}`);
}
binding = bound.binding;
} else if (spawn.thread !== "off") {
@@ -221,7 +221,7 @@ export async function handleAcpSpawnAction(
shouldDeleteSession: true,
initializedRuntime,
});
return stopWithText(`⚠️ ${bound.error}`);
return commandReply(`⚠️ ${bound.error}`);
}
binding = bound.binding;
}
@@ -240,7 +240,7 @@ export async function handleAcpSpawnAction(
initializedRuntime,
});
const message = formatErrorMessage(err);
return stopWithText(`⚠️ ACP spawn failed: ${message}`);
return commandReply(`⚠️ ACP spawn failed: ${message}`);
}
const parts = [
@@ -286,7 +286,7 @@ export async function handleAcpSpawnAction(
parts.push(`${dispatchNote}`);
}
return stopWithText(parts.join(" "));
return commandReply(parts.join(" "));
}
function resolveAcpSessionForCommandOrStop(params: {
@@ -300,7 +300,7 @@ function resolveAcpSessionForCommandOrStop(params: {
});
const error = resolveAcpSessionResolutionError(resolved);
if (error) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error,
fallbackCode: "ACP_SESSION_INIT_FAILED",
@@ -321,7 +321,7 @@ async function resolveAcpTokenTargetSessionKeyOrStop(params: {
token,
});
if (!target.ok) {
return stopWithText(`⚠️ ${target.error}`);
return commandReply(`⚠️ ${target.error}`);
}
return target.sessionKey;
}
@@ -373,7 +373,7 @@ export async function handleAcpCancelAction(
}),
fallbackCode: "ACP_TURN_FAILED",
fallbackMessage: "ACP cancel failed before completion.",
onSuccess: () => stopWithText(`✅ Cancel requested for ACP session ${sessionKey}.`),
onSuccess: () => commandReply(`✅ Cancel requested for ACP session ${sessionKey}.`),
}),
});
}
@@ -418,7 +418,7 @@ export async function handleAcpSteerAction(
): Promise<CommandHandlerResult> {
const dispatchPolicyError = resolveAcpDispatchPolicyError(params.cfg);
if (dispatchPolicyError) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error: dispatchPolicyError,
fallbackCode: "ACP_DISPATCH_DISABLED",
@@ -429,7 +429,7 @@ export async function handleAcpSteerAction(
const parsed = parseSteerInput(restTokens);
if (!parsed.ok) {
return stopWithText(`⚠️ ${parsed.error}`);
return commandReply(`⚠️ ${parsed.error}`);
}
const acpManager = getAcpSessionManager();
@@ -438,7 +438,7 @@ export async function handleAcpSteerAction(
token: parsed.value.sessionToken,
});
if (!target.ok) {
return stopWithText(`⚠️ ${target.error}`);
return commandReply(`⚠️ ${target.error}`);
}
const guardFailure = resolveAcpSessionForCommandOrStop({
@@ -462,9 +462,9 @@ export async function handleAcpSteerAction(
fallbackMessage: "ACP steer failed before completion.",
onSuccess: (steerOutput) => {
if (!steerOutput) {
return stopWithText(`✅ ACP steer sent to ${target.sessionKey}.`);
return commandReply(`✅ ACP steer sent to ${target.sessionKey}.`);
}
return stopWithText(`✅ ACP steer sent to ${target.sessionKey}.\n${steerOutput}`);
return commandReply(`✅ ACP steer sent to ${target.sessionKey}.\n${steerOutput}`);
},
});
}
@@ -488,7 +488,7 @@ export async function handleAcpCloseAction(
});
runtimeNotice = closed.runtimeNotice ? ` (${closed.runtimeNotice})` : "";
} catch (error) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error,
fallbackCode: "ACP_TURN_FAILED",
@@ -502,7 +502,7 @@ export async function handleAcpCloseAction(
reason: "manual",
});
return stopWithText(
return commandReply(
`✅ Closed ACP session ${sessionKey}${runtimeNotice}. Removed ${removedBindings.length} binding${removedBindings.length === 1 ? "" : "s"}.`,
);
},
@@ -14,6 +14,7 @@ import {
import type { AcpSessionRuntimeOptions } from "../../../config/sessions/types.js";
import { findLatestTaskForRelatedSessionKeyForOwner } from "../../../tasks/task-owner-access.js";
import { sanitizeTaskStatusText } from "../../../tasks/task-status.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult, HandleCommandsParams } from "../commands-types.js";
import {
ACP_CWD_USAGE,
@@ -28,7 +29,6 @@ import {
parseOptionalSingleTarget,
parseSetCommandInput,
parseSingleValueCommandInput,
stopWithText,
withAcpCommandErrorBoundary,
} from "./shared.js";
import { resolveAcpTargetSessionKey } from "./targets.js";
@@ -42,7 +42,7 @@ async function resolveTargetSessionKeyOrStop(params: {
token: params.token,
});
if (!target.ok) {
return stopWithText(`⚠️ ${target.error}`);
return commandReply(`⚠️ ${target.error}`);
}
return target.sessionKey;
}
@@ -54,7 +54,7 @@ async function resolveOptionalSingleTargetOrStop(params: {
}): Promise<string | CommandHandlerResult> {
const parsed = parseOptionalSingleTarget(params.restTokens, params.usage);
if (!parsed.ok) {
return stopWithText(`⚠️ ${parsed.error}`);
return commandReply(`⚠️ ${parsed.error}`);
}
return await resolveTargetSessionKeyOrStop({
commandParams: params.commandParams,
@@ -74,7 +74,7 @@ async function resolveSingleTargetValueOrStop(params: {
}): Promise<SingleTargetValue | CommandHandlerResult> {
const parsed = parseSingleValueCommandInput(params.restTokens, params.usage);
if (!parsed.ok) {
return stopWithText(`⚠️ ${parsed.error}`);
return commandReply(`⚠️ ${parsed.error}`);
}
const targetSessionKey = await resolveTargetSessionKeyOrStop({
commandParams: params.commandParams,
@@ -132,7 +132,7 @@ async function handleSingleRuntimeOptionAction<T>(
fallbackMessage: `Could not update ACP ${action.optionLabel}.`,
onSuccess: ({ parsedValue, options }) => {
const valueText = action.formatValue?.(parsedValue) ?? String(parsedValue);
return stopWithText(
return commandReply(
`✅ Updated ACP ${action.optionLabel} for ${targetSessionKey}: ${valueText}. Effective options: ${formatRuntimeOptionsText(options)}`,
);
},
@@ -214,7 +214,7 @@ export async function handleAcpStatusAction(
...(runtimeSummary ? [`runtime: ${runtimeSummary}`] : []),
...(runtimeDetails ? [`runtimeDetails: ${runtimeDetails}`] : []),
];
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
},
});
}
@@ -244,7 +244,7 @@ export async function handleAcpSetModeAction(
fallbackCode: "ACP_TURN_FAILED",
fallbackMessage: "Could not update ACP runtime mode.",
onSuccess: ({ runtimeMode, options }) =>
stopWithText(
commandReply(
`✅ Updated ACP runtime mode for ${targetSessionKey}: ${runtimeMode}. Effective options: ${formatRuntimeOptionsText(options)}`,
),
}),
@@ -257,14 +257,14 @@ export async function handleAcpSetAction(
): Promise<CommandHandlerResult> {
const parsed = parseSetCommandInput(restTokens);
if (!parsed.ok) {
return stopWithText(`⚠️ ${parsed.error}`);
return commandReply(`⚠️ ${parsed.error}`);
}
const target = await resolveAcpTargetSessionKey({
commandParams: params,
token: parsed.value.sessionToken,
});
if (!target.ok) {
return stopWithText(`⚠️ ${target.error}`);
return commandReply(`⚠️ ${target.error}`);
}
const key = parsed.value.key.trim();
const value = parsed.value.value.trim();
@@ -296,7 +296,7 @@ export async function handleAcpSetAction(
},
fallbackCode: "ACP_TURN_FAILED",
fallbackMessage: "Could not update ACP config option.",
onSuccess: ({ text }) => stopWithText(text),
onSuccess: ({ text }) => commandReply(text),
});
}
@@ -393,6 +393,6 @@ export async function handleAcpResetOptionsAction(
}),
fallbackCode: "ACP_TURN_FAILED",
fallbackMessage: "Could not reset ACP runtime options.",
onSuccess: () => stopWithText(`✅ Reset ACP runtime options for ${targetSessionKey}.`),
onSuccess: () => commandReply(`✅ Reset ACP runtime options for ${targetSessionKey}.`),
});
}
+2 -8
View File
@@ -10,6 +10,7 @@ import { type AcpRuntimeError, toAcpRuntimeErrorText } from "../../../acp/runtim
import { supportsAutomaticThreadBindingSpawn } from "../../../channels/thread-bindings-policy.js";
import type { AcpSessionRuntimeOptions } from "../../../config/sessions/types.js";
import { normalizeAgentId } from "../../../routing/session-key.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult, HandleCommandsParams } from "../commands-types.js";
import { resolveAcpCommandChannel, resolveAcpCommandThreadId } from "./context.js";
@@ -84,13 +85,6 @@ type ParsedSetCommandInput = {
const ACP_UNICODE_DASH_PREFIX_RE =
/^[\u2010\u2011\u2012\u2013\u2014\u2015\u2212\uFE58\uFE63\uFF0D]+/;
export function stopWithText(text: string): CommandHandlerResult {
return {
shouldContinue: false,
reply: { text },
};
}
export function resolveAcpAction(tokens: string[]): AcpAction {
const action = normalizeOptionalLowercaseString(tokens[0]);
if (
@@ -524,7 +518,7 @@ export async function withAcpCommandErrorBoundary<T>(params: {
const result = await params.run();
return params.onSuccess(result);
} catch (error) {
return stopWithText(
return commandReply(
collectAcpErrorText({
error,
fallbackCode: params.fallbackCode,
+4 -4
View File
@@ -8,7 +8,7 @@ import { normalizeStringEntries } from "@openclaw/normalization-core/string-norm
import { resolveExplicitConfigWriteTarget } from "../../channels/plugins/config-writes.js";
import { getChannelPlugin } from "../../channels/plugins/index.js";
import type { ChannelId } from "../../channels/plugins/types.public.js";
import { normalizeChannelId } from "../../channels/registry.js";
import { normalizeChatChannelId } from "../../channels/registry.js";
import { readConfigFileSnapshot } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import {
@@ -284,9 +284,9 @@ export const handleAllowlistCommand: CommandHandler = async (params, allowTextCo
}
const channelId =
normalizeChannelId(parsed.channel) ??
normalizeChatChannelId(parsed.channel) ??
params.command.channelId ??
normalizeChannelId(params.command.channel);
normalizeChatChannelId(params.command.channel);
if (!channelId) {
return commandReply("⚠️ Unknown channel. Add channel=<id> to the command.");
}
@@ -302,7 +302,7 @@ export const handleAllowlistCommand: CommandHandler = async (params, allowTextCo
ctxAccountId: params.ctx.AccountId,
});
const originChannelId =
params.command.channelId ?? normalizeChannelId(resolveCommandSurfaceChannel(params));
params.command.channelId ?? normalizeChatChannelId(resolveCommandSurfaceChannel(params));
const originAccountId = resolveChannelAccountId({
cfg: params.cfg,
ctx: params.ctx,
+2 -2
View File
@@ -1,7 +1,7 @@
// Implements config inspection and mutation commands for reply sessions.
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { resolveConfigWriteTargetFromPath } from "../../channels/plugins/config-writes.js";
import { normalizeChannelId } from "../../channels/registry.js";
import { normalizeChatChannelId } from "../../channels/registry.js";
import {
getConfigValueAtPath,
parseConfigPath,
@@ -82,7 +82,7 @@ export const handleConfigCommand: CommandHandler = defineAuthorizedTextCommand(
return commandReply(`⚠️ ${parsedPath.error}`);
}
parsedWritePath = parsedPath.path;
const channelId = params.command.channelId ?? normalizeChannelId(params.command.channel);
const channelId = params.command.channelId ?? normalizeChatChannelId(params.command.channel);
const deniedText = resolveConfigWriteDeniedText({
cfg: params.cfg,
channel: params.command.channel,
+20 -20
View File
@@ -21,10 +21,10 @@ import {
import type { ModelDefinitionConfig } from "../../config/types.models.js";
import type { ProviderThinkingProfile } from "../../plugins/provider-thinking.types.js";
import {
completeTaskRunByRunId,
createQueuedTaskRun,
createRunningTaskRun,
failTaskRunByRunId,
completeTaskRunByRunIdCore,
createQueuedTaskRunCore,
createRunningTaskRunCore,
failTaskRunByRunIdCore,
} from "../../tasks/task-executor.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { withEnvAsync } from "../../test-utils/env.js";
@@ -444,7 +444,7 @@ describe("buildStatusReply subagent summary", () => {
});
it("includes active and total task counts for the current session", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-running",
@@ -452,7 +452,7 @@ describe("buildStatusReply subagent summary", () => {
task: "active background task",
progressSummary: "still working",
});
createQueuedTaskRun({
createQueuedTaskRunCore({
runtime: "cron",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-queued",
@@ -467,7 +467,7 @@ describe("buildStatusReply subagent summary", () => {
});
it("hides stale completed task rows from the session task line", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-live",
@@ -475,14 +475,14 @@ describe("buildStatusReply subagent summary", () => {
task: "live background task",
progressSummary: "still working",
});
createQueuedTaskRun({
createQueuedTaskRunCore({
runtime: "cron",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-stale-done",
runId: "run-status-task-stale-done",
task: "stale completed task",
});
completeTaskRunByRunId({
completeTaskRunByRunIdCore({
runId: "run-status-task-stale-done",
endedAt: Date.now() - 10 * 60_000,
terminalSummary: "done a while ago",
@@ -497,14 +497,14 @@ describe("buildStatusReply subagent summary", () => {
});
it("shows a recent failure when no active tasks remain", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "acp",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:acp:status-task-failed",
runId: "run-status-task-failed",
task: "failed background task",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "run-status-task-failed",
endedAt: Date.now(),
error: "approval denied",
@@ -518,14 +518,14 @@ describe("buildStatusReply subagent summary", () => {
});
it("does not leak internal runtime context through the task status line", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-leak",
runId: "run-status-task-leak",
task: "leaked context task",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "run-status-task-leak",
endedAt: Date.now(),
error: [
@@ -546,7 +546,7 @@ describe("buildStatusReply subagent summary", () => {
});
it("truncates long task titles and details in the session task line", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-truncated",
@@ -569,26 +569,26 @@ describe("buildStatusReply subagent summary", () => {
});
it("prefers failure context over newer success context when showing recent failures", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "acp",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:acp:status-task-failed-priority",
runId: "run-status-task-failed-priority",
task: "failed background task",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "run-status-task-failed-priority",
endedAt: Date.now() - 30_000,
error: "approval denied",
});
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:status-task-succeeded-later",
runId: "run-status-task-succeeded-later",
task: "later successful task",
});
completeTaskRunByRunId({
completeTaskRunByRunIdCore({
runId: "run-status-task-succeeded-later",
endedAt: Date.now(),
terminalSummary: "all done",
@@ -604,7 +604,7 @@ describe("buildStatusReply subagent summary", () => {
});
it("falls back to same-agent task counts without details when the current session has none", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:other",
childSessionKey: "agent:main:subagent:status-agent-fallback-running",
@@ -613,7 +613,7 @@ describe("buildStatusReply subagent summary", () => {
task: "hidden task title",
progressSummary: "hidden progress detail",
});
createQueuedTaskRun({
createQueuedTaskRunCore({
runtime: "cron",
requesterSessionKey: "agent:main:another",
childSessionKey: "agent:main:subagent:status-agent-fallback-queued",
@@ -6,7 +6,6 @@ export {
resolveHandledPrefix,
resolveRequesterSessionKey,
resolveSubagentsAction,
stopWithText,
} from "./commands-subagents/shared.js";
export type SubagentsCommandContext = {
@@ -13,7 +13,6 @@ import {
resolveHandledPrefix,
resolveRequesterSessionKey,
resolveSubagentsAction,
stopWithText,
} from "./commands-subagents-dispatch.js";
import { handleSubagentsCommand } from "./commands-subagents.js";
import type { HandleCommandsParams } from "./commands-types.js";
@@ -165,13 +164,6 @@ describe("subagents command dispatch", () => {
expect(restTokens).toEqual(["foo"]);
});
it("builds stop replies", () => {
expect(stopWithText("hello")).toEqual({
shouldContinue: false,
reply: { text: "hello" },
});
});
it("rejects native subagents commands from non-owner senders when the plugin enforces owner-only commands", async () => {
registerOwnerEnforcingTelegramPlugin();
const cfg = {
@@ -20,7 +20,7 @@ import {
} from "../../agents/subagents/registry/subagent-registry.test-helpers.js";
import type { SubagentRunRecord } from "../../agents/subagents/registry/subagent-registry.types.js";
import type { OpenClawConfig } from "../../config/config.js";
import { failTaskRunByRunId } from "../../tasks/task-executor.js";
import { failTaskRunByRunIdCore } from "../../tasks/task-executor.js";
import { createTaskRecord } from "../../tasks/task-registry.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import type { ReplyPayload } from "../types.js";
@@ -371,7 +371,7 @@ describe("subagents info", () => {
status: "running",
deliveryStatus: "delivered",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId,
endedAt: now - 1_000,
error: [
+2 -3
View File
@@ -1,11 +1,10 @@
// Implements subagent commands for spawn, focus, routing, and status.
import { createLazyImportLoader } from "../../shared/lazy-promise.js";
import { defineAuthorizedTextCommand } from "./command-gates.js";
import { commandReply, defineAuthorizedTextCommand } from "./command-gates.js";
import {
resolveHandledPrefix,
resolveRequesterSessionKey,
resolveSubagentsAction,
stopWithText,
type SubagentsCommandContext,
} from "./commands-subagents-dispatch.js";
import type { CommandHandler } from "./commands-types.js";
@@ -82,7 +81,7 @@ export const handleSubagentsCommand: CommandHandler = defineAuthorizedTextComman
const requesterKey = resolveRequesterSessionKey(params);
if (!requesterKey) {
return stopWithText("⚠️ Missing session key.");
return commandReply("⚠️ Missing session key.");
}
const ctx: SubagentsCommandContext = {
@@ -6,9 +6,10 @@ import { getSubagentRunsSnapshotForRead } from "../../../agents/subagents/regist
import { getChannelPlugin, normalizeChannelId } from "../../../channels/plugins/index.js";
import { getSessionBindingService } from "../../../infra/outbound/session-binding-service.js";
import { resolveChannelAccountId, resolveCommandSurfaceChannel } from "../channel-context.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { formatRunLabel, sortSubagentRuns } from "../subagents-utils.js";
import { RECENT_WINDOW_MINUTES, type SubagentsCommandContext, stopWithText } from "./shared.js";
import { RECENT_WINDOW_MINUTES, type SubagentsCommandContext } from "./shared.js";
function formatConversationBindingText(params: { conversationId: string }): string {
return `binding:${params.conversationId}`;
@@ -124,5 +125,5 @@ export function handleSubagentsAgentsAction(ctx: SubagentsCommandContext): Comma
}
}
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
}
@@ -20,13 +20,13 @@ import {
} from "../../../channels/thread-bindings-policy.js";
import { normalizeConversationRef } from "../../../infra/outbound/session-binding-normalization.js";
import { getSessionBindingService } from "../../../infra/outbound/session-binding-service.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { resolveConversationBindingContextFromAcpCommand } from "../conversation-binding-input.js";
import {
type SubagentsCommandContext,
resolveCommandSubagentController,
resolveFocusTargetSession,
stopWithText,
} from "./shared.js";
type FocusBindingContext = {
@@ -74,17 +74,17 @@ export async function handleSubagentsFocusAction(
const { params, runs, restTokens } = ctx;
const token = restTokens.join(" ").trim();
if (!token) {
return stopWithText("Usage: /focus <subagent-label|session-key|session-id|session-label>");
return commandReply("Usage: /focus <subagent-label|session-key|session-id|session-label>");
}
const controller = resolveCommandSubagentController(params, ctx.requesterKey);
if (controller.controlScope !== "children") {
return stopWithText("⚠️ Leaf subagents cannot control other sessions.");
return commandReply("⚠️ Leaf subagents cannot control other sessions.");
}
const bindingContext = resolveFocusBindingContext(params);
if (!bindingContext) {
return stopWithText("⚠️ /focus must be run inside a bindable conversation.");
return commandReply("⚠️ /focus must be run inside a bindable conversation.");
}
const bindingService = getSessionBindingService();
@@ -93,7 +93,7 @@ export async function handleSubagentsFocusAction(
accountId: bindingContext.accountId,
});
if (!capabilities.adapterAvailable || !capabilities.bindSupported) {
return stopWithText("⚠️ Conversation bindings are unavailable for this account.");
return commandReply("⚠️ Conversation bindings are unavailable for this account.");
}
const focusTarget = await resolveFocusTargetSession({
@@ -102,7 +102,7 @@ export async function handleSubagentsFocusAction(
requesterKey: controller.controllerSessionKey,
});
if (!focusTarget) {
return stopWithText(`⚠️ Unable to resolve focus target: ${token}`);
return commandReply(`⚠️ Unable to resolve focus target: ${token}`);
}
if (bindingContext.placement === "child") {
@@ -113,7 +113,7 @@ export async function handleSubagentsFocusAction(
kind: "subagent",
});
if (!spawnPolicy.enabled) {
return stopWithText(
return commandReply(
`⚠️ ${formatThreadBindingDisabledError({
channel: spawnPolicy.channel,
accountId: spawnPolicy.accountId,
@@ -122,7 +122,7 @@ export async function handleSubagentsFocusAction(
);
}
if (bindingContext.placement === "child" && !spawnPolicy.spawnEnabled) {
return stopWithText(
return commandReply(
`⚠️ ${formatThreadBindingSpawnDisabledError({
channel: spawnPolicy.channel,
accountId: spawnPolicy.accountId,
@@ -145,7 +145,7 @@ export async function handleSubagentsFocusAction(
? existingBinding.metadata.boundBy.trim()
: "";
if (existingBinding && boundBy && boundBy !== "system" && senderId && senderId !== boundBy) {
return stopWithText(`⚠️ Only ${boundBy} can refocus this conversation.`);
return commandReply(`⚠️ Only ${boundBy} can refocus this conversation.`);
}
const label = focusTarget.label || token;
@@ -158,7 +158,7 @@ export async function handleSubagentsFocusAction(
})?.acp
: undefined;
if (!capabilities.placements.includes(bindingContext.placement)) {
return stopWithText("⚠️ Conversation bindings are unavailable for this account.");
return commandReply("⚠️ Conversation bindings are unavailable for this account.");
}
let binding;
@@ -206,12 +206,12 @@ export async function handleSubagentsFocusAction(
},
});
} catch {
return stopWithText("⚠️ Failed to bind this conversation to the target session.");
return commandReply("⚠️ Failed to bind this conversation to the target session.");
}
const actionText =
bindingContext.placement === "child"
? `created child conversation ${binding.conversation.conversationId} and bound it to ${binding.targetSessionKey}`
: `bound this conversation to ${binding.targetSessionKey}`;
return stopWithText(`${actionText} (${focusTarget.targetKind}).`);
return commandReply(`${actionText} (${focusTarget.targetKind}).`);
}
@@ -1,7 +1,8 @@
import { commandReply } from "../command-gates.js";
// Formats subagent command help text and usage summaries.
import type { CommandHandlerResult } from "../commands-types.js";
import { buildSubagentsHelp, stopWithText } from "./shared.js";
import { buildSubagentsHelp } from "./shared.js";
export function handleSubagentsHelpAction(): CommandHandlerResult {
return stopWithText(buildSubagentsHelp());
return commandReply(buildSubagentsHelp());
}
@@ -11,13 +11,10 @@ import { formatTimeAgo } from "../../../infra/format-time/format-relative.ts";
import { parseAgentSessionKey } from "../../../routing/session-key.js";
import { findTaskByRunIdForOwner } from "../../../tasks/task-owner-access.js";
import { sanitizeTaskStatusText } from "../../../tasks/task-status.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { formatRunLabel } from "../subagents-utils.js";
import {
resolveSubagentEntryForToken,
stopWithText,
type SubagentsCommandContext,
} from "./shared.js";
import { resolveSubagentEntryForToken, type SubagentsCommandContext } from "./shared.js";
function formatTimestampWithAge(valueMs?: number) {
if (!valueMs || !Number.isFinite(valueMs) || valueMs <= 0) {
@@ -48,7 +45,7 @@ export function handleSubagentsInfoAction(ctx: SubagentsCommandContext): Command
const { params, requesterKey, runs, restTokens } = ctx;
const target = restTokens[0];
if (!target) {
return stopWithText("️ Usage: /subagents info <id|#>");
return commandReply("️ Usage: /subagents info <id|#>");
}
const targetResolution = resolveSubagentEntryForToken(runs, target);
@@ -108,5 +105,5 @@ export function handleSubagentsInfoAction(ctx: SubagentsCommandContext): Command
linkedTask ? `Delivery: ${linkedTask.deliveryStatus}` : undefined,
].filter(Boolean);
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
}
@@ -1,7 +1,8 @@
// Lists subagent runs with focus and status information.
import { buildSubagentList } from "../../../agents/subagents/registry/subagent-list.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { type SubagentsCommandContext, RECENT_WINDOW_MINUTES, stopWithText } from "./shared.js";
import { type SubagentsCommandContext, RECENT_WINDOW_MINUTES } from "./shared.js";
export function handleSubagentsListAction(ctx: SubagentsCommandContext): CommandHandlerResult {
const { params, runs } = ctx;
@@ -24,5 +25,5 @@ export function handleSubagentsListAction(ctx: SubagentsCommandContext): Command
lines.push(list.recent.map((entry) => entry.line).join("\n"));
}
return stopWithText(lines.join("\n"));
return commandReply(lines.join("\n"));
}
@@ -3,6 +3,7 @@ import { parseStrictNonNegativeInteger } from "@openclaw/normalization-core/numb
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { stripToolMessages } from "../../../agents/tools/chat-history-text.js";
import { callGateway } from "../../../gateway/call.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { formatRunLabel } from "../subagents-utils.js";
import {
@@ -10,7 +11,6 @@ import {
type SubagentsCommandContext,
formatLogLines,
resolveSubagentEntryForToken,
stopWithText,
} from "./shared.js";
export async function handleSubagentsLogAction(
@@ -19,7 +19,7 @@ export async function handleSubagentsLogAction(
const { runs, restTokens } = ctx;
const target = restTokens[0];
if (!target) {
return stopWithText("📜 Usage: /subagents log <id|#> [limit]");
return commandReply("📜 Usage: /subagents log <id|#> [limit]");
}
const includeTools = restTokens.some(
@@ -45,7 +45,7 @@ export async function handleSubagentsLogAction(
const lines = formatLogLines(filtered as ChatMessage[]);
const header = `📜 Subagent log: ${formatRunLabel(targetResolution.entry)}`;
if (lines.length === 0) {
return stopWithText(`${header}\n(no messages)`);
return commandReply(`${header}\n(no messages)`);
}
return stopWithText([header, ...lines].join("\n"));
return commandReply([header, ...lines].join("\n"));
}
@@ -2,9 +2,10 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { normalizeConversationRef } from "../../../infra/outbound/session-binding-normalization.js";
import { getSessionBindingService } from "../../../infra/outbound/session-binding-service.js";
import { commandReply } from "../command-gates.js";
import type { CommandHandlerResult } from "../commands-types.js";
import { resolveConversationBindingContextFromAcpCommand } from "../conversation-binding-input.js";
import { type SubagentsCommandContext, stopWithText } from "./shared.js";
import type { SubagentsCommandContext } from "./shared.js";
export async function handleSubagentsUnfocusAction(
ctx: SubagentsCommandContext,
@@ -13,7 +14,7 @@ export async function handleSubagentsUnfocusAction(
const bindingService = getSessionBindingService();
const bindingContext = resolveConversationBindingContextFromAcpCommand(params);
if (!bindingContext) {
return stopWithText("⚠️ /unfocus must be run inside a focused conversation.");
return commandReply("⚠️ /unfocus must be run inside a focused conversation.");
}
const binding = bindingService.resolveByConversation(
@@ -25,18 +26,18 @@ export async function handleSubagentsUnfocusAction(
}),
);
if (!binding) {
return stopWithText("️ This conversation is not currently focused.");
return commandReply("️ This conversation is not currently focused.");
}
const senderId = normalizeOptionalString(params.command.senderId) ?? "";
const boundBy = normalizeOptionalString(binding.metadata?.boundBy) ?? "";
if (boundBy && boundBy !== "system" && senderId && senderId !== boundBy) {
return stopWithText(`⚠️ Only ${boundBy} can unfocus this conversation.`);
return commandReply(`⚠️ Only ${boundBy} can unfocus this conversation.`);
}
await bindingService.unbind({
bindingId: binding.bindingId,
reason: "manual",
});
return stopWithText("✅ Conversation unfocused.");
return commandReply("✅ Conversation unfocused.");
}
@@ -18,6 +18,7 @@ import { parseAgentSessionKey } from "../../../routing/session-key.js";
import { isSubagentSessionKey } from "../../../routing/session-key.js";
import { looksLikeSessionId } from "../../../sessions/session-id.js";
import { isNativeCommandTurn, resolveCommandTurnContext } from "../../command-turn-context.js";
import { commandReply } from "../command-gates.js";
import { extractMessageText, type ChatMessage } from "../commands-subagents-text.js";
import type { CommandHandler, CommandHandlerResult } from "../commands-types.js";
import {
@@ -48,12 +49,8 @@ export type SubagentsCommandContext = {
restTokens: string[];
};
export function stopWithText(text: string): CommandHandlerResult {
return { shouldContinue: false, reply: { text } };
}
function stopWithUnknownTargetError(error?: string): CommandHandlerResult {
return stopWithText(`⚠️ ${error ?? "Unknown subagent."}`);
return commandReply(`⚠️ ${error ?? "Unknown subagent."}`);
}
function resolveSubagentTarget(
+19 -19
View File
@@ -2,10 +2,10 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
import {
completeTaskRunByRunId,
createQueuedTaskRun,
createRunningTaskRun,
failTaskRunByRunId,
completeTaskRunByRunIdCore,
createQueuedTaskRunCore,
createRunningTaskRunCore,
failTaskRunByRunIdCore,
} from "../../tasks/task-executor.js";
import { resetTaskRegistryForTests } from "../../tasks/task-runtime.test-helpers.js";
import { handleTasksCommand } from "./commands-tasks.js";
@@ -55,7 +55,7 @@ describe("handleTasksCommand task board", () => {
});
it("lists active and recent tasks for the current session", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:tasks-running",
@@ -63,21 +63,21 @@ describe("handleTasksCommand task board", () => {
task: "active background task",
progressSummary: "still working",
});
createQueuedTaskRun({
createQueuedTaskRunCore({
runtime: "cron",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:tasks-queued",
runId: "run-tasks-queued",
task: "queued background task",
});
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "acp",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:acp:tasks-failed",
runId: "run-tasks-failed",
task: "failed background task",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "run-tasks-failed",
endedAt: Date.now(),
error: "approval denied",
@@ -94,7 +94,7 @@ describe("handleTasksCommand task board", () => {
});
it("lists session-backed video generation tasks for the current session", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "cli",
taskKind: "video_generation",
sourceId: "video_generate:openai",
@@ -117,7 +117,7 @@ describe("handleTasksCommand task board", () => {
});
it("lists session-backed image generation tasks for the current session", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "cli",
taskKind: "image_generation",
sourceId: "image_generate:openai",
@@ -140,7 +140,7 @@ describe("handleTasksCommand task board", () => {
});
it("sanitizes leaked internal runtime context from visible task details", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "acp",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:acp:tasks-sanitized-failed",
@@ -148,7 +148,7 @@ describe("handleTasksCommand task board", () => {
task: "Visible failed task",
progressSummary: "still working",
});
failTaskRunByRunId({
failTaskRunByRunIdCore({
runId: "run-tasks-sanitized-failed",
endedAt: Date.now(),
error: [
@@ -170,7 +170,7 @@ describe("handleTasksCommand task board", () => {
});
it("sanitizes inline internal runtime fences from visible task titles", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "cli",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:main",
@@ -182,7 +182,7 @@ describe("handleTasksCommand task board", () => {
].join("\n"),
progressSummary: "done",
});
completeTaskRunByRunId({
completeTaskRunByRunIdCore({
runId: "run-tasks-inline-fence",
endedAt: Date.now(),
terminalSummary: "Finished.",
@@ -198,14 +198,14 @@ describe("handleTasksCommand task board", () => {
});
it("hides stale completed tasks from the task board", async () => {
createQueuedTaskRun({
createQueuedTaskRunCore({
runtime: "cron",
requesterSessionKey: "agent:main:main",
childSessionKey: "agent:main:subagent:tasks-stale",
runId: "run-tasks-stale",
task: "stale completed task",
});
completeTaskRunByRunId({
completeTaskRunByRunIdCore({
runId: "run-tasks-stale",
endedAt: Date.now() - 10 * 60_000,
terminalSummary: "done a while ago",
@@ -219,7 +219,7 @@ describe("handleTasksCommand task board", () => {
});
it("falls back to agent-local counts when the current session has no visible tasks", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:main:other-session",
childSessionKey: "agent:main:subagent:tasks-agent-fallback",
@@ -240,7 +240,7 @@ describe("handleTasksCommand task board", () => {
});
it("counts session-backed video generation tasks in agent-local fallback", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "cli",
taskKind: "video_generation",
sourceId: "video_generate:openai",
@@ -265,7 +265,7 @@ describe("handleTasksCommand task board", () => {
});
it("uses the canonical target session agent for agent-local fallback counts", async () => {
createRunningTaskRun({
createRunningTaskRunCore({
runtime: "subagent",
requesterSessionKey: "agent:target:other-session",
childSessionKey: "agent:target:subagent:tasks-target-fallback",
+2 -2
View File
@@ -3,7 +3,7 @@ import { createLazyImportLoader } from "../../shared/lazy-promise.js";
type ShouldBypassAcpDispatchForCommand =
(typeof import("./dispatch-acp-command-bypass.js"))["shouldBypassAcpDispatchForCommand"];
type TryDispatchAcpReply = (typeof import("./dispatch-acp.js"))["tryDispatchAcpReply"];
type TryDispatchAcpReply = (typeof import("./dispatch-acp.js"))["tryDispatchAcpReplyCore"];
const dispatchAcpLoader = createLazyImportLoader(() => import("./dispatch-acp.js"));
const dispatchAcpCommandBypassLoader = createLazyImportLoader(
@@ -29,5 +29,5 @@ export async function tryDispatchAcpReply(
...args: Parameters<TryDispatchAcpReply>
): Promise<Awaited<ReturnType<TryDispatchAcpReply>>> {
const mod = await loadDispatchAcp();
return await mod.tryDispatchAcpReply(...args);
return await mod.tryDispatchAcpReplyCore(...args);
}
+3 -3
View File
@@ -17,7 +17,7 @@ import {
resolveAgentTurnAttachments,
resolveInlineAgentImageAttachments,
} from "./agent-turn-attachments.js";
import { tryDispatchAcpReply } from "./dispatch-acp.js";
import { tryDispatchAcpReplyCore } from "./dispatch-acp.js";
import { createAbortAwareDispatcher } from "./dispatch-from-config.abort.js";
import {
appendRecentHistoryImageContext,
@@ -370,7 +370,7 @@ async function runDispatch(params: {
markIdle?: (reason: string) => void;
}) {
const targetSessionKey = params.sessionKeyOverride ?? sessionKey;
return tryDispatchAcpReply({
return tryDispatchAcpReplyCore({
ctx: buildTestCtx({
Provider: "discord",
Surface: "discord",
@@ -486,7 +486,7 @@ function expectRoutedPayload(callIndex: number, payload: Partial<MockTtsReply>)
}
}
describe("tryDispatchAcpReply", () => {
describe("tryDispatchAcpReplyCore", () => {
beforeEach(() => {
auditMocks.emitAcpLifecycleStart.mockReset();
auditMocks.emitAcpRuntimeEvent.mockReset();
+1 -1
View File
@@ -408,7 +408,7 @@ async function finalizeAcpTurnOutput(params: {
return queuedFinal;
}
export async function tryDispatchAcpReply(params: {
export async function tryDispatchAcpReplyCore(params: {
ctx: FinalizedRuntimeMsgContext;
cfg: OpenClawConfig;
dispatcher: ReplyDispatcher;
+3 -6
View File
@@ -118,18 +118,15 @@ export function isSessionDefaultDirectiveValue(raw?: string | null): boolean {
}
/** Chooses the default thinking level for one provider/model catalog entry. */
export function resolveThinkingDefaultForModel(params: {
export function resolveThinkingDefaultForModelCore(params: {
provider: string;
model: string;
catalog?: ThinkingCatalogEntry[];
catalog?: readonly ThinkingCatalogEntry[];
}): ThinkLevel {
const candidate = params.catalog?.find(
(entry) => entry.provider === params.provider && entry.id === params.model,
);
if (candidate?.reasoning) {
return "low";
}
return "off";
return candidate?.reasoning ? "low" : "off";
}
type OnOffFullLevel = "off" | "on" | "full";
+2 -2
View File
@@ -4,7 +4,7 @@ import { resolveClaudeThinkingProfile } from "../plugins/provider-claude-thinkin
import {
BASE_THINKING_LEVELS,
normalizeThinkLevel,
resolveThinkingDefaultForModel as resolveThinkingDefaultForModelFallback,
resolveThinkingDefaultForModelCore,
THINKING_LEVEL_RANKS,
} from "./thinking.shared.js";
import type { ThinkLevel, ThinkingCatalogEntry } from "./thinking.shared.js";
@@ -311,7 +311,7 @@ export function resolveThinkingDefaultForModel(params: {
if (profile.defaultLevel) {
return profile.defaultLevel;
}
const fallback = resolveThinkingDefaultForModelFallback(params);
const fallback = resolveThinkingDefaultForModelCore(params);
if (fallback === "off") {
return "off";
}
+3 -3
View File
@@ -1,9 +1,9 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { buildChannelAccountSnapshot } from "./account-summary.js";
import { buildChannelAccountSummary } from "./account-summary.js";
import type { ChannelPlugin } from "./plugins/types.plugin.js";
describe("buildChannelAccountSnapshot", () => {
describe("buildChannelAccountSummary", () => {
it("redacts a raw baseUrl returned by describeAccount without mutating the account", () => {
const rawBaseUrl = [
"https://",
@@ -25,7 +25,7 @@ describe("buildChannelAccountSnapshot", () => {
},
} as unknown as ChannelPlugin;
const snapshot = buildChannelAccountSnapshot({
const snapshot = buildChannelAccountSummary({
plugin,
account,
cfg: {} as OpenClawConfig,
+1 -1
View File
@@ -16,7 +16,7 @@ import type { ChannelPlugin } from "./plugins/types.plugin.js";
/**
* Builds the safe account snapshot shown by CLI, gateway, and status summaries.
*/
export function buildChannelAccountSnapshot(params: {
export function buildChannelAccountSummary(params: {
plugin: ChannelPlugin;
account: unknown;
cfg: OpenClawConfig;
+1 -1
View File
@@ -16,7 +16,7 @@ import {
type ParsedThreadSessionSuffix,
type RawSessionConversationRef,
} from "../../sessions/session-key-utils.js";
import { normalizeChannelId as normalizeChatChannelId } from "../registry.js";
import { normalizeChatChannelId } from "../registry.js";
import { getLoadedChannelPlugin, normalizeChannelId as normalizeAnyChannelId } from "./registry.js";
/**
+1 -1
View File
@@ -96,7 +96,7 @@ export async function buildReadOnlySourceChannelAccountSnapshot<ResolvedAccount>
});
}
export async function buildChannelAccountSnapshot<ResolvedAccount>(params: {
export async function resolveChannelAccountSnapshot<ResolvedAccount>(params: {
plugin: ChannelPlugin<ResolvedAccount>;
cfg: OpenClawConfig;
accountId: string;
+1 -8
View File
@@ -1,6 +1,6 @@
// Public channel registry facade for channel ids, metadata, and setup copy.
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { normalizeChatChannelId, type ChatChannelId } from "./ids.js";
import { normalizeChatChannelId } from "./ids.js";
import type { ChannelId } from "./plugins/channel-id.types.js";
import type { ChannelMeta } from "./plugins/types.core.js";
import {
@@ -13,13 +13,6 @@ export type { ChatChannelId } from "./ids.js";
export { normalizeAnyChannelId } from "./registry-normalize.js";
export { normalizeChatChannelId };
/**
* Normalizes built-in chat channel ids without loading channel plugin implementations.
*/
export function normalizeChannelId(raw?: string | null): ChatChannelId | null {
return normalizeChatChannelId(raw);
}
/**
* Lists registered channel plugin ids without importing their runtime implementations.
*/
+2 -2
View File
@@ -25,7 +25,7 @@ import {
import { publishOutputFileAtomically } from "./output-file.runtime.js";
import { getCoreCliCommandNames, registerCoreCliByName } from "./program/command-registry-core.js";
import { getProgramContext } from "./program/program-context.js";
import { getSubCliEntries, registerSubCliByName } from "./program/register.subclis-core.js";
import { getSubCliEntries, registerSubCliByNameCore } from "./program/register.subclis-core.js";
import { quoteCliArg } from "./quote-cli-arg.js";
export function getCompletionScript(shell: CompletionShell, program: Command): string {
@@ -164,7 +164,7 @@ async function registerSubcommandsForCompletion(program: Command): Promise<void>
continue;
}
try {
await registerSubCliByName(program, entry.name, process.argv, { purpose: "completion" });
await registerSubCliByNameCore(program, entry.name, process.argv, { purpose: "completion" });
} catch (error) {
writeCompletionRegistrationWarning(
`skipping subcommand \`${entry.name}\` while building completion cache: ${error instanceof Error ? error.message : String(error)}`,
+1 -1
View File
@@ -63,7 +63,7 @@ vi.mock("./program/program-context.js", () => ({
vi.mock("./program/register.subclis-core.js", () => ({
getSubCliEntries: getSubCliEntriesMock,
registerSubCliByName: registerSubCliByNameMock,
registerSubCliByNameCore: registerSubCliByNameMock,
}));
vi.mock("../plugins/cli.js", () => ({
+5 -5
View File
@@ -7,7 +7,7 @@ import {
defaultRuntime,
resetLifecycleRuntimeLogs,
resetLifecycleServiceMocks,
runtimeLogs,
lifecycleRuntimeLogs,
service,
stubEmptyGatewayEnv,
} from "./test-helpers/lifecycle-core-harness.js";
@@ -74,7 +74,7 @@ let runServiceStop: typeof import("./lifecycle-core.js").runServiceStop;
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- Test helper lets assertions ascribe logged JSON shape.
function readJsonLog<T extends object>() {
const jsonLine = runtimeLogs.find((line) => line.trim().startsWith("{"));
const jsonLine = lifecycleRuntimeLogs.find((line) => line.trim().startsWith("{"));
return JSON.parse(jsonLine ?? "{}") as T;
}
@@ -248,8 +248,8 @@ describe("runServiceRestart token drift", () => {
opts: { json: false },
});
expect(runtimeLogs).toContain("Gateway service not loaded.");
expect(runtimeLogs).toContain(
expect(lifecycleRuntimeLogs).toContain("Gateway service not loaded.");
expect(lifecycleRuntimeLogs).toContain(
"Start with: Restart the container or the service that manages it for openclaw-demo-container.",
);
});
@@ -680,7 +680,7 @@ describe("runServiceRestart token drift", () => {
expectedPort: 19_001,
});
const repairWarnings = runtimeLogs.filter((line) =>
const repairWarnings = lifecycleRuntimeLogs.filter((line) =>
line.startsWith(
"Gateway service already running, but its installed service definition needs repair:",
),
@@ -5,7 +5,7 @@ import type { MockFn } from "../../../test-utils/vitest-mock-fn.js";
import { createCliRuntimeCapture } from "../../test-runtime-capture.js";
const lifecycleRuntimeCapture = createCliRuntimeCapture();
export const runtimeLogs = lifecycleRuntimeCapture.runtimeLogs;
export const lifecycleRuntimeLogs = lifecycleRuntimeCapture.runtimeLogs;
type LifecycleRuntimeHarness = typeof lifecycleRuntimeCapture.defaultRuntime;
type LifecycleServiceHarness = GatewayService & {
+2 -2
View File
@@ -1,5 +1,5 @@
// Default CLI dependency surface with lazy outbound channel send adapters.
import { normalizeChannelId } from "../channels/registry.js";
import { normalizeChatChannelId } from "../channels/registry.js";
import { getOrCreatePromise } from "../shared/lazy-promise.js";
import type { CliDeps } from "./deps.types.js";
@@ -45,7 +45,7 @@ const NON_CHANNEL_DEP_KEYS = new Set([
]);
function resolveKnownChannelId(raw: string): string | undefined {
return normalizeChannelId(raw) ?? undefined;
return normalizeChatChannelId(raw) ?? undefined;
}
// Per-channel module caches for lazy loading.
+46 -46
View File
@@ -141,14 +141,14 @@ export const buildPluginDiagnosticsReport: UnknownMock = vi.fn();
const buildPluginCompatibilityNotices: UnknownMock = vi.fn();
export const inspectPluginRegistry: AsyncUnknownMock = vi.fn();
export const refreshPluginRegistry: AsyncUnknownMock = vi.fn();
export const notifyGatewayPluginMetadataChanged: AsyncUnknownMock = vi.fn();
export const notifyGatewayPluginMetadataChangedMock: AsyncUnknownMock = vi.fn();
export const clearPluginRegistryLoadCache: UnknownMock = vi.fn();
export const applyExclusiveSlotSelection: UnknownMock = vi.fn();
export const planPluginUninstall: UnknownMock = vi.fn();
export const applyPluginUninstallDirectoryRemoval: AsyncUnknownMock = vi.fn();
export const updateNpmInstalledPlugins: Mock<UpdateNpmInstalledPluginsFn> = vi.fn();
export const updateNpmInstalledHookPacks: Mock<UpdateNpmInstalledHookPacksFn> = vi.fn();
export const promptYesNo: AsyncUnknownMock = vi.fn();
export const promptYesNoMock: AsyncUnknownMock = vi.fn();
const promptText: AsyncUnknownMock = vi.fn();
export class PromptInputClosedError extends Error {
constructor() {
@@ -168,42 +168,44 @@ export const installHooksFromNpmSpec: AsyncUnknownMock = vi.fn();
export const installHooksFromPath: AsyncUnknownMock = vi.fn();
export const recordHookInstall: UnknownMock = vi.fn();
const { defaultRuntime, runtimeLogs, runtimeErrors, resetRuntimeCapture } = vi.hoisted(() => {
const runtimeLogsLocal: string[] = [];
const runtimeErrorsLocal: string[] = [];
const stringifyArgs = (args: unknown[]) => args.map((value) => String(value)).join(" ");
const normalizeStdout = (value: string) => (value.endsWith("\n") ? value.slice(0, -1) : value);
const stringifyJson = (value: unknown, space = 2) =>
JSON.stringify(value, null, space > 0 ? space : undefined);
const defaultRuntimeLocal = {
log: vi.fn((...args: unknown[]) => {
runtimeLogsLocal.push(stringifyArgs(args));
}),
error: vi.fn((...args: unknown[]) => {
runtimeErrorsLocal.push(stringifyArgs(args));
}),
writeStdout: vi.fn((value: string) => {
defaultRuntimeLocal.log(normalizeStdout(value));
}),
writeJson: vi.fn((value: unknown, space = 2) => {
defaultRuntimeLocal.log(stringifyJson(value, space));
}),
exit: vi.fn((code: number) => {
throw new Error(`__exit__:${code}`);
}),
} as CliMockOutputRuntime;
return {
defaultRuntime: defaultRuntimeLocal,
runtimeLogs: runtimeLogsLocal,
runtimeErrors: runtimeErrorsLocal,
resetRuntimeCapture: () => {
runtimeLogsLocal.length = 0;
runtimeErrorsLocal.length = 0;
},
};
});
const { defaultRuntime, pluginsCliRuntimeLogs, runtimeErrors, resetRuntimeCapture } = vi.hoisted(
() => {
const runtimeLogsLocal: string[] = [];
const runtimeErrorsLocal: string[] = [];
const stringifyArgs = (args: unknown[]) => args.map((value) => String(value)).join(" ");
const normalizeStdout = (value: string) => (value.endsWith("\n") ? value.slice(0, -1) : value);
const stringifyJson = (value: unknown, space = 2) =>
JSON.stringify(value, null, space > 0 ? space : undefined);
const defaultRuntimeLocal = {
log: vi.fn((...args: unknown[]) => {
runtimeLogsLocal.push(stringifyArgs(args));
}),
error: vi.fn((...args: unknown[]) => {
runtimeErrorsLocal.push(stringifyArgs(args));
}),
writeStdout: vi.fn((value: string) => {
defaultRuntimeLocal.log(normalizeStdout(value));
}),
writeJson: vi.fn((value: unknown, space = 2) => {
defaultRuntimeLocal.log(stringifyJson(value, space));
}),
exit: vi.fn((code: number) => {
throw new Error(`__exit__:${code}`);
}),
} as CliMockOutputRuntime;
return {
defaultRuntime: defaultRuntimeLocal,
pluginsCliRuntimeLogs: runtimeLogsLocal,
runtimeErrors: runtimeErrorsLocal,
resetRuntimeCapture: () => {
runtimeLogsLocal.length = 0;
runtimeErrorsLocal.length = 0;
},
};
},
);
export { runtimeErrors, runtimeLogs };
export { runtimeErrors, pluginsCliRuntimeLogs };
export function setInstalledPluginIndexInstallRecords(records: PluginInstallRecordMap): void {
mockInstalledPluginIndexInstallRecords = clonePluginInstallRecords(records);
@@ -212,7 +214,7 @@ export function setInstalledPluginIndexInstallRecords(records: PluginInstallReco
function restoreRuntimeCaptureMocks() {
defaultRuntime.log.mockReset();
defaultRuntime.log.mockImplementation((...args: unknown[]) => {
runtimeLogs.push(args.map((value) => String(value)).join(" "));
pluginsCliRuntimeLogs.push(args.map((value) => String(value)).join(" "));
});
defaultRuntime.error.mockReset();
@@ -244,7 +246,7 @@ vi.mock("../runtime.js", () => ({
vi.mock("./plugins-update-gateway-signal.js", () => ({
notifyGatewayPluginMetadataChanged: (...args: unknown[]) =>
notifyGatewayPluginMetadataChanged(...args),
notifyGatewayPluginMetadataChangedMock(...args),
}));
vi.mock("../config/config.js", () => ({
@@ -630,7 +632,7 @@ vi.mock("./prompt.js", () => ({
invokeMock<
Parameters<(typeof import("./prompt.js"))["promptYesNo"]>,
ReturnType<(typeof import("./prompt.js"))["promptYesNo"]>
>(promptYesNo, ...args)) as (typeof import("./prompt.js"))["promptYesNo"],
>(promptYesNoMock, ...args)) as (typeof import("./prompt.js"))["promptYesNo"],
}));
vi.mock("../plugins/install.js", () => ({
@@ -806,8 +808,6 @@ vi.mock("../infra/clawhub-packages.js", () => ({
const { registerPluginsCli } = await import("./plugins-cli.js");
export { registerPluginsCli };
export async function runPluginsCommand(argv: string[]) {
const program = new Command();
program.exitOverride();
@@ -844,7 +844,7 @@ export function resetPluginsCliTestState() {
buildPluginCompatibilityNotices.mockReset();
inspectPluginRegistry.mockReset();
refreshPluginRegistry.mockReset();
notifyGatewayPluginMetadataChanged.mockReset();
notifyGatewayPluginMetadataChangedMock.mockReset();
clearPluginRegistryLoadCache.mockReset();
applyExclusiveSlotSelection.mockReset();
planPluginUninstall.mockReset();
@@ -853,7 +853,7 @@ export function resetPluginsCliTestState() {
updateNpmInstalledHookPacks.mockReset();
mockHookInstallRecords = {};
promptText.mockReset();
promptYesNo.mockReset();
promptYesNoMock.mockReset();
installPluginFromGitSpec.mockReset();
parseGitPluginSpec.mockReset();
installPluginFromNpmSpec.mockReset();
@@ -976,7 +976,7 @@ export function resetPluginsCliTestState() {
current: defaultRegistryIndex,
});
refreshPluginRegistry.mockResolvedValue(defaultRegistryIndex);
notifyGatewayPluginMetadataChanged.mockResolvedValue(true);
notifyGatewayPluginMetadataChangedMock.mockResolvedValue(true);
applyExclusiveSlotSelection.mockImplementation((({ config }: { config: OpenClawConfig }) => ({
config,
warnings: [],
@@ -1008,7 +1008,7 @@ export function resetPluginsCliTestState() {
changed: false,
config: {} as OpenClawConfig,
});
promptYesNo.mockResolvedValue(true);
promptYesNoMock.mockResolvedValue(true);
promptText.mockResolvedValue("demo");
installPluginFromPath.mockResolvedValue({ ok: false, error: "path install disabled in test" });
installPluginFromGitSpec.mockResolvedValue({
+8 -8
View File
@@ -30,7 +30,7 @@ import {
readConfigFileSnapshot,
readConfigFileSnapshotForWrite,
parseClawHubPluginSpec,
promptYesNo,
promptYesNoMock,
reportClawHubPluginInstallTelemetry,
recordHookInstall,
recordPluginInstall,
@@ -38,7 +38,7 @@ import {
replaceConfigFile,
runPluginsCommand,
runtimeErrors,
runtimeLogs,
pluginsCliRuntimeLogs,
writeConfigFile,
writePersistedInstalledPluginIndexInstallRecordsWithLease,
} from "./plugins-cli-test-helpers.js";
@@ -456,7 +456,7 @@ function recordHookInstallCall(callIndex = 0): PersistedInstallRecord {
}
function runtimeLogsContain(fragment: string): boolean {
return runtimeLogs.some((line) => line.includes(fragment));
return pluginsCliRuntimeLogs.some((line) => line.includes(fragment));
}
function setTty(value: boolean): void {
@@ -1444,14 +1444,14 @@ describe("plugins cli install", () => {
fs.rmSync(localPath, { recursive: true, force: true });
}
expect(promptYesNo).not.toHaveBeenCalled();
expect(promptYesNoMock).not.toHaveBeenCalled();
expect(runtimeErrors.join("\n")).not.toContain("outside ClawHub review");
expect(installPluginFromPath).toHaveBeenCalledTimes(1);
});
it("prompts interactive users before non-ClawHub plugin installs and cancels on no", async () => {
setTty(true);
promptYesNo.mockResolvedValueOnce(false);
promptYesNoMock.mockResolvedValueOnce(false);
primeSuccessfulPluginPersistence("demo");
installPluginFromNpmSpec.mockResolvedValue(createNpmPluginInstallResult("demo"));
@@ -1459,7 +1459,7 @@ describe("plugins cli install", () => {
"__exit__:1",
);
expect(promptYesNo).toHaveBeenCalledWith("Install this non-ClawHub plugin source?");
expect(promptYesNoMock).toHaveBeenCalledWith("Install this non-ClawHub plugin source?");
expect(runtimeLogsContain("Installing plugin from npm registry")).toBe(true);
expect(runtimeLogsContain("outside ClawHub review")).toBe(true);
expect(installPluginFromNpmSpec).not.toHaveBeenCalled();
@@ -1467,13 +1467,13 @@ describe("plugins cli install", () => {
it("prompts interactive users before non-ClawHub plugin installs and proceeds on yes", async () => {
setTty(true);
promptYesNo.mockResolvedValueOnce(true);
promptYesNoMock.mockResolvedValueOnce(true);
primeSuccessfulPluginPersistence("demo");
installPluginFromNpmSpec.mockResolvedValue(createNpmPluginInstallResult("demo"));
await runPluginsCommand(["plugins", "install", "npm:demo"]);
expect(promptYesNo).toHaveBeenCalledWith("Install this non-ClawHub plugin source?");
expect(promptYesNoMock).toHaveBeenCalledWith("Install this non-ClawHub plugin source?");
expect(runtimeLogsContain("Installing plugin from npm registry")).toBe(true);
expect(runtimeLogsContain("outside ClawHub review")).toBe(true);
expect(installPluginFromNpmSpec).toHaveBeenCalledTimes(1);
+46 -46
View File
@@ -20,7 +20,7 @@ import {
refreshPluginRegistry,
runPluginsCommand,
runtimeErrors,
runtimeLogs,
pluginsCliRuntimeLogs,
setInstalledPluginIndexInstallRecords,
} from "./plugins-cli-test-helpers.js";
@@ -103,7 +103,7 @@ describe("plugins cli list", () => {
expect(reportOptions?.logger?.warn).toBeTypeOf("function");
expect(reportOptions?.logger?.error).toBeTypeOf("function");
const output = JSON.parse(runtimeLogs[0] ?? "null") as {
const output = JSON.parse(pluginsCliRuntimeLogs[0] ?? "null") as {
workspaceDir?: string;
registry?: { source?: string; diagnostics?: unknown[] };
plugins?: Array<{
@@ -134,7 +134,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
expect(buildPluginDiagnosticsReport).toHaveBeenCalledWith({ config: {}, effectiveOnly: true });
expect(runtimeLogs).toContain(cleanDoctorMessage);
expect(pluginsCliRuntimeLogs).toContain(cleanDoctorMessage);
});
it.each([
@@ -155,7 +155,7 @@ describe("plugins cli list", () => {
const warning =
"- plugins.entries.google: plugin disabled (not in allowlist) but config is present";
if (args.includes("--json")) {
const output = JSON.parse(runtimeLogs[0] ?? "null") as {
const output = JSON.parse(pluginsCliRuntimeLogs[0] ?? "null") as {
ok: boolean;
configurationWarnings: string[];
};
@@ -163,8 +163,8 @@ describe("plugins cli list", () => {
expect(output.configurationWarnings).toEqual([warning]);
return;
}
expect(runtimeLogs.join("\n")).toContain(warning);
expect(runtimeLogs).not.toContain(cleanDoctorMessage);
expect(pluginsCliRuntimeLogs.join("\n")).toContain(warning);
expect(pluginsCliRuntimeLogs).not.toContain(cleanDoctorMessage);
},
);
@@ -183,7 +183,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor", "--json"]);
const output = JSON.parse(runtimeLogs[0] ?? "null") as {
const output = JSON.parse(pluginsCliRuntimeLogs[0] ?? "null") as {
ok: boolean;
configurationWarnings: string[];
};
@@ -205,13 +205,13 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor", ...args]);
if (args.includes("--json")) {
expect(JSON.parse(runtimeLogs[0] ?? "null")).toMatchObject({
expect(JSON.parse(pluginsCliRuntimeLogs[0] ?? "null")).toMatchObject({
ok: true,
configurationWarnings: [],
});
return;
}
expect(runtimeLogs).toContain(cleanDoctorMessage);
expect(pluginsCliRuntimeLogs).toContain(cleanDoctorMessage);
});
it.each([
@@ -229,13 +229,13 @@ describe("plugins cli list", () => {
const warning = "- plugins.\\nentries.google: bad\\r\\n\\tvalue";
if (args.includes("--json")) {
expect(JSON.parse(runtimeLogs[0] ?? "null")).toMatchObject({
expect(JSON.parse(pluginsCliRuntimeLogs[0] ?? "null")).toMatchObject({
ok: false,
configurationWarnings: [warning],
});
return;
}
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain(warning);
expect(output).not.toContain("\u0007");
expect(output).not.toContain("\u001b");
@@ -273,12 +273,12 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor", "--json"]);
});
expect(runtimeLogs).toHaveLength(1);
expect(pluginsCliRuntimeLogs).toHaveLength(1);
expect(runtimeErrors).toEqual([]);
expect(runtimeLogs[0]).not.toContain(homeDir);
expect(runtimeLogs[0]).not.toContain("Plugin errors:");
expect(runtimeLogs[0]).not.toContain("Docs:");
expect(JSON.parse(runtimeLogs[0] ?? "null")).toEqual({
expect(pluginsCliRuntimeLogs[0]).not.toContain(homeDir);
expect(pluginsCliRuntimeLogs[0]).not.toContain("Plugin errors:");
expect(pluginsCliRuntimeLogs[0]).not.toContain("Docs:");
expect(JSON.parse(pluginsCliRuntimeLogs[0] ?? "null")).toEqual({
ok: false,
pluginErrors: [
{
@@ -344,7 +344,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("Diagnostics:");
expect(output).toContain(expected);
expect(output).not.toContain(cleanDoctorMessage);
@@ -362,7 +362,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("broken: plugin manifest invalid");
expect(output).toContain("calendar: required plugin contacts is missing");
expect(output).not.toContain(cleanDoctorMessage);
@@ -403,7 +403,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("Plugin configuration:");
expect(output).toContain(
"Stale plugin references (plugins.allow/deny/entries): lossless-claw.",
@@ -455,7 +455,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("Plugin configuration:");
expect(output).toContain('Configured runtime "codex" requires the Codex plugin');
expect(output).toContain("openclaw doctor --fix");
@@ -480,7 +480,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("Plugin configuration:");
expect(output).toContain('Configured runtime "acpx" requires the ACPX Runtime plugin');
expect(output).toContain("openclaw doctor --fix");
@@ -507,7 +507,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain('Configured runtime "acpx" requires the ACPX Runtime plugin');
expect(output).toContain("Set plugins.entries.acpx.enabled=true");
expect(output).toContain("disable ACP/acpx in acp config");
@@ -530,7 +530,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain('Configured runtime "acpx" requires the ACPX Runtime plugin');
expect(output).toContain('Enable the "acpx" plugin');
expect(output).toContain("disable ACP/acpx in acp config");
@@ -555,7 +555,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).not.toContain('Configured runtime "codex"');
expect(output).toContain(cleanDoctorMessage);
});
@@ -580,7 +580,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
expect(runtimeLogs).toContain(cleanDoctorMessage);
expect(pluginsCliRuntimeLogs).toContain(cleanDoctorMessage);
});
it("reports configured Codex runtime when the plugin record is disabled", async () => {
@@ -603,7 +603,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain('Configured runtime "codex" requires the Codex plugin');
expect(output).toContain('but "codex" is disabled');
expect(output).toContain('Enable the "codex" plugin');
@@ -634,7 +634,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain('Configured runtime "codex" requires the Codex plugin');
expect(output).toContain('but "codex" is blocked by plugin configuration');
expect(output).toContain('Remove "codex" from plugins.deny');
@@ -668,7 +668,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain('Configured runtime "codex" requires the Codex plugin');
expect(output).toContain('but "codex" is blocked by plugin configuration');
expect(output).toContain("Set plugins.entries.codex.enabled=true");
@@ -701,7 +701,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
const output = runtimeLogs.join("\n");
const output = pluginsCliRuntimeLogs.join("\n");
expect(output).toContain("Plugin source shadowing:");
expect(output).toContain(
"discord: duplicate plugin id resolved by explicit config-selected plugin",
@@ -734,7 +734,7 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "doctor"]);
expect(runtimeLogs).toContain(cleanDoctorMessage);
expect(pluginsCliRuntimeLogs).toContain(cleanDoctorMessage);
});
it("reports persisted plugin registry state without refreshing", async () => {
@@ -756,10 +756,10 @@ describe("plugins cli list", () => {
expect(inspectPluginRegistry).toHaveBeenCalledWith({ config: {} });
expect(refreshPluginRegistry).not.toHaveBeenCalled();
expect(runtimeLogs.join("\n")).toContain("State:");
expect(runtimeLogs.join("\n")).toContain("stale");
expect(runtimeLogs.join("\n")).toContain("Refresh reasons:");
expect(runtimeLogs.join("\n")).toContain("openclaw plugins registry --refresh");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("State:");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("stale");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("Refresh reasons:");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("openclaw plugins registry --refresh");
});
it("refreshes the persisted plugin registry on request", async () => {
@@ -777,7 +777,7 @@ describe("plugins cli list", () => {
reason: "manual",
});
expect(inspectPluginRegistry).not.toHaveBeenCalled();
expect(runtimeLogs.join("\n")).toContain("Plugin registry refreshed: 1/2 enabled");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("Plugin registry refreshed: 1/2 enabled");
});
it("keeps inspect on the static snapshot by default", async () => {
@@ -839,19 +839,19 @@ describe("plugins cli list", () => {
await runPluginsCommand(["plugins", "inspect", "openclaw-mem0"]);
expect(buildPluginDiagnosticsReport).not.toHaveBeenCalled();
expect(runtimeLogs.join("\n")).toContain("Policy");
expect(runtimeLogs.join("\n")).toContain("allowConversationAccess: true");
expect(runtimeLogs.join("\n")).toContain("ClawHub package: openclaw-mem0");
expect(runtimeLogs.join("\n")).toContain("Artifact kind: npm-pack");
expect(runtimeLogs.join("\n")).toContain("Npm integrity: sha512-clawpack");
expect(runtimeLogs.join("\n")).toContain(
expect(pluginsCliRuntimeLogs.join("\n")).toContain("Policy");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("allowConversationAccess: true");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("ClawHub package: openclaw-mem0");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("Artifact kind: npm-pack");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("Npm integrity: sha512-clawpack");
expect(pluginsCliRuntimeLogs.join("\n")).toContain(
"ClawPack sha256: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
);
expect(runtimeLogs.join("\n")).toContain("ClawPack spec: 1");
expect(runtimeLogs.join("\n")).toContain("ClawPack size: 4096 bytes");
expect(runtimeLogs.join("\n")).toContain("remote");
expect(runtimeLogs.join("\n")).not.toContain("remote (unsupported transport)");
expect(runtimeLogs.join("\n")).toContain("broken (unsupported transport)");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("ClawPack spec: 1");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("ClawPack size: 4096 bytes");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("remote");
expect(pluginsCliRuntimeLogs.join("\n")).not.toContain("remote (unsupported transport)");
expect(pluginsCliRuntimeLogs.join("\n")).toContain("broken (unsupported transport)");
});
it("runtime-inspects without repairing deps", async () => {
+2 -2
View File
@@ -9,7 +9,7 @@ import {
refreshPluginRegistry,
resetPluginsCliTestState,
runtimeErrors,
runtimeLogs,
pluginsCliRuntimeLogs,
runPluginsCommand,
writeConfigFile,
} from "./plugins-cli-test-helpers.js";
@@ -135,7 +135,7 @@ describe("plugins cli policy mutations", () => {
expect(writeConfigFile).not.toHaveBeenCalled();
expect(refreshPluginRegistry).not.toHaveBeenCalled();
expect(runtimeErrors).toContain(`Plugin "alpha" could not be enabled (${reason}).`);
expect(runtimeLogs).not.toContain(`Plugin "alpha" could not be enabled (${reason}).`);
expect(pluginsCliRuntimeLogs).not.toContain(`Plugin "alpha" could not be enabled (${reason}).`);
});
it("refuses plugin enablement in Nix mode before config mutation", async () => {
+9 -9
View File
@@ -14,7 +14,7 @@ import {
loadConfig,
planPluginUninstall,
PromptInputClosedError,
promptYesNo,
promptYesNoMock,
readPersistedInstalledPluginIndex,
refreshPluginRegistry,
replaceConfigFile,
@@ -22,7 +22,7 @@ import {
restorePersistedInstalledPluginIndexIfCurrent,
runPluginsCommand,
runtimeErrors,
runtimeLogs,
pluginsCliRuntimeLogs,
setInstalledPluginIndexInstallRecords,
writeConfigFile,
writePersistedInstalledPluginIndexInstallRecordsWithLease,
@@ -59,7 +59,7 @@ function primeUninstallPlan(
}
function expectRuntimeLogIncludes(fragment: string) {
expect(runtimeLogs.join("\n")).toContain(fragment);
expect(pluginsCliRuntimeLogs.join("\n")).toContain(fragment);
}
function expectInstallRecordsWrittenWithLease(records: unknown, config: unknown) {
@@ -195,7 +195,7 @@ describe("plugins cli uninstall", () => {
await runPluginsCommand(["plugins", "uninstall", "alpha", "--force", "--keep-files"]);
expect(promptYesNo).not.toHaveBeenCalled();
expect(promptYesNoMock).not.toHaveBeenCalled();
expectLatestUninstallPlanParams({ pluginId: "alpha", deleteFiles: false });
expectInstallRecordsWrittenWithLease({}, { plugins: { entries: {} } });
expect(writeConfigFile).toHaveBeenCalledWith({
@@ -306,7 +306,7 @@ describe("plugins cli uninstall", () => {
expect(runtimeErrors.at(-1)).toContain('Plugin uninstall target "calendar" is ambiguous');
expect(planPluginUninstall).not.toHaveBeenCalled();
expect(promptYesNo).not.toHaveBeenCalled();
expect(promptYesNoMock).not.toHaveBeenCalled();
expect(applyPluginUninstallDirectoryRemoval).not.toHaveBeenCalled();
expect(writePersistedInstalledPluginIndexInstallRecordsWithLease).not.toHaveBeenCalled();
expect(writeConfigFile).not.toHaveBeenCalled();
@@ -392,7 +392,7 @@ describe("plugins cli uninstall", () => {
diagnostics: [],
});
primeUninstallPlan({ plugins: { entries: {}, installs: {} } } as OpenClawConfig);
promptYesNo.mockRejectedValueOnce(new PromptInputClosedError());
promptYesNoMock.mockRejectedValueOnce(new PromptInputClosedError());
await expect(runPluginsCommand(["plugins", "uninstall", "alpha"])).rejects.toThrow(
"__exit__:1",
@@ -595,7 +595,7 @@ describe("plugins cli uninstall", () => {
expectLatestUninstallPlanParams({ pluginId: "alpha", deleteFiles: true });
expect(writeConfigFile).toHaveBeenCalledWith(nextConfig);
expect(runtimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
expect(pluginsCliRuntimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
});
it("uninstalls stale enabled entries when plugin is absent from the current registry", async () => {
@@ -627,7 +627,7 @@ describe("plugins cli uninstall", () => {
reason: "source-changed",
});
expect(runtimeErrors).not.toContain("Plugin not found: alpha");
expect(runtimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
expect(pluginsCliRuntimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
});
it.each([
@@ -758,7 +758,7 @@ describe("plugins cli uninstall", () => {
expectInstallRecordsWrittenWithLease({}, nextConfig);
expect(writeConfigFile).toHaveBeenCalledWith(nextConfig);
expectRuntimeLogIncludes("channel config (channels.alpha)");
expect(runtimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
expect(pluginsCliRuntimeLogs.at(-2)).toContain('Uninstalled plugin "alpha"');
});
it("exits when uninstall target is not managed by plugin install records", async () => {
+15 -13
View File
@@ -10,17 +10,16 @@ import { VERSION } from "../version.js";
import {
createTestInstalledPluginIndex,
loadConfig,
notifyGatewayPluginMetadataChanged,
notifyGatewayPluginMetadataChangedMock,
readConfigFileSnapshotForWrite,
readPersistedInstalledPluginIndex,
refreshPluginRegistry,
registerPluginsCli,
replaceConfigFile,
resetPluginsCliTestState,
restorePersistedInstalledPluginIndexIfCurrent,
runPluginsCommand,
runtimeErrors,
runtimeLogs,
pluginsCliRuntimeLogs,
setInstalledPluginIndexInstallRecords,
setHookInstallRecords,
updateNpmInstalledHookPacks,
@@ -28,6 +27,7 @@ import {
writeConfigFile,
writePersistedInstalledPluginIndexInstallRecordsWithLease,
} from "./plugins-cli-test-helpers.js";
import { registerPluginsCli } from "./plugins-cli.js";
const ORIGINAL_OPENCLAW_NIX_MODE = process.env.OPENCLAW_NIX_MODE;
const ORIGINAL_STDIN_TTY = Object.getOwnPropertyDescriptor(process.stdin, "isTTY");
@@ -78,7 +78,7 @@ function createTrackedPluginConfig(params: {
function expectRestartNoticeLogged() {
expect(
runtimeLogs.some((message) =>
pluginsCliRuntimeLogs.some((message) =>
message.includes("Restart the gateway to load plugins and hooks."),
),
).toBe(true);
@@ -237,7 +237,7 @@ async function expectSkippedClawHubPluginUpdate(params: {
await expect(runPluginsCommand(["plugins", "update", "demo"])).rejects.toThrow("__exit__:1");
expect(writePersistedInstalledPluginIndexInstallRecordsWithLease).not.toHaveBeenCalled();
expect(runtimeLogs.at(-1)).toContain(params.expectedLog);
expect(pluginsCliRuntimeLogs.at(-1)).toContain(params.expectedLog);
}
describe("plugins cli update", () => {
@@ -317,7 +317,7 @@ describe("plugins cli update", () => {
expect(replaceConfigFile).not.toHaveBeenCalled();
expect(writePersistedInstalledPluginIndexInstallRecordsWithLease).not.toHaveBeenCalled();
expect(refreshPluginRegistry).not.toHaveBeenCalled();
expect(runtimeLogs).toContain("Would update alpha: 1.0.0 -> 1.1.0.");
expect(pluginsCliRuntimeLogs).toContain("Would update alpha: 1.0.0 -> 1.1.0.");
} finally {
acquireLease.mockRestore();
}
@@ -681,7 +681,7 @@ describe("plugins cli update", () => {
installRecords: nextRecords,
reason: "source-changed",
});
expect(notifyGatewayPluginMetadataChanged).toHaveBeenCalledWith(cfg);
expect(notifyGatewayPluginMetadataChangedMock).toHaveBeenCalledWith(cfg);
expectRestartNoticeLogged();
});
@@ -749,7 +749,7 @@ describe("plugins cli update", () => {
installRecords: nextRecords,
reason: "source-changed",
});
expect(notifyGatewayPluginMetadataChanged).not.toHaveBeenCalled();
expect(notifyGatewayPluginMetadataChangedMock).not.toHaveBeenCalled();
});
it("rolls back persisted install records when source config changes during a records-only update", async () => {
@@ -811,7 +811,7 @@ describe("plugins cli update", () => {
expect(writeConfigFile).not.toHaveBeenCalled();
expect(replaceConfigFile).not.toHaveBeenCalled();
expect(refreshPluginRegistry).not.toHaveBeenCalled();
expect(notifyGatewayPluginMetadataChanged).not.toHaveBeenCalled();
expect(notifyGatewayPluginMetadataChangedMock).not.toHaveBeenCalled();
});
it("rolls back persisted install records when included config changes during a records-only update", async () => {
@@ -1216,7 +1216,7 @@ describe("plugins cli update", () => {
expect(updateNpmInstalledPlugins).not.toHaveBeenCalled();
expect(updateNpmInstalledHookPacks).not.toHaveBeenCalled();
expect(runtimeLogs.at(-1)).toBe("No tracked plugins or hook packs to update.");
expect(pluginsCliRuntimeLogs.at(-1)).toBe("No tracked plugins or hook packs to update.");
});
it("passes dangerous force unsafe install to plugin updates", async () => {
@@ -1240,7 +1240,7 @@ describe("plugins cli update", () => {
expect(updateParams.pluginIds).toEqual(["openclaw-codex-app-server"]);
expect(updateParams.dangerouslyForceUnsafeInstall).toBe(true);
expect(
runtimeLogs.some((message) =>
pluginsCliRuntimeLogs.some((message) =>
message.includes(
"--dangerously-force-unsafe-install is deprecated and no longer affects plugin updates",
),
@@ -1536,7 +1536,7 @@ describe("plugins cli update", () => {
installRecords: nextConfig.plugins?.installs,
reason: "source-changed",
});
expect(runtimeLogs).toContain("Failed to update beta: registry timeout");
expect(pluginsCliRuntimeLogs).toContain("Failed to update beta: registry timeout");
});
it("exits non-zero when a ClawHub update is skipped for missing risk acknowledgement", async () => {
@@ -1596,7 +1596,9 @@ describe("plugins cli update", () => {
);
expect(writeConfigFile).not.toHaveBeenCalled();
expect(runtimeLogs).toContain('Failed to update hook pack "demo-hooks": registry timeout');
expect(pluginsCliRuntimeLogs).toContain(
'Failed to update hook pack "demo-hooks": registry timeout',
);
});
});
/* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */
+2 -2
View File
@@ -10,7 +10,7 @@ import {
installPluginFromNpmSpec,
installPluginFromPath,
parseClawHubPluginSpec,
promptYesNo,
promptYesNoMock,
readConfigFileSnapshotForWrite,
resetPluginsCliTestState,
resolveMarketplaceInstallShortcut,
@@ -31,7 +31,7 @@ vi.mock("../plugins/plugin-lifecycle-lease.js", () => ({
function expectNoPluginInstallSideEffects(): void {
expect(withPluginLifecycleLeaseMock).not.toHaveBeenCalled();
expect(readConfigFileSnapshotForWrite).not.toHaveBeenCalled();
expect(promptYesNo).not.toHaveBeenCalled();
expect(promptYesNoMock).not.toHaveBeenCalled();
expect(installPluginFromClawHub).not.toHaveBeenCalled();
expect(installPluginFromGitSpec).not.toHaveBeenCalled();
expect(installPluginFromMarketplace).not.toHaveBeenCalled();
+2 -2
View File
@@ -4,7 +4,7 @@ import { buildProgram } from "./program.js";
import {
callGateway,
configureCommand,
ensureConfigReady,
ensureConfigReadyMock,
runSystemAgentWithInference,
runTui,
runtime,
@@ -46,7 +46,7 @@ describe("cli program (smoke)", () => {
vi.clearAllMocks();
runTui.mockResolvedValue(undefined);
runSystemAgentWithInference.mockResolvedValue(undefined);
ensureConfigReady.mockResolvedValue(undefined);
ensureConfigReadyMock.mockResolvedValue(undefined);
});
it("registers message + status commands", () => {
+1 -1
View File
@@ -44,7 +44,7 @@ export const setupWizardCommand = programMocks.setupWizardCommand as AnyMock;
export const callGateway = programMocks.callGateway as AnyMock;
export const runTui = programMocks.runTui as AnyMock;
export const runSystemAgentWithInference = programMocks.runSystemAgentWithInference as AnyMock;
export const ensureConfigReady = programMocks.ensureConfigReady as AnyMock;
export const ensureConfigReadyMock = programMocks.ensureConfigReady as AnyMock;
export const runtime = programMocks.runtime as {
log: Mock<(...args: unknown[]) => void>;
+2 -2
View File
@@ -332,7 +332,7 @@ export function getSubCliEntries(): ReadonlyArray<SubCliDescriptor> {
return getSubCliEntryDescriptors();
}
export async function registerSubCliByName(
export async function registerSubCliByNameCore(
program: Command,
name: string,
argv: string[] = process.argv,
@@ -345,7 +345,7 @@ export async function registerSubCliByName(
return registerCommandGroupByName(program, resolveSubCliCommandGroups(argv, context), name);
}
export function registerSubCliCommands(program: Command, argv: string[] = process.argv) {
export function registerSubCliCommandsCore(program: Command, argv: string[] = process.argv) {
const { primary } = resolveCliArgvInvocation(argv);
registerCommandGroups(program, resolveSubCliCommandGroups(argv), {
eager: shouldEagerRegisterSubcommands(),
+2 -2
View File
@@ -16,8 +16,8 @@ import {
type CommandGroupEntry,
} from "./register-command-groups.js";
import {
registerSubCliByName as registerSubCliByNameCore,
registerSubCliCommands as registerSubCliCommandsCore,
registerSubCliByNameCore,
registerSubCliCommandsCore,
type SubCliRegistrationContext,
} from "./register.subclis-core.js";
import { getSubCliEntries as getSubCliEntryDescriptors } from "./subcli-descriptors.js";
+7 -24
View File
@@ -20,7 +20,6 @@ import type { ProxyHandle } from "../infra/net/proxy/proxy-lifecycle.js";
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
import { assertSupportedRuntime } from "../infra/runtime-guard.js";
import { tryProcessCwd } from "../infra/safe-cwd.js";
import type { PluginManifestCommandAliasRegistry } from "../plugins/manifest-command-aliases.js";
import { resolveCliArgvInvocation } from "./argv-invocation.js";
import {
normalizeGeneratedHelpCommandArgv,
@@ -58,7 +57,7 @@ import {
} from "./program/core-command-descriptors.js";
import { getSubCliEntries } from "./program/subcli-descriptors.js";
import {
resolveMissingPluginCommandMessage as resolveMissingPluginCommandMessageFromPolicy,
resolveMissingPluginCommandMessage,
rewriteUpdateFlagArgv,
shouldHandleBareRoot,
shouldEnsureCliPath,
@@ -695,18 +694,6 @@ function pauseNonTtyStdinForCliExit(): void {
}
}
export function resolveMissingPluginCommandMessage(
pluginId: string,
config?: OpenClawConfig,
options?: { registry?: PluginManifestCommandAliasRegistry },
): string | null {
return resolveMissingPluginCommandMessageFromPolicy(
pluginId,
config,
options?.registry ? { registry: options.registry } : undefined,
);
}
function shouldLoadCliDotEnv(
loadGlobalEnv: boolean,
env: NodeJS.ProcessEnv = process.env,
@@ -1005,15 +992,11 @@ async function resolveUnownedCliPrimaryMessage(params: {
const { resolveManifestCommandAliasOwner, resolveManifestToolOwner } =
await loadManifestCommandAliasesRuntimeModule();
const cliCommandSurfaceOwner = await resolveCliCommandSurfaceOwner(params);
const pluginPolicyMessage = resolveMissingPluginCommandMessageFromPolicy(
params.primary,
params.config,
{
resolveCommandAliasOwner: resolveManifestCommandAliasOwner,
resolveToolOwner: resolveManifestToolOwner,
resolveCliCommandSurfaceOwner: () => cliCommandSurfaceOwner,
},
);
const pluginPolicyMessage = resolveMissingPluginCommandMessage(params.primary, params.config, {
resolveCommandAliasOwner: resolveManifestCommandAliasOwner,
resolveToolOwner: resolveManifestToolOwner,
resolveCliCommandSurfaceOwner: () => cliCommandSurfaceOwner,
});
if (pluginPolicyMessage) {
return pluginPolicyMessage;
}
@@ -1628,7 +1611,7 @@ async function runCliWithPreparedOutputMode(
primary,
config,
});
const missingPluginCommandMessage = resolveMissingPluginCommandMessageFromPolicy(
const missingPluginCommandMessage = resolveMissingPluginCommandMessage(
primary,
config,
{
+1 -1
View File
@@ -6,7 +6,7 @@ import { getBundledChannelSetupPlugin } from "../channels/plugins/bundled.js";
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
import { getLoadedChannelPlugin } from "../channels/plugins/index.js";
import type { ChannelId } from "../channels/plugins/types.public.js";
import { normalizeChannelId as normalizeBundledChannelId } from "../channels/registry.js";
import { normalizeChatChannelId as normalizeBundledChannelId } from "../channels/registry.js";
import { formatUnknownChannelMessage } from "../cli/error-format.js";
import { isRouteBinding, listRouteBindings } from "../config/bindings.js";
import type { AgentRouteBinding } from "../config/types.js";
+9 -9
View File
@@ -18,7 +18,7 @@ const mocks = vi.hoisted(() => ({
diagnostics: [],
})),
listReadOnlyChannelPluginsForConfig: vi.fn<() => ChannelPlugin[]>(() => []),
buildChannelAccountSnapshot: vi.fn(),
resolveChannelAccountSnapshot: vi.fn(),
listTrustedChannelPluginCatalogEntries: vi.fn<() => ChannelPluginCatalogEntry[]>(() => []),
listManifestInstalledChannelIds: vi.fn<() => Set<string>>(() => new Set()),
resolveMissingOfficialExternalChannelPluginRepairHint: vi.fn(),
@@ -53,7 +53,7 @@ vi.mock("../channels/plugins/read-only.js", () => ({
}));
vi.mock("../channels/plugins/status.js", () => ({
buildChannelAccountSnapshot: mocks.buildChannelAccountSnapshot,
resolveChannelAccountSnapshot: mocks.resolveChannelAccountSnapshot,
}));
vi.mock("./channel-setup/trusted-catalog.js", () => ({
@@ -130,7 +130,7 @@ describe("channels list", () => {
mocks.resolveCommandConfigWithSecrets.mockClear();
mocks.listReadOnlyChannelPluginsForConfig.mockReset();
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([]);
mocks.buildChannelAccountSnapshot.mockReset();
mocks.resolveChannelAccountSnapshot.mockReset();
mocks.listTrustedChannelPluginCatalogEntries.mockReset();
mocks.listTrustedChannelPluginCatalogEntries.mockReturnValue([]);
mocks.listManifestInstalledChannelIds.mockReset();
@@ -213,7 +213,7 @@ describe("channels list", () => {
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([
createMockChannelPlugin({ accountIds: ["default"] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: true,
tokenSource: "config",
@@ -253,7 +253,7 @@ describe("channels list", () => {
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([
createMockChannelPlugin({ id: "discord", label: "Discord", accountIds: ["default"] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: false,
tokenSource: "none",
@@ -302,7 +302,7 @@ describe("channels list", () => {
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([
createMockChannelPlugin({ id: "discord", label: "Discord", accountIds: ["default"] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: false,
tokenSource: "none",
@@ -331,7 +331,7 @@ describe("channels list", () => {
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([
createMockChannelPlugin({ id: "discord", label: "Discord", accountIds: ["default"] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: true,
tokenSource: "config",
@@ -488,7 +488,7 @@ describe("channels list", () => {
mocks.listReadOnlyChannelPluginsForConfig.mockReturnValue([
createMockChannelPlugin({ id: "discord", label: "Discord", accountIds: [] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: false,
enabled: false,
@@ -520,7 +520,7 @@ describe("channels list", () => {
createMockChannelPlugin({ id: "telegram", accountIds: ["default"] }),
createMockChannelPlugin({ id: "discord", label: "Discord", accountIds: [] }),
]);
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: false,
enabled: false,
@@ -152,7 +152,7 @@ vi.mock("../channels/plugins/status.js", () => ({
accountId,
...plugin.config.inspectAccount(cfg),
}),
buildChannelAccountSnapshot: async ({
resolveChannelAccountSnapshot: async ({
plugin,
cfg,
accountId,
+3 -3
View File
@@ -5,7 +5,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/ag
import type { ChannelPluginCatalogEntry } from "../../channels/plugins/catalog.js";
import { isChannelVisibleInConfiguredLists } from "../../channels/plugins/exposure.js";
import { listReadOnlyChannelPluginsForConfig } from "../../channels/plugins/read-only.js";
import { buildChannelAccountSnapshot } from "../../channels/plugins/status.js";
import { resolveChannelAccountSnapshot } from "../../channels/plugins/status.js";
import type { ChannelPlugin } from "../../channels/plugins/types.plugin.js";
import type { ChannelAccountSnapshot } from "../../channels/plugins/types.public.js";
import {
@@ -223,7 +223,7 @@ export async function channelsListCommand(
localAccountIds: accountIds,
runtimeAccounts,
resolveLocalSnapshot: (accountId) =>
buildChannelAccountSnapshot({ plugin, cfg, accountId }),
resolveChannelAccountSnapshot({ plugin, cfg, accountId }),
});
for (const row of rows) {
accountLines.push({
@@ -245,7 +245,7 @@ export async function channelsListCommand(
// full set of channels they could enable without first running
// `channels add`. Use the channel's default account so the snapshot
// can reflect "not configured / not enabled" state.
const snapshot = await buildChannelAccountSnapshot({
const snapshot = await resolveChannelAccountSnapshot({
plugin,
cfg,
accountId: "default",
+1 -1
View File
@@ -2,7 +2,7 @@
import fs from "node:fs/promises";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { theme } from "../../../packages/terminal-core/src/theme.js";
import { normalizeChannelId as normalizeBundledChannelId } from "../../channels/registry.js";
import { normalizeChatChannelId as normalizeBundledChannelId } from "../../channels/registry.js";
import { readFileWindowFully } from "../../infra/file-read.js";
import { parseStrictPositiveInteger } from "../../infra/parse-finite-number.js";
import { getResolvedLoggerSettings } from "../../logging.js";
@@ -9,7 +9,7 @@ import {
import { normalizeChannelId } from "../../channels/plugins/index.js";
import { listReadOnlyChannelPluginsForConfig } from "../../channels/plugins/read-only.js";
import {
buildChannelAccountSnapshot,
resolveChannelAccountSnapshot,
buildReadOnlySourceChannelAccountSnapshot,
} from "../../channels/plugins/status.js";
import type { ChannelAccountSnapshot } from "../../channels/plugins/types.public.js";
@@ -87,7 +87,7 @@ export async function formatConfigChannelsStatusLines(
cfg: sourceConfig,
accountId,
});
const resolvedSnapshot = await buildChannelAccountSnapshot({
const resolvedSnapshot = await resolveChannelAccountSnapshot({
plugin,
cfg,
accountId,
+10 -10
View File
@@ -2,7 +2,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { visibleWidth } from "../../packages/terminal-core/src/ansi.js";
import type { RuntimeEnv } from "../runtime.js";
import { createRunningTaskRun as createRunningTaskRunOrNull } from "../tasks/task-executor.js";
import { createRunningTaskRunCore as createRunningTaskRunOrNull } from "../tasks/task-executor.js";
import { createManagedTaskFlow as createManagedTaskFlowOrNull } from "../tasks/task-flow-registry.js";
import type { TaskFlowRecord } from "../tasks/task-flow-registry.types.js";
import { markTaskLostById, markTaskTerminalById } from "../tasks/task-registry.js";
@@ -37,7 +37,7 @@ function createManagedTaskFlow(
return flow;
}
function createRunningTaskRun(
function createRunningTaskRunCore(
params: Parameters<typeof createRunningTaskRunOrNull>[0],
): TaskRecord {
const task = createRunningTaskRunOrNull(params);
@@ -109,7 +109,7 @@ describe("flows commands", () => {
updatedAt: 100,
});
const childTask = createRunningTaskRun({
const childTask = createRunningTaskRunCore({
runtime: "acp",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -302,7 +302,7 @@ describe("flows commands", () => {
updatedAt: 100,
});
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -347,7 +347,7 @@ describe("flows commands", () => {
goal: "Inspect child task failures",
status: "running",
});
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -402,7 +402,7 @@ describe("flows commands", () => {
goal: "Inspect child task updates",
status: "running",
});
const running = createRunningTaskRun({
const running = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -415,7 +415,7 @@ describe("flows commands", () => {
startedAt: Date.now(),
progressSummary: "Downloading provider metadata",
});
const completed = createRunningTaskRun({
const completed = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -455,7 +455,7 @@ describe("flows commands", () => {
goal: "Inspect unsafe child error",
status: "running",
});
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -495,7 +495,7 @@ describe("flows commands", () => {
currentStep: `step${unsafe}`,
status: "running",
});
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
@@ -603,7 +603,7 @@ describe("flows commands", () => {
updatedAt: 100,
});
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "subagent",
ownerKey: unsafeOwnerKey,
scopeKind: "session",
+2 -2
View File
@@ -9,7 +9,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/ag
import { resolveInspectedChannelAccount } from "../../channels/account-inspection.js";
import { hasConfiguredUnavailableCredentialStatus } from "../../channels/account-snapshot-fields.js";
import {
buildChannelAccountSnapshot,
buildChannelAccountSummary,
formatChannelAllowFrom,
} from "../../channels/account-summary.js";
import { resolveChannelDefaultAccountId } from "../../channels/plugins/helpers.js";
@@ -79,7 +79,7 @@ async function resolveChannelAccountRow(
sourceConfig,
accountId,
});
const snapshot = buildChannelAccountSnapshot({
const snapshot = buildChannelAccountSummary({
plugin,
cfg,
accountId,
+6 -6
View File
@@ -1,9 +1,9 @@
import { createConfigIoContext } from "./io.context.js";
import { loadConfigFromContext } from "./io.load.js";
import {
preserveConfigSnapshotAsClobbered,
promoteConfigSnapshotToLastKnownGood,
recoverConfigFromLastKnownGood,
preserveConfigSnapshotAsClobberedCore,
promoteConfigSnapshotToLastKnownGoodCore,
recoverConfigFromLastKnownGoodCore,
} from "./io.observe-recovery.js";
import { recoverConfigFromJsonRootSuffixWithContext } from "./io.recovery.js";
import {
@@ -36,20 +36,20 @@ export function createConfigIO(options: ConfigIoFactoryOptions = {}) {
readConfigFileSnapshotWithPluginMetadataFromContext(context, readOptions),
readConfigFileSnapshotForWrite: () => readConfigFileSnapshotForWriteFromContext(context),
promoteConfigSnapshotToLastKnownGood: (snapshot: ConfigFileSnapshot) =>
promoteConfigSnapshotToLastKnownGood({
promoteConfigSnapshotToLastKnownGoodCore({
deps: context.deps,
snapshot,
logger: context.deps.logger,
}),
recoverConfigFromLastKnownGood: (params: { snapshot: ConfigFileSnapshot; reason: string }) =>
recoverConfigFromLastKnownGood({
recoverConfigFromLastKnownGoodCore({
deps: context.deps,
snapshot: params.snapshot,
reason: params.reason,
prepareCandidate: context.prepareRecoveryBackupCandidate,
}),
preserveConfigSnapshotAsClobbered: (snapshot: ConfigFileSnapshot) =>
preserveConfigSnapshotAsClobbered({ deps: context.deps, snapshot }),
preserveConfigSnapshotAsClobberedCore({ deps: context.deps, snapshot }),
recoverConfigFromJsonRootSuffix: (snapshot: ConfigFileSnapshot) =>
recoverConfigFromJsonRootSuffixWithContext(context, snapshot),
writeConfigFile: (
+14 -14
View File
@@ -16,8 +16,8 @@ import { createConfigIO } from "./io.js";
import {
maybeRecoverSuspiciousConfigRead,
maybeRecoverSuspiciousConfigReadSync,
promoteConfigSnapshotToLastKnownGood,
recoverConfigFromLastKnownGood,
promoteConfigSnapshotToLastKnownGoodCore,
recoverConfigFromLastKnownGoodCore,
} from "./io.observe-recovery.js";
import type { ConfigFileSnapshot } from "./types.js";
@@ -866,7 +866,7 @@ describe("config observe recovery", () => {
await withSuiteHome(async (home) => {
const { deps, configPath, auditPath } = makeDeps(home);
const snapshot = await makeSnapshot(configPath, recoverableTelegramConfig);
await promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger });
await promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger });
await fsp.writeFile(
`${configPath}.bak`,
`${JSON.stringify({ meta: { lastTouchedVersion: "2026.4.22" } })}\n`,
@@ -1174,7 +1174,7 @@ describe("config observe recovery", () => {
const snapshot = await makeSnapshot(configPath, recoverableTelegramConfig);
await expect(
promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger }),
promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger }),
).resolves.toBe(true);
await expectPathMissing(path.join(home, ".openclaw", "logs", "config-health.json"));
@@ -1216,7 +1216,7 @@ describe("config observe recovery", () => {
});
await expect(
promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger }),
promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger }),
).resolves.toBe(true);
await expect(fsp.readFile(resolveLastKnownGoodConfigPath(configPath), "utf-8")).resolves.toBe(
snapshot.raw,
@@ -1224,7 +1224,7 @@ describe("config observe recovery", () => {
const brokenRaw = "{ gateway: { mode: 123 } }\n";
await fsp.writeFile(configPath, brokenRaw, "utf-8");
const restored = await recoverConfigFromLastKnownGood({
const restored = await recoverConfigFromLastKnownGoodCore({
deps,
snapshot: {
...snapshot,
@@ -1254,12 +1254,12 @@ describe("config observe recovery", () => {
gateway: { mode: "local" },
});
await expect(
promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger }),
promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger }),
).resolves.toBe(true);
const brokenRaw = "{ gateway: { mode: 123 } }\n";
await fsp.writeFile(configPath, brokenRaw, "utf-8");
const restored = await recoverConfigFromLastKnownGood({
const restored = await recoverConfigFromLastKnownGoodCore({
deps,
snapshot: {
...snapshot,
@@ -1289,7 +1289,7 @@ describe("config observe recovery", () => {
const lastGoodPath = resolveLastKnownGoodConfigPath(configPath);
await expect(
promoteConfigSnapshotToLastKnownGood({
promoteConfigSnapshotToLastKnownGoodCore({
deps: withAsyncChmodFailure(deps, lastGoodPath),
snapshot,
logger: deps.logger,
@@ -1311,13 +1311,13 @@ describe("config observe recovery", () => {
channels: { discord: { enabled: true, dmPolicy: "pairing" } },
});
await expect(
promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger }),
promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger }),
).resolves.toBe(true);
const brokenRaw = "{ gateway: { mode: 123 } }\n";
await fsp.writeFile(configPath, brokenRaw, "utf-8");
await expect(
recoverConfigFromLastKnownGood({
recoverConfigFromLastKnownGoodCore({
deps: withAsyncChmodFailure(deps, configPath),
snapshot: {
...snapshot,
@@ -1395,14 +1395,14 @@ describe("config observe recovery", () => {
const { deps, configPath, warn } = makeDeps(home);
const staleSnapshot = await makeSnapshot(configPath, staleConfig);
await expect(
promoteConfigSnapshotToLastKnownGood({
promoteConfigSnapshotToLastKnownGoodCore({
deps,
snapshot: staleSnapshot,
logger: deps.logger,
}),
).resolves.toBe(true);
const active = await writeConfigRaw(configPath, activeConfig);
const restored = await recoverConfigFromLastKnownGood({
const restored = await recoverConfigFromLastKnownGoodCore({
deps,
snapshot: { ...staleSnapshot, ...active, valid: false, issues: [issue] },
reason: "reload-invalid-config",
@@ -1427,7 +1427,7 @@ describe("config observe recovery", () => {
});
await expect(
promoteConfigSnapshotToLastKnownGood({ deps, snapshot, logger: deps.logger }),
promoteConfigSnapshotToLastKnownGoodCore({ deps, snapshot, logger: deps.logger }),
).resolves.toBe(false);
await expectPathMissing(resolveLastKnownGoodConfigPath(configPath));
expectWarnContaining(warn, "Config last-known-good promotion skipped");
+4 -4
View File
@@ -498,7 +498,7 @@ function* recoverSuspiciousConfigRead(
return preparedCandidate;
}
export async function promoteConfigSnapshotToLastKnownGood(params: {
export async function promoteConfigSnapshotToLastKnownGoodCore(params: {
deps: ObserveRecoveryDeps;
snapshot: ConfigFileSnapshot;
logger?: Pick<typeof console, "warn">;
@@ -548,7 +548,7 @@ export async function promoteConfigSnapshotToLastKnownGood(params: {
return true;
}
export async function recoverConfigFromLastKnownGood(params: {
export async function recoverConfigFromLastKnownGoodCore(params: {
deps: ObserveRecoveryDeps;
snapshot: ConfigFileSnapshot;
reason: string;
@@ -611,7 +611,7 @@ export async function recoverConfigFromLastKnownGood(params: {
stat,
observedAt: now,
});
const clobberedPath = await preserveConfigSnapshotAsClobbered({
const clobberedPath = await preserveConfigSnapshotAsClobberedCore({
deps,
snapshot,
observedAt: now,
@@ -662,7 +662,7 @@ export async function recoverConfigFromLastKnownGood(params: {
return true;
}
export async function preserveConfigSnapshotAsClobbered(params: {
export async function preserveConfigSnapshotAsClobberedCore(params: {
deps: ObserveRecoveryDeps;
snapshot: ConfigFileSnapshot;
observedAt?: string;
+3 -3
View File
@@ -760,7 +760,7 @@ describe("cron service ops seam coverage", () => {
const taskRunId =
reservationOffsetMs === undefined
? tryCreateCronTaskRun({ state, job, startedAt })
: taskExecutor.createRunningTaskRun({
: taskExecutor.createRunningTaskRunCore({
runtime: "cron",
sourceId: job.id,
ownerKey: "",
@@ -1334,7 +1334,7 @@ describe("cron service ops seam coverage", () => {
});
const createTaskRecordSpy = vi
.spyOn(taskExecutor, "createRunningTaskRun")
.spyOn(taskExecutor, "createRunningTaskRunCore")
.mockImplementation(() => {
throw new Error("disk full");
});
@@ -1357,7 +1357,7 @@ describe("cron service ops seam coverage", () => {
await writeDueIsolatedJobSnapshot(storePath, now);
const updateTaskRecordSpy = vi
.spyOn(taskExecutor, "finalizeTaskRunByRunId")
.spyOn(taskExecutor, "finalizeTaskRunByRunIdCore")
.mockImplementation(() => {
throw new Error("disk full");
});
+6 -6
View File
@@ -1,7 +1,7 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { getDetachedTaskLifecycleRuntime } from "../../tasks/detached-task-runtime.js";
import * as taskExecutor from "../../tasks/task-executor.js";
import { finalizeTaskRunByRunId } from "../../tasks/task-executor.js";
import { finalizeTaskRunByRunIdCore } from "../../tasks/task-executor.js";
import * as taskRegistry from "../../tasks/task-registry.js";
import { markTaskLostById } from "../../tasks/task-registry.js";
import { listTaskRegistryRecordsByRuntimeSourceIdFromSqlite } from "../../tasks/task-registry.store.sqlite.js";
@@ -584,7 +584,7 @@ describe("cron task run terminal records", () => {
if (!taskRunId) {
throw new Error("expected cron task run id");
}
finalizeTaskRunByRunId({
finalizeTaskRunByRunIdCore({
runId: taskRunId,
runtime: "cron",
status: "cancelled",
@@ -664,8 +664,8 @@ describe("cron task run terminal records", () => {
if (!taskRunId) {
throw new Error("expected cron task run id");
}
const finalize = taskExecutor.finalizeTaskRunByRunId;
vi.spyOn(taskExecutor, "finalizeTaskRunByRunId")
const finalize = taskExecutor.finalizeTaskRunByRunIdCore;
vi.spyOn(taskExecutor, "finalizeTaskRunByRunIdCore")
.mockReturnValueOnce([])
.mockImplementation((params) => finalize(params));
@@ -929,7 +929,7 @@ describe("cron task run terminal records", () => {
});
const legacyRunId = `cron:legacy-job:${startedAt}`;
// Older releases persisted the reservation id without a uniqueness suffix.
taskExecutor.createRunningTaskRun({
taskExecutor.createRunningTaskRunCore({
runtime: "cron",
sourceId: "legacy-job",
ownerKey: "",
@@ -941,7 +941,7 @@ describe("cron task run terminal records", () => {
startedAt,
});
expect(tryFindCronTaskRunIdForRecovery(state, "legacy-job", startedAt)).toBe(legacyRunId);
finalizeTaskRunByRunId({
finalizeTaskRunByRunIdCore({
runId: legacyRunId,
runtime: "cron",
status: "timed_out",
+7 -7
View File
@@ -18,12 +18,12 @@ function resolveCurrentDefaultAgentId(state: CronServiceState): string | undefin
}
import { CRON_TASK_KIND } from "../../tasks/cron-task-contract.js";
import {
createRunningTaskRun,
createRunningTaskRunCore,
finalizeTaskRunById,
finalizeTaskRunByRunId,
finalizeTaskRunByRunIdCore,
findTaskByRunId,
listTaskRecordsUnsorted,
recordTaskRunProgressByRunId,
recordTaskRunProgressByRunIdCore,
} from "../../tasks/task-executor.js";
import type { JsonValue, TaskRecord, TaskStatus } from "../../tasks/task-registry.types.js";
import { createCronExecutionId } from "../run-id.js";
@@ -105,7 +105,7 @@ export function tryUpdateCronTaskRunSession(
return;
}
try {
const updated = recordTaskRunProgressByRunId({
const updated = recordTaskRunProgressByRunIdCore({
runId: taskRunId,
runtime: "cron",
childSessionKey,
@@ -249,7 +249,7 @@ function tryCreateCronTaskRunRecord(params: {
const effectiveJobAgentId = params.job
? resolveCronJobEffectiveAgentId(params.job, resolveCurrentDefaultAgentId(params.state))
: undefined;
const task = createRunningTaskRun({
const task = createRunningTaskRunCore({
runtime: "cron",
taskKind: CRON_TASK_KIND,
sourceId: params.jobId,
@@ -310,7 +310,7 @@ export function tryFinishCronTaskRunWithoutHistory(
}
const error = result.status === "error" ? normalizeCronRunErrorText(result.error) : undefined;
try {
finalizeTaskRunByRunId({
finalizeTaskRunByRunIdCore({
runId: result.taskRunId,
runtime: "cron",
status:
@@ -383,7 +383,7 @@ export function tryFinishCronTaskRun(
"succeeded" | "failed" | "timed_out" | "cancelled"
> = cronRunStatusToTaskStatus(entry),
) =>
finalizeTaskRunByRunId({
finalizeTaskRunByRunIdCore({
runId,
runtime: "cron",
status,
+3 -3
View File
@@ -323,7 +323,7 @@ describe("cron service timer seam coverage", () => {
let terminalStatePersisted = false;
let finalizedAfterPersist = false;
const save = cronStoreModule.saveCronJobsStore;
const finalize = taskExecutor.finalizeTaskRunByRunId;
const finalize = taskExecutor.finalizeTaskRunByRunIdCore;
const saveSpy = vi
.spyOn(cronStoreModule, "saveCronJobsStore")
.mockImplementation(async (...args) => {
@@ -337,7 +337,7 @@ describe("cron service timer seam coverage", () => {
}
});
const finalizeSpy = vi
.spyOn(taskExecutor, "finalizeTaskRunByRunId")
.spyOn(taskExecutor, "finalizeTaskRunByRunIdCore")
.mockImplementation((params) => {
finalizedAfterPersist = terminalStatePersisted;
return finalize(params);
@@ -800,7 +800,7 @@ describe("cron service timer seam coverage", () => {
});
const createTaskRecordSpy = vi
.spyOn(taskExecutor, "createRunningTaskRun")
.spyOn(taskExecutor, "createRunningTaskRunCore")
.mockImplementation(() => {
throw ledgerError;
});
@@ -317,7 +317,7 @@ export function withClaudeMcpConfigOverrides(args: string[], mcpConfigPath: stri
return next;
}
export async function getFreeGatewayPort(): Promise<number> {
export async function getCliBackendPortBlock(): Promise<number> {
return await getFreePortBlockWithPermissionFallback({
offsets: [0, 1, 2, 4],
fallbackBase: 40_000,
+2 -2
View File
@@ -23,7 +23,7 @@ import {
buildClaudeCliResumeContinuityProbe,
createBootstrapWorkspace,
ensurePairedTestGatewayClientIdentity,
getFreeGatewayPort,
getCliBackendPortBlock,
matchesCliBackendReply,
parseImageMode,
parseJsonStringArray,
@@ -297,7 +297,7 @@ describeLive("gateway live (cli backend)", () => {
const token = `test-${randomUUID()}`;
setTestEnvValue("OPENCLAW_GATEWAY_TOKEN", token);
const port = await getFreeGatewayPort();
const port = await getCliBackendPortBlock();
logCliBackendLiveStep("env-ready", { port });
const rawModel = process.env.OPENCLAW_LIVE_CLI_BACKEND_MODEL ?? DEFAULT_MODEL;
+2 -2
View File
@@ -27,7 +27,7 @@ import { sleep } from "../utils.js";
import type { GatewayClient } from "./client.js";
import {
connectTestGatewayClient,
getFreeGatewayPort,
getCliBackendPortBlock,
} from "./gateway-cli-backend.live-helpers.js";
import { restoreLiveEnv, snapshotLiveEnv, type LiveEnvSnapshot } from "./live-env-test-helpers.js";
import { startGatewayServer } from "./server.js";
@@ -395,7 +395,7 @@ describeLive("gateway live (native Codex conversation binding)", () => {
const workspace = path.join(tempRoot, "workspace");
const configPath = path.join(tempRoot, "openclaw.json");
const token = `test-${randomUUID()}`;
const port = await getFreeGatewayPort();
const port = await getCliBackendPortBlock();
const sessionKey = "main";
const accountId = "default";
const slackUserId = `U${randomUUID().replace(/-/g, "").slice(0, 10).toUpperCase()}`;
@@ -4576,7 +4576,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
"OPENCLAW_LOG_LEVEL",
"OPENCLAW_AGENT_DIR",
]);
const { startGatewayServer } = await import("./server.impl.js");
const { startGatewayServerCore } = await import("./server.impl.js");
let runtimeEnv: ReturnType<typeof enterProductionEnvForLiveRun> | undefined;
let cleanupTempStateDir: string | undefined;
let cleanupTempAgentDir: string | undefined;
@@ -4692,7 +4692,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
`${params.label}: gateway-port`,
);
server = await withGatewayLiveProbeTimeout(
startGatewayServer(port, {
startGatewayServerCore(port, {
bind: "loopback",
auth: { mode: "token", token },
controlUiEnabled: false,
@@ -5734,7 +5734,7 @@ describeLive("gateway live (dev agent, profile keys)", () => {
clearRuntimeConfigSnapshot();
const runtimeEnv = enterProductionEnvForLiveRun();
const previousEnv = snapshotLiveEnv(["OPENCLAW_AGENT_DIR"]);
const { startGatewayServer } = await import("./server.impl.js");
const { startGatewayServerCore } = await import("./server.impl.js");
process.env.OPENCLAW_SKIP_CHANNELS = "1";
process.env.OPENCLAW_SKIP_GMAIL_WATCHER = "1";
@@ -5833,7 +5833,7 @@ describeLive("gateway live (dev agent, profile keys)", () => {
"zai-fallback: gateway-port",
);
server = await withGatewayLiveProbeTimeout(
startGatewayServer(port, {
startGatewayServerCore(port, {
bind: "loopback",
auth: { mode: "token", token },
controlUiEnabled: false,
@@ -13,7 +13,7 @@ import {
connectTestGatewayClient,
createBootstrapWorkspace,
ensurePairedTestGatewayClientIdentity,
getFreeGatewayPort,
getCliBackendPortBlock,
} from "./gateway-cli-backend.live-helpers.js";
import { restoreLiveEnv, snapshotLiveEnv, type LiveEnvSnapshot } from "./live-env-test-helpers.js";
import { loadSessionEntry } from "./session-utils.js";
@@ -470,7 +470,7 @@ describeLive("gateway live trajectory export", () => {
const { workspaceDir } = await createBootstrapWorkspace(tempDir);
const configPath = path.join(tempDir, "openclaw.json");
const token = `test-${randomUUID()}`;
const port = await getFreeGatewayPort();
const port = await getCliBackendPortBlock();
const modelKey = process.env.OPENCLAW_LIVE_CODEX_HARNESS_MODEL ?? DEFAULT_CODEX_MODEL;
clearRuntimeConfigSnapshot();
@@ -13,7 +13,7 @@ import { startGatewayServer } from "./server.js";
import {
connectGatewayClient,
disconnectGatewayClient,
getFreeGatewayPort,
getGatewayE2ePortBlock,
} from "./test-helpers.e2e.js";
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
@@ -77,7 +77,7 @@ describe("gateway wizard cancellation lifecycle", () => {
setTestEnvValue("OPENCLAW_DISABLE_BUNDLED_PLUGINS", "1");
setTestEnvValue("OPENCLAW_TEST_MINIMAL_GATEWAY", "1");
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const server = await startGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token },
+10 -10
View File
@@ -25,7 +25,7 @@ import {
connectDeviceAuthReq,
disconnectGatewayClient,
connectGatewayClient,
getFreeGatewayPort,
getGatewayE2ePortBlock,
startGatewayWithClient,
} from "./test-helpers.e2e.js";
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
@@ -79,7 +79,7 @@ async function removeGatewayTempHome(tempHome: string): Promise<void> {
}
async function startLoopbackTokenGateway(token: string) {
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const server = await startGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token },
@@ -203,7 +203,7 @@ describe("gateway e2e", () => {
logging: { level: "info" },
};
await createConfigIO({ configPath }).writeConfigFile(initialConfig);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
server = await startGatewayServer(port, {
bind: "loopback",
controlUiEnabled: false,
@@ -316,7 +316,7 @@ describe("gateway e2e", () => {
authSource === "explicit-override"
? { mode: "off" as const, serviceName: "svc:startup" }
: undefined;
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
server = await startGatewayServer(port, {
bind: "loopback",
...(callerAuthOverride ? { auth: callerAuthOverride } : {}),
@@ -432,7 +432,7 @@ describe("gateway e2e", () => {
logging: { level: "info" },
});
setTestEnvValue("OPENCLAW_TEST_GATEWAY_OVERRIDE_TOKEN", oldToken);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
server = await startGatewayServer(port, {
bind: "loopback",
auth: {
@@ -499,7 +499,7 @@ describe("gateway e2e", () => {
logging: { level: "info" },
};
await configIO.writeConfigFile(initialConfig);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const server = await startGatewayServer(port, {
bind: "lan",
controlUiEnabled: false,
@@ -724,7 +724,7 @@ module.exports = {
clearConfigCache();
const wizardToken = nextGatewayId("wiz-token");
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const server = await startGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token: wizardToken },
@@ -805,7 +805,7 @@ module.exports = {
await server.close({ reason: "wizard e2e complete" });
}
const port2 = await getFreeGatewayPort();
const port2 = await getGatewayE2ePortBlock();
const server2 = await startGatewayServer(port2, {
bind: "loopback",
controlUiEnabled: false,
@@ -844,7 +844,7 @@ module.exports = {
minimalGateway: true,
});
const wizardToken = nextGatewayId("wiz-contained-exit");
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const server = await startGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token: wizardToken },
@@ -912,7 +912,7 @@ module.exports = {
minimalGateway: true,
});
const wizAuth = nextGatewayId("wiz-chan");
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const channelRuns: Array<string | undefined> = [];
const server = await startGatewayServer(port, {
bind: "loopback",
@@ -22,7 +22,7 @@ import { startGatewayServer } from "./server.js";
import {
connectGatewayClient,
disconnectGatewayClient,
getFreeGatewayPort,
getGatewayE2ePortBlock,
} from "./test-helpers.e2e.js";
import {
configureManualGatewayBackgroundEnv,
@@ -93,7 +93,7 @@ describe("operator approval gateway client e2e", () => {
setTestEnvValue("OPENCLAW_STATE_DIR", stateDir);
configureManualGatewayBackgroundEnv(tempHome);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const token = "approval-client-e2e-token";
const url = `ws://127.0.0.1:${port}`;
setTestEnvValue("OPENCLAW_GATEWAY_PORT", String(port));
@@ -209,7 +209,7 @@ describe("operator approval gateway client e2e", () => {
});
expect(requesterIdentity.deviceId).not.toBe(reviewerIdentity.deviceId);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const token = "approval-surfaces-e2e-token";
const url = `ws://127.0.0.1:${port}`;
setTestEnvValue("OPENCLAW_GATEWAY_PORT", String(port));
@@ -26,7 +26,7 @@ const mocks = vi.hoisted(() => ({
applyPluginAutoEnable: vi.fn(),
listChannelPlugins: vi.fn(),
buildChannelUiCatalog: vi.fn(),
buildChannelAccountSnapshot: vi.fn(),
resolveChannelAccountSnapshot: vi.fn(),
getChannelActivity: vi.fn(),
}));
@@ -55,7 +55,7 @@ vi.mock("../../channels/plugins/catalog.js", () => ({
}));
vi.mock("../../channels/plugins/status.js", () => ({
buildChannelAccountSnapshot: mocks.buildChannelAccountSnapshot,
resolveChannelAccountSnapshot: mocks.resolveChannelAccountSnapshot,
}));
vi.mock("../../infra/channel-activity.js", () => ({
@@ -180,7 +180,7 @@ describe("channelsHandlers channels.status", () => {
systemImages: { whatsapp: undefined },
entries: { whatsapp: { id: "whatsapp" } },
});
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: true,
});
@@ -201,7 +201,7 @@ describe("channelsHandlers channels.status", () => {
config: {},
});
const snapshotArgs = requireRecord(
requireFirstCallArg(mocks.buildChannelAccountSnapshot),
requireFirstCallArg(mocks.resolveChannelAccountSnapshot),
"snapshot args",
);
expect(snapshotArgs.cfg).toBe(autoEnabledConfig);
@@ -337,7 +337,7 @@ describe("channelsHandlers channels.status", () => {
throw new Error("probe failed");
});
mocks.applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
mocks.buildChannelAccountSnapshot.mockImplementation(async ({ accountId, probe }) => ({
mocks.resolveChannelAccountSnapshot.mockImplementation(async ({ accountId, probe }) => ({
accountId,
configured: true,
probe,
@@ -366,7 +366,7 @@ describe("channelsHandlers channels.status", () => {
createChannelPlugin({ id: "hanging", probeAccount: hangingProbe }),
createChannelPlugin({ id: "healthy", probeAccount: healthyProbe }),
]);
mocks.buildChannelAccountSnapshot.mockImplementation(async ({ accountId, probe }) => ({
mocks.resolveChannelAccountSnapshot.mockImplementation(async ({ accountId, probe }) => ({
accountId,
configured: true,
probe,
@@ -400,7 +400,7 @@ describe("channelsHandlers channels.status", () => {
it("falls back to account-derived channel summaries when summary building fails", async () => {
const autoEnabledConfig = { autoEnabled: true };
mocks.applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
configured: true,
});
@@ -425,7 +425,7 @@ describe("channelsHandlers channels.status", () => {
it("annotates terminal-disconnect accounts with terminal-disconnect health state", async () => {
mocks.applyPluginAutoEnable.mockReturnValue({ config: { autoEnabled: true }, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
enabled: true,
configured: true,
@@ -457,7 +457,7 @@ describe("channelsHandlers channels.status", () => {
it("annotates unhealthy channel snapshots and includes event-loop health", async () => {
const now = Date.now();
mocks.applyPluginAutoEnable.mockReturnValue({ config: { autoEnabled: true }, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
enabled: true,
configured: true,
@@ -506,7 +506,7 @@ describe("channelsHandlers channels.status", () => {
it("preserves channel-authored health state when shared health is healthy", async () => {
mocks.applyPluginAutoEnable.mockReturnValue({ config: { autoEnabled: true }, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
enabled: true,
configured: true,
@@ -522,7 +522,7 @@ describe("channelsHandlers channels.status", () => {
it("preserves channel-authored conflict when recorded blocked lifecycle is unhealthy", async () => {
mocks.applyPluginAutoEnable.mockReturnValue({ config: { autoEnabled: true }, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
enabled: true,
configured: true,
@@ -546,7 +546,7 @@ describe("channelsHandlers channels.status", () => {
it("derives blocked health from recorded lifecycle", async () => {
mocks.applyPluginAutoEnable.mockReturnValue({ config: { autoEnabled: true }, changes: [] });
mocks.buildChannelAccountSnapshot.mockResolvedValue({
mocks.resolveChannelAccountSnapshot.mockResolvedValue({
accountId: "default",
enabled: true,
configured: true,
+2 -2
View File
@@ -17,7 +17,7 @@ import {
listChannelPlugins,
normalizeChannelId,
} from "../../channels/plugins/index.js";
import { buildChannelAccountSnapshot } from "../../channels/plugins/status.js";
import { resolveChannelAccountSnapshot } from "../../channels/plugins/status.js";
import type { ChannelPlugin } from "../../channels/plugins/types.plugin.js";
import type { ChannelAccountSnapshot } from "../../channels/plugins/types.public.js";
import { readConfigFileSnapshot } from "../../config/config.js";
@@ -449,7 +449,7 @@ export const channelsHandlers: GatewayRequestHandlers = {
}
}
const runtimeSnapshot = resolveRuntimeSnapshot(channelId, accountId, defaultAccountId);
const snapshot = await buildChannelAccountSnapshot({
const snapshot = await resolveChannelAccountSnapshot({
plugin,
cfg,
accountId,
@@ -20,7 +20,7 @@ import { startGatewayServer } from "../server.js";
import {
connectGatewayClient,
disconnectGatewayClient,
getFreeGatewayPort,
getGatewayE2ePortBlock,
} from "../test-helpers.e2e.js";
import {
configureManualGatewayBackgroundEnv,
@@ -61,7 +61,7 @@ describe("plugin.approval.request delivery routing (real gateway)", () => {
setTestEnvValue("OPENCLAW_STATE_DIR", stateDir);
configureManualGatewayBackgroundEnv(tempHome);
const port = await getFreeGatewayPort();
const port = await getGatewayE2ePortBlock();
const token = "plugin-approval-turn-source-e2e-token";
const url = `ws://127.0.0.1:${port}`;
setTestEnvValue("OPENCLAW_GATEWAY_PORT", String(port));
+2 -2
View File
@@ -130,9 +130,9 @@ export const tasksHandlers: GatewayRequestHandlers = {
}
const taskId = params.taskId;
const reason = normalizeOptionalString(params.reason);
const { cancelDetachedTaskRunById } =
const { cancelDetachedTaskRunByIdCore } =
await import("../../tasks/task-executor-cancel.runtime.js");
const result = await cancelDetachedTaskRunById({
const result = await cancelDetachedTaskRunByIdCore({
cfg: context.getRuntimeConfig(),
taskId,
...(reason ? { reason } : {}),
+1 -1
View File
@@ -39,7 +39,7 @@ async function resolveLoader(
}
// Isolated gateway tests share process module state with lifecycle-owner tests.
export async function resetPreparedModelCatalogForTest(): Promise<void> {
export async function resetPreparedModelCatalogStateForTest(): Promise<void> {
const [{ resetPreparedModelRuntimeSnapshotsForTest }, { resetModelCatalogBuilderCacheForTest }] =
await Promise.all([
import("../agents/prepared-model-runtime.test-support.js"),
@@ -10,7 +10,7 @@ import { resetAgentEventsForTest } from "../infra/agent-events.js";
import { PROXY_ENV_KEYS } from "../infra/net/proxy-env.js";
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
import { startGatewayServer } from "./server.js";
import { getFreeGatewayPort } from "./test-helpers.e2e.js";
import { getGatewayE2ePortBlock } from "./test-helpers.e2e.js";
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
const NETWORK_GATEWAY_ENV_KEYS = [
@@ -98,7 +98,7 @@ describe("gateway network runtime", () => {
);
setTestEnvValue("OPENCLAW_CONFIG_PATH", configPath);
server = await startGatewayServer(await getFreeGatewayPort(), {
server = await startGatewayServer(await getGatewayE2ePortBlock(), {
bind: "loopback",
auth: { mode: "token", token },
controlUiEnabled: false,
@@ -154,7 +154,7 @@ describe("gateway network runtime", () => {
await fs.writeFile(configPath, raw, { mode: 0o600 });
setTestEnvValue("OPENCLAW_CONFIG_PATH", configPath);
server = await startGatewayServer(await getFreeGatewayPort(), {
server = await startGatewayServer(await getGatewayE2ePortBlock(), {
controlUiEnabled: false,
});
+4 -5
View File
@@ -24,10 +24,9 @@ const loadWorkerPlacementStartupModule = createLazyRuntimeModule(
() => import("./server-worker-placement-startup.js"),
);
export async function resetPreparedModelCatalogForTest(): Promise<void> {
const { resetPreparedModelCatalogForTest: resetPreparedModelCatalogForTestLocal } =
await loadGatewayModelCatalogModule();
await resetPreparedModelCatalogForTestLocal();
export async function resetPreparedModelCatalogForTestCore(): Promise<void> {
const { resetPreparedModelCatalogStateForTest } = await loadGatewayModelCatalogModule();
await resetPreparedModelCatalogStateForTest();
}
const loadGatewayStartupEarlyModule = createLazyRuntimeModule(
@@ -102,7 +101,7 @@ async function stopTaskRegistryMaintenanceOnDemand(): Promise<void> {
stopTaskRegistryMaintenance();
}
export async function startGatewayServer(
export async function startGatewayServerCore(
port = 18789,
opts: GatewayServerOptions = {},
): Promise<GatewayServer> {
@@ -12,12 +12,12 @@ import {
clearSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshot,
} from "../secrets/runtime.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
import { getFreePort, installGatewayTestHooks, startTestGatewayServer } from "./test-helpers.js";
installGatewayTestHooks({ scope: "suite" });
describe("Gateway startup copied auth SecretRef isolation", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let server: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
let agentDir: string | undefined;
afterEach(async () => {
@@ -57,7 +57,7 @@ describe("Gateway startup copied auth SecretRef isolation", () => {
await writeConfigFile(config);
const port = await getFreePort();
server = await startGatewayServer(port, { auth: { mode: "none" } });
server = await startTestGatewayServer(port, { auth: { mode: "none" } });
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -13,13 +13,13 @@ import {
getFreePort,
installGatewayTestHooks,
setTestPluginRegistry,
startGatewayServer,
startTestGatewayServer,
} from "./test-helpers.js";
installGatewayTestHooks({ scope: "suite" });
describe("Gateway startup plugin quarantine", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let server: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
const tempDirs: string[] = [];
afterEach(async () => {
@@ -158,7 +158,7 @@ describe("Gateway startup plugin quarantine", () => {
});
const port = await getFreePort();
server = await startGatewayServer(port, { auth: { mode: "none" } });
server = await startTestGatewayServer(port, { auth: { mode: "none" } });
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -18,7 +18,7 @@ import { withEnvAsync } from "../test-utils/env.js";
import {
getFreePort,
installGatewayTestHooks,
startGatewayServer,
startTestGatewayServer,
testState,
} from "./test-helpers.js";
import "./server-startup-secret-diagnostics.test-support.js";
@@ -125,7 +125,7 @@ async function startVaultAclFixture() {
}
describe("Gateway startup SecretRef owner isolation", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let server: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
afterEach(async () => {
await server?.close();
@@ -272,7 +272,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
testState.gatewayAuth = undefined;
const port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -435,7 +435,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
});
const port = await getFreePort();
server = await startGatewayServer(port, { auth: { mode: "none" } });
server = await startTestGatewayServer(port, { auth: { mode: "none" } });
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -508,7 +508,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
});
const port = await getFreePort();
server = await startGatewayServer(port, { auth: { mode: "none" } });
server = await startTestGatewayServer(port, { auth: { mode: "none" } });
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -582,7 +582,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
await writeConfig(config);
const port = await getFreePort();
server = await startGatewayServer(port, { auth: { mode: "none" } });
server = await startTestGatewayServer(port, { auth: { mode: "none" } });
const ready = await fetch(`http://127.0.0.1:${port}/readyz`);
expect(ready.status).toBe(200);
@@ -631,7 +631,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
});
testState.gatewayAuth = undefined;
await expect(startGatewayServer(await getFreePort())).rejects.toThrow(
await expect(startTestGatewayServer(await getFreePort())).rejects.toThrow(
/Startup failed: required secrets are unavailable/,
);
});
@@ -4,7 +4,7 @@
import http from "node:http";
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
import { getFreePort, installGatewayTestHooks, startTestGatewayServer } from "./test-helpers.js";
import { readClientResponseBody } from "./test-http-response.js";
const webFetchProviderDiscovery = vi.hoisted(() => ({
@@ -94,7 +94,7 @@ async function writeConfig(config: OpenClawConfig): Promise<void> {
describe("gateway startup web fetch config", () => {
let port: number;
let previousMinimal: string | undefined;
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let server: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
beforeAll(async () => {
previousMinimal = process.env.OPENCLAW_TEST_MINIMAL_GATEWAY;
@@ -122,7 +122,7 @@ describe("gateway startup web fetch config", () => {
} as OpenClawConfig);
port = await getFreePort();
server = await startGatewayServer(port, {
server = await startTestGatewayServer(port, {
auth: { mode: "none" },
});
});
@@ -14,7 +14,7 @@ import {
createDirectOutboundTestAdapter,
} from "../test-utils/channel-plugins.js";
import { waitForAgentCommandCall } from "./agent-command.test-helpers.js";
import { resetPreparedModelCatalogForTest } from "./server-model-catalog.js";
import { resetPreparedModelCatalogStateForTest } from "./server-model-catalog.js";
import { setRegistry } from "./server.agent.gateway-server-agent.mocks.js";
import { createRegistry } from "./server.e2e-registry-helpers.js";
import { installConnectedSessionStoreGatewaySuite } from "./test-helpers.connected-session-store.js";
@@ -101,7 +101,7 @@ async function setGatewayModelCatalogForTest(
testState.sessionStorePath = gatewaySuite.sessionStorePath;
agentDiscoveryMock.enabled = true;
agentDiscoveryMock.models = models;
await resetPreparedModelCatalogForTest();
await resetPreparedModelCatalogStateForTest();
const [
{ refreshPreparedModelRuntimeSnapshots },
{ clearRuntimeConfigSnapshot, getRuntimeConfig },
@@ -18,7 +18,7 @@ import {
originForPort,
rpcReq,
restoreGatewayToken,
startGatewayServer,
startTestGatewayServer,
testState,
installGatewayTestHooks,
} from "./server.auth.test-helpers.js";
@@ -137,7 +137,7 @@ async function expectLocalCliSharedAuthScopesPreserved(
describe("gateway auth compatibility baseline", () => {
describe("token mode", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port = 0;
let prevToken: string | undefined;
@@ -146,7 +146,7 @@ describe("gateway auth compatibility baseline", () => {
testState.gatewayAuth = { mode: "token", token: "secret" };
process.env.OPENCLAW_GATEWAY_TOKEN = "secret";
port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
});
afterAll(async () => {
@@ -299,7 +299,7 @@ describe("gateway auth compatibility baseline", () => {
});
describe("password mode", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port = 0;
let prevToken: string | undefined;
@@ -308,7 +308,7 @@ describe("gateway auth compatibility baseline", () => {
testState.gatewayAuth = { mode: "password", password: "secret" };
delete process.env.OPENCLAW_GATEWAY_TOKEN;
port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
});
afterAll(async () => {
@@ -356,7 +356,7 @@ describe("gateway auth compatibility baseline", () => {
});
describe("none mode", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port = 0;
let prevToken: string | undefined;
@@ -365,7 +365,7 @@ describe("gateway auth compatibility baseline", () => {
testState.gatewayAuth = { mode: "none" };
delete process.env.OPENCLAW_GATEWAY_TOKEN;
port = await getFreePort();
server = await startGatewayServer(port, { controlUiEnabled: true });
server = await startTestGatewayServer(port, { controlUiEnabled: true });
});
afterAll(async () => {
+2 -2
View File
@@ -22,7 +22,7 @@ import {
restoreGatewayToken,
rpcReq,
startRateLimitedTokenServerWithPairedDeviceToken,
startGatewayServer,
startTestGatewayServer,
startServer,
startServerWithClient,
TEST_OPERATOR_CLIENT,
@@ -166,7 +166,7 @@ export function registerControlUiAndPairingSuite(): void {
const withControlUiGatewayServer = async <T>(
fn: (ctx: {
port: number;
server: Awaited<ReturnType<typeof startGatewayServer>>;
server: Awaited<ReturnType<typeof startTestGatewayServer>>;
}) => Promise<T>,
): Promise<T> => {
return await withGatewayServer(fn, {
@@ -25,7 +25,7 @@ import {
resolvePreauthHandshakeTimeoutMs,
rpcReq,
sendRawConnectReq,
startGatewayServer,
startTestGatewayServer,
TEST_OPERATOR_CLIENT,
waitForWsClose,
withGatewayServer,
@@ -34,12 +34,12 @@ import {
export function registerDefaultAuthTokenSuite(): void {
describe("default auth (token)", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let server: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
let port: number;
beforeAll(async () => {
port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
});
afterAll(async () => {
+11 -11
View File
@@ -11,7 +11,7 @@ import {
originForPort,
rpcReq,
restoreGatewayToken,
startGatewayServer,
startTestGatewayServer,
testState,
testTailscaleWhois,
} from "./server.auth.test-helpers.js";
@@ -26,13 +26,13 @@ async function requestModels(port: number, secret: string): Promise<Response> {
export function registerAuthModesSuite(): void {
describe("password auth", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port: number;
beforeAll(async () => {
testState.gatewayAuth = { mode: "password", password: "secret" }; // pragma: allowlist secret
port = await getFreePort();
server = await startGatewayServer(port, { openAiChatCompletionsEnabled: true });
server = await startTestGatewayServer(port, { openAiChatCompletionsEnabled: true });
});
beforeEach(() => {
@@ -81,7 +81,7 @@ export function registerAuthModesSuite(): void {
});
describe("token auth", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port: number;
let prevToken: string | undefined;
@@ -90,7 +90,7 @@ export function registerAuthModesSuite(): void {
process.env.OPENCLAW_GATEWAY_TOKEN = "secret";
testState.gatewayAuth = { mode: "token", token: "secret" };
port = await getFreePort();
server = await startGatewayServer(port, { openAiChatCompletionsEnabled: true });
server = await startTestGatewayServer(port, { openAiChatCompletionsEnabled: true });
});
beforeEach(() => {
@@ -171,7 +171,7 @@ export function registerAuthModesSuite(): void {
});
describe("explicit none auth", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port: number;
let prevToken: string | undefined;
@@ -180,7 +180,7 @@ export function registerAuthModesSuite(): void {
delete process.env.OPENCLAW_GATEWAY_TOKEN;
testState.gatewayAuth = { mode: "none" };
port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
});
beforeEach(() => {
@@ -227,7 +227,7 @@ export function registerAuthModesSuite(): void {
const port = await getFreePort();
try {
await expect(startGatewayServer(port, { auth })).rejects.toThrow(testCase.expected);
await expect(startTestGatewayServer(port, { auth })).rejects.toThrow(testCase.expected);
} finally {
if (previous === undefined) {
delete process.env[testCase.envKey];
@@ -242,7 +242,7 @@ export function registerAuthModesSuite(): void {
const port = await getFreePort();
await expect(
startGatewayServer(port, {
startTestGatewayServer(port, {
bind: "lan",
host: "0.0.0.0",
auth: { mode: "none" },
@@ -255,7 +255,7 @@ export function registerAuthModesSuite(): void {
});
describe("tailscale auth", () => {
let server: Awaited<ReturnType<typeof startGatewayServer>>;
let server: Awaited<ReturnType<typeof startTestGatewayServer>>;
let port: number;
const tailscaleOrigin = "https://gateway.tailnet.ts.net";
@@ -273,7 +273,7 @@ export function registerAuthModesSuite(): void {
afterWrite: { mode: "auto" },
});
port = await getFreePort();
server = await startGatewayServer(port);
server = await startTestGatewayServer(port);
});
afterAll(async () => {
+2 -2
View File
@@ -18,7 +18,7 @@ import {
installGatewayTestHooks,
onceMessage,
rpcReq,
startGatewayServer,
startTestGatewayServer,
startServer,
startServerWithClient,
trackConnectChallengeNonce,
@@ -393,7 +393,7 @@ export {
restoreGatewayToken,
rpcReq,
sendRawConnectReq,
startGatewayServer,
startTestGatewayServer,
startRateLimitedTokenServerWithPairedDeviceToken,
startServer,
startServerWithClient,
@@ -11,7 +11,7 @@ import {
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { READ_SCOPE, WRITE_SCOPE } from "./method-scopes.js";
import { connectGatewayClient, disconnectGatewayClient } from "./test-helpers.e2e.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
import { getFreePort, installGatewayTestHooks, startTestGatewayServer } from "./test-helpers.js";
installGatewayTestHooks({ scope: "suite" });
@@ -48,7 +48,7 @@ it(
const events: string[] = [];
const start = async () => {
const port = await getFreePort();
const server = await startGatewayServer(port, {
const server = await startTestGatewayServer(port, {
auth: { mode: "none" },
bind: "loopback",
controlUiEnabled: false,
@@ -74,10 +74,10 @@ it(
timeoutMs: 30_000,
});
let firstServer: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let firstServer: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
let firstClient: Awaited<ReturnType<typeof connectGatewayClient>> | undefined;
let secondClient: Awaited<ReturnType<typeof connectGatewayClient>> | undefined;
let restartedServer: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
let restartedServer: Awaited<ReturnType<typeof startTestGatewayServer>> | undefined;
let restartedClient: Awaited<ReturnType<typeof connectGatewayClient>> | undefined;
try {
const first = await start();
@@ -11,7 +11,7 @@ import { resetContextWindowCacheForTest } from "../agents/context-runtime-state.
import { resetPreparedModelRuntimeSnapshotsForTest } from "../agents/prepared-model-runtime.test-support.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { connectGatewayClient, disconnectGatewayClient } from "./test-helpers.e2e.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
import { getFreePort, installGatewayTestHooks, startTestGatewayServer } from "./test-helpers.js";
installGatewayTestHooks();
@@ -35,7 +35,7 @@ describe("Gateway context cache remote proof", () => {
}));
const port = await getFreePort();
const token = "context-prewarm-proof-token";
const server = await startGatewayServer(port, {
const server = await startTestGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token },
controlUiEnabled: false,
+3 -3
View File
@@ -5,7 +5,7 @@ import { captureEnv } from "../test-utils/env.js";
import {
connectOk,
getFreePort,
startGatewayServer,
startTestGatewayServer,
trackConnectChallengeNonce,
} from "./test-helpers.js";
@@ -16,7 +16,7 @@ type GatewayWsClient = {
export type GatewayServerHarness = {
port: number;
server: Awaited<ReturnType<typeof startGatewayServer>>;
server: Awaited<ReturnType<typeof startTestGatewayServer>>;
openClient: (opts?: Parameters<typeof connectOk>[1]) => Promise<GatewayWsClient>;
close: () => Promise<void>;
};
@@ -27,7 +27,7 @@ export async function startGatewayServerHarness(): Promise<GatewayServerHarness>
const clients = new Set<WebSocket>();
delete process.env.OPENCLAW_GATEWAY_TOKEN;
const port = await getFreePort();
const server = await startGatewayServer(port, {
const server = await startTestGatewayServer(port, {
auth: { mode: "none" },
bind: "loopback",
controlUiEnabled: false,
+1 -1
View File
@@ -9,4 +9,4 @@ export {
type GatewayServer,
type GatewayServerOptions,
} from "./server-public.js";
export { resetPreparedModelCatalogForTest, startGatewayServer } from "./server-start.js";
export { resetPreparedModelCatalogForTestCore, startGatewayServerCore } from "./server-start.js";

Some files were not shown because too many files have changed in this diff Show More