feat: MetonaAI Desktop 初始项目
- Electron + React + TypeScript 架构 - 三栏布局: Sidebar | ChatPanel | DetailPanel - 9 个内置工具 (文件系统/网络/记忆/命令) - SQLite 持久化 (better-sqlite3) - MUI 暗色/亮色主题系统 - Agent Loop ReAct 状态机引擎 - DeepSeek / Agnes AI / Ollama Provider 适配器 - MCP 协议集成 - 系统托盘 + 全局快捷键 - Tailwind CSS v4 + Tailwind Merge - 修复: Sidebar 缺失 TextField 导入导致黑屏
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 记忆工具(2 个)
|
||||
*
|
||||
* memory_store, memory_search
|
||||
*
|
||||
* @see docs/MetonaAI-Desktop 架构与交互设计.html — 9 个基础工具
|
||||
*/
|
||||
|
||||
import type { IMetonaTool, ToolExecutionContext } from '../../types/metona-tool';
|
||||
import type { MetonaToolDef } from '../../../harness/types';
|
||||
import { MetonaToolCategory, MetonaRiskLevel } from '../../../harness/types';
|
||||
import type { MemoryManager } from '../../memory/manager';
|
||||
|
||||
// ===== 7. memory_store =====
|
||||
|
||||
export class MemoryStoreTool implements IMetonaTool {
|
||||
readonly definition: MetonaToolDef = {
|
||||
name: 'memory_store',
|
||||
description: 'Store a piece of information in persistent memory. Useful for remembering important facts, decisions, or user preferences across sessions.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
content: { type: 'string', description: 'The memory content to store' },
|
||||
type: { type: 'string', description: 'Memory type: "episodic" (events), "semantic" (knowledge), or "working" (task state)', enum: ['episodic', 'semantic', 'working'] },
|
||||
importance: { type: 'number', description: 'Importance score 0-1 (default 0.5)' },
|
||||
source: { type: 'string', description: 'Source identifier (default "agent")' },
|
||||
tags: { type: 'array', description: 'Tag list for categorization', items: { type: 'string', description: 'Tag' } },
|
||||
},
|
||||
required: ['content', 'type'],
|
||||
},
|
||||
category: MetonaToolCategory.DATABASE,
|
||||
riskLevel: MetonaRiskLevel.MEDIUM,
|
||||
requiresPermission: false,
|
||||
timeoutMs: 10_000,
|
||||
};
|
||||
|
||||
constructor(private memoryManager: MemoryManager) {}
|
||||
|
||||
async execute(args: Record<string, unknown>, context: ToolExecutionContext): Promise<unknown> {
|
||||
const content = args.content as string;
|
||||
const type = args.type as 'episodic' | 'semantic' | 'working';
|
||||
const importance = (args.importance as number) ?? 0.5;
|
||||
const source = (args.source as string) ?? 'agent';
|
||||
const tags = (args.tags as string[]) ?? [];
|
||||
|
||||
const id = await this.memoryManager.store({
|
||||
type,
|
||||
content,
|
||||
source: source as 'user_input' | 'tool_result' | 'agent_thought' | 'imported',
|
||||
importance,
|
||||
sessionId: context.sessionId,
|
||||
});
|
||||
|
||||
return { id, type, content_preview: content.slice(0, 100), importance };
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 8. memory_search =====
|
||||
|
||||
export class MemorySearchTool implements IMetonaTool {
|
||||
readonly definition: MetonaToolDef = {
|
||||
name: 'memory_search',
|
||||
description: 'Search persistent memory for relevant information. Returns memories sorted by relevance.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string', description: 'Search query or keywords' },
|
||||
type: { type: 'string', description: 'Filter by memory type', enum: ['episodic', 'semantic', 'working'] },
|
||||
topK: { type: 'number', description: 'Number of results (default 5)' },
|
||||
threshold: { type: 'number', description: 'Minimum relevance score 0-1 (default 0.7)' },
|
||||
},
|
||||
required: ['query'],
|
||||
},
|
||||
category: MetonaToolCategory.DATABASE,
|
||||
riskLevel: MetonaRiskLevel.SAFE,
|
||||
requiresPermission: false,
|
||||
timeoutMs: 10_000,
|
||||
};
|
||||
|
||||
constructor(private memoryManager: MemoryManager) {}
|
||||
|
||||
async execute(args: Record<string, unknown>, _context: ToolExecutionContext): Promise<unknown> {
|
||||
const query = args.query as string;
|
||||
const type = args.type as 'episodic' | 'semantic' | 'working' | undefined;
|
||||
const topK = (args.topK as number) ?? 5;
|
||||
const threshold = (args.threshold as number) ?? 0.7;
|
||||
|
||||
const results = await this.memoryManager.search(query, {
|
||||
topK,
|
||||
type,
|
||||
minImportance: threshold,
|
||||
});
|
||||
|
||||
return {
|
||||
query,
|
||||
results: results.map((r) => ({
|
||||
id: r.id,
|
||||
type: r.type,
|
||||
content: r.content.slice(0, 500),
|
||||
importance: r.importance,
|
||||
score: r.score,
|
||||
})),
|
||||
count: results.length,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user