pi-webapp 0.1.10 → 0.1.12

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.
@@ -0,0 +1,75 @@
1
+ # 用 Sentry CLI + Codex 分析已有问题
2
+
3
+ 在仓库根目录运行。流程读取 Sentry 的 Issue 和多个事件样本,让 Codex 对照本地源码分析,生成中文 Markdown 和结构化 JSON 报告。它不修改应用代码或 Sentry 问题状态,也不调用 Seer。
4
+
5
+ ## 首次准备
6
+
7
+ ```sh
8
+ npm install -g sentry
9
+ sentry auth login --read-only
10
+ sentry auth status
11
+ codex login status
12
+ ```
13
+
14
+ 需要官方 `sentry` CLI(不是旧的 `sentry-cli` 命令)和已登录的 Codex CLI。账号须能读取目标组织和项目。OAuth 凭据由 CLI 保存,不写入仓库。Codex 使用用户现有的模型和登录配置;分析会消耗正常 Codex 使用额度。
15
+
16
+ ## 运行
17
+
18
+ ```sh
19
+ # 最近 7 天仍未解决的问题:最多 20 个,每个最多读取 3 个事件
20
+ npm run sentry:triage
21
+
22
+ # 调整范围。按发生次数排序;limit 最大 1000
23
+ npm run sentry:triage -- --period 30d --limit 50 --events 5
24
+
25
+ # 专门看 edit 工具的未知失败
26
+ npm run sentry:triage -- --query 'is:unresolved toolName:edit failureKind:unknown'
27
+
28
+ # 只拉取证据,在当前 Codex 聊天中分析,或稍后重用
29
+ npm run sentry:triage -- --collect-only
30
+
31
+ # 重用已有证据,不再访问 Sentry
32
+ npm run sentry:triage -- --input artifacts/sentry-triage/run-XXXXXX/evidence.json
33
+
34
+ # 也支持 Sentry 下载的单个原始事件 JSON
35
+ npm run sentry:triage -- --input /absolute/path/event.json
36
+ ```
37
+
38
+ 默认目标为 `soft/pi-webapp`,可用 `--project org/project` 更改。默认排除 `sentry-verification`,自定义 Issue 查询会替换默认查询。事件采样始终排除验证环境。
39
+
40
+ 每次创建独立的 `artifacts/sentry-triage/run-*` 目录,避免覆盖之前的结果。`artifacts/` 已被 Git 忽略。
41
+
42
+ | 文件 | 内容 |
43
+ | --- | --- |
44
+ | `evidence.json` | Issue 摘要、事件异常和 breadcrumbs、诊断上下文、采样范围 |
45
+ | `prompt.md` | 本次分析的规则和输入位置 |
46
+ | `report.schema.json` | 结构化输出格式 |
47
+ | `report.json` / `report.md` | 已校验的分类、修复判断、证据、代码位置和下一步 |
48
+ | `analysis.json` / `codex.log` | Codex 原始分析结果及运行日志;失败时不一定存在 |
49
+
50
+ 报告只在完整性校验通过后写出。Issue 列表查询失败会直接退出;某个 Issue 的事件读取失败会记录采集限制,要求对该 Issue 判为证据不足,不能悄悄丢弃。
51
+
52
+ ## 判断规则
53
+
54
+ | 分类 | 含义 |
55
+ | --- | --- |
56
+ | `app_bug` | 有证据支持的 pi-webapp 程序缺陷 |
57
+ | `dependency_or_external` | Pi、插件、网络或外部服务问题 |
58
+ | `expected_tool_failure` | 已识别的正常工具失败结果;不代表用户任务成功 |
59
+ | `monitoring_gap` | 错误分类、上报级别、重复采集或诊断信息的缺口 |
60
+ | `insufficient_evidence` | 无法确认根因,需要补充证据 |
61
+
62
+ 修复判断为 `fix`、`no_fix`、`monitor` 或 `investigate`,同时输出 P0–P3 优先级和 high/medium/low 置信度。分类是模型的有证据分析,仍需审阅。脚本校验枚举、Issue 覆盖和部分判断约束,不能代替对根因的验证。
63
+
64
+ 每个 Issue 有一个主要结论,并允许附带独立发现。例如 `edit: unknown` 的实际失败原因可以判为证据不足,同时建议补充监控分类;不能把两者合并成“已确认编辑功能 BUG”。
65
+
66
+ ## 数据和范围
67
+
68
+ - 默认分析最近活跃的未解决问题,不是所有历史错误。需要分析已解决问题时使用自定义 `--query`。
69
+ - `issueLimitReached` 为 true 时,可能还有未读取的 Issue;增加 `--limit` 或缩小查询范围。每个 Issue 的事件是近期样本,不是随机采样,也不保证覆盖所有版本。
70
+ - `count`、`lifetime` 和所选时间内的统计可能不同;采集限流也会少计事件。用户数为 0 不能证明没有影响用户,`handled=true` 不能证明没有功能故障。
71
+ - 报告记录本地 Git revision。工作区可能含未提交修改,本地代码不一定等于事件发布版本。报告应说明版本匹配的证据或限制。
72
+ - 不保留事件中的 request、user、附件、frame vars 或任意 extra 字段。异常文本与 breadcrumbs 仍可能含业务信息;证据、报告及运行日志是本地诊断资料,不进入 Git 或 npm 包。Codex 会读取这些证据并通过当前配置的模型服务分析。
73
+ - Codex 用 `--sandbox read-only` 分析源码,最终报告由宿主脚本保存。规则禁止在分析中修改代码、更新 Sentry、发消息或读取凭据。无需在 pi-webapp 运行时配置查询凭据。
74
+
75
+ 参考:[Sentry CLI 安装](https://cli.sentry.dev/getting-started/)、[Issue 命令](https://cli.sentry.dev/commands/issue/)、[Codex 非交互运行](https://learn.chatgpt.com/docs/non-interactive-mode)。
package/docs/sentry.md CHANGED
@@ -26,6 +26,8 @@ Browser events go directly to the configured Sentry host with no Pi authorizatio
26
26
 
27
27
  ## Diagnosing a tool failure
28
28
 
29
+ For CLI + Codex analysis of existing issues, including classifications and repair decisions, see [Sentry triage](sentry-triage.md). Run `npm run sentry:triage` from the repository after authenticating the Sentry and Codex CLIs.
30
+
29
31
  Both TUI and SDK workspace sessions observe `tool_execution_start/end`. A failed `message_end` is a fallback only: the same tool call is not reported twice. Tool execution behavior and visible results are unchanged.
30
32
 
31
33
  | Diagnostic field | Meaning |
@@ -53,6 +55,8 @@ Filter Sentry by `side:node`, `toolName`, `failureKind` and `errorCode`, then in
53
55
 
54
56
  ## Performance and reliability
55
57
 
58
+ After an accepted update, browser version polling retains temporary network failures as `request_failed` breadcrumbs while waiting for the restarted service. If the target version is still unavailable after 60 seconds, it stops polling and reports one `stage=update_restart`, `code=update_restart_timeout` error, even if a request is still pending. Closing settings cancels the pending request and deadline. HTTP and response parsing failures, and network failures from other requests, retain normal reporting.
59
+
56
60
  Each side sends at most 20 events/minute and one event per fingerprint/minute. Repetition counts appear on the next retained event. Startup and transport queues are bounded to 20 events. Transport requests time out after 3 seconds, do not persist offline, and do not retry indefinitely. Rate-limited/dropped events are intentionally lossy. Browser configuration has a 1-second timeout and never gates rendering; SDKs load only when reporting is enabled. No tracing, profiling, automatic console/DOM instrumentation or token-by-token logging is enabled.
57
61
 
58
62
  Request failures and asynchronous error events include additive `errorId`, `requestId`, `operationId`, `errorCode` and `errorReported` metadata. `errorReported` prevents the browser from bypassing server-side deduplication/rate limits. Protocol version 7 is retained. A `shutdown` event stops reconnection on normal exit; controlled launcher upgrades mark it with `reconnect: true` so the browser reconnects without reporting the expected interruption. A changed build ID replaces a retained bridge on `/web` after `/reload` so its static manifest matches the new assets.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-webapp",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "description": "A browser interface for Pi with live chat, workspaces, models, and attachments",
6
6
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "pi-webapp": "./bin/pi-webapp.mjs"
16
16
  },
