Skip to content

refactor: monorepo 化重组 + 桌面端 j-gui 集成 + v12.10.73 同步#4

Open
wuqie-xuanzhao wants to merge 175 commits into
LingoJack:mainfrom
wuqie-xuanzhao:main
Open

refactor: monorepo 化重组 + 桌面端 j-gui 集成 + v12.10.73 同步#4
wuqie-xuanzhao wants to merge 175 commits into
LingoJack:mainfrom
wuqie-xuanzhao:main

Conversation

@wuqie-xuanzhao
Copy link
Copy Markdown

@wuqie-xuanzhao wuqie-xuanzhao commented May 25, 2026

Summary

将 fork 上的 monorepo 改造和桌面端集成工作提交回上游,供参考和讨论。

主要变更

  • monorepo 重组: Rust crates 移入 crates/(j-cli、j-tui、j-md、j-agent),前端资源移入 apps/
  • j-tui crate 提取: TUI 组件、Markdown 编辑器、终端渲染器独立为共享 crate
  • j-md crate 提取: 共享 Markdown IR 与解析器独立化
  • 桌面端 j-gui: 基于 Tauri 的桌面应用导入到 apps/desktop/
  • editor.rs 拆分: 从 1600 行拆分为 api/commands/render/selection 子模块
  • Insert 命令面板: 编辑器 Insert 模式下输入 / 弹出命令面板
  • 流式 Markdown 重绘: 从 DSR 光标定位改为行数跟踪 + Unicode 宽度
  • v12.10.73 同步: 合并上游最新 6 个 commit 的全部内容

结构对比

路径 上游 本 PR
Rust 主程序 src/ crates/j-cli/src/
TUI 组件 src/tui/ crates/j-tui/src/
Markdown src/markdown/ crates/j-md/src/
桌面端 apps/desktop/

编译验证

  • cargo check / cargo clippy 全 workspace 通过
  • 所有 crate 版本已同步至 v12.10.73

Test plan

  • cargo build 全 workspace 编译通过
  • cargo clippy 无警告
  • cargo test 全 workspace 测试通过
  • j ai "测试" oneshot 模式 Markdown 渲染正常
  • j TUI 模式编辑器、命令面板、鼠标选区功能正常
  • j md 编辑器 Insert 模式 / 命令面板弹出并正常工作

🤖 Generated with Claude Code

LingoJack and others added 30 commits May 8, 2026 11:46
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
从 jcli 继承 Rust 编码约束,适配至 j-gui (Tauri 桌面应用),参照 Rust API Guidelines 补充官方命名和文档规范。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 后端新增 YamlConfig 读写命令(get_config/set_config)和别名 CRUD 命令(list/set/remove)
- 设置对话框三 tab 全部实现(模型/通用/别名),修复 provider 移除时 activeIndex 越界
- 消息操作完善:JSONL 行级删除 + 截断重发 + CopyButton
- session_id 路径穿越校验(hex-only)+ 代码审查 5 项修复
- 新增 CLAUDE.md(CodeStable 工作流集成 + 行为准则)
- 配套 CodeStable 文档:架构子系统 4 份、决策/探索/需求/roadmap 同步更新

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ystem-prompt

- 主题持久化到 agent_config.theme,j-cli 7 主题选择器(暗/亮 optgroup)+ 字体大小
- Ctrl+K 全局搜索对话框(模糊过滤 + 键盘导航 Arrow/Enter/Escape)
- 无 Provider 时 WelcomePage 引导页(三步文案 + 一键跳转设置)
- 流式取消:Channel send 失败 → cancelled 标志位 → 跳过后续 chunk + 不写盘
- 系统提示词弹窗编辑器(Pencil 图标 + textarea + click-outside 关闭)
- ChatHeader token 估算徽章(字符/3.5)+ 清空上下文按钮(SessionEvent::Clear)
- ErrorBoundary(componentDidCatch 日志 + 重试计数上限 3 次)包裹所有 Tab 内容
- 代码审查修复:stale state provider 移除、session ID 路径穿越校验、JSON 解析替换字符串匹配

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… commands/session_id验证/TOCTOU修复

前端:
- sessions.ts 重构为 per-tab Map atoms,每个标签页独立消息/流式/草稿状态
- currentSessionIdAtom 写回 activeTab,支持多标签并行对话
- 新增 Governance 模块:HooksTab / McpTab / SkillsTab + settings primitives
- LeftSidebar/MainArea/AppShell setTabs 全部改用函数式更新器防 stale closure
- ChatView catch 块 null activeTabId 防御

