Adam 3 недель назад
Родитель
Сommit
5179b87aef

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

@@ -15,7 +15,7 @@ import { retry } from "@opencode-ai/util/retry"
 import { batch } from "solid-js"
 import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
 import type { State, VcsCache } from "./types"
-import { cmp, normalizeProviderList } from "./utils"
+import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
 import { formatServerError } from "@/utils/server-errors"
 
 type GlobalStore = {
@@ -174,7 +174,7 @@ export async function bootstrapDirectory(input: {
       seededProject
         ? Promise.resolve()
         : retry(() => input.sdk.project.current()).then((x) => input.setStore("project", x.data!.id)),
-    () => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", x.data ?? []))),
+    () => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", normalizeAgentList(x.data)))),
     () => retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
     () =>
       retry(() =>

+ 35 - 0
packages/app/src/context/global-sync/utils.test.ts

@@ -0,0 +1,35 @@
+import { describe, expect, test } from "bun:test"
+import type { Agent } from "@opencode-ai/sdk/v2/client"
+import { normalizeAgentList } from "./utils"
+
+const agent = (name = "build") =>
+  ({
+    name,
+    mode: "primary",
+    permission: {},
+    options: {},
+  }) as Agent
+
+describe("normalizeAgentList", () => {
+  test("keeps array payloads", () => {
+    expect(normalizeAgentList([agent("build"), agent("docs")])).toEqual([agent("build"), agent("docs")])
+  })
+
+  test("wraps a single agent payload", () => {
+    expect(normalizeAgentList(agent("docs"))).toEqual([agent("docs")])
+  })
+
+  test("extracts agents from keyed objects", () => {
+    expect(
+      normalizeAgentList({
+        build: agent("build"),
+        docs: agent("docs"),
+      }),
+    ).toEqual([agent("build"), agent("docs")])
+  })
+
+  test("drops invalid payloads", () => {
+    expect(normalizeAgentList({ name: "AbortError" })).toEqual([])
+    expect(normalizeAgentList([{ name: "build" }, agent("docs")])).toEqual([agent("docs")])
+  })
+})

+ 15 - 1
packages/app/src/context/global-sync/utils.ts

@@ -1,7 +1,21 @@
-import type { Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
+import type { Agent, Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
 
 export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)
 
+function isAgent(input: unknown): input is Agent {
+  if (!input || typeof input !== "object") return false
+  const item = input as { name?: unknown; mode?: unknown }
+  if (typeof item.name !== "string") return false
+  return item.mode === "subagent" || item.mode === "primary" || item.mode === "all"
+}
+
+export function normalizeAgentList(input: unknown): Agent[] {
+  if (Array.isArray(input)) return input.filter(isAgent)
+  if (isAgent(input)) return [input]
+  if (!input || typeof input !== "object") return []
+  return Object.values(input).filter(isAgent)
+}
+
 export function normalizeProviderList(input: ProviderListResponse): ProviderListResponse {
   return {
     ...input,