@selesai/code 0.13.16 → 0.13.19

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 (479) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +2 -14
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.js +3 -9
  5. package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
  6. package/dist/bun/sandbox-env-setup.d.ts +1 -0
  7. package/dist/bun/sandbox-env-setup.js +3 -0
  8. package/dist/cli/auth-command.d.ts +23 -0
  9. package/dist/cli/auth-command.js +102 -0
  10. package/dist/cli/config-selector.js +2 -1
  11. package/dist/cli/setup.d.ts +1 -0
  12. package/dist/cli/setup.js +11 -0
  13. package/dist/cli.js +2 -14
  14. package/dist/config.d.ts +3 -2
  15. package/dist/config.js +9 -4
  16. package/dist/core/agent-session-runtime.js +15 -7
  17. package/dist/core/agent-session.d.ts +2 -6
  18. package/dist/core/agent-session.js +15 -4
  19. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  20. package/dist/core/compaction/branch-summarization.js +2 -1
  21. package/dist/core/extensions/loader.js +3 -0
  22. package/dist/core/extensions/types.d.ts +16 -2
  23. package/dist/core/http-dispatcher.js +2 -0
  24. package/dist/core/keybindings.d.ts +5 -0
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/messages.d.ts +1 -1
  27. package/dist/core/model-config.d.ts +15 -0
  28. package/dist/core/model-config.js +3 -0
  29. package/dist/core/model-runtime.d.ts +1 -0
  30. package/dist/core/model-runtime.js +5 -2
  31. package/dist/core/provider-composer.js +8 -2
  32. package/dist/core/session-export.d.ts +3 -0
  33. package/dist/core/session-export.js +31 -0
  34. package/dist/core/session-manager.d.ts +3 -2
  35. package/dist/core/session-manager.js +40 -13
  36. package/dist/core/skills.d.ts +1 -1
  37. package/dist/core/skills.js +4 -2
  38. package/dist/core/system-prompt.js +10 -10
  39. package/dist/core/tools/bash.js +3 -117
  40. package/dist/core/tools/edit.d.ts +1 -12
  41. package/dist/core/tools/edit.js +5 -163
  42. package/dist/core/tools/find.js +4 -55
  43. package/dist/core/tools/grep.js +4 -60
  44. package/dist/core/tools/ls.js +4 -49
  45. package/dist/core/tools/read.d.ts +4 -0
  46. package/dist/core/tools/read.js +10 -122
  47. package/dist/core/tools/renderers/bash.d.ts +11 -0
  48. package/dist/core/tools/renderers/bash.js +129 -0
  49. package/dist/core/tools/renderers/edit.d.ts +22 -0
  50. package/dist/core/tools/renderers/edit.js +166 -0
  51. package/dist/core/tools/renderers/find.d.ts +9 -0
  52. package/dist/core/tools/renderers/find.js +63 -0
  53. package/dist/core/tools/renderers/grep.d.ts +9 -0
  54. package/dist/core/tools/renderers/grep.js +68 -0
  55. package/dist/core/tools/renderers/index.d.ts +27 -0
  56. package/dist/core/tools/renderers/index.js +46 -0
  57. package/dist/core/tools/renderers/ls.d.ts +9 -0
  58. package/dist/core/tools/renderers/ls.js +57 -0
  59. package/dist/core/tools/renderers/read.d.ts +10 -0
  60. package/dist/core/tools/renderers/read.js +128 -0
  61. package/dist/core/tools/renderers/write.d.ts +9 -0
  62. package/dist/core/tools/renderers/write.js +152 -0
  63. package/dist/core/tools/write.js +5 -146
  64. package/dist/extensions/agent-browser.ts +1 -2
  65. package/dist/extensions/package.json +0 -1
  66. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
  67. package/dist/extensions/pi-hermes-memory/README.md +16 -12
  68. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
  69. package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
  70. package/dist/extensions/pi-hermes-memory/package.json +4 -4
  71. package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
  72. package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
  73. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
  74. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
  75. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
  76. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
  77. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
  78. package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
  79. package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
  80. package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
  84. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
  85. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
  86. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
  87. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
  88. package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
  89. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
  90. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
  91. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
  92. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
  93. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
  94. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
  95. package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
  96. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
  97. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
  98. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
  99. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
  100. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
  101. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
  102. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
  103. package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
  104. package/dist/extensions/pi-intercom/README.md +16 -2
  105. package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
  106. package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
  107. package/dist/extensions/pi-intercom/index.ts +1 -1
  108. package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
  109. package/dist/extensions/pi-intercom/package.json +1 -1
  110. package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
  111. package/dist/extensions/pi-intercom/project-agent.ts +1 -6
  112. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
  113. package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
  114. package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
  115. package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
  116. package/dist/extensions/pi-subagents/README.md +3 -3
  117. package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
  118. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
  119. package/dist/extensions/pi-subagents/agents/scout.md +1 -1
  120. package/dist/extensions/pi-subagents/docs/agents.md +32 -16
  121. package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
  122. package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
  123. package/dist/extensions/pi-subagents/docs/missions.md +2 -0
  124. package/dist/extensions/pi-subagents/docs/models.md +58 -1
  125. package/dist/extensions/pi-subagents/docs/observability.md +50 -12
  126. package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
  127. package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
  128. package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
  129. package/dist/extensions/pi-subagents/package-lock.json +747 -177
  130. package/dist/extensions/pi-subagents/package.json +6 -4
  131. package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
  132. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
  133. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
  137. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
  138. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
  139. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
  140. package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
  141. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
  142. package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  143. package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
  144. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
  145. package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
  146. package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
  147. package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
  148. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
  149. package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
  150. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
  151. package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
  152. package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
  153. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
  154. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
  155. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
  156. package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
  157. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
  158. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
  159. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
  160. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
  161. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
  164. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
  165. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
  168. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
  170. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
  171. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
  174. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
  175. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
  176. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
  177. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
  179. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
  180. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
  181. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
  182. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
  183. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
  184. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
  185. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
  186. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
  187. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
  188. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
  189. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
  190. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
  192. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  193. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
  194. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
  195. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
  196. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
  197. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
  198. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
  199. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
  202. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
  203. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
  206. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
  207. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  208. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
  210. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
  211. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
  212. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
  213. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
  216. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
  218. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
  219. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
  220. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
  221. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
  222. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
  223. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
  224. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
  225. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
  226. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
  227. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
  228. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
  229. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
  230. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
  231. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
  232. package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
  233. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
  234. package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
  235. package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
  236. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
  237. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
  238. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
  239. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
  240. package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
  241. package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
  242. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
  243. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
  244. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  245. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
  246. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
  247. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
  248. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
  249. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
  250. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
  251. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
  252. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
  253. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
  254. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
  255. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
  256. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
  257. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
  258. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
  259. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
  260. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
  261. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
  262. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
  263. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
  264. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
  265. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
  266. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
  267. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
  268. package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
  269. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
  270. package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
  271. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
  272. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
  273. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
  274. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
  275. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
  276. package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
  277. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
  278. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
  279. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
  280. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
  281. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
  282. package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
  283. package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
  284. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
  285. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
  286. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
  287. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
  288. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
  289. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
  290. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
  291. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
  292. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
  293. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
  294. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
  295. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
  296. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
  297. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
  298. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
  299. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
  300. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
  301. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
  302. package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
  303. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
  304. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
  305. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
  306. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
  307. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
  308. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
  309. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
  310. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
  311. package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
  312. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
  313. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
  314. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
  315. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
  316. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
  317. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
  318. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  319. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
  320. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
  321. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
  322. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
  323. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
  324. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
  325. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
  326. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
  327. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
  328. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
  329. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
  330. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
  331. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
  332. package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
  333. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
  334. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
  335. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
  336. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
  337. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
  338. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
  339. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
  340. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
  341. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
  342. package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
  343. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
  344. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
  345. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
  346. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
  347. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
  348. package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
  349. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
  350. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
  351. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
  352. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
  353. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
  354. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
  355. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
  356. package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
  357. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
  358. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
  359. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
  360. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
  361. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
  362. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
  363. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
  364. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
  365. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
  366. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
  367. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
  368. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
  369. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
  370. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
  371. package/dist/extensions/pi-web-agent/README.md +6 -5
  372. package/dist/extensions/pi-web-agent/src/backends/config.ts +12 -6
  373. package/dist/extensions/pi-web-agent/src/backends/factory.ts +2 -2
  374. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +4 -5
  375. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +8 -8
  376. package/dist/extensions/pi-web-agent/src/extension.ts +3 -3
  377. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +2 -2
  378. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +14 -3
  379. package/dist/extensions/pi-zentui/README.md +17 -0
  380. package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
  381. package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
  382. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
  383. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
  384. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
  385. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
  386. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
  387. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
  388. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
  389. package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
  390. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
  391. package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
  392. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
  393. package/dist/extensions/pi-zentui/package-lock.json +277 -517
  394. package/dist/extensions/pi-zentui/package.json +7 -4
  395. package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
  396. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
  397. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
  398. package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
  399. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
  400. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  401. package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
  402. package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
  403. package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
  404. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
  405. package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
  406. package/dist/index.d.ts +1 -1
  407. package/dist/main.js +4 -1
  408. package/dist/modes/interactive/chat-viewport.d.ts +19 -0
  409. package/dist/modes/interactive/chat-viewport.js +27 -0
  410. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  411. package/dist/modes/interactive/components/assistant-message.js +30 -13
  412. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  413. package/dist/modes/interactive/components/custom-editor.js +39 -1
  414. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  415. package/dist/modes/interactive/components/index.d.ts +1 -1
  416. package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
  417. package/dist/modes/interactive/components/markdown-transform.js +18 -0
  418. package/dist/modes/interactive/components/model-selector.js +19 -17
  419. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  420. package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
  421. package/dist/modes/interactive/components/settings-selector.js +128 -20
  422. package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
  423. package/dist/modes/interactive/components/settings-submenu.js +164 -0
  424. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  425. package/dist/modes/interactive/components/status-indicator.js +10 -3
  426. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  427. package/dist/modes/interactive/components/thinking-selector.js +75 -18
  428. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  429. package/dist/modes/interactive/components/tool-execution.js +35 -33
  430. package/dist/modes/interactive/components/trust-selector.js +2 -2
  431. package/dist/modes/interactive/interactive-mode.d.ts +13 -15
  432. package/dist/modes/interactive/interactive-mode.js +144 -80
  433. package/dist/modes/interactive/session-share.d.ts +15 -0
  434. package/dist/modes/interactive/session-share.js +183 -0
  435. package/dist/modes/interactive/theme/dark.json +2 -1
  436. package/dist/modes/interactive/theme/light.json +2 -1
  437. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  438. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  439. package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
  440. package/dist/modes/interactive/theme/theme-json.js +129 -0
  441. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  442. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  443. package/dist/modes/interactive/theme/theme.js +18 -119
  444. package/dist/modes/interactive/tui-renderer.d.ts +20 -0
  445. package/dist/modes/interactive/tui-renderer.js +65 -0
  446. package/dist/utils/exif-orientation.js +2 -3
  447. package/dist/utils/management-http.d.ts +24 -0
  448. package/dist/utils/management-http.js +53 -0
  449. package/dist/utils/text.d.ts +7 -0
  450. package/dist/utils/text.js +8 -0
  451. package/dist/utils/tools-manager.d.ts +1 -0
  452. package/dist/utils/tools-manager.js +43 -21
  453. package/docs/docs.json +0 -4
  454. package/package.json +6 -6
  455. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
  456. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
  457. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
  458. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  459. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
  460. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
  461. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
  462. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
  463. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
  464. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
  465. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
  466. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
  467. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
  468. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
  469. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
  470. package/dist/extensions/web-agent-onboarding.test.ts +0 -415
  471. package/dist/extensions/web-agent-onboarding.ts +0 -222
  472. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
  473. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
  474. package/dist/skills/implanger/SKILL.md +0 -70
  475. package/dist/skills/output/SKILL.md +0 -49
  476. package/dist/skills/planger/SKILL.md +0 -167
  477. package/dist/skills/workflow/SKILL.md +0 -95
  478. package/docs/workflows.md +0 -18
  479. /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
