@north-light/crouter 0.3.170 → 0.3.172

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 (670) hide show
  1. package/dist/api/client.d.ts +37 -11
  2. package/dist/api/client.js +84 -15
  3. package/dist/api/dto/human.d.ts +53 -39
  4. package/dist/api/dto/human.js +2 -3
  5. package/dist/api/dto/inbox.d.ts +0 -1
  6. package/dist/api/dto/nodes.d.ts +12 -0
  7. package/dist/api/dto/review-comments.d.ts +137 -0
  8. package/dist/api/dto/review-comments.js +5 -0
  9. package/dist/api/dto/reviews.d.ts +109 -0
  10. package/dist/api/dto/reviews.js +5 -0
  11. package/dist/api/index.d.ts +2 -0
  12. package/dist/api/index.js +2 -0
  13. package/dist/api/routes.d.ts +17 -4
  14. package/dist/api/routes.js +21 -5
  15. package/dist/build-root.d.ts +1 -16
  16. package/dist/build-root.js +1 -25
  17. package/dist/builtin-memory/00-runtime-base.md +7 -5
  18. package/dist/builtin-memory/04-base-worker.md +1 -1
  19. package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
  20. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  21. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
  23. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
  27. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
  28. package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
  29. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
  30. package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
  31. package/dist/builtin-memory/design.md +2 -2
  32. package/dist/builtin-memory/insights/capture.md +50 -0
  33. package/dist/builtin-memory/insights/init.md +45 -0
  34. package/dist/builtin-memory/insights/listen.md +9 -0
  35. package/dist/builtin-memory/internal/agent-shaping.md +2 -2
  36. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  37. package/dist/builtin-memory/internal/plugins.md +12 -11
  38. package/dist/builtin-memory/internal/storage-tiers.md +2 -2
  39. package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
  40. package/dist/builtin-memory/plan.md +19 -0
  41. package/dist/builtin-memory/spec/guide.md +38 -0
  42. package/dist/builtin-memory/spec/requirements.md +31 -0
  43. package/dist/builtin-memory/spec/roadmap.md +35 -0
  44. package/dist/builtin-memory/spec.md +10 -86
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
  51. package/dist/cli.js +2 -6
  52. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
  53. package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
  54. package/dist/clients/attach/__tests__/context-message.test.js +142 -6
  55. package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
  56. package/dist/clients/attach/__tests__/diagram.test.js +1 -1
  57. package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
  58. package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
  59. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
  60. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
  61. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
  62. package/dist/clients/attach/chrome/header.d.ts +10 -0
  63. package/dist/clients/attach/chrome/header.js +30 -0
  64. package/dist/clients/attach/chrome/recap.d.ts +7 -0
  65. package/dist/clients/attach/chrome/recap.js +19 -0
  66. package/dist/clients/attach/chrome/status-line.d.ts +3 -0
  67. package/dist/clients/attach/chrome/status-line.js +5 -0
  68. package/dist/clients/attach/chrome/widgets.js +11 -21
  69. package/dist/clients/attach/command.js +11 -7
  70. package/dist/clients/attach/config.d.ts +4 -0
  71. package/dist/clients/attach/config.js +3 -0
  72. package/dist/clients/attach/input/controller.d.ts +19 -0
  73. package/dist/clients/attach/input/controller.js +62 -28
  74. package/dist/clients/attach/input/titled-editor.d.ts +0 -4
  75. package/dist/clients/attach/input/titled-editor.js +2 -10
  76. package/dist/clients/attach/overlays/file-review.d.ts +9 -5
  77. package/dist/clients/attach/overlays/file-review.js +9 -70
  78. package/dist/clients/attach/overlays/help.d.ts +33 -0
  79. package/dist/clients/attach/overlays/help.js +204 -0
  80. package/dist/clients/attach/render/activity-slot.d.ts +4 -0
  81. package/dist/clients/attach/render/activity-slot.js +13 -0
  82. package/dist/clients/attach/render/chat-view.d.ts +117 -12
  83. package/dist/clients/attach/render/chat-view.js +604 -135
  84. package/dist/clients/attach/render/context-message.d.ts +2 -1
  85. package/dist/clients/attach/render/context-message.js +17 -13
  86. package/dist/clients/attach/render/crtr-output.js +1 -3
  87. package/dist/clients/attach/render/diagram.js +2 -2
  88. package/dist/clients/attach/render/edit-diff.d.ts +4 -1
  89. package/dist/clients/attach/render/edit-diff.js +7 -11
  90. package/dist/clients/attach/render/group-activity.d.ts +32 -0
  91. package/dist/clients/attach/render/group-activity.js +206 -0
  92. package/dist/clients/attach/render/group-recap.d.ts +10 -0
  93. package/dist/clients/attach/render/group-recap.js +93 -0
  94. package/dist/clients/attach/render/html-markdown.d.ts +17 -0
  95. package/dist/clients/attach/render/html-markdown.js +228 -0
  96. package/dist/clients/attach/render/measured-container.d.ts +96 -0
  97. package/dist/clients/attach/render/measured-container.js +322 -0
  98. package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
  99. package/dist/clients/attach/render/scroll-animation.js +80 -0
  100. package/dist/clients/attach/render/tool-calls.js +6 -6
  101. package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
  102. package/dist/clients/attach/render/transcript-copy.js +81 -0
  103. package/dist/clients/attach/render/viewport.d.ts +29 -0
  104. package/dist/clients/attach/render/viewport.js +159 -0
  105. package/dist/clients/attach/session/bindings.d.ts +10 -7
  106. package/dist/clients/attach/session/bindings.js +23 -8
  107. package/dist/clients/attach/session/connection.js +4 -5
  108. package/dist/clients/attach/session/context.d.ts +6 -4
  109. package/dist/clients/attach/session/frame.d.ts +34 -0
  110. package/dist/clients/attach/session/frame.js +176 -0
  111. package/dist/clients/attach/session/frames.d.ts +4 -1
  112. package/dist/clients/attach/session/frames.js +14 -1
  113. package/dist/clients/attach/session/identity.js +4 -3
  114. package/dist/clients/attach/session/input-wiring.d.ts +14 -4
  115. package/dist/clients/attach/session/input-wiring.js +15 -13
  116. package/dist/clients/attach/session/invariant.d.ts +9 -0
  117. package/dist/clients/attach/session/invariant.js +15 -0
  118. package/dist/clients/attach/session/keys.d.ts +10 -2
  119. package/dist/clients/attach/session/keys.js +13 -5
  120. package/dist/clients/attach/session/layout.d.ts +10 -8
  121. package/dist/clients/attach/session/layout.js +33 -34
  122. package/dist/clients/attach/session/mouse.d.ts +18 -0
  123. package/dist/clients/attach/session/mouse.js +64 -0
  124. package/dist/clients/attach/session/pane-tag.d.ts +3 -0
  125. package/dist/clients/attach/session/pane-tag.js +51 -8
  126. package/dist/clients/attach/session/reconnect.d.ts +3 -0
  127. package/dist/clients/attach/session/reconnect.js +42 -5
  128. package/dist/clients/attach/session/surface-frame.d.ts +20 -0
  129. package/dist/clients/attach/session/surface-frame.js +73 -0
  130. package/dist/clients/attach/session/surface-host.d.ts +64 -0
  131. package/dist/clients/attach/session/surface-host.js +255 -0
  132. package/dist/clients/attach/session/whip.d.ts +17 -0
  133. package/dist/clients/attach/session/whip.js +334 -0
  134. package/dist/clients/attach/slash/dispatch.d.ts +13 -1
  135. package/dist/clients/attach/slash/dispatch.js +51 -29
  136. package/dist/clients/attach/viewer.js +907 -819
  137. package/dist/clients/conversation/conversation.d.ts +65 -0
  138. package/dist/clients/conversation/conversation.js +318 -0
  139. package/dist/clients/conversation/frames.d.ts +30 -0
  140. package/dist/clients/conversation/frames.js +52 -0
  141. package/dist/clients/conversation/region.d.ts +51 -0
  142. package/dist/clients/conversation/region.js +265 -0
  143. package/dist/clients/conversation/submit.d.ts +38 -0
  144. package/dist/clients/conversation/submit.js +51 -0
  145. package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
  146. package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
  147. package/dist/clients/inbox/controller.d.ts +79 -0
  148. package/dist/clients/inbox/controller.js +448 -0
  149. package/dist/clients/inbox/deck-adapter.d.ts +29 -0
  150. package/dist/clients/inbox/deck-adapter.js +62 -0
  151. package/dist/clients/inbox/layout.d.ts +8 -0
  152. package/dist/clients/inbox/layout.js +9 -0
  153. package/dist/clients/inbox/resolve.d.ts +10 -0
  154. package/dist/clients/inbox/resolve.js +34 -0
  155. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
  156. package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
  157. package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
  158. package/dist/clients/inbox/review/anchors.d.ts +41 -0
  159. package/dist/clients/inbox/review/anchors.js +89 -0
  160. package/dist/clients/inbox/review/columns.d.ts +22 -0
  161. package/dist/clients/inbox/review/columns.js +40 -0
  162. package/dist/clients/inbox/review/comments-client.d.ts +66 -0
  163. package/dist/clients/inbox/review/comments-client.js +98 -0
  164. package/dist/clients/inbox/review/composition.d.ts +60 -0
  165. package/dist/clients/inbox/review/composition.js +278 -0
  166. package/dist/clients/inbox/review/document-region.d.ts +120 -0
  167. package/dist/clients/inbox/review/document-region.js +902 -0
  168. package/dist/clients/inbox/review/frame.d.ts +45 -0
  169. package/dist/clients/inbox/review/frame.js +215 -0
  170. package/dist/clients/inbox/review/keys.d.ts +67 -0
  171. package/dist/clients/inbox/review/keys.js +130 -0
  172. package/dist/clients/inbox/review/launch.d.ts +10 -0
  173. package/dist/clients/inbox/review/launch.js +129 -0
  174. package/dist/clients/inbox/review/live-source.d.ts +24 -0
  175. package/dist/clients/inbox/review/live-source.js +160 -0
  176. package/dist/clients/inbox/review/nvim.d.ts +13 -0
  177. package/dist/clients/inbox/review/nvim.js +42 -0
  178. package/dist/clients/inbox/review/remap.d.ts +51 -0
  179. package/dist/clients/inbox/review/remap.js +157 -0
  180. package/dist/clients/inbox/review/review-client.d.ts +30 -0
  181. package/dist/clients/inbox/review/review-client.js +107 -0
  182. package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
  183. package/dist/clients/inbox/review/roundtrip.js +36 -0
  184. package/dist/clients/inbox/review/state.d.ts +143 -0
  185. package/dist/clients/inbox/review/state.js +282 -0
  186. package/dist/clients/inbox/review-adapter.d.ts +29 -0
  187. package/dist/clients/inbox/review-adapter.js +92 -0
  188. package/dist/clients/inbox/review-visibility.d.ts +5 -0
  189. package/dist/clients/inbox/review-visibility.js +19 -0
  190. package/dist/clients/inbox/surface.d.ts +19 -0
  191. package/dist/clients/inbox/surface.js +128 -0
  192. package/dist/clients/inbox/tui/ansi.d.ts +66 -0
  193. package/dist/clients/inbox/tui/ansi.js +317 -0
  194. package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
  195. package/dist/clients/inbox/tui/clipboard.js +26 -0
  196. package/dist/clients/inbox/tui/input.d.ts +7 -0
  197. package/dist/clients/inbox/tui/input.js +653 -0
  198. package/dist/clients/inbox/tui/keys.d.ts +28 -0
  199. package/dist/clients/inbox/tui/keys.js +111 -0
  200. package/dist/clients/inbox/tui/panel.d.ts +2 -0
  201. package/dist/clients/inbox/tui/panel.js +217 -0
  202. package/dist/clients/inbox/tui/render.d.ts +37 -0
  203. package/dist/clients/inbox/tui/render.js +476 -0
  204. package/dist/clients/inbox/tui/types.d.ts +57 -0
  205. package/dist/clients/inbox/tui/types.js +1 -0
  206. package/dist/clients/inbox/tui.d.ts +6 -0
  207. package/dist/clients/inbox/tui.js +74 -0
  208. package/dist/clients/surfaces/host.d.ts +66 -0
  209. package/dist/clients/surfaces/host.js +1 -0
  210. package/dist/clients/surfaces/region.d.ts +16 -0
  211. package/dist/clients/surfaces/region.js +1 -0
  212. package/dist/clients/web/__tests__/push-engine.test.js +14 -158
  213. package/dist/clients/web/dev-server.d.ts +3 -3
  214. package/dist/clients/web/dev-server.js +9 -23
  215. package/dist/clients/web/events.js +4 -6
  216. package/dist/clients/web/push-engine.d.ts +2 -66
  217. package/dist/clients/web/push-engine.js +30 -161
  218. package/dist/clients/web/push-registry.d.ts +0 -4
  219. package/dist/clients/web/push-registry.js +2 -7
  220. package/dist/clients/web/server.js +3 -35
  221. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
  222. package/dist/clients/web/web-cmd.js +2 -2
  223. package/dist/commands/__tests__/human.test.js +27 -15
  224. package/dist/commands/api-client.js +3 -3
  225. package/dist/commands/canvas-browse.js +1 -1
  226. package/dist/commands/canvas-issue.js +1 -1
  227. package/dist/commands/canvas-use.js +1 -1
  228. package/dist/commands/human/doc.d.ts +2 -0
  229. package/dist/commands/human/doc.js +98 -0
  230. package/dist/commands/human/inbox.d.ts +2 -0
  231. package/dist/commands/human/inbox.js +101 -0
  232. package/dist/commands/human/prompts.d.ts +2 -3
  233. package/dist/commands/human/prompts.js +27 -180
  234. package/dist/commands/human/queue.d.ts +1 -5
  235. package/dist/commands/human/queue.js +54 -216
  236. package/dist/commands/human/review.d.ts +2 -0
  237. package/dist/commands/human/review.js +298 -0
  238. package/dist/commands/human/shared.d.ts +2 -69
  239. package/dist/commands/human/shared.js +1 -181
  240. package/dist/commands/human.js +15 -20
  241. package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
  242. package/dist/commands/memory/__tests__/lint.test.js +15 -0
  243. package/dist/commands/memory/delete.js +2 -2
  244. package/dist/commands/memory/lint.d.ts +1 -0
  245. package/dist/commands/memory/lint.js +21 -3
  246. package/dist/commands/memory/read.js +4 -4
  247. package/dist/commands/node.js +8 -7
  248. package/dist/commands/pkg/plugin-manage.js +143 -68
  249. package/dist/commands/surface-inspect.js +2 -2
  250. package/dist/commands/surface.js +6 -12
  251. package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
  252. package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
  253. package/dist/commands/sys/config.js +29 -3
  254. package/dist/commands/sys/feedback.js +1 -1
  255. package/dist/commands/sys/setup-core.d.ts +12 -11
  256. package/dist/commands/sys/setup-core.js +55 -46
  257. package/dist/commands/sys/setup-wizard.d.ts +4 -1
  258. package/dist/commands/sys/setup-wizard.js +50 -9
  259. package/dist/commands/sys/sync-deps.js +1 -1
  260. package/dist/commands/sys.js +4 -6
  261. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
  262. package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
  263. package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
  264. package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
  265. package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
  266. package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
  267. package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
  268. package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
  269. package/dist/core/__tests__/full/detach-focus.test.js +1 -1
  270. package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
  271. package/dist/core/__tests__/human-deliver.test.js +71 -345
  272. package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
  273. package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
  274. package/dist/core/__tests__/migration.test.js +10 -0
  275. package/dist/core/__tests__/model-pin-durability.test.js +14 -0
  276. package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
  277. package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
  278. package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
  279. package/dist/core/__tests__/phase4-review-store.test.js +143 -0
  280. package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
  281. package/dist/core/__tests__/revive.test.js +22 -53
  282. package/dist/core/__tests__/session-cycles.test.js +48 -18
  283. package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
  284. package/dist/core/__tests__/stop-guard.test.js +16 -1
  285. package/dist/core/__tests__/tmux-surface.test.js +21 -25
  286. package/dist/core/asset-root.d.ts +7 -0
  287. package/dist/core/asset-root.js +18 -0
  288. package/dist/core/broker-client/client.d.ts +0 -7
  289. package/dist/core/broker-client/client.js +4 -10
  290. package/dist/core/broker-client/transport-relay.d.ts +3 -4
  291. package/dist/core/broker-client/transport-relay.js +3 -4
  292. package/dist/core/canvas/__tests__/attention.test.js +1 -1
  293. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  294. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
  295. package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
  296. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  297. package/dist/core/canvas/attention.js +4 -4
  298. package/dist/core/canvas/canvas.d.ts +6 -11
  299. package/dist/core/canvas/canvas.js +11 -33
  300. package/dist/core/canvas/db.js +207 -38
  301. package/dist/core/canvas/extensions.d.ts +1 -1
  302. package/dist/core/canvas/extensions.js +8 -1
  303. package/dist/core/canvas/index.d.ts +0 -1
  304. package/dist/core/canvas/index.js +0 -1
  305. package/dist/core/canvas/nav-model.d.ts +1 -1
  306. package/dist/core/canvas/nav-model.js +1 -1
  307. package/dist/core/canvas/paths.d.ts +5 -0
  308. package/dist/core/canvas/paths.js +16 -0
  309. package/dist/core/canvas/remote-canvas-source.js +2 -2
  310. package/dist/core/canvas/remote-transport.d.ts +7 -0
  311. package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
  312. package/dist/core/canvas/source.js +1 -1
  313. package/dist/core/canvas/status-glyph.js +4 -12
  314. package/dist/core/canvas/types.d.ts +10 -35
  315. package/dist/core/clipboard-text.d.ts +8 -0
  316. package/dist/core/clipboard-text.js +18 -0
  317. package/dist/core/command-manifests/registry.d.ts +1 -3
  318. package/dist/core/command-plugins/bundle.d.ts +29 -0
  319. package/dist/core/command-plugins/bundle.js +198 -0
  320. package/dist/core/command-plugins/discovery.d.ts +0 -8
  321. package/dist/core/command-plugins/discovery.js +2 -39
  322. package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
  323. package/dist/core/command-plugins/transport/http-fetch.js +17 -95
  324. package/dist/core/command.d.ts +1 -13
  325. package/dist/core/command.js +1 -16
  326. package/dist/core/config.d.ts +4 -0
  327. package/dist/core/config.js +28 -3
  328. package/dist/core/document-lines.d.ts +4 -0
  329. package/dist/core/document-lines.js +6 -0
  330. package/dist/core/feed/feed.d.ts +2 -0
  331. package/dist/core/feed/feed.js +11 -7
  332. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
  333. package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
  334. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
  335. package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
  336. package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
  337. package/dist/core/human/__tests__/inbox-core.test.js +144 -0
  338. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
  339. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
  340. package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
  341. package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
  342. package/dist/core/human/claim.d.ts +23 -0
  343. package/dist/core/human/claim.js +67 -0
  344. package/dist/core/human/convention.d.ts +30 -0
  345. package/dist/core/human/convention.js +202 -0
  346. package/dist/core/human/deck-factories.d.ts +8 -0
  347. package/dist/core/human/deck-factories.js +15 -0
  348. package/dist/core/human/deck-schema.d.ts +70 -0
  349. package/dist/core/human/deck-schema.js +92 -0
  350. package/dist/core/human/root.d.ts +7 -0
  351. package/dist/core/human/root.js +37 -0
  352. package/dist/core/human/scan.d.ts +3 -0
  353. package/dist/core/human/scan.js +76 -0
  354. package/dist/core/human/summary.d.ts +8 -0
  355. package/dist/core/human/summary.js +44 -0
  356. package/dist/core/human/tickets.d.ts +49 -0
  357. package/dist/core/human/tickets.js +190 -0
  358. package/dist/core/human/types.d.ts +136 -0
  359. package/dist/core/human/types.js +5 -0
  360. package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
  361. package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
  362. package/dist/core/inspector/chrome.d.ts +6 -0
  363. package/dist/core/inspector/chrome.js +14 -0
  364. package/dist/core/inspector/contract.d.ts +105 -0
  365. package/dist/core/inspector/contract.js +1 -0
  366. package/dist/core/inspector/core.d.ts +4 -5
  367. package/dist/core/inspector/core.js +3 -5
  368. package/dist/core/inspector/host.d.ts +46 -0
  369. package/dist/core/{tui → inspector}/host.js +42 -208
  370. package/dist/core/inspector/text.d.ts +2 -2
  371. package/dist/core/inspector/transport.d.ts +6 -0
  372. package/dist/core/inspector/transport.js +36 -0
  373. package/dist/core/inspector/tui.d.ts +2 -2
  374. package/dist/core/inspector/tui.js +15 -15
  375. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
  376. package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
  377. package/dist/core/keybindings/attach-control.d.ts +9 -3
  378. package/dist/core/keybindings/attach-control.js +3 -1
  379. package/dist/core/keybindings/catalog.d.ts +6 -5
  380. package/dist/core/keybindings/catalog.js +61 -133
  381. package/dist/core/keybindings/inbox.d.ts +5 -6
  382. package/dist/core/keybindings/inbox.js +9 -10
  383. package/dist/core/keybindings/index.d.ts +3 -3
  384. package/dist/core/keybindings/index.js +3 -3
  385. package/dist/core/keybindings/persistence.d.ts +5 -1
  386. package/dist/core/keybindings/persistence.js +24 -6
  387. package/dist/core/keybindings/resolve.d.ts +6 -0
  388. package/dist/core/keybindings/resolve.js +10 -3
  389. package/dist/core/memory/inline-ref-grammar.js +2 -3
  390. package/dist/core/memory-resolver.d.ts +27 -29
  391. package/dist/core/memory-resolver.js +45 -39
  392. package/dist/core/model-routes.d.ts +33 -0
  393. package/dist/core/model-routes.js +42 -3
  394. package/dist/core/preview-registry.js +17 -55
  395. package/dist/core/profiles/select.js +3 -3
  396. package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
  397. package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
  398. package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
  399. package/dist/core/review/__tests__/capture-origin.test.js +139 -0
  400. package/dist/core/review/__tests__/comments.test.d.ts +1 -0
  401. package/dist/core/review/__tests__/comments.test.js +98 -0
  402. package/dist/core/review/__tests__/project.test.d.ts +1 -0
  403. package/dist/core/review/__tests__/project.test.js +71 -0
  404. package/dist/core/review/__tests__/remap.test.d.ts +1 -0
  405. package/dist/core/review/__tests__/remap.test.js +159 -0
  406. package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
  407. package/dist/core/review/__tests__/stage-identity.test.js +140 -0
  408. package/dist/core/review/birth.d.ts +7 -0
  409. package/dist/core/review/birth.js +23 -0
  410. package/dist/core/review/comments.d.ts +69 -0
  411. package/dist/core/review/comments.js +295 -0
  412. package/dist/core/review/companion.d.ts +35 -0
  413. package/dist/core/review/companion.js +205 -0
  414. package/dist/core/review/document.d.ts +27 -0
  415. package/dist/core/review/document.js +138 -0
  416. package/dist/core/review/project.d.ts +13 -0
  417. package/dist/core/review/project.js +58 -0
  418. package/dist/core/review/realize.d.ts +19 -0
  419. package/dist/core/review/realize.js +217 -0
  420. package/dist/core/review/remap.d.ts +24 -0
  421. package/dist/core/review/remap.js +156 -0
  422. package/dist/core/review/signal.d.ts +5 -0
  423. package/dist/core/review/signal.js +31 -0
  424. package/dist/core/review/stage.d.ts +26 -0
  425. package/dist/core/review/stage.js +184 -0
  426. package/dist/core/review/store.d.ts +46 -0
  427. package/dist/core/review/store.js +163 -0
  428. package/dist/core/review/ticket-filter.d.ts +17 -0
  429. package/dist/core/review/ticket-filter.js +32 -0
  430. package/dist/core/review/types.d.ts +130 -0
  431. package/dist/core/review/types.js +23 -0
  432. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
  433. package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
  434. package/dist/core/runtime/bearings.d.ts +5 -17
  435. package/dist/core/runtime/bearings.js +88 -71
  436. package/dist/core/runtime/broker-protocol.d.ts +31 -8
  437. package/dist/core/runtime/broker.d.ts +15 -1
  438. package/dist/core/runtime/broker.js +573 -141
  439. package/dist/core/runtime/canvas-extensions.d.ts +4 -5
  440. package/dist/core/runtime/canvas-extensions.js +5 -5
  441. package/dist/core/runtime/front-door.js +4 -4
  442. package/dist/core/runtime/headless-pi.d.ts +24 -0
  443. package/dist/core/runtime/headless-pi.js +152 -0
  444. package/dist/core/runtime/kickoff.d.ts +1 -5
  445. package/dist/core/runtime/kickoff.js +1 -5
  446. package/dist/core/runtime/model-registry.d.ts +3 -0
  447. package/dist/core/runtime/model-registry.js +13 -0
  448. package/dist/core/runtime/naming-persist.d.ts +4 -0
  449. package/dist/core/runtime/naming-persist.js +27 -1
  450. package/dist/core/runtime/naming.d.ts +17 -12
  451. package/dist/core/runtime/naming.js +91 -140
  452. package/dist/core/runtime/node-read.js +19 -10
  453. package/dist/core/runtime/nodes.d.ts +9 -14
  454. package/dist/core/runtime/nodes.js +3 -53
  455. package/dist/core/runtime/package-health.d.ts +6 -21
  456. package/dist/core/runtime/package-health.js +12 -123
  457. package/dist/core/runtime/placement-tmux.d.ts +2 -1
  458. package/dist/core/runtime/placement-tmux.js +6 -4
  459. package/dist/core/runtime/placement.d.ts +1 -0
  460. package/dist/core/runtime/placement.js +4 -8
  461. package/dist/core/runtime/promote.js +3 -0
  462. package/dist/core/runtime/recap.d.ts +2 -7
  463. package/dist/core/runtime/recap.js +35 -69
  464. package/dist/core/runtime/revive.js +34 -77
  465. package/dist/core/runtime/session-cycles.d.ts +4 -0
  466. package/dist/core/runtime/session-cycles.js +14 -1
  467. package/dist/core/runtime/session-visibility.d.ts +37 -0
  468. package/dist/core/runtime/session-visibility.js +83 -0
  469. package/dist/core/runtime/spawn.js +10 -22
  470. package/dist/core/runtime/stop-guard.d.ts +1 -1
  471. package/dist/core/runtime/stop-guard.js +18 -13
  472. package/dist/core/runtime/surface-bg.js +1 -1
  473. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  474. package/dist/core/runtime/tmux-chrome.js +1 -1
  475. package/dist/core/runtime/tmux.d.ts +35 -7
  476. package/dist/core/runtime/tmux.js +439 -62
  477. package/dist/core/runtime/tool-group-summary.d.ts +19 -0
  478. package/dist/core/runtime/tool-group-summary.js +88 -0
  479. package/dist/core/scope.d.ts +2 -7
  480. package/dist/core/scope.js +9 -35
  481. package/dist/core/substrate/schema.d.ts +2 -2
  482. package/dist/core/termrender/code-doc.d.ts +12 -0
  483. package/dist/core/termrender/code-doc.js +92 -0
  484. package/dist/core/termrender/display.d.ts +12 -0
  485. package/dist/core/termrender/display.js +19 -0
  486. package/dist/core/termrender/termrender.d.ts +73 -0
  487. package/dist/core/termrender/termrender.js +795 -0
  488. package/dist/core/termrender/version.d.ts +1 -0
  489. package/dist/core/termrender/version.js +1 -0
  490. package/dist/core/tui/terminal.js +1 -2
  491. package/dist/core/user-settings.d.ts +71 -3
  492. package/dist/core/user-settings.js +83 -1
  493. package/dist/daemon/api/__tests__/inbox.test.js +44 -133
  494. package/dist/daemon/api/handlers/human.d.ts +0 -10
  495. package/dist/daemon/api/handlers/human.js +104 -702
  496. package/dist/daemon/api/handlers/inbox.js +113 -142
  497. package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
  498. package/dist/daemon/api/handlers/review-comments.js +500 -0
  499. package/dist/daemon/api/handlers/reviews.d.ts +2 -0
  500. package/dist/daemon/api/handlers/reviews.js +287 -0
  501. package/dist/daemon/api/map.d.ts +22 -7
  502. package/dist/daemon/api/map.js +159 -11
  503. package/dist/daemon/api/server.js +4 -0
  504. package/dist/daemon/cron-run.js +6 -9
  505. package/dist/daemon/crtrd.js +17 -33
  506. package/dist/daemon/fleet.d.ts +1 -8
  507. package/dist/daemon/fleet.js +4 -30
  508. package/dist/daemon/human/finish.d.ts +14 -0
  509. package/dist/daemon/human/finish.js +115 -0
  510. package/dist/daemon/human/sweep.d.ts +6 -0
  511. package/dist/daemon/human/sweep.js +49 -0
  512. package/dist/daemon/messaging/node-message.d.ts +18 -0
  513. package/dist/daemon/messaging/node-message.js +70 -0
  514. package/dist/daemon/review/comment-notify.d.ts +26 -0
  515. package/dist/daemon/review/comment-notify.js +107 -0
  516. package/dist/daemon/review/deliver.d.ts +7 -0
  517. package/dist/daemon/review/deliver.js +56 -0
  518. package/dist/daemon/review/finish.d.ts +22 -0
  519. package/dist/daemon/review/finish.js +254 -0
  520. package/dist/daemon/review/sweep.d.ts +11 -0
  521. package/dist/daemon/review/sweep.js +120 -0
  522. package/dist/index.d.ts +2 -0
  523. package/dist/index.js +2 -2
  524. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
  525. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
  526. package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
  527. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
  528. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
  529. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
  530. package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
  531. package/dist/pi-extensions/canvas-context-intro.js +50 -104
  532. package/dist/pi-extensions/canvas-recap.d.ts +15 -2
  533. package/dist/pi-extensions/canvas-recap.js +192 -69
  534. package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
  535. package/dist/pi-extensions/canvas-review-boundary.js +81 -0
  536. package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
  537. package/dist/pi-extensions/canvas-stophook.js +78 -128
  538. package/dist/pi-extensions/canvas-structured-output.js +52 -8
  539. package/dist/shared/generated-context.d.ts +29 -4
  540. package/dist/shared/generated-context.js +122 -7
  541. package/dist/shared/tool-groups.d.ts +23 -0
  542. package/dist/shared/tool-groups.js +60 -0
  543. package/dist/shared/working-activity.d.ts +8 -0
  544. package/dist/shared/working-activity.js +26 -0
  545. package/dist/types.d.ts +36 -2
  546. package/dist/types.js +51 -0
  547. package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
  548. package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
  549. package/dist/web-client/index.html +2 -2
  550. package/dist/web-client/sw.js +1 -1
  551. package/docs/compat/hearth-crtr-v4.md +2 -2
  552. package/docs/compat/hearth-crtr-v5.md +4 -2
  553. package/docs/public-api.md +3 -3
  554. package/package.json +21 -14
  555. package/runtime.lock.json +4661 -1453
  556. package/scripts/postinstall.mjs +15 -2
  557. package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
  558. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
  559. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
  560. package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
  561. package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
  562. package/dist/builtin-views/_lib/states.mjs +0 -161
  563. package/dist/builtin-views/canvas/core.mjs +0 -657
  564. package/dist/builtin-views/canvas/text.mjs +0 -58
  565. package/dist/builtin-views/canvas/tui.mjs +0 -168
  566. package/dist/builtin-views/canvas/web.jsx +0 -121
  567. package/dist/builtin-views/chat/core.mjs +0 -684
  568. package/dist/builtin-views/chat/text.mjs +0 -101
  569. package/dist/builtin-views/chat/tui.mjs +0 -360
  570. package/dist/builtin-views/chat/web.jsx +0 -362
  571. package/dist/builtin-views/git-pr/core.mjs +0 -673
  572. package/dist/builtin-views/git-pr/text.mjs +0 -84
  573. package/dist/builtin-views/git-pr/tui.mjs +0 -301
  574. package/dist/builtin-views/git-pr/web.jsx +0 -216
  575. package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
  576. package/dist/builtin-views/inbox/core.mjs +0 -1273
  577. package/dist/builtin-views/inbox/text.mjs +0 -73
  578. package/dist/builtin-views/inbox/tui.mjs +0 -314
  579. package/dist/builtin-views/inbox/web.jsx +0 -188
  580. package/dist/builtin-views/linkedin/core.mjs +0 -906
  581. package/dist/builtin-views/linkedin/text.mjs +0 -69
  582. package/dist/builtin-views/linkedin/tui.mjs +0 -413
  583. package/dist/builtin-views/linkedin/web.jsx +0 -206
  584. package/dist/builtin-views/prompt-review/core.mjs +0 -735
  585. package/dist/builtin-views/prompt-review/text.mjs +0 -15
  586. package/dist/builtin-views/prompt-review/tui.mjs +0 -196
  587. package/dist/builtin-views/prompt-review/web.jsx +0 -484
  588. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
  589. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
  590. package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
  591. package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
  592. package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
  593. package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
  594. package/dist/clients/attach/session/mode.d.ts +0 -25
  595. package/dist/clients/attach/session/mode.js +0 -97
  596. package/dist/commands/sys/promptstudio.d.ts +0 -2
  597. package/dist/commands/sys/promptstudio.js +0 -65
  598. package/dist/commands/view-cycle.d.ts +0 -2
  599. package/dist/commands/view-cycle.js +0 -130
  600. package/dist/commands/view-list.d.ts +0 -2
  601. package/dist/commands/view-list.js +0 -66
  602. package/dist/commands/view-new.d.ts +0 -2
  603. package/dist/commands/view-new.js +0 -74
  604. package/dist/commands/view-pick.d.ts +0 -6
  605. package/dist/commands/view-pick.js +0 -129
  606. package/dist/commands/view-run.d.ts +0 -2
  607. package/dist/commands/view-run.js +0 -214
  608. package/dist/commands/view.d.ts +0 -2
  609. package/dist/commands/view.js +0 -31
  610. package/dist/commands/workspace.d.ts +0 -2
  611. package/dist/commands/workspace.js +0 -165
  612. package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
  613. package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
  614. package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
  615. package/dist/core/canvas/human-work-outbox.d.ts +0 -73
  616. package/dist/core/canvas/human-work-outbox.js +0 -261
  617. package/dist/core/command-plugins/store.d.ts +0 -16
  618. package/dist/core/command-plugins/store.js +0 -64
  619. package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
  620. package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
  621. package/dist/core/runtime/fault-recovery-nudge.js +0 -3
  622. package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
  623. package/dist/core/tui/host.d.ts +0 -66
  624. package/dist/core/view/__tests__/transport-cache.test.js +0 -62
  625. package/dist/core/view/bridge.d.ts +0 -10
  626. package/dist/core/view/bridge.js +0 -31
  627. package/dist/core/view/chrome.d.ts +0 -9
  628. package/dist/core/view/chrome.js +0 -22
  629. package/dist/core/view/contract.d.ts +0 -205
  630. package/dist/core/view/contract.js +0 -23
  631. package/dist/core/view/loader.d.ts +0 -31
  632. package/dist/core/view/loader.js +0 -188
  633. package/dist/core/view/stream-local.d.ts +0 -3
  634. package/dist/core/view/stream-local.js +0 -231
  635. package/dist/core/view/transport-cache.d.ts +0 -8
  636. package/dist/core/view/transport-cache.js +0 -38
  637. package/dist/core/view/transport-local.d.ts +0 -7
  638. package/dist/core/view/transport-local.js +0 -83
  639. package/dist/core/view/transport-remote.d.ts +0 -2
  640. package/dist/core/view/transport.d.ts +0 -10
  641. package/dist/core/view/transport.js +0 -15
  642. package/dist/pi-extensions/naming-tool.d.ts +0 -24
  643. package/dist/pi-extensions/naming-tool.js +0 -67
  644. package/dist/prompts/view.d.ts +0 -7
  645. package/dist/prompts/view.js +0 -172
  646. package/dist/web/ViewChrome.d.ts +0 -7
  647. package/dist/web/ViewChrome.js +0 -28
  648. package/dist/web/ViewPane.d.ts +0 -39
  649. package/dist/web/ViewPane.js +0 -48
  650. package/dist/web/index.d.ts +0 -8
  651. package/dist/web/index.js +0 -22
  652. package/dist/web/runtime.d.ts +0 -39
  653. package/dist/web/runtime.js +0 -232
  654. package/dist/web/states.d.ts +0 -24
  655. package/dist/web/states.js +0 -24
  656. package/dist/web/transport-http.d.ts +0 -5
  657. package/dist/web/transport-http.js +0 -34
  658. package/dist/web/transport-stream.d.ts +0 -3
  659. package/dist/web/transport-stream.js +0 -204
  660. package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
  661. package/dist/web-client/assets/index-aaeu4adv.css +0 -2
  662. /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
  663. /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
  664. /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
  665. /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
  666. /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
  667. /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
  668. /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
  669. /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
  670. /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
