Metadata-Version: 2.4
Name: tinychat-ai
Version: 0.1.9
Summary: A feature-rich yet lightweight terminal AI chat application designed for low resource consumption
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27.0
Requires-Dist: tomli>=2.0.0
Requires-Dist: textual>=8.0.2
Requires-Dist: rich>=14.3.3
Requires-Dist: pyperclip>=1.11.0
Requires-Dist: tomli-w>=1.2.0
Requires-Dist: aiosqlite>=0.20.0
Requires-Dist: pypika>=0.49.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: respx>=0.20.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"

# TinyChat

**TinyChat** 是一款功能丰富且轻量的终端 AI 聊天应用，基于 [Textual](https://github.com/Textualize/textual) 框架构建，专为低资源消耗设计。支持 Ollama 本地模型和 OpenAI 兼容 API，内置插件式工具系统，提供流式响应、多会话管理、工作流引擎和中英文双语界面，满足从日常对话到 AI 辅助编程的多种场景。

## 特性

### 多后端支持
- **Ollama** — 本地 Ollama 服务器
- **OpenAI 兼容** — 支持 vLLM、LM Studio、OpenRouter、Azure OpenAI 等所有 OpenAI 兼容 API
- 运行时热切换后端与模型，侧边栏一键操作（`Ctrl+B`）
- 自动验证并修正旧会话中失效的模型名称
- 非阻塞启动 — 后台异步获取模型列表，界面立即可用

### 现代化终端界面
- 基于 [Textual](https://github.com/Textualize/textual) 框架，响应式布局自适应终端尺寸
- 丰富的 Markdown 渲染和代码高亮，流式响应逐 token 实时显示
- 明/暗双主题，遵循 WCAG AA 无障碍对比度标准
- 原生鼠标支持（点击、滚动、右键菜单）
- 状态栏实时显示连接状态、模型名称、响应耗时和 tokens/s 吞吐量
- `ESC` 停止流式响应，输入历史导航（上下方向键）

### 多会话管理
- 标签式多会话，`Ctrl+T` 新建、`Ctrl+L` 打开会话列表
- 会话持久化至 `~/.tinychat/sessions/`，每次对话自动保存（防抖 2 秒）
- 会话列表对话框：模糊搜索、按日期分组、相对时间戳、消息预览、`j`/`k` 键盘导航
- 会话分叉（Fork） — 从任意助手消息创建新分支会话
- 重命名（`Ctrl+R`，会话列表中）、两步删除确认（`Ctrl+D` 两次，5 秒自动取消）
- 会话导出（Markdown / JSON）、导入（JSON），损坏文件自动备份恢复
- 单会话内存模式，切换时自动卸载非活跃会话

### 消息操作
- `Alt+M` 消息操作菜单：分叉（Fork）、重新生成（Regenerate）、删除（Delete）
- 删除消息时自动清理关联的工具调用和错误消息
- 工具执行结果可折叠卡片，超长内容自动收起，智能标题摘要（显示命令、文件名、行范围等）

### 工具系统（插件架构）
- 基于 Python entry points 的插件发现机制，第三方工具通过 pip 安装即可使用
- 智能工具选择 — 根据用户消息自动匹配文件路径、命令关键词、任务关键词，动态决定注入哪些工具
- 多语言触发词系统（`en.json`/`zh.json`），按相关性百分比生成工具使用提示
- 三种工具调用适配器：
  - **NativeAdapter** — 原生 `tool_calls` 支持（Ollama 0.3+、OpenAI）
  - **PromptAdapter** — 无原生工具调用时的提示词降级方案
  - **DSMLParser** — DeepSeek DSML 工具调用解析，支持 XML 和 JSON 参数格式，流式输出时自动屏蔽原始标记
- 渐进信任机制 — 每次执行需确认，连续允许 3 次后提示"始终允许"，偏好持久化到配置文件
- 重复调用检测，最大递归深度 50 层防止无限循环

### 内置工具（tinychat-builtin-tools）
- **`read_file`** — 读取文件，支持偏移量、行数限制和尾部读取
- **`write_file`** — 写入文件，自动创建父目录
- **`edit_file`** — 查找替换编辑，支持全局替换
- **`list_directory`** — 列出目录内容
- **`glob`** — 按通配符模式搜索文件（`**/*.py`）
- **`grep`** — 正则搜索文件树，支持包含过滤、上下文行和最大匹配数
- **`exec_shell`** — Shell 命令执行，命令白名单、危险模式拦截、环境变量清理、超时控制
- **`no_action`** — 显式无操作工具，让 LLM 主动声明无需调用工具
- **`todo_list`** — 任务管理，支持传统待办模式和工作流模式

### 工作流引擎
- 多步骤工作流执行，支持步骤间依赖关系（DAG）
- 每步骤独立超时、重试次数和确认开关
- 工作流状态持久化，应用重启后自动恢复未完成的执行
- 状态追踪：pending → running → paused → completed / failed / cancelled

### 国际化
- 中文/英文双语界面，基于 gettext 运行时切换语言
- 所有 UI 文本均可翻译：绑定描述、状态消息、对话框标签、错误提示
- 翻译快捷命令：`翻译：内容` / `translate:content`

### 跨平台
- 支持 Windows、macOS、Linux
- 跨平台剪贴板 — pyperclip 优先，OSC 52 降级（适配 SSH/远程终端）

### 快捷命令
- `翻译：内容` — 自动改写为翻译提示（中文）
- `translate:content` — 自动改写为翻译提示（英文）

---

## 安装

### 系统要求
- Python 3.9+
- pip 或 uv 包管理器

### 从 PyPI 安装

```bash
pip install tinychat
```

### 从源码安装

```bash
git clone <repository-url>
cd tinychat
pip install .
```

详细开发环境搭建请参阅 [开发指南](docs/CONTRIBUTING.md)。

### 安装内置工具

内置工具提供文件读写、Shell 执行、搜索和工作流等功能，需单独安装：

```bash
pip install tinychat-builtin-tools
```

---

## 使用

### 启动应用

```bash
tinychat
```

或直接运行模块：

```bash
python -m tinychat
```

### 基本操作

1. **选择后端** - 在左侧边栏点击后端名称
2. **选择模型** - 在边栏点击模型名称
3. **发送消息** - 输入内容后按 Enter
4. **换行** - 按 Ctrl+Enter 插入换行
5. **滚动历史** - 使用鼠标滚轮或方向键

### 快捷键

| 按键 | 功能 |
|------|------|
| **Enter** | 发送消息 |
| **Ctrl+J** | 输入换行 |
| **Ctrl+T** | 新建会话 |
| **Ctrl+L** | 会话列表 |
| **Ctrl+B** | 后端/模型面板 |
| **Ctrl+P** | 命令面板 |
| **Alt+M** | 消息操作（分叉/重新生成/删除） |
| **Ctrl+Q** | 退出应用 |
| **ESC** | 停止流式响应 / 关闭面板 |

---

## 配置

配置文件位于 `~/.config/tinychat/config.toml`（如不存在会自动创建）。

### 配置结构

```toml
[settings]
locale = "zh"  # 语言: "en" (英语) 或 "zh" (中文)
# Progressive loading settings (optional)
loading_batch_size = 15            # 每批渲染的消息数，默认15
loading_frame_delay = 0.016        # 批次间延迟（秒），默认0.016（约1帧，60Hz）
virtualization_threshold = 28      # 启用虚拟滚动的消息数阈值，默认28

[[backends]]  # 可以配置多个后端
name = "backend-name"       # 后端显示名称
type = "backend-type"       # 后端类型
endpoint = "API地址"         # API 端点
default_model = "模型名"     # 默认模型
api_key = "密钥"            # API 密钥（可选）
```

### 后端类型详解

| 类型 | 说明 | API 端点示例 |
|------|------|--------------|
| `ollama` | 本地 Ollama 服务器 | `http://localhost:11434` |
| `openai-compatible` | OpenAI 兼容的 API 服务 | `https://api.example.com/v1` |

### 后端配置参数

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `name` | 字符串 | 是 | 后端显示名称，用于 UI 标识 |
| `type` | 字符串 | 是 | 后端类型：`ollama` 或 `openai-compatible` |
| `endpoint` | 字符串 | 是 | API 地址，需包含完整路径（如 `/v1`） |
| `default_model` | 字符串 | 是 | 默认使用的模型名称 |
| `api_key` | 字符串 | 否 | API 密钥（Ollama 不需要） |

### 配置示例

**Ollama 本地服务器：**

```toml
[[backends]]
name = "ollama-local"
type = "ollama"
endpoint = "http://localhost:11434"
default_model = "llama3.2"
```

**OpenAI 官方 API：**

```toml
[[backends]]
name = "openai"
type = "openai-compatible"
endpoint = "https://api.openai.com/v1"
api_key = "sk-..."
default_model = "gpt-4o"
```

**vLLM / LM Studio / Text Generation WebUI 等 OpenAI 兼容服务：**

```toml
[[backends]]
name = "vllm-server"
type = "openai-compatible"
endpoint = "http://localhost:8000/v1"
api_key = "not-required"  # 多数本地服务不需要密钥
default_model = "meta-llama/Llama-2-7b-chat-hf"
```

**OpenRouter / Together AI 等云服务：**

```toml
[[backends]]
name = "openrouter"
type = "openai-compatible"
endpoint = "https://openrouter.ai/api/v1"
api_key = "sk-or-..."
default_model = "openai/gpt-3.5-turbo"
```

**Azure OpenAI Service：**

```toml
[[backends]]
name = "azure-openai"
type = "openai-compatible"
endpoint = "https://your-resource.openai.azure.com/openai/deployments/your-deployment"
api_key = "your-azure-api-key"
default_model = "gpt-35-turbo"
```

### 多后端配置

可以同时配置多个后端，通过 `name` 字段区分：

```toml
[settings]
locale = "zh"

[[backends]]
name = "ollama-local"
type = "ollama"
endpoint = "http://localhost:11434"
default_model = "llama3.2"

[[backends]]
name = "openai-cloud"
type = "openai-compatible"
endpoint = "https://api.openai.com/v1"
api_key = "sk-..."
default_model = "gpt-4o"

[[backends]]
name = "vllm-server"
type = "openai-compatible"
endpoint = "http://localhost:8000/v1"
default_model = "meta-llama/Llama-2-7b-chat-hf"
```

启动后可在左侧边栏点击切换不同后端和模型。

---

## 贡献

欢迎贡献！请参阅 [开发指南](docs/CONTRIBUTING.md) 了解项目结构、开发环境搭建、代码规范和插件开发。

---

## Storybook (组件预览)

TinyChat 包含一个基于 TUI 的 Storybook 工具，用于可视化预览和测试自定义组件。

### 启动 Storybook

```bash
storybook
```

或

```bash
python -m tinychat.storybook
```

### 导航

- `↑` / `↓` — 在故事列表中上下移动
- `Enter` — 选中并预览当前故事
- `Tab` — 在侧边栏和预览区域间切换焦点
- `t` — 切换明/暗主题
- `q` — 退出

### 开发：添加新故事

1. 在 `src/tinychat/components/` 开发或修改组件。
2. 在 `src/tinychat/storybook/stories/` 创建故事文件，使用 `register()` 注册 Story。
3. 在 `src/tinychat/storybook/stories/__init__.py` 中导入新模块以自动加载。
4. 运行 `storybook` 预览。

详细设计文档见 `docs/design/storybook-tui-design.md`。

---

## 致谢

- [Textual](https://github.com/Textualize/textual) — 现代 TUI 框架
- [Rich](https://github.com/Textualize/rich) — 富文本渲染
- [httpx](https://www.python-httpx.org/) — 异步 HTTP 客户端

## 许可证

MIT License
