mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
Feishu cards used to sit on "正在思考中..." for the entire turn and
then dump everything at message_complete, while Telegram showed the
reasoning and tool calls progressively. Two underlying causes:
1. handleServerMessage ignored `thinking`, `content_start{tool_use}`
and `tool_use_complete` entirely, so nothing was fed into the card
between turns of text output.
2. StreamingCard.performFlush silently set `cardKitStreamActive=false`
on any non-rate-limit error, after which all middle frames were
skipped and only finalize touched the card — exactly the
"long wait → all at once" symptom.
StreamingCard now tracks accumulatedReasoningText and a toolSteps
list, with appendReasoning / startTool / completeTool methods that
trigger throttled flushes like appendText. renderedText composes
tools → reasoning → answer in plain markdown (no blockquotes / lists
that historically tripped Feishu's parser). consecutiveStreamFailures
threshold (3) keeps a single transient error from killing the stream.
terminalText() is used by finalize so the final card holds only the
answer text, matching the Desktop UI's clean post-completion view.
handleServerMessage wires the new events to the existing per-chat
StreamingCard via the streamingCards map (read-only — never
auto-creates cards from thinking/tool events to avoid empty cards
for /clear-style commands).
Test coverage: realistic event-stream regression (thinking → tool_use
→ text → finalize), first-frame-failure recovery, finalize drops
intermediate state, plus per-method tests for the new APIs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code IM Adapters
当前目录只放 IM Adapter 运行时代码。
用户文档已经迁移到 docs/,并且以 Desktop Webapp 配置流程为准:
docs/im/index.mddocs/im/telegram.mddocs/im/feishu.md
当前方案摘要
当前真实链路是:
Desktop Webapp Settings
-> /api/adapters
-> ~/.claude/adapters.json
-> adapters/<platform>/index.ts
-> /api/sessions + /ws/:sessionId
-> Claude Code session
注意两点:
- IM 配置和配对都在 Desktop Webapp 的
Settings -> IM 接入 - Webapp 不会自动启动 Adapter 进程,仍需手动运行
bun run telegram或bun run feishu
快速启动
cd adapters
bun install
bun run telegram
# 或
bun run feishu
开发
运行测试
cd adapters
bun test
bun test common/
bun test telegram/
bun test feishu/
目录结构
adapters/
├── common/
│ └── attachment/ # 跨平台附件工具(types / limits / store / image-watcher)
├── telegram/
│ └── media.ts # TelegramMediaService(grammy Bot API 封装)
├── feishu/
│ ├── media.ts # FeishuMediaService(@larksuiteoapi/node-sdk 封装)
│ └── extract-payload.ts # 入站 im.message.receive_v1 事件解析
├── package.json
├── tsconfig.json
└── README.md
附件收发
两个 Adapter 都支持双向图片/文件,和 Desktop 端走同一套 AttachmentRef 协议透传给主进程。
入站(用户 → Claude):
- 飞书: 图片(jpg/png/gif/webp/heic)、文档(doc/xls/ppt/pdf 等)、post 富文本里的 img/file 元素
- Telegram: photo、document、video、audio、voice
下载落地到 ~/.claude/im-downloads/{platform}/{sessionId}/,24 小时后自动 GC(.part 孤文件 10 分钟超时)。大小限制:单张图 ≤10 MB、单个文件 ≤30 MB,超限直接拒收并在 IM 里提示。
出站(Claude → 用户):
Agent 流式文本里的 markdown 图片引用  会被 ImageBlockWatcher 识别、上传到 IM 平台,作为独立图片消息发出:
- 飞书:
im.message.create(msg_type='image')单发(card 内嵌是后续优化) - Telegram:
bot.api.sendPhoto(InputFile)单发
非图片类出站(Agent 产的 pdf/zip 等)暂不支持。
设计细节: docs/superpowers/specs/2026-04-11-im-attachment-support-design.md。