feat(app-iced): M104 AGENTRAIL —— 右栗三档 + 布局数学 + 独立页复用同一会话视图

用户定案(D16):右侧常驻可折叠、允许拆分成独立页、中栗宽度可调(磁铁吸附)。
本 mission 只做壳:三档状态 + 布局数学 + 一份会话视图;真数据仍归 M103,一行 presenter 都不调。

- 右栗三档:Collapsed(48) / Expanded(280~360,默认 320,锚=令牌 ai_panel_width) / Detached(Route::Agent);
  会话、草稿、未读在切档时一条不丢(拆出去再收回,话说了一半还在)
- 布局数学:中栗 = 窗口 − 右栗 − 拖拽缝(8),下限 472(= 行宽上限 424 + 两侧页边距);
  右栗一展开,页面按更窄的宽度重新排版(收缩而不是溢出);拖拽磁铁吸附到 280/320/360,超上限夹紧
- 独立页与右栗共用 conversation::view 这一份实现(输入=纯数据,输出=agent::Message)
- 控件:多行输入框(Enter 发送 / Shift+Enter 换行,走 text_editor::key_binding 的 modifiers 分流)、
  发送禁用态、流式中断、未读点 + 可读计数、⌄ 收起 / ⇥ 拆出 / ⇤ 收回;Esc 收栗、Tab 焦点环、Enter 激活
- 文案全部进 crates/i18n 的新域 catalog/agent.rs(+ golden 追加 20 行),零硬编码中文
- 取证:ULL_AGENT_RAIL / ULL_AGENT_FIXTURE / ULL_AGENT_WIDTH(截图走产品 bin,标题栏与三键可见)
- 消息不走 pages::Message(外壳级视图),走 app::Message::Agent(..) → app/update/agent.rs
- 删掉 M68 骨架回落(shell::view + shell/fallback.rs):Route::Agent 现在有真页面

门禁:fmt 0 / clippy(workspace,-D warnings) 0 / pages_demo 0 / app-iced lib 418 条全绿
This commit is contained in:
AskaEth committed 2026-11-04 00:21:32 +08:00
1 parent 875ac159ee
commit c3f20784a8
20 files changed
+2463 -153

No files matched your search

+3
View File
@@ -111,6 +111,7 @@ macro_rules! finish {
({ $($acc:tt)* }) => { catalog! { $($acc)* } };
}
mod agent;
mod core_text;
mod download;
mod font;
@@ -127,6 +128,7 @@ mod golden;
#[cfg(test)]
mod tests;
use agent::agent_entries;
use core_text::core_text_entries;
use download::download_entries;
use font::font_entries;
@@ -155,6 +157,7 @@ nav_entries! {
core_text_entries,
download_entries,
logs_entries,
agent_entries,
finish,
{}
}
+40
View File
@@ -0,0 +1,40 @@
//! AI 助手栏 / AI 独立页的文案(M104 `AGENTRAIL`)。
//!
//! 这两处**共用同一套会话视图**(`crates/app-iced/src/pages/agent/`),所以文案也只在这里出现一次:
//! 栏上的折叠/拆出、页上的收回、两处都要的发送/中断/空会话引导。
//!
//! 域文件的形状见 [`crate::catalog`] 的「域装配」一节:本宏把条目**追加**到 `$acc` 之后,
//! 再把「还没装配的域」原样交给 `$next`。条目顺序 = `Key` 的声明顺序(金表 `catalog::golden` 守门)。
//!
//! **新增 key 时按顺序追加在最后**:金表是「拆分前那份表的逐字快照」,重排既有行会让它红。
macro_rules! agent_entries {
($next:ident, $($rest:ident,)* { $($acc:tt)* }) => {
$next! { $($rest,)* {
$($acc)*
// ── AI 助手(右栗 + 独立页共用)
AgentTitle => ("Assistant", "助手"),
AgentSubtitle => ("Conversation shell · no backend yet", "会话外壳 · 后端未接"),
AgentCollapse => ("Collapse", "收起"),
AgentDetach => ("Pop out", "拆出"),
AgentDock => ("Dock back", "收回"),
AgentOpen => ("Open assistant", "打开助手"),
AgentStripLabel => ("AI", "AI"),
AgentSend => ("Send", "发送"),
AgentStop => ("Stop", "中断"),
AgentPlaceholder => ("Message the assistant…", "给助手发消息…"),
AgentEmptyTitle => ("Nothing in this session yet", "这个会话还没有内容"),
AgentEmptyBody => ("Ask about instances, downloads or logs. No model is wired up yet.", "可以问实例、下载或日志。模型还没接上。"),
AgentNotePending => ("Placeholder shell: your message is kept here, nothing was sent to a model.", "占位外壳:消息留在这里,没有发给任何模型。"),
AgentNoteStopped => ("Stopped by you.", "你中断了这次回复。"),
AgentUnread => ("{count} unread", "{count} 条未读"),
AgentResize => ("Drag to resize the assistant rail", "拖动调整助手栏宽度"),
AgentWidthLabel => ("Width {width}", "宽度 {width}"),
AgentRoleYou => ("You", "你"),
AgentRoleAssistant => ("Assistant", "助手"),
AgentRoleNotice => ("Notice", "提示"),
} }
};
}
pub(crate) use agent_entries;
+20
View File
@@ -94,4 +94,24 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
("LogsEmptyTitle", "No output yet", "还没有输出"),
("LogsEmptyBody", "Logs stream here while the launcher or the game is running. Pick an instance and start it to see the first lines.", "启动器或游戏运行时,日志会实时出现在这里。选择一个实例并启动,就能看到第一批日志。"),
("LogsEmptyAction", "Choose an instance", "选择实例"),
("AgentTitle", "Assistant", "助手"),
("AgentSubtitle", "Conversation shell · no backend yet", "会话外壳 · 后端未接"),
("AgentCollapse", "Collapse", "收起"),
("AgentDetach", "Pop out", "拆出"),
("AgentDock", "Dock back", "收回"),
("AgentOpen", "Open assistant", "打开助手"),
("AgentStripLabel", "AI", "AI"),
("AgentSend", "Send", "发送"),
("AgentStop", "Stop", "中断"),
("AgentPlaceholder", "Message the assistant…", "给助手发消息…"),
("AgentEmptyTitle", "Nothing in this session yet", "这个会话还没有内容"),
("AgentEmptyBody", "Ask about instances, downloads or logs. No model is wired up yet.", "可以问实例、下载或日志。模型还没接上。"),
("AgentNotePending", "Placeholder shell: your message is kept here, nothing was sent to a model.", "占位外壳:消息留在这里,没有发给任何模型。"),
("AgentNoteStopped", "Stopped by you.", "你中断了这次回复。"),
("AgentUnread", "{count} unread", "{count} 条未读"),
("AgentResize", "Drag to resize the assistant rail", "拖动调整助手栏宽度"),
("AgentWidthLabel", "Width {width}", "宽度 {width}"),
("AgentRoleYou", "You", "你"),
("AgentRoleAssistant", "Assistant", "助手"),
("AgentRoleNotice", "Notice", "提示"),
];