后端:
- 新增 commands/governance.rs: list_skills / list_hooks / list_mcp_servers / save_mcp_servers
- agent_session.rs: 所有公共函数加 validate_session_id 防路径遍历
- governance.rs: save_mcp_servers 加 MCP_CONFIG_LOCK 防 TOCTOU 竞态
- chat_engine.rs: SESSION_WRITE_LOCK 统一写入锁 + clear_session 方法
- agent_engine.rs: let _ = 改为 write_error_log

文档:
- CodeStable: 6 份 feature design + 17 份 audit findings + roadmap/架构更新
- docs/api/: 全量 API 参考文档

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…DD 5/5

后端:
- governance.rs 新增 BUILTIN_TOOLS 静态目录(21 工具)+ list_chat_tools / set_tool_enabled 命令
- set_tool_enabled 复用 MCP_CONFIG_LOCK 保护配置读写,验证未知工具名

前端:
- ToolsTab.tsx:Wrench 图标 + 名称/描述 + SettingsToggle 启停 + 空态/加载态
- tauri.ts 新增 ToolInfo/listChatTools/setToolEnabled IPC 绑定
- SettingsDialog 注册 "工具" tab

测试:
- tools-tab.test.tsx: 5/5 (loading / 列表渲染 / 描述 / toggle交互 / 空态)

其他:
- CLAUDE.md: bun test → bun run test (修复 jsdom 配置不生效)
- attention.md: 新增测试命令说明 + roadmap 进度报告约束

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#55 proma-parity-agent-tool-renderers (P0):
- ToolCallDisplay 重构为分型渲染:Read/Write/Edit/PowerShell/Grep/Glob/Web 各有专属 header + 摘要
- 安全 JSON parse + extractPath/extractCommand/extractPattern 提取函数
- 错误态红色文本、运行态格式化输入、完成态摘要
- AgentMessages 传递扁平 props
- TDD: 7/7 tests

#60 proma-parity-core-shortcuts (P1):
- useKeyboardShortcuts hook: Ctrl+,/N/B/F/L/K/W + Ctrl+Shift+M/Backspace 共 9 个快捷键
- Ctrl+W 关 tab 时检查 streaming 状态弹确认
- atoms/ui.ts: settingsOpenAtom + searchOpenAtom
- AppShell 改用 atom 驱动 settings/search 开关
- TDD: 5/5 tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#50 proma-parity-shell-sidebar (P0):
- sessionsAtom 已按 activeTab.type 正确路由(chat→chatSessions, agent→agentSessionsList)
- LeftSidebar 添加模式指示器("Chat 模式" / "Agent 模式")
- 会话创建/切换/删除按当前 tab 类型路由
- TDD: 3/3 atoms tests pass

#58 proma-parity-search-navigation (P1):
- SearchDialog 内部获取会话数据,合并 Chat+Agent 结果
- highlightMatch 导出 + <mark> 高亮匹配文本
- data-mode="chat"/"agent" 属性 + 模式图标(MessageSquare/Bot)
- Props 简化为 onSelectSession 单一回调
- IPC: listAgentSessions → getAgentSessionList 统一命名
- TDD: 3/3 search tests pass

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ings-console

#51 proma-parity-tabs-workspace (P0):
- MainArea: 流式 tab 关闭确认弹窗 + 欢迎空态 + overflow-x-auto + per-tab ErrorBoundary
- Ctrl+Tab / Ctrl+Shift+Tab 键盘切换标签
- executeCloseTab 改用函数式更新器防 stale closure

#53 proma-parity-chat-tools (P1):
- ChatView: Channel 新增 toolStart/toolResult/toolError 事件处理
- ChatToolBlock 组件: running/done/error 三态渲染
- Message.toolCall 类型 + MessageBubble 条件渲染

#59 proma-parity-settings-console (P1):
- 验证 7 tab 全覆盖 + 模态布局 + dirty 保护 + 空/错态
- SettingsDialog 测试: 5/5 (导航/模态/切换/结构/空态)

安全修复(code review):
- MainArea executeCloseTab/setTabs 全部改用函数式更新器
- useKeyboardShortcuts handleCloseTab 改用函数式更新器

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
修复发现 LingoJack#4 #6 #8 #11 #12 #13 #14,覆盖 bug/security/performance/maintainability 四维:

