npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-agent-qqbot

v1.0.4

Published

Pi extension that connects the official QQ Bot API to the active native Pi coding agent session.

Readme

Pi Agent QQBot

English | 简体中文

English

Connect a QQ C2C conversation to the native Pi session that is already running in your terminal, using the official QQ Bot API.

Why This Exists

QQ is not a separate agent. It is a second input surface for the same Pi runtime: terminal and QQ share the working directory, model, tools, context, session history, and extension-created interaction UI.

Use the same live coding session from QQ when you are away from the terminal, without creating a second agent, duplicating context, or exposing a general-purpose remote command shell.

Requirements

  • Pi >=0.82.0 <1.0.0
  • Node.js >=22.19.0
  • An official QQ bot with C2C direct messages enabled
  • Native Windows, macOS, or Linux

WSL path translation and mixed Windows/WSL installations are not supported.

Highlights

  • Bind one configured QQ C2C owner to the active native Pi session.
  • Work from QQ with the same workspace, model, context, and session history.
  • Use QQ Keyboard controls for models, thinking levels, and native Pi sessions.
  • Deliver ctx.ui.confirm(), select(), and input() to both terminal and QQ. The first response from either side wins.
  • Operate extension-created ctx.ui.custom() remotely through a TUI snapshot, keys, and text input.
  • Receive images, voice, documents, and ordinary files without extension-level file count, type, or size quotas.
  • Send verified local files through QQ's official chunked-upload API.
  • Transfer Gateway ownership between local Pi processes without stopping either process.

Install

Install the published npm package:

pi install npm:pi-agent-qqbot

You can also install a tagged GitHub release:

pi install git:github.com/gtiders/[email protected]

When HTTPS access to GitHub is unavailable, use SSH:

pi install git:[email protected]:gtiders/[email protected]

Completely exit and restart Pi after installation or upgrade.

Configure

Create ~/.pi/agent/pi-agent-qqbot.json. On Windows, this is %USERPROFILE%\.pi\agent\pi-agent-qqbot.json.

{
  "schemaVersion": 5,
  "appId": "YOUR_QQBOT_APP_ID",
  "clientSecret": "YOUR_QQBOT_APP_SECRET",
  "sandbox": true,
  "ownerOpenId": "",
  "link": { "conflictPolicy": "ask" },
  "inboundMedia": { "deniedKinds": [], "deniedExtensions": [] },
  "outboundMedia": {
    "enabled": false,
    "deniedRoots": [],
    "deniedKinds": [],
    "deniedExtensions": []
  },
  "logging": { "level": "info" }
}

Only schema 5 is accepted. Earlier configurations are neither read nor migrated. For first-time setup, leave ownerOpenId empty and use /qqbot-start to discover and confirm it locally.

| Field | Meaning | | --- | --- | | appId | QQ bot application ID. | | clientSecret | QQ bot secret. Never commit a real value. | | sandbox | Use QQ's sandbox endpoint when true. | | ownerOpenId | The only QQ C2C user allowed to access Pi. Leave it empty only during first-time bootstrap. | | link.conflictPolicy | ask requests terminal approval before takeover; takeover transfers ownership automatically. | | inboundMedia.deniedKinds | Deny image, video, voice, or file; an empty list denies no type. | | inboundMedia.deniedExtensions | Deny file extensions such as .exe; an empty list denies none. | | inboundMedia.stt | Optional OpenAI-compatible speech-to-text settings: baseUrl, apiKeyEnv, and model. | | outboundMedia.enabled | Master switch for local file delivery; defaults to false. | | outboundMedia.deniedRoots | Real directory roots that must never be sent; an empty list permits every path readable by the current account. | | outboundMedia.deniedKinds | Deny outbound media types; an empty list denies none. | | outboundMedia.deniedExtensions | Deny outbound extensions; an empty list denies none. | | logging.level | error, info, or debug. |

Media policies use denylist semantics. An omitted field or empty list adds no product-level restriction. QQ platform limits and file-integrity checks still apply.

Start and Link

The extension does not connect to QQ automatically. For normal use, run this command in the local terminal for each new Pi process:

/qqbot-link

For first-time setup only: save appId and clientSecret, leave ownerOpenId empty, run /qqbot-start, then send any C2C message to the bot. Pi displays the detected user_openid locally; after terminal confirmation it saves the value. Run /qqbot-link afterwards.

