@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21

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 (359) hide show
  1. package/CHANGELOG.md +292 -0
  2. package/README.md +8 -11
  3. package/docs/prefix-cache-architecture.md +14 -0
  4. package/package.json +22 -24
  5. package/packages/ask-user/README.md +55 -107
  6. package/packages/ask-user/ask-ui.ts +306 -732
  7. package/packages/ask-user/clipboard.ts +50 -0
  8. package/packages/ask-user/config.ts +74 -78
  9. package/packages/ask-user/package.json +2 -2
  10. package/packages/ask-user/questions.ts +151 -0
  11. package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
  12. package/packages/ask-user/tools.ts +198 -432
  13. package/packages/autocomplete/package.json +1 -1
  14. package/packages/autocomplete/src/constants.ts +38 -43
  15. package/packages/autocomplete/src/sorting.ts +8 -0
  16. package/packages/background-tasks/package.json +2 -2
  17. package/packages/background-tasks/src/config.ts +0 -73
  18. package/packages/background-tasks/src/index.ts +20 -16
  19. package/packages/background-tasks/src/registry.ts +1 -171
  20. package/packages/background-tasks/src/types.ts +0 -32
  21. package/packages/btw/README.md +13 -56
  22. package/packages/btw/extensions/btw.ts +403 -1796
  23. package/packages/btw/package.json +5 -2
  24. package/packages/btw/skills/btw/SKILL.md +7 -143
  25. package/packages/compactor/README.md +56 -287
  26. package/packages/compactor/package.json +5 -9
  27. package/packages/compactor/skills/compactor/SKILL.md +13 -20
  28. package/packages/compactor/src/card.ts +90 -0
  29. package/packages/compactor/src/commands/index.ts +73 -130
  30. package/packages/compactor/src/compaction/compact-args.ts +5 -3
  31. package/packages/compactor/src/compaction/filter-noise.ts +1 -1
  32. package/packages/compactor/src/compaction/hooks.ts +487 -311
  33. package/packages/compactor/src/compaction/source.ts +178 -0
  34. package/packages/compactor/src/compaction/summarize.ts +586 -52
  35. package/packages/compactor/src/config/manager.ts +130 -127
  36. package/packages/compactor/src/config/schema.ts +32 -48
  37. package/packages/compactor/src/index.ts +40 -431
  38. package/packages/compactor/src/info-screen.ts +44 -190
  39. package/packages/compactor/src/session/recall-blocks.ts +1 -1
  40. package/packages/compactor/src/stats.ts +76 -0
  41. package/packages/compactor/src/tools/context-budget.ts +17 -34
  42. package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
  43. package/packages/compactor/src/tools/register.ts +29 -269
  44. package/packages/compactor/src/types.ts +47 -186
  45. package/packages/core/README.md +25 -0
  46. package/packages/core/child-agent.ts +1 -0
  47. package/packages/core/command-echo.ts +63 -0
  48. package/packages/core/compaction-context.ts +41 -0
  49. package/packages/core/constants.ts +8 -38
  50. package/packages/core/events.ts +0 -53
  51. package/packages/core/fusion-status.ts +4 -0
  52. package/packages/core/global.d.ts +10 -0
  53. package/packages/core/harness-messages.ts +392 -0
  54. package/packages/core/index.ts +14 -0
  55. package/packages/core/kanboard-status.ts +49 -0
  56. package/packages/core/long-horizon-owner-status.ts +46 -0
  57. package/packages/core/model-cache.ts +81 -7
  58. package/packages/core/package.json +6 -3
  59. package/packages/core/src/attach/detect.ts +163 -0
  60. package/packages/core/src/child-agent/child-args.ts +31 -0
  61. package/packages/core/src/child-agent/delivery.ts +41 -0
  62. package/packages/core/src/child-agent/index.ts +5 -0
  63. package/packages/core/src/child-agent/readers.ts +203 -0
  64. package/packages/core/src/child-agent/runtime.ts +584 -0
  65. package/packages/core/src/evidence.ts +78 -0
  66. package/packages/core/src/hints/browser.ts +278 -0
  67. package/packages/core/src/hints/crab-data.ts +19 -0
  68. package/packages/core/src/hints/index.ts +865 -0
  69. package/packages/core/src/hints/lines.ts +607 -0
  70. package/packages/core/src/hints/store.ts +120 -0
  71. package/packages/core/src/jev/chatter.ts +24 -0
  72. package/packages/core/src/jev/settings.ts +177 -14
  73. package/packages/core/src/package-colors.ts +2 -0
  74. package/packages/core/src/settings/catalog.ts +39 -15
  75. package/packages/core/src/settings/engine.ts +48 -2
  76. package/packages/core/src/settings/hub.ts +83 -20
  77. package/packages/core/src/settings/open.ts +49 -0
  78. package/packages/core/src/settings/schema.ts +27 -7
  79. package/packages/core/src/tui/hub-kit.ts +18 -5
  80. package/packages/core/src/tui/kit.ts +198 -0
  81. package/packages/core/src/tui/progress.ts +73 -0
  82. package/packages/core/src/turn/arbiter.ts +290 -0
  83. package/packages/footer/README.md +4 -6
  84. package/packages/footer/package.json +3 -3
  85. package/packages/footer/src/glance-editor.ts +19 -11
  86. package/packages/footer/src/help.ts +1 -1
  87. package/packages/footer/src/index.ts +36 -3
  88. package/packages/footer/src/presets.ts +3 -4
  89. package/packages/footer/src/rendering/icons.ts +0 -20
  90. package/packages/footer/src/segments/compactor.ts +52 -142
  91. package/packages/footer/src/segments/status-ext.ts +0 -1
  92. package/packages/fusion/README.md +14 -4
  93. package/packages/fusion/package.json +4 -3
  94. package/packages/fusion/src/child-args.ts +1 -0
  95. package/packages/fusion/src/index.ts +161 -8
  96. package/packages/fusion/src/pi-settings.ts +57 -0
  97. package/packages/fusion/src/picker.ts +186 -51
  98. package/packages/fusion/src/preset.ts +56 -2
  99. package/packages/fusion/src/prompts.ts +1 -1
  100. package/packages/fusion/src/sidekick-runtime.ts +1 -420
  101. package/packages/fusion/src/tools.ts +107 -128
  102. package/packages/fusion/src/transcript.ts +27 -85
  103. package/packages/info-screen/package.json +2 -2
  104. package/packages/input-shortcuts/README.md +18 -30
  105. package/packages/input-shortcuts/package.json +2 -2
  106. package/packages/input-shortcuts/src/burst.ts +88 -0
  107. package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
  108. package/packages/input-shortcuts/src/cleared-input.ts +97 -0
  109. package/packages/input-shortcuts/src/index.ts +99 -193
  110. package/packages/input-shortcuts/src/last-response.ts +40 -0
  111. package/packages/input-shortcuts/src/registers.ts +8 -23
  112. package/packages/input-shortcuts/src/types.ts +4 -16
  113. package/packages/input-shortcuts/src/undo-redo.ts +59 -47
  114. package/packages/kanboard/README.md +51 -47
  115. package/packages/kanboard/index.ts +293 -55
  116. package/packages/kanboard/package.json +8 -8
  117. package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
  118. package/packages/kanboard/src/badges.ts +93 -0
  119. package/packages/kanboard/src/bin.ts +4 -2
  120. package/packages/kanboard/src/commands.ts +218 -84
  121. package/packages/kanboard/src/debug.ts +20 -0
  122. package/packages/kanboard/src/guard.ts +267 -109
  123. package/packages/kanboard/src/monitor.ts +330 -0
  124. package/packages/kanboard/src/notice-buffer.ts +74 -0
  125. package/packages/kanboard/src/progress.ts +27 -0
  126. package/packages/kanboard/src/reminders.ts +234 -0
  127. package/packages/kanboard/src/settings.ts +69 -15
  128. package/packages/kanboard/src/shapes.ts +5 -0
  129. package/packages/long-horizon/index.ts +190 -13
  130. package/packages/long-horizon/package.json +3 -3
  131. package/packages/long-horizon/src/commands.ts +103 -7
  132. package/packages/long-horizon/src/compaction-brief.ts +35 -0
  133. package/packages/long-horizon/src/engine/continuation.ts +84 -15
  134. package/packages/long-horizon/src/engine/goal-state.ts +64 -13
  135. package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
  136. package/packages/long-horizon/src/engine/ralph.ts +3 -2
  137. package/packages/long-horizon/src/engine/runaway.ts +68 -11
  138. package/packages/long-horizon/src/engine/verifier.ts +19 -0
  139. package/packages/long-horizon/src/gate.ts +37 -12
  140. package/packages/long-horizon/src/judge/resolve.ts +1 -0
  141. package/packages/long-horizon/src/owner.ts +35 -2
  142. package/packages/long-horizon/src/progress.ts +87 -0
  143. package/packages/long-horizon/src/prompts/goal.ts +1 -1
  144. package/packages/long-horizon/src/runtime.ts +172 -18
  145. package/packages/long-horizon/src/settings.ts +54 -39
  146. package/packages/long-horizon/src/tools/goal.ts +6 -0
  147. package/packages/long-horizon/src/tools/graph.ts +1 -1
  148. package/packages/long-horizon/src/tools/swarm.ts +3 -3
  149. package/packages/mcp/package.json +2 -2
  150. package/packages/memory/commands.ts +7 -2
  151. package/packages/memory/index.ts +210 -32
  152. package/packages/memory/package.json +3 -3
  153. package/packages/memory/save-session.ts +264 -0
  154. package/packages/memory/settings.ts +17 -0
  155. package/packages/memory/tools.ts +253 -203
  156. package/packages/notify/package.json +2 -2
  157. package/packages/skill-registry/README.md +53 -16
  158. package/packages/skill-registry/index.ts +230 -0
  159. package/packages/skill-registry/package.json +19 -8
  160. package/packages/skill-registry/src/editor.ts +206 -0
  161. package/packages/skill-registry/src/judge.ts +289 -0
  162. package/packages/skill-registry/src/registry.ts +87 -0
  163. package/packages/skill-registry/src/settings.ts +259 -0
  164. package/packages/skill-registry/src/vault.ts +80 -0
  165. package/packages/subagents/README.md +39 -119
  166. package/packages/subagents/package.json +6 -13
  167. package/packages/subagents/skills/subagents/SKILL.md +18 -42
  168. package/packages/subagents/src/agents.ts +213 -0
  169. package/packages/subagents/src/cards.ts +182 -0
  170. package/packages/subagents/src/index.ts +609 -1084
  171. package/packages/subagents/src/manager.ts +429 -0
  172. package/packages/subagents/src/profiles.ts +130 -0
  173. package/packages/subagents/src/transcript.ts +154 -0
  174. package/packages/subagents/src/ui.ts +389 -0
  175. package/packages/unipi/bundled.js +39756 -45569
  176. package/packages/unipi/index.ts +55 -10
  177. package/packages/updater/package.json +2 -2
  178. package/packages/utility/README.md +76 -69
  179. package/packages/utility/package.json +2 -2
  180. package/packages/utility/skills/image/SKILL.md +37 -0
  181. package/packages/utility/skills/utility/SKILL.md +17 -60
  182. package/packages/utility/src/answer/extract.ts +128 -0
  183. package/packages/utility/src/answer/index.ts +213 -0
  184. package/packages/utility/src/answer/reply.ts +133 -0
  185. package/packages/utility/src/answer/web.ts +167 -0
  186. package/packages/utility/src/attach/index.ts +205 -0
  187. package/packages/utility/src/commands.ts +38 -142
  188. package/packages/utility/src/diagnostics/engine.ts +50 -5
  189. package/packages/utility/src/image/index.ts +33 -0
  190. package/packages/utility/src/image/models.ts +221 -0
  191. package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
  192. package/packages/utility/src/image/settings.ts +178 -0
  193. package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
  194. package/packages/utility/src/image/tools.ts +168 -0
  195. package/packages/utility/src/image/transports.ts +186 -0
  196. package/packages/utility/src/index.ts +68 -389
  197. package/packages/utility/src/lifecycle/cleanup.ts +116 -311
  198. package/packages/utility/src/rename/gate.ts +102 -0
  199. package/packages/utility/src/rename/index.ts +191 -0
  200. package/packages/utility/src/rename/session.ts +170 -0
  201. package/packages/utility/src/render/delegated.ts +285 -0
  202. package/packages/utility/src/render/harness.ts +683 -0
  203. package/packages/utility/src/render/parse.ts +156 -0
  204. package/packages/utility/src/render/pi-settings.ts +38 -0
  205. package/packages/utility/src/render/reply-bg.ts +307 -0
  206. package/packages/utility/src/render/simple.ts +724 -0
  207. package/packages/utility/src/render/spacing.ts +235 -0
  208. package/packages/utility/src/render/styled.ts +251 -0
  209. package/packages/utility/src/render/tools.ts +353 -0
  210. package/packages/utility/src/settings.ts +166 -233
  211. package/packages/utility/src/types.ts +1 -222
  212. package/packages/watchdog/index.ts +17 -6
  213. package/packages/watchdog/package.json +3 -3
  214. package/packages/watchdog/src/config.ts +3 -2
  215. package/packages/web-api/package.json +2 -2
  216. package/packages/workflow/README.md +3 -0
  217. package/packages/workflow/index.ts +0 -2
  218. package/packages/workflow/package.json +2 -2
  219. package/packages/workflow/src/permission/decide.ts +6 -4
  220. package/packages/workflow/src/permission/index.ts +17 -7
  221. package/packages/workflow/src/permission/settings.ts +39 -4
  222. package/packages/workflow/src/plan/index.ts +19 -4
  223. package/packages/background-tasks/extensions/delegate-child.ts +0 -1
  224. package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
  225. package/packages/background-tasks/src/context-token-budget.ts +0 -903
  226. package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
  227. package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
  228. package/packages/background-tasks/src/delegate/budget.ts +0 -415
  229. package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
  230. package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
  231. package/packages/background-tasks/src/delegate/launch.ts +0 -484
  232. package/packages/background-tasks/src/delegate/result-package.ts +0 -459
  233. package/packages/background-tasks/src/delegate/runner.ts +0 -430
  234. package/packages/background-tasks/src/delegate/seed.ts +0 -423
  235. package/packages/background-tasks/src/delegate/types.ts +0 -323
  236. package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
  237. package/packages/background-tasks/src/delegate-extension.ts +0 -654
  238. package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
  239. package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
  240. package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
  241. package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
  242. package/packages/compactor/src/compaction/build-sections.ts +0 -76
  243. package/packages/compactor/src/compaction/extract/goals.ts +0 -36
  244. package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
  245. package/packages/compactor/src/compaction/format.ts +0 -53
  246. package/packages/compactor/src/compaction/merge.ts +0 -143
  247. package/packages/compactor/src/config/presets.ts +0 -160
  248. package/packages/compactor/src/executor/executor.ts +0 -233
  249. package/packages/compactor/src/executor/runtime.ts +0 -115
  250. package/packages/compactor/src/security/evaluator.ts +0 -89
  251. package/packages/compactor/src/security/policy.ts +0 -96
  252. package/packages/compactor/src/security/scanner.ts +0 -65
  253. package/packages/compactor/src/session/auto-inject.ts +0 -60
  254. package/packages/compactor/src/session/db.ts +0 -325
  255. package/packages/compactor/src/session/extract.ts +0 -144
  256. package/packages/compactor/src/session/resume-inject.ts +0 -64
  257. package/packages/compactor/src/session/snapshot.ts +0 -327
  258. package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
  259. package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
  260. package/packages/compactor/src/tools/ctx-execute.ts +0 -23
  261. package/packages/compactor/src/tools/ctx-stats.ts +0 -96
  262. package/packages/image/README.md +0 -99
  263. package/packages/image/package.json +0 -61
  264. package/packages/image/skills/image/SKILL.md +0 -76
  265. package/packages/image/src/generate.ts +0 -256
  266. package/packages/image/src/index.ts +0 -135
  267. package/packages/image/src/models.ts +0 -519
  268. package/packages/image/src/openai-images-api.ts +0 -282
  269. package/packages/image/src/register-providers.ts +0 -209
  270. package/packages/image/src/settings.ts +0 -173
  271. package/packages/image/src/tools.ts +0 -326
  272. package/packages/input-shortcuts/src/clipboard.ts +0 -119
  273. package/packages/kanboard/src/runner.ts +0 -817
  274. package/packages/skill-registry/skills/auto/SKILL.md +0 -465
  275. package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
  276. package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
  277. package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
  278. package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
  279. package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
  280. package/packages/skill-registry/skills/debug/SKILL.md +0 -228
  281. package/packages/skill-registry/skills/document/SKILL.md +0 -120
  282. package/packages/skill-registry/skills/fix/SKILL.md +0 -212
  283. package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
  284. package/packages/skill-registry/skills/plan/SKILL.md +0 -231
  285. package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
  286. package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
  287. package/packages/skill-registry/skills/research/SKILL.md +0 -251
  288. package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
  289. package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
  290. package/packages/skill-registry/skills/work/SKILL.md +0 -218
  291. package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
  292. package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
  293. package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
  294. package/packages/subagents/agents/delegate.md +0 -14
  295. package/packages/subagents/agents/oracle.md +0 -78
  296. package/packages/subagents/agents/researcher.md +0 -52
  297. package/packages/subagents/agents/reviewer.md +0 -80
  298. package/packages/subagents/agents/scout.md +0 -50
  299. package/packages/subagents/agents/worker.md +0 -59
  300. package/packages/subagents/prompts/council.md +0 -48
  301. package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
  302. package/packages/subagents/prompts/parallel-cleanup.md +0 -59
  303. package/packages/subagents/prompts/parallel-research.md +0 -50
  304. package/packages/subagents/prompts/parallel-review.md +0 -54
  305. package/packages/subagents/prompts/review-loop.md +0 -43
  306. package/packages/subagents/skills/council-mode/SKILL.md +0 -230
  307. package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
  308. package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
  309. package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
  310. package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
  311. package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
  312. package/packages/subagents/src/acceptance.ts +0 -331
  313. package/packages/subagents/src/agent-manager.ts +0 -405
  314. package/packages/subagents/src/agent-memory.ts +0 -300
  315. package/packages/subagents/src/agent-overrides.ts +0 -183
  316. package/packages/subagents/src/agent-runner.ts +0 -271
  317. package/packages/subagents/src/async-runner.ts +0 -422
  318. package/packages/subagents/src/authority-policy.ts +0 -47
  319. package/packages/subagents/src/budgets.ts +0 -285
  320. package/packages/subagents/src/child-safety.ts +0 -140
  321. package/packages/subagents/src/config.ts +0 -249
  322. package/packages/subagents/src/conversation-viewer.ts +0 -281
  323. package/packages/subagents/src/core-compat.ts +0 -94
  324. package/packages/subagents/src/custom-agents.ts +0 -343
  325. package/packages/subagents/src/file-system-retry.ts +0 -50
  326. package/packages/subagents/src/fleet-data.ts +0 -105
  327. package/packages/subagents/src/fleet-view.ts +0 -322
  328. package/packages/subagents/src/foreground-detach.ts +0 -59
  329. package/packages/subagents/src/fork-context.ts +0 -285
  330. package/packages/subagents/src/global.d.ts +0 -7
  331. package/packages/subagents/src/guide.ts +0 -129
  332. package/packages/subagents/src/mission-state.ts +0 -133
  333. package/packages/subagents/src/mission-store.ts +0 -436
  334. package/packages/subagents/src/output-limits.ts +0 -142
  335. package/packages/subagents/src/parity-types.ts +0 -315
  336. package/packages/subagents/src/pi-args.ts +0 -167
  337. package/packages/subagents/src/result-files.ts +0 -232
  338. package/packages/subagents/src/result-watcher.ts +0 -221
  339. package/packages/subagents/src/retained-children.ts +0 -176
  340. package/packages/subagents/src/run-fanout-budget.ts +0 -356
  341. package/packages/subagents/src/scheduled-runs.ts +0 -349
  342. package/packages/subagents/src/schemas.ts +0 -263
  343. package/packages/subagents/src/slash-commands.ts +0 -80
  344. package/packages/subagents/src/supervisor-channel.ts +0 -249
  345. package/packages/subagents/src/tool-handler.ts +0 -1144
  346. package/packages/subagents/src/types.ts +0 -238
  347. package/packages/subagents/src/widget.ts +0 -457
  348. package/packages/subagents/src/workflow-script.ts +0 -737
  349. package/packages/subagents/src/workflow-worker.ts +0 -384
  350. package/packages/subagents/src/worktree.ts +0 -614
  351. package/packages/utility/src/analytics/collector.ts +0 -293
  352. package/packages/utility/src/info-screen.ts +0 -80
  353. package/packages/utility/src/lifecycle/process.ts +0 -162
  354. package/packages/utility/src/prefix-cache.ts +0 -263
  355. package/packages/utility/src/skill-discovery.ts +0 -542
  356. package/packages/utility/src/tools/env.ts +0 -113
  357. package/packages/utility/src/tui/name-badge-state.ts +0 -315
  358. package/packages/utility/src/tui/name-badge.ts +0 -109
  359. /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The compaction card — one line in the transcript after each compaction,