后端:
- LingoJack#4: AgentEngine::close() 加入 500ms grace period 再杀子进程
- #6: API Key 环境变量添加安全注释
- #8: JSON 解析中关键字段缺失时 eprintln! 告警

前端组件拆分:
- #11: RightSidePanel TreeNodeItem 抽取 memo 组件
- #12: AgentView 抽取 useAgentEngine hook (510→175行)
- #13: SettingsDialog 抽取 ModelsTab/GeneralTab/AliasTab (488→85行)
- #14: LeftSidebar 抽取 SessionItem memo 组件

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
currentSessionIdAtom 的 write 函数无条件创建新 tabsAtom 引用,
导致 AppShell 的 useEffect 触发 setSessionId → 再写 tabsAtom → 死循环。

修复:写前检查 sessionId 是否实际变化,相等则跳过。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#52 chat-experience:
- ContextDivider 组件 — 清上下文后可见分割线
- ScrollMinimap 组件 — 长对话滚动定位
- AgentRecommendBanner — Chat 模式推荐切换 Agent
- chatClearMarker atom — per-tab 清空标记

#54 agent-interrupts:
- AskUserBanner + ExitPlanModeBanner — 三类中断审批 UI
- Interrupt kind 路由 (permission/ask_user/plan)
- respond_agent_interrupt 响应按 kind 分型
- PermissionBanner Always Allow 按钮

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…1 session-workbench

#57 agent-file-context:
- RightSidePanel 多目录支持 + "添加目录"按钮
- @ 文件 mention picker (Agent 模式)
- Per-tab 右面板状态隔离

#56 agent-task-context:
- ContextUsageBadge 真实 token 圈环指示器
- BackgroundTasksPanel 跨 tab 后台任务面板
- TaskProgressCard 失败态 + 动画增强
- Permission mode per-tab 持久化

#61 agent-session-workbench:
- AgentHeader 组件 (标题编辑、面板切换)
- Agent 7 态状态机 (starting/waiting/streaming/done/empty/timeout/disconnected)
- 启动超时 + 重试 + 错误状态 UI
- 会话隔离验证

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…early return

Moved useCallback before the `if (!hasAnyAgents) return null` early return
to avoid "Rendered more hooks than during the previous render" crash when
switching to Agent mode.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
items.yaml: #52 #54 #56 #57 #61 → done, #62 → in-progress
roadmap.md: 更新完成度清单 (62/62 items, 60 done)
acceptance/proma-parity/: #62 首次验收证据收口

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
LingoJack#2 (P0): Agent 默认 permissionMode → "default" (非 bypass)
LingoJack#3 (P1): 关闭最后 tab 不再自动补位,空态可见
LingoJack#4 (P1): 添加停止按钮 (ChatInput onStop + AgentView/ChatView 接入)
#5 (P1): parse_sdk_line 未知消息类型加 eprintln! 日志
LingoJack#1 (P0): ChatView Channel 添加 DEV 日志用于调试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
LingoJack#1: LeftSidebar 无活动 tab 时不再清空会话列表
LingoJack#2: ChatMessages 添加流式自动滚动 (onScroll + userScrolledUpRef)
LingoJack#3: BackgroundTasksPanel 仅 Agent 模式显示
LingoJack#4+#5: 后端 start_agent 默认 permission_mode → "default"
     追加 stream-json 前5行 raw dump 到 stderr 用于诊断

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
list_agent_sessions() 在 meta.json title 为 null 时自动从 transcript 第一条
user_message 提取标题前缀,避免侧栏显示随机 ID 片段。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
P0 阻塞: #63 fix-agent-cli-integration, #64 fix-agent-tool-approval, #65 fix-agent-streaming-ui
P1 UI 追平: #66 shell, #67 agent-ux, #68 chat-ux, #69 settings, #70 shortcuts-help

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…und 1)

#63 fix-agent-cli-integration:
- agent_engine.rs: tool_use 解析尝试多 key 变体 (id/tool_use_id/tool_use.id + name/tool_name/tool_use.name)
- 空 tool_id/tool_name 时 dump item keys 到 stderr 诊断
- ToolCallDisplay: toolName 空值时显示 "工具" 回退
- AgentView: handleInterruptDecision 空 interruptId 防御
- AgentMessages: 添加流式自动滚动 (同 ChatMessages)
- agent_session: 标题自动派生使用 map_while(Result::ok) 修复 clippy

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
增加诊断范围:前十行扩大截断、含 tool_use 的行完整输出

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rkaround)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- tool_id 为空时从 item JSON hash 生成合成 ID
- tool_name 为空时回退 "Tool"
- 每条 tool_use 写入 temp/jgui-agent-tooluse.json
- 清理冗余 debug 代码

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
wuqie-xuanzhao and others added 30 commits May 15, 2026 19:43
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- j-agent → crates/j-agent/
- j-cli → crates/j-cli/(含 src、assets、helpers、prompts、scripts)
- web/ → apps/docs/
- assets/remote/ → apps/remote/
- 根 Cargo.toml 改为纯 workspace 配置
- 移除 rust-embed 的 remote/ 排除规则(remote/ 已迁出)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

