配置: - rustfmt.toml: 固化 max_width=100 / 4 空格缩进,cargo fmt 全量格式化 - Cargo.toml: 配置 [lints.rust] 与 [lints.clippy] 渐进式规则 - .github/workflows/ci.yml: Rust(fmt+clippy+test) + 前端(eslint+tsc+test) 双平台 CI - Makefile: 新增 check/fmt/fix 目标,clippy 对齐 --all-targets --all-features - web: eslint flat config + prettier 配置 + package.json 脚本与依赖 - src/main.rs: loop→while 修复 clippy::never_loop 对抗性审查发现并修复: - eslint 缺 caughtErrorsIgnorePattern 导致 catch(_) 误报为 error - 前端 lint 未接入 CI,现已补上 Lint 步骤 - Makefile 与 CI 的 clippy flags 不一致,已对齐
150 lines
4.3 KiB
Rust
150 lines
4.3 KiB
Rust
use crate::command::Command;
|
|
use crate::command::adapter::{AdapterError, InputAdapter};
|
|
use crate::command::context::AdapterContext;
|
|
|
|
/// Channel 输入适配器
|
|
///
|
|
/// 将 Channel 消息中的文本命令(如 "/new", "/save")转换为 Command
|
|
pub struct ChannelInputAdapter;
|
|
|
|
impl ChannelInputAdapter {
|
|
/// 创建新的 Channel 输入适配器
|
|
pub fn new() -> Self {
|
|
Self
|
|
}
|
|
}
|
|
|
|
impl Default for ChannelInputAdapter {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl InputAdapter for ChannelInputAdapter {
|
|
fn try_parse(
|
|
&self,
|
|
input: &str,
|
|
_ctx: AdapterContext,
|
|
) -> Result<Option<Command>, AdapterError> {
|
|
let trimmed = input.trim();
|
|
|
|
// 解析 /new 命令
|
|
if trimmed == "/new" {
|
|
return Ok(Some(Command::CreateSession { title: None }));
|
|
}
|
|
|
|
if let Some(title) = trimmed.strip_prefix("/new ") {
|
|
let title = title.trim();
|
|
return Ok(Some(Command::CreateSession {
|
|
title: Some(title.to_string()),
|
|
}));
|
|
}
|
|
|
|
// 解析 /save 命令 - 保存当前话题
|
|
if trimmed == "/save" {
|
|
return Ok(Some(Command::SaveTopic {
|
|
filepath: None,
|
|
include_subagents: false,
|
|
}));
|
|
}
|
|
|
|
if let Some(args) = trimmed.strip_prefix("/save ") {
|
|
let args = args.trim();
|
|
let parts: Vec<&str> = args.split_whitespace().collect();
|
|
|
|
// 解析参数
|
|
let mut include_subagents = false;
|
|
let mut filepath = None;
|
|
|
|
for part in parts {
|
|
if part == "+sub" {
|
|
include_subagents = true;
|
|
} else if !part.is_empty() {
|
|
// 非特殊参数视为文件路径
|
|
filepath = Some(part.to_string());
|
|
}
|
|
}
|
|
|
|
return Ok(Some(Command::SaveTopic {
|
|
filepath,
|
|
include_subagents,
|
|
}));
|
|
}
|
|
|
|
// 解析 /save-session 命令 - 保存整个会话
|
|
if trimmed == "/save-session" {
|
|
return Ok(Some(Command::SaveSession {
|
|
filepath: None,
|
|
include_all: false,
|
|
include_subagents: false,
|
|
}));
|
|
}
|
|
|
|
if let Some(args) = trimmed.strip_prefix("/save-session ") {
|
|
let args = args.trim();
|
|
let parts: Vec<&str> = args.split_whitespace().collect();
|
|
|
|
// 解析参数
|
|
let mut include_all = false;
|
|
let mut include_subagents = false;
|
|
let mut filepath = None;
|
|
|
|
for part in parts {
|
|
if part == "all" {
|
|
include_all = true;
|
|
} else if part == "+sub" {
|
|
include_subagents = true;
|
|
} else if !part.is_empty() {
|
|
// 非特殊参数视为文件路径
|
|
filepath = Some(part.to_string());
|
|
}
|
|
}
|
|
|
|
return Ok(Some(Command::SaveSession {
|
|
filepath,
|
|
include_all,
|
|
include_subagents,
|
|
}));
|
|
}
|
|
|
|
// 解析 /list 命令
|
|
if trimmed == "/list" {
|
|
return Ok(Some(Command::ListSessions {
|
|
include_archived: false,
|
|
}));
|
|
}
|
|
|
|
if trimmed == "/list all" {
|
|
return Ok(Some(Command::ListSessions {
|
|
include_archived: true,
|
|
}));
|
|
}
|
|
|
|
// 解析 /use 命令 - 切换话题(支持 topic_id 或序号)
|
|
if let Some(topic_id) = trimmed.strip_prefix("/use ") {
|
|
let topic_id = topic_id.trim();
|
|
return Ok(Some(Command::SwitchTopic {
|
|
topic_id: topic_id.to_string(),
|
|
}));
|
|
}
|
|
|
|
// 解析 /current 命令 - 获取当前会话信息
|
|
if trimmed == "/current" {
|
|
return Ok(Some(Command::GetCurrentSession));
|
|
}
|
|
|
|
// 解析 /stop 命令 - 停止当前执行的 Agent
|
|
if trimmed == "/stop" {
|
|
return Ok(Some(Command::StopExecution));
|
|
}
|
|
|
|
// 解析 /help 命令 - 显示所有支持的命令
|
|
if trimmed == "/help" {
|
|
return Ok(Some(Command::Help));
|
|
}
|
|
|
|
// 不是命令,返回 None
|
|
Ok(None)
|
|
}
|
|
}
|