refactor: enhance tool discovery by excluding read-only tools

- Introduced a utility function to identify read-only tools in both TypeScript and Rust implementations.
- Updated tool discovery logic to filter out read-only tools, ensuring only actionable tools are included in the skill definitions.
- Improved comments for clarity regarding the handling of tool data from the memory layer.
This commit is contained in:
M3gA-Mind
2026-03-26 23:01:45 +05:30
parent debd044491
commit a4d0c3a8cb
3 changed files with 31 additions and 11 deletions
+13 -2
View File
@@ -312,15 +312,26 @@ fn has_meaningful_content(content: &str) -> bool {
// ─── Tool discovery (desktop only) ───────────────────────────────────────────
/// Returns true for read-only tools whose data is served by the memory layer, not the LLM tool loop.
fn is_read_tool(name: &str) -> bool {
name.starts_with("get-")
|| name.starts_with("list-")
|| name.starts_with("query-")
|| name == "search"
|| name == "sync-status"
}
/// Build OpenAI-format tool definitions from the Rust skill registry.
/// Tool names are namespaced as `{skill_id}__{tool_name}`.
/// Read-only tools are excluded — their data comes from the memory layer (Step 2 context recall).
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn discover_tools(
engine: &crate::runtime::qjs_engine::RuntimeEngine,
) -> Vec<serde_json::Value> {
let raw_tools = engine.all_tools();
raw_tools
engine
.all_tools()
.into_iter()
.filter(|(_, tool)| !is_read_tool(&tool.name))
.map(|(skill_id, tool)| {
serde_json::json!({
"type": "function",
-1
View File
@@ -230,7 +230,6 @@ impl MemoryClient {
log::warn!("[memory] recall_skill_context: exit — error (namespace={namespace}): {e}");
format!("Memory recall failed: {e}")
})?;
log::info!("[memory] recall_skill_context: response: {res:?}");
let response = res.data.context;
log::info!(
"[memory] recall_skill_context: exit — ok (namespace={namespace}, has_response={})",
+18 -8
View File
@@ -463,18 +463,28 @@ const Conversations = () => {
{ role: 'user' as const, content: processedUserContent },
];
// Read-only tools are excluded — their data comes from the memory layer (recalled in context above).
const isReadTool = (toolName: string): boolean =>
toolName.startsWith('get-') ||
toolName.startsWith('list-') ||
toolName.startsWith('query-') ||
toolName === 'search' ||
toolName === 'sync-status';
// Build tool definitions for ALL ready skills — namespaced as {skillId}__{toolName}
const allSkillTools: Tool[] = Object.entries(skillsState.skills)
.filter(([, skill]) => skill.status === 'ready' && skill.tools?.length)
.flatMap(([skillId, skill]) =>
(skill.tools ?? []).map(t => ({
type: 'function' as const,
function: {
name: `${skillId}__${t.name}`,
description: t.description,
parameters: t.inputSchema as Tool['function']['parameters'],
},
}))
(skill.tools ?? [])
.filter(t => !isReadTool(t.name))
.map(t => ({
type: 'function' as const,
function: {
name: `${skillId}__${t.name}`,
description: t.description,
parameters: t.inputSchema as Tool['function']['parameters'],
},
}))
);
console.log(