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