From 273f69eb0528e045ca6446ff0e3e4b416019ba24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Sat, 23 May 2026 20:44:09 -0400 Subject: [PATCH] Add provider request control surface --- .../src/renderer/src/pages/SettingsPage.tsx | 1 + .../pages/settings/ProviderRequestPanel.tsx | 199 ++++++++++++++++++ .../src/pages/settings/ProvidersPanel.tsx | 12 +- AgentCompany-New/tests/e2e/desktop.spec.ts | 7 + 4 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 AgentCompany-New/src/renderer/src/pages/settings/ProviderRequestPanel.tsx diff --git a/AgentCompany-New/src/renderer/src/pages/SettingsPage.tsx b/AgentCompany-New/src/renderer/src/pages/SettingsPage.tsx index c016a0d7..44581c1b 100644 --- a/AgentCompany-New/src/renderer/src/pages/SettingsPage.tsx +++ b/AgentCompany-New/src/renderer/src/pages/SettingsPage.tsx @@ -135,6 +135,7 @@ export function SettingsPage({ snapshot, actions }: PageProps) { catalog={snapshot.providerCatalog} agents={agents} providerRateLimits={providerRateLimits} + providerRequests={providerRequests} actions={actions} /> )} diff --git a/AgentCompany-New/src/renderer/src/pages/settings/ProviderRequestPanel.tsx b/AgentCompany-New/src/renderer/src/pages/settings/ProviderRequestPanel.tsx new file mode 100644 index 00000000..be8141f3 --- /dev/null +++ b/AgentCompany-New/src/renderer/src/pages/settings/ProviderRequestPanel.tsx @@ -0,0 +1,199 @@ +import { useState, type FormEvent } from "react"; +import type { ProviderCatalogEntry, ProviderRecord, ProviderRequestRecord } from "../../../../shared/domain"; +import { PROVIDER_DATA_POLICY, PROVIDER_EXECUTION_MODE, PROVIDER_REQUEST_STATE, type ProviderExecutionMode } from "../../../../shared/domain"; +import type { SnapshotActions } from "../../app/useSnapshot"; +import { Button, Field, Icon, Pill, Segmented } from "../../shared/ui"; + +interface ProviderRequestPanelProps { + orgId: string; + providers: ProviderRecord[]; + catalog: ProviderCatalogEntry[]; + providerRequests: ProviderRequestRecord[]; + actions: SnapshotActions; +} + +const MODE_OPTIONS: ReadonlyArray<{ id: ProviderExecutionMode; label: string }> = [ + { id: PROVIDER_EXECUTION_MODE.FOREGROUND, label: "Foreground" }, + { id: PROVIDER_EXECUTION_MODE.BACKGROUND, label: "Background" }, +]; + +const ACTIVE_REQUEST_STATES = new Set([ + PROVIDER_REQUEST_STATE.PENDING, + PROVIDER_REQUEST_STATE.STREAMING, +]); + +export function ProviderRequestPanel({ + orgId, + providers, + catalog, + providerRequests, + actions, +}: ProviderRequestPanelProps) { + const executableProviders = providers.filter((provider) => provider.enabled && provider.authType === "api_key"); + const [providerId, setProviderId] = useState(executableProviders[0]?.id ?? ""); + const [mode, setMode] = useState(PROVIDER_EXECUTION_MODE.FOREGROUND); + const selectedProvider = resolveSelectedProvider(executableProviders, providerId); + const canRunBackground = selectedProvider ? isBackgroundReady(selectedProvider, catalog) : false; + const selectedMode = canRunBackground ? mode : PROVIDER_EXECUTION_MODE.FOREGROUND; + const recentRequests = providerRequests + .filter((request) => executableProviders.some((provider) => provider.id === request.providerId)) + .slice(0, 8); + + if (executableProviders.length === 0) return null; + + const submit = (event: FormEvent) => { + event.preventDefault(); + const form = new FormData(event.currentTarget); + const prompt = String(form.get("prompt") ?? "").trim(); + if (!prompt) throw new Error("Prompt is required."); + const instructions = String(form.get("instructions") ?? "").trim(); + const formElement = event.currentTarget; + void actions.run(() => window.agentCompany.createProviderResponse({ + orgId, + providerId: requireProviderId(selectedProvider), + prompt, + instructions: instructions || null, + executionMode: selectedMode, + })).then((result) => { if (result) formElement.reset(); }); + }; + + return ( + <> +
Requests
+
+
+ + + +
+ Mode +
+ +
+
+ +
+ +