git-subtree-dir: apps/desktop
git-subtree-mainline: 9125453
git-subtree-split: a87b5c0
- workspace 加入 apps/desktop/src-tauri
- j-gui Cargo.toml 改 path 依赖 j-cli,reqwest 统一到 0.13
- Makefile 所有路径指向 crates/ 和 apps/
- CI workflow helpers 路径更新
- Cargo.lock 同步更新

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- apps/remote/remote/ 提升为 apps/remote/(修复 git mv 嵌套问题)
- 删除 apps/desktop/src-tauri/Cargo.lock(workspace 由根目录统一管理)
- src-tauri/.gitignore 添加 Cargo.lock

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
将 j-cli 中的 TUI 层提取为独立 crate j-tui,包含:
- components/(14 个 UI 组件)
- editor_core/(Markdown 编辑器、Vim 键绑定、文本缓冲区)
- markdown/(解析器、渲染器、语法高亮、图片加载)
- util/text(纯文本工具函数)

Theme 解耦:j-tui 内部统一使用 EditorTheme,j-cli 通过 From<&Theme> 桥接。
image 相关模块通过 feature gate 控制。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- file_index 测试中 fuzzy_match 改为 FileIndex::fuzzy_match 关联函数调用
- 修正 fuzzy_match("main.rs", "mrs") 期望值 Some(2) → Some(4)
- tool_result_render doc comment 代码块添加 text 标注避免 doctest 编译

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- bridge.rs: Child import 添加 #[cfg(target_os = "macos")] 条件编译
- update.rs: format!() 改为 .to_string()(clippy useless_format)
- update.rs: cargo fmt 自动格式化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
从 j-tui 中提取平台无关的 Markdown IR 和解析器为独立 crate j-md:
- ir.rs:IR 类型(ParsedDocument、Block、Inline、TableData 等)+ Alignment 枚举
- parser.rs:纯解析逻辑(去终端清洗预处理)+ 表格分隔行修复
- util.rs:char_width、display_width(unicode-width 依赖)

j-tui 改为依赖 j-md:
- ir.rs → re-export j_md::ir::*
- parser.rs → 瘦 facade(终端字符清洗 + 委托 j-md)
- render/table.rs → 使用 j_md::Alignment

可选 serde feature 支持序列化(用于 Tauri IPC)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1. Alignment 枚举添加 serde 条件派生(与其他 IR 类型一致)
2. 删除空壳 parser 子目录(j-md/parser/table.rs、j-tui/parser/table.rs、j-tui/parser/text.rs)
3. j-tui parser 重构:预处理后委托 j_md::parse_markdown,删除 639 行重复代码

j-tui 现仅保留 TUI 特有预处理(终端字符清洗、中文引号零宽空格),核心解析委托 j-md。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
拆分为 name.rs + name/ 子模块模式(禁止 mod.rs):

- chat_app.rs (1230→592): 提取 remote, init_hooks, remote_ops, model_mgr, tool_ops
- tui_loop.rs (1473→536): 提取 terminal, event_dispatch, websocket
- tool_call_render.rs (1619→489): 提取 agent, bash, description, file_tools, web_tools, task_tools, other_tools
- tool_result_render.rs (1574→571): 提取 command_line, common, file_operations, search_tools, task_management
- update.rs (1152→24): 提取 github, fallback, feature_select, cargo_update, indicator, macos, restart, auth

Lint 结果: PASS 3, WARN 37, FAIL 0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 5 清理内容:
- 拆分 10 个中等规模文件为 name.rs + name/ 子模块
- 合并过小单功能文件(task_tools + web_tools → specialized_tools; command_line + common → helpers)
- 补充公共 API 文档注释(j-md ir.rs、chat_app、tool_call_render 等)
- 修复 lint 脚本 3 个 bug:缩进属性匹配、多行 SAFETY 检测、unwrap 模式匹配
- 消除 super::super:: 过度层级引用,改用 crate:: 绝对路径
- 移除 unwrap() 改用 let-else 模式(notebook/types.rs)