@@ -1,6 +1,7 @@
1
1
  import type { CustomEditor } from '@earendil-works/pi-coding-agent';
2
2
  import type { Component, KeybindingsManager, TUI } from '@earendil-works/pi-tui';
3
3
  import { type BrokerDataFrame, type ClientRole, type BrokerSnapshot, type ClientToBroker, type RpcExtensionUIRequest, type RpcExtensionUIResponse } from '../../../core/runtime/broker-protocol.js';
4
+ import type { CopyTarget } from '../render/transcript-copy.js';
4
5
  import type { ReadOpRequest } from '../../../core/broker-client/index.js';
5
6
  import { type Picker, type PickerControls } from '../overlays/pickers.js';
6
7
  export interface InputControllerHooks {
@@ -33,12 +34,23 @@ export interface InputControllerHooks {
33
34
  /** OPTIONAL: toggle the GRAPH overlay — forwarded to the slash context so
34
35
  * `/graph` opens/closes it (Unit Q wires it from runAttach). */
35
36
  onGraph?: () => void;
37
+ /** OPTIONAL: toggle the human inbox surface — forwarded to the slash context so `/inbox` opens/closes it. */
38
+ onInbox?: () => void;
39
+ /** OPTIONAL: toggle the Help overlay — forwarded to the slash context so
40
+ * `/hotkeys` opens/closes it. */
41
+ onHelp?: () => void;
36
42
  /** OPTIONAL: detach the viewer — forwarded to the slash context so `/quit`
37
43
  * tears down the TUI/socket (the engine keeps running). Wired by viewer.ts. */
38
44
  onQuit?: () => void;
39
45
  /** OPTIONAL: copy the last assistant message to the clipboard — forwarded to
40
46
  * the slash context so `/copy` works. Wired by viewer.ts (it owns ChatView). */
41
47
  onCopy?: () => void;
48
+ /** OPTIONAL: copy a viewer-local transcript target — forwarded to the slash
49
+ * context so `/copy-message`, `/copy-tool`, and `/copy-transcript` work. */
50
+ onCopyTarget?: (target: CopyTarget) => void;
51
+ /** OPTIONAL: toggle mouse wheel reporting — forwarded to the slash context so
52
+ * `/mouse` can change viewer-local mouse state. */
53
+ onToggleMouse?: () => void;
42
54
  /** OPTIONAL: recolor the editor's name chip — forwarded to the slash context
43
55
  * so `/color` paints it (`null` clears). Wired by viewer.ts (it owns the
44
56
  * TitledEditor). */
@@ -79,6 +91,9 @@ export interface InputControllerHooks {
79
91
  * by viewer.ts to `cliClient().sendMessage`; absent (e.g. remote attach) →
80
92
  * the dormant-submit path is disabled and prompts fall through as before. */
81
93
  onDormantSubmit?: (text: string) => void;
94
+ /** OPTIONAL: a real prompt or steer was accepted from the editor, including a
95
+ * dormant wake-message submit. Slash commands and bash submissions do not fire it. */
96
+ onPromptSent?: () => void;
82
97
  }
83
98
  export declare class InputController {
84
99
  private readonly tui;
@@ -122,6 +137,10 @@ export declare class InputController {
122
137
  * key listener owns rather than the editor's action table. Public so that
123
138
  * binding rides the gate above instead of going straight to the socket. */
124
139
  cycleLadder(direction: 'forward' | 'backward'): void;
140
+ /** Send viewer-owned text without touching the editor or its history. The
141
+ * broker aborts an active turn before starting this prompt, so a whip never
142
+ * waits in pi's steering queue behind the work it is meant to replace. */
143
+ sendInterrupting(text: string): boolean;
125
144
  /** Render extension UI requests from the broker. Blocking dialogs route their
126
145
  * answer back to the broker; non-blocking notify requests become the viewer's
127
146
  * normal notice line and NOTHING else — a notify must never tear down an
@@ -20,6 +20,7 @@ import { BROKER_READ_CAPS, encodeFrame, } from '../../../core/runtime/broker-pro
20
20
  import { isBlockingDialog, renderDialog } from '../overlays/dialogs.js';
21
21
  import { readClipboardImage, writeClipboardImageToFile } from './clipboard-image.js';
22
22
  import { dispatchSlashCommand, isSlashCommand, readOnlySlashRefusal } from '../slash/dispatch.js';
23
+ import { classifySubmit } from '../../conversation/submit.js';
23
24
  import { buildForkPicker, buildModelPicker, buildScopedModelsPicker, buildSessionPicker, buildSettingsPicker, buildTreePicker, } from '../overlays/pickers.js';
24
25
  import { buildMcpPicker, readMcpServers, startMcpServerAction, MCP_EMPTY_STATE_HINT } from '../overlays/mcp.js';
25
26
  import { buildFileReviewPicker } from '../overlays/file-review.js';
@@ -123,6 +124,12 @@ export class InputController {
123
124
  cycleLadder(direction) {
124
125
  this.emitCommand({ type: 'cycle_ladder', direction });
125
126
  }
127
+ /** Send viewer-owned text without touching the editor or its history. The
128
+ * broker aborts an active turn before starting this prompt, so a whip never
129
+ * waits in pi's steering queue behind the work it is meant to replace. */
130
+ sendInterrupting(text) {
131
+ return this.emitDrive({ type: 'prompt', text, interrupt: true });
132
+ }
126
133
  /** Render extension UI requests from the broker. Blocking dialogs route their
127
134
  * answer back to the broker; non-blocking notify requests become the viewer's
128
135
  * normal notice line and NOTHING else — a notify must never tear down an
@@ -240,8 +247,12 @@ export class InputController {
240
247
  remote: this.hooks.remote,
241
248
  role: this.hooks.role,
242
249
  onGraph: this.hooks.onGraph,
250
+ onInbox: this.hooks.onInbox,
251
+ onHelp: this.hooks.onHelp,
243
252
  onQuit: this.hooks.onQuit,
244
253
  onCopy: this.hooks.onCopy,
254
+ onCopyTarget: this.hooks.onCopyTarget,
255
+ onToggleMouse: this.hooks.onToggleMouse,
245
256
  onColor: this.hooks.onColor,
246
257
  onNodeMetadata: this.hooks.onNodeMetadata,
247
258
  onFoldTools: this.hooks.onFoldTools,
@@ -425,7 +436,13 @@ export class InputController {
425
436
  /** Open the transcript-backed file-review picker. The caller owns the popup
426
437
  * process and cursor insertion; this controller only owns picker lifetime. */
427
438
  openFileReviewPicker(candidates, cwd, onChoose) {
428
- this.showPicker((controls) => buildFileReviewPicker(candidates, cwd, onChoose, controls.close, (message) => this.notify(message)));
439
+ this.showPicker((controls) => buildFileReviewPicker(candidates, cwd, (file) => {
440
+ // The review mounts a full-pane surface and takes focus. Close this
441
+ // picker first so its editor-focus restoration cannot steal focus
442
+ // back from the newly mounted review.
443
+ controls.close();
444
+ onChoose(file);
445
+ }, controls.close, (message) => this.notify(message)));
429
446
  }
430
447
  /** Open a viewer-local auth picker (login/logout) — uses the same showPicker
431
448
  * machinery as read-op pickers, but with a locally-built component (no read-op
@@ -465,56 +482,73 @@ export class InputController {
465
482
  return;
466
483
  }
467
484
  }
468
- // Node dormant → there is NO broker to drive. Rather than emit a prompt/steer
469
- // frame into a dead socket (the old "I typed and nothing happened" trap),
470
- // deliver the text as a wake message: it revives the node and lands as the
471
- // first thing it reads, and the reconnect supervisor repaints the live pane.
472
- // Local-only — remote attach leaves onDormantSubmit unwired, so prompts fall
473
- // through unchanged there. Slash commands are dispatched above and don't reach
474
- // here, so `/quit`-style local commands keep working while dormant.
475
- if (this.hooks.isDormant?.() === true && this.hooks.onDormantSubmit !== undefined) {
485
+ // Classify the remaining cases: dormant, bash, prompt/steer.
486
+ const isDormant = this.hooks.isDormant?.() === true;
487
+ const onDormantSubmit = this.hooks.onDormantSubmit;
488
+ const classification = classifySubmit(text, {
489
+ isDormant,
490
+ canWakeDormant: isDormant && onDormantSubmit !== undefined,
491
+ isStreaming: this.state?.isStreaming === true,
492
+ });
493
+ if (classification.kind === 'empty')
494
+ return;
495
+ if (classification.kind === 'dormant') {
496
+ // Node dormant → there is NO broker to drive. Rather than emit a prompt/steer
497
+ // frame into a dead socket (the old "I typed and nothing happened" trap),
498
+ // deliver the text as a wake message: it revives the node and lands as the
499
+ // first thing it reads, and the reconnect supervisor repaints the live pane.
500
+ // Local-only — remote attach leaves onDormantSubmit unwired, so prompts fall
501
+ // through unchanged there. Slash commands are dispatched above and don't reach
502
+ // here, so `/quit`-style local commands keep working while dormant.
476
503
  // Raw text (whitespace and all) — not `trimmed` — per Major 4: emptiness is
477
504
  // judged on the trimmed view above, but what's actually delivered is the
478
505
  // human's exact typed content, same as the prompt/steer frame below.
479
- const expanded = this.expandImagePlaceholders(text);
480
- this.hooks.onDormantSubmit(expanded);
481
- this.editor.addToHistory(trimmed);
506
+ if (onDormantSubmit === undefined)
507
+ return;
508
+ const expanded = this.expandImagePlaceholders(classification.text);
509
+ onDormantSubmit(expanded);
510
+ this.editor.addToHistory(classification.trimmed);
482
511
  this.editor.setText('');
483
512
  this.clearPastedImages();
513
+ this.hooks.onPromptSent?.();
484
514
  return;
485
515
  }
486
- // `!cmd` / `!!cmd` → run bash in the engine and inject output into context,
487
- // WITHOUT starting an agent turn (pi-native `!` semantics). `!!` withholds
488
- // the output from the LLM. The broker relays the run as bash_* frames.
489
- if (trimmed.startsWith('!')) {
490
- const excludeFromContext = trimmed.startsWith('!!');
491
- const command = trimmed.slice(excludeFromContext ? 2 : 1).trim();
492
- if (command === '')
493
- return; // bare `!`/`!!`: nothing to run
494
- if (!this.emitDrive({ type: 'bash', command, excludeFromContext }))
516
+ if (classification.kind === 'bash') {
517
+ // `!cmd` / `!!cmd` → run bash in the engine and inject output into context,
518
+ // WITHOUT starting an agent turn (pi-native `!` semantics). `!!` withholds
519
+ // the output from the LLM. The broker relays the run as bash_* frames.
520
+ if (!this.emitDrive({ type: 'bash', command: classification.command, excludeFromContext: classification.excludeFromContext }))
495
521
  return;
496
- this.editor.addToHistory(trimmed);
522
+ this.editor.addToHistory(classification.trimmed);
497
523
  this.editor.setText('');
498
524
  return;
499
525
  }
500
- // Submit-while-streaming = steer (pi-native parity): interject into the
501
- // running turn instead of queueing a fresh prompt. `isStreaming` is the
526
+ // An unrecognized slash command belongs to the engine's extension runner.
527
+ // `dispatchSlashCommand` returned false above, so route it exactly like
528
+ // ordinary text instead of dropping the classifier's intermediate `slash`
529
+ // result. Submit-while-streaming = steer (pi-native parity): interject into
530
+ // the running turn instead of queueing a fresh prompt. `isStreaming` is the
502
531
  // broker snapshot's busy signal; the broker routes `steer` → session.steer()
503
532
  // and `prompt` → session.prompt(). Idle / no state yet → prompt (safe default).
504
533
  // Classification above (slash/dormant/bash/emptiness) reads the TRIMMED
505
534
  // view, but the frame itself carries the exact editor text (post image-
506
535
  // placeholder substitution) — leading/trailing whitespace is the human's,
507
536
  // not ours to discard.
508
- const expanded = this.expandImagePlaceholders(text);
509
- const busy = this.state?.isStreaming === true;
510
- const frame = busy
537
+ const delivery = classification.kind === 'slash'
538
+ ? (this.state?.isStreaming === true ? 'steer' : 'prompt')
539
+ : classification.kind;
540
+ if (delivery !== 'steer' && delivery !== 'prompt')
541
+ return;
542
+ const expanded = this.expandImagePlaceholders(classification.kind === 'slash' ? text : classification.text);
543
+ const frame = delivery === 'steer'
511
544
  ? { type: 'steer', text: expanded }
512
545
  : { type: 'prompt', text: expanded };
513
546
  if (!this.emitDrive(frame))
514
547
  return; // refused or too large — no frame emitted
515
- this.editor.addToHistory(trimmed);
548
+ this.editor.addToHistory(classification.trimmed);
516
549
  this.editor.setText('');
517
550
  this.clearPastedImages();
551
+ this.hooks.onPromptSent?.();
518
552
  }
519
553
  handleFollowUp() {
520
554
  const text = this.editor.getText();
@@ -144,16 +144,12 @@ export declare class TitledEditor extends CustomEditor {
144
144
  /** Pre-styled context string painted into the RIGHT of the top border (cwd /
145
145
  * branch / git status). Already colorized by the caller; empty → omitted. */
146
146
  info: string;
147
- /** Editor-mode badge painted into the bottom-right of the outline. Empty → omitted. */
148
- mode: string;
149
147
  /** Node and workspace badge painted at the far bottom-right of the outline. */
150
148
  contextBadge: string;
151
149
  /** Paint the chip solid so the name reads as a label sitting on the border
152
150
  * rule. Defaults to the reverse-video chip; viewer.ts swaps in a
153
151
  * thinking-colored background (bold white text) on each state update. */
154
152
  titleStyle: (s: string) => string;
155
- /** Editor-mode badge colorizer, matched to the current mode type. */
156
- modeStyle: (s: string) => string;
157
153
  /** Node and workspace badge colorizer, matched to the editor frame. */
158
154
  contextBadgeStyle: (s: string) => string;
159
155
  /** Whether the hosting tmux pane / terminal window has FOCUS (terminal focus
@@ -640,16 +640,12 @@ export class TitledEditor extends CustomEditor {
640
640
  /** Pre-styled context string painted into the RIGHT of the top border (cwd /
641
641
  * branch / git status). Already colorized by the caller; empty → omitted. */
642
642
  info = '';
643
- /** Editor-mode badge painted into the bottom-right of the outline. Empty → omitted. */
644
- mode = '';
645
643
  /** Node and workspace badge painted at the far bottom-right of the outline. */
646
644
  contextBadge = '';
647
645
  /** Paint the chip solid so the name reads as a label sitting on the border
648
646
  * rule. Defaults to the reverse-video chip; viewer.ts swaps in a
649
647
  * thinking-colored background (bold white text) on each state update. */
650
648
  titleStyle = defaultTitleStyle;
651
- /** Editor-mode badge colorizer, matched to the current mode type. */
652
- modeStyle = defaultTitleStyle;
653
649
  /** Node and workspace badge colorizer, matched to the editor frame. */
654
650
  contextBadgeStyle = defaultTitleStyle;
655
651
  /** Whether the hosting tmux pane / terminal window has FOCUS (terminal focus
@@ -784,12 +780,8 @@ export class TitledEditor extends CustomEditor {
784
780
  // border color.
785
781
  lines[0] = composeTopBorder(width, this.title, this.info, this.titleStyle, (s) => this.borderColor(s));
786
782
  }
787
- if ((this.mode || this.contextBadge) && lines.length > 0) {
788
- // Context stays at the far edge; an active editor mode sits immediately
789
- // to its left as the local state badge for this input surface.
790
- const modeBadge = this.mode ? this.modeStyle(this.mode) : '';
791
- const contextBadge = this.contextBadge ? this.contextBadgeStyle(this.contextBadge) : '';
792
- const badge = modeBadge + contextBadge;
783
+ if (this.contextBadge && lines.length > 0) {
784
+ const badge = this.contextBadgeStyle(this.contextBadge);
793
785
  const badgeWidth = visibleWidth(badge);
794
786
  if (badgeWidth + 2 < width) {
795
787
  const last = lines.length - 1;
@@ -1,9 +1,13 @@
1
- import type { AccessoryOutcome } from '@crouton-kit/humanloop';
1
+ import type { TUI } from '@earendil-works/pi-tui';
2
+ import type { CanvasSource } from '../../../core/canvas/source.js';
3
+ import type { SurfaceHost } from '../../surfaces/host.js';
2
4
  import type { Picker } from './pickers.js';
3
- import { extractFilePaths } from '../visible-paths.js';
5
+ import { extractFilePaths } from '#core/human/visible-paths';
4
6
  export declare function buildFileReviewPicker(candidates: readonly string[], cwd: string, onChoose: (file: string) => void, close: () => void, notify: (message: string) => void): Picker;
5
- export declare function launchFileReview(file: string, cwd: string, opts: {
6
- onDone: (outcome: AccessoryOutcome) => void;
7
+ export declare function launchFileReview(host: SurfaceHost, file: string, opts: {
8
+ originNodeId: string;
9
+ tui: TUI;
10
+ canvasSource: CanvasSource;
7
11
  onNotice: (message: string) => void;
8
- }): void;
12
+ }): Promise<void>;
9
13
  export { extractFilePaths };
@@ -1,13 +1,10 @@
1
- import { execFile } from 'node:child_process';
2
- import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
3
- import { homedir, tmpdir } from 'node:os';
1
+ import { homedir } from 'node:os';
4
2
  import { isAbsolute, join, relative, resolve } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
3
  import { Input, SelectList, getKeybindings, } from '@earendil-works/pi-tui';
7
4
  import { getSelectListTheme } from '@earendil-works/pi-coding-agent';
8
- import { shellQuote } from '../../../core/runtime/placement-tmux.js';
9
- import { surfaceTmuxStyleArgs } from '../../../core/runtime/surface-bg.js';
10
- import { checkReviewableFile, extractFilePaths } from '../visible-paths.js';
5
+ import { openComposedReview } from '../../inbox/review/launch.js';
6
+ import { createReviewClient } from '../../inbox/review/review-client.js';
7
+ import { checkReviewableFile, extractFilePaths } from '#core/human/visible-paths';
11
8
  const MAX_VISIBLE_ROWS = 12;
12
9
  function labelForPath(file, cwd) {
13
10
  const rel = relative(cwd, file);
@@ -103,79 +100,21 @@ class FileReviewPicker {
103
100
  this.notify(check.reason);
104
101
  return;
105
102
  }
106
- this.close();
107
103
  this.onChoose(file);
104
+ this.close();
108
105
  }
109
106
  }
110
107
  export function buildFileReviewPicker(candidates, cwd, onChoose, close, notify) {
111
108
  const picker = new FileReviewPicker(candidates, cwd, onChoose, close, notify);
112
109
  return { component: picker, focus: picker };
113
110
  }
114
- function parseOutcome(path, notify) {
115
- let text;
116
- try {
117
- text = readFileSync(path, 'utf8');
118
- }
119
- catch {
120
- return { kind: 'cancel' };
121
- }
122
- let raw;
123
- try {
124
- raw = JSON.parse(text);
125
- }
126
- catch {
127
- notify('File review result was invalid');
128
- return { kind: 'cancel' };
129
- }
130
- if (typeof raw !== 'object' || raw === null || !('kind' in raw)) {
131
- notify('File review result was invalid');
132
- return { kind: 'cancel' };
133
- }
134
- const result = raw;
135
- if (result.kind === 'cancel')
136
- return { kind: 'cancel' };
137
- if ((result.kind === 'insert' || result.kind === 'copy') && typeof result.text === 'string') {
138
- return { kind: result.kind, text: result.text };
139
- }
140
- notify('File review result was invalid');
141
- return { kind: 'cancel' };
142
- }
143
- export function launchFileReview(file, cwd, opts) {
144
- let dir;
145
- try {
146
- dir = mkdtempSync(join(tmpdir(), 'crtr-review-'));
147
- }
148
- catch (err) {
149
- opts.onNotice(`Could not prepare file review: ${err instanceof Error ? err.message : String(err)}`);
150
- return;
151
- }
152
- const result = join(dir, 'result.json');
153
- // Run the humanloop CLI we depend on, not whatever `hl` is first on PATH: a global hl
154
- // older than our exact pin has no `review file` leaf and the popup dies on an unknown command.
155
- const hlCli = fileURLToPath(import.meta.resolve('@crouton-kit/humanloop/cli'));
156
- const cmd = `cd ${shellQuote(cwd)} && exec ${shellQuote(process.execPath)} ${shellQuote(hlCli)} review file --path ${shellQuote(file)} --cwd ${shellQuote(cwd)} --result ${shellQuote(result)}`;
111
+ export async function launchFileReview(host, file, opts) {
157
112
  try {
158
- execFile('tmux', ['display-popup', '-E', '-T', ' file review ', '-w', '90%', '-h', '85%', ...surfaceTmuxStyleArgs(), cmd], (err) => {
159
- try {
160
- if (err && !existsSync(result)) {
161
- opts.onNotice(`File review did not run: ${err.message}`);
162
- opts.onDone({ kind: 'cancel' });
163
- return;
164
- }
165
- const outcome = parseOutcome(result, opts.onNotice);
166
- opts.onDone(outcome);
167
- }
168
- catch (err) {
169
- opts.onNotice(`Could not finish file review: ${err instanceof Error ? err.message : String(err)}`);
170
- }
171
- finally {
172
- rmSync(dir, { recursive: true, force: true });
173
- }
174
- });
113
+ const review = await createReviewClient().createInline({ originNodeId: opts.originNodeId, file });
114
+ await openComposedReview(host, { reviewId: review.reviewId, tui: opts.tui, canvasSource: opts.canvasSource });
175
115
  }
176
116
  catch (err) {
177
- rmSync(dir, { recursive: true, force: true });
178
- opts.onNotice(`Could not open file review: ${err instanceof Error ? err.message : String(err)}`);
117
+ opts.onNotice(err instanceof Error ? err.message : String(err));
179
118
  }
180
119
  }
181
120
  export { extractFilePaths };
@@ -0,0 +1,33 @@
1
+ import { type Component, type TUI } from '@earendil-works/pi-tui';
2
+ import type { AttachPalette } from '../config.js';
3
+ import type { AttachBindings } from '../session/bindings.js';
4
+ /** A bounded, focused reference for the attach viewer's viewport controls. */
5
+ export declare class HelpOverlay implements Component {
6
+ private readonly tui;
7
+ private readonly pal;
8
+ private handle;
9
+ private bindings;
10
+ private scrollTop;
11
+ private lastContentRows;
12
+ constructor(tui: TUI, pal: AttachPalette);
13
+ /** Re-resolve key spellings after `/reload` (mirrors GraphOverlay.setBindings). */
14
+ setBindings(bindings: AttachBindings): void;
15
+ toggle(): void;
16
+ close(): void;
17
+ isOpen(): boolean;
18
+ invalidate(): void;
19
+ render(width: number): string[];
20
+ handleInput(data: string): boolean;
21
+ private open;
22
+ private matchesBinding;
23
+ private scrollBy;
24
+ private pageSize;
25
+ private body;
26
+ private lines;
27
+ private binding;
28
+ private wrap;
29
+ private style;
30
+ private boxRow;
31
+ private borderRow;
32
+ private renderNarrow;
33
+ }
@@ -0,0 +1,204 @@
1
+ import { matchesKey, truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
2
+ import { ATTACH_CONTROL_BINDINGS, BINDING_CATALOG, formatBinding, matchesPiTuiInput, } from '../../../core/keybindings/index.js';
3
+ const HEIGHT_PCT = 0.72;
4
+ const OVERLAY_OPTIONS = { anchor: 'center', width: '72%', minWidth: 48, maxHeight: '72%', margin: 1 };
5
+ /** A bounded, focused reference for the attach viewer's viewport controls. */
6
+ export class HelpOverlay {
7
+ tui;
8
+ pal;
9
+ handle;
10
+ bindings;
11
+ scrollTop = 0;
12
+ lastContentRows = 1;
13
+ constructor(tui, pal) {
14
+ this.tui = tui;
15
+ this.pal = pal;
16
+ }
17
+ /** Re-resolve key spellings after `/reload` (mirrors GraphOverlay.setBindings). */
18
+ setBindings(bindings) {
19
+ this.bindings = bindings;
20
+ if (this.handle !== undefined)
21
+ this.tui.requestRender();
22
+ }
23
+ toggle() {
24
+ if (this.handle === undefined)
25
+ this.open();
26
+ else
27
+ this.close();
28
+ }
29
+ close() {
30
+ if (this.handle === undefined)
31
+ return;
32
+ this.handle.hide();
33
+ this.handle = undefined;
34
+ this.tui.requestRender();
35
+ }
36
+ isOpen() {
37
+ return this.handle !== undefined;
38
+ }
39
+ invalidate() {
40
+ if (this.handle !== undefined)
41
+ this.tui.requestRender();
42
+ }
43
+ render(width) {
44
+ const panelWidth = Math.max(1, width);
45
+ if (panelWidth < 5)
46
+ return this.renderNarrow(panelWidth);
47
+ const innerWidth = panelWidth - 4;
48
+ const allLines = this.body(innerWidth);
49
+ const terminalRows = Math.max(1, this.tui.terminal.rows);
50
+ const maxPanelHeight = Math.max(3, Math.min(Math.floor(terminalRows * HEIGHT_PCT), Math.max(3, terminalRows - 2)));
51
+ const bodyRows = Math.max(1, maxPanelHeight - 2);
52
+ const overflow = allLines.length > bodyRows;
53
+ const contentRows = overflow && bodyRows >= 3 ? bodyRows - 2 : 1;
54
+ this.lastContentRows = contentRows;
55
+ this.scrollTop = Math.max(0, Math.min(this.scrollTop, Math.max(0, allLines.length - contentRows)));
56
+ const end = Math.min(allLines.length, this.scrollTop + contentRows);
57
+ const body = [];
58
+ if (overflow && bodyRows >= 3) {
59
+ body.push(this.scrollTop > 0 ? this.pal.muted(`↑ ${this.scrollTop} more`) : '');
60
+ }
61
+ body.push(...allLines.slice(this.scrollTop, end));
62
+ if (overflow && bodyRows >= 3) {
63
+ body.push(end < allLines.length ? this.pal.muted(`↓ ${allLines.length - end} more`) : '');
64
+ }
65
+ else if (overflow && bodyRows === 2) {
66
+ body.push(end < allLines.length ? this.pal.muted(`↓ ${allLines.length - end} more`) : '');
67
+ }
68
+ while (body.length < bodyRows)
69
+ body.push('');
70
+ const title = this.pal.bold(this.pal.accent('⌨ attach help'));
71
+ const hint = this.pal.muted('esc dismiss · ↑↓ scroll');
72
+ return [
73
+ this.borderRow('╭', '╮', title, panelWidth),
74
+ ...body.map((line) => this.boxRow(line, panelWidth)),
75
+ this.borderRow('╰', '╯', hint, panelWidth),
76
+ ].map(this.pal.surface);
77
+ }
78
+ handleInput(data) {
79
+ if (matchesKey(data, 'escape') || matchesKey(data, 'q')) {
80
+ this.close();
81
+ return true;
82
+ }
83
+ if (matchesKey(data, 'up') || this.matchesBinding('crtr.attach.scroll.up', data))
84
+ return this.scrollBy(-1);
85
+ if (matchesKey(data, 'down') || this.matchesBinding('crtr.attach.scroll.down', data))
86
+ return this.scrollBy(1);
87
+ if (matchesKey(data, 'pageUp') || this.matchesBinding('crtr.attach.scroll.page-up', data))
88
+ return this.scrollBy(-this.pageSize());
89
+ if (matchesKey(data, 'pageDown') || this.matchesBinding('crtr.attach.scroll.page-down', data))
90
+ return this.scrollBy(this.pageSize());
91
+ return true;
92
+ }
93
+ open() {
94
+ this.scrollTop = 0;
95
+ this.handle = this.tui.showOverlay(this, OVERLAY_OPTIONS);
96
+ }
97
+ matchesBinding(id, data) {
98
+ return this.bindings !== undefined && matchesPiTuiInput(this.bindings, id, data, (input, gesture) => matchesKey(input, gesture));
99
+ }
100
+ scrollBy(lines) {
101
+ const lineCount = this.body(Math.max(1, this.tui.terminal.columns - 4)).length;
102
+ const maxTop = Math.max(0, lineCount - this.lastContentRows);
103
+ const next = Math.max(0, Math.min(maxTop, this.scrollTop + lines));
104
+ if (next !== this.scrollTop) {
105
+ this.scrollTop = next;
106
+ this.tui.requestRender();
107
+ }
108
+ return true;
109
+ }
110
+ pageSize() {
111
+ return Math.max(1, this.lastContentRows - 1);
112
+ }
113
+ body(width) {
114
+ return this.lines().flatMap((line) => this.wrap(line.text, width).map((text) => this.style(text, line.style)));
115
+ }
116
+ lines() {
117
+ const binding = (id, description) => ({
118
+ text: `${this.binding(id)} ${description}`,
119
+ style: 'plain',
120
+ });
121
+ const heading = (text) => ({ text, style: 'heading' });
122
+ const muted = (text) => ({ text, style: 'muted' });
123
+ const blank = { text: '', style: 'plain' };
124
+ const otherKeys = ATTACH_CONTROL_BINDINGS.map(({ actionId }) => {
125
+ const name = BINDING_CATALOG.find((definition) => definition.id === actionId)?.name ?? actionId;
126
+ return binding(actionId, name);
127
+ });
128
+ return [
129
+ heading('Scrolling'),
130
+ binding('crtr.attach.scroll.up', 'scroll one line up'),
131
+ binding('crtr.attach.scroll.down', 'scroll one line down'),
132
+ binding('crtr.attach.scroll.page-up', 'scroll one page up'),
133
+ binding('crtr.attach.scroll.page-down', 'scroll one page down'),
134
+ binding('crtr.attach.scroll.live', 'return to the live bottom'),
135
+ muted('mouse wheel (when reporting is on)'),
136
+ blank,
137
+ heading('Selection and copy'),
138
+ { text: 'prefix + [ tmux copy-mode selects and copies the visible screenful; it works even while mouse reporting is on.', style: 'plain' },
139
+ { text: 'Option-drag (iTerm2, Terminal.app) or Shift-drag (Ghostty, Alacritty, xterm) makes a true terminal selection that bypasses mouse reporting.', style: 'plain' },
140
+ { text: 'Block-copy commands copy transcript content and are not capped at one screenful.', style: 'plain' },
141
+ blank,
142
+ heading('Copy commands'),
143
+ { text: '/copy last assistant message.', style: 'plain' },
144
+ { text: `/copy-message (${this.binding('crtr.attach.copy.message')}) newest copyable block entirely visible in the viewport; otherwise the newest one that intersects it.`, style: 'plain' },
145
+ { text: "/copy-tool newest tool call's result text.", style: 'plain' },
146
+ { text: "/copy-transcript every copyable block's text, oldest to newest, joined by blank lines.", style: 'plain' },
147
+ blank,
148
+ heading('Mouse'),
149
+ { text: `/mouse or ${this.binding('crtr.attach.mouse.toggle')} toggle mouse wheel scrolling. Turning it off restores tmux drag-select and copy-mode mouse.`, style: 'plain' },
150
+ blank,
151
+ heading('Other attach keys'),
152
+ ...otherKeys,
153
+ ];
154
+ }
155
+ binding(id) {
156
+ return this.bindings === undefined ? 'Loading…' : formatBinding(this.bindings, id);
157
+ }
158
+ wrap(text, width) {
159
+ if (text === '')
160
+ return [''];
161
+ const limit = Math.max(1, width);
162
+ const words = text.split(/\s+/);
163
+ const lines = [];
164
+ let current = '';
165
+ for (const word of words) {
166
+ const candidate = current === '' ? word : `${current} ${word}`;
167
+ if (current !== '' && visibleWidth(candidate) > limit) {
168
+ lines.push(truncateToWidth(current, limit, '', true));
169
+ current = ` ${word}`;
170
+ }
171
+ else {
172
+ current = candidate;
173
+ }
174
+ }
175
+ if (current !== '')
176
+ lines.push(truncateToWidth(current, limit, '', true));
177
+ return lines;
178
+ }
179
+ style(text, style) {
180
+ switch (style) {
181
+ case 'heading': return this.pal.bold(this.pal.accent(text));
182
+ case 'muted': return this.pal.muted(text);
183
+ case 'plain': return text;
184
+ }
185
+ }
186
+ boxRow(content, width) {
187
+ const innerWidth = width - 4;
188
+ const clipped = truncateToWidth(content, innerWidth, '', true);
189
+ const padding = ' '.repeat(Math.max(0, innerWidth - visibleWidth(clipped)));
190
+ return `${this.pal.border('│')} ${clipped}${padding} ${this.pal.border('│')}`;
191
+ }
192
+ borderRow(left, right, label, width) {
193
+ if (width < 6)
194
+ return truncateToWidth(`${this.pal.border(left)}${label}${this.pal.border(right)}`, width, '', true);
195
+ const span = width - 5;
196
+ const clipped = truncateToWidth(label, span, '…');
197
+ const fill = Math.max(0, width - 5 - visibleWidth(clipped));
198
+ return `${this.pal.border(`${left}─`)} ${clipped} ${this.pal.border('─'.repeat(fill) + right)}`;
199
+ }
200
+ renderNarrow(width) {
201
+ const title = truncateToWidth(this.pal.bold(this.pal.accent('help')), width, '', true);
202
+ return [this.pal.surface(title)];
203
+ }
204
+ }
@@ -0,0 +1,4 @@
1
+ import { Container } from '@earendil-works/pi-tui';
2
+ export declare class ActivitySlot extends Container {
3
+ render(width: number): string[];
4
+ }
@@ -0,0 +1,13 @@
1
+ // render/activity-slot.ts — the viewer-owned fixed activity row.
2
+ //
3
+ // pi's Loader prepends an empty line because its native placement is inline in
4
+ // a flowing transcript. The fixed cockpit already owns spacing, so this slot
5
+ // removes that margin and keeps Working/Compacting/Retrying flush with the next
6
+ // bottom-region row.
7
+ import { Container } from '@earendil-works/pi-tui';
8
+ export class ActivitySlot extends Container {
9
+ render(width) {
10
+ const lines = super.render(width);
11
+ return lines[0] === '' ? lines.slice(1) : lines;
12
+ }
13
+ }