17
17
  "pi": {
18
- "image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.10/assets/cover-webapp.png",
18
+ "image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.12/assets/cover-webapp.png",
19
19
  "extensions": [
20
20
  "./dist/extension.js"
21
21
  ]
@@ -29,7 +29,8 @@
29
29
  "README.zh-CN.md",
30
30
  "LICENSE",
31
31
  "web/src/ui/shared/LICENSE.txt",
32
- "docs/sentry.md"
32
+ "docs/sentry.md",
33
+ "docs/sentry-triage.md"
33
34
  ],
34
35
  "scripts": {
35
36
  "start": "npm run build && node bin/pi-webapp.mjs",
@@ -45,6 +46,7 @@
45
46
  "build:sentry": "node scripts/build.mjs all --sentry",
46
47
  "verify:package": "node scripts/verify-sentry-release.mjs --package-only",
47
48
  "verify:sentry": "node scripts/verify-sentry-release.mjs --live",
49
+ "sentry:triage": "node scripts/sentry-triage.mjs",
48
50
  "test:browser": "playwright test"
49
51
  },
50
52
  "publishConfig": {
@@ -122,13 +122,13 @@
122
122
  "isDynamicEntry": true
123
123
  },
124
124
  "../../node_modules/@shikijs/langs/dist/graphql.mjs": {
125
- "file": "assets/graphql-DvPK7yuL.js",
125
+ "file": "assets/graphql-IPoCyjbx.js",
126
126
  "name": "graphql",
127
127
  "src": "../../node_modules/@shikijs/langs/dist/graphql.mjs",
128
128
  "isDynamicEntry": true,
129
129
  "imports": [
130
130
  "_javascript-D_ijBMSX.js",
131
- "_app-B2Ac56ic.js",
131
+ "_app-Boh5DRzv.js",
132
132
  "index.html"
133
133
  ]
134
134
  },
