惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
J
Java Code Geeks
爱范儿
爱范儿
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
The GitHub Blog
The GitHub Blog
I
InfoQ
月光博客
月光博客
博客园 - 聂微东
博客园 - Franky
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
refactor(copilot): drop unused permission policy helpers ...
vincentkoc · 2026-06-19 · via Recent Commits to openclaw:main
11

// Copilot tests cover permission bridge plugin behavior.

22

import type {

33

PermissionRequest as SdkPermissionRequest,

4-

PermissionRequestResult as SdkPermissionRequestResult,

54

} from "@github/copilot-sdk";

65

import { describe, expect, it, vi } from "vitest";

76

import {

8-

allowListPolicy,

9-

allowOncePolicy,

10-

composePolicies,

117

createPermissionBridge,

12-

delegatingPolicy,

138

rejectAllPolicy,

149

REJECT_ALL_FEEDBACK,

1510

type CopilotPermissionContext,

@@ -52,168 +47,9 @@ describe("rejectAllPolicy", () => {

5247

});

5348

});

544955-

describe("allowOncePolicy", () => {

56-

it("returns approve-once for every request kind", async () => {

57-

for (const kind of [

58-

"shell",

59-

"write",

60-

"mcp",

61-

"read",

62-

"url",

63-

"custom-tool",

64-

"memory",

65-

"hook",

66-

] as const) {

67-

const result = await allowOncePolicy(makeCtx({ request: makeRequest({ kind }) }));

68-

expect(result).toEqual({ kind: "approve-once" });

69-

}

70-

});

71-

});

72-73-

describe("allowListPolicy", () => {

74-

it("approves listed kinds and rejects others with default feedback", async () => {

75-

const policy = allowListPolicy({ kinds: ["read"] });

76-

const approved = await policy(makeCtx({ request: makeRequest({ kind: "read" }) }));

77-

expect(approved).toEqual({ kind: "approve-once" });

78-

const rejected = await policy(makeCtx({ request: makeRequest({ kind: "shell" }) }));

79-

expect(rejected).toEqual({ kind: "reject", feedback: REJECT_ALL_FEEDBACK });

80-

});

81-82-

it("uses custom rejectFeedback when provided", async () => {

83-

const policy = allowListPolicy({

84-

kinds: ["read"],

85-

rejectFeedback: "only reads allowed",

86-

});

87-

const result = await policy(makeCtx({ request: makeRequest({ kind: "write" }) }));

88-

expect(result).toEqual({ kind: "reject", feedback: "only reads allowed" });

89-

});

90-91-

it("supports multiple kinds in the allow-list", async () => {

92-

const policy = allowListPolicy({ kinds: ["read", "write"] });

93-

expect(await policy(makeCtx({ request: makeRequest({ kind: "read" }) }))).toEqual({

94-

kind: "approve-once",

95-

});

96-

expect(await policy(makeCtx({ request: makeRequest({ kind: "write" }) }))).toEqual({

97-

kind: "approve-once",

98-

});

99-

expect((await policy(makeCtx({ request: makeRequest({ kind: "mcp" }) })))?.kind).toBe("reject");

100-

});

101-102-

it("rejects all when given an empty allow-list", async () => {

103-

const policy = allowListPolicy({ kinds: [] });

104-

for (const kind of ["shell", "read", "write"] as const) {

105-

const result = await policy(makeCtx({ request: makeRequest({ kind }) }));

106-

expect(result?.kind).toBe("reject");

107-

}

108-

});

109-

});

110-111-

