fix: repair local approval resolution (#86771) · openclaw/openclaw@13cfb77
fuller-stack
·
2026-05-27
·
via Recent Commits to openclaw:main
File tree
extensions/discord/src/monitor
| Original file line number | Diff line number | Diff line change |
|---|
@@ -144,7 +144,7 @@ describe("discord exec approval monitor helpers", () => {
|
144 | 144 | }); |
145 | 145 | }); |
146 | 146 | |
147 | | -it("keeps already-resolved approval clicks quiet", async () => { |
| 147 | +it("shows a follow-up for already-resolved approval clicks", async () => { |
148 | 148 | const interaction = createInteraction(); |
149 | 149 | const button = new ExecApprovalButton({ |
150 | 150 | getApprovers: () => ["123"], |
@@ -154,7 +154,11 @@ describe("discord exec approval monitor helpers", () => {
|
154 | 154 | await button.run(interaction, { id: "abc", action: "allow-once" }); |
155 | 155 | |
156 | 156 | expect(interaction.acknowledge).toHaveBeenCalled(); |
157 | | -expect(interaction.followUp).not.toHaveBeenCalled(); |
| 157 | +expect(interaction.followUp).toHaveBeenCalledWith({ |
| 158 | +content: |
| 159 | +"That approval request is no longer pending. It may have expired or already been resolved.", |
| 160 | +ephemeral: true, |
| 161 | +}); |
158 | 162 | }); |
159 | 163 | |
160 | 164 | it("builds button context from config and routes resolution over gateway", async () => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -112,10 +112,13 @@ export class ExecApprovalButton extends Button {
|
112 | 112 | } catch {} |
113 | 113 | |
114 | 114 | const result = await this.ctx.resolveApproval(parsed.approvalId, parsed.action); |
115 | | -if (!result.ok && result.reason !== "not-found") { |
| 115 | +if (!result.ok) { |
116 | 116 | try { |
117 | 117 | await interaction.followUp({ |
118 | | -content: `Failed to submit approval decision for **${decisionLabel}**. The request may have expired or already been resolved.`, |
| 118 | +content: |
| 119 | +result.reason === "not-found" |
| 120 | + ? `That approval request is no longer pending. It may have expired or already been resolved.` |
| 121 | + : `Failed to submit approval decision for **${decisionLabel}**. The request may have expired or already been resolved.`, |
119 | 122 | ephemeral: true, |
120 | 123 | }); |
121 | 124 | } catch {} |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -117,7 +117,7 @@ describe("withOperatorApprovalsGatewayClient", () => {
|
117 | 117 | expect(clientState.options?.deviceIdentity).toBeUndefined(); |
118 | 118 | }); |
119 | 119 | |
120 | | -it("omits approval runtime token for explicit gateway URL overrides", async () => { |
| 120 | +it("keeps approval runtime token for loopback explicit gateway URL overrides", async () => { |
121 | 121 | await withOperatorApprovalsGatewayClient( |
122 | 122 | { |
123 | 123 | config: {} as never, |
@@ -127,6 +127,21 @@ describe("withOperatorApprovalsGatewayClient", () => {
|
127 | 127 | async () => undefined, |
128 | 128 | ); |
129 | 129 | |
| 130 | +expect(typeof clientState.options?.approvalRuntimeToken).toBe("string"); |
| 131 | +}); |
| 132 | + |
| 133 | +it("omits approval runtime token for remote explicit gateway URL overrides", async () => { |
| 134 | +bootstrapState.url = "wss://gateway.example/ws"; |
| 135 | + |
| 136 | +await withOperatorApprovalsGatewayClient( |
| 137 | +{ |
| 138 | +config: {} as never, |
| 139 | +gatewayUrl: "wss://gateway.example/ws", |
| 140 | +clientDisplayName: "Matrix approval (@owner:example.org)", |
| 141 | +}, |
| 142 | +async () => undefined, |
| 143 | +); |
| 144 | + |
130 | 145 | expect(clientState.options).not.toHaveProperty("approvalRuntimeToken"); |
131 | 146 | }); |
132 | 147 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -44,12 +44,15 @@ export async function createOperatorApprovalsGatewayClient(
|
44 | 44 | gatewayUrl: params.gatewayUrl, |
45 | 45 | env: process.env, |
46 | 46 | }); |
| 47 | +const shouldSendApprovalRuntimeToken = !params.gatewayUrl || isLoopbackGatewayUrl(bootstrap.url); |
47 | 48 | |
48 | 49 | return new GatewayClient({ |
49 | 50 | url: bootstrap.url, |
50 | 51 | token: bootstrap.auth.token, |
51 | 52 | password: bootstrap.auth.password, |
52 | | - ...(params.gatewayUrl ? {} : { approvalRuntimeToken: getOperatorApprovalRuntimeToken() }), |
| 53 | + ...(shouldSendApprovalRuntimeToken |
| 54 | + ? { approvalRuntimeToken: getOperatorApprovalRuntimeToken() } |
| 55 | + : {}), |
53 | 56 | preauthHandshakeTimeoutMs: bootstrap.preauthHandshakeTimeoutMs, |
54 | 57 | clientName: GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT, |
55 | 58 | clientDisplayName: params.clientDisplayName, |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。