diff --git a/packages/opencode/src/config/agent.ts b/packages/opencode/src/config/agent.ts index a6719e86743a..57438f6f717e 100644 --- a/packages/opencode/src/config/agent.ts +++ b/packages/opencode/src/config/agent.ts @@ -38,7 +38,7 @@ const AgentSchema = Schema.StructWithRest( description: "Hide this subagent from the @ autocomplete menu (default: false, only applies to mode: subagent)", }), options: Schema.optional(Schema.Record(Schema.String, Schema.Any)), - color: Schema.optional(Color).annotate({ + color: Schema.optional(Schema.NullOr(Color)).annotate({ description: "Hex color code (e.g., #FF5733) or theme color (e.g., primary)", }), steps: Schema.optional(PositiveInt).annotate({ @@ -93,7 +93,9 @@ const normalize = (agent: Schema.Schema.Type): Schema.Schema globalThis.Object.assign(permission, agent.permission) const steps = agent.steps ?? agent.maxSteps - return { ...agent, options, permission, ...(steps !== undefined ? { steps } : {}) } + const result = { ...agent, options, permission, ...(steps !== undefined ? { steps } : {}) } + if (result.color === null) delete result.color + return result } export const Info = AgentSchema.pipe( diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index 4d3ed45d2fc6..664229e23a1a 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -912,6 +912,44 @@ Nested agent prompt`, }) }) +test("loads many agents when unquoted hex colors parse as null", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const agentsDir = path.join(dir, ".opencode", "agents") + await fs.mkdir(agentsDir, { recursive: true }) + + for (let i = 0; i < 184; i++) { + const name = `agent-${String(i).padStart(3, "0")}` + await Filesystem.write( + path.join(agentsDir, `${name}.md`), + `--- +name: ${name} +description: Test agent +mode: subagent +color: #9B59B6 +--- +Agent prompt`, + ) + } + }, + }) + + await withTestInstance({ + directory: tmp.path, + fn: async (ctx) => { + const config = await load(ctx) + + expect(Object.keys(config.agent ?? {}).filter((name) => name.startsWith("agent-"))).toHaveLength(184) + expect(config.agent?.["agent-183"]).toMatchObject({ + name: "agent-183", + mode: "subagent", + prompt: "Agent prompt", + }) + expect(config.agent?.["agent-183"]?.color).toBeUndefined() + }, + }) +}) + test("loads commands from .opencode/command (singular)", async () => { await using tmp = await tmpdir({ init: async (dir) => {