Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,92 @@ function registerIpcHandlers() {
}
);

// ======================== agent-templates (global Worker Agent templates) ========================
const AGENT_TEMPLATES_FILE = 'agent-templates.json';
type AgentTemplateIpcPayload = {
id: string;
name: string;
description: string;
tools: string[];
mcp_tools: Record<string, unknown>;
custom_model_config?: Record<string, unknown>;
selected_tools_snapshot?: unknown[];
updatedAt: number;
};

function getAgentTemplatesPath(userId: string): string {
return path.join(os.homedir(), '.eigent', userId, AGENT_TEMPLATES_FILE);
}

async function loadAgentTemplates(userId: string): Promise<{
version: number;
templates: AgentTemplateIpcPayload[];
}> {
const configPath = getAgentTemplatesPath(userId);
const defaultData = { version: 1, templates: [] };
if (!existsSync(configPath)) {
try {
await fsp.mkdir(path.dirname(configPath), { recursive: true });
await fsp.writeFile(
configPath,
JSON.stringify(defaultData, null, 2),
'utf-8'
);
return defaultData;
} catch (error) {
log.error('Failed to create default agent-templates', error);
return defaultData;
}
}
try {
const content = await fsp.readFile(configPath, 'utf-8');
const data = JSON.parse(content);
if (!Array.isArray(data.templates)) data.templates = [];
return { version: data.version ?? 1, templates: data.templates };
} catch (error) {
log.error('Failed to load agent-templates', error);
return defaultData;
}
}

async function saveAgentTemplates(
userId: string,
data: { version: number; templates: AgentTemplateIpcPayload[] }
): Promise<void> {
const configPath = getAgentTemplatesPath(userId);
await fsp.mkdir(path.dirname(configPath), { recursive: true });
await fsp.writeFile(configPath, JSON.stringify(data, null, 2), 'utf-8');
}

ipcMain.handle('agent-templates-load', async (_event, userId: string) => {
try {
const data = await loadAgentTemplates(userId);
return { success: true, templates: data.templates };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.error('agent-templates-load failed', error);
return { success: false, error: message, templates: [] };
}
});

ipcMain.handle(
'agent-templates-save',
async (_event, userId: string, templates: AgentTemplateIpcPayload[]) => {
try {
const current = await loadAgentTemplates(userId);
await saveAgentTemplates(userId, {
version: current.version,
templates,
});
return { success: true };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.error('agent-templates-save failed', error);
return { success: false, error: message };
}
}
);

// Initialize skills config for a user (ensures config file exists)
ipcMain.handle('skill-config-init', async (_event, userId: string) => {
try {
Expand Down
7 changes: 7 additions & 0 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import { contextBridge, ipcRenderer, webUtils } from 'electron';

type AgentTemplateIpcPayload = Record<string, unknown>;

contextBridge.exposeInMainWorld('ipcRenderer', {
on(...args: Parameters<typeof ipcRenderer.on>) {
const [channel, listener] = args;
Expand Down Expand Up @@ -201,6 +203,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
ipcRenderer.invoke('skill-config-update', userId, skillName, skillConfig),
skillConfigDelete: (userId: string, skillName: string) =>
ipcRenderer.invoke('skill-config-delete', userId, skillName),
// Global Agent Templates (~/.eigent/<userId>/agent-templates.json)
agentTemplatesLoad: (userId: string) =>
ipcRenderer.invoke('agent-templates-load', userId),
agentTemplatesSave: (userId: string, templates: AgentTemplateIpcPayload[]) =>
ipcRenderer.invoke('agent-templates-save', userId, templates),
});

// --------- Preload scripts loading ---------
Expand Down
8 changes: 4 additions & 4 deletions src/pages/Agents/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export default function Capabilities() {

return (
<div className="m-auto flex h-auto max-w-[940px] flex-col">
<div className="px-6 flex h-auto w-full">
<div className="top-20 w-40 pr-6 pt-8 sticky flex h-full flex-shrink-0 flex-grow-0 flex-col justify-between self-start">
<div className="flex h-auto w-full px-6">
<div className="sticky top-20 flex h-full w-40 flex-shrink-0 flex-grow-0 flex-col justify-between self-start pr-6 pt-8">
<VerticalNavigation
items={
menuItems.map((menu) => ({
Expand All @@ -59,14 +59,14 @@ export default function Capabilities() {
}
value={activeTab}
onValueChange={handleTabChange}
className="min-h-0 gap-0 h-full w-full flex-1"
className="h-full min-h-0 w-full flex-1 gap-0"
listClassName="w-full h-full overflow-y-auto"
contentClassName="hidden"
/>
</div>

<div className="flex h-auto w-full flex-1 flex-col">
<div className="gap-4 flex flex-col">
<div className="flex flex-col gap-4">
{activeTab === 'models' && <Models />}
{activeTab === 'skills' && <Skills />}
{activeTab === 'memory' && <Memory />}
Expand Down
Loading
Loading