3
+ * details on ctrl+o. A custom entry: rendered, never sent to the model.
4
+ *
5
+ * Pi draws its own `[compaction] Compacted from N tokens` block (expands to
6
+ * the summary); this card adds what Pi does not say: the size after, the
7
+ * method, what triggered it, and what was kept.
8
+ */
9
+
10
+ import { truncateToWidth, type Component } from "@earendil-works/pi-tui";
11
+ import { formatTokens, rail, type KitTheme } from "@pi-unipi/core";
12
+ import type { CompactionMethod } from "./types.js";
13
+
14
+ export const CARD_TYPE = "unipi-compaction";
15
+
16
+ export type CompactionTrigger = "manual" | "threshold" | "overflow" | "percent";
17
+
18
+ export interface CompactionCardData {
19
+ method: CompactionMethod;
20
+ trigger: CompactionTrigger;
21
+ /** The command that ran it (manual only), e.g. "unipi:compact-vcc". */
22
+ command?: string;
23
+ tokensBefore: number;
24
+ tokensAfter?: number;
25
+ summaryTokens?: number;
26
+ keptTurns?: number;
27
+ totalTurns?: number;
28
+ keptTokens?: number;
29
+ sections?: string[];
30
+ percent?: number;
31
+ threshold?: number;
32
+ }
33
+
34
+ const METHOD_NAME: Record<CompactionMethod, string> = {
35
+ vcc: "lossless",
36
+ llm: "model summary",
37
+ };
38
+
39
+ const COLOR = "customMessageLabel";
40
+
41
+ function triggerShort(d: CompactionCardData): string {
42
+ if (d.trigger === "percent") return d.percent != null ? `at ${Math.round(d.percent)}%` : "at threshold";
43
+ if (d.trigger === "threshold") return "context limit";
44
+ if (d.trigger === "overflow") return "overflow";
45
+ return d.command ? `/${d.command}` : "manual";
46
+ }
47
+
48
+ function triggerLong(d: CompactionCardData): string {
49
+ if (d.trigger === "percent") return `${d.percent != null ? `${Math.round(d.percent)}%` : "threshold"} of context${d.threshold != null ? ` (setting: ${d.threshold}%)` : ""}`;
50
+ if (d.trigger === "threshold") return "Pi's context limit";
51
+ if (d.trigger === "overflow") return "context overflow — the request did not fit";
52
+ return d.command ? `/${d.command}` : "manual /compact";
53
+ }
54
+
55
+ /** The collapsed line: sizes, method, notable outcome, trigger. */
56
+ export function cardHeadline(d: CompactionCardData): string {
57
+ const size = d.tokensAfter != null ? `${formatTokens(d.tokensBefore)} → ${formatTokens(d.tokensAfter)}` : `from ${formatTokens(d.tokensBefore)}`;
58
+ const parts = [`Compacted ${size} tokens`, METHOD_NAME[d.method]];
59
+ parts.push(triggerShort(d));
60
+ return parts.join(" · ");
61
+ }
62
+
63
+ /** Label/value rows for the expanded card. */
64
+ export function cardDetails(d: CompactionCardData): Array<[string, string]> {
65
+ const rows: Array<[string, string]> = [
66
+ ["Method", METHOD_NAME[d.method]],
67
+ ["Trigger", triggerLong(d)],
68
+ ];
69
+ if (d.keptTurns != null && d.totalTurns != null) {
70
+ rows.push(["Kept", `last ${d.keptTurns} of ${d.totalTurns} turns${d.keptTokens != null ? ` · ~${formatTokens(d.keptTokens)} tokens verbatim` : ""}`]);
71
+ }
72
+ if (d.summaryTokens != null) {
73
+ rows.push(["Summary", `~${formatTokens(d.summaryTokens)} tokens${d.sections?.length ? ` · ${d.sections.join(", ")}` : ""}`]);
74
+ }
75
+ rows.push(["Recall", "everything before stays searchable: /unipi:session-recall"]);
76
+ return rows;
77
+ }
78
+
79
+ export function renderCompactionCard(d: CompactionCardData, expanded: boolean, theme: KitTheme): Component {
80
+ const lines = (width: number): string[] => {
81
+ const out = [rail(theme, COLOR, cardHeadline(d), expanded ? "" : theme.fg("dim", "ctrl+o"), width)];
82
+ if (expanded) {
83
+ for (const [label, value] of cardDetails(d)) {
84
+ out.push(rail(theme, COLOR, `${theme.fg("dim", label.padEnd(8))} ${theme.fg("muted", value)}`, "", width));
85
+ }
86
+ }
87
+ return out.map((l) => truncateToWidth(l, width));
88
+ };
89
+ return { invalidate() {}, render: lines };
90
+ }
@@ -1,182 +1,125 @@
1
1
  /**
2
- * All /unipi:compact-* commands
2
+ * Compactor commands
3
3
  *
4
- * Commands perform real work by calling tool implementations directly.
5
- * Dependencies (sessionDB, sessionId) are injected at registration time.
4
+ * /unipi:compact-vcc [keep:N] lossless zero-LLM compaction
5
+ * /unipi:compact-by-llm [focus] model-written summary (Pi's summarizer)
6
+ * /unipi:session-recall <query> search the full session history
7
+ * /unipi:compact-stats | -doctor | -help
6
8
  */
