

























@@ -33,6 +33,10 @@ function readChatUpdatePayload(
3333}
34343535describe("slackApprovalNativeRuntime", () => {
36+it("subscribes to plugin approval events", () => {
37+expect(slackApprovalNativeRuntime.eventKinds).toEqual(["exec", "plugin"]);
38+});
39+3640it("renders only the allowed pending actions", async () => {
3741const payload = (await slackApprovalNativeRuntime.presentation.buildPendingPayload({
3842cfg: {} as never,
@@ -89,6 +93,81 @@ describe("slackApprovalNativeRuntime", () => {
8993expect(JSON.stringify(payload.blocks)).not.toContain("Allow Always");
9094});
919596+it("renders plugin pending approvals with plugin approval actions", async () => {
97+const payload = (await slackApprovalNativeRuntime.presentation.buildPendingPayload({
98+cfg: {} as never,
99+accountId: "default",
100+context: {
101+app: {} as never,
102+config: {} as never,
103+},
104+request: {
105+id: "plugin:req-1",
106+request: {
107+title: "Share screen with Computer Use",
108+description: "Computer Use wants to inspect the desktop.",
109+},
110+createdAtMs: 0,
111+expiresAtMs: 60_000,
112+},
113+approvalKind: "plugin",
114+nowMs: 0,
115+view: {
116+approvalKind: "plugin",
117+phase: "pending",
118+approvalId: "plugin:req-1",
119+title: "Share screen with Computer Use",
120+description: "Computer Use wants to inspect the desktop.",
121+severity: "warning",
122+pluginId: "computer-use",
123+toolName: "screenshot",
124+metadata: [
125+{ label: "Severity", value: "Warning" },
126+{ label: "Plugin", value: "computer-use" },
127+],
128+actions: [
129+{
130+decision: "allow-once",
131+label: "Allow Once",
132+command: "/approve plugin:req-1 allow-once",
133+style: "success",
134+},
135+{
136+decision: "allow-always",
137+label: "Allow Always",
138+command: "/approve plugin:req-1 allow-always",
139+style: "success",
140+},
141+{
142+decision: "deny",
143+label: "Deny",
144+command: "/approve plugin:req-1 deny",
145+style: "danger",
146+},
147+],
148+expiresAtMs: 60_000,
149+},
150+})) as SlackPayload;
151+152+expect(payload.text).toContain("*Plugin approval required*");
153+expect(payload.text).toContain("Share screen with Computer Use");
154+expect(payload.text).toContain("*Approval ID:* plugin:req-1");
155+expect(payload.text).not.toContain("*Command*");
156+const actionsBlock = findSlackActionsBlock(
157+payload.blocks as Array<{ type?: string; elements?: unknown[] }>,
158+);
159+const labels = (actionsBlock?.elements ?? []).map((element) =>
160+typeof element === "object" &&
161+element &&
162+typeof (element as { text?: { text?: unknown } }).text?.text === "string"
163+ ? (element as { text: { text: string } }).text.text
164+ : "",
165+);
166+167+expect(labels).toEqual(["Allow Once", "Allow Always", "Deny"]);
168+expect(JSON.stringify(payload.blocks)).toContain("plugin:req-1");
169+});
170+92171it("renders resolved updates without interactive blocks", async () => {
93172const result = await slackApprovalNativeRuntime.presentation.buildResolvedResult({
94173cfg: {} as never,
@@ -136,6 +215,101 @@ describe("slackApprovalNativeRuntime", () => {
136215).toBe(false);
137216});
138217218+it("renders plugin resolved and expired updates without command text", async () => {
219+const resolved = await slackApprovalNativeRuntime.presentation.buildResolvedResult({
220+cfg: {} as never,
221+accountId: "default",
222+context: {
223+app: {} as never,
224+config: {} as never,
225+},
226+request: {
227+id: "plugin:req-1",
228+request: {
229+title: "Share screen with Computer Use",
230+description: "Computer Use wants to inspect the desktop.",
231+},
232+createdAtMs: 0,
233+expiresAtMs: 60_000,
234+},
235+resolved: {
236+id: "plugin:req-1",
237+decision: "allow-once",
238+resolvedBy: "U123APPROVER",
239+ts: 0,
240+} as never,
241+view: {
242+approvalKind: "plugin",
243+phase: "resolved",
244+approvalId: "plugin:req-1",
245+title: "Share screen with Computer Use",
246+description: "Computer Use wants to inspect the desktop.",
247+severity: "warning",
248+pluginId: "computer-use",
249+toolName: "screenshot",
250+metadata: [{ label: "Plugin", value: "computer-use" }],
251+decision: "allow-once",
252+resolvedBy: "U123APPROVER",
253+},
254+entry: {
255+channelId: "D123APPROVER",
256+messageTs: "1712345678.999999",
257+},
258+});
259+const expired = await slackApprovalNativeRuntime.presentation.buildExpiredResult({
260+cfg: {} as never,
261+accountId: "default",
262+context: {
263+app: {} as never,
264+config: {} as never,
265+},
266+request: {
267+id: "plugin:req-1",
268+request: {
269+title: "Share screen with Computer Use",
270+description: "Computer Use wants to inspect the desktop.",
271+},
272+createdAtMs: 0,
273+expiresAtMs: 60_000,
274+},
275+view: {
276+approvalKind: "plugin",
277+phase: "expired",
278+approvalId: "plugin:req-1",
279+title: "Share screen with Computer Use",
280+description: "Computer Use wants to inspect the desktop.",
281+severity: "warning",
282+pluginId: "computer-use",
283+toolName: "screenshot",
284+metadata: [{ label: "Plugin", value: "computer-use" }],
285+},
286+entry: {
287+channelId: "D123APPROVER",
288+messageTs: "1712345678.999999",
289+},
290+});
291+292+expect(resolved.kind).toBe("update");
293+expect(expired.kind).toBe("update");
294+if (resolved.kind !== "update" || expired.kind !== "update") {
295+throw new Error("expected Slack update payloads");
296+}
297+const resolvedPayload = resolved.payload as SlackPayload;
298+const expiredPayload = expired.payload as SlackPayload;
299+expect(resolvedPayload.text).toContain("*Plugin approval: Allowed once*");
300+expect(resolvedPayload.text).toContain("Resolved by <@U123APPROVER>.");
301+expect(resolvedPayload.text).toContain("Share screen with Computer Use");
302+expect(resolvedPayload.text).not.toContain("*Command*");
303+expect(expiredPayload.text).toContain("*Plugin approval expired*");
304+expect(expiredPayload.text).toContain("Share screen with Computer Use");
305+expect(expiredPayload.text).not.toContain("*Command*");
306+expect(
307+(resolvedPayload.blocks as Array<{ type?: string }>).some(
308+(block) => block.type === "actions",
309+),
310+).toBe(false);
311+});
312+139313it("caps resolved update fallback text to Slack chat.update limits while preserving blocks", async () => {
140314const blocks = [
141315{
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。