Download src/plugin-sdk/test-helpers/native-approval.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 14.4 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugin-sdk/test-helpers/native-approval.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/plugin-sdk/test-helpers/native-approval.ts
-
curl -L -o native-approval.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugin-sdk/test-helpers/native-approval.ts
14.4 kB
| import { expect } from "vitest"; | |
| import type { ChannelApprovalKind } from "../../infra/approval-types.js"; | |
| import type { ExecApprovalRequest } from "../../infra/exec-approvals.js"; | |
| import type { PluginApprovalRequest } from "../../infra/plugin-approvals.js"; | |
| import type { ChannelApprovalCapability, ChannelOutboundPayloadHint } from "../channel-contract.js"; | |
| import type { OpenClawConfig } from "../config-contracts.js"; | |
| import type { ReplyPayload } from "../reply-runtime.js"; | |
| type ApprovalTestConfig = { | |
| channel?: { | |
| enabled?: boolean; | |
| allowFrom?: string[]; | |
| defaultAccount?: string; | |
| accounts?: Record<string, { enabled?: boolean }>; | |
| }; | |
| approvals?: OpenClawConfig["approvals"]; | |
| }; | |
| type ApprovalConfigBuilder = (params?: ApprovalTestConfig) => OpenClawConfig; | |
| type ApprovalRequest = ExecApprovalRequest | PluginApprovalRequest; | |
| type ForwardingParams = Parameters< | |
| NonNullable< | |
| NonNullable<ChannelApprovalCapability["delivery"]>["shouldSuppressForwardingFallback"] | |
| > | |
| >[0]; | |
| export function createNativeApprovalTestFixture(params: { | |
| channel: string; | |
| capability: ChannelApprovalCapability; | |
| buildConfig: ApprovalConfigBuilder; | |
| }) { | |
| const { channel, capability, buildConfig } = params; | |
| const directTarget = "+15551230000"; | |
| function buildExecRequest( | |
| to = directTarget, | |
| overrides: Partial<ExecApprovalRequest["request"]> = {}, | |
| ): ExecApprovalRequest { | |
| return { | |
| id: "exec-1", | |
| request: { | |
| command: "echo hi", | |
| agentId: "main", | |
| turnSourceChannel: channel, | |
| turnSourceTo: to, | |
| turnSourceAccountId: "default", | |
| sessionKey: `agent:main:${channel}:${to}`, | |
| ...overrides, | |
| }, | |
| createdAtMs: 0, | |
| expiresAtMs: 1000, | |
| }; | |
| } | |
| function buildPluginRequest( | |
| to = directTarget, | |
| overrides: Partial<PluginApprovalRequest["request"]> = {}, | |
| ): PluginApprovalRequest { | |
| return { | |
| id: "plugin:approval-1", | |
| request: { | |
| title: "Plugin approval", | |
| description: "Allow plugin action", | |
| agentId: "main", | |
| turnSourceChannel: channel, | |
| turnSourceTo: to, | |
| turnSourceAccountId: "default", | |
| sessionKey: `agent:main:${channel}:${to}`, | |
| ...overrides, | |
| }, | |
| createdAtMs: 0, | |
| expiresAtMs: 1000, | |
| }; | |
| } | |
| function buildTargetModeConfig( | |
| approvalKind: "exec" | "plugin", | |
| targets: Array<{ channel: string; to: string; accountId?: string }>, | |
| options: { mode?: "targets" | "both"; channel?: ApprovalTestConfig["channel"] } = {}, | |
| ) { | |
| return buildConfig({ | |
| channel: options.channel, | |
| approvals: { [approvalKind]: { enabled: true, mode: options.mode ?? "targets", targets } }, | |
| }); | |
| } | |
| function getAvailability( | |
| cfg: OpenClawConfig, | |
| accountId = "default", | |
| approvalKind: ChannelApprovalKind = "exec", | |
| ) { | |
| return capability.getActionAvailabilityState?.({ | |
| cfg, | |
| accountId, | |
| action: "approve", | |
| approvalKind, | |
| }); | |
| } | |
| function describeDelivery( | |
| cfg: OpenClawConfig, | |
| request: ApprovalRequest, | |
| approvalKind: ChannelApprovalKind = "exec", | |
| ) { | |
| return capability.native?.describeDeliveryCapabilities({ | |
| cfg, | |
| accountId: "default", | |
| approvalKind, | |
| request, | |
| }); | |
| } | |
| function nativeShouldHandle(input: { | |
| cfg: OpenClawConfig; | |
| approvalKind: ChannelApprovalKind; | |
| request: ApprovalRequest; | |
| accountId?: string | null; | |
| }) { | |
| return capability.nativeRuntime?.availability.shouldHandle({ | |
| ...input, | |
| accountId: input.accountId ?? "default", | |
| context: {}, | |
| }); | |
| } | |
| function resolveExecOrigin(cfg: OpenClawConfig, request: ExecApprovalRequest) { | |
| return capability.native?.resolveOriginTarget?.({ | |
| cfg, | |
| accountId: "default", | |
| approvalKind: "exec", | |
| request, | |
| }); | |
| } | |
| function suppressForwardingFallback(input: ForwardingParams) { | |
| return capability.delivery?.shouldSuppressForwardingFallback?.(input); | |
| } | |
| function suppressTargetForwarding(cfg: OpenClawConfig, to: string, request = buildExecRequest()) { | |
| return suppressForwardingFallback({ | |
| cfg, | |
| approvalKind: "exec", | |
| target: { channel, to, source: "target" }, | |
| request, | |
| }); | |
| } | |
| return { | |
| buildConfig, | |
| buildExecRequest, | |
| buildPluginRequest, | |
| buildTargetModeConfig, | |
| describeDelivery, | |
| nativeShouldHandle, | |
| resolveExecOrigin, | |
| checks: { | |
| systemAgentEvents: () => { | |
| expect(capability.nativeRuntime?.eventKinds).toContain("system-agent"); | |
| }, | |
| disabledByDefault: () => { | |
| const cfg = buildConfig(); | |
| const execRequest = buildExecRequest(); | |
| const pluginRequest = buildPluginRequest(); | |
| expect(getAvailability(cfg)).toEqual({ kind: "disabled" }); | |
| expect(getAvailability(cfg, "default", "plugin")).toEqual({ kind: "disabled" }); | |
| expect(describeDelivery(cfg, execRequest)?.enabled).toBe(false); | |
| expect(nativeShouldHandle({ cfg, approvalKind: "exec", request: execRequest })).toBe(false); | |
| expect(nativeShouldHandle({ cfg, approvalKind: "plugin", request: pluginRequest })).toBe( | |
| false, | |
| ); | |
| }, | |
| sessionDelivery: () => { | |
| const cfg = buildConfig({ approvals: { exec: { enabled: true } } }); | |
| const request = buildExecRequest(); | |
| expect(describeDelivery(cfg, request)).toEqual({ | |
| enabled: true, | |
| preferredSurface: "origin", | |
| supportsOriginSurface: true, | |
| supportsApproverDmSurface: false, | |
| notifyOriginWhenDmOnly: true, | |
| }); | |
| expect(nativeShouldHandle({ cfg, approvalKind: "exec", request })).toBe(true); | |
| }, | |
| independentKinds: () => { | |
| const execOnly = buildConfig({ approvals: { exec: { enabled: true } } }); | |
| const pluginOnly = buildConfig({ approvals: { plugin: { enabled: true } } }); | |
| expect( | |
| nativeShouldHandle({ | |
| cfg: execOnly, | |
| approvalKind: "plugin", | |
| request: buildPluginRequest(), | |
| }), | |
| ).toBe(false); | |
| expect( | |
| nativeShouldHandle({ | |
| cfg: pluginOnly, | |
| approvalKind: "exec", | |
| request: buildExecRequest(), | |
| }), | |
| ).toBe(false); | |
| expect( | |
| nativeShouldHandle({ | |
| cfg: pluginOnly, | |
| approvalKind: "plugin", | |
| request: buildPluginRequest(), | |
| }), | |
| ).toBe(true); | |
| }, | |
| foreignOrigin: () => { | |
| const cfg = buildConfig({ approvals: { exec: { enabled: true } } }); | |
| const request = buildExecRequest("", { | |
| turnSourceChannel: "slack", | |
| turnSourceTo: "C123", | |
| sessionKey: "agent:main:slack:channel:c123", | |
| }); | |
| expect(nativeShouldHandle({ cfg, approvalKind: "exec", request })).toBe(false); | |
| expect(describeDelivery(cfg, request)?.enabled).toBe(false); | |
| }, | |
| targetMode: (cfg = buildTargetModeConfig("exec", [{ channel, to: directTarget }])) => { | |
| const request = buildExecRequest(); | |
| expect(getAvailability(cfg)).toEqual({ kind: "enabled" }); | |
| expect( | |
| capability.nativeRuntime?.availability.isConfigured({ | |
| cfg, | |
| accountId: "default", | |
| context: {}, | |
| }), | |
| ).toBe(false); | |
| expect(nativeShouldHandle({ cfg, approvalKind: "exec", request })).toBe(false); | |
| expect(describeDelivery(cfg, request)?.enabled).toBe(false); | |
| }, | |
| noMatchingTarget: () => { | |
| const cfg = buildTargetModeConfig("exec", [{ channel: "slack", to: "C123" }]); | |
| expect(getAvailability(cfg)).toEqual({ kind: "disabled" }); | |
| }, | |
| requestFilters: () => { | |
| const request = buildExecRequest(directTarget, { | |
| agentId: "main", | |
| sessionKey: `agent:main:${channel}:+15551230000`, | |
| }); | |
| const blockedByAgent = buildConfig({ | |
| approvals: { exec: { enabled: true, agentFilter: ["other"] } }, | |
| }); | |
| const blockedBySession = buildConfig({ | |
| approvals: { exec: { enabled: true, sessionFilter: ["telegram"] } }, | |
| }); | |
| expect(nativeShouldHandle({ cfg: blockedByAgent, approvalKind: "exec", request })).toBe( | |
| false, | |
| ); | |
| expect(nativeShouldHandle({ cfg: blockedBySession, approvalKind: "exec", request })).toBe( | |
| false, | |
| ); | |
| }, | |
| accountScopedTargets: () => { | |
| const cfg = buildTargetModeConfig( | |
| "exec", | |
| [{ channel, to: directTarget, accountId: "work" }], | |
| { channel: { accounts: { work: { enabled: true } } } }, | |
| ); | |
| expect(getAvailability(cfg)).toEqual({ kind: "disabled" }); | |
| expect(getAvailability(cfg, "work")).toEqual({ kind: "enabled" }); | |
| }, | |
| exactSessionTarget: () => { | |
| const cfg = buildConfig({ approvals: { exec: { enabled: true } } }); | |
| const request = buildExecRequest(); | |
| for (const [to, expected] of [ | |
| [directTarget, true], | |
| ["+15550000000", false], | |
| ] as const) { | |
| expect( | |
| suppressForwardingFallback({ | |
| cfg, | |
| approvalKind: "exec", | |
| target: { channel, to, accountId: "default", source: "session" }, | |
| request, | |
| }), | |
| ).toBe(expected); | |
| } | |
| }, | |
| targetOnlyFallback: () => { | |
| const cfg = buildTargetModeConfig("exec", [{ channel, to: "+15550000000" }]); | |
| expect(suppressTargetForwarding(cfg, "+15550000000")).toBe(false); | |
| }, | |
| unscopedBothTarget: () => { | |
| const cfg = buildTargetModeConfig("exec", [{ channel, to: directTarget }], { | |
| mode: "both", | |
| }); | |
| expect(suppressTargetForwarding(cfg, directTarget)).toBe(true); | |
| }, | |
| defaultAccountBothTarget: () => { | |
| const cfg = buildTargetModeConfig("exec", [{ channel, to: directTarget }], { | |
| mode: "both", | |
| channel: { | |
| defaultAccount: "work", | |
| accounts: { default: { enabled: true }, work: { enabled: true } }, | |
| }, | |
| }); | |
| expect( | |
| suppressTargetForwarding( | |
| cfg, | |
| directTarget, | |
| buildExecRequest(directTarget, { turnSourceAccountId: "work" }), | |
| ), | |
| ).toBe(true); | |
| }, | |
| }, | |
| }; | |
| } | |
| type LocalSuppressionParams = { | |
| cfg: OpenClawConfig; | |
| accountId?: string | null; | |
| payload: ReplyPayload; | |
| hint?: ChannelOutboundPayloadHint; | |
| }; | |
| export function createLocalApprovalPromptTestFixture(params: { | |
| channel: string; | |
| buildConfig: ApprovalConfigBuilder; | |
| suppress: (input: LocalSuppressionParams) => boolean; | |
| }) { | |
| const { channel, buildConfig } = params; | |
| const activeExecHint = { | |
| kind: "approval-pending", | |
| approvalKind: "exec", | |
| nativeRouteActive: true, | |
| } as const; | |
| function buildLocalApprovalPayload( | |
| input: { | |
| approvalKind?: ChannelApprovalKind; | |
| agentId?: string | null; | |
| sessionKey?: string | null; | |
| } = {}, | |
| ) { | |
| return { | |
| text: "Approval required.", | |
| channelData: { | |
| execApproval: { | |
| approvalId: input.approvalKind === "plugin" ? "plugin:approval-1" : "exec-1", | |
| approvalSlug: input.approvalKind === "plugin" ? "plugin:approval-1" : "exec-1", | |
| approvalKind: input.approvalKind ?? "exec", | |
| agentId: input.agentId, | |
| sessionKey: input.sessionKey, | |
| }, | |
| }, | |
| }; | |
| } | |
| function suppressLocalPrompt(input: LocalSuppressionParams) { | |
| return params.suppress({ ...input, hint: input.hint ?? activeExecHint }); | |
| } | |
| function suppressLocalSessionPrompt( | |
| cfg: OpenClawConfig, | |
| sessionKey: string, | |
| input: { accountId?: string; agentId?: string | null } = {}, | |
| ) { | |
| return suppressLocalPrompt({ | |
| cfg, | |
| accountId: input.accountId, | |
| payload: buildLocalApprovalPayload({ | |
| agentId: input.agentId === undefined ? "main" : input.agentId, | |
| sessionKey, | |
| }), | |
| }); | |
| } | |
| return { | |
| suppressLocalSessionPrompt, | |
| checks: { | |
| eligibleSession: () => { | |
| const cfg = buildConfig({ | |
| channel: { allowFrom: ["+15551230000"] }, | |
| approvals: { exec: { enabled: true, agentFilter: ["main"] } }, | |
| }); | |
| expect( | |
| suppressLocalSessionPrompt(cfg, `agent:main:${channel}:+15551230000`, { | |
| accountId: "default", | |
| agentId: null, | |
| }), | |
| ).toBe(true); | |
| }, | |
| inactiveRoutes: () => { | |
| const enabledConfig = buildConfig({ | |
| channel: { allowFrom: ["+15551230000"] }, | |
| approvals: { exec: { enabled: true } }, | |
| }); | |
| const payload = buildLocalApprovalPayload({ | |
| agentId: "main", | |
| sessionKey: `agent:main:${channel}:+15551230000`, | |
| }); | |
| const routes: LocalSuppressionParams[] = [ | |
| { cfg: buildConfig(), payload }, | |
| { | |
| cfg: buildConfig({ | |
| channel: { allowFrom: ["+15551230000"] }, | |
| approvals: { exec: { enabled: false } }, | |
| }), | |
| payload, | |
| }, | |
| { | |
| cfg: buildConfig({ | |
| channel: { allowFrom: ["+15551230000"] }, | |
| approvals: { | |
| exec: { | |
| enabled: true, | |
| mode: "targets", | |
| targets: [{ channel, to: "+15551230000" }], | |
| }, | |
| }, | |
| }), | |
| payload, | |
| }, | |
| { cfg: enabledConfig, payload, hint: { ...activeExecHint, nativeRouteActive: false } }, | |
| { cfg: enabledConfig, payload: buildLocalApprovalPayload({ approvalKind: "plugin" }) }, | |
| { cfg: enabledConfig, payload: { text: "Approval required." } }, | |
| ]; | |
| for (const route of routes) { | |
| expect(suppressLocalPrompt(route)).toBe(false); | |
| } | |
| }, | |
| sessionFilters: () => { | |
| const cfg = buildConfig({ | |
| channel: { allowFrom: ["+15551230000"] }, | |
| approvals: { exec: { enabled: true, agentFilter: ["ops"], sessionFilter: [channel] } }, | |
| }); | |
| for (const [sessionKey, expected] of [ | |
| [`agent:ops:${channel}:+15551230000`, true], | |
| [`agent:main:${channel}:+15551230000`, false], | |
| ["agent:ops:slack:C123", false], | |
| ] as const) { | |
| expect(suppressLocalSessionPrompt(cfg, sessionKey, { agentId: null })).toBe(expected); | |
| } | |
| }, | |
| }, | |
| }; | |
| } | |