@@ -161,12 +161,12 @@
161
161
  ]
162
162
  },
163
163
  "../../node_modules/@shikijs/langs/dist/http.mjs": {
164
- "file": "assets/http-B5WHvjtS.js",
164
+ "file": "assets/http-k59Hanmf.js",
165
165
  "name": "http",
166
166
  "src": "../../node_modules/@shikijs/langs/dist/http.mjs",
167
167
  "isDynamicEntry": true,
168
168
  "imports": [
169
- "_app-B2Ac56ic.js",
169
+ "_app-Boh5DRzv.js",
170
170
  "../../node_modules/@shikijs/langs/dist/xml.mjs",
171
171
  "../../node_modules/@shikijs/langs/dist/graphql.mjs",
172
172
  "index.html",
@@ -275,7 +275,7 @@
275
275
  ]
276
276
  },
277
277
  "../../node_modules/@shikijs/langs/dist/php.mjs": {
278
- "file": "assets/php-s52DiJil.js",
278
+ "file": "assets/php-BG9P_ECJ.js",
279
279
  "name": "php",
280
280
  "src": "../../node_modules/@shikijs/langs/dist/php.mjs",
281
281
  "isDynamicEntry": true,
@@ -284,7 +284,7 @@
284
284
  "../../node_modules/@shikijs/langs/dist/xml.mjs",
285
285
  "../../node_modules/@shikijs/langs/dist/sql.mjs",
286
286
  "_javascript-D_ijBMSX.js",
287
- "_app-B2Ac56ic.js",
287
+ "_app-Boh5DRzv.js",
288
288
  "../../node_modules/@shikijs/langs/dist/css.mjs",
289
289
  "../../node_modules/@shikijs/langs/dist/java.mjs",
290
290
  "index.html"
@@ -315,7 +315,7 @@
315
315
  "isDynamicEntry": true
316
316
  },
