Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/remote-connect/feishu-bot-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Credentials & Basic Info - Copy App ID and App Secret

### Step6

Open BitFun - Remote Connect - SMS Bot - Feishu Bot - Fill in App ID and App Secret - Connect
Open BitFun - Remote Connect - IM Bot - Feishu Bot - Fill in App ID and App Secret - Connect

### Step7

Expand Down
2 changes: 1 addition & 1 deletion docs/remote-connect/feishu-bot-setup.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

### 第六步

打开 BitFun - 远程连接 - SMS 机器人 - Feishu 机器人 - 填写 App ID 和 App Secret - 连接
打开 BitFun - 远程连接 - IM 机器人 - Feishu 机器人 - 填写 App ID 和 App Secret - 连接

### 第七步

Expand Down
6 changes: 6 additions & 0 deletions src/apps/cli/src/ui/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub struct Theme {
pub border: Color,
}

impl Default for Theme {
fn default() -> Self {
Self::dark()
}
}

impl Theme {
pub fn dark() -> Self {
Self {
Expand Down
47 changes: 46 additions & 1 deletion src/apps/desktop/src/api/remote_connect_api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Tauri commands for Remote Connect.

use bitfun_core::service::remote_connect::{
bot::{self, BotConfig},
bot::{self, weixin, BotConfig},
lan, ConnectionMethod, ConnectionResult, PairingState, RemoteConnectConfig,
RemoteConnectService,
};
Expand Down Expand Up @@ -363,6 +363,12 @@ pub async fn remote_connect_get_methods() -> Result<Vec<ConnectionMethodInfo>, S
available: true,
description: "Via Telegram".into(),
},
ConnectionMethod::BotWeixin => ConnectionMethodInfo {
id: "bot_weixin".into(),
name: "WeChat (Weixin)".into(),
available: true,
description: "Via WeChat iLink bot".into(),
},
})
.collect();

Expand All @@ -382,6 +388,7 @@ fn parse_connection_method(
}),
"bot_feishu" => Ok(ConnectionMethod::BotFeishu),
"bot_telegram" => Ok(ConnectionMethod::BotTelegram),
"bot_weixin" => Ok(ConnectionMethod::BotWeixin),
_ => Err(format!("unknown connection method: {method}")),
}
}
Expand Down Expand Up @@ -485,6 +492,20 @@ pub struct ConfigureBotRequest {
pub app_id: Option<String>,
pub app_secret: Option<String>,
pub bot_token: Option<String>,
pub weixin_ilink_token: Option<String>,
pub weixin_base_url: Option<String>,
pub weixin_bot_account_id: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct WeixinQrStartRequest {
pub base_url: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct WeixinQrPollRequest {
pub session_key: String,
pub base_url: Option<String>,
}

#[tauri::command]
Expand All @@ -500,6 +521,11 @@ pub async fn remote_connect_configure_bot(request: ConfigureBotRequest) -> Resul
"telegram" => BotConfig::Telegram {
bot_token: request.bot_token.unwrap_or_default(),
},
"weixin" => BotConfig::Weixin {
ilink_token: request.weixin_ilink_token.unwrap_or_default(),
base_url: request.weixin_base_url.unwrap_or_default(),
bot_account_id: request.weixin_bot_account_id.unwrap_or_default(),
},
_ => return Err(format!("unknown bot type: {}", request.bot_type)),
};

Expand All @@ -509,6 +535,7 @@ pub async fn remote_connect_configure_bot(request: ConfigureBotRequest) -> Resul
match &bot_config {
BotConfig::Feishu { .. } => config.bot_feishu = Some(bot_config),
BotConfig::Telegram { .. } => config.bot_telegram = Some(bot_config),
BotConfig::Weixin { .. } => config.bot_weixin = Some(bot_config),
}
let service = RemoteConnectService::new(config).map_err(|e| format!("init: {e}"))?;
*guard = Some(service);
Expand All @@ -519,6 +546,24 @@ pub async fn remote_connect_configure_bot(request: ConfigureBotRequest) -> Resul
Ok(())
}

#[tauri::command]
pub async fn remote_connect_weixin_qr_start(
request: WeixinQrStartRequest,
) -> Result<weixin::WeixinQrStartResponse, String> {
weixin::weixin_qr_start(request.base_url)
.await
.map_err(|e| format!("weixin qr start: {e}"))
}

#[tauri::command]
pub async fn remote_connect_weixin_qr_poll(
request: WeixinQrPollRequest,
) -> Result<weixin::WeixinQrPollResponse, String> {
weixin::weixin_qr_poll(&request.session_key, request.base_url)
.await
.map_err(|e| format!("weixin qr poll: {e}"))
}

