diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index 38ae5cf34ba1..7baa6a532631 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -53,7 +53,7 @@ {"closureHash":"ff3c4616cd6212a6d698831a8b287ad87e3968c8663f4090d095bb30ec40fc1c","declaration":"export function abortAndDrainAgentHarnessRun(params: { sessionId: string; sessionKey?: string; settleMs?: number; forceClear?: boolean; reason?: string; }): Promise;","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; };","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>; };","entrypoint":"agent-harness","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} -{"closureHash":"fd6548682cda2d069f1a9b6eef190102b4ebcadc20d485d5ee9d2cb6e4419011","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} +{"closureHash":"a0fb4f1e4227c4a6707752fe63fa5ef71bdd67b9c95a12ed86380ad34e13c50f","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;","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":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","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":"3bf0706b73e9be9ae75dc4be9c5e93981d9152af4713168ce74e57b1197d8f23","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":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","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":"3bf0706b73e9be9ae75dc4be9c5e93981d9152af4713168ce74e57b1197d8f23","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;","entrypoint":"inbound-reply-dispatch","exportName":"resolveInboundReplyDispatchCounts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"9d503d05e408ddd1a1c373e3c4485b1f9acff4c240fdc241840a2cfa8b55c3a7","declaration":"export function runChannelInboundEvent(params: RunChannelTurnParams): Promise>;\nexport function runChannelInboundEvent(params: ChannelInboundEventRunnerParams): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runChannelInboundEvent","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"2c68496a174872b31aaf1ac8fad2789deb79d490c5ffbcb157325f1c95d1b51f","declaration":"export function runPreparedInboundReply(params: PreparedChannelTurn): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runPreparedInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} -{"closureHash":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","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":"3bf0706b73e9be9ae75dc4be9c5e93981d9152af4713168ce74e57b1197d8f23","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;","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":"cc82f299f781157a633a599387ba8190b4f9163b031ea44cb27df50b0aeed48f","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":"29367eafb2db114b39885ff1af531eac437ce422e310b3cd141493a7ffd90ee3","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; };","entrypoint":"meeting-runtime","exportName":"createMeetingNodeHost","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"6030bd4718a6362627f0388a624505ad6680512881e27c42a7792ec0d52f9d58","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; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"748916cfb7434a63b8b8ea475ff0c28837e625c5c1c4edb30d3dc4dc598cd1c3","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; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"9124db05923060c467edb149bd8abdc8be1d00d00f867cf84600972923a58489","declaration":"export function createMeetingSession(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { provider?: string; voiceProvider?: string; transcriptionProvider?: string; model?: string; toolPolicy: TToolPolicy; }; }; resolved: MeetingResolvedJoin; createdAt: string; }): MeetingSessionRecord;","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; }): MeetingVoiceCallGateway;","entrypoint":"meeting-runtime","exportName":"createMeetingVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"e1c082dd9e7ecc190f8cbd1e9706e37a805d64a55ee7256f84f5d39dc2edaaf4","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":"ffbeab86625120d41301a0733b71b73109c0e6d4e49ba187bbf6deb0e6cef9f3","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;","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;","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":"59bf540846422a2078a247b42ea08bba1bf81b46b732a19180790f2a73568f11","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;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"8b4bbc797cf19f17d8fd452e48c613c7dbc0861c82da6aa3231483145d1bafc1","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;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"bac9621cd025754fbcd4c21409b06eb0503405db81f35cac993aaf0b881ab3e1","declaration":"export function leaveMeetingWithBrowser(params: { adapter: BrowserAdapter; 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, Mode extends string, Health extends MeetingBrowserHealth & { browserTitle?: string; browserUrl?: string; notes?: string[]; }, Transcript extends MeetingTranscriptSnapshot>(params: { adapter: BrowserAdapter; 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;","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;","entrypoint":"meeting-runtime","exportName":"speakMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"3130ab53a021c7e3f2970bf24e318a1f06ca09ea91d3c9bd51581bf39481d229","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;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"b943ecbbcebec424120f28f33fb2f8b382d2ae91adad8fac853496bd2eed1984","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; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"4572bca066f52b78e800aaaeb4d847e74706490ec2da986b2647c718f9b51038","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;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"bddb4095f4b87644f2c16a58220d3f1c734577d053aa762e46d386f444a7616b","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; }): Promise;","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 = MeetingSessionRuntimeHandles;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeHandles","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"aa8054fc2c442891197e89bdad61e79999ea15d813c4b127fb6150607b9e67e7","declaration":"export type MeetingSessionRuntimeJoinContext, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab> = MeetingSessionRuntimeJoinContext;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeJoinContext","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"325241724edd38da439c5df03d225e2a7cb8e56d817e98ed7c37850656d3744b","declaration":"export type MeetingSessionRuntimeMessages = MeetingSessionRuntimeMessages;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeMessages","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} -{"closureHash":"8345dc18050019a013d34a7653ed0d12e6178bcc18dfdb52f85a05a46bbd4e22","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} +{"closureHash":"27608aa6c6035520513bc6abeee9d6f32f55a30616f6d9c4c67f79eb2e882694","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","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":"4eaf1fc1a9108206f22d89e18f61a55a34c7270419bd533692cb6106b0491dff","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} +{"closureHash":"2ad141bbb02357b206458b7a56b85af8de8b0bd764ebc535b41352c767a826a3","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\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;\n writeOutput(audio: Buffer): Promise;\n clearOutput(): Promise;\n dispose(): Promise;\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":"42723d088f7aacd0105697bace2776af0f0b6634c40183ad06a24f563ecca26f","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\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;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): 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>;\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;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\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): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\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;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): 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":"6f77c9bfb0db31396eddc4c4aa0b4cbccb88c4fbe44de1e3ecf7e067811d5ea6","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\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;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): 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>;\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;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\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): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\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;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): 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;","entrypoint":"provider-catalog-runtime","exportName":"augmentModelCatalogWithProviderPlugins","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"77aaebb98084205149391d11ef31ffa8a2f29a42271a5f0b47e97e101d581c8c","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"33a282a2bcfe6babd26520c27b40d86b143d487b044fa25adb696b621f099685","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":"3932fb64965f1f19ca12606778b78bb13beab0fd953b7b4025f84edb91c68206","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"35714460e5a066deaceac3617abe4a955bdb14e563c1e76412d65ef9da774e83","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":"2a6358ef7aaa6bb2f2ef060e681153ab09057bb14ab27957b33fb2e273158a25","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"483c21186302dabbec9f25b56147996767f3b2bbf9c8af3848ee3134a7b733a6","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":"483e73139394dff2f3d8d10e7de39da7aaee62af9586f440a3c99d79a1a52de7","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"f268bd216543f34454f50743913d908e777fd73befc7feed40938ef935c7e1f9","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 | undefined; requestBody?: BodyInit | Buffer | string | null; response: Response; transport?: \"http\" | \"sse\"; flowId?: string; meta?: Record; }, resolved?: DebugProxySettings, deps?: DebugProxyCaptureRuntimeDeps): void;","entrypoint":"proxy-capture","exportName":"captureHttpExchange","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"} diff --git a/scripts/lib/export-name-collision-baseline.json b/scripts/lib/export-name-collision-baseline.json index 633591bc8d50..e65932e0947d 100644 --- a/scripts/lib/export-name-collision-baseline.json +++ b/scripts/lib/export-name-collision-baseline.json @@ -261,13 +261,6 @@ "src/agents/tools/transcripts-tool-runtime.ts" ] }, - { - "name": "createSessionSlug", - "files": [ - "src/agents/bash-process-registry.ts", - "src/agents/session-slug.ts" - ] - }, { "name": "createSuiteTempRootTracker", "files": [ @@ -1533,14 +1526,6 @@ ], "sdk": true }, - { - "name": "sleep", - "files": [ - "src/tui/tui-pty-test-support.ts", - "src/utils/sleep.ts" - ], - "sdk": true - }, { "name": "startGatewayServer", "files": [ diff --git a/scripts/lib/wrapper-shadowing-baseline.json b/scripts/lib/wrapper-shadowing-baseline.json index 306a57755b62..0c8fe130f15b 100644 --- a/scripts/lib/wrapper-shadowing-baseline.json +++ b/scripts/lib/wrapper-shadowing-baseline.json @@ -59,11 +59,6 @@ "wrapped": "src/shared/deferred.ts", "wrapper": "src/plugin-sdk/extension-shared.ts" }, - { - "name": "createSessionSlug", - "wrapped": "src/agents/session-slug.ts", - "wrapper": "src/agents/bash-process-registry.ts" - }, { "name": "DEFAULT_PROGRESS_DRAFT_LABELS", "wrapped": "src/shared/progress-labels.ts", @@ -350,11 +345,6 @@ "wrapped": "src/config/sessions/store-entry.ts", "wrapper": "src/plugin-sdk/session-store-runtime.ts" }, - { - "name": "resolveSessionTranscriptActiveLeafEntryId", - "wrapped": "src/config/sessions/session-accessor.sqlite-message-cut.ts", - "wrapper": "src/config/sessions/session-accessor.message-cut.ts" - }, { "name": "resolveStorePath", "wrapped": "src/config/sessions/paths.ts", diff --git a/src/agents/bash-process-registry.test.ts b/src/agents/bash-process-registry.test.ts index 0a0dd2f62734..44816ccf5236 100644 --- a/src/agents/bash-process-registry.test.ts +++ b/src/agents/bash-process-registry.test.ts @@ -10,13 +10,13 @@ import { acknowledgeNotifyOnExit, addSession, appendOutput, - createSessionSlug, deleteSession, drainFinishedSession, drainSession, getActiveBackgroundExecSessionCount, getFinishedSession, getFinishedSessionForProcess, + isProcessSessionIdTaken, listFinishedSessions, listRunningSessions, markBackgrounded, @@ -28,6 +28,7 @@ import { } from "./bash-process-registry.js"; import { createProcessSessionFixture } from "./bash-process-registry.test-helpers.js"; import { resetProcessRegistryForTests } from "./bash-process-registry.test-support.js"; +import { createSessionSlug } from "./session-slug.js"; const randomMocks = vi.hoisted(() => ({ generateSecureInt: vi.fn(() => 0), @@ -370,11 +371,11 @@ describe("bash process registry", () => { addSession(session); markBackgrounded(session); deleteSession(session.id); - expect(createSessionSlug()).toBe("amber-atlas-2"); + expect(createSessionSlug(isProcessSessionIdTaken)).toBe("amber-atlas-2"); session.backgrounded = false; markExited(session, 0, null, "completed"); - expect(createSessionSlug()).toBe("amber-atlas"); + expect(createSessionSlug(isProcessSessionIdTaken)).toBe("amber-atlas"); }); it("clears background activity in the test reset", () => { diff --git a/src/agents/bash-process-registry.ts b/src/agents/bash-process-registry.ts index e0a15591b115..dc561985a7e2 100644 --- a/src/agents/bash-process-registry.ts +++ b/src/agents/bash-process-registry.ts @@ -9,7 +9,6 @@ import type { EventSessionRoutingPolicy } from "../infra/event-session-routing.j import type { TerminationReason } from "../process/supervisor/types.js"; import type { DeliveryContext } from "../utils/delivery-context.types.js"; import { readEnvInt } from "./bash-tools.shared.js"; -import { createSessionSlug as createSessionSlugId } from "./session-slug.js"; const DEFAULT_JOB_TTL_MS = 30 * 60 * 1000; // 30 minutes const MIN_JOB_TTL_MS = 60 * 1000; // 1 minute @@ -132,17 +131,13 @@ let finishedSessionOutputChars = 0; let sweeper: NodeJS.Timeout | null = null; -function isSessionIdTaken(id: string) { +/** Return whether a process session id is live, retained, or reserved for notification. */ +export function isProcessSessionIdTaken(id: string): boolean { return ( runningSessions.has(id) || finishedSessions.has(id) || activeBackgroundExecSessionIds.has(id) ); } -/** Creates a unique short session id that avoids running and retained sessions. */ -export function createSessionSlug(): string { - return createSessionSlugId(isSessionIdTaken); -} - /** Adds a running session and starts retention sweeping if needed. */ export function addSession(session: ProcessSession) { runningSessions.set(session.id, session); diff --git a/src/agents/bash-tools.exec-runtime.test.ts b/src/agents/bash-tools.exec-runtime.test.ts index b4e6f63d9af3..e0857961f4e8 100644 --- a/src/agents/bash-tools.exec-runtime.test.ts +++ b/src/agents/bash-tools.exec-runtime.test.ts @@ -193,8 +193,9 @@ describe("runExecProcess cursor tracking", () => { describe("sandbox exec preparation failures", () => { it("settles the registered session once when buildExecSpec rejects", async () => { const registry = await import("./bash-process-registry.js"); + const sessionSlugs = await import("./session-slug.js"); const sessionId = "sandbox-preparation-failure"; - const sessionSlug = vi.spyOn(registry, "createSessionSlug").mockReturnValue(sessionId); + const sessionSlug = vi.spyOn(sessionSlugs, "createSessionSlug").mockReturnValue(sessionId); const preparation = createDeferred>>>(); const finalizeExec = vi.fn>(async () => {}); diff --git a/src/agents/bash-tools.exec-runtime.ts b/src/agents/bash-tools.exec-runtime.ts index 8230006697ba..40df2a7dc2cf 100644 --- a/src/agents/bash-tools.exec-runtime.ts +++ b/src/agents/bash-tools.exec-runtime.ts @@ -43,7 +43,7 @@ import { resolveSafeTimeoutDelayMs } from "../utils/timer-delay.js"; import { addSession, appendOutput, - createSessionSlug, + isProcessSessionIdTaken, markExited, recordNotifyOnExitRemoval, tail, @@ -60,6 +60,7 @@ import { readEnvInt, } from "./bash-tools.shared.js"; import { buildCursorPositionResponse, stripDsrRequests } from "./pty-dsr.js"; +import { createSessionSlug } from "./session-slug.js"; import { maybeWrapCommandWithShellSnapshot } from "./shell-snapshot.js"; import { createStreamingBinaryOutputSanitizer, getShellConfig } from "./shell-utils.js"; @@ -639,7 +640,7 @@ export async function runExecProcess(opts: { onSettledBeforeNotify?: (outcome: ExecProcessOutcome) => void; }): Promise { const startedAt = Date.now(); - const sessionId = createSessionSlug(); + const sessionId = createSessionSlug(isProcessSessionIdTaken); const execCommand = opts.execCommand ?? opts.command; const diagnosticTarget = opts.sandbox ? "sandbox" : "host"; const supervisor = getProcessSupervisor(); diff --git a/src/cli/channels-list-catalog-row-discovery.test.ts b/src/cli/channels-list-catalog-row-discovery.test.ts index 6c08828f3a9c..7f63879bba97 100644 --- a/src/cli/channels-list-catalog-row-discovery.test.ts +++ b/src/cli/channels-list-catalog-row-discovery.test.ts @@ -38,7 +38,7 @@ vi.mock("./command-execution-startup.js", () => ({ vi.mock("../commands/channels/shared.js", () => ({ formatChannelAccountLabel: vi.fn(), - requireValidConfig: vi.fn(async () => testState.config), + requireValidChannelConfig: vi.fn(async () => testState.config), })); vi.mock("../commands/channel-setup/trusted-catalog.js", () => ({ diff --git a/src/cli/channels-list-route-cold-imports.test.ts b/src/cli/channels-list-route-cold-imports.test.ts index a1fecb7b043e..a0266ff592cc 100644 --- a/src/cli/channels-list-route-cold-imports.test.ts +++ b/src/cli/channels-list-route-cold-imports.test.ts @@ -24,7 +24,7 @@ vi.mock("./command-execution-startup.js", () => ({ vi.mock("../commands/channels/shared.js", () => ({ formatChannelAccountLabel: vi.fn(), - requireValidConfig: vi.fn(async () => testState.config), + requireValidChannelConfig: vi.fn(async () => testState.config), })); vi.mock("../commands/channel-setup/trusted-catalog.js", () => ({ diff --git a/src/cli/daemon-cli/restart-health.ts b/src/cli/daemon-cli/restart-health.ts index 9f4bf63965d6..96911de5c6a4 100644 --- a/src/cli/daemon-cli/restart-health.ts +++ b/src/cli/daemon-cli/restart-health.ts @@ -38,7 +38,7 @@ export type { GatewayRestartSnapshot, GatewayRestartWaitOutcome, } from "./restart-health.types.js"; -export { terminateStaleGatewayPids } from "./restart-stale-pids.js"; +export { terminateStaleGatewayPids } from "../../infra/restart-stale-pids.js"; const STARTUP_MIGRATION_ACTIVITY_POLL_MS = 5_000; const STOPPED_FREE_EARLY_EXIT_GRACE_MS = 10_000; diff --git a/src/cli/daemon-cli/restart-stale-pids.ts b/src/cli/daemon-cli/restart-stale-pids.ts deleted file mode 100644 index 3843c2e73267..000000000000 --- a/src/cli/daemon-cli/restart-stale-pids.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { killProcessTree } from "../../process/kill-tree.js"; -import { sleep } from "../../utils.js"; - -export async function terminateStaleGatewayPids(pids: number[]): Promise { - const targets = Array.from( - new Set(pids.filter((pid): pid is number => Number.isFinite(pid) && pid > 0)), - ); - for (const pid of targets) { - killProcessTree(pid, { graceMs: 300 }); - } - if (targets.length > 0) { - await sleep(500); - } - return targets; -} diff --git a/src/commands/agents.bind.test-support.ts b/src/commands/agents.bind.test-support.ts index ecd00cec9702..daadadd96b9d 100644 --- a/src/commands/agents.bind.test-support.ts +++ b/src/commands/agents.bind.test-support.ts @@ -34,8 +34,12 @@ vi.mock("../config/config.js", () => ({ replaceConfigFile: (...args: unknown[]) => replaceConfigFileMock(...args), })); +vi.mock("./agents.command-shared.js", () => ({ + createQuietRuntime: (runtime: T) => runtime, +})); + vi.mock("./config-validation.js", () => ({ - requireValidConfigSnapshot: async (_runtime: unknown, opts?: unknown) => { + requireValidConfig: async (_runtime: unknown, opts?: unknown) => { const snapshot = (await readConfigFileSnapshotMock(opts)) as | { config?: OpenClawConfig; sourceConfig?: OpenClawConfig } | undefined; diff --git a/src/commands/agents.commands.bind.ts b/src/commands/agents.commands.bind.ts index 370dc88d90fb..a7fee3587dd9 100644 --- a/src/commands/agents.commands.bind.ts +++ b/src/commands/agents.commands.bind.ts @@ -11,7 +11,7 @@ import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js"; import { defaultRuntime } from "../runtime.js"; import { createLazyImportLoader } from "../shared/lazy-promise.js"; import { describeBinding } from "./agents.binding-format.js"; -import { requireValidConfigFileSnapshot, requireValidConfigSnapshot } from "./config-validation.js"; +import { requireValidConfig, requireValidConfigFileSnapshot } from "./config-validation.js"; type AgentBindingsModule = typeof import("./agents.bindings.js"); @@ -42,7 +42,7 @@ function loadAgentBindingsModule(): Promise { } function resolveAgentId( - cfg: Awaited>, + cfg: Awaited>, agentInput: string | undefined, params?: { fallbackToDefault?: boolean }, ): string | null { @@ -58,10 +58,7 @@ function resolveAgentId( return null; } -function hasAgent( - cfg: Awaited>, - agentId: string, -): boolean { +function hasAgent(cfg: Awaited>, agentId: string): boolean { if (!cfg) { return false; } @@ -78,7 +75,7 @@ function formatBindingOwnerLine(binding: AgentRouteBinding): string { } function resolveTargetAgentIdOrExit(params: { - cfg: Awaited>; + cfg: Awaited>; runtime: RuntimeEnv; agentInput: string | undefined; }): string | null { @@ -112,7 +109,7 @@ function formatBindingConflicts( async function resolveParsedBindingsOrExit(params: { runtime: RuntimeEnv; - cfg: NonNullable>>; + cfg: NonNullable>>; agentId: string; bindValues: string[] | undefined; emptyMessage: string; @@ -157,7 +154,7 @@ async function resolveConfigAndTargetAgentIdOrExit(params: { runtime: RuntimeEnv; agentInput: string | undefined; }): Promise<{ - cfg: NonNullable>>; + cfg: NonNullable>>; agentId: string; baseHash?: string; } | null> { @@ -182,7 +179,7 @@ export async function agentsBindingsCommand( opts: AgentsBindingsListOptions, runtime: RuntimeEnv = defaultRuntime, ) { - const cfg = await requireValidConfigSnapshot(runtime, { skipPluginValidation: true }); + const cfg = await requireValidConfig(runtime, { skipPluginValidation: true }); if (!cfg) { return; } diff --git a/src/commands/agents.commands.list.test.ts b/src/commands/agents.commands.list.test.ts index 0f1c90ed2ed5..0b6766bf9865 100644 --- a/src/commands/agents.commands.list.test.ts +++ b/src/commands/agents.commands.list.test.ts @@ -33,7 +33,7 @@ const { })); vi.mock("./config-validation.js", () => ({ - requireValidConfigSnapshot: requireValidConfigMock, + requireValidConfig: requireValidConfigMock, })); vi.mock("./agents.providers.js", () => ({ diff --git a/src/commands/agents.commands.list.ts b/src/commands/agents.commands.list.ts index 642c50fdd6e4..e76fbfd04b52 100644 --- a/src/commands/agents.commands.list.ts +++ b/src/commands/agents.commands.list.ts @@ -15,7 +15,7 @@ import { listProvidersForAgent, summarizeBindings, } from "./agents.providers.js"; -import { requireValidConfigSnapshot } from "./config-validation.js"; +import { requireValidConfig } from "./config-validation.js"; type AgentsListOptions = { json?: boolean; @@ -79,7 +79,7 @@ export async function agentsListCommand( opts: AgentsListOptions, runtime: RuntimeEnv = defaultRuntime, ) { - const cfg = await requireValidConfigSnapshot(runtime); + const cfg = await requireValidConfig(runtime); if (!cfg) { return; } diff --git a/src/commands/channels.status.command-flow.test.ts b/src/commands/channels.status.command-flow.test.ts index 1fdef8abadd1..cdb4bb4394f5 100644 --- a/src/commands/channels.status.command-flow.test.ts +++ b/src/commands/channels.status.command-flow.test.ts @@ -11,7 +11,7 @@ const mocks = vi.hoisted(() => ({ callGateway: vi.fn(), resolveCommandConfigWithSecrets: vi.fn(), readConfigFileSnapshot: vi.fn(async () => ({ path: "/tmp/openclaw.json" })), - requireValidConfigSnapshot: vi.fn(), + requireValidConfig: vi.fn(), listChannelPlugins: vi.fn(), listConfiguredAnnounceChannelIdsForConfig: vi.fn((_params: unknown) => ["discord"]), missingOfficialExternalChannels: new Set(), @@ -39,6 +39,10 @@ vi.mock("../config/config.js", () => ({ readConfigFileSnapshot: () => mocks.readConfigFileSnapshot(), })); +vi.mock("./config-validation.js", () => ({ + requireValidConfig: (runtime: unknown) => mocks.requireValidConfig(runtime), +})); + vi.mock("../plugins/channel-plugin-ids.js", () => ({ listExplicitConfiguredChannelIdsForConfig: (config: { channels?: Record }) => Object.keys(config.channels ?? {}), @@ -73,7 +77,6 @@ vi.mock("../plugins/official-external-plugin-repair-hints.js", () => ({ })); vi.mock("./channels/shared.js", () => ({ - requireValidConfigSnapshot: (runtime: unknown) => mocks.requireValidConfigSnapshot(runtime), formatChannelAccountLabel: ({ channel, accountId, @@ -216,7 +219,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { mocks.callGateway.mockReset(); mocks.resolveCommandConfigWithSecrets.mockReset(); mocks.readConfigFileSnapshot.mockClear(); - mocks.requireValidConfigSnapshot.mockReset(); + mocks.requireValidConfig.mockReset(); mocks.listChannelPlugins.mockReset(); mocks.missingOfficialExternalChannels.clear(); mocks.repairHintChannelIdCalls.length = 0; @@ -254,7 +257,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("keeps read-only fallback output when SecretRefs are unresolved", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); - mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} }); + mocks.requireValidConfig.mockResolvedValue({ secretResolved: false, channels: {} }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: { secretResolved: false, channels: {} }, effectiveConfig: { secretResolved: false, channels: {} }, @@ -285,7 +288,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { mocks.callGateway.mockRejectedValue( new GatewaySecretRefUnavailableError("gateway.auth.password"), ); - mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} }); + mocks.requireValidConfig.mockResolvedValue({ secretResolved: false, channels: {} }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: { secretResolved: false, channels: {} }, effectiveConfig: { secretResolved: false, channels: {} }, @@ -306,7 +309,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("prefers resolved snapshots when command-local SecretRef resolution succeeds", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); - mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} }); + mocks.requireValidConfig.mockResolvedValue({ secretResolved: false, channels: {} }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: { secretResolved: true, channels: {} }, effectiveConfig: { secretResolved: true, channels: {} }, @@ -325,7 +328,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("shows missing official external plugin repair hints in config-only output", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); - mocks.requireValidConfigSnapshot.mockResolvedValue({ + mocks.requireValidConfig.mockResolvedValue({ channels: { feishu: { appId: "cli_xxx" } }, }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ @@ -349,7 +352,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("resolves config-only repair hints only for the requested channel", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); const config = { channels: { feishu: { appId: "cli_xxx" }, matrix: { enabled: true } } }; - mocks.requireValidConfigSnapshot.mockResolvedValue(config); + mocks.requireValidConfig.mockResolvedValue(config); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: config, effectiveConfig: config, @@ -370,7 +373,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { const config = { channels: { discord: { enabled: true }, feishu: { appId: "cli_xxx" } }, }; - mocks.requireValidConfigSnapshot.mockResolvedValue(config); + mocks.requireValidConfig.mockResolvedValue(config); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: config, effectiveConfig: config, @@ -395,7 +398,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { ].join("\n"), ), ); - mocks.requireValidConfigSnapshot.mockResolvedValue({ secretResolved: false, channels: {} }); + mocks.requireValidConfig.mockResolvedValue({ secretResolved: false, channels: {} }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: { secretResolved: true, channels: {} }, effectiveConfig: { secretResolved: true, channels: {} }, @@ -433,7 +436,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("treats all as no filter in JSON config-only fallback", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); - mocks.requireValidConfigSnapshot.mockResolvedValue({ + mocks.requireValidConfig.mockResolvedValue({ channels: { clickclack: { enabled: true } }, }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ @@ -454,7 +457,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { it("filters explicitly configured channels in JSON config-only fallback", async () => { mocks.callGateway.mockRejectedValue(new Error("gateway closed")); - mocks.requireValidConfigSnapshot.mockResolvedValue({ + mocks.requireValidConfig.mockResolvedValue({ channels: { clickclack: { enabled: true }, telegram: { enabled: true } }, }); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ @@ -486,6 +489,6 @@ describe("channelsStatusCommand SecretRef fallback flow", () => { ); expect(mocks.callGateway).not.toHaveBeenCalled(); - expect(mocks.requireValidConfigSnapshot).not.toHaveBeenCalled(); + expect(mocks.requireValidConfig).not.toHaveBeenCalled(); }); }); diff --git a/src/commands/channels.status.external-env.test.ts b/src/commands/channels.status.external-env.test.ts index 039d127327ff..53c9953fc77f 100644 --- a/src/commands/channels.status.external-env.test.ts +++ b/src/commands/channels.status.external-env.test.ts @@ -17,7 +17,7 @@ import { createCapturingTestRuntime } from "./test-runtime-config-helpers.js"; const mocks = vi.hoisted(() => ({ callGateway: vi.fn(), readConfigFileSnapshot: vi.fn(async () => ({ path: "/tmp/openclaw.json" })), - requireValidConfigSnapshot: vi.fn(), + requireValidConfig: vi.fn(), resolveCommandConfigWithSecrets: vi.fn(), })); @@ -29,12 +29,15 @@ vi.mock("../config/config.js", () => ({ readConfigFileSnapshot: () => mocks.readConfigFileSnapshot(), })); +vi.mock("./config-validation.js", () => ({ + requireValidConfig: (runtime: unknown) => mocks.requireValidConfig(runtime), +})); + vi.mock("../cli/command-config-resolution.js", () => ({ resolveCommandConfigWithSecrets: (opts: unknown) => mocks.resolveCommandConfigWithSecrets(opts), })); vi.mock("./channels/shared.js", () => ({ - requireValidConfigSnapshot: (runtime: unknown) => mocks.requireValidConfigSnapshot(runtime), formatChannelAccountLabel: ({ channel, accountId }: { channel: string; accountId: string }) => `${channel} ${accountId}`, appendBaseUrlBit: () => undefined, @@ -97,7 +100,7 @@ describe("channelsStatusCommand external env-only channel fallback", () => { mocks.callGateway.mockReset(); mocks.callGateway.mockRejectedValue(new Error("gateway closed")); mocks.readConfigFileSnapshot.mockClear(); - mocks.requireValidConfigSnapshot.mockReset(); + mocks.requireValidConfig.mockReset(); mocks.resolveCommandConfigWithSecrets.mockReset(); }); @@ -113,7 +116,7 @@ describe("channelsStatusCommand external env-only channel fallback", () => { allow: ["external-env-channel-plugin"], }, } as OpenClawConfig; - mocks.requireValidConfigSnapshot.mockResolvedValue(config); + mocks.requireValidConfig.mockResolvedValue(config); mocks.resolveCommandConfigWithSecrets.mockResolvedValue({ resolvedConfig: config, effectiveConfig: config, diff --git a/src/commands/channels/capabilities.test.ts b/src/commands/channels/capabilities.test.ts index 498d0865b011..d3c2553996fa 100644 --- a/src/commands/channels/capabilities.test.ts +++ b/src/commands/channels/capabilities.test.ts @@ -21,7 +21,7 @@ vi.mock("./shared.js", async () => { const actual = await vi.importActual("./shared.js"); return { ...actual, - requireValidConfig: vi.fn(async () => ({ channels: {} })), + requireValidChannelConfig: vi.fn(async () => ({ channels: {} })), formatChannelAccountLabel: vi.fn( ({ channel, accountId }: { channel: string; accountId: string }) => `${channel}:${accountId}`, ), diff --git a/src/commands/channels/capabilities.ts b/src/commands/channels/capabilities.ts index e538f17419bd..1860539d26af 100644 --- a/src/commands/channels/capabilities.ts +++ b/src/commands/channels/capabilities.ts @@ -26,7 +26,7 @@ import { formatErrorMessage } from "../../infra/errors.js"; import { defaultRuntime, type RuntimeEnv, writeRuntimeJson } from "../../runtime.js"; import { resolveInstallableChannelPlugin } from "../channel-setup/channel-plugin-resolution.js"; import { persistResolvedChannelPluginConfig } from "./plugin-config-persistence.js"; -import { formatChannelAccountLabel, requireValidConfig } from "./shared.js"; +import { formatChannelAccountLabel, requireValidChannelConfig } from "./shared.js"; export type ChannelsCapabilitiesOptions = { channel?: string; @@ -303,7 +303,7 @@ export async function channelsCapabilitiesCommand( runtime: RuntimeEnv = defaultRuntime, ) { const sourceSnapshotPromise = readConfigFileSnapshot().catch(() => null); - const loadedCfg = await requireValidConfig(runtime); + const loadedCfg = await requireValidChannelConfig(runtime); if (!loadedCfg) { return; } diff --git a/src/commands/channels/list.ts b/src/commands/channels/list.ts index 415e97e7b544..7060b8d262b3 100644 --- a/src/commands/channels/list.ts +++ b/src/commands/channels/list.ts @@ -19,7 +19,7 @@ import { resolvePluginMetadataSnapshot } from "../../plugins/plugin-metadata-sna import { defaultRuntime, type RuntimeEnv, writeRuntimeJson } from "../../runtime.js"; import { listManifestInstalledChannelIds } from "../channel-setup/discovery.js"; import { listTrustedChannelPluginCatalogEntries } from "../channel-setup/trusted-catalog.js"; -import { formatChannelAccountLabel, requireValidConfig } from "./shared.js"; +import { formatChannelAccountLabel, requireValidChannelConfig } from "./shared.js"; export type ChannelsListOptions = { json?: boolean; @@ -148,7 +148,7 @@ export async function channelsListCommand( opts: ChannelsListOptions, runtime: RuntimeEnv = defaultRuntime, ) { - const cfg = await requireValidConfig(runtime, { skipPluginValidation: true }); + const cfg = await requireValidChannelConfig(runtime, { skipPluginValidation: true }); if (!cfg) { return; } diff --git a/src/commands/channels/shared.ts b/src/commands/channels/shared.ts index 08ba333e38c3..892634133a7c 100644 --- a/src/commands/channels/shared.ts +++ b/src/commands/channels/shared.ts @@ -7,18 +7,14 @@ import { getChannelsCommandSecretTargetIds } from "../../cli/command-secret-targ import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js"; import { defaultRuntime, type RuntimeEnv } from "../../runtime.js"; -import { - requireValidConfigFileSnapshot, - requireValidConfigSnapshot, -} from "../config-validation.js"; +import { requireValidConfig, requireValidConfigFileSnapshot } from "../config-validation.js"; export type ChatChannel = ChannelId; -export { requireValidConfigSnapshot }; export { requireValidConfigFileSnapshot }; /** Load valid channel command config with read-only secret resolution applied. */ -export async function requireValidConfig( +export async function requireValidChannelConfig( runtime: RuntimeEnv = defaultRuntime, secretResolution?: { commandName?: string; @@ -26,7 +22,7 @@ export async function requireValidConfig( skipPluginValidation?: boolean; }, ): Promise { - const cfg = await requireValidConfigSnapshot( + const cfg = await requireValidConfig( runtime, secretResolution?.skipPluginValidation ? { skipPluginValidation: true } : undefined, ); diff --git a/src/commands/channels/status.runtime.ts b/src/commands/channels/status.runtime.ts index f65ba5e233fb..6abc02637c34 100644 --- a/src/commands/channels/status.runtime.ts +++ b/src/commands/channels/status.runtime.ts @@ -13,6 +13,7 @@ import { formatTimeAgo } from "../../infra/format-time/format-relative.ts"; import { formatPhoneNumberForCli } from "../../infra/phone-number-presentation.js"; import { listConfiguredAnnounceChannelIdsForConfig } from "../../plugins/channel-plugin-ids.js"; import { type RuntimeEnv, writeRuntimeJson } from "../../runtime.js"; +import { requireValidConfig } from "../config-validation.js"; import { appendBaseUrlBit, appendEnabledConfiguredLinkedBits, @@ -20,7 +21,6 @@ import { appendTokenSourceBits, buildChannelAccountLine, type ChatChannel, - requireValidConfigSnapshot, } from "./shared.js"; import { formatConfigChannelsStatusLines } from "./status-config-format.js"; import type { ChannelsStatusOptions } from "./status.js"; @@ -217,7 +217,7 @@ export async function renderChannelsStatusFallback(params: { runtime.error( `${gatewayAuthUnavailable ? "Gateway auth unavailable" : "Gateway not reachable"}: ${safeError}`, ); - const cfg = await requireValidConfigSnapshot(runtime); + const cfg = await requireValidConfig(runtime); if (!cfg) { return; } diff --git a/src/commands/config-validation.test.ts b/src/commands/config-validation.test.ts index 9177e3f27598..1177100ee78d 100644 --- a/src/commands/config-validation.test.ts +++ b/src/commands/config-validation.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import type { PluginCompatibilityNotice } from "../plugins/status.js"; import { createCompatibilityNotice } from "../plugins/status.test-fixtures.js"; -import { requireValidConfigSnapshot } from "./config-validation.js"; +import { requireValidConfig } from "./config-validation.js"; const { readConfigFileSnapshot, buildPluginCompatibilitySnapshotNotices } = vi.hoisted(() => ({ readConfigFileSnapshot: vi.fn(), @@ -21,7 +21,7 @@ vi.mock("../plugins/status.js", () => ({ `${notice.pluginId} ${notice.message}`, })); -describe("requireValidConfigSnapshot", () => { +describe("requireValidConfig", () => { beforeEach(() => { vi.clearAllMocks(); }); @@ -62,7 +62,7 @@ describe("requireValidConfigSnapshot", () => { createValidSnapshot(); const runtime = createRuntime(); - const config = await requireValidConfigSnapshot(runtime); + const config = await requireValidConfig(runtime); expect(config).toEqual({ plugins: {} }); expect(runtime.error).not.toHaveBeenCalled(); @@ -75,9 +75,9 @@ describe("requireValidConfigSnapshot", () => { createValidSnapshot(); const runtime = createRuntime(); - await expect( - requireValidConfigSnapshot(runtime, { skipPluginValidation: true }), - ).resolves.toEqual({ plugins: {} }); + await expect(requireValidConfig(runtime, { skipPluginValidation: true })).resolves.toEqual({ + plugins: {}, + }); expect(readConfigFileSnapshot).toHaveBeenCalledWith({ skipPluginValidation: true }); }); @@ -86,7 +86,7 @@ describe("requireValidConfigSnapshot", () => { createValidSnapshot(); const runtime = createRuntime(); - const config = await requireValidConfigSnapshot(runtime, { + const config = await requireValidConfig(runtime, { includeCompatibilityAdvisory: true, }); @@ -111,7 +111,7 @@ describe("requireValidConfigSnapshot", () => { }); const runtime = createRuntime(); - const config = await requireValidConfigSnapshot(runtime, { + const config = await requireValidConfig(runtime, { includeCompatibilityAdvisory: true, }); @@ -143,7 +143,7 @@ describe("requireValidConfigSnapshot", () => { }); const runtime = createRuntime(); - const config = await requireValidConfigSnapshot(runtime); + const config = await requireValidConfig(runtime); expect(config).toBeNull(); expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("plugin not found")); @@ -164,7 +164,7 @@ describe("requireValidConfigSnapshot", () => { }); const runtime = createRuntime(); - const config = await requireValidConfigSnapshot(runtime); + const config = await requireValidConfig(runtime); expect(config).toBeNull(); expect(runtime.error).toHaveBeenCalledWith("Fix: openclaw doctor --fix"); diff --git a/src/commands/config-validation.ts b/src/commands/config-validation.ts index e8161c6df03c..b69002da6920 100644 --- a/src/commands/config-validation.ts +++ b/src/commands/config-validation.ts @@ -57,7 +57,7 @@ export async function requireValidConfigFileSnapshot( } /** Read and return a valid OpenClaw config, or null after reporting validation errors. */ -export async function requireValidConfigSnapshot( +export async function requireValidConfig( runtime: RuntimeEnv, opts?: { includeCompatibilityAdvisory?: boolean; skipPluginValidation?: boolean }, ): Promise { diff --git a/src/infra/restart-stale-pids.ts b/src/infra/restart-stale-pids.ts index d6df34493658..5d67f7ad20a1 100644 --- a/src/infra/restart-stale-pids.ts +++ b/src/infra/restart-stale-pids.ts @@ -6,6 +6,8 @@ import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/st import { uniqueValues } from "@openclaw/normalization-core/string-normalization"; import { resolveGatewayPort } from "../config/paths.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; +import { killProcessTree } from "../process/kill-tree.js"; +import { sleep } from "../utils/sleep.js"; import { formatErrorMessage, hasErrnoCode } from "./errors.js"; import { isGatewayArgv, parseProcCmdline } from "./gateway-process-argv.js"; import { parseStrictPositiveInteger } from "./parse-finite-number.js"; @@ -56,6 +58,20 @@ const sleepSyncOverride: ((ms: number) => void) | null = null; const dateNowOverride: (() => number) | null = null; const parentPidOverride: (() => number) | null = null; +/** Terminate externally discovered stale gateway processes and allow cleanup to settle. */ +export async function terminateStaleGatewayPids(pids: number[]): Promise { + const targets = Array.from( + new Set(pids.filter((pid): pid is number => Number.isFinite(pid) && pid > 0)), + ); + for (const pid of targets) { + killProcessTree(pid, { graceMs: 300 }); + } + if (targets.length > 0) { + await sleep(500); + } + return targets; +} + function getTimeMs(): number { return dateNowOverride ? dateNowOverride() : Date.now(); } diff --git a/src/tui/tui-pty-harness-assertion-test-support.ts b/src/tui/tui-pty-harness-assertion-test-support.ts index 9997a0ee141d..dd08c9d88cf8 100644 --- a/src/tui/tui-pty-harness-assertion-test-support.ts +++ b/src/tui/tui-pty-harness-assertion-test-support.ts @@ -3,10 +3,10 @@ import { readFile } from "node:fs/promises"; import { expect } from "vitest"; import * as ansiSequences from "../../packages/terminal-core/src/ansi-sequences.js"; import * as ansi from "../../packages/terminal-core/src/ansi.js"; +import { sleep } from "../utils/sleep.js"; import { formatTuiFooter, sanitizeRenderableLine } from "./tui-formatters.js"; import { PtyTestScreen, - sleep, type PtyRun, type PtyTerminalDimensions, waitFor, diff --git a/src/tui/tui-pty-harness.e2e.test.ts b/src/tui/tui-pty-harness.e2e.test.ts index 94c3ab0569d7..1609439d53e5 100644 --- a/src/tui/tui-pty-harness.e2e.test.ts +++ b/src/tui/tui-pty-harness.e2e.test.ts @@ -3,6 +3,7 @@ import { mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { sleep } from "../utils/sleep.js"; import { exerciseTuiCommandSurface } from "./tui-pty-command-surfaces-test-support.js"; import { approveWorkspaceSkill, @@ -22,7 +23,7 @@ import { streamingPrefixFrame, toolFrame, } from "./tui-pty-rendering-test-support.js"; -import { sleep, startPty, type PtyRun } from "./tui-pty-test-support.js"; +import { startPty, type PtyRun } from "./tui-pty-test-support.js"; const activeRuns: PtyRun[] = []; const STARTUP_TIMEOUT_MS = 20_000; diff --git a/src/tui/tui-pty-local.e2e.test.ts b/src/tui/tui-pty-local.e2e.test.ts index e1d7b77cba24..2183b49fe846 100644 --- a/src/tui/tui-pty-local.e2e.test.ts +++ b/src/tui/tui-pty-local.e2e.test.ts @@ -17,6 +17,7 @@ import type { ModelProviderConfig } from "../config/types.models.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; import { connectGatewayClient } from "../gateway/test-helpers.e2e.js"; import { runExec } from "../process/exec.js"; +import { sleep } from "../utils/sleep.js"; import { GatewayChatClient } from "./gateway-chat.js"; import { extractTextFromMessage } from "./tui-formatters.js"; import { @@ -32,7 +33,7 @@ import { registerIdempotentCleanup, waitForOutputAfter, } from "./tui-pty-local-test-support.js"; -import { sleep, startPty, waitFor, type PtyRun } from "./tui-pty-test-support.js"; +import { startPty, waitFor, type PtyRun } from "./tui-pty-test-support.js"; type MockModelServer = { baseUrl: string; diff --git a/src/tui/tui-pty-test-support.ts b/src/tui/tui-pty-test-support.ts index e15739d9bf34..4f5f6707a42b 100644 --- a/src/tui/tui-pty-test-support.ts +++ b/src/tui/tui-pty-test-support.ts @@ -6,6 +6,7 @@ import { AnsiSequenceStripper } from "../../packages/terminal-core/src/ansi-sequ import * as ansi from "../../packages/terminal-core/src/ansi.js"; import { toErrorObject } from "../infra/errors.js"; import { signalProcessTree } from "../process/kill-tree.js"; +import { sleep } from "../utils/sleep.js"; // Shared PTY harness utilities for fake-backend and local TUI smoke tests. type PtyExitEvent = Parameters[0]>[0]; @@ -224,13 +225,6 @@ export function waitFor(params: { }); } -/** Async sleep used to simulate slower PTY typing. */ -export function sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - function readPositiveIntegerEnv(name: string, env: NodeJS.ProcessEnv = process.env): number | null { const value = Number.parseInt(env[name] ?? "", 10); return Number.isFinite(value) && value > 0 ? value : null;