317
317
  "../../node_modules/@shikijs/langs/dist/rst.mjs": {
318
- "file": "assets/rst-CN3AX0Wt.js",
318
+ "file": "assets/rst-Rxh6XweC.js",
319
319
  "name": "rst",
320
320
  "src": "../../node_modules/@shikijs/langs/dist/rst.mjs",
321
321
  "isDynamicEntry": true,
@@ -324,7 +324,7 @@
324
324
  "../../node_modules/@shikijs/langs/dist/cpp.mjs",
325
325
  "../../node_modules/@shikijs/langs/dist/python.mjs",
326
326
  "_javascript-D_ijBMSX.js",
327
- "_app-B2Ac56ic.js",
327
+ "_app-Boh5DRzv.js",
328
328
  "../../node_modules/@shikijs/langs/dist/yaml.mjs",
329
329
  "../../node_modules/@shikijs/langs/dist/cmake.mjs",
330
330
  "../../node_modules/@shikijs/langs/dist/ruby.mjs",
@@ -340,7 +340,7 @@
340
340
  ]
341
341
  },
342
342
  "../../node_modules/@shikijs/langs/dist/ruby.mjs": {
343
- "file": "assets/ruby-TeaxAh4o.js",
343
+ "file": "assets/ruby-vsmpeItB.js",
344
344
  "name": "ruby",
345
345
  "src": "../../node_modules/@shikijs/langs/dist/ruby.mjs",
346
346
  "isDynamicEntry": true,
@@ -353,7 +353,7 @@
353
353
  "../../node_modules/@shikijs/langs/dist/graphql.mjs",
354
354
  "../../node_modules/@shikijs/langs/dist/cpp.mjs",
355
355
  "../../node_modules/@shikijs/langs/dist/c.mjs",
356
- "_app-B2Ac56ic.js",
356
+ "_app-Boh5DRzv.js",
357
357
  "../../node_modules/@shikijs/langs/dist/lua.mjs",
358
358
  "../../node_modules/@shikijs/langs/dist/yaml.mjs",
359
359
  "../../node_modules/@shikijs/langs/dist/java.mjs",
@@ -388,13 +388,13 @@
388
388
  "isDynamicEntry": true
389
389
  },
390
390
  "../../node_modules/@shikijs/langs/dist/svelte.mjs": {
391
- "file": "assets/svelte-D-qO2kbs.js",
391
+ "file": "assets/svelte-BbsEXeJC.js",
392
392
  "name": "svelte",
393
393
  "src": "../../node_modules/@shikijs/langs/dist/svelte.mjs",
394
394
  "isDynamicEntry": true,
395
395
  "imports": [
396
396
  "_javascript-D_ijBMSX.js",
397
- "_app-B2Ac56ic.js",
397
+ "_app-Boh5DRzv.js",
398
398
  "../../node_modules/@shikijs/langs/dist/css.mjs",
399
399
  "index.html"
400
400
  ]
@@ -430,14 +430,14 @@
430
430
  "isDynamicEntry": true
431
431
  },
432
432
  "../../node_modules/@shikijs/langs/dist/vue.mjs": {
433
- "file": "assets/vue-xQhdtb6A.js",
433
+ "file": "assets/vue-DgFjFt96.js",
434
434
  "name": "vue",
435
435
  "src": "../../node_modules/@shikijs/langs/dist/vue.mjs",
436
436
  "isDynamicEntry": true,
437
437
  "imports": [
438
438
  "../../node_modules/@shikijs/langs/dist/css.mjs",
439
439
  "_javascript-D_ijBMSX.js",
440
- "_app-B2Ac56ic.js",
440
+ "_app-Boh5DRzv.js",
441
441
  "../../node_modules/@shikijs/langs/dist/html.mjs",
442
442
  "_html-derivative-CADUTaWI.js",
443
443
  "index.html"
@@ -694,8 +694,8 @@
694
694
  "file": "assets/KaTeX_Typewriter-Regular.woff2",
695
695
  "src": "../../node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff2"
696
696
  },
697
- "_app-B2Ac56ic.js": {
698
- "file": "assets/app-B2Ac56ic.js",
697
+ "_app-Boh5DRzv.js": {
698
+ "file": "assets/app-Boh5DRzv.js",
699
699
  "name": "app",
700
700
  "isDynamicEntry": true,
701
701
  "imports": [
@@ -840,7 +840,7 @@
840
840
  "isEntry": true,
841
841
  "dynamicImports": [
842
842
  "telemetry-client.ts",
843
- "_app-B2Ac56ic.js"
843
+ "_app-Boh5DRzv.js"
844
844
  ]
845
845
  },
846
846
  "style.css": {