diff --git a/src/app/AgentSettings.tsx b/src/app/AgentSettings.tsx index 4ff1962ca7..8a5ef62470 100644 --- a/src/app/AgentSettings.tsx +++ b/src/app/AgentSettings.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import type { Agents } from "../features/agents/service"; +import type { AgentsClient } from "../features/agents/service"; import { AgentDefaults } from "../bundled/agents/AgentDefaults"; import { Header, InlineHeader } from "../shared/design-system/ui/Header"; @@ -16,7 +16,7 @@ export function AgentSettings({ agents, active = true, }: { - agents?: Agents | undefined; + agents?: AgentsClient | undefined; active?: boolean; }) { const rememberAgents = useRememberAgentsPreference(); diff --git a/src/app/DecisionsSettings.tsx b/src/app/DecisionsSettings.tsx index f63fa3610d..ebfa8a4293 100644 --- a/src/app/DecisionsSettings.tsx +++ b/src/app/DecisionsSettings.tsx @@ -1,5 +1,5 @@ import { useState, useSyncExternalStore } from "react"; -import type { Agents, AgentsSnapshot } from "../features/agents/service"; +import type { AgentsClient, AgentsSnapshot } from "../features/agents/service"; import { isApplePlatform } from "../features/shortcuts/format"; import { Button } from "../shared/design-system/ui/Button"; import { Field } from "../shared/design-system/ui/Field"; @@ -28,7 +28,7 @@ export function DecisionsSettings({ apple = isApplePlatform(navigator.platform), }: { agents: Pick< - Agents, + AgentsClient, "snapshot" | "subscribe" | "setClassifierKey" | "clearClassifierKey" >; active(): boolean; diff --git a/src/app/Settings.tsx b/src/app/Settings.tsx index 7b13b26a71..c96fe599c8 100644 --- a/src/app/Settings.tsx +++ b/src/app/Settings.tsx @@ -11,7 +11,7 @@ import { } from "motion/react"; import { SidebarNavigation } from "../shared/design-system/ui/SidebarNavigation"; import { CommunityAddress } from "./CommunityAddress"; -import type { Agents } from "../features/agents/service"; +import type { AgentsClient } from "../features/agents/service"; import type { DecisionsService } from "../features/decisions/service"; import { DecisionsSettings } from "./DecisionsSettings"; import { Header, InlineHeader } from "../shared/design-system/ui/Header"; @@ -595,7 +595,7 @@ export function Settings({ onDeparturePending, onUnsavedChange, }: { - agents?: Agents | undefined; + agents?: AgentsClient | undefined; decisions?: DecisionsService | undefined; cards: SettingsCards; plugins: PluginManager; diff --git a/src/app/shell/NewMenu.tsx b/src/app/shell/NewMenu.tsx index 2c90094a76..33cf3e5a44 100644 --- a/src/app/shell/NewMenu.tsx +++ b/src/app/shell/NewMenu.tsx @@ -1,5 +1,5 @@ import { useRef, useState, useSyncExternalStore } from "react"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { CreateChannelDialog } from "../../bundled/channels/CreateChannelDialog"; import { revealCreatedChannel } from "../../features/channel-navigation/created-channel"; import { useSidebarPreferences } from "../../bundled/channels/useSidebarPreferences"; @@ -24,7 +24,7 @@ import { PlusIcon } from "../../shared/design-system/icons"; type Props = { relay: RelayData; navigator: Navigation; - agents?: Agents | undefined; + agents?: AgentsClient | undefined; }; export function NewMenu(props: Props) { diff --git a/src/app/shell/PrimarySidebar.tsx b/src/app/shell/PrimarySidebar.tsx index 9cead2022a..d6e8f8b6e9 100644 --- a/src/app/shell/PrimarySidebar.tsx +++ b/src/app/shell/PrimarySidebar.tsx @@ -15,7 +15,7 @@ import { ResizableSidebar } from "../../features/channel-navigation/ResizableSid import { SidebarUnread } from "../../bundled/channels/SidebarUnread"; import { Button } from "../../shared/design-system/ui/Button"; import type { RelayData } from "../../features/relay/service"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import type { Navigation } from "../../features/navigation/controller"; import type { OpenTarget } from "../../features/navigation/targets"; import { InlineHeader } from "../../shared/design-system/ui/Header"; @@ -42,7 +42,7 @@ const filters = [ type Props = { relay: RelayData; navigator: Navigation; - agents?: Agents | undefined; + agents?: AgentsClient | undefined; chatIcons?: ContributionReader | undefined; chatMenus?: ContributionReader | undefined; target: OpenTarget; diff --git a/src/app/shell/sidebar-testing.tsx b/src/app/shell/sidebar-testing.tsx index c79c51939c..48d2ce4d81 100644 --- a/src/app/shell/sidebar-testing.tsx +++ b/src/app/shell/sidebar-testing.tsx @@ -9,7 +9,7 @@ import type { Navigation } from "../../features/navigation/controller"; import { ChannelNavigationProvider } from "../../features/channel-navigation/ChannelNavigationState"; import type { OpenTarget } from "../../features/navigation/targets"; import { NewMenu } from "./NewMenu"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { PrimarySidebar } from "./PrimarySidebar"; import { ToastProvider } from "../../shared/design-system/ui/Toast"; import { SoloInventory } from "../../features/channel-navigation/SoloInventory"; @@ -28,7 +28,7 @@ export const scope = `https://relay.test:${viewer}`; export function fixture( combined = false, canCreate = false, - agents?: Agents, + agents?: AgentsClient, counts = { observedCount: 2, attentionCount: 1 }, /** Newer, read Solo chats ahead of Planning and Other; only Planning is unread. */ newer = 0, diff --git a/src/bundled/agent-activity/ActivityAccessory.tsx b/src/bundled/agent-activity/ActivityAccessory.tsx index c3b9266ce2..970be37b72 100644 --- a/src/bundled/agent-activity/ActivityAccessory.tsx +++ b/src/bundled/agent-activity/ActivityAccessory.tsx @@ -32,7 +32,7 @@ import { import { currentActivity } from "./current-activity"; import { messageWork } from "./message-activity"; import type { ActivityTurn } from "../../features/agents/activity"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { requestWork, type RequestWork, @@ -50,7 +50,7 @@ const noSubscribe = () => () => {}; * its provider may never report the turn's end. */ const HOSTED_STOP_MS = 30_000; /** What Stop needs of Agents: a hosted agent's provider stops its turns. */ -export type ActivityAgents = Pick; +export type ActivityAgents = Pick; type ActivityProps = ComposerAccessoryProps & { agents?: ActivityAgents }; /** Activity belongs to the exact triggering message, not the composer. */ export function ActivityAccessory(props: ActivityProps) { diff --git a/src/bundled/agents/AgentBrowse.tsx b/src/bundled/agents/AgentBrowse.tsx index c87f27dbe1..d1805031ff 100644 --- a/src/bundled/agents/AgentBrowse.tsx +++ b/src/bundled/agents/AgentBrowse.tsx @@ -12,7 +12,7 @@ import { flushSync } from "react-dom"; import { AGENT_CATALOG_KIND } from "../../features/agents/catalog-envelope"; import { ModelIcon } from "../../features/agents/ModelPicker"; import type { - Agents, + AgentsClient, RegisteredAgentType, } from "../../features/agents/service"; import { @@ -49,7 +49,7 @@ import styles from "./AgentBrowse.module.css"; const pageSize = 200; type Importing = Readonly<{ - agents: Agents; + agents: AgentsClient; /** The types an import can be, which run on this computer. */ types: readonly RegisteredAgentType[]; onImported(): void; diff --git a/src/bundled/agents/AgentCreateDialog.tsx b/src/bundled/agents/AgentCreateDialog.tsx index bc5caab460..4d18e60747 100644 --- a/src/bundled/agents/AgentCreateDialog.tsx +++ b/src/bundled/agents/AgentCreateDialog.tsx @@ -3,7 +3,7 @@ import { useId, useRef, useState } from "react"; import { randomAgentAvatar } from "../../features/agents/avatar-packs"; import type { Agent, - Agents, + AgentsClient, RegisteredAgentType, NewAgent, AgentCreationRequest, @@ -60,7 +60,7 @@ export function AgentCreateDialog({ onCreate, update, }: { - agents: Agents; + agents: AgentsClient; types: readonly RegisteredAgentType[]; community?: string | undefined; onClose(): void; diff --git a/src/bundled/agents/AgentDefaults.tsx b/src/bundled/agents/AgentDefaults.tsx index f4f8db1496..83cd29fe9d 100644 --- a/src/bundled/agents/AgentDefaults.tsx +++ b/src/bundled/agents/AgentDefaults.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState, useSyncExternalStore } from "react"; import type { - Agents, + AgentsClient, RegisteredAgentType, } from "../../features/agents/service"; import { @@ -14,7 +14,7 @@ import { PreferenceRow } from "../../shared/design-system/ui/PreferenceRow"; import { SettingsGroup } from "../../shared/design-system/ui/SettingsGroup"; import { ProviderDialog } from "./ProviderDialog"; -export function AgentDefaults({ agents }: { agents: Agents }) { +export function AgentDefaults({ agents }: { agents: AgentsClient }) { const types = useSyncExternalStore( agents.subscribe, agents.types, diff --git a/src/bundled/agents/AgentDetails.tsx b/src/bundled/agents/AgentDetails.tsx index 82ee6a75cb..5ab46692d8 100644 --- a/src/bundled/agents/AgentDetails.tsx +++ b/src/bundled/agents/AgentDetails.tsx @@ -17,7 +17,7 @@ import type { ChannelChoice } from "../../features/agents/attention"; import type { AgentMemories } from "../../features/agents/MemoryPanel"; import type { Agent, - Agents, + AgentsClient, AgentConversation, RegisteredAgentType, } from "../../features/agents/service"; @@ -69,7 +69,7 @@ export function AgentDetails({ conversation, initialActivity, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; types: readonly RegisteredAgentType[]; diff --git a/src/bundled/agents/AgentIdentityDialog.tsx b/src/bundled/agents/AgentIdentityDialog.tsx index 28882b01b6..a5326974c7 100644 --- a/src/bundled/agents/AgentIdentityDialog.tsx +++ b/src/bundled/agents/AgentIdentityDialog.tsx @@ -7,7 +7,7 @@ import { type RefObject, } from "react"; import { useReducedMotion } from "motion/react"; -import type { Agent, Agents } from "../../features/agents/service"; +import type { Agent, AgentsClient } from "../../features/agents/service"; import { Button } from "../../shared/design-system/ui/Button"; import { Dialog } from "../../shared/design-system/ui/Dialog"; import { AgentCreateHeader } from "./AgentCreateHeader"; @@ -22,7 +22,7 @@ export function AgentIdentityDialog({ initialAvatarPicker = false, }: { agent: Agent; - agents: Agents; + agents: AgentsClient; onClose(): void; finalFocus: RefObject; initialAvatarPicker?: boolean; diff --git a/src/bundled/agents/AgentSettingsHost.tsx b/src/bundled/agents/AgentSettingsHost.tsx index 63b56f7666..c61f873552 100644 --- a/src/bundled/agents/AgentSettingsHost.tsx +++ b/src/bundled/agents/AgentSettingsHost.tsx @@ -3,7 +3,7 @@ import { useRef, useState } from "react"; import type { Agent, AgentSettingsHost, - Agents, + AgentsClient, Carry, RegisteredAgentType, } from "../../features/agents/service"; @@ -26,7 +26,7 @@ const message = (error: unknown) => /** One settings composition for both the Agents page and profile panes. */ export function useAgentSettingsHost(options: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; types: readonly RegisteredAgentType[]; @@ -36,7 +36,7 @@ export function useAgentSettingsHost(options: { settingsHost: AgentSettingsHost; }; export function useAgentSettingsHost(options: { - agents: Agents | undefined; + agents: AgentsClient | undefined; agent: Agent | undefined; type: RegisteredAgentType | undefined; types: readonly RegisteredAgentType[]; @@ -51,7 +51,7 @@ export function useAgentSettingsHost({ type, types, }: { - agents: Agents | undefined; + agents: AgentsClient | undefined; agent: Agent | undefined; type: RegisteredAgentType | undefined; types: readonly RegisteredAgentType[]; @@ -124,7 +124,7 @@ function TypeField({ selected, onSelect, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; types: readonly RegisteredAgentType[]; @@ -143,7 +143,7 @@ function TypeField({ const [configuring, setConfiguring] = useState(false); const [migration, setMigration] = useState<{ target: RegisteredAgentType; - preview: ReturnType; + preview: ReturnType; }>(); const choose = (next: string) => { if (next === selected) return; @@ -312,7 +312,7 @@ export function MigrationPreview({ }: { source: RegisteredAgentType | undefined; target: RegisteredAgentType; - preview: ReturnType; + preview: ReturnType; discardDraft: boolean; }) { const SourceIcon = source?.icon; diff --git a/src/bundled/agents/AgentTabs.tsx b/src/bundled/agents/AgentTabs.tsx index b5ea8cbc63..7aa30617bf 100644 --- a/src/bundled/agents/AgentTabs.tsx +++ b/src/bundled/agents/AgentTabs.tsx @@ -4,7 +4,7 @@ import type { Agent, AgentConversation, AgentSettingsHost, - Agents, + AgentsClient, RegisteredAgentType, } from "../../features/agents/service"; import type { AgentMemories } from "../../features/agents/MemoryPanel"; @@ -13,7 +13,7 @@ import { Tabs } from "../../shared/design-system/ui/Tabs"; /** An agent's sections as tabs, opening on the first. */ export function AgentTabs(props: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; channels: readonly ChannelChoice[]; diff --git a/src/bundled/agents/AgentsPage.tsx b/src/bundled/agents/AgentsPage.tsx index f61d3f960b..2858b1813d 100644 --- a/src/bundled/agents/AgentsPage.tsx +++ b/src/bundled/agents/AgentsPage.tsx @@ -39,7 +39,7 @@ import type { } from "../../features/agents/native"; import type { Agent, - Agents, + AgentsClient, FoundAgents, RegisteredAgentType, Team, @@ -135,7 +135,7 @@ export function AgentsPage({ navigation, navigator, }: { - agents: Agents; + agents: AgentsClient; relay: RelayData; navigation?: PageNavigation; navigator?: Navigation; @@ -611,7 +611,7 @@ export function AgentsPage({ } type InventoryProps = { - service: Agents; + service: AgentsClient; agents: readonly Agent[]; selected: string | undefined; typeOf(agent: Agent): RegisteredAgentType | undefined; @@ -861,7 +861,7 @@ function InventoryCard({ ...props }: Omit, "agent"> & { agent: Agent; - service: Agents; + service: AgentsClient; type: RegisteredAgentType | undefined; onBuild(): void; onRemoved(): void; @@ -1024,7 +1024,7 @@ function AgentPeek({ channels, onClose, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; channels: readonly ChannelChoice[]; @@ -1164,7 +1164,7 @@ function ImportAgents({ onImported, onPendingChange, }: { - agents: Agents; + agents: AgentsClient; types: readonly RegisteredAgentType[]; /** The section its entry point imports. */ only: "agents" | "teams"; @@ -1599,7 +1599,7 @@ function Teams({ onEdit, newTeam, }: { - agents: Agents; + agents: AgentsClient; saved: readonly Agent[]; teams: readonly Team[]; /** A team's id while it is edited, or "new" for one being made. */ @@ -1653,7 +1653,7 @@ function TeamEditor({ team, onDone, }: { - agents: Agents; + agents: AgentsClient; saved: readonly Agent[]; team?: Team; onDone(): void; diff --git a/src/bundled/agents/CreationReview.tsx b/src/bundled/agents/CreationReview.tsx index c467add9a4..1dcc19272b 100644 --- a/src/bundled/agents/CreationReview.tsx +++ b/src/bundled/agents/CreationReview.tsx @@ -1,9 +1,9 @@ import { useSyncExternalStore } from "react"; import { AgentCreateDialog } from "./AgentCreateDialog"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; /** The owner reviews the same creation form as a manually started agent. */ -export function CreationReview({ agents }: { agents: Agents }) { +export function CreationReview({ agents }: { agents: AgentsClient }) { const requests = useSyncExternalStore( agents.subscribe, agents.creationRequests, diff --git a/src/bundled/agents/UpdateReview.tsx b/src/bundled/agents/UpdateReview.tsx index d47fa3d561..37ca14b9bf 100644 --- a/src/bundled/agents/UpdateReview.tsx +++ b/src/bundled/agents/UpdateReview.tsx @@ -1,10 +1,10 @@ import { useState, useSyncExternalStore } from "react"; import { AgentCreateDialog } from "./AgentCreateDialog"; -import type { Agent, Agents } from "../../features/agents/service"; +import type { Agent, AgentsClient } from "../../features/agents/service"; /** The owner reviews another agent's proposed changes in the same form as a * new agent, filled in with the agent's settings. */ -export function UpdateReview({ agents }: { agents: Agents }) { +export function UpdateReview({ agents }: { agents: AgentsClient }) { const requests = useSyncExternalStore( agents.subscribe, agents.updateRequests, diff --git a/src/bundled/channels/ChannelMembersDialog.tsx b/src/bundled/channels/ChannelMembersDialog.tsx index b1f5f1193d..ddd1c4d374 100644 --- a/src/bundled/channels/ChannelMembersDialog.tsx +++ b/src/bundled/channels/ChannelMembersDialog.tsx @@ -18,7 +18,7 @@ import { } from "react"; import type { RelaySession } from "../../features/relay/session"; import type { Navigation } from "../../features/navigation/controller"; -import type { Agents, Team } from "../../features/agents/service"; +import type { AgentsClient, Team } from "../../features/agents/service"; import { useAgentChoices } from "../../features/agents/use-choices"; import { useIdentityNames } from "../../features/identity-names/react"; import { usePresenceStatus } from "../../features/presence/react"; @@ -332,7 +332,7 @@ export function ChannelMembersButton({ label?: string; /** Someone else's Solo chat names its owner on the Access control. */ owner?: { name: string; picture?: string | undefined } | undefined; - agents?: Agents | undefined; + agents?: AgentsClient | undefined; navigator?: Navigation | undefined; signal?: AbortSignal | undefined; presentation?: @@ -452,7 +452,7 @@ export function ChannelMembersDialog({ trigger: RefObject; title?: string; description?: string; - agents?: Agents; + agents?: AgentsClient; navigator?: Navigation | undefined; /** The visit that opened this dialog; leaving it retires late results. */ signal?: AbortSignal | undefined; diff --git a/src/bundled/channels/ChannelTemplateSettings.tsx b/src/bundled/channels/ChannelTemplateSettings.tsx index d9080dda40..84b8e72935 100644 --- a/src/bundled/channels/ChannelTemplateSettings.tsx +++ b/src/bundled/channels/ChannelTemplateSettings.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useAgentsSnapshot, useTeams } from "../../features/agents/react"; -import type { Agent, Agents, Team } from "../../features/agents/service"; +import type { Agent, AgentsClient, Team } from "../../features/agents/service"; import { channelTemplates, useChannelTemplates, @@ -26,7 +26,7 @@ export function ChannelTemplateSettings({ agents, active, }: { - agents?: Agents | undefined; + agents?: AgentsClient | undefined; active(): boolean; }) { const templates = useChannelTemplates(); diff --git a/src/bundled/channels/ChannelsPage.tsx b/src/bundled/channels/ChannelsPage.tsx index f071169555..5142579512 100644 --- a/src/bundled/channels/ChannelsPage.tsx +++ b/src/bundled/channels/ChannelsPage.tsx @@ -5,7 +5,7 @@ import { } from "../../features/solo/linked-chat"; import { EmptyState } from "../../shared/design-system/ui/EmptyState"; import { profileActivityViewTarget } from "../../features/profiles/target"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { SoloDraft } from "../../features/solo/SoloDraft"; import { useChannelNavigation } from "../../features/channel-navigation/ChannelNavigationState"; import { soloSuccessor } from "../../features/channel-navigation/solo-successor"; @@ -110,7 +110,7 @@ export function ChannelsPage({ }: { extensions?: ConversationExtensions | undefined; /** For adding a whole team of the owner's agents from the members dialog. */ - agents?: Agents | undefined; + agents?: AgentsClient | undefined; relay: RelayData; navigation?: PageNavigation | undefined; navigator?: Navigation | undefined; @@ -180,7 +180,7 @@ function ChannelWorkspace({ archive, }: { extensions?: ConversationExtensions | undefined; - agents?: Agents | undefined; + agents?: AgentsClient | undefined; companion?: ReactNode; scope: string; navigation?: PageNavigation | undefined; diff --git a/src/bundled/channels/CreateChannelDialog.tsx b/src/bundled/channels/CreateChannelDialog.tsx index a2ac7dd309..1309941655 100644 --- a/src/bundled/channels/CreateChannelDialog.tsx +++ b/src/bundled/channels/CreateChannelDialog.tsx @@ -1,6 +1,6 @@ import type { ChannelCreationInput } from "../../features/channel-templates/setup"; import type { RelaySession } from "../../features/relay/session"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { templateAgents, useChannelTemplates, @@ -49,7 +49,7 @@ type Props = { finalFocus?: RefObject | undefined; session: RelaySession; /** Supplies the agents and teams a template adds. */ - agents?: Agents | undefined; + agents?: AgentsClient | undefined; destinations: readonly Readonly<{ id: string; name: string; diff --git a/src/bundled/profiles/ProfilePanel.tsx b/src/bundled/profiles/ProfilePanel.tsx index 6a53fcdcf8..c21a19a48b 100644 --- a/src/bundled/profiles/ProfilePanel.tsx +++ b/src/bundled/profiles/ProfilePanel.tsx @@ -47,7 +47,7 @@ import { PreferenceRow } from "../../shared/design-system/ui/PreferenceRow"; import { SettingsGroup } from "../../shared/design-system/ui/SettingsGroup"; import { AgentDelete } from "../../features/agents/AgentManage"; import { useAgent, useChannelChoices } from "../../features/agents/react"; -import type { Agents } from "../../features/agents/service"; +import type { AgentsClient } from "../../features/agents/service"; import { agentSections } from "../../features/agents/tabs"; import { useAgentSettingsHost } from "../agents/AgentSettingsHost"; import { avatarMedia } from "../../shared/avatar-source"; @@ -66,7 +66,7 @@ export function ProfilePanel({ relay: RelayData; navigation?: Navigation; /** Agents show their type's tabs. */ - agents?: Agents; + agents?: AgentsClient; }) { const connection = useRelayConnection(relay); const activityKey = profileActivityViewKey(target); @@ -121,7 +121,7 @@ function OwnedAgentProfile({ context, close, }: { - agents: Agents; + agents: AgentsClient; initialActivity: boolean; pubkey: string; relay: RelayData; @@ -175,7 +175,7 @@ function ProfileDetails({ viewer, close, }: { - agents: Agents | undefined; + agents: AgentsClient | undefined; initialTab: "info" | "activity"; agentHint: boolean; session: RelaySession; diff --git a/src/bundled/usage/UsagePage.tsx b/src/bundled/usage/UsagePage.tsx index 9845961960..860e628bb0 100644 --- a/src/bundled/usage/UsagePage.tsx +++ b/src/bundled/usage/UsagePage.tsx @@ -8,7 +8,7 @@ import { } from "react"; import type { Agent, - Agents, + AgentsClient, SessionUsage, } from "../../features/agents/service"; import { relayOrigin } from "../../features/communities/destination"; @@ -77,7 +77,7 @@ const readKey = (agent: Agent) => * meanwhile. Each agent's read is shown as it finishes, merged over what * earlier ones found, so a slow harness holds up only its own agents; an agent * that cannot be read keeps what was found before. */ -function useUsage(agents: Agents, keys: string, reload: number) { +function useUsage(agents: AgentsClient, keys: string, reload: number) { const [load, setLoad] = useState(); // biome-ignore lint/correctness/useExhaustiveDependencies: Refresh reads the same agents again. useEffect(() => { @@ -206,7 +206,7 @@ export function UsagePage({ agents, open, }: { - agents: Agents; + agents: AgentsClient; open: Navigation["open"]; }) { const snapshot = useSyncExternalStore( diff --git a/src/features/agents/AgentManage.tsx b/src/features/agents/AgentManage.tsx index f177b18949..8883871ac6 100644 --- a/src/features/agents/AgentManage.tsx +++ b/src/features/agents/AgentManage.tsx @@ -5,7 +5,7 @@ import { TrashIcon } from "../../shared/design-system/icons"; import { Button } from "../../shared/design-system/ui/Button"; import { Dialog } from "../../shared/design-system/ui/Dialog"; import { PreferenceRow } from "../../shared/design-system/ui/PreferenceRow"; -import type { Agent, Agents } from "./service"; +import type { Agent, AgentsClient } from "./service"; const message = (error: unknown) => error instanceof Error ? error.message : String(error); @@ -15,7 +15,7 @@ const hostOf = (origin: string) => origin.replace(/^https:\/\//, ""); /** Whether the agent shown here is also in another of the owner's * communities that it isn't leaving, so it can be removed from this one * alone, or again after a Remove that didn't finish. */ -export const inSeveral = (agents: Agents, agent: Agent) => +export const inSeveral = (agents: AgentsClient, agent: Agent) => agent.place === "here" && agents .memberships(agent.pubkey) @@ -37,7 +37,7 @@ export function AgentDelete({ onRemoved, trigger, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; onRemoved(): void; trigger?: (open: () => void) => ReactNode; @@ -206,7 +206,7 @@ export function AgentRemoveHere({ onRemoved, trigger, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; onRemoved(): void; trigger: (open: () => void) => ReactNode; @@ -268,7 +268,7 @@ export function AgentArchiveRetry({ agents, agent, }: { - agents: Pick; + agents: Pick; agent: Agent; }) { const [checking, setChecking] = useState(false); diff --git a/src/features/agents/InterruptedNotice.tsx b/src/features/agents/InterruptedNotice.tsx index b0b1f4d6aa..5013bbcde7 100644 --- a/src/features/agents/InterruptedNotice.tsx +++ b/src/features/agents/InterruptedNotice.tsx @@ -1,11 +1,11 @@ import { Button } from "../../shared/design-system/ui/Button"; import { ToastNotice } from "../../shared/design-system/ui/Toast"; import { useAgentsSnapshot } from "./react"; -import type { Agents } from "./service"; +import type { AgentsClient } from "./service"; /** Asks the owner whether agents that were working when the app last closed * or reloaded carry on; nothing resumes until they choose. */ -export function InterruptedNotice({ agents }: { agents: Agents }) { +export function InterruptedNotice({ agents }: { agents: AgentsClient }) { const interrupted = useAgentsSnapshot(agents)?.interrupted ?? []; if (!interrupted.length) return null; const names = new Intl.ListFormat(undefined, { type: "conjunction" }).format( diff --git a/src/features/agents/react.ts b/src/features/agents/react.ts index d51d2e78e7..d726b2825b 100644 --- a/src/features/agents/react.ts +++ b/src/features/agents/react.ts @@ -9,13 +9,18 @@ import { } from "react"; import type { ChannelQueries } from "../relay/contracts"; import type { ChannelChoice } from "./attention"; -import type { Agents, Models, SessionPlace, SessionState } from "./service"; +import type { + AgentsClient, + Models, + SessionPlace, + SessionState, +} from "./service"; const noSubscribe = () => () => {}; const none = () => undefined; /** The selected community's agents and the registered types. */ -export function useAgents(agents: Agents) { +export function useAgents(agents: AgentsClient) { const snapshot = useSyncExternalStore( agents.subscribe, agents.snapshot, @@ -30,19 +35,19 @@ export function useAgents(agents: Agents) { } /** Agents' snapshot, or undefined without it. */ -export function useAgentsSnapshot(agents: Agents | undefined) { +export function useAgentsSnapshot(agents: AgentsClient | undefined) { const subscribe = agents?.subscribe ?? noSubscribe; const snapshot = agents?.snapshot ?? none; return useSyncExternalStore(subscribe, snapshot, snapshot); } const noTeams: readonly never[] = Object.freeze([]); /** The owner's teams on this device, or none without Agents. */ -export const useTeams = (agents: Agents | undefined) => +export const useTeams = (agents: AgentsClient | undefined) => useAgentsSnapshot(agents)?.teams ?? noTeams; /** The agent at `pubkey`, with its type when that is registered. A saved * agent whose type plugin is disabled or reloading is still an agent. */ -export function useAgent(agents: Agents | undefined, pubkey: string) { +export function useAgent(agents: AgentsClient | undefined, pubkey: string) { const subscribe = agents?.subscribe ?? noSubscribe; const agent = useSyncExternalStore( subscribe, @@ -65,7 +70,7 @@ const noTypes = () => EMPTY_TYPES; /** The state of the targeted harness sessions. Any compaction blocks a send * to those targets; ordinary active turns keep accepting steering. */ export function useSessionState( - agents: Agents | undefined, + agents: AgentsClient | undefined, pubkeys: readonly string[], place: SessionPlace, ): SessionState { @@ -105,7 +110,7 @@ export function useSessionState( } /** The app's Agents, for surfaces such as the composer that plugins do not own. */ -export const AgentsContext = createContext(undefined); +export const AgentsContext = createContext(undefined); export const MentionModelsContext = createContext< | ((pubkeys: readonly string[]) => Promise) diff --git a/src/features/agents/service.ts b/src/features/agents/service.ts index f0afa801eb..cdfc7005d6 100644 --- a/src/features/agents/service.ts +++ b/src/features/agents/service.ts @@ -1120,6 +1120,24 @@ export type Agents = { /** Deletes the team; its agents are untouched. */ removeTeam(id: string): Promise; }; +/** What the app's screens use of the agents. It leaves out what only running + * agents and plugin entries use (registration, tools, wakes, relay access, + * storage), so agents can later run in another page with screens as clients. */ +export type AgentsClient = Omit< + Agents, + | "addAttentionSource" + | "attentionProviders" + | "register" + | "present" + | "addTool" + | "tools" + | "wake" + | "handle" + | "relay" + | "core" + | "storage" + | "note" +>; declare module "@deepseek-ai/cordis" { interface Context { agents: Agents; diff --git a/src/features/agents/tabs.tsx b/src/features/agents/tabs.tsx index 950466a626..1d44e8d814 100644 --- a/src/features/agents/tabs.tsx +++ b/src/features/agents/tabs.tsx @@ -10,7 +10,7 @@ import type { Agent, AgentConversation, AgentSettingsHost, - Agents, + AgentsClient, RegisteredAgentType, } from "./service"; import { AgentSaveButton } from "./AgentSaveButton"; @@ -34,7 +34,7 @@ export function agentSections({ settingsSection, settingsContent, }: { - agents: Agents; + agents: AgentsClient; agent: Agent; type: RegisteredAgentType | undefined; channels: readonly ChannelChoice[]; @@ -142,7 +142,7 @@ function AttentionSection({ agent, channels, }: { - agents: Pick; + agents: Pick; agent: Agent; channels: readonly ChannelChoice[]; }) { diff --git a/src/features/channel-navigation/ChannelInventory.tsx b/src/features/channel-navigation/ChannelInventory.tsx index 2077bf2f54..8a18b6d1c5 100644 --- a/src/features/channel-navigation/ChannelInventory.tsx +++ b/src/features/channel-navigation/ChannelInventory.tsx @@ -15,7 +15,7 @@ import { lifecycleNoun } from "../../bundled/channels/ChannelLifecycleDialog"; import type { ChannelLifecycleAction } from "../relay/channel-lifecycle-protocol"; import { inTeamInventory } from "./team-inventory"; import type { RelayData } from "../relay/service"; -import type { Agents } from "../agents/service"; +import type { AgentsClient } from "../agents/service"; import type { RelaySession } from "../relay/session"; import { useChannelList } from "../relay/react"; import type { Navigation } from "../navigation/controller"; @@ -110,7 +110,7 @@ export function ChannelInventory({ }: { relay: RelayData; navigator: Navigation; - agents?: Agents | undefined; + agents?: AgentsClient | undefined; target: OpenTarget; queries: RelaySession; cached: boolean; diff --git a/src/features/huddle/composer-owner.ts b/src/features/huddle/composer-owner.ts index 8a5d6e211d..463434741a 100644 --- a/src/features/huddle/composer-owner.ts +++ b/src/features/huddle/composer-owner.ts @@ -27,7 +27,7 @@ export function createHuddleComposerOwner( extensions: ComposerReader | undefined, current: () => boolean, verified?: () => boolean, - agents?: import("../agents/service").Agents, + agents?: import("../agents/service").AgentsClient, ) { async function modelChoices(pubkeys: readonly string[]) { const revision = modelRevision; diff --git a/src/features/huddle/window.ts b/src/features/huddle/window.ts index 31d0b78a67..1e07f3ad53 100644 --- a/src/features/huddle/window.ts +++ b/src/features/huddle/window.ts @@ -92,7 +92,7 @@ export function createHuddleWindow( bridge = nativeHuddleWindow, extensions?: ComposerReader, openLink?: (target: string) => boolean, - agents?: import("../agents/service").Agents, + agents?: import("../agents/service").AgentsClient, ) { let disposed = false; let attempted: string | undefined; diff --git a/src/features/messages/useBringAgents.tsx b/src/features/messages/useBringAgents.tsx index 80218982bb..2a87d606e8 100644 --- a/src/features/messages/useBringAgents.tsx +++ b/src/features/messages/useBringAgents.tsx @@ -2,7 +2,7 @@ import { useRef, useState } from "react"; import type { ComposerSession } from "./composer-session"; import { canAddMembers } from "../channel-members/members"; import { communityHost } from "./community-host"; -import type { Agent, Agents } from "../agents/service"; +import type { Agent, AgentsClient } from "../agents/service"; import { sameAgent } from "../agents/AgentManage"; import { splitPartition } from "../relay/partition"; import { Dialog } from "../../shared/design-system/ui/Dialog"; @@ -32,7 +32,7 @@ type Pending = { */ export function useBringAgents( session: ComposerSession, - agents: Agents | undefined, + agents: AgentsClient | undefined, channelId: string, restoreFocus: () => void, ) { diff --git a/src/features/messages/useOldAgentMentions.tsx b/src/features/messages/useOldAgentMentions.tsx index 04a5ab619b..69f8c89a48 100644 --- a/src/features/messages/useOldAgentMentions.tsx +++ b/src/features/messages/useOldAgentMentions.tsx @@ -1,5 +1,5 @@ import { useRef, useState } from "react"; -import type { Agents } from "../agents/service"; +import type { AgentsClient } from "../agents/service"; import type { PortableAgent } from "../agents/native"; import type { MentionRecipient } from "./mention-draft"; import { Dialog } from "../../shared/design-system/ui/Dialog"; @@ -24,7 +24,7 @@ const declined = new Set(); /** Offers to import a mentioned agent that only an earlier Buzz on this * machine runs, before the send that would otherwise go unanswered. */ export function useOldAgentMentions( - agents: Agents | undefined, + agents: AgentsClient | undefined, restoreFocus: () => void, ) { const [pending, setPending] = useState();