Compare commits
2
Commits
c3df4a23cc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084452abf6 | ||
|
|
8b4bd59572 |
No files matched your search
@@ -3,6 +3,15 @@
|
|||||||
All notable changes to CodeCraft. Versions follow [Semantic Versioning](https://semver.org/);
|
All notable changes to CodeCraft. Versions follow [Semantic Versioning](https://semver.org/);
|
||||||
until 1.0, minor versions may contain breaking changes.
|
until 1.0, minor versions may contain breaking changes.
|
||||||
|
|
||||||
|
## [v202611-00025] – 2026-11-12
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Models did not find built-in tools via `mcp_search`** (e.g. `generate_3d` in a chat that
|
||||||
|
had just been switched from plan to build): the search only looked at MCP servers. It now also
|
||||||
|
lists matching built-in tools and says whether the current mode has them ("available – call it
|
||||||
|
directly", or "not in the read-only mode plan – ask the user to switch to build").
|
||||||
|
|
||||||
## [v202611-00024] – 2026-11-12
|
## [v202611-00024] – 2026-11-12
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="Version v202611-00024" src="https://img.shields.io/badge/version-v202611--00024-d69e2e?style=flat-square">
|
<img alt="Version v202611-00025" src="https://img.shields.io/badge/version-v202611--00025-d69e2e?style=flat-square">
|
||||||
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-689d6a?style=flat-square">
|
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-689d6a?style=flat-square">
|
||||||
<img alt="Rust backend" src="https://img.shields.io/badge/backend-Rust-b7410e?style=flat-square&logo=rust">
|
<img alt="Rust backend" src="https://img.shields.io/badge/backend-Rust-b7410e?style=flat-square&logo=rust">
|
||||||
<img alt="React PWA" src="https://img.shields.io/badge/frontend-React%20PWA-2d81ff?style=flat-square&logo=react">
|
<img alt="React PWA" src="https://img.shields.io/badge/frontend-React%20PWA-2d81ff?style=flat-square&logo=react">
|
||||||
|
|||||||
+41
-2
@@ -558,6 +558,42 @@ impl McpManager {
|
|||||||
/// Search the on-demand MCP tools by keywords.
|
/// Search the on-demand MCP tools by keywords.
|
||||||
pub struct McpSearch;
|
pub struct McpSearch;
|
||||||
|
|
||||||
|
/// Built-in tools matching the search words, with their availability in the current mode.
|
||||||
|
fn builtin_matches(ctx: &ToolCtx, words: &[&str]) -> String {
|
||||||
|
if words.is_empty() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
let app = &ctx.app;
|
||||||
|
let owner_id = app.session(&ctx.session_id).ok().and_then(|s| s.owner_id);
|
||||||
|
let owner_user = owner_id.as_deref().and_then(|id| app.store.user(id).ok().flatten());
|
||||||
|
let root = app.root_for(owner_id.as_deref(), &ctx.cwd);
|
||||||
|
let agent = crate::prompts::find_agent_for(app, &root, &ctx.cwd, &ctx.agent, owner_id.as_deref());
|
||||||
|
let available: std::collections::HashSet<String> = crate::runner::available_tools(app, &agent, owner_user.as_ref()).iter().map(|t| t.name().to_string()).collect();
|
||||||
|
let mut hits: Vec<(usize, String)> = crate::tools::builtin_tools()
|
||||||
|
.iter()
|
||||||
|
.map(|t| {
|
||||||
|
let name = t.name().to_lowercase();
|
||||||
|
let desc = t.description().to_lowercase();
|
||||||
|
let score: usize = words.iter().map(|w| if name.contains(w) { 3 } else if desc.contains(w) { 1 } else { 0 }).sum();
|
||||||
|
let state = if available.contains(t.name()) {
|
||||||
|
"available – call it directly".to_string()
|
||||||
|
} else if agent.read_only && !t.read_only() {
|
||||||
|
format!("exists, but not in the read-only mode \"{}\" – ask the user to switch to build mode", agent.name)
|
||||||
|
} else {
|
||||||
|
format!("exists, but not available in mode \"{}\" (or disabled in the settings)", agent.name)
|
||||||
|
};
|
||||||
|
(score, format!("- {}: {state}", t.name()))
|
||||||
|
})
|
||||||
|
.filter(|(s, _)| *s >= 2 || words.len() == 1 && *s >= 1)
|
||||||
|
.collect();
|
||||||
|
hits.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
if hits.is_empty() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
let list: Vec<String> = hits.into_iter().take(4).map(|(_, l)| l).collect();
|
||||||
|
format!("Built-in tools (not MCP – call them directly by name, not via mcp_call):\n{}\n\n", list.join("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Tool for McpSearch {
|
impl Tool for McpSearch {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@@ -602,10 +638,13 @@ impl Tool for McpSearch {
|
|||||||
.filter(|(s, _)| *s > 0 || words.is_empty())
|
.filter(|(s, _)| *s > 0 || words.is_empty())
|
||||||
.collect();
|
.collect();
|
||||||
scored.sort_by(|a, b| b.0.cmp(&a.0));
|
scored.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
// Models also look here for built-in tools (e.g. generate_3d): say that they exist,
|
||||||
|
// whether this mode has them, and that they are called directly.
|
||||||
|
let builtin = if server.is_none() { builtin_matches(ctx, &words) } else { String::new() };
|
||||||
if scored.is_empty() {
|
if scored.is_empty() {
|
||||||
return Ok(ToolOutput::text("No matching tools. Try other keywords or another server."));
|
return Ok(ToolOutput::text(if builtin.is_empty() { "No matching tools. Try other keywords or another server.".to_string() } else { builtin }));
|
||||||
}
|
}
|
||||||
let mut out = String::new();
|
let mut out = builtin;
|
||||||
for (_, t) in scored.iter().take(8) {
|
for (_, t) in scored.iter().take(8) {
|
||||||
let desc: String = t.info.description.chars().take(300).collect();
|
let desc: String = t.info.description.chars().take(300).collect();
|
||||||
out.push_str(&format!("## {}\n{}\nInput schema: {}\n\n", t.full_name, desc, t.info.input_schema));
|
out.push_str(&format!("## {}\n{}\nInput schema: {}\n\n", t.full_name, desc, t.info.input_schema));
|
||||||
|
|||||||
Reference in new issue
Block a user