| Local command | Purpose | | --- | --- | | /qqbot-start | First-time bootstrap only. Temporarily starts the Gateway to discover the first private sender OpenID; terminal confirmation writes it to the config and stops bootstrap. | | /qqbot-stop | Stop transport only; preserve the link and native Pi session. | | /qqbot-link | Start the QQ Gateway and bind the configured owner to the current Pi runtime. | | /qqbot-unlink | Remove the logical link and invalidate pending QQ replies. | | /qqbot-status | Show Gateway, ownership, link, session, model, and queue state. | | /qqbot-takeover | Take Gateway ownership from another local Pi process. |

QQ cannot run /qqbot-* commands.

QQ Commands

QQ commands are explicitly allowlisted and appear as a Keyboard when supported by the client.

| Command | Purpose | | --- | --- | | /help | Show the command menu. | | /status | Show the active link and Pi state. | | /model [provider/model] | Browse, search, or switch the active model. | | /thinking [level] | Show or change the thinking level. | | /new [name] | Create a native Pi session, optionally named. | | /sessions [query] | List or search native Pi sessions. | | /resume <id-or-name> | Switch to a uniquely matching native Pi session. | | /name <name> | Rename the current session. | | /compact [instructions] | Compact the active context. | | /stop | Abort the active Pi turn. |

Normal QQ text is injected into the linked Pi session and uses Pi's native follow-up delivery while Pi is busy. Only output from QQ-originated turns is returned to QQ; output from terminal-originated turns remains in the terminal.

Shared Interaction UI

When a QQ-originated turn opens ctx.ui.confirm(), ctx.ui.select(), or ctx.ui.input(), both QQ and terminal receive the interaction. The first side to complete it wins and invalidates the other side.

For extension-created ctx.ui.custom(), both surfaces operate the same component instance. QQ receives a 72-column TUI snapshot with terminal control sequences removed, plus directional, paging, Home/End, Tab, space, backspace, delete, submit, cancel, and refresh controls. Normal QQ text is injected as terminal bracketed-paste input, including into password fields.

Pi core TUI, external PTY programs, and custom UI opened only by terminal-originated turns are outside this relay's scope.

Media

Inbound media has no extension-level count, type, individual-size, or total-size quotas. Images go to image-capable models; supported documents are extracted within remaining context budget; voice uses QQ ASR text when available; unknown files remain as temporary local resources for Pi tools.

Inbound downloads still enforce HTTPS, SSRF protection, bounded redirects, cancellation, and stalled-network detection.

With outbound media enabled, the qq_send_local_file tool can send a local file only to the original conversation of the current QQ turn. Candidates are checked with realpath, regular-file identity, hard-link, symlink/junction, and rename-race validation. QQ's 200 MB upload limit and passive-reply count remain platform constraints.

Current Boundaries

  • One configured QQ C2C owner only. Group messages and other users are ignored before attachment handling and agent work.
  • The Gateway does not start automatically with the extension. Run /qqbot-link for normal operation.
  • Pi 0.82 can discover Skills, prompt templates, and extension commands, but does not expose a complete public input-dispatch API. QQ therefore cannot generically execute every Skill, template, or third-party slash command; it supports only the allowlisted commands above.
  • Restart Pi completely after upgrading an installed package.

Troubleshooting

  • Invalid configuration: verify schemaVersion, appId, clientSecret, and ownerOpenId.
  • No QQ response: run /qqbot-status, then run /qqbot-link locally.
  • Missing ownerOpenId: leave it empty, run /qqbot-start, message the bot from QQ, and confirm the displayed OpenID in the terminal.
  • Gateway owned by another Pi: run /qqbot-takeover, or retain conflictPolicy: "ask" and approve in the terminal.
  • Cannot send local files: set outboundMedia.enabled to true, then restart Pi.
  • QQ buttons unavailable: send the corresponding text command shown on the card.

Development

See the development guide for architecture, development, and release procedures, and CHANGELOG for release history.

License

Apache-2.0


简体中文

通过 QQ 官方机器人 API,将一个 QQ 私聊连接到终端中正在运行的原生 Pi 会话。

为什么需要它

QQ 不是另起一个 Agent,而是同一 Pi runtime 的第二个输入端:终端与 QQ 共享工作目录、模型、工具、上下文、会话历史,以及扩展创建的交互界面。

