@herbertgao/pi-extensions 2026.9.19 → 2026.10.0

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.
Files changed (444) hide show
  1. package/README.md +14 -16
  2. package/THIRD_PARTY_NOTICES.md +29 -3
  3. package/node_modules/@herbertgao/pi-bark/README.md +39 -3
  4. package/node_modules/@herbertgao/pi-bark/package.json +1 -1
  5. package/node_modules/@herbertgao/pi-bark/src/index.ts +275 -15
  6. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +85 -68
  7. package/node_modules/@herbertgao/pi-cc-extensions/README.md +79 -62
  8. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +116 -34
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +370 -118
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +31 -33
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +521 -0
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/mcp-chip.ts +136 -0
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +58 -38
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1127 -231
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +267 -262
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +38 -48
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +287 -114
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +303 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +151 -0
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +4 -4
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +103 -48
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +8 -7
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +2 -1
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +171 -196
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +27 -93
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +429 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +259 -164
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +77 -0
  61. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  62. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  64. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  65. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/package.json +10 -8
  67. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  68. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  69. package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +3 -2
  70. package/node_modules/@herbertgao/sol-pi/CONTRIBUTING.md +22 -0
  71. package/node_modules/@herbertgao/sol-pi/README.md +36 -17
  72. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +10 -6
  73. package/node_modules/@herbertgao/sol-pi/agents-install.md +15 -12
  74. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +24 -8
  75. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +2 -2
  76. package/node_modules/@herbertgao/sol-pi/docs/star-history.md +18 -0
  77. package/node_modules/@herbertgao/sol-pi/package.json +4 -2
  78. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +1 -1
  79. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +1 -1
  80. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +23 -4
  81. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +32 -1
  82. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +3 -2
  83. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +1 -1
  84. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +27 -7
  85. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +137 -41
  86. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +1 -0
  87. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +2 -1
  88. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/projection.ts +58 -0
  89. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +28 -6
  90. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +2 -1
  91. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +15 -2
  92. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  93. package/node_modules/@pi-plugins/fast-mode/README.md +7 -1
  94. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  95. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +7 -1
  96. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  97. package/node_modules/@pi-plugins/fast-mode/package.json +5 -5
  98. package/node_modules/pi-antigravity/README.md +3 -0
  99. package/node_modules/pi-antigravity/package.json +8 -8
  100. package/node_modules/pi-antigravity/src/auth/oauth.ts +6 -3
  101. package/node_modules/pi-antigravity/src/index.ts +114 -110
  102. package/node_modules/pi-antigravity/src/stream/stream.ts +1 -1
  103. package/node_modules/pi-antigravity/src/utils/util.ts +18 -1
  104. package/node_modules/pi-multi-account/CHANGELOG.md +20 -0
  105. package/node_modules/pi-multi-account/README.md +46 -8
  106. package/node_modules/pi-multi-account/config-file-transaction.ts +42 -0
  107. package/node_modules/pi-multi-account/index.ts +255 -269
  108. package/node_modules/pi-multi-account/model-pins.ts +36 -0
  109. package/node_modules/pi-multi-account/package.json +9 -7
  110. package/node_modules/pi-multi-account/slot-proxy-auth.ts +12 -2
  111. package/node_modules/pi-multi-account/slot-proxy.ts +27 -5
  112. package/node_modules/pi-web-access/CHANGELOG.md +17 -0
  113. package/node_modules/pi-web-access/README.md +6 -3
  114. package/node_modules/pi-web-access/brave-rate-limit.ts +170 -0
  115. package/node_modules/pi-web-access/brave.ts +28 -11
  116. package/node_modules/pi-web-access/dist/index.js +202 -33
  117. package/node_modules/pi-web-access/gemini-search.ts +2 -5
  118. package/node_modules/pi-web-access/index.ts +13 -7
  119. package/node_modules/pi-web-access/openai-search.ts +24 -10
  120. package/node_modules/pi-web-access/package.json +1 -1
  121. package/node_modules/pi-web-access/summary-review.ts +8 -2
  122. package/node_modules/{@herbertgao/resume-from → resume-from}/README.md +16 -12
  123. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.d.ts +0 -5
  124. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.js +2 -3
  125. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.d.ts +2 -2
  126. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.d.ts +3 -0
  127. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.js +27 -15
  128. package/node_modules/{@herbertgao/resume-from/dist/adapters/codex → resume-from/dist/adapters/claude-code}/redaction.js +16 -3
  129. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.d.ts +2 -4
  130. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.js +1 -1
  131. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.d.ts +2 -4
  132. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.js +1 -2
  133. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/read.d.ts +16 -0
  134. package/node_modules/resume-from/dist/adapters/codex/read.js +723 -0
  135. package/node_modules/{@herbertgao/resume-from/dist/adapters/pi → resume-from/dist/adapters/codex}/redaction.js +16 -3
  136. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.d.ts +44 -4
  137. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.js +88 -4
  138. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.d.ts +2 -2
  139. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.js +2 -2
  140. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.d.ts +5 -1
  141. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.js +10 -6
  142. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.d.ts +2 -2
  143. package/node_modules/{@herbertgao/resume-from/dist/adapters/claude-code → resume-from/dist/adapters/pi}/redaction.js +16 -3
  144. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.d.ts +2 -4
  145. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.js +2 -2
  146. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.d.ts +1 -1
  147. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.js +4 -4
  148. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.js +2 -2
  149. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.d.ts +2 -2
  150. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.js +31 -8
  151. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.d.ts +1 -1
  152. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.js +1 -2
  153. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.d.ts +4 -1
  154. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.js +2 -2
  155. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.d.ts +8 -6
  156. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.d.ts +10 -5
  157. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/finder.d.ts +2 -1
  158. package/node_modules/resume-from/dist/import/discovery/finder.js +269 -0
  159. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.d.ts +3 -3
  160. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.js +3 -3
  161. package/node_modules/resume-from/dist/import/pipeline.d.ts +28 -0
  162. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/pipeline.js +31 -11
  163. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.d.ts +2 -2
  164. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.js +9 -5
  165. package/node_modules/resume-from/dist/import/preview/warnings.d.ts +14 -0
  166. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/warnings.js +26 -20
  167. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.js +12 -2
  168. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.d.ts +9 -3
  169. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.d.ts +4 -4
  170. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.js +7 -4
  171. package/node_modules/resume-from/dist/platform/repo/reader.d.ts +3 -0
  172. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/reader.js +60 -20
  173. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.d.ts +8 -1
  174. package/node_modules/{@herbertgao/resume-from → resume-from}/package.json +19 -32
  175. package/node_modules/{@herbertgao/resume-from → resume-from}/shims/pi/extensions/resume-from.js +2 -2
  176. package/package.json +18 -22
  177. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  178. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  179. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  180. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  181. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  182. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  183. package/node_modules/@herbertgao/resume-from/dist/adapters/codex/read.js +0 -270
  184. package/node_modules/@herbertgao/resume-from/dist/import/discovery/finder.js +0 -129
  185. package/node_modules/@herbertgao/resume-from/dist/import/pipeline.d.ts +0 -17
  186. package/node_modules/@herbertgao/resume-from/dist/import/preview/warnings.d.ts +0 -11
  187. package/node_modules/@herbertgao/resume-from/dist/platform/repo/reader.d.ts +0 -8
  188. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  189. package/node_modules/pi-footer/LICENSE +0 -21
  190. package/node_modules/pi-footer/README.md +0 -354
  191. package/node_modules/pi-footer/package.json +0 -68
  192. package/node_modules/pi-footer/src/cache.ts +0 -106
  193. package/node_modules/pi-footer/src/colors.ts +0 -237
  194. package/node_modules/pi-footer/src/config.ts +0 -202
  195. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  196. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  197. package/node_modules/pi-footer/src/git.ts +0 -135
  198. package/node_modules/pi-footer/src/index.ts +0 -268
  199. package/node_modules/pi-footer/src/metrics.ts +0 -141
  200. package/node_modules/pi-footer/src/presets.ts +0 -383
  201. package/node_modules/pi-footer/src/render.ts +0 -114
  202. package/node_modules/pi-footer/src/separators.ts +0 -52
  203. package/node_modules/pi-footer/src/types.ts +0 -122
  204. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  205. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  206. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  207. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  208. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  209. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  210. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  211. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  212. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  213. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  214. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  215. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  216. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  217. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  218. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  219. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  220. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  221. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  222. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  223. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  224. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  225. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  226. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  227. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  228. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  229. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  230. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  231. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  232. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  233. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  234. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  235. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  236. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  237. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  238. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  239. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  240. package/node_modules/pi-footer/src/ui.ts +0 -66
  241. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  242. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  243. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  244. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  245. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  246. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  247. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  248. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  249. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  250. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  251. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  252. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  253. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  254. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  255. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  256. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  257. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  258. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  259. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  260. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  261. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  262. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  263. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  264. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  265. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  266. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  267. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  268. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  269. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  270. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  271. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  272. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  273. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  274. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  275. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  276. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  277. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  278. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  279. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  280. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  281. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  282. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  283. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  284. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  285. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  286. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  287. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  288. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  289. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  290. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  291. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  292. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  293. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  294. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  295. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  296. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  297. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  298. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  299. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  300. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  301. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  302. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  303. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  304. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  305. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  306. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
  307. /package/node_modules/{@herbertgao/resume-from → resume-from}/LICENSE +0 -0
  308. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.js +0 -0
  309. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.d.ts +0 -0
  310. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.js +0 -0
  311. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.d.ts +0 -0
  312. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.js +0 -0
  313. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.d.ts +0 -0
  314. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.js +0 -0
  315. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.d.ts +0 -0
  316. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.js +0 -0
  317. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/redaction.d.ts +0 -0
  318. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.d.ts +0 -0
  319. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.js +0 -0
  320. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.js +0 -0
  321. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.d.ts +0 -0
  322. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.d.ts +0 -0
  323. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.js +0 -0
  324. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/redaction.d.ts +0 -0
  325. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.d.ts +0 -0
  326. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.js +0 -0
  327. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.js +0 -0
  328. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.d.ts +0 -0
  329. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.js +0 -0
  330. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.d.ts +0 -0
  331. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.js +0 -0
  332. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.d.ts +0 -0
  333. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.js +0 -0
  334. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.d.ts +0 -0
  335. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.js +0 -0
  336. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/redaction.d.ts +0 -0
  337. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.d.ts +0 -0
  338. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.js +0 -0
  339. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.d.ts +0 -0
  340. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.js +0 -0
  341. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.d.ts +0 -0
  342. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.js +0 -0
  343. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.d.ts +0 -0
  344. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.js +0 -0
  345. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.d.ts +0 -0
  346. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.js +0 -0
  347. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.d.ts +0 -0
  348. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.js +0 -0
  349. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.d.ts +0 -0
  350. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.js +0 -0
  351. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.d.ts +0 -0
  352. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.js +0 -0
  353. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.d.ts +0 -0
  354. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.js +0 -0
  355. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.d.ts +0 -0
  356. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.js +0 -0
  357. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.d.ts +0 -0
  358. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.js +0 -0
  359. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.d.ts +0 -0
  360. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.d.ts +0 -0
  361. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.js +0 -0
  362. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.d.ts +0 -0
  363. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.js +0 -0
  364. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.d.ts +0 -0
  365. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.js +0 -0
  366. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.d.ts +0 -0
  367. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.js +0 -0
  368. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.d.ts +0 -0
  369. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.js +0 -0
  370. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.d.ts +0 -0
  371. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.js +0 -0
  372. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.d.ts +0 -0
  373. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.js +0 -0
  374. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.d.ts +0 -0
  375. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.js +0 -0
  376. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.js +0 -0
  377. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.js +0 -0
  378. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.d.ts +0 -0
  379. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.js +0 -0
  380. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.d.ts +0 -0
  381. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.js +0 -0
  382. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.d.ts +0 -0
  383. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.js +0 -0
  384. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.d.ts +0 -0
  385. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.js +0 -0
  386. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.d.ts +0 -0
  387. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.js +0 -0
  388. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.d.ts +0 -0
  389. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.js +0 -0
  390. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.js +0 -0
  391. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.d.ts +0 -0
  392. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.js +0 -0
  393. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.d.ts +0 -0
  394. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.js +0 -0
  395. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.d.ts +0 -0
  396. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.js +0 -0
  397. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.d.ts +0 -0
  398. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.d.ts +0 -0
  399. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.js +0 -0
  400. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.d.ts +0 -0
  401. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.js +0 -0
  402. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.d.ts +0 -0
  403. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.js +0 -0
  404. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.d.ts +0 -0
  405. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.js +0 -0
  406. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.d.ts +0 -0
  407. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.js +0 -0
  408. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.d.ts +0 -0
  409. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.js +0 -0
  410. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.d.ts +0 -0
  411. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.js +0 -0
  412. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.d.ts +0 -0
  413. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.d.ts +0 -0
  414. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.js +0 -0
  415. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.d.ts +0 -0
  416. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.js +0 -0
  417. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.d.ts +0 -0
  418. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.js +0 -0
  419. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.d.ts +0 -0
  420. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.js +0 -0
  421. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.d.ts +0 -0
  422. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.js +0 -0
  423. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.d.ts +0 -0
  424. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.js +0 -0
  425. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.d.ts +0 -0
  426. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.js +0 -0
  427. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.d.ts +0 -0
  428. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.js +0 -0
  429. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.js +0 -0
  430. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.d.ts +0 -0
  431. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.js +0 -0
  432. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.d.ts +0 -0
  433. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.js +0 -0
  434. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.d.ts +0 -0
  435. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.js +0 -0
  436. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.d.ts +0 -0
  437. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.js +0 -0
  438. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.d.ts +0 -0
  439. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.js +0 -0
  440. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.d.ts +0 -0
  441. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.js +0 -0
  442. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.d.ts +0 -0
  443. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.js +0 -0
  444. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.js +0 -0