describe("delegatingPolicy", () => {

112-

it("forwards the request to the host callback and returns its decision", async () => {

113-

const onRequest = vi.fn<CopilotPermissionPolicy>().mockResolvedValue({

114-

kind: "approve-for-session",

115-

} satisfies SdkPermissionRequestResult);

116-

const policy = delegatingPolicy({ onRequest });

117-

const ctx = makeCtx({ sessionId: "sess-xyz", request: makeRequest({ kind: "write" }) });

118-

const result = await policy(ctx);

119-

expect(result).toEqual({ kind: "approve-for-session" });

120-

expect(onRequest).toHaveBeenCalledTimes(1);

121-

expect(onRequest).toHaveBeenCalledWith(ctx);

122-

});

123-124-

it("returns the rejectAll default when host callback returns undefined", async () => {

125-

const onRequest = vi.fn<CopilotPermissionPolicy>().mockResolvedValue(undefined);

126-

const policy = delegatingPolicy({ onRequest });

127-

const result = await policy(makeCtx());

128-

expect(result).toEqual({ kind: "reject", feedback: REJECT_ALL_FEEDBACK });

129-

});

130-131-

it("rejects with the error message when host callback throws", async () => {

132-

const onRequest = vi

133-

.fn<CopilotPermissionPolicy>()

134-

.mockRejectedValue(new Error("host policy boom"));

135-

const policy = delegatingPolicy({ onRequest });

136-

const result = await policy(makeCtx());

137-

expect(result?.kind).toBe("reject");

138-

expect((result as { feedback?: string }).feedback).toContain("host policy boom");

139-

});

140-141-

it("falls back to onError policy when host callback throws", async () => {

142-

const onError = vi.fn<CopilotPermissionPolicy>().mockResolvedValue({ kind: "approve-once" });

143-

const policy = delegatingPolicy({

144-

onRequest: () => {

145-

throw new Error("host policy boom");

146-

},

147-

onError,

148-

});

149-

const result = await policy(makeCtx());

150-

expect(result).toEqual({ kind: "approve-once" });

151-

expect(onError).toHaveBeenCalledTimes(1);

152-

});

153-154-

it("falls through to a hard-coded reject if onError also throws", async () => {

155-

const policy = delegatingPolicy({

156-

onRequest: () => {

157-

throw new Error("host boom");

158-

},

159-

onError: () => {

160-

throw new Error("fallback boom");

161-

},

162-

});

163-

const result = await policy(makeCtx());

164-

expect(result?.kind).toBe("reject");

165-

expect((result as { feedback?: string }).feedback).toContain("host boom");

166-

});

167-168-

it("formats non-Error throws via JSON.stringify", async () => {

169-

const policy = delegatingPolicy({

170-

onRequest: () => {

171-

throw { code: 42, msg: "weird" } as unknown as Error;

172-

},

173-

});

174-

const result = await policy(makeCtx());

175-

expect((result as { feedback?: string }).feedback).toContain('"code":42');

176-

});

177-

});

178-179-

describe("composePolicies", () => {

180-

it("returns the first non-undefined result and skips subsequent policies", async () => {

181-

const a: CopilotPermissionPolicy = () => undefined;

182-

const b: CopilotPermissionPolicy = () => ({ kind: "approve-once" });

183-

const c = vi.fn<CopilotPermissionPolicy>(() => ({

184-

kind: "reject",

185-

feedback: "should never run",

186-

}));

187-

const policy = composePolicies(a, b, c);

188-

const result = await policy(makeCtx());

189-

expect(result).toEqual({ kind: "approve-once" });

190-

expect(c).not.toHaveBeenCalled();

191-

});

192-193-

it("falls through to fail-closed reject when all policies return undefined", async () => {

194-

const policy = composePolicies(

195-

() => undefined,

196-

() => undefined,

197-

);

198-

const result = await policy(makeCtx());

199-

expect(result).toEqual({ kind: "reject", feedback: REJECT_ALL_FEEDBACK });

200-

});

201-202-

it("short-circuits to reject if any policy throws (does not consult later policies)", async () => {

203-

const later = vi.fn<CopilotPermissionPolicy>(() => ({ kind: "approve-once" }));

204-

const policy = composePolicies(() => {

205-

throw new Error("nope");

206-

}, later);

207-

const result = await policy(makeCtx());

208-

expect(result?.kind).toBe("reject");

209-

expect((result as { feedback?: string }).feedback).toContain("nope");

210-

expect(later).not.toHaveBeenCalled();

211-

});

212-

});

213-21450

describe("createPermissionBridge", () => {

21551

it("adapts a policy to the SDK PermissionHandler shape", async () => {

216-

const handler = createPermissionBridge(allowOncePolicy);

52+

const handler = createPermissionBridge(() => ({ kind: "approve-once" }));

21753

const result = await handler(makeRequest(), { sessionId: "sess-1" });

21854

expect(result).toEqual({ kind: "approve-once" });

21955

});

@@ -251,7 +87,7 @@ describe("createPermissionBridge", () => {

25187

});

2528825389

it("handles all SDK permission kinds without throwing", async () => {

254-

const handler = createPermissionBridge(allowOncePolicy);

90+

const handler = createPermissionBridge(() => ({ kind: "approve-once" }));

25591

for (const kind of [

25692

"shell",

25793

"write",