yee88 0.4.0__py3-none-any.whl → 0.6.1__py3-none-any.whl
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.
- yee88/__init__.py +1 -1
- yee88/cli/__init__.py +4 -0
- yee88/cli/cron.py +214 -0
- yee88/cli/reload.py +140 -0
- yee88/cli/run.py +7 -0
- yee88/cron/__init__.py +5 -0
- yee88/cron/manager.py +140 -0
- yee88/cron/models.py +13 -0
- yee88/cron/scheduler.py +57 -0
- yee88/markdown.py +2 -0
- yee88/progress.py +3 -0
- yee88/runner.py +1 -0
- yee88/runner_bridge.py +18 -0
- yee88/runners/mock.py +3 -0
- yee88/runtime_loader.py +4 -0
- yee88/settings.py +1 -1
- yee88/skills/yee88/SKILL.md +530 -0
- yee88/telegram/commands/__init__.py +2 -0
- yee88/telegram/commands/executor.py +5 -1
- yee88/telegram/commands/model.py +131 -4
- yee88/telegram/commands/topics.py +10 -0
- yee88/telegram/context.py +6 -0
- yee88/telegram/loop.py +63 -2
- yee88/telegram/onboarding.py +40 -0
- yee88/transport_runtime.py +21 -0
- {yee88-0.4.0.dist-info → yee88-0.6.1.dist-info}/METADATA +2 -1
- {yee88-0.4.0.dist-info → yee88-0.6.1.dist-info}/RECORD +30 -23
- {yee88-0.4.0.dist-info → yee88-0.6.1.dist-info}/WHEEL +0 -0
- {yee88-0.4.0.dist-info → yee88-0.6.1.dist-info}/entry_points.txt +0 -0
- {yee88-0.4.0.dist-info → yee88-0.6.1.dist-info}/licenses/LICENSE +0 -0
yee88/runner_bridge.py
CHANGED
|
@@ -9,6 +9,7 @@ import anyio
|
|
|
9
9
|
from .context import RunContext
|
|
10
10
|
from .logging import bind_run_context, get_logger
|
|
11
11
|
from .model import CompletedEvent, ResumeToken, StartedEvent, TakopiEvent
|
|
12
|
+
from .runners.run_options import get_run_options
|
|
12
13
|
from .presenter import Presenter
|
|
13
14
|
from .markdown import render_event_cli
|
|
14
15
|
from .runner import Runner
|
|
@@ -26,6 +27,13 @@ from .transport import (
|
|
|
26
27
|
logger = get_logger(__name__)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
def _effective_model(runner: Runner) -> str | None:
|
|
31
|
+
run_options = get_run_options()
|
|
32
|
+
if run_options is not None and run_options.model:
|
|
33
|
+
return run_options.model
|
|
34
|
+
return runner.model
|
|
35
|
+
|
|
36
|
+
|
|
29
37
|
def _log_runner_event(evt: TakopiEvent) -> None:
|
|
30
38
|
for line in render_event_cli(evt):
|
|
31
39
|
logger.debug(
|
|
@@ -165,6 +173,7 @@ class ProgressEdits:
|
|
|
165
173
|
resume_formatter: Callable[[ResumeToken], str] | None = None,
|
|
166
174
|
label: str = "working",
|
|
167
175
|
context_line: str | None = None,
|
|
176
|
+
model: str | None = None,
|
|
168
177
|
) -> None:
|
|
169
178
|
self.transport = transport
|
|
170
179
|
self.presenter = presenter
|
|
@@ -177,6 +186,7 @@ class ProgressEdits:
|
|
|
177
186
|
self.resume_formatter = resume_formatter
|
|
178
187
|
self.label = label
|
|
179
188
|
self.context_line = context_line
|
|
189
|
+
self.model = model
|
|
180
190
|
self.event_seq = 0
|
|
181
191
|
self.rendered_seq = 0
|
|
182
192
|
self.signal_send, self.signal_recv = anyio.create_memory_object_stream(1)
|
|
@@ -196,6 +206,7 @@ class ProgressEdits:
|
|
|
196
206
|
state = self.tracker.snapshot(
|
|
197
207
|
resume_formatter=self.resume_formatter,
|
|
198
208
|
context_line=self.context_line,
|
|
209
|
+
model=self.model,
|
|
199
210
|
)
|
|
200
211
|
rendered = self.presenter.render_progress(
|
|
201
212
|
state, elapsed_s=now - self.started_at, label=self.label
|
|
@@ -248,12 +259,14 @@ async def send_initial_progress(
|
|
|
248
259
|
resume_formatter: Callable[[ResumeToken], str] | None = None,
|
|
249
260
|
context_line: str | None = None,
|
|
250
261
|
thread_id: ThreadId | None = None,
|
|
262
|
+
model: str | None = None,
|
|
251
263
|
) -> ProgressMessageState:
|
|
252
264
|
last_rendered: RenderedMessage | None = None
|
|
253
265
|
|
|
254
266
|
state = tracker.snapshot(
|
|
255
267
|
resume_formatter=resume_formatter,
|
|
256
268
|
context_line=context_line,
|
|
269
|
+
model=model,
|
|
257
270
|
)
|
|
258
271
|
initial_rendered = cfg.presenter.render_progress(
|
|
259
272
|
state,
|
|
@@ -426,6 +439,7 @@ async def handle_message(
|
|
|
426
439
|
resume_formatter=runner.format_resume,
|
|
427
440
|
context_line=context_line,
|
|
428
441
|
thread_id=incoming.thread_id,
|
|
442
|
+
model=_effective_model(runner),
|
|
429
443
|
)
|
|
430
444
|
progress_ref = progress_state.ref
|
|
431
445
|
|
|
@@ -440,6 +454,7 @@ async def handle_message(
|
|
|
440
454
|
last_rendered=progress_state.last_rendered,
|
|
441
455
|
resume_formatter=runner.format_resume,
|
|
442
456
|
context_line=context_line,
|
|
457
|
+
model=_effective_model(runner),
|
|
443
458
|
)
|
|
444
459
|
|
|
445
460
|
running_task: RunningTask | None = None
|
|
@@ -499,6 +514,7 @@ async def handle_message(
|
|
|
499
514
|
state = progress_tracker.snapshot(
|
|
500
515
|
resume_formatter=runner.format_resume,
|
|
501
516
|
context_line=context_line,
|
|
517
|
+
model=_effective_model(runner),
|
|
502
518
|
)
|
|
503
519
|
final_rendered = cfg.presenter.render_final(
|
|
504
520
|
state,
|
|
@@ -535,6 +551,7 @@ async def handle_message(
|
|
|
535
551
|
state = progress_tracker.snapshot(
|
|
536
552
|
resume_formatter=runner.format_resume,
|
|
537
553
|
context_line=context_line,
|
|
554
|
+
model=_effective_model(runner),
|
|
538
555
|
)
|
|
539
556
|
final_rendered = cfg.presenter.render_progress(
|
|
540
557
|
state,
|
|
@@ -589,6 +606,7 @@ async def handle_message(
|
|
|
589
606
|
state = progress_tracker.snapshot(
|
|
590
607
|
resume_formatter=runner.format_resume,
|
|
591
608
|
context_line=context_line,
|
|
609
|
+
model=_effective_model(runner),
|
|
592
610
|
)
|
|
593
611
|
final_rendered = cfg.presenter.render_final(
|
|
594
612
|
state,
|
yee88/runners/mock.py
CHANGED
|
@@ -60,6 +60,7 @@ def _resume_token(engine: EngineId, value: str | None) -> ResumeToken:
|
|
|
60
60
|
|
|
61
61
|
class MockRunner(SessionLockMixin, ResumeTokenMixin, Runner):
|
|
62
62
|
engine: EngineId
|
|
63
|
+
model: str | None
|
|
63
64
|
|
|
64
65
|
def __init__(
|
|
65
66
|
self,
|
|
@@ -69,8 +70,10 @@ class MockRunner(SessionLockMixin, ResumeTokenMixin, Runner):
|
|
|
69
70
|
engine: EngineId = ENGINE,
|
|
70
71
|
resume_value: str | None = None,
|
|
71
72
|
title: str | None = None,
|
|
73
|
+
model: str | None = None,
|
|
72
74
|
) -> None:
|
|
73
75
|
self.engine = engine
|
|
76
|
+
self.model = model
|
|
74
77
|
self._events = list(events or [])
|
|
75
78
|
self._answer = answer
|
|
76
79
|
self._resume_value = resume_value
|
yee88/runtime_loader.py
CHANGED
|
@@ -24,6 +24,7 @@ class RuntimeSpec:
|
|
|
24
24
|
projects: ProjectsConfig
|
|
25
25
|
allowlist: list[str] | None
|
|
26
26
|
plugin_configs: Mapping[str, Any] | None
|
|
27
|
+
engine_configs: Mapping[str, Any] | None = None
|
|
27
28
|
watch_config: bool = False
|
|
28
29
|
|
|
29
30
|
def to_runtime(self, *, config_path: Path | None) -> TransportRuntime:
|
|
@@ -33,6 +34,7 @@ class RuntimeSpec:
|
|
|
33
34
|
allowlist=self.allowlist,
|
|
34
35
|
config_path=config_path,
|
|
35
36
|
plugin_configs=self.plugin_configs,
|
|
37
|
+
engine_configs=self.engine_configs,
|
|
36
38
|
watch_config=self.watch_config,
|
|
37
39
|
)
|
|
38
40
|
|
|
@@ -43,6 +45,7 @@ class RuntimeSpec:
|
|
|
43
45
|
allowlist=self.allowlist,
|
|
44
46
|
config_path=config_path,
|
|
45
47
|
plugin_configs=self.plugin_configs,
|
|
48
|
+
engine_configs=self.engine_configs,
|
|
46
49
|
watch_config=self.watch_config,
|
|
47
50
|
)
|
|
48
51
|
|
|
@@ -203,5 +206,6 @@ def build_runtime_spec(
|
|
|
203
206
|
projects=projects,
|
|
204
207
|
allowlist=allowlist,
|
|
205
208
|
plugin_configs=settings.plugins.model_extra,
|
|
209
|
+
engine_configs=settings.model_extra,
|
|
206
210
|
watch_config=settings.watch_config,
|
|
207
211
|
)
|
yee88/settings.py
CHANGED
|
@@ -145,7 +145,7 @@ class TakopiSettings(BaseSettings):
|
|
|
145
145
|
default_project: NonEmptyStr | None = None
|
|
146
146
|
system_prompt: str | None = (
|
|
147
147
|
"你是我的专业秘书,请用中文回复。"
|
|
148
|
-
"
|
|
148
|
+
"每次会话结束以后,都要叫我老板,用简短、调皮但不轻浮的回复,告诉我你的任务结果!"
|
|
149
149
|
)
|
|
150
150
|
projects: dict[str, ProjectSettings] = Field(default_factory=dict)
|
|
151
151
|
|
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yee88
|
|
3
|
+
description: 当用户说"提醒我"、"X分钟/小时后"、"定时"、"每天/每周"、"设置闹钟"、"注册项目"、"切换引擎"、"创建话题"时使用。yee88 Telegram 桥接工具,支持一次性提醒(+30m, +2h)、定时任务(cron)、项目管理、话题管理、多引擎切换。通过 yee88 CLI 命令直接操作。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# yee88 CLI 工具
|
|
7
|
+
|
|
8
|
+
## ⚠️ 重要:必须执行真实命令
|
|
9
|
+
|
|
10
|
+
当用户请求以下功能时,**必须使用 Bash 执行对应的 yee88 命令**,不能只是口头回复!
|
|
11
|
+
|
|
12
|
+
## 💬 回复用户时保持简洁
|
|
13
|
+
|
|
14
|
+
**不要透露内部实现细节!** 用户不需要知道:
|
|
15
|
+
- "一次性任务"、"执行后自动清理"等技术细节
|
|
16
|
+
- 命令参数含义(如 `-o`、`--project`)
|
|
17
|
+
- 内部调度机制
|
|
18
|
+
|
|
19
|
+
| 用户说 | 正确回复 ✅ | 错误回复 ❌ |
|
|
20
|
+
|--------|-------------|-------------|
|
|
21
|
+
| "1分钟后提醒我喝水" | "好的,1分钟后提醒你喝水" | "已创建一次性定时任务,将在1分钟后触发,执行后自动清理..." |
|
|
22
|
+
| "每天9点提醒我站会" | "好的,每天早上9点提醒你站会" | "已添加 cron 任务,schedule 为 0 9 * * *,project 为..." |
|
|
23
|
+
| "取消那个提醒" | "已取消" | "已执行 yee88 cron remove xxx --force,任务已从列表中删除..." |
|
|
24
|
+
|
|
25
|
+
## 🚨 关键区分:设置提醒 vs 执行任务
|
|
26
|
+
|
|
27
|
+
**设置提醒时,你只需要创建定时任务,不要执行任务本身!**
|
|
28
|
+
|
|
29
|
+
| 场景 | 正确做法 | 错误做法 |
|
|
30
|
+
|------|----------|----------|
|
|
31
|
+
| "1分钟后提醒我查天气" | 只执行 `yee88 cron add ...` 创建提醒 | ❌ 立即查天气,把结果写进 message |
|
|
32
|
+
| "30分钟后提醒我开会" | 只执行 `yee88 cron add ...` 创建提醒 | ❌ 立即做任何与"开会"相关的操作 |
|
|
33
|
+
| "2小时后帮我发邮件" | 只执行 `yee88 cron add ...` 创建提醒 | ❌ 立即发邮件 |
|
|
34
|
+
|
|
35
|
+
**message 参数应该是用户的原话或简短描述,不是执行结果!**
|
|
36
|
+
|
|
37
|
+
## ⛔ 默认不传 --project!除非用户明确要求
|
|
38
|
+
|
|
39
|
+
**简单规则:不知道项目别名就不传 `--project`,让 yee88 使用默认上下文。**
|
|
40
|
+
|
|
41
|
+
| 场景 | 做法 |
|
|
42
|
+
|------|------|
|
|
43
|
+
| 用户只说"1分钟后提醒我..." | `yee88 cron add reminder "+1m" "..." -o` (不传 --project) |
|
|
44
|
+
| 用户说"在 takopi 项目提醒我..." | `yee88 cron add reminder "+1m" "..." --project takopi -o` |
|
|
45
|
+
| 不确定项目别名 | **不传 --project** |
|
|
46
|
+
|
|
47
|
+
**⚠️ --project 只接受项目别名,不是路径!**
|
|
48
|
+
|
|
49
|
+
| 正确 ✅ | 错误 ❌ |
|
|
50
|
+
|---------|---------|
|
|
51
|
+
| 不传(默认) | `--project /Users/yee.wang/Code/github/takopi` |
|
|
52
|
+
| `--project takopi` | `--project ~/dev/work-project` |
|
|
53
|
+
| `--project work` | `--project /Users/yee.wang/.yee88` |
|
|
54
|
+
| | `--project .` |
|
|
55
|
+
|
|
56
|
+
**如何获取项目别名(仅当用户要求时):**
|
|
57
|
+
```bash
|
|
58
|
+
yee88 config list | grep projects
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🎯 快速触发表(立即执行)
|
|
62
|
+
|
|
63
|
+
| 用户说 | 必须执行的命令 |
|
|
64
|
+
|--------|----------------|
|
|
65
|
+
| "5分钟后提醒我..." | `yee88 cron add reminder "+5m" "提醒内容" -o` |
|
|
66
|
+
| "30分钟后提醒我..." | `yee88 cron add reminder "+30m" "提醒内容" -o` |
|
|
67
|
+
| "2小时后提醒我..." | `yee88 cron add reminder "+2h" "提醒内容" -o` |
|
|
68
|
+
| "明天提醒我..." | `yee88 cron add reminder "+1d" "提醒内容" -o` |
|
|
69
|
+
| "每天早上9点提醒我..." | `yee88 cron add daily "0 9 * * *" "提醒内容"` |
|
|
70
|
+
| "每周一提醒我..." | `yee88 cron add weekly "0 9 * * 1" "提醒内容"` |
|
|
71
|
+
| "查看所有提醒" | `yee88 cron list` |
|
|
72
|
+
| "删除提醒 X" | `yee88 cron remove X --force` |
|
|
73
|
+
|
|
74
|
+
### 一次性提醒命令格式
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
yee88 cron add <id> "<时间>" "<消息>" -o
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**参数说明:**
|
|
81
|
+
- `<id>`: 任务ID(如 reminder, meeting, break)
|
|
82
|
+
- `<时间>`: 相对时间格式 `+5m`, `+30m`, `+1h`, `+2h`, `+1d`
|
|
83
|
+
- `<消息>`: **用户的原话或简短描述**(不是执行结果!)
|
|
84
|
+
- `--project <alias>`: 可选,项目别名(如 takopi, myproject),不指定则在默认上下文执行
|
|
85
|
+
- `-o`: 一次性任务(执行后自动删除)
|
|
86
|
+
|
|
87
|
+
**正确示例:**
|
|
88
|
+
```bash
|
|
89
|
+
# 用户说:"5分钟后提醒我该健身了"
|
|
90
|
+
yee88 cron add reminder "+5m" "该健身了" -o
|
|
91
|
+
|
|
92
|
+
# 用户说:"30分钟后提醒我开会"
|
|
93
|
+
yee88 cron add meeting "+30m" "开会时间到" -o
|
|
94
|
+
|
|
95
|
+
# 用户说:"1分钟后提醒我查天气"
|
|
96
|
+
# ✅ 正确:只设置提醒,不查天气
|
|
97
|
+
yee88 cron add weather "+1m" "查天气" -o
|
|
98
|
+
|
|
99
|
+
# ❌ 错误:立即查天气并把结果写进 message
|
|
100
|
+
# yee88 cron add weather "+1m" "杭州今天晴,15度..." -o
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 完整能力参考
|
|
106
|
+
|
|
107
|
+
### 1. 定时任务 (Cron)
|
|
108
|
+
|
|
109
|
+
#### 注册项目
|
|
110
|
+
```bash
|
|
111
|
+
yee88 init <alias>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
在指定目录注册项目:
|
|
115
|
+
```bash
|
|
116
|
+
cd ~/dev/my-project
|
|
117
|
+
yee88 init myproject
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 查看项目配置
|
|
121
|
+
```bash
|
|
122
|
+
yee88 config list | grep projects
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 2. 配置管理
|
|
126
|
+
|
|
127
|
+
#### 查看配置路径
|
|
128
|
+
```bash
|
|
129
|
+
yee88 config path
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### 列出所有配置
|
|
133
|
+
```bash
|
|
134
|
+
yee88 config list
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### 获取配置项
|
|
138
|
+
```bash
|
|
139
|
+
yee88 config get <key>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
示例:
|
|
143
|
+
```bash
|
|
144
|
+
yee88 config get default_engine
|
|
145
|
+
yee88 config get projects.myproject.path
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### 设置配置项
|
|
149
|
+
```bash
|
|
150
|
+
yee88 config set <key> <value>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
示例:
|
|
154
|
+
```bash
|
|
155
|
+
# 设置默认引擎
|
|
156
|
+
yee88 config set default_engine "claude"
|
|
157
|
+
|
|
158
|
+
# 设置默认项目
|
|
159
|
+
yee88 config set default_project "myproject"
|
|
160
|
+
|
|
161
|
+
# 设置项目路径
|
|
162
|
+
yee88 config set projects.myproject.path "~/dev/my-project"
|
|
163
|
+
|
|
164
|
+
# 设置项目默认引擎
|
|
165
|
+
yee88 config set projects.myproject.default_engine "claude"
|
|
166
|
+
|
|
167
|
+
# Telegram 设置
|
|
168
|
+
yee88 config set transports.telegram.session_mode "chat"
|
|
169
|
+
yee88 config set transports.telegram.show_resume_line false
|
|
170
|
+
|
|
171
|
+
# 引擎特定配置
|
|
172
|
+
yee88 config set claude.model "claude-sonnet-4-5-20250929"
|
|
173
|
+
yee88 config set codex.profile "work"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### 删除配置项
|
|
177
|
+
```bash
|
|
178
|
+
yee88 config unset <key>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 3. 定时任务 (Cron)
|
|
182
|
+
|
|
183
|
+
#### 添加定时任务
|
|
184
|
+
```bash
|
|
185
|
+
yee88 cron add <id> <schedule> <message> [--project <alias>]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
参数:
|
|
189
|
+
- `id`: 任务唯一标识
|
|
190
|
+
- `schedule`: Cron 表达式(如 "0 9 * * 1-5")
|
|
191
|
+
- `message`: 推送消息内容
|
|
192
|
+
- `--project`: 可选,项目别名(如 takopi),不指定则在默认上下文执行
|
|
193
|
+
|
|
194
|
+
示例:
|
|
195
|
+
```bash
|
|
196
|
+
# 每日站会(工作日早上9点)
|
|
197
|
+
yee88 cron add standup "0 9 * * 1-5" "准备每日站会" --project work
|
|
198
|
+
|
|
199
|
+
# 周报(周五下午6点)
|
|
200
|
+
yee88 cron add weekly "0 18 * * 5" "生成本周工作报告" --project work
|
|
201
|
+
|
|
202
|
+
# 提醒(每30分钟)
|
|
203
|
+
yee88 cron add reminder "*/30 * * * *" "该休息眼睛了" --project personal
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### 列出所有定时任务
|
|
207
|
+
```bash
|
|
208
|
+
yee88 cron list
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
显示所有(包括禁用的):
|
|
212
|
+
```bash
|
|
213
|
+
yee88 cron list --all
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### 启用/禁用任务
|
|
217
|
+
```bash
|
|
218
|
+
yee88 cron enable <id>
|
|
219
|
+
yee88 cron disable <id>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### 删除任务
|
|
223
|
+
```bash
|
|
224
|
+
yee88 cron remove <id>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
强制删除(不确认):
|
|
228
|
+
```bash
|
|
229
|
+
yee88 cron remove <id> --force
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### 立即执行一次(测试)
|
|
233
|
+
```bash
|
|
234
|
+
yee88 cron run <id>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### 添加一次性定时任务
|
|
238
|
+
|
|
239
|
+
使用 `--one-time` 或 `-o` 参数创建只执行一次的任务,执行后自动删除。
|
|
240
|
+
|
|
241
|
+
支持两种时间格式:
|
|
242
|
+
- **相对时间**: `+30m` (30分钟后), `+2h` (2小时后), `+1d` (1天后)
|
|
243
|
+
- **ISO 8601**: `2026-02-01T14:00:00` (具体日期时间)
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# 30分钟后提醒
|
|
247
|
+
yee88 cron add reminder "+30m" "该开会了" --project work -o
|
|
248
|
+
|
|
249
|
+
# 2小时后部署
|
|
250
|
+
yee88 cron add deploy "+2h" "部署到生产环境" --project myapp -o
|
|
251
|
+
|
|
252
|
+
# 指定具体时间
|
|
253
|
+
yee88 cron add meeting "2026-02-01T14:00:00" "项目评审会议" --project work -o
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
查看任务列表时,一次性任务会标记为 `once` 类型:
|
|
257
|
+
```bash
|
|
258
|
+
yee88 cron list
|
|
259
|
+
# 输出: ID TYPE SCHEDULE STATUS PROJECT
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 4. 话题管理
|
|
263
|
+
|
|
264
|
+
#### 初始化话题
|
|
265
|
+
```bash
|
|
266
|
+
yee88 topic init
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
在当前目录创建话题并绑定到项目。
|
|
270
|
+
|
|
271
|
+
#### 创建话题
|
|
272
|
+
```bash
|
|
273
|
+
yee88 topic create <project> [@branch]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
示例:
|
|
277
|
+
```bash
|
|
278
|
+
yee88 topic create myproject
|
|
279
|
+
yee88 topic create myproject @feat/new-feature
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### 查看话题状态
|
|
283
|
+
```bash
|
|
284
|
+
yee88 topic status
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
#### 切换话题
|
|
288
|
+
```bash
|
|
289
|
+
yee88 topic switch <topic_id>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 5. 引擎运行
|
|
293
|
+
|
|
294
|
+
#### 启动 yee88
|
|
295
|
+
```bash
|
|
296
|
+
yee88
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### 指定引擎启动
|
|
300
|
+
```bash
|
|
301
|
+
yee88 claude
|
|
302
|
+
yee88 codex
|
|
303
|
+
yee88 opencode
|
|
304
|
+
yee88 pi
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### 带选项启动
|
|
308
|
+
```bash
|
|
309
|
+
yee88 --debug
|
|
310
|
+
yee88 --onboard
|
|
311
|
+
yee88 --transport telegram
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 6. 诊断检查
|
|
315
|
+
|
|
316
|
+
#### 运行配置检查
|
|
317
|
+
```bash
|
|
318
|
+
yee88 doctor
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
检查配置是否正确,包括:
|
|
322
|
+
- Telegram bot token
|
|
323
|
+
- Chat ID
|
|
324
|
+
- 引擎可用性
|
|
325
|
+
- 项目配置
|
|
326
|
+
|
|
327
|
+
### 7. 插件管理
|
|
328
|
+
|
|
329
|
+
#### 列出插件
|
|
330
|
+
```bash
|
|
331
|
+
yee88 plugins
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### 验证插件
|
|
335
|
+
```bash
|
|
336
|
+
yee88 plugins --validate
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 8. 获取 Chat ID
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
yee88 chat-id
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
启动临时 bot 捕获 Telegram chat ID。
|
|
346
|
+
|
|
347
|
+
### 9. 查看引导路径
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
yee88 onboarding-paths
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
显示所有可能的配置路径。
|
|
354
|
+
|
|
355
|
+
## 配置参考
|
|
356
|
+
|
|
357
|
+
### 配置文件位置
|
|
358
|
+
- 主配置:`~/.yee88/yee88.toml`
|
|
359
|
+
- 定时任务:`~/.yee88/cron.toml`
|
|
360
|
+
- 话题状态:`~/.yee88/topics.json`
|
|
361
|
+
|
|
362
|
+
### 常用配置示例
|
|
363
|
+
|
|
364
|
+
```toml
|
|
365
|
+
# ~/.yee88/yee88.toml
|
|
366
|
+
|
|
367
|
+
watch_config = true
|
|
368
|
+
default_engine = "claude"
|
|
369
|
+
default_project = "myproject"
|
|
370
|
+
transport = "telegram"
|
|
371
|
+
|
|
372
|
+
[transports.telegram]
|
|
373
|
+
bot_token = "YOUR_BOT_TOKEN"
|
|
374
|
+
chat_id = 123456789
|
|
375
|
+
session_mode = "chat"
|
|
376
|
+
show_resume_line = false
|
|
377
|
+
|
|
378
|
+
[projects.myproject]
|
|
379
|
+
path = "~/dev/my-project"
|
|
380
|
+
default_engine = "claude"
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## 使用场景
|
|
384
|
+
|
|
385
|
+
### 场景 1:每日工作流自动化
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# 1. 注册项目
|
|
389
|
+
cd ~/dev/work-project
|
|
390
|
+
yee88 init work
|
|
391
|
+
|
|
392
|
+
# 2. 设置默认项目
|
|
393
|
+
yee88 config set default_project work
|
|
394
|
+
|
|
395
|
+
# 3. 添加定时任务(使用项目别名)
|
|
396
|
+
yee88 cron add morning "0 9 * * 1-5" "准备每日站会" --project work
|
|
397
|
+
yee88 cron add evening "0 18 * * 1-5" "总结今日工作" --project work
|
|
398
|
+
yee88 cron add weekly "0 17 * * 5" "生成本周报告" --project work
|
|
399
|
+
|
|
400
|
+
# 4. 启动 yee88
|
|
401
|
+
yee88
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### 场景 2:多项目管理
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
# 注册多个项目
|
|
408
|
+
cd ~/dev/project-a && yee88 init project-a
|
|
409
|
+
cd ~/dev/project-b && yee88 init project-b
|
|
410
|
+
|
|
411
|
+
# 设置不同默认引擎
|
|
412
|
+
yee88 config set projects.project-a.default_engine "claude"
|
|
413
|
+
yee88 config set projects.project-b.default_engine "codex"
|
|
414
|
+
|
|
415
|
+
# 为每个项目创建话题
|
|
416
|
+
cd ~/dev/project-a
|
|
417
|
+
yee88 topic init
|
|
418
|
+
|
|
419
|
+
cd ~/dev/project-b
|
|
420
|
+
yee88 topic init
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### 场景 3:团队协作
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# 1. 配置群组 chat_id
|
|
427
|
+
yee88 config set transports.telegram.chat_id -1001234567890
|
|
428
|
+
|
|
429
|
+
# 2. 启用话题模式
|
|
430
|
+
yee88 config set transports.telegram.topics.enabled true
|
|
431
|
+
|
|
432
|
+
# 3. 创建团队话题
|
|
433
|
+
yee88 topic create team-project @main
|
|
434
|
+
|
|
435
|
+
# 4. 设置定时提醒(使用项目别名)
|
|
436
|
+
yee88 cron add daily-sync "0 10 * * 1-5" "团队同步时间" --project team-project
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### 场景 4:临时提醒和一次性任务
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
# 30分钟后提醒自己休息
|
|
443
|
+
yee88 cron add break "+30m" "该休息眼睛了,起来活动一下" --project personal -o
|
|
444
|
+
|
|
445
|
+
# 今天下午3点的会议提醒
|
|
446
|
+
yee88 cron add meeting "2026-02-01T15:00:00" "参加产品评审会议" --project work -o
|
|
447
|
+
|
|
448
|
+
# 明天早上执行代码审查
|
|
449
|
+
yee88 cron add review "+1d" "审查昨天的 PR" --project work -o
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## 故障排查
|
|
453
|
+
|
|
454
|
+
### 检查配置
|
|
455
|
+
```bash
|
|
456
|
+
yee88 doctor
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### 查看日志
|
|
460
|
+
```bash
|
|
461
|
+
# yee88 日志
|
|
462
|
+
tail -f /tmp/yee88.log
|
|
463
|
+
|
|
464
|
+
# 定时任务日志
|
|
465
|
+
tail -f /tmp/yee88-cron.log
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 验证 cron 表达式
|
|
469
|
+
```bash
|
|
470
|
+
python -c "from croniter import croniter; print(croniter('0 9 * * *').get_next(str))"
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### 测试任务
|
|
474
|
+
```bash
|
|
475
|
+
yee88 cron run <task-id>
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## 注意事项
|
|
479
|
+
|
|
480
|
+
1. **项目别名要求**:
|
|
481
|
+
- 定时任务的 `--project` 使用项目别名(如 `takopi`, `work`)
|
|
482
|
+
- 通过 `yee88 config list | grep projects` 查看已注册项目
|
|
483
|
+
- 使用 `yee88 init <alias>` 注册新项目
|
|
484
|
+
|
|
485
|
+
2. **配置热重载**:
|
|
486
|
+
- 设置 `watch_config = true` 可热重载配置
|
|
487
|
+
- 定时任务配置修改后需重启 yee88
|
|
488
|
+
|
|
489
|
+
3. **调度精度**:
|
|
490
|
+
- 定时任务每分钟检查一次
|
|
491
|
+
- 实际执行可能有 1 分钟内延迟
|
|
492
|
+
|
|
493
|
+
4. **权限问题**:
|
|
494
|
+
- 确保 yee88 命令在 PATH 中
|
|
495
|
+
- 定时任务执行时保持 yee88 运行
|
|
496
|
+
|
|
497
|
+
5. **一次性任务**:
|
|
498
|
+
- 使用 `-o` 或 `--one-time` 参数创建
|
|
499
|
+
- 支持相对时间 (`+30m`, `+2h`, `+1d`) 和 ISO 8601 格式
|
|
500
|
+
- 执行后自动从列表中删除
|
|
501
|
+
- 无法对一次性任务使用 enable/disable(执行前自动删除)
|
|
502
|
+
|
|
503
|
+
## 完整命令速查表
|
|
504
|
+
|
|
505
|
+
| 命令 | 说明 |
|
|
506
|
+
|------|------|
|
|
507
|
+
| `yee88` | 启动 yee88 |
|
|
508
|
+
| `yee88 init <alias>` | 注册项目 |
|
|
509
|
+
| `yee88 config path` | 查看配置路径 |
|
|
510
|
+
| `yee88 config list` | 列出配置 |
|
|
511
|
+
| `yee88 config get <key>` | 获取配置项 |
|
|
512
|
+
| `yee88 config set <key> <value>` | 设置配置项 |
|
|
513
|
+
| `yee88 config unset <key>` | 删除配置项 |
|
|
514
|
+
| `yee88 cron add <id> <schedule> <msg> [--project <alias>]` | 添加定时任务 |
|
|
515
|
+
| `yee88 cron add <id> <time> <msg> [-p <alias>] -o` | 添加一次性任务 (-o = --one-time) |
|
|
516
|
+
| `yee88 cron list` | 列出定时任务 |
|
|
517
|
+
| `yee88 cron enable <id>` | 启用任务 |
|
|
518
|
+
| `yee88 cron disable <id>` | 禁用任务 |
|
|
519
|
+
| `yee88 cron remove <id>` | 删除任务 |
|
|
520
|
+
| `yee88 cron run <id>` | 立即执行任务 |
|
|
521
|
+
| `yee88 topic init` | 初始化话题 |
|
|
522
|
+
| `yee88 topic create <project> [@branch]` | 创建话题 |
|
|
523
|
+
| `yee88 topic status` | 查看话题状态 |
|
|
524
|
+
| `yee88 doctor` | 运行诊断检查 |
|
|
525
|
+
| `yee88 plugins` | 列出插件 |
|
|
526
|
+
| `yee88 chat-id` | 获取 Chat ID |
|
|
527
|
+
| `yee88 claude` | 使用 Claude 引擎 |
|
|
528
|
+
| `yee88 codex` | 使用 Codex 引擎 |
|
|
529
|
+
| `yee88 opencode` | 使用 OpenCode 引擎 |
|
|
530
|
+
| `yee88 pi` | 使用 Pi 引擎 |
|
|
@@ -2,11 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from .cancel import handle_callback_cancel, handle_cancel
|
|
4
4
|
from .menu import build_bot_commands
|
|
5
|
+
from .model import handle_model_select_callback
|
|
5
6
|
from .parse import is_cancel_command
|
|
6
7
|
|
|
7
8
|
__all__ = [
|
|
8
9
|
"build_bot_commands",
|
|
9
10
|
"handle_callback_cancel",
|
|
10
11
|
"handle_cancel",
|
|
12
|
+
"handle_model_select_callback",
|
|
11
13
|
"is_cancel_command",
|
|
12
14
|
]
|