@entelligentsia/forgecli 1.1.0 → 1.1.3

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 (284) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +4 -0
  3. package/dist/CHANGELOG-forge-plugin.md +114 -0
  4. package/dist/CHANGELOG-pi.md +56 -0
  5. package/dist/extensions/forgecli/forge-subagent.js +58 -0
  6. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  7. package/dist/extensions/forgecli/mcp-bridge/grove.d.ts +38 -0
  8. package/dist/extensions/forgecli/mcp-bridge/grove.js +88 -2
  9. package/dist/extensions/forgecli/mcp-bridge/grove.js.map +1 -1
  10. package/dist/extensions/forgecli/mcp-bridge/json-rpc-stdio.d.ts +26 -2
  11. package/dist/extensions/forgecli/mcp-bridge/json-rpc-stdio.js +68 -13
  12. package/dist/extensions/forgecli/mcp-bridge/json-rpc-stdio.js.map +1 -1
  13. package/dist/extensions/forgecli/mcp-bridge/mcp-bridge.js +13 -2
  14. package/dist/extensions/forgecli/mcp-bridge/mcp-bridge.js.map +1 -1
  15. package/dist/extensions/forgecli/mcp-bridge/mcp-session.d.ts +3 -3
  16. package/dist/extensions/forgecli/mcp-bridge/mcp-session.js +3 -6
  17. package/dist/extensions/forgecli/mcp-bridge/mcp-session.js.map +1 -1
  18. package/dist/extensions/forgecli/orchestrators/init/init-phase-dispatch.d.ts +49 -40
  19. package/dist/extensions/forgecli/orchestrators/init/init-phase-dispatch.js +59 -188
  20. package/dist/extensions/forgecli/orchestrators/init/init-phase-dispatch.js.map +1 -1
  21. package/dist/extensions/forgecli/orchestrators/init/init-phases.d.ts +0 -43
  22. package/dist/extensions/forgecli/orchestrators/init/init-phases.js +11 -59
  23. package/dist/extensions/forgecli/orchestrators/init/init-phases.js.map +1 -1
  24. package/dist/extensions/forgecli/orchestrators/init/init-steps.d.ts +115 -0
  25. package/dist/extensions/forgecli/orchestrators/init/init-steps.js +125 -0
  26. package/dist/extensions/forgecli/orchestrators/init/init-steps.js.map +1 -0
  27. package/dist/extensions/forgecli/orchestrators/init/run-init-pipeline.js +400 -211
  28. package/dist/extensions/forgecli/orchestrators/init/run-init-pipeline.js.map +1 -1
  29. package/dist/extensions/forgecli/orchestrators/init/run-init-types.d.ts +8 -2
  30. package/dist/extensions/forgecli/orchestrators/init/run-init-types.js +15 -5
  31. package/dist/extensions/forgecli/orchestrators/init/run-init-types.js.map +1 -1
  32. package/dist/forge-payload/.base-pack/workflows-js/wfl-init.js +99 -38
  33. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  34. package/dist/forge-payload/.init/generation/generate-kb-doc.md +24 -0
  35. package/dist/forge-payload/.schemas/migrations.json +77 -0
  36. package/dist/forge-payload/init/generation/generate-kb-doc.md +24 -0
  37. package/dist/forge-payload/init/phases/phase-2/context.md +23 -0
  38. package/dist/forge-payload/init/phases/phase-2/database.md +26 -0
  39. package/dist/forge-payload/init/phases/phase-2/deployment.md +26 -0
  40. package/dist/forge-payload/init/phases/phase-2/domain-concepts.md +26 -0
  41. package/dist/forge-payload/init/phases/phase-2/domain-model.md +26 -0
  42. package/dist/forge-payload/init/phases/phase-2/entity-model.md +26 -0
  43. package/dist/forge-payload/init/phases/phase-2/index.md +25 -0
  44. package/dist/forge-payload/init/phases/phase-2/processes.md +26 -0
  45. package/dist/forge-payload/init/phases/phase-2/routing.md +25 -0
  46. package/dist/forge-payload/init/phases/phase-2/stack-checklist.md +25 -0
  47. package/dist/forge-payload/init/phases/phase-2/stack.md +27 -0
  48. package/dist/forge-payload/init/phases/phase-2/testing.md +26 -0
  49. package/dist/forge-payload/init/phases/phase-2-discover.md +15 -9
  50. package/dist/forge-payload/payload-manifest.json +2 -2
  51. package/dist/forge-payload/tools/seed-store.cjs +14 -0
  52. package/dist/forge-payload/tools/verify-phase.cjs +61 -4
  53. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +3 -1
  54. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  55. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +10 -1
  56. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  57. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
  58. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +4 -6
  59. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
  60. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  61. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +20 -2
  62. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  63. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  64. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
  65. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +2 -14
  66. package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
  67. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  68. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +16 -5
  69. package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
  70. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
  71. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +2 -1
  72. package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
  73. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
  74. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +2 -1
  75. package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
  76. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  77. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +61 -41
  78. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  79. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  80. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +8 -3
  81. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  82. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  83. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +2 -14
  84. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  85. package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.d.ts.map +1 -1
  86. package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js +2 -1
  87. package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js.map +1 -1
  88. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -45
  89. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  90. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -45
  91. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  92. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +461 -22
  93. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  94. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts +140 -0
  95. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  96. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js +141 -4
  97. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js.map +1 -1
  98. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +20 -0
  99. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
  100. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +18 -0
  101. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
  102. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts +21 -0
  103. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts.map +1 -1
  104. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js +18 -0
  105. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js.map +1 -1
  106. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts +21 -0
  107. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  108. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js +18 -0
  109. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  110. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts +10 -5
  111. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts.map +1 -1
  112. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js +4 -3
  113. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js.map +1 -1
  114. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +82 -0
  115. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
  116. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +57 -0
  117. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
  118. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts.map +1 -1
  119. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js +1 -1
  120. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js.map +1 -1
  121. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts +1 -1
  122. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts.map +1 -1
  123. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js +4 -4
  124. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js.map +1 -1
  125. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts +1 -1
  126. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts.map +1 -1
  127. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js +4 -4
  128. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js.map +1 -1
  129. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts.map +1 -1
  130. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +5 -5
  131. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
  132. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +88 -0
  133. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
  134. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +75 -2
  135. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
  136. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +33 -15
  137. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  138. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +101 -84
  139. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  140. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts.map +1 -1
  141. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js +2 -2
  142. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js.map +1 -1
  143. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +44 -0
  144. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  145. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +41 -4
  146. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  147. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  148. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js +12 -12
  149. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  150. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  151. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js +12 -12
  152. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  153. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  154. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js +12 -12
  155. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  156. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts.map +1 -1
  157. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js +15 -15
  158. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js.map +1 -1
  159. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts +25 -0
  160. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts.map +1 -0
  161. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js +109 -0
  162. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js.map +1 -0
  163. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +2 -0
  164. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
  165. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +15 -2
  166. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  168. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +3 -2
  169. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  170. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +1 -0
  171. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  172. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -0
  173. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  174. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  175. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -0
  176. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  177. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  178. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +56 -0
  179. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts +6 -1
  180. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  181. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +39 -15
  182. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  183. package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  184. package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js +13 -5
  185. package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  186. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  187. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +5 -8
  188. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  189. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  190. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  191. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  192. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  193. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js +6 -0
  194. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  195. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -1
  196. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  197. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +33 -1
  198. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  199. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +16 -2
  200. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  201. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  202. package/node_modules/@earendil-works/pi-coding-agent/dist/core/http-dispatcher.d.ts.map +1 -1
  203. package/node_modules/@earendil-works/pi-coding-agent/dist/core/http-dispatcher.js +28 -1
  204. package/node_modules/@earendil-works/pi-coding-agent/dist/core/http-dispatcher.js.map +1 -1
  205. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts +10 -0
  206. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  207. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +14 -17
  208. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  209. package/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-attribution.d.ts.map +1 -1
  210. package/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-attribution.js +0 -10
  211. package/node_modules/@earendil-works/pi-coding-agent/dist/core/provider-attribution.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts +20 -1
  213. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  214. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +87 -68
  215. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  216. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  217. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  218. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +8 -0
  219. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  220. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  221. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +20 -5
  222. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  223. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  224. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +2 -2
  225. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  226. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts +3 -2
  227. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts.map +1 -1
  228. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +2 -1
  229. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js.map +1 -1
  230. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  231. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  232. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +15 -7
  233. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  234. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  235. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  236. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/custom-entry.js +52 -0
  237. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/custom-entry.js.map +1 -0
  238. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  239. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +13 -1
  241. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  242. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  243. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
  244. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/status-indicator.js +60 -0
  245. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/status-indicator.js.map +1 -0
  246. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +6 -2
  247. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  248. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +18 -5
  249. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  250. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +10 -10
  251. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  252. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +143 -130
  253. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  254. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +15 -0
  255. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  256. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +14 -0
  257. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  258. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  259. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +16 -0
  260. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  261. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +26 -0
  262. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  263. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.d.ts.map +1 -1
  265. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js +7 -0
  266. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +55 -8
  268. package/node_modules/@earendil-works/pi-coding-agent/docs/rpc.md +58 -0
  269. package/node_modules/@earendil-works/pi-coding-agent/docs/sdk.md +28 -0
  270. package/node_modules/@earendil-works/pi-coding-agent/docs/session-format.md +18 -8
  271. package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +1 -0
  272. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/README.md +1 -0
  273. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  274. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  275. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/entry-renderer.ts +41 -0
  276. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/gondolin/package-lock.json +2 -2
  277. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/gondolin/package.json +1 -1
  278. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/question.ts +1 -0
  279. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  280. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  281. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +12 -12
  282. package/node_modules/@earendil-works/pi-coding-agent/package.json +4 -4
  283. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  284. package/package.json +7 -7
