Merge pull request #4081 from PeterPonyu/feat/4004-agent-display-name-i18n

feat(agents): support per-agent displayName for i18n (#4004)
This commit is contained in:
YeonGyu-Kim
2026-05-21 12:58:21 +09:00
committed by GitHub
5 changed files with 80 additions and 6 deletions
@@ -401,6 +401,7 @@ export async function applyAgentConfig(params: {
if (params.config.agent) {
params.config.agent = remapAgentKeysToDisplayNames(
params.config.agent as Record<string, unknown>,
params.pluginConfig.agents as Record<string, { displayName?: string } | undefined> | undefined,
);
params.config.agent = reorderAgentsByPriority(
params.config.agent as Record<string, unknown>,
@@ -197,4 +197,54 @@ describe("remapAgentKeysToDisplayNames", () => {
foo: "bar",
})
})
describe("displayName i18n override (#4004)", () => {
it("uses per-agent displayName override when set", () => {
// given sisyphus config with a Chinese displayName override
const agents = {
sisyphus: { prompt: "test", mode: "primary" },
}
const overrides = {
sisyphus: { displayName: "总指挥" },
}
// when remapping with overrides
const result = remapAgentKeysToDisplayNames(agents, overrides)
// then the localized name is used instead of "Sisyphus - Ultraworker"
expect(result["总指挥"]).toBeDefined()
expect((result["总指挥"] as Record<string, unknown>).name).toBe("总指挥")
expect(result["Sisyphus - Ultraworker"]).toBeUndefined()
})
it("falls back to hardcoded English name when displayName is not set", () => {
// given sisyphus config without displayName override
const agents = {
sisyphus: { prompt: "test", mode: "primary" },
}
const overrides = {
sisyphus: { model: "claude-opus-4-7" },
}
// when remapping with overrides that have no displayName
const result = remapAgentKeysToDisplayNames(agents, overrides)
// then the legacy AGENT_DISPLAY_NAMES value is used
expect(result["Sisyphus - Ultraworker"]).toBeDefined()
expect(result["总指挥"]).toBeUndefined()
})
it("falls back to hardcoded English name when no overrides are passed", () => {
// given sisyphus config with no overrides at all
const agents = {
sisyphus: { prompt: "test", mode: "primary" },
}
// when remapping without overrides
const result = remapAgentKeysToDisplayNames(agents)
// then the legacy AGENT_DISPLAY_NAMES value is used
expect(result["Sisyphus - Ultraworker"]).toBeDefined()
})
})
})
+7 -3
View File
@@ -1,8 +1,11 @@
import { getAgentListDisplayName } from "../shared/agent-display-names"
type AgentOverridesMap = Record<string, { displayName?: string } | undefined>
function rewriteAgentNameForListDisplay(
key: string,
value: unknown,
overrides?: AgentOverridesMap,
): unknown {
if (typeof value !== "object" || value === null) {
return value
@@ -11,19 +14,20 @@ function rewriteAgentNameForListDisplay(
const agent = value as Record<string, unknown>
return {
...agent,
name: getAgentListDisplayName(key),
name: getAgentListDisplayName(key, overrides),
}
}
export function remapAgentKeysToDisplayNames(
agents: Record<string, unknown>,
overrides?: AgentOverridesMap,
): Record<string, unknown> {
const result: Record<string, unknown> = {}
for (const [key, value] of Object.entries(agents)) {
const displayName = getAgentListDisplayName(key)
const displayName = getAgentListDisplayName(key, overrides)
if (displayName && displayName !== key) {
result[displayName] = rewriteAgentNameForListDisplay(key, value)
result[displayName] = rewriteAgentNameForListDisplay(key, value, overrides)
// Regression guard: do not also assign result[key].
// This line was repeatedly re-added and caused duplicate agent rows in the UI.
// Runtime callers that previously depended on config-key aliases were fixed in: