#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum InvocationKind { Command, Query, Job, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ToolExecutionMode { Plan, Result, ExplainPlan, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ToolInvocation { pub tool: String, pub kind: InvocationKind, pub mode: ToolExecutionMode, pub args_json: String, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ToolEffect { Read, Write, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ToolSpec { pub name: &'static str, pub display_name: &'static str, pub description: &'static str, pub toolset_id: &'static str, pub invocation_kind: InvocationKind, pub effect: ToolEffect, pub requires_confirmation: bool, pub input_schema_json: &'static str, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ToolSetSpec { pub id: &'static str, pub display_name: &'static str, pub description: &'static str, pub write_toolset: bool, pub tool_names: &'static [&'static str], } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ToolRegistry { pub toolsets: &'static [ToolSetSpec], pub tools: &'static [ToolSpec], } impl ToolRegistry { pub const fn new(toolsets: &'static [ToolSetSpec], tools: &'static [ToolSpec]) -> Self { Self { toolsets, tools } } pub fn tool(&self, name: &str) -> Option<&'static ToolSpec> { self.tools.iter().find(|spec| spec.name == name) } pub fn toolset(&self, id: &str) -> Option<&'static ToolSetSpec> { self.toolsets.iter().find(|spec| spec.id == id) } pub fn tool_names(&self) -> Vec<&'static str> { self.tools.iter().map(|spec| spec.name).collect() } pub fn tool_names_in_set(&self, id: &str) -> Option> { self.toolset(id).map(|toolset| toolset.tool_names.to_vec()) } pub fn tools_in_set(&self, id: &str) -> Option> { self.toolset(id).map(|toolset| { toolset .tool_names .iter() .filter_map(|tool_name| self.tool(tool_name)) .collect() }) } } pub const DOC_TOOL_GET: ToolSpec = ToolSpec { name: "doc_get", display_name: "文档读取", description: "读取当前文档快照,用于查看页面内容和结构。", toolset_id: "toolset.doc_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","properties":{"maxBlocks":{"type":"integer","minimum":10,"maximum":240}}}"#, }; pub const SEARCH_WEB_TOOL: ToolSpec = ToolSpec { name: "search_web", display_name: "联网检索", description: "使用 SearxNG 进行联网检索,返回标题、URL 与摘要。", toolset_id: "toolset.readonly", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["query"],"properties":{"query":{"type":"string"},"count":{"type":"integer","minimum":1,"maximum":10}}}"#, }; pub const DOC_TOOL_FIND: ToolSpec = ToolSpec { name: "doc_find", display_name: "文档查找", description: "在当前文档范围内查找片段、标题或结构信息。", toolset_id: "toolset.doc_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["query"],"properties":{"query":{"type":"string"},"maxResults":{"type":"integer","minimum":1,"maximum":30}}}"#, }; pub const IMAGE_READ_TOOL: ToolSpec = ToolSpec { name: "image_read", display_name: "读取图片", description: "读取图片/附件 OCR 信息并返回归一化结果。", toolset_id: "toolset.media_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","properties":{"assetId":{"type":"string"},"fileUrl":{"type":"string"},"attachmentRef":{"type":"string"}}}"#, }; pub const DOC_TOOL_INSERT_BLOCKS: ToolSpec = ToolSpec { name: "doc_insert_blocks", display_name: "插入块", description: "在文档中插入一个或多个块,是写入类操作。", toolset_id: "toolset.doc_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["blocks"],"properties":{"afterBlockId":{"type":"string"},"beforeBlockId":{"type":"string"},"blocks":{"type":"array","minItems":1,"maxItems":20}}}"#, }; pub const DOC_TOOL_REPLACE_RANGE: ToolSpec = ToolSpec { name: "doc_replace_range", display_name: "替换范围", description: "替换文档中的块范围,是写入类操作。", toolset_id: "toolset.doc_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["blockId","text"],"properties":{"blockId":{"type":"string"},"text":{"type":"string"},"mode":{"enum":["replace","append","prepend"]}}}"#, }; pub const SLASH_RUN_TOOL: ToolSpec = ToolSpec { name: "slash_run", display_name: "斜杠命令", description: "解析并规范化斜杠命令,用于创建或重命名页面。", toolset_id: "toolset.slash_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","properties":{"text":{"type":"string"},"command":{"enum":["new_doc","rename_doc"]},"params":{"type":"object"},"reason":{"type":"string"}}}"#, }; pub const MINDMAP_TOOL_GET: ToolSpec = ToolSpec { name: "mindmap_get", display_name: "导图读取", description: "读取当前思维导图的节点摘要,用于定位节点和规划改动。", toolset_id: "toolset.mindmap_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","properties":{"maxNodes":{"type":"integer","minimum":10,"maximum":300}}}"#, }; pub const MINDMAP_TOOL_GET_SUBTREE: ToolSpec = ToolSpec { name: "mindmap_get_subtree", display_name: "导图子树读取", description: "读取指定节点 uid 的子树摘要,供 AI 精确查看局部结构。", toolset_id: "toolset.mindmap_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["uid"],"properties":{"uid":{"type":"string"},"depth":{"type":"integer","minimum":0,"maximum":6},"maxNodes":{"type":"integer","minimum":5,"maximum":200}}}"#, }; pub const MINDMAP_TOOL_PUT: ToolSpec = ToolSpec { name: "mindmap_put", display_name: "导图覆盖写入", description: "使用完整思维导图树覆盖当前导图,适合 CLI 或 AI 在拿到完整快照后直接写回。", toolset_id: "toolset.mindmap_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["data"],"properties":{"data":{"type":"object"},"createOnly":{"type":"boolean"}}}"#, }; pub const MINDMAP_TOOL_APPLY_OPS: ToolSpec = ToolSpec { name: "mindmap_apply_ops", display_name: "导图增量写入", description: "对思维导图应用增量 ops,并返回新的整棵树快照。", toolset_id: "toolset.mindmap_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["ops"],"properties":{"ops":{"type":"array","minItems":1,"maxItems":80},"reason":{"type":"string"},"targetUid":{"type":"string"},"searchResults":{"type":"array"}}}"#, }; pub const MINDMAP_TOOL_EXPAND_NODE: ToolSpec = ToolSpec { name: "mindmap_expand_node", display_name: "补完思维导图节点", description: "对 AI 生成的补完候选做统一归一化,再应用到当前思维导图并返回新树。", toolset_id: "toolset.mindmap_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["targetUid"],"properties":{"targetUid":{"type":"string"},"instruction":{"type":"string"},"ops":{"type":"array","maxItems":80},"searchResults":{"type":"array"},"reason":{"type":"string"}}}"#, }; pub const MINDMAP_TOOL_EMPTY_TRASH: ToolSpec = ToolSpec { name: "mindmap_empty_trash", display_name: "清空导图回收站", description: "校验并标准化清空导图回收站所需的工作区对象,供 route 继续执行实际写入。", toolset_id: "toolset.mindmap_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["workspaceId"],"properties":{"workspaceId":{"type":"string"}}}"#, }; pub const MINDMAP_TOOL_OUTLINE_TO_MINDMAP: ToolSpec = ToolSpec { name: "mindmap_outline_to_mindmap", display_name: "大纲转导图", description: "把结构化大纲转换为标准思维导图树,统一 uid、refs 与 page 链接生成规则。", toolset_id: "toolset.mindmap_write", invocation_kind: InvocationKind::Command, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["rootTitle","pageLinkPattern","outline"],"properties":{"rootTitle":{"type":"string"},"pageLinkPattern":{"type":"string"},"outline":{"type":"array","items":{"type":"object","required":["title","level","page"],"properties":{"title":{"type":"string"},"level":{"type":"integer","minimum":1,"maximum":6},"page":{"type":"integer","minimum":1}}}}}}"#, }; pub const BRIDGE_TOOL_REQUEST_GET: ToolSpec = ToolSpec { name: "bridge_request_get", display_name: "请求回查", description: "按 request_id 查询统一 command log 与 domain event 视图。", toolset_id: "toolset.observe_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["workspaceId","requestId"],"properties":{"workspaceId":{"type":"string"},"requestId":{"type":"string"},"commandId":{"type":"string"}}}"#, }; pub const BRIDGE_TOOL_TRACE_GET: ToolSpec = ToolSpec { name: "bridge_trace_get", display_name: "链路回查", description: "按 trace_id 查询统一 command log 与 domain event 视图。", toolset_id: "toolset.observe_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["workspaceId","traceId"],"properties":{"workspaceId":{"type":"string"},"traceId":{"type":"string"},"commandId":{"type":"string"}}}"#, }; pub const BRIDGE_TOOL_COMMAND_GET: ToolSpec = ToolSpec { name: "bridge_command_get", display_name: "命令回查", description: "按 command_id 查询统一 command log 与 domain event 视图。", toolset_id: "toolset.observe_read", invocation_kind: InvocationKind::Query, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["workspaceId","commandId"],"properties":{"workspaceId":{"type":"string"},"commandId":{"type":"string"}}}"#, }; pub const REPLAY_TOOL_EVENTS: ToolSpec = ToolSpec { name: "event_replay", display_name: "事件回放", description: "基于统一事件流做回放预演,输出将被追平的 event 与派生批次摘要。", toolset_id: "toolset.recovery_job", invocation_kind: InvocationKind::Job, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["workspaceId"],"properties":{"workspaceId":{"type":"string"},"lastProcessedEventId":{"type":"string"},"lastProcessedAt":{"type":"string"}}}"#, }; pub const INDEX_TOOL_REBUILD: ToolSpec = ToolSpec { name: "index_rebuild", display_name: "索引重建", description: "根据事件流重建全文索引游标与派生批次,作为回放和恢复前置命令。", toolset_id: "toolset.recovery_job", invocation_kind: InvocationKind::Job, effect: ToolEffect::Write, requires_confirmation: true, input_schema_json: r#"{"type":"object","required":["workspaceId"],"properties":{"workspaceId":{"type":"string"},"lastProcessedEventId":{"type":"string"},"lastProcessedAt":{"type":"string"}}}"#, }; pub const ONLYOFFICE_TOOL_SESSION_RESOLVE: ToolSpec = ToolSpec { name: "onlyoffice_session_resolve", display_name: "OnlyOffice 会话解析", description: "解析 OnlyOffice 的附件/页面/用户上下文,返回统一 session 与 asset 边界。", toolset_id: "toolset.onlyoffice_service", invocation_kind: InvocationKind::Job, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["assetId"],"properties":{"assetId":{"type":"string"},"workspaceId":{"type":"string"},"documentId":{"type":"string"},"userId":{"type":"string"},"sessionId":{"type":"string"}}}"#, }; pub const ONLYOFFICE_TOOL_SIGN: ToolSpec = ToolSpec { name: "onlyoffice_sign", display_name: "OnlyOffice 签名", description: "为 OnlyOffice config/document/editorConfig 生成 JWT 签名。", toolset_id: "toolset.onlyoffice_service", invocation_kind: InvocationKind::Job, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","properties":{"config":{"type":"object"},"secret":{"type":"string"}}}"#, }; pub const ONLYOFFICE_TOOL_PREPARE_PROXY: ToolSpec = ToolSpec { name: "onlyoffice_prepare_proxy", display_name: "OnlyOffice 代理预处理", description: "校验 proxy 回源目标并返回同源回源所需的上游 URL 与请求头。", toolset_id: "toolset.onlyoffice_service", invocation_kind: InvocationKind::Job, effect: ToolEffect::Read, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["encodedUrl"],"properties":{"encodedUrl":{"type":"string"},"method":{"enum":["GET","HEAD"]},"range":{"type":"string"}}}"#, }; pub const ONLYOFFICE_TOOL_PREPARE_CALLBACK: ToolSpec = ToolSpec { name: "onlyoffice_prepare_callback", display_name: "OnlyOffice callback 预处理", description: "解析 callback 状态、下载地址和 session 边界,供写回链继续执行。", toolset_id: "toolset.onlyoffice_service", invocation_kind: InvocationKind::Job, effect: ToolEffect::Write, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["assetId","status","onlyofficeInternalUrl"],"properties":{"assetId":{"type":"string"},"documentId":{"type":"string"},"workspaceId":{"type":"string"},"userId":{"type":"string"},"sessionId":{"type":"string"},"status":{"type":"integer"},"url":{"type":"string"},"key":{"type":"string"},"onlyofficeInternalUrl":{"type":"string"}}}"#, }; pub const ONLYOFFICE_TOOL_PREPARE_FORCESAVE: ToolSpec = ToolSpec { name: "onlyoffice_prepare_forcesave", display_name: "OnlyOffice forcesave 预处理", description: "生成触发 forcesave 所需的请求序列与 JWT 负载。", toolset_id: "toolset.onlyoffice_service", invocation_kind: InvocationKind::Job, effect: ToolEffect::Write, requires_confirmation: false, input_schema_json: r#"{"type":"object","required":["assetId","key","onlyofficeInternalUrl"],"properties":{"assetId":{"type":"string"},"key":{"type":"string"},"onlyofficeInternalUrl":{"type":"string"},"secret":{"type":"string"}}}"#, }; pub const DOC_TOOLSET_READ: ToolSetSpec = ToolSetSpec { id: "toolset.doc_read", display_name: "文档读取", description: "只读文档工具集合。", write_toolset: false, tool_names: &["doc_get", "doc_find"], }; pub const READONLY_TOOLSET: ToolSetSpec = ToolSetSpec { id: "toolset.readonly", display_name: "只读工具", description: "Rust 只读工具集合。", write_toolset: false, tool_names: &["search_web"], }; pub const MEDIA_TOOLSET: ToolSetSpec = ToolSetSpec { id: "toolset.media_read", display_name: "媒体读取", description: "Rust 媒体读取工具集合。", write_toolset: false, tool_names: &["image_read"], }; pub const DOC_TOOLSET_WRITE: ToolSetSpec = ToolSetSpec { id: "toolset.doc_write", display_name: "文档写入", description: "写入文档工具集合。", write_toolset: true, tool_names: &["doc_insert_blocks", "doc_replace_range"], }; pub const MINDMAP_TOOLSET_READ: ToolSetSpec = ToolSetSpec { id: "toolset.mindmap_read", display_name: "导图读取", description: "只读思维导图工具集合。", write_toolset: false, tool_names: &["mindmap_get", "mindmap_get_subtree"], }; pub const MINDMAP_TOOLSET_WRITE: ToolSetSpec = ToolSetSpec { id: "toolset.mindmap_write", display_name: "导图写入", description: "写入思维导图的工具集合。", write_toolset: true, tool_names: &[ "mindmap_put", "mindmap_apply_ops", "mindmap_expand_node", "mindmap_empty_trash", "mindmap_outline_to_mindmap", ], }; pub const OBSERVE_TOOLSET_READ: ToolSetSpec = ToolSetSpec { id: "toolset.observe_read", display_name: "统一观测", description: "按 request、trace、command 回查统一日志与事件视图。", write_toolset: false, tool_names: &[ "bridge_request_get", "bridge_trace_get", "bridge_command_get", ], }; pub const RECOVERY_TOOLSET_JOB: ToolSetSpec = ToolSetSpec { id: "toolset.recovery_job", display_name: "恢复与重建", description: "统一事件回放、索引重建与恢复类任务集合。", write_toolset: true, tool_names: &["event_replay", "index_rebuild"], }; pub const ONLYOFFICE_TOOLSET_SERVICE: ToolSetSpec = ToolSetSpec { id: "toolset.onlyoffice_service", display_name: "OnlyOffice 服务边界", description: "供 Web route / CLI / AI 共享的 OnlyOffice 对象适配工具集合。", write_toolset: true, tool_names: &[ "onlyoffice_session_resolve", "onlyoffice_sign", "onlyoffice_prepare_proxy", "onlyoffice_prepare_callback", "onlyoffice_prepare_forcesave", ], }; pub const SLASH_TOOLSET_WRITE: ToolSetSpec = ToolSetSpec { id: "toolset.slash_write", display_name: "斜杠命令", description: "Rust 斜杠命令工具集合。", write_toolset: true, tool_names: &["slash_run"], }; pub const DOC_TOOL_REGISTRY: ToolRegistry = ToolRegistry::new( &[ READONLY_TOOLSET, MEDIA_TOOLSET, SLASH_TOOLSET_WRITE, DOC_TOOLSET_READ, DOC_TOOLSET_WRITE, MINDMAP_TOOLSET_READ, MINDMAP_TOOLSET_WRITE, OBSERVE_TOOLSET_READ, RECOVERY_TOOLSET_JOB, ONLYOFFICE_TOOLSET_SERVICE, ], &[ SEARCH_WEB_TOOL, DOC_TOOL_GET, DOC_TOOL_FIND, IMAGE_READ_TOOL, DOC_TOOL_INSERT_BLOCKS, DOC_TOOL_REPLACE_RANGE, SLASH_RUN_TOOL, MINDMAP_TOOL_GET, MINDMAP_TOOL_GET_SUBTREE, MINDMAP_TOOL_PUT, MINDMAP_TOOL_APPLY_OPS, MINDMAP_TOOL_EXPAND_NODE, MINDMAP_TOOL_EMPTY_TRASH, MINDMAP_TOOL_OUTLINE_TO_MINDMAP, BRIDGE_TOOL_REQUEST_GET, BRIDGE_TOOL_TRACE_GET, BRIDGE_TOOL_COMMAND_GET, REPLAY_TOOL_EVENTS, INDEX_TOOL_REBUILD, ONLYOFFICE_TOOL_SESSION_RESOLVE, ONLYOFFICE_TOOL_SIGN, ONLYOFFICE_TOOL_PREPARE_PROXY, ONLYOFFICE_TOOL_PREPARE_CALLBACK, ONLYOFFICE_TOOL_PREPARE_FORCESAVE, ], ); pub fn default_tool_registry() -> &'static ToolRegistry { &DOC_TOOL_REGISTRY } pub fn tool_mode_label(mode: &ToolExecutionMode) -> &'static str { match mode { ToolExecutionMode::Plan => "plan", ToolExecutionMode::Result => "result", ToolExecutionMode::ExplainPlan => "explain-plan", } } pub fn invocation_kind_label(kind: &InvocationKind) -> &'static str { match kind { InvocationKind::Command => "command", InvocationKind::Query => "query", InvocationKind::Job => "job", } } pub fn tool_effect_label(effect: &ToolEffect) -> &'static str { match effect { ToolEffect::Read => "read", ToolEffect::Write => "write", } }