@@ -7,7 +7,7 @@ import * as fs from "node:fs";
7
7
  import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import { getProviders, } from "@earendil-works/pi-ai/compat";
10
- import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
10
+ import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
11
11
  import chalk from "chalk";
12
12
  import { spawn, spawnSync } from "child_process";
13
13
  import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
@@ -21,7 +21,7 @@ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScop
21
21
  import { DefaultPackageManager } from "../../core/package-manager.js";
22
22
  import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
23
23
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
24
- import { SessionManager } from "../../core/session-manager.js";
24
+ import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
25
25
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
26
26
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
27
27
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
@@ -40,8 +40,8 @@ import { BashExecutionComponent } from "./components/bash-execution.js";
40
40
  import { BorderedLoader } from "./components/bordered-loader.js";
41
41
  import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
42
42
  import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
43
- import { CountdownTimer } from "./components/countdown-timer.js";
44
43
  import { CustomEditor } from "./components/custom-editor.js";
44
+ import { CustomEntryComponent } from "./components/custom-entry.js";
45
45
  import { CustomMessageComponent } from "./components/custom-message.js";
46
46
  import { DaxnutsComponent } from "./components/daxnuts.js";
47
47
  import { DynamicBorder } from "./components/dynamic-border.js";
@@ -58,6 +58,7 @@ import { ScopedModelsSelectorComponent } from "./components/scoped-models-select
58
58
  import { SessionSelectorComponent } from "./components/session-selector.js";
