mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-31 08:39:24 +00:00
Fix Telegram Markdown formatting and clarify tool/memory distinctions
- Add escape_telegram_markdown() to handle underscores in tool names (e.g., build_software was breaking Telegram's Markdown parser) - Use Telegram-compatible *bold* syntax instead of **bold** - Clarify workspace memory vs filesystem tool descriptions to prevent LLM from using read_file on memory_tree paths - Update build_software to strongly prefer Rust WASM for agent tools - Rewrite WASM tool template to use Component Model with wit_bindgen instead of outdated extern "C" approach Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
9edc666ee3
commit
aec42aceda
+35
-7
@@ -2,6 +2,29 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Escape special characters for Telegram's legacy Markdown.
|
||||
///
|
||||
/// In Telegram's Markdown mode, these characters have special meaning:
|
||||
/// - `_` starts/ends italic
|
||||
/// - `*` starts/ends bold
|
||||
/// - `` ` `` starts/ends code
|
||||
/// - `[` starts a link
|
||||
///
|
||||
/// We escape them with backslash so dynamic content doesn't break formatting.
|
||||
fn escape_telegram_markdown(s: &str) -> String {
|
||||
let mut result = String::with_capacity(s.len());
|
||||
for c in s.chars() {
|
||||
match c {
|
||||
'_' | '*' | '`' | '[' => {
|
||||
result.push('\\');
|
||||
result.push(c);
|
||||
}
|
||||
_ => result.push(c),
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
use futures::StreamExt;
|
||||
use tokio::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
@@ -341,17 +364,22 @@ impl Agent {
|
||||
} else {
|
||||
params_preview
|
||||
};
|
||||
// Escape Markdown special chars in dynamic values to avoid breaking
|
||||
// Telegram's Markdown parser (underscores, asterisks, backticks, brackets)
|
||||
let tool_name_escaped = escape_telegram_markdown(&tool_name);
|
||||
let description_escaped = escape_telegram_markdown(&description);
|
||||
// Params go inside a code block, so no escaping needed there
|
||||
Ok(Some(format!(
|
||||
"🔒 Tool requires approval:\n\n\
|
||||
**Tool:** {}\n\
|
||||
**Description:** {}\n\
|
||||
**Parameters:** ```\n{}\n```\n\n\
|
||||
*Tool:* {}\n\
|
||||
*Description:* {}\n\
|
||||
*Parameters:*\n```\n{}\n```\n\n\
|
||||
Reply with:\n\
|
||||
- `yes` or `approve` to allow this tool\n\
|
||||
- `always` to always allow this tool in this session\n\
|
||||
- `no` or `deny` to reject\n\n\
|
||||
• yes or approve to allow this tool\n\
|
||||
• always to always allow this tool in this session\n\
|
||||
• no or deny to reject\n\n\
|
||||
Request ID: {}",
|
||||
tool_name, description, params_truncated, request_id
|
||||
tool_name_escaped, description_escaped, params_truncated, request_id
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ impl HeartbeatRunner {
|
||||
};
|
||||
|
||||
let response = OutgoingResponse {
|
||||
content: format!("🔔 **Heartbeat Alert**\n\n{}", message),
|
||||
content: format!("🔔 *Heartbeat Alert*\n\n{}", message),
|
||||
thread_id: None,
|
||||
metadata: serde_json::json!({
|
||||
"source": "heartbeat",
|
||||
|
||||
Reference in New Issue
Block a user