Metadata-Version: 2.4
Name: tinychat-ai
Version: 0.1.6
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
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`）、两步删除确认（5 秒自动取消）
- 会话导入/导出（Markdown / JSON），损坏文件自动备份恢复
- LRU 缓存策略，仅保留当前会话在内存中

### 消息操作
- `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
pip install -e ".[dev]"

# 或使用 uv
uv sync --extra dev
```

### 安装内置工具

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

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

> 如从源码安装，可使用：`pip install -e "./packages/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" (中文)

[[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"
```

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

---

## 开发

### 项目结构

```
tinychat/
├── src/tinychat/
│   ├── __main__.py              # 入口
│   ├── app_textual.py           # 主应用
│   ├── backends/                # 后端实现
│   │   ├── base.py              # 抽象基类
│   │   ├── ollama.py            # Ollama 后端
│   │   ├── openai.py            # OpenAI 后端
│   │   └── dsml_parser.py       # DSML 工具调用解析
│   ├── components/              # UI 组件
│   │   ├── chat_view.py         # 聊天消息显示
│   │   ├── input_area.py        # 用户输入区
│   │   ├── sidebar.py           # 后端/模型侧边栏
│   │   ├── status_bar.py        # 状态栏
│   │   ├── message_widgets.py   # 消息渲染组件
│   │   ├── tool_result_card.py  # 工具结果折叠卡片
│   │   ├── tool_confirm_screen.py  # 工具执行确认
│   │   ├── session_list_dialog.py   # 会话列表对话框
│   │   ├── rename_dialog.py     # 会话重命名对话框
│   │   ├── message_action_screen.py # 消息操作菜单
│   │   └── left_panel.py        # 左侧面板容器
│   ├── models/                  # 数据模型
│   ├── tools/                   # 工具系统
│   │   ├── base.py              # 工具基类
│   │   ├── manager.py           # 插件管理器
│   │   ├── executor.py          # 工具执行器（信任机制）
│   │   ├── adapter.py           # LLM 工具调用适配器
│   │   └── trigger_manager.py   # 触发词管理器
│   ├── workflow/                # 工作流引擎
│   │   └── engine.py            # 多步骤工作流执行
│   ├── utils/                   # 工具函数
│   │   ├── config_manager.py    # 统一 TOML 配置管理
│   │   ├── i18n.py              # 国际化
│   │   ├── theme_manager.py     # 主题管理
│   │   ├── session_persistence.py # 会话持久化
│   │   ├── session_manager.py   # 会话状态管理
│   │   ├── metrics.py           # 流式性能指标
│   │   ├── clipboard.py         # 剪贴板（OSC 52 降级）
│   │   └── logging_config.py    # 日志配置
│   ├── locales/                 # 翻译文件
│   └── styles/                  # CSS 样式
├── packages/
│   └── tinychat-builtin-tools/  # 内置工具插件
└── tests/                       # 测试
```

### 运行测试

```bash
# 运行所有测试
pytest tests/ -v

# 带覆盖率报告
pytest tests/ --cov=src/tinychat --cov-report=html

# 运行单个测试
pytest tests/unit/test_app_textual.py -v
```

### 代码检查

```bash
ruff check src/ tests/
ruff format src/ tests/
```

### 打包发布

```bash
# 安装构建工具
pip install build

# 构建
python -m build

# 生成的文件在 dist/ 目录
```

---

## 致谢

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

## 许可证

MIT License