59
59
  import { SettingsSelectorComponent } from "./components/settings-selector.js";
60
60
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
61
+ import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
61
62
  import { ToolExecutionComponent } from "./components/tool-execution.js";
62
63
  import { TreeSelectorComponent } from "./components/tree-selector.js";
63
64
  import { TrustSelectorComponent } from "./components/trust-selector.js";
@@ -106,6 +107,9 @@ class SourceOverridableContainer extends Container {
106
107
  super.invalidate();
107
108
  }
108
109
  }
110
+ function isCustomSessionEntry(item) {
111
+ return "type" in item && item.type === "custom";
112
+ }
109
113
  const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
110
114
  function isDeadTerminalError(error) {
111
115
  if (!error || typeof error !== "object" || !("code" in error)) {
@@ -178,7 +182,8 @@ export class InteractiveMode {
178
182
  isInitialized = false;
179
183
  onInputCallback;
180
184
  pendingUserInputs = [];
181
- loadingAnimation = undefined;
185
+ activeStatusIndicator = undefined;
186
+ idleStatus = new IdleStatus();
182
187
  workingMessage = undefined;
183
188
  workingVisible = true;
184
189
  workingIndicatorOptions = undefined;
@@ -202,6 +207,7 @@ export class InteractiveMode {
202
207
  toolOutputExpanded = false;
203
208
  // Thinking block visibility state
204
209
  hideThinkingBlock = false;
210
+ outputPad = 1;
205
211
  // Skill commands: command name -> skill file path
206
212
  skillCommands = new Map();
207
213
  // Agent subscription unsubscribe function
@@ -214,11 +220,8 @@ export class InteractiveMode {
214
220
  // Track pending bash components (shown in pending area, moved to chat on submit)
215
221
  pendingBashComponents = [];
216
222
  // Auto-compaction state
217
- autoCompactionLoader = undefined;
218
223
  autoCompactionEscapeHandler;
219
224
  // Auto-retry state
220
- retryLoader = undefined;
221
- retryCountdown = undefined;
222
225
  retryEscapeHandler;
223
226
  // Messages queued while compaction is running
224
227
  compactionQueuedMessages = [];
@@ -294,6 +297,7 @@ export class InteractiveMode {
294
297
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
295
298
  // Load hide thinking block setting
296
299
  this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
300
+ this.outputPad = this.settingsManager.getOutputPad();
297
301
  // Register themes from resource loader and initialize
298
302
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
299
303
  this.themeController = new InteractiveThemeController(this.ui, this.settingsManager, (message) => this.showError(message), () => this.updateEditorBorderColor());
@@ -1186,11 +1190,7 @@ export class InteractiveMode {
1186
1190
  commandContextActions: {
1187
1191
  waitForIdle: () => this.session.agent.waitForIdle(),
1188
1192
  newSession: async (options) => {
1189
- if (this.loadingAnimation) {
1190
- this.loadingAnimation.stop();
1191
- this.loadingAnimation = undefined;
1192
- }
1193
- this.statusContainer.clear();
1193
+ this.clearStatusIndicator();
1194
1194
  try {
1195
1195
  return await this.runtimeHost.newSession(options);
1196
1196
  }
@@ -1260,8 +1260,13 @@ export class InteractiveMode {
1260
1260
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
1261
1261
  this.footerDataProvider.setCwd(this.sessionManager.getCwd());
1262
1262
  this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
1263
+ this.outputPad = this.settingsManager.getOutputPad();
1263
1264
  this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
1264
- this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
1265
+ const clearOnShrink = this.settingsManager.getClearOnShrink();
1266
+ this.ui.setClearOnShrink(clearOnShrink);
1267
+ if (!clearOnShrink && !this.activeStatusIndicator) {
1268
+ this.statusContainer.clear();
1269
+ }
1265
1270
  const editorPaddingX = this.settingsManager.getEditorPaddingX();
1266
1271
  const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
1267
1272
  this.defaultEditor.setPaddingX(editorPaddingX);
@@ -1374,36 +1379,41 @@ export class InteractiveMode {
1374
1379
  this.footerDataProvider.setExtensionStatus(key, text);
1375
1380
  this.ui.requestRender();
1376
1381
  }
1377
- getWorkingLoaderMessage() {
1378
- return this.workingMessage ?? this.defaultWorkingMessage;
1379
- }
1380
- createWorkingLoader() {
1381
- return new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), this.getWorkingLoaderMessage(), this.workingIndicatorOptions);
1382
+ showStatusIndicator(indicator) {
1383
+ this.activeStatusIndicator?.dispose();
1384
+ this.activeStatusIndicator = indicator;
1385
+ this.statusContainer.clear();
1386
+ this.statusContainer.addChild(indicator);
1382
1387
  }
1383
- stopWorkingLoader() {
1384
- if (this.loadingAnimation) {
1385
- this.loadingAnimation.stop();
1386
- this.loadingAnimation = undefined;
1388
+ clearStatusIndicator(kind) {
1389
+ if (kind && this.activeStatusIndicator?.kind !== kind) {
1390
+ return;
1387
1391
  }
1392
+ const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
1393
+ this.activeStatusIndicator?.dispose();
1394
+ this.activeStatusIndicator = undefined;
1388
1395
  this.statusContainer.clear();
1396
+ if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
1397
+ this.statusContainer.addChild(this.idleStatus);
1398
+ }
1389
1399
  }
1390
1400
  setWorkingVisible(visible) {
1391
1401
  this.workingVisible = visible;
1392
1402
  if (!visible) {
1393
- this.stopWorkingLoader();
1403
+ this.clearStatusIndicator("working");
1394
1404
  this.ui.requestRender();
1395
1405
  return;
1396
1406
  }
1397
- if (this.session.isStreaming && !this.loadingAnimation) {
1398
- this.statusContainer.clear();
1399
- this.loadingAnimation = this.createWorkingLoader();
1400
- this.statusContainer.addChild(this.loadingAnimation);
1407
+ if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
1408
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
1401
1409
  }
1402
1410
  this.ui.requestRender();
1403
1411
  }
1404
1412
  setWorkingIndicator(options) {
1405
1413
  this.workingIndicatorOptions = options;
1406
- this.loadingAnimation?.setIndicator(options);
1414
+ if (this.activeStatusIndicator?.kind === "working") {
1415
+ this.activeStatusIndicator.setIndicator(options);
1416
+ }
1407
1417
  this.ui.requestRender();
1408
1418
  }
1409
1419
  setHiddenThinkingLabel(label) {
@@ -1491,8 +1501,8 @@ export class InteractiveMode {
1491
1501
  this.workingMessage = undefined;
1492
1502
  this.workingVisible = true;
1493
1503
  this.setWorkingIndicator();
1494
- if (this.loadingAnimation) {
1495
- this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
1504
+ if (this.activeStatusIndicator?.kind === "working") {
1505
+ this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
1496
1506
  }
1497
1507
  this.setHiddenThinkingLabel();
1498
1508
  }
@@ -1649,8 +1659,8 @@ export class InteractiveMode {
1649
1659
  setStatus: (key, text) => this.setExtensionStatus(key, text),
1650
1660
  setWorkingMessage: (message) => {
1651
1661
  this.workingMessage = message;
1652
- if (this.loadingAnimation) {
1653
- this.loadingAnimation.setMessage(message ?? this.defaultWorkingMessage);
1662
+ if (this.activeStatusIndicator?.kind === "working") {
1663
+ this.activeStatusIndicator.setMessage(message ?? this.defaultWorkingMessage);
1654
1664
  }
1655
1665
  },
1656
1666
  setWorkingVisible: (visible) => this.setWorkingVisible(visible),
@@ -2270,18 +2280,11 @@ export class InteractiveMode {
2270
2280
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2271
2281
  this.retryEscapeHandler = undefined;
2272
2282
  }
2273
- if (this.retryCountdown) {
2274
- this.retryCountdown.dispose();
2275
- this.retryCountdown = undefined;
2276
- }
2277
- if (this.retryLoader) {
2278
- this.retryLoader.stop();
2279
- this.retryLoader = undefined;
2280
- }
2281
- this.stopWorkingLoader();
2282
2283
  if (this.workingVisible) {
2283
- this.loadingAnimation = this.createWorkingLoader();
2284
- this.statusContainer.addChild(this.loadingAnimation);
2284
+ this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
2285
+ }
2286
+ else {
2287
+ this.clearStatusIndicator();
2285
2288
  }
2286
2289
  this.ui.requestRender();
2287
2290
  break;
@@ -2289,6 +2292,12 @@ export class InteractiveMode {
2289
2292
  this.updatePendingMessagesDisplay();
2290
2293
  this.ui.requestRender();
2291
2294
  break;
2295
+ case "entry_appended":
2296
+ if (event.entry.type === "custom") {
2297
+ this.addCustomEntryToChat(event.entry);
2298
+ this.ui.requestRender();
2299
+ }
2300
+ break;
2292
2301
  case "session_info_changed":
2293
2302
  this.updateTerminalTitle();
2294
2303
  this.footer.invalidate();
@@ -2309,7 +2318,7 @@ export class InteractiveMode {
2309
2318
  this.ui.requestRender();
2310
2319
  }
2311
2320
  else if (event.message.role === "assistant") {
2312
- this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
2321
+ this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
2313
2322
  this.streamingMessage = event.message;
2314
2323
  this.chatContainer.addChild(this.streamingComponent);
2315
2324
  this.streamingComponent.updateContent(this.streamingMessage);
@@ -2417,11 +2426,7 @@ export class InteractiveMode {
2417
2426
  if (this.settingsManager.getShowTerminalProgress()) {
2418
2427
  this.ui.terminal.setProgress(false);
2419
2428
  }
2420
- if (this.loadingAnimation) {
2421
- this.loadingAnimation.stop();
2422
- this.loadingAnimation = undefined;
2423
- this.statusContainer.clear();
2424
- }
2429
+ this.clearStatusIndicator("working");
2425
2430
  if (this.streamingComponent) {
2426
2431
  this.chatContainer.removeChild(this.streamingComponent);
2427
2432
  this.streamingComponent = undefined;
@@ -2440,13 +2445,7 @@ export class InteractiveMode {
2440
2445
  this.defaultEditor.onEscape = () => {
2441
2446
  this.session.abortCompaction();
2442
2447
  };
2443
- this.statusContainer.clear();
2444
- const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
2445
- const label = event.reason === "manual"
2446
- ? `Compacting context... ${cancelHint}`
2447
- : `${event.reason === "overflow" ? "Context overflow detected, " : ""}Auto-compacting... ${cancelHint}`;
2448
- this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
2449
- this.statusContainer.addChild(this.autoCompactionLoader);
2448
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
2450
2449
  this.ui.requestRender();
2451
2450
  break;
2452
2451
  }
@@ -2458,11 +2457,7 @@ export class InteractiveMode {
2458
2457
  this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
2459
2458
  this.autoCompactionEscapeHandler = undefined;
2460
2459
  }
2461
- if (this.autoCompactionLoader) {
2462
- this.autoCompactionLoader.stop();
2463
- this.autoCompactionLoader = undefined;
2464
- this.statusContainer.clear();
2465
- }
2460
+ this.clearStatusIndicator("compaction");
2466
2461
  if (event.aborted) {
2467
2462
  if (event.reason === "manual") {
2468
2463
  this.showError("Compaction cancelled");
@@ -2496,17 +2491,7 @@ export class InteractiveMode {
2496
2491
  this.defaultEditor.onEscape = () => {
2497
2492
  this.session.abortRetry();
2498
2493
  };
2499
- // Show retry indicator
2500
- this.statusContainer.clear();
2501
- this.retryCountdown?.dispose();
2502
- const retryMessage = (seconds) => `Retrying (${event.attempt}/${event.maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;
2503
- this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), retryMessage(Math.ceil(event.delayMs / 1000)));
2504
- this.retryCountdown = new CountdownTimer(event.delayMs, this.ui, (seconds) => {
2505
- this.retryLoader?.setMessage(retryMessage(seconds));
2506
- }, () => {
2507
- this.retryCountdown = undefined;
2508
- });
2509
- this.statusContainer.addChild(this.retryLoader);
2494
+ this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
2510
2495
  this.ui.requestRender();
2511
2496
  break;
2512
2497
  }
@@ -2516,16 +2501,7 @@ export class InteractiveMode {
2516
2501
  this.defaultEditor.onEscape = this.retryEscapeHandler;
2517
2502
  this.retryEscapeHandler = undefined;
2518
2503
  }
2519
- if (this.retryCountdown) {
2520
- this.retryCountdown.dispose();
2521
- this.retryCountdown = undefined;
2522
- }
2523
- // Stop loader
2524
- if (this.retryLoader) {
2525
- this.retryLoader.stop();
2526
- this.retryLoader = undefined;
2527
- this.statusContainer.clear();
2528
- }
2504
+ this.clearStatusIndicator("retry");
2529
2505
  // Show error only on final failure (success shows normal response)
2530
2506
  if (!event.success) {
2531
2507
  this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
@@ -2567,6 +2543,25 @@ export class InteractiveMode {
2567
2543
  this.lastStatusText = text;
2568
2544
  this.ui.requestRender();
2569
2545
  }
2546
+ addCustomEntryToChat(entry) {
2547
+ const renderer = this.session.extensionRunner.getEntryRenderer(entry.customType);
2548
+ if (!renderer) {
2549
+ return;
2550
+ }
2551
+ const component = new CustomEntryComponent(entry, renderer);
2552
+ component.setExpanded(this.toolOutputExpanded);
2553
+ if (!component.hasContent()) {
2554
+ return;
2555
+ }
2556
+ if (this.streamingComponent) {
2557
+ const streamingIndex = this.chatContainer.children.indexOf(this.streamingComponent);
2558
+ if (streamingIndex >= 0) {
2559
+ this.chatContainer.children.splice(streamingIndex, 0, component);
2560
+ return;
2561
+ }
2562
+ }
2563
+ this.chatContainer.addChild(component);
2564
+ }
2570
2565
  addMessageToChat(message, options) {
2571
2566
  switch (message.role) {
2572
2567
  case "bashExecution": {
@@ -2616,12 +2611,12 @@ export class InteractiveMode {
2616
2611
  // Render user message separately if present
2617
2612
  if (skillBlock.userMessage) {
2618
2613
  this.chatContainer.addChild(new Spacer(1));
2619
- const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings());
2614
+ const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
2620
2615
  this.chatContainer.addChild(userComponent);
2621
2616
  }
2622
2617
  }
2623
2618
  else {
2624
- const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings());
2619
+ const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
2625
2620
  this.chatContainer.addChild(userComponent);
2626
2621
  }
2627
2622
  if (options?.populateHistory) {
@@ -2631,7 +2626,7 @@ export class InteractiveMode {
2631
2626
  break;
2632
2627
  }
2633
2628
  case "assistant": {
2634
- const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
2629
+ const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
2635
2630
  this.chatContainer.addChild(assistantComponent);
2636
2631
  break;
2637
2632
  }
@@ -2644,20 +2639,19 @@ export class InteractiveMode {
2644
2639
  }
2645
2640
  }
2646
2641
  }
2647
- /**
2648
- * Render session context to chat. Used for initial load and rebuild after compaction.
2649
- * @param sessionContext Session context to render
2650
- * @param options.updateFooter Update footer state
2651
- * @param options.populateHistory Add user messages to editor history
2652
- */
2653
- renderSessionContext(sessionContext, options = {}) {
2642
+ renderSessionItems(items, options = {}) {
2654
2643
  this.pendingTools.clear();
2655
2644
  const renderedPendingTools = new Map();
2656
2645
  if (options.updateFooter) {
2657
2646
  this.footer.invalidate();
2658
2647
  this.updateEditorBorderColor();
2659
2648
  }
2660
- for (const message of sessionContext.messages) {
2649
+ for (const item of items) {
2650
+ if (isCustomSessionEntry(item)) {
2651
+ this.addCustomEntryToChat(item);
2652
+ continue;
2653
+ }
2654
+ const message = item;
2661
2655
  // Assistant messages need special handling for tool calls
2662
2656
  if (message.role === "assistant") {
2663
2657
  this.addMessageToChat(message);
@@ -2708,10 +2702,24 @@ export class InteractiveMode {
2708
2702
  }
2709
2703
  this.ui.requestRender();
2710
2704
  }
2705
+ /**
2706
+ * Render session entries to chat. Used for initial load and rebuild after compaction.
2707
+ * @param entries Compaction-aware session entries to render
2708
+ * @param options.updateFooter Update footer state
2709
+ * @param options.populateHistory Add user messages to editor history
2710
+ */
2711
+ renderSessionEntries(entries, options = {}) {
2712
+ const items = entries.flatMap((entry) => {
2713
+ if (entry.type === "custom") {
2714
+ return [entry];
2715
+ }
2716
+ return sessionEntryToContextMessages(entry);
2717
+ });
2718
+ this.renderSessionItems(items, options);
2719
+ }
2711
2720
  renderInitialMessages() {
2712
- // Get aligned messages and entries from session context
2713
- const context = this.sessionManager.buildSessionContext();
2714
- this.renderSessionContext(context, {
2721
+ const entries = this.sessionManager.buildContextEntries();
2722
+ this.renderSessionEntries(entries, {
2715
2723
  updateFooter: true,
2716
2724
  populateHistory: true,
2717
2725
  });
@@ -2747,8 +2755,7 @@ export class InteractiveMode {
2747
2755
  }
2748
2756
  rebuildChatFromMessages() {
2749
2757
  this.chatContainer.clear();
2750
- const context = this.sessionManager.buildSessionContext();
2751
- this.renderSessionContext(context);
2758
+ this.renderSessionEntries(this.sessionManager.buildContextEntries());
2752
2759
  }
2753
2760
  // =========================================================================
2754
2761
  // Key handlers
@@ -3349,6 +3356,7 @@ export class InteractiveMode {
3349
3356
  showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
3350
3357
  defaultProjectTrust: this.settingsManager.getDefaultProjectTrust(),
3351
3358
  editorPaddingX: this.settingsManager.getEditorPaddingX(),
3359
+ outputPad: this.settingsManager.getOutputPad(),
3352
3360
  autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
3353
3361
  quietStartup: this.settingsManager.getQuietStartup(),
3354
3362
  clearOnShrink: this.settingsManager.getClearOnShrink(),
@@ -3450,6 +3458,23 @@ export class InteractiveMode {
3450
3458
  this.editor.setPaddingX(padding);
3451
3459
  }
3452
3460
  },
3461
+ onOutputPadChange: (padding) => {
3462
+ this.settingsManager.setOutputPad(padding);
3463
+ this.outputPad = padding;
3464
+ if (this.streamingComponent || this.session.isStreaming) {
3465
+ for (const child of this.chatContainer.children) {
3466
+ if (child instanceof AssistantMessageComponent || child instanceof UserMessageComponent) {
3467
+ child.setOutputPad(padding);
3468
+ }
3469
+ }
3470
+ if (this.streamingComponent) {
3471
+ this.streamingComponent.setOutputPad(padding);
3472
+ }
3473
+ this.ui.requestRender();
3474
+ return;
3475
+ }
3476
+ this.rebuildChatFromMessages();
3477
+ },
3453
3478
  onAutocompleteMaxVisibleChange: (maxVisible) => {
3454
3479
  this.settingsManager.setAutocompleteMaxVisible(maxVisible);
3455
3480
  this.defaultEditor.setAutocompleteMaxVisible(maxVisible);
@@ -3460,6 +3485,9 @@ export class InteractiveMode {
3460
3485
  onClearOnShrinkChange: (enabled) => {
3461
3486
  this.settingsManager.setClearOnShrink(enabled);
3462
3487
  this.ui.setClearOnShrink(enabled);
3488
+ if (!enabled && !this.activeStatusIndicator) {
3489
+ this.statusContainer.clear();
3490
+ }
3463
3491
  },
3464
3492
  onShowTerminalProgressChange: (enabled) => {
3465
3493
  this.settingsManager.setShowTerminalProgress(enabled);
@@ -3777,16 +3805,16 @@ export class InteractiveMode {
3777
3805
  break;
3778
3806
  }
3779
3807
  }
3780
- // Set up escape handler and loader if summarizing
3781
- let summaryLoader;
3808
+ // Set up escape handler and status indicator if summarizing
3809
+ let showingSummaryIndicator = false;
3782
3810
  const originalOnEscape = this.defaultEditor.onEscape;
3783
3811
  if (wantsSummary) {
3784
3812
  this.defaultEditor.onEscape = () => {
3785
3813
  this.session.abortBranchSummary();
3786
3814
  };
3787
3815
  this.chatContainer.addChild(new Spacer(1));
3788
- summaryLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `Summarizing branch... (${keyText("app.interrupt")} to cancel)`);
3789
- this.statusContainer.addChild(summaryLoader);
3816
+ this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
3817
+ showingSummaryIndicator = true;
3790
3818
  this.ui.requestRender();
3791
3819
  }
3792
3820
  try {
@@ -3817,9 +3845,8 @@ export class InteractiveMode {
3817
3845
  this.showError(error instanceof Error ? error.message : String(error));
3818
3846
  }
3819
3847
  finally {
3820
- if (summaryLoader) {
3821
- summaryLoader.stop();
3822
- this.statusContainer.clear();
3848
+ if (showingSummaryIndicator) {
3849
+ this.clearStatusIndicator("branchSummary");
3823
3850
  }
3824
3851
  this.defaultEditor.onEscape = originalOnEscape;
3825
3852
  }
@@ -3860,11 +3887,7 @@ export class InteractiveMode {
3860
3887
  });
3861
3888
  }
3862
3889
  async handleResumeSession(sessionPath, options) {
3863
- if (this.loadingAnimation) {
3864
- this.loadingAnimation.stop();
3865
- this.loadingAnimation = undefined;
3866
- }
3867
- this.statusContainer.clear();
3890
+ this.clearStatusIndicator();
3868
3891
  try {
3869
3892
  const result = await this.runtimeHost.switchSession(sessionPath, {
3870
3893
  withSession: options?.withSession,
@@ -4257,6 +4280,7 @@ export class InteractiveMode {
4257
4280
  return;
4258
4281
  }
4259
4282
  this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
4283
+ this.outputPad = this.settingsManager.getOutputPad();
4260
4284
  this.rebuildChatFromMessages();
4261
4285
  chatRestoredBeforeSessionStart = true;
4262
4286
  };
@@ -4280,7 +4304,11 @@ export class InteractiveMode {
4280
4304
  this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
4281
4305
  }
4282
4306
  this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
4283
- this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
4307
+ const clearOnShrink = this.settingsManager.getClearOnShrink();
4308
+ this.ui.setClearOnShrink(clearOnShrink);
4309
+ if (!clearOnShrink && !this.activeStatusIndicator) {
4310
+ this.statusContainer.clear();
4311
+ }
4284
4312
  this.setupAutocompleteProvider();
4285
4313
  const runner = this.session.extensionRunner;
4286
4314
  this.setupExtensionShortcuts(runner);
@@ -4359,11 +4387,7 @@ export class InteractiveMode {
4359
4387
  return;
4360
4388
  }
4361
4389
  try {
4362
- if (this.loadingAnimation) {
4363
- this.loadingAnimation.stop();
4364
- this.loadingAnimation = undefined;
4365
- }
4366
- this.statusContainer.clear();
4390
+ this.clearStatusIndicator();
4367
4391
  const result = await this.runtimeHost.importFromJsonl(inputPath);
4368
4392
  if (result.cancelled) {
4369
4393
  this.showStatus("Import cancelled");
@@ -4689,11 +4713,7 @@ export class InteractiveMode {
4689
4713
  this.ui.requestRender();
4690
4714
  }
4691
4715
  async handleClearCommand() {
4692
- if (this.loadingAnimation) {
4693
- this.loadingAnimation.stop();
4694
- this.loadingAnimation = undefined;
4695
- }
4696
- this.statusContainer.clear();
4716
+ this.clearStatusIndicator();
4697
4717
  try {
4698
4718
  const result = await this.runtimeHost.newSession();
4699
4719
  if (result.cancelled) {
@@ -4820,11 +4840,7 @@ export class InteractiveMode {
4820
4840
  this.ui.requestRender();
4821
4841
  }
4822
4842
  async handleCompactCommand(customInstructions) {
4823
- if (this.loadingAnimation) {
4824
- this.loadingAnimation.stop();
4825
- this.loadingAnimation = undefined;
4826
- }
4827
- this.statusContainer.clear();
4843
+ this.clearStatusIndicator();
4828
4844
  try {
4829
4845
  await this.session.compact(customInstructions);
4830
4846
  }
@@ -4836,10 +4852,7 @@ export class InteractiveMode {
4836
4852
  if (this.settingsManager.getShowTerminalProgress()) {
4837
4853
  this.ui.terminal.setProgress(false);
4838
4854
  }
4839
- if (this.loadingAnimation) {
4840
- this.loadingAnimation.stop();
4841
- this.loadingAnimation = undefined;
4842
- }
4855
+ this.clearStatusIndicator();
4843
4856
  this.themeController.disableAutoSync();
4844
4857
  this.clearExtensionTerminalInputListeners();
4845
4858
  this.footer.dispose();