yee88 0.7.0__py3-none-any.whl → 0.7.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/cli/handoff.py +2 -0
- yee88/ids.py +1 -1
- yee88/skills/yee88/SKILL.md +26 -0
- yee88/telegram/commands/handlers.py +2 -0
- yee88/telegram/commands/menu.py +4 -1
- yee88/telegram/commands/topics.py +82 -0
- yee88/telegram/loop.py +10 -0
- {yee88-0.7.0.dist-info → yee88-0.7.1.dist-info}/METADATA +1 -1
- {yee88-0.7.0.dist-info → yee88-0.7.1.dist-info}/RECORD +12 -12
- {yee88-0.7.0.dist-info → yee88-0.7.1.dist-info}/WHEEL +0 -0
- {yee88-0.7.0.dist-info → yee88-0.7.1.dist-info}/entry_points.txt +0 -0
- {yee88-0.7.0.dist-info → yee88-0.7.1.dist-info}/licenses/LICENSE +0 -0
yee88/cli/handoff.py
CHANGED
|
@@ -223,6 +223,8 @@ def send(
|
|
|
223
223
|
typer.echo("❌ 未找到 OpenCode 会话", err=True)
|
|
224
224
|
raise typer.Exit(1)
|
|
225
225
|
|
|
226
|
+
typer.echo("\n📲 会话接力 - 将电脑端会话发送到 Telegram 继续对话")
|
|
227
|
+
typer.echo("━" * 50)
|
|
226
228
|
typer.echo("\n📋 最近的会话:\n")
|
|
227
229
|
for i, s in enumerate(sessions[:10], 1):
|
|
228
230
|
title_display = s.title[:40] if s.title else s.project_name
|
yee88/ids.py
CHANGED
|
@@ -7,7 +7,7 @@ _ID_RE = re.compile(ID_PATTERN)
|
|
|
7
7
|
|
|
8
8
|
RESERVED_CLI_COMMANDS = frozenset({"config", "doctor", "init", "plugins"})
|
|
9
9
|
RESERVED_CHAT_COMMANDS = frozenset(
|
|
10
|
-
{"cancel", "file", "new", "agent", "model", "reasoning", "trigger", "topic", "ctx"}
|
|
10
|
+
{"cancel", "file", "new", "fork", "agent", "model", "reasoning", "trigger", "topic", "ctx"}
|
|
11
11
|
)
|
|
12
12
|
RESERVED_ENGINE_IDS = RESERVED_CLI_COMMANDS | RESERVED_CHAT_COMMANDS
|
|
13
13
|
RESERVED_COMMAND_IDS = RESERVED_CLI_COMMANDS | RESERVED_CHAT_COMMANDS
|
yee88/skills/yee88/SKILL.md
CHANGED
|
@@ -525,12 +525,38 @@ yee88 cron run <task-id>
|
|
|
525
525
|
- 执行后自动从列表中删除
|
|
526
526
|
- 无法对一次性任务使用 enable/disable(执行前自动删除)
|
|
527
527
|
|
|
528
|
+
### 10. 会话接力(Handoff)
|
|
529
|
+
|
|
530
|
+
将当前 OpenCode 会话上下文发送到 Telegram,方便在手机上继续对话。
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
yee88 handoff
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
功能:
|
|
537
|
+
- 自动列出当前项目的最近会话(带话题名称)
|
|
538
|
+
- 选择会话后,创建新的 Telegram Topic
|
|
539
|
+
- 将会话上下文和最近消息发送到 Topic
|
|
540
|
+
- 在 Telegram 中直接继续对话
|
|
541
|
+
|
|
542
|
+
选项:
|
|
543
|
+
- `--session, -s`: 指定会话 ID(默认交互选择)
|
|
544
|
+
- `--limit, -n`: 包含的消息数量(默认 3)
|
|
545
|
+
- `--project, -p`: 项目名称
|
|
546
|
+
|
|
547
|
+
示例:
|
|
548
|
+
```bash
|
|
549
|
+
yee88 handoff
|
|
550
|
+
yee88 handoff -s ses_abc123 -n 5
|
|
551
|
+
```
|
|
552
|
+
|
|
528
553
|
## 完整命令速查表
|
|
529
554
|
|
|
530
555
|
| 命令 | 说明 |
|
|
531
556
|
|------|------|
|
|
532
557
|
| `yee88` | 启动 yee88 |
|
|
533
558
|
| `yee88 init <alias>` | 注册项目 |
|
|
559
|
+
| `yee88 handoff` | 会话接力到 Telegram |
|
|
534
560
|
| `yee88 config path` | 查看配置路径 |
|
|
535
561
|
| `yee88 config list` | 列出配置 |
|
|
536
562
|
| `yee88 config get <key>` | 获取配置项 |
|
|
@@ -18,6 +18,7 @@ from .reasoning import _handle_reasoning_command as handle_reasoning_command
|
|
|
18
18
|
from .topics import _handle_chat_new_command as handle_chat_new_command
|
|
19
19
|
from .topics import _handle_chat_ctx_command as handle_chat_ctx_command
|
|
20
20
|
from .topics import _handle_ctx_command as handle_ctx_command
|
|
21
|
+
from .topics import _handle_fork_command as handle_fork_command
|
|
21
22
|
from .topics import _handle_new_command as handle_new_command
|
|
22
23
|
from .topics import _handle_topic_command as handle_topic_command
|
|
23
24
|
from .trigger import _handle_trigger_command as handle_trigger_command
|
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
|
31
32
|
"handle_ctx_command",
|
|
32
33
|
"handle_file_command",
|
|
33
34
|
"handle_file_put_default",
|
|
35
|
+
"handle_fork_command",
|
|
34
36
|
"handle_media_group",
|
|
35
37
|
"handle_model_command",
|
|
36
38
|
"handle_new_command",
|
yee88/telegram/commands/menu.py
CHANGED
|
@@ -83,7 +83,10 @@ def build_bot_commands(
|
|
|
83
83
|
commands.append({"command": cmd, "description": description})
|
|
84
84
|
seen.add(cmd)
|
|
85
85
|
if include_topics:
|
|
86
|
-
for cmd, description in [
|
|
86
|
+
for cmd, description in [
|
|
87
|
+
("topic", "create or bind a topic"),
|
|
88
|
+
("fork", "fork current topic to new topic"),
|
|
89
|
+
]:
|
|
87
90
|
if cmd in seen:
|
|
88
91
|
continue
|
|
89
92
|
commands.append({"command": cmd, "description": description})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import re as _re
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from ...context import RunContext
|
|
@@ -340,3 +341,84 @@ async def _handle_topic_command(
|
|
|
340
341
|
message=RenderedMessage(text=rendered_text, extra={"entities": entities}),
|
|
341
342
|
options=SendOptions(thread_id=thread_id),
|
|
342
343
|
)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
_FORK_TITLE_PATTERN = _re.compile(r"^(.+) \(fork #(\d+)\)$")
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _get_forked_title(title: str | None) -> str:
|
|
350
|
+
if title is None:
|
|
351
|
+
return "topic (fork #1)"
|
|
352
|
+
match = _FORK_TITLE_PATTERN.match(title)
|
|
353
|
+
if match:
|
|
354
|
+
base = match.group(1)
|
|
355
|
+
num = int(match.group(2))
|
|
356
|
+
return f"{base} (fork #{num + 1})"
|
|
357
|
+
return f"{title} (fork #1)"
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
async def _handle_fork_command(
|
|
361
|
+
cfg: TelegramBridgeConfig,
|
|
362
|
+
msg: TelegramIncomingMessage,
|
|
363
|
+
store: TopicStateStore,
|
|
364
|
+
*,
|
|
365
|
+
resolved_scope: str | None = None,
|
|
366
|
+
scope_chat_ids: frozenset[int] | None = None,
|
|
367
|
+
) -> None:
|
|
368
|
+
from ...model import ResumeToken
|
|
369
|
+
|
|
370
|
+
reply = make_reply(cfg, msg)
|
|
371
|
+
error = _topics_command_error(
|
|
372
|
+
cfg,
|
|
373
|
+
msg.chat_id,
|
|
374
|
+
resolved_scope=resolved_scope,
|
|
375
|
+
scope_chat_ids=scope_chat_ids,
|
|
376
|
+
)
|
|
377
|
+
if error is not None:
|
|
378
|
+
await reply(text=error)
|
|
379
|
+
return
|
|
380
|
+
tkey = _topic_key(msg, cfg, scope_chat_ids=scope_chat_ids)
|
|
381
|
+
if tkey is None:
|
|
382
|
+
await reply(text="this command only works inside a topic.")
|
|
383
|
+
return
|
|
384
|
+
|
|
385
|
+
snapshot = await store.get_thread(*tkey)
|
|
386
|
+
current_title = snapshot.topic_title if snapshot else None
|
|
387
|
+
forked_title = _get_forked_title(current_title)
|
|
388
|
+
|
|
389
|
+
created = await cfg.bot.create_forum_topic(msg.chat_id, forked_title)
|
|
390
|
+
if created is None:
|
|
391
|
+
await reply(text="failed to create forked topic.")
|
|
392
|
+
return
|
|
393
|
+
|
|
394
|
+
new_thread_id = created.message_thread_id
|
|
395
|
+
|
|
396
|
+
if snapshot and snapshot.context:
|
|
397
|
+
await store.set_context(
|
|
398
|
+
msg.chat_id,
|
|
399
|
+
new_thread_id,
|
|
400
|
+
snapshot.context,
|
|
401
|
+
topic_title=forked_title,
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
if snapshot and snapshot.sessions:
|
|
405
|
+
for engine, resume_value in snapshot.sessions.items():
|
|
406
|
+
token = ResumeToken(engine=engine, value=resume_value)
|
|
407
|
+
await store.set_session_resume(msg.chat_id, new_thread_id, token)
|
|
408
|
+
|
|
409
|
+
await reply(text=f"forked to new topic `{forked_title}`.")
|
|
410
|
+
|
|
411
|
+
context_label = _format_context(cfg.runtime, snapshot.context) if snapshot and snapshot.context else "none"
|
|
412
|
+
sessions_label = ", ".join(sorted(snapshot.sessions.keys())) if snapshot and snapshot.sessions else "none"
|
|
413
|
+
welcome_text = (
|
|
414
|
+
f"forked from previous topic\n\n"
|
|
415
|
+
f"context: `{context_label}`\n"
|
|
416
|
+
f"sessions: {sessions_label}\n\n"
|
|
417
|
+
"continue your conversation here!"
|
|
418
|
+
)
|
|
419
|
+
rendered_text, entities = prepare_telegram(MarkdownParts(header=welcome_text))
|
|
420
|
+
await cfg.exec_cfg.transport.send(
|
|
421
|
+
channel_id=msg.chat_id,
|
|
422
|
+
message=RenderedMessage(text=rendered_text, extra={"entities": entities}),
|
|
423
|
+
options=SendOptions(thread_id=new_thread_id),
|
|
424
|
+
)
|
yee88/telegram/loop.py
CHANGED
|
@@ -44,6 +44,7 @@ from .commands.handlers import (
|
|
|
44
44
|
handle_ctx_command,
|
|
45
45
|
handle_file_command,
|
|
46
46
|
handle_file_put_default,
|
|
47
|
+
handle_fork_command,
|
|
47
48
|
handle_media_group,
|
|
48
49
|
handle_model_command,
|
|
49
50
|
handle_new_command,
|
|
@@ -224,6 +225,15 @@ def _dispatch_builtin_command(
|
|
|
224
225
|
resolved_scope=resolved_scope,
|
|
225
226
|
scope_chat_ids=scope_chat_ids,
|
|
226
227
|
)
|
|
228
|
+
elif command_id == "fork":
|
|
229
|
+
handler = partial(
|
|
230
|
+
handle_fork_command,
|
|
231
|
+
cfg,
|
|
232
|
+
msg,
|
|
233
|
+
topic_store,
|
|
234
|
+
resolved_scope=resolved_scope,
|
|
235
|
+
scope_chat_ids=scope_chat_ids,
|
|
236
|
+
)
|
|
227
237
|
elif command_id == "topic":
|
|
228
238
|
handler = partial(
|
|
229
239
|
handle_topic_command,
|
|
@@ -10,7 +10,7 @@ yee88/context.py,sha256=2GXdWY8KpWbEARJNo34unLN8nqGBtiE72Z_mjwrJTUM,187
|
|
|
10
10
|
yee88/directives.py,sha256=28XG1f7yQs8GAgvPoy5g0pTe_aaVQeWFSD4-S5mC5oo,4583
|
|
11
11
|
yee88/engines.py,sha256=uXtGie-XkQDB1LROTjPlCkYKbCu7XgyTr0yGn837gN4,1646
|
|
12
12
|
yee88/events.py,sha256=1yo6l5D4xFreyPoU1d4L1ckaplPizxpFeJJevP8JDtk,4225
|
|
13
|
-
yee88/ids.py,sha256=
|
|
13
|
+
yee88/ids.py,sha256=n8ULXEUpeHRCGc571ZH2IAIGPRuf9lB0g1pZRFm8dWY,542
|
|
14
14
|
yee88/lockfile.py,sha256=xCSsxVQMqnCN2RWFkkDOVg1qm5D-Sb4AMKr6FdP0kbY,4162
|
|
15
15
|
yee88/logging.py,sha256=aqoIClE5_vlASKXsc9FjrmsmBy-7jLYOomHheSWSadA,8227
|
|
16
16
|
yee88/markdown.py,sha256=__2qyoBXTBZVVD7DgZvjDaj67xQCJHMfU0yQ8jcY1pQ,9144
|
|
@@ -32,7 +32,7 @@ yee88/cli/__init__.py,sha256=_Ji5MfYqvF2nuC7_sgbtZOOe0pvIuk0RQ47Hw_aCV_k,6684
|
|
|
32
32
|
yee88/cli/config.py,sha256=gTDdaTkJGGooeGECgcOXkpF-Y7Kmqi_Iyum0ghQzazg,9560
|
|
33
33
|
yee88/cli/cron.py,sha256=uvzgkAmMom8sDMjLgdMcB8V7DACmmdoGTiefif1Ol3U,6215
|
|
34
34
|
yee88/cli/doctor.py,sha256=FPLXk-ZSPZiHtWrncEqborcz4e1dhb3S5sUVcOw-n60,6000
|
|
35
|
-
yee88/cli/handoff.py,sha256=
|
|
35
|
+
yee88/cli/handoff.py,sha256=gd_4HE98wooT4n9gM2if5LkXZMoMi47Fd3A5U4ogBzE,9417
|
|
36
36
|
yee88/cli/init.py,sha256=y1Z08rh9t4RPhzsgJRtopgd6UvjEPYi9Wfv_t2KlrxI,3761
|
|
37
37
|
yee88/cli/onboarding_cmd.py,sha256=VNJl9cpfz-Bo7LNpGUIH-VtbOFdATTn1ry21cwtyQQM,4170
|
|
38
38
|
yee88/cli/plugins.py,sha256=Kxr1FgLIjN6c8il83_cfE9nix0jYPUvI6KXtol3Swow,6319
|
|
@@ -56,7 +56,7 @@ yee88/schemas/claude.py,sha256=HqOik1O4u3WcMb4RN2cTVJw6VRYn3EaYj8h5Sevs1XY,5702
|
|
|
56
56
|
yee88/schemas/codex.py,sha256=bgIsh35LuaqoOYdTl6BWR-mn-mvh3ouwes_Jn9JMVXg,3412
|
|
57
57
|
yee88/schemas/opencode.py,sha256=ODhnKXTzxZ_8qaQ7AYqXB7J-XoAjQnXbGMBVTUEM2qY,1175
|
|
58
58
|
yee88/schemas/pi.py,sha256=e5ETawxk8jrdJbEbeBI_pWQKeCFiBBZLEF-Wo5Fx0XY,2680
|
|
59
|
-
yee88/skills/yee88/SKILL.md,sha256=
|
|
59
|
+
yee88/skills/yee88/SKILL.md,sha256=GrZ7a8sm2ArUo5OdeUC3OECavnykx2DcsBI5EdtdvuQ,15113
|
|
60
60
|
yee88/telegram/__init__.py,sha256=hX_Wvu920dNLTDrKlj0fsZFSewOo-_otN26O1UNPNA4,452
|
|
61
61
|
yee88/telegram/api_models.py,sha256=d3H4o2sRZuFgfZfxF1Y1z_xzzCoOy3bKhMeKggYCW3w,538
|
|
62
62
|
yee88/telegram/api_schemas.py,sha256=Xj-i68GFSb9Uk6GhU2Etp-gYhAat9DKYcvQN9av1NPQ,3823
|
|
@@ -70,7 +70,7 @@ yee88/telegram/context.py,sha256=Hb8-k-YbAjO0EmZ35hA8yyMvl1kozgYHUL1L-lbCglA,468
|
|
|
70
70
|
yee88/telegram/engine_defaults.py,sha256=n6ROkTmP_s-H5AhPz_OdT62oZf0QtZJyFEDjp5gfub4,2594
|
|
71
71
|
yee88/telegram/engine_overrides.py,sha256=kv2j102VP-Bqzbutd5ApBkjW3LmVwvCYixsFewVXVeY,3122
|
|
72
72
|
yee88/telegram/files.py,sha256=Cvmw6r_ocSb3jLzJLGVbzr46m8cRU159majJ1-A5lvg,5053
|
|
73
|
-
yee88/telegram/loop.py,sha256
|
|
73
|
+
yee88/telegram/loop.py,sha256=pjSIsvIAg4N-83EjNHkDnoz8LHF0rQkwkdCN8NAcNZY,69778
|
|
74
74
|
yee88/telegram/onboarding.py,sha256=QWYaJT_s2bujDxzKjsZuLytyxs_XFDRuiBrsZGRjoOw,35633
|
|
75
75
|
yee88/telegram/outbox.py,sha256=OcoRyQ7zmQCXR8ZXEMK2f_7-UMRVRAbBgmJGS1u_lcU,5939
|
|
76
76
|
yee88/telegram/parsing.py,sha256=5PvIPns1NnKryt3XNxPCp4BpWX1gI8kjKi4VxcQ0W-Q,7429
|
|
@@ -87,16 +87,16 @@ yee88/telegram/commands/cancel.py,sha256=jE93VjztNETlmAgb7FJX0sLR3O-NHy5XcraUbK1
|
|
|
87
87
|
yee88/telegram/commands/dispatch.py,sha256=zcvX0V6_klf5jXqJlBwAK25e83WC9z3-KoRcDbeWre0,3572
|
|
88
88
|
yee88/telegram/commands/executor.py,sha256=eczs7Ds_S8GVX2_OvdmN23y6zE1fhYTpIAuchfH0eRU,14781
|
|
89
89
|
yee88/telegram/commands/file_transfer.py,sha256=yfopf_If9f7Scaz4dlUsfcrVvg24QmQdajLzemaENy0,17697
|
|
90
|
-
yee88/telegram/commands/handlers.py,sha256=
|
|
90
|
+
yee88/telegram/commands/handlers.py,sha256=KsmV6U_TKeNBvy5UdjuC4DQ3_xYiw_CFIYNrrQYlUfQ,1925
|
|
91
91
|
yee88/telegram/commands/media.py,sha256=drSKTf_BbyvXOGhS9UKwey_243Ic5XissoaxCykpd-c,5045
|
|
92
|
-
yee88/telegram/commands/menu.py,sha256=
|
|
92
|
+
yee88/telegram/commands/menu.py,sha256=vkvH0E4-sizhtyLgq5YRcptcWkzsVgMHkADxkQGscFo,4546
|
|
93
93
|
yee88/telegram/commands/model.py,sha256=GwdEHuebm02aUIqkcvznPh0FSViVlAjxeMks7TjFXIE,12729
|
|
94
94
|
yee88/telegram/commands/overrides.py,sha256=lLlIuCWkKwbS5WlQOOr_Ftv_EvfHR9DhjBpWaf6FBng,4853
|
|
95
95
|
yee88/telegram/commands/parse.py,sha256=0QVW1TVdBWadLbpJ9lRY3s7W4Cm62JJa9jfAaFHQmXU,887
|
|
96
96
|
yee88/telegram/commands/plan.py,sha256=iKsaRBS-qIfvAaxik5ZEA_VzAnFwx7aEED8sKXNq1wE,487
|
|
97
97
|
yee88/telegram/commands/reasoning.py,sha256=UFEJOHm4d0v2jFh5HC3oQGS41NYKbmJHRTaAmu_LiGo,8188
|
|
98
98
|
yee88/telegram/commands/reply.py,sha256=a3zkNjKzn3qZXEZFXuflX-tdhQKQyhYDqZskMy1nS3o,580
|
|
99
|
-
yee88/telegram/commands/topics.py,sha256=
|
|
99
|
+
yee88/telegram/commands/topics.py,sha256=TBUdhqtTyDv7I6qFlxeENPMfvZGkYUjvHsEI2Q2b2Mc,13899
|
|
100
100
|
yee88/telegram/commands/trigger.py,sha256=RgB4V7NoFdfDLk83xl3BPTsIIVr5A2zCNstR_5B_mEw,5201
|
|
101
101
|
yee88/utils/__init__.py,sha256=cV9_7v07Y6XkrUju0lHdO1ia0-Q57NqyFVMaFCg--do,34
|
|
102
102
|
yee88/utils/git.py,sha256=SVKcPNl2mUrv-cVHZQ5b8QXWKi33e_Jc4_vfCLwagkg,2413
|
|
@@ -104,8 +104,8 @@ yee88/utils/json_state.py,sha256=cnSvGbB9zj90GdYSyigId1M0nEx54T3A3CqqhkAm9kQ,524
|
|
|
104
104
|
yee88/utils/paths.py,sha256=_Tp-LyFLeyGD0P0agRudLuT1NR_XTIpryxk3OYDJAGQ,1318
|
|
105
105
|
yee88/utils/streams.py,sha256=TQezA-A5VCNksLOtwsJplfr8vm1xPTXoGxvik8G2NPI,1121
|
|
106
106
|
yee88/utils/subprocess.py,sha256=2if6IxTZVSB1kDa8SXw3igj3E-zhKB8P4z5MVe-odzY,2169
|
|
107
|
-
yee88-0.7.
|
|
108
|
-
yee88-0.7.
|
|
109
|
-
yee88-0.7.
|
|
110
|
-
yee88-0.7.
|
|
111
|
-
yee88-0.7.
|
|
107
|
+
yee88-0.7.1.dist-info/METADATA,sha256=CcgQN8xjM0IfbL-tv1FY8HcH4jz-tcPV27VROzOGgOg,4340
|
|
108
|
+
yee88-0.7.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
109
|
+
yee88-0.7.1.dist-info/entry_points.txt,sha256=P4MVZ_sZfrHaARVMImNJjoGamP8VDukARWMKfDh20V8,282
|
|
110
|
+
yee88-0.7.1.dist-info/licenses/LICENSE,sha256=poyQ59wnbmL3Ox3TiiephfHvUpLvJl0DwLFFgqBDdHY,1063
|
|
111
|
+
yee88-0.7.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|