7
9
 
8
10
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
9
- import { loadConfig, saveConfig } from "../config/manager.js";
10
- import { applyPreset } from "../config/presets.js";
11
- import { COMPACTOR_INSTRUCTION, formatTokens, registerCommandRunner } from "@pi-unipi/core";
12
- import { getLastCompactionStats, formatCompactionStats } from "../compaction/hooks.js";
11
+ import { COMPACTOR_INSTRUCTION, formatTokens, harnessMetadata } from "@pi-unipi/core";
12
+ import { loadConfig } from "../config/manager.js";
13
+ import { setPendingCompaction } from "../compaction/hooks.js";
13
14
  import { vccRecall } from "../tools/vcc-recall.js";
14
- import { ctxStats } from "../tools/ctx-stats.js";
15
15
  import { ctxDoctor } from "../tools/ctx-doctor.js";
16
16
  import { recallBlocksFromContext } from "../session/recall-blocks.js";
17
17
  import { filterNoise } from "../compaction/filter-noise.js";
18
18
  import { parseRecallScope } from "../compaction/recall-scope.js";
19
- import type { SessionDB } from "../session/db.js";
20
- import type { NormalizedBlock, RuntimeCounters } from "../types.js";
19
+ import { methodBreakdown, sessionCompactionStats } from "../stats.js";
20
+ import type { CompactionMethod } from "../types.js";
21
21
 
