- index.ts: add _storesInitialized guard to prevent triple initialization - offlineStore.ts: add isRetrying mutex for retryAllMessages concurrency - PropertyPanel.tsx: replace 13x (data as any) with typed d accessor - chatStore.ts: replace window as any with Record<string, unknown> - kernel-*.ts: replace prototype as any with Record<string, unknown> - gateway-heartbeat.ts: delete dead code (9 as any, zero imports)
151 lines
4.7 KiB
TypeScript
151 lines
4.7 KiB
TypeScript
/**
|
|
* kernel-agent.ts - Agent & Clone management methods for KernelClient
|
|
*
|
|
* Installed onto KernelClient.prototype via installAgentMethods().
|
|
*/
|
|
|
|
import { invoke } from '@tauri-apps/api/core';
|
|
import type { KernelClient } from './kernel-client';
|
|
import type { AgentInfo, CreateAgentRequest, CreateAgentResponse } from './kernel-types';
|
|
|
|
export function installAgentMethods(ClientClass: { prototype: KernelClient }): void {
|
|
const proto = ClientClass.prototype as unknown as Record<string, unknown>;
|
|
|
|
// ─── Agent Management ───
|
|
|
|
/**
|
|
* List all agents
|
|
*/
|
|
proto.listAgents = async function (this: KernelClient): Promise<AgentInfo[]> {
|
|
return invoke<AgentInfo[]>('agent_list');
|
|
};
|
|
|
|
/**
|
|
* Get agent by ID
|
|
*/
|
|
proto.getAgent = async function (this: KernelClient, agentId: string): Promise<AgentInfo | null> {
|
|
return invoke<AgentInfo | null>('agent_get', { agentId });
|
|
};
|
|
|
|
/**
|
|
* Create a new agent
|
|
*/
|
|
proto.createAgent = async function (this: KernelClient, request: CreateAgentRequest): Promise<CreateAgentResponse> {
|
|
return invoke<CreateAgentResponse>('agent_create', {
|
|
request: {
|
|
name: request.name,
|
|
description: request.description,
|
|
systemPrompt: request.systemPrompt,
|
|
soul: request.soul,
|
|
provider: request.provider || 'anthropic',
|
|
model: request.model || 'claude-sonnet-4-20250514',
|
|
maxTokens: request.maxTokens || 4096,
|
|
temperature: request.temperature || 0.7,
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Delete an agent
|
|
*/
|
|
proto.deleteAgent = async function (this: KernelClient, agentId: string): Promise<void> {
|
|
return invoke('agent_delete', { agentId });
|
|
};
|
|
|
|
// ─── Clone/Agent Adaptation (GatewayClient interface compatibility) ───
|
|
|
|
/**
|
|
* List clones — maps to listAgents() with field adaptation
|
|
*/
|
|
proto.listClones = async function (this: KernelClient): Promise<{ clones: any[] }> {
|
|
const agents = await this.listAgents();
|
|
const clones = agents.map((agent) => ({
|
|
id: agent.id,
|
|
name: agent.name,
|
|
role: agent.description,
|
|
model: agent.model,
|
|
createdAt: new Date().toISOString(),
|
|
}));
|
|
return { clones };
|
|
};
|
|
|
|
/**
|
|
* Create clone — maps to createAgent()
|
|
*/
|
|
proto.createClone = async function (this: KernelClient, opts: {
|
|
name: string;
|
|
role?: string;
|
|
model?: string;
|
|
personality?: string;
|
|
communicationStyle?: string;
|
|
scenarios?: string[];
|
|
emoji?: string;
|
|
notes?: string;
|
|
[key: string]: unknown;
|
|
}): Promise<{ clone: any }> {
|
|
// Build soul content from personality data
|
|
const soulParts: string[] = [];
|
|
if (opts.personality) soulParts.push(`## 性格\n${opts.personality}`);
|
|
if (opts.communicationStyle) soulParts.push(`## 沟通风格\n${opts.communicationStyle}`);
|
|
if (opts.scenarios?.length) soulParts.push(`## 使用场景\n${opts.scenarios.join(', ')}`);
|
|
if (opts.notes) soulParts.push(`## 备注\n${opts.notes}`);
|
|
const soul = soulParts.length > 0 ? soulParts.join('\n\n') : undefined;
|
|
|
|
const response = await this.createAgent({
|
|
name: opts.name,
|
|
description: opts.role,
|
|
model: opts.model,
|
|
soul,
|
|
});
|
|
const clone = {
|
|
id: response.id,
|
|
name: response.name,
|
|
role: opts.role,
|
|
model: opts.model,
|
|
personality: opts.personality,
|
|
communicationStyle: opts.communicationStyle,
|
|
emoji: opts.emoji,
|
|
scenarios: opts.scenarios,
|
|
createdAt: new Date().toISOString(),
|
|
};
|
|
return { clone };
|
|
};
|
|
|
|
/**
|
|
* Delete clone — maps to deleteAgent()
|
|
*/
|
|
proto.deleteClone = async function (this: KernelClient, id: string): Promise<void> {
|
|
return this.deleteAgent(id);
|
|
};
|
|
|
|
/**
|
|
* Update clone — maps to kernel agent_update
|
|
*/
|
|
proto.updateClone = async function (this: KernelClient, id: string, updates: Record<string, unknown>): Promise<{ clone: unknown }> {
|
|
await invoke('agent_update', {
|
|
agentId: id,
|
|
updates: {
|
|
name: updates.name as string | undefined,
|
|
description: updates.description as string | undefined,
|
|
systemPrompt: updates.systemPrompt as string | undefined,
|
|
model: updates.model as string | undefined,
|
|
provider: updates.provider as string | undefined,
|
|
maxTokens: updates.maxTokens as number | undefined,
|
|
temperature: updates.temperature as number | undefined,
|
|
},
|
|
});
|
|
|
|
// Return updated clone representation
|
|
const clone = {
|
|
id,
|
|
name: updates.name,
|
|
role: updates.description || updates.role,
|
|
model: updates.model,
|
|
personality: updates.personality,
|
|
communicationStyle: updates.communicationStyle,
|
|
systemPrompt: updates.systemPrompt,
|
|
};
|
|
return { clone };
|
|
};
|
|
}
|