离开终端时也能从 QQ 继续使用同一个实时编码会话,无需另起 Agent、复制上下文,也不会把 Pi 暴露成通用远程命令终端。

环境要求

  • Pi >=0.82.0 <1.0.0
  • Node.js >=22.19.0
  • 已启用 C2C 私聊消息的 QQ 官方机器人
  • 原生 Windows、macOS 或 Linux

不支持 WSL 路径转换,也不支持 Windows/WSL 混合安装。

主要能力

  • 将唯一配置的 QQ C2C owner 绑定到当前原生 Pi 会话。
  • 从 QQ 操作同一工作目录、模型、上下文和会话历史。
  • 使用 QQ Keyboard 切换模型、思考等级和原生 Pi 会话。
  • ctx.ui.confirm()select()input() 同时发送到终端和 QQ,任意一端先完成即生效。
  • 通过 TUI 快照、按键和文字输入远程操作扩展创建的 ctx.ui.custom()
  • 接收图片、语音、文档及普通文件,不增加扩展层文件数量、格式或大小配额。
  • 通过 QQ 官方分片上传 API 发送经过本地文件身份校验的文件。
  • 在本机多个 Pi 进程间转移 Gateway 所有权,不终止任何 Pi 进程。

安装

安装 npm 正式版本:

pi install npm:pi-agent-qqbot

也可以从 GitHub 的版本标签安装:

pi install git:github.com/gtiders/[email protected]

如果本机无法通过 HTTPS 连接 GitHub,可使用 SSH:

pi install git:[email protected]:gtiders/[email protected]

安装或升级后必须完整退出并重新启动 Pi。

配置

创建 ~/.pi/agent/pi-agent-qqbot.json。Windows 路径为 %USERPROFILE%\.pi\agent\pi-agent-qqbot.json

{
  "schemaVersion": 5,
  "appId": "YOUR_QQBOT_APP_ID",
  "clientSecret": "YOUR_QQBOT_APP_SECRET",
  "sandbox": true,
  "ownerOpenId": "",
  "link": {
    "conflictPolicy": "ask"
  },
  "inboundMedia": {
    "deniedKinds": [],
    "deniedExtensions": []
  },
  "outboundMedia": {
    "enabled": false,
    "deniedRoots": [],
    "deniedKinds": [],
    "deniedExtensions": []
  },
  "logging": {
    "level": "info"
  }
}

扩展只接受 schema 5,不读取也不迁移过时配置。首次配置时可将 ownerOpenId 留空,通过 /qqbot-start 在本地发现并确认写入。

| 字段 | 含义 | | --- | --- | | appId | QQ 机器人应用 ID。 | | clientSecret | QQ 机器人密钥,不得提交真实值。 | | sandbox | true 表示使用 QQ 沙箱端点。 | | ownerOpenId | 唯一允许访问 Pi 的 QQ C2C 用户;仅首次引导时可留空。 | | link.conflictPolicy | ask 在接管前请求终端确认;takeover 自动转移所有权。 | | inboundMedia.deniedKinds | 禁止 imagevideovoicefile;空数组表示不禁止类型。 | | inboundMedia.deniedExtensions | 禁止 .exe 等扩展名;空数组表示不禁止扩展名。 | | inboundMedia.stt | 可选的 OpenAI 兼容语音转写配置:baseUrlapiKeyEnvmodel。 | | outboundMedia.enabled | 本地文件出站总开关,默认 false。 | | outboundMedia.deniedRoots | 永远禁止发送的真实目录根路径;空数组允许所有当前账户可读路径。 | | outboundMedia.deniedKinds | 禁止出站媒体类型;空数组表示不禁止类型。 | | outboundMedia.deniedExtensions | 禁止出站文件扩展名;空数组表示不禁止扩展名。 | | logging.level | errorinfodebug。 |

媒体配置统一采用黑名单语义:字段缺失或数组为空表示不增加产品限制。QQ 平台硬限制和文件完整性校验仍然生效。

启动与绑定

扩展加载时不会自动连接 QQ。正常使用时,每个新的 Pi 进程都需要在本地终端执行:

/qqbot-link

仅首次配置:先写入 appIdclientSecret,将 ownerOpenId 留空,执行 /qqbot-start,再从 QQ 私聊机器人发送任意消息。Pi 会在本地显示收到的 user_openid;终端确认后自动写入配置。随后执行 /qqbot-link

