mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-10 08:41:13 +00:00
Exec approvals: soften effective-policy triage regressions
This commit is contained in:
@@ -368,11 +368,13 @@ export function buildApprovalPendingMessage(params: {
|
||||
lines.push(
|
||||
allowedDecisions.includes("allow-always")
|
||||
? "Background mode requires pre-approved policy (allow-always or ask=off)."
|
||||
: "Background mode requires host policy that allows pre-approval (for example ask=off).",
|
||||
: "Background mode requires an effective policy that allows pre-approval (for example ask=off).",
|
||||
);
|
||||
lines.push(`Reply with: /approve ${params.approvalSlug} ${decisionText}`);
|
||||
if (!allowedDecisions.includes("allow-always")) {
|
||||
lines.push("Host policy requires approval every time, so Allow Always is unavailable.");
|
||||
lines.push(
|
||||
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
|
||||
);
|
||||
}
|
||||
lines.push("If the short code is ambiguous, use the full id in /approve.");
|
||||
return lines.join("\n");
|
||||
|
||||
@@ -251,6 +251,38 @@ describe("exec approvals CLI", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps gateway approvals output when config.get fails", async () => {
|
||||
callGatewayFromCli.mockImplementation(
|
||||
async (method: string, _opts: unknown, params?: unknown) => {
|
||||
if (method === "config.get") {
|
||||
throw new Error("gateway config unavailable");
|
||||
}
|
||||
if (method === "exec.approvals.get") {
|
||||
return {
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
hash: "hash-1",
|
||||
file: { version: 1, agents: {} },
|
||||
};
|
||||
}
|
||||
return { method, params };
|
||||
},
|
||||
);
|
||||
|
||||
await runApprovalsCommand(["approvals", "get", "--gateway", "--json"]);
|
||||
|
||||
expect(defaultRuntime.writeJson).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
effectivePolicy: {
|
||||
note: "Config unavailable.",
|
||||
scopes: [],
|
||||
},
|
||||
}),
|
||||
0,
|
||||
);
|
||||
expect(runtimeErrors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("reports agent scopes with inherited global requested policy", async () => {
|
||||
localSnapshot.file = {
|
||||
version: 1,
|
||||
|
||||
@@ -168,8 +168,16 @@ async function loadConfigForApprovalsTarget(params: {
|
||||
if (params.source === "local") {
|
||||
return await readBestEffortConfig();
|
||||
}
|
||||
const snapshot = (await callGatewayFromCli("config.get", params.opts, {})) as ConfigSnapshotLike;
|
||||
return snapshot.config && typeof snapshot.config === "object" ? snapshot.config : null;
|
||||
try {
|
||||
const snapshot = (await callGatewayFromCli(
|
||||
"config.get",
|
||||
params.opts,
|
||||
{},
|
||||
)) as ConfigSnapshotLike;
|
||||
return snapshot.config && typeof snapshot.config === "object" ? snapshot.config : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function collectExecPolicySnapshots(params: { cfg: OpenClawConfig; approvals: ExecApprovalsFile }) {
|
||||
|
||||
@@ -337,7 +337,7 @@ export function createExecApprovalHandlers(
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"allow-always is unavailable because host policy requires approval every time",
|
||||
"allow-always is unavailable because the effective policy requires approval every time",
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -597,7 +597,8 @@ describe("exec approval handlers", () => {
|
||||
false,
|
||||
undefined,
|
||||
expect.objectContaining({
|
||||
message: "allow-always is unavailable because host policy requires approval every time",
|
||||
message:
|
||||
"allow-always is unavailable because the effective policy requires approval every time",
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -238,11 +238,13 @@ function buildRequestMessage(request: ExecApprovalRequest, nowMs: number) {
|
||||
lines.push(
|
||||
allowedDecisions.includes("allow-always")
|
||||
? "Background mode note: non-interactive runs cannot wait for chat approvals; use pre-approved policy (allow-always or ask=off)."
|
||||
: "Background mode note: non-interactive runs cannot wait for chat approvals; host policy still requires per-run approval unless ask=off.",
|
||||
: "Background mode note: non-interactive runs cannot wait for chat approvals; the effective policy still requires per-run approval unless ask=off.",
|
||||
);
|
||||
lines.push(`Reply with: /approve <id> ${decisionText}`);
|
||||
if (!allowedDecisions.includes("allow-always")) {
|
||||
lines.push("Allow Always is unavailable because host policy requires approval every time.");
|
||||
lines.push(
|
||||
"Allow Always is unavailable because the effective policy requires approval every time.",
|
||||
);
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ describe("exec approval reply helpers", () => {
|
||||
expect(payload.text).toContain("Full id: `req-1`");
|
||||
});
|
||||
|
||||
it("omits allow-always actions when host policy requires approval every time", () => {
|
||||
it("omits allow-always actions when the effective policy requires approval every time", () => {
|
||||
const payload = buildExecApprovalPendingReplyPayload({
|
||||
approvalId: "req-ask-always",
|
||||
approvalSlug: "slug-always",
|
||||
@@ -156,7 +156,9 @@ describe("exec approval reply helpers", () => {
|
||||
});
|
||||
expect(payload.text).toContain("```txt\n/approve slug-always allow-once\n```");
|
||||
expect(payload.text).not.toContain("allow-always");
|
||||
expect(payload.text).toContain("Allow Always is unavailable");
|
||||
expect(payload.text).toContain(
|
||||
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
|
||||
);
|
||||
expect(payload.interactive).toEqual({
|
||||
blocks: [
|
||||
{
|
||||
|
||||
@@ -267,7 +267,9 @@ export function buildExecApprovalPendingReplyPayload(
|
||||
lines.push(secondaryFence);
|
||||
}
|
||||
if (!allowedDecisions.includes("allow-always")) {
|
||||
lines.push("Host policy requires approval every time, so Allow Always is unavailable.");
|
||||
lines.push(
|
||||
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
|
||||
);
|
||||
}
|
||||
const info: string[] = [];
|
||||
info.push(`Host: ${params.host}`);
|
||||
|
||||
Reference in New Issue
Block a user