Improve local evidence search and AI capabilities

This commit is contained in:
lix-2026
2026-06-05 23:00:53 +08:00
parent a1dcfc9f76
commit 4dbd9a978b
52 changed files with 6415 additions and 527 deletions
@@ -1,9 +1,94 @@
use super::skill;
use serde_json::{json, Value};
pub const MANIFEST_SCHEMA_VERSION: &str = "mnote.hermes_tool_manifest.v1";
pub const TOOL_SCHEMA_VERSION: &str = "mnote.hermes_tool.v1";
pub fn manifest() -> Value {
let tools = annotate_tools_with_capabilities(vec![
skill_read_tool(),
context_snapshot_tool(),
context_read_current_page_tool(),
context_resolve_target_tool(),
doc_fetch_tool(),
doc_find_tool(),
evidence_search_tool(),
evidence_read_tool(),
evidence_open_tool(),
index_status_tool(),
index_refresh_tool(),
index_update_settings_tool(),
block_fetch_tool(),
doc_plan_update_tool(),
block_replace_tool(),
block_insert_after_tool(),
block_delete_tool(),
block_move_after_tool(),
doc_apply_block_ops_tool(),
doc_markdown_edit_tool(),
page_get_tool(),
page_save_tool(),
available_tool(
"mnote.page.update_title",
"更新当前页面标题",
["page.write"],
),
available_tool(
"mnote.page.update_options",
"更新当前页面设置",
["page.write"],
),
mindmap_fetch_tool(),
mindmap_apply_ops_tool(),
mindmap_create_from_outline_tool(),
office_fetch_summary_tool(),
office_propose_changes_tool(),
onlyoffice_session_current_tool(),
onlyoffice_capabilities_tool(),
onlyoffice_selection_get_tool(),
onlyoffice_document_insert_text_tool(),
onlyoffice_document_replace_selection_tool(),
onlyoffice_document_insert_html_tool(),
onlyoffice_document_export_tool(),
onlyoffice_document_search_replace_tool(),
onlyoffice_document_insert_table_tool(),
onlyoffice_document_get_comments_tool(),
onlyoffice_document_add_comment_tool(),
onlyoffice_sheet_get_sheets_tool(),
onlyoffice_sheet_add_sheet_tool(),
onlyoffice_sheet_rename_sheet_tool(),
onlyoffice_sheet_get_range_tool(),
onlyoffice_sheet_get_range_values_tool(),
onlyoffice_sheet_get_values_tool(),
onlyoffice_sheet_set_value_tool(),
onlyoffice_sheet_set_formula_tool(),
onlyoffice_sheet_batch_set_values_tool(),
onlyoffice_sheet_set_range_values_tool(),
onlyoffice_sheet_format_range_tool(),
onlyoffice_sheet_set_dimensions_tool(),
onlyoffice_sheet_sort_range_tool(),
onlyoffice_sheet_add_chart_tool(),
onlyoffice_presentation_get_slides_tool(),
onlyoffice_presentation_get_slide_texts_tool(),
onlyoffice_presentation_get_shapes_tool(),
onlyoffice_presentation_add_text_slide_tool(),
onlyoffice_presentation_replace_text_tool(),
onlyoffice_presentation_set_shape_text_tool(),
onlyoffice_presentation_delete_slide_tool(),
onlyoffice_presentation_add_table_tool(),
onlyoffice_presentation_clear_slide_tool(),
onlyoffice_presentation_add_shape_tool(),
available_tool(
"mnote.artifact.create_summary",
"为当前页面创建或更新 AI Summary",
["artifact.write"],
),
available_tool(
"mnote.artifact.create_ai_note",
"基于当前页面创建新的 AI Note",
["artifact.write"],
),
]);
json!({
"schemaVersion": MANIFEST_SCHEMA_VERSION,
"plugin": {
@@ -12,74 +97,30 @@ pub fn manifest() -> Value {
"runtimeOwner": "mnote-web",
"writeOwner": "rust-runtime-kernel"
},
"tools": [
skill_read_tool(),
context_snapshot_tool(),
context_read_current_page_tool(),
context_resolve_target_tool(),
doc_fetch_tool(),
doc_find_tool(),
evidence_search_tool(),
evidence_read_tool(),
evidence_open_tool(),
block_fetch_tool(),
doc_plan_update_tool(),
block_replace_tool(),
block_insert_after_tool(),
block_delete_tool(),
block_move_after_tool(),
doc_apply_block_ops_tool(),
doc_markdown_edit_tool(),
page_get_tool(),
page_save_tool(),
available_tool("mnote.page.update_title", "更新当前页面标题", ["page.write"]),
available_tool("mnote.page.update_options", "更新当前页面设置", ["page.write"]),
mindmap_fetch_tool(),
mindmap_apply_ops_tool(),
mindmap_create_from_outline_tool(),
office_fetch_summary_tool(),
office_propose_changes_tool(),
onlyoffice_session_current_tool(),
onlyoffice_capabilities_tool(),
onlyoffice_selection_get_tool(),
onlyoffice_document_insert_text_tool(),
onlyoffice_document_replace_selection_tool(),
onlyoffice_document_insert_html_tool(),
onlyoffice_document_export_tool(),
onlyoffice_document_search_replace_tool(),
onlyoffice_document_insert_table_tool(),
onlyoffice_document_get_comments_tool(),
onlyoffice_document_add_comment_tool(),
onlyoffice_sheet_get_sheets_tool(),
onlyoffice_sheet_add_sheet_tool(),
onlyoffice_sheet_rename_sheet_tool(),
onlyoffice_sheet_get_range_tool(),
onlyoffice_sheet_get_range_values_tool(),
onlyoffice_sheet_get_values_tool(),
onlyoffice_sheet_set_value_tool(),
onlyoffice_sheet_set_formula_tool(),
onlyoffice_sheet_batch_set_values_tool(),
onlyoffice_sheet_set_range_values_tool(),
onlyoffice_sheet_format_range_tool(),
onlyoffice_sheet_set_dimensions_tool(),
onlyoffice_sheet_sort_range_tool(),
onlyoffice_sheet_add_chart_tool(),
onlyoffice_presentation_get_slides_tool(),
onlyoffice_presentation_get_slide_texts_tool(),
onlyoffice_presentation_get_shapes_tool(),
onlyoffice_presentation_add_text_slide_tool(),
onlyoffice_presentation_replace_text_tool(),
onlyoffice_presentation_set_shape_text_tool(),
onlyoffice_presentation_delete_slide_tool(),
onlyoffice_presentation_add_table_tool(),
onlyoffice_presentation_clear_slide_tool(),
onlyoffice_presentation_add_shape_tool(),
available_tool("mnote.artifact.create_summary", "为当前页面创建或更新 AI Summary", ["artifact.write"]),
available_tool("mnote.artifact.create_ai_note", "基于当前页面创建新的 AI Note", ["artifact.write"])
]
"capabilities": skill::manifest_capabilities(),
"tools": tools
})
}
fn annotate_tools_with_capabilities(tools: Vec<Value>) -> Vec<Value> {
tools
.into_iter()
.map(|mut tool| {
let name = tool.get("name").and_then(Value::as_str).unwrap_or_default();
let capability_ids = skill::capability_ids_for_tool(name);
if let Value::Object(map) = &mut tool {
if let Some(first) = capability_ids.first() {
map.insert("capabilityId".into(), json!(first));
}
if !capability_ids.is_empty() {
map.insert("capabilityIds".into(), json!(capability_ids));
}
}
tool
})
.collect()
}
fn skill_read_tool() -> Value {
let mut properties = base_identity_properties();
if let Value::Object(map) = &mut properties {
@@ -286,7 +327,7 @@ fn evidence_search_tool() -> Value {
}
json!({
"name": "mnote.evidence.search",
"description": "搜索可回跳原文的文档证据,返回 quote、EvidenceLocatoropenAction。",
"description": "搜索可回跳原文的文档证据,返回 quote、EvidenceLocatoropenAction 与可直接放进最终回答的 citationMarkdown 链接",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["evidence.read", "page.read"],
"status": "available",
@@ -317,7 +358,7 @@ fn evidence_read_tool() -> Value {
}
json!({
"name": "mnote.evidence.read",
"description": "按 EvidenceLocator 读取原文证据及周边上下文,供回答引用。",
"description": "按 EvidenceLocator 读取原文证据及周边上下文,返回 quote/contextBlocks 与可点击引用链接供回答引用。",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["evidence.read", "page.read"],
"status": "available",
@@ -337,7 +378,7 @@ fn evidence_open_tool() -> Value {
}
json!({
"name": "mnote.evidence.open",
"description": "把 EvidenceLocator 归一化为 MNote 可执行的打开/定位动作。",
"description": "把 EvidenceLocator 归一化为 MNote 可执行的打开/定位动作,并返回 citationUrl/citationMarkdown",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["evidence.read", "page.read"],
"status": "available",
@@ -350,6 +391,79 @@ fn evidence_open_tool() -> Value {
})
}
fn index_status_tool() -> Value {
let mut properties = base_identity_properties();
if let Value::Object(map) = &mut properties {
map.insert("rootUri".into(), json!({ "type": "string" }));
}
json!({
"name": "mnote.index.status",
"description": "查看本地索引范围、缓存文件、构建时间、文档数和 evidence block 数。",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["index.read", "evidence.read"],
"status": "available",
"annotations": tool_annotations(true, false, true, false),
"inputSchema": {
"type": "object",
"required": ["workspaceId", "rootUri"],
"properties": properties
}
})
}
fn index_refresh_tool() -> Value {
let mut properties = base_identity_properties();
if let Value::Object(map) = &mut properties {
map.insert("rootUri".into(), json!({ "type": "string" }));
}
json!({
"name": "mnote.index.refresh",
"description": "按当前有效索引范围重建本地搜索/evidence 缓存,不修改 Markdown 正文。",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["index.read", "evidence.read"],
"status": "available",
"annotations": tool_annotations(true, false, false, false),
"inputSchema": {
"type": "object",
"required": ["workspaceId", "rootUri"],
"properties": properties
}
})
}
fn index_update_settings_tool() -> Value {
let mut properties = base_identity_properties();
if let Value::Object(map) = &mut properties {
map.insert("rootUri".into(), json!({ "type": "string" }));
map.insert(
"includePaths".into(),
json!({ "type": "array", "items": { "type": "string" } }),
);
map.insert(
"scheduleMode".into(),
json!({ "type": "string", "enum": ["manual", "daily", "weekly", "monthly"] }),
);
map.insert("scheduleTime".into(), json!({ "type": "string" }));
map.insert("scheduleDate".into(), json!({ "type": "string" }));
map.insert("runOnChange".into(), json!({ "type": "boolean" }));
map.insert("dryRun".into(), json!({ "type": "boolean" }));
map.insert("idempotencyKey".into(), json!({ "type": "string" }));
}
json!({
"name": "mnote.index.update_settings",
"description": "新增或删除本地索引范围;includePaths 为空表示删除当前用户索引范围并在无有效范围时清空索引文件。",
"schemaVersion": TOOL_SCHEMA_VERSION,
"capabilityScope": ["index.write", "evidence.read"],
"status": "available",
"annotations": tool_annotations(false, true, false, false),
"inputSchema": {
"type": "object",
"required": ["workspaceId", "rootUri", "includePaths", "dryRun", "idempotencyKey"],
"properties": properties
}
})
}
fn block_fetch_tool() -> Value {
let mut properties = base_identity_properties();
if let Value::Object(map) = &mut properties {