#[tauri::command]
pub async fn remote_connect_get_bot_verbose_mode() -> Result<bool, String> {
let data = bot::load_bot_persistence();
Expand Down
2 changes: 2 additions & 0 deletions src/apps/desktop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ pub async fn run() {
api::remote_connect_api::remote_connect_set_form_state,
api::remote_connect_api::remote_connect_configure_custom_server,
api::remote_connect_api::remote_connect_configure_bot,
api::remote_connect_api::remote_connect_weixin_qr_start,
api::remote_connect_api::remote_connect_weixin_qr_poll,
api::remote_connect_api::remote_connect_get_bot_verbose_mode,
api::remote_connect_api::remote_connect_set_bot_verbose_mode,
// MiniApp API
Expand Down
2 changes: 2 additions & 0 deletions src/crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ regex = { workspace = true }
base64 = { workspace = true }
image = { workspace = true }
md5 = { workspace = true }
aes = "0.8"
hex = "0.4"
dashmap = { workspace = true }
indexmap = { workspace = true }

Expand Down
2 changes: 1 addition & 1 deletion src/crates/core/src/agentic/agents/explore_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl Agent for ExploreAgent {
}

fn description(&self) -> &str {
r#"Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. \"src/components/**/*.tsx\"), search code for keywords (eg. \"API endpoints\"), or answer questions about the codebase (eg. \"how do API endpoints work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"very thorough\" for comprehensive analysis across multiple locations and naming conventions."#
r#"Subagent for **wide** codebase exploration only. Use when the main agent would need many sequential search/read rounds across multiple areas, or the user asks for an architectural survey. Do **not** use for narrow tasks: a known path, a single class/symbol lookup, one obvious Grep pattern, or reading a handful of files — the main agent should use Grep, Glob, and Read for those. When calling, set thoroughness in the prompt: \"quick\", \"medium\", or \"very thorough\"."#
}

fn prompt_template_name(&self, _model_name: Option<&str>) -> &str {
Expand Down
14 changes: 7 additions & 7 deletions src/crates/core/src/agentic/agents/prompts/agentic_mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,20 @@ The user will primarily request you perform software engineering tasks. This inc


# Tool usage policy
- When doing file search, prefer to use the Task tool in order to reduce context usage.
- You should proactively use the Task tool with specialized agents when the task at hand matches the agent's description.
- For routine codebase lookups (known or guessable paths, a single symbol or class name, one Grep/Glob pattern, or reading a few files), use Read, Grep, and Glob directly. That is usually faster than spawning a subagent.
- Use the Task tool with specialized subagents only when the work clearly matches that subagent and is substantial enough to justify the extra session (multi-step autonomous work, or genuinely broad exploration as described below).
- When WebFetch returns a message about a redirect to a different host, you should immediately make a new WebFetch request with the redirect URL provided in the response.
- You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.
- If the user specifies that they want you to run tools "in parallel", you MUST send a single message with multiple tool use content blocks. For example, if you need to launch multiple agents in parallel, send a single message with multiple Task tool calls.
- Use specialized tools instead of bash commands when possible, as this provides a better user experience. For file operations, use dedicated tools: Read for reading files instead of cat/head/tail, Edit for editing instead of sed/awk, and Write for creating files instead of cat with heredoc or echo redirection. Reserve bash tools exclusively for actual system commands and terminal operations that require shell execution. NEVER use bash echo or other command-line tools to communicate thoughts, explanations, or instructions to the user. Output all communication directly in your response text instead.
- VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the Task tool with subagent_type=Explore instead of running search commands directly.
- Use Task with subagent_type=Explore only for **broad** exploration: the location is unknown across several areas, you need a survey of many modules, or the question is architectural ("how is X wired end-to-end?") and would otherwise take many sequential search rounds. If you can answer with a few Grep/Glob/Read calls, do that yourself instead of Explore.
<example>
user: Where are errors from the client handled?
assistant: [Uses the Task tool with subagent_type=Explore to find the files that handle client errors instead of using Glob or Grep directly]
user: Give me a high-level map of how authentication flows through this monorepo
assistant: [Uses the Task tool with subagent_type=Explore because multiple services and layers must be traced]
</example>
<example>
user: What is the codebase structure?
assistant: [Uses the Task tool with subagent_type=Explore]
user: Where is class ClientError defined?
assistant: [Uses Grep or Glob directly — a needle query; do not spawn Explore]
</example>

IMPORTANT: Assist with defensive security tasks only. Refuse to create, modify, or improve code that may be used maliciously. Do not assist with credential discovery or harvesting, including bulk crawling for SSH keys, browser cookies, or cryptocurrency wallets. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ IMPORTANT: Never generate or guess URLs for the user unless you are confident th
# Tools
- Use TodoWrite for non-trivial or multi-step tasks, and keep it updated.
- Use AskUserQuestion only when a decision materially changes the result and cannot be inferred safely.
- Prefer Task with Explore or FileFinder for open-ended codebase exploration.
- Prefer Read, Grep, and Glob for targeted lookups.
- Use Read, Grep, and Glob by default for codebase lookups; they are faster for narrow or single-location questions.
- Use Task with Explore or FileFinder only for genuinely open-ended or multi-area exploration (many modules, unclear ownership, architectural surveys).
- Prefer specialized file tools over Bash for reading and editing files.
- Use Bash for builds, tests, git, and scripts.
- Run independent tool calls in parallel when possible.
Expand Down
4 changes: 3 additions & 1 deletion src/crates/core/src/agentic/session/compression_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,9 @@ impl CompressionManager {
self.compressed_histories
.insert(session_id.to_string(), compressed_messages.clone());

// Persist compression history (similar to MessageHistoryManager pattern)
// Persist compression history (similar to MessageHistoryManager pattern).
// Persistence is intentionally off until the storage contract is finalized.
#[allow(clippy::overly_complex_bool_expr)]
if false && self.config.enable_persistence {
if let Err(e) = self
.persistence
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ When NOT to use the Task tool:
- If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly
- If you are searching for a specific class definition like "class Foo", use the Glob tool instead, to find the match more quickly
- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly
- For subagent_type=Explore: do not use it for simple lookups above; reserve it for broad or multi-area exploration where many tool rounds would be needed
- Other tasks that are not related to the agent descriptions above


Expand Down
Loading
Loading