Skip to content

Commit 5179b87

Browse files
authored
fix(app): agent normalization (anomalyco#19169)
1 parent 66a5655 commit 5179b87

3 files changed

Lines changed: 52 additions & 3 deletions

File tree

packages/app/src/context/global-sync/bootstrap.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { retry } from "@opencode-ai/util/retry"
1515
import { batch } from "solid-js"
1616
import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
1717
import type { State, VcsCache } from "./types"
18-
import { cmp, normalizeProviderList } from "./utils"
18+
import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
1919
import { formatServerError } from "@/utils/server-errors"
2020

2121
type GlobalStore = {
@@ -174,7 +174,7 @@ export async function bootstrapDirectory(input: {
174174
seededProject
175175
? Promise.resolve()
176176
: retry(() => input.sdk.project.current()).then((x) => input.setStore("project", x.data!.id)),
177-
() => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", x.data ?? []))),
177+
() => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", normalizeAgentList(x.data)))),
178178
() => retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
179179
() =>
180180
retry(() =>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, expect, test } from "bun:test"
2+
import type { Agent } from "@opencode-ai/sdk/v2/client"
3+
import { normalizeAgentList } from "./utils"
4+
5+
const agent = (name = "build") =>
6+
({
7+
name,
8+
mode: "primary",
9+
permission: {},
10+
options: {},
11+
}) as Agent
12+
13+
describe("normalizeAgentList", () => {
14+
test("keeps array payloads", () => {
15+
expect(normalizeAgentList([agent("build"), agent("docs")])).toEqual([agent("build"), agent("docs")])
16+
})
17+
18+
test("wraps a single agent payload", () => {
19+
expect(normalizeAgentList(agent("docs"))).toEqual([agent("docs")])
20+
})
21+
22+
test("extracts agents from keyed objects", () => {
23+
expect(
24+
normalizeAgentList({
25+
build: agent("build"),
26+
docs: agent("docs"),
27+
}),
28+
).toEqual([agent("build"), agent("docs")])
29+
})
30+
31+
test("drops invalid payloads", () => {
32+
expect(normalizeAgentList({ name: "AbortError" })).toEqual([])
33+
expect(normalizeAgentList([{ name: "build" }, agent("docs")])).toEqual([agent("docs")])
34+
})
35+
})

packages/app/src/context/global-sync/utils.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1-
import type { Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
1+
import type { Agent, Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
22

33
export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)
44

5+
function isAgent(input: unknown): input is Agent {
6+
if (!input || typeof input !== "object") return false
7+
const item = input as { name?: unknown; mode?: unknown }
8+
if (typeof item.name !== "string") return false
9+
return item.mode === "subagent" || item.mode === "primary" || item.mode === "all"
10+
}
11+
12+
export function normalizeAgentList(input: unknown): Agent[] {
13+
if (Array.isArray(input)) return input.filter(isAgent)
14+
if (isAgent(input)) return [input]
15+
if (!input || typeof input !== "object") return []
16+
return Object.values(input).filter(isAgent)
17+
}
18+
519
export function normalizeProviderList(input: ProviderListResponse): ProviderListResponse {
620
return {
721
...input,

0 commit comments

Comments
 (0)