fix(agents): re-apply GPT apply_patch deny after config override merge
This commit is contained in:
@@ -7,6 +7,7 @@ import { createHephaestusAgent } from "../hephaestus"
|
|||||||
import { applyEnvironmentContext } from "./environment-context"
|
import { applyEnvironmentContext } from "./environment-context"
|
||||||
import { applyCategoryOverride, mergeAgentConfig } from "./agent-overrides"
|
import { applyCategoryOverride, mergeAgentConfig } from "./agent-overrides"
|
||||||
import { applyModelResolution, getFirstFallbackModel } from "./model-resolution"
|
import { applyModelResolution, getFirstFallbackModel } from "./model-resolution"
|
||||||
|
import { getGptApplyPatchPermission } from "../gpt-apply-patch-guard"
|
||||||
|
|
||||||
export function maybeCreateHephaestusConfig(input: {
|
export function maybeCreateHephaestusConfig(input: {
|
||||||
disabledAgents: string[]
|
disabledAgents: string[]
|
||||||
@@ -86,5 +87,12 @@ export function maybeCreateHephaestusConfig(input: {
|
|||||||
if (hephaestusOverride) {
|
if (hephaestusOverride) {
|
||||||
hephaestusConfig = mergeAgentConfig(hephaestusConfig, hephaestusOverride, directory)
|
hephaestusConfig = mergeAgentConfig(hephaestusConfig, hephaestusOverride, directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolvedModel = hephaestusConfig.model ?? ""
|
||||||
|
const gptDeny = getGptApplyPatchPermission(resolvedModel)
|
||||||
|
if (Object.keys(gptDeny).length > 0 && hephaestusConfig.permission) {
|
||||||
|
Object.assign(hephaestusConfig.permission, gptDeny)
|
||||||
|
}
|
||||||
|
|
||||||
return hephaestusConfig
|
return hephaestusConfig
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import { maybeCreateSisyphusConfig } from "./sisyphus-agent";
|
||||||
|
import type { AgentOverrides } from "../types";
|
||||||
|
import type { CategoryConfig } from "../../config/schema";
|
||||||
|
|
||||||
|
describe("maybeCreateSisyphusConfig", () => {
|
||||||
|
describe("#given GPT model with user override allowing apply_patch", () => {
|
||||||
|
test("#when config is created #then apply_patch is still denied", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
sisyphus: {
|
||||||
|
model: "openai/gpt-5.4",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateSisyphusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["openai/gpt-5.4"]),
|
||||||
|
systemDefaultModel: "openai/gpt-5.4",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("openai/gpt-5.4");
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "deny");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#given non-GPT model with user override", () => {
|
||||||
|
test("#when config is created #then apply_patch is not forced to deny", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
sisyphus: {
|
||||||
|
model: "anthropic/claude-opus-4-6",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateSisyphusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["anthropic/claude-opus-4-6"]),
|
||||||
|
systemDefaultModel: "anthropic/claude-opus-4-6",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("anthropic/claude-opus-4-6");
|
||||||
|
// Claude models should allow the user override
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "allow");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#given generic GPT model with user override allowing apply_patch", () => {
|
||||||
|
test("#when config is created #then apply_patch is still denied", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
sisyphus: {
|
||||||
|
model: "openai/gpt-4o",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateSisyphusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["openai/gpt-4o"]),
|
||||||
|
systemDefaultModel: "openai/gpt-4o",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("openai/gpt-4o");
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "deny");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -7,6 +7,7 @@ import { applyEnvironmentContext } from "./environment-context"
|
|||||||
import { applyOverrides } from "./agent-overrides"
|
import { applyOverrides } from "./agent-overrides"
|
||||||
import { applyModelResolution, getFirstFallbackModel } from "./model-resolution"
|
import { applyModelResolution, getFirstFallbackModel } from "./model-resolution"
|
||||||
import { createSisyphusAgent } from "../sisyphus"
|
import { createSisyphusAgent } from "../sisyphus"
|
||||||
|
import { getGptApplyPatchPermission } from "../gpt-apply-patch-guard"
|
||||||
|
|
||||||
export function maybeCreateSisyphusConfig(input: {
|
export function maybeCreateSisyphusConfig(input: {
|
||||||
disabledAgents: string[]
|
disabledAgents: string[]
|
||||||
@@ -80,6 +81,13 @@ export function maybeCreateSisyphusConfig(input: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sisyphusConfig = applyOverrides(sisyphusConfig, sisyphusOverride, mergedCategories, directory)
|
sisyphusConfig = applyOverrides(sisyphusConfig, sisyphusOverride, mergedCategories, directory)
|
||||||
|
|
||||||
|
const resolvedModel = sisyphusConfig.model ?? ""
|
||||||
|
const gptDeny = getGptApplyPatchPermission(resolvedModel)
|
||||||
|
if (Object.keys(gptDeny).length > 0 && sisyphusConfig.permission) {
|
||||||
|
Object.assign(sisyphusConfig.permission, gptDeny)
|
||||||
|
}
|
||||||
|
|
||||||
sisyphusConfig = applyEnvironmentContext(sisyphusConfig, directory, {
|
sisyphusConfig = applyEnvironmentContext(sisyphusConfig, directory, {
|
||||||
disableOmoEnv,
|
disableOmoEnv,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -277,3 +277,111 @@ describe("createHephaestusAgent", () => {
|
|||||||
expect(config.prompt).not.toContain("task_create");
|
expect(config.prompt).not.toContain("task_create");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import { maybeCreateHephaestusConfig } from "../builtin-agents/hephaestus-agent";
|
||||||
|
import type { AgentOverrides } from "../types";
|
||||||
|
import type { CategoryConfig } from "../../config/schema";
|
||||||
|
|
||||||
|
describe("maybeCreateHephaestusConfig GPT apply_patch guard", () => {
|
||||||
|
describe("#given GPT model with user override allowing apply_patch", () => {
|
||||||
|
test("#when config is created #then apply_patch is still denied", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
hephaestus: {
|
||||||
|
model: "openai/gpt-5.4",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateHephaestusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["openai/gpt-5.4"]),
|
||||||
|
systemDefaultModel: "openai/gpt-5.4",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("openai/gpt-5.4");
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "deny");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#given non-GPT model with user override allowing apply_patch", () => {
|
||||||
|
test("#when config is created #then user override is respected", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
hephaestus: {
|
||||||
|
model: "anthropic/claude-opus-4-6",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateHephaestusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["anthropic/claude-opus-4-6"]),
|
||||||
|
systemDefaultModel: "anthropic/claude-opus-4-6",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("anthropic/claude-opus-4-6");
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "allow");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#given generic GPT model with user override allowing apply_patch", () => {
|
||||||
|
test("#when config is created #then apply_patch is still denied", () => {
|
||||||
|
// given
|
||||||
|
const agentOverrides: AgentOverrides = {
|
||||||
|
hephaestus: {
|
||||||
|
model: "openai/gpt-4o",
|
||||||
|
permission: {
|
||||||
|
apply_patch: "allow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mergedCategories: Record<string, CategoryConfig> = {};
|
||||||
|
|
||||||
|
// when
|
||||||
|
const config = maybeCreateHephaestusConfig({
|
||||||
|
disabledAgents: [],
|
||||||
|
agentOverrides,
|
||||||
|
availableModels: new Set(["openai/gpt-4o"]),
|
||||||
|
systemDefaultModel: "openai/gpt-4o",
|
||||||
|
isFirstRunNoCache: false,
|
||||||
|
availableAgents: [],
|
||||||
|
availableSkills: [],
|
||||||
|
availableCategories: [],
|
||||||
|
mergedCategories,
|
||||||
|
useTaskSystem: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config?.model).toBe("openai/gpt-4o");
|
||||||
|
expect(config?.permission).toHaveProperty("apply_patch", "deny");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user