问题报告:一份报告包含什么
当 aipager 遇到 bug 时,你只需点一下,就能给 aipager 开发者发送一份问题报告。在发送任何东西之前你都能看到完整的报告,在你同意之前没有任何东西会离开你的电脑,而且报告绝不包含你的聊天、消息、名称、路径或 token。它只由一份固定的字段列表构成:版本、次数、日期、是/否回答、来自固定列表的选项、aipager 自身代码中的位置以及它的 bug 的 ap1- 名称,再加上一条简短的备注(仅当你写了的时候)。
当 aipager 遇到 bug 时,你只需点一下,就能给 aipager 开发者发送一份问题报告。在发送任何东西之前你都能看到完整的报告,在你同意之前没有任何东西会离开你的电脑,而且报告绝不包含你的聊天、消息、名称、路径或 token。它只由一份固定的字段列表构成:版本、次数、日期、是/否回答、来自固定列表的选项、aipager 自身代码中的位置以及它的 bug 的 ap1- 名称,再加上一条简短的备注(仅当你写了的时候)。
如何发送#
只有 aipager 安装的所有者才能从 Telegram 发送报告:也就是在这个安装自己的私聊里与机器人对话的那个人(机器人主人;如果有好几个这样的私聊而没有唯一的所有者,就没有“报告问题”按钮,也没有自动提议,但终端里的 aipager report 仍然可用)。Mini App 有自己的报告页面;从 Telegram 进入的其他所有途径,都会在你和机器人的私聊里打开同一张预览卡片:
/help:所有者发送它时,帮助文字会带一个“🐞 报告问题”按钮。在群组里,只有所有者的点按才有作用,预览会在所有者的私聊里打开,绝不会在群组里打开。- Mini App:在设置标签页里,“报告问题”(当应用在你的私聊上打开时)会在应用内打开一个页面。你的备注在最上面(可选,最多 500 个字符,带计数器)。下面是报告的简短摘要:版本、设置、错误(点一个错误可查看它在代码中的位置)以及更多详情。显示报告原文会显示将要发送的确切文本,包括你的备注,并随你的输入而变化。发送报告(底部的 Telegram 按钮)只发送一次,发送的正是这份内容,然后页面会显示参考编号和一个复制按钮。返回不会发送任何东西。如果 aipager 整理了你的备注(两端的空格、不可见字符、超过 500 个字符的部分),页面会显示整理后的备注,并且在你再次点按“发送报告”之前什么都不会发送。
- 内存上限通知:当 aipager 的 hook 内存耗尽时,聊天里的通知会带一个“🐞 报告这个问题”按钮。
- 自动提议:aipager 偶尔会提议发送一份关于它注意到的 bug 的报告(见aipager 何时提议发送报告)。
- 在终端里:
aipager report打印一份报告并问Send this report? [y/N]。它包含同样类型的字段,但关于正在运行的 aipager 的信息更少(模式、聊天、功能、运行时长、会话和 Claude Code 的细节留空或标为未知)。aipager report --note "what you were doing"会添加一条备注。没有终端时(脚本、管道、Claude Code 会话的 shell),它只打印报告,绝不发送。
预览卡片会按将要发送的样子显示报告:一个可以展开的折叠块里的 JSON,或者在一条消息放不下时,作为回复这张卡片的 report.json 文件。它的按钮:
- 📤 发送:只发送一次,发送的正是这份报告。之后卡片显示
已发送。参考编号:ap1-...。 - ✏️ 添加备注:你在 10 分钟内在这个聊天里发送的下一条消息会成为报告的备注(在 500 个字符处截断),卡片会在你发送之前重新显示带有这条备注的报告。如果你先做了别的事(一个命令、另一个按钮、一张照片、Mini App 里的一个操作),备注的提问会关闭,不添加备注;10 分钟后,你的下一条消息会像平常一样发给 Claude。这个提问有 ‹ 返回(回到不带备注的预览)和取消。
- ✖️ 取消:不发送任何东西。
预览保持打开 24 小时,最新的 5 个保持打开(打开第 6 个会关闭最旧的一个)。aipager 重启之后,旧卡片就不能再发送了:再次打开“报告问题”获取一份新的。在 Mini App 里打开的报告可以在 24 小时内发送(最新的 3 个);重启后页面会加载一份新的。
一份报告包含什么#
用简单的话逐项说明。在显示预览之前以及在发送之前,每个值都会与允许值列表核对一次;任何不符合的值都会被替换为 <invalid> 或删去,绝不会原样发送。
关于报告
schema:报告格式(aipager-report/1)。trigger:manual(你自己打开的)或auto(自动提议)。day:日期,UTC(不含具体时间)。note:仅当你添加了备注时:你的原话,与预览显示的完全一致(最多 500 个字符,不含不可见字符)。
aipager 和电脑
aipager:版本;安装方式(pipx、uv、brew、pip、editable、nix、snap、docker、system、foreign或unknown);来源(软件包索引、本地文件夹、git 副本);aipager update能否升级它。python:Python 版本,以及是 CPython 还是 PyPy。os:系统(linux、darwin、windows、freebsd)、处理器类型、来自固定列表的 Linux 发行版及其版本号、内核的 major.minor 版本、容器类型(如果有:docker、lxc、wsl、podman),以及 aipager 是否被设置为 systemd 或 launchd 服务。deps:aipager 依赖的库的版本(python-telegram-bot、httpx、aiohttp、PyYAML、rich、questionary、dtach-bin)。claude_code:Claude Code 版本、找到了几个 Claude Code 安装,以及它的登录方式(env、file、keychain,或无法判断的原因)。绝不包含登录信息本身。
你的设置,以数量表示
config:模式(personal、team、scope);配置了多少个私聊、多少个群组;有多少个自定义角色(不含它们的名称);哪些功能已开启(Mini App 及其隧道类型、语音消息、改动预览、格式化摘要)。runtime:aipager 已运行多久,以区间表示(<10m、10m-1h、1-24h、1-7d、>7d);有多少会话在运行、多少在工作;过去 7 天里 aipager 意外停止了几次,以及上一次是如何结束的(clean、crash、reboot)。doctor:一份固定的健康检查列表的结果(ok、warn、fail),在无需重新运行检查就能获得时提供(来自机器人和终端的报告会把这一项留空)。flood:所有聊天汇总的 Telegram 限流状态:过去 7 天的封禁次数、此刻是否有聊天被停止发送、处于最小模式或正在放慢,以及最忙的聊天已用掉的每小时额度比例(以区间表示)。不含聊天 ID。
出了什么问题
counters_24h:一份固定列表中的每件事在过去 24 小时里发生了几次(例如工作卡片看守重启、某类 Telegram 错误、hook 触到内存上限、网络或磁盘错误)。只有次数。log_digest_24h:过去 24 小时里写入警告或错误日志最多的 aipager 代码中的 15 个位置,给出位置(aipager/state.py:1234)、级别和次数。绝不包含日志文本。errors:aipager 记录的最多 10 个错误,每个包括:fingerprint:bug 的ap1-名称(对错误类型以及 aipager 代码中最多 8 个位置的名称取哈希,绝不对任何文本或数据取哈希);- 它发生在哪里(aipager、hook、状态行、某个命令、Mini App)、它是如何被捕获的,以及它是 bug 还是只是不寻常的情况(
tier); - 对于 aipager 写入日志的错误,记录器的名称(一个
aipager模块、asyncio或telegram.ext的某部分); - 异常的类型名(例如
builtins.KeyError,或者来自固定软件包列表之外的异常记为<other>)、最多三个起因的类型,以及像ENOSPC这样的错误编号名; - 对于 hook 错误,hook 事件和工具(内置工具用其名称,任何 MCP 工具记为
mcp); - 它发生了几次、在哪几天、在哪些 aipager 版本上;
- 它经过的 aipager 自身代码中最多 12 个位置(文件、行、函数名),以及它经过的、来自固定列表的最多 8 个外部软件包名称。
绝不包含:你的聊天、消息、Claude 的回答、会话名称、文件夹或文件路径、token 或密钥、聊天或用户 ID、用户名、电脑的名称、任何错误消息的文本,以及日志行。上面的字段里没有它们的位置,而且报告在显示之前和发送之前都会与这份列表核对。
报告发到哪里#
报告会不带你的名字发到 aipager 开发者在 Sentry 上的私人错误收件箱:没有账号,也没有安装 ID。像任何网页请求一样,它来自你电脑的互联网地址,GitHub 和 Sentry 能看到这个地址;收件箱被设置为不保存它(Sentry 的“Prevent Storing of IP Addresses”选项)。aipager 用一次 HTTPS 请求自己发送报告(它不使用 Sentry 自己的库,那个库收集的东西要多得多):你看过的报告作为 report.json 附件发送,旁边附一份用于归类的简短摘要(版本、安装方式以及是否为开发版安装、系统、Python 和 Claude Code 版本、触发方式,以及第一个错误的指纹、类型和代码位置)。请求只注明 aipager/<version>。
发送后,卡片(或终端)会显示一个参考编号:第一个错误的 ap1- 指纹,或者对于没有错误的报告,它 32 个字符的事件 ID。如果你同时在 GitHub 上提 issue,请附上参考编号,方便开发者找到你的报告。不要把日志或 aipager doctor 的输出粘贴到 issue 里:其中有你的聊天 ID、你主文件夹的路径以及你消息的开头。
就在发送之前,aipager 会从 GitHub 上的 aipager 仓库读取 report-endpoint.json,以知道该发到哪里(正在运行的 aipager 会把一份可用的副本保留一天;读取失败会在下次发送时重试,每次 aipager report 都会重新读取)。这让开发者无需发布新版本,就能更换 Sentry 密钥、为所有人关闭报告,或阻止低于某个版本号的版本发送(无法判断自身版本的构建视为低于该版本)。如果无法连接 GitHub,或文件不是 aipager 能理解的格式,aipager 会使用这个版本内置的密钥;能读取且写明关闭的文件总是会被遵守。
限制#
- 每台电脑每天(UTC)最多尝试发送 5 次,手动和自动合计,失败的尝试也算。下一次会显示
每台电脑每天最多发送 5 份报告。请明天再试。 - 不会在后台重试:如果发送失败,卡片会显示
暂时无法发送。没有丢失任何内容;请稍后再试。,并保留发送按钮。
aipager 何时提议发送报告#
aipager 会注意到自己的 bug,偶尔会在你的私聊里提议发送关于它们的报告:aipager 在“工作卡片”里遇到了 N 次内部错误(TypeError)。报告能帮助更快修复问题。...,带有查看报告、暂不和不要再问。“查看报告”会打开只包含这些错误的预览卡片;在你在那里点按“发送”之前,什么都不会发送。
只有以下条件全部满足时,才会出现提议:
- 这是 aipager 真正的 bug:aipager 自身代码中的一个错误,至少发生两次且间隔至少 10 分钟,或者 aipager 作为服务运行时崩溃则立即算数(在前台运行的
aipager start被终止,例如因为关闭了它的终端,则只计数)。hook、状态行程序或某个命令报告给 aipager 的错误(包括 hook 内存耗尽)还必须分布在至少一天里,所以单独一次这样的错误绝不会引起提议;这类错误由通知上的“报告这个问题”按钮处理。不是 aipager 的过错的情况(Telegram 的限制、网络、磁盘已满)绝不会引起提议;它们只会被计数,用于你自己发送的报告。 - 每 3 天最多一次提议,期间所有待处理的内容合并在这一次提议里。
- 在 aipager 第一次在这台电脑上启动后的 48 小时内不会提议(更新不会让这个计时重新开始),在 aipager 重启后的第一个小时内也不会。
- 只在连续 2 分钟没有任何东西在运行或等待发送,并且你在过去 30 分钟内用过和机器人的私聊时。绝不在群组里,也绝不在 Telegram 正在限制那个聊天时。
- 每个 bug 在每个 aipager 版本上只提议一次。无论你怎么回答,它在那个版本上都不会再被提议;更新之后,只有再次发生时它才可能回来。
- 暂不和不要再问都算作“不”,一天之内没有回答的提议也算。查看报告会把计数清零,即使你之后取消了。连续两次“不”会关闭自动提议:如果第二次是点按的,会有一行文字告诉你;无论哪种情况,
/settings里都能看到。 - 绝不针对开发版安装(从本地文件夹、git 副本安装的 aipager,或 editable 模式安装的)。
要关闭自动提议,在你的私聊里使用 /settings:问题报告:关。当连续两次“不”关闭了它们时,同一个页面上会有重新开启提议。一个存在但无法读取的 reports.json 也会关闭自动提议(aipager 已无法知道你之前的回答);重新开启提议同样会清除这种状态。在没有聊天可以询问的电脑上,在 aipager 的环境里设置 AIPAGER_REPORT_PROMPTS=0。无论这些设置如何,“报告问题”和 aipager report 都始终可用。
保存在你电脑上的内容#
~/.local/state/aipager/reports.json:aipager 记录的错误(形式如上:类型名、版本、代码位置,最多 50 个)、8 天的每小时计数、2 天的日志摘要、最近几次停止是如何结束的,以及提议状态(上次提议的时间、连续“不”的次数、哪些 bug 在哪个版本上提议过)。只有你能读取。~/.local/state/aipager/report-sends.json:今天发送或尝试发送了多少份报告。~/.local/share/aipager/install.json:aipager 第一次在这台电脑上启动的时间(用于上面的 48 小时)。~/.local/share/aipager/running.json:在 aipager 运行期间写入(它的进程号、启动时间、是否作为服务运行,以及这次开机的 ID),用来区分崩溃和正常停止。
它们都不包含聊天、消息、名称、路径或 token。aipager uninstall 会保留它们以及 aipager 的其余数据,这样重新安装后可以接着上次继续;它会列出保留了哪些内容,并打印删除它们的命令(见 aipager uninstall)。只想删除这些,就删除这四个文件:删除整个 ~/.local/state/aipager 文件夹会删除前两个(连同语言状态 languages.json),但 install.json 和 running.json 必须按名称删除(不要删除 ~/.local/share/aipager,那里还存放着 aipager 的会话文件夹)。