pi-channels-streaming-card

Pi messaging channels (Feishu/Lark, DingTalk, WeCom, webhooks) with native streaming cards: CardKit typewriter output, collapsible thinking/tools timeline, and context-window footer. Fork of @amaster.ai/pi-channels.

Packages

Package details

extension

Install pi-channels-streaming-card from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-channels-streaming-card
Package
pi-channels-streaming-card
Version
0.2.0
Published
Aug 9, 2026
Downloads
140/mo · 14/wk
Author
davidhe607
License
Apache-2.0
Types
extension
Size
296.4 KB
Dependencies
4 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./dist/index.js"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-channels-streaming-card

Pi 消息通道插件(飞书/Lark、DingTalk、企微、webhook),内置原生流式卡片能力,并针对飞书深度增强:图片自动识别重启自愈答案兜底

Fork 自 @amaster.ai/pi-channels(Apache-2.0),新增飞书流式卡片 + 视觉识别 + 自愈能力。

✨ 特性

  • 飞书打字机流式输出:基于飞书 CardKit cardElement.content 接口,文字逐字蹦出(动画跟随生成速度,不拖慢输出)
  • 思考与工具折叠面板:思考过程、工具调用收进原生 collapsible_panel(默认收起,点击展开);上一轮答案归档为「过程 N」同样收纳
  • 上下文底栏已完成 · 耗时 · 模型 · ↑输入 · ↓输出 · ctx 用量/窗口 百分比
  • 🖼 飞书图片自动识别(无需切换模型)
    • 图片消息到达后自动通过 im.messageResource.get 拉取字节,纯内存处理(零磁盘写入)
    • 自动调用视觉模型(qwen-vl-plus 等,从 models.json 读取)生成描述,前置注入主模型提示词
    • 主模型保持 deepseek-v4-flash 等文本模型即可「看懂」图片
  • 🛟 重启自愈
    • 流式卡片状态持久化到 card-state.json(创建即存、流式中节流保存、完成即删)
    • 启动时自动把上次中断的卡片标记为 ⚠️ 已中断(重启),不再永久卡在「思考中」
    • 孤儿集合只在启动时捕获一次,重试窗口绝不误伤新创建的流式卡片
  • 📨 答案兜底:若卡片中途死亡(更新全部失败),自动转纯文本消息补发,答案永不丢失
  • 🖼 图片消息卡片独立发送:回复图片消息时卡片以新消息发送,规避飞书引用缩略图的兼容问题
  • 其他通道(DingTalk/企微/webhook)保持原 pi-channels 行为不变

📦 安装

先卸载原版 pi-channels(避免冲突),再安装本插件:

pi remove npm:@amaster.ai/pi-channels
pi install npm:pi-channels-streaming-card     # 发布到 npm 后
# 或从 GitHub 安装:
pi install git:github.com/<你的用户名>/pi-channels-streaming-card

重启 pi 生效:

# 交互模式下 /reload,或重启进程

⚙️ 配置

配置方式和 pi-channels 完全一致(~/.pi/agent/settings.json):

{
  "pi-channels": {
    "adapters": {
      "feishu": {
        "type": "feishu",
        "appId": "cli_xxx",
        "appSecret": "xxx",
        "eventMode": "websocket",
        "respondToMentionsOnly": true
      }
    },
    "bridge": {
      "enabled": true,
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "streamingCards": true
    }
  }
}

bridge.streamingCards: true 开启飞书流式卡片(CardKit 打字机)。

🖼 图片识别配置(可选)

~/.pi/agent/models.json 配置任意 OpenAI 兼容的视觉模型即可(插件自动探测含 vl/vision/image 的模型 id):

{
  "providers": {
    "qwen-vl": {
      "baseUrl": "https://<你的百炼网关>/compatible-mode/v1",
      "apiKey": "sk-xxx",
      "api": "openai-completions",
      "models": [{ "id": "qwen-vl-plus", "name": "通义千问 VL Plus(识图)" }]
    }
  }
}

未配置视觉模型时,图片消息降级为纯文本 [图片],不影响其他功能。

🎴 卡片效果

┌─────────────────────────────────┐
│ π pi                    ✅ 已完成 │  ← 头部状态(蓝=进行中/绿=完成/红=失败/橙=中断)
│                                  │
│  答案内容(打字机逐字输出)        │  ← 主内容(仅最终答案)
│                                  │
│  ▸ 思考与工具 · 6 次工具调用      │  ← 原生折叠面板(默认收起)
│    - 思考 1 · completed          │
│    - ✓ bash                     │
│    - ✕ edit · 失败              │
│─────────────────────────────────│
│ 已完成 · 28s · deepseek-v4-flash │  ← 底栏
│ · ↑129k · ↓379 · ctx 129k/1m 13%│
└─────────────────────────────────┘

🛠 实现说明

  • 创建卡片实体:POST /cardkit/v1/cardsstreaming_mode: true
  • 发送卡片:im.message.create + content: {type:"card", data:{card_id}}(图片消息改为独立新消息,不 reply)
  • 流式文本:PUT /cardkit/v1/cards/{id}/elements/{element_id}/content(打字机动效,print_strategy: "fast" 保证不落后于生成速度)
  • 结构更新:PUT /cardkit/v1/cards/{id} 全量更新(头部状态、折叠面板、底栏)
  • 完成时:card.settings 关闭 streaming_mode(移除打字光标)
  • CardKit 失败时自动回退到 im.message.patch 全卡更新(功能不中断)
  • 图片识别:im.messageResource.getparams: {type:'image'})→ 内存字节 → base64 data URL → OpenAI 兼容 /chat/completions 视觉请求
  • 自愈:卡片快照持久化 → 启动时 healOrphanedCards(仅处理启动时存在的孤儿,3s 延迟 + 指数退避重试,序列号大跳步规避 sequence 冲突)

📄 许可

Apache-2.0(与上游 pi-channels 一致)