Revert "Merge pull request #1951 from edxeth/feat/custom-agents"
This reverts commit47e300b17e, reversing changes made to243ce1b7e8.
This commit is contained in:
@@ -4,7 +4,6 @@ import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { log, migrateAgentConfig } from "../shared";
|
||||
import { AGENT_NAME_MAP } from "../shared/migration";
|
||||
import { getAgentDisplayName } from "../shared/agent-display-names";
|
||||
import { mergeCategories } from "../shared/merge-categories";
|
||||
import {
|
||||
discoverConfigSourceSkills,
|
||||
discoverOpencodeGlobalSkills,
|
||||
@@ -18,13 +17,6 @@ import { reorderAgentsByPriority } from "./agent-priority-order";
|
||||
import { remapAgentKeysToDisplayNames } from "./agent-key-remapper";
|
||||
import { buildPrometheusAgentConfig } from "./prometheus-agent-config-builder";
|
||||
import { buildPlanDemoteConfig } from "./plan-model-inheritance";
|
||||
import {
|
||||
applyCustomAgentOverrides,
|
||||
collectCustomAgentSummariesFromRecord,
|
||||
mergeCustomAgentSummaries,
|
||||
collectKnownCustomAgentNames,
|
||||
filterSummariesByKnownNames,
|
||||
} from "./custom-agent-utils";
|
||||
|
||||
type AgentConfigRecord = Record<string, Record<string, unknown> | undefined> & {
|
||||
build?: Record<string, unknown>;
|
||||
@@ -82,19 +74,26 @@ export async function applyAgentConfig(params: {
|
||||
const browserProvider =
|
||||
params.pluginConfig.browser_automation_engine?.provider ?? "playwright";
|
||||
const currentModel = params.config.model as string | undefined;
|
||||
const disabledAgentNames = new Set(
|
||||
(migratedDisabledAgents ?? []).map((agent) => agent.toLowerCase()),
|
||||
);
|
||||
const filterDisabledAgents = (agents: Record<string, unknown>) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(agents).filter(
|
||||
([name]) => !disabledAgentNames.has(name.toLowerCase()),
|
||||
),
|
||||
);
|
||||
const disabledSkills = new Set<string>(params.pluginConfig.disabled_skills ?? []);
|
||||
const useTaskSystem = params.pluginConfig.experimental?.task_system ?? false;
|
||||
const disableOmoEnv = params.pluginConfig.experimental?.disable_omo_env ?? false;
|
||||
|
||||
const builtinAgents = await createBuiltinAgents(
|
||||
migratedDisabledAgents,
|
||||
params.pluginConfig.agents,
|
||||
params.ctx.directory,
|
||||
currentModel,
|
||||
params.pluginConfig.categories,
|
||||
params.pluginConfig.git_master,
|
||||
allDiscoveredSkills,
|
||||
params.ctx.client,
|
||||
browserProvider,
|
||||
currentModel,
|
||||
disabledSkills,
|
||||
useTaskSystem,
|
||||
disableOmoEnv,
|
||||
);
|
||||
|
||||
const includeClaudeAgents = params.pluginConfig.claude_code?.agents ?? true;
|
||||
const userAgents = includeClaudeAgents ? loadUserAgents() : {};
|
||||
const projectAgents = includeClaudeAgents ? loadProjectAgents(params.ctx.directory) : {};
|
||||
@@ -107,49 +106,15 @@ export async function applyAgentConfig(params: {
|
||||
]),
|
||||
);
|
||||
|
||||
const configAgent = params.config.agent as AgentConfigRecord | undefined;
|
||||
const filteredUserAgents = filterDisabledAgents(userAgents as Record<string, unknown>);
|
||||
const filteredProjectAgents = filterDisabledAgents(projectAgents as Record<string, unknown>);
|
||||
const filteredPluginAgents = filterDisabledAgents(pluginAgents as Record<string, unknown>);
|
||||
const filteredConfigAgentsForSummary = filterDisabledAgents(
|
||||
(configAgent as Record<string, unknown> | undefined) ?? {},
|
||||
const disabledAgentNames = new Set(
|
||||
(migratedDisabledAgents ?? []).map(a => a.toLowerCase())
|
||||
);
|
||||
const mergedCategories = mergeCategories(params.pluginConfig.categories)
|
||||
const knownCustomAgentNames = collectKnownCustomAgentNames(
|
||||
filteredUserAgents,
|
||||
filteredProjectAgents,
|
||||
filteredPluginAgents,
|
||||
filteredConfigAgentsForSummary,
|
||||
)
|
||||
|
||||
const customAgentSummaries = mergeCustomAgentSummaries(
|
||||
collectCustomAgentSummariesFromRecord(filteredUserAgents),
|
||||
collectCustomAgentSummariesFromRecord(filteredProjectAgents),
|
||||
collectCustomAgentSummariesFromRecord(filteredPluginAgents),
|
||||
collectCustomAgentSummariesFromRecord(filteredConfigAgentsForSummary),
|
||||
filterSummariesByKnownNames(
|
||||
collectCustomAgentSummariesFromRecord(
|
||||
params.pluginConfig.custom_agents as Record<string, unknown> | undefined,
|
||||
),
|
||||
knownCustomAgentNames,
|
||||
),
|
||||
)
|
||||
const filterDisabledAgents = (agents: Record<string, unknown>) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(agents).filter(([name]) => !disabledAgentNames.has(name.toLowerCase()))
|
||||
);
|
||||
|
||||
const builtinAgents = await createBuiltinAgents(
|
||||
migratedDisabledAgents,
|
||||
params.pluginConfig.agents,
|
||||
params.ctx.directory,
|
||||
currentModel,
|
||||
params.pluginConfig.categories,
|
||||
params.pluginConfig.git_master,
|
||||
allDiscoveredSkills,
|
||||
customAgentSummaries,
|
||||
browserProvider,
|
||||
currentModel,
|
||||
disabledSkills,
|
||||
useTaskSystem,
|
||||
disableOmoEnv,
|
||||
);
|
||||
const isSisyphusEnabled = params.pluginConfig.sisyphus_agent?.disabled !== true;
|
||||
const builderEnabled =
|
||||
params.pluginConfig.sisyphus_agent?.default_builder_enabled ?? false;
|
||||
@@ -158,6 +123,8 @@ export async function applyAgentConfig(params: {
|
||||
const shouldDemotePlan = plannerEnabled && replacePlan;
|
||||
const configuredDefaultAgent = getConfiguredDefaultAgent(params.config);
|
||||
|
||||
const configAgent = params.config.agent as AgentConfigRecord | undefined;
|
||||
|
||||
if (isSisyphusEnabled && builtinAgents.sisyphus) {
|
||||
if (configuredDefaultAgent) {
|
||||
(params.config as { default_agent?: string }).default_agent =
|
||||
@@ -201,7 +168,6 @@ export async function applyAgentConfig(params: {
|
||||
pluginPrometheusOverride: prometheusOverride,
|
||||
userCategories: params.pluginConfig.categories,
|
||||
currentModel,
|
||||
customAgentSummaries,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -237,9 +203,9 @@ export async function applyAgentConfig(params: {
|
||||
...Object.fromEntries(
|
||||
Object.entries(builtinAgents).filter(([key]) => key !== "sisyphus"),
|
||||
),
|
||||
...filteredUserAgents,
|
||||
...filteredProjectAgents,
|
||||
...filteredPluginAgents,
|
||||
...filterDisabledAgents(userAgents),
|
||||
...filterDisabledAgents(projectAgents),
|
||||
...filterDisabledAgents(pluginAgents),
|
||||
...filteredConfigAgents,
|
||||
build: { ...migratedBuild, mode: "subagent", hidden: true },
|
||||
...(planDemoteConfig ? { plan: planDemoteConfig } : {}),
|
||||
@@ -247,31 +213,13 @@ export async function applyAgentConfig(params: {
|
||||
} else {
|
||||
params.config.agent = {
|
||||
...builtinAgents,
|
||||
...filteredUserAgents,
|
||||
...filteredProjectAgents,
|
||||
...filteredPluginAgents,
|
||||
...filterDisabledAgents(userAgents),
|
||||
...filterDisabledAgents(projectAgents),
|
||||
...filterDisabledAgents(pluginAgents),
|
||||
...configAgent,
|
||||
};
|
||||
}
|
||||
|
||||
if (params.config.agent) {
|
||||
const builtinOverrideKeys = new Set([
|
||||
...Object.keys(builtinAgents).map((key) => key.toLowerCase()),
|
||||
"build",
|
||||
"plan",
|
||||
"sisyphus-junior",
|
||||
"opencode-builder",
|
||||
])
|
||||
|
||||
applyCustomAgentOverrides({
|
||||
mergedAgents: params.config.agent as Record<string, unknown>,
|
||||
userOverrides: params.pluginConfig.custom_agents,
|
||||
builtinOverrideKeys,
|
||||
mergedCategories,
|
||||
directory: params.ctx.directory,
|
||||
})
|
||||
}
|
||||
|
||||
if (params.config.agent) {
|
||||
params.config.agent = remapAgentKeysToDisplayNames(
|
||||
params.config.agent as Record<string, unknown>,
|
||||
|
||||
@@ -162,347 +162,6 @@ describe("Sisyphus-Junior model inheritance", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("custom agent overrides", () => {
|
||||
test("passes custom agent summaries into builtin agent prompt builder", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "Translate and localize text",
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
const createBuiltinAgentsMock = agents.createBuiltinAgents as unknown as {
|
||||
mock: { calls: unknown[][] }
|
||||
}
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const firstCallArgs = createBuiltinAgentsMock.mock.calls[0]
|
||||
expect(firstCallArgs).toBeDefined()
|
||||
expect(Array.isArray(firstCallArgs[7])).toBe(true)
|
||||
expect(firstCallArgs[7]).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
name: "translator",
|
||||
description: "Translate and localize text",
|
||||
}),
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
test("applies oh-my-opencode agent overrides to custom Claude agents", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "(user) translator",
|
||||
prompt: "Base translator prompt",
|
||||
},
|
||||
})
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
custom_agents: {
|
||||
translator: {
|
||||
model: "google/gemini-3-flash-preview",
|
||||
temperature: 0,
|
||||
prompt_append: "Always preserve placeholders exactly.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const agentConfig = config.agent as Record<string, { model?: string; temperature?: number; prompt?: string }>
|
||||
expect(agentConfig.translator).toBeDefined()
|
||||
expect(agentConfig.translator.model).toBe("google/gemini-3-flash-preview")
|
||||
expect(agentConfig.translator.temperature).toBe(0)
|
||||
expect(agentConfig.translator.prompt).toContain("Base translator prompt")
|
||||
expect(agentConfig.translator.prompt).toContain("Always preserve placeholders exactly.")
|
||||
})
|
||||
|
||||
test("prometheus prompt includes custom agent catalog for planning", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "Translate and localize locale files",
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const agentsConfig = config.agent as Record<string, { prompt?: string }>
|
||||
const pKey = getAgentDisplayName("prometheus")
|
||||
expect(agentsConfig[pKey]).toBeDefined()
|
||||
expect(agentsConfig[pKey].prompt).toContain("<custom_agent_catalog>")
|
||||
expect(agentsConfig[pKey].prompt).toContain("translator")
|
||||
expect(agentsConfig[pKey].prompt).toContain("Translate and localize locale files")
|
||||
})
|
||||
|
||||
test("prometheus prompt excludes unknown custom_agents entries", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "Translate and localize locale files",
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
custom_agents: {
|
||||
translator: {
|
||||
description: "Translate and localize locale files",
|
||||
},
|
||||
ghostwriter: {
|
||||
description: "This agent does not exist in runtime",
|
||||
},
|
||||
},
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const agentsConfig = config.agent as Record<string, { prompt?: string }>
|
||||
const pKey = getAgentDisplayName("prometheus")
|
||||
expect(agentsConfig[pKey]).toBeDefined()
|
||||
expect(agentsConfig[pKey].prompt).toContain("translator")
|
||||
expect(agentsConfig[pKey].prompt).not.toContain("ghostwriter")
|
||||
})
|
||||
|
||||
test("prometheus prompt excludes disabled custom agents from catalog", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "Translate and localize locale files",
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
disabled_agents: ["translator"],
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const agentsConfig = config.agent as Record<string, { prompt?: string }>
|
||||
const pKey = getAgentDisplayName("prometheus")
|
||||
expect(agentsConfig[pKey]).toBeDefined()
|
||||
expect(agentsConfig[pKey].prompt).not.toContain("translator")
|
||||
})
|
||||
|
||||
test("prometheus custom prompt override still includes custom agent catalog", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "Translate and localize locale files",
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
agents: {
|
||||
prometheus: {
|
||||
prompt: "Custom planner prompt",
|
||||
},
|
||||
},
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const agentsConfig = config.agent as Record<string, { prompt?: string }>
|
||||
const pKey = getAgentDisplayName("prometheus")
|
||||
expect(agentsConfig[pKey]).toBeDefined()
|
||||
expect(agentsConfig[pKey].prompt).toContain("Custom planner prompt")
|
||||
expect(agentsConfig[pKey].prompt).toContain("<custom_agent_catalog>")
|
||||
expect(agentsConfig[pKey].prompt).toContain("translator")
|
||||
})
|
||||
|
||||
test("custom agent summary merge preserves flags when custom_agents adds description", async () => {
|
||||
// #given
|
||||
;(agentLoader.loadUserAgents as any).mockReturnValue({
|
||||
translator: {
|
||||
name: "translator",
|
||||
mode: "subagent",
|
||||
description: "",
|
||||
hidden: true,
|
||||
disabled: true,
|
||||
enabled: false,
|
||||
prompt: "Translate content",
|
||||
},
|
||||
})
|
||||
const createBuiltinAgentsMock = agents.createBuiltinAgents as unknown as {
|
||||
mock: { calls: unknown[][] }
|
||||
}
|
||||
|
||||
const pluginConfig: OhMyOpenCodeConfig = {
|
||||
custom_agents: {
|
||||
translator: {
|
||||
description: "Translate and localize locale files",
|
||||
},
|
||||
},
|
||||
sisyphus_agent: {
|
||||
planner_enabled: true,
|
||||
},
|
||||
}
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// #when
|
||||
await handler(config)
|
||||
|
||||
// #then
|
||||
const firstCallArgs = createBuiltinAgentsMock.mock.calls[0]
|
||||
const summaries = firstCallArgs[7] as Array<{
|
||||
name: string
|
||||
description: string
|
||||
hidden?: boolean
|
||||
disabled?: boolean
|
||||
enabled?: boolean
|
||||
}>
|
||||
const translatorSummary = summaries.find((summary) => summary.name === "translator")
|
||||
|
||||
expect(translatorSummary).toBeDefined()
|
||||
expect(translatorSummary?.description).toBe("Translate and localize locale files")
|
||||
expect(translatorSummary?.hidden).toBe(true)
|
||||
expect(translatorSummary?.disabled).toBe(true)
|
||||
expect(translatorSummary?.enabled).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Plan agent demote behavior", () => {
|
||||
test("orders core agents as sisyphus -> hephaestus -> prometheus -> atlas", async () => {
|
||||
// #given
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
import type { AgentConfig } from "@opencode-ai/sdk";
|
||||
import { applyOverrides } from "../agents/builtin-agents/agent-overrides";
|
||||
import type { AgentOverrideConfig } from "../agents/types";
|
||||
import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { getAgentConfigKey } from "../shared/agent-display-names";
|
||||
import { AGENT_NAME_MAP } from "../shared/migration";
|
||||
import { mergeCategories } from "../shared/merge-categories";
|
||||
|
||||
const RESERVED_AGENT_KEYS = new Set(
|
||||
[
|
||||
"build",
|
||||
"plan",
|
||||
"sisyphus-junior",
|
||||
"opencode-builder",
|
||||
...Object.keys(AGENT_NAME_MAP),
|
||||
...Object.values(AGENT_NAME_MAP),
|
||||
].map((key) => getAgentConfigKey(key).toLowerCase()),
|
||||
);
|
||||
|
||||
export type AgentSummary = {
|
||||
name: string;
|
||||
description: string;
|
||||
hidden?: boolean;
|
||||
disabled?: boolean;
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
export function applyCustomAgentOverrides(params: {
|
||||
mergedAgents: Record<string, unknown>;
|
||||
userOverrides: OhMyOpenCodeConfig["custom_agents"] | undefined;
|
||||
builtinOverrideKeys: Set<string>;
|
||||
mergedCategories: ReturnType<typeof mergeCategories>;
|
||||
directory: string;
|
||||
}): void {
|
||||
if (!params.userOverrides) return;
|
||||
|
||||
for (const [overrideKey, override] of Object.entries(params.userOverrides)) {
|
||||
if (!override) continue;
|
||||
|
||||
const normalizedOverrideKey = getAgentConfigKey(overrideKey).toLowerCase();
|
||||
if (params.builtinOverrideKeys.has(normalizedOverrideKey)) continue;
|
||||
|
||||
const existingKey = Object.keys(params.mergedAgents).find(
|
||||
(key) => key.toLowerCase() === overrideKey.toLowerCase() || key.toLowerCase() === normalizedOverrideKey,
|
||||
);
|
||||
if (!existingKey) continue;
|
||||
|
||||
const existingAgent = params.mergedAgents[existingKey];
|
||||
if (!existingAgent || typeof existingAgent !== "object") continue;
|
||||
|
||||
params.mergedAgents[existingKey] = applyOverrides(
|
||||
existingAgent as AgentConfig,
|
||||
override as AgentOverrideConfig,
|
||||
params.mergedCategories,
|
||||
params.directory,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function collectCustomAgentSummariesFromRecord(
|
||||
agents: Record<string, unknown> | undefined,
|
||||
): AgentSummary[] {
|
||||
if (!agents) return [];
|
||||
|
||||
const summaries: AgentSummary[] = [];
|
||||
for (const [name, value] of Object.entries(agents)) {
|
||||
const normalizedName = getAgentConfigKey(name).toLowerCase();
|
||||
if (RESERVED_AGENT_KEYS.has(normalizedName)) continue;
|
||||
if (!value || typeof value !== "object") continue;
|
||||
|
||||
const agentValue = value as Record<string, unknown>;
|
||||
const description = typeof agentValue.description === "string" ? agentValue.description : "";
|
||||
|
||||
summaries.push({
|
||||
name,
|
||||
description,
|
||||
hidden: typeof agentValue.hidden === "boolean" ? agentValue.hidden : undefined,
|
||||
disabled: typeof agentValue.disabled === "boolean" ? agentValue.disabled : undefined,
|
||||
enabled: typeof agentValue.enabled === "boolean" ? agentValue.enabled : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
return summaries;
|
||||
}
|
||||
|
||||
export function mergeCustomAgentSummaries(...summaryGroups: AgentSummary[][]): AgentSummary[] {
|
||||
const merged = new Map<string, AgentSummary>();
|
||||
|
||||
for (const group of summaryGroups) {
|
||||
for (const summary of group) {
|
||||
const key = summary.name.toLowerCase();
|
||||
if (!merged.has(key)) {
|
||||
merged.set(key, summary);
|
||||
continue;
|
||||
}
|
||||
|
||||
const existing = merged.get(key);
|
||||
if (!existing) continue;
|
||||
|
||||
const existingDescription = existing.description.trim();
|
||||
const incomingDescription = summary.description.trim();
|
||||
|
||||
merged.set(key, {
|
||||
...existing,
|
||||
...summary,
|
||||
hidden: summary.hidden ?? existing.hidden,
|
||||
disabled: summary.disabled ?? existing.disabled,
|
||||
enabled: summary.enabled ?? existing.enabled,
|
||||
description: incomingDescription || existingDescription,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(merged.values());
|
||||
}
|
||||
|
||||
export function collectKnownCustomAgentNames(
|
||||
...agentGroups: Array<Record<string, unknown> | undefined>
|
||||
): Set<string> {
|
||||
const knownNames = new Set<string>();
|
||||
|
||||
for (const group of agentGroups) {
|
||||
if (!group) continue;
|
||||
|
||||
for (const [name, value] of Object.entries(group)) {
|
||||
const normalizedName = getAgentConfigKey(name).toLowerCase();
|
||||
if (RESERVED_AGENT_KEYS.has(normalizedName)) continue;
|
||||
if (!value || typeof value !== "object") continue;
|
||||
|
||||
knownNames.add(normalizedName);
|
||||
}
|
||||
}
|
||||
|
||||
return knownNames;
|
||||
}
|
||||
|
||||
export function filterSummariesByKnownNames(
|
||||
summaries: AgentSummary[],
|
||||
knownNames: Set<string>,
|
||||
): AgentSummary[] {
|
||||
return summaries.filter((summary) => knownNames.has(summary.name.toLowerCase()));
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { CategoryConfig } from "../config/schema";
|
||||
import { PROMETHEUS_PERMISSION, getPrometheusPrompt } from "../agents/prometheus";
|
||||
import { resolvePromptAppend } from "../agents/builtin-agents/resolve-file-uri";
|
||||
import { parseRegisteredAgentSummaries } from "../agents/custom-agent-summaries";
|
||||
import { AGENT_MODEL_REQUIREMENTS } from "../shared/model-requirements";
|
||||
import {
|
||||
fetchAvailableModels,
|
||||
@@ -28,7 +27,6 @@ export async function buildPrometheusAgentConfig(params: {
|
||||
pluginPrometheusOverride: PrometheusOverride | undefined;
|
||||
userCategories: Record<string, CategoryConfig> | undefined;
|
||||
currentModel: string | undefined;
|
||||
customAgentSummaries?: unknown;
|
||||
}): Promise<Record<string, unknown>> {
|
||||
const categoryConfig = params.pluginPrometheusOverride?.category
|
||||
? resolveCategoryConfig(params.pluginPrometheusOverride.category, params.userCategories)
|
||||
@@ -67,18 +65,11 @@ export async function buildPrometheusAgentConfig(params: {
|
||||
const maxTokensToUse =
|
||||
params.pluginPrometheusOverride?.maxTokens ?? categoryConfig?.maxTokens;
|
||||
|
||||
const customAgentCatalog = parseRegisteredAgentSummaries(params.customAgentSummaries)
|
||||
const customAgentBlock = customAgentCatalog.length > 0
|
||||
? `\n\n<custom_agent_catalog>\nAvailable custom agents for planning/delegation:\n${customAgentCatalog
|
||||
.map((agent) => `- ${agent.name}: ${agent.description || "No description provided"}`)
|
||||
.join("\n")}\n</custom_agent_catalog>`
|
||||
: ""
|
||||
|
||||
const base: Record<string, unknown> = {
|
||||
...(resolvedModel ? { model: resolvedModel } : {}),
|
||||
...(variantToUse ? { variant: variantToUse } : {}),
|
||||
mode: "all",
|
||||
prompt: getPrometheusPrompt(resolvedModel) + customAgentBlock,
|
||||
prompt: getPrometheusPrompt(resolvedModel),
|
||||
permission: PROMETHEUS_PERMISSION,
|
||||
description: `${(params.configAgentPlan?.description as string) ?? "Plan agent"} (Prometheus - OhMyOpenCode)`,
|
||||
color: (params.configAgentPlan?.color as string) ?? "#FF5722",
|
||||
@@ -103,12 +94,5 @@ export async function buildPrometheusAgentConfig(params: {
|
||||
if (prompt_append && typeof merged.prompt === "string") {
|
||||
merged.prompt = merged.prompt + "\n" + resolvePromptAppend(prompt_append);
|
||||
}
|
||||
if (
|
||||
customAgentBlock
|
||||
&& typeof merged.prompt === "string"
|
||||
&& !merged.prompt.includes("<custom_agent_catalog>")
|
||||
) {
|
||||
merged.prompt = merged.prompt + customAgentBlock;
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user