@@ -36,6 +36,7 @@ import {
36
36
  type SelectorBordersComponentConfig,
37
37
  type SeparatorStyle,
38
38
  saveAccentRailEditorStylePatch,
39
+ saveComponentPreset,
39
40
  saveEditorComponentPatch,
40
41
  saveExtensionStatusColorMode,
41
42
  saveExtensionStatusDefaultPlacement,
@@ -74,6 +75,7 @@ import {
74
75
  } from "./interaction-summary";
75
76
  import { LiveContextController } from "./live-context";
76
77
  import { readPackageVersionResult } from "./package-version";
78
+ import { getComponentPreset } from "./presets";
77
79
  import {
78
80
  createProjectRefreshScheduler,
79
81
  type ProjectRefreshRun,
@@ -97,6 +99,7 @@ import {
97
99
  snapshotWorkingLineHighStyle,
98
100
  WorkingLineController,
99
101
  } from "./working-line";
102
+ import { WorkingLineExtensionSegments } from "./working-line-extension-segments";
100
103
 
101
104
  const ZENTUI_EDITOR_FACTORY = Symbol.for("pi-zentui.editor-factory");
102
105
  const ZENTUI_EDITOR_BASE_FACTORY = Symbol.for("pi-zentui.editor-base-factory");
@@ -293,6 +296,7 @@ export default function (pi: ExtensionAPI) {
293
296
  const liveContext = new LiveContextController(sessionLifecycle, refresh);
294
297
  const getActiveTheme = () => activeTheme;
295
298
  const getCurrentConfig = () => currentConfig;
299
+ let invalidateWorkingLinePublisherState = () => {};
296
300
  const workingLine = new WorkingLineController(
297
301
  getCurrentConfig,
298
302
  () => activeTheme as Theme,
@@ -300,7 +304,29 @@ export default function (pi: ExtensionAPI) {
300
304
  Math.random,
301
305
  Date.now,
302
306
  () => interactionMetrics.currentThought(),
307
+ () => invalidateWorkingLinePublisherState(),
303
308
  );
309
+ let workingLineSessionReady = false;
310
+ const workingLineExtensions = new WorkingLineExtensionSegments(
311
+ pi.events,
312
+ () =>
313
+ workingLineSessionReady &&
314
+ sessionLifecycle.isCurrent() &&
315
+ currentConfig.components.workingLine.enabled &&
316
+ activeTuiContext !== undefined &&
317
+ workingLine.isAvailable(),
318
+ (segments) => {
319
+ if (activeTuiContext && sessionLifecycle.isCurrent()) {
320
+ const applied = workingLine.updateExtensionSegments(segments, activeTuiContext);
321
+ if (!applied && !workingLine.isAvailable()) {
322
+ workingLine.invalidateExtensionSegments();
323
+ }
324
+ return applied;
325
+ }
326
+ return false;
327
+ },
328
+ );
329
+ invalidateWorkingLinePublisherState = () => workingLineExtensions.invalidate();
304
330
  const getContextSnapshot = (ctx: ExtensionContext) => resolveContextUsage(ctx, liveContext.get());
305
331
  const getContextWindow = (ctx: ExtensionContext): number | undefined =>
306
332
  getContextSnapshot(ctx).contextWindow;
@@ -995,7 +1021,11 @@ export default function (pi: ExtensionAPI) {
995
1021
  !options.allowStaleZentui
996
1022
  ) {
997
1023
  clearEditorOwnership();
998
- return;
1024
+ return {
1025
+ ok: false,
1026
+ reason:
1027
+ "another Zentui instance is currently managing the editor; reload Pi to apply this change",
1028
+ };
999
1029
  }
1000
1030
  const editorMissingOrReplaced = !editorInstalled || !isOwnedEditorFactory(currentFactory);
1001
1031
  if (editorMissingOrReplaced) return installEditor(ctx);
@@ -1147,6 +1177,12 @@ export default function (pi: ExtensionAPI) {
1147
1177
 
1148
1178
  pi.on("session_start", async (_event, ctx) => {
1149
1179
  const lifecycleGeneration = sessionLifecycle.start();
1180
+ // A new generation must not expose or route extension segments through the previous
1181
+ // session while asynchronous TUI startup is still pending.
1182
+ workingLineSessionReady = false;
1183
+ workingLineExtensions.invalidate();
1184
+ if (activeTuiContext) workingLine.dispose(activeTuiContext);
1185
+ else workingLine.invalidateExtensionSegments();
1150
1186
  // Reload synchronously so private ownership uses this session's disk snapshot before
1151
1187
  // any await or transcript restoration.
1152
1188
  currentConfig = loadConfig();
@@ -1173,6 +1209,7 @@ export default function (pi: ExtensionAPI) {
1173
1209
  if (!sessionLifecycle.isCurrent(lifecycleGeneration)) return;
1174
1210
  liveContext.clear();
1175
1211
  interactionMetrics.shutdown();
1212
+ workingLineExtensions.invalidate();
1176
1213
  state.sessionStartEpoch = Date.now();
1177
1214
  invalidateUsageTotalsCache();
1178
1215
  resetAgentTimer();
@@ -1181,16 +1218,50 @@ export default function (pi: ExtensionAPI) {
1181
1218
  repositoryRoots.reset();
1182
1219
  installUi(ctx);
1183
1220
  workingLine.startSession(ctx);
1221
+ workingLineSessionReady = true;
1184
1222
  scheduleEditorReconciliation(ctx);
1185
1223
  });
1186
1224
 
1187
1225
  registerZentuiSettingsCommand(pi, {
1188
1226
  sessionLifecycle,
1189
1227
  getConfig: getCurrentConfig,
1190
- setEditorComponent(patch: Partial<EditorComponentConfig>, ctx: ExtensionContext) {
1228
+ applyPreset(id, ctx, options) {
1229
+ const preset = getComponentPreset(id);
1230
+ if (!preset) throw new Error(`Unknown Zentui preset: ${id}`);
1231
+ const previousFooterStyle = effectiveFooterStyle();
1232
+ currentConfig = saveComponentPreset(preset);
1233
+ if (!isTuiContext(ctx)) return { applied: true };
1234
+ activeTheme = ctx.ui.theme;
1235
+ const result = options?.deferEditor ? undefined : reconcileEditor(ctx);
1236
+ if (currentConfig.components.editor.style !== "minimalist") {
1237
+ setMinimalistDecorationActive(false);
1238
+ }
1239
+ reconcileUserMessages();
1240
+ reconcileFooter(ctx);
1241
+ reconcileProjectRefresh(ctx, effectiveFooterStyle() !== previousFooterStyle);
1242
+ reconcileSessionTimer();
1243
+ reconcileAgentTimer();
1244
+ refresh();
1245
+ return {
1246
+ applied: !result || result.ok,
1247
+ reason: result && !result.ok ? result.reason : undefined,
1248
+ };
1249
+ },
1250
+ reconcilePresetEditor(ctx) {
1251
+ if (!isTuiContext(ctx) || !sessionLifecycle.isCurrent()) return { applied: true };
1252
+ const result = reconcileEditor(ctx);
1253
+ reconcileProjectRefresh(ctx);
1254
+ reconcileAgentTimer();
1255
+ refresh();
1256
+ return {
1257
+ applied: !result || result.ok,
1258
+ reason: result && !result.ok ? result.reason : undefined,
1259
+ };
1260
+ },
1261
+ setEditorComponent(patch: Partial<EditorComponentConfig>, ctx: ExtensionContext, options) {
1191
1262
  currentConfig = saveEditorComponentPatch(patch);
1192
1263
  let result: EditorChangeResult | undefined;
1193
- if (patch.enabled !== undefined && isTuiContext(ctx)) {
1264
+ if (patch.enabled !== undefined && isTuiContext(ctx) && !options?.deferEditor) {
1194
1265
  result = reconcileEditor(ctx);
1195
1266
  }
1196
1267
  if (patch.style !== undefined && patch.style !== "minimalist") {
@@ -1241,6 +1312,7 @@ export default function (pi: ExtensionAPI) {
1241
1312
  },
1242
1313
  setWorkingLineComponent(patch: WorkingLineComponentPatch, ctx: ExtensionContext) {
1243
1314
  currentConfig = saveWorkingLineComponentPatch(patch);
1315
+ if (patch.enabled === false) workingLineExtensions.clear();
1244
1316
  return workingLine.reconcile(ctx);
1245
1317
  },
1246
1318
  setSelectorBordersComponent(
@@ -1326,10 +1398,12 @@ export default function (pi: ExtensionAPI) {
1326
1398
  });
1327
1399
 
1328
1400
  pi.on("session_shutdown", async (_event, ctx) => {
1401
+ workingLineSessionReady = false;
1329
1402
  thinkingExperimental.shutdown();
1330
1403
  liveContext.clear();
1331
1404
  interactionMetrics.shutdown();
1332
1405
  workingLine.dispose(ctx);
1406
+ workingLineExtensions.invalidate();
1333
1407
  cleanupUi(ctx);
1334
1408
  });
1335
1409
 
@@ -0,0 +1,77 @@
1
+ import {
2
+ type EditorComponentConfig,
3
+ type FooterComponentConfig,
4
+ hasUnsupportedComponentStyle,
5
+ type UserMessagesComponentConfig,
6
+ type ZentuiConfig,
7
+ } from "./config";
8
+
9
+ export type PresetId = "opencode" | "opencode-copy-friendly" | "rail" | "minimalist";
10
+ export type ComponentPreset = Readonly<{
11
+ id: PresetId;
12
+ label: string;
13
+ components: Readonly<{
14
+ editor: Readonly<Pick<EditorComponentConfig, "enabled" | "style">>;
15
+ footer: Readonly<Pick<FooterComponentConfig, "style">>;
16
+ userMessages: Readonly<
17
+ Pick<UserMessagesComponentConfig, "enabled"> &
18
+ Partial<Pick<UserMessagesComponentConfig, "style">>
19
+ >;
20
+ }>;
21
+ }>;
22
+
23
+ export const componentPresets: readonly ComponentPreset[] = [
24
+ {
25
+ id: "opencode",
26
+ label: "Opencode",
27
+ components: {
28
+ editor: { enabled: true, style: "opencode" },
29
+ footer: { style: "starship" },
30
+ userMessages: { enabled: true, style: "framed" },
31
+ },
32
+ },
33
+ {
34
+ id: "opencode-copy-friendly",
35
+ label: "Opencode (copy-friendly)",
36
+ components: {
37
+ editor: { enabled: true, style: "opencode-copy-friendly" },
38
+ footer: { style: "starship" },
39
+ userMessages: { enabled: true, style: "framed-copy-friendly" },
40
+ },
41
+ },
42
+ {
43
+ id: "rail",
44
+ label: "Rail",
45
+ components: {
46
+ editor: { enabled: true, style: "accent-rail" },
47
+ footer: { style: "starship" },
48
+ userMessages: { enabled: true, style: "compact" },
49
+ },
50
+ },
51
+ {
52
+ id: "minimalist",
53
+ label: "Minimalist",
54
+ components: {
55
+ editor: { enabled: true, style: "minimalist" },
56
+ footer: { style: "hidden" },
57
+ userMessages: { enabled: false },
58
+ },
59
+ },
60
+ ];
61
+
62
+ export function getComponentPreset(id: string): ComponentPreset | undefined {
63
+ return componentPresets.find((preset) => preset.id === id);
64
+ }
65
+
66
+ /** Match configured selections, not live ownership or dormant style options. */
67
+ export function matchingComponentPreset(config: ZentuiConfig): ComponentPreset | undefined {
68
+ return componentPresets.find(({ components }) =>
69
+ (["editor", "footer", "userMessages"] as const).every((owner) => {
70
+ const selection = components[owner];
71
+ if ("style" in selection && hasUnsupportedComponentStyle(config, owner)) return false;
72
+ return Object.entries(selection).every(
73
+ ([key, value]) => config.components[owner][key as keyof typeof selection] === value,
74
+ );
75
+ }),
76
+ );
77
+ }
@@ -53,8 +53,15 @@ import {
53
53
  type WorkingLineSpinner,
54
54
  type WorkingLineTextAnimation,
55
55
  } from "./config";
56
+ import { prepareEditorTextForCustomUi } from "./editor-transfer";
56
57
  import { sanitizeExtensionStatusText } from "./extension-status";
57
58
  import { isIconMode } from "./icons";
59
+ import {
60
+ componentPresets,
61
+ getComponentPreset,
62
+ matchingComponentPreset,
63
+ type PresetId,
64
+ } from "./presets";
58
65
  import type { SessionLifecycle } from "./session-lifecycle";
59
66
  import {
60
67
  renderEditorSettingsPreview,
@@ -213,7 +220,17 @@ function experimentalThinkingCapability(
213
220
  type SettingsCommandDeps = {
214
221
  sessionLifecycle: SessionLifecycle;
215
222
  getConfig: () => PolishedTuiConfig;
216
- setEditorComponent: (patch: EditorPatch, ctx: ExtensionContext) => ApplyResult;
223
+ applyPreset: (
224
+ id: PresetId,
225
+ ctx: ExtensionContext,
226
+ options?: { deferEditor?: boolean },
227
+ ) => ApplyResult;
228
+ reconcilePresetEditor: (ctx: ExtensionContext) => ApplyResult;
229
+ setEditorComponent: (
230
+ patch: EditorPatch,
231
+ ctx: ExtensionContext,
232
+ options?: { deferEditor?: boolean },
233
+ ) => ApplyResult;
217
234
  setPolished: (patch: Partial<PolishedEditorStyleConfig>, ctx: ExtensionContext) => void;
218
235
  setPolishedCopyFriendly: (
219
236
  patch: Partial<PolishedCopyFriendlyEditorStyleConfig>,
@@ -310,6 +327,7 @@ const footerSegmentSettingDescriptions: Record<FooterSegmentSettingId, string> =
310
327
  };
311
328
 
312
329
  const directCommandSuggestions = [
330
+ ...componentPresets.map(({ id }) => `preset ${id}`),
313
331
  "editor enable",
314
332
  "editor disable",
315
333
  "editor toggle",
@@ -471,12 +489,20 @@ function argumentCompletions(prefix: string): AutocompleteItem[] | null {
471
489
  }
472
490
 
473
491
  function usageText(): string {
474
- return "Usage: /zentui [editor|messages|statusline|viewport-indicators] [enable|disable|toggle], /zentui [messages|user-messages|working-line], or /zentui format <template>";
492
+ return "Usage: /zentui [editor|messages|statusline|viewport-indicators] [enable|disable|toggle], /zentui [messages|user-messages|working-line], /zentui preset <opencode|opencode-copy-friendly|rail|minimalist>, or /zentui format <template>";
475
493
  }
476
494
 
477
495
  function buildAppearanceItems(config: PolishedTuiConfig): SettingItem[] {
478
496
  const component = config.components.selectorBorders;
479
497
  return [
498
+ {
499
+ id: "preset",
500
+ label: "Preset",
501
+ description:
502
+ "Apply Editor, Footer, and User messages together once. Preserves colors and other settings; editor installation waits until this panel closes. Custom means no matching combination.",
503
+ currentValue: matchingComponentPreset(config)?.label ?? "Custom",
504
+ values: componentPresets.map(({ label }) => label),
505
+ },
480
506
  {
481
507
  id: "selectorBordersEnabled",
482
508
  label: "Selector borders",
@@ -1133,11 +1159,38 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
1133
1159
  deps.setFooterComponent(patch, ctx);
1134
1160
  };
1135
1161
 
1162
+ const applyPreset = (id: PresetId, ctx: ExtensionContext) => {
1163
+ try {
1164
+ const result = deps.applyPreset(id, ctx);
1165
+ deps.requestRender();
1166
+ if (ctx.hasUI) {
1167
+ const detail = result.reason?.trim();
1168
+ ctx.ui.notify(
1169
+ `Preset saved: ${getComponentPreset(id)?.label}${detail ? ` (${detail})` : !result.applied ? " (reload Pi to apply this change)" : ""}`,
1170
+ !result.applied || detail ? "warning" : "info",
1171
+ );
1172
+ }
1173
+ } catch (error) {
1174
+ if (ctx.hasUI)
1175
+ ctx.ui.notify(
1176
+ `Could not update Zentui settings: ${error instanceof Error ? error.message : String(error)}`,
1177
+ "error",
1178
+ );
1179
+ }
1180
+ };
1181
+
1136
1182
  pi.registerCommand("zentui", {
1137
1183
  description: "Configure Zentui",
1138
1184
  getArgumentCompletions: argumentCompletions,
1139
1185
  handler: async (_args, ctx) => {
1140
1186
  const args = typeof _args === "string" ? _args : "";
1187
+ const words = args.trim().split(/\s+/);
1188
+ if (words[0]?.toLowerCase() === "preset") {
1189
+ const preset = words.length === 2 ? getComponentPreset(words[1] ?? "") : undefined;
1190
+ if (preset) applyPreset(preset.id, ctx);
1191
+ else if (ctx.hasUI) ctx.ui.notify(usageText(), "warning");
1192
+ return;
1193
+ }
1141
1194
  const format = parseFormatCommand(args);
1142
1195
  if (format) {
1143
1196
  try {
@@ -1210,8 +1263,19 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
1210
1263
  let requestedSection = initialSection ?? "appearance";
1211
1264
  let requestedFocusId: string | undefined;
1212
1265
  while (true) {
1266
+ try {
1267
+ prepareEditorTextForCustomUi(ctx.ui);
1268
+ } catch (error) {
1269
+ ctx.ui.notify(
1270
+ `Could not open Zentui settings safely: ${error instanceof Error ? error.message : String(error)}`,
1271
+ "error",
1272
+ );
1273
+ return;
1274
+ }
1213
1275
  const initialFocusId = requestedFocusId;
1214
1276
  requestedFocusId = undefined;
1277
+ const generation = deps.sessionLifecycle.currentGeneration();
1278
+ let pendingPresetEditor = false;
1215
1279
  const outcome = await ctx.ui.custom<SettingsOutcome>((tui, theme, _keybindings, done) => {
1216
1280
  const listTheme = deps.settingsListTheme ?? getSettingsListTheme();
1217
1281
  let activeSection = requestedSection;
@@ -1315,8 +1379,26 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
1315
1379
  listTheme,
1316
1380
  (id, newValue) => {
1317
1381
  try {
1382
+ if (id === "preset") {
1383
+ const preset = componentPresets.find(({ label }) => label === newValue);
1384
+ if (!preset) return;
1385
+ if (!deps.sessionLifecycle.isCurrent(generation)) return;
1386
+ const result = deps.applyPreset(preset.id, ctx, { deferEditor: true });
1387
+ pendingPresetEditor = true;
1388
+ settingsList = makeSettingsList("preset");
1389
+ notifyChange("Preset saved", preset.label, result);
1390
+ return;
1391
+ }
1318
1392
  const enabled = isFeatureState(newValue) ? newValue === "enabled" : undefined;
1319
1393
  if (id === "editorEnabled" && enabled !== undefined) {
1394
+ if (pendingPresetEditor) {
1395
+ const result = deps.setEditorComponent({ enabled }, ctx, {
1396
+ deferEditor: true,
1397
+ });
1398
+ notifyChange("Editor", newValue, result);
1399
+ finishSettings("close");
1400
+ return;
1401
+ }
1320
1402
  finishSettings("close");
1321
1403
  deps.sessionLifecycle.defer(() => {
1322
1404
  try {
@@ -1838,6 +1920,25 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
1838
1920
  },
1839
1921
  };
1840
1922
  });
1923
+ // Pi restores its saved editor text before custom() resolves. Reconcile only
1924
+ // now, using the latest config and observed factory, never a captured factory.
1925
+ if (pendingPresetEditor && !deps.sessionLifecycle.isCurrent(generation)) return;
1926
+ if (pendingPresetEditor) {
1927
+ try {
1928
+ const result = deps.reconcilePresetEditor(ctx);
1929
+ if (!result.applied || result.reason) {
1930
+ ctx.ui.notify(
1931
+ `Preset saved: editor (${result.reason ?? "reload Pi to apply this change"})`,
1932
+ "warning",
1933
+ );
1934
+ }
1935
+ } catch (error) {
1936
+ ctx.ui.notify(
1937
+ `Could not apply preset editor; reload Pi: ${error instanceof Error ? error.message : String(error)}`,
1938
+ "error",
1939
+ );
1940
+ }
1941
+ }
1841
1942
  if (outcome === "close" || outcome === undefined) return;
1842
1943
  if (
1843
1944
  outcome === "edit-working-line-spinner-speed" ||
@@ -0,0 +1,115 @@
1
+ import type { EventBus } from "@earendil-works/pi-coding-agent";
2
+
3
+ export const ZENTUI_WORKING_LINE_SEGMENT_CAPABILITY_EVENT =
4
+ "zentui:working-line-segment-capability";
5
+ export const ZENTUI_WORKING_LINE_SEGMENT_EVENT = "zentui:working-line-segment";
6
+ export const ZENTUI_WORKING_LINE_SEGMENT_PROTOCOL_VERSION = 1;
7
+
8
+ export const MAX_WORKING_LINE_EXTENSION_SEGMENTS = 16;
9
+ export const MAX_WORKING_LINE_EXTENSION_KEY_CODE_UNITS = 64;
10
+ export const MAX_WORKING_LINE_EXTENSION_TEXT_CODE_UNITS = 256;
11
+
12
+ export type WorkingLineSegmentCapability = {
13
+ supported: boolean;
14
+ active: boolean;
15
+ /** Present in protocol version 1 and later. */
16
+ version?: number;
17
+ };
18
+
19
+ export type WorkingLineSegmentUpdate = {
20
+ key: string;
21
+ text?: string;
22
+ };
23
+
24
+ type EventRecord = Record<string, unknown>;
25
+
26
+ function eventRecord(value: unknown): EventRecord | undefined {
27
+ return value !== null && typeof value === "object" && !Array.isArray(value)
28
+ ? (value as EventRecord)
29
+ : undefined;
30
+ }
31
+
32
+ function segmentUpdate(value: unknown): WorkingLineSegmentUpdate | undefined {
33
+ const record = eventRecord(value);
34
+ if (!record) return undefined;
35
+ if (
36
+ typeof record.key !== "string" ||
37
+ record.key.length === 0 ||
38
+ record.key.length > MAX_WORKING_LINE_EXTENSION_KEY_CODE_UNITS
39
+ ) {
40
+ return undefined;
41
+ }
42
+ if (
43
+ record.text !== undefined &&
44
+ (typeof record.text !== "string" ||
45
+ record.text.length > MAX_WORKING_LINE_EXTENSION_TEXT_CODE_UNITS)
46
+ ) {
47
+ return undefined;
48
+ }
49
+ return { key: record.key, text: record.text as string | undefined };
50
+ }
51
+
52
+ /** Collects keyed third-party segments and publishes deterministic snapshots to the Working line. */
53
+ export class WorkingLineExtensionSegments {
54
+ private readonly segments = new Map<string, string>();
55
+ private publishDirty = false;
56
+
57
+ constructor(
58
+ events: EventBus | undefined,
59
+ private readonly isActive: () => boolean,
60
+ private readonly onChange: (segments: readonly string[]) => boolean | undefined,
61
+ ) {
62
+ if (!events) return;
63
+ events.on(ZENTUI_WORKING_LINE_SEGMENT_CAPABILITY_EVENT, (value) => {
64
+ const capability = eventRecord(value);
65
+ if (!capability) return;
66
+ capability.supported = true;
67
+ capability.active = this.isActive();
68
+ capability.version = ZENTUI_WORKING_LINE_SEGMENT_PROTOCOL_VERSION;
69
+ });
70
+ events.on(ZENTUI_WORKING_LINE_SEGMENT_EVENT, (value) => {
71
+ const update = segmentUpdate(value);
72
+ if (!update) return;
73
+ if (update.text !== undefined && update.text.length > 0 && !this.isActive()) return;
74
+ if (update.text === undefined || update.text.length === 0) {
75
+ if (!this.segments.delete(update.key) && !this.publishDirty) return;
76
+ } else {
77
+ if (
78
+ !this.segments.has(update.key) &&
79
+ this.segments.size >= MAX_WORKING_LINE_EXTENSION_SEGMENTS
80
+ )
81
+ return;
82
+ if (this.segments.get(update.key) === update.text && !this.publishDirty) return;
83
+ this.segments.set(update.key, update.text);
84
+ }
85
+ this.publishDirty = true;
86
+ this.publish();
87
+ });
88
+ }
89
+
90
+ clear(): void {
91
+ if (this.segments.size === 0 && !this.publishDirty) return;
92
+ this.segments.clear();
93
+ this.publishDirty = true;
94
+ this.publish();
95
+ }
96
+
97
+ /** Drops session-scoped publisher state without attempting a Working-row write. */
98
+ invalidate(): void {
99
+ this.segments.clear();
100
+ this.publishDirty = false;
101
+ }
102
+
103
+ private publish(): void {
104
+ const applied = this.onChange(
105
+ [...this.segments.entries()]
106
+ .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
107
+ .map(([, text]) => text),
108
+ );
109
+ if (applied === false && !this.isActive()) {
110
+ this.invalidate();
111
+ return;
112
+ }
113
+ this.publishDirty = applied === false;
114
+ }
115
+ }