nonebot-plugin-codex 0.1.1__tar.gz → 0.1.2__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.
- nonebot_plugin_codex-0.1.2/PKG-INFO +246 -0
- nonebot_plugin_codex-0.1.2/README.md +233 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/pyproject.toml +2 -1
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/src/nonebot_plugin_codex/__init__.py +29 -16
- nonebot_plugin_codex-0.1.2/src/nonebot_plugin_codex/config.py +15 -0
- nonebot_plugin_codex-0.1.2/src/nonebot_plugin_codex/runtime.py +21 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/src/nonebot_plugin_codex/service.py +525 -52
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/src/nonebot_plugin_codex/telegram.py +176 -54
- nonebot_plugin_codex-0.1.2/src/nonebot_plugin_codex/telegram_rendering.py +114 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/tests/conftest.py +28 -0
- nonebot_plugin_codex-0.1.2/tests/test_config.py +53 -0
- nonebot_plugin_codex-0.1.2/tests/test_plugin_meta.py +32 -0
- nonebot_plugin_codex-0.1.2/tests/test_release_notes.py +52 -0
- nonebot_plugin_codex-0.1.2/tests/test_runtime.py +25 -0
- nonebot_plugin_codex-0.1.2/tests/test_service.py +491 -0
- nonebot_plugin_codex-0.1.2/tests/test_telegram_handlers.py +596 -0
- nonebot_plugin_codex-0.1.2/tests/test_telegram_rendering.py +56 -0
- nonebot_plugin_codex-0.1.1/PKG-INFO +0 -196
- nonebot_plugin_codex-0.1.1/README.md +0 -184
- nonebot_plugin_codex-0.1.1/src/nonebot_plugin_codex/config.py +0 -84
- nonebot_plugin_codex-0.1.1/tests/test_config.py +0 -33
- nonebot_plugin_codex-0.1.1/tests/test_plugin_meta.py +0 -8
- nonebot_plugin_codex-0.1.1/tests/test_service.py +0 -164
- nonebot_plugin_codex-0.1.1/tests/test_telegram_handlers.py +0 -246
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/LICENSE +0 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/src/nonebot_plugin_codex/native_client.py +0 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/tests/__init__.py +0 -0
- {nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/tests/test_native_client.py +0 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: nonebot-plugin-codex
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Telegram bridge plugin for driving Codex from NoneBot
|
|
5
|
+
Author-Email: ttiee <469784630@qq.com>
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: nonebot2>=2.4.4
|
|
9
|
+
Requires-Dist: nonebot-adapter-telegram>=0.1.0b20
|
|
10
|
+
Requires-Dist: nonebot-plugin-localstore>=0.7.4
|
|
11
|
+
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
<!-- markdownlint-disable MD033 MD041 -->
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://nonebot.dev/"><img src="https://nonebot.dev/logo.png" width="200" height="200" alt="nonebot"></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<div align="center">
|
|
20
|
+
|
|
21
|
+
# nonebot-plugin-codex
|
|
22
|
+
|
|
23
|
+
_✨ 在 Telegram 里驱动 Codex CLI 的 NoneBot 插件 ✨_
|
|
24
|
+
<!-- **把本机 Codex CLI 接入 Telegram 的 NoneBot 插件** -->
|
|
25
|
+
|
|
26
|
+
让你直接在 Telegram 里发起 Codex 会话、续聊上下文、切换工作目录、浏览历史会话,把本地开发工作流搬进聊天窗口。
|
|
27
|
+
|
|
28
|
+
<p>
|
|
29
|
+
<a href="https://github.com/ttiee/nonebot-plugin-codex/blob/main/LICENSE">
|
|
30
|
+
<img src="https://img.shields.io/github/license/ttiee/nonebot-plugin-codex.svg" alt="license">
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://pypi.org/project/nonebot-plugin-codex/">
|
|
33
|
+
<img src="https://img.shields.io/pypi/v/nonebot-plugin-codex.svg" alt="pypi">
|
|
34
|
+
</a>
|
|
35
|
+
<img src="https://img.shields.io/badge/python-3.10+-3776AB.svg" alt="python">
|
|
36
|
+
<img src="https://img.shields.io/badge/NoneBot-2.4.4+-00A7E1.svg" alt="nonebot">
|
|
37
|
+
<img src="https://img.shields.io/badge/adapter-Telegram-26A5E4.svg" alt="telegram">
|
|
38
|
+
<img src="https://img.shields.io/github/actions/workflow/status/ttiee/nonebot-plugin-codex/test.yml?branch=main&label=test" alt="test">
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
## 项目介绍
|
|
44
|
+
|
|
45
|
+
`nonebot-plugin-codex` 是一个面向 Telegram 场景的 NoneBot 插件,用来把本机 `codex` CLI 暴露为可对话、可续聊、可管理工作目录的聊天式开发助手。
|
|
46
|
+
|
|
47
|
+
它不是简单地把命令行输出转发到聊天窗口,而是围绕实际使用场景补齐了会话管理与状态管理能力:
|
|
48
|
+
|
|
49
|
+
- 同一聊天内持续续聊,保留上下文
|
|
50
|
+
- 支持 `resume` 与 `exec` 两种运行模式
|
|
51
|
+
- 每个聊天独立维护模型、推理强度、权限模式和工作目录
|
|
52
|
+
- 可视化浏览目录与历史会话
|
|
53
|
+
- 插件自身状态使用 localstore 管理,本地 Codex 历史读取 `~/.codex/*`
|
|
54
|
+
|
|
55
|
+
如果你已经习惯在本机使用 Codex,又希望通过 Telegram 远程发起编码、排查、审阅或文档整理任务,这个插件就是为这个场景设计的。
|
|
56
|
+
|
|
57
|
+
## 核心特性
|
|
58
|
+
|
|
59
|
+
- **聊天即入口**:`/codex` 连接后,普通文本消息可直接续聊当前会话。
|
|
60
|
+
- **双模式工作流**:持续对话用 `resume`,一次性任务用 `exec`。
|
|
61
|
+
- **细粒度会话隔离**:不同聊天各自持有模型、权限、工作目录与历史绑定。
|
|
62
|
+
- **目录浏览能力**:支持在 Telegram 内切换目录、设定 Home、查看隐藏目录。
|
|
63
|
+
- **历史会话恢复**:可浏览 native 与 exec 历史,并尽量恢复原始工作目录。
|
|
64
|
+
- **兼容迁移**:可以沿用旧配置文件与 Codex 历史目录,减少迁移成本。
|
|
65
|
+
|
|
66
|
+
## 快速开始
|
|
67
|
+
|
|
68
|
+
### 1. 准备运行环境
|
|
69
|
+
|
|
70
|
+
确保满足以下条件:
|
|
71
|
+
|
|
72
|
+
- Python `3.10+`
|
|
73
|
+
- NoneBot `2.4.4+`
|
|
74
|
+
- 已安装 `nonebot-adapter-telegram`
|
|
75
|
+
- 目标主机上已安装并可直接调用 `codex`
|
|
76
|
+
|
|
77
|
+
### 2. 安装插件
|
|
78
|
+
|
|
79
|
+
在 NoneBot 项目根目录中执行其一:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
nb plugin install nonebot-plugin-codex
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
或:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install nonebot-plugin-codex
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
或:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pdm add nonebot-plugin-codex
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. 启用插件
|
|
98
|
+
|
|
99
|
+
在 `pyproject.toml` 中启用:
|
|
100
|
+
|
|
101
|
+
```toml
|
|
102
|
+
[tool.nonebot]
|
|
103
|
+
plugins = ["nonebot_plugin_codex"]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 4. 写入最小可用配置
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[tool.nonebot]
|
|
110
|
+
plugins = ["nonebot_plugin_codex"]
|
|
111
|
+
|
|
112
|
+
[tool.nonebot.plugin_config]
|
|
113
|
+
codex_binary = "codex"
|
|
114
|
+
codex_workdir = "/home/yourname"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
如果你的 `codex` 不在 `PATH` 中,把 `codex_binary` 改成绝对路径即可。
|
|
118
|
+
|
|
119
|
+
## 使用方式
|
|
120
|
+
|
|
121
|
+
一个典型工作流通常是这样的:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
/codex 帮我检查当前仓库为什么测试失败
|
|
125
|
+
/cd /home/yourname/projects/demo
|
|
126
|
+
/permission danger
|
|
127
|
+
/mode resume
|
|
128
|
+
然后继续直接发送普通文本消息续聊
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
你也可以把一次性任务交给 `exec` 模式:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
/exec 用三点总结这个仓库 README 还缺什么
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 配置说明
|
|
138
|
+
|
|
139
|
+
完整配置如下,配置名与当前实现保持一致:
|
|
140
|
+
|
|
141
|
+
```toml
|
|
142
|
+
[tool.nonebot]
|
|
143
|
+
plugins = ["nonebot_plugin_codex"]
|
|
144
|
+
|
|
145
|
+
[tool.nonebot.plugin_config]
|
|
146
|
+
# Codex 可执行文件名或绝对路径,默认直接调用 PATH 中的 `codex`
|
|
147
|
+
codex_binary = "codex"
|
|
148
|
+
|
|
149
|
+
# 默认工作目录;新会话、目录浏览器 Home 入口、相对路径解析都基于它
|
|
150
|
+
codex_workdir = "/home/yourname"
|
|
151
|
+
|
|
152
|
+
# `/stop` 或重置会话时,等待 Codex 子进程退出的超时时间,单位秒
|
|
153
|
+
codex_kill_timeout = 5.0
|
|
154
|
+
|
|
155
|
+
# 运行中在 Telegram 中保留的进度消息条数
|
|
156
|
+
codex_progress_history = 6
|
|
157
|
+
|
|
158
|
+
# 运行失败时最多保留多少条诊断输出
|
|
159
|
+
codex_diagnostic_history = 20
|
|
160
|
+
|
|
161
|
+
# 单条 Telegram 消息的分片长度,过长回复会自动拆分
|
|
162
|
+
codex_chunk_size = 3500
|
|
163
|
+
|
|
164
|
+
# 读取 Codex stdout / stderr 的缓冲区大小
|
|
165
|
+
codex_stream_read_limit = 1048576
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
几个最关键的配置项:
|
|
170
|
+
|
|
171
|
+
- `codex_binary`:如果宿主机不是直接执行 `codex`,改成实际绝对路径。
|
|
172
|
+
- `codex_workdir`:默认工作目录,也是 `/cd` 相对路径解析与目录浏览器 Home 的基准。
|
|
173
|
+
- 其余项分别控制停止超时、进度保留条数、诊断输出条数、Telegram 分片长度和流读取上限。
|
|
174
|
+
- 插件自己的配置数据由 `nonebot-plugin-localstore` 自动管理。
|
|
175
|
+
- 模型缓存、Codex CLI 配置和历史会话目录默认读取 `~/.codex/*`,属于插件内部实现路径。
|
|
176
|
+
|
|
177
|
+
## 命令一览
|
|
178
|
+
|
|
179
|
+
| 命令 | 说明 |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| `/codex [prompt]` | 连接 Codex,会附带发送首条 prompt |
|
|
182
|
+
| `/mode [resume\|exec]` | 查看或切换默认模式 |
|
|
183
|
+
| `/exec <prompt>` | 以一次性 `exec` 模式执行任务 |
|
|
184
|
+
| `/new` | 清空当前聊天绑定的会话 |
|
|
185
|
+
| `/stop` | 断开当前聊天的 Codex 会话 |
|
|
186
|
+
| `/models` | 查看可用模型 |
|
|
187
|
+
| `/model [slug]` | 查看或切换模型 |
|
|
188
|
+
| `/effort [high\|xhigh]` | 查看或切换推理强度 |
|
|
189
|
+
| `/permission [safe\|danger]` | 查看或切换权限模式 |
|
|
190
|
+
| `/pwd` | 查看当前工作目录与当前设置 |
|
|
191
|
+
| `/cd [path]` | 直接切换目录;不带参数时打开目录浏览器 |
|
|
192
|
+
| `/home` | 将工作目录重置到 Home |
|
|
193
|
+
| `/sessions` | 打开历史会话浏览器 |
|
|
194
|
+
|
|
195
|
+
## 模式说明
|
|
196
|
+
|
|
197
|
+
### `resume`
|
|
198
|
+
|
|
199
|
+
适合需要持续上下文的对话式场景:
|
|
200
|
+
|
|
201
|
+
- 优先使用 `codex app-server`
|
|
202
|
+
- 为同一聊天维持 native thread
|
|
203
|
+
- 更适合连续编码、持续追问和多轮调试
|
|
204
|
+
|
|
205
|
+
### `exec`
|
|
206
|
+
|
|
207
|
+
适合一次性任务或脚本式调用:
|
|
208
|
+
|
|
209
|
+
- 使用 `codex exec --json`
|
|
210
|
+
- 支持恢复已有 exec thread
|
|
211
|
+
- 恢复失败时会自动新开会话并提示
|
|
212
|
+
|
|
213
|
+
## 目录与历史会话
|
|
214
|
+
|
|
215
|
+
- `/cd` 可打开目录浏览器,逐级进入目录、切换 Home、显示隐藏目录,并把当前浏览目录设置为工作目录。
|
|
216
|
+
- `/sessions` 会列出 native 与 exec 历史会话,便于恢复此前任务。
|
|
217
|
+
- 历史会话恢复时会尝试切回原始工作目录;如果原目录不存在,会保留当前目录并给出提示。
|
|
218
|
+
|
|
219
|
+
## 发布说明
|
|
220
|
+
|
|
221
|
+
仓库已包含基础发布流程:
|
|
222
|
+
|
|
223
|
+
- `test.yml`:安装依赖并运行测试
|
|
224
|
+
- `release.yml`:在推送 `v*` 标签时执行 `pdm publish`、生成两个版本间的结构化发布说明,并上传构建产物
|
|
225
|
+
|
|
226
|
+
Release 说明会按 tag 区间内的 Conventional Commits 自动分组,例如 `feat`、`fix`、`docs`、`chore` 等,并附上 compare 链接,避免每次手工整理改动列表。
|
|
227
|
+
|
|
228
|
+
如果你要启用 PyPI Trusted Publishing,请在 PyPI 项目设置中添加以下信息:
|
|
229
|
+
|
|
230
|
+
- Project name: `nonebot-plugin-codex`
|
|
231
|
+
- Owner: `ttiee`
|
|
232
|
+
- Repository name: `nonebot-plugin-codex`
|
|
233
|
+
- Workflow name: `release.yml`
|
|
234
|
+
|
|
235
|
+
## 本地开发
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
pdm sync -G:all
|
|
239
|
+
pdm run pytest
|
|
240
|
+
pdm run ruff check .
|
|
241
|
+
pdm build
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
本项目使用 [GPL-3.0-or-later](https://github.com/ttiee/nonebot-plugin-codex/blob/main/LICENSE) 许可证。
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD033 MD041 -->
|
|
2
|
+
<p align="center">
|
|
3
|
+
<a href="https://nonebot.dev/"><img src="https://nonebot.dev/logo.png" width="200" height="200" alt="nonebot"></a>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<div align="center">
|
|
7
|
+
|
|
8
|
+
# nonebot-plugin-codex
|
|
9
|
+
|
|
10
|
+
_✨ 在 Telegram 里驱动 Codex CLI 的 NoneBot 插件 ✨_
|
|
11
|
+
<!-- **把本机 Codex CLI 接入 Telegram 的 NoneBot 插件** -->
|
|
12
|
+
|
|
13
|
+
让你直接在 Telegram 里发起 Codex 会话、续聊上下文、切换工作目录、浏览历史会话,把本地开发工作流搬进聊天窗口。
|
|
14
|
+
|
|
15
|
+
<p>
|
|
16
|
+
<a href="https://github.com/ttiee/nonebot-plugin-codex/blob/main/LICENSE">
|
|
17
|
+
<img src="https://img.shields.io/github/license/ttiee/nonebot-plugin-codex.svg" alt="license">
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://pypi.org/project/nonebot-plugin-codex/">
|
|
20
|
+
<img src="https://img.shields.io/pypi/v/nonebot-plugin-codex.svg" alt="pypi">
|
|
21
|
+
</a>
|
|
22
|
+
<img src="https://img.shields.io/badge/python-3.10+-3776AB.svg" alt="python">
|
|
23
|
+
<img src="https://img.shields.io/badge/NoneBot-2.4.4+-00A7E1.svg" alt="nonebot">
|
|
24
|
+
<img src="https://img.shields.io/badge/adapter-Telegram-26A5E4.svg" alt="telegram">
|
|
25
|
+
<img src="https://img.shields.io/github/actions/workflow/status/ttiee/nonebot-plugin-codex/test.yml?branch=main&label=test" alt="test">
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 项目介绍
|
|
31
|
+
|
|
32
|
+
`nonebot-plugin-codex` 是一个面向 Telegram 场景的 NoneBot 插件,用来把本机 `codex` CLI 暴露为可对话、可续聊、可管理工作目录的聊天式开发助手。
|
|
33
|
+
|
|
34
|
+
它不是简单地把命令行输出转发到聊天窗口,而是围绕实际使用场景补齐了会话管理与状态管理能力:
|
|
35
|
+
|
|
36
|
+
- 同一聊天内持续续聊,保留上下文
|
|
37
|
+
- 支持 `resume` 与 `exec` 两种运行模式
|
|
38
|
+
- 每个聊天独立维护模型、推理强度、权限模式和工作目录
|
|
39
|
+
- 可视化浏览目录与历史会话
|
|
40
|
+
- 插件自身状态使用 localstore 管理,本地 Codex 历史读取 `~/.codex/*`
|
|
41
|
+
|
|
42
|
+
如果你已经习惯在本机使用 Codex,又希望通过 Telegram 远程发起编码、排查、审阅或文档整理任务,这个插件就是为这个场景设计的。
|
|
43
|
+
|
|
44
|
+
## 核心特性
|
|
45
|
+
|
|
46
|
+
- **聊天即入口**:`/codex` 连接后,普通文本消息可直接续聊当前会话。
|
|
47
|
+
- **双模式工作流**:持续对话用 `resume`,一次性任务用 `exec`。
|
|
48
|
+
- **细粒度会话隔离**:不同聊天各自持有模型、权限、工作目录与历史绑定。
|
|
49
|
+
- **目录浏览能力**:支持在 Telegram 内切换目录、设定 Home、查看隐藏目录。
|
|
50
|
+
- **历史会话恢复**:可浏览 native 与 exec 历史,并尽量恢复原始工作目录。
|
|
51
|
+
- **兼容迁移**:可以沿用旧配置文件与 Codex 历史目录,减少迁移成本。
|
|
52
|
+
|
|
53
|
+
## 快速开始
|
|
54
|
+
|
|
55
|
+
### 1. 准备运行环境
|
|
56
|
+
|
|
57
|
+
确保满足以下条件:
|
|
58
|
+
|
|
59
|
+
- Python `3.10+`
|
|
60
|
+
- NoneBot `2.4.4+`
|
|
61
|
+
- 已安装 `nonebot-adapter-telegram`
|
|
62
|
+
- 目标主机上已安装并可直接调用 `codex`
|
|
63
|
+
|
|
64
|
+
### 2. 安装插件
|
|
65
|
+
|
|
66
|
+
在 NoneBot 项目根目录中执行其一:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
nb plugin install nonebot-plugin-codex
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
或:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install nonebot-plugin-codex
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
或:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pdm add nonebot-plugin-codex
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. 启用插件
|
|
85
|
+
|
|
86
|
+
在 `pyproject.toml` 中启用:
|
|
87
|
+
|
|
88
|
+
```toml
|
|
89
|
+
[tool.nonebot]
|
|
90
|
+
plugins = ["nonebot_plugin_codex"]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 4. 写入最小可用配置
|
|
94
|
+
|
|
95
|
+
```toml
|
|
96
|
+
[tool.nonebot]
|
|
97
|
+
plugins = ["nonebot_plugin_codex"]
|
|
98
|
+
|
|
99
|
+
[tool.nonebot.plugin_config]
|
|
100
|
+
codex_binary = "codex"
|
|
101
|
+
codex_workdir = "/home/yourname"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
如果你的 `codex` 不在 `PATH` 中,把 `codex_binary` 改成绝对路径即可。
|
|
105
|
+
|
|
106
|
+
## 使用方式
|
|
107
|
+
|
|
108
|
+
一个典型工作流通常是这样的:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
/codex 帮我检查当前仓库为什么测试失败
|
|
112
|
+
/cd /home/yourname/projects/demo
|
|
113
|
+
/permission danger
|
|
114
|
+
/mode resume
|
|
115
|
+
然后继续直接发送普通文本消息续聊
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
你也可以把一次性任务交给 `exec` 模式:
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
/exec 用三点总结这个仓库 README 还缺什么
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 配置说明
|
|
125
|
+
|
|
126
|
+
完整配置如下,配置名与当前实现保持一致:
|
|
127
|
+
|
|
128
|
+
```toml
|
|
129
|
+
[tool.nonebot]
|
|
130
|
+
plugins = ["nonebot_plugin_codex"]
|
|
131
|
+
|
|
132
|
+
[tool.nonebot.plugin_config]
|
|
133
|
+
# Codex 可执行文件名或绝对路径,默认直接调用 PATH 中的 `codex`
|
|
134
|
+
codex_binary = "codex"
|
|
135
|
+
|
|
136
|
+
# 默认工作目录;新会话、目录浏览器 Home 入口、相对路径解析都基于它
|
|
137
|
+
codex_workdir = "/home/yourname"
|
|
138
|
+
|
|
139
|
+
# `/stop` 或重置会话时,等待 Codex 子进程退出的超时时间,单位秒
|
|
140
|
+
codex_kill_timeout = 5.0
|
|
141
|
+
|
|
142
|
+
# 运行中在 Telegram 中保留的进度消息条数
|
|
143
|
+
codex_progress_history = 6
|
|
144
|
+
|
|
145
|
+
# 运行失败时最多保留多少条诊断输出
|
|
146
|
+
codex_diagnostic_history = 20
|
|
147
|
+
|
|
148
|
+
# 单条 Telegram 消息的分片长度,过长回复会自动拆分
|
|
149
|
+
codex_chunk_size = 3500
|
|
150
|
+
|
|
151
|
+
# 读取 Codex stdout / stderr 的缓冲区大小
|
|
152
|
+
codex_stream_read_limit = 1048576
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
几个最关键的配置项:
|
|
157
|
+
|
|
158
|
+
- `codex_binary`:如果宿主机不是直接执行 `codex`,改成实际绝对路径。
|
|
159
|
+
- `codex_workdir`:默认工作目录,也是 `/cd` 相对路径解析与目录浏览器 Home 的基准。
|
|
160
|
+
- 其余项分别控制停止超时、进度保留条数、诊断输出条数、Telegram 分片长度和流读取上限。
|
|
161
|
+
- 插件自己的配置数据由 `nonebot-plugin-localstore` 自动管理。
|
|
162
|
+
- 模型缓存、Codex CLI 配置和历史会话目录默认读取 `~/.codex/*`,属于插件内部实现路径。
|
|
163
|
+
|
|
164
|
+
## 命令一览
|
|
165
|
+
|
|
166
|
+
| 命令 | 说明 |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `/codex [prompt]` | 连接 Codex,会附带发送首条 prompt |
|
|
169
|
+
| `/mode [resume\|exec]` | 查看或切换默认模式 |
|
|
170
|
+
| `/exec <prompt>` | 以一次性 `exec` 模式执行任务 |
|
|
171
|
+
| `/new` | 清空当前聊天绑定的会话 |
|
|
172
|
+
| `/stop` | 断开当前聊天的 Codex 会话 |
|
|
173
|
+
| `/models` | 查看可用模型 |
|
|
174
|
+
| `/model [slug]` | 查看或切换模型 |
|
|
175
|
+
| `/effort [high\|xhigh]` | 查看或切换推理强度 |
|
|
176
|
+
| `/permission [safe\|danger]` | 查看或切换权限模式 |
|
|
177
|
+
| `/pwd` | 查看当前工作目录与当前设置 |
|
|
178
|
+
| `/cd [path]` | 直接切换目录;不带参数时打开目录浏览器 |
|
|
179
|
+
| `/home` | 将工作目录重置到 Home |
|
|
180
|
+
| `/sessions` | 打开历史会话浏览器 |
|
|
181
|
+
|
|
182
|
+
## 模式说明
|
|
183
|
+
|
|
184
|
+
### `resume`
|
|
185
|
+
|
|
186
|
+
适合需要持续上下文的对话式场景:
|
|
187
|
+
|
|
188
|
+
- 优先使用 `codex app-server`
|
|
189
|
+
- 为同一聊天维持 native thread
|
|
190
|
+
- 更适合连续编码、持续追问和多轮调试
|
|
191
|
+
|
|
192
|
+
### `exec`
|
|
193
|
+
|
|
194
|
+
适合一次性任务或脚本式调用:
|
|
195
|
+
|
|
196
|
+
- 使用 `codex exec --json`
|
|
197
|
+
- 支持恢复已有 exec thread
|
|
198
|
+
- 恢复失败时会自动新开会话并提示
|
|
199
|
+
|
|
200
|
+
## 目录与历史会话
|
|
201
|
+
|
|
202
|
+
- `/cd` 可打开目录浏览器,逐级进入目录、切换 Home、显示隐藏目录,并把当前浏览目录设置为工作目录。
|
|
203
|
+
- `/sessions` 会列出 native 与 exec 历史会话,便于恢复此前任务。
|
|
204
|
+
- 历史会话恢复时会尝试切回原始工作目录;如果原目录不存在,会保留当前目录并给出提示。
|
|
205
|
+
|
|
206
|
+
## 发布说明
|
|
207
|
+
|
|
208
|
+
仓库已包含基础发布流程:
|
|
209
|
+
|
|
210
|
+
- `test.yml`:安装依赖并运行测试
|
|
211
|
+
- `release.yml`:在推送 `v*` 标签时执行 `pdm publish`、生成两个版本间的结构化发布说明,并上传构建产物
|
|
212
|
+
|
|
213
|
+
Release 说明会按 tag 区间内的 Conventional Commits 自动分组,例如 `feat`、`fix`、`docs`、`chore` 等,并附上 compare 链接,避免每次手工整理改动列表。
|
|
214
|
+
|
|
215
|
+
如果你要启用 PyPI Trusted Publishing,请在 PyPI 项目设置中添加以下信息:
|
|
216
|
+
|
|
217
|
+
- Project name: `nonebot-plugin-codex`
|
|
218
|
+
- Owner: `ttiee`
|
|
219
|
+
- Repository name: `nonebot-plugin-codex`
|
|
220
|
+
- Workflow name: `release.yml`
|
|
221
|
+
|
|
222
|
+
## 本地开发
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pdm sync -G:all
|
|
226
|
+
pdm run pytest
|
|
227
|
+
pdm run ruff check .
|
|
228
|
+
pdm build
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
本项目使用 [GPL-3.0-or-later](https://github.com/ttiee/nonebot-plugin-codex/blob/main/LICENSE) 许可证。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nonebot-plugin-codex"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "Telegram bridge plugin for driving Codex from NoneBot"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "ttiee", email = "469784630@qq.com" },
|
|
@@ -8,6 +8,7 @@ authors = [
|
|
|
8
8
|
dependencies = [
|
|
9
9
|
"nonebot2>=2.4.4",
|
|
10
10
|
"nonebot-adapter-telegram>=0.1.0b20",
|
|
11
|
+
"nonebot-plugin-localstore>=0.7.4",
|
|
11
12
|
"tomli>=2.0.1; python_version < '3.11'",
|
|
12
13
|
]
|
|
13
14
|
requires-python = ">=3.10"
|
{nonebot_plugin_codex-0.1.1 → nonebot_plugin_codex-0.1.2}/src/nonebot_plugin_codex/__init__.py
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from nonebot import get_plugin_config, on_command, on_message, on_type, require
|
|
4
6
|
from nonebot.plugin import PluginMetadata
|
|
5
7
|
from nonebot.params import CommandArg
|
|
6
8
|
from nonebot.adapters.telegram import Bot
|
|
@@ -10,7 +12,8 @@ from nonebot.adapters.telegram.event import MessageEvent, CallbackQueryEvent
|
|
|
10
12
|
from .config import Config
|
|
11
13
|
from .telegram import TelegramHandlers
|
|
12
14
|
from .native_client import NativeCodexClient
|
|
13
|
-
from .
|
|
15
|
+
from .runtime import build_service_settings
|
|
16
|
+
from .service import CodexBridgeService
|
|
14
17
|
|
|
15
18
|
__plugin_meta__ = PluginMetadata(
|
|
16
19
|
name="Codex",
|
|
@@ -32,21 +35,21 @@ except ValueError:
|
|
|
32
35
|
plugin_config = Config()
|
|
33
36
|
_runtime_ready = False
|
|
34
37
|
|
|
38
|
+
|
|
39
|
+
def _get_plugin_data_dir() -> Path:
|
|
40
|
+
try:
|
|
41
|
+
require("nonebot_plugin_localstore")
|
|
42
|
+
import nonebot_plugin_localstore as store
|
|
43
|
+
|
|
44
|
+
return store.get_plugin_data_dir()
|
|
45
|
+
except Exception:
|
|
46
|
+
return Path("data") / "nonebot_plugin_codex"
|
|
47
|
+
|
|
48
|
+
|
|
35
49
|
service = CodexBridgeService(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
kill_timeout=plugin_config.codex_kill_timeout,
|
|
40
|
-
progress_history=plugin_config.codex_progress_history,
|
|
41
|
-
diagnostic_history=plugin_config.codex_diagnostic_history,
|
|
42
|
-
chunk_size=plugin_config.codex_chunk_size,
|
|
43
|
-
stream_read_limit=plugin_config.codex_stream_read_limit,
|
|
44
|
-
models_cache_path=plugin_config.codex_models_cache_path,
|
|
45
|
-
codex_config_path=plugin_config.codex_codex_config_path,
|
|
46
|
-
preferences_path=plugin_config.codex_preferences_path,
|
|
47
|
-
session_index_path=plugin_config.codex_session_index_path,
|
|
48
|
-
sessions_dir=plugin_config.codex_sessions_dir,
|
|
49
|
-
archived_sessions_dir=plugin_config.codex_archived_sessions_dir,
|
|
50
|
+
build_service_settings(
|
|
51
|
+
plugin_config,
|
|
52
|
+
plugin_data_dir=_get_plugin_data_dir(),
|
|
50
53
|
),
|
|
51
54
|
native_client=NativeCodexClient(
|
|
52
55
|
binary=plugin_config.codex_binary,
|
|
@@ -82,6 +85,12 @@ if _runtime_ready:
|
|
|
82
85
|
block=True,
|
|
83
86
|
rule=handlers.is_history_callback,
|
|
84
87
|
)
|
|
88
|
+
setting_callback = on_type(
|
|
89
|
+
CallbackQueryEvent,
|
|
90
|
+
priority=10,
|
|
91
|
+
block=True,
|
|
92
|
+
rule=handlers.is_setting_callback,
|
|
93
|
+
)
|
|
85
94
|
|
|
86
95
|
@codex_cmd.handle()
|
|
87
96
|
async def _handle_codex(
|
|
@@ -159,6 +168,10 @@ if _runtime_ready:
|
|
|
159
168
|
async def _handle_history_callback(bot: Bot, event: CallbackQueryEvent) -> None:
|
|
160
169
|
await handlers.handle_history_callback(bot, event)
|
|
161
170
|
|
|
171
|
+
@setting_callback.handle()
|
|
172
|
+
async def _handle_setting_callback(bot: Bot, event: CallbackQueryEvent) -> None:
|
|
173
|
+
await handlers.handle_setting_callback(bot, event)
|
|
174
|
+
|
|
162
175
|
@follow_up.handle()
|
|
163
176
|
async def _handle_follow_up(bot: Bot, event: MessageEvent) -> None:
|
|
164
177
|
await handlers.handle_follow_up(bot, event)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Config(BaseModel):
|
|
9
|
+
codex_binary: str = "codex"
|
|
10
|
+
codex_workdir: Path = Field(default_factory=Path.home)
|
|
11
|
+
codex_kill_timeout: float = 5.0
|
|
12
|
+
codex_progress_history: int = 6
|
|
13
|
+
codex_diagnostic_history: int = 20
|
|
14
|
+
codex_chunk_size: int = 3500
|
|
15
|
+
codex_stream_read_limit: int = 1024 * 1024
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .config import Config
|
|
6
|
+
from .service import CodexBridgeSettings
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_service_settings(
|
|
10
|
+
plugin_config: Config, *, plugin_data_dir: Path
|
|
11
|
+
) -> CodexBridgeSettings:
|
|
12
|
+
return CodexBridgeSettings(
|
|
13
|
+
binary=plugin_config.codex_binary,
|
|
14
|
+
workdir=str(plugin_config.codex_workdir),
|
|
15
|
+
kill_timeout=plugin_config.codex_kill_timeout,
|
|
16
|
+
progress_history=plugin_config.codex_progress_history,
|
|
17
|
+
diagnostic_history=plugin_config.codex_diagnostic_history,
|
|
18
|
+
chunk_size=plugin_config.codex_chunk_size,
|
|
19
|
+
stream_read_limit=plugin_config.codex_stream_read_limit,
|
|
20
|
+
preferences_path=plugin_data_dir / "preferences.json",
|
|
21
|
+
)
|