# Avalonia-Assistant **Repository Path**: imiyu/Avalonia-Assistant ## Basic Information - **Project Name**: Avalonia-Assistant - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-23 - **Last Updated**: 2026-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Avalonia Assistant Windows 桌面 AI 助理。Agent 循环用 [pi.net](https://github.com/AIDotNet/pi.net) 的 **Pi.CodingAgent**, 界面用 [TKCode.Arc](https://github.com/AIDotNet/TKCode.Arc),交互参考 WorkBuddy:左侧任务与空间, 中间对话,输入框里带模型、权限和工作区选择。 ![首页](docs/images/home.png) ## 现在能做什么 - **流式对话**:DeepSeek / OpenAI / Anthropic / 任意 OpenAI 兼容端点(Ollama、LM Studio、vLLM、One-API)。 - **真的会动手**:自建 8 个日常办公 / 编码工具 + CodingAgent 内置的 read / grep / find / ls / edit。 - **技能与 MCP**:工作区 `.pi/skills` 的 `SKILL.md` 按需加载,技能页可从文件夹或 zip 导入; `.pi/mcp.json` 的 MCP 服务端启动时连接。 - **@ 直接引用文件**:输入框打 `@` 按名字搜当前工作区的文件——文件名精确 > 前缀 > 包含 > 路径 > 字符子序列, 自动跳过 `node_modules` / `.git` 这类目录;选中即引用,**发送时才读内容**,不用先把文件导入到哪里。 - **粘贴图片**:输入框里 Ctrl+V 直接贴图(截图也行),缩略图挂在输入框上方,和文字一起发; 图片落在数据目录的 `images/` 下,会话 JSON 只记路径,存档不会被 base64 撑大。 - **拖进来就行**:文件/图片拖到窗口任意位置都能接住,不用先去找输入框; 图片按图片加,其它文件走引用,文件夹和重复项各有提示。 - **长会话能自己压缩**:CodingAgent 的上下文压缩与自动重试,不必手动清空。 - **三档权限**:只读 / 工作区 / 完全访问;执行命令会在对话里弹授权卡。 - **工具过程可见**:每次调用压成一行(「执行命令:dotnet build」+ 耗时),点开才看参数和结果; 连续十几次调用也只是一列短行,不会把对话淹掉。 - **改了什么看得见**:写过的文件右侧列成一张产物清单,显示新建 / 修改 / 删除、增删行数, 点开是逐行差异(`+` 绿 `−` 红),能直接打开文件或在资源管理器里定位。导出会话时会一起带上。 工具卡说的是过程,这里说的是结果——两者不混在一起。 - **文档在应用内就能看**:产物卡上点「预览」,docx / xlsx / pptx / pdf 的内容直接开窗显示—— 标题层级、表格、工作表、按页正文都在。是文字预览不是版式预览,窗口里写明了, 要看排版还是点「打开原文件」。 - **真的产出办公文件**:`read_document` 读 docx / xlsx / pptx / pdf,表格和标题层级都还原成 Markdown; `write_document` 把 Markdown 写成 .docx / .xlsx,标题、项目符号、表格、代码块都落成真正的样式。 - **多步任务先给计划**:模型调 `update_plan` 列出步骤,对话里显示成清单,做到哪一步标到哪一步 (打勾 / 时钟 / 空心方块)。方向不对,在第一步之前就能叫停。 - **提问发错了能改**:用户消息点「编辑」就地改,保存后截断其后几轮并重新回答—— 比重新开一条任务把上下文全丢掉划算。 - **跑完会叫你**:窗口不在前台时,一轮结束会闪任务栏并响一声,失败用警示音、成功用提示音; 嫌吵可以在设置里静音,任务栏闪烁不受影响。 - **会话留在本机**:一个会话一个 JSON 文件,第一句话一发出就落盘(不用等回复跑完)。 侧栏「任务」列全部任务、按今天 / 昨天 / 最近 7 天分组,「空间」只是按目录再归一次类—— 归了空间的任务在「任务」里照样看得见。 - **工作区一点就换**:输入框下面那条点开是「搜索 + 工作区列表」,当前那个打勾; 新建工作空间、打开本地文件夹、不使用工作空间都在这一个浮层里,首页右上角是同一个。 **新建任务默认是普通任务**,上一次选的空间不跟过来;还没发第一条时挑的空间当场生效, 发过话就钉在那条任务上——中途换目录,前面引用过的文件就对不上了。 普通任务的文件落在 `~/.avaloniaassistant`(像 `.claude` / `.codex` 那样藏在用户目录里, 第一次用到时才建),不再把整个用户目录当工作区。 - **窗口记着上次的样子**:位置、尺寸、侧栏宽度(可拖动分隔条)、界面缩放(90%–125%,Ctrl+滚轮 / Ctrl+0) 和最后看的那条任务,关掉再开直接接上;设置里可选「启动时:首页 / 上次会话」。 - **时间与引用看得清**:跨天的消息之间插日期分隔,时间悬停给完整日期; 引用文件是带大小、行数、截断状态的标签,点一下在资源管理器中定位。 - **快捷键有张表**:Ctrl+/ 打开;Ctrl+N 新建任务、Ctrl+K 搜任务、Ctrl+F 会话内查找; 审批卡支持 Ctrl+Enter 允许一次、Ctrl+Shift+Enter 本会话允许、Esc 拒绝。 - **Markdown**:标题、列表、表格、行内代码、代码块高亮。 - **语音输入**:NAudio 录音 + `/audio/transcriptions` 转写(端点需支持)。 - **技能页**:卡片式浏览,按分类筛选、关键词搜索,开关与导入都持久化。 - **MCP 页**:列出 `mcp.json` 里的服务端,并**真的起一次进程握手**——已连接会给出工具数, 起不来会给出原因(Windows 上 `npx` 少了 `cmd /c` 包装在这里就能看见),每张卡可重试。 整段粘贴标准 JSON(`mcpServers` / VS Code 的 `servers` 写法)就能一次导入多个,也能从现成的 `mcp.json` 文件读进来;只加一个 stdio 服务端时用表单。 - **导出会话**:对话页右上角一键存成 Markdown,工具调用、失败轮次、引用文件都在里面。 | 会话 | 设置 | | --- | --- | | ![会话](docs/images/chat.png) | ![设置](docs/images/settings.png) | ![技能](docs/images/tools.png) ## 两个核心框架 界面用 **TKCode.Arc**,Agent 循环用 **pi.net**,其余选型都是围着这两个补的。 | 层 | 框架 | 引用包 | 版本 | | --- | --- | --- | --- | | UI 框架 | [TKCode.Arc](https://github.com/AIDotNet/TKCode.Arc)(AtomUI 生态) | `TKCode.Arc`、`TKCode.Arc.Fonts` | 0.3.1-preview.3 | | Agent 框架 | [pi.net](https://github.com/AIDotNet/pi.net)(Pi 的 .NET 移植) | `Pi.CodingAgent`(传递引入 `Pi.Agent` / `Pi.Ai` / `Pi.Mcp` 等) | 1.4.4 | - **TKCode.Arc 负责界面**:控件、主题、图标字体全部来自 Arc,入口在 `Program.BuildAvaloniaApp` 里一次装好——`WithArcFonts()` 加 `UseAtomUI(b => b.UseDesktopControls().UseArc())`, 页面、样式、VM 都在 `AvaloniaAssistant.UI`。 - **pi.net 负责 Agent**:`Sdk.CreateAgentSessionAsync` 装配出 `AgentSession`,技能、MCP、 上下文压缩、自动重试都由它带着;模型出入仍由本项目自己的 provider 设置决定, 通过 `ProviderConfigInput.StreamSimple` 直连 `Pi.Ai` 的流式实现,不读 `~/.pi/agent/auth.json`。 - **权限没有让给框架**:CodingAgent 的 `BeforeToolCall` 只服务扩展的 `tool_call` 事件, 本项目在它外面串了一层三档权限与授权卡片(`PiAgentRuntime.InstallPermissionHook`)。 只读模式下连 `edit` 都不会出现在工具集里。 - **两边只在一个地方碰面**:`AvaloniaAssistant.Desktop` 这个组合根。`UI` 不引用 `Pi.*`, `Agent` 不引用 Avalonia,换掉其中任何一个都不用动另一边。 两个包都直接走 NuGet,不依赖本机参考仓库路径。Arc 包与本地源码的命名空间差异 (`AtomUICommunity` vs `AIDotNet`)及踩坑记录见 [docs/research.md](docs/research.md)。 ## 其余技术栈 | 层 | 选型 | 版本 | | --- | --- | --- | | 运行时 | .NET | 10.0(`net10.0`) | | 基础 UI | Avalonia | 12.1.4 | | 控件库 | AtomUI.Desktop.Controls(Arc 依赖) | 6.2.8 | | MVVM | CommunityToolkit.Mvvm | 8.4.0 | | 语音 | NAudio | 2.2.1 | ## 快速开始 要求:Windows 10/11,.NET 10 SDK(在 10.0.401 上验证)。 ```bash dotnet restore dotnet run --project src/AvaloniaAssistant.Desktop ``` 首次启动进入首页,点右上角「设置」或提示条里的「去设置」: 1. 进「模型设置」配一套:名称(可留空,留空就显示模型名)、Base URL、API Key、模型名; 2. 服务商预设只负责带默认值(DeepSeek / OpenAI / Anthropic / 自定义),协议按端点选 Chat Completions / Responses / Anthropic Messages; 3. 需要多个渠道就点左边「+ 添加模型」继续加:每套有各自的地址、Key 和协议,互不影响; 4. 保存后,输入框下方那颗胶囊里随时切换当前模型。列表里只有你配过的那几套。 预设带出的默认值: | 预设 | Base URL | 默认模型 | 协议 | 该厂商其它常用模型 | | --- | --- | --- | --- | --- | | DeepSeek | `https://api.deepseek.com/v1` | `deepseek-flash` | Chat Completions | `deepseek-v4-pro` | | OpenAI | `https://api.openai.com/v1` | `gpt-6.1-sol` | Chat Completions | `gpt-6-astra`(需申请)、`gpt-6-luna` | | Anthropic | `https://api.anthropic.com` | `claude-sonnet-5-5` | Anthropic Messages | `claude-opus-5-5`、`claude-haiku-5-5` | | 自定义 | `http://localhost:11434/v1` | `qwen3.8:27b` | Chat Completions | `qwen3.8-flash`(云端 API 名) | > 默认走「够用且便宜」的那一档:DeepSeek 用 Flash、Anthropic 用 Sonnet、本地用 27B。要更强就换成 > `deepseek-v4-pro` 或 `claude-opus-5-5`,Token 消耗也会跟着上去。 > > 模型名填的是厂商 API 的 `model` 字段,不是 App 里的展示名,而且写法各家不一样: > DeepSeek `deepseek-flash` 用连字符,Ollama 的 tag 用冒号(`qwen3.8:27b`),填错直接 404。 > 旧的 `deepseek-chat` / `deepseek-reasoner` 已于 2026-07-24 下线,`deepseek-v4-flash` 也已退役 > (请求会被转到 `deepseek-flash`,但别再写了)。 > > 公司网关、代理这类自建端点选「自定义」:预设里的模型名只是该厂商的示例, > App 不会替你猜端点上有哪些模型。旧版单套配置(settings.json 里的扁平 provider/apiKey/...) > 会在首次启动时自动搬成一套模型,地址和预设对不上时标为「自定义」。 > 自定义端点必须是 OpenAI 兼容的 `/chat/completions`。本地 LLM 不再走 LLamaSharp, > 用 Ollama / LM Studio 暴露一个兼容端点即可。 ### 发布 框架依赖(体积小,要求目标机器装了 .NET 10 运行时): ```bash dotnet publish src/AvaloniaAssistant.Desktop -c Release -r win-x64 --self-contained false ``` 自包含单文件(一个 exe,双击就跑,约 82 MB): ```bash dotnet publish src/AvaloniaAssistant.Desktop -c Release -r win-x64 --self-contained true \ -p:PublishSingleFile=true \ -p:IncludeNativeLibrariesForSelfExtract=true \ -p:IncludeAllContentForSelfExtract=true \ -p:EnableCompressionInSingleFile=true \ -o dist/win-x64-single ``` 三个 `Include*` 参数各有用处,少一个就凑不齐单文件: - `IncludeNativeLibrariesForSelfExtract` —— Avalonia / SkiaSharp / HarfBuzz 的 native 库得一起塞进去 - `IncludeAllContentForSelfExtract` —— `Pi.CodingAgent` 带了一批内容文件(导出模板、schema、主题), 不加这个它们会散落在 exe 旁边,变成「exe + Assets 目录」 - `EnableCompressionInSingleFile` —— 压到 82 MB,不压约 150 MB 产物目录里只有一个 `AvaloniaAssistant.exe`:native 库的 pdb(`libSkiaSharp.pdb` 就有 96 MB) 在 `Desktop.csproj` 里被 `DropPdbsFromPublish` 排掉了。 首次运行时内容文件会解到 `%TEMP%\.net\` 下,之后启动直接复用。 ## 项目结构 ``` Avalonia-Assistant/ ├── Avalonia.Assistant.slnx ├── Directory.Build.props # net10.0 / 语言版本 / 依赖版本变量 ├── Directory.Packages.props # 集中包版本 ├── src/ │ ├── AvaloniaAssistant.Abstractions/ # 契约与 DTO(零依赖) │ │ ├── IAssistantRuntime.cs # 运行时、授权、会话、设置、语音接口 │ │ ├── AgentContracts.cs # 事件、模型、工具描述、运行请求 │ │ ├── ChatSession.cs # 会话 / 消息 / 工具调用 DTO │ │ └── AssistantSettings.cs # 设置、provider 预设、权限 │ ├── AvaloniaAssistant.Agent/ # 唯一认识 pi.net 的项目 │ │ ├── PiAgentRuntime.cs # 会话缓存、事件映射、权限钩子、abort │ │ ├── CodingSessionFactory.cs # ModelRuntime + Sdk 装配(技能 / MCP / 内置扩展) │ │ ├── CapabilityScanner.cs # 扫 .pi/skills 与 mcp.json,供界面展示 │ │ ├── ToolAccess.cs # 内置 / MCP 工具的安全属性判定 │ │ ├── PiStreamFactory.cs # 测试可替换的 OpenAI / Anthropic 流式入口 │ │ ├── AgentToolRegistry.cs # 自建工具清单 → ToolDefinition │ │ └── Tools/ # 5 个自建工具(读 / 列 / 搜走 CodingAgent 内置) │ ├── AvaloniaAssistant.Storage/ # settings.json / sessions/*.json / 技能导入 │ ├── AvaloniaAssistant.Speech/ # NAudio 录音 + 转写 │ ├── AvaloniaAssistant.UI/ # 窗口、页面、VM、样式 │ │ ├── Views/ # MainWindow / Sidebar / Home / Chat / Tools / Mcp / Settings │ │ ├── ViewModels/ # 命令、会话状态、消息 VM │ │ └── Styles/ # Tokens.axaml / AppStyles.axaml │ └── AvaloniaAssistant.Desktop/ # 入口、DI、Arc 初始化 ├── tests/AvaloniaAssistant.Agent.Tests/ # 171 个测试 └── docs/ ├── research.md # 两个参考项目的结构与集成方式 ├── migration.md # 旧功能逐项盘点与取舍 ├── architecture.md # 分层、时序、权限、扩展点 └── images/ # README 截图 ``` ## 分层与解耦 ``` UI ──► Abstractions ◄── Agent ──► Pi.CodingAgent ──► Pi.Agent / Pi.Ai / Pi.Mcp ▲ ▲ Storage Speech ``` - `UI` 不引用任何 `Pi.*`,只消费 `IAssistantRuntime`、`AgentStreamEvent` 与 `AgentCapabilities`; - `Agent` 不引用 Avalonia,工具执行结果只返回文本; - `Desktop` 是唯一同时认识两边的组合根。 想换 Agent 框架:实现 `IAssistantRuntime` 并在 `Program.cs` 替换注册。 想换 UI:`Agent` / `Storage` 不变。详见 [docs/architecture.md](docs/architecture.md)。 ## 技能与 MCP 两者都按 CodingAgent 的目录约定发现,不需要写代码: ``` <工作区>/.pi/ ├── skills/<名称>/SKILL.md # 项目级技能,frontmatter 写 name / description └── mcp.json # 项目级 MCP 服务端 ~/.pi/agent/ ├── skills/<名称>/SKILL.md # 全局技能 └── mcp.json # 全局 MCP 服务端 ``` - 技能的正文由内置 `read` 工具按需加载,模型只先看到名字和描述;`/skill:<名称>` 也能显式触发。 - MCP 服务端**必须写 `"exposure": "direct"`**,否则工具只留给 codemode,模型直接调不到。 - **Windows 上手写 `mcp.json` 时,`npx` / `npm` 这类命令必须用 `cmd /c` 包一层**: ```json { "mcpServers": { "filesystem": { "command": "cmd", "args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "D:/work"], "exposure": "direct" } } } ``` 原因是 MCP 的 stdio 传输用 `UseShellExecute = false` 直接起进程,而 `CreateProcess` 不认 `.cmd` / `.bat` 垫片:写 `"command": "npx"`(或 `npx.cmd`)时服务端进程根本起不来, 表现是「配置在、工具永远不出现」,且没有明显报错。通过 MCP 页导入(粘贴 JSON 或填表单)时, `CapabilityInstaller` 会自动补这层包装,不用自己写;直接手写文件则要自己写 `cmd /c`。 macOS / Linux 直接写 `npx`。 - 项目级 `.pi` 属于「需要信任」的配置(技能、MCP、`AGENTS.md` 都会进上下文)。 桌面助理默认信任你选的工作区,`settings.json` 里把 `TrustWorkspace` 设为 `false` 可以关掉, 关掉后只读全局 `~/.pi/agent`。 - 技能页列出扫到的技能,MCP 页列出服务端并显示这一次真实握手的结果(配置在 ≠ 连上了); 加完文件点「重新扫描」,新配置在下一个会话生效。 - 技能页的「导入文件夹」选一个直接含 `SKILL.md` 的目录;「导入 zip」选一个 `.zip` 技能包。 包里可以带一层外层目录,也可以把 `SKILL.md` 放在压缩包根上(用包名当技能名); 一个包只装一个技能,重名会拒绝,装完自动让会话重建。校验与解压在 `Storage/CapabilityInstaller`。 - MCP 页的「导入 JSON」认三种写法:`{"mcpServers": {...}}`、VS Code 的 `{"servers": {...}}` (含外面再套一层 `mcp`)、以及直接一层「名称 → 配置」。字段原样保留(`env` / `headers` / `url` / `cwd` 都不动),只做三件事:缺 `exposure` 补 `direct`、`npx` 这类命令补 Windows 启动层、 校验能起得来;同名默认跳过,勾「覆盖同名」才替换。JSON 里的尾逗号和注释会被容忍。 ## 内置工具 工具分两拨,但同一件事只留一个实现:读文件、列目录、搜内容交给 CodingAgent 的内置工具, 自建工具(`AvaloniaAssistant.Agent/Tools`)只补它没有的能力,一共 8 个。 系统信息、进程管理、在浏览器打开这类低频动作用 `run_command` 或系统自带工具做, 少一个工具就少一次选错。 | 工具 | 说明 | 权限 | | --- | --- | --- | | `write_file` | 写工作区文件(含追加、自动建父目录) | 工作区可写 / 只读拦截 | | `read_document` | 读 docx / xlsx / pptx / pdf,输出接近 Markdown 的结构 | 只读 | | `write_document` | 把 Markdown 写成 .docx / .xlsx(标题、列表、表格、代码块) | 工作区可写 / 只读拦截 | | `update_plan` | 多步任务列计划并更新进度,对话里显示成清单 | 只读 | | `open_path` | 用系统程序打开文件/文件夹 | 只读 | | `run_command` | 执行 shell 命令(60s 超时) | 需确认 | | `fetch_url` | 抓网页正文 | 只读 | | `current_time` | 当前时间与时区 | 只读 | CodingAgent 提供的内置工具(`tools` allowlist 里固定启用): | 工具 | 说明 | 权限 | | --- | --- | --- | | `read` | 按行读文件,技能正文靠它加载 | 只读 | | `grep` | 正则搜内容,遵循 `.gitignore` | 只读 | | `find` | glob 找文件,遵循 `.gitignore` | 只读 | | `ls` | 列目录 | 只读 | | `edit` | 最小替换改文件 | 需确认 / 只读模式不启用 | | `write` | 新建或整写文件 | 需确认 / 仅完全访问 | | `mcp____` | MCP 服务端暴露的工具 | 需确认 / 只读模式拦截 | 写文件为什么还留 `write_file`:内置 `write` 只在「完全访问」启用,默认权限下新建文件走 `write_file`, 它带工作区沙箱、支持追加,且在工作区内写入不弹确认;改已有文件的单行才用 `edit`。 路径默认限制在当前工作区;要越界需要切到「完全访问」。 `open_path` 不会直接启动 `.exe` / `.bat` / `.ps1` 等可执行文件;需要运行时走 `run_command` 并确认。 ## 测试 ```bash dotnet test tests/AvaloniaAssistant.Agent.Tests ``` 覆盖: - Faux 模型驱动的完整 agent 循环与工具调用; - 只读模式拦截、授权拒绝、缺 API Key; - 切换权限后会话重建,只读模式立即生效; - 项目级技能发现(真实 `SKILL.md` → system prompt); - MCP 端到端:测试里起一个 Node stdio 服务端,断言 `mcp__demo__echo` 进入可调用工具集; - 本机 TCP 模拟 OpenAI SSE 端点,验证真实 HTTP 流式与工具声明; - 文件工具的目录 / 读取 / 越界写入; - 技能导入:文件夹与 zip(外层目录、根级 `SKILL.md`、缺清单、多技能、重名)各走一遍; - settings / session 的 JSON 往返; - 文档往返:Markdown 写成 docx / xlsx 再读回来,标题层级、表格、项目符号、代码块都得对得上; - 行级 diff 与计划文本解析:新增 / 删除行数、上下文折叠、大文件降级、三种步骤状态。 ## 截图模式 用于 UI 回归和文档配图,不需要 API Key: ```bash dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page home dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page chat dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page settings dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page tools ``` `--page chat` 会加载一份内存里的示例会话(不写入 `sessions/`),用来检查消息、工具卡、表格渲染。 界面绑定错误不会让编译失败,只会在运行期静默失效。排查时加上环境变量,把 Warning 以上的 Avalonia 日志(含 `[Warning/Binding]`)打到控制台: ```bash AA_LOG_BINDINGS=1 dotnet run --project src/AvaloniaAssistant.Desktop -- --page chat ``` 弹层(Popup / Flyout)挂在另一个 TopLevel 上,截主窗口是看不到的,单独有两个入口: ```bash # 把工作区浮层摆进一个无边框窗口再截,检查列表 / 新建 / 搜索三种版式 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --workspace-picker dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --workspace-picker --workspace-picker-create dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --workspace-picker --workspace-picker-query banana # 在主窗口里真的打开浮层,让弹层自己出图(含 Flyout 外壳和真实定位) dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --workspace-flyout ``` 新增的几处界面也走同一套验收参数: ```bash # 快捷键总览 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --shortcuts # 跨天消息:日期分隔与完整时间(--scroll-top 看最早一条) dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page chat --chat-dates --scroll-top # 界面缩放 125%,设置页滚到底 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page settings --scroll-bottom --scale 1.25 # 授权卡版式;--press-escape 会真的发一次 Esc,验证「Esc 拒绝」 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page chat --approval-demo --press-escape --scroll-bottom # 产物面板:文件卡 + 一段展开的逐行差异 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page chat --artifacts # 消息编辑态:最后一条提问变成输入框 + 保存并重发 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page chat --chat-edit # 文档预览窗:--preview 指定文件,docx / xlsx / pptx / pdf / 纯文本都行 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page preview --preview "docs/项目介绍.pdf" # 设置页直接停在「系统设置」:检查权限、缩放、跑完提示三张卡片 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --page settings --settings-system # 悬停提示的皮:短提示 / 中等长度 / 长路径折行三种样例 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --tooltips # 输入框拖放提示层:文件 / 图片 / 文件夹三种落点各是什么样 dotnet run --project src/AvaloniaAssistant.Desktop -- --screenshot out.png --composer-drop # 拖放探针:在输入框上真的走一遍路由(无 OLE,其余链路都是真的) dotnet run --project src/AvaloniaAssistant.Desktop -- --drop-probe "D:/some/文件.md" # 隔离数据目录:设置/会话都写到这里,验收启动恢复时不碰真实数据 dotnet run --project src/AvaloniaAssistant.Desktop -- --data-dir .tmp/verify ``` 还提供一个开发用的自动发送参数,用来跑真实的端到端链路: ```bash dotnet run --project src/AvaloniaAssistant.Desktop -- --run "用三句话介绍你自己" --screenshot out.png ``` 它会加载 `%APPDATA%\AvaloniaAssistant\settings.json`,走完整的 Agent → HTTP → UI → 会话落盘流程。 ## 数据目录 ``` %APPDATA%\AvaloniaAssistant\ ├── settings.json ├── sessions\.json └── Workspace\ # 默认工作区 ``` 删除 `sessions\` 下的文件即可清空对应会话。设置页有「打开数据目录」。 ## 已知边界 - **API Key 明文保存**在 `settings.json`,目前没有接 DPAPI;不要在共享机器上使用生产密钥。 - **语音转写依赖端点**支持 `/audio/transcriptions`;DeepSeek 官方端点不支持,会给出错误提示。 - **MCP 工具要写 `exposure: "direct"`**:不写就只有 codemode / tool_search 能碰到,模型直接调不到。 - **会话存档仍是本项目自己的 JSON**:CodingAgent 的会话跑在内存里,压缩结果不跨进程保存; 重启后由 `sessions/*.json` 的历史重建上下文,压缩收益会重新累计。 - **上下文窗口读本地模型目录**:从 `~/.pi/agent/models-store.json` 取当前模型的 `contextWindow`, 水位条和自动压缩用同一个值;目录里没有这个模型时退回 128k,界面上会标 `*` 并说明是估算。 - **图片要模型支持视觉**:不支持的模型由 pi.net 降级成占位符,不会报错,但也看不到图。 - **@ 只按文件名和路径匹配**:不是全文检索,搜文件里的内容要等后面的索引;二进制文件可以引用但没有正文。 - **产物面板抓不到 `run_command` 改的文件**:采集靠「工具调用前后对比文件」,走 shell 脚本改的东西 连改了哪些文件都不知道,只能看命令输出。二进制文件(docx / 图片)只记一条「改过」, 不给逐行差异——读出来全是乱码。 - **只生成 docx / xlsx**:pptx 需要母版和版式,随手拼出来的文件 PowerPoint 打不开, 所以宁可报错让人先出 docx 大纲。旧版 .doc / .xls / .ppt 是二进制格式,读不了。 - **提示只有任务栏闪烁和提示音**:没做托盘图标和系统通知,那需要注册 AUMID, 为一个提醒引入这套东西不划算;应用完全退出后也不会有任何提醒。 - **没有定时任务 / 专家市场**:导航里暂未提供入口,避免假按钮;扩展点见架构文档。 - **Windows 优先**:代码里对 macOS/Linux 的路径和 shell 做了分支,但只在 Windows 上验证过。 ## 文档 - [两个参考项目的调研与集成结论](docs/research.md) - [旧项目功能盘点与迁移决定](docs/migration.md) - [架构、时序、权限与扩展点](docs/architecture.md) ## 许可证 MIT,见 [LICENSE](LICENSE)。