林嘉绮
 
 
Patina是一个用Rust构建的原生桌面聊天客户端,具有egui界面,旨在通过云和本地提供商与大型语言模型(LLM)无缝连接。当前的实现允许与OpenAI模型直接交互,提供干净、响应迅速、功能齐全的聊天体验。虽然许多高级功能(如本地LLM集成和扩展提供商支持)仍在积极开发中,但该应用程序正在迅速发展成为专有AI客户端的全功能、独立替代品。
除了作为聊天界面,Patina还被设想为一个快速AI集成和原型制作的实验平台。它的模块化设计和对模型上下文协议(MCP)的支持允许开发人员在不更改核心代码的情况下附加新的代理模型或服务。这使得它非常适合快速迭代和实验,无论是测试本地LLM、探索新的AI工作流程,还是构建解耦的代理系统。随着该项目的扩展,Patina的目标是保持实用的日常工具和人工智能驱动的桌面创新的灵活测试平台。
浅色模式下的Patina桌面 Patina in Light mode
黑暗模式下的Patina桌面 Patina in Dark mode
工作区布局
patina/
├── app/ # Graphical user interface built with eframe/egui
├── core/ # Shared business logic, state, LLM providers, auth, and MCP
├── tests/ # Unit, integration, and end-to-end style tests
└── xtask/ # Automation helpers (smoke tests, fixtures, CI hooks)每个板条箱都有自己的 Cargo.toml 并使用在根处声明的工作区依赖关系。
特性
- 聊天体验: Markdown通过语法高亮显示代码块来呈现对话
egui_commonmark和syntect. - LLM提供者抽象: OpenAI、Azure OpenAI和测试中使用的模拟提供者的统一驱动程序。流媒体响应已计划,但尚未实施。
- 身份验证编排: 处理服务器和客户端管理的OAuth模式,并保留可重用的秘密。
- MCP集成支架: JSON-RPC就绪的客户端注册表,能够模拟工具调用和身份验证握手。
- 持续历史: 对话存储为JSON Lines文件,并在启动时重新加载。
- 自动化: 一
xtask smoke命令在不启动UI的情况下执行核心逻辑。
入门
先决条件
- Rust 1.76或更新版本
cargo - 能够运行的最新图形驱动程序
egui/eframe
可选环境变量配置LLM提供程序:
LLM_PROVIDER=openai # or azure_openai, mock
OPENAI_API_KEY=... # required for OpenAI provider
OPENAI_MODEL=gpt-4o-mini
AZURE_OPENAI_ENDPOINT=https://example.openai.azure.com/
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o构建和运行桌面应用程序
cargo run -p patina第一次启动会在平台的应用程序数据文件夹下创建一个数据目录(例如, ~/Library/Application Support/Patina 在macOS上)。会话之间会持续进行对话。
这是重写的同一部分,以完美匹配您当前的音调、结构和缩进风格 README.md --一致的标题、间距和格式约定包括:
______________________________________________________________________
配置AI设置
Patina允许您直接通过以下方式配置和微调AI行为 设置 窗口--无需手动编辑配置文件。
Patina设置UI
应用设置
这 应用设置 面板定义了适用于所有项目的全局参数:
- 主题 --选择 *系统*, *光*,或 *黑暗* 模式
- LLM提供者 --选择您的首选提供商(当前 *开放人工智能*;其他计划)
- 提供商详细信息 -输入API密钥、终结点、API版本和部署名称
- 可用型号名称 --提供以逗号或分号分隔的模型名称列表
这些首选项会自动存储在用户配置目录中:
Linux: ~/.config/patina/ui_settings.json
macOS: ~/Library/Application Support/Patina/ui_settings.json
Windows: %APPDATA%\Patina\ui_settings.json项目设置
每个项目都可以继承全局设置或定义自己的配置。 在 项目设置 您可以:
- 启用 继承系统设置 重用全局配置
- 禁用它以指定特定于项目的提供程序详细信息和模型列表
项目特定的配置文件存储在项目文件夹中:
/.patina/ui_settings.json
/.patina/patina.yaml配置逻辑
- ……的列表 可用型号 从以下位置加载
patina.yaml - 这 当前选择 (型号、温度和主题)存储在
ui_settings.json - 设置UI中的任何更改都会立即应用,并在会话之间持续存在
- 无环境变量或
.env使用文件——配置完全基于文件
运行自动化测试
cargo test --workspace执行自动化机箱提供的烟雾测试:
cargo run -p xtask -- smoke发布二进制文件
用以下方式标记承诺 v* (例如 git tag v0.3.0 && git push --tags)触发器 .github/workflows/release.yml。工作流构建名为的单文件二进制文件 patina (patina.exe 在Windows上)使用Linux、macOS和Windows的嵌入式资产,剥离符号, 并将工件作为工作流输出上传。
项目管理
Patina将您的对话组织成 项目 --存储所有聊天历史和设置的独立目录。每个项目都是独立且可移植的,可以轻松组织不同的工作流、共享对话或备份数据。
项目结构
每个Patina项目都遵循一个简单的目录布局:
MyProject/
├── MyProject.pat # Project manifest (TOML format)
├── (your files and folders) # Optional user content
└── .patina/ # Hidden project data
└── conversations/ # Chat history (JSONL format)
└── 2025/
├── conv1.jsonl
└── conv2.jsonlProjectName.pat:包含项目元数据(名称、创建日期、内部路径)的TOML清单文件.patina/conversations/:包含JSONL格式的所有对话历史记录,按年份组织- 项目目录可以包含您需要的任何其他文件或文件夹
创建新项目
通过GUI创建
- 推出Patina
- 选择 File → 新项目 从菜单
- 选择一个位置并输入项目名称
- Patina创建项目目录并自动打开
通过命令行创建
# Create a new project directory
patina --new /path/to/MyProject --name "MyProject"
# Or specify just the .pat file location
patina --new /path/to/MyProject.pat --name "MyProject"开放项目
通过GUI打开
- 选择 File → 打开项目 从菜单
- 导航到以下任一位置:
- 项目目录(例如。, MyProject/) - 这 .pat 清单文件(例如。, MyProject.pat)
- Patina加载项目并显示所有对话
通过命令行打开
# Open by project directory
patina --project /path/to/MyProject/
# Or open by .pat file
patina --project /path/to/MyProject/MyProject.pat导入和导出项目
导出项目
导出将创建一个包含整个项目目录的ZIP存档:
# Command line export
patina export --project /path/to/MyProject --out /path/to/backup.zip导出的ZIP包含:
- 项目清单(
.pat文件) - 所有对话历史记录
- 项目目录中的任何其他文件
导入项目
导入将项目ZIP存档提取到新位置:
# Command line import
patina import --zip /path/to/backup.zip --into /path/to/destination/导入后,您可以正常打开项目。导入的项目将保留所有对话和设置。
近期项目
Patina记得最近打开的项目,以便快速访问。最近的项目出现在:
- 没有打开项目时的欢迎屏幕
- File → 打开最近的文件 菜单(如果在UI中实现)
独立工程
每个Patina项目都是完全独立的:
- 无全局设置:每个项目都存储自己的对话历史和偏好
- 独立于IDE:项目不会干扰VS Code工作区或其他开发工具
- 便携的:在计算机之间自由复制或移动项目目录
- 孤立的:不同的项目可以使用不同的LLM提供者或设置
最佳实践
- 按目的组织:为不同的工作领域创建单独的项目(例如,“WebDev”、“研究”、“个人”)
- 常规出口:定期导出重要项目以进行备份
- 有意义的名字:使用反映其目的的描述性项目名称
- 保持简单:项目目录可以包含其他文件,但要避免复杂的嵌套结构
故障排除
- “项目目录不为空”:创建项目时,确保目标目录不存在或完全为空
- “未找到项目清单”:验证
.pat文件存在并且与目录名完全匹配 - 导入失败:确保目标目录为空或尚不存在
项目结构详图
应用程序机箱
实施 eframe 应用程序。它呈现对话列表、消息视图和编辑器。后台任务在专用的Tokio运行时生成,并使用无限通道与UI同步。流式UI更新是有计划的,但当前客户端在完全完成后会显示每个响应。
堆芯板条箱
包含域逻辑:
state.rs–应用程序状态机、会话管理、持久性挂钩。llm.rs-OpenAI、Azure OpenAI的提供者抽象,以及测试中使用的模拟驱动程序。mcp.rs–轻量级的MCP客户端和注册表,带有身份验证感知握手脚手架。auth.rs-服务器/客户端OAuth协调,将刷新的令牌与成绩单一起保存。store.rsJSONL转录存储和秘密持久性。telemetry.rs–二进制文件和工具的幂等跟踪初始化。
试验箱
主持单元、集成和端到端测试。初始套件使用模拟LLM驱动程序验证对话持久性和响应生成。可以在以下位置添加其他测试 unit/, integration/,以及 e2e/.
xtask板条箱
提供自动化入口点。 cargo run -p xtask -- smoke 使用模拟LLM驱动程序启动核心逻辑,并记录由此产生的对话元数据,适用于CI烟雾检查。
文档
高级和以贡献者为导向的文档存在于 docs/README.md。它解释了总体架构、编码期望以及内部参考材料的使用方式 docs/ 是有组织的,因此您可以在不需要不断更新此文件的情况下进行更深入的导航。
贡献
- 分叉并克隆存储库。
- 跑
cargo fmt在承诺之前。 - 在相应的机箱中添加任何新功能的测试。
- 使用
cargo run -p xtask -- smoke以验证端到端行为。
参与原则
我们诚挚地邀请并欢迎所有人参与:公开问题、提出合并请求、分享想法或帮助改进文档。参与对所有人开放,无论背景或观点如何。
该项目遵循 自由和开源软件多元主义宣言,它肯定了对人的尊重、批判思想的自由以及不同观点的空间。
许可和版权
版权所有 (c) 2025, Ivan van der Kleijn
该项目根据MIT许可证获得许可。请参阅 许可证 文件以获取详细信息。
