diff --git a/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx b/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx index 6a1086bd..08518ad5 100644 --- a/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx +++ b/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx @@ -18,6 +18,8 @@ function optional(form: FormData, key: string): string | null { export function TeamPage({ snapshot, actions }: PageProps) { const orgId = activeOrgId(snapshot); const [hireOpen, setHireOpen] = useState(false); + const [hireProviderId, setHireProviderId] = useState(""); + const [hireModelId, setHireModelId] = useState(""); const [editAgentId, setEditAgentId] = useState(null); const [filter, setFilter] = useState<"all" | "human" | "agent">("all"); @@ -27,24 +29,45 @@ export function TeamPage({ snapshot, actions }: PageProps) { () => snapshot.providers.filter((provider) => provider.orgId === orgId && provider.enabled), [snapshot.providers, orgId], ); + const workspaces = useMemo(() => snapshot.workspaces.filter((workspace) => workspace.orgId === orgId), [snapshot.workspaces, orgId]); + const primaryWorkspace = useMemo( + () => workspaces.find((workspace) => workspace.isPrimary) ?? workspaces[0] ?? null, + [workspaces], + ); + + const openHireDialog = () => { + const provider = providers[0] ?? null; + setHireProviderId(provider?.id ?? ""); + setHireModelId(provider?.model ?? ""); + setHireOpen(true); + }; + + const updateHireProvider = (providerId: string) => { + const provider = providers.find((item) => item.id === providerId) ?? null; + setHireProviderId(providerId); + setHireModelId(provider?.model ?? ""); + }; const submit = (event: FormEvent) => { event.preventDefault(); const form = new FormData(event.currentTarget); + const selectedProvider = providers.find((provider) => provider.id === hireProviderId) ?? null; + const modelId = selectedProvider ? hireModelId.trim() || selectedProvider.model : null; void actions.run(() => window.agentCompany.createAgent({ orgId, name: text(form, "name"), role: text(form, "role"), department: text(form, "department"), - modelProviderId: optional(form, "modelProviderId"), - modelId: optional(form, "modelId"), + modelProviderId: selectedProvider?.id ?? null, + modelId, budgetCents: Math.max(0, Math.round(Number(text(form, "budget")) * 100)), managerAgentId: optional(form, "managerAgentId"), title: text(form, "title") || text(form, "role"), roleLevel: text(form, "roleLevel") || "staff", - modelStrategy: text(form, "modelId") ? "explicit" : "pooled", - heartbeatEnabled: false, - heartbeatIntervalSec: 0, + modelStrategy: selectedProvider ? "explicit" : "pooled", + workspaceId: primaryWorkspace?.id ?? null, + heartbeatEnabled: Boolean(selectedProvider), + heartbeatIntervalSec: selectedProvider ? 120 : 0, })).then((result) => { if (result) setHireOpen(false); }); }; @@ -73,7 +96,7 @@ export function TeamPage({ snapshot, actions }: PageProps) { - +

Team

@@ -111,13 +134,13 @@ export function TeamPage({ snapshot, actions }: PageProps) { - updateHireProvider(event.currentTarget.value)}> {providers.map((provider) => )} - + setHireModelId(event.currentTarget.value)} /> diff --git a/AgentCompany-New/tests/e2e/desktop.spec.ts b/AgentCompany-New/tests/e2e/desktop.spec.ts index be05e6dd..f47d9792 100644 --- a/AgentCompany-New/tests/e2e/desktop.spec.ts +++ b/AgentCompany-New/tests/e2e/desktop.spec.ts @@ -42,6 +42,31 @@ test("onboards, hires, and creates work in the Electron shell", async () => { await page.getByLabel("Monthly budget").fill("250"); await page.locator(".modal").getByRole("button", { name: "Hire" }).click(); await expect(page.getByText("Alex Chen").first()).toBeVisible(); + const hiredAgent = await page.evaluate(async () => { + const api = (window as unknown as { agentCompany: { loadSnapshot: () => Promise } }).agentCompany; + const result = await api.loadSnapshot() as { + ok: true; + data: { + agents: Array<{ name: string; modelProviderId: string | null; modelId: string | null; workspaceId: string | null; heartbeatEnabled: boolean; heartbeatIntervalSec: number }>; + workspaces: Array<{ id: string; isPrimary: boolean }>; + }; + }; + const agent = result.data.agents.find((item) => item.name === "Alex Chen"); + const primaryWorkspace = result.data.workspaces.find((item) => item.isPrimary) ?? null; + return { + modelProviderId: agent?.modelProviderId ?? null, + modelId: agent?.modelId ?? null, + workspaceId: agent?.workspaceId ?? null, + heartbeatEnabled: agent?.heartbeatEnabled ?? false, + heartbeatIntervalSec: agent?.heartbeatIntervalSec ?? 0, + primaryWorkspaceId: primaryWorkspace?.id ?? null, + }; + }); + expect(hiredAgent.modelProviderId).toBeTruthy(); + expect(hiredAgent.modelId).toBe("gpt-5.4"); + expect(hiredAgent.workspaceId).toBe(hiredAgent.primaryWorkspaceId); + expect(hiredAgent.heartbeatEnabled).toBe(true); + expect(hiredAgent.heartbeatIntervalSec).toBe(120); await page.getByRole("button", { name: "Settings" }).click(); await page.getByRole("button", { name: "Members" }).click(); await expect(page.getByText("Identity & Access")).toBeVisible();