fix(frontend): 移除运行时演示数据并接入真实后端状态
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import apiClient from './apiClient'
|
||||
import { SseClient } from './sseClient'
|
||||
import type { AgentRun, AgentEvent, AgentTraceResponse, ApiAgentRun, OperationResponse, PageMeta, ToolDefinition, PermissionRequest } from '@/contracts'
|
||||
import type { AgentRun, AgentEvent, AgentTraceResponse, ApiAgentRun, OperationResponse, PageMeta, ToolDefinition } from '@/contracts'
|
||||
|
||||
function toAgentRun(run: ApiAgentRun): AgentRun {
|
||||
// API 的 token_usage 是累计值,UI 模型预留了输入/输出拆分字段。
|
||||
@@ -10,8 +10,6 @@ function toAgentRun(run: ApiAgentRun): AgentRun {
|
||||
current_step: run.current_step,
|
||||
max_steps: run.max_steps,
|
||||
token_usage: {
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
total_tokens: run.token_usage,
|
||||
},
|
||||
started_at: run.created_at,
|
||||
@@ -107,207 +105,3 @@ export async function respondToPermission(
|
||||
decision,
|
||||
})
|
||||
}
|
||||
|
||||
export const mockTools: ToolDefinition[] = [
|
||||
{
|
||||
name: 'notes.search',
|
||||
description: '搜索笔记,支持关键词和语义检索',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string', description: '搜索关键词' },
|
||||
limit: { type: 'number', description: '返回结果数量' },
|
||||
},
|
||||
required: ['query'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'notes.read',
|
||||
description: '读取指定笔记的完整内容',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
note_id: { type: 'string' },
|
||||
},
|
||||
required: ['note_id'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'notes.create',
|
||||
description: '创建新笔记',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
content: { type: 'string' },
|
||||
folder_path: { type: 'string' },
|
||||
},
|
||||
required: ['title', 'content'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'rag.search',
|
||||
description: '基于 RAG 的语义检索,返回相关知识片段',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string' },
|
||||
top_k: { type: 'number' },
|
||||
},
|
||||
required: ['query'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'tasks.create',
|
||||
description: '创建任务',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
priority: { type: 'string', enum: ['low', 'medium', 'high'] },
|
||||
},
|
||||
required: ['title'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'system.echo',
|
||||
description: '回显输入内容(测试用)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
text: { type: 'string' },
|
||||
},
|
||||
required: ['text'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
{
|
||||
name: 'math.add',
|
||||
description: '两数相加(测试用)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
a: { type: 'number' },
|
||||
b: { type: 'number' },
|
||||
},
|
||||
required: ['a', 'b'],
|
||||
},
|
||||
source: 'builtin',
|
||||
},
|
||||
]
|
||||
|
||||
export const mockAgentRuns: AgentRun[] = [
|
||||
{
|
||||
run_id: 'run-1',
|
||||
status: 'completed',
|
||||
current_step: 3,
|
||||
max_steps: 10,
|
||||
token_usage: { input_tokens: 2340, output_tokens: 890, total_tokens: 3230 },
|
||||
started_at: '2026-08-25T11:00:00Z',
|
||||
completed_at: '2026-08-25T11:02:30Z',
|
||||
},
|
||||
{
|
||||
run_id: 'run-2',
|
||||
status: 'running',
|
||||
current_step: 2,
|
||||
max_steps: 10,
|
||||
token_usage: { input_tokens: 1500, output_tokens: 420, total_tokens: 1920 },
|
||||
started_at: '2026-08-26T09:30:00Z',
|
||||
},
|
||||
]
|
||||
|
||||
export const mockAgentEvents: AgentEvent[] = [
|
||||
{
|
||||
event: 'RunStarted',
|
||||
sequence: 1,
|
||||
run_id: 'run-1',
|
||||
data: { task: '帮我整理红黑树的核心知识点' },
|
||||
timestamp: '2026-08-25T11:00:00Z',
|
||||
},
|
||||
{
|
||||
event: 'ThinkingDelta',
|
||||
sequence: 2,
|
||||
run_id: 'run-1',
|
||||
data: { text: '我需要先搜索笔记中关于红黑树的内容...' },
|
||||
timestamp: '2026-08-25T11:00:01Z',
|
||||
},
|
||||
{
|
||||
event: 'ToolCall',
|
||||
sequence: 3,
|
||||
run_id: 'run-1',
|
||||
data: {
|
||||
tool_call_id: 'tc-1',
|
||||
name: 'notes.search',
|
||||
parameters: { query: '红黑树 插入 删除', limit: 5 },
|
||||
status: 'running',
|
||||
},
|
||||
timestamp: '2026-08-25T11:00:02Z',
|
||||
},
|
||||
{
|
||||
event: 'ToolResult',
|
||||
sequence: 4,
|
||||
run_id: 'run-1',
|
||||
data: {
|
||||
tool_call_id: 'tc-1',
|
||||
name: 'notes.search',
|
||||
status: 'completed',
|
||||
result: '找到 5 条相关结果,包括红黑树性质、插入操作、删除操作等...',
|
||||
duration_ms: 320,
|
||||
},
|
||||
timestamp: '2026-08-25T11:00:02Z',
|
||||
},
|
||||
{
|
||||
event: 'Citation',
|
||||
sequence: 5,
|
||||
run_id: 'run-1',
|
||||
data: {
|
||||
note_id: 'n-rbt',
|
||||
block_id: 'b1',
|
||||
heading_path: '数据结构 / 红黑树 / 性质',
|
||||
},
|
||||
timestamp: '2026-08-25T11:00:03Z',
|
||||
},
|
||||
{
|
||||
event: 'ThinkingDelta',
|
||||
sequence: 6,
|
||||
run_id: 'run-1',
|
||||
data: { text: '搜索结果很全面,让我整理一下结构...' },
|
||||
timestamp: '2026-08-25T11:00:03Z',
|
||||
},
|
||||
{
|
||||
event: 'TextDelta',
|
||||
sequence: 7,
|
||||
run_id: 'run-1',
|
||||
data: { text: '## 红黑树核心知识点整理\n\n### 1. 基本性质\n红黑树是一种自平衡二叉搜索树,每个节点带有颜色属性...' },
|
||||
timestamp: '2026-08-25T11:00:04Z',
|
||||
},
|
||||
{
|
||||
event: 'Usage',
|
||||
sequence: 8,
|
||||
run_id: 'run-1',
|
||||
data: { input_tokens: 2340, output_tokens: 890, total_tokens: 3230 },
|
||||
timestamp: '2026-08-25T11:02:30Z',
|
||||
},
|
||||
{
|
||||
event: 'RunCompleted',
|
||||
sequence: 9,
|
||||
run_id: 'run-1',
|
||||
data: { message: 'Task completed successfully' },
|
||||
timestamp: '2026-08-25T11:02:30Z',
|
||||
},
|
||||
]
|
||||
|
||||
export const mockPermissionRequest: PermissionRequest = {
|
||||
request_id: 'perm-1',
|
||||
run_id: 'run-2',
|
||||
tool_name: 'notes.create',
|
||||
permission: 'notes.write',
|
||||
parameters: { title: '红黑树知识点总结', folder_path: '/数据结构' },
|
||||
impact: '将在你的知识库中创建一篇新笔记',
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SseClient } from './sseClient'
|
||||
import type { Conversation, ChatMessage, ModelEvent } from '@/contracts'
|
||||
import type { ModelEvent } from '@/contracts'
|
||||
|
||||
export interface ChatRequest {
|
||||
provider_id: string
|
||||
@@ -46,87 +46,3 @@ export function streamChat(
|
||||
client.connect().catch(() => {})
|
||||
return client
|
||||
}
|
||||
|
||||
export const mockConversations: Conversation[] = [
|
||||
{
|
||||
conversation_id: 'conv-1',
|
||||
title: '关于红黑树的讨论',
|
||||
created_at: '2026-08-25T10:00:00Z',
|
||||
updated_at: '2026-08-25T10:30:00Z',
|
||||
message_count: 6,
|
||||
},
|
||||
{
|
||||
conversation_id: 'conv-2',
|
||||
title: '死锁避免算法',
|
||||
created_at: '2026-08-24T14:00:00Z',
|
||||
updated_at: '2026-08-24T15:20:00Z',
|
||||
message_count: 4,
|
||||
},
|
||||
{
|
||||
conversation_id: 'conv-3',
|
||||
title: 'TCP三次握手',
|
||||
created_at: '2026-08-22T09:00:00Z',
|
||||
updated_at: '2026-08-22T09:15:00Z',
|
||||
message_count: 3,
|
||||
},
|
||||
]
|
||||
|
||||
export const mockMessages: Record<string, ChatMessage[]> = {
|
||||
'conv-1': [
|
||||
{
|
||||
message_id: 'msg-1',
|
||||
conversation_id: 'conv-1',
|
||||
role: 'user',
|
||||
content: '红黑树的插入操作有哪些情况需要调整?',
|
||||
created_at: '2026-08-25T10:00:00Z',
|
||||
},
|
||||
{
|
||||
message_id: 'msg-2',
|
||||
conversation_id: 'conv-1',
|
||||
role: 'assistant',
|
||||
content:
|
||||
'红黑树插入后可能违反红黑性质,需要通过旋转和变色来修复。主要有以下几种情况:\n\n**情况1:叔叔节点是红色**\n- 将父节点和叔叔节点设为黑色\n- 将祖父节点设为红色\n- 当前节点上移到祖父节点,继续向上调整\n\n**情况2:叔叔节点是黑色,且当前节点是右孩子**\n- 以父节点为支点左旋\n- 将当前节点转换为左孩子,进入情况3\n\n**情况3:叔叔节点是黑色,且当前节点是左孩子**\n- 以祖父节点为支点右旋\n- 将父节点设为黑色,祖父节点设为红色\n\n以上三种情况需要从插入节点开始向上递归处理,直到根节点。',
|
||||
created_at: '2026-08-25T10:01:00Z',
|
||||
citations: [
|
||||
{
|
||||
note_id: 'n-rbt',
|
||||
block_id: 'b1',
|
||||
file_path: '/数据结构/红黑树.md',
|
||||
heading_path: '数据结构 / 红黑树 / 插入操作',
|
||||
content: '插入后可能破坏红黑性质,需要通过变色和旋转来修复...',
|
||||
},
|
||||
{
|
||||
note_id: 'n-rbt',
|
||||
block_id: 'b2',
|
||||
file_path: '/数据结构/红黑树.md',
|
||||
heading_path: '数据结构 / 红黑树 / 五种情况',
|
||||
content: 'Case 1: 叔叔为红色,直接变色...',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
message_id: 'msg-3',
|
||||
conversation_id: 'conv-1',
|
||||
role: 'user',
|
||||
content: '能对比一下 AVL 树和红黑树的性能差异吗?',
|
||||
created_at: '2026-08-25T10:10:00Z',
|
||||
},
|
||||
{
|
||||
message_id: 'msg-4',
|
||||
conversation_id: 'conv-1',
|
||||
role: 'assistant',
|
||||
content:
|
||||
'AVL 树和红黑树都是平衡二叉搜索树,但它们的平衡策略和性能特点有所不同:\n\n| 特性 | AVL 树 | 红黑树 |\n|------|--------|--------|\n| 严格平衡 | 高度差 ≤ 1 | 黑色高度相同 |\n| 查找速度 | 更快(严格平衡) | 略慢但仍为 O(log n) |\n| 插入/删除 | 旋转更多 | 旋转更少(颜色调整为主) |\n| 存储开销 | 每个节点存高度(int) | 每个节点存颜色(1 bit) |\n| 适用场景 | 读多写少 | 读写均衡或写较多 |\n\n**总结:**\n- 如果应用以查询为主,很少修改,AVL 树可能更优\n- 如果插入删除频繁,红黑树更合适,重平衡开销更低\n- 红黑树在工业界应用更广泛(C++ STL 的 map/set、Java 的 TreeMap 等)',
|
||||
created_at: '2026-08-25T10:11:00Z',
|
||||
citations: [
|
||||
{
|
||||
note_id: 'n-rbt',
|
||||
block_id: 'b3',
|
||||
file_path: '/数据结构/红黑树.md',
|
||||
heading_path: '数据结构 / 红黑树 / 与AVL树对比',
|
||||
content: '红黑树相比AVL树,牺牲了部分平衡性以换取更少的旋转操作...',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@ function toIndexStatus(status: ApiIndexStatus): IndexStatus {
|
||||
return {
|
||||
status: status.status === 'idle' ? 'idle' : status.status === 'failed' ? 'error' : 'indexing',
|
||||
pending_jobs: status.pending_jobs,
|
||||
total_notes: 0,
|
||||
total_blocks: 0,
|
||||
fts_enabled: true,
|
||||
vector_enabled: true,
|
||||
total_notes: status.total_notes ?? null,
|
||||
total_blocks: status.total_blocks ?? null,
|
||||
last_indexed_at: status.last_completed_at ?? undefined,
|
||||
error: status.error_message ?? undefined,
|
||||
}
|
||||
@@ -26,15 +24,3 @@ export async function rebuildIndex(scope: 'full' | 'fts' | 'vector' = 'full'): P
|
||||
export async function getIndexJob(jobId: string): Promise<ApiIndexJob> {
|
||||
return apiClient.get(`/api/index/jobs/${jobId}`)
|
||||
}
|
||||
|
||||
export const mockIndexStatus: IndexStatus = {
|
||||
status: 'idle',
|
||||
pending_jobs: 0,
|
||||
total_notes: 42,
|
||||
total_blocks: 318,
|
||||
fts_enabled: true,
|
||||
vector_enabled: true,
|
||||
embedding_model: 'bge-m3',
|
||||
reranker_model: 'bge-reranker-base',
|
||||
last_indexed_at: new Date().toISOString(),
|
||||
}
|
||||
|
||||
@@ -126,92 +126,3 @@ export async function deletePluginSecret(pluginId: string, key: string): Promise
|
||||
export async function uninstallPlugin(pluginId: string): Promise<OperationResponse> {
|
||||
return apiClient.delete(`/api/plugins/${pluginId}`)
|
||||
}
|
||||
|
||||
export const mockPlugins: Plugin[] = [
|
||||
{
|
||||
plugin_id: 'github-integration',
|
||||
name: 'GitHub 集成',
|
||||
version: '1.3.2',
|
||||
description: '接入 GitHub API,支持搜索 Issue、查看 PR 和管理仓库',
|
||||
icon: '',
|
||||
author: 'NotesAgent 团队',
|
||||
status: 'ready',
|
||||
enabled: true,
|
||||
permissions: ['notes.read', 'network.request'],
|
||||
contributions: [
|
||||
{ type: 'tool', id: 'github.search_issues', name: '搜索 Issue', description: '搜索 GitHub 仓库中的 Issue' },
|
||||
{ type: 'tool', id: 'github.get_pr', name: '获取 PR 详情', description: '获取 Pull Request 的详细信息' },
|
||||
{ type: 'command', id: 'github.open_repo', name: '打开仓库', description: '在浏览器中打开对应 GitHub 仓库' },
|
||||
],
|
||||
backend_type: 'mcp',
|
||||
transport: 'stdio',
|
||||
dependent_skills: ['research-assistant'],
|
||||
},
|
||||
{
|
||||
plugin_id: 'translator',
|
||||
name: '翻译助手',
|
||||
version: '1.0.0',
|
||||
description: '提供多语言翻译能力,支持文档批量翻译',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
status: 'ready',
|
||||
enabled: false,
|
||||
permissions: ['notes.read', 'notes.write', 'network.request'],
|
||||
contributions: [
|
||||
{ type: 'tool', id: 'translator.translate', name: '翻译文本', description: '翻译指定文本到目标语言' },
|
||||
{ type: 'command', id: 'translator.translate_note', name: '翻译当前笔记', description: '翻译当前打开的笔记' },
|
||||
{ type: 'settings_section', id: 'translator.settings', name: '翻译设置', description: '配置翻译服务和默认语言' },
|
||||
],
|
||||
backend_type: 'mcp',
|
||||
transport: 'stdio',
|
||||
},
|
||||
{
|
||||
plugin_id: 'kanban',
|
||||
name: '看板视图',
|
||||
version: '0.8.0',
|
||||
description: '为任务提供看板视图,支持拖拽排序和多维度筛选',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
status: 'installed',
|
||||
enabled: false,
|
||||
permissions: ['tasks.read', 'tasks.write'],
|
||||
contributions: [
|
||||
{ type: 'sidebar_panel', id: 'kanban.panel', name: '任务看板', description: '以看板方式查看和管理任务' },
|
||||
],
|
||||
backend_type: 'internal_rpc',
|
||||
},
|
||||
{
|
||||
plugin_id: 'pdf-importer',
|
||||
name: 'PDF 导入',
|
||||
version: '2.1.0',
|
||||
description: '导入 PDF 文档,提取文本和目录结构生成笔记',
|
||||
icon: '',
|
||||
author: 'NotesAgent 团队',
|
||||
status: 'error',
|
||||
enabled: false,
|
||||
permissions: ['notes.write', 'attachments.read'],
|
||||
contributions: [
|
||||
{ type: 'importer', id: 'pdf.import', name: 'PDF 导入器', description: '从 PDF 文件导入内容' },
|
||||
],
|
||||
backend_type: 'mcp',
|
||||
transport: 'stdio',
|
||||
last_error: 'PDF 解析库初始化失败,请检查 Python 依赖',
|
||||
},
|
||||
{
|
||||
plugin_id: 'calendar',
|
||||
name: '日历同步',
|
||||
version: '0.5.0',
|
||||
description: '同步日历事件,自动生成相关笔记和任务提醒',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
status: 'dependency_missing',
|
||||
enabled: false,
|
||||
permissions: ['tasks.read', 'tasks.write', 'network.request'],
|
||||
contributions: [
|
||||
{ type: 'tool', id: 'calendar.events', name: '日历事件', description: '获取日历事件列表' },
|
||||
{ type: 'sidebar_panel', id: 'calendar.widget', name: '日历小部件', description: '侧边栏日历视图' },
|
||||
],
|
||||
backend_type: 'mcp',
|
||||
transport: 'http',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -15,7 +15,7 @@ function toProvider(provider: ApiProviderConfig): ProviderConfig {
|
||||
enabled: provider.enabled,
|
||||
capabilities: capabilityMap(provider.capabilities),
|
||||
credential_id: provider.credential_id ?? undefined,
|
||||
has_credential: Boolean(provider.credential_id) || provider.provider_type === 'mock',
|
||||
has_credential: Boolean(provider.credential_id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ function toModel(model: ApiModelInfo): ModelInfo {
|
||||
|
||||
export async function listProviders(): Promise<ProviderConfig[]> {
|
||||
const response = await apiClient.get<{ items: ApiProviderConfig[] }>('/api/providers')
|
||||
return response.items.map(toProvider)
|
||||
return response.items.filter(provider => provider.provider_type !== 'mock').map(toProvider)
|
||||
}
|
||||
|
||||
export async function getProvider(providerId: string): Promise<ProviderConfig> {
|
||||
@@ -97,102 +97,3 @@ export async function testProvider(providerId: string): Promise<TestResult> {
|
||||
return { success: false, error_code: e.code || 'TEST_FAILED', error_message: e.message }
|
||||
}
|
||||
}
|
||||
|
||||
export const mockProviders: ProviderConfig[] = [
|
||||
{
|
||||
provider_id: 'mock',
|
||||
provider_type: 'mock',
|
||||
name: 'Mock Provider (测试)',
|
||||
default_model: 'mock-1',
|
||||
enabled: true,
|
||||
has_credential: true,
|
||||
capabilities: {
|
||||
chat: true,
|
||||
tool_calling: true,
|
||||
streaming: true,
|
||||
vision: false,
|
||||
reasoning: false,
|
||||
structured_output: true,
|
||||
embedding: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
provider_id: 'openai-compat-1',
|
||||
provider_type: 'openai_compatible',
|
||||
name: 'OpenAI 兼容服务',
|
||||
base_url: 'https://api.openai.com/v1',
|
||||
default_model: 'gpt-4o-mini',
|
||||
enabled: true,
|
||||
has_credential: true,
|
||||
capabilities: {
|
||||
chat: true,
|
||||
tool_calling: true,
|
||||
streaming: true,
|
||||
vision: true,
|
||||
reasoning: false,
|
||||
structured_output: true,
|
||||
embedding: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
provider_id: 'ollama-local',
|
||||
provider_type: 'ollama',
|
||||
name: 'Ollama (本地)',
|
||||
base_url: 'http://127.0.0.1:11434',
|
||||
default_model: 'qwen2.5:7b',
|
||||
enabled: false,
|
||||
has_credential: false,
|
||||
capabilities: {
|
||||
chat: true,
|
||||
tool_calling: false,
|
||||
streaming: true,
|
||||
vision: false,
|
||||
reasoning: false,
|
||||
structured_output: false,
|
||||
embedding: true,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const mockModels: Record<string, ModelInfo[]> = {
|
||||
mock: [
|
||||
{
|
||||
model_id: 'mock-1',
|
||||
name: 'Mock Model v1',
|
||||
capabilities: { chat: true, tool_calling: true, streaming: true, structured_output: true },
|
||||
context_window: 8192,
|
||||
},
|
||||
],
|
||||
'openai-compat-1': [
|
||||
{
|
||||
model_id: 'gpt-4o-mini',
|
||||
name: 'GPT-4o Mini',
|
||||
capabilities: { chat: true, tool_calling: true, streaming: true, vision: true, structured_output: true },
|
||||
context_window: 128000,
|
||||
},
|
||||
{
|
||||
model_id: 'gpt-4o',
|
||||
name: 'GPT-4o',
|
||||
capabilities: { chat: true, tool_calling: true, streaming: true, vision: true, structured_output: true, reasoning: true },
|
||||
context_window: 128000,
|
||||
},
|
||||
{
|
||||
model_id: 'text-embedding-3-small',
|
||||
name: 'Text Embedding 3 Small',
|
||||
capabilities: { embedding: true },
|
||||
},
|
||||
],
|
||||
'ollama-local': [
|
||||
{
|
||||
model_id: 'qwen2.5:7b',
|
||||
name: 'Qwen 2.5 7B',
|
||||
capabilities: { chat: true, streaming: true },
|
||||
context_window: 32768,
|
||||
},
|
||||
{
|
||||
model_id: 'bge-m3',
|
||||
name: 'BGE M3',
|
||||
capabilities: { embedding: true },
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -35,69 +35,3 @@ export async function search(request: SearchRequest): Promise<{
|
||||
mode: response.mode,
|
||||
}
|
||||
}
|
||||
|
||||
export async function searchMock(
|
||||
query: string,
|
||||
mode: 'fts' | 'vector' | 'hybrid' = 'hybrid'
|
||||
): Promise<{
|
||||
results: SearchResult[]
|
||||
total: number
|
||||
mode: 'fts' | 'vector' | 'hybrid'
|
||||
}> {
|
||||
await new Promise((r) => setTimeout(r, 300))
|
||||
if (!query.trim()) return { results: [], total: 0, mode }
|
||||
const results: SearchResult[] = [
|
||||
{
|
||||
block_id: 'b1',
|
||||
note_id: 'n-rbt',
|
||||
note_title: '红黑树',
|
||||
file_path: '/数据结构/红黑树.md',
|
||||
heading_path: '数据结构 / 红黑树 / 插入操作',
|
||||
snippet: '插入后可能破坏红黑性质,需要通过变色和旋转来修复...',
|
||||
score: 0.95,
|
||||
match_type: 'hybrid',
|
||||
tags: ['数据结构', '树'],
|
||||
},
|
||||
{
|
||||
block_id: 'b2',
|
||||
note_id: 'n-rbt',
|
||||
note_title: '红黑树',
|
||||
file_path: '/数据结构/红黑树.md',
|
||||
heading_path: '数据结构 / 红黑树 / 性质',
|
||||
snippet: '红黑树是一种自平衡二叉搜索树,每个节点带有颜色属性(红或黑)...',
|
||||
score: 0.87,
|
||||
match_type: 'fts',
|
||||
tags: ['数据结构'],
|
||||
},
|
||||
{
|
||||
block_id: 'b3',
|
||||
note_id: 'n-bst',
|
||||
note_title: '二叉搜索树',
|
||||
file_path: '/数据结构/二叉搜索树.md',
|
||||
heading_path: '数据结构 / 二叉搜索树 / 基本操作',
|
||||
snippet: '二叉搜索树的插入需要先找到合适的位置,再添加新节点...',
|
||||
score: 0.72,
|
||||
match_type: 'vector',
|
||||
tags: ['数据结构', '树'],
|
||||
},
|
||||
{
|
||||
block_id: 'b4',
|
||||
note_id: 'n-deadlock',
|
||||
note_title: '死锁',
|
||||
file_path: '/操作系统/死锁.md',
|
||||
heading_path: '操作系统 / 死锁 / 必要条件',
|
||||
snippet: '死锁的四个必要条件:互斥、占有并等待、不可抢占、循环等待...',
|
||||
score: 0.45,
|
||||
match_type: 'vector',
|
||||
tags: ['操作系统'],
|
||||
},
|
||||
]
|
||||
const filtered = results.filter(
|
||||
(r) =>
|
||||
r.note_title.includes(query) ||
|
||||
r.snippet.includes(query) ||
|
||||
r.heading_path.includes(query) ||
|
||||
query.length > 1
|
||||
)
|
||||
return { results: filtered, total: filtered.length, mode }
|
||||
}
|
||||
|
||||
@@ -42,77 +42,3 @@ export async function disableSkill(skillId: string): Promise<Skill> {
|
||||
export async function uninstallSkill(skillId: string): Promise<OperationResponse> {
|
||||
return apiClient.delete(`/api/skills/${skillId}`)
|
||||
}
|
||||
|
||||
export const mockSkills: Skill[] = [
|
||||
{
|
||||
skill_id: 'exam-review',
|
||||
name: '期末复习助手',
|
||||
version: '1.0.0',
|
||||
description: '根据课程笔记生成复习要点和练习题,帮助高效备考',
|
||||
icon: '',
|
||||
author: 'NotesAgent 团队',
|
||||
permissions: ['notes.search', 'notes.read', 'tasks.create'],
|
||||
tools: ['notes.search', 'notes.read', 'tasks.create'],
|
||||
retrieval_config: { top_k: 10, rerank: true, citation: true },
|
||||
model_requirements: { capabilities: ['chat', 'tool_calling'] },
|
||||
status: 'ready',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
skill_id: 'meeting-summary',
|
||||
name: '会议纪要生成',
|
||||
version: '1.1.0',
|
||||
description: '从音频或文本中提取会议要点、行动项和待办任务',
|
||||
icon: '',
|
||||
author: 'NotesAgent 团队',
|
||||
permissions: ['notes.search', 'notes.write', 'tasks.write', 'attachments.read'],
|
||||
tools: ['notes.search', 'notes.create', 'tasks.create', 'attachments.read'],
|
||||
retrieval_config: { top_k: 5, rerank: false, citation: true },
|
||||
model_requirements: { capabilities: ['chat', 'tool_calling', 'structured_output'] },
|
||||
status: 'ready',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
skill_id: 'code-explainer',
|
||||
name: '代码解读助手',
|
||||
version: '0.9.0',
|
||||
description: '分析代码片段,解释功能、复杂度和优化建议',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
permissions: ['notes.search', 'notes.read'],
|
||||
tools: ['notes.search', 'notes.read', 'rag.search'],
|
||||
retrieval_config: { top_k: 8, rerank: true, citation: true },
|
||||
model_requirements: { capabilities: ['chat', 'tool_calling'] },
|
||||
status: 'installed',
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
skill_id: 'research-assistant',
|
||||
name: '文献研究助手',
|
||||
version: '1.2.0',
|
||||
description: '自动整理文献笔记,生成研究综述和引用关系图',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
permissions: ['notes.search', 'notes.read', 'notes.write'],
|
||||
tools: ['notes.search', 'notes.read', 'notes.create', 'rag.search'],
|
||||
retrieval_config: { top_k: 15, rerank: true, citation: true },
|
||||
model_requirements: { capabilities: ['chat', 'tool_calling', 'reasoning'] },
|
||||
status: 'dependency_missing',
|
||||
enabled: false,
|
||||
missing_dependencies: ['文献引用插件', '知识图谱插件'],
|
||||
},
|
||||
{
|
||||
skill_id: 'language-tutor',
|
||||
name: '语言学习助手',
|
||||
version: '0.5.0',
|
||||
description: '基于你的学习笔记生成语言练习和记忆卡片',
|
||||
icon: '',
|
||||
author: '社区贡献',
|
||||
permissions: ['notes.search', 'notes.read', 'tasks.create'],
|
||||
tools: ['notes.search', 'notes.read', 'tasks.create'],
|
||||
retrieval_config: { top_k: 6, rerank: false, citation: false },
|
||||
model_requirements: { capabilities: ['chat'] },
|
||||
status: 'ready',
|
||||
enabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import apiClient from './apiClient'
|
||||
import type { SystemStatus } from '@/contracts'
|
||||
|
||||
export async function healthCheck(): Promise<{ status: string }> {
|
||||
try {
|
||||
return await apiClient.get<{ status: string }>('/health')
|
||||
} catch {
|
||||
return { status: 'unavailable' }
|
||||
}
|
||||
export function healthCheck(): Promise<{ status: string }> {
|
||||
return apiClient.get('/health')
|
||||
}
|
||||
|
||||
export async function getStatus(): Promise<SystemStatus> {
|
||||
try {
|
||||
return await apiClient.get<SystemStatus>('/api/status')
|
||||
} catch {
|
||||
return {
|
||||
status: 'ok',
|
||||
name: 'notes-agent',
|
||||
version: '0.1.0',
|
||||
environment: import.meta.env.DEV ? 'development' : 'production',
|
||||
}
|
||||
}
|
||||
export function getStatus(): Promise<SystemStatus> {
|
||||
return apiClient.get('/api/status')
|
||||
}
|
||||
|
||||
export function getPermissionPolicy(): Promise<Record<string, 'allow' | 'confirm' | 'deny'>> {
|
||||
return apiClient.get('/api/permissions/policy')
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import apiClient from './apiClient'
|
||||
import type { ApiTask, OperationResponse, PageMeta, TaskItem, TaskStatus, TaskPriority } from '@/contracts'
|
||||
import type { ApiTask, OperationResponse, PageMeta, TaskItem, TaskStatus } from '@/contracts'
|
||||
|
||||
function toTask(task: ApiTask): TaskItem {
|
||||
return {
|
||||
@@ -7,10 +7,8 @@ function toTask(task: ApiTask): TaskItem {
|
||||
title: task.title,
|
||||
description: task.description,
|
||||
status: task.status,
|
||||
priority: 'medium',
|
||||
due_date: task.due_at ?? undefined,
|
||||
note_id: task.note_id ?? undefined,
|
||||
source: 'user',
|
||||
created_at: task.created_at,
|
||||
updated_at: task.updated_at,
|
||||
}
|
||||
@@ -60,67 +58,3 @@ export async function updateTask(
|
||||
export async function deleteTask(taskId: string): Promise<OperationResponse> {
|
||||
return apiClient.delete(`/api/tasks/${taskId}`)
|
||||
}
|
||||
|
||||
export const mockTasks: TaskItem[] = [
|
||||
{
|
||||
task_id: 't-1',
|
||||
title: '完成红黑树章节复习',
|
||||
description: '整理插入、删除操作的所有情况,准备期末复习',
|
||||
status: 'todo',
|
||||
priority: 'high',
|
||||
due_date: '2026-08-30T23:59:00Z',
|
||||
note_id: 'n-rbt',
|
||||
note_title: '红黑树',
|
||||
source: 'user',
|
||||
created_at: '2026-08-20T10:00:00Z',
|
||||
updated_at: '2026-08-25T14:30:00Z',
|
||||
},
|
||||
{
|
||||
task_id: 't-2',
|
||||
title: '理解死锁的银行家算法',
|
||||
description: '推导银行家算法的安全性检查过程',
|
||||
status: 'in_progress',
|
||||
priority: 'medium',
|
||||
note_id: 'n-deadlock',
|
||||
note_title: '死锁',
|
||||
source: 'agent',
|
||||
created_at: '2026-08-22T09:00:00Z',
|
||||
updated_at: '2026-08-24T16:00:00Z',
|
||||
},
|
||||
{
|
||||
task_id: 't-3',
|
||||
title: 'TCP 三次握手与四次挥手',
|
||||
description: '',
|
||||
status: 'done',
|
||||
priority: 'high',
|
||||
note_id: 'n-tcp',
|
||||
note_title: 'TCP_IP',
|
||||
source: 'user',
|
||||
created_at: '2026-08-15T08:00:00Z',
|
||||
updated_at: '2026-08-18T20:00:00Z',
|
||||
},
|
||||
{
|
||||
task_id: 't-4',
|
||||
title: 'HTTP 状态码整理',
|
||||
description: '整理常见 HTTP 状态码及含义',
|
||||
status: 'todo',
|
||||
priority: 'low',
|
||||
note_id: 'n-http',
|
||||
note_title: 'HTTP协议',
|
||||
source: 'note',
|
||||
created_at: '2026-08-10T10:00:00Z',
|
||||
updated_at: '2026-08-10T10:00:00Z',
|
||||
},
|
||||
{
|
||||
task_id: 't-5',
|
||||
title: '链表操作实现练习',
|
||||
description: '实现单链表和双向链表的基本操作',
|
||||
status: 'todo',
|
||||
priority: 'medium',
|
||||
note_id: 'n-slist',
|
||||
note_title: '单链表',
|
||||
source: 'agent',
|
||||
created_at: '2026-08-23T11:00:00Z',
|
||||
updated_at: '2026-08-23T11:00:00Z',
|
||||
},
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user