22
- export interface CommandDeps {
23
- sessionDB: SessionDB | null;
24
- getSessionId: () => string;
25
- getBlocks: () => NormalizedBlock[];
26
- getCounters?: () => RuntimeCounters;
22
+ function runCompaction(ctx: ExtensionCommandContext, method: CompactionMethod, args: string, command: string): void {
23
+ const trimmed = args.trim();
24
+ setPendingCompaction(method, true, command);
25
+ ctx.compact({
26
+ customInstructions: method === "llm" ? trimmed || undefined : trimmed ? `${COMPACTOR_INSTRUCTION} ${trimmed}` : COMPACTOR_INSTRUCTION,
27
+ // Success shows as the compaction card in the transcript.
28
+ onComplete: () => setPendingCompaction(null),
29
+ onError: (err: Error) => {
30
+ setPendingCompaction(null);
31
+ // Pi already reports "Nothing to compact (session too small)".
32
+ if (/too small/i.test(err.message)) return;
33
+ if (err.message === "Compaction cancelled" || err.message === "Already compacted") ctx.ui.notify("Nothing to compact.", "info");
34
+ else ctx.ui.notify(`Compaction failed: ${err.message}`, "error");
35
+ },
36
+ });
27
37
  }
28
38
 
29
- export function registerCommands(pi: ExtensionAPI, deps?: CommandDeps): void {
30
- // ── /unipi:lossless-compact ──────────────────────────
31
- const losslessCompactHandler = async (_args: string, ctx: ExtensionCommandContext) => {
32
- ctx.compact({
33
- customInstructions: COMPACTOR_INSTRUCTION,
34
- onComplete: () => {
35
- const stats = getLastCompactionStats();
36
- if (stats) {
37
- ctx.ui.notify(formatCompactionStats(stats), "info");
38
- } else {
39
- ctx.ui.notify("Compaction completed.", "info");
40
- }
41
- },
42
- onError: (err: Error) => {
43
- if (err.message === "Compaction cancelled" || err.message === "Already compacted") {
44
- ctx.ui.notify("Nothing to compact.", "info");
45
- } else {
46
- ctx.ui.notify(`Compaction failed: ${err.message}`, "error");
47
- }
48
- },
49
- });
50
- };
51
- pi.registerCommand("unipi:lossless-compact", {
52
- description: "Immediate zero-LLM compaction — structured summary with full recall",
53
- handler: losslessCompactHandler,
39
+ export function registerCommands(pi: ExtensionAPI): void {
40
+ pi.registerCommand("unipi:compact-vcc", {
41
+ description: "Lossless compaction now — instant structured summary, no model call (keep:N keeps N recent turns)",
42
+ handler: async (args: string, ctx: ExtensionCommandContext) => runCompaction(ctx, "vcc", args, "unipi:compact-vcc"),
54
43
  });
55
- pi.registerCommand("unipi:compact", {
56
- description: "Alias for /unipi:lossless-compact",
57
- handler: losslessCompactHandler,
44
+ pi.registerCommand("unipi:compact-by-llm", {
45
+ description: "Compact now with a model-written summary (optional text focuses the summary)",
46
+ handler: async (args: string, ctx: ExtensionCommandContext) => runCompaction(ctx, "llm", args, "unipi:compact-by-llm"),
58
47
  });
59
-
60
- // ── /unipi:session-recall (new) ─────────────────────
61
- // pi-vcc parity: results are sent as a visible custom message AND fed to the
62
- // agent as context (triggerTurn), so recall results drive the next turn.
63
- const sessionRecallHandler = async (args: string, ctx: ExtensionCommandContext, commandName = "/unipi:session-recall") => {
48
+ // pi-vcc parity: results are shown AND fed to the agent (triggerTurn).
49
+ const sessionRecallHandler = async (args: string, ctx: ExtensionCommandContext) => {
64
50
  const raw = args.trim();
65
- const suffix = commandName === "/unipi:compact-recall" ? " (deprecated; use /unipi:session-recall <query>)" : "";
51
+ const usage = "Usage: /unipi:session-recall <query>";
66
52
  if (!raw) {
67
- ctx.ui.notify(`Usage: ${commandName} <query>${suffix}`, "warning");
53
+ ctx.ui.notify(usage, "warning");
68
54
  return;
69
55
  }
70
-
71
- // Parse scope:all and page:N inline (pi-vcc parity)
72
56
  const parsed = parseRecallScope(raw);
73
57
  const pageMatch = parsed.text.match(/\bpage:(\d+)\b/i);
74
58
  const page = pageMatch ? Math.max(1, parseInt(pageMatch[1], 10)) : 1;
75
59
  const query = parsed.text.replace(/\bpage:\d+\b/i, "").trim();
76
-
77
60
  if (!query) {
78
- ctx.ui.notify(`Usage: ${commandName} <query>${suffix}`, "warning");
61
+ ctx.ui.notify(usage, "warning");
79
62
  return;
80
63
  }
81
-
82
- // Prefer the live session branch over cached blocks. The branch includes raw
83
- // pre-compaction messages that are omitted from the compacted LLM context.
84
- const config = loadConfig((ctx as any).cwd ?? process.cwd());
85
- const liveBlocks = filterNoise(recallBlocksFromContext(ctx), config.pipeline?.customNoisePatterns);
86
- const blocks = liveBlocks.length > 0 ? liveBlocks : (deps?.getBlocks() ?? []);
64
+ const blocks = filterNoise(recallBlocksFromContext(ctx));
87
65
  if (blocks.length === 0) {
88
66
  ctx.ui.notify("No session history available for search.", "warning");
89
67
  return;
90
68
  }
91
69
  const result = vccRecall(blocks, { query, scope: parsed.scope, page });
92
- pi.sendMessage(
93
- { customType: "compactor-recall", content: result.text, display: true },
94
- { triggerTurn: true },
95
- );
70
+ pi.sendMessage({
71
+ customType: "compactor-recall",
72
+ content: result.text,
73
+ display: true,
74
+ details: { unipiHarness: harnessMetadata({ source: "Compactor", title: "Session recall", synopsis: "Results from /unipi:session-recall" }, "direct") },
75
+ }, { triggerTurn: true });
96
76
  };
97
77
  pi.registerCommand("unipi:session-recall", {
98
78
  description: "Recall earlier parts of this session. Plain keywords work best; add scope:all to reach edited or retried turns.",
99
79
  handler: sessionRecallHandler,
100
80
  });
101
- // Deprecated alias
102
- pi.registerCommand("unipi:compact-recall", {
103
- description: "(DEPRECATED) Search session history — use /unipi:session-recall instead",
104
- handler: async (args: string, ctx: ExtensionCommandContext) => {
105
- return sessionRecallHandler(args, ctx, "/unipi:compact-recall");
106
- },
107
- });
108
-
109
- // ── /unipi:compact-stats ─────────────────────────────
110
81
  pi.registerCommand("unipi:compact-stats", {
111
- description: "Show context savings dashboard",
82
+ description: "Show this session's compaction savings",
112
83
  handler: async (_args: string, ctx: ExtensionCommandContext) => {
113
- if (!deps?.sessionDB) {
114
- ctx.ui.notify("Compactor services not initialized.", "error");
115
- return;
116
- }
117
- try {
118
- const stats = await ctxStats(deps.sessionDB, deps.getSessionId(), deps.getCounters?.());
119
- const lines = [
120
- "📊 Compactor Stats",
121
- `Session events: ${stats.sessionEvents}`,
122
- `Compactions: ${stats.compactions}`,
123
- `Tokens saved: ${stats.tokensSaved}`,
124
- `Sandbox runs: ${stats.sandboxRuns}`,
125
- `Search queries: ${stats.searchQueries}`,
126
- ];
127
- ctx.ui.notify(lines.join("\n"), "info");
128
- } catch (err) {
129
- ctx.ui.notify(`Stats error: ${err}`, "error");
130
- }
84
+ const stats = sessionCompactionStats(ctx.sessionManager.getBranch() as any[]);
85
+ const usage = ctx.getContextUsage?.();
86
+ const lines = [
87
+ "Compactor — this session",
88
+ `Compactions: ${stats.compactions.length}${stats.compactions.length ? ` (${methodBreakdown(stats)})` : ""}`,
89
+ `Tokens: ${stats.tokensBefore ? `${formatTokens(stats.tokensBefore)} → ${formatTokens(stats.tokensAfter)} (−${formatTokens(stats.tokensSaved)})` : "nothing compacted yet"}`,
90
+ usage?.tokens != null && usage.contextWindow ? `Context now: ~${formatTokens(usage.tokens)} / ${formatTokens(usage.contextWindow)}` : "",
91
+ ].filter(Boolean);
92
+ ctx.ui.notify(lines.join("\n"), "info");
131
93
  },
132
94
  });
133
95
 
134
- // ── /unipi:compact-doctor ────────────────────────────
135
96
  pi.registerCommand("unipi:compact-doctor", {
136
- description: "Run diagnostics checklist",
97
+ description: "Check compaction settings and leftovers",
137
98
  handler: async (_args: string, ctx: ExtensionCommandContext) => {
138
- if (!deps?.sessionDB) {
139
- ctx.ui.notify("Compactor services not initialized.", "error");
140
- return;
141
- }
142
- try {
143
- const result = await ctxDoctor(deps.sessionDB);
144
- const icon = (s: string) => (s === "pass" ? "✅" : s === "warn" ? "⚠️" : "❌");
145
- const lines = [
146
- result.healthy ? "🩺 All checks passed" : "🩺 Issues found",
147
- "",
148
- ...result.checks.map((c) => `${icon(c.status)} ${c.name}: ${c.message}`),
149
- ];
150
- ctx.ui.notify(lines.join("\n"), result.healthy ? "info" : "warning");
151
- } catch (err) {
152
- ctx.ui.notify(`Doctor error: ${err}`, "error");
153
- }
99
+ const result = ctxDoctor(loadConfig(ctx.cwd), { hasModel: Boolean(ctx.model) });
100
+ const icon = (s: string) => (s === "pass" ? "✓" : s === "warn" ? "!" : "✗");
101
+ const lines = [
102
+ result.healthy ? "Compactor: all checks passed" : "Compactor: issues found",
103
+ ...result.checks.map((c) => `${icon(c.status)} ${c.name}: ${c.message}`),
104
+ ];
105
+ ctx.ui.notify(lines.join("\n"), result.healthy ? "info" : "warning");
154
106
  },
155
107
  });
156
108
 
157
- // Hub action runners — "Apply preset: X" rows in /unipi:settings. These
158
- // mirror the removed slash-command preset flow (applyPreset + save).
159
- for (const name of ["precise", "balanced", "thorough", "lean"] as const) {
160
- registerCommandRunner(`unipi:compact-apply-${name}`, () => {
161
- saveConfig(applyPreset(name));
162
- });
163
- }
164
-
165
- // ── /unipi:compact-help ──────────────────────────────
166
109
  pi.registerCommand("unipi:compact-help", {
167
- description: "Show detailed compactor documentation (tier-2 skill)",
110
+ description: "Show compactor help",
168
111
  handler: async (_args: string, ctx: ExtensionCommandContext) => {
169
112
  ctx.ui.notify(
170
- "🗜️ Compactor Help\n" +
171
- "Quick commands:\n" +
172
- " /unipi:lossless-compact — trigger immediate compaction\n" +
173
- " /unipi:session-recall <query> — search session history\n" +
174
- " /unipi:compact-stats — view stats\n" +
175
- " /unipi:compact-doctor — run diagnostics\n" +
176
- " auto-compaction settings — /unipi:settings (Compactor group)\n" +
177
- "\n" +
178
- "Percentage trigger:\n" +
179
- " Disabled by default. Enable it in /unipi:settings (Compactor › Auto) to compact at a context % before Pi's reserve-token limit.",
113
+ [
114
+ "Compactor",
115
+ " /unipi:compact-vcc [keep:N] lossless compaction now (no model call)",
116
+ " /unipi:compact-by-llm [focus] compact now with a model-written summary",
117
+ " /unipi:session-recall <query> search everything in this session, including compacted parts",
118
+ " /unipi:compact-stats this session's savings",
119
+ " /unipi:compact-doctor check settings",
120
+ "",
121
+ "Settings: /unipi:settings → Compactor (method, what Pi's /compact does, when to compact).",
122
+ ].join("\n"),
180
123
  "info",
181
124
  );
182
125
  },
@@ -65,9 +65,11 @@ export const parseCompactionInstructions = (
65
65
  return { isCompactor: true, keepUserTurns: 1, keepUserTurnsExplicit: false, followUpPrompt: null };
66
66
  }
67
67
 
68
- const keepPrefix = `${COMPACTOR_INSTRUCTION} `;
69
- if (trimmed?.startsWith(keepPrefix)) {
70
- const parsed = parseKeepAndPrompt(trimmed.slice(keepPrefix.length));
68
+ // Marker + anything after whitespace (space or newline, e.g. ask-user's
69
+ // handoff text) is ours; only a keep:N is honored — the caller delivers
70
+ // its own follow-up, so no prompt is replayed from here.
71
+ if (trimmed?.startsWith(COMPACTOR_INSTRUCTION) && /^\s/.test(trimmed.slice(COMPACTOR_INSTRUCTION.length))) {
72
+ const parsed = parseKeepAndPrompt(trimmed.slice(COMPACTOR_INSTRUCTION.length).trim().split(/\n/)[0]);
71
73
  return {
72
74
  isCompactor: true,
73
75
  keepUserTurns: parsed.keepUserTurns ?? 1,
@@ -38,7 +38,7 @@ export const filterNoise = (blocks: NormalizedBlock[], extraPatterns?: string[])
38
38
  if (isNoiseUserBlock(b.text, extraPatterns)) continue;
39
39
  const cleaned = cleanUserText(b.text);
40
40
  if (!cleaned) continue;
41
- out.push({ kind: "user", text: cleaned });
41
+ out.push({ ...b, text: cleaned });
42
42
  continue;
43
43
  }
44
44
  out.push(b);