refactor: consolidate duplicate helpers (#121431)

* refactor(agents): consolidate session slug creation

* refactor(commands): consolidate config validation

* refactor(infra): consolidate stale pid termination

* refactor(tui): reuse canonical sleep helper

* chore(scripts): burn resolved entries from collision baseline

* fix(refactor): preserve cross-platform helper contracts

* fix(plugin-sdk): keep approval helper private

* chore(scripts): burn resolved wrapper shadowing entry

* chore(scripts): refresh wrapper shadowing baseline

* test(agents): target canonical session slug helper

* chore(plugin-sdk): refresh API baseline
This commit is contained in:
Peter Steinberger
2026-08-10 15:57:24 -07:00
committed by GitHub
parent cef6e690d5
commit a770218518
29 changed files with 112 additions and 139 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":"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<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":"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<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":"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<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":"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<string>; };","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<void>; };","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<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":"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<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":"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<MeetingVoiceCallJoinResult>;","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<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":"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<MeetingRealtimeAudioEngineHandle>;","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<void>; }): Promise<MeetingRealtimeAudioEngineHandle>;","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<MeetingRealtimeAudioEngineHandle>;","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<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":"8345dc18050019a013d34a7653ed0d12e6178bcc18dfdb52f85a05a46bbd4e22","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":"27608aa6c6035520513bc6abeee9d6f32f55a30616f6d9c4c67f79eb2e882694","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":"4eaf1fc1a9108206f22d89e18f61a55a34c7270419bd533692cb6106b0491dff","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":"2ad141bbb02357b206458b7a56b85af8de8b0bd764ebc535b41352c767a826a3","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":"42723d088f7aacd0105697bace2776af0f0b6634c40183ad06a24f563ecca26f","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":"6f77c9bfb0db31396eddc4c4aa0b4cbccb88c4fbe44de1e3ecf7e067811d5ea6","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":"77aaebb98084205149391d11ef31ffa8a2f29a42271a5f0b47e97e101d581c8c","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":"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<PluginMetadataSnapshot, \"owners\" | \"manifestRegistry\" | \"byPluginId\">; }): 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<typeof resolvePluginProviders>[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<PluginMetadataSnapshot, \"owners\" | \"manifestRegistry\" | \"byPluginId\">; }): 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<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"}
@@ -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": [
@@ -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",
+4 -3
View File
@@ -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", () => {
+2 -7
View File
@@ -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);
+2 -1
View File
@@ -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<Awaited<ReturnType<NonNullable<BashSandboxConfig["buildExecSpec"]>>>>();
const finalizeExec = vi.fn<NonNullable<BashSandboxConfig["finalizeExec"]>>(async () => {});
+3 -2
View File
@@ -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<ExecProcessHandle> {
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();
@@ -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", () => ({
@@ -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", () => ({
+1 -1
View File
@@ -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;
-15
View File
@@ -1,15 +0,0 @@
import { killProcessTree } from "../../process/kill-tree.js";
import { sleep } from "../../utils.js";
export async function terminateStaleGatewayPids(pids: number[]): Promise<number[]> {
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;
}
+5 -1
View File
@@ -34,8 +34,12 @@ vi.mock("../config/config.js", () => ({
replaceConfigFile: (...args: unknown[]) => replaceConfigFileMock(...args),
}));
vi.mock("./agents.command-shared.js", () => ({
createQuietRuntime: <T>(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;
+7 -10
View File
@@ -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<AgentBindingsModule> {
}
function resolveAgentId(
cfg: Awaited<ReturnType<typeof requireValidConfigSnapshot>>,
cfg: Awaited<ReturnType<typeof requireValidConfig>>,
agentInput: string | undefined,
params?: { fallbackToDefault?: boolean },
): string | null {
@@ -58,10 +58,7 @@ function resolveAgentId(
return null;
}
function hasAgent(
cfg: Awaited<ReturnType<typeof requireValidConfigSnapshot>>,
agentId: string,
): boolean {
function hasAgent(cfg: Awaited<ReturnType<typeof requireValidConfig>>, agentId: string): boolean {
if (!cfg) {
return false;
}
@@ -78,7 +75,7 @@ function formatBindingOwnerLine(binding: AgentRouteBinding): string {
}
function resolveTargetAgentIdOrExit(params: {
cfg: Awaited<ReturnType<typeof requireValidConfigSnapshot>>;
cfg: Awaited<ReturnType<typeof requireValidConfig>>;
runtime: RuntimeEnv;
agentInput: string | undefined;
}): string | null {
@@ -112,7 +109,7 @@ function formatBindingConflicts(
async function resolveParsedBindingsOrExit(params: {
runtime: RuntimeEnv;
cfg: NonNullable<Awaited<ReturnType<typeof requireValidConfigSnapshot>>>;
cfg: NonNullable<Awaited<ReturnType<typeof requireValidConfig>>>;
agentId: string;
bindValues: string[] | undefined;
emptyMessage: string;
@@ -157,7 +154,7 @@ async function resolveConfigAndTargetAgentIdOrExit(params: {
runtime: RuntimeEnv;
agentInput: string | undefined;
}): Promise<{
cfg: NonNullable<Awaited<ReturnType<typeof requireValidConfigSnapshot>>>;
cfg: NonNullable<Awaited<ReturnType<typeof requireValidConfig>>>;
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;
}
+1 -1
View File
@@ -33,7 +33,7 @@ const {
}));
vi.mock("./config-validation.js", () => ({
requireValidConfigSnapshot: requireValidConfigMock,
requireValidConfig: requireValidConfigMock,
}));
vi.mock("./agents.providers.js", () => ({
+2 -2
View File
@@ -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;
}
@@ -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<string>(),
@@ -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<string, unknown> }) =>
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();
});
});
@@ -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,
+1 -1
View File
@@ -21,7 +21,7 @@ vi.mock("./shared.js", async () => {
const actual = await vi.importActual<typeof import("./shared.js")>("./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}`,
),
+2 -2
View File
@@ -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;
}
+2 -2
View File
@@ -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;
}
+3 -7
View File
@@ -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<OpenClawConfig | null> {
const cfg = await requireValidConfigSnapshot(
const cfg = await requireValidConfig(
runtime,
secretResolution?.skipPluginValidation ? { skipPluginValidation: true } : undefined,
);
+2 -2
View File
@@ -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;
}
+10 -10
View File
@@ -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");
+1 -1
View File
@@ -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<OpenClawConfig | null> {
+16
View File
@@ -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<number[]> {
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();
}
@@ -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,
+2 -1
View File
@@ -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;
+2 -1
View File
@@ -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;
+1 -7
View File
@@ -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<Parameters<IPty["onExit"]>[0]>[0];
@@ -224,13 +225,6 @@ export function waitFor<T>(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;