Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ce89b09d9 | ||
|
|
0bf0f50aaa |
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
> Windows 桌面端 LLM 供应商配置管理器,让你在 **Kimi Code CLI** 和 **Pi** 两个 Agent 之间无缝切换多家 LLM 供应商与模型。
|
> Windows 桌面端 LLM 供应商配置管理器,让你在 **Kimi Code CLI** 和 **Pi** 两个 Agent 之间无缝切换多家 LLM 供应商与模型。
|
||||||
|
|
||||||
|
[English](./README_EN.md) | **中文**
|
||||||
|
|
||||||
[](https://tauri.app)
|
[](https://tauri.app)
|
||||||
[](https://react.dev)
|
[](https://react.dev)
|
||||||
[](https://www.typescriptlang.org)
|
[](https://www.typescriptlang.org)
|
||||||
@@ -14,7 +16,6 @@
|
|||||||
|
|
||||||
- [这是什么](#这是什么)
|
- [这是什么](#这是什么)
|
||||||
- [核心特性](#核心特性)
|
- [核心特性](#核心特性)
|
||||||
- [截图](#截图)
|
|
||||||
- [架构总览](#架构总览)
|
- [架构总览](#架构总览)
|
||||||
- [支持的供应商类型](#支持的供应商类型)
|
- [支持的供应商类型](#支持的供应商类型)
|
||||||
- [数据存储位置](#数据存储位置)
|
- [数据存储位置](#数据存储位置)
|
||||||
@@ -26,7 +27,6 @@
|
|||||||
- [打包发布](#打包发布)
|
- [打包发布](#打包发布)
|
||||||
- [常见问题](#常见问题)
|
- [常见问题](#常见问题)
|
||||||
- [安全提示](#安全提示)
|
- [安全提示](#安全提示)
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
Pi Switch 提供统一的图形界面:
|
Pi Switch 提供统一的图形界面:
|
||||||
|
|
||||||
- 一处编辑,两处生效(Kimi Code + Pi)
|
- 统一图形界面,分别管理 Kimi Code 和 Pi 两套 Agent 配置,顶部 Tab 切换
|
||||||
- 一键切换供应商,自动写入对应 Agent 的原生配置
|
- 一键切换供应商,自动写入对应 Agent 的原生配置
|
||||||
- 一键拉取模型列表(OpenAI / Anthropic / Google GenAI)
|
- 一键拉取模型列表(OpenAI / Anthropic / Google GenAI)
|
||||||
- 切换后给出 `/reload` 提示,确保 Kimi Code 会话立即生效
|
- 切换后给出 `/reload` 提示,确保 Kimi Code 会话立即生效
|
||||||
@@ -57,9 +57,9 @@ Pi Switch 提供统一的图形界面:
|
|||||||
| **全局设置** | 思考开关/等级、循环重试、后台任务、权限规则、生命周期钩子(仅 Kimi Code) |
|
| **全局设置** | 思考开关/等级、循环重试、后台任务、权限规则、生命周期钩子(仅 Kimi Code) |
|
||||||
| **JSON 直编** | 高级用户可手动编辑完整配置 JSON(保留未知字段,不会丢字段) |
|
| **JSON 直编** | 高级用户可手动编辑完整配置 JSON(保留未知字段,不会丢字段) |
|
||||||
| **i18n** | 简体中文 / English,运行时切换 |
|
| **i18n** | 简体中文 / English,运行时切换 |
|
||||||
| **自动备份** | 写入 Kimi Code / Pi 原生配置前自动备份,保留最近 7 个版本 |
|
| **自动备份** | 写入 Kimi Code / Pi 原生配置前自动备份,按时间戳命名,保留最近 7 天(见 `src-tauri/src/config_io.rs`) |
|
||||||
| **快捷键** | Ctrl+S 保存、Ctrl+R 重载、Ctrl+O 打开配置目录 |
|
| **快捷键** | Ctrl+S 保存、Ctrl+R 重载、Ctrl+O 打开配置目录 |
|
||||||
| **校验** | 切换前检查名称重复、凭证缺失、Vertex 字段缺失等 |
|
| **校验(预留)** | i18n 已定义错误文案(名称重复、凭证缺失、Vertex 字段缺失等),后端 `validators.rs` 为占位实现,尚未接线 |
|
||||||
| **未保存提示** | 关闭窗口前检测未保存修改,标题栏加 `*` 前缀 |
|
| **未保存提示** | 关闭窗口前检测未保存修改,标题栏加 `*` 前缀 |
|
||||||
|
|
||||||
## 架构总览
|
## 架构总览
|
||||||
@@ -119,9 +119,9 @@ Pi Switch 提供统一的图形界面:
|
|||||||
| 文件 | 用途 | 备份 |
|
| 文件 | 用途 | 备份 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `%USERPROFILE%\.pi-switch\pi-switch.db` | Pi Switch 自己的 SQLite 数据库,存全量配置 | — |
|
| `%USERPROFILE%\.pi-switch\pi-switch.db` | Pi Switch 自己的 SQLite 数据库,存全量配置 | — |
|
||||||
| `%USERPROFILE%\.kimi-code\config.toml` | Kimi Code CLI 的 TOML 配置(**切换时写入**) | 自动保留最近 7 份 `config.toml.bak.N` |
|
| `%USERPROFILE%\.kimi-code\config.toml` | Kimi Code CLI 的 TOML 配置(**切换时写入**) | 同目录下 `backups/config.toml.bak.{YYYYMMDD_HHMMSS}`,保留 7 天 |
|
||||||
| `%USERPROFILE%\.pi\agent\models.json` | Pi 的供应商+模型配置(**切换时写入**) | 自动保留最近 7 份 `models.json.bak.N` |
|
| `%USERPROFILE%\.pi\agent\models.json` | Pi 的供应商+模型配置(**切换时写入**) | 同目录下 `backups/models.json.bak.{YYYYMMDD_HHMMSS}`,保留 7 天 |
|
||||||
| `%USERPROFILE%\.pi\agent\settings.json` | Pi 的默认供应商/模型(**切换时写入**) | 自动保留最近 7 份 `settings.json.bak.N` |
|
| `%USERPROFILE%\.pi\agent\settings.json` | Pi 的默认供应商/模型(**切换时写入**) | 同目录下 `backups/settings.json.bak.{YYYYMMDD_HHMMSS}`,保留 7 天 |
|
||||||
| `localStorage[pi-switch-agent]` | 前端记住上次选中的 Agent(kimi_code / pi) | — |
|
| `localStorage[pi-switch-agent]` | 前端记住上次选中的 Agent(kimi_code / pi) | — |
|
||||||
|
|
||||||
环境变量覆盖:
|
环境变量覆盖:
|
||||||
@@ -136,7 +136,7 @@ Pi Switch 提供统一的图形界面:
|
|||||||
| 工具 | 版本 | 说明 |
|
| 工具 | 版本 | 说明 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Node.js | ≥ 18 | 前端构建 |
|
| Node.js | ≥ 18 | 前端构建 |
|
||||||
| Rust | ≥ 1.77 stable (edition 2021) | Tauri 后端编译 |
|
| Rust | stable 最新版(edition 2021) | Tauri 后端编译 |
|
||||||
| WebView2 Runtime | Windows 10/11 默认已装 | Tauri v2 运行时 |
|
| WebView2 Runtime | Windows 10/11 默认已装 | Tauri v2 运行时 |
|
||||||
| Microsoft C++ Build Tools | 最新版 | Rust 编译依赖 |
|
| Microsoft C++ Build Tools | 最新版 | Rust 编译依赖 |
|
||||||
| WiX Toolset 3.14 | `src-tauri/wix314-binaries/` 目录 | MSI 打包(首次构建自动下载) |
|
| WiX Toolset 3.14 | `src-tauri/wix314-binaries/` 目录 | MSI 打包(首次构建自动下载) |
|
||||||
@@ -274,7 +274,6 @@ cargo test
|
|||||||
- [ ] 切换供应商后默认模型正确回填
|
- [ ] 切换供应商后默认模型正确回填
|
||||||
- [ ] 重命名供应商后引用它的模型也跟着改
|
- [ ] 重命名供应商后引用它的模型也跟着改
|
||||||
- [ ] JSON 直编后 `raw_other` 不丢字段
|
- [ ] JSON 直编后 `raw_other` 不丢字段
|
||||||
- [ ] Vertex 供应商缺 GOOGLE_CLOUD_PROJECT 时给出明确报错
|
|
||||||
|
|
||||||
## 打包发布
|
## 打包发布
|
||||||
|
|
||||||
@@ -312,20 +311,20 @@ A: Vertex 需要 GCP project/location 凭证,当前实现留了 TODO,等 GCP
|
|||||||
**Q: 支持 macOS / Linux 吗?**
|
**Q: 支持 macOS / Linux 吗?**
|
||||||
A: 代码不依赖 Windows 专属 API,但 `tauri.conf.json` 的 bundle 目标目前只配了 `msi`。理论上把 `bundle.targets` 改成 `["app", "dmg"]` 等即可跨平台,但未验证。
|
A: 代码不依赖 Windows 专属 API,但 `tauri.conf.json` 的 bundle 目标目前只配了 `msi`。理论上把 `bundle.targets` 改成 `["app", "dmg"]` 等即可跨平台,但未验证。
|
||||||
|
|
||||||
- 协议:MIT(详见 [LICENSE](./LICENSE))
|
|
||||||
|
|
||||||
## 安全提示
|
## 安全提示
|
||||||
|
|
||||||
- API Key 以明文存储在本地 SQLite 和 Agent 原生配置里——**不要在共享电脑上保存**
|
- API Key 以明文存储在本地 SQLite 和 Agent 原生配置里——**不要在共享电脑上保存**
|
||||||
- 不要把 `pi-switch.db`、`config.toml`、`models.json` 提交到 Git
|
- 不要把 `pi-switch.db`、`config.toml`、`models.json` 提交到 Git
|
||||||
- 应用 CSP 已收紧(`default-src 'self'`),但 WebView2 仍可能缓存表单内容,注意在公共电脑用完退出
|
- 应用 CSP 已收紧(`default-src 'self'`),但 WebView2 仍可能缓存表单内容,注意在公共电脑用完退出
|
||||||
|
|
||||||
- 许可证:MIT(详见 [LICENSE](./LICENSE))
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 附录:相关项目
|
## 附录:相关项目
|
||||||
|
|
||||||
- [Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli) — 兼容的 Agent 之一
|
- [Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli) — 兼容的 Agent 之一
|
||||||
- [Tauri](https://tauri.app) — 桌面应用框架
|
- [Tauri](https://tauri.app) — 桌面应用框架
|
||||||
- 设计文档见 `docs/superpowers/specs/`,实施计划见 `docs/superpowers/plans/`
|
- 设计文档见 `docs/superpowers/specs/`,实施计划见 `docs/superpowers/plans/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
许可证:MIT,详见 [LICENSE](./LICENSE)。Copyright (c) 2026 CodingPlan.site
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
# Pi Switch
|
||||||
|
|
||||||
|
> A Windows desktop LLM provider config manager that lets you switch between multiple LLM providers and models across the **Kimi Code CLI** and **Pi** agents.
|
||||||
|
|
||||||
|
**English** | [中文](./README.md)
|
||||||
|
|
||||||
|
[](https://tauri.app)
|
||||||
|
[](https://react.dev)
|
||||||
|
[](https://www.typescriptlang.org)
|
||||||
|
[](https://www.rust-lang.org)
|
||||||
|
[](./LICENSE)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [What Is This](#what-is-this)
|
||||||
|
- [Key Features](#key-features)
|
||||||
|
- [Architecture Overview](#architecture-overview)
|
||||||
|
- [Supported Provider Types](#supported-provider-types)
|
||||||
|
- [Data Storage Locations](#data-storage-locations)
|
||||||
|
- [Getting Started](#getting-started)
|
||||||
|
- [Development Guide](#development-guide)
|
||||||
|
- [Keyboard Shortcuts](#keyboard-shortcuts)
|
||||||
|
- [Internationalization](#internationalization)
|
||||||
|
- [Testing](#testing)
|
||||||
|
- [Build & Release](#build--release)
|
||||||
|
- [FAQ](#faq)
|
||||||
|
- [Security Notes](#security-notes)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What Is This
|
||||||
|
|
||||||
|
**Pi Switch** is a Windows desktop configuration tool built for LLM CLI users. It solves two pain points:
|
||||||
|
|
||||||
|
1. **Tedious multi-provider management**: switching between Kimi / Anthropic / OpenAI / Google GenAI / self-hosted proxies requires repeatedly hand-editing TOML/JSON, which is error-prone.
|
||||||
|
2. **Fragmented multi-agent configs**: developers using both **Kimi Code CLI** and **Pi** have to maintain two independent config formats, duplicating every change.
|
||||||
|
|
||||||
|
Pi Switch provides a unified GUI:
|
||||||
|
|
||||||
|
- One unified interface to manage two separate agent configs (Kimi Code and Pi), switched via a top tab
|
||||||
|
- One-click provider switching that writes the active provider into the target agent's native config
|
||||||
|
- One-click model-list fetching (OpenAI / Anthropic / Google GenAI)
|
||||||
|
- A `/reload` hint after switching so Kimi Code sessions take effect immediately
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
| Category | Feature |
|
||||||
|
| --- | --- |
|
||||||
|
| **Multi-agent** | Manage Kimi Code and Pi configs independently without interference, via a top tab |
|
||||||
|
| **Multi-provider** | Kimi / Anthropic / OpenAI / OpenAI Responses / Google GenAI / Vertex AI |
|
||||||
|
| **Model mapping** | Alias ↔ real model ID, with display name, context size, role (Sonnet/Opus/Fable/Haiku), and 1M-context declaration |
|
||||||
|
| **One-click discovery** | Auto-fetch available model lists from the provider API |
|
||||||
|
| **Managed providers** | Flag OAuth/managed providers to skip credential validation and preserve the `oauth` section in Kimi Code config |
|
||||||
|
| **Env credentials** | Supports both the `api_key` field and env-table keys (e.g. `OPENAI_API_KEY`) |
|
||||||
|
| **Global settings** | Thinking toggle/level, loop retries, background tasks, permission rules, lifecycle hooks (Kimi Code only) |
|
||||||
|
| **Raw JSON editing** | Power users can hand-edit the full config JSON (unknown fields are preserved, never dropped) |
|
||||||
|
| **i18n** | Simplified Chinese / English, switched at runtime |
|
||||||
|
| **Auto backup** | Before writing the Kimi Code / Pi native configs, back up with timestamp-based names and keep the last 7 days (see `src-tauri/src/config_io.rs`) |
|
||||||
|
| **Shortcuts** | Ctrl+S save, Ctrl+R reload, Ctrl+O open config dir |
|
||||||
|
| **Validation (reserved)** | i18n error strings are defined (duplicate names, missing credentials, missing Vertex fields, etc.), but the backend `validators.rs` is a stub and not yet wired |
|
||||||
|
| **Unsaved-changes prompt** | Detects unsaved edits before closing the window and prefixes the title bar with `*` |
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Pi Switch (Tauri v2) │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
|
||||||
|
│ │ React Frontend (TS) │ │ Rust Backend (lib.rs) │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ src/App.tsx │◄──►│ src-tauri/src/ │ │
|
||||||
|
│ │ src/components/ │ Tauri ├── commands.rs │ │
|
||||||
|
│ │ ProviderList │ invoke ├── db.rs │ │
|
||||||
|
│ │ ProviderEdit │ ├── kimi_code_io │ │
|
||||||
|
│ │ AgentSettingsPanel │ ├── pi_io.rs │ │
|
||||||
|
│ │ src/hooks/useConfig │ ├── config_io.rs │ │
|
||||||
|
│ │ src/i18n/{zh,en}.ts │ ├── validators.rs │ │
|
||||||
|
│ │ src/types/index.ts │ └── profile_manager│ │
|
||||||
|
│ └──────────────────────────┘ └──────────────────────────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
└──────────────────┼──────────────────────────────┼──────────────────┘
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌──────────────────────┐ ┌──────────────────────────┐
|
||||||
|
│ SQLite │ │ Agent native configs │
|
||||||
|
│ ~/.pi-switch/ │ │ ├─ ~/.kimi-code/ │
|
||||||
|
│ pi-switch.db │ │ │ └─ config.toml │
|
||||||
|
│ │ │ └─ ~/.pi/agent/ │
|
||||||
|
│ (Pi Switch internal)│ │ ├─ models.json │
|
||||||
|
└──────────────────────┘ │ └─ settings.json │
|
||||||
|
└──────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key design points**:
|
||||||
|
|
||||||
|
- Pi Switch keeps its own SQLite database for the **full config** (all providers + all models, including inactive ones)
|
||||||
|
- Clicking "Switch to" writes **only the active provider** into the agent's native config; the others are not written
|
||||||
|
- This way Kimi Code / Pi always see exactly one active provider and are never confused by managed/OAuth defaults
|
||||||
|
- The `raw_other` field passes unknown keys through untouched, so round-trips never lose fields
|
||||||
|
|
||||||
|
## Supported Provider Types
|
||||||
|
|
||||||
|
| Type | Identifier | Default base_url | Model discovery | Credentials |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| Kimi | `kimi` | `https://api.openai.com/v1` | ✅ OpenAI protocol | `KIMI_API_KEY` or `env.KIMI_API_KEY` |
|
||||||
|
| Anthropic | `anthropic` | — | ✅ `/v1/models` | `ANTHROPIC_API_KEY` or `env` |
|
||||||
|
| OpenAI | `openai` | `https://api.openai.com/v1` | ✅ `/models` | `OPENAI_API_KEY` or `env` |
|
||||||
|
| OpenAI Responses | `openai_responses` | `https://api.openai.com/v1` | ✅ `/models` | `OPENAI_API_KEY` or `env` |
|
||||||
|
| Google GenAI | `google-genai` | `https://generativelanguage.googleapis.com` | ✅ `/v1beta/models` | `GOOGLE_API_KEY` or `env` |
|
||||||
|
| Vertex AI | `vertexai` | — | ⚠️ Not yet implemented | `VERTEXAI_API_KEY` + `GOOGLE_CLOUD_PROJECT` + `GOOGLE_CLOUD_LOCATION` |
|
||||||
|
|
||||||
|
Credential precedence: the `api_key` field wins over the same-named key in the `env` table.
|
||||||
|
|
||||||
|
## Data Storage Locations
|
||||||
|
|
||||||
|
| File | Purpose | Backup |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `%USERPROFILE%\.pi-switch\pi-switch.db` | Pi Switch's own SQLite database holding the full config | — |
|
||||||
|
| `%USERPROFILE%\.kimi-code\config.toml` | Kimi Code CLI's TOML config (**written on switch**) | `backups/config.toml.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||||||
|
| `%USERPROFILE%\.pi\agent\models.json` | Pi's provider+model config (**written on switch**) | `backups/models.json.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||||||
|
| `%USERPROFILE%\.pi\agent\settings.json` | Pi's default provider/model (**written on switch**) | `backups/settings.json.bak.{YYYYMMDD_HHMMSS}` next to it, kept 7 days |
|
||||||
|
| `localStorage[pi-switch-agent]` | Frontend remembers the last selected agent (kimi_code / pi) | — |
|
||||||
|
|
||||||
|
Environment-variable overrides:
|
||||||
|
|
||||||
|
- `KIMI_CODE_HOME` overrides the Kimi Code config dir (default `~/.kimi-code`)
|
||||||
|
- `PI_CODING_AGENT_DIR` overrides the Pi agent config dir (default `~/.pi/agent`)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
| Tool | Version | Purpose |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Node.js | ≥ 18 | Frontend build |
|
||||||
|
| Rust | Latest stable (edition 2021) | Tauri backend compilation |
|
||||||
|
| WebView2 Runtime | Bundled with Windows 10/11 | Tauri v2 runtime |
|
||||||
|
| Microsoft C++ Build Tools | Latest | Rust compile dependency |
|
||||||
|
| WiX Toolset 3.14 | `src-tauri/wix314-binaries/` | MSI bundling (auto-downloaded on first build) |
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dev mode (hot reload)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run tauri-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Starts both the Vite dev server (port 1420) and the Tauri window. Frontend edits hot-reload; Rust edits trigger a recompile.
|
||||||
|
|
||||||
|
### Frontend-only dev (no Tauri window)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Good for pure UI debugging.
|
||||||
|
|
||||||
|
## Development Guide
|
||||||
|
|
||||||
|
### Project structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── src/ # React frontend
|
||||||
|
│ ├── App.tsx # Root component routing ProviderList/ProviderEdit
|
||||||
|
│ ├── main.tsx # React entry + ErrorBoundary + I18nProvider
|
||||||
|
│ ├── components/
|
||||||
|
│ │ ├── ProviderList.tsx # Provider list + switch button
|
||||||
|
│ │ ├── ProviderEdit.tsx # Edit provider + model mapping + raw JSON
|
||||||
|
│ │ └── AgentSettingsPanel.tsx# Global settings (thinking/loop/permissions/hooks)
|
||||||
|
│ ├── hooks/
|
||||||
|
│ │ └── useConfig.ts # Config load/save hook
|
||||||
|
│ ├── lib/
|
||||||
|
│ │ ├── agent-settings.ts # AgentSettings parse/serialize
|
||||||
|
│ │ └── model-defaults.ts # Default model context sizes
|
||||||
|
│ ├── types/index.ts # Provider/Model/Config type definitions
|
||||||
|
│ ├── i18n/
|
||||||
|
│ │ ├── zh.ts # Chinese translations (143 keys)
|
||||||
|
│ │ ├── en.ts # English translations
|
||||||
|
│ │ └── index.tsx # useTranslation hook + Provider
|
||||||
|
│ └── index.css # Tailwind entry
|
||||||
|
│
|
||||||
|
├── src-tauri/ # Rust backend
|
||||||
|
│ ├── src/
|
||||||
|
│ │ ├── lib.rs # Tauri Builder + invoke_handler registration
|
||||||
|
│ │ ├── main.rs # Binary entry
|
||||||
|
│ │ ├── commands.rs # 7 Tauri commands
|
||||||
|
│ │ ├── db.rs # SQLite persistence
|
||||||
|
│ │ ├── kimi_code_io.rs # ~/.kimi-code/config.toml read/write
|
||||||
|
│ │ ├── pi_io.rs # ~/.pi/agent/*.json read/write
|
||||||
|
│ │ ├── config_io.rs # File backup utilities
|
||||||
|
│ │ ├── models.rs # Config/Provider/Model data structures
|
||||||
|
│ │ ├── profile_manager.rs # Multi-profile management (stub)
|
||||||
|
│ │ └── validators.rs # Config validation
|
||||||
|
│ ├── capabilities/ # Tauri permission declarations
|
||||||
|
│ ├── icons/ # App icons (script-generated)
|
||||||
|
│ └── tauri.conf.json # Tauri config (window/bundle/CSP)
|
||||||
|
│
|
||||||
|
├── scripts/generate-icons.py # Generate all icon sizes from SVG
|
||||||
|
├── public/pi.svg # App icon source (blue-purple gradient π)
|
||||||
|
└── docs/superpowers/ # Design specs & implementation plans
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tauri commands (frontend ↔ backend)
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| `load_agent_config_command(agent)` | Load config: SQLite first, falling back to the agent's native config on first use |
|
||||||
|
| `save_agent_config_command(agent, config)` | Save the full config to SQLite |
|
||||||
|
| `activate_agent_config_command(agent)` | Write the active provider into the agent's native config |
|
||||||
|
| `open_agent_config_dir(agent)` | Open the agent's config dir in the system file manager |
|
||||||
|
| `get_app_version()` | Return the `Cargo.toml` version |
|
||||||
|
| `list_provider_models(provider)` | Fetch model list from the provider API (async) |
|
||||||
|
| `debug_log(message)` | Forward frontend logs to stderr (dev use) |
|
||||||
|
|
||||||
|
### Adding a new provider type
|
||||||
|
|
||||||
|
1. Add a new variant to the `ProviderType` enum in `src-tauri/src/models.rs`
|
||||||
|
2. Add a default in `default_base_url()`
|
||||||
|
3. Add a dispatch arm in `commands.rs::list_provider_models`
|
||||||
|
4. Add mappings in `kimi_code_io.rs::provider_type_for_kimi_type` and `pi_io.rs::provider_type_for_pi_api`
|
||||||
|
5. Add an option to the API-format dropdown in `src/components/ProviderEdit.tsx`
|
||||||
|
6. Add new i18n keys in `src/i18n/{zh,en}.ts`
|
||||||
|
|
||||||
|
### Adding a new Tauri command
|
||||||
|
|
||||||
|
1. Add a `#[tauri::command]` in `src-tauri/src/commands.rs`
|
||||||
|
2. Register it in the `tauri::generate_handler![...]` list in `src-tauri/src/lib.rs`
|
||||||
|
3. Call it from the frontend with `import { invoke } from "@tauri-apps/api/core"`
|
||||||
|
4. Add a permission in `src-tauri/capabilities/default.json` (if filesystem access is needed)
|
||||||
|
|
||||||
|
## Keyboard Shortcuts
|
||||||
|
|
||||||
|
| Shortcut | Action |
|
||||||
|
| --- | --- |
|
||||||
|
| `Ctrl + S` | Save current changes to SQLite |
|
||||||
|
| `Ctrl + R` | Reload config (prompts if unsaved) |
|
||||||
|
| `Ctrl + O` | Open the current agent's config dir |
|
||||||
|
|
||||||
|
## Internationalization
|
||||||
|
|
||||||
|
- Translation sources: `src/i18n/zh.ts` (source) and `src/i18n/en.ts` (target)
|
||||||
|
- When adding a key, **add it to `zh.ts` first** — the `Record<TranslationKey, string>` type in `en.ts` will flag any missing entry at compile time
|
||||||
|
- Language is switched at runtime via the top-right dropdown and held in component state (not persisted to SQLite)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Rust unit tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src-tauri
|
||||||
|
cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently covered:
|
||||||
|
|
||||||
|
- `kimi_code_io::tests` — TOML import/export round-trips
|
||||||
|
- `pi_io::tests` — JSON round-trips, including advanced fields (headers/compat/cost/extra)
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
No automated tests yet. Suggested manual checklist:
|
||||||
|
|
||||||
|
- [ ] Switching agents doesn't cross-contaminate configs
|
||||||
|
- [ ] Deleting a provider also deletes its models
|
||||||
|
- [ ] The default model restores correctly after switching providers
|
||||||
|
- [ ] Renaming a provider updates models that reference it
|
||||||
|
- [ ] Raw-JSON editing preserves `raw_other` fields
|
||||||
|
|
||||||
|
## Build & Release
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run tauri-build
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
- `src-tauri/target/release/bundle/msi/Pi Switch_0.1.0_x64_en-US.msi`
|
||||||
|
|
||||||
|
A Windows installer (MSI) with the WebView2 bootstrapper embedded for auto-download. `nsis` is disabled; only MSI is produced.
|
||||||
|
|
||||||
|
### First build
|
||||||
|
|
||||||
|
The first run downloads:
|
||||||
|
|
||||||
|
- WiX Toolset 3.14 binaries → `src-tauri/wix314-binaries/`
|
||||||
|
- WebView2 bootstrapper → embedded into the MSI
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
**Q: Kimi Code didn't pick up the change after switching providers?**
|
||||||
|
A: Run `/reload` inside the Kimi Code session (the CLI only re-reads `~/.kimi-code/config.toml` on reload). The app shows this hint in the UI.
|
||||||
|
|
||||||
|
**Q: I edited the config but closed the window without saving?**
|
||||||
|
A: A native `beforeunload` prompt appears before closing, and the title bar shows a `*` prefix.
|
||||||
|
|
||||||
|
**Q: How do I back up / migrate my config?**
|
||||||
|
A: Back up `%USERPROFILE%\.pi-switch\pi-switch.db`; it holds the full config (including inactive providers).
|
||||||
|
|
||||||
|
**Q: Why can't Vertex AI fetch the model list?**
|
||||||
|
A: Vertex requires GCP project/location credentials. The current implementation leaves a TODO pending GCP SDK integration.
|
||||||
|
|
||||||
|
**Q: macOS / Linux support?**
|
||||||
|
A: The code doesn't depend on Windows-only APIs, but `tauri.conf.json` only targets `msi` for bundling. In theory, changing `bundle.targets` to `["app", "dmg"]` etc. would enable cross-platform builds, but this is unverified.
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- API keys are stored in plaintext in the local SQLite database and agent native configs — **do not store them on shared computers**
|
||||||
|
- Do not commit `pi-switch.db`, `config.toml`, or `models.json` to Git
|
||||||
|
- The app CSP is tightened (`default-src 'self'`), but WebView2 may still cache form content — log out when finished on public machines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix: Related Projects
|
||||||
|
|
||||||
|
- [Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli) — one of the compatible agents
|
||||||
|
- [Tauri](https://tauri.app) — the desktop app framework
|
||||||
|
- Design specs in `docs/superpowers/specs/`, implementation plans in `docs/superpowers/plans/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
License: MIT, see [LICENSE](./LICENSE). Copyright (c) 2026 CodingPlan.site
|
||||||
Reference in New Issue
Block a user