hotaru-code 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hotaru_code-0.1.0/.github/workflows/publish-pypi.yml +50 -0
- hotaru_code-0.1.0/.gitignore +15 -0
- hotaru_code-0.1.0/.python-version +1 -0
- hotaru_code-0.1.0/PKG-INFO +218 -0
- hotaru_code-0.1.0/README.md +194 -0
- hotaru_code-0.1.0/docs/tui-migration.md +25 -0
- hotaru_code-0.1.0/pyproject.toml +40 -0
- hotaru_code-0.1.0/src/hotaru/__init__.py +97 -0
- hotaru_code-0.1.0/src/hotaru/agent/__init__.py +5 -0
- hotaru_code-0.1.0/src/hotaru/agent/agent.py +343 -0
- hotaru_code-0.1.0/src/hotaru/cli/__init__.py +5 -0
- hotaru_code-0.1.0/src/hotaru/cli/cmd/__init__.py +1 -0
- hotaru_code-0.1.0/src/hotaru/cli/cmd/chat.py +280 -0
- hotaru_code-0.1.0/src/hotaru/cli/cmd/run.py +376 -0
- hotaru_code-0.1.0/src/hotaru/cli/cmd/tui.py +40 -0
- hotaru_code-0.1.0/src/hotaru/cli/main.py +432 -0
- hotaru_code-0.1.0/src/hotaru/core/__init__.py +12 -0
- hotaru_code-0.1.0/src/hotaru/core/bus.py +259 -0
- hotaru_code-0.1.0/src/hotaru/core/config.py +467 -0
- hotaru_code-0.1.0/src/hotaru/core/context.py +81 -0
- hotaru_code-0.1.0/src/hotaru/core/env.py +75 -0
- hotaru_code-0.1.0/src/hotaru/core/global_paths.py +101 -0
- hotaru_code-0.1.0/src/hotaru/core/id.py +139 -0
- hotaru_code-0.1.0/src/hotaru/lsp/__init__.py +33 -0
- hotaru_code-0.1.0/src/hotaru/lsp/client.py +534 -0
- hotaru_code-0.1.0/src/hotaru/lsp/language.py +140 -0
- hotaru_code-0.1.0/src/hotaru/lsp/lsp.py +594 -0
- hotaru_code-0.1.0/src/hotaru/lsp/server.py +429 -0
- hotaru_code-0.1.0/src/hotaru/mcp/__init__.py +33 -0
- hotaru_code-0.1.0/src/hotaru/mcp/auth.py +325 -0
- hotaru_code-0.1.0/src/hotaru/mcp/mcp.py +992 -0
- hotaru_code-0.1.0/src/hotaru/mcp/oauth_callback.py +320 -0
- hotaru_code-0.1.0/src/hotaru/mcp/oauth_provider.py +197 -0
- hotaru_code-0.1.0/src/hotaru/permission/__init__.py +29 -0
- hotaru_code-0.1.0/src/hotaru/permission/permission.py +460 -0
- hotaru_code-0.1.0/src/hotaru/project/__init__.py +7 -0
- hotaru_code-0.1.0/src/hotaru/project/instance.py +216 -0
- hotaru_code-0.1.0/src/hotaru/project/project.py +258 -0
- hotaru_code-0.1.0/src/hotaru/project/state.py +147 -0
- hotaru_code-0.1.0/src/hotaru/provider/__init__.py +17 -0
- hotaru_code-0.1.0/src/hotaru/provider/auth.py +74 -0
- hotaru_code-0.1.0/src/hotaru/provider/models.py +241 -0
- hotaru_code-0.1.0/src/hotaru/provider/provider.py +546 -0
- hotaru_code-0.1.0/src/hotaru/provider/sdk/__init__.py +6 -0
- hotaru_code-0.1.0/src/hotaru/provider/sdk/anthropic.py +276 -0
- hotaru_code-0.1.0/src/hotaru/provider/sdk/openai.py +275 -0
- hotaru_code-0.1.0/src/hotaru/server/__init__.py +33 -0
- hotaru_code-0.1.0/src/hotaru/server/server.py +364 -0
- hotaru_code-0.1.0/src/hotaru/session/__init__.py +38 -0
- hotaru_code-0.1.0/src/hotaru/session/llm.py +241 -0
- hotaru_code-0.1.0/src/hotaru/session/message.py +299 -0
- hotaru_code-0.1.0/src/hotaru/session/processor.py +544 -0
- hotaru_code-0.1.0/src/hotaru/session/prompt/default.txt +53 -0
- hotaru_code-0.1.0/src/hotaru/session/session.py +422 -0
- hotaru_code-0.1.0/src/hotaru/session/system.py +113 -0
- hotaru_code-0.1.0/src/hotaru/shell/__init__.py +27 -0
- hotaru_code-0.1.0/src/hotaru/shell/shell.py +431 -0
- hotaru_code-0.1.0/src/hotaru/skill/__init__.py +42 -0
- hotaru_code-0.1.0/src/hotaru/skill/skill.py +415 -0
- hotaru_code-0.1.0/src/hotaru/storage/__init__.py +5 -0
- hotaru_code-0.1.0/src/hotaru/storage/lock.py +101 -0
- hotaru_code-0.1.0/src/hotaru/storage/storage.py +168 -0
- hotaru_code-0.1.0/src/hotaru/tool/__init__.py +50 -0
- hotaru_code-0.1.0/src/hotaru/tool/bash.py +186 -0
- hotaru_code-0.1.0/src/hotaru/tool/edit.py +383 -0
- hotaru_code-0.1.0/src/hotaru/tool/external_directory.py +53 -0
- hotaru_code-0.1.0/src/hotaru/tool/glob.py +187 -0
- hotaru_code-0.1.0/src/hotaru/tool/grep.py +218 -0
- hotaru_code-0.1.0/src/hotaru/tool/read.py +218 -0
- hotaru_code-0.1.0/src/hotaru/tool/registry.py +158 -0
- hotaru_code-0.1.0/src/hotaru/tool/skill.py +223 -0
- hotaru_code-0.1.0/src/hotaru/tool/tool.py +210 -0
- hotaru_code-0.1.0/src/hotaru/tool/truncation.py +217 -0
- hotaru_code-0.1.0/src/hotaru/tool/write.py +110 -0
- hotaru_code-0.1.0/src/hotaru/tui/__init__.py +135 -0
- hotaru_code-0.1.0/src/hotaru/tui/app.py +1229 -0
- hotaru_code-0.1.0/src/hotaru/tui/commands.py +405 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/__init__.py +44 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/args.py +107 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/kv.py +185 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/local.py +410 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/route.py +186 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/sdk.py +617 -0
- hotaru_code-0.1.0/src/hotaru/tui/context/sync.py +466 -0
- hotaru_code-0.1.0/src/hotaru/tui/dialogs.py +962 -0
- hotaru_code-0.1.0/src/hotaru/tui/event.py +60 -0
- hotaru_code-0.1.0/src/hotaru/tui/input_parsing.py +132 -0
- hotaru_code-0.1.0/src/hotaru/tui/screens.py +765 -0
- hotaru_code-0.1.0/src/hotaru/tui/theme.py +312 -0
- hotaru_code-0.1.0/src/hotaru/tui/transcript.py +172 -0
- hotaru_code-0.1.0/src/hotaru/tui/turns.py +35 -0
- hotaru_code-0.1.0/src/hotaru/tui/util/__init__.py +9 -0
- hotaru_code-0.1.0/src/hotaru/tui/util/filtered_list.py +289 -0
- hotaru_code-0.1.0/src/hotaru/tui/util.py +263 -0
- hotaru_code-0.1.0/src/hotaru/tui/widgets.py +940 -0
- hotaru_code-0.1.0/src/hotaru/util/__init__.py +6 -0
- hotaru_code-0.1.0/src/hotaru/util/error.py +47 -0
- hotaru_code-0.1.0/src/hotaru/util/log.py +274 -0
- hotaru_code-0.1.0/tests/agent/test_agent_permissions.py +86 -0
- hotaru_code-0.1.0/tests/provider/test_provider_auth.py +29 -0
- hotaru_code-0.1.0/tests/provider/test_provider_key_resolution.py +37 -0
- hotaru_code-0.1.0/tests/tui/test_commands.py +57 -0
- hotaru_code-0.1.0/tests/tui/test_dialogs.py +72 -0
- hotaru_code-0.1.0/tests/tui/test_input_parsing.py +51 -0
- hotaru_code-0.1.0/tests/tui/test_local_model_state.py +65 -0
- hotaru_code-0.1.0/tests/tui/test_sync_context.py +27 -0
- hotaru_code-0.1.0/tests/tui/test_transcript.py +65 -0
- hotaru_code-0.1.0/tests/tui/test_turns.py +40 -0
- hotaru_code-0.1.0/uv.lock +1047 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Publish PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v5
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: uv build
|
|
27
|
+
|
|
28
|
+
- name: Upload dist artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
needs: build
|
|
37
|
+
environment:
|
|
38
|
+
name: pypi
|
|
39
|
+
url: https://pypi.org/p/hotaru-code
|
|
40
|
+
permissions:
|
|
41
|
+
id-token: write
|
|
42
|
+
steps:
|
|
43
|
+
- name: Download dist artifacts
|
|
44
|
+
uses: actions/download-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
- name: Publish to PyPI
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hotaru-code
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python translation of OpenCode - AI-powered coding assistant
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: aiofiles>=23.0
|
|
7
|
+
Requires-Dist: anthropic>=0.30
|
|
8
|
+
Requires-Dist: anyio>=4.0
|
|
9
|
+
Requires-Dist: httpx>=0.25
|
|
10
|
+
Requires-Dist: mcp>=1.0
|
|
11
|
+
Requires-Dist: openai>=1.30
|
|
12
|
+
Requires-Dist: pathspec>=0.12
|
|
13
|
+
Requires-Dist: platformdirs>=4.0
|
|
14
|
+
Requires-Dist: pydantic>=2.0
|
|
15
|
+
Requires-Dist: python-ulid>=2.0
|
|
16
|
+
Requires-Dist: pyyaml>=6.0
|
|
17
|
+
Requires-Dist: rich>=13.0
|
|
18
|
+
Requires-Dist: starlette>=0.35
|
|
19
|
+
Requires-Dist: structlog>=24.0
|
|
20
|
+
Requires-Dist: textual>=0.50
|
|
21
|
+
Requires-Dist: typer>=0.9
|
|
22
|
+
Requires-Dist: uvicorn>=0.27
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Hotaru Code
|
|
26
|
+
|
|
27
|
+
Hotaru Code 用于在终端中提供 AI 编码助手能力。
|
|
28
|
+
|
|
29
|
+
它支持 TUI、交互式 Chat 和一次性 Run 三种使用模式,并具备工具调用、权限控制、会话持久化、MCP 扩展等能力。
|
|
30
|
+
|
|
31
|
+
## 功能概览
|
|
32
|
+
|
|
33
|
+
- 多种交互方式
|
|
34
|
+
- `hotaru`:默认进入 TUI(Textual)
|
|
35
|
+
- `hotaru chat`:交互式命令行聊天
|
|
36
|
+
- `hotaru run "你的问题"`:一次性执行
|
|
37
|
+
- Agentic 工具调用循环
|
|
38
|
+
- LLM 输出可触发工具执行,结果会回注到上下文继续推理
|
|
39
|
+
- 内置工具
|
|
40
|
+
- `read`、`write`、`edit`、`bash`、`glob`、`grep`、`skill`
|
|
41
|
+
- 细粒度权限系统
|
|
42
|
+
- 对 `bash`、`edit`、`read` 等按规则 `allow/ask/deny`
|
|
43
|
+
- 支持“仅本次允许/始终允许/拒绝”交互
|
|
44
|
+
- 内置重复工具调用(doom loop)保护
|
|
45
|
+
- Provider 与模型抽象
|
|
46
|
+
- 支持 OpenAI、Anthropic 及 OpenAI-compatible 自定义服务
|
|
47
|
+
- 通过 `provider/model` 选择模型
|
|
48
|
+
- MCP (Model Context Protocol)
|
|
49
|
+
- 支持本地(stdio)和远程(HTTP/SSE)MCP 服务
|
|
50
|
+
- MCP 工具会自动并入可调用工具列表
|
|
51
|
+
- Skill 系统
|
|
52
|
+
- 支持从 `SKILL.md` 发现并加载领域技能
|
|
53
|
+
- 会话持久化
|
|
54
|
+
- 会话与消息写入本地 JSON 存储,可继续/切换历史会话
|
|
55
|
+
|
|
56
|
+
## 快速开始
|
|
57
|
+
|
|
58
|
+
### 1. 安装依赖
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. 配置 API Key
|
|
65
|
+
|
|
66
|
+
至少配置一个可用 Provider 的密钥,例如:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# PowerShell
|
|
70
|
+
$env:OPENAI_API_KEY = "your-key"
|
|
71
|
+
|
|
72
|
+
# 或
|
|
73
|
+
$env:ANTHROPIC_API_KEY = "your-key"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. 启动
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# 默认进入 TUI
|
|
80
|
+
uv run hotaru
|
|
81
|
+
|
|
82
|
+
# 交互式 chat
|
|
83
|
+
uv run hotaru chat
|
|
84
|
+
|
|
85
|
+
# 一次性执行
|
|
86
|
+
uv run hotaru run "请分析这个仓库的结构"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 常用命令
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
hotaru --help
|
|
93
|
+
hotaru --version
|
|
94
|
+
hotaru providers # 列出可用 provider 和模型
|
|
95
|
+
hotaru agents # 列出 agent
|
|
96
|
+
hotaru sessions -n 20 # 列出最近会话
|
|
97
|
+
hotaru config --show # 展示合并后的配置
|
|
98
|
+
hotaru config --path # 展示配置目录
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `run` 子命令常用参数
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
hotaru run "修复 tests 失败" --model openai/gpt-4o-mini --agent build
|
|
105
|
+
hotaru run "总结这段日志" --json
|
|
106
|
+
hotaru run "重构这个函数" --yes
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- `--model/-m`:指定 `provider/model`
|
|
110
|
+
- `--agent/-a`:指定 agent
|
|
111
|
+
- `--session/-s` / `--continue/-c`:继续会话
|
|
112
|
+
- `--file/-f`:附加文件
|
|
113
|
+
- `--json`:输出 JSON 事件流
|
|
114
|
+
- `--yes/-y`:自动通过权限请求
|
|
115
|
+
|
|
116
|
+
## 配置说明
|
|
117
|
+
|
|
118
|
+
Hotaru 会合并多来源配置(后者覆盖前者):
|
|
119
|
+
|
|
120
|
+
1. 全局配置目录(`hotaru config --path` 可查看)
|
|
121
|
+
2. 项目目录向上查找的 `hotaru.json` / `hotaru.jsonc`
|
|
122
|
+
3. `.hotaru/hotaru.json` / `.hotaru/hotaru.jsonc`
|
|
123
|
+
4. 环境变量 `HOTARU_CONFIG_CONTENT`
|
|
124
|
+
5. 托管配置目录(最高优先级)
|
|
125
|
+
|
|
126
|
+
### 最小 `hotaru.json` 示例
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"model": "openai/gpt-4o-mini",
|
|
131
|
+
"default_agent": "build",
|
|
132
|
+
"provider": {
|
|
133
|
+
"openai": {
|
|
134
|
+
"options": {
|
|
135
|
+
"apiKey": "{env:OPENAI_API_KEY}"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"permission": {
|
|
140
|
+
"bash": "ask",
|
|
141
|
+
"edit": "ask",
|
|
142
|
+
"read": {
|
|
143
|
+
"*.env": "ask",
|
|
144
|
+
"*.env.example": "allow"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 自定义 OpenAI-compatible Provider 示例
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"provider": {
|
|
155
|
+
"my-provider": {
|
|
156
|
+
"type": "openai",
|
|
157
|
+
"name": "My Provider",
|
|
158
|
+
"options": {
|
|
159
|
+
"baseURL": "https://api.example.com/v1",
|
|
160
|
+
"apiKey": "{env:MY_PROVIDER_API_KEY}"
|
|
161
|
+
},
|
|
162
|
+
"models": {
|
|
163
|
+
"my-model": {
|
|
164
|
+
"name": "My Model"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### MCP 示例(本地服务)
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"mcp": {
|
|
177
|
+
"filesystem": {
|
|
178
|
+
"type": "local",
|
|
179
|
+
"command": [
|
|
180
|
+
"npx",
|
|
181
|
+
"-y",
|
|
182
|
+
"@modelcontextprotocol/server-filesystem",
|
|
183
|
+
"."
|
|
184
|
+
],
|
|
185
|
+
"enabled": true,
|
|
186
|
+
"timeout": 30
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 项目结构
|
|
193
|
+
|
|
194
|
+
- `src/hotaru/cli/`:CLI 入口与命令实现
|
|
195
|
+
- `src/hotaru/tui/`:Textual TUI
|
|
196
|
+
- `src/hotaru/session/`:消息、会话、处理循环
|
|
197
|
+
- `src/hotaru/tool/`:内置工具与注册中心
|
|
198
|
+
- `src/hotaru/provider/`:Provider/模型抽象
|
|
199
|
+
- `src/hotaru/mcp/`:MCP 客户端与认证
|
|
200
|
+
- `src/hotaru/permission/`:权限规则与交互
|
|
201
|
+
- `src/hotaru/skill/`:Skill 发现与加载
|
|
202
|
+
|
|
203
|
+
## 开发
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# 运行测试
|
|
207
|
+
uv run pytest tests
|
|
208
|
+
|
|
209
|
+
# 构建包
|
|
210
|
+
uv build
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## 说明
|
|
214
|
+
|
|
215
|
+
- Python 版本要求:`>=3.12`
|
|
216
|
+
- 包名:`hotaru-code`
|
|
217
|
+
- 命令行入口:`hotaru`
|
|
218
|
+
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Hotaru Code
|
|
2
|
+
|
|
3
|
+
Hotaru Code 用于在终端中提供 AI 编码助手能力。
|
|
4
|
+
|
|
5
|
+
它支持 TUI、交互式 Chat 和一次性 Run 三种使用模式,并具备工具调用、权限控制、会话持久化、MCP 扩展等能力。
|
|
6
|
+
|
|
7
|
+
## 功能概览
|
|
8
|
+
|
|
9
|
+
- 多种交互方式
|
|
10
|
+
- `hotaru`:默认进入 TUI(Textual)
|
|
11
|
+
- `hotaru chat`:交互式命令行聊天
|
|
12
|
+
- `hotaru run "你的问题"`:一次性执行
|
|
13
|
+
- Agentic 工具调用循环
|
|
14
|
+
- LLM 输出可触发工具执行,结果会回注到上下文继续推理
|
|
15
|
+
- 内置工具
|
|
16
|
+
- `read`、`write`、`edit`、`bash`、`glob`、`grep`、`skill`
|
|
17
|
+
- 细粒度权限系统
|
|
18
|
+
- 对 `bash`、`edit`、`read` 等按规则 `allow/ask/deny`
|
|
19
|
+
- 支持“仅本次允许/始终允许/拒绝”交互
|
|
20
|
+
- 内置重复工具调用(doom loop)保护
|
|
21
|
+
- Provider 与模型抽象
|
|
22
|
+
- 支持 OpenAI、Anthropic 及 OpenAI-compatible 自定义服务
|
|
23
|
+
- 通过 `provider/model` 选择模型
|
|
24
|
+
- MCP (Model Context Protocol)
|
|
25
|
+
- 支持本地(stdio)和远程(HTTP/SSE)MCP 服务
|
|
26
|
+
- MCP 工具会自动并入可调用工具列表
|
|
27
|
+
- Skill 系统
|
|
28
|
+
- 支持从 `SKILL.md` 发现并加载领域技能
|
|
29
|
+
- 会话持久化
|
|
30
|
+
- 会话与消息写入本地 JSON 存储,可继续/切换历史会话
|
|
31
|
+
|
|
32
|
+
## 快速开始
|
|
33
|
+
|
|
34
|
+
### 1. 安装依赖
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv sync
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. 配置 API Key
|
|
41
|
+
|
|
42
|
+
至少配置一个可用 Provider 的密钥,例如:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# PowerShell
|
|
46
|
+
$env:OPENAI_API_KEY = "your-key"
|
|
47
|
+
|
|
48
|
+
# 或
|
|
49
|
+
$env:ANTHROPIC_API_KEY = "your-key"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. 启动
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# 默认进入 TUI
|
|
56
|
+
uv run hotaru
|
|
57
|
+
|
|
58
|
+
# 交互式 chat
|
|
59
|
+
uv run hotaru chat
|
|
60
|
+
|
|
61
|
+
# 一次性执行
|
|
62
|
+
uv run hotaru run "请分析这个仓库的结构"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 常用命令
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
hotaru --help
|
|
69
|
+
hotaru --version
|
|
70
|
+
hotaru providers # 列出可用 provider 和模型
|
|
71
|
+
hotaru agents # 列出 agent
|
|
72
|
+
hotaru sessions -n 20 # 列出最近会话
|
|
73
|
+
hotaru config --show # 展示合并后的配置
|
|
74
|
+
hotaru config --path # 展示配置目录
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `run` 子命令常用参数
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
hotaru run "修复 tests 失败" --model openai/gpt-4o-mini --agent build
|
|
81
|
+
hotaru run "总结这段日志" --json
|
|
82
|
+
hotaru run "重构这个函数" --yes
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- `--model/-m`:指定 `provider/model`
|
|
86
|
+
- `--agent/-a`:指定 agent
|
|
87
|
+
- `--session/-s` / `--continue/-c`:继续会话
|
|
88
|
+
- `--file/-f`:附加文件
|
|
89
|
+
- `--json`:输出 JSON 事件流
|
|
90
|
+
- `--yes/-y`:自动通过权限请求
|
|
91
|
+
|
|
92
|
+
## 配置说明
|
|
93
|
+
|
|
94
|
+
Hotaru 会合并多来源配置(后者覆盖前者):
|
|
95
|
+
|
|
96
|
+
1. 全局配置目录(`hotaru config --path` 可查看)
|
|
97
|
+
2. 项目目录向上查找的 `hotaru.json` / `hotaru.jsonc`
|
|
98
|
+
3. `.hotaru/hotaru.json` / `.hotaru/hotaru.jsonc`
|
|
99
|
+
4. 环境变量 `HOTARU_CONFIG_CONTENT`
|
|
100
|
+
5. 托管配置目录(最高优先级)
|
|
101
|
+
|
|
102
|
+
### 最小 `hotaru.json` 示例
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"model": "openai/gpt-4o-mini",
|
|
107
|
+
"default_agent": "build",
|
|
108
|
+
"provider": {
|
|
109
|
+
"openai": {
|
|
110
|
+
"options": {
|
|
111
|
+
"apiKey": "{env:OPENAI_API_KEY}"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"permission": {
|
|
116
|
+
"bash": "ask",
|
|
117
|
+
"edit": "ask",
|
|
118
|
+
"read": {
|
|
119
|
+
"*.env": "ask",
|
|
120
|
+
"*.env.example": "allow"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 自定义 OpenAI-compatible Provider 示例
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"provider": {
|
|
131
|
+
"my-provider": {
|
|
132
|
+
"type": "openai",
|
|
133
|
+
"name": "My Provider",
|
|
134
|
+
"options": {
|
|
135
|
+
"baseURL": "https://api.example.com/v1",
|
|
136
|
+
"apiKey": "{env:MY_PROVIDER_API_KEY}"
|
|
137
|
+
},
|
|
138
|
+
"models": {
|
|
139
|
+
"my-model": {
|
|
140
|
+
"name": "My Model"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### MCP 示例(本地服务)
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcp": {
|
|
153
|
+
"filesystem": {
|
|
154
|
+
"type": "local",
|
|
155
|
+
"command": [
|
|
156
|
+
"npx",
|
|
157
|
+
"-y",
|
|
158
|
+
"@modelcontextprotocol/server-filesystem",
|
|
159
|
+
"."
|
|
160
|
+
],
|
|
161
|
+
"enabled": true,
|
|
162
|
+
"timeout": 30
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 项目结构
|
|
169
|
+
|
|
170
|
+
- `src/hotaru/cli/`:CLI 入口与命令实现
|
|
171
|
+
- `src/hotaru/tui/`:Textual TUI
|
|
172
|
+
- `src/hotaru/session/`:消息、会话、处理循环
|
|
173
|
+
- `src/hotaru/tool/`:内置工具与注册中心
|
|
174
|
+
- `src/hotaru/provider/`:Provider/模型抽象
|
|
175
|
+
- `src/hotaru/mcp/`:MCP 客户端与认证
|
|
176
|
+
- `src/hotaru/permission/`:权限规则与交互
|
|
177
|
+
- `src/hotaru/skill/`:Skill 发现与加载
|
|
178
|
+
|
|
179
|
+
## 开发
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# 运行测试
|
|
183
|
+
uv run pytest tests
|
|
184
|
+
|
|
185
|
+
# 构建包
|
|
186
|
+
uv build
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 说明
|
|
190
|
+
|
|
191
|
+
- Python 版本要求:`>=3.12`
|
|
192
|
+
- 包名:`hotaru-code`
|
|
193
|
+
- 命令行入口:`hotaru`
|
|
194
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# TUI Migration Map (Hotaru <- OpenCode)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Track high-impact migration targets from `../opencode/packages/app/src` into `src/hotaru/tui` while keeping Textual-native architecture.
|
|
5
|
+
|
|
6
|
+
## Mapping
|
|
7
|
+
- `pages/session.tsx` -> `src/hotaru/tui/screens.py`
|
|
8
|
+
- Session lifecycle, message timeline, prompt loop.
|
|
9
|
+
- `components/prompt-input.tsx` -> `src/hotaru/tui/widgets.py`
|
|
10
|
+
- Slash completion, submission behavior, command affordances.
|
|
11
|
+
- `context/command.tsx` -> `src/hotaru/tui/commands.py` + `src/hotaru/tui/app.py`
|
|
12
|
+
- Command registry, palette invocation, availability checks.
|
|
13
|
+
- `components/status-popover.tsx` -> `src/hotaru/tui/dialogs.py` (`StatusDialog`) + `src/hotaru/tui/app.py`
|
|
14
|
+
- Runtime status (model/agent/MCP/LSP), refresh flow.
|
|
15
|
+
|
|
16
|
+
## Implemented in This Pass
|
|
17
|
+
- Session history loading for resumed sessions.
|
|
18
|
+
- Route-driven navigation for home/session entry points.
|
|
19
|
+
- Command execution unification and disabled-command reasons.
|
|
20
|
+
- Runtime status dialog and MCP/LSP refresh integration.
|
|
21
|
+
- Transcript copy/export/share command flows for the active session.
|
|
22
|
+
|
|
23
|
+
## Deferred
|
|
24
|
+
- Worktree/file-tree/review panels.
|
|
25
|
+
- Terminal tab system parity with OpenCode.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "hotaru-code"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Python translation of OpenCode - AI-powered coding assistant"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"pydantic>=2.0",
|
|
9
|
+
"python-ulid>=2.0",
|
|
10
|
+
"platformdirs>=4.0",
|
|
11
|
+
"typer>=0.9",
|
|
12
|
+
"rich>=13.0",
|
|
13
|
+
"anyio>=4.0",
|
|
14
|
+
"httpx>=0.25",
|
|
15
|
+
"aiofiles>=23.0",
|
|
16
|
+
"anthropic>=0.30",
|
|
17
|
+
"openai>=1.30",
|
|
18
|
+
"structlog>=24.0",
|
|
19
|
+
"pathspec>=0.12",
|
|
20
|
+
"pyyaml>=6.0",
|
|
21
|
+
"starlette>=0.35",
|
|
22
|
+
"uvicorn>=0.27",
|
|
23
|
+
"textual>=0.50",
|
|
24
|
+
"mcp>=1.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
hotaru = "hotaru.cli.main:app"
|
|
29
|
+
|
|
30
|
+
[build-system]
|
|
31
|
+
requires = ["hatchling"]
|
|
32
|
+
build-backend = "hatchling.build"
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["src/hotaru"]
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=9.0.2",
|
|
40
|
+
]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Hotaru Code - AI-powered coding assistant.
|
|
2
|
+
|
|
3
|
+
A Python translation of OpenCode, providing AI agent capabilities
|
|
4
|
+
for software development tasks.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
# Lazy imports to avoid circular dependencies
|
|
10
|
+
def __getattr__(name: str):
|
|
11
|
+
"""Lazy import module components."""
|
|
12
|
+
if name in ("GlobalPath", "Identifier", "Bus", "BusEvent", "Context", "Log"):
|
|
13
|
+
from . import core
|
|
14
|
+
return getattr(core, name)
|
|
15
|
+
if name in ("Project", "Instance", "State"):
|
|
16
|
+
from . import project
|
|
17
|
+
return getattr(project, name)
|
|
18
|
+
if name in ("Provider", "ModelsDev"):
|
|
19
|
+
from . import provider
|
|
20
|
+
return getattr(provider, name)
|
|
21
|
+
if name in ("Agent", "AgentInfo"):
|
|
22
|
+
from . import agent
|
|
23
|
+
return getattr(agent, name)
|
|
24
|
+
if name in ("Session", "Message", "MessageInfo"):
|
|
25
|
+
from . import session
|
|
26
|
+
return getattr(session, name)
|
|
27
|
+
if name == "Permission":
|
|
28
|
+
from . import permission
|
|
29
|
+
return permission.Permission
|
|
30
|
+
if name in ("Tool", "ToolContext", "ToolResult"):
|
|
31
|
+
from . import tool
|
|
32
|
+
return getattr(tool, name)
|
|
33
|
+
if name in ("Skill",):
|
|
34
|
+
from . import skill
|
|
35
|
+
return getattr(skill, name)
|
|
36
|
+
if name in ("Server", "ServerInfo"):
|
|
37
|
+
from . import server
|
|
38
|
+
return getattr(server, name)
|
|
39
|
+
if name in ("MCP", "MCPStatus", "MCPResource"):
|
|
40
|
+
from . import mcp
|
|
41
|
+
return getattr(mcp, name)
|
|
42
|
+
if name in ("LSP", "LSPStatus"):
|
|
43
|
+
from . import lsp
|
|
44
|
+
return getattr(lsp, name)
|
|
45
|
+
if name in ("TuiApp", "run_tui", "TuiEvent"):
|
|
46
|
+
from . import tui
|
|
47
|
+
return getattr(tui, name)
|
|
48
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__all__ = [
|
|
52
|
+
# Version
|
|
53
|
+
"__version__",
|
|
54
|
+
# Core
|
|
55
|
+
"GlobalPath",
|
|
56
|
+
"Identifier",
|
|
57
|
+
"Bus",
|
|
58
|
+
"BusEvent",
|
|
59
|
+
"Context",
|
|
60
|
+
"Log",
|
|
61
|
+
# Project
|
|
62
|
+
"Project",
|
|
63
|
+
"Instance",
|
|
64
|
+
"State",
|
|
65
|
+
# Provider
|
|
66
|
+
"Provider",
|
|
67
|
+
"ModelsDev",
|
|
68
|
+
# Agent
|
|
69
|
+
"Agent",
|
|
70
|
+
"AgentInfo",
|
|
71
|
+
# Session
|
|
72
|
+
"Session",
|
|
73
|
+
"Message",
|
|
74
|
+
"MessageInfo",
|
|
75
|
+
# Permission
|
|
76
|
+
"Permission",
|
|
77
|
+
# Tool
|
|
78
|
+
"Tool",
|
|
79
|
+
"ToolContext",
|
|
80
|
+
"ToolResult",
|
|
81
|
+
# Skill
|
|
82
|
+
"Skill",
|
|
83
|
+
# Server
|
|
84
|
+
"Server",
|
|
85
|
+
"ServerInfo",
|
|
86
|
+
# MCP
|
|
87
|
+
"MCP",
|
|
88
|
+
"MCPStatus",
|
|
89
|
+
"MCPResource",
|
|
90
|
+
# LSP
|
|
91
|
+
"LSP",
|
|
92
|
+
"LSPStatus",
|
|
93
|
+
# TUI
|
|
94
|
+
"TuiApp",
|
|
95
|
+
"run_tui",
|
|
96
|
+
"TuiEvent",
|
|
97
|
+
]
|