本地专用命令:

| 命令 | 作用 | | --- | --- | | /qqbot-start | 仅首次引导使用。临时启动 Gateway 发现第一位私聊用户的 OpenID;终端确认后写入配置并停止引导。 | | /qqbot-stop | 只停止传输,保留 link 和当前原生 Pi 会话。 | | /qqbot-link | 启动 QQ Gateway,并将配置的 owner 绑定到当前 Pi runtime。 | | /qqbot-unlink | 解除逻辑 link,并使未完成的旧 QQ 回复失效。 | | /qqbot-status | 查看 Gateway、所有权、link、会话、模型和队列状态。 | | /qqbot-takeover | 从本机另一个 Pi 进程接管 Gateway。 |

QQ 端不能执行任何 /qqbot-* 命令。

QQ 命令

QQ 命令采用显式白名单,并在客户端支持时显示 Keyboard:

| 命令 | 作用 | | --- | --- | | /help | 显示命令菜单。 | | /status | 查看当前 link 和 Pi 状态。 | | /model [provider/model] | 浏览、搜索或切换当前模型。 | | /thinking [level] | 查看或切换思考等级。 | | /new [name] | 新建原生 Pi 会话,可同时命名。 | | /sessions [query] | 列出或搜索原生 Pi 会话。 | | /resume <id-or-name> | 切换到唯一匹配的原生 Pi 会话。 | | /name <name> | 重命名当前会话。 | | /compact [instructions] | 压缩当前上下文。 | | /stop | 中止当前 Pi 回合。 |

普通 QQ 文本会注入已绑定的 Pi 会话;Pi 忙碌时按原生 follow-up 投递。只有 QQ 发起的回合会回复 QQ,终端发起的输出只留在终端。

双端交互界面

QQ 发起的回合打开 ctx.ui.confirm()ctx.ui.select()ctx.ui.input() 时,终端与 QQ 会同时收到交互。任意一端最先完成即生效,另一端随即失效。

扩展创建的 ctx.ui.custom() 在两端共享同一个组件实例。QQ 会收到去除终端控制序列后的 72 列 TUI 快照,并提供方向键、翻页、Home/End、Tab、空格、退格、删除、确认、取消和刷新。普通 QQ 文本按终端 bracketed paste 输入,包括密码字段。

Pi 核心 TUI、外部 PTY 程序,以及仅由终端回合打开的自定义界面不在代理范围内。

媒体

入站媒体没有扩展层数量、格式、单文件或总大小配额。图片会传给支持图片的模型,已支持的文档按剩余上下文预算提取,语音优先使用 QQ ASR 文本,未知文件保留为临时本地资源供 Pi 工具读取。

入站下载仍强制 HTTPS、SSRF 防护、有限重定向、取消处理和网络停滞检测。

启用出站媒体后,qq_send_local_file 工具只能向当前 QQ 回合的原始会话发送本地文件。候选文件会经过 realpath、普通文件身份、hard-link、symlink/junction 和 rename-race 校验。QQ 的 200 MB 上传上限与被动回复次数仍是平台约束。

当前边界

  • 只支持一个配置的 QQ C2C owner;群消息和其他用户会在附件处理与 Agent 工作前被忽略。
  • Gateway 不会随扩展自动启动;日常运行请执行 /qqbot-link
  • Pi 0.82 可以发现 Skills、提示词模板和扩展命令,但没有公开完整输入分发 API。因此 QQ 不能通用执行任意 Skill、模板或第三方 slash command,只能使用上面的白名单命令。
  • 升级已安装包后必须完整重启 Pi。

故障排查

  • 提示配置无效:检查 schemaVersionappIdclientSecretownerOpenId
  • QQ 没有响应:先运行 /qqbot-status,再在本地执行 /qqbot-link
  • 缺少 ownerOpenId:将其留空,执行 /qqbot-start,从 QQ 向机器人发消息,并在终端确认显示的 OpenID。
  • Gateway 被其他 Pi 占用:执行 /qqbot-takeover,或保留 conflictPolicy: "ask" 并在终端批准。
  • 无法发送本地文件:将 outboundMedia.enabled 设置为 true,然后重启 Pi。
  • QQ 按钮不可用:直接发送卡片中显示的对应文字命令。

开发

开发、架构与发布流程见 开发指南,发布记录见 CHANGELOG

License

Apache-2.0