@@ -0,0 +1,723 @@
1
+ /**
2
+ * The source role: a Codex home becomes a list of sessions, and one session becomes the
3
+ * canonical vocabulary. Every result body is dropped (FR-24) and every reasoning trace is
4
+ * ignored (FR-28, C-4).
5
+ */
6
+ import { isAbsolute } from "node:path";
7
+ import { redactSensitiveArgumentsText, redactSensitiveText } from "./redaction.js";
8
+ import { CODEX_ENTRY_COMPACTED, CODEX_ENTRY_EVENT_MSG, CODEX_ENTRY_RESPONSE_ITEM, CODEX_EVENT_AGENT_MESSAGE, CODEX_EVENT_ITEM_COMPLETED, CODEX_EVENT_USER_MESSAGE, CODEX_EXTENSION_KIND_WEB_SEARCH, CODEX_ITEM_CUSTOM_TOOL_CALL, CODEX_ITEM_CUSTOM_TOOL_CALL_OUTPUT, CODEX_ITEM_FUNCTION_CALL, CODEX_ITEM_FUNCTION_CALL_OUTPUT, CODEX_THREAD_ITEM_AGENT_MESSAGE, CODEX_THREAD_ITEM_COLLAB_AGENT_TOOL_CALL, CODEX_THREAD_ITEM_COMMAND_EXECUTION, CODEX_THREAD_ITEM_CONTEXT_COMPACTION, CODEX_THREAD_ITEM_EXTENSION, CODEX_THREAD_ITEM_FILE_CHANGE, CODEX_THREAD_ITEM_IMAGE_VIEW, CODEX_THREAD_ITEM_MCP_TOOL_CALL, CODEX_THREAD_ITEM_REASONING, CODEX_THREAD_ITEM_SUB_AGENT_ACTIVITY, CODEX_THREAD_ITEM_USER_MESSAGE, isNotFoundError, KNOWN_ENTRY_TYPES, listRolloutFiles, payloadType, readSessionMeta, sessionsRoot, streamRolloutEntries, toIsoUtc, } from "./rollout.js";
9
+ const TITLE_LIMIT = 80;
10
+ const ARGUMENTS_PREVIEW_LIMIT = 60;
11
+ /** Tools whose name alone settles the question (FR-26). Everything else stays "unknown". */
12
+ const READ_ONLY_TOOLS = new Set([
13
+ "read_file",
14
+ "read",
15
+ "view_image",
16
+ "list_dir",
17
+ "grep",
18
+ "find",
19
+ "web_search",
20
+ ]);
21
+ const MUTATING_TOOLS = new Set([
22
+ "apply_patch",
23
+ "write_file",
24
+ "edit_file",
25
+ "create_file",
26
+ "delete_file",
27
+ ]);
28
+ /**
29
+ * `Extension.kind` values that are reads by their own name. Any other kind is a call whose kind
30
+ * does not settle the question, so it stays "unknown" (FR-26).
31
+ */
32
+ const READ_ONLY_EXTENSION_KINDS = new Set([CODEX_EXTENSION_KIND_WEB_SEARCH]);
33
+ export class CodexRolloutUnreadableError extends Error {
34
+ constructor(filePath) {
35
+ super(`Codex thread is unreadable: ${filePath} was cut mid-entry`);
36
+ this.name = "CodexRolloutUnreadableError";
37
+ }
38
+ }
39
+ /** Lenient: a file cut mid-entry still yields whatever parsed, with `truncated` set. */
40
+ export async function scanRollout(filePath) {
41
+ // The same streamed reader the listing uses, so both call a line over the cap damage (C-13): one
42
+ // reader, one damage rule, and no whole file in memory. Reading stops at the first damage through
43
+ // `stop`, which lets the reader end the file on its own terms instead of being abandoned mid-read;
44
+ // `readRollout` refuses a damaged file anyway, so the rest of it cannot matter.
45
+ const state = { truncated: false, stop: false };
46
+ const entries = [];
47
+ for await (const entry of streamRolloutEntries(filePath, state)) {
48
+ if (state.truncated) {
49
+ state.stop = true;
50
+ continue;
51
+ }
52
+ entries.push(entry);
53
+ }
54
+ let meta = null;
55
+ for (const entry of entries) {
56
+ meta = readSessionMeta(entry);
57
+ if (meta !== null)
58
+ break;
59
+ }
60
+ const { turns, skippedEntries, changedPaths } = toCanonicalTurns(entries);
61
+ const firstUserTurn = turns.find((turn) => turn.role === "user" && turn.kind === "message");
62
+ const lastStamp = [...entries].reverse().find((entry) => toIsoUtc(entry.timestamp) !== null);
63
+ return {
64
+ filePath,
65
+ meta,
66
+ turns,
67
+ skippedEntries,
68
+ startedAt: toIsoUtc(meta?.timestamp ?? entries[0]?.timestamp ?? null),
69
+ updatedAt: toIsoUtc(lastStamp?.timestamp ?? meta?.timestamp ?? null),
70
+ title: titleOf(firstUserTurn?.text ?? ""),
71
+ changedPaths,
72
+ truncated: state.truncated,
73
+ };
74
+ }
75
+ /** Strict: FR-51's "unreadable" answer. */
76
+ export async function readRollout(filePath) {
77
+ const rollout = await scanRollout(filePath);
78
+ if (rollout.truncated)
79
+ throw new CodexRolloutUnreadableError(filePath);
80
+ return rollout;
81
+ }
82
+ /**
83
+ * Sums up one rollout for the selection list in a single streamed pass (C-13): no turn is built,
84
+ * no argument is redacted, and neither the file nor its entries are held whole. Every field comes
85
+ * from the same classifier the loader uses, so a row cannot disagree with the session it opens.
86
+ */
87
+ export async function summarizeRollout(filePath) {
88
+ // The listing never stops early: every entry decides the row (C-13).
89
+ const state = { truncated: false, stop: false };
90
+ let meta = null;
91
+ let firstEntryStamp = null;
92
+ let seenEntry = false;
93
+ let lastStamp = null;
94
+ let messages = 0;
95
+ let itemToolCalls = 0;
96
+ let summaryTurns = 0;
97
+ let itemSeen = false;
98
+ let legacyDialogueBeforeItems = false;
99
+ let legacyCallsBeforeItems = 0;
100
+ let legacyCallsAfterItems = 0;
101
+ let title = "";
102
+ for await (const entry of streamRolloutEntries(filePath, state)) {
103
+ if (meta === null)
104
+ meta = readSessionMeta(entry);
105
+ const stamp = toIsoUtc(entry.timestamp);
106
+ if (!seenEntry) {
107
+ seenEntry = true;
108
+ firstEntryStamp = stamp;
109
+ }
110
+ if (stamp !== null)
111
+ lastStamp = stamp;
112
+ const itemTurn = isItemCompletedTurn(entry);
113
+ if (itemTurn)
114
+ itemSeen = true;
115
+ const turn = classifyEntry(entry);
116
+ switch (turn.kind) {
117
+ case "summary":
118
+ summaryTurns += 1;
119
+ break;
120
+ case "message":
121
+ messages += 1;
122
+ if (!itemSeen && isLegacyMessageTurn(entry))
123
+ legacyDialogueBeforeItems = true;
124
+ if (turn.role === "user" && title === "")
125
+ title = turn.text;
126
+ break;
127
+ case "tool-call":
128
+ if (turn.schema === "item-completed")
129
+ itemToolCalls += 1;
130
+ else if (itemSeen)
131
+ legacyCallsAfterItems += 1;
132
+ else
133
+ legacyCallsBeforeItems += 1;
134
+ break;
135
+ default:
136
+ // "none" and "unknown" contribute no turn.
137
+ break;
138
+ }
139
+ }
140
+ const metaStamp = toIsoUtc(meta?.timestamp ?? null);
141
+ return {
142
+ filePath,
143
+ meta,
144
+ // The title reaches the target's metadata, so it is redacted as the turn text is (FR-28).
145
+ title: titleOf(redactSensitiveText(title)),
146
+ startedAt: metaStamp ?? firstEntryStamp,
147
+ updatedAt: lastStamp ?? metaStamp,
148
+ // The calls a mixed-era file made before its first item turn are kept; the rest are repeats or
149
+ // an item-era file's whole `response_item` stream, so they are not counted (C-12).
150
+ turnCount: summaryTurns +
151
+ messages +
152
+ itemToolCalls +
153
+ (itemSeen
154
+ ? legacyDialogueBeforeItems
155
+ ? legacyCallsBeforeItems
156
+ : 0
157
+ : legacyCallsBeforeItems + legacyCallsAfterItems),
158
+ truncated: state.truncated,
159
+ };
160
+ }
161
+ export async function listCodexSessions(home) {
162
+ const descriptors = [];
163
+ let failed = 0;
164
+ let firstFailure = null;
165
+ for (const filePath of await listRolloutFiles(sessionsRoot(home))) {
166
+ let summary;
167
+ try {
168
+ summary = await summarizeRollout(filePath);
169
+ }
170
+ catch (error) {
171
+ if (isNotFoundError(error))
172
+ continue; // A rollout may disappear during a concurrent cleanup.
173
+ // One unreadable rollout must not hide the rest of the home (C-13). The home still reports a
174
+ // failure when nothing at all could be read, so a broken mount is never silent.
175
+ failed += 1;
176
+ firstFailure ??= error;
177
+ continue;
178
+ }
179
+ const meta = summary.meta;
180
+ if (meta === null)
181
+ continue;
182
+ const repoPaths = meta.cwd !== null && isAbsolute(meta.cwd) ? [meta.cwd] : [];
183
+ descriptors.push({
184
+ ref: { agent: "codex", home, id: meta.id },
185
+ title: summary.title,
186
+ startedAt: summary.startedAt ?? "",
187
+ updatedAt: summary.updatedAt ?? summary.startedAt ?? "",
188
+ turnCount: summary.turnCount,
189
+ repoPath: repoPaths[0] ?? null,
190
+ repoPaths,
191
+ startDirectory: repoPaths[0] ?? null,
192
+ filePath,
193
+ });
194
+ }
195
+ if (descriptors.length === 0 && failed > 0) {
196
+ throw firstFailure instanceof Error ? firstFailure : new Error(String(firstFailure));
197
+ }
198
+ descriptors.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
199
+ return descriptors;
200
+ }
201
+ export async function loadCodexSession(descriptor) {
202
+ const rollout = await readRollout(descriptor.filePath);
203
+ return {
204
+ provenance: {
205
+ ref: descriptor.ref,
206
+ title: descriptor.title,
207
+ startedAt: descriptor.startedAt,
208
+ updatedAt: descriptor.updatedAt,
209
+ repo: {
210
+ commit: rollout.meta?.commit ?? null,
211
+ branch: rollout.meta?.branch ?? null,
212
+ changedPaths: rollout.changedPaths,
213
+ },
214
+ },
215
+ turns: rollout.turns,
216
+ };
217
+ }
218
+ function titleOf(text) {
219
+ const line = text
220
+ .split("\n")
221
+ .find((candidate) => candidate.trim() !== "")
222
+ ?.trim() ?? "";
223
+ return line.length > TITLE_LIMIT ? `${line.slice(0, TITLE_LIMIT - 1)}…` : line;
224
+ }
225
+ /**
226
+ * Two dialogue schemas exist, and a rollout may even carry both (C-7, C-12):
227
+ *
228
+ * - the older one: messages from `event_msg` (`user_message`/`agent_message`) and tool calls from
229
+ * `response_item` (`function_call`/`custom_tool_call`);
230
+ * - the `item_completed` one: every turn — user text, agent text and every tool-like action — is a
231
+ * single `event_msg` whose `payload.item.type` says which. Its `response_item` stream repeats the
232
+ * same actions at a coarser granularity, so once a file speaks it, those repeats are not read as
233
+ * turns.
234
+ *
235
+ * Messages are never gated by schema: a legacy thread that was resumed by a newer client carries
236
+ * the dialogue of both eras, and each stays readable. The repeat rule therefore applies to tool
237
+ * calls only.
238
+ *
239
+ * Reasoning, in either shape, produces nothing at all (C-4, FR-28, NG-8). Which entries count is
240
+ * settled by `classifyEntry`, the same function the selection list counts with.
241
+ */
242
+ function toCanonicalTurns(entries) {
243
+ const cut = entries.findIndex(isItemCompletedTurn);
244
+ const legacyCalls = legacyCallScope(entries, cut);
245
+ const outputs = legacyCalls === "none" ? new Map() : callOutputs(entries);
246
+ const turns = [];
247
+ const changed = new Set();
248
+ let skippedEntries = 0;
249
+ for (const [position, entry] of entries.entries()) {
250
+ const turn = classifyEntry(entry);
251
+ if (turn.kind === "unknown") {
252
+ skippedEntries += 1;
253
+ continue;
254
+ }
255
+ if (turn.kind === "none")
256
+ continue;
257
+ if (turn.kind === "summary") {
258
+ turns.push({
259
+ index: turns.length,
260
+ role: "agent",
261
+ kind: "summary",
262
+ // FR-28, security: credentials in message text must not cross to a different vendor.
263
+ text: redactSensitiveText(turn.text),
264
+ toolCall: null,
265
+ timestamp: toIsoUtc(entry.timestamp),
266
+ });
267
+ continue;
268
+ }
269
+ if (turn.kind === "message") {
270
+ turns.push({
271
+ index: turns.length,
272
+ role: turn.role,
273
+ kind: "message",
274
+ // FR-28, security: credentials in message text must not cross to a different vendor.
275
+ text: redactSensitiveText(turn.text),
276
+ toolCall: null,
277
+ timestamp: toIsoUtc(entry.timestamp),
278
+ });
279
+ continue;
280
+ }
281
+ // The newer schema repeats its actions in `response_item`, so those repeats are not turns.
282
+ if (turn.schema === "legacy" && !readsLegacyCall(legacyCalls, position, cut))
283
+ continue;
284
+ const body = turn.schema === "item-completed" ? itemTurn(entry) : legacyCallTurn(entry, outputs);
285
+ if (body === null)
286
+ continue;
287
+ turns.push({
288
+ index: turns.length,
289
+ role: body.role,
290
+ kind: body.kind,
291
+ text: body.text,
292
+ toolCall: body.toolCall,
293
+ timestamp: toIsoUtc(entry.timestamp),
294
+ });
295
+ for (const path of body.changedPaths)
296
+ changed.add(path);
297
+ }
298
+ return { turns, skippedEntries, changedPaths: [...changed] };
299
+ }
300
+ /**
301
+ * Classifies one entry without building anything: no record, no redaction, and no string work beyond
302
+ * the message text a title needs. A kind this module does not understand is reported, never guessed
303
+ * at (C-6); reasoning, compaction and activity markers are understood and carry no turn (C-4, C-12).
304
+ * An empty message carries no turn in either schema, so both eras agree on what a row counts.
305
+ */
306
+ function classifyEntry(entry) {
307
+ if (!KNOWN_ENTRY_TYPES.has(entry.type))
308
+ return { kind: "unknown" };
309
+ if (entry.type === CODEX_ENTRY_COMPACTED) {
310
+ const message = entry.payload.message;
311
+ if (typeof message !== "string" || message.trim() === "")
312
+ return { kind: "none" };
313
+ return { kind: "summary", text: message };
314
+ }
315
+ if (entry.type === CODEX_ENTRY_EVENT_MSG) {
316
+ const type = payloadType(entry);
317
+ if (type === CODEX_EVENT_ITEM_COMPLETED)
318
+ return itemCompletedTurn(entry);
319
+ if (type !== CODEX_EVENT_USER_MESSAGE && type !== CODEX_EVENT_AGENT_MESSAGE)
320
+ return { kind: "none" };
321
+ const message = entry.payload.message;
322
+ if (typeof message !== "string" || message.trim() === "")
323
+ return { kind: "none" };
324
+ return {
325
+ kind: "message",
326
+ role: type === CODEX_EVENT_USER_MESSAGE ? "user" : "agent",
327
+ text: message,
328
+ };
329
+ }
330
+ if (entry.type !== CODEX_ENTRY_RESPONSE_ITEM)
331
+ return { kind: "none" };
332
+ const type = payloadType(entry);
333
+ if (type !== CODEX_ITEM_FUNCTION_CALL && type !== CODEX_ITEM_CUSTOM_TOOL_CALL)
334
+ return { kind: "none" };
335
+ const toolName = entry.payload.name;
336
+ if (typeof toolName !== "string" || toolName === "")
337
+ return { kind: "none" };
338
+ return { kind: "tool-call", schema: "legacy" };
339
+ }
340
+ /** The class of one `item_completed` entry, from the same tables its builder reads (C-12). */
341
+ function itemCompletedTurn(entry) {
342
+ const item = itemCompletedItem(entry);
343
+ if (item === null)
344
+ return { kind: "none" };
345
+ const itemType = typeof item.type === "string" ? item.type : "";
346
+ const role = ITEM_MESSAGE_ROLES.get(itemType);
347
+ if (role !== undefined) {
348
+ const text = itemContentText(item);
349
+ // An item the model sent no text in — an image only, for one — carries no turn, exactly as the
350
+ // older schema's empty message does, so a row and the session it opens agree on the count. It
351
+ // does not mark the file as recording turns as items either: `isItemCompletedTurn` asks the same
352
+ // question this function answers.
353
+ if (text.trim() === "")
354
+ return { kind: "none" };
355
+ return { kind: "message", role, text };
356
+ }
357
+ if (ITEM_TOOL_TURN_BUILDERS.has(itemType))
358
+ return { kind: "tool-call", schema: "item-completed" };
359
+ return IGNORED_ITEM_TYPES.has(itemType) ? { kind: "none" } : { kind: "unknown" };
360
+ }
361
+ /**
362
+ * True when this entry records a turn as an `item_completed` item (C-12), whatever text a message
363
+ * carries. A file that records turns this way repeats them coarsely in `response_item`, so those
364
+ * repeats are not read as turns. An empty message or a kind that carries no turn marks nothing.
365
+ */
366
+ function isItemCompletedTurn(entry) {
367
+ const turn = itemCompletedTurn(entry);
368
+ return turn.kind === "message" || turn.kind === "tool-call";
369
+ }
370
+ /**
371
+ * Which older-schema calls a rollout still has to offer (C-12). `response_item` in a file that
372
+ * records turns as items holds the coarser repeat of those items, so those calls are not read — but
373
+ * a thread that a newer client resumed keeps the dialogue of both eras, and the calls it made
374
+ * before the first item turn are the only record of that work. Those are read; the ones after it
375
+ * are the repeats.
376
+ */
377
+ function legacyCallScope(entries, cut) {
378
+ if (cut === -1)
379
+ return "all";
380
+ return entries.slice(0, cut).some(isLegacyMessageTurn) ? "before-items" : "none";
381
+ }
382
+ /** True when one older-schema call at this position is read under `scope` (C-12). */
383
+ function readsLegacyCall(scope, position, cut) {
384
+ if (scope === "all")
385
+ return true;
386
+ return scope === "before-items" && position < cut;
387
+ }
388
+ /** True when this entry is an older-schema dialogue message that carries text (C-7). */
389
+ function isLegacyMessageTurn(entry) {
390
+ if (entry.type !== CODEX_ENTRY_EVENT_MSG)
391
+ return false;
392
+ const type = payloadType(entry);
393
+ if (type !== CODEX_EVENT_USER_MESSAGE && type !== CODEX_EVENT_AGENT_MESSAGE)
394
+ return false;
395
+ const message = entry.payload.message;
396
+ return typeof message === "string" && message.trim() !== "";
397
+ }
398
+ /** The recorded answers of the older schema's calls, by call id (FR-25, FR-54). */
399
+ function callOutputs(entries) {
400
+ const outputs = new Map();
401
+ for (const entry of entries) {
402
+ if (entry.type !== CODEX_ENTRY_RESPONSE_ITEM)
403
+ continue;
404
+ const type = payloadType(entry);
405
+ if (type !== CODEX_ITEM_FUNCTION_CALL_OUTPUT && type !== CODEX_ITEM_CUSTOM_TOOL_CALL_OUTPUT)
406
+ continue;
407
+ const callId = entry.payload.call_id;
408
+ if (typeof callId !== "string")
409
+ continue;
410
+ outputs.set(callId, outputTextOf(entry.payload.output));
411
+ }
412
+ return outputs;
413
+ }
414
+ /** One older-schema `response_item` call becomes one tool-call turn (C-7). */
415
+ function legacyCallTurn(entry, outputs) {
416
+ const toolName = entry.payload.name;
417
+ if (typeof toolName !== "string" || toolName === "")
418
+ return null;
419
+ const rawArguments = payloadType(entry) === CODEX_ITEM_FUNCTION_CALL ? entry.payload.arguments : entry.payload.input;
420
+ const argumentsText = typeof rawArguments === "string" ? rawArguments : "";
421
+ const callId = entry.payload.call_id;
422
+ // FR-54: use has() not get() — outputs.get() can return "" for an empty result.
423
+ const resultRecorded = typeof callId === "string" && outputs.has(callId);
424
+ const output = typeof callId === "string" ? (outputs.get(callId) ?? null) : null;
425
+ const toolCall = toolCallRecord(toolName, argumentsText, output, resultRecorded);
426
+ return toolTurn(toolCall, toolCall.effect === "mutating" ? pathsOf(argumentsText) : []);
427
+ }
428
+ /** One `item_completed` entry becomes one tool-call turn, through the table that built it (C-12). */
429
+ function itemTurn(entry) {
430
+ const item = itemCompletedItem(entry);
431
+ return item === null ? null : turnFromItemCompleted(item);
432
+ }
433
+ /** The inner `item` of an `item_completed` entry, when the entry is one (C-12). */
434
+ function itemCompletedItem(entry) {
435
+ if (entry.type !== CODEX_ENTRY_EVENT_MSG)
436
+ return null;
437
+ if (payloadType(entry) !== CODEX_EVENT_ITEM_COMPLETED)
438
+ return null;
439
+ const item = entry.payload.item;
440
+ return typeof item === "object" && item !== null ? item : null;
441
+ }
442
+ /** Item kinds that are understood and deliberately carry no turn (C-4, C-12). */
443
+ const IGNORED_ITEM_TYPES = new Set([
444
+ CODEX_THREAD_ITEM_REASONING,
445
+ CODEX_THREAD_ITEM_CONTEXT_COMPACTION,
446
+ CODEX_THREAD_ITEM_SUB_AGENT_ACTIVITY,
447
+ ]);
448
+ /** The role of a message item, by kind. A kind outside this table is not a message (C-12). */
449
+ const ITEM_MESSAGE_ROLES = new Map([
450
+ [CODEX_THREAD_ITEM_USER_MESSAGE, "user"],
451
+ [CODEX_THREAD_ITEM_AGENT_MESSAGE, "agent"],
452
+ ]);
453
+ /**
454
+ * Every `item_completed` kind that carries a tool call, and how its record is built (C-12). The
455
+ * classifier and the builder read this one table, so no kind can be counted as a turn and then
456
+ * built as none, or the reverse.
457
+ */
458
+ const ITEM_TOOL_TURN_BUILDERS = new Map([
459
+ [CODEX_THREAD_ITEM_COMMAND_EXECUTION, commandExecutionTurn],
460
+ [CODEX_THREAD_ITEM_FILE_CHANGE, fileChangeTurn],
461
+ [CODEX_THREAD_ITEM_EXTENSION, extensionTurn],
462
+ [CODEX_THREAD_ITEM_MCP_TOOL_CALL, mcpToolCallTurn],
463
+ [CODEX_THREAD_ITEM_COLLAB_AGENT_TOOL_CALL, collabAgentToolCallTurn],
464
+ [CODEX_THREAD_ITEM_IMAGE_VIEW, imageViewTurn],
465
+ ]);
466
+ /**
467
+ * One `item_completed` item becomes one canonical turn. The kind of the call is settled by
468
+ * `item.type` itself, so the effect is read from that and never guessed from a tool name (FR-26).
469
+ * Returns null for a kind that carries no turn.
470
+ */
471
+ function turnFromItemCompleted(item) {
472
+ const itemType = typeof item.type === "string" ? item.type : "";
473
+ const role = ITEM_MESSAGE_ROLES.get(itemType);
474
+ if (role !== undefined) {
475
+ return {
476
+ role,
477
+ kind: "message",
478
+ // FR-28, security: credentials in message text must not cross to a different vendor.
479
+ text: redactSensitiveText(itemContentText(item)),
480
+ toolCall: null,
481
+ changedPaths: [],
482
+ };
483
+ }
484
+ return ITEM_TOOL_TURN_BUILDERS.get(itemType)?.(item) ?? null;
485
+ }
486
+ /** The common shape of a turn a tool-like item produces. */
487
+ function toolTurn(toolCall, changedPaths = []) {
488
+ return { role: "agent", kind: "tool-call", text: "", toolCall, changedPaths };
489
+ }
490
+ /** `CommandExecution`: the shell line the model wrote, and the shape of its output (FR-23..FR-25). */
491
+ function commandExecutionTurn(item) {
492
+ const output = firstString(item.aggregated_output, item.formatted_output, item.stdout);
493
+ return toolTurn(toolCallRecord("exec", commandText(item.command), output, output !== null));
494
+ }
495
+ /** `FileChange`: the patch is the argument, and its paths are the files the call touched (FR-24, FR-36). */
496
+ function fileChangeTurn(item) {
497
+ const paths = objectKeys(item.changes);
498
+ return toolTurn(itemToolCallRecord("apply_patch", fileChangeArguments(item.changes), `${paths.length} file(s) changed`, "mutating", false), paths);
499
+ }
500
+ /** `Extension`: a tool action such as a web search, with its queries kept and its results dropped. */
501
+ function extensionTurn(item) {
502
+ const kind = firstNonEmptyString(item.kind) ?? "extension";
503
+ const results = Array.isArray(item.results) ? item.results.length : 0;
504
+ return toolTurn(itemToolCallRecord(kind, extensionArguments(item), `${results} result(s) dropped`, READ_ONLY_EXTENSION_KINDS.has(kind) ? "read-only" : "unknown", true));
505
+ }
506
+ /** `McpToolCall`: a server tool call, named by server and tool (FR-27). */
507
+ function mcpToolCallTurn(item) {
508
+ const call = mcpToolCall(item);
509
+ return toolTurn(itemToolCallRecord(call.toolName, call.argumentsText, mcpOutcome(item),
510
+ // A server's own `readOnlyHint` is a claim by another party, not the item kind (FR-26).
511
+ "unknown", item.result !== undefined && item.result !== null));
512
+ }
513
+ /** `CollabAgentToolCall`: an action on another agent of the same client. */
514
+ function collabAgentToolCallTurn(item) {
515
+ const call = collabAgentToolCall(item);
516
+ return toolTurn(itemToolCallRecord(call.toolName, call.argumentsText, call.outcome, "unknown", objectKeys(item.agents_states).length > 0));
517
+ }
518
+ /** `ImageView`: the path the model asked for; the image itself never crosses (FR-24). */
519
+ function imageViewTurn(item) {
520
+ return toolTurn(itemToolCallRecord("view_image", firstNonEmptyString(item.path) ?? "", "image not carried", "read-only", false));
521
+ }
522
+ /**
523
+ * The text of a message item. `content[].type` is `"text"` on a user message and `"Text"` on an
524
+ * agent message, so the text is taken from the part's own field and never by that casing.
525
+ */
526
+ function itemContentText(item) {
527
+ const content = item.content;
528
+ if (!Array.isArray(content))
529
+ return "";
530
+ return content
531
+ .map((part) => typeof part === "object" && part !== null
532
+ ? firstNonEmptyString(part.text)
533
+ : null)
534
+ .filter((part) => part !== null)
535
+ .join("\n");
536
+ }
537
+ /** A Codex command is an argv array; the shell line the model wrote is its joined form. */
538
+ function commandText(value) {
539
+ if (Array.isArray(value))
540
+ return value.filter((part) => typeof part === "string").join(" ");
541
+ return typeof value === "string" ? value : "";
542
+ }
543
+ /**
544
+ * FR-24 protects a result body, not a tool argument, and the legacy `apply_patch` call already
545
+ * carries the patch text it was given. A `FileChange` item is the same kind of argument, so the
546
+ * patch is rebuilt from it whole — path plus content — in `apply_patch`'s own shape.
547
+ */
548
+ function fileChangeArguments(changes) {
549
+ if (typeof changes !== "object" || changes === null)
550
+ return "";
551
+ const parts = [];
552
+ for (const [path, change] of Object.entries(changes)) {
553
+ const record = typeof change === "object" && change !== null ? change : {};
554
+ const kind = firstNonEmptyString(record.type) ?? "update";
555
+ const verb = kind === "add" ? "Add" : kind === "delete" ? "Delete" : "Update";
556
+ const content = firstNonEmptyString(record.content);
557
+ parts.push(`*** ${verb} File: ${path}${content === null ? "" : `\n${content}`}`);
558
+ }
559
+ return parts.join("\n");
560
+ }
561
+ /** The queries an `Extension` item searched with, one per line. */
562
+ function extensionArguments(item) {
563
+ const action = item.action;
564
+ if (typeof action === "object" && action !== null) {
565
+ const queries = action.queries;
566
+ if (Array.isArray(queries)) {
567
+ const lines = queries.filter((query) => typeof query === "string" && query !== "");
568
+ if (lines.length > 0)
569
+ return lines.join("\n");
570
+ }
571
+ }
572
+ return firstNonEmptyString(item.query) ?? "";
573
+ }
574
+ /**
575
+ * A server tool call names itself in `server` and `tool` and states its arguments as JSON. Both
576
+ * are kept: the name unchanged (FR-27) and the arguments redacted like any other call (FR-24).
577
+ */
578
+ function mcpToolCall(item) {
579
+ const server = firstNonEmptyString(item.server);
580
+ const tool = firstNonEmptyString(item.tool);
581
+ const toolName = server !== null && tool !== null ? `${server}.${tool}` : (tool ?? server ?? "mcp");
582
+ return { toolName, argumentsText: jsonArguments(item.arguments) };
583
+ }
584
+ /** The recorded status of a server call, plus how many result items were dropped (FR-24, FR-25). */
585
+ function mcpOutcome(item) {
586
+ const result = item.result;
587
+ const record = typeof result === "object" && result !== null ? result : null;
588
+ const content = record === null ? null : record.content;
589
+ const results = Array.isArray(content) ? content.length : record === null ? 0 : 1;
590
+ const dropped = `${results} result(s) dropped`;
591
+ const status = firstNonEmptyString(item.status);
592
+ return status === null ? dropped : `${status}, ${dropped}`;
593
+ }
594
+ /**
595
+ * An action on another agent. Its `tool` field names the action, and the agents it addresses are
596
+ * the argument; the per-agent states it records are that call's result and are dropped (FR-24).
597
+ */
598
+ function collabAgentToolCall(item) {
599
+ const targets = [
600
+ ...stringValues(item.receiver_agents),
601
+ ...stringValues(item.receiver_thread_ids),
602
+ ];
603
+ return {
604
+ toolName: firstNonEmptyString(item.tool) ?? "collab-agent",
605
+ argumentsText: targets.join("\n"),
606
+ outcome: firstNonEmptyString(item.status) ?? "no status recorded",
607
+ };
608
+ }
609
+ /** Tool arguments as the recorded JSON text, or as they already are when they are a string. */
610
+ function jsonArguments(value) {
611
+ if (typeof value === "string")
612
+ return value;
613
+ if (typeof value !== "object" || value === null)
614
+ return "";
615
+ return JSON.stringify(value);
616
+ }
617
+ /** The non-empty strings of an array field, in source order. */
618
+ function stringValues(value) {
619
+ if (!Array.isArray(value))
620
+ return [];
621
+ return value.filter((part) => typeof part === "string" && part !== "");
622
+ }
623
+ /** Non-empty string keys of an object, in source order — the paths a change touched. */
624
+ function objectKeys(value) {
625
+ if (typeof value !== "object" || value === null)
626
+ return [];
627
+ return Object.keys(value).filter((key) => key !== "");
628
+ }
629
+ /** The first value that is a string, empty string included: an empty result was still recorded. */
630
+ function firstString(...values) {
631
+ for (const value of values) {
632
+ if (typeof value === "string")
633
+ return value;
634
+ }
635
+ return null;
636
+ }
637
+ /** The first value that is a non-empty string, or null. `""` counts as absent here. */
638
+ function firstNonEmptyString(...values) {
639
+ for (const value of values) {
640
+ if (typeof value === "string" && value !== "")
641
+ return value;
642
+ }
643
+ return null;
644
+ }
645
+ /**
646
+ * A structured item states its own outcome, so this variant names it instead of measuring a dropped
647
+ * body. The arguments still cross redacted, exactly like the legacy tool-call path (FR-24, FR-28).
648
+ */
649
+ function itemToolCallRecord(toolName, argumentsText, outcome, effect, bodyDropped) {
650
+ const safeArguments = redactSensitiveArgumentsText(argumentsText);
651
+ const head = `${toolName}(${singleLine(safeArguments, ARGUMENTS_PREVIEW_LIMIT)})`;
652
+ return {
653
+ toolName,
654
+ argumentsText: safeArguments,
655
+ outcomeLine: redactSensitiveText(`${head} → ${outcome}`),
656
+ effect,
657
+ bodyDropped,
658
+ resultRecorded: true,
659
+ };
660
+ }
661
+ /** Only the shape of the output is measured. Not one fragment of it is carried (FR-24, FR-25). */
662
+ function toolCallRecord(toolName, argumentsText, output, resultRecorded) {
663
+ const safeArguments = redactSensitiveArgumentsText(argumentsText);
664
+ const head = `${toolName}(${singleLine(safeArguments, ARGUMENTS_PREVIEW_LIMIT)})`;
665
+ const outcomeLine = output === null
666
+ ? `${head} → no output recorded`
667
+ : `${head} → ${output.split("\n").length} lines, body dropped`;
668
+ return {
669
+ toolName,
670
+ argumentsText: safeArguments,
671
+ outcomeLine: redactSensitiveText(outcomeLine),
672
+ effect: effectOf(toolName),
673
+ bodyDropped: output !== null,
674
+ // FR-54: false when no *_call_output entry existed for this call_id (broken tail signal).
675
+ resultRecorded,
676
+ };
677
+ }
678
+ function effectOf(toolName) {
679
+ if (MUTATING_TOOLS.has(toolName))
680
+ return "mutating";
681
+ if (READ_ONLY_TOOLS.has(toolName))
682
+ return "read-only";
683
+ return "unknown";
684
+ }
685
+ function outputTextOf(output) {
686
+ if (typeof output === "string")
687
+ return output;
688
+ if (Array.isArray(output)) {
689
+ return output
690
+ .map((part) => typeof part === "object" && part !== null
691
+ ? String(part.text ?? "")
692
+ : "")
693
+ .join("\n");
694
+ }
695
+ return output === undefined || output === null ? "" : JSON.stringify(output);
696
+ }
697
+ function singleLine(text, limit) {
698
+ const flat = text.replaceAll(/\s+/g, " ").trim();
699
+ return flat.length > limit ? `${flat.slice(0, limit - 1)}…` : flat;
700
+ }
701
+ /** Files a mutating call touched, for RepoSnapshot.changedPaths (FR-36). */
702
+ function pathsOf(argumentsText) {
703
+ let text = argumentsText;
704
+ const direct = [];
705
+ try {
706
+ const parsed = JSON.parse(argumentsText);
707
+ if (typeof parsed === "object" && parsed !== null) {
708
+ const record = parsed;
709
+ const strings = Object.values(record).filter((value) => typeof value === "string");
710
+ text = strings.join("\n");
711
+ for (const key of ["path", "file_path", "filename"]) {
712
+ const value = record[key];
713
+ if (typeof value === "string" && value !== "")
714
+ direct.push(value);
715
+ }
716
+ }
717
+ }
718
+ catch {
719
+ // Arguments that are not JSON are searched as they were recorded.
720
+ }
721
+ const patched = [...text.matchAll(/\*\*\* (?:Add|Update|Delete) File: (.+)/g)].map((match) => (match[1] ?? "").trim());
722
+ return [...direct, ...patched].filter((path) => path !== "");
723
+ }