Files
DeskClaw/src/stores/agents.ts

169 lines
5.1 KiB
TypeScript

import { create } from 'zustand';
import { hostApiFetch } from '@/lib/host-api';
import type { ChannelType } from '@/types/channel';
import type { AgentSummary, AgentsSnapshot } from '@/types/agent';
interface AgentsState {
agents: AgentSummary[];
defaultAgentId: string;
defaultModelRef: string | null;
configuredChannelTypes: string[];
channelOwners: Record<string, string>;
channelAccountOwners: Record<string, string>;
loading: boolean;
error: string | null;
fetchAgents: () => Promise<void>;
createAgent: (name: string, options?: { inheritWorkspace?: boolean }) => Promise<void>;
updateAgent: (agentId: string, name: string) => Promise<void>;
updateAgentModel: (agentId: string, modelRef: string | null) => Promise<void>;
updateDefaultModel: (modelRef: string | null) => Promise<void>;
deleteAgent: (agentId: string) => Promise<void>;
assignChannel: (agentId: string, channelType: ChannelType) => Promise<void>;
removeChannel: (agentId: string, channelType: ChannelType) => Promise<void>;
clearError: () => void;
}
function applySnapshot(snapshot: AgentsSnapshot | undefined) {
return snapshot ? {
agents: snapshot.agents ?? [],
defaultAgentId: snapshot.defaultAgentId ?? 'main',
defaultModelRef: snapshot.defaultModelRef ?? null,
configuredChannelTypes: snapshot.configuredChannelTypes ?? [],
channelOwners: snapshot.channelOwners ?? {},
channelAccountOwners: snapshot.channelAccountOwners ?? {},
} : {};
}
export const useAgentsStore = create<AgentsState>((set) => ({
agents: [],
defaultAgentId: 'main',
defaultModelRef: null,
configuredChannelTypes: [],
channelOwners: {},
channelAccountOwners: {},
loading: false,
error: null,
fetchAgents: async () => {
set({ loading: true, error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>('/api/agents');
set({
...applySnapshot(snapshot),
loading: false,
});
} catch (error) {
set({ loading: false, error: String(error) });
}
},
createAgent: async (name: string, options?: { inheritWorkspace?: boolean }) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>('/api/agents', {
method: 'POST',
body: JSON.stringify({ name, inheritWorkspace: options?.inheritWorkspace }),
});
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
updateAgent: async (agentId: string, name: string) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
`/api/agents/${encodeURIComponent(agentId)}`,
{
method: 'PUT',
body: JSON.stringify({ name }),
}
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
updateAgentModel: async (agentId: string, modelRef: string | null) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
`/api/agents/${encodeURIComponent(agentId)}/model`,
{
method: 'PUT',
body: JSON.stringify({ modelRef }),
}
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
updateDefaultModel: async (modelRef: string | null) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
'/api/agents/default-model',
{
method: 'PUT',
body: JSON.stringify({ modelRef }),
}
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
deleteAgent: async (agentId: string) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
`/api/agents/${encodeURIComponent(agentId)}`,
{ method: 'DELETE' }
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
assignChannel: async (agentId: string, channelType: ChannelType) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
`/api/agents/${encodeURIComponent(agentId)}/channels/${encodeURIComponent(channelType)}`,
{ method: 'PUT' }
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
removeChannel: async (agentId: string, channelType: ChannelType) => {
set({ error: null });
try {
const snapshot = await hostApiFetch<AgentsSnapshot & { success?: boolean }>(
`/api/agents/${encodeURIComponent(agentId)}/channels/${encodeURIComponent(channelType)}`,
{ method: 'DELETE' }
);
set(applySnapshot(snapshot));
} catch (error) {
set({ error: String(error) });
throw error;
}
},
clearError: () => set({ error: null }),
}));