feat(page-ai): add skill context and agent profile policy
This commit is contained in:
@@ -2,7 +2,9 @@ use super::hermes_client;
|
||||
use crate::app::AppState;
|
||||
use crate::context::RequestContext;
|
||||
use crate::error::WebError;
|
||||
use crate::hermes_tools::{artifact, block, doc, manifest, page, resource, ToolCallInput};
|
||||
use crate::hermes_tools::{
|
||||
artifact, block, context_tools, doc, manifest, page, resource, skill, ToolCallInput,
|
||||
};
|
||||
use axum::extract::{Extension, Query, State};
|
||||
use axum::http::{HeaderMap, HeaderName, HeaderValue, StatusCode};
|
||||
use axum::Json;
|
||||
@@ -347,6 +349,14 @@ pub(crate) async fn execute_mnote_tool_call(
|
||||
return Ok(cached);
|
||||
}
|
||||
let result = match input.tool_name.as_str() {
|
||||
"mnote.skill.read" => skill::skill_read(&context, &input).await,
|
||||
"mnote.context.snapshot" => context_tools::context_snapshot(&state, &context, &input).await,
|
||||
"mnote.context.read_current_page" => {
|
||||
context_tools::read_current_page(&state, &context, &input).await
|
||||
}
|
||||
"mnote.context.resolve_target" => {
|
||||
context_tools::resolve_target(&state, &context, &input).await
|
||||
}
|
||||
"mnote.doc.fetch" => doc::doc_fetch(&state, &context, &input).await,
|
||||
"mnote.doc.find" => doc::doc_find(&state, &context, &input).await,
|
||||
"mnote.doc.plan_update" => doc::plan_update(&state, &context, &input).await,
|
||||
@@ -538,6 +548,10 @@ fn is_read_tool(tool_name: &str) -> bool {
|
||||
matches!(
|
||||
tool_name,
|
||||
"mnote.page.get"
|
||||
| "mnote.skill.read"
|
||||
| "mnote.context.snapshot"
|
||||
| "mnote.context.read_current_page"
|
||||
| "mnote.context.resolve_target"
|
||||
| "mnote.doc.fetch"
|
||||
| "mnote.doc.find"
|
||||
| "mnote.block.fetch"
|
||||
@@ -1359,6 +1373,80 @@ mod tests {
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn hermes_tools_context_read_current_page_reads_local_markdown() {
|
||||
let root = std::env::temp_dir().join(format!(
|
||||
"mnote-context-read-current-page-{}",
|
||||
std::process::id()
|
||||
));
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
fs::create_dir_all(&root).expect("root");
|
||||
fs::write(
|
||||
root.join("README.md"),
|
||||
"# 当前页\n\n来自 mnote.context.read_current_page 的正文。\n",
|
||||
)
|
||||
.expect("markdown");
|
||||
let root_uri = format!("file://{}", root.display());
|
||||
crate::routes::local_folder_source::initialize_local_workspace_for_actor(
|
||||
"user_1", &root_uri,
|
||||
)
|
||||
.expect("workspace");
|
||||
|
||||
let response = app()
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method("POST")
|
||||
.uri("/api/hermes/tools/mnote/call")
|
||||
.header("content-type", "application/json")
|
||||
.header("x-mnote-actor-id", "user_1")
|
||||
.header("x-mnote-actor-type", "user")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"toolName": "mnote.context.read_current_page",
|
||||
"workspaceId": "local-ws-context",
|
||||
"documentId": "local-md:README.md",
|
||||
"sourceKind": "local_folder",
|
||||
"rootUri": root_uri,
|
||||
"profile": "reasonix",
|
||||
"actorId": "user_1",
|
||||
"sessionId": "sess_context_read",
|
||||
"runId": "run_context_read",
|
||||
"toolCallId": "call_context_read",
|
||||
"traceId": "trace_context_read",
|
||||
"args": {
|
||||
"format": "markdown",
|
||||
"contextRefs": [{ "kind": "current_page" }],
|
||||
"aiAccessScope": {
|
||||
"permissionLevel": "read_write",
|
||||
"allowedRoots": [{ "rootUri": root_uri, "permission": "write" }],
|
||||
"allowedResourceIds": ["local-md:README.md"]
|
||||
}
|
||||
}
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.expect("request"),
|
||||
)
|
||||
.await
|
||||
.expect("response");
|
||||
let status = response.status();
|
||||
let body = to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.expect("body");
|
||||
let payload: Value = serde_json::from_slice(&body).expect("json");
|
||||
assert_eq!(status, StatusCode::OK, "{payload}");
|
||||
assert_eq!(payload["ok"], true);
|
||||
assert_eq!(payload["result"]["ok"], true);
|
||||
assert!(
|
||||
payload["result"]["content"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.contains("mnote.context.read_current_page"),
|
||||
"{payload}"
|
||||
);
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn hermes_tools_mindmap_fetch_reads_authorized_local_resource() {
|
||||
let root = std::env::temp_dir().join(format!(
|
||||
|
||||
Reference in New Issue
Block a user