lint 结果:PASS 9 / WARN 0 / FAIL 0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 1-5 重构后项目结构已显著变化:
- 新增 Workspace Architecture 章节(j-agent, j-cli, j-tui, j-md, desktop)
- 更新依赖图和 crate 边界说明
- 精简 Chat Module 描述(agent loop 在 j-agent)
- 新增模块模式规范(name.rs + name/,lint 规则)
- 更新常用命令(lint 脚本路径)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
解决冲突:
- Cargo.toml: 保留 workspace 结构,版本升至 12.10.71
- chat_app.rs/tui_loop.rs: 删除旧路径文件(已移至 crates/j-cli/)
- UIState: 补充上游新增的 config_lines_cache/config_content_inner/config_content_scroll 字段

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
审查发现上游 da8d1dc 的 Config 模式鼠标选区交互丢失:
- 'c' 键复制:补充 Config 模式从 config_lines_cache 提取选区文本
- 左键点击:优先检查 config_content_inner 创建选区,否则走 Tab 切换
- 拖拽选区:补充 Config 模式下拖拽更新 sel.current

同时将 j-cli crate 版本从 12.10.69 升至 12.10.71 与 workspace 同步

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
上游 v12.10.72~v12.10.73 变更手动整合到 monorepo 结构:

- editor.rs 拆分为 editor/ 子模块 (api/commands/render/selection)
- 新增 Insert 模式命令面板 (InsertCommandPanel + filter_insert_commands)
- 流式 Markdown 重绘改用行数跟踪 + Unicode 宽度,移除 DSR 光标定位
- 表格渲染简化,移除 display_width 依赖
- tool_call_render Glob 工具也显示 pattern 参数
- 版本号同步 12.10.71 → 12.10.73
- CHANGELOG 新增 v12.10.72/v12.10.73 条目

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
上游变更整合:
- 新增 j read 命令(浏览器预览 Markdown)
- 新增代码块边框样式配置 (BorderStyle: rounded/plain)
- 新增编辑器 :w 保存不退出 (EditorAction::Save)
- 新增交互模式使用技巧提示
- 重构: tui_loop/editor/tool_call_render/tool_result_render/update 模块拆分
- 修复: soft_break 渲染、编辑器滚动、oneshot Markdown 重绘
- ParsedDocument Serialize 支持 (j-md serde feature)
- Config 补全 DynamicValueForkey
- 版本同步至 v12.10.80
- Notebook Tree 焦点:补充 / 按键打开命令面板(上游 handle_tree_focus_key)
- Notebook Tree 焦点:补充 auto_save_if_dirty(上移/下移前保存脏数据)
- Notebook Editor 非 Esc 按键:补充 Save/Continue action 处理
- Theme::from_name:补充 with_border_style 注入全局边框样式配置
上游在 editor.rs 中定义了 is_idle_normal_mode() 方法,用于判断编辑器
是否处于空闲 Normal 模式(无活跃搜索)。Notebook 的 Esc 处理需要此方法
来正确判断是将 Esc 传给编辑器(Insert→Normal 切换)还是切回目录树。

之前直接把 Esc 传给编辑器再判断 action,导致 Insert 模式下 Esc 会被
误判为切回目录树而非先切换到 Normal 模式。
上游变更:
- refactor: read 命令从 mod.rs 子目录结构改为 read.rs + read/ 扁平结构
- feat: Reader 添加目录侧边栏导航(TOC)
- 删除 TableOfContents.tsx(简化前端)
- reader_web 资源更新(新增 JS/CSS 哈希)
- 版本同步至 v12.10.81
- check_lint.sh: 兼容 Windows Git Bash(去掉 pipefail、修复路径)
- tool_call_render/tool_result_render: mod.rs → name.rs + name/ 结构
公共 API 文档注释:
- j-agent: agent/api, context/plan_state, llm/stream, permission/queue,
  storage/session, tools/{computer_use,load_tool,task,todo,worktree}
- j-cli: tool_call_render render_tool_call_request_msg
- j-tui: image_cache new

test 代码 unwrap→expect:
- j-agent: context/{regression_tests,window/tests}, infra/hook/tests,
  permission/queue/tests, storage/tests, tools/definition/tests
- j-tui: markdown_cache, search/tests, wrap_engine/tests, parser/tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants