yee88 0.4.0__py3-none-any.whl → 0.6.0__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/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,8 @@ class TakopiSettings(BaseSettings):
145
145
  default_project: NonEmptyStr | None = None
146
146
  system_prompt: str | None = (
147
147
  "你是我的专业秘书,请用中文回复。"
148
- "每次会话结束以后,都请叫我老板,用简短、调皮的职场回复,告诉我你的任务结果!"
148
+ "每次会话结束以后,都要叫我老板,用简短、调皮但不轻浮的回复,告诉我你的任务结果!",
149
+ "返回格式给 Markdown Table"
149
150
  )
150
151
  projects: dict[str, ProjectSettings] = Field(default_factory=dict)
151
152
 
@@ -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
  ]