@ikie-dev/cli 9.8.1

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 (2522) hide show
  1. package/.envrc +3 -0
  2. package/.github/CODEOWNERS +16 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +85 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  6. package/.github/ISSUE_TEMPLATE/question.yml +16 -0
  7. package/.github/actions/setup/action.yml +49 -0
  8. package/.github/pull_request_template.md +18 -0
  9. package/.github/release.yml +17 -0
  10. package/.github/workflows/acp-e2e.yml +52 -0
  11. package/.github/workflows/arc-terminal-bench-poc.yml +157 -0
  12. package/.github/workflows/auto-label-pr.yml +90 -0
  13. package/.github/workflows/canary.yml +302 -0
  14. package/.github/workflows/ci.yml +114 -0
  15. package/.github/workflows/close-stale.yml +21 -0
  16. package/.github/workflows/release.yml +288 -0
  17. package/.github/workflows/require-linked-issue.yml +21 -0
  18. package/.github/workflows/stale.yml +32 -0
  19. package/.github/workflows/tui-e2e.yml +52 -0
  20. package/.github/workflows/welcome.yml +21 -0
  21. package/.gitmodules +3 -0
  22. package/.husky/pre-commit +1 -0
  23. package/.ikie/ferments/019f2735-088f-75e4-9a8f-7d7b037c2a59/runtime.json +11 -0
  24. package/.ikie/ferments/019f2735-08b3-70fe-88df-8dd1494f6a8e/runtime.json +11 -0
  25. package/.ikie/ferments/019f2735-08d3-7041-8d5e-a153e2937274/runtime.json +11 -0
  26. package/.ikie/ferments/019f2735-08f8-7591-bf1a-6c1324842331/runtime.json +12 -0
  27. package/.ikie/ferments/019f2735-0913-73d5-82b4-37012a5c1148/runtime.json +11 -0
  28. package/.ikie/ferments/019f2735-0940-76dc-b667-964b9cd9294d/runtime.json +11 -0
  29. package/.ikie/ferments/019f2735-0971-7094-92e3-b8ea4cdb9390/runtime.json +15 -0
  30. package/.ikie/ferments/019f2735-0999-72aa-9727-f6e8c3427ed6/runtime.json +15 -0
  31. package/.ikie/ferments/019f2735-09bf-76dd-88a2-c7e574b45636/runtime.json +15 -0
  32. package/.ikie/ferments/019f2735-09f1-77af-8820-89c0b3b5a182/runtime.json +13 -0
  33. package/.ikie/ferments/019f2735-0a49-77d9-b4c7-5a80bbbbafd9/runtime.json +15 -0
  34. package/.ikie/ferments/019f2735-0a79-73c3-977b-0c9164267b94/runtime.json +15 -0
  35. package/.ikie/ferments/019f2735-0abd-70ba-a794-fbb63fbf23de/runtime.json +11 -0
  36. package/.ikie/ferments/019f2735-0ad6-7079-8576-8fb651b4b698/runtime.json +15 -0
  37. package/.ikie/ferments/019f2735-0b03-70db-b5e5-59b1869aa2dc/runtime.json +15 -0
  38. package/.ikie/ferments/019f2735-0b34-7675-a4ed-39a15333e3b8/runtime.json +15 -0
  39. package/.ikie/ferments/019f2735-0b6c-716e-9f92-c391d6acb6f0/runtime.json +15 -0
  40. package/.ikie/ferments/019f2735-0b90-72be-a60d-3dd4c514d1c3/runtime.json +15 -0
  41. package/.ikie/ferments/019f2735-0baf-72e7-b5c5-99d8533b8343/runtime.json +15 -0
  42. package/.ikie/ferments/019f2735-0bd8-70f8-9d83-1a2b9152a013/runtime.json +15 -0
  43. package/.ikie/ferments/019f2735-0bfa-70de-ad20-7fe8c41b968e/runtime.json +15 -0
  44. package/.ikie/ferments/019f2735-0c26-7246-a2ab-f24f5a76fc5f/runtime.json +15 -0
  45. package/.ikie/ferments/019f2735-0c49-771b-934f-4afdb5664666/runtime.json +11 -0
  46. package/.ikie/ferments/019f2735-0c63-73f8-944e-14d19e69ba41/runtime.json +11 -0
  47. package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/reviews/phase-phase-1-1.json +63 -0
  48. package/.ikie/ferments/019f2735-0c80-772b-8530-2df4d15b9d7a/runtime.json +17 -0
  49. package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/reviews/phase-phase-1-1.json +63 -0
  50. package/.ikie/ferments/019f2735-0dfc-7551-b147-aa46815027f5/runtime.json +17 -0
  51. package/.ikie/ferments/019f2735-0f74-70f6-804c-e4d2145b32e1/runtime.json +11 -0
  52. package/.ikie/ferments/019f2735-1354-7041-854e-e6a577467dd0/runtime.json +11 -0
  53. package/.ikie/ferments/019f2735-1371-749f-8ea9-01f7f8734568/runtime.json +11 -0
  54. package/.ikie/ferments/019f2735-138f-72f2-ba7b-7912ad4cd7b9/runtime.json +11 -0
  55. package/.ikie/ferments/019f2735-13ad-710a-9c4d-38a30a0f4b37/runtime.json +11 -0
  56. package/.ikie/ferments/019f2735-13cb-7698-88c1-890fba497dc0/pending-proposal.json +45 -0
  57. package/.ikie/ferments/019f2735-13da-77dd-a916-8d82348671d2/pending-proposal.json +45 -0
  58. package/.ikie/ferments/019f2735-14d3-727a-81db-347c03cb2919/pending-proposal.json +45 -0
  59. package/.ikie/ferments/019f2735-1521-736e-8b75-22e94a8775f7/pending-proposal.json +45 -0
  60. package/.ikie/ferments/019f2735-1542-777c-a3a7-bc7f1edf1922/pending-proposal.json +45 -0
  61. package/.ikie/ferments/019f2735-3528-75bc-b100-8deb63dfde55/runtime.json +13 -0
  62. package/.ikie/ferments/019f2735-3553-72d8-a60d-9357420e110a/runtime.json +11 -0
  63. package/.ikie/ferments/019f2735-3569-756b-bc90-01c9ab00e413/runtime.json +11 -0
  64. package/.ikie/ferments/019f2735-3583-71d0-83f9-fc40b292190b/runtime.json +11 -0
  65. package/.ikie/ferments/019f2735-3597-7571-8332-47b3443395a6/runtime.json +11 -0
  66. package/.ikie/ferments/019f2735-35b3-74fe-a5db-82651a97cf0d/runtime.json +11 -0
  67. package/.ikie/ferments/019f2735-35de-741a-94e7-7b89c4eaaa43/runtime.json +11 -0
  68. package/.ikie/ferments/019f2735-35f5-713c-9892-f6179e783d02/runtime.json +11 -0
  69. package/.ikie/ferments/019f2735-360d-7056-a5e0-43fb3eb0f98e/runtime.json +9 -0
  70. package/.ikie/ferments/019f2735-362e-756c-b848-34f3c3c4602b/runtime.json +13 -0
  71. package/.ikie/ferments/019f2735-364a-76f9-bfba-ba52ca3852fd/runtime.json +11 -0
  72. package/.ikie/ferments/019f2735-3662-754c-8a88-807a68e0790e/runtime.json +11 -0
  73. package/.ikie/ferments/019f2735-36c2-71f9-a003-2921a1792be1/runtime.json +11 -0
  74. package/.ikie/ferments/019f2735-36d6-751d-9776-1e1def988d2d/runtime.json +9 -0
  75. package/.ikie/ferments/019f2735-36ef-70bf-a6b2-f2a0944f1b7e/runtime.json +9 -0
  76. package/.ikie/ferments/019f2735-3712-77e3-a46e-c69470e4e850/runtime.json +11 -0
  77. package/.ikie/ferments/019f2735-37cf-712f-bfaa-8fc9e29da513/runtime.json +11 -0
  78. package/.ikie/ferments/019f2735-37ed-727a-8a74-fe716d22571d/runtime.json +12 -0
  79. package/.ikie/ferments/019f2735-3810-7370-b587-eef0bb9d4d81/runtime.json +11 -0
  80. package/.ikie/ferments/019f2735-3828-71ad-9ee9-62fa0f46cad7/runtime.json +11 -0
  81. package/.ikie/ferments/019f2735-383f-722b-8d96-5038b9c9aa5a/runtime.json +11 -0
  82. package/.ikie/ferments/019f2735-385a-72c8-b269-a87a416c5a10/runtime.json +11 -0
  83. package/.ikie/ferments/019f2735-386d-73fe-be0a-1bc89a0264c4/runtime.json +13 -0
  84. package/.ikie/ferments/019f2735-388a-7276-9bee-81dcd177953f/runtime.json +11 -0
  85. package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/reviews/phase-phase-1-1.json +41 -0
  86. package/.ikie/ferments/019f2735-82ed-74e8-870d-d8678feaf7bb/runtime.json +11 -0
  87. package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/reviews/phase-phase-1-1.json +47 -0
  88. package/.ikie/ferments/019f2735-831e-70aa-b9d6-1214165775d0/runtime.json +13 -0
  89. package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/reviews/phase-phase-1-1.json +40 -0
  90. package/.ikie/ferments/019f2735-835e-73b3-bb48-2d0080526fc3/runtime.json +9 -0
  91. package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/reviews/phase-phase-1-1.json +40 -0
  92. package/.ikie/ferments/019f2735-8379-74b6-b62f-816bb5276a85/runtime.json +9 -0
  93. package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/reviews/phase-phase-1-1.json +40 -0
  94. package/.ikie/ferments/019f2735-8391-7385-bab6-03362866622a/runtime.json +9 -0
  95. package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/reviews/phase-phase-1-1.json +40 -0
  96. package/.ikie/ferments/019f2735-83ad-7251-8280-aa6f7f3bfc5e/runtime.json +9 -0
  97. package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/reviews/phase-phase-1-1.json +40 -0
  98. package/.ikie/ferments/019f2735-83d2-77be-984e-fb65263a3a5b/runtime.json +9 -0
  99. package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/reviews/phase-phase-1-1.json +62 -0
  100. package/.ikie/ferments/019f2735-83ec-7743-acc5-b2bf14c3cc54/runtime.json +9 -0
  101. package/.ikie/ferments/019f2740-c8c5-720f-b641-214bb99d8a83/runtime.json +11 -0
  102. package/.ikie/ferments/019f2740-c8fb-763f-8310-88c7e558e410/runtime.json +11 -0
  103. package/.ikie/ferments/019f2740-c917-70d2-8be6-15f376c60a70/runtime.json +11 -0
  104. package/.ikie/ferments/019f2740-c984-711f-a903-4b2251918413/runtime.json +12 -0
  105. package/.ikie/ferments/019f2740-ca09-71cf-93a5-86efc136ecd5/runtime.json +11 -0
  106. package/.ikie/ferments/019f2740-ca46-77f4-ae02-88e42f2153fb/runtime.json +15 -0
  107. package/.ikie/ferments/019f2740-ca74-72dd-8855-3feedfa071db/runtime.json +15 -0
  108. package/.ikie/ferments/019f2740-ca9a-710b-9bb7-feffa42cdb36/runtime.json +15 -0
  109. package/.ikie/ferments/019f2740-cac9-7518-ae93-973e4cf364ce/runtime.json +13 -0
  110. package/.ikie/ferments/019f2740-cb04-71c1-83a7-a448fefc6764/runtime.json +15 -0
  111. package/.ikie/ferments/019f2740-cb35-743b-bc18-434c7c233a08/runtime.json +15 -0
  112. package/.ikie/ferments/019f2740-cb6e-742c-970b-1893b4bf4e87/runtime.json +11 -0
  113. package/.ikie/ferments/019f2740-cb92-76a7-bd20-fd4f3f17664f/runtime.json +15 -0
  114. package/.ikie/ferments/019f2740-cbc1-7509-8542-302d2d1d3084/runtime.json +15 -0
  115. package/.ikie/ferments/019f2740-cbfa-719d-94c0-9d03a864e7e1/runtime.json +15 -0
  116. package/.ikie/ferments/019f2740-cc31-75f8-82a0-7d8078979000/runtime.json +15 -0
  117. package/.ikie/ferments/019f2740-cc58-765b-9f0c-c3aa2e09f27b/runtime.json +15 -0
  118. package/.ikie/ferments/019f2740-cc7c-7375-99b4-e90496e819e3/runtime.json +15 -0
  119. package/.ikie/ferments/019f2740-cca3-704a-bc20-e8c35cff6cec/runtime.json +15 -0
  120. package/.ikie/ferments/019f2740-ccd1-71cf-b8e8-be3527117f9a/runtime.json +15 -0
  121. package/.ikie/ferments/019f2740-cd0c-771f-ba4a-9188c31f3ee4/runtime.json +15 -0
  122. package/.ikie/ferments/019f2740-cd39-778e-a052-cc7f522f022d/runtime.json +11 -0
  123. package/.ikie/ferments/019f2740-cd5f-725e-8ec7-48a624398d2f/runtime.json +11 -0
  124. package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/reviews/phase-phase-1-1.json +63 -0
  125. package/.ikie/ferments/019f2740-cd7f-713e-b20f-2321c13a86a8/runtime.json +17 -0
  126. package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/reviews/phase-phase-1-1.json +63 -0
  127. package/.ikie/ferments/019f2740-cf49-72fc-94b1-a262676c1136/runtime.json +17 -0
  128. package/.ikie/ferments/019f2740-d16a-763d-b668-7c7cebc74c16/runtime.json +11 -0
  129. package/.ikie/ferments/019f2740-d675-747d-aa4c-b60d1616d218/runtime.json +11 -0
  130. package/.ikie/ferments/019f2740-d6ad-72de-bab7-e6344d568636/runtime.json +11 -0
  131. package/.ikie/ferments/019f2740-d6db-751a-bf3b-09d1c7ba989b/runtime.json +11 -0
  132. package/.ikie/ferments/019f2740-d712-75c8-b209-efc11bb1a22a/runtime.json +11 -0
  133. package/.ikie/ferments/019f2740-d745-764f-b758-99b0df2d6c01/pending-proposal.json +45 -0
  134. package/.ikie/ferments/019f2740-d76b-74a8-94c1-3d0cabd8cacf/pending-proposal.json +45 -0
  135. package/.ikie/ferments/019f2740-d88d-722b-8265-c8b89e1e59db/pending-proposal.json +45 -0
  136. package/.ikie/ferments/019f2740-d8f6-756a-b704-8a64a28290e8/pending-proposal.json +45 -0
  137. package/.ikie/ferments/019f2740-d90b-730f-87b9-85bee8e00a55/pending-proposal.json +45 -0
  138. package/.ikie/ferments/019f2740-f11f-76ff-9bd0-1e449804cc12/runtime.json +13 -0
  139. package/.ikie/ferments/019f2740-f155-767e-96db-6cf60c8b8dc1/runtime.json +11 -0
  140. package/.ikie/ferments/019f2740-f172-755f-a741-8e55858f5362/runtime.json +11 -0
  141. package/.ikie/ferments/019f2740-f18f-7328-b679-49f91b3c558c/runtime.json +11 -0
  142. package/.ikie/ferments/019f2740-f1b4-7289-b2f3-46f2bedf0e8f/runtime.json +11 -0
  143. package/.ikie/ferments/019f2740-f1dc-769b-bfe1-abcbcfd8ff2f/runtime.json +11 -0
  144. package/.ikie/ferments/019f2740-f1ed-760b-91dc-3bf7950fc112/runtime.json +11 -0
  145. package/.ikie/ferments/019f2740-f1fd-72dd-9c40-e6ab17b819ef/runtime.json +11 -0
  146. package/.ikie/ferments/019f2740-f23d-7588-95af-66be8cae9529/runtime.json +9 -0
  147. package/.ikie/ferments/019f2740-f269-7334-9c82-6554d9fc595a/runtime.json +13 -0
  148. package/.ikie/ferments/019f2740-f2bf-7147-9e68-cd8cb74d1604/runtime.json +11 -0
  149. package/.ikie/ferments/019f2740-f2f3-73db-9542-23a91c3632e5/runtime.json +11 -0
  150. package/.ikie/ferments/019f2740-f387-77e6-99f2-7cabb6f1ef37/runtime.json +11 -0
  151. package/.ikie/ferments/019f2740-f3af-722d-92a8-b49ab2e974fd/runtime.json +9 -0
  152. package/.ikie/ferments/019f2740-f3e6-7142-870c-ec1ee626cef4/runtime.json +9 -0
  153. package/.ikie/ferments/019f2740-f408-74f3-b1a2-3187af4e7bf8/runtime.json +11 -0
  154. package/.ikie/ferments/019f2740-f535-7419-8dc5-3c00bfeb566e/runtime.json +11 -0
  155. package/.ikie/ferments/019f2740-f546-7749-b0bd-cc0ec724f9c4/runtime.json +12 -0
  156. package/.ikie/ferments/019f2740-f576-7649-a468-cc473a719123/runtime.json +11 -0
  157. package/.ikie/ferments/019f2740-f599-7239-aa50-4bde87b6fe17/runtime.json +11 -0
  158. package/.ikie/ferments/019f2740-f5b8-7236-9b88-a0abe214d6b6/runtime.json +11 -0
  159. package/.ikie/ferments/019f2740-f5d1-73fc-9eea-06cf527069f2/runtime.json +11 -0
  160. package/.ikie/ferments/019f2740-f5fb-757e-b89e-52aeb00d53a0/runtime.json +13 -0
  161. package/.ikie/ferments/019f2740-f616-7770-96df-c4d02e293b96/runtime.json +11 -0
  162. package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/reviews/phase-phase-1-1.json +41 -0
  163. package/.ikie/ferments/019f2741-09b2-777a-960c-544786151af2/runtime.json +11 -0
  164. package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/reviews/phase-phase-1-1.json +47 -0
  165. package/.ikie/ferments/019f2741-0a0a-735a-b158-6a1f99b53082/runtime.json +13 -0
  166. package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/reviews/phase-phase-1-1.json +40 -0
  167. package/.ikie/ferments/019f2741-0a87-74ec-bcb1-e88127e8739b/runtime.json +9 -0
  168. package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/reviews/phase-phase-1-1.json +40 -0
  169. package/.ikie/ferments/019f2741-0aaa-7399-905b-0c8f62000e15/runtime.json +9 -0
  170. package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/reviews/phase-phase-1-1.json +40 -0
  171. package/.ikie/ferments/019f2741-0acc-7062-86e9-0d2d365446d9/runtime.json +9 -0
  172. package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/reviews/phase-phase-1-1.json +40 -0
  173. package/.ikie/ferments/019f2741-0b14-709e-a5aa-80efb5a3c7d7/runtime.json +9 -0
  174. package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/reviews/phase-phase-1-1.json +40 -0
  175. package/.ikie/ferments/019f2741-0b3d-77ed-bdd9-322103b094e2/runtime.json +9 -0
  176. package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/reviews/phase-phase-1-1.json +62 -0
  177. package/.ikie/ferments/019f2741-0b7b-70ab-b3d6-ada61a3e0a92/runtime.json +9 -0
  178. package/.ikie/ferments/019f2742-b177-74a8-90f2-c1130a6ddae7/runtime.json +11 -0
  179. package/.ikie/ferments/019f2742-b193-72cf-9826-86ede671e061/runtime.json +11 -0
  180. package/.ikie/ferments/019f2742-b1af-76d9-972c-b67a2f5854d1/runtime.json +11 -0
  181. package/.ikie/ferments/019f2742-b1de-763e-8e31-a14505f9b64d/runtime.json +12 -0
  182. package/.ikie/ferments/019f2742-b25b-71fe-81de-89fc3b431b39/runtime.json +11 -0
  183. package/.ikie/ferments/019f2742-b291-7078-ba58-d4b50df3dd81/runtime.json +15 -0
  184. package/.ikie/ferments/019f2742-b2db-71a8-9d5d-da4bccc3e572/runtime.json +15 -0
  185. package/.ikie/ferments/019f2742-b305-7323-86c6-39adaa181f18/runtime.json +15 -0
  186. package/.ikie/ferments/019f2742-b330-77ad-9315-8ca801c973e8/runtime.json +13 -0
  187. package/.ikie/ferments/019f2742-b377-703f-9781-394729f9fe89/runtime.json +15 -0
  188. package/.ikie/ferments/019f2742-b3af-75aa-9bb7-750cb6af56e4/runtime.json +15 -0
  189. package/.ikie/ferments/019f2742-b3fb-7159-a969-be0073f90b6d/runtime.json +11 -0
  190. package/.ikie/ferments/019f2742-b41a-730e-ae6e-89421276e69d/runtime.json +15 -0
  191. package/.ikie/ferments/019f2742-b44e-75ec-824c-f6b77f643438/runtime.json +15 -0
  192. package/.ikie/ferments/019f2742-b47d-70c6-af2f-04922c1aef02/runtime.json +15 -0
  193. package/.ikie/ferments/019f2742-b4ad-748b-86db-3c8ae8907dbc/runtime.json +15 -0
  194. package/.ikie/ferments/019f2742-b4d5-72ff-a1b0-0da356ab94e6/runtime.json +15 -0
  195. package/.ikie/ferments/019f2742-b508-71fd-8181-7bb013178e5e/runtime.json +15 -0
  196. package/.ikie/ferments/019f2742-b536-7129-8b5c-2e132b38a98e/runtime.json +15 -0
  197. package/.ikie/ferments/019f2742-b55d-738b-8663-88a05c1e44b5/runtime.json +15 -0
  198. package/.ikie/ferments/019f2742-b587-714c-b043-f0a553a22404/runtime.json +15 -0
  199. package/.ikie/ferments/019f2742-b5b5-74ff-a850-a24ff317c1df/runtime.json +11 -0
  200. package/.ikie/ferments/019f2742-b5f5-72ba-b6b8-a4d62df39a2c/runtime.json +11 -0
  201. package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/reviews/phase-phase-1-1.json +63 -0
  202. package/.ikie/ferments/019f2742-b621-7530-8e63-d252ae47ffd6/runtime.json +17 -0
  203. package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/reviews/phase-phase-1-1.json +63 -0
  204. package/.ikie/ferments/019f2742-b7c0-756d-8014-e96fec9713ee/runtime.json +17 -0
  205. package/.ikie/ferments/019f2742-b95b-76bb-a4a6-e5cc31788fe3/runtime.json +11 -0
  206. package/.ikie/ferments/019f2742-be6b-759b-ba34-29d0245dc929/runtime.json +11 -0
  207. package/.ikie/ferments/019f2742-be98-73ba-aac5-07ad4f7d887d/runtime.json +11 -0
  208. package/.ikie/ferments/019f2742-beba-703c-aadb-32c590404bfa/runtime.json +11 -0
  209. package/.ikie/ferments/019f2742-bee0-76ad-9e47-81cff634877f/runtime.json +11 -0
  210. package/.ikie/ferments/019f2742-bf10-742f-a792-7aa3836d81ad/pending-proposal.json +45 -0
  211. package/.ikie/ferments/019f2742-bf36-779c-b126-2ccb8ec97138/pending-proposal.json +45 -0
  212. package/.ikie/ferments/019f2742-c098-74ee-9a07-575f50989d9f/pending-proposal.json +45 -0
  213. package/.ikie/ferments/019f2742-c135-74fe-aefa-d1a5db536132/pending-proposal.json +45 -0
  214. package/.ikie/ferments/019f2742-c19a-779c-a175-27330932470d/pending-proposal.json +45 -0
  215. package/.ikie/ferments/019f2742-db2a-745f-b7c8-8fb383e044e7/runtime.json +13 -0
  216. package/.ikie/ferments/019f2742-db83-77ac-b1d2-a422571fbcf6/runtime.json +11 -0
  217. package/.ikie/ferments/019f2742-dba7-779e-9560-7df90ddab3c4/runtime.json +11 -0
  218. package/.ikie/ferments/019f2742-dbd2-740c-9f94-9f313c07ee52/runtime.json +11 -0
  219. package/.ikie/ferments/019f2742-dbfb-77b3-8e3f-b0d20bd29689/runtime.json +11 -0
  220. package/.ikie/ferments/019f2742-dc10-769d-b9a2-bab4851f5cf5/runtime.json +11 -0
  221. package/.ikie/ferments/019f2742-dc23-7235-a215-8b86d261566a/runtime.json +11 -0
  222. package/.ikie/ferments/019f2742-dc37-762d-a5da-87ff3f2206b0/runtime.json +11 -0
  223. package/.ikie/ferments/019f2742-dc65-73c8-aa07-f803b1066c8b/runtime.json +9 -0
  224. package/.ikie/ferments/019f2742-dc91-7165-bbfe-4659f754c4a6/runtime.json +13 -0
  225. package/.ikie/ferments/019f2742-dcd1-7252-ad9b-12c0dab633e6/runtime.json +11 -0
  226. package/.ikie/ferments/019f2742-dceb-75ba-b8cb-557e60aa4a9b/runtime.json +11 -0
  227. package/.ikie/ferments/019f2742-dd2f-77a6-b71c-a9543ac1145f/runtime.json +11 -0
  228. package/.ikie/ferments/019f2742-dd6a-70ab-aff3-ae678e8be52f/runtime.json +9 -0
  229. package/.ikie/ferments/019f2742-dd85-7529-90c0-2cb497df7711/runtime.json +9 -0
  230. package/.ikie/ferments/019f2742-dda0-715e-ae24-693bfa79f191/runtime.json +11 -0
  231. package/.ikie/ferments/019f2742-deb9-7319-9599-d96743413a8c/runtime.json +11 -0
  232. package/.ikie/ferments/019f2742-dee3-705e-9550-b7701bc8dfbf/runtime.json +12 -0
  233. package/.ikie/ferments/019f2742-df10-71bf-8ac0-8e4a8c40cfa8/runtime.json +11 -0
  234. package/.ikie/ferments/019f2742-df29-735f-817c-2819becd5092/runtime.json +11 -0
  235. package/.ikie/ferments/019f2742-df46-7592-b070-7bdf50095ce2/runtime.json +11 -0
  236. package/.ikie/ferments/019f2742-df66-75e4-9926-4d5dacd457f4/runtime.json +11 -0
  237. package/.ikie/ferments/019f2742-df96-71c4-973e-045dc4f272e0/runtime.json +13 -0
  238. package/.ikie/ferments/019f2742-dfca-7353-bfd3-f010ec0726e8/runtime.json +11 -0
  239. package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/reviews/phase-phase-1-1.json +41 -0
  240. package/.ikie/ferments/019f2742-f0fb-77cb-9a95-25a7231702b7/runtime.json +11 -0
  241. package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/reviews/phase-phase-1-1.json +47 -0
  242. package/.ikie/ferments/019f2742-f145-77ec-a4c7-fafd1605d492/runtime.json +13 -0
  243. package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/reviews/phase-phase-1-1.json +40 -0
  244. package/.ikie/ferments/019f2742-f1dc-74bd-8452-067d9c1b909d/runtime.json +9 -0
  245. package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/reviews/phase-phase-1-1.json +40 -0
  246. package/.ikie/ferments/019f2742-f1fd-745d-b989-9a2d3ec7594d/runtime.json +9 -0
  247. package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/reviews/phase-phase-1-1.json +40 -0
  248. package/.ikie/ferments/019f2742-f21a-7398-9190-8bba01c6248e/runtime.json +9 -0
  249. package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/reviews/phase-phase-1-1.json +40 -0
  250. package/.ikie/ferments/019f2742-f23a-73b1-89d2-1272093e6d2d/runtime.json +9 -0
  251. package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/reviews/phase-phase-1-1.json +40 -0
  252. package/.ikie/ferments/019f2742-f25c-74d1-80b3-129a992edd3f/runtime.json +9 -0
  253. package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/reviews/phase-phase-1-1.json +62 -0
  254. package/.ikie/ferments/019f2742-f285-708d-bdd2-c2875cc16158/runtime.json +9 -0
  255. package/.ikie/ferments/019f2745-3a6e-7769-8da0-1994b591349d/runtime.json +11 -0
  256. package/.ikie/ferments/019f2745-3a8c-74db-bd6b-b4a1164b381a/runtime.json +11 -0
  257. package/.ikie/ferments/019f2745-3aad-7249-b742-f1e6722d5c97/runtime.json +11 -0
  258. package/.ikie/ferments/019f2745-3ae9-76fb-861c-49f13c1db883/runtime.json +12 -0
  259. package/.ikie/ferments/019f2745-3b16-721b-b523-469846e0c9e5/runtime.json +11 -0
  260. package/.ikie/ferments/019f2745-3b53-7119-ae88-20cf3d567e91/runtime.json +11 -0
  261. package/.ikie/ferments/019f2745-3ba2-71b6-9fab-faaf750f8535/runtime.json +15 -0
  262. package/.ikie/ferments/019f2745-3bed-764b-9b4b-79b4d7daa35d/runtime.json +15 -0
  263. package/.ikie/ferments/019f2745-3c3e-7792-8df7-d88bab7aa48d/runtime.json +15 -0
  264. package/.ikie/ferments/019f2745-3c81-770d-bcf9-6d163ffeb285/runtime.json +13 -0
  265. package/.ikie/ferments/019f2745-3cca-748d-9740-8c55644c9afa/runtime.json +15 -0
  266. package/.ikie/ferments/019f2745-3d12-71cc-923f-520142ddf544/runtime.json +15 -0
  267. package/.ikie/ferments/019f2745-3d79-7083-8865-8f54989080e0/runtime.json +11 -0
  268. package/.ikie/ferments/019f2745-3da9-74f9-a640-86b4685f40a0/runtime.json +15 -0
  269. package/.ikie/ferments/019f2745-3ddf-721b-8a40-3a2318b6bc0a/runtime.json +15 -0
  270. package/.ikie/ferments/019f2745-3e2a-76a8-8c61-ef15db41aef2/runtime.json +15 -0
  271. package/.ikie/ferments/019f2745-3e5d-75bb-ab71-b4aa83c491b7/runtime.json +15 -0
  272. package/.ikie/ferments/019f2745-3e7e-7437-848a-100463c72f90/runtime.json +15 -0
  273. package/.ikie/ferments/019f2745-3ea7-7729-9000-7874145f4bb5/runtime.json +15 -0
  274. package/.ikie/ferments/019f2745-3ecf-760c-931c-3dc5996b06b1/runtime.json +15 -0
  275. package/.ikie/ferments/019f2745-3f05-72d8-ad71-d1df02c5939a/runtime.json +15 -0
  276. package/.ikie/ferments/019f2745-3f37-74ad-9e02-6e0d3854b664/runtime.json +15 -0
  277. package/.ikie/ferments/019f2745-3f65-740d-8094-58f60c9cdcec/runtime.json +11 -0
  278. package/.ikie/ferments/019f2745-3f91-7219-8eec-f5f7873a434a/runtime.json +11 -0
  279. package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/reviews/phase-phase-1-1.json +63 -0
  280. package/.ikie/ferments/019f2745-3fc5-706a-8188-5a3b4e13a796/runtime.json +17 -0
  281. package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/reviews/phase-phase-1-1.json +63 -0
  282. package/.ikie/ferments/019f2745-417c-77ad-bdaf-380b81846577/runtime.json +17 -0
  283. package/.ikie/ferments/019f2745-4372-72ff-a50c-3eaad36a726b/runtime.json +11 -0
  284. package/.ikie/ferments/019f2745-4859-714b-a8b7-0a82d35b87c7/runtime.json +11 -0
  285. package/.ikie/ferments/019f2745-488a-724f-91a9-d621e9f2b3f7/runtime.json +11 -0
  286. package/.ikie/ferments/019f2745-48ae-7741-8598-03ede47b4594/runtime.json +11 -0
  287. package/.ikie/ferments/019f2745-48e9-710f-889b-e88aa5d7e60e/runtime.json +11 -0
  288. package/.ikie/ferments/019f2745-4917-7268-9b76-f8bb1215ea19/pending-proposal.json +45 -0
  289. package/.ikie/ferments/019f2745-493c-775d-a10d-4a2cf8305a4e/pending-proposal.json +45 -0
  290. package/.ikie/ferments/019f2745-4abd-7319-9e11-4b348ab24547/pending-proposal.json +45 -0
  291. package/.ikie/ferments/019f2745-4b10-726d-ad1f-c086e7d4dfc0/pending-proposal.json +45 -0
  292. package/.ikie/ferments/019f2745-4b21-75a6-b151-472f4eb9b95d/pending-proposal.json +45 -0
  293. package/.ikie/ferments/019f2745-5dd5-741b-85e2-1d67ce09a138/runtime.json +13 -0
  294. package/.ikie/ferments/019f2745-5e14-73dd-bd03-3b5765f70fac/runtime.json +11 -0
  295. package/.ikie/ferments/019f2745-5e2e-70b5-9348-35ebbdb8ec8e/runtime.json +11 -0
  296. package/.ikie/ferments/019f2745-5e4f-7626-b075-6b6d30099847/runtime.json +11 -0
  297. package/.ikie/ferments/019f2745-5e71-7768-b436-e739555f1038/runtime.json +11 -0
  298. package/.ikie/ferments/019f2745-5e8a-77c5-ba98-cb2802c55266/runtime.json +11 -0
  299. package/.ikie/ferments/019f2745-5ea8-707f-b034-9c98e6ca720b/runtime.json +11 -0
  300. package/.ikie/ferments/019f2745-5ebd-73aa-a919-150c9bb014f9/runtime.json +11 -0
  301. package/.ikie/ferments/019f2745-5ed6-71e9-9a20-360fa807f598/runtime.json +9 -0
  302. package/.ikie/ferments/019f2745-5ef8-7199-bd13-69b5c883541b/runtime.json +13 -0
  303. package/.ikie/ferments/019f2745-5f30-73f9-a647-9e7518599c32/runtime.json +11 -0
  304. package/.ikie/ferments/019f2745-5f53-7358-897a-37717d64d996/runtime.json +11 -0
  305. package/.ikie/ferments/019f2745-5fb6-736b-b42d-bbc3c1916321/runtime.json +11 -0
  306. package/.ikie/ferments/019f2745-5fea-730e-b57b-d7f1965d5934/runtime.json +9 -0
  307. package/.ikie/ferments/019f2745-6014-77cb-b01f-d93baf8af409/runtime.json +9 -0
  308. package/.ikie/ferments/019f2745-602f-74b9-8eed-bb29fa4a76d4/runtime.json +11 -0
  309. package/.ikie/ferments/019f2745-60e2-7562-8e7c-2ded6cf75426/runtime.json +11 -0
  310. package/.ikie/ferments/019f2745-6114-703e-ac05-5ba11b255b62/runtime.json +12 -0
  311. package/.ikie/ferments/019f2745-6160-733e-93f5-df586c6afc0a/runtime.json +11 -0
  312. package/.ikie/ferments/019f2745-6179-702b-84fb-09bc60f8c04c/runtime.json +11 -0
  313. package/.ikie/ferments/019f2745-618d-74dc-a174-28a134d353fa/runtime.json +11 -0
  314. package/.ikie/ferments/019f2745-619e-72a8-8377-34127bfc774f/runtime.json +11 -0
  315. package/.ikie/ferments/019f2745-61ae-767e-8a2e-a5ca6bc84a88/runtime.json +13 -0
  316. package/.ikie/ferments/019f2745-61c7-760c-9914-a9bf3c96acd8/runtime.json +11 -0
  317. package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/reviews/phase-phase-1-1.json +41 -0
  318. package/.ikie/ferments/019f2745-79a2-70b8-bcd0-fbaee13849db/runtime.json +11 -0
  319. package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/reviews/phase-phase-1-1.json +47 -0
  320. package/.ikie/ferments/019f2745-79e7-74d5-b867-e23b027a8512/runtime.json +13 -0
  321. package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/reviews/phase-phase-1-1.json +40 -0
  322. package/.ikie/ferments/019f2745-7a5b-703e-999e-dd5cb98133eb/runtime.json +9 -0
  323. package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/reviews/phase-phase-1-1.json +40 -0
  324. package/.ikie/ferments/019f2745-7a90-732a-b09a-9aa29e2390cd/runtime.json +9 -0
  325. package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/reviews/phase-phase-1-1.json +40 -0
  326. package/.ikie/ferments/019f2745-7aad-731c-ac2a-cf71d20fb709/runtime.json +9 -0
  327. package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/reviews/phase-phase-1-1.json +40 -0
  328. package/.ikie/ferments/019f2745-7ad2-70ff-986b-83679208066a/runtime.json +9 -0
  329. package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/reviews/phase-phase-1-1.json +40 -0
  330. package/.ikie/ferments/019f2745-7af8-735c-8200-f49b201f5b7f/runtime.json +9 -0
  331. package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/reviews/phase-phase-1-1.json +62 -0
  332. package/.ikie/ferments/019f2745-7b17-7489-b4d5-b83e4feeb641/runtime.json +9 -0
  333. package/.ikie/ferments/019f2747-700f-77dd-8fec-eec70eb204bf/runtime.json +11 -0
  334. package/.ikie/ferments/019f2747-702b-748d-83a8-a44d909b5d84/runtime.json +11 -0
  335. package/.ikie/ferments/019f2747-704a-77c6-a068-5eff8527f149/runtime.json +11 -0
  336. package/.ikie/ferments/019f2747-7075-7628-9088-9c79d85087be/runtime.json +12 -0
  337. package/.ikie/ferments/019f2747-70e4-7157-aa37-d8201f07134a/runtime.json +11 -0
  338. package/.ikie/ferments/019f2747-7139-74da-8f85-02b76ecfc932/runtime.json +15 -0
  339. package/.ikie/ferments/019f2747-7156-762f-8c31-84ae357e2edd/runtime.json +15 -0
  340. package/.ikie/ferments/019f2747-7175-76e7-9d21-15608a6463ca/runtime.json +15 -0
  341. package/.ikie/ferments/019f2747-71c8-777c-8106-df11073ad85f/runtime.json +13 -0
  342. package/.ikie/ferments/019f2747-7209-71f5-8f4e-ccfd46653321/runtime.json +15 -0
  343. package/.ikie/ferments/019f2747-723d-728f-baa8-dd3b4b239037/runtime.json +15 -0
  344. package/.ikie/ferments/019f2747-728d-749b-9e9a-962ea824d13d/runtime.json +11 -0
  345. package/.ikie/ferments/019f2747-72b0-756e-b648-c5491d46dc37/runtime.json +15 -0
  346. package/.ikie/ferments/019f2747-72e8-747e-9e5b-93005dd51d36/runtime.json +15 -0
  347. package/.ikie/ferments/019f2747-7319-702b-84bd-aed70c3f60c3/runtime.json +15 -0
  348. package/.ikie/ferments/019f2747-734a-732c-89d8-47fa74a13f6b/runtime.json +15 -0
  349. package/.ikie/ferments/019f2747-7372-72ce-99d0-ddeeb20c73e5/runtime.json +15 -0
  350. package/.ikie/ferments/019f2747-73a1-723d-b064-2240965b5460/runtime.json +15 -0
  351. package/.ikie/ferments/019f2747-73cd-71b5-9b21-481224573278/runtime.json +15 -0
  352. package/.ikie/ferments/019f2747-73f7-779f-a227-64ba479c2615/runtime.json +15 -0
  353. package/.ikie/ferments/019f2747-743e-759e-856b-283e346eec66/runtime.json +15 -0
  354. package/.ikie/ferments/019f2747-74ac-702b-877f-1b4447f77938/runtime.json +11 -0
  355. package/.ikie/ferments/019f2747-74cc-773a-ad3a-febf5e9e5a57/runtime.json +11 -0
  356. package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/reviews/phase-phase-1-1.json +63 -0
  357. package/.ikie/ferments/019f2747-750b-77dc-aa24-230eef901e40/runtime.json +17 -0
  358. package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/reviews/phase-phase-1-1.json +63 -0
  359. package/.ikie/ferments/019f2747-76f2-72c9-8764-82fdd0429215/runtime.json +17 -0
  360. package/.ikie/ferments/019f2747-795d-7452-9810-a64e86f3d5c5/runtime.json +11 -0
  361. package/.ikie/ferments/019f2747-7ee1-770e-ace1-bc0f5571f69a/runtime.json +11 -0
  362. package/.ikie/ferments/019f2747-7f01-738d-a2a2-c7aa33365582/runtime.json +11 -0
  363. package/.ikie/ferments/019f2747-7f40-712b-bea9-8a20399c9dfd/runtime.json +11 -0
  364. package/.ikie/ferments/019f2747-7fb4-70c9-aaf6-af4ac5fbebef/runtime.json +11 -0
  365. package/.ikie/ferments/019f2747-7fe2-77e7-90d5-dcee3cbe73ea/pending-proposal.json +45 -0
  366. package/.ikie/ferments/019f2747-7ff9-7028-ac25-77ab9c513710/pending-proposal.json +45 -0
  367. package/.ikie/ferments/019f2747-81c3-7320-8a96-88880d06cc14/pending-proposal.json +45 -0
  368. package/.ikie/ferments/019f2747-8236-76c0-b17c-1f13a22af974/pending-proposal.json +45 -0
  369. package/.ikie/ferments/019f2747-824b-77ba-90bd-67bcb4e9d5d6/pending-proposal.json +45 -0
  370. package/.ikie/ferments/019f2747-a18a-77f4-802d-18ab07f51261/runtime.json +13 -0
  371. package/.ikie/ferments/019f2747-a1b6-76cf-9688-94e8f41b179f/runtime.json +11 -0
  372. package/.ikie/ferments/019f2747-a1e2-730b-a56d-cb622d190c49/runtime.json +11 -0
  373. package/.ikie/ferments/019f2747-a20b-739e-a524-b5b2cdabdf49/runtime.json +11 -0
  374. package/.ikie/ferments/019f2747-a228-7026-9fe2-79fc90d7c622/runtime.json +11 -0
  375. package/.ikie/ferments/019f2747-a244-71b5-8ceb-d6094c7a5d28/runtime.json +11 -0
  376. package/.ikie/ferments/019f2747-a25d-723e-9962-ed1f266a9709/runtime.json +11 -0
  377. package/.ikie/ferments/019f2747-a275-734d-9ede-ae9644a179b6/runtime.json +11 -0
  378. package/.ikie/ferments/019f2747-a2a4-7280-b8c4-d8233d9e322a/runtime.json +9 -0
  379. package/.ikie/ferments/019f2747-a2ca-767d-8a35-9043b18e5ec7/runtime.json +13 -0
  380. package/.ikie/ferments/019f2747-a2f5-745d-929e-9fb2ef5d333f/runtime.json +11 -0
  381. package/.ikie/ferments/019f2747-a317-76b9-8954-2b7a4487a352/runtime.json +11 -0
  382. package/.ikie/ferments/019f2747-a380-7746-be44-cb9e1920561f/runtime.json +11 -0
  383. package/.ikie/ferments/019f2747-a3a2-77ac-9fe5-2a844b64872d/runtime.json +9 -0
  384. package/.ikie/ferments/019f2747-a3b7-70ee-ba83-b3c43d3122c8/runtime.json +9 -0
  385. package/.ikie/ferments/019f2747-a3e7-76e9-96f0-143c82d8005b/runtime.json +11 -0
  386. package/.ikie/ferments/019f2747-a4d3-737b-8d80-2dc63a0fbe1a/runtime.json +11 -0
  387. package/.ikie/ferments/019f2747-a506-7442-919f-50ae2b602e7a/runtime.json +12 -0
  388. package/.ikie/ferments/019f2747-a53e-76cb-9876-a81dd08e3fe7/runtime.json +11 -0
  389. package/.ikie/ferments/019f2747-a56a-7208-ad93-0fdcbc41c1ed/runtime.json +11 -0
  390. package/.ikie/ferments/019f2747-a581-73fc-aac5-a44f696ccbe8/runtime.json +11 -0
  391. package/.ikie/ferments/019f2747-a595-71d2-9c2d-d846e9803665/runtime.json +11 -0
  392. package/.ikie/ferments/019f2747-a5a7-73c6-b881-f9c0a08f3af3/runtime.json +13 -0
  393. package/.ikie/ferments/019f2747-a5be-7777-94c0-0849e693ffcb/runtime.json +11 -0
  394. package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/reviews/phase-phase-1-1.json +41 -0
  395. package/.ikie/ferments/019f2747-b3e6-706a-912c-71d57080c7c1/runtime.json +11 -0
  396. package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/reviews/phase-phase-1-1.json +47 -0
  397. package/.ikie/ferments/019f2747-b464-75bd-9c0b-c6b5e5de789e/runtime.json +13 -0
  398. package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/reviews/phase-phase-1-1.json +40 -0
  399. package/.ikie/ferments/019f2747-b4f2-719c-86a6-763c494a680c/runtime.json +9 -0
  400. package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/reviews/phase-phase-1-1.json +40 -0
  401. package/.ikie/ferments/019f2747-b52b-75cd-b664-8c2aedd87893/runtime.json +9 -0
  402. package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/reviews/phase-phase-1-1.json +40 -0
  403. package/.ikie/ferments/019f2747-b551-7188-81a3-7b7e8371aea4/runtime.json +9 -0
  404. package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/reviews/phase-phase-1-1.json +40 -0
  405. package/.ikie/ferments/019f2747-b5a5-703f-98e6-5eac131044ed/runtime.json +9 -0
  406. package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/reviews/phase-phase-1-1.json +40 -0
  407. package/.ikie/ferments/019f2747-b5cc-7560-80d8-509578bdae44/runtime.json +9 -0
  408. package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/reviews/phase-phase-1-1.json +62 -0
  409. package/.ikie/ferments/019f2747-b5f7-7079-ba17-833018701a06/runtime.json +9 -0
  410. package/.ikie/ferments/019f274a-bb4e-77b1-9f03-633b22b8e54c/runtime.json +11 -0
  411. package/.ikie/ferments/019f274a-bb6e-7715-92a0-c73da2ff97da/runtime.json +11 -0
  412. package/.ikie/ferments/019f274a-bb89-75b5-9daa-c57ef85c64c1/runtime.json +11 -0
  413. package/.ikie/ferments/019f274a-bbb7-72ad-9695-3227786b16ef/runtime.json +12 -0
  414. package/.ikie/ferments/019f274a-bbfb-70da-95f3-54a3e507888d/runtime.json +11 -0
  415. package/.ikie/ferments/019f274a-bc37-771a-8e77-b8d5476a8a1e/runtime.json +15 -0
  416. package/.ikie/ferments/019f274a-bc61-7024-9311-148a94a6713e/runtime.json +15 -0
  417. package/.ikie/ferments/019f274a-bca0-76a9-b966-59bbe3fb5bdd/runtime.json +15 -0
  418. package/.ikie/ferments/019f274a-bcc9-774d-adc2-aa99e82abb79/runtime.json +13 -0
  419. package/.ikie/ferments/019f274a-bcfb-737e-9c7d-b9db4762b624/runtime.json +15 -0
  420. package/.ikie/ferments/019f274a-bd3f-725b-9d39-b672191556ac/runtime.json +15 -0
  421. package/.ikie/ferments/019f274a-bd82-75a8-b936-350a55a7a1da/runtime.json +11 -0
  422. package/.ikie/ferments/019f274a-bda4-71b2-aa8b-7ba6f6103814/runtime.json +15 -0
  423. package/.ikie/ferments/019f274a-bddc-70ff-90f8-f1648dede718/runtime.json +15 -0
  424. package/.ikie/ferments/019f274a-be12-70bd-b935-0173946e60c2/runtime.json +15 -0
  425. package/.ikie/ferments/019f274a-be51-7719-b04b-d720a1d215f7/runtime.json +15 -0
  426. package/.ikie/ferments/019f274a-be8c-7084-aa78-4d139084333b/runtime.json +15 -0
  427. package/.ikie/ferments/019f274a-bebc-70b7-8c8d-fc7b50eda266/runtime.json +15 -0
  428. package/.ikie/ferments/019f274a-bee6-732f-b9ee-9fb3f1966e3d/runtime.json +15 -0
  429. package/.ikie/ferments/019f274a-bf19-76bc-8ab4-fe8c3fb28875/runtime.json +15 -0
  430. package/.ikie/ferments/019f274a-bf40-755b-bd4f-eec6d8e7a4de/runtime.json +15 -0
  431. package/.ikie/ferments/019f274a-bf74-7013-beb9-08aab0dc8866/runtime.json +11 -0
  432. package/.ikie/ferments/019f274a-bfa3-718d-ab5d-ededc4cf9e63/runtime.json +11 -0
  433. package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/reviews/phase-phase-1-1.json +63 -0
  434. package/.ikie/ferments/019f274a-bfd6-7689-b29b-2c3ebfe1afd3/runtime.json +17 -0
  435. package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/reviews/phase-phase-1-1.json +63 -0
  436. package/.ikie/ferments/019f274a-c186-77ea-a92c-78fa52657710/runtime.json +17 -0
  437. package/.ikie/ferments/019f274a-c3cf-77e8-9917-76d94992456a/runtime.json +11 -0
  438. package/.ikie/ferments/019f274a-c8eb-7071-9900-1668ccf13dad/runtime.json +11 -0
  439. package/.ikie/ferments/019f274a-c928-7276-9fd8-c8fdfbd215ff/runtime.json +11 -0
  440. package/.ikie/ferments/019f274a-c957-7698-8a97-54584a38f472/runtime.json +11 -0
  441. package/.ikie/ferments/019f274a-c97f-71b5-8fd9-727b49c9b72c/runtime.json +11 -0
  442. package/.ikie/ferments/019f274a-c9ad-76bb-99f8-b8f7840ad3ab/pending-proposal.json +45 -0
  443. package/.ikie/ferments/019f274a-c9cf-73ad-8229-d03bd5389697/pending-proposal.json +45 -0
  444. package/.ikie/ferments/019f274a-cb01-720a-b512-e49f820b9be5/pending-proposal.json +45 -0
  445. package/.ikie/ferments/019f274a-cbba-764d-a8e7-da6a060d9cd1/pending-proposal.json +45 -0
  446. package/.ikie/ferments/019f274a-cbdd-744f-84e9-af64527ff116/pending-proposal.json +45 -0
  447. package/.ikie/ferments/019f274a-efc1-75b6-ad54-83a9fcb061af/runtime.json +13 -0
  448. package/.ikie/ferments/019f274a-effe-713a-9672-ca8c839b0936/runtime.json +11 -0
  449. package/.ikie/ferments/019f274a-f03c-7194-b9e6-a24620ef1b89/runtime.json +11 -0
  450. package/.ikie/ferments/019f274a-f058-758c-9ecf-f6af131a0798/runtime.json +11 -0
  451. package/.ikie/ferments/019f274a-f06e-712d-b720-09a6188a152a/runtime.json +11 -0
  452. package/.ikie/ferments/019f274a-f085-715e-8b5b-07587107bc86/runtime.json +11 -0
  453. package/.ikie/ferments/019f274a-f0a8-755b-b747-adaa0f997d8a/runtime.json +11 -0
  454. package/.ikie/ferments/019f274a-f0cd-765c-90ce-48685c67299c/runtime.json +11 -0
  455. package/.ikie/ferments/019f274a-f0e1-71a8-bafc-cc3eeff4f275/runtime.json +9 -0
  456. package/.ikie/ferments/019f274a-f104-73c0-be62-16f724e0d4c6/runtime.json +13 -0
  457. package/.ikie/ferments/019f274a-f129-70ea-aa16-254d0fc662bf/runtime.json +11 -0
  458. package/.ikie/ferments/019f274a-f14b-7742-8e88-7a3fe9d16f08/runtime.json +11 -0
  459. package/.ikie/ferments/019f274a-f18b-7148-afb1-b9ff1ab54bbc/runtime.json +11 -0
  460. package/.ikie/ferments/019f274a-f1a2-734d-bf87-6f80955a3b64/runtime.json +9 -0
  461. package/.ikie/ferments/019f274a-f1c0-75a7-8675-f4fcf15df9bd/runtime.json +9 -0
  462. package/.ikie/ferments/019f274a-f1e2-7346-b97f-9340f86e6397/runtime.json +11 -0
  463. package/.ikie/ferments/019f274a-f2a1-7758-a891-413d15c9c29c/runtime.json +11 -0
  464. package/.ikie/ferments/019f274a-f2bc-76fd-b2dc-e14feea4fb86/runtime.json +12 -0
  465. package/.ikie/ferments/019f274a-f2e0-7474-97b8-79e01d130940/runtime.json +11 -0
  466. package/.ikie/ferments/019f274a-f2fa-70fb-a2da-0fb3e9a729ef/runtime.json +11 -0
  467. package/.ikie/ferments/019f274a-f30f-71bc-bf7f-198ef4b68568/runtime.json +11 -0
  468. package/.ikie/ferments/019f274a-f326-768b-b55e-e340dd3bf7fc/runtime.json +11 -0
  469. package/.ikie/ferments/019f274a-f339-75a5-9d45-d9393ccf3436/runtime.json +13 -0
  470. package/.ikie/ferments/019f274a-f35b-7386-9eb0-8f1e45618131/runtime.json +11 -0
  471. package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/reviews/phase-phase-1-1.json +41 -0
  472. package/.ikie/ferments/019f274a-f96b-7633-9b6d-6722ea8232a2/runtime.json +11 -0
  473. package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/reviews/phase-phase-1-1.json +47 -0
  474. package/.ikie/ferments/019f274a-f9b7-769e-94ac-8f5c7e23ee88/runtime.json +13 -0
  475. package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/reviews/phase-phase-1-1.json +40 -0
  476. package/.ikie/ferments/019f274a-fa07-70b1-bc68-1a9d3378deff/runtime.json +9 -0
  477. package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/reviews/phase-phase-1-1.json +40 -0
  478. package/.ikie/ferments/019f274a-fa2f-7658-86ad-cc69215f1c94/runtime.json +9 -0
  479. package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/reviews/phase-phase-1-1.json +40 -0
  480. package/.ikie/ferments/019f274a-fa46-72ca-a252-65a5b2995bc4/runtime.json +9 -0
  481. package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/reviews/phase-phase-1-1.json +40 -0
  482. package/.ikie/ferments/019f274a-fa70-705f-9112-d48e1042f1d4/runtime.json +9 -0
  483. package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/reviews/phase-phase-1-1.json +40 -0
  484. package/.ikie/ferments/019f274a-fa94-73e5-9fc3-ea21ee5cfc59/runtime.json +9 -0
  485. package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/reviews/phase-phase-1-1.json +62 -0
  486. package/.ikie/ferments/019f274a-fab9-720d-9ce3-0041a27f83e0/runtime.json +9 -0
  487. package/.ikie/ferments/019f274c-7608-76f8-89c7-6e3b7d9095b2/runtime.json +11 -0
  488. package/.ikie/ferments/019f274c-762a-717c-9ec2-530d37897051/runtime.json +11 -0
  489. package/.ikie/ferments/019f274c-7644-76fc-a27d-c699d368a511/runtime.json +11 -0
  490. package/.ikie/ferments/019f274c-7667-7260-87b3-f2ad6ff10c04/runtime.json +12 -0
  491. package/.ikie/ferments/019f274c-7696-753f-8634-5cb24d2aabaa/runtime.json +11 -0
  492. package/.ikie/ferments/019f274c-76c8-76e8-b4d8-0cabd7f32047/runtime.json +15 -0
  493. package/.ikie/ferments/019f274c-76f5-732e-88f3-0461f79b7733/runtime.json +15 -0
  494. package/.ikie/ferments/019f274c-771b-762e-abb6-1bfe6838545b/runtime.json +15 -0
  495. package/.ikie/ferments/019f274c-774a-769f-b15f-d36a990c8aa2/runtime.json +13 -0
  496. package/.ikie/ferments/019f274c-7791-7040-9c73-fe5922824edc/runtime.json +15 -0
  497. package/.ikie/ferments/019f274c-77c3-76f9-a5c6-e0f5030f615c/runtime.json +15 -0
  498. package/.ikie/ferments/019f274c-7805-70eb-ac17-888c2a0ab5cb/runtime.json +11 -0
  499. package/.ikie/ferments/019f274c-7820-71da-9baf-d7953b547620/runtime.json +15 -0
  500. package/.ikie/ferments/019f274c-7855-708f-bbe8-a9e13258cc98/runtime.json +15 -0
  501. package/.ikie/ferments/019f274c-7886-70fc-9572-b96090b16cf9/runtime.json +15 -0
  502. package/.ikie/ferments/019f274c-78b7-756e-82ef-8a8e953000bf/runtime.json +15 -0
  503. package/.ikie/ferments/019f274c-78df-7198-b1dd-58c3ea1e0d6e/runtime.json +15 -0
  504. package/.ikie/ferments/019f274c-7902-77d4-b443-b105d0a3acd5/runtime.json +15 -0
  505. package/.ikie/ferments/019f274c-7926-7628-82dc-e71e8f5d58f0/runtime.json +15 -0
  506. package/.ikie/ferments/019f274c-7948-7755-bc18-c8d9975c762f/runtime.json +15 -0
  507. package/.ikie/ferments/019f274c-7972-72a5-bc5e-e47579f25c32/runtime.json +15 -0
  508. package/.ikie/ferments/019f274c-7998-71bf-960e-caba2791ece7/runtime.json +11 -0
  509. package/.ikie/ferments/019f274c-79c4-71c6-97ef-0dac30d26152/runtime.json +11 -0
  510. package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/reviews/phase-phase-1-1.json +63 -0
  511. package/.ikie/ferments/019f274c-79e3-7249-8bac-82b74fbd9d1d/runtime.json +17 -0
  512. package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/reviews/phase-phase-1-1.json +63 -0
  513. package/.ikie/ferments/019f274c-7b11-769e-b05b-354105048fb2/runtime.json +17 -0
  514. package/.ikie/ferments/019f274c-7c7b-73ad-98d3-739e5f0187ec/runtime.json +11 -0
  515. package/.ikie/ferments/019f274c-8054-728f-96c1-6cae4b96c94e/runtime.json +11 -0
  516. package/.ikie/ferments/019f274c-8072-7209-82b0-84facff2e61a/runtime.json +11 -0
  517. package/.ikie/ferments/019f274c-8094-77ec-81dd-e50e61dc11db/runtime.json +11 -0
  518. package/.ikie/ferments/019f274c-80bc-75c9-89e8-540dba77996e/runtime.json +11 -0
  519. package/.ikie/ferments/019f274c-80dd-7439-a5b0-b36fcf77c8f1/pending-proposal.json +45 -0
  520. package/.ikie/ferments/019f274c-80f1-71ac-bd32-fd151f38519c/pending-proposal.json +45 -0
  521. package/.ikie/ferments/019f274c-81dc-70e6-a5c9-249b196c75c3/pending-proposal.json +45 -0
  522. package/.ikie/ferments/019f274c-8238-772c-9da3-f27e467100a7/pending-proposal.json +45 -0
  523. package/.ikie/ferments/019f274c-824a-76d9-aac3-c51171e256b4/pending-proposal.json +45 -0
  524. package/.ikie/ferments/019f274c-a854-7349-b76a-4a0bc2ecc2f7/runtime.json +11 -0
  525. package/.ikie/ferments/019f274c-a872-701b-a311-51267fc54aa5/runtime.json +11 -0
  526. package/.ikie/ferments/019f274c-a8a2-756e-9051-15fcd0be1584/runtime.json +11 -0
  527. package/.ikie/ferments/019f274c-a8d8-767c-8190-d30a2e78815f/runtime.json +12 -0
  528. package/.ikie/ferments/019f274c-a914-701e-95ab-9eeca15f5ccd/runtime.json +11 -0
  529. package/.ikie/ferments/019f274c-a951-720f-bc99-2ea22021a624/runtime.json +15 -0
  530. package/.ikie/ferments/019f274c-a978-750b-aecb-a5a2aa684cdf/runtime.json +15 -0
  531. package/.ikie/ferments/019f274c-a9a6-71e9-82ac-66c74cf51964/runtime.json +15 -0
  532. package/.ikie/ferments/019f274c-a9e0-77ae-96eb-dad523b6a843/runtime.json +13 -0
  533. package/.ikie/ferments/019f274c-aa2c-7658-a652-ca1a27093c42/runtime.json +15 -0
  534. package/.ikie/ferments/019f274c-aa77-72b4-a8de-56a2217c759f/runtime.json +15 -0
  535. package/.ikie/ferments/019f274c-aacf-74fa-943c-26412ddd8b5d/runtime.json +11 -0
  536. package/.ikie/ferments/019f274c-ab08-709f-aaff-09f10230738f/runtime.json +15 -0
  537. package/.ikie/ferments/019f274c-ab66-730b-86a5-7571dac8802c/runtime.json +15 -0
  538. package/.ikie/ferments/019f274c-abb2-77d2-91b6-ea175f561d8a/runtime.json +15 -0
  539. package/.ikie/ferments/019f274c-ac01-74ff-a2c6-28dbadc051e7/runtime.json +15 -0
  540. package/.ikie/ferments/019f274c-ac4b-75ad-93a6-aa6af74ca708/runtime.json +15 -0
  541. package/.ikie/ferments/019f274c-ac80-77b4-bfcf-f7a7187a42f6/runtime.json +15 -0
  542. package/.ikie/ferments/019f274c-acd9-7239-ad37-73d57031d1bc/runtime.json +15 -0
  543. package/.ikie/ferments/019f274c-ad22-74bb-9cf2-ed681dd73504/runtime.json +15 -0
  544. package/.ikie/ferments/019f274c-ad7d-720c-89bf-5a79ceec8173/runtime.json +15 -0
  545. package/.ikie/ferments/019f274c-adca-762a-b177-4d76b886003b/runtime.json +11 -0
  546. package/.ikie/ferments/019f274c-ae26-7109-bfaa-39d692fdc1ac/runtime.json +11 -0
  547. package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/reviews/phase-phase-1-1.json +63 -0
  548. package/.ikie/ferments/019f274c-ae59-76bb-80ae-f556e764f2ca/runtime.json +17 -0
  549. package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/reviews/phase-phase-1-1.json +63 -0
  550. package/.ikie/ferments/019f274c-b059-76e5-9b73-bedc0d4b5aaa/runtime.json +17 -0
  551. package/.ikie/ferments/019f274c-b21f-700a-adda-4bfd9d27a0ac/runtime.json +11 -0
  552. package/.ikie/ferments/019f274c-b91a-7306-8825-3581ef16ab34/runtime.json +11 -0
  553. package/.ikie/ferments/019f274c-b966-737f-a1c7-e8e7d3af929c/runtime.json +11 -0
  554. package/.ikie/ferments/019f274c-b99d-74dd-b8e8-1ddc50293a9a/runtime.json +11 -0
  555. package/.ikie/ferments/019f274c-ba0e-72ae-ad14-983edb8d90ac/runtime.json +11 -0
  556. package/.ikie/ferments/019f274c-ba4f-7101-b851-12564620c50f/pending-proposal.json +45 -0
  557. package/.ikie/ferments/019f274c-ba63-712c-858f-96cee1384cec/pending-proposal.json +45 -0
  558. package/.ikie/ferments/019f274c-bbe3-7343-a8b0-e6f91c3ab922/pending-proposal.json +45 -0
  559. package/.ikie/ferments/019f274c-bc4a-740e-a12a-9c04181702d9/pending-proposal.json +45 -0
  560. package/.ikie/ferments/019f274c-bc7b-707c-90b9-d30cf92b5fb9/pending-proposal.json +45 -0
  561. package/.ikie/ferments/019f274c-e044-750a-a9e1-623de3afa666/runtime.json +13 -0
  562. package/.ikie/ferments/019f274c-e07a-77cb-9f17-726e4afb3ee1/runtime.json +11 -0
  563. package/.ikie/ferments/019f274c-e0a2-754a-ac70-aac9cd3d3dc2/runtime.json +11 -0
  564. package/.ikie/ferments/019f274c-e0ba-72de-bf83-25a8319eddc5/runtime.json +11 -0
  565. package/.ikie/ferments/019f274c-e0cf-77c1-9c23-65745da294b4/runtime.json +11 -0
  566. package/.ikie/ferments/019f274c-e0e7-77f7-9436-0537e2095c6b/runtime.json +11 -0
  567. package/.ikie/ferments/019f274c-e103-70d7-abd9-01305b905259/runtime.json +11 -0
  568. package/.ikie/ferments/019f274c-e121-7328-9eab-3babb40f26b3/runtime.json +11 -0
  569. package/.ikie/ferments/019f274c-e135-76d4-9176-2033e41fa5a8/runtime.json +9 -0
  570. package/.ikie/ferments/019f274c-e157-7043-9b54-fd7c40cb0793/runtime.json +13 -0
  571. package/.ikie/ferments/019f274c-e181-718e-804d-d0edfaabd5cd/runtime.json +11 -0
  572. package/.ikie/ferments/019f274c-e19b-72ab-bf87-b7a53037becb/runtime.json +11 -0
  573. package/.ikie/ferments/019f274c-e20a-716e-8cab-f0cd93259148/runtime.json +11 -0
  574. package/.ikie/ferments/019f274c-e228-73a3-a655-48bc44db0325/runtime.json +9 -0
  575. package/.ikie/ferments/019f274c-e243-7609-bec4-905caa78d674/runtime.json +9 -0
  576. package/.ikie/ferments/019f274c-e258-76ba-912c-bab41dfeaac2/runtime.json +11 -0
  577. package/.ikie/ferments/019f274c-e35a-776b-a644-52ee82afec4d/runtime.json +11 -0
  578. package/.ikie/ferments/019f274c-e378-73e8-943d-f2fc2ee875ef/runtime.json +12 -0
  579. package/.ikie/ferments/019f274c-e3a6-757d-b33c-c6fbdd9cf8c7/runtime.json +11 -0
  580. package/.ikie/ferments/019f274c-e3c9-77a7-be2b-43891355a506/runtime.json +11 -0
  581. package/.ikie/ferments/019f274c-e3db-776b-8de6-fb1aeab60a7b/runtime.json +11 -0
  582. package/.ikie/ferments/019f274c-e3f4-700e-8780-2dee3c117eb8/runtime.json +11 -0
  583. package/.ikie/ferments/019f274c-e409-71af-a0f9-ff159811e472/runtime.json +13 -0
  584. package/.ikie/ferments/019f274c-e432-73cd-bd34-39f0e34a568d/runtime.json +11 -0
  585. package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/reviews/phase-phase-1-1.json +41 -0
  586. package/.ikie/ferments/019f274c-eb55-73fe-bb2a-34b4a2df3f4e/runtime.json +11 -0
  587. package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/reviews/phase-phase-1-1.json +47 -0
  588. package/.ikie/ferments/019f274c-eb9b-728e-93e2-80afb71ae50e/runtime.json +13 -0
  589. package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/reviews/phase-phase-1-1.json +40 -0
  590. package/.ikie/ferments/019f274c-ebf3-77bb-8f8a-6081787fbcb3/runtime.json +9 -0
  591. package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/reviews/phase-phase-1-1.json +40 -0
  592. package/.ikie/ferments/019f274c-ec22-7123-8c8f-0c129c2e0719/runtime.json +9 -0
  593. package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/reviews/phase-phase-1-1.json +40 -0
  594. package/.ikie/ferments/019f274c-ec85-757c-9600-8be68ceccb55/runtime.json +9 -0
  595. package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/reviews/phase-phase-1-1.json +40 -0
  596. package/.ikie/ferments/019f274c-ecd9-704e-8c99-65c64be0a8e1/runtime.json +9 -0
  597. package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/reviews/phase-phase-1-1.json +40 -0
  598. package/.ikie/ferments/019f274c-ecee-70bb-9087-da3b4c57d281/runtime.json +9 -0
  599. package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/reviews/phase-phase-1-1.json +62 -0
  600. package/.ikie/ferments/019f274c-ed18-77bf-8cde-812d1e273bda/runtime.json +9 -0
  601. package/.ikie/ferments/019f274f-0303-7543-9aa9-fa7f54d5f6c6/runtime.json +11 -0
  602. package/.ikie/ferments/019f274f-032c-70aa-b5b5-d695429a50bc/runtime.json +11 -0
  603. package/.ikie/ferments/019f274f-036d-763c-8cf9-cb62245aff49/runtime.json +11 -0
  604. package/.ikie/ferments/019f274f-03bd-709c-85ee-698745beac66/runtime.json +12 -0
  605. package/.ikie/ferments/019f274f-0404-75cf-8731-f0182bd84d87/runtime.json +11 -0
  606. package/.ikie/ferments/019f274f-0442-75fe-8cc3-44bfe5dd84bf/runtime.json +15 -0
  607. package/.ikie/ferments/019f274f-048f-759f-ae18-5fe9975647bf/runtime.json +15 -0
  608. package/.ikie/ferments/019f274f-04f1-72fa-a2ba-0b9e066ae6eb/runtime.json +15 -0
  609. package/.ikie/ferments/019f274f-0541-728d-8893-0b0b45547a56/runtime.json +13 -0
  610. package/.ikie/ferments/019f274f-058e-7508-b67a-ebe736113e1e/runtime.json +15 -0
  611. package/.ikie/ferments/019f274f-0625-77d9-bf99-bcdf0ca2d5b2/runtime.json +15 -0
  612. package/.ikie/ferments/019f274f-0694-715c-b008-29a3cf0d6c9c/runtime.json +11 -0
  613. package/.ikie/ferments/019f274f-06b1-71fb-a812-3fd3cefda2ea/runtime.json +15 -0
  614. package/.ikie/ferments/019f274f-06e9-701b-9396-dca2be2330e5/runtime.json +15 -0
  615. package/.ikie/ferments/019f274f-072b-76b2-8d77-32d0ad5abb81/runtime.json +15 -0
  616. package/.ikie/ferments/019f274f-0770-75ce-886f-c1c12d6682eb/runtime.json +15 -0
  617. package/.ikie/ferments/019f274f-07ab-75fc-a71b-ca3b4b4acca5/runtime.json +15 -0
  618. package/.ikie/ferments/019f274f-07f0-72cd-a577-316526b45983/runtime.json +15 -0
  619. package/.ikie/ferments/019f274f-0837-72ed-94f2-dd68e9273549/runtime.json +15 -0
  620. package/.ikie/ferments/019f274f-0866-765d-a2fc-8cce9d53e417/runtime.json +15 -0
  621. package/.ikie/ferments/019f274f-08bb-737e-8f23-4b2e069bc7e5/runtime.json +15 -0
  622. package/.ikie/ferments/019f274f-08f6-73aa-968a-85f55d5e047c/runtime.json +11 -0
  623. package/.ikie/ferments/019f274f-0949-77b7-8d2c-46fbeb423e3a/runtime.json +11 -0
  624. package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/reviews/phase-phase-1-1.json +63 -0
  625. package/.ikie/ferments/019f274f-0979-71ad-91b5-d2e52366b74d/runtime.json +17 -0
  626. package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/reviews/phase-phase-1-1.json +63 -0
  627. package/.ikie/ferments/019f274f-0b57-7329-884a-43e712cd093c/runtime.json +17 -0
  628. package/.ikie/ferments/019f274f-0d87-772d-a6f3-b71179eec14f/runtime.json +11 -0
  629. package/.ikie/ferments/019f274f-12f0-73be-b630-54a329974d0b/runtime.json +11 -0
  630. package/.ikie/ferments/019f274f-1332-7202-90be-f7e94dd16e66/runtime.json +11 -0
  631. package/.ikie/ferments/019f274f-1368-778a-b044-0306086fe9cf/runtime.json +11 -0
  632. package/.ikie/ferments/019f274f-13a9-7287-974d-8db5c1b7dda6/runtime.json +11 -0
  633. package/.ikie/ferments/019f274f-13d1-7069-91d8-2e4efe8d8982/pending-proposal.json +45 -0
  634. package/.ikie/ferments/019f274f-13f8-717c-92c9-9bc9b37ee2cc/pending-proposal.json +45 -0
  635. package/.ikie/ferments/019f274f-1566-753b-b053-f14ccb779e36/pending-proposal.json +45 -0
  636. package/.ikie/ferments/019f274f-15d3-76f8-8467-e368f0c40baf/pending-proposal.json +45 -0
  637. package/.ikie/ferments/019f274f-15f0-716f-92e7-d966f4476b09/pending-proposal.json +45 -0
  638. package/.ikie/ferments/019f274f-2a19-762d-be24-59afdd71b303/runtime.json +13 -0
  639. package/.ikie/ferments/019f274f-2a74-74cb-ab51-dd779739478e/runtime.json +11 -0
  640. package/.ikie/ferments/019f274f-2a92-71e1-9e68-15f750efc6ec/runtime.json +11 -0
  641. package/.ikie/ferments/019f274f-2ab1-73eb-8930-b9d161230fcc/runtime.json +11 -0
  642. package/.ikie/ferments/019f274f-2ad9-70ea-83a9-f8ae1af1edcf/runtime.json +11 -0
  643. package/.ikie/ferments/019f274f-2b02-77ea-b187-43489c9a88f8/runtime.json +11 -0
  644. package/.ikie/ferments/019f274f-2b2d-728c-9b69-7a6e4956a88c/runtime.json +11 -0
  645. package/.ikie/ferments/019f274f-2b42-7358-b1fa-9754d2ca530d/runtime.json +11 -0
  646. package/.ikie/ferments/019f274f-2b74-77ee-b062-8b111368fc58/runtime.json +9 -0
  647. package/.ikie/ferments/019f274f-2b9b-703b-8abd-5b4ff212ce66/runtime.json +13 -0
  648. package/.ikie/ferments/019f274f-2bd6-7109-93ec-12f609270c84/runtime.json +11 -0
  649. package/.ikie/ferments/019f274f-2bea-75cf-b3d2-aedca4b0c8a4/runtime.json +11 -0
  650. package/.ikie/ferments/019f274f-2c1c-7085-b221-ecf2a371e6cf/runtime.json +11 -0
  651. package/.ikie/ferments/019f274f-2c2f-71fb-9b03-41d6f8a5d2d6/runtime.json +9 -0
  652. package/.ikie/ferments/019f274f-2c5d-719d-a913-5255a7b3e376/runtime.json +9 -0
  653. package/.ikie/ferments/019f274f-2c92-75bb-b691-4efd9b706418/runtime.json +11 -0
  654. package/.ikie/ferments/019f274f-2d9e-7186-b8f9-0d5863265329/runtime.json +11 -0
  655. package/.ikie/ferments/019f274f-2dbb-73f9-8231-b52b6e1eb863/runtime.json +12 -0
  656. package/.ikie/ferments/019f274f-2ddf-7477-a5a2-a20be1921fbf/runtime.json +11 -0
  657. package/.ikie/ferments/019f274f-2e01-710b-8175-18eeb0e792e2/runtime.json +11 -0
  658. package/.ikie/ferments/019f274f-2e26-7217-a41e-3bd106e0a9cf/runtime.json +11 -0
  659. package/.ikie/ferments/019f274f-2e3a-72bc-9945-37a576bb7ef1/runtime.json +11 -0
  660. package/.ikie/ferments/019f274f-2e61-77e5-85ab-dda905bded90/runtime.json +13 -0
  661. package/.ikie/ferments/019f274f-2e7e-73ea-a7c9-14ab5125c3d3/runtime.json +11 -0
  662. package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/reviews/phase-phase-1-1.json +41 -0
  663. package/.ikie/ferments/019f274f-4262-76b9-884a-9ff2121f2c3a/runtime.json +11 -0
  664. package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/reviews/phase-phase-1-1.json +47 -0
  665. package/.ikie/ferments/019f274f-42ce-753f-ba6d-c1c2be5b7c71/runtime.json +13 -0
  666. package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/reviews/phase-phase-1-1.json +40 -0
  667. package/.ikie/ferments/019f274f-4353-75ed-bad2-0f74d61ceff5/runtime.json +9 -0
  668. package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/reviews/phase-phase-1-1.json +40 -0
  669. package/.ikie/ferments/019f274f-4379-7716-af61-2381f422540e/runtime.json +9 -0
  670. package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/reviews/phase-phase-1-1.json +40 -0
  671. package/.ikie/ferments/019f274f-43a1-716c-ba31-4b705e8afb1a/runtime.json +9 -0
  672. package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/reviews/phase-phase-1-1.json +40 -0
  673. package/.ikie/ferments/019f274f-43de-761a-b793-fca5ca243eea/runtime.json +9 -0
  674. package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/reviews/phase-phase-1-1.json +40 -0
  675. package/.ikie/ferments/019f274f-4401-73e9-b9d8-99631bab030b/runtime.json +9 -0
  676. package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/reviews/phase-phase-1-1.json +62 -0
  677. package/.ikie/ferments/019f274f-442b-770b-b411-feeb46ae7a8d/runtime.json +9 -0
  678. package/.ikie/ferments/019f275c-3e9e-7557-b50e-0e56cc6b07f5/runtime.json +11 -0
  679. package/.ikie/ferments/019f275c-3ec3-73ea-b557-77cc517095f2/runtime.json +11 -0
  680. package/.ikie/ferments/019f275c-3ee5-774f-876e-3caacb9b1d95/runtime.json +11 -0
  681. package/.ikie/ferments/019f275c-3f28-73ee-8eae-568fec8011b6/runtime.json +12 -0
  682. package/.ikie/ferments/019f275c-3f57-70a8-ba4d-d179cceaabbf/runtime.json +11 -0
  683. package/.ikie/ferments/019f275c-3f88-72cb-abb5-8e0e176e1dd2/runtime.json +15 -0
  684. package/.ikie/ferments/019f275c-3fb4-7248-9c23-874baa6e2a9d/runtime.json +15 -0
  685. package/.ikie/ferments/019f275c-3fe1-759b-afd9-f5e47564de48/runtime.json +15 -0
  686. package/.ikie/ferments/019f275c-401f-74e8-b968-d325ae2faf56/runtime.json +13 -0
  687. package/.ikie/ferments/019f275c-4067-752e-a0d8-d85f670f9473/runtime.json +15 -0
  688. package/.ikie/ferments/019f275c-40a2-74de-b858-ef4ad52484ea/runtime.json +15 -0
  689. package/.ikie/ferments/019f275c-4105-738f-95d0-6e9f7f9568fb/runtime.json +11 -0
  690. package/.ikie/ferments/019f275c-411b-76e9-b030-df118a1b23b4/runtime.json +15 -0
  691. package/.ikie/ferments/019f275c-4153-74ec-8b93-e2e0e82c27b0/runtime.json +15 -0
  692. package/.ikie/ferments/019f275c-4199-739b-9af9-b1cfc26623c3/runtime.json +15 -0
  693. package/.ikie/ferments/019f275c-41cb-746b-8481-7ca9d82a8b64/runtime.json +15 -0
  694. package/.ikie/ferments/019f275c-4209-756f-b335-8e6dfe51bac1/runtime.json +15 -0
  695. package/.ikie/ferments/019f275c-424c-7512-ac17-b8c04dcf82ac/runtime.json +15 -0
  696. package/.ikie/ferments/019f275c-4269-74eb-a213-e221479a26e5/runtime.json +15 -0
  697. package/.ikie/ferments/019f275c-428b-71ea-acda-027b98d191d1/runtime.json +15 -0
  698. package/.ikie/ferments/019f275c-42bb-75da-b330-e9f101c36d5c/runtime.json +15 -0
  699. package/.ikie/ferments/019f275c-42e3-777a-8e8c-80772f6d6bcb/runtime.json +11 -0
  700. package/.ikie/ferments/019f275c-430b-7779-bcc7-95a0b6fc693d/runtime.json +11 -0
  701. package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/reviews/phase-phase-1-1.json +63 -0
  702. package/.ikie/ferments/019f275c-432e-71f9-b65d-88d26f3b185f/runtime.json +17 -0
  703. package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/reviews/phase-phase-1-1.json +63 -0
  704. package/.ikie/ferments/019f275c-447e-756d-8ec0-091e54bcc7b4/runtime.json +17 -0
  705. package/.ikie/ferments/019f275c-4602-757e-9283-3606516f4d15/runtime.json +11 -0
  706. package/.ikie/ferments/019f275c-4a3b-75f0-8355-8524d1589242/runtime.json +11 -0
  707. package/.ikie/ferments/019f275c-4a5c-744e-9792-deb33fe1e244/runtime.json +11 -0
  708. package/.ikie/ferments/019f275c-4a79-73d2-beae-4e85f8906581/runtime.json +11 -0
  709. package/.ikie/ferments/019f275c-4a97-70b9-98d1-53d9326b4c95/runtime.json +11 -0
  710. package/.ikie/ferments/019f275c-4ac1-7452-ab7a-485bde641591/pending-proposal.json +45 -0
  711. package/.ikie/ferments/019f275c-4ad7-77ba-8a63-d8586db466e7/pending-proposal.json +45 -0
  712. package/.ikie/ferments/019f275c-4bee-77b9-8470-98c4aafeae43/pending-proposal.json +45 -0
  713. package/.ikie/ferments/019f275c-4c3d-712b-95f6-a671b7884658/pending-proposal.json +45 -0
  714. package/.ikie/ferments/019f275c-4c4e-73a0-accb-e76c29bc1f6d/pending-proposal.json +45 -0
  715. package/.ikie/ferments/019f275c-7598-775d-beed-cde3b6cb74e6/runtime.json +13 -0
  716. package/.ikie/ferments/019f275c-75c0-773d-9c0c-dd4943fc6092/runtime.json +11 -0
  717. package/.ikie/ferments/019f275c-75dc-7629-8a52-1eba66275779/runtime.json +11 -0
  718. package/.ikie/ferments/019f275c-75f3-742b-8494-e8a1facb02bb/runtime.json +11 -0
  719. package/.ikie/ferments/019f275c-760c-705e-8d98-7963d8830086/runtime.json +11 -0
  720. package/.ikie/ferments/019f275c-7627-763c-ae8e-20dde59c64b9/runtime.json +11 -0
  721. package/.ikie/ferments/019f275c-763c-74ae-b835-b52b57c52e9b/runtime.json +11 -0
  722. package/.ikie/ferments/019f275c-7650-7499-b744-7f38cfa776f4/runtime.json +11 -0
  723. package/.ikie/ferments/019f275c-766d-75b8-ba35-69e472baf630/runtime.json +9 -0
  724. package/.ikie/ferments/019f275c-7687-72cc-beac-339a11625f14/runtime.json +13 -0
  725. package/.ikie/ferments/019f275c-76a6-773d-a4c1-19a5ec313596/runtime.json +11 -0
  726. package/.ikie/ferments/019f275c-76c1-71b9-a49e-4b520fcef543/runtime.json +11 -0
  727. package/.ikie/ferments/019f275c-7706-761f-a9cf-7e412e88015d/runtime.json +11 -0
  728. package/.ikie/ferments/019f275c-772b-745f-a74d-de30f52a3316/runtime.json +9 -0
  729. package/.ikie/ferments/019f275c-7746-759c-a116-c2cd08e2f29b/runtime.json +9 -0
  730. package/.ikie/ferments/019f275c-7760-709d-83bc-4d6fff7ac768/runtime.json +11 -0
  731. package/.ikie/ferments/019f275c-780e-74db-9d7d-bcc430c1a964/runtime.json +11 -0
  732. package/.ikie/ferments/019f275c-7826-734e-8113-90111e82d96a/runtime.json +12 -0
  733. package/.ikie/ferments/019f275c-7849-72ed-8fb0-d1815d2f66d3/runtime.json +11 -0
  734. package/.ikie/ferments/019f275c-785f-716e-b077-eee453653ee0/runtime.json +11 -0
  735. package/.ikie/ferments/019f275c-7871-70fe-b543-bcdaaa10d320/runtime.json +11 -0
  736. package/.ikie/ferments/019f275c-7888-777d-8edf-1a5a906679d7/runtime.json +11 -0
  737. package/.ikie/ferments/019f275c-78b3-722e-9d1a-f354b0d0fa96/runtime.json +13 -0
  738. package/.ikie/ferments/019f275c-78cb-7568-ad11-191bc98cabe5/runtime.json +11 -0
  739. package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/reviews/phase-phase-1-1.json +41 -0
  740. package/.ikie/ferments/019f275c-8905-76ae-beb3-2ec9138b799b/runtime.json +11 -0
  741. package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/reviews/phase-phase-1-1.json +47 -0
  742. package/.ikie/ferments/019f275c-8970-713f-a498-af24ac57355a/runtime.json +13 -0
  743. package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/reviews/phase-phase-1-1.json +40 -0
  744. package/.ikie/ferments/019f275c-89c6-712f-b3c9-d9459bdaba76/runtime.json +9 -0
  745. package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/reviews/phase-phase-1-1.json +40 -0
  746. package/.ikie/ferments/019f275c-89e8-7105-9ba9-eda02056339a/runtime.json +9 -0
  747. package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/reviews/phase-phase-1-1.json +40 -0
  748. package/.ikie/ferments/019f275c-8a0d-71cb-bbb3-aa061c305aab/runtime.json +9 -0
  749. package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/reviews/phase-phase-1-1.json +40 -0
  750. package/.ikie/ferments/019f275c-8a31-758b-87c7-1b2ec8b0bd7a/runtime.json +9 -0
  751. package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/reviews/phase-phase-1-1.json +40 -0
  752. package/.ikie/ferments/019f275c-8a4f-7649-a250-4074bed6f208/runtime.json +9 -0
  753. package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/reviews/phase-phase-1-1.json +62 -0
  754. package/.ikie/ferments/019f275c-8a6e-706d-af6d-f6636f3b229e/runtime.json +9 -0
  755. package/.ikie/ferments/019f275e-8903-721d-98f8-0135ab6b4698/runtime.json +11 -0
  756. package/.ikie/ferments/019f275e-8920-7644-a529-664b63f9bab1/runtime.json +11 -0
  757. package/.ikie/ferments/019f275e-8938-75c2-85ab-f5a50138a4eb/runtime.json +11 -0
  758. package/.ikie/ferments/019f275e-895e-74a1-b263-2f73d989898e/runtime.json +12 -0
  759. package/.ikie/ferments/019f275e-8977-75ee-9e9a-cc069fff1cfa/runtime.json +11 -0
  760. package/.ikie/ferments/019f275e-899d-773b-abe3-e93c56f57cf1/runtime.json +11 -0
  761. package/.ikie/ferments/019f275e-89d1-72ea-9362-d4ce4079e846/runtime.json +15 -0
  762. package/.ikie/ferments/019f275e-89f9-7007-b382-a55e983d9520/runtime.json +15 -0
  763. package/.ikie/ferments/019f275e-8a1d-7687-a56e-94ead3cafbf8/runtime.json +15 -0
  764. package/.ikie/ferments/019f275e-8a49-760f-9639-3ce1494f37e9/runtime.json +13 -0
  765. package/.ikie/ferments/019f275e-8a7d-7461-b978-c3478b99b386/runtime.json +15 -0
  766. package/.ikie/ferments/019f275e-8aac-736d-bd96-6b442359993b/runtime.json +15 -0
  767. package/.ikie/ferments/019f275e-8ae6-7298-a523-d2fb7287bed3/runtime.json +11 -0
  768. package/.ikie/ferments/019f275e-8b01-7059-85a1-a665334ced3e/runtime.json +15 -0
  769. package/.ikie/ferments/019f275e-8b29-7295-be5b-0468763ab101/runtime.json +15 -0
  770. package/.ikie/ferments/019f275e-8b51-7204-9d30-0a67dae9c341/runtime.json +15 -0
  771. package/.ikie/ferments/019f275e-8b78-71eb-a8a3-1448d3373912/runtime.json +15 -0
  772. package/.ikie/ferments/019f275e-8b9d-76bf-9caa-0fed193b85bf/runtime.json +15 -0
  773. package/.ikie/ferments/019f275e-8bc0-71df-9356-19d3075c9568/runtime.json +15 -0
  774. package/.ikie/ferments/019f275e-8be2-75bd-be4a-ba2ede0e95f3/runtime.json +15 -0
  775. package/.ikie/ferments/019f275e-8c0b-714a-a389-20ffe6d0e66d/runtime.json +15 -0
  776. package/.ikie/ferments/019f275e-8c30-7371-86af-78e5f5ac8b23/runtime.json +15 -0
  777. package/.ikie/ferments/019f275e-8c5a-7383-bd79-c7fec3a71946/runtime.json +11 -0
  778. package/.ikie/ferments/019f275e-8c75-76b1-bcaa-81e67fc35aa8/runtime.json +11 -0
  779. package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/reviews/phase-phase-1-1.json +63 -0
  780. package/.ikie/ferments/019f275e-8caa-71e9-9e66-0d30c4a03123/runtime.json +17 -0
  781. package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/reviews/phase-phase-1-1.json +63 -0
  782. package/.ikie/ferments/019f275e-8e59-7787-84f8-fcf93ec75949/runtime.json +17 -0
  783. package/.ikie/ferments/019f275e-8ffb-70c2-844e-e1f4fa4c2cc4/runtime.json +11 -0
  784. package/.ikie/ferments/019f275e-949b-7158-a426-07bcca442439/runtime.json +11 -0
  785. package/.ikie/ferments/019f275e-94c6-7479-abcb-c22fc19445a0/runtime.json +11 -0
  786. package/.ikie/ferments/019f275e-94eb-76e9-a148-fb5001492823/runtime.json +11 -0
  787. package/.ikie/ferments/019f275e-9516-765a-b8ee-e88e5ab2530f/runtime.json +11 -0
  788. package/.ikie/ferments/019f275e-9539-740f-bbdb-09b82f71fc81/pending-proposal.json +45 -0
  789. package/.ikie/ferments/019f275e-954f-73e0-9286-fdf09cb1cbc6/pending-proposal.json +45 -0
  790. package/.ikie/ferments/019f275e-967d-73dc-bfaf-18e44335cff8/pending-proposal.json +45 -0
  791. package/.ikie/ferments/019f275e-96f0-702d-b0d2-f2aeb1c7ee15/pending-proposal.json +45 -0
  792. package/.ikie/ferments/019f275e-9708-770c-bae2-2652e32be3cf/pending-proposal.json +45 -0
  793. package/.ikie/ferments/019f275e-c992-77a4-960a-d6d51983c9d6/runtime.json +13 -0
  794. package/.ikie/ferments/019f275e-c9cf-724a-a59f-8e34f026db5e/runtime.json +11 -0
  795. package/.ikie/ferments/019f275e-c9e6-7647-9517-b2b25cd1f495/runtime.json +11 -0
  796. package/.ikie/ferments/019f275e-ca11-716b-832b-11fc14ce1ded/runtime.json +11 -0
  797. package/.ikie/ferments/019f275e-ca2f-74df-90fa-2eed00b55ecf/runtime.json +11 -0
  798. package/.ikie/ferments/019f275e-ca49-77ed-bb62-cd9c3c1176a5/runtime.json +11 -0
  799. package/.ikie/ferments/019f275e-ca62-77ca-aed0-74728cab4be4/runtime.json +11 -0
  800. package/.ikie/ferments/019f275e-ca7a-76aa-a860-42152a699337/runtime.json +11 -0
  801. package/.ikie/ferments/019f275e-ca9b-766c-9ad4-2f86ff5c9dbe/runtime.json +9 -0
  802. package/.ikie/ferments/019f275e-cabc-77cf-a94a-9f8988667998/runtime.json +13 -0
  803. package/.ikie/ferments/019f275e-cae6-76d9-8682-d138cbd0e3cf/runtime.json +11 -0
  804. package/.ikie/ferments/019f275e-cb0a-7361-8e72-84e44afa7847/runtime.json +11 -0
  805. package/.ikie/ferments/019f275e-cb67-71dd-a7b7-35d98fca2379/runtime.json +11 -0
  806. package/.ikie/ferments/019f275e-cb8c-75c8-9a02-812c50dbcc28/runtime.json +9 -0
  807. package/.ikie/ferments/019f275e-cba7-74c5-8a0e-facff616ecf0/runtime.json +9 -0
  808. package/.ikie/ferments/019f275e-cbc6-719a-a1e9-86fad18fb0de/runtime.json +11 -0
  809. package/.ikie/ferments/019f275e-cc83-7608-878d-3b107b55db48/runtime.json +11 -0
  810. package/.ikie/ferments/019f275e-cc96-72f9-9e5d-a350ea59c5b7/runtime.json +12 -0
  811. package/.ikie/ferments/019f275e-ccb5-72bf-8ad6-8ea4f87f86c0/runtime.json +11 -0
  812. package/.ikie/ferments/019f275e-ccd9-77de-89ff-25fa626c05b4/runtime.json +11 -0
  813. package/.ikie/ferments/019f275e-ccfb-777a-8a40-1ccaf4c139c4/runtime.json +11 -0
  814. package/.ikie/ferments/019f275e-cd15-7785-be69-1f9ef80faa52/runtime.json +11 -0
  815. package/.ikie/ferments/019f275e-cd31-7629-9034-57bcde8cf8e1/runtime.json +13 -0
  816. package/.ikie/ferments/019f275e-cd56-74be-8cdd-94af39b5593b/runtime.json +11 -0
  817. package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/reviews/phase-phase-1-1.json +41 -0
  818. package/.ikie/ferments/019f275e-db71-73fb-9992-6d52de708265/runtime.json +11 -0
  819. package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/reviews/phase-phase-1-1.json +47 -0
  820. package/.ikie/ferments/019f275e-dbc0-725b-bb55-3eca5072215b/runtime.json +13 -0
  821. package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/reviews/phase-phase-1-1.json +40 -0
  822. package/.ikie/ferments/019f275e-dc11-7320-bc60-fbca50c8e709/runtime.json +9 -0
  823. package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/reviews/phase-phase-1-1.json +40 -0
  824. package/.ikie/ferments/019f275e-dc39-73ee-9d63-d8fbb906d877/runtime.json +9 -0
  825. package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/reviews/phase-phase-1-1.json +40 -0
  826. package/.ikie/ferments/019f275e-dc60-7649-9918-b236d9a16cef/runtime.json +9 -0
  827. package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/reviews/phase-phase-1-1.json +40 -0
  828. package/.ikie/ferments/019f275e-dc83-7030-aa35-3a78b18fadb4/runtime.json +9 -0
  829. package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/reviews/phase-phase-1-1.json +40 -0
  830. package/.ikie/ferments/019f275e-dcb3-706f-b3b0-b44556b7d3cb/runtime.json +9 -0
  831. package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/reviews/phase-phase-1-1.json +62 -0
  832. package/.ikie/ferments/019f275e-dcd6-717c-afe6-82a959a0fcbd/runtime.json +9 -0
  833. package/.ikie/ferments/019f2764-6cde-7610-b409-ee715ca796e8/runtime.json +11 -0
  834. package/.ikie/ferments/019f2764-6cfa-733d-8231-937535e2e6b8/runtime.json +11 -0
  835. package/.ikie/ferments/019f2764-6d11-7611-b216-dcdaa468d686/runtime.json +11 -0
  836. package/.ikie/ferments/019f2764-6d33-728f-901c-4fef8141050d/runtime.json +12 -0
  837. package/.ikie/ferments/019f2764-6d5d-7314-9e98-3851effc803f/runtime.json +11 -0
  838. package/.ikie/ferments/019f2764-6d87-722e-bf53-0dd6182ea7c6/runtime.json +15 -0
  839. package/.ikie/ferments/019f2764-6daa-7052-b766-8aef8e542b88/runtime.json +15 -0
  840. package/.ikie/ferments/019f2764-6dc9-73fc-8665-a3f8b51f7450/runtime.json +15 -0
  841. package/.ikie/ferments/019f2764-6df3-7368-94a2-5369f3276848/runtime.json +13 -0
  842. package/.ikie/ferments/019f2764-6e25-762c-a0e0-0ef60c6e2653/runtime.json +15 -0
  843. package/.ikie/ferments/019f2764-6e58-733d-ab0e-8fad4b2c665e/runtime.json +15 -0
  844. package/.ikie/ferments/019f2764-6ead-742a-afc5-e10a044333ec/runtime.json +11 -0
  845. package/.ikie/ferments/019f2764-6ec9-7566-a4f0-e0d14f80e103/runtime.json +15 -0
  846. package/.ikie/ferments/019f2764-6efe-727d-a81b-36fbde2904b3/runtime.json +15 -0
  847. package/.ikie/ferments/019f2764-6f3d-7292-bbf4-88e9ee6b077e/runtime.json +15 -0
  848. package/.ikie/ferments/019f2764-6f6c-758f-9427-652571b7494f/runtime.json +15 -0
  849. package/.ikie/ferments/019f2764-6faa-700b-8d2d-cbed35957db8/runtime.json +15 -0
  850. package/.ikie/ferments/019f2764-6fcb-71d8-9daf-225746805ba4/runtime.json +15 -0
  851. package/.ikie/ferments/019f2764-6ff0-7573-9208-e236e2969c5a/runtime.json +15 -0
  852. package/.ikie/ferments/019f2764-7012-77ce-97c9-6e99dd0367b3/runtime.json +15 -0
  853. package/.ikie/ferments/019f2764-703d-7554-8008-5104879d081d/runtime.json +15 -0
  854. package/.ikie/ferments/019f2764-7082-7399-80d5-659015dc6129/runtime.json +11 -0
  855. package/.ikie/ferments/019f2764-70b4-7581-b83e-9945010b008b/runtime.json +11 -0
  856. package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/reviews/phase-phase-1-1.json +63 -0
  857. package/.ikie/ferments/019f2764-70d2-71a1-8b2f-1db7c0de5d5b/runtime.json +17 -0
  858. package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/reviews/phase-phase-1-1.json +63 -0
  859. package/.ikie/ferments/019f2764-7256-714b-9804-17a6ad3c7996/runtime.json +17 -0
  860. package/.ikie/ferments/019f2764-742b-711f-9997-ae6ce141d7d9/runtime.json +11 -0
  861. package/.ikie/ferments/019f2764-78e4-765c-bcf6-ae76955d98c0/runtime.json +11 -0
  862. package/.ikie/ferments/019f2764-7900-7573-afaf-c32d1b6a7be0/runtime.json +11 -0
  863. package/.ikie/ferments/019f2764-7920-7463-b2c3-132980285998/runtime.json +11 -0
  864. package/.ikie/ferments/019f2764-7947-721f-9c5e-6fc087b2e912/runtime.json +11 -0
  865. package/.ikie/ferments/019f2764-7967-735b-9066-12a93c490f17/pending-proposal.json +45 -0
  866. package/.ikie/ferments/019f2764-798b-749d-b86b-90c55c838b29/pending-proposal.json +45 -0
  867. package/.ikie/ferments/019f2764-7a9f-747c-81ce-f27825e1cefb/pending-proposal.json +45 -0
  868. package/.ikie/ferments/019f2764-7afc-745a-8d70-a2ebf234977d/pending-proposal.json +45 -0
  869. package/.ikie/ferments/019f2764-7b0f-715d-a410-e707593c0f1b/pending-proposal.json +45 -0
  870. package/.ikie/ferments/019f2764-a49c-750d-8022-8d5ef7b34341/runtime.json +13 -0
  871. package/.ikie/ferments/019f2764-a4c0-7779-a268-1589e2c4d025/runtime.json +11 -0
  872. package/.ikie/ferments/019f2764-a4e2-706f-8cc3-f71f13a5334c/runtime.json +11 -0
  873. package/.ikie/ferments/019f2764-a4fc-765c-b248-0fd90d273737/runtime.json +11 -0
  874. package/.ikie/ferments/019f2764-a511-7719-b577-47d9389dc68c/runtime.json +11 -0
  875. package/.ikie/ferments/019f2764-a524-731c-91d5-99c2242128e7/runtime.json +11 -0
  876. package/.ikie/ferments/019f2764-a53c-7308-a4a2-2c4ebd0af1f2/runtime.json +11 -0
  877. package/.ikie/ferments/019f2764-a555-762a-b6ec-c7a1ea59914b/runtime.json +11 -0
  878. package/.ikie/ferments/019f2764-a56e-776a-8421-d52ce16332e6/runtime.json +9 -0
  879. package/.ikie/ferments/019f2764-a584-75ad-8cf4-02ad739aeac6/runtime.json +13 -0
  880. package/.ikie/ferments/019f2764-a5a6-716c-8803-03dfe8638639/runtime.json +11 -0
  881. package/.ikie/ferments/019f2764-a5cb-75a8-9184-8bc493e04858/runtime.json +11 -0
  882. package/.ikie/ferments/019f2764-a613-726d-9770-828b95668f3d/runtime.json +11 -0
  883. package/.ikie/ferments/019f2764-a62b-703f-ad34-e560da58091f/runtime.json +9 -0
  884. package/.ikie/ferments/019f2764-a646-75a7-a048-e1c6a57c17db/runtime.json +9 -0
  885. package/.ikie/ferments/019f2764-a65d-7369-8043-22e8aa877564/runtime.json +11 -0
  886. package/.ikie/ferments/019f2764-a714-7737-9aca-229d1f730df1/runtime.json +11 -0
  887. package/.ikie/ferments/019f2764-a725-71af-91db-6146483607ce/runtime.json +12 -0
  888. package/.ikie/ferments/019f2764-a748-721c-a9bb-9a5cd1a6390b/runtime.json +11 -0
  889. package/.ikie/ferments/019f2764-a761-7632-84ba-5d4da92e371d/runtime.json +11 -0
  890. package/.ikie/ferments/019f2764-a776-76dd-a48e-148e4d5e6dcd/runtime.json +11 -0
  891. package/.ikie/ferments/019f2764-a78f-77d0-9647-ffb2ed828229/runtime.json +11 -0
  892. package/.ikie/ferments/019f2764-a7ab-716e-958d-c3f3c4d33a34/runtime.json +13 -0
  893. package/.ikie/ferments/019f2764-a7cb-775b-8844-8faa27f1ac1c/runtime.json +11 -0
  894. package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/reviews/phase-phase-1-1.json +41 -0
  895. package/.ikie/ferments/019f2764-bd5e-773d-9b24-9da824db3174/runtime.json +11 -0
  896. package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/reviews/phase-phase-1-1.json +47 -0
  897. package/.ikie/ferments/019f2764-bda9-7207-b421-beff2d49cd2a/runtime.json +13 -0
  898. package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/reviews/phase-phase-1-1.json +40 -0
  899. package/.ikie/ferments/019f2764-be1e-775f-b937-81b9fd368168/runtime.json +9 -0
  900. package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/reviews/phase-phase-1-1.json +40 -0
  901. package/.ikie/ferments/019f2764-be38-7792-b549-8583fd6c5e70/runtime.json +9 -0
  902. package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/reviews/phase-phase-1-1.json +40 -0
  903. package/.ikie/ferments/019f2764-be5e-73da-85c5-508167795c94/runtime.json +9 -0
  904. package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/reviews/phase-phase-1-1.json +40 -0
  905. package/.ikie/ferments/019f2764-be82-721a-aa06-3b54c6236827/runtime.json +9 -0
  906. package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/reviews/phase-phase-1-1.json +40 -0
  907. package/.ikie/ferments/019f2764-be97-703d-8e0a-6496ed0a83ca/runtime.json +9 -0
  908. package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/reviews/phase-phase-1-1.json +62 -0
  909. package/.ikie/ferments/019f2764-bebc-756a-a6ca-0f40b9705a0f/runtime.json +9 -0
  910. package/.ikie/ferments/019f2766-a81a-73aa-ba58-4a0192a7b079/runtime.json +11 -0
  911. package/.ikie/ferments/019f2766-a839-708c-b3bf-4c3f2279558e/runtime.json +11 -0
  912. package/.ikie/ferments/019f2766-a852-7641-a85f-69ea0ce5d73b/runtime.json +11 -0
  913. package/.ikie/ferments/019f2766-a877-74b8-b1de-3ffbbcb6f14b/runtime.json +12 -0
  914. package/.ikie/ferments/019f2766-a892-767d-b447-2e7a666f42f0/runtime.json +11 -0
  915. package/.ikie/ferments/019f2766-a8c2-7178-b06c-00d7646d1966/runtime.json +11 -0
  916. package/.ikie/ferments/019f2766-a8f5-713b-92d4-c4c70e48c5db/runtime.json +15 -0
  917. package/.ikie/ferments/019f2766-a91c-76a8-9d47-7e07b7843506/runtime.json +15 -0
  918. package/.ikie/ferments/019f2766-a944-7458-bae5-e3c38b3eec06/runtime.json +15 -0
  919. package/.ikie/ferments/019f2766-a973-77da-b2c0-d4f59f145d19/runtime.json +13 -0
  920. package/.ikie/ferments/019f2766-a9ae-701f-b8af-2d02369bc2f1/runtime.json +15 -0
  921. package/.ikie/ferments/019f2766-a9e5-7319-882f-58450ee132ea/runtime.json +15 -0
  922. package/.ikie/ferments/019f2766-aa3a-722b-9ed0-f38465896d02/runtime.json +11 -0
  923. package/.ikie/ferments/019f2766-aa58-7389-b25e-688385ff4a7f/runtime.json +15 -0
  924. package/.ikie/ferments/019f2766-aa8c-72f1-8b4e-a5260ac64189/runtime.json +15 -0
  925. package/.ikie/ferments/019f2766-aab7-7310-a9ec-b3027823b960/runtime.json +15 -0
  926. package/.ikie/ferments/019f2766-aae0-714c-b796-491d0c0d0e5b/runtime.json +15 -0
  927. package/.ikie/ferments/019f2766-ab05-740a-9fe0-2882dcad789b/runtime.json +15 -0
  928. package/.ikie/ferments/019f2766-ab2d-7188-9d25-545da08208e3/runtime.json +15 -0
  929. package/.ikie/ferments/019f2766-ab55-71d1-aafa-b6c62c6d7c7c/runtime.json +15 -0
  930. package/.ikie/ferments/019f2766-ab7f-76a1-9cde-c84ebb38a76c/runtime.json +15 -0
  931. package/.ikie/ferments/019f2766-abad-71db-9b6c-c341a91e609c/runtime.json +15 -0
  932. package/.ikie/ferments/019f2766-abd1-7392-a14e-a62f58887e86/runtime.json +11 -0
  933. package/.ikie/ferments/019f2766-abee-7229-9251-77f5474df062/runtime.json +11 -0
  934. package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/reviews/phase-phase-1-1.json +63 -0
  935. package/.ikie/ferments/019f2766-ac13-77ab-ad1f-179bbf19f285/runtime.json +17 -0
  936. package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/reviews/phase-phase-1-1.json +63 -0
  937. package/.ikie/ferments/019f2766-ad4e-771a-8809-da61d5e9187d/runtime.json +17 -0
  938. package/.ikie/ferments/019f2766-aec7-72c7-8400-65d8774d93fe/runtime.json +11 -0
  939. package/.ikie/ferments/019f2766-b2e5-775e-a211-97476c9184fa/runtime.json +11 -0
  940. package/.ikie/ferments/019f2766-b303-70c5-a66a-e39ce29d0a4a/runtime.json +11 -0
  941. package/.ikie/ferments/019f2766-b32e-7618-860c-3cf1a98c2562/runtime.json +11 -0
  942. package/.ikie/ferments/019f2766-b353-719b-9299-207b9a3b41b3/runtime.json +11 -0
  943. package/.ikie/ferments/019f2766-b374-72e3-a804-8f3c82dc2059/pending-proposal.json +45 -0
  944. package/.ikie/ferments/019f2766-b38b-75ca-83c3-d4e5625f814b/pending-proposal.json +45 -0
  945. package/.ikie/ferments/019f2766-b495-73d6-a0d3-b26c033d4769/pending-proposal.json +45 -0
  946. package/.ikie/ferments/019f2766-b4e1-70f8-a38e-c478ab72c091/pending-proposal.json +45 -0
  947. package/.ikie/ferments/019f2766-b4f5-7671-b2c4-76d6f9f68cd3/pending-proposal.json +45 -0
  948. package/.ikie/ferments/019f2766-d341-7410-8d94-056f70b5d884/runtime.json +11 -0
  949. package/.ikie/ferments/019f2766-d35f-71a3-bdd3-c749aa870ff8/runtime.json +11 -0
  950. package/.ikie/ferments/019f2766-d382-70be-9a79-094070335d58/runtime.json +11 -0
  951. package/.ikie/ferments/019f2766-d3ae-75c7-b83e-4636e859cf7d/runtime.json +12 -0
  952. package/.ikie/ferments/019f2766-d3c7-778d-b399-f3e13fa34204/runtime.json +11 -0
  953. package/.ikie/ferments/019f2766-d3f0-7730-9e47-9bbc5483d5c9/runtime.json +11 -0
  954. package/.ikie/ferments/019f2766-d422-74ab-8e0b-6b5f139658b8/runtime.json +15 -0
  955. package/.ikie/ferments/019f2766-d448-7428-94ec-084521c6f60a/runtime.json +15 -0
  956. package/.ikie/ferments/019f2766-d46e-730e-89a6-dd0907baa5aa/runtime.json +15 -0
  957. package/.ikie/ferments/019f2766-d49b-71df-91f7-b4fb8e050c88/runtime.json +13 -0
  958. package/.ikie/ferments/019f2766-d4d6-72fd-b5ab-8aa8554c3ac8/runtime.json +15 -0
  959. package/.ikie/ferments/019f2766-d50b-7146-a0e2-bcc33cbf8168/runtime.json +15 -0
  960. package/.ikie/ferments/019f2766-d54e-7614-a157-8c6225b09552/runtime.json +11 -0
  961. package/.ikie/ferments/019f2766-d571-72f9-ac5f-9a58f8913af1/runtime.json +15 -0
  962. package/.ikie/ferments/019f2766-d5aa-7756-b523-29a10b1f0f93/runtime.json +15 -0
  963. package/.ikie/ferments/019f2766-d5ce-77b9-9746-ca5281e76d1e/runtime.json +15 -0
  964. package/.ikie/ferments/019f2766-d5f2-76ee-92f0-88e85515bb8c/runtime.json +15 -0
  965. package/.ikie/ferments/019f2766-d617-7669-8175-57038e3790b0/runtime.json +15 -0
  966. package/.ikie/ferments/019f2766-d63b-72aa-a6ca-f355b068db00/runtime.json +15 -0
  967. package/.ikie/ferments/019f2766-d664-754e-b827-42f9c6fc161b/runtime.json +15 -0
  968. package/.ikie/ferments/019f2766-d68c-710d-8769-befe67aad042/runtime.json +15 -0
  969. package/.ikie/ferments/019f2766-d6af-767c-9547-eee7f9c08dcf/runtime.json +15 -0
  970. package/.ikie/ferments/019f2766-d6d5-751e-8752-dcdc451712e2/runtime.json +11 -0
  971. package/.ikie/ferments/019f2766-d6f7-77b8-807d-75d914ff0302/runtime.json +11 -0
  972. package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/reviews/phase-phase-1-1.json +63 -0
  973. package/.ikie/ferments/019f2766-d720-7159-97a9-820f305b3805/runtime.json +17 -0
  974. package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/reviews/phase-phase-1-1.json +63 -0
  975. package/.ikie/ferments/019f2766-d87f-729d-be05-90c4adb20ade/runtime.json +17 -0
  976. package/.ikie/ferments/019f2766-da17-724b-ab3c-7154c7845381/runtime.json +11 -0
  977. package/.ikie/ferments/019f2766-ddf5-7470-a884-297c8936753a/runtime.json +11 -0
  978. package/.ikie/ferments/019f2766-de1a-7283-89b6-a249b9c8bdc1/runtime.json +11 -0
  979. package/.ikie/ferments/019f2766-de39-7771-a717-14beb4313f79/runtime.json +11 -0
  980. package/.ikie/ferments/019f2766-de5b-7418-bbcc-2ed38543137c/runtime.json +11 -0
  981. package/.ikie/ferments/019f2766-de7d-76cc-a74f-def9d1d99ac3/pending-proposal.json +45 -0
  982. package/.ikie/ferments/019f2766-de92-75a2-bcae-86efd5efe066/pending-proposal.json +45 -0
  983. package/.ikie/ferments/019f2766-dfb5-771c-adc0-9e948e0b8f18/pending-proposal.json +45 -0
  984. package/.ikie/ferments/019f2766-dff6-71cd-a14e-ab9e88792ca4/pending-proposal.json +45 -0
  985. package/.ikie/ferments/019f2766-e006-727b-83d9-af9c71158bef/pending-proposal.json +45 -0
  986. package/.ikie/ferments/019f2767-0345-74ba-a163-0c909ee37df1/runtime.json +11 -0
  987. package/.ikie/ferments/019f2767-036c-713d-9ef9-58a1191bd341/runtime.json +11 -0
  988. package/.ikie/ferments/019f2767-0387-72e6-b8b6-314fedade6e0/runtime.json +11 -0
  989. package/.ikie/ferments/019f2767-03af-738b-acde-360fa30a55f8/runtime.json +12 -0
  990. package/.ikie/ferments/019f2767-03cc-76e8-ae01-5b33c85fb46b/runtime.json +11 -0
  991. package/.ikie/ferments/019f2767-0409-7745-8f9d-a41ce8b7b11e/runtime.json +11 -0
  992. package/.ikie/ferments/019f2767-0467-70a9-8a75-2688109ab9c3/runtime.json +15 -0
  993. package/.ikie/ferments/019f2767-0493-7047-b2c9-a7ed6f70c89f/runtime.json +15 -0
  994. package/.ikie/ferments/019f2767-04b7-7486-a7cf-5ad7a09060a7/runtime.json +15 -0
  995. package/.ikie/ferments/019f2767-050f-713f-ba94-c01b549b3dfa/runtime.json +13 -0
  996. package/.ikie/ferments/019f2767-0561-7481-90da-2febe6cffddd/runtime.json +15 -0
  997. package/.ikie/ferments/019f2767-059c-74bb-b3fb-5e762939b3f6/runtime.json +15 -0
  998. package/.ikie/ferments/019f2767-05f6-7778-87d7-bd17f16cbfb5/runtime.json +11 -0
  999. package/.ikie/ferments/019f2767-0621-765e-9af4-4fd53e8fa0ec/runtime.json +15 -0
  1000. package/.ikie/ferments/019f2767-0652-77a4-86f8-fd32c3d03927/runtime.json +15 -0
  1001. package/.ikie/ferments/019f2767-067b-734b-85e5-cd7fc79c73cb/runtime.json +15 -0
  1002. package/.ikie/ferments/019f2767-06aa-71fa-a287-db9463cdae51/runtime.json +15 -0
  1003. package/.ikie/ferments/019f2767-06d5-771d-8f7b-cb18b2f9f122/runtime.json +15 -0
  1004. package/.ikie/ferments/019f2767-070a-7043-87fe-09012eaea4d6/runtime.json +15 -0
  1005. package/.ikie/ferments/019f2767-0733-707e-b141-7af7e0e43e30/runtime.json +15 -0
  1006. package/.ikie/ferments/019f2767-0751-7478-ae88-39af753f8f08/runtime.json +15 -0
  1007. package/.ikie/ferments/019f2767-0791-73af-be60-fe5a809f66bc/runtime.json +15 -0
  1008. package/.ikie/ferments/019f2767-07c5-720a-b9b7-1f96816c4122/runtime.json +11 -0
  1009. package/.ikie/ferments/019f2767-07e4-74fc-bf92-5f4c9c1cefab/runtime.json +11 -0
  1010. package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/reviews/phase-phase-1-1.json +63 -0
  1011. package/.ikie/ferments/019f2767-080c-77c8-a174-e8b97bd69510/runtime.json +17 -0
  1012. package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/reviews/phase-phase-1-1.json +63 -0
  1013. package/.ikie/ferments/019f2767-0986-7509-b1d0-7650aae65deb/runtime.json +17 -0
  1014. package/.ikie/ferments/019f2767-0b6e-7011-aec4-f728f98727ed/runtime.json +11 -0
  1015. package/.ikie/ferments/019f2767-10a6-75cc-850a-34d704f7eac9/runtime.json +11 -0
  1016. package/.ikie/ferments/019f2767-10cf-70aa-a00c-086ec4813201/runtime.json +11 -0
  1017. package/.ikie/ferments/019f2767-1101-74f7-8518-da795dd7aef7/runtime.json +11 -0
  1018. package/.ikie/ferments/019f2767-1140-738e-b9ce-35b94e415549/runtime.json +11 -0
  1019. package/.ikie/ferments/019f2767-1172-75a9-8f24-74316bfc7d53/pending-proposal.json +45 -0
  1020. package/.ikie/ferments/019f2767-118b-7048-a5d7-cffbef0e44e2/pending-proposal.json +45 -0
  1021. package/.ikie/ferments/019f2767-12be-730b-92b2-0bba958b78a1/pending-proposal.json +45 -0
  1022. package/.ikie/ferments/019f2767-131f-720b-b45a-382835a523ef/pending-proposal.json +45 -0
  1023. package/.ikie/ferments/019f2767-1335-74eb-b84c-9af1e9e52ff0/pending-proposal.json +45 -0
  1024. package/.ikie/ferments/019f2767-4563-715a-8c3c-cadf61ab94cf/runtime.json +13 -0
  1025. package/.ikie/ferments/019f2767-45b2-701b-990c-a8a30ff2c5f2/runtime.json +11 -0
  1026. package/.ikie/ferments/019f2767-45d7-705e-a8fc-202c2c894d5f/runtime.json +11 -0
  1027. package/.ikie/ferments/019f2767-45ee-773f-a4e7-6022c91b113c/runtime.json +11 -0
  1028. package/.ikie/ferments/019f2767-4613-7769-b4fa-6abde054e49d/runtime.json +11 -0
  1029. package/.ikie/ferments/019f2767-4626-704a-9d3e-6d51ff2c45c6/runtime.json +11 -0
  1030. package/.ikie/ferments/019f2767-4637-7346-b00e-35216ec55688/runtime.json +11 -0
  1031. package/.ikie/ferments/019f2767-4649-709c-9269-7d92ac49807a/runtime.json +11 -0
  1032. package/.ikie/ferments/019f2767-465e-76ec-a7c0-c63d79f0807f/runtime.json +9 -0
  1033. package/.ikie/ferments/019f2767-4679-76c1-8e62-1c105c4c6b0b/runtime.json +13 -0
  1034. package/.ikie/ferments/019f2767-4692-762a-963b-a53456d259fc/runtime.json +11 -0
  1035. package/.ikie/ferments/019f2767-46a7-7236-9510-fd0d5ecf273f/runtime.json +11 -0
  1036. package/.ikie/ferments/019f2767-46ee-705c-ad1a-e028ca79062a/runtime.json +11 -0
  1037. package/.ikie/ferments/019f2767-4702-741b-bb09-b4fd8cd9f15a/runtime.json +9 -0
  1038. package/.ikie/ferments/019f2767-4720-7192-9e90-89cc2710255a/runtime.json +9 -0
  1039. package/.ikie/ferments/019f2767-475f-70dc-9883-271aaa69c2b4/runtime.json +11 -0
  1040. package/.ikie/ferments/019f2767-4852-749f-9c8b-920b2c2b25d3/runtime.json +11 -0
  1041. package/.ikie/ferments/019f2767-486c-7309-a9ff-92579b04dc8c/runtime.json +12 -0
  1042. package/.ikie/ferments/019f2767-4899-771f-9f50-89e448dff488/runtime.json +11 -0
  1043. package/.ikie/ferments/019f2767-48ae-7328-a163-a959e2087743/runtime.json +11 -0
  1044. package/.ikie/ferments/019f2767-48ce-717a-828c-6b765da0a306/runtime.json +11 -0
  1045. package/.ikie/ferments/019f2767-48ef-707c-a17e-9db9da0eee1f/runtime.json +11 -0
  1046. package/.ikie/ferments/019f2767-490b-704b-9369-05fcbb050e2b/runtime.json +13 -0
  1047. package/.ikie/ferments/019f2767-4938-752e-a022-f76dadf8fcaf/runtime.json +11 -0
  1048. package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/reviews/phase-phase-1-1.json +41 -0
  1049. package/.ikie/ferments/019f2767-5cc6-73b9-b8e4-cb3719bbdc8d/runtime.json +11 -0
  1050. package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/reviews/phase-phase-1-1.json +47 -0
  1051. package/.ikie/ferments/019f2767-5d22-7419-840b-e18d2fe5a41d/runtime.json +13 -0
  1052. package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/reviews/phase-phase-1-1.json +40 -0
  1053. package/.ikie/ferments/019f2767-5d8c-75b0-bf28-5a0781cd0686/runtime.json +9 -0
  1054. package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/reviews/phase-phase-1-1.json +40 -0
  1055. package/.ikie/ferments/019f2767-5dae-76e9-b23a-366527e3a529/runtime.json +9 -0
  1056. package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/reviews/phase-phase-1-1.json +40 -0
  1057. package/.ikie/ferments/019f2767-5dd4-73bf-821e-d74e53b266e1/runtime.json +9 -0
  1058. package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/reviews/phase-phase-1-1.json +40 -0
  1059. package/.ikie/ferments/019f2767-5de9-7518-a677-02b4926a0196/runtime.json +9 -0
  1060. package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/reviews/phase-phase-1-1.json +40 -0
  1061. package/.ikie/ferments/019f2767-5dff-772a-b855-57afbb5e9c7e/runtime.json +9 -0
  1062. package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/reviews/phase-phase-1-1.json +62 -0
  1063. package/.ikie/ferments/019f2767-5e39-76a5-8dcc-6f9004f4a58e/runtime.json +9 -0
  1064. package/.ikie/ferments/019f2769-b766-74eb-844e-9903bf64f06d/runtime.json +11 -0
  1065. package/.ikie/ferments/019f2769-b784-72fa-a138-7bdc2fc6e070/runtime.json +11 -0
  1066. package/.ikie/ferments/019f2769-b79d-745b-b577-2ee15d5649b0/runtime.json +11 -0
  1067. package/.ikie/ferments/019f2769-b7c3-75be-9db0-360b0deea44b/runtime.json +12 -0
  1068. package/.ikie/ferments/019f2769-b7e0-758f-bd6a-734520ad3afa/runtime.json +11 -0
  1069. package/.ikie/ferments/019f2769-b807-721e-8827-30e490c8823c/runtime.json +11 -0
  1070. package/.ikie/ferments/019f2769-b836-727d-9c7f-b5a5f03dcc56/runtime.json +15 -0
  1071. package/.ikie/ferments/019f2769-b858-76ae-9fe0-b56d97afdf9b/runtime.json +15 -0
  1072. package/.ikie/ferments/019f2769-b87a-716c-9c81-14f1fa52f217/runtime.json +15 -0
  1073. package/.ikie/ferments/019f2769-b8a2-73dc-9d6d-ac781b700816/runtime.json +13 -0
  1074. package/.ikie/ferments/019f2769-b8d1-7689-9405-e97b063ec3a1/runtime.json +15 -0
  1075. package/.ikie/ferments/019f2769-b904-7154-8946-12e041f89921/runtime.json +15 -0
  1076. package/.ikie/ferments/019f2769-b941-713f-8e2b-1a608dec7ca6/runtime.json +11 -0
  1077. package/.ikie/ferments/019f2769-b95b-7122-bb5d-0bb3a2ad220a/runtime.json +15 -0
  1078. package/.ikie/ferments/019f2769-b97d-728d-b8fb-b1f302b1d819/runtime.json +15 -0
  1079. package/.ikie/ferments/019f2769-b99d-747b-853b-e415c006bfd2/runtime.json +15 -0
  1080. package/.ikie/ferments/019f2769-b9c0-76d6-a254-fba31ac6b662/runtime.json +15 -0
  1081. package/.ikie/ferments/019f2769-b9dd-7349-b246-95853d5d3af0/runtime.json +15 -0
  1082. package/.ikie/ferments/019f2769-b9fe-774f-80cd-06bfedd8a956/runtime.json +15 -0
  1083. package/.ikie/ferments/019f2769-ba1e-70d2-af18-3ea245abc903/runtime.json +15 -0
  1084. package/.ikie/ferments/019f2769-ba45-7730-aae9-9ca14bc6a81b/runtime.json +15 -0
  1085. package/.ikie/ferments/019f2769-ba72-7273-903c-d33bcd036a6b/runtime.json +15 -0
  1086. package/.ikie/ferments/019f2769-ba93-70f3-8884-7b067dd711a4/runtime.json +11 -0
  1087. package/.ikie/ferments/019f2769-baad-714f-8207-a7d630f37e84/runtime.json +11 -0
  1088. package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/reviews/phase-phase-1-1.json +63 -0
  1089. package/.ikie/ferments/019f2769-bac7-75ae-95cb-dda85f7fd6a8/runtime.json +17 -0
  1090. package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/reviews/phase-phase-1-1.json +63 -0
  1091. package/.ikie/ferments/019f2769-bbf3-745d-87d3-d594593afbf0/runtime.json +17 -0
  1092. package/.ikie/ferments/019f2769-bd4e-735d-b931-2077f62d385a/runtime.json +11 -0
  1093. package/.ikie/ferments/019f2769-c103-723f-aebe-ab3ae76aedd9/runtime.json +11 -0
  1094. package/.ikie/ferments/019f2769-c11e-771a-b365-96bf54691b95/runtime.json +11 -0
  1095. package/.ikie/ferments/019f2769-c13b-749e-840d-5136528371f3/runtime.json +11 -0
  1096. package/.ikie/ferments/019f2769-c15a-7065-83b5-2064b699a6d9/runtime.json +11 -0
  1097. package/.ikie/ferments/019f2769-c175-77b2-80df-918134508175/pending-proposal.json +45 -0
  1098. package/.ikie/ferments/019f2769-c189-7508-8a46-3ff461bf759f/pending-proposal.json +45 -0
  1099. package/.ikie/ferments/019f2769-c27c-71eb-910f-36daf69588f8/pending-proposal.json +45 -0
  1100. package/.ikie/ferments/019f2769-c2c5-71bd-b6a6-dd0f8365cc7c/pending-proposal.json +45 -0
  1101. package/.ikie/ferments/019f2769-c2d6-7260-bab6-3e46b6e9100c/pending-proposal.json +45 -0
  1102. package/.ikie/ferments/019f2769-e6d9-700b-a486-64cad0909610/runtime.json +11 -0
  1103. package/.ikie/ferments/019f2769-e6f5-7524-955a-dd4d91813ee5/runtime.json +11 -0
  1104. package/.ikie/ferments/019f2769-e713-715e-9450-42b5250709c8/runtime.json +11 -0
  1105. package/.ikie/ferments/019f2769-e738-7537-b5d5-5209200233da/runtime.json +12 -0
  1106. package/.ikie/ferments/019f2769-e769-752f-b806-14f369200356/runtime.json +11 -0
  1107. package/.ikie/ferments/019f2769-e795-77e8-bc69-fa7496923f00/runtime.json +15 -0
  1108. package/.ikie/ferments/019f2769-e7bb-72a8-ba2a-6d90fe6003cc/runtime.json +15 -0
  1109. package/.ikie/ferments/019f2769-e7e1-719b-becd-d456fe580bf8/runtime.json +15 -0
  1110. package/.ikie/ferments/019f2769-e80b-7539-ac23-4ccf01499e01/runtime.json +13 -0
  1111. package/.ikie/ferments/019f2769-e83e-77c7-8415-7b3e76c827b1/runtime.json +15 -0
  1112. package/.ikie/ferments/019f2769-e86c-7008-8cdb-4d2ae411fc57/runtime.json +15 -0
  1113. package/.ikie/ferments/019f2769-e8ac-7480-b1cc-6913e20e012f/runtime.json +11 -0
  1114. package/.ikie/ferments/019f2769-e8ca-76bd-b0be-bee2f2a97d7d/runtime.json +15 -0
  1115. package/.ikie/ferments/019f2769-e904-7759-b2aa-dbb47427c11b/runtime.json +15 -0
  1116. package/.ikie/ferments/019f2769-e92a-7285-bbd7-ed4220ac3f44/runtime.json +15 -0
  1117. package/.ikie/ferments/019f2769-e95e-77eb-9e17-6b2ad4532f0c/runtime.json +15 -0
  1118. package/.ikie/ferments/019f2769-e992-75ea-adf9-53f548b600a0/runtime.json +15 -0
  1119. package/.ikie/ferments/019f2769-e9b9-75bc-ab7a-a4ba5e8f1124/runtime.json +15 -0
  1120. package/.ikie/ferments/019f2769-e9ec-700b-990f-320c347ee271/runtime.json +15 -0
  1121. package/.ikie/ferments/019f2769-ea15-72cb-96af-a45603082ee1/runtime.json +15 -0
  1122. package/.ikie/ferments/019f2769-ea42-735c-b71e-259c75688841/runtime.json +15 -0
  1123. package/.ikie/ferments/019f2769-ea6f-7074-acde-65385abd199a/runtime.json +11 -0
  1124. package/.ikie/ferments/019f2769-ea98-759c-aeda-90b28cab640c/runtime.json +11 -0
  1125. package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/reviews/phase-phase-1-1.json +63 -0
  1126. package/.ikie/ferments/019f2769-eac3-70a7-993e-435d9a1dfd91/runtime.json +17 -0
  1127. package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/reviews/phase-phase-1-1.json +63 -0
  1128. package/.ikie/ferments/019f2769-ec3c-7674-829a-fba66a9bc62e/runtime.json +17 -0
  1129. package/.ikie/ferments/019f2769-edcb-748c-be28-51e21c608c6f/runtime.json +11 -0
  1130. package/.ikie/ferments/019f2769-f2df-7759-811f-ef76a54375e8/runtime.json +11 -0
  1131. package/.ikie/ferments/019f2769-f311-7641-88b0-81c54945642f/runtime.json +11 -0
  1132. package/.ikie/ferments/019f2769-f363-723b-80f1-b52334dc6a15/runtime.json +11 -0
  1133. package/.ikie/ferments/019f2769-f38e-72cc-a4ac-81cefc3a95f4/runtime.json +11 -0
  1134. package/.ikie/ferments/019f2769-f3b6-763a-bf65-011ce164f5d4/pending-proposal.json +45 -0
  1135. package/.ikie/ferments/019f2769-f3c7-745e-9da1-37e14b1cfddf/pending-proposal.json +45 -0
  1136. package/.ikie/ferments/019f2769-f4e4-71b1-83f1-b16014904ec3/pending-proposal.json +45 -0
  1137. package/.ikie/ferments/019f2769-f556-761d-b331-acc7cc02317d/pending-proposal.json +45 -0
  1138. package/.ikie/ferments/019f2769-f56d-77af-82f3-b9915ca80a61/pending-proposal.json +45 -0
  1139. package/.ikie/ferments/019f276a-23f9-7653-8be0-dca748ac5e0f/runtime.json +13 -0
  1140. package/.ikie/ferments/019f276a-2428-731f-959b-8d346551f0c4/runtime.json +11 -0
  1141. package/.ikie/ferments/019f276a-2446-7250-be5c-bdb0ac1ef2fa/runtime.json +11 -0
  1142. package/.ikie/ferments/019f276a-2462-764e-a7f4-d9ab3876fbd2/runtime.json +11 -0
  1143. package/.ikie/ferments/019f276a-2482-768b-919e-d81a0709abd5/runtime.json +11 -0
  1144. package/.ikie/ferments/019f276a-2494-77ee-8b28-72b9b0d19d56/runtime.json +11 -0
  1145. package/.ikie/ferments/019f276a-24aa-76fd-8fba-2a1d73960010/runtime.json +11 -0
  1146. package/.ikie/ferments/019f276a-24c3-7799-bd35-0a3374f3e469/runtime.json +11 -0
  1147. package/.ikie/ferments/019f276a-24f1-7498-a372-975f72302a0d/runtime.json +9 -0
  1148. package/.ikie/ferments/019f276a-251e-71ac-ba90-af2a49c22b6b/runtime.json +13 -0
  1149. package/.ikie/ferments/019f276a-2545-746f-bdf3-ca3c11ab9968/runtime.json +11 -0
  1150. package/.ikie/ferments/019f276a-256d-765b-9f94-90047d4ca21e/runtime.json +11 -0
  1151. package/.ikie/ferments/019f276a-25cb-753b-9905-7250e4eea970/runtime.json +11 -0
  1152. package/.ikie/ferments/019f276a-25f8-73a2-aede-f2c017fa80c9/runtime.json +9 -0
  1153. package/.ikie/ferments/019f276a-2613-774b-80c0-3b206ac95435/runtime.json +9 -0
  1154. package/.ikie/ferments/019f276a-264e-73a3-90ad-017ef8ea05b6/runtime.json +11 -0
  1155. package/.ikie/ferments/019f276a-2760-758f-b0a6-cd04a8b0ee76/runtime.json +11 -0
  1156. package/.ikie/ferments/019f276a-277b-73a9-8655-6bf7018262dc/runtime.json +12 -0
  1157. package/.ikie/ferments/019f276a-27a6-709d-a90f-f1784e248fca/runtime.json +11 -0
  1158. package/.ikie/ferments/019f276a-27b7-75bf-b0b5-013581917821/runtime.json +11 -0
  1159. package/.ikie/ferments/019f276a-27ce-759a-93de-474988efc050/runtime.json +11 -0
  1160. package/.ikie/ferments/019f276a-27e9-7564-999a-73beef96d35c/runtime.json +11 -0
  1161. package/.ikie/ferments/019f276a-27fc-714b-9ddb-117b439b664e/runtime.json +13 -0
  1162. package/.ikie/ferments/019f276a-2824-762e-8def-3c17aa4041f9/runtime.json +11 -0
  1163. package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/reviews/phase-phase-1-1.json +41 -0
  1164. package/.ikie/ferments/019f276a-38fe-725b-9c16-f1b5174302d0/runtime.json +11 -0
  1165. package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/reviews/phase-phase-1-1.json +47 -0
  1166. package/.ikie/ferments/019f276a-393c-75e2-b29f-092b82105a74/runtime.json +13 -0
  1167. package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/reviews/phase-phase-1-1.json +40 -0
  1168. package/.ikie/ferments/019f276a-3990-75f9-9b6f-ab6d45bf8e32/runtime.json +9 -0
  1169. package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/reviews/phase-phase-1-1.json +40 -0
  1170. package/.ikie/ferments/019f276a-39ab-76bb-be69-8658a1b6a76f/runtime.json +9 -0
  1171. package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/reviews/phase-phase-1-1.json +40 -0
  1172. package/.ikie/ferments/019f276a-39c9-76ac-95a8-2d5575d26573/runtime.json +9 -0
  1173. package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/reviews/phase-phase-1-1.json +40 -0
  1174. package/.ikie/ferments/019f276a-39f6-76cc-9011-3f6b08068155/runtime.json +9 -0
  1175. package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/reviews/phase-phase-1-1.json +40 -0
  1176. package/.ikie/ferments/019f276a-3a0c-76a9-80b2-2bb7952fe9d7/runtime.json +9 -0
  1177. package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/reviews/phase-phase-1-1.json +62 -0
  1178. package/.ikie/ferments/019f276a-3a22-7140-8a4d-0d17ada653b3/runtime.json +9 -0
  1179. package/.ikie/ferments/019f276c-2f88-74ae-8bc2-5cec42d56757/runtime.json +11 -0
  1180. package/.ikie/ferments/019f276c-2fb8-7599-b61c-e73c85399ee0/runtime.json +11 -0
  1181. package/.ikie/ferments/019f276c-2fd9-75db-8e13-8e9137cecedd/runtime.json +11 -0
  1182. package/.ikie/ferments/019f276c-302f-760f-97e7-2f10f283dfe1/runtime.json +12 -0
  1183. package/.ikie/ferments/019f276c-3060-77ca-a0e3-d49781feca6d/runtime.json +11 -0
  1184. package/.ikie/ferments/019f276c-3091-744e-9394-a59b9f37db9e/runtime.json +11 -0
  1185. package/.ikie/ferments/019f276c-30da-76ba-bd76-a72e053f218d/runtime.json +15 -0
  1186. package/.ikie/ferments/019f276c-3110-7277-ab9a-820992db76da/runtime.json +15 -0
  1187. package/.ikie/ferments/019f276c-314a-740f-b533-a31c4e9ebd52/runtime.json +15 -0
  1188. package/.ikie/ferments/019f276c-3189-732c-a4ec-09e4f1e3a8da/runtime.json +13 -0
  1189. package/.ikie/ferments/019f276c-31ce-75c8-a4e9-507d408920b6/runtime.json +15 -0
  1190. package/.ikie/ferments/019f276c-320e-710b-b32a-4577244dcc6a/runtime.json +15 -0
  1191. package/.ikie/ferments/019f276c-3262-7611-af21-ad12693acdd5/runtime.json +11 -0
  1192. package/.ikie/ferments/019f276c-3288-7559-b7c3-299dd548decb/runtime.json +15 -0
  1193. package/.ikie/ferments/019f276c-32c4-70a0-899d-ad17469a015c/runtime.json +15 -0
  1194. package/.ikie/ferments/019f276c-32f0-7036-86ae-19c9f703cd9a/runtime.json +15 -0
  1195. package/.ikie/ferments/019f276c-3324-7021-8f89-d46fbfa45e00/runtime.json +15 -0
  1196. package/.ikie/ferments/019f276c-334b-71df-b20d-d9a7bcccdc0a/runtime.json +15 -0
  1197. package/.ikie/ferments/019f276c-3379-7593-957a-ee9631368280/runtime.json +15 -0
  1198. package/.ikie/ferments/019f276c-33a9-705d-a590-eff1c46bcd67/runtime.json +15 -0
  1199. package/.ikie/ferments/019f276c-33d5-7784-b35a-01d3c06b16c0/runtime.json +15 -0
  1200. package/.ikie/ferments/019f276c-341c-76ce-b950-7a7e7472eeb8/runtime.json +15 -0
  1201. package/.ikie/ferments/019f276c-3462-744d-b42a-9756a33b7223/runtime.json +11 -0
  1202. package/.ikie/ferments/019f276c-348e-706a-9791-5213dfd00593/runtime.json +11 -0
  1203. package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/reviews/phase-phase-1-1.json +63 -0
  1204. package/.ikie/ferments/019f276c-34b6-70f9-b678-d3a7d876758c/runtime.json +17 -0
  1205. package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/reviews/phase-phase-1-1.json +63 -0
  1206. package/.ikie/ferments/019f276c-3640-75da-915e-b0dba80bfcda/runtime.json +17 -0
  1207. package/.ikie/ferments/019f276c-37df-76f9-b7a8-1285ee0ac11d/runtime.json +11 -0
  1208. package/.ikie/ferments/019f276c-3caa-748a-a0aa-9e068f18f2ac/runtime.json +11 -0
  1209. package/.ikie/ferments/019f276c-3cc8-7347-9764-dd4ab7f87646/runtime.json +11 -0
  1210. package/.ikie/ferments/019f276c-3cef-75dd-be90-593fd20a850d/runtime.json +11 -0
  1211. package/.ikie/ferments/019f276c-3d14-72af-ae89-6c0605227a05/runtime.json +11 -0
  1212. package/.ikie/ferments/019f276c-3d36-716c-ac4e-59444fdec814/pending-proposal.json +45 -0
  1213. package/.ikie/ferments/019f276c-3d4c-7208-9130-7f168aeba08e/pending-proposal.json +45 -0
  1214. package/.ikie/ferments/019f276c-3e7f-7552-a37f-61442d720fb9/pending-proposal.json +45 -0
  1215. package/.ikie/ferments/019f276c-3ed9-74f2-9332-d5a492d39130/pending-proposal.json +45 -0
  1216. package/.ikie/ferments/019f276c-3ef4-757e-b0c6-9d7c6f0326e7/pending-proposal.json +45 -0
  1217. package/.ikie/ferments/019f276c-651d-70ac-bfb4-5d033388e28c/runtime.json +13 -0
  1218. package/.ikie/ferments/019f276c-6546-7569-b609-74b2258985a8/runtime.json +11 -0
  1219. package/.ikie/ferments/019f276c-6566-71e2-b937-390aea78900a/runtime.json +11 -0
  1220. package/.ikie/ferments/019f276c-657c-75ee-864b-5b5601e3b9d1/runtime.json +11 -0
  1221. package/.ikie/ferments/019f276c-6590-7729-a6e7-466ace311e0d/runtime.json +11 -0
  1222. package/.ikie/ferments/019f276c-65a5-779f-a3da-36bc91cf31f3/runtime.json +11 -0
  1223. package/.ikie/ferments/019f276c-65b9-77f0-97fc-fcf70d7125b8/runtime.json +11 -0
  1224. package/.ikie/ferments/019f276c-65cd-74ef-9094-db3c5a98348b/runtime.json +11 -0
  1225. package/.ikie/ferments/019f276c-65e3-7632-9df9-58cfa083a065/runtime.json +9 -0
  1226. package/.ikie/ferments/019f276c-65fb-763a-aec7-54ece64d7342/runtime.json +13 -0
  1227. package/.ikie/ferments/019f276c-661a-74e9-81b1-d1ba625c04b0/runtime.json +11 -0
  1228. package/.ikie/ferments/019f276c-6630-7748-ab90-869f75ed2de5/runtime.json +11 -0
  1229. package/.ikie/ferments/019f276c-6670-758f-b0da-673d81bd319e/runtime.json +11 -0
  1230. package/.ikie/ferments/019f276c-6687-71fa-8286-2d25de36c9b4/runtime.json +9 -0
  1231. package/.ikie/ferments/019f276c-669d-7679-91d5-4df6315d3823/runtime.json +9 -0
  1232. package/.ikie/ferments/019f276c-66b3-72a6-974d-1bc3477eb6f2/runtime.json +11 -0
  1233. package/.ikie/ferments/019f276c-6769-776c-9868-0c929ee31f5f/runtime.json +11 -0
  1234. package/.ikie/ferments/019f276c-678e-7588-a059-c1efd9e9c9a6/runtime.json +12 -0
  1235. package/.ikie/ferments/019f276c-67af-729c-a5f8-79e8e78bbe9b/runtime.json +11 -0
  1236. package/.ikie/ferments/019f276c-67c3-70b8-8606-aad72ab0cd6f/runtime.json +11 -0
  1237. package/.ikie/ferments/019f276c-67d7-734c-83fd-132c54564004/runtime.json +11 -0
  1238. package/.ikie/ferments/019f276c-67ec-710d-8497-eba65301d741/runtime.json +11 -0
  1239. package/.ikie/ferments/019f276c-6805-742c-8a1c-f370733226ae/runtime.json +13 -0
  1240. package/.ikie/ferments/019f276c-6825-7768-8ca1-f5dac5c1d374/runtime.json +11 -0
  1241. package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/reviews/phase-phase-1-1.json +41 -0
  1242. package/.ikie/ferments/019f276c-7f49-751d-bbb8-f828debd3cb9/runtime.json +11 -0
  1243. package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/reviews/phase-phase-1-1.json +47 -0
  1244. package/.ikie/ferments/019f276c-7f7b-74d0-b46e-e8efa73fb5b5/runtime.json +13 -0
  1245. package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/reviews/phase-phase-1-1.json +40 -0
  1246. package/.ikie/ferments/019f276c-8004-74fe-b37f-f9fc659f7f0c/runtime.json +9 -0
  1247. package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/reviews/phase-phase-1-1.json +40 -0
  1248. package/.ikie/ferments/019f276c-8025-7328-afef-6703215c208c/runtime.json +9 -0
  1249. package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/reviews/phase-phase-1-1.json +40 -0
  1250. package/.ikie/ferments/019f276c-8043-749c-8cbb-47d0df9819df/runtime.json +9 -0
  1251. package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/reviews/phase-phase-1-1.json +40 -0
  1252. package/.ikie/ferments/019f276c-8062-7436-99eb-80e09bc6b067/runtime.json +9 -0
  1253. package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/reviews/phase-phase-1-1.json +40 -0
  1254. package/.ikie/ferments/019f276c-8081-727c-aa11-d606a64b88ed/runtime.json +9 -0
  1255. package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/reviews/phase-phase-1-1.json +62 -0
  1256. package/.ikie/ferments/019f276c-80b6-7528-8687-e11cc4691930/runtime.json +9 -0
  1257. package/AGENTS.md +120 -0
  1258. package/CLA.md +39 -0
  1259. package/CODE_OF_CONDUCT.md +83 -0
  1260. package/CONTRIBUTING.md +57 -0
  1261. package/LICENSE +203 -0
  1262. package/NOTICE +28 -0
  1263. package/README.md +568 -0
  1264. package/SECURITY.md +36 -0
  1265. package/TODO.md +33 -0
  1266. package/benchmark/audit-session/README.md +217 -0
  1267. package/benchmark/audit-session/audit-session-prompt.md +557 -0
  1268. package/benchmark/audit-session/audit-session.sh +323 -0
  1269. package/benchmark/manual/README.md +166 -0
  1270. package/benchmark/manual/__pycache__/check-session.cpython-313.pyc +0 -0
  1271. package/benchmark/manual/analyze-session.py +290 -0
  1272. package/benchmark/manual/benchmark.json +4 -0
  1273. package/benchmark/manual/check-session.py +268 -0
  1274. package/benchmark/manual/compare-sessions.py +118 -0
  1275. package/benchmark/manual/lib.sh +284 -0
  1276. package/benchmark/manual/new-session-claude.sh +86 -0
  1277. package/benchmark/manual/new-session.sh +191 -0
  1278. package/benchmark/manual/run-evaluation.sh +201 -0
  1279. package/benchmark/manual/seeds/explore-refactor/cmd/server/main.go +37 -0
  1280. package/benchmark/manual/seeds/explore-refactor/go.mod +3 -0
  1281. package/benchmark/manual/seeds/explore-refactor/internal/handler/audit.go +39 -0
  1282. package/benchmark/manual/seeds/explore-refactor/internal/handler/invitation.go +56 -0
  1283. package/benchmark/manual/seeds/explore-refactor/internal/handler/team.go +86 -0
  1284. package/benchmark/manual/seeds/explore-refactor/internal/handler/user.go +126 -0
  1285. package/benchmark/manual/seeds/explore-refactor/internal/model/model.go +37 -0
  1286. package/benchmark/manual/seeds/explore-refactor/internal/repository/audit.go +57 -0
  1287. package/benchmark/manual/seeds/explore-refactor/internal/repository/invitation.go +58 -0
  1288. package/benchmark/manual/seeds/explore-refactor/internal/repository/team.go +66 -0
  1289. package/benchmark/manual/seeds/explore-refactor/internal/repository/user.go +91 -0
  1290. package/benchmark/manual/seeds/explore-refactor/internal/service/invitation.go +45 -0
  1291. package/benchmark/manual/seeds/explore-refactor/internal/service/team.go +62 -0
  1292. package/benchmark/manual/seeds/explore-refactor/internal/service/user.go +94 -0
  1293. package/benchmark/manual/self-improvement.md +203 -0
  1294. package/benchmark/manual/session-summary.py +95 -0
  1295. package/benchmark/manual/start-self-improvement.sh +27 -0
  1296. package/benchmark/manual/tasks.md +154 -0
  1297. package/benchmark/terminal-bench-2/README.md +261 -0
  1298. package/benchmark/terminal-bench-2/config/retry.yaml +48 -0
  1299. package/benchmark/terminal-bench-2/docs/ferment-terminal-bench-analysis.md +233 -0
  1300. package/benchmark/terminal-bench-2/pyproject.toml +32 -0
  1301. package/benchmark/terminal-bench-2/scripts/analyze-ferment-bench.py +1193 -0
  1302. package/benchmark/terminal-bench-2/scripts/run-claude-code-ikie.sh +41 -0
  1303. package/benchmark/terminal-bench-2/scripts/run-gsd-ikie.sh +29 -0
  1304. package/benchmark/terminal-bench-2/scripts/run-local.sh +32 -0
  1305. package/benchmark/terminal-bench-2/scripts/run-opencode-ikie.sh +30 -0
  1306. package/benchmark/terminal-bench-2/scripts/run-release.sh +28 -0
  1307. package/benchmark/terminal-bench-2/src/ikie_agent/__init__.py +6 -0
  1308. package/benchmark/terminal-bench-2/src/ikie_agent/agent.py +445 -0
  1309. package/benchmark/terminal-bench-2/src/ikie_agent/agent_test.py +233 -0
  1310. package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie.py +356 -0
  1311. package/benchmark/terminal-bench-2/src/ikie_agent/claude_code_ikie_test.py +506 -0
  1312. package/benchmark/terminal-bench-2/src/ikie_agent/config.py +56 -0
  1313. package/benchmark/terminal-bench-2/src/ikie_agent/gateway.py +163 -0
  1314. package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie.py +340 -0
  1315. package/benchmark/terminal-bench-2/src/ikie_agent/gsd_ikie_test.py +304 -0
  1316. package/benchmark/terminal-bench-2/src/ikie_agent/messages.py +27 -0
  1317. package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie.py +146 -0
  1318. package/benchmark/terminal-bench-2/src/ikie_agent/opencode_ikie_test.py +308 -0
  1319. package/benchmark/terminal-bench-2/src/ikie_agent/release.py +174 -0
  1320. package/benchmark/terminal-bench-2/src/ikie_agent/retry_config_test.py +55 -0
  1321. package/benchmark/terminal-bench-2/uv.lock +1948 -0
  1322. package/biome.json +54 -0
  1323. package/docs/agents.md +295 -0
  1324. package/docs/bash-tool-guard.md +206 -0
  1325. package/docs/expected-execution-scenarios.md +348 -0
  1326. package/docs/ferment-storage-schema.md +199 -0
  1327. package/docs/ferment.md +633 -0
  1328. package/docs/hooks.md +263 -0
  1329. package/docs/subagents/README.md +22 -0
  1330. package/docs/subagents/code-reviewer.md +39 -0
  1331. package/docs/subagents/research-assistant.md +81 -0
  1332. package/docs/subagents/test-writer.md +49 -0
  1333. package/docs/teleport.md +424 -0
  1334. package/docs/windows/README.md +226 -0
  1335. package/extensions/active-tools.ts +74 -0
  1336. package/ikie.png +0 -0
  1337. package/package.json +125 -0
  1338. package/patches/@earendil-works__pi-ai@0.78.1.patch +68 -0
  1339. package/patches/@earendil-works__pi-coding-agent@0.78.1.patch +535 -0
  1340. package/patches/@earendil-works__pi-tui.patch +171 -0
  1341. package/patches/playwright-core@1.59.1.patch +24 -0
  1342. package/resources/oauth/error.html +185 -0
  1343. package/resources/oauth/success.html +185 -0
  1344. package/scripts/build-binary.js +113 -0
  1345. package/scripts/build-proxy-helper.js +66 -0
  1346. package/scripts/copy-resources.js +104 -0
  1347. package/scripts/dev-overlay.sh +52 -0
  1348. package/scripts/dev-startup.sh +82 -0
  1349. package/scripts/install-local.js +34 -0
  1350. package/scripts/install.ps1 +258 -0
  1351. package/scripts/install.sh +160 -0
  1352. package/scripts/package-release-asset.js +82 -0
  1353. package/scripts/patch-pi-ai-oauth.js +109 -0
  1354. package/scripts/run-tui-e2e.js +153 -0
  1355. package/scripts/set-version.js +31 -0
  1356. package/scripts/verify-acp-load.mjs +358 -0
  1357. package/scripts/verify-acp.mjs +217 -0
  1358. package/src/__mocks__/earendil-clipboard-image.js +6 -0
  1359. package/src/agent-discovery/agents/claude-code.test.ts +156 -0
  1360. package/src/agent-discovery/agents/claude-code.ts +85 -0
  1361. package/src/agent-discovery/agents/cursor.test.ts +178 -0
  1362. package/src/agent-discovery/agents/cursor.ts +74 -0
  1363. package/src/agent-discovery/agents/opencode.test.ts +461 -0
  1364. package/src/agent-discovery/agents/opencode.ts +156 -0
  1365. package/src/agent-discovery/agents/skills-only.test.ts +77 -0
  1366. package/src/agent-discovery/agents/skills-only.ts +47 -0
  1367. package/src/agent-discovery/engine.test.ts +408 -0
  1368. package/src/agent-discovery/engine.ts +117 -0
  1369. package/src/agent-discovery/index.ts +75 -0
  1370. package/src/agent-discovery/jsonc.ts +52 -0
  1371. package/src/ansi.ts +51 -0
  1372. package/src/api/me.test.ts +86 -0
  1373. package/src/api/me.ts +59 -0
  1374. package/src/auth/validator.test.ts +106 -0
  1375. package/src/auth/validator.ts +103 -0
  1376. package/src/auxiliary-files/resolver.test.ts +85 -0
  1377. package/src/auxiliary-files/resolver.ts +27 -0
  1378. package/src/auxiliary-files/validator.test.ts +68 -0
  1379. package/src/auxiliary-files/validator.ts +31 -0
  1380. package/src/cli-args.test.ts +232 -0
  1381. package/src/cli-args.ts +94 -0
  1382. package/src/cli-auth/callback-server.test.ts +169 -0
  1383. package/src/cli-auth/callback-server.ts +165 -0
  1384. package/src/cli-auth/index.test.ts +103 -0
  1385. package/src/cli-auth/index.ts +117 -0
  1386. package/src/cli-auth/oauth-page.ts +94 -0
  1387. package/src/cli.ts +564 -0
  1388. package/src/commands/_helpers.ts +87 -0
  1389. package/src/commands/banner.test.ts +39 -0
  1390. package/src/commands/banner.ts +74 -0
  1391. package/src/commands/claude.ts +28 -0
  1392. package/src/commands/config.test.ts +149 -0
  1393. package/src/commands/config.ts +98 -0
  1394. package/src/commands/cursor.ts +23 -0
  1395. package/src/commands/dispatch.test.ts +102 -0
  1396. package/src/commands/dispatch.ts +40 -0
  1397. package/src/commands/gsd2.ts +23 -0
  1398. package/src/commands/help.ts +104 -0
  1399. package/src/commands/login.ts +46 -0
  1400. package/src/commands/openclaw.ts +23 -0
  1401. package/src/commands/opencode.ts +31 -0
  1402. package/src/commands/registry.ts +44 -0
  1403. package/src/commands/resources.ts +77 -0
  1404. package/src/commands/setup-tools.test.ts +231 -0
  1405. package/src/commands/setup-tools.ts +164 -0
  1406. package/src/commands/setup.ts +28 -0
  1407. package/src/commands/update.test.ts +312 -0
  1408. package/src/commands/update.ts +291 -0
  1409. package/src/commands/version.ts +9 -0
  1410. package/src/components/editor.test.ts +182 -0
  1411. package/src/components/editor.ts +186 -0
  1412. package/src/components/footer.test.ts +790 -0
  1413. package/src/components/footer.ts +640 -0
  1414. package/src/components/logo-art.test.ts +30 -0
  1415. package/src/components/logo-art.ts +66 -0
  1416. package/src/components/logo.test.ts +316 -0
  1417. package/src/components/logo.ts +127 -0
  1418. package/src/components/tool-block.test.ts +75 -0
  1419. package/src/components/tool-block.ts +166 -0
  1420. package/src/config/footer-config.test.ts +191 -0
  1421. package/src/config/footer-config.ts +130 -0
  1422. package/src/config/json.test.ts +78 -0
  1423. package/src/config/json.ts +112 -0
  1424. package/src/config/scope.test.ts +49 -0
  1425. package/src/config/scope.ts +38 -0
  1426. package/src/config/shell-profile.test.ts +130 -0
  1427. package/src/config/shell-profile.ts +131 -0
  1428. package/src/config.test.ts +723 -0
  1429. package/src/config.ts +697 -0
  1430. package/src/entry.ts +62 -0
  1431. package/src/env.ts +4 -0
  1432. package/src/expand-state.ts +41 -0
  1433. package/src/extensions/activity.test.ts +160 -0
  1434. package/src/extensions/activity.ts +192 -0
  1435. package/src/extensions/agent-worker-context.test.ts +31 -0
  1436. package/src/extensions/agent-worker-context.ts +11 -0
  1437. package/src/extensions/agents/default-agents.test.ts +24 -0
  1438. package/src/extensions/agents/discovery-priority.test.ts +65 -0
  1439. package/src/extensions/agents/env.ts +33 -0
  1440. package/src/extensions/agents/index.test.ts +32 -0
  1441. package/src/extensions/agents/index.ts +2226 -0
  1442. package/src/extensions/agents/manager/agent-manager.test.ts +896 -0
  1443. package/src/extensions/agents/manager/agent-manager.ts +714 -0
  1444. package/src/extensions/agents/manager/agent-runner.test.ts +1846 -0
  1445. package/src/extensions/agents/manager/agent-runner.ts +964 -0
  1446. package/src/extensions/agents/manager/budget-retry-guard.test.ts +95 -0
  1447. package/src/extensions/agents/manager/budget-retry-guard.ts +57 -0
  1448. package/src/extensions/agents/manager/constants.ts +1 -0
  1449. package/src/extensions/agents/manager/group-join.ts +136 -0
  1450. package/src/extensions/agents/manager/output-file.test.ts +31 -0
  1451. package/src/extensions/agents/manager/output-file.ts +92 -0
  1452. package/src/extensions/agents/manager/session-file.test.ts +59 -0
  1453. package/src/extensions/agents/manager/session-file.ts +37 -0
  1454. package/src/extensions/agents/manager/usage.ts +52 -0
  1455. package/src/extensions/agents/memory/memory.test.ts +54 -0
  1456. package/src/extensions/agents/memory/memory.ts +166 -0
  1457. package/src/extensions/agents/memory.test.ts +54 -0
  1458. package/src/extensions/agents/package-resources.test.ts +147 -0
  1459. package/src/extensions/agents/package-resources.ts +37 -0
  1460. package/src/extensions/agents/personas/__snapshots__/default-agents.test.ts.snap +75 -0
  1461. package/src/extensions/agents/personas/agent-types.test.ts +33 -0
  1462. package/src/extensions/agents/personas/agent-types.ts +150 -0
  1463. package/src/extensions/agents/personas/custom-agents.test.ts +171 -0
  1464. package/src/extensions/agents/personas/custom-agents.ts +147 -0
  1465. package/src/extensions/agents/personas/default-agents.test.ts +101 -0
  1466. package/src/extensions/agents/personas/default-agents.ts +335 -0
  1467. package/src/extensions/agents/personas/discovery-priority.test.ts +65 -0
  1468. package/src/extensions/agents/personas/types.ts +229 -0
  1469. package/src/extensions/agents/prompt/context.ts +54 -0
  1470. package/src/extensions/agents/prompt/prompts.test.ts +314 -0
  1471. package/src/extensions/agents/prompt/prompts.ts +164 -0
  1472. package/src/extensions/agents/prompt/skill-loader.test.ts +41 -0
  1473. package/src/extensions/agents/prompt/skill-loader.ts +80 -0
  1474. package/src/extensions/agents/resolution/invocation-config.test.ts +81 -0
  1475. package/src/extensions/agents/resolution/invocation-config.ts +68 -0
  1476. package/src/extensions/agents/resolution/model-resolver.ts +85 -0
  1477. package/src/extensions/agents/resume-tool.test.ts +146 -0
  1478. package/src/extensions/agents/resume-tool.ts +90 -0
  1479. package/src/extensions/agents/settings.ts +163 -0
  1480. package/src/extensions/agents/skill-loader.test.ts +41 -0
  1481. package/src/extensions/agents/tool-result.ts +4 -0
  1482. package/src/extensions/agents/ui/agent-widget.ts +458 -0
  1483. package/src/extensions/agents/ui/conversation-viewer.ts +261 -0
  1484. package/src/extensions/agents/worker-budget-policy.ts +48 -0
  1485. package/src/extensions/agents/worker-report.test.ts +69 -0
  1486. package/src/extensions/agents/worker-report.ts +72 -0
  1487. package/src/extensions/assistant-prefix.ts +80 -0
  1488. package/src/extensions/bash-collapse.test.ts +21 -0
  1489. package/src/extensions/bash-collapse.ts +3 -0
  1490. package/src/extensions/bash-default-timeout.test.ts +189 -0
  1491. package/src/extensions/bash-default-timeout.ts +73 -0
  1492. package/src/extensions/bash-tool-guard-events.ts +39 -0
  1493. package/src/extensions/bash-tool-guard.integration.test.ts +771 -0
  1494. package/src/extensions/bash-tool-guard.test.ts +890 -0
  1495. package/src/extensions/bash-tool-guard.ts +640 -0
  1496. package/src/extensions/behaviours/bash-tokenize.test.ts +125 -0
  1497. package/src/extensions/behaviours/bash-tokenize.ts +272 -0
  1498. package/src/extensions/behaviours/bodies/bound-tool-output.md +11 -0
  1499. package/src/extensions/behaviours/bodies/gh-cli.md +80 -0
  1500. package/src/extensions/behaviours/bodies/git-hygiene.md +13 -0
  1501. package/src/extensions/behaviours/bodies/glab-cli.md +95 -0
  1502. package/src/extensions/behaviours/bodies/python-edit.md +10 -0
  1503. package/src/extensions/behaviours/bodies/re-read-before-edit.md +10 -0
  1504. package/src/extensions/behaviours/bodies.d.ts +7 -0
  1505. package/src/extensions/behaviours/build.test.ts +89 -0
  1506. package/src/extensions/behaviours/build.ts +63 -0
  1507. package/src/extensions/behaviours/engine.test.ts +300 -0
  1508. package/src/extensions/behaviours/engine.ts +131 -0
  1509. package/src/extensions/behaviours/eval-engine.test.ts +165 -0
  1510. package/src/extensions/behaviours/eval-engine.ts +104 -0
  1511. package/src/extensions/behaviours/frontmatter.ts +22 -0
  1512. package/src/extensions/behaviours/index.ts +35 -0
  1513. package/src/extensions/behaviours/matchers.test.ts +153 -0
  1514. package/src/extensions/behaviours/matchers.ts +69 -0
  1515. package/src/extensions/behaviours/registry.ts +73 -0
  1516. package/src/extensions/behaviours/session-context.test.ts +192 -0
  1517. package/src/extensions/behaviours/session-context.ts +170 -0
  1518. package/src/extensions/behaviours/stats.ts +47 -0
  1519. package/src/extensions/behaviours/tool-args.smoke.test.ts +34 -0
  1520. package/src/extensions/behaviours/tool-args.ts +65 -0
  1521. package/src/extensions/behaviours/triggers.ts +164 -0
  1522. package/src/extensions/behaviours/types.ts +49 -0
  1523. package/src/extensions/behaviours/wiring.smoke.test.ts +488 -0
  1524. package/src/extensions/behaviours/wiring.ts +196 -0
  1525. package/src/extensions/branch-command.test.ts +208 -0
  1526. package/src/extensions/branch-command.ts +89 -0
  1527. package/src/extensions/claude-code-hook-adapter/definition.test.ts +51 -0
  1528. package/src/extensions/claude-code-hook-adapter/definition.ts +36 -0
  1529. package/src/extensions/claude-code-hook-adapter/index.ts +6 -0
  1530. package/src/extensions/claude-code-skills/definition.test.ts +228 -0
  1531. package/src/extensions/claude-code-skills/definition.ts +475 -0
  1532. package/src/extensions/claude-code-skills/index.test.ts +227 -0
  1533. package/src/extensions/claude-code-skills/index.ts +101 -0
  1534. package/src/extensions/clipboard-image.test.ts +383 -0
  1535. package/src/extensions/clipboard-image.ts +266 -0
  1536. package/src/extensions/compaction-thresholds.test.ts +8 -0
  1537. package/src/extensions/compaction-thresholds.ts +13 -0
  1538. package/src/extensions/curator/index.test.ts +33 -0
  1539. package/src/extensions/curator/index.ts +296 -0
  1540. package/src/extensions/curator/review.test.ts +82 -0
  1541. package/src/extensions/curator/review.ts +438 -0
  1542. package/src/extensions/curator/state.test.ts +79 -0
  1543. package/src/extensions/curator/state.ts +61 -0
  1544. package/src/extensions/curator/transitions.test.ts +96 -0
  1545. package/src/extensions/curator/transitions.ts +56 -0
  1546. package/src/extensions/customize-footer-command.test.ts +258 -0
  1547. package/src/extensions/customize-footer-command.ts +158 -0
  1548. package/src/extensions/deferred-action.ts +38 -0
  1549. package/src/extensions/disabled/tool-result-pruning.test.ts +397 -0
  1550. package/src/extensions/disabled/tool-result-pruning.ts +181 -0
  1551. package/src/extensions/exit-utils.ts +8 -0
  1552. package/src/extensions/exploration-guard.test.ts +646 -0
  1553. package/src/extensions/exploration-guard.ts +293 -0
  1554. package/src/extensions/ferment/action-tool-names.ts +25 -0
  1555. package/src/extensions/ferment/agent-spawn-guard.test.ts +339 -0
  1556. package/src/extensions/ferment/agent-spawn-guard.ts +188 -0
  1557. package/src/extensions/ferment/ask-user.test.ts +838 -0
  1558. package/src/extensions/ferment/ask-user.ts +569 -0
  1559. package/src/extensions/ferment/auto-compaction.test.ts +933 -0
  1560. package/src/extensions/ferment/auto-compaction.ts +525 -0
  1561. package/src/extensions/ferment/breadcrumb-renderer.ts +46 -0
  1562. package/src/extensions/ferment/colors.ts +95 -0
  1563. package/src/extensions/ferment/command-parser.test.ts +82 -0
  1564. package/src/extensions/ferment/command-parser.ts +52 -0
  1565. package/src/extensions/ferment/commands.test.ts +1659 -0
  1566. package/src/extensions/ferment/commands.ts +1025 -0
  1567. package/src/extensions/ferment/constants.ts +37 -0
  1568. package/src/extensions/ferment/contextual-options.test.ts +70 -0
  1569. package/src/extensions/ferment/contextual-options.ts +107 -0
  1570. package/src/extensions/ferment/continuation.test.ts +141 -0
  1571. package/src/extensions/ferment/continuation.ts +59 -0
  1572. package/src/extensions/ferment/derive-state.test.ts +222 -0
  1573. package/src/extensions/ferment/derive-state.ts +158 -0
  1574. package/src/extensions/ferment/domain-events-emitter.ts +255 -0
  1575. package/src/extensions/ferment/domain-events.ts +146 -0
  1576. package/src/extensions/ferment/events.test.ts +616 -0
  1577. package/src/extensions/ferment/events.ts +561 -0
  1578. package/src/extensions/ferment/footer-status.test.ts +62 -0
  1579. package/src/extensions/ferment/footer-status.ts +61 -0
  1580. package/src/extensions/ferment/format.test.ts +55 -0
  1581. package/src/extensions/ferment/format.ts +111 -0
  1582. package/src/extensions/ferment/fsm-adapter.test.ts +43 -0
  1583. package/src/extensions/ferment/fsm-adapter.ts +112 -0
  1584. package/src/extensions/ferment/gate-registry.test.ts +176 -0
  1585. package/src/extensions/ferment/gate-registry.ts +352 -0
  1586. package/src/extensions/ferment/gate-validation.test.ts +319 -0
  1587. package/src/extensions/ferment/gate-validation.ts +160 -0
  1588. package/src/extensions/ferment/git-init.test.ts +146 -0
  1589. package/src/extensions/ferment/git-init.ts +66 -0
  1590. package/src/extensions/ferment/index.test.ts +1439 -0
  1591. package/src/extensions/ferment/index.ts +337 -0
  1592. package/src/extensions/ferment/judge.test.ts +172 -0
  1593. package/src/extensions/ferment/judge.ts +342 -0
  1594. package/src/extensions/ferment/nudge.test.ts +700 -0
  1595. package/src/extensions/ferment/nudge.ts +332 -0
  1596. package/src/extensions/ferment/oneshot.test.ts +115 -0
  1597. package/src/extensions/ferment/oneshot.ts +52 -0
  1598. package/src/extensions/ferment/pending-proposal-store.test.ts +272 -0
  1599. package/src/extensions/ferment/pending-proposal-store.ts +142 -0
  1600. package/src/extensions/ferment/phase-editor.test.ts +174 -0
  1601. package/src/extensions/ferment/phase-editor.ts +148 -0
  1602. package/src/extensions/ferment/phase-evidence.test.ts +154 -0
  1603. package/src/extensions/ferment/phase-evidence.ts +179 -0
  1604. package/src/extensions/ferment/plan-review-trigger.ts +34 -0
  1605. package/src/extensions/ferment/plan-review.test.ts +182 -0
  1606. package/src/extensions/ferment/plan-review.ts +205 -0
  1607. package/src/extensions/ferment/progress-overlay.test.ts +197 -0
  1608. package/src/extensions/ferment/progress-overlay.ts +326 -0
  1609. package/src/extensions/ferment/project-tests.test.ts +160 -0
  1610. package/src/extensions/ferment/project-tests.ts +246 -0
  1611. package/src/extensions/ferment/prompt-block.test.ts +501 -0
  1612. package/src/extensions/ferment/prompt-block.ts +203 -0
  1613. package/src/extensions/ferment/prompt-ui.test.ts +311 -0
  1614. package/src/extensions/ferment/prompt-ui.ts +302 -0
  1615. package/src/extensions/ferment/resume.test.ts +218 -0
  1616. package/src/extensions/ferment/resume.ts +180 -0
  1617. package/src/extensions/ferment/review-evidence.ts +269 -0
  1618. package/src/extensions/ferment/runtime-state-store.test.ts +148 -0
  1619. package/src/extensions/ferment/runtime-state-store.ts +132 -0
  1620. package/src/extensions/ferment/runtime.test.ts +38 -0
  1621. package/src/extensions/ferment/runtime.ts +208 -0
  1622. package/src/extensions/ferment/scheduler.ts +226 -0
  1623. package/src/extensions/ferment/scoping-benchmark.test.ts +137 -0
  1624. package/src/extensions/ferment/scoping-confirmation.test.ts +209 -0
  1625. package/src/extensions/ferment/scoping-confirmation.ts +87 -0
  1626. package/src/extensions/ferment/scoping-flow.integration.test.ts +203 -0
  1627. package/src/extensions/ferment/scoping.test.ts +235 -0
  1628. package/src/extensions/ferment/scoping.ts +208 -0
  1629. package/src/extensions/ferment/state.test.ts +300 -0
  1630. package/src/extensions/ferment/state.ts +696 -0
  1631. package/src/extensions/ferment/tips.test.ts +171 -0
  1632. package/src/extensions/ferment/tips.ts +61 -0
  1633. package/src/extensions/ferment/todo-headless-wiring.test.ts +641 -0
  1634. package/src/extensions/ferment/todo-sync.test.ts +805 -0
  1635. package/src/extensions/ferment/todo-sync.ts +520 -0
  1636. package/src/extensions/ferment/tool-helpers.test.ts +121 -0
  1637. package/src/extensions/ferment/tool-helpers.ts +217 -0
  1638. package/src/extensions/ferment/tool-names.test.ts +55 -0
  1639. package/src/extensions/ferment/tool-names.ts +78 -0
  1640. package/src/extensions/ferment/tool-schemas.test.ts +587 -0
  1641. package/src/extensions/ferment/tool-schemas.ts +428 -0
  1642. package/src/extensions/ferment/tool-scope.test.ts +373 -0
  1643. package/src/extensions/ferment/tool-scope.ts +176 -0
  1644. package/src/extensions/ferment/tools/knowledge.ts +60 -0
  1645. package/src/extensions/ferment/tools/lifecycle.test.ts +1196 -0
  1646. package/src/extensions/ferment/tools/lifecycle.ts +1296 -0
  1647. package/src/extensions/ferment/tools/phases.test.ts +379 -0
  1648. package/src/extensions/ferment/tools/phases.ts +757 -0
  1649. package/src/extensions/ferment/tools/steps.test.ts +998 -0
  1650. package/src/extensions/ferment/tools/steps.ts +765 -0
  1651. package/src/extensions/ferment/tools.integration.test.ts +1975 -0
  1652. package/src/extensions/ferment/ui.ts +10 -0
  1653. package/src/extensions/ferment/worker-prompt.test.ts +285 -0
  1654. package/src/extensions/ferment/worker-prompt.ts +85 -0
  1655. package/src/extensions/ferment/worktree.ts +44 -0
  1656. package/src/extensions/format.ts +12 -0
  1657. package/src/extensions/help.ts +172 -0
  1658. package/src/extensions/hide-thinking.test.ts +407 -0
  1659. package/src/extensions/hide-thinking.ts +375 -0
  1660. package/src/extensions/hook-adapters/adapter.integration.test.ts +134 -0
  1661. package/src/extensions/hook-adapters/adapter.test.ts +1062 -0
  1662. package/src/extensions/hook-adapters/adapter.ts +784 -0
  1663. package/src/extensions/hook-adapters/discovery.test.ts +105 -0
  1664. package/src/extensions/hook-adapters/discovery.ts +213 -0
  1665. package/src/extensions/ide-adapter/ARCHITECTURE.md +77 -0
  1666. package/src/extensions/ide-adapter/CONTRACT.md +129 -0
  1667. package/src/extensions/ide-adapter/README.md +24 -0
  1668. package/src/extensions/ide-adapter/at-mentions.test.ts +40 -0
  1669. package/src/extensions/ide-adapter/at-mentions.ts +44 -0
  1670. package/src/extensions/ide-adapter/index.test.ts +434 -0
  1671. package/src/extensions/ide-adapter/index.ts +250 -0
  1672. package/src/extensions/ide-adapter/lockfile.test.ts +137 -0
  1673. package/src/extensions/ide-adapter/lockfile.ts +82 -0
  1674. package/src/extensions/ide-adapter/mcp-client.test.ts +285 -0
  1675. package/src/extensions/ide-adapter/mcp-client.ts +208 -0
  1676. package/src/extensions/ide-adapter/types.ts +47 -0
  1677. package/src/extensions/ikie-minimal-tints.ts +124 -0
  1678. package/src/extensions/ikie-process.ts +49 -0
  1679. package/src/extensions/improve/SKILL.md +51 -0
  1680. package/src/extensions/improve/index.ts +72 -0
  1681. package/src/extensions/input-history.test.ts +475 -0
  1682. package/src/extensions/input-history.ts +111 -0
  1683. package/src/extensions/llm-response-log.test.ts +200 -0
  1684. package/src/extensions/llm-response-log.ts +87 -0
  1685. package/src/extensions/login/flow.test.ts +47 -0
  1686. package/src/extensions/login/flow.ts +638 -0
  1687. package/src/extensions/login/index.ts +57 -0
  1688. package/src/extensions/login/startup-auth.test.ts +510 -0
  1689. package/src/extensions/login/startup-auth.ts +205 -0
  1690. package/src/extensions/loop-guard.test.ts +993 -0
  1691. package/src/extensions/loop-guard.ts +710 -0
  1692. package/src/extensions/lsp/client.ts +501 -0
  1693. package/src/extensions/lsp/edits.test.ts +69 -0
  1694. package/src/extensions/lsp/edits.ts +78 -0
  1695. package/src/extensions/lsp/lsp-entry.test.ts +24 -0
  1696. package/src/extensions/lsp/servers.ts +76 -0
  1697. package/src/extensions/lsp/types.ts +166 -0
  1698. package/src/extensions/lsp/utils.test.ts +81 -0
  1699. package/src/extensions/lsp/utils.ts +80 -0
  1700. package/src/extensions/lsp.test.ts +1049 -0
  1701. package/src/extensions/lsp.ts +470 -0
  1702. package/src/extensions/mcp-adapter/CHANGELOG.md +264 -0
  1703. package/src/extensions/mcp-adapter/LICENSE +21 -0
  1704. package/src/extensions/mcp-adapter/README.md +316 -0
  1705. package/src/extensions/mcp-adapter/app-bridge.bundle.js +10430 -0
  1706. package/src/extensions/mcp-adapter/bm25.ts +187 -0
  1707. package/src/extensions/mcp-adapter/cache-resolver.integration.test.ts +282 -0
  1708. package/src/extensions/mcp-adapter/commands.ts +235 -0
  1709. package/src/extensions/mcp-adapter/config.test.ts +189 -0
  1710. package/src/extensions/mcp-adapter/config.ts +233 -0
  1711. package/src/extensions/mcp-adapter/consent-manager.ts +64 -0
  1712. package/src/extensions/mcp-adapter/context-providers.test.ts +123 -0
  1713. package/src/extensions/mcp-adapter/context-providers.ts +55 -0
  1714. package/src/extensions/mcp-adapter/direct-tool-visibility.test.ts +61 -0
  1715. package/src/extensions/mcp-adapter/direct-tool-visibility.ts +47 -0
  1716. package/src/extensions/mcp-adapter/direct-tools.ts +413 -0
  1717. package/src/extensions/mcp-adapter/errors.ts +198 -0
  1718. package/src/extensions/mcp-adapter/glimpse-ui.ts +78 -0
  1719. package/src/extensions/mcp-adapter/host-html-template.ts +423 -0
  1720. package/src/extensions/mcp-adapter/index.test.ts +323 -0
  1721. package/src/extensions/mcp-adapter/index.ts +604 -0
  1722. package/src/extensions/mcp-adapter/init.ts +402 -0
  1723. package/src/extensions/mcp-adapter/lifecycle.ts +93 -0
  1724. package/src/extensions/mcp-adapter/logger.ts +169 -0
  1725. package/src/extensions/mcp-adapter/mcp-auth-flow.ts +394 -0
  1726. package/src/extensions/mcp-adapter/mcp-auth.ts +267 -0
  1727. package/src/extensions/mcp-adapter/mcp-callback-server.ts +284 -0
  1728. package/src/extensions/mcp-adapter/mcp-oauth-provider.ts +288 -0
  1729. package/src/extensions/mcp-adapter/mcp-panel.test.ts +321 -0
  1730. package/src/extensions/mcp-adapter/mcp-panel.ts +835 -0
  1731. package/src/extensions/mcp-adapter/metadata-cache.test.ts +83 -0
  1732. package/src/extensions/mcp-adapter/metadata-cache.ts +332 -0
  1733. package/src/extensions/mcp-adapter/npx-resolver.ts +429 -0
  1734. package/src/extensions/mcp-adapter/oauth-handler.ts +57 -0
  1735. package/src/extensions/mcp-adapter/proxy-modes.test.ts +147 -0
  1736. package/src/extensions/mcp-adapter/proxy-modes.ts +1035 -0
  1737. package/src/extensions/mcp-adapter/resource-tools.ts +17 -0
  1738. package/src/extensions/mcp-adapter/server-manager.ts +355 -0
  1739. package/src/extensions/mcp-adapter/state.ts +45 -0
  1740. package/src/extensions/mcp-adapter/tool-metadata.test.ts +115 -0
  1741. package/src/extensions/mcp-adapter/tool-metadata.ts +185 -0
  1742. package/src/extensions/mcp-adapter/tool-registrar.ts +46 -0
  1743. package/src/extensions/mcp-adapter/types.ts +423 -0
  1744. package/src/extensions/mcp-adapter/ui-resource-handler.ts +143 -0
  1745. package/src/extensions/mcp-adapter/ui-server.ts +619 -0
  1746. package/src/extensions/mcp-adapter/ui-session.ts +378 -0
  1747. package/src/extensions/mcp-adapter/ui-stream-types.ts +93 -0
  1748. package/src/extensions/mcp-adapter/utils.ts +76 -0
  1749. package/src/extensions/model-catalog/builtin-models.ts +180 -0
  1750. package/src/extensions/model-catalog/guidelines/claude-family.ts +49 -0
  1751. package/src/extensions/model-catalog/guidelines/default-orchestration-guidelines.ts +11 -0
  1752. package/src/extensions/model-catalog/guidelines/default-phase-guidelines.ts +59 -0
  1753. package/src/extensions/model-catalog/guidelines/guidelines-resolver.test.ts +191 -0
  1754. package/src/extensions/model-catalog/guidelines/guidelines-resolver.ts +39 -0
  1755. package/src/extensions/model-catalog/guidelines/kimi-family.ts +82 -0
  1756. package/src/extensions/model-catalog/guidelines/minimax-family.ts +62 -0
  1757. package/src/extensions/model-catalog/guidelines/nemotron-family.ts +53 -0
  1758. package/src/extensions/model-catalog/index.ts +10 -0
  1759. package/src/extensions/model-catalog/model-metadata.test.ts +688 -0
  1760. package/src/extensions/model-catalog/model-metadata.ts +250 -0
  1761. package/src/extensions/model-catalog/model-registry.test.ts +228 -0
  1762. package/src/extensions/model-catalog/model-registry.ts +116 -0
  1763. package/src/extensions/model-catalog/ref-utils.ts +22 -0
  1764. package/src/extensions/model-catalog/types.ts +41 -0
  1765. package/src/extensions/model-guard.test.ts +756 -0
  1766. package/src/extensions/model-guard.ts +402 -0
  1767. package/src/extensions/model-switch.test.ts +1105 -0
  1768. package/src/extensions/model-switch.ts +261 -0
  1769. package/src/extensions/onboarding/picker-editor.ts +22 -0
  1770. package/src/extensions/onboarding/session-mode-picker.test.ts +135 -0
  1771. package/src/extensions/onboarding/session-mode-picker.ts +136 -0
  1772. package/src/extensions/onboarding/session-mode-startup.test.ts +237 -0
  1773. package/src/extensions/onboarding/session-mode-startup.ts +36 -0
  1774. package/src/extensions/onboarding/session-mode.test.ts +501 -0
  1775. package/src/extensions/onboarding/session-mode.ts +363 -0
  1776. package/src/extensions/orchestration/continuation-nudge.test.ts +595 -0
  1777. package/src/extensions/orchestration/continuation-nudge.ts +270 -0
  1778. package/src/extensions/orchestration/model-metadata.test.ts +671 -0
  1779. package/src/extensions/orchestration/model-metadata.ts +246 -0
  1780. package/src/extensions/orchestration/model-ref-utils.ts +5 -0
  1781. package/src/extensions/orchestration/model-registry/builtin-models.ts +223 -0
  1782. package/src/extensions/orchestration/model-registry/guidelines/claude-family.ts +49 -0
  1783. package/src/extensions/orchestration/model-registry/guidelines/default-orchestration-guidelines.ts +11 -0
  1784. package/src/extensions/orchestration/model-registry/guidelines/default-phase-guidelines.ts +67 -0
  1785. package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.test.ts +273 -0
  1786. package/src/extensions/orchestration/model-registry/guidelines/guidelines-resolver.ts +39 -0
  1787. package/src/extensions/orchestration/model-registry/guidelines/kimi-family.ts +89 -0
  1788. package/src/extensions/orchestration/model-registry/guidelines/minimax-family.ts +68 -0
  1789. package/src/extensions/orchestration/model-registry/guidelines/nemotron-family.ts +60 -0
  1790. package/src/extensions/orchestration/model-registry/index.ts +4 -0
  1791. package/src/extensions/orchestration/model-registry/model-registry.test.ts +228 -0
  1792. package/src/extensions/orchestration/model-registry/model-registry.ts +116 -0
  1793. package/src/extensions/orchestration/model-registry/types.ts +41 -0
  1794. package/src/extensions/orchestration/model-roles-command.test.ts +367 -0
  1795. package/src/extensions/orchestration/model-roles-command.ts +531 -0
  1796. package/src/extensions/orchestration/model-roles.test.ts +448 -0
  1797. package/src/extensions/orchestration/model-roles.ts +302 -0
  1798. package/src/extensions/orchestration/orchestration-instructions.test.ts +459 -0
  1799. package/src/extensions/orchestration/orchestration-instructions.ts +614 -0
  1800. package/src/extensions/orphan-tool-result-sanitizer.test.ts +198 -0
  1801. package/src/extensions/orphan-tool-result-sanitizer.ts +128 -0
  1802. package/src/extensions/permissions/classifier-model.test.ts +127 -0
  1803. package/src/extensions/permissions/classifier-model.ts +65 -0
  1804. package/src/extensions/permissions/classifier.test.ts +334 -0
  1805. package/src/extensions/permissions/classifier.ts +228 -0
  1806. package/src/extensions/permissions/commands.ts +244 -0
  1807. package/src/extensions/permissions/config.test.ts +101 -0
  1808. package/src/extensions/permissions/config.ts +143 -0
  1809. package/src/extensions/permissions/constants.ts +1 -0
  1810. package/src/extensions/permissions/index.test.ts +1822 -0
  1811. package/src/extensions/permissions/index.ts +1193 -0
  1812. package/src/extensions/permissions/keybindings.test.ts +130 -0
  1813. package/src/extensions/permissions/keybindings.ts +91 -0
  1814. package/src/extensions/permissions/mode-controller-registry.ts +50 -0
  1815. package/src/extensions/permissions/mode-controller.ts +91 -0
  1816. package/src/extensions/permissions/mode.test.ts +51 -0
  1817. package/src/extensions/permissions/mode.ts +29 -0
  1818. package/src/extensions/permissions/plan-persistence.test.ts +56 -0
  1819. package/src/extensions/permissions/plan-persistence.ts +12 -0
  1820. package/src/extensions/permissions/plan-persona.test.ts +42 -0
  1821. package/src/extensions/permissions/prompter.ts +21 -0
  1822. package/src/extensions/permissions/prompts/classifier-system-prompt.ts +33 -0
  1823. package/src/extensions/permissions/prompts/plan-mode-supplement.test.ts +59 -0
  1824. package/src/extensions/permissions/prompts/plan-mode-supplement.ts +38 -0
  1825. package/src/extensions/permissions/prompts.test.ts +67 -0
  1826. package/src/extensions/permissions/prompts.ts +212 -0
  1827. package/src/extensions/permissions/rules.test.ts +327 -0
  1828. package/src/extensions/permissions/rules.ts +210 -0
  1829. package/src/extensions/permissions/select-utils.ts +2 -0
  1830. package/src/extensions/permissions/session-memory.test.ts +75 -0
  1831. package/src/extensions/permissions/session-memory.ts +94 -0
  1832. package/src/extensions/permissions/taxonomy.test.ts +684 -0
  1833. package/src/extensions/permissions/taxonomy.ts +616 -0
  1834. package/src/extensions/permissions/types.ts +70 -0
  1835. package/src/extensions/pi-compat.test.ts +201 -0
  1836. package/src/extensions/pi-package-lookup/index.test.ts +177 -0
  1837. package/src/extensions/pi-package-lookup/index.ts +263 -0
  1838. package/src/extensions/pi-package-lookup/native-compat.test.ts +230 -0
  1839. package/src/extensions/pi-package-lookup/native-compat.ts +279 -0
  1840. package/src/extensions/plugin-package-hook-adapter/definition.test.ts +220 -0
  1841. package/src/extensions/plugin-package-hook-adapter/definition.ts +60 -0
  1842. package/src/extensions/plugin-package-hook-adapter/index.ts +4 -0
  1843. package/src/extensions/prompt-construction/context-files.test.ts +167 -0
  1844. package/src/extensions/prompt-construction/context-files.ts +111 -0
  1845. package/src/extensions/prompt-construction/index.ts +8 -0
  1846. package/src/extensions/prompt-construction/prompt-enrichment.test.ts +1103 -0
  1847. package/src/extensions/prompt-construction/prompt-enrichment.ts +588 -0
  1848. package/src/extensions/prompt-construction/system-prompt-blocks.test.ts +323 -0
  1849. package/src/extensions/prompt-construction/system-prompt-blocks.ts +122 -0
  1850. package/src/extensions/prompt-construction/system-prompt.test.ts +528 -0
  1851. package/src/extensions/prompt-construction/system-prompt.ts +316 -0
  1852. package/src/extensions/prompt-construction/tool-visibility.test.ts +170 -0
  1853. package/src/extensions/prompt-construction/tool-visibility.ts +121 -0
  1854. package/src/extensions/prompt-summary.test.ts +56 -0
  1855. package/src/extensions/prompt-summary.ts +258 -0
  1856. package/src/extensions/questionnaire/constants.ts +6 -0
  1857. package/src/extensions/questionnaire/index.ts +8 -0
  1858. package/src/extensions/questionnaire/questionnaire-fallback.test.ts +948 -0
  1859. package/src/extensions/questionnaire/questionnaire-fallback.ts +230 -0
  1860. package/src/extensions/questionnaire/questionnaire-form.ts +314 -0
  1861. package/src/extensions/questionnaire/questionnaire-reducer.test.ts +508 -0
  1862. package/src/extensions/questionnaire/questionnaire-reducer.ts +510 -0
  1863. package/src/extensions/questionnaire/questionnaire.test.ts +425 -0
  1864. package/src/extensions/questionnaire/questionnaire.ts +280 -0
  1865. package/src/extensions/report-bug.test.ts +301 -0
  1866. package/src/extensions/report-bug.ts +93 -0
  1867. package/src/extensions/review-write-guard.integration.test.ts +167 -0
  1868. package/src/extensions/review-write-guard.test.ts +150 -0
  1869. package/src/extensions/review-write-guard.ts +143 -0
  1870. package/src/extensions/rtk-rewrite.test.ts +325 -0
  1871. package/src/extensions/rtk-rewrite.ts +201 -0
  1872. package/src/extensions/session-metadata/index.test.ts +158 -0
  1873. package/src/extensions/session-metadata/index.ts +66 -0
  1874. package/src/extensions/session-name.test.ts +248 -0
  1875. package/src/extensions/session-name.ts +192 -0
  1876. package/src/extensions/session-repair/orphan-tool-result-repair.test.ts +227 -0
  1877. package/src/extensions/session-repair/orphan-tool-result-repair.ts +183 -0
  1878. package/src/extensions/shared-footer.ts +24 -0
  1879. package/src/extensions/shared-input.test.ts +27 -0
  1880. package/src/extensions/shared-input.ts +24 -0
  1881. package/src/extensions/shutdown-marker.test.ts +195 -0
  1882. package/src/extensions/shutdown-marker.ts +61 -0
  1883. package/src/extensions/skills-manager/index.test.ts +17 -0
  1884. package/src/extensions/skills-manager/index.ts +18 -0
  1885. package/src/extensions/skills-manager/skill-manager.test.ts +350 -0
  1886. package/src/extensions/skills-manager/skill-manager.ts +508 -0
  1887. package/src/extensions/skills-manager/tool.test.ts +234 -0
  1888. package/src/extensions/skills-manager/tool.ts +241 -0
  1889. package/src/extensions/skills-manager/usage.test.ts +119 -0
  1890. package/src/extensions/skills-manager/usage.ts +249 -0
  1891. package/src/extensions/slash-commands.ts +22 -0
  1892. package/src/extensions/spinner.ts +117 -0
  1893. package/src/extensions/stale-ctx.ts +15 -0
  1894. package/src/extensions/startup-update.test.ts +130 -0
  1895. package/src/extensions/startup-update.ts +33 -0
  1896. package/src/extensions/stats/api.ts +168 -0
  1897. package/src/extensions/stats/display.ts +210 -0
  1898. package/src/extensions/stats/index.ts +130 -0
  1899. package/src/extensions/stats/stats.test.ts +547 -0
  1900. package/src/extensions/stats/types.ts +263 -0
  1901. package/src/extensions/stats/visual.ts +439 -0
  1902. package/src/extensions/strip-images.test.ts +118 -0
  1903. package/src/extensions/strip-images.ts +162 -0
  1904. package/src/extensions/superpowers/config.ts +10 -0
  1905. package/src/extensions/superpowers.test.ts +17 -0
  1906. package/src/extensions/superpowers.ts +5 -0
  1907. package/src/extensions/surveys/index.test.ts +200 -0
  1908. package/src/extensions/surveys/index.ts +107 -0
  1909. package/src/extensions/surveys/survey.test.ts +157 -0
  1910. package/src/extensions/surveys/survey.ts +204 -0
  1911. package/src/extensions/tags.test.ts +275 -0
  1912. package/src/extensions/tags.ts +662 -0
  1913. package/src/extensions/telemetry/README.md +113 -0
  1914. package/src/extensions/telemetry/accumulator.test.ts +260 -0
  1915. package/src/extensions/telemetry/accumulator.ts +146 -0
  1916. package/src/extensions/telemetry/config-snapshot.test.ts +259 -0
  1917. package/src/extensions/telemetry/config-snapshot.ts +177 -0
  1918. package/src/extensions/telemetry/handlers/messages.test.ts +422 -0
  1919. package/src/extensions/telemetry/handlers/messages.ts +113 -0
  1920. package/src/extensions/telemetry/handlers/session.test.ts +198 -0
  1921. package/src/extensions/telemetry/handlers/session.ts +24 -0
  1922. package/src/extensions/telemetry/handlers/tools.test.ts +416 -0
  1923. package/src/extensions/telemetry/handlers/tools.ts +171 -0
  1924. package/src/extensions/telemetry/handlers/transport-errors.test.ts +178 -0
  1925. package/src/extensions/telemetry/handlers/transport-errors.ts +42 -0
  1926. package/src/extensions/telemetry/helpers.test.ts +266 -0
  1927. package/src/extensions/telemetry/helpers.ts +146 -0
  1928. package/src/extensions/telemetry/index.test.ts +1170 -0
  1929. package/src/extensions/telemetry/index.ts +609 -0
  1930. package/src/extensions/telemetry/pre-session.test.ts +390 -0
  1931. package/src/extensions/telemetry/pre-session.ts +135 -0
  1932. package/src/extensions/telemetry/session-context.test.ts +487 -0
  1933. package/src/extensions/telemetry/session-context.ts +281 -0
  1934. package/src/extensions/telemetry/session-type.ts +5 -0
  1935. package/src/extensions/telemetry/settings-change-emitter.test.ts +197 -0
  1936. package/src/extensions/telemetry/settings-change-emitter.ts +127 -0
  1937. package/src/extensions/telemetry/survey.test.ts +140 -0
  1938. package/src/extensions/telemetry/survey.ts +70 -0
  1939. package/src/extensions/telemetry/transport.test.ts +301 -0
  1940. package/src/extensions/telemetry/transport.ts +217 -0
  1941. package/src/extensions/teleport/commands/args.test.ts +166 -0
  1942. package/src/extensions/teleport/commands/args.ts +226 -0
  1943. package/src/extensions/teleport/commands/attach.test.ts +209 -0
  1944. package/src/extensions/teleport/commands/attach.ts +91 -0
  1945. package/src/extensions/teleport/commands/errors.ts +26 -0
  1946. package/src/extensions/teleport/commands/remote-sessions.test.ts +350 -0
  1947. package/src/extensions/teleport/commands/remote-sessions.ts +193 -0
  1948. package/src/extensions/teleport/commands/ssh-config.ts +25 -0
  1949. package/src/extensions/teleport/commands/sync.test.ts +104 -0
  1950. package/src/extensions/teleport/commands/sync.ts +205 -0
  1951. package/src/extensions/teleport/commands/teleport.test.ts +593 -0
  1952. package/src/extensions/teleport/commands/teleport.ts +359 -0
  1953. package/src/extensions/teleport/commands/terminal.test.ts +228 -0
  1954. package/src/extensions/teleport/commands/terminal.ts +97 -0
  1955. package/src/extensions/teleport/commands/workspace-ref.test.ts +269 -0
  1956. package/src/extensions/teleport/commands/workspace-ref.ts +105 -0
  1957. package/src/extensions/teleport/index.test.ts +72 -0
  1958. package/src/extensions/teleport/index.ts +66 -0
  1959. package/src/extensions/teleport/overlay/keybindings.test.ts +101 -0
  1960. package/src/extensions/teleport/overlay/keybindings.ts +65 -0
  1961. package/src/extensions/teleport/overlay/overlay-component.test.ts +102 -0
  1962. package/src/extensions/teleport/overlay/overlay-component.ts +284 -0
  1963. package/src/extensions/teleport/overlay/reconnect-banner.test.ts +63 -0
  1964. package/src/extensions/teleport/overlay/reconnect-banner.ts +69 -0
  1965. package/src/extensions/teleport/overlay/tab-bar.test.ts +72 -0
  1966. package/src/extensions/teleport/overlay/tab-bar.ts +146 -0
  1967. package/src/extensions/teleport/overlay/tab-manager.test.ts +484 -0
  1968. package/src/extensions/teleport/overlay/tab-manager.ts +293 -0
  1969. package/src/extensions/teleport/preflight/git.test.ts +94 -0
  1970. package/src/extensions/teleport/preflight/git.ts +40 -0
  1971. package/src/extensions/teleport/preflight/index.test.ts +97 -0
  1972. package/src/extensions/teleport/preflight/index.ts +43 -0
  1973. package/src/extensions/teleport/preflight/rsync.test.ts +39 -0
  1974. package/src/extensions/teleport/preflight/rsync.ts +23 -0
  1975. package/src/extensions/teleport/preflight/workspace-size.ts +2 -0
  1976. package/src/extensions/teleport/provisioning/concurrency.ts +40 -0
  1977. package/src/extensions/teleport/provisioning/constants.ts +3 -0
  1978. package/src/extensions/teleport/provisioning/estimate-bytes.test.ts +107 -0
  1979. package/src/extensions/teleport/provisioning/estimate-bytes.ts +123 -0
  1980. package/src/extensions/teleport/provisioning/git-provision.test.ts +76 -0
  1981. package/src/extensions/teleport/provisioning/git-provision.ts +54 -0
  1982. package/src/extensions/teleport/provisioning/include-list.test.ts +222 -0
  1983. package/src/extensions/teleport/provisioning/include-list.ts +203 -0
  1984. package/src/extensions/teleport/provisioning/paths.ts +54 -0
  1985. package/src/extensions/teleport/provisioning/proxy-command.ts +30 -0
  1986. package/src/extensions/teleport/provisioning/rsync-runner.test.ts +544 -0
  1987. package/src/extensions/teleport/provisioning/rsync-runner.ts +675 -0
  1988. package/src/extensions/teleport/pty/mouse-capture.ts +7 -0
  1989. package/src/extensions/teleport/pty/reconnect-supervisor.ts +117 -0
  1990. package/src/extensions/teleport/pty/terminal-component.test.ts +282 -0
  1991. package/src/extensions/teleport/pty/terminal-component.ts +331 -0
  1992. package/src/extensions/teleport/pty/websocket-transport.test.ts +440 -0
  1993. package/src/extensions/teleport/pty/websocket-transport.ts +228 -0
  1994. package/src/extensions/teleport/pty/xterm-core.test.ts +79 -0
  1995. package/src/extensions/teleport/pty/xterm-core.ts +159 -0
  1996. package/src/extensions/teleport/session-filter.ts +10 -0
  1997. package/src/extensions/teleport/ssh-config/paths.ts +27 -0
  1998. package/src/extensions/teleport/ssh-config/render.test.ts +111 -0
  1999. package/src/extensions/teleport/ssh-config/render.ts +97 -0
  2000. package/src/extensions/teleport/ssh-config/sync.test.ts +170 -0
  2001. package/src/extensions/teleport/ssh-config/sync.ts +92 -0
  2002. package/src/extensions/teleport/types.ts +14 -0
  2003. package/src/extensions/teleport/ui/format-bytes.ts +13 -0
  2004. package/src/extensions/teleport/ui/git-token-prompt.ts +164 -0
  2005. package/src/extensions/teleport/ui/help-modal.ts +100 -0
  2006. package/src/extensions/teleport/ui/progress.test.ts +236 -0
  2007. package/src/extensions/teleport/ui/progress.ts +345 -0
  2008. package/src/extensions/teleport/ui/remote-sessions-panel.test.ts +221 -0
  2009. package/src/extensions/teleport/ui/remote-sessions-panel.ts +309 -0
  2010. package/src/extensions/teleport/ui/sessions-table.ts +24 -0
  2011. package/src/extensions/teleport/ui/sync-progress-row.ts +30 -0
  2012. package/src/extensions/teleport/ui/tty-handoff.ts +131 -0
  2013. package/src/extensions/teleport/ui/workspaces-panel.test.ts +307 -0
  2014. package/src/extensions/teleport/ui/workspaces-panel.ts +364 -0
  2015. package/src/extensions/teleport/ui/workspaces-table.ts +12 -0
  2016. package/src/extensions/terminal-colors.ts +256 -0
  2017. package/src/extensions/terminal-compat/keyboard-capability.test.ts +69 -0
  2018. package/src/extensions/terminal-compat/keyboard-capability.ts +103 -0
  2019. package/src/extensions/terminal-compat/startup-warning.test.ts +273 -0
  2020. package/src/extensions/terminal-compat/startup-warning.ts +77 -0
  2021. package/src/extensions/theme-selector.test.ts +297 -0
  2022. package/src/extensions/theme-selector.ts +156 -0
  2023. package/src/extensions/thinking-steps/index.ts +429 -0
  2024. package/src/extensions/thinking-steps/internal-patch.ts +483 -0
  2025. package/src/extensions/thinking-steps/parse.ts +1376 -0
  2026. package/src/extensions/thinking-steps/persistence.ts +95 -0
  2027. package/src/extensions/thinking-steps/render.ts +496 -0
  2028. package/src/extensions/thinking-steps/state.ts +482 -0
  2029. package/src/extensions/thinking-steps/types.ts +55 -0
  2030. package/src/extensions/tips/general-tips.test.ts +33 -0
  2031. package/src/extensions/tips/general-tips.ts +81 -0
  2032. package/src/extensions/tips/index.test.ts +198 -0
  2033. package/src/extensions/tips/index.ts +231 -0
  2034. package/src/extensions/tips/presenter.test.ts +160 -0
  2035. package/src/extensions/tips/presenter.ts +170 -0
  2036. package/src/extensions/tips/registry.test.ts +59 -0
  2037. package/src/extensions/tips/registry.ts +66 -0
  2038. package/src/extensions/tips/tip-row.test.ts +97 -0
  2039. package/src/extensions/tips/tip-row.ts +48 -0
  2040. package/src/extensions/tips/tips-panel.test.ts +222 -0
  2041. package/src/extensions/tips/tips-panel.ts +310 -0
  2042. package/src/extensions/tips/types.ts +21 -0
  2043. package/src/extensions/todos/command.test.ts +103 -0
  2044. package/src/extensions/todos/command.ts +266 -0
  2045. package/src/extensions/todos/constants.ts +1 -0
  2046. package/src/extensions/todos/index.test.ts +405 -0
  2047. package/src/extensions/todos/index.ts +238 -0
  2048. package/src/extensions/todos/prompt-block.test.ts +219 -0
  2049. package/src/extensions/todos/prompt-block.ts +176 -0
  2050. package/src/extensions/todos/reducer.test.ts +141 -0
  2051. package/src/extensions/todos/reducer.ts +155 -0
  2052. package/src/extensions/todos/scope.test.ts +42 -0
  2053. package/src/extensions/todos/scope.ts +109 -0
  2054. package/src/extensions/todos/store.test.ts +78 -0
  2055. package/src/extensions/todos/store.ts +92 -0
  2056. package/src/extensions/todos/tool.test.ts +84 -0
  2057. package/src/extensions/todos/tool.ts +240 -0
  2058. package/src/extensions/todos/types.ts +79 -0
  2059. package/src/extensions/todos/widget.test.ts +348 -0
  2060. package/src/extensions/todos/widget.ts +332 -0
  2061. package/src/extensions/tool-grouping.test.ts +387 -0
  2062. package/src/extensions/tool-grouping.ts +346 -0
  2063. package/src/extensions/tool-rendering.test.ts +401 -0
  2064. package/src/extensions/tool-rendering.ts +4511 -0
  2065. package/src/extensions/trace-id.test.ts +230 -0
  2066. package/src/extensions/trace-id.ts +46 -0
  2067. package/src/extensions/ui-branch-poll.test.ts +164 -0
  2068. package/src/extensions/ui-branch-poll.ts +57 -0
  2069. package/src/extensions/ui.test.ts +185 -0
  2070. package/src/extensions/ui.ts +649 -0
  2071. package/src/extensions/web-fetch/browser-pool.test.ts +237 -0
  2072. package/src/extensions/web-fetch/browser-pool.ts +145 -0
  2073. package/src/extensions/web-fetch/cache.test.ts +196 -0
  2074. package/src/extensions/web-fetch/cache.ts +114 -0
  2075. package/src/extensions/web-fetch/content-converter.test.ts +341 -0
  2076. package/src/extensions/web-fetch/content-converter.ts +188 -0
  2077. package/src/extensions/web-fetch/execute-handler.test.ts +384 -0
  2078. package/src/extensions/web-fetch/execute-handler.ts +131 -0
  2079. package/src/extensions/web-fetch/index.ts +113 -0
  2080. package/src/extensions/web-fetch/integration.test.ts +618 -0
  2081. package/src/extensions/web-fetch/page-fetcher.test.ts +532 -0
  2082. package/src/extensions/web-fetch/page-fetcher.ts +358 -0
  2083. package/src/extensions/web-fetch/url-validator.test.ts +230 -0
  2084. package/src/extensions/web-fetch/url-validator.ts +153 -0
  2085. package/src/extensions/web-search/execute-handler.test.ts +216 -0
  2086. package/src/extensions/web-search/execute-handler.ts +151 -0
  2087. package/src/extensions/web-search/index.ts +107 -0
  2088. package/src/ferment/engine.test.ts +279 -0
  2089. package/src/ferment/engine.ts +320 -0
  2090. package/src/ferment/event-mapper.ts +313 -0
  2091. package/src/ferment/event-store.property.test.ts +240 -0
  2092. package/src/ferment/event-store.test.ts +780 -0
  2093. package/src/ferment/event-store.ts +1332 -0
  2094. package/src/ferment/fsm.test.ts +630 -0
  2095. package/src/ferment/fsm.ts +466 -0
  2096. package/src/ferment/lifecycle.ts +35 -0
  2097. package/src/ferment/state-machine.test.ts +1215 -0
  2098. package/src/ferment/state-machine.ts +994 -0
  2099. package/src/ferment/stats.test.ts +31 -0
  2100. package/src/ferment/stats.ts +334 -0
  2101. package/src/ferment/store.test.ts +543 -0
  2102. package/src/ferment/store.ts +906 -0
  2103. package/src/ferment/success-criteria.ts +51 -0
  2104. package/src/ferment/text.ts +11 -0
  2105. package/src/ferment/title.test.ts +35 -0
  2106. package/src/ferment/title.ts +28 -0
  2107. package/src/ferment/types.ts +277 -0
  2108. package/src/fs-paths.test.ts +104 -0
  2109. package/src/fs-paths.ts +112 -0
  2110. package/src/integrations/__fixtures__/models.ts +72 -0
  2111. package/src/integrations/bun-sqlite.d.ts +22 -0
  2112. package/src/integrations/claude-code.test.ts +488 -0
  2113. package/src/integrations/claude-code.ts +221 -0
  2114. package/src/integrations/constants.ts +9 -0
  2115. package/src/integrations/cursor.test.ts +91 -0
  2116. package/src/integrations/cursor.ts +188 -0
  2117. package/src/integrations/detect.ts +92 -0
  2118. package/src/integrations/gsd2.test.ts +146 -0
  2119. package/src/integrations/gsd2.ts +162 -0
  2120. package/src/integrations/models.ts +212 -0
  2121. package/src/integrations/openclaw.test.ts +314 -0
  2122. package/src/integrations/openclaw.ts +276 -0
  2123. package/src/integrations/opencode.test.ts +216 -0
  2124. package/src/integrations/opencode.ts +226 -0
  2125. package/src/integrations/provider/opencode.ts +37 -0
  2126. package/src/integrations/registry.test.ts +43 -0
  2127. package/src/integrations/registry.ts +33 -0
  2128. package/src/integrations/spawn.ts +88 -0
  2129. package/src/integrations/types.ts +35 -0
  2130. package/src/login-command-patch.test.ts +609 -0
  2131. package/src/login-command-patch.ts +299 -0
  2132. package/src/models.test.ts +827 -0
  2133. package/src/models.ts +379 -0
  2134. package/src/modes/acp/acp-prompter.ts +64 -0
  2135. package/src/modes/acp/acp-ui-context.test.ts +1001 -0
  2136. package/src/modes/acp/acp-ui-context.ts +435 -0
  2137. package/src/modes/acp/capabilities.ts +36 -0
  2138. package/src/modes/acp/commands.test.ts +29 -0
  2139. package/src/modes/acp/commands.ts +19 -0
  2140. package/src/modes/acp/permission-prompter-registry.ts +17 -0
  2141. package/src/modes/acp/server.test.ts +4392 -0
  2142. package/src/modes/acp/server.ts +1569 -0
  2143. package/src/modes/acp/utils.ts +10 -0
  2144. package/src/oauth-page-patch.test.ts +84 -0
  2145. package/src/ollama.test.ts +1469 -0
  2146. package/src/ollama.ts +491 -0
  2147. package/src/paste-interceptor.test.ts +179 -0
  2148. package/src/paste-interceptor.ts +61 -0
  2149. package/src/paste-to-editor-patch.test.ts +24 -0
  2150. package/src/paste-to-editor-patch.ts +27 -0
  2151. package/src/posthog-device.ts +31 -0
  2152. package/src/proxy.test.ts +36 -0
  2153. package/src/proxy.ts +36 -0
  2154. package/src/resources/bash-hook-discovery.ts +69 -0
  2155. package/src/resources/bash-hooks.test.ts +93 -0
  2156. package/src/resources/bash-hooks.ts +109 -0
  2157. package/src/resources/claude-code-hook-resources.ts +35 -0
  2158. package/src/resources/definitions.test.ts +92 -0
  2159. package/src/resources/definitions.ts +149 -0
  2160. package/src/resources/extension.test.ts +168 -0
  2161. package/src/resources/extension.ts +114 -0
  2162. package/src/resources/filter.ts +11 -0
  2163. package/src/resources/package-resources.test.ts +234 -0
  2164. package/src/resources/package-resources.ts +152 -0
  2165. package/src/resources/rtk-install.test.ts +37 -0
  2166. package/src/resources/rtk-install.ts +289 -0
  2167. package/src/resources/store.test.ts +118 -0
  2168. package/src/resources/store.ts +76 -0
  2169. package/src/resources/tool-blocker.ts +14 -0
  2170. package/src/resources/types.ts +23 -0
  2171. package/src/resources/ui.test.ts +74 -0
  2172. package/src/resources/ui.ts +221 -0
  2173. package/src/sandbox/cloud/auth.test.ts +219 -0
  2174. package/src/sandbox/cloud/auth.ts +127 -0
  2175. package/src/sandbox/cloud/http.test.ts +88 -0
  2176. package/src/sandbox/cloud/http.ts +46 -0
  2177. package/src/sandbox/cloud/index.ts +18 -0
  2178. package/src/sandbox/cloud/keys.test.ts +44 -0
  2179. package/src/sandbox/cloud/keys.ts +34 -0
  2180. package/src/sandbox/cloud/readiness.test.ts +115 -0
  2181. package/src/sandbox/cloud/readiness.ts +122 -0
  2182. package/src/sandbox/cloud/types.ts +70 -0
  2183. package/src/sandbox/cloud/uri.test.ts +51 -0
  2184. package/src/sandbox/cloud/uri.ts +30 -0
  2185. package/src/sandbox/cloud/workspaces.test.ts +249 -0
  2186. package/src/sandbox/cloud/workspaces.ts +161 -0
  2187. package/src/sandbox/constants.ts +2 -0
  2188. package/src/sandbox/git-credentials.test.ts +89 -0
  2189. package/src/sandbox/git-credentials.ts +72 -0
  2190. package/src/sandbox/worker/client.test.ts +156 -0
  2191. package/src/sandbox/worker/client.ts +201 -0
  2192. package/src/sandbox/worker/git-identity.test.ts +99 -0
  2193. package/src/sandbox/worker/git-identity.ts +69 -0
  2194. package/src/sandbox/worker/index.ts +36 -0
  2195. package/src/sandbox/worker/secrets.test.ts +61 -0
  2196. package/src/sandbox/worker/secrets.ts +28 -0
  2197. package/src/sandbox/worker/sessions.test.ts +197 -0
  2198. package/src/sandbox/worker/sessions.ts +32 -0
  2199. package/src/sandbox/worker/status.test.ts +57 -0
  2200. package/src/sandbox/worker/status.ts +6 -0
  2201. package/src/sandbox/worker/types.ts +119 -0
  2202. package/src/set-package-dir.ts +5 -0
  2203. package/src/settings-watcher.test.ts +116 -0
  2204. package/src/settings-watcher.ts +79 -0
  2205. package/src/setup-wizard/apply-tools.test.ts +131 -0
  2206. package/src/setup-wizard/apply-tools.ts +70 -0
  2207. package/src/setup-wizard/index.ts +107 -0
  2208. package/src/setup-wizard/prompt.ts +126 -0
  2209. package/src/setup-wizard/shell-profile.test.ts +154 -0
  2210. package/src/setup-wizard/shell-profile.ts +169 -0
  2211. package/src/setup-wizard/state.ts +45 -0
  2212. package/src/setup-wizard/steps/auth.test.ts +145 -0
  2213. package/src/setup-wizard/steps/auth.ts +130 -0
  2214. package/src/setup-wizard/steps/done.test.ts +267 -0
  2215. package/src/setup-wizard/steps/done.ts +121 -0
  2216. package/src/setup-wizard/steps/rtk.ts +6 -0
  2217. package/src/setup-wizard/steps/telemetry.test.ts +46 -0
  2218. package/src/setup-wizard/steps/telemetry.ts +41 -0
  2219. package/src/setup-wizard/steps/tools.ts +45 -0
  2220. package/src/setup-wizard/steps/welcome.ts +42 -0
  2221. package/src/setup-wizard.test.ts +384 -0
  2222. package/src/setup-wizard.ts +405 -0
  2223. package/src/shared/planning/entry-trigger-registry.test.ts +427 -0
  2224. package/src/shared/planning/entry-trigger-registry.ts +216 -0
  2225. package/src/shared/planning/plan-artifact-store.test.ts +338 -0
  2226. package/src/shared/planning/plan-artifact-store.ts +244 -0
  2227. package/src/shared/planning/plan-decomposition.test.ts +183 -0
  2228. package/src/shared/planning/plan-decomposition.ts +338 -0
  2229. package/src/shared/planning/planning-stop-nudge.test.ts +217 -0
  2230. package/src/shared/planning/planning-stop-nudge.ts +133 -0
  2231. package/src/shared/planning/prompt-supplement-registry.test.ts +264 -0
  2232. package/src/shared/planning/prompt-supplement-registry.ts +250 -0
  2233. package/src/shared/planning/read-only-tool-registry.test.ts +96 -0
  2234. package/src/shared/planning/read-only-tool-registry.ts +98 -0
  2235. package/src/shared/planning/shared-planning-process.test.ts +224 -0
  2236. package/src/shared/planning/shared-planning-process.ts +128 -0
  2237. package/src/shared/planning/tool-catalog.test.ts +344 -0
  2238. package/src/shared/planning/tool-catalog.ts +258 -0
  2239. package/src/shared/planning/tool-profile-manager.test.ts +409 -0
  2240. package/src/shared/planning/tool-profile-manager.ts +281 -0
  2241. package/src/skill-paths.test.ts +33 -0
  2242. package/src/skill-paths.ts +18 -0
  2243. package/src/skills-wizard.ts +44 -0
  2244. package/src/ssh-proxy.test.ts +102 -0
  2245. package/src/ssh-proxy.ts +79 -0
  2246. package/src/startup-context.ts +23 -0
  2247. package/src/startup-settings.test.ts +37 -0
  2248. package/src/startup-settings.ts +26 -0
  2249. package/src/terminal-bg-probe.test.ts +131 -0
  2250. package/src/terminal-bg-probe.ts +238 -0
  2251. package/src/theme-file-watcher.ts +95 -0
  2252. package/src/types/before-provider-headers.ts +48 -0
  2253. package/src/types/pi-coding-agent-utils.d.ts +34 -0
  2254. package/src/update/extract.ts +75 -0
  2255. package/src/update/github.test.ts +133 -0
  2256. package/src/update/github.ts +190 -0
  2257. package/src/update/install.test.ts +210 -0
  2258. package/src/update/install.ts +205 -0
  2259. package/src/update/paths.test.ts +97 -0
  2260. package/src/update/paths.ts +109 -0
  2261. package/src/update/state.test.ts +215 -0
  2262. package/src/update/state.ts +94 -0
  2263. package/src/update/workflow.test.ts +397 -0
  2264. package/src/update/workflow.ts +217 -0
  2265. package/src/upstream-retry-patch.test.ts +77 -0
  2266. package/src/upstream-retry-patch.ts +41 -0
  2267. package/src/utils/clipboard-image.test.ts +117 -0
  2268. package/src/utils/clipboard-image.ts +316 -0
  2269. package/src/utils/clipboard-linux-routing.test.ts +100 -0
  2270. package/src/utils/clipboard-linux-subprocess.test.ts +176 -0
  2271. package/src/utils/clipboard-linux-subprocess.ts +58 -0
  2272. package/src/utils/clipboard-native-harness-wsl.test.ts +109 -0
  2273. package/src/utils/clipboard-native-harness.test.ts +54 -0
  2274. package/src/utils/clipboard-native-harness.ts +146 -0
  2275. package/src/utils/clipboard-read.test.ts +88 -0
  2276. package/src/utils/clipboard-read.ts +69 -0
  2277. package/src/utils/export-post-process.test.ts +539 -0
  2278. package/src/utils/export-post-process.ts +213 -0
  2279. package/src/utils/http.test.ts +302 -0
  2280. package/src/utils/http.ts +106 -0
  2281. package/src/utils/image-registry.test.ts +88 -0
  2282. package/src/utils/image-registry.ts +132 -0
  2283. package/src/utils/image-utils.test.ts +58 -0
  2284. package/src/utils/image-utils.ts +38 -0
  2285. package/src/utils/os-metadata.ts +65 -0
  2286. package/src/utils/sandbox.test.ts +98 -0
  2287. package/src/utils/sandbox.ts +24 -0
  2288. package/src/utils/session-metadata-store.test.ts +228 -0
  2289. package/src/utils/session-metadata-store.ts +96 -0
  2290. package/src/utils/spawn-ikie-subprocess.ts +57 -0
  2291. package/src/utils/trace-id-export.test.ts +343 -0
  2292. package/src/utils/trace-id-export.ts +84 -0
  2293. package/src/utils.test.ts +38 -0
  2294. package/src/utils.ts +65 -0
  2295. package/test-cases/README.md +54 -0
  2296. package/test-cases/bitcoin-price.md +52 -0
  2297. package/test-cases/golang-question.md +29 -0
  2298. package/test-cases/offender.md +32 -0
  2299. package/test-cases/pi-mono-design.md +27 -0
  2300. package/test-cases/pi-mono-tool-card-loop.txt +1381 -0
  2301. package/test-cases/pi-mono-tool-card.md +60 -0
  2302. package/test-cases/pokemon.md +27 -0
  2303. package/test-cases/problem-740.md +20 -0
  2304. package/test-cases/python-project.md +24 -0
  2305. package/test-cases/remove-home-directory.md +53 -0
  2306. package/test-cases/use-gh.md +25 -0
  2307. package/tests/e2e/acp/all-capabilities.test.ts +102 -0
  2308. package/tests/e2e/acp/elicitation-dialogs.test.ts +139 -0
  2309. package/tests/e2e/acp/elicitation-only.test.ts +76 -0
  2310. package/tests/e2e/acp/message-id.test.ts +139 -0
  2311. package/tests/e2e/acp/no-capabilities.test.ts +71 -0
  2312. package/tests/e2e/acp/permission-flow.test.ts +237 -0
  2313. package/tests/e2e/acp/support/acp-fixture.ts +413 -0
  2314. package/tests/e2e/acp/support/scenarios.ts +55 -0
  2315. package/tests/e2e/acp/support/test-dialog-extension.js +22 -0
  2316. package/tests/e2e/acp/support/test-ui-extension.js +14 -0
  2317. package/tests/e2e/acp/vitest.config.ts +12 -0
  2318. package/tests/e2e/tui/ask-user-form.test.ts +310 -0
  2319. package/tests/e2e/tui/basic-session-lifecycle.test.ts +20 -0
  2320. package/tests/e2e/tui/branch-resume.test.ts +71 -0
  2321. package/tests/e2e/tui/cooking-animation.test.ts +213 -0
  2322. package/tests/e2e/tui/editor-narrow-layout.test.ts +47 -0
  2323. package/tests/e2e/tui/extension-custom-headers.test.ts +75 -0
  2324. package/tests/e2e/tui/ferment-draft-proposal-persistence.test.ts +125 -0
  2325. package/tests/e2e/tui/ferment-new-runs-planning.test.ts +211 -0
  2326. package/tests/e2e/tui/ferment-phase-review.test.ts +78 -0
  2327. package/tests/e2e/tui/ferment-plan-review-suppression.test.ts +404 -0
  2328. package/tests/e2e/tui/multi-model-command.test.ts +624 -0
  2329. package/tests/e2e/tui/nudge-wiring.test.ts +129 -0
  2330. package/tests/e2e/tui/ollama-models.test.ts +143 -0
  2331. package/tests/e2e/tui/oneshot-bypasses-dropdown.test.ts +97 -0
  2332. package/tests/e2e/tui/plan-mode-tool-switch.test.ts +73 -0
  2333. package/tests/e2e/tui/plan-review-dismissal.test.ts +291 -0
  2334. package/tests/e2e/tui/plan-to-ferment-promo.test.ts +204 -0
  2335. package/tests/e2e/tui/skip-list.js +9 -0
  2336. package/tests/e2e/tui/support/assertions.ts +41 -0
  2337. package/tests/e2e/tui/support/fake-ollama-server.ts +356 -0
  2338. package/tests/e2e/tui/support/fake-openai-server.ts +361 -0
  2339. package/tests/e2e/tui/support/ikie-fixture.ts +374 -0
  2340. package/tests/e2e/tui/theme-selector.test.ts +99 -0
  2341. package/tests/e2e/tui/todo-overlay.test.ts +163 -0
  2342. package/tests/e2e/tui/todo-widget-ferment.test.ts +346 -0
  2343. package/tests/e2e/tui/tui-test.config.ts +6 -0
  2344. package/tests/smoke/agent-session-tracking.test.ts +203 -0
  2345. package/tests/smoke/binary.test.ts +186 -0
  2346. package/tests/smoke/ferment-oneshot-exit.test.ts +514 -0
  2347. package/tests/smoke/harness.ts +236 -0
  2348. package/tests/smoke/interactive-paste.test.ts +167 -0
  2349. package/tests/smoke/vitest.config.ts +12 -0
  2350. package/tests/smoke/web-fetch.test.ts +41 -0
  2351. package/tests/smoke/web-search.test.ts +47 -0
  2352. package/themes/catppuccin-macchiato.json +82 -0
  2353. package/themes/dark.json +87 -0
  2354. package/themes/dracula.json +79 -0
  2355. package/themes/github-dark.json +80 -0
  2356. package/themes/github-light.json +80 -0
  2357. package/themes/ikie-light.json +92 -0
  2358. package/themes/ikie-minimal.json +79 -0
  2359. package/themes/ikie.json +96 -0
  2360. package/themes/light.json +86 -0
  2361. package/themes/lucent-orng.json +79 -0
  2362. package/themes/monokai.json +78 -0
  2363. package/themes/neon.json +87 -0
  2364. package/themes/night-owl.json +87 -0
  2365. package/themes/nord.json +82 -0
  2366. package/themes/one-dark.json +79 -0
  2367. package/themes/solarized-dark.json +81 -0
  2368. package/themes/solarized-light.json +81 -0
  2369. package/tools/proxy-helper/Makefile +11 -0
  2370. package/tools/proxy-helper/cmd/proxy/proxy.go +211 -0
  2371. package/tools/proxy-helper/cmd/proxy/proxy_test.go +309 -0
  2372. package/tools/proxy-helper/go.mod +13 -0
  2373. package/tools/proxy-helper/go.sum +12 -0
  2374. package/tools/proxy-helper/main.go +29 -0
  2375. package/tools/proxy-helper/pkg/cast/cast.go +287 -0
  2376. package/tsconfig.json +17 -0
  2377. package/vendor/superpowers/.claude-plugin/marketplace.json +20 -0
  2378. package/vendor/superpowers/.claude-plugin/plugin.json +20 -0
  2379. package/vendor/superpowers/.codex-plugin/plugin.json +47 -0
  2380. package/vendor/superpowers/.cursor-plugin/plugin.json +25 -0
  2381. package/vendor/superpowers/.gitattributes +18 -0
  2382. package/vendor/superpowers/.github/FUNDING.yml +3 -0
  2383. package/vendor/superpowers/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
  2384. package/vendor/superpowers/.github/ISSUE_TEMPLATE/config.yml +5 -0
  2385. package/vendor/superpowers/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
  2386. package/vendor/superpowers/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
  2387. package/vendor/superpowers/.github/PULL_REQUEST_TEMPLATE.md +126 -0
  2388. package/vendor/superpowers/.opencode/INSTALL.md +110 -0
  2389. package/vendor/superpowers/.opencode/plugins/superpowers.js +135 -0
  2390. package/vendor/superpowers/.version-bump.json +20 -0
  2391. package/vendor/superpowers/CLAUDE.md +106 -0
  2392. package/vendor/superpowers/CODE_OF_CONDUCT.md +128 -0
  2393. package/vendor/superpowers/GEMINI.md +2 -0
  2394. package/vendor/superpowers/LICENSE +21 -0
  2395. package/vendor/superpowers/README.md +233 -0
  2396. package/vendor/superpowers/RELEASE-NOTES.md +1180 -0
  2397. package/vendor/superpowers/assets/app-icon.png +0 -0
  2398. package/vendor/superpowers/assets/superpowers-small.svg +1 -0
  2399. package/vendor/superpowers/docs/README.opencode.md +157 -0
  2400. package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-design.md +294 -0
  2401. package/vendor/superpowers/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
  2402. package/vendor/superpowers/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
  2403. package/vendor/superpowers/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
  2404. package/vendor/superpowers/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
  2405. package/vendor/superpowers/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
  2406. package/vendor/superpowers/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
  2407. package/vendor/superpowers/docs/superpowers/plans/2026-03-23-codex-app-compatibility.md +564 -0
  2408. package/vendor/superpowers/docs/superpowers/plans/2026-04-06-worktree-rototill.md +879 -0
  2409. package/vendor/superpowers/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
  2410. package/vendor/superpowers/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
  2411. package/vendor/superpowers/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
  2412. package/vendor/superpowers/docs/superpowers/specs/2026-03-23-codex-app-compatibility-design.md +244 -0
  2413. package/vendor/superpowers/docs/superpowers/specs/2026-04-06-worktree-rototill-design.md +342 -0
  2414. package/vendor/superpowers/docs/testing.md +303 -0
  2415. package/vendor/superpowers/docs/windows/polyglot-hooks.md +212 -0
  2416. package/vendor/superpowers/gemini-extension.json +6 -0
  2417. package/vendor/superpowers/hooks/hooks-cursor.json +10 -0
  2418. package/vendor/superpowers/hooks/hooks.json +16 -0
  2419. package/vendor/superpowers/hooks/run-hook.cmd +46 -0
  2420. package/vendor/superpowers/hooks/session-start +57 -0
  2421. package/vendor/superpowers/package.json +6 -0
  2422. package/vendor/superpowers/scripts/bump-version.sh +220 -0
  2423. package/vendor/superpowers/scripts/sync-to-codex-plugin.sh +462 -0
  2424. package/vendor/superpowers/skills/brainstorming/SKILL.md +164 -0
  2425. package/vendor/superpowers/skills/brainstorming/scripts/frame-template.html +214 -0
  2426. package/vendor/superpowers/skills/brainstorming/scripts/helper.js +88 -0
  2427. package/vendor/superpowers/skills/brainstorming/scripts/server.cjs +354 -0
  2428. package/vendor/superpowers/skills/brainstorming/scripts/start-server.sh +148 -0
  2429. package/vendor/superpowers/skills/brainstorming/scripts/stop-server.sh +56 -0
  2430. package/vendor/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  2431. package/vendor/superpowers/skills/brainstorming/visual-companion.md +287 -0
  2432. package/vendor/superpowers/skills/dispatching-parallel-agents/SKILL.md +182 -0
  2433. package/vendor/superpowers/skills/executing-plans/SKILL.md +70 -0
  2434. package/vendor/superpowers/skills/finishing-a-development-branch/SKILL.md +251 -0
  2435. package/vendor/superpowers/skills/receiving-code-review/SKILL.md +213 -0
  2436. package/vendor/superpowers/skills/requesting-code-review/SKILL.md +103 -0
  2437. package/vendor/superpowers/skills/requesting-code-review/code-reviewer.md +168 -0
  2438. package/vendor/superpowers/skills/subagent-driven-development/SKILL.md +279 -0
  2439. package/vendor/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
  2440. package/vendor/superpowers/skills/subagent-driven-development/implementer-prompt.md +113 -0
  2441. package/vendor/superpowers/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  2442. package/vendor/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
  2443. package/vendor/superpowers/skills/systematic-debugging/SKILL.md +296 -0
  2444. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  2445. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
  2446. package/vendor/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
  2447. package/vendor/superpowers/skills/systematic-debugging/find-polluter.sh +63 -0
  2448. package/vendor/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
  2449. package/vendor/superpowers/skills/systematic-debugging/test-academic.md +14 -0
  2450. package/vendor/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
  2451. package/vendor/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
  2452. package/vendor/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
  2453. package/vendor/superpowers/skills/test-driven-development/SKILL.md +371 -0
  2454. package/vendor/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
  2455. package/vendor/superpowers/skills/using-git-worktrees/SKILL.md +215 -0
  2456. package/vendor/superpowers/skills/using-superpowers/SKILL.md +117 -0
  2457. package/vendor/superpowers/skills/using-superpowers/references/codex-tools.md +59 -0
  2458. package/vendor/superpowers/skills/using-superpowers/references/copilot-tools.md +42 -0
  2459. package/vendor/superpowers/skills/using-superpowers/references/gemini-tools.md +51 -0
  2460. package/vendor/superpowers/skills/verification-before-completion/SKILL.md +139 -0
  2461. package/vendor/superpowers/skills/writing-plans/SKILL.md +152 -0
  2462. package/vendor/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  2463. package/vendor/superpowers/skills/writing-skills/SKILL.md +655 -0
  2464. package/vendor/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
  2465. package/vendor/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  2466. package/vendor/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
  2467. package/vendor/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
  2468. package/vendor/superpowers/skills/writing-skills/render-graphs.js +168 -0
  2469. package/vendor/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  2470. package/vendor/superpowers/tests/brainstorm-server/package-lock.json +36 -0
  2471. package/vendor/superpowers/tests/brainstorm-server/package.json +10 -0
  2472. package/vendor/superpowers/tests/brainstorm-server/server.test.js +427 -0
  2473. package/vendor/superpowers/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
  2474. package/vendor/superpowers/tests/brainstorm-server/ws-protocol.test.js +392 -0
  2475. package/vendor/superpowers/tests/claude-code/README.md +170 -0
  2476. package/vendor/superpowers/tests/claude-code/analyze-token-usage.py +168 -0
  2477. package/vendor/superpowers/tests/claude-code/run-skill-tests.sh +188 -0
  2478. package/vendor/superpowers/tests/claude-code/test-document-review-system.sh +177 -0
  2479. package/vendor/superpowers/tests/claude-code/test-helpers.sh +202 -0
  2480. package/vendor/superpowers/tests/claude-code/test-requesting-code-review.sh +214 -0
  2481. package/vendor/superpowers/tests/claude-code/test-subagent-driven-development-integration.sh +322 -0
  2482. package/vendor/superpowers/tests/claude-code/test-subagent-driven-development.sh +165 -0
  2483. package/vendor/superpowers/tests/claude-code/test-worktree-native-preference.sh +176 -0
  2484. package/vendor/superpowers/tests/codex-plugin-sync/test-sync-to-codex-plugin.sh +615 -0
  2485. package/vendor/superpowers/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
  2486. package/vendor/superpowers/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
  2487. package/vendor/superpowers/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
  2488. package/vendor/superpowers/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
  2489. package/vendor/superpowers/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
  2490. package/vendor/superpowers/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
  2491. package/vendor/superpowers/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
  2492. package/vendor/superpowers/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
  2493. package/vendor/superpowers/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
  2494. package/vendor/superpowers/tests/explicit-skill-requests/run-all.sh +70 -0
  2495. package/vendor/superpowers/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
  2496. package/vendor/superpowers/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
  2497. package/vendor/superpowers/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
  2498. package/vendor/superpowers/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
  2499. package/vendor/superpowers/tests/explicit-skill-requests/run-test.sh +136 -0
  2500. package/vendor/superpowers/tests/opencode/run-tests.sh +165 -0
  2501. package/vendor/superpowers/tests/opencode/setup.sh +88 -0
  2502. package/vendor/superpowers/tests/opencode/test-bootstrap-caching.mjs +124 -0
  2503. package/vendor/superpowers/tests/opencode/test-bootstrap-caching.sh +32 -0
  2504. package/vendor/superpowers/tests/opencode/test-plugin-loading.sh +82 -0
  2505. package/vendor/superpowers/tests/opencode/test-priority.sh +217 -0
  2506. package/vendor/superpowers/tests/opencode/test-tools.sh +95 -0
  2507. package/vendor/superpowers/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
  2508. package/vendor/superpowers/tests/skill-triggering/prompts/executing-plans.txt +1 -0
  2509. package/vendor/superpowers/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
  2510. package/vendor/superpowers/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
  2511. package/vendor/superpowers/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
  2512. package/vendor/superpowers/tests/skill-triggering/prompts/writing-plans.txt +10 -0
  2513. package/vendor/superpowers/tests/skill-triggering/run-all.sh +60 -0
  2514. package/vendor/superpowers/tests/skill-triggering/run-test.sh +88 -0
  2515. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/design.md +81 -0
  2516. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
  2517. package/vendor/superpowers/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
  2518. package/vendor/superpowers/tests/subagent-driven-dev/run-test.sh +106 -0
  2519. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
  2520. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
  2521. package/vendor/superpowers/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
  2522. package/vitest.config.ts +22 -0
@@ -0,0 +1,4511 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
2
+ import { readFile as readFileAsync } from "node:fs/promises"
3
+ import { extname, relative, resolve } from "node:path"
4
+ import { formatDuration } from "../extensions/format.js"
5
+
6
+ import type {
7
+ BashToolDetails,
8
+ ExtensionAPI,
9
+ GrepToolDetails,
10
+ ReadToolDetails,
11
+ Theme,
12
+ } from "@earendil-works/pi-coding-agent"
13
+ import {
14
+ AssistantMessageComponent,
15
+ ToolExecutionComponent,
16
+ UserMessageComponent,
17
+ createBashTool,
18
+ createEditTool,
19
+ createFindTool,
20
+ createGrepTool,
21
+ createLsTool,
22
+ createReadTool,
23
+ createWriteTool,
24
+ } from "@earendil-works/pi-coding-agent"
25
+ import {
26
+ Container,
27
+ Text,
28
+ deleteAllKittyImages,
29
+ getCapabilities,
30
+ getImageDimensions,
31
+ imageFallback,
32
+ truncateToWidth,
33
+ visibleWidth,
34
+ wrapTextWithAnsi,
35
+ } from "@earendil-works/pi-tui"
36
+
37
+ import * as Diff from "diff"
38
+ import { getBashCommandForDisplay } from "./rtk-rewrite.js"
39
+ import { TODO_TOOL_NAMES } from "./todos/tool.js"
40
+ import type { BundledLanguage, BundledTheme } from "shiki"
41
+
42
+ const RESET = "\x1b[0m"
43
+ const TRANSPARENT_BG = "\x1b[49m"
44
+ const TRANSPARENT_RESET = `${RESET}${TRANSPARENT_BG}`
45
+
46
+ // Border / branch rule colors. Defaults match the previous hardcoded values
47
+ // so behavior is identical when the theme is unavailable or themeAdaptive=false.
48
+ // `applyThemePaletteIfNeeded(theme)` re-derives these from `theme.fg("borderMuted"|"muted")`.
49
+ let BORDER_COLOR = "\x1b[38;5;238m"
50
+ const ANSI_RE = /\x1b\[[0-9;]*m/g
51
+ const ANSI_PRESENT_RE = /\x1b\[[0-9;]*m/
52
+ const PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-container-render")
53
+ const TOOL_RENDER_CACHE = Symbol.for("pi-claude-style-tools:tool-render-cache")
54
+ const TOOL_CACHE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-tool-cache-invalidation")
55
+ const TOOL_IMAGE_EXPAND_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-read-image-expansion")
56
+ const USER_MESSAGE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-user-message-render")
57
+ const HIDDEN_TOOL_BLOCK_NAMES = new Set(["write_todos", ...TODO_TOOL_NAMES])
58
+ const WRAP_MARK = "\uE000"
59
+ const KITTY_IMAGE_PREFIX = "\x1b_G"
60
+ const ITERM2_IMAGE_PREFIX = "\x1b]1337;File="
61
+
62
+ let toolBackgroundMode: "default" | "transparent" | "outlines" = "outlines"
63
+
64
+ interface SettingsFile {
65
+ toolBackground?: "default" | "transparent" | "outlines" | "border"
66
+ readOutputMode?: "hidden" | "summary" | "preview"
67
+ searchOutputMode?: "hidden" | "count" | "preview"
68
+ mcpOutputMode?: "hidden" | "summary" | "preview"
69
+ previewLines?: number
70
+ expandedPreviewMaxLines?: number
71
+ bashOutputMode?: "opencode" | "summary" | "preview"
72
+ bashCollapsedLines?: number
73
+ showTruncationHints?: boolean
74
+ diffCollapsedLines?: number
75
+ diffTheme?: string
76
+ diffColors?: Record<string, string>
77
+ /**
78
+ * When true (default), derive borders, dim text, branch rules, and diff
79
+ * accents from the active pi theme via `theme.getFgAnsi`/`getBgAnsi`.
80
+ * Explicit `diffTheme` / `diffColors` always win over theme-derived
81
+ * defaults so users keep full control.
82
+ */
83
+ themeAdaptive?: boolean
84
+ /**
85
+ * Theme color key used for the spinner verb (e.g. "Cooking…"). Defaults
86
+ * to "accent". Useful when the active theme's accent is overloaded for
87
+ * borders, headings, or bash mode and the verb should pop differently.
88
+ * Valid keys are any of the pi theme `ThemeColor` names (e.g. accent,
89
+ * borderAccent, success, warning, mdHeading, thinkingMedium, bashMode).
90
+ */
91
+ spinnerVerbColor?: string
92
+ /**
93
+ * Theme color key used for the spinner status suffix (the parenthesized
94
+ * "(thinking · ↓ 10 tokens · 2s)" trailer). Defaults to "muted".
95
+ */
96
+ spinnerStatusColor?: string
97
+ }
98
+
99
+ let _settingsCache: { value: SettingsFile; timestamp: number } | null = null
100
+ const SETTINGS_CACHE_TTL_MS = 5_000
101
+
102
+ function readSettings(): SettingsFile {
103
+ const now = Date.now()
104
+ if (_settingsCache && now - _settingsCache.timestamp < SETTINGS_CACHE_TTL_MS) {
105
+ return _settingsCache.value
106
+ }
107
+ const paths = [`${process.cwd()}/.pi/settings.json`, `${process.env.HOME ?? ""}/.pi/settings.json`]
108
+ for (const path of paths) {
109
+ try {
110
+ if (!path || !existsSync(path)) continue
111
+ const raw = JSON.parse(readFileSync(path, "utf8"))
112
+ if (raw && typeof raw === "object") {
113
+ const result = raw as SettingsFile
114
+ _settingsCache = { value: result, timestamp: now }
115
+ return result
116
+ }
117
+ } catch {
118
+ // ignore invalid settings files
119
+ }
120
+ }
121
+ const empty: SettingsFile = {}
122
+ _settingsCache = { value: empty, timestamp: now }
123
+ return empty
124
+ }
125
+
126
+ // Cross-extension bust signal for spinner.ts — it watches this counter on
127
+ // globalThis and invalidates its settings cache when it changes. Lets
128
+ // /cc-spinner edits take effect on the next 250ms spinner tick instead of
129
+ // waiting for the file-stat TTL.
130
+ const SPINNER_BUST_KEY = Symbol.for("pi-claude-style-tools:spinner-settings-bust")
131
+ function bustSpinnerSettingsCache(): void {
132
+ const current = ((globalThis as any)[SPINNER_BUST_KEY] as number | undefined) ?? 0
133
+ ;(globalThis as any)[SPINNER_BUST_KEY] = current + 1
134
+ }
135
+
136
+ function writeSettingsKey(key: string, value: unknown): void {
137
+ _settingsCache = null // invalidate cache on write
138
+ const home = process.env.HOME ?? ""
139
+ if (!home) return
140
+ const dir = `${home}/.pi`
141
+ const path = `${dir}/settings.json`
142
+ let settings: Record<string, unknown> = {}
143
+ try {
144
+ if (existsSync(path)) settings = JSON.parse(readFileSync(path, "utf8")) ?? {}
145
+ } catch {
146
+ /* start fresh */
147
+ }
148
+ if (value === undefined) {
149
+ delete settings[key]
150
+ } else {
151
+ settings[key] = value
152
+ }
153
+ try {
154
+ mkdirSync(dir, { recursive: true })
155
+ writeFileSync(path, JSON.stringify(settings, null, 2) + "\n")
156
+ } catch {
157
+ /* best effort */
158
+ }
159
+ }
160
+
161
+ let toolBackgroundOverride: "default" | "transparent" | "outlines" | null = null
162
+
163
+ function syncToolBackgroundMode(): void {
164
+ if (toolBackgroundOverride) {
165
+ toolBackgroundMode = toolBackgroundOverride
166
+ return
167
+ }
168
+ const settings = readSettings()
169
+ // Backward compat: "border" was renamed to "outlines"
170
+ const raw = settings.toolBackground === "border" ? "outlines" : settings.toolBackground
171
+ toolBackgroundMode = raw ?? "outlines"
172
+ }
173
+
174
+ function setThemeBg(theme: unknown, key: string, value: string): void {
175
+ const themeAny = theme as any
176
+ if (themeAny.bgColors instanceof Map) {
177
+ themeAny.bgColors.set(key, value)
178
+ } else if (themeAny.bgColors && typeof themeAny.bgColors === "object") {
179
+ themeAny.bgColors[key] = value
180
+ }
181
+ }
182
+
183
+ function applyToolBackgroundMode(theme: unknown): void {
184
+ syncToolBackgroundMode()
185
+ if (toolBackgroundMode === "default") return
186
+
187
+ setThemeBg(theme, "toolPendingBg", TRANSPARENT_BG)
188
+ setThemeBg(theme, "toolSuccessBg", TRANSPARENT_BG)
189
+ setThemeBg(theme, "toolErrorBg", TRANSPARENT_BG)
190
+ }
191
+
192
+ function stripAnsi(text: string): string {
193
+ return text.replace(ANSI_RE, "")
194
+ }
195
+
196
+ function isBlankLine(text: string): boolean {
197
+ // Strip ANSI escapes and the ▍ stroke prefix (with its trailing space) before checking.
198
+ return stripAnsi(text).replace(/▍ ?/g, "").trim().length === 0
199
+ }
200
+
201
+ function borderLine(width: number): string {
202
+ return `${BORDER_COLOR}${"─".repeat(Math.max(1, width))}${TRANSPARENT_RESET}`
203
+ }
204
+
205
+ function clampLineWidth(line: string, width: number): string {
206
+ if (width <= 0) return ""
207
+ return visibleWidth(line) > width ? truncateToWidth(line, width) : line
208
+ }
209
+
210
+ function isToolExecutionLike(value: unknown): value is { toolName: string; toolCallId: string } {
211
+ if (!value || typeof value !== "object") return false
212
+ const candidate = value as Record<string, unknown>
213
+ return typeof candidate.toolName === "string" && typeof candidate.toolCallId === "string"
214
+ }
215
+
216
+ function isTerminalImageLine(line: string): boolean {
217
+ return line.includes(KITTY_IMAGE_PREFIX) || line.includes(ITERM2_IMAGE_PREFIX)
218
+ }
219
+
220
+ function normalizeLeadingCheckGlyph(line: string): string {
221
+ return line.replace(/^((?:\x1b\[[0-9;]*m|[ \t])*)[✓✔](?=\s)/, "$1●")
222
+ }
223
+
224
+ function firstImageBlockStart(lines: string[]): number {
225
+ const imageLineIndex = lines.findIndex(isTerminalImageLine)
226
+ if (imageLineIndex === -1) return -1
227
+ let start = imageLineIndex
228
+ while (start > 0 && isBlankLine(lines[start - 1])) start--
229
+ return start
230
+ }
231
+
232
+ function splitRenderedImageBlock(lines: string[]): { textLines: string[]; imageLines: string[] } {
233
+ const imageStart = firstImageBlockStart(lines)
234
+ if (imageStart === -1) return { textLines: lines, imageLines: [] }
235
+ const textLines = lines.slice(0, imageStart)
236
+ while (textLines.length > 0 && isBlankLine(textLines[textLines.length - 1])) textLines.pop()
237
+ return { textLines, imageLines: lines.slice(imageStart) }
238
+ }
239
+
240
+ function patchGlobalToolBorders(): void {
241
+ const proto = Container.prototype as any
242
+ if (proto[PATCH_FLAG]) return
243
+
244
+ const originalRender = proto.render
245
+ proto.render = function patchedContainerRender(width: number): string[] {
246
+ if (isToolExecutionLike(this) && HIDDEN_TOOL_BLOCK_NAMES.has(this.toolName.toLowerCase())) return []
247
+ if (isToolExecutionLike(this)) {
248
+ const cached = (this as any)[TOOL_RENDER_CACHE]
249
+ if (cached?.width === width && cached?.mode === toolBackgroundMode) {
250
+ return cached.lines
251
+ }
252
+ }
253
+
254
+ const rendered = originalRender.call(this, width)
255
+ if (!Array.isArray(rendered) || rendered.length === 0) return rendered
256
+ if (!isToolExecutionLike(this)) return rendered
257
+ if (toolBackgroundMode === "default") {
258
+ ;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: rendered }
259
+ return rendered
260
+ }
261
+
262
+ let start = 0
263
+ while (start < rendered.length && isBlankLine(rendered[start])) start++
264
+ let end = rendered.length - 1
265
+ while (end >= start && isBlankLine(rendered[end])) end--
266
+ if (start > end) return rendered
267
+
268
+ const { textLines, imageLines } = splitRenderedImageBlock(rendered.slice(start, end + 1))
269
+ if (imageLines.length > 0) {
270
+ ;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: rendered }
271
+ return rendered
272
+ }
273
+ const core = textLines.map((line) => clampLineWidth(normalizeLeadingCheckGlyph(line), width))
274
+ const spacerLine = " ".repeat(width)
275
+ let result: string[]
276
+
277
+ if (toolBackgroundMode === "outlines") {
278
+ const ruleWidth = Math.max(1, width)
279
+ const framed = core.length > 0 ? [borderLine(ruleWidth), ...core, borderLine(ruleWidth)] : []
280
+ result = [spacerLine, ...framed, ...imageLines]
281
+ } else {
282
+ result = [spacerLine, ...core, ...imageLines]
283
+ }
284
+ ;(this as any)[TOOL_RENDER_CACHE] = { width, mode: toolBackgroundMode, lines: result }
285
+ return result
286
+ }
287
+
288
+ proto[PATCH_FLAG] = true
289
+ }
290
+
291
+ function summarizeText(text: string, max = 60): string {
292
+ const oneLine = text.replace(/\n/g, " ").trim()
293
+ if (oneLine.length <= max) return oneLine
294
+ return `${oneLine.slice(0, Math.max(0, max - 3))}...`
295
+ }
296
+
297
+ function hashText(text: string): string {
298
+ let hash = 2166136261
299
+ for (let i = 0; i < text.length; i++) {
300
+ hash ^= text.charCodeAt(i)
301
+ hash = Math.imul(hash, 16777619)
302
+ }
303
+ return (hash >>> 0).toString(36)
304
+ }
305
+
306
+ function clearToolRenderCache(value: unknown): void {
307
+ if (!value || typeof value !== "object") return
308
+ delete (value as any)[TOOL_RENDER_CACHE]
309
+ }
310
+
311
+ function unrefTimer(timer: ReturnType<typeof setTimeout> | null | undefined): void {
312
+ ;(timer as any)?.unref?.()
313
+ }
314
+
315
+ const TOOL_EXECUTION_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-tool-execution")
316
+ const WORKED_DURATION_KEY = "_piClaudeStyleWorkedDurationMs"
317
+ const WORKED_START_KEY = "_piClaudeStyleWorkedStartMs"
318
+ const ASSISTANT_MESSAGE_PATCH_FLAG = Symbol.for("pi-claude-style-tools:patched-assistant-message-render")
319
+ // OSC 133 zone markers applied by AssistantMessageComponent.render() — must be
320
+ // reattached to the last line after we append the duration widget.
321
+ const OSC133_ZONE_END = "\x1b]133;B\x07"
322
+ const OSC133_ZONE_FINAL = "\x1b]133;C\x07"
323
+ const OSC133_ZONE_SUFFIX = OSC133_ZONE_END + OSC133_ZONE_FINAL
324
+ // WORKED_LINE_FG is theme-derived (from "muted") when themeAdaptive is on.
325
+ let WORKED_LINE_FG = "\x1b[38;2;140;140;140m"
326
+ let currentAgentWorkStartMs: number | undefined
327
+ let currentAssistantMessageStartMs: number | undefined
328
+
329
+ function formatWorkedDuration(ms: number): string {
330
+ const safeMs = Math.max(0, Number.isFinite(ms) ? ms : 0)
331
+ if (safeMs < 60_000) {
332
+ return `${Math.max(0, Math.floor(safeMs / 1000))}s`
333
+ }
334
+ let days = Math.floor(safeMs / 86_400_000)
335
+ let hours = Math.floor((safeMs % 86_400_000) / 3_600_000)
336
+ let minutes = Math.floor((safeMs % 3_600_000) / 60_000)
337
+ let seconds = Math.round((safeMs % 60_000) / 1000)
338
+ if (seconds === 60) {
339
+ seconds = 0
340
+ minutes++
341
+ }
342
+ if (minutes === 60) {
343
+ minutes = 0
344
+ hours++
345
+ }
346
+ if (hours === 24) {
347
+ hours = 0
348
+ days++
349
+ }
350
+ if (days > 0) return `${days}d ${hours}h ${minutes}m`
351
+ if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`
352
+ return `${minutes}m ${seconds}s`
353
+ }
354
+
355
+ /**
356
+ * Returns elapsed milliseconds for a tool call.
357
+ *
358
+ * Note: `ctx.state` is the component's `rendererState` — the upstream
359
+ * framework's `getRenderContext` method aliases them via
360
+ * `state: this.rendererState`.
361
+ */
362
+ export function getToolElapsedMs(ctx: any): number {
363
+ const startedAt = ctx?.state?._executionStartedAt
364
+ if (!startedAt) return 0
365
+ const endedAt = ctx?.state?._executionEndedAt
366
+ return (endedAt ?? Date.now()) - startedAt
367
+ }
368
+
369
+ export function formatToolTimer(elapsedMs: number): string | undefined {
370
+ if (elapsedMs <= 0) return undefined
371
+ return formatDuration(elapsedMs)
372
+ }
373
+
374
+ // One space of indent — aligns the ✻ glyph with the assistant message body.
375
+ const WORKED_DURATION_INDENT = " "
376
+
377
+ function inlineWorkedDurationText(ms: number): string {
378
+ return `${WORKED_DURATION_INDENT}${WORKED_LINE_FG}✻ Worked for ${formatWorkedDuration(ms)}${RESET}`
379
+ }
380
+
381
+ function patchAssistantMessageRender(): void {
382
+ const proto = AssistantMessageComponent.prototype as any
383
+ if (proto[ASSISTANT_MESSAGE_PATCH_FLAG]) return
384
+ const originalRender = proto.render
385
+ if (typeof originalRender !== "function") return
386
+ proto.render = function patchedAssistantMessageRender(width: number) {
387
+ const lines: string[] = originalRender.call(this, width)
388
+ if (!Array.isArray(lines) || lines.length === 0) return lines
389
+ const message = (this as any).lastMessage
390
+ const durationMs = message?.[WORKED_DURATION_KEY]
391
+ if (typeof durationMs !== "number" || durationMs <= 0) return lines
392
+ // The original render() appends OSC 133 zone markers to the last line
393
+ // (B = command end, C = command output). Strip them off, push the widget
394
+ // line, then reattach so the zone still brackets the full message.
395
+ const lastIdx = lines.length - 1
396
+ const widgetLine = inlineWorkedDurationText(durationMs)
397
+ if (lines[lastIdx].includes(OSC133_ZONE_END)) {
398
+ lines[lastIdx] = lines[lastIdx].replace(OSC133_ZONE_SUFFIX, "")
399
+ lines.push("", widgetLine)
400
+ lines[lines.length - 1] += OSC133_ZONE_SUFFIX
401
+ } else {
402
+ lines.push("", widgetLine)
403
+ }
404
+ return lines
405
+ }
406
+ proto[ASSISTANT_MESSAGE_PATCH_FLAG] = true
407
+ }
408
+
409
+ // OSC 133 zone markers that UserMessageComponent prepends/appends for shell integration.
410
+ // A one-line message can start with multiple markers because the first and last
411
+ // rendered lines are the same physical line.
412
+ const OSC133_MARKER_RE = /^(?:\x1b\]133;[ABC]\x07)+/
413
+
414
+ export function splitLeadingOsc133Markers(line: string): { markers: string; rest: string } {
415
+ const match = line.match(OSC133_MARKER_RE)
416
+ if (!match) return { markers: "", rest: line }
417
+ const markers = match[0]
418
+ return { markers, rest: line.slice(markers.length) }
419
+ }
420
+
421
+ export function patchUserMessageRender(): void {
422
+ const proto = UserMessageComponent.prototype as any
423
+ if (proto[USER_MESSAGE_PATCH_FLAG]) return
424
+ const originalRender = proto.render
425
+ if (typeof originalRender !== "function") return
426
+ proto.render = function patchedUserMessageRender(width: number) {
427
+ const box = (this as any).contentBox
428
+ if (box) {
429
+ // Remove the ▍ stroke and blank padding lines. paddingX=0 lets content
430
+ // render at full width; we prepend the prefix and truncate explicitly.
431
+ box.bgFn = null
432
+ box.paddingY = 0
433
+ box.paddingX = 0
434
+ box.invalidateCache?.()
435
+ }
436
+ const theme = _themePaletteCacheTheme as any
437
+ const glyph = typeof theme?.fg === "function" ? theme.fg("accent", "❯") : "❯"
438
+ const prefix = ` ${glyph} `
439
+ const prefixW = visibleWidth(prefix)
440
+ // Render content narrower so all lines fit when we prepend the indent.
441
+ const innerWidth = Math.max(1, width - prefixW)
442
+ const lines: string[] = originalRender.call(this, innerWidth)
443
+ if (!Array.isArray(lines) || lines.length === 0) return lines
444
+ const indent = " ".repeat(prefixW)
445
+ const hasBg = typeof theme?.bg === "function"
446
+ for (let i = 0; i < lines.length; i++) {
447
+ const linePrefix = i === 0 ? prefix : indent
448
+ const { markers, rest } = i === 0 ? splitLeadingOsc133Markers(lines[0]) : { markers: "", rest: lines[i] }
449
+ const composed = linePrefix + rest
450
+ const pad = Math.max(0, width - visibleWidth(composed))
451
+ const styled = hasBg ? theme.bg("userMessageBg", composed + " ".repeat(pad)) : composed
452
+ lines[i] = markers + styled
453
+ }
454
+ return lines
455
+ }
456
+ proto[USER_MESSAGE_PATCH_FLAG] = true
457
+ }
458
+
459
+ export function patchToolRenderCacheInvalidation(): void {
460
+ const proto = ToolExecutionComponent.prototype as any
461
+ if (proto[TOOL_CACHE_PATCH_FLAG]) return
462
+
463
+ const methods = [
464
+ "updateDisplay",
465
+ "updateArgs",
466
+ "markExecutionStarted",
467
+ "setArgsComplete",
468
+ "updateResult",
469
+ "setExpanded",
470
+ "setShowImages",
471
+ "setImageWidthCells",
472
+ "invalidate",
473
+ ]
474
+
475
+ for (const method of methods) {
476
+ const original = proto[method]
477
+ if (typeof original !== "function") continue
478
+ proto[method] = function patchedToolMutation(...args: any[]) {
479
+ clearToolRenderCache(this)
480
+ if (method === "markExecutionStarted" && !this.rendererState._executionStartedAt) {
481
+ this.rendererState._executionStartedAt = Date.now()
482
+ }
483
+ if (
484
+ method === "updateResult" &&
485
+ !this.rendererState._executionEndedAt &&
486
+ args[1] !== true
487
+ ) {
488
+ this.rendererState._executionEndedAt = Date.now()
489
+ }
490
+ const result = original.apply(this, args)
491
+ clearToolRenderCache(this)
492
+ return result
493
+ }
494
+ }
495
+
496
+ proto[TOOL_CACHE_PATCH_FLAG] = true
497
+ }
498
+
499
+ function deleteRenderedKittyImages(component: any): void {
500
+ if (
501
+ !process.stdout.isTTY ||
502
+ getCapabilities().images !== "kitty" ||
503
+ !Array.isArray(component.imageComponents) ||
504
+ component.imageComponents.length === 0
505
+ )
506
+ return
507
+ try {
508
+ process.stdout.write(deleteAllKittyImages())
509
+ } catch {
510
+ /* noop */
511
+ }
512
+ }
513
+
514
+ function removeImageChildren(component: any): void {
515
+ deleteRenderedKittyImages(component)
516
+ const children = [
517
+ ...(Array.isArray(component.imageComponents) ? component.imageComponents : []),
518
+ ...(Array.isArray(component.imageSpacers) ? component.imageSpacers : []),
519
+ ]
520
+ for (const child of children) {
521
+ try {
522
+ component.removeChild?.(child)
523
+ } catch {
524
+ /* noop */
525
+ }
526
+ }
527
+ component.imageComponents = []
528
+ component.imageSpacers = []
529
+ }
530
+
531
+ function patchReadImageExpansion(): void {
532
+ const proto = ToolExecutionComponent.prototype as any
533
+ if (proto[TOOL_IMAGE_EXPAND_PATCH_FLAG]) return
534
+ const originalUpdateDisplay = proto.updateDisplay
535
+ if (typeof originalUpdateDisplay !== "function") return
536
+ proto.updateDisplay = function patchedReadImageUpdateDisplay(...args: any[]) {
537
+ const result = originalUpdateDisplay.apply(this, args)
538
+ const hasImage =
539
+ Array.isArray(this.result?.content) && this.result.content.some((block: any) => block?.type === "image")
540
+ if (this.toolName === "read" && hasImage && this.expanded !== true) {
541
+ removeImageChildren(this)
542
+ clearToolRenderCache(this)
543
+ }
544
+ return result
545
+ }
546
+ proto[TOOL_IMAGE_EXPAND_PATCH_FLAG] = true
547
+ }
548
+
549
+ function patchToolExecutionRenderers(): void {
550
+ const proto = ToolExecutionComponent.prototype as any
551
+ if (proto[TOOL_EXECUTION_PATCH_FLAG]) return
552
+
553
+ const originalHasRendererDefinition = proto.hasRendererDefinition
554
+ const originalGetCallRenderer = proto.getCallRenderer
555
+ const originalGetResultRenderer = proto.getResultRenderer
556
+
557
+ if (typeof originalHasRendererDefinition === "function") {
558
+ proto.hasRendererDefinition = function patchedHasRendererDefinition() {
559
+ return originalHasRendererDefinition.call(this) || shouldUseGenericToolRenderer(this?.toolName)
560
+ }
561
+ }
562
+
563
+ proto.getCallRenderer = function patchedGetCallRenderer() {
564
+ const toolName = typeof this?.toolName === "string" ? this.toolName : ""
565
+ if (toolName === "apply_patch") {
566
+ return (args: any, theme: Theme, ctx: any) =>
567
+ renderApplyPatchCall(args, theme, ctx, (path: string) => shortPath(ctx.cwd ?? process.cwd(), path))
568
+ }
569
+ if (shouldUseGenericToolRenderer(toolName)) {
570
+ return (args: any, theme: Theme, ctx: any) => renderGenericToolCall(toolName, args, theme, ctx)
571
+ }
572
+ return typeof originalGetCallRenderer === "function" ? originalGetCallRenderer.call(this) : undefined
573
+ }
574
+
575
+ proto.getResultRenderer = function patchedGetResultRenderer() {
576
+ const toolName = typeof this?.toolName === "string" ? this.toolName : ""
577
+ if (toolName === "apply_patch") {
578
+ return (result: any, options: any, theme: Theme, ctx: any) =>
579
+ renderApplyPatchResult({ content: result.content, details: result.details }, options.isPartial, theme, ctx)
580
+ }
581
+ if (shouldUseGenericToolRenderer(toolName)) {
582
+ return (result: any, options: any, theme: Theme, ctx: any) =>
583
+ renderGenericToolResult(toolName, result, options, theme, ctx)
584
+ }
585
+ return typeof originalGetResultRenderer === "function" ? originalGetResultRenderer.call(this) : undefined
586
+ }
587
+
588
+ proto[TOOL_EXECUTION_PATCH_FLAG] = true
589
+ }
590
+
591
+ function shortPath(cwd: string, filePath: string): string {
592
+ if (!filePath) return ""
593
+ const rel = relative(cwd, filePath)
594
+ if (!rel.startsWith("..") && !rel.startsWith("/")) return rel || "."
595
+ const home = process.env.HOME ?? ""
596
+ return home ? filePath.replace(home, "~") : filePath
597
+ }
598
+
599
+ // ---------------------------------------------------------------------------
600
+ // Status dot — flickers green/gray while pending
601
+ // ---------------------------------------------------------------------------
602
+
603
+ export function toolHeader(tool: string, summary: string, theme: Theme, prefix = "", timer?: string): string {
604
+ applyThemePaletteIfNeeded(theme)
605
+ const label = theme.fg("toolTitle", theme.bold(tool))
606
+ let result = `${prefix}${label}`
607
+ if (summary) result += ` ${WRAP_MARK}${theme.fg("accent", summary)}`
608
+ if (timer) result += ` ${theme.fg("dim", timer)}`
609
+ return result
610
+ }
611
+
612
+
613
+ function shouldRevealCallArgs(ctx: any): boolean {
614
+ if (ctx?.argsComplete === true || ctx?.executionStarted === true) return true
615
+ const args = ctx?.args
616
+ if (!args || typeof args !== "object") return false
617
+ return Object.keys(args).some((key) => args[key] !== undefined && args[key] !== null && args[key] !== "")
618
+ }
619
+
620
+ function stableCallSummary(ctx: any, key: string, build: () => string, reveal = shouldRevealCallArgs(ctx)): string {
621
+ const state = ctx?.state
622
+ const cached = state?.[key]
623
+ const completeKey = `${key}Complete`
624
+ if (!reveal) return typeof cached === "string" ? cached : ""
625
+ if (ctx?.argsComplete === true && state?.[completeKey] === true && typeof cached === "string") return cached
626
+ if (!shouldRevealCallArgs(ctx) && typeof cached === "string" && cached) return cached
627
+ const summary = build()
628
+ if (state) {
629
+ state[key] = summary
630
+ if (ctx?.argsComplete === true) state[completeKey] = true
631
+ else delete state[completeKey]
632
+ }
633
+ return summary
634
+ }
635
+
636
+ function hasOwnArg(args: any, key: string): boolean {
637
+ return !!args && Object.prototype.hasOwnProperty.call(args, key)
638
+ }
639
+
640
+ function fileExistsForTool(cwd: string, filePath: string): boolean {
641
+ if (!filePath) return false
642
+ try {
643
+ return existsSync(resolve(cwd, filePath))
644
+ } catch {
645
+ return false
646
+ }
647
+ }
648
+
649
+ const WRITE_EXISTED_BEFORE = new Map<string, boolean>()
650
+
651
+ function getWriteWasNewFile(
652
+ ctx: any,
653
+ cwd: string,
654
+ filePath: string,
655
+ reveal = shouldRevealCallArgs(ctx),
656
+ ): boolean | undefined {
657
+ if (typeof ctx?.state?._writeWasNewFile === "boolean") return ctx.state._writeWasNewFile
658
+ if (!filePath || !reveal) return undefined
659
+ const existedBefore = typeof ctx?.toolCallId === "string" ? WRITE_EXISTED_BEFORE.get(ctx.toolCallId) : undefined
660
+ const wasNew = existedBefore === undefined ? !fileExistsForTool(cwd, filePath) : !existedBefore
661
+ if (ctx?.state) ctx.state._writeWasNewFile = wasNew
662
+ return wasNew
663
+ }
664
+
665
+ function toolStatusDot(ctx: any, theme: Theme): string {
666
+ if (!ctx.isPartial && !ctx.isError) return `${theme.fg("success", "●")} `
667
+ if (!ctx.isPartial && ctx.isError) return `${theme.fg("error", "●")} `
668
+ return `${blinkDot(ctx, theme)} `
669
+ }
670
+
671
+ // ---------------------------------------------------------------------------
672
+ // Branch connector — visual tree from header to output
673
+ // ---------------------------------------------------------------------------
674
+
675
+ function branchIndent(text: string, continued = false): string {
676
+ const prefix = continued ? `${TOOL_RULE}│${TRANSPARENT_RESET} ` : " "
677
+ return `${prefix}${WRAP_MARK}${text}`
678
+ }
679
+
680
+ function branchLead(text: string, continued = false): string {
681
+ return `${TOOL_RULE}${continued ? "├─" : "└─"}${TRANSPARENT_RESET} ${WRAP_MARK}${text}`
682
+ }
683
+
684
+ function withBranch(content: string, _theme: Theme, _isError = false, continued = false): string {
685
+ if (!content || !content.trim()) return ""
686
+ const lines = content.split("\n")
687
+ const first = lines[0] ?? ""
688
+ if (lines.length === 1) return branchLead(first, continued)
689
+ const rest = lines.slice(1).map((line) => branchIndent(line, continued))
690
+ return `${branchLead(first, continued)}\n${rest.join("\n")}`
691
+ }
692
+
693
+ function withFinalBranchBlock(content: string): string {
694
+ if (!content || !content.trim()) return ""
695
+ const lines = content.split("\n")
696
+ const first = lines[0] ?? ""
697
+ if (lines.length === 1) return branchLead(first, false)
698
+ const middle = lines.slice(1, -1).map((line) => branchIndent(line, true))
699
+ const last = lines[lines.length - 1] ?? ""
700
+ return [branchLead(first, true), ...middle, branchLead(last, false)].join("\n")
701
+ }
702
+
703
+ function indentBranchBlock(block: string): string {
704
+ return block
705
+ .split("\n")
706
+ .map((line) => (line ? ` ${line}` : line))
707
+ .join("\n")
708
+ }
709
+
710
+ // ---------------------------------------------------------------------------
711
+ // Blink timer for partial (running) states
712
+ // ---------------------------------------------------------------------------
713
+
714
+ // ---------------------------------------------------------------------------
715
+ // Global blink timer — single timer invalidates all active contexts
716
+ // ---------------------------------------------------------------------------
717
+
718
+ const MAX_BLINKING_TOOLS = 5
719
+ const BLINK_INTERVAL_MS = 500
720
+
721
+ type BlinkEntry = { key: any; order: number; invalidate: () => void }
722
+
723
+ const _blinkContexts = new Map<any, BlinkEntry>()
724
+ let _globalBlinkTimer: ReturnType<typeof setTimeout> | null = null
725
+ let _blinkOrder = 0
726
+ let _globalBlinkPhase = true
727
+
728
+ function getBlinkIntervalMs(): number {
729
+ return BLINK_INTERVAL_MS
730
+ }
731
+
732
+ function getBlinkKey(ctx: any): any {
733
+ return ctx?.state ?? ctx
734
+ }
735
+
736
+ function getBlinkingEntries(): BlinkEntry[] {
737
+ return [..._blinkContexts.values()].sort((a, b) => b.order - a.order).slice(0, MAX_BLINKING_TOOLS)
738
+ }
739
+
740
+ function updateBlinkActiveStates(): void {
741
+ const activeSet = new Set(getBlinkingEntries().map((entry) => entry.key))
742
+ for (const entry of _blinkContexts.values()) {
743
+ const active = activeSet.has(entry.key)
744
+ if (entry.key?._blinkActive !== active) {
745
+ entry.key._blinkActive = active
746
+ try {
747
+ entry.invalidate()
748
+ } catch {
749
+ /* noop */
750
+ }
751
+ }
752
+ }
753
+ }
754
+
755
+ function _scheduleGlobalBlinkTimer(): void {
756
+ if (_globalBlinkTimer) return
757
+ const intervalMs = getBlinkIntervalMs()
758
+ if (_blinkContexts.size === 0) return
759
+ _globalBlinkTimer = setTimeout(() => {
760
+ _globalBlinkTimer = null
761
+ if (_blinkContexts.size === 0) {
762
+ updateBlinkActiveStates()
763
+ return
764
+ }
765
+ _globalBlinkPhase = !_globalBlinkPhase
766
+ for (const entry of getBlinkingEntries()) {
767
+ try {
768
+ entry.invalidate()
769
+ } catch {
770
+ /* noop */
771
+ }
772
+ }
773
+ _scheduleGlobalBlinkTimer()
774
+ }, intervalMs)
775
+ unrefTimer(_globalBlinkTimer)
776
+ }
777
+
778
+ function _stopGlobalBlinkTimerIfEmpty(): void {
779
+ if (_globalBlinkTimer && _blinkContexts.size === 0) {
780
+ clearTimeout(_globalBlinkTimer)
781
+ _globalBlinkTimer = null
782
+ }
783
+ }
784
+
785
+ function setupBlinkTimer(ctx: any): void {
786
+ const key = getBlinkKey(ctx)
787
+ if (!key) return
788
+ const invalidate = typeof ctx?.invalidate === "function" ? () => ctx.invalidate() : () => {}
789
+ const existing = _blinkContexts.get(key)
790
+ if (existing) {
791
+ // Already tracked — just refresh the invalidate fn, skip expensive recalc
792
+ existing.invalidate = invalidate
793
+ return
794
+ }
795
+ _blinkContexts.set(key, { key, order: ++_blinkOrder, invalidate })
796
+ key._blinkActive = false
797
+ updateBlinkActiveStates()
798
+ _stopGlobalBlinkTimerIfEmpty()
799
+ _scheduleGlobalBlinkTimer()
800
+ }
801
+
802
+ function clearBlinkTimer(ctx: any): void {
803
+ const key = getBlinkKey(ctx)
804
+ if (!key) return
805
+ _blinkContexts.delete(key)
806
+ key._blinkActive = false
807
+ updateBlinkActiveStates()
808
+ _stopGlobalBlinkTimerIfEmpty()
809
+ _scheduleGlobalBlinkTimer()
810
+ }
811
+
812
+ function blinkDot(ctx: any, theme: Theme): string {
813
+ setupBlinkTimer(ctx)
814
+ const key = getBlinkKey(ctx)
815
+ if (key?._blinkActive !== true) return theme.fg("muted", "○")
816
+ return _globalBlinkPhase ? theme.fg("success", "●") : theme.fg("muted", "○")
817
+ }
818
+
819
+ // ---------------------------------------------------------------------------
820
+ // File icons — Nerd Font glyphs (requires Nerd Font terminal)
821
+ // ---------------------------------------------------------------------------
822
+
823
+ const NF_DIR = `\x1b[38;2;100;140;220m\ue5ff\x1b[0m`
824
+ const NF_DEFAULT = `\x1b[38;2;80;80;80m\uf15b\x1b[0m`
825
+
826
+ const EXT_ICON: Record<string, string> = {
827
+ ts: `\x1b[38;2;49;120;198m\ue628\x1b[0m`,
828
+ tsx: `\x1b[38;2;49;120;198m\ue7ba\x1b[0m`,
829
+ js: `\x1b[38;2;241;224;90m\ue74e\x1b[0m`,
830
+ jsx: `\x1b[38;2;97;218;251m\ue7ba\x1b[0m`,
831
+ py: `\x1b[38;2;55;118;171m\ue73c\x1b[0m`,
832
+ rs: `\x1b[38;2;222;165;132m\ue7a8\x1b[0m`,
833
+ go: `\x1b[38;2;0;173;216m\ue724\x1b[0m`,
834
+ java: `\x1b[38;2;204;62;68m\ue738\x1b[0m`,
835
+ rb: `\x1b[38;2;204;52;45m\ue739\x1b[0m`,
836
+ swift: `\x1b[38;2;255;172;77m\ue755\x1b[0m`,
837
+ c: `\x1b[38;2;85;154;211m\ue61e\x1b[0m`,
838
+ cpp: `\x1b[38;2;85;154;211m\ue61d\x1b[0m`,
839
+ html: `\x1b[38;2;228;77;38m\ue736\x1b[0m`,
840
+ css: `\x1b[38;2;66;165;245m\ue749\x1b[0m`,
841
+ scss: `\x1b[38;2;207;100;154m\ue749\x1b[0m`,
842
+ vue: `\x1b[38;2;65;184;131m\ue6a0\x1b[0m`,
843
+ svelte: `\x1b[38;2;255;62;0m\ue697\x1b[0m`,
844
+ json: `\x1b[38;2;241;224;90m\ue60b\x1b[0m`,
845
+ yaml: `\x1b[38;2;160;116;196m\ue6a8\x1b[0m`,
846
+ yml: `\x1b[38;2;160;116;196m\ue6a8\x1b[0m`,
847
+ toml: `\x1b[38;2;160;116;196m\ue6b2\x1b[0m`,
848
+ md: `\x1b[38;2;66;165;245m\ue73e\x1b[0m`,
849
+ sh: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
850
+ bash: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
851
+ zsh: `\x1b[38;2;137;180;130m\ue795\x1b[0m`,
852
+ lua: `\x1b[38;2;81;160;207m\ue620\x1b[0m`,
853
+ php: `\x1b[38;2;137;147;186m\ue73d\x1b[0m`,
854
+ sql: `\x1b[38;2;218;218;218m\ue706\x1b[0m`,
855
+ xml: `\x1b[38;2;228;77;38m\ue619\x1b[0m`,
856
+ graphql: `\x1b[38;2;224;51;144m\ue662\x1b[0m`,
857
+ dockerfile: `\x1b[38;2;56;152;236m\ue7b0\x1b[0m`,
858
+ lock: `\x1b[38;2;130;130;130m\uf023\x1b[0m`,
859
+ png: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
860
+ jpg: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
861
+ svg: `\x1b[38;2;255;180;50m\uf1c5\x1b[0m`,
862
+ gif: `\x1b[38;2;160;116;196m\uf1c5\x1b[0m`,
863
+ }
864
+
865
+ const NAME_ICON: Record<string, string> = {
866
+ "package.json": `\x1b[38;2;137;180;130m\ue71e\x1b[0m`,
867
+ "tsconfig.json": `\x1b[38;2;49;120;198m\ue628\x1b[0m`,
868
+ ".gitignore": `\x1b[38;2;222;165;132m\ue702\x1b[0m`,
869
+ dockerfile: `\x1b[38;2;56;152;236m\ue7b0\x1b[0m`,
870
+ makefile: `\x1b[38;2;130;130;130m\ue615\x1b[0m`,
871
+ "readme.md": `\x1b[38;2;66;165;245m\ue73e\x1b[0m`,
872
+ license: `\x1b[38;2;218;218;218m\ue60a\x1b[0m`,
873
+ }
874
+
875
+ function fileIcon(fp: string): string {
876
+ const base = fp.split("/").pop()?.toLowerCase() ?? ""
877
+ if (NAME_ICON[base]) return `${NAME_ICON[base]} `
878
+ const ext = base.includes(".") ? (base.split(".").pop() ?? "") : ""
879
+ return EXT_ICON[ext] ? `${EXT_ICON[ext]} ` : `${NF_DEFAULT} `
880
+ }
881
+
882
+ function dirIcon(): string {
883
+ return `${NF_DIR} `
884
+ }
885
+
886
+ function lineCount(text: string): number {
887
+ if (!text) return 0
888
+ return text.split("\n").length
889
+ }
890
+
891
+ function padToWidth(line: string, width: number): string {
892
+ const padding = Math.max(0, width - visibleWidth(line))
893
+ return `${line}${" ".repeat(padding)}`
894
+ }
895
+
896
+ function markedContinuationPrefix(prefix: string): string {
897
+ const plain = stripAnsi(prefix)
898
+ const branchMatch = /^(\s*)(│ {2}|├─ |└─ )/.exec(plain)
899
+ if (branchMatch) {
900
+ const connector = branchMatch[2]
901
+ if (connector === "└─ ") return `${branchMatch[1]} `
902
+ return `${branchMatch[1]}${TOOL_RULE}│${TRANSPARENT_RESET} `
903
+ }
904
+ return " ".repeat(visibleWidth(prefix))
905
+ }
906
+
907
+ function wrapMarkedLine(line: string, width: number): string[] {
908
+ const markerIndex = line.indexOf(WRAP_MARK)
909
+ if (markerIndex === -1) return wrapTextWithAnsi(line, width)
910
+ const prefix = line.slice(0, markerIndex)
911
+ const body = line.slice(markerIndex + WRAP_MARK.length)
912
+ const prefixWidth = visibleWidth(prefix)
913
+ const bodyWidth = Math.max(1, width - prefixWidth)
914
+ const wrapped = wrapTextWithAnsi(body, bodyWidth)
915
+ const continuation = markedContinuationPrefix(prefix)
916
+ return wrapped.map((part, index) => (index === 0 ? `${prefix}${part}` : `${continuation}${part}`))
917
+ }
918
+
919
+ class ToolText extends Text {
920
+ private value = ""
921
+ private toolCachedValue?: string
922
+ private toolCachedWidth?: number
923
+ private toolCachedLines?: string[]
924
+
925
+ constructor(text = "") {
926
+ super("", 0, 0)
927
+ this.value = text
928
+ }
929
+
930
+ setText(text: string): void {
931
+ if (this.value === text) return
932
+ this.value = text
933
+ this.invalidate()
934
+ }
935
+
936
+ invalidate(): void {
937
+ this.toolCachedValue = undefined
938
+ this.toolCachedWidth = undefined
939
+ this.toolCachedLines = undefined
940
+ super.invalidate()
941
+ }
942
+
943
+ render(width: number): string[] {
944
+ if (this.toolCachedLines && this.toolCachedValue === this.value && this.toolCachedWidth === width)
945
+ return this.toolCachedLines
946
+ if (!this.value || this.value.trim() === "") {
947
+ this.toolCachedValue = this.value
948
+ this.toolCachedWidth = width
949
+ this.toolCachedLines = []
950
+ return this.toolCachedLines
951
+ }
952
+ const contentWidth = Math.max(1, width)
953
+ const lines = this.value.replace(/\t/g, " ").split("\n")
954
+ const rendered = lines.flatMap((line) => wrapMarkedLine(line, contentWidth)).map((line) => padToWidth(line, width))
955
+ this.toolCachedValue = this.value
956
+ this.toolCachedWidth = width
957
+ this.toolCachedLines = rendered
958
+ return rendered
959
+ }
960
+ }
961
+
962
+ function makeText(last: unknown, text: string): Text {
963
+ const component = last instanceof ToolText ? last : new ToolText()
964
+ component.setText(text)
965
+ return component
966
+ }
967
+
968
+ function previewLimit(): number {
969
+ const value = readSettings().previewLines
970
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 8
971
+ }
972
+
973
+ function expandedPreviewLimit(): number {
974
+ const value = readSettings().expandedPreviewMaxLines
975
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 4000
976
+ }
977
+
978
+ function bashCollapsedLimit(): number {
979
+ const value = readSettings().bashCollapsedLines
980
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : 10
981
+ }
982
+
983
+ function diffCollapsedLimit(): number {
984
+ const value = readSettings().diffCollapsedLines
985
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 24
986
+ }
987
+
988
+ function collapsedPreviewCount(expanded: boolean, fallback: number): number {
989
+ return expanded ? expandedPreviewLimit() : fallback
990
+ }
991
+
992
+ function buildPreviewText(lines: string[], expanded: boolean, theme: Theme, fallbackCollapsed = 8): string {
993
+ if (lines.length === 0) return theme.fg("muted", "(no output)")
994
+ const maxLines = collapsedPreviewCount(expanded, fallbackCollapsed)
995
+ const shown = lines.slice(0, maxLines)
996
+ let text = shown.join("\n")
997
+ const remaining = lines.length - shown.length
998
+ if (remaining > 0) {
999
+ text += `\n${theme.fg("muted", `... (${remaining} more lines${expanded ? "" : " • ctrl+o to expand"})`)}`
1000
+ }
1001
+ if (expanded && lines.length > maxLines) {
1002
+ text += `\n${theme.fg("warning", `(display capped at ${maxLines} lines)`)}`
1003
+ }
1004
+ return text
1005
+ }
1006
+
1007
+ // ===========================================================================
1008
+ // Diff rendering — adapted from /tmp/pi-diff
1009
+ // ===========================================================================
1010
+
1011
+ interface DiffPreset {
1012
+ name: string
1013
+ description: string
1014
+ shikiTheme?: string
1015
+ bgAdd?: string
1016
+ bgDel?: string
1017
+ bgAddHighlight?: string
1018
+ bgDelHighlight?: string
1019
+ bgGutterAdd?: string
1020
+ bgGutterDel?: string
1021
+ bgEmpty?: string
1022
+ fgAdd?: string
1023
+ fgDel?: string
1024
+ fgDim?: string
1025
+ fgLnum?: string
1026
+ fgRule?: string
1027
+ fgStripe?: string
1028
+ fgSafeMuted?: string
1029
+ }
1030
+
1031
+ interface DiffUserConfig {
1032
+ diffTheme?: string
1033
+ diffColors?: Record<string, string>
1034
+ }
1035
+
1036
+ const DIFF_PRESETS: Record<string, DiffPreset> = {
1037
+ default: {
1038
+ name: "default",
1039
+ description: "Original pi-diff colors",
1040
+ bgAdd: "#162620",
1041
+ bgDel: "#2d1919",
1042
+ bgAddHighlight: "#234b32",
1043
+ bgDelHighlight: "#502323",
1044
+ bgGutterAdd: "#12201a",
1045
+ bgGutterDel: "#261616",
1046
+ bgEmpty: "#121212",
1047
+ fgDim: "#505050",
1048
+ fgLnum: "#646464",
1049
+ fgRule: "#323232",
1050
+ fgStripe: "#282828",
1051
+ fgSafeMuted: "#8b949e",
1052
+ },
1053
+ midnight: {
1054
+ name: "midnight",
1055
+ description: "Subtle tints for black backgrounds",
1056
+ bgAdd: "#0d1a12",
1057
+ bgDel: "#1a0d0d",
1058
+ bgAddHighlight: "#1a3825",
1059
+ bgDelHighlight: "#381a1a",
1060
+ bgGutterAdd: "#091208",
1061
+ bgGutterDel: "#120908",
1062
+ bgEmpty: "#080808",
1063
+ fgDim: "#404040",
1064
+ fgLnum: "#505050",
1065
+ fgRule: "#282828",
1066
+ fgStripe: "#1e1e1e",
1067
+ fgSafeMuted: "#8b949e",
1068
+ },
1069
+ neon: {
1070
+ name: "neon",
1071
+ description: "Higher contrast backgrounds",
1072
+ bgAdd: "#1a3320",
1073
+ bgDel: "#331a16",
1074
+ bgAddHighlight: "#2d5c3a",
1075
+ bgDelHighlight: "#5c2d2d",
1076
+ bgGutterAdd: "#142818",
1077
+ bgGutterDel: "#28120e",
1078
+ bgEmpty: "#141414",
1079
+ fgDim: "#606060",
1080
+ fgLnum: "#787878",
1081
+ fgRule: "#404040",
1082
+ fgStripe: "#303030",
1083
+ fgSafeMuted: "#9da5ae",
1084
+ },
1085
+ }
1086
+
1087
+ function loadDiffConfig(): DiffUserConfig {
1088
+ const settings = readSettings()
1089
+ return { diffTheme: settings.diffTheme, diffColors: settings.diffColors }
1090
+ }
1091
+
1092
+ // 6x6x6 color cube channel values used by pi's 256color fallback.
1093
+ const CUBE_VALUES = [0, 95, 135, 175, 215, 255]
1094
+
1095
+ function xterm256ToRgb(index: number): { r: number; g: number; b: number } | null {
1096
+ if (!Number.isInteger(index) || index < 0 || index > 255) return null
1097
+ if (index < 16) {
1098
+ // Standard 16 ANSI colors — terminal-defined, approximate with VS Code defaults.
1099
+ const basic: Array<[number, number, number]> = [
1100
+ [0, 0, 0],
1101
+ [128, 0, 0],
1102
+ [0, 128, 0],
1103
+ [128, 128, 0],
1104
+ [0, 0, 128],
1105
+ [128, 0, 128],
1106
+ [0, 128, 128],
1107
+ [192, 192, 192],
1108
+ [128, 128, 128],
1109
+ [255, 0, 0],
1110
+ [0, 255, 0],
1111
+ [255, 255, 0],
1112
+ [0, 0, 255],
1113
+ [255, 0, 255],
1114
+ [0, 255, 255],
1115
+ [255, 255, 255],
1116
+ ]
1117
+ const [r, g, b] = basic[index]
1118
+ return { r, g, b }
1119
+ }
1120
+ if (index < 232) {
1121
+ const i = index - 16
1122
+ return {
1123
+ r: CUBE_VALUES[Math.floor(i / 36) % 6],
1124
+ g: CUBE_VALUES[Math.floor(i / 6) % 6],
1125
+ b: CUBE_VALUES[i % 6],
1126
+ }
1127
+ }
1128
+ const level = 8 + (index - 232) * 10
1129
+ return { r: level, g: level, b: level }
1130
+ }
1131
+
1132
+ function parseAnsiRgb(ansi: string): { r: number; g: number; b: number } | null {
1133
+ if (!ansi) return null
1134
+ const esc = "\u001b"
1135
+ // Truecolor: \e[38;2;R;G;Bm or \e[48;2;R;G;Bm
1136
+ const tc = ansi.match(new RegExp(`${esc}\\[(?:38|48);2;(\\d+);(\\d+);(\\d+)m`))
1137
+ if (tc) return { r: +tc[1], g: +tc[2], b: +tc[3] }
1138
+ // 256-color: \e[38;5;Nm or \e[48;5;Nm — happens on Apple Terminal, screen, etc.
1139
+ const idx = ansi.match(new RegExp(`${esc}\\[(?:38|48);5;(\\d+)m`))
1140
+ if (idx) return xterm256ToRgb(+idx[1])
1141
+ return null
1142
+ }
1143
+
1144
+ function hexToBgAnsi(hex: string): string {
1145
+ if (!hex || !/^#[0-9a-fA-F]{6}$/.test(hex)) return ""
1146
+ const r = Number.parseInt(hex.slice(1, 3), 16)
1147
+ const g = Number.parseInt(hex.slice(3, 5), 16)
1148
+ const b = Number.parseInt(hex.slice(5, 7), 16)
1149
+ return `\x1b[48;2;${r};${g};${b}m`
1150
+ }
1151
+
1152
+ function hexToFgAnsi(hex: string): string {
1153
+ if (!hex || !/^#[0-9a-fA-F]{6}$/.test(hex)) return ""
1154
+ const r = Number.parseInt(hex.slice(1, 3), 16)
1155
+ const g = Number.parseInt(hex.slice(3, 5), 16)
1156
+ const b = Number.parseInt(hex.slice(5, 7), 16)
1157
+ return `\x1b[38;2;${r};${g};${b}m`
1158
+ }
1159
+
1160
+ // ---------------------------------------------------------------------------
1161
+ // Theme palette extraction — pull RGB from the active pi theme so our
1162
+ // hardcoded greys and accent colors track the user's selected theme.
1163
+ //
1164
+ // `theme.getFgAnsi(name)` / `theme.getBgAnsi(name)` return raw ANSI escapes
1165
+ // (either truecolor or 256color depending on the terminal). We parse those
1166
+ // back into RGB so we can mix tints for diff backgrounds.
1167
+ // ---------------------------------------------------------------------------
1168
+
1169
+ type Rgb = { r: number; g: number; b: number }
1170
+
1171
+ function safeFgAnsi(theme: any, key: string): string | null {
1172
+ try {
1173
+ const ansi = theme?.getFgAnsi?.(key)
1174
+ return typeof ansi === "string" && ansi.length > 0 ? ansi : null
1175
+ } catch {
1176
+ return null
1177
+ }
1178
+ }
1179
+
1180
+ function safeBgAnsi(theme: any, key: string): string | null {
1181
+ try {
1182
+ const ansi = theme?.getBgAnsi?.(key)
1183
+ return typeof ansi === "string" && ansi.length > 0 ? ansi : null
1184
+ } catch {
1185
+ return null
1186
+ }
1187
+ }
1188
+
1189
+ function themeFgRgb(theme: any, key: string): Rgb | null {
1190
+ const ansi = safeFgAnsi(theme, key)
1191
+ return ansi ? parseAnsiRgb(ansi) : null
1192
+ }
1193
+
1194
+ function themeBgRgb(theme: any, key: string): Rgb | null {
1195
+ const ansi = safeBgAnsi(theme, key)
1196
+ return ansi ? parseAnsiRgb(ansi) : null
1197
+ }
1198
+
1199
+ // Cache theme identity so we only recompute on theme change. The Theme
1200
+ // object is reused across renders within a single session unless the user
1201
+ // switches themes via the picker.
1202
+ let _themePaletteCacheTheme: unknown = null
1203
+
1204
+ function themeAdaptiveEnabled(): boolean {
1205
+ const settings = readSettings()
1206
+ return settings.themeAdaptive !== false
1207
+ }
1208
+
1209
+ let DIFF_THEME: BundledTheme = (process.env.DIFF_THEME as BundledTheme | undefined) ?? "github-dark"
1210
+ let codeToAnsiLoader: Promise<any> | null = null
1211
+
1212
+ const SPLIT_MIN_WIDTH = 150
1213
+ const SPLIT_MIN_CODE_WIDTH = 60
1214
+ const SPLIT_MAX_WRAP_RATIO = 0.2
1215
+ const SPLIT_MAX_WRAP_LINES = 8
1216
+ const MAX_TERM_WIDTH = 210
1217
+ const DEFAULT_TERM_WIDTH = 200
1218
+ const MAX_PREVIEW_LINES = 60
1219
+ const MAX_RENDER_LINES = 150
1220
+ const MAX_HL_CHARS = 32_000
1221
+ const CACHE_LIMIT = 48
1222
+ const WORD_DIFF_MIN_SIM = 0.15
1223
+ const MAX_WRAP_ROWS_WIDE = 3
1224
+ const MAX_WRAP_ROWS_MED = 2
1225
+ const MAX_WRAP_ROWS_NARROW = 1
1226
+
1227
+ let D_RST = "\x1b[0m"
1228
+ const D_BOLD = "\x1b[1m"
1229
+ const D_DIM = "\x1b[2m"
1230
+
1231
+ // Diff backgrounds — defaults are transparent; autoDeriveBgFromTheme fills them
1232
+ // using pi-tool-display's mix ratios against the theme's toolSuccessBg.
1233
+ let BG_ADD = "\x1b[49m"
1234
+ let BG_DEL = "\x1b[49m"
1235
+ let BG_ADD_W = "\x1b[49m"
1236
+ let BG_DEL_W = "\x1b[49m"
1237
+ let BG_GUTTER_ADD = "\x1b[49m"
1238
+ let BG_GUTTER_DEL = "\x1b[49m"
1239
+ let BG_EMPTY = "\x1b[49m"
1240
+ let BG_BASE = "\x1b[49m"
1241
+
1242
+ let FG_ADD = "\x1b[38;2;100;180;120m"
1243
+ let FG_DEL = "\x1b[38;2;200;100;100m"
1244
+ let FG_DIM = "\x1b[38;2;80;80;80m"
1245
+ let FG_LNUM = "\x1b[38;2;100;100;100m"
1246
+ let FG_RULE = "\x1b[38;2;50;50;50m"
1247
+ let TOOL_RULE = "\x1b[38;2;153;153;153m"
1248
+ let FG_SAFE_MUTED = "\x1b[38;2;139;148;158m"
1249
+ let FG_STRIPE = "\x1b[38;2;40;40;40m"
1250
+
1251
+ let DIVIDER = `${FG_RULE}│${D_RST}`
1252
+
1253
+ interface DiffColors {
1254
+ fgAdd: string
1255
+ fgDel: string
1256
+ fgCtx: string
1257
+ }
1258
+
1259
+ let DEFAULT_DIFF_COLORS: DiffColors = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
1260
+ let autoDerivePending = true
1261
+ let hasExplicitBgConfig = false
1262
+
1263
+ // pi-tool-display tint targets for diff palette derivation
1264
+ const ADDITION_TINT_TARGET = { r: 84, g: 190, b: 118 }
1265
+ const DELETION_TINT_TARGET = { r: 232, g: 95, b: 122 }
1266
+ // Fallback base that matches most dark themes (NOT black)
1267
+ const FALLBACK_BASE_BG = { r: 32, g: 35, b: 42 }
1268
+ const UNIVERSAL_DIFF_ADD_FG = { r: 110, g: 210, b: 130 }
1269
+ const UNIVERSAL_DIFF_DEL_FG = { r: 225, g: 110, b: 110 }
1270
+
1271
+ function mixRgb(
1272
+ a: { r: number; g: number; b: number },
1273
+ b: { r: number; g: number; b: number },
1274
+ ratio: number,
1275
+ ): { r: number; g: number; b: number } {
1276
+ return {
1277
+ r: a.r + (b.r - a.r) * ratio,
1278
+ g: a.g + (b.g - a.g) * ratio,
1279
+ b: a.b + (b.b - a.b) * ratio,
1280
+ }
1281
+ }
1282
+
1283
+ function rgbToBgAnsi(c: { r: number; g: number; b: number }): string {
1284
+ return `\x1b[48;2;${Math.round(c.r)};${Math.round(c.g)};${Math.round(c.b)}m`
1285
+ }
1286
+
1287
+ function autoDeriveBgFromTheme(theme: any): void {
1288
+ // Diff palette derivation.
1289
+ //
1290
+ // `toolDiffAdded` / `toolDiffRemoved` from the active pi theme give us the
1291
+ // fg accents. The base background is taken from `toolSuccessBg` (close to
1292
+ // the panel color the row will sit on) so the tinted backgrounds blend in
1293
+ // instead of forcing a hardcoded dark hue. Falls back to the universal
1294
+ // dark palette when the theme is unavailable or themeAdaptive=false.
1295
+ const useTheme = themeAdaptiveEnabled() && theme
1296
+ const addFgRgb = (useTheme && themeFgRgb(theme, "toolDiffAdded")) || UNIVERSAL_DIFF_ADD_FG
1297
+ const delFgRgb = (useTheme && themeFgRgb(theme, "toolDiffRemoved")) || UNIVERSAL_DIFF_DEL_FG
1298
+ const base = (useTheme && themeBgRgb(theme, "toolSuccessBg")) || FALLBACK_BASE_BG
1299
+
1300
+ const addTint = mixRgb(addFgRgb, ADDITION_TINT_TARGET, 0.35)
1301
+ const delTint = mixRgb(delFgRgb, DELETION_TINT_TARGET, 0.65)
1302
+
1303
+ FG_ADD = `\x1b[38;2;${Math.round(addFgRgb.r)};${Math.round(addFgRgb.g)};${Math.round(addFgRgb.b)}m`
1304
+ FG_DEL = `\x1b[38;2;${Math.round(delFgRgb.r)};${Math.round(delFgRgb.g)};${Math.round(delFgRgb.b)}m`
1305
+ BG_ADD = rgbToBgAnsi(mixRgb(base, addTint, 0.24))
1306
+ BG_DEL = rgbToBgAnsi(mixRgb(base, delTint, 0.12))
1307
+ BG_ADD_W = rgbToBgAnsi(mixRgb(base, addTint, 0.44))
1308
+ BG_DEL_W = rgbToBgAnsi(mixRgb(base, delTint, 0.26))
1309
+ BG_GUTTER_ADD = rgbToBgAnsi(mixRgb(base, addTint, 0.14))
1310
+ BG_GUTTER_DEL = rgbToBgAnsi(mixRgb(base, delTint, 0.08))
1311
+ BG_EMPTY = TRANSPARENT_BG
1312
+ BG_BASE = TRANSPARENT_BG
1313
+ D_RST = TRANSPARENT_RESET
1314
+ DIVIDER = `${FG_RULE}│${D_RST}`
1315
+ DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
1316
+ }
1317
+
1318
+ // Track which palette fields the user explicitly set so theme-derived
1319
+ // updates don't clobber their config.
1320
+ const _explicitFgFields = new Set<"fgAdd" | "fgDel" | "fgDim" | "fgLnum" | "fgRule" | "fgStripe" | "fgSafeMuted">()
1321
+
1322
+ // Original Claude-Code-style palette captured at module-load so we can
1323
+ // restore it when the user toggles themeAdaptive off at runtime.
1324
+ const _claudeStyleDefaults = {
1325
+ BORDER_COLOR: "\x1b[38;5;238m",
1326
+ WORKED_LINE_FG: "\x1b[38;2;140;140;140m",
1327
+ TOOL_RULE: "\x1b[38;2;153;153;153m",
1328
+ FG_DIM: "\x1b[38;2;80;80;80m",
1329
+ FG_LNUM: "\x1b[38;2;100;100;100m",
1330
+ FG_RULE: "\x1b[38;2;50;50;50m",
1331
+ FG_STRIPE: "\x1b[38;2;40;40;40m",
1332
+ FG_SAFE_MUTED: "\x1b[38;2;139;148;158m",
1333
+ FG_ADD: "\x1b[38;2;100;180;120m",
1334
+ FG_DEL: "\x1b[38;2;200;100;100m",
1335
+ }
1336
+
1337
+ function resetThemePalette(): void {
1338
+ BORDER_COLOR = _claudeStyleDefaults.BORDER_COLOR
1339
+ WORKED_LINE_FG = _claudeStyleDefaults.WORKED_LINE_FG
1340
+ TOOL_RULE = _claudeStyleDefaults.TOOL_RULE
1341
+ if (!_explicitFgFields.has("fgDim")) FG_DIM = _claudeStyleDefaults.FG_DIM
1342
+ if (!_explicitFgFields.has("fgLnum")) FG_LNUM = _claudeStyleDefaults.FG_LNUM
1343
+ if (!_explicitFgFields.has("fgRule")) FG_RULE = _claudeStyleDefaults.FG_RULE
1344
+ if (!_explicitFgFields.has("fgStripe")) FG_STRIPE = _claudeStyleDefaults.FG_STRIPE
1345
+ if (!_explicitFgFields.has("fgSafeMuted")) FG_SAFE_MUTED = _claudeStyleDefaults.FG_SAFE_MUTED
1346
+ if (!_explicitFgFields.has("fgAdd")) FG_ADD = _claudeStyleDefaults.FG_ADD
1347
+ if (!_explicitFgFields.has("fgDel")) FG_DEL = _claudeStyleDefaults.FG_DEL
1348
+ DIVIDER = `${FG_RULE}│${D_RST}`
1349
+ DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
1350
+ }
1351
+
1352
+ function applyThemePaletteIfNeeded(theme: any): void {
1353
+ if (!theme) return
1354
+ if (!themeAdaptiveEnabled()) return
1355
+ if (_themePaletteCacheTheme === theme) return // already applied for this theme instance
1356
+ _themePaletteCacheTheme = theme
1357
+
1358
+ // Borders (top/bottom outlines, user-message frame, branch rule).
1359
+ const borderMuted = safeFgAnsi(theme, "borderMuted")
1360
+ if (borderMuted) BORDER_COLOR = borderMuted
1361
+
1362
+ // "Worked for Ns" line + thinking-block italics share pi's `muted` color.
1363
+ const muted = safeFgAnsi(theme, "muted")
1364
+ if (muted) WORKED_LINE_FG = muted
1365
+
1366
+ // Tool branch rule (├─ / └─ connectors). Use `dim` if present, else `muted`.
1367
+ const dim = safeFgAnsi(theme, "dim") ?? muted
1368
+ if (dim) TOOL_RULE = dim
1369
+
1370
+ // Diff support text colors. These are user-overridable via diffColors.* so
1371
+ // we only touch the ones not explicitly set.
1372
+ if (!_explicitFgFields.has("fgDim") && muted) FG_DIM = muted
1373
+ if (!_explicitFgFields.has("fgLnum") && muted) FG_LNUM = muted
1374
+ if (!_explicitFgFields.has("fgRule") && borderMuted) FG_RULE = borderMuted
1375
+ if (!_explicitFgFields.has("fgStripe") && borderMuted) FG_STRIPE = borderMuted
1376
+ if (!_explicitFgFields.has("fgSafeMuted") && muted) FG_SAFE_MUTED = muted
1377
+
1378
+ DIVIDER = `${FG_RULE}│${D_RST}`
1379
+
1380
+ // Re-trigger background derivation against the new theme unless the user
1381
+ // set explicit bg overrides via diffTheme/diffColors.
1382
+ if (!hasExplicitBgConfig) {
1383
+ autoDeriveBgFromTheme(theme)
1384
+ autoDerivePending = false
1385
+ }
1386
+ }
1387
+
1388
+ function applyDiffPalette(): void {
1389
+ const config = loadDiffConfig()
1390
+ const preset = config.diffTheme ? DIFF_PRESETS[config.diffTheme] : null
1391
+ if (preset) hasExplicitBgConfig = true
1392
+ const overrides = config.diffColors ?? {}
1393
+ if (Object.keys(overrides).length > 0) hasExplicitBgConfig = true
1394
+ _explicitFgFields.clear()
1395
+
1396
+ const applyBg = (key: string, presetValue: string | undefined, set: (value: string) => void) => {
1397
+ const hex = overrides[key] ?? presetValue
1398
+ if (!hex) return
1399
+ const ansi = hexToBgAnsi(hex)
1400
+ if (ansi) set(ansi)
1401
+ }
1402
+ const applyFg = (
1403
+ key: "fgAdd" | "fgDel" | "fgDim" | "fgLnum" | "fgRule" | "fgStripe" | "fgSafeMuted",
1404
+ presetValue: string | undefined,
1405
+ set: (value: string) => void,
1406
+ ) => {
1407
+ const hex = overrides[key] ?? presetValue
1408
+ if (!hex) return
1409
+ const ansi = hexToFgAnsi(hex)
1410
+ if (!ansi) return
1411
+ set(ansi)
1412
+ _explicitFgFields.add(key)
1413
+ }
1414
+
1415
+ applyBg("bgAdd", preset?.bgAdd, (v) => {
1416
+ BG_ADD = v
1417
+ })
1418
+ applyBg("bgDel", preset?.bgDel, (v) => {
1419
+ BG_DEL = v
1420
+ })
1421
+ applyBg("bgAddHighlight", preset?.bgAddHighlight, (v) => {
1422
+ BG_ADD_W = v
1423
+ })
1424
+ applyBg("bgDelHighlight", preset?.bgDelHighlight, (v) => {
1425
+ BG_DEL_W = v
1426
+ })
1427
+ applyBg("bgGutterAdd", preset?.bgGutterAdd, (v) => {
1428
+ BG_GUTTER_ADD = v
1429
+ })
1430
+ applyBg("bgGutterDel", preset?.bgGutterDel, (v) => {
1431
+ BG_GUTTER_DEL = v
1432
+ })
1433
+ applyBg("bgEmpty", preset?.bgEmpty, (v) => {
1434
+ BG_EMPTY = v
1435
+ })
1436
+
1437
+ applyFg("fgAdd", preset?.fgAdd, (v) => {
1438
+ FG_ADD = v
1439
+ })
1440
+ applyFg("fgDel", preset?.fgDel, (v) => {
1441
+ FG_DEL = v
1442
+ })
1443
+ applyFg("fgDim", preset?.fgDim, (v) => {
1444
+ FG_DIM = v
1445
+ })
1446
+ applyFg("fgLnum", preset?.fgLnum, (v) => {
1447
+ FG_LNUM = v
1448
+ })
1449
+ applyFg("fgRule", preset?.fgRule, (v) => {
1450
+ FG_RULE = v
1451
+ })
1452
+ applyFg("fgStripe", preset?.fgStripe, (v) => {
1453
+ FG_STRIPE = v
1454
+ })
1455
+ applyFg("fgSafeMuted", preset?.fgSafeMuted, (v) => {
1456
+ FG_SAFE_MUTED = v
1457
+ })
1458
+
1459
+ const shiki = overrides.shikiTheme ?? preset?.shikiTheme
1460
+ if (shiki) DIFF_THEME = shiki as BundledTheme
1461
+
1462
+ DIVIDER = `${FG_RULE}│${D_RST}`
1463
+ DEFAULT_DIFF_COLORS = { fgAdd: FG_ADD, fgDel: FG_DEL, fgCtx: FG_DIM }
1464
+ // Only trigger auto-derive when the user did NOT supply an explicit
1465
+ // preset or per-color override; otherwise we would overwrite their config
1466
+ // with the hardcoded dark palette on first render.
1467
+ autoDerivePending = !hasExplicitBgConfig
1468
+ }
1469
+
1470
+ function resolveDiffColors(theme?: any): DiffColors {
1471
+ applyThemePaletteIfNeeded(theme)
1472
+ if (autoDerivePending && theme?.getFgAnsi) {
1473
+ autoDeriveBgFromTheme(theme)
1474
+ autoDerivePending = false
1475
+ }
1476
+ return DEFAULT_DIFF_COLORS
1477
+ }
1478
+
1479
+ interface DiffLine {
1480
+ type: "add" | "del" | "ctx" | "sep"
1481
+ oldNum: number | null
1482
+ newNum: number | null
1483
+ content: string
1484
+ }
1485
+
1486
+ interface ParsedDiff {
1487
+ lines: DiffLine[]
1488
+ added: number
1489
+ removed: number
1490
+ chars: number
1491
+ }
1492
+
1493
+ function diffStrip(value: string): string {
1494
+ return value.replace(ANSI_RE, "")
1495
+ }
1496
+
1497
+ function tabs(text: string): string {
1498
+ return text.replace(/\t/g, " ")
1499
+ }
1500
+
1501
+ function termW(): number {
1502
+ const raw =
1503
+ process.stdout.columns ||
1504
+ (process.stderr as any).columns ||
1505
+ Number.parseInt(process.env.COLUMNS ?? "", 10) ||
1506
+ DEFAULT_TERM_WIDTH
1507
+ return Math.max(40, Math.min(raw - 4, MAX_TERM_WIDTH))
1508
+ }
1509
+
1510
+ function branchDiffWidth(): number {
1511
+ return Math.max(40, termW() - 8)
1512
+ }
1513
+
1514
+ function adaptiveWrapRows(tw?: number): number {
1515
+ const width = tw ?? termW()
1516
+ if (width >= 180) return MAX_WRAP_ROWS_WIDE
1517
+ if (width >= 120) return MAX_WRAP_ROWS_MED
1518
+ return MAX_WRAP_ROWS_NARROW
1519
+ }
1520
+
1521
+ function fit(value: string, width: number): string {
1522
+ if (width <= 0) return ""
1523
+ const plain = diffStrip(value)
1524
+ if (plain.length <= width) return value + " ".repeat(width - plain.length)
1525
+ const showWidth = width > 2 ? width - 1 : width
1526
+ let vis = 0
1527
+ let i = 0
1528
+ while (i < value.length && vis < showWidth) {
1529
+ if (value[i] === "\x1b") {
1530
+ const end = value.indexOf("m", i)
1531
+ if (end !== -1) {
1532
+ i = end + 1
1533
+ continue
1534
+ }
1535
+ }
1536
+ vis++
1537
+ i++
1538
+ }
1539
+ return width > 2 ? `${value.slice(0, i)}${D_RST}${FG_DIM}›${D_RST}` : `${value.slice(0, i)}${D_RST}`
1540
+ }
1541
+
1542
+ function ansiState(text: string): string {
1543
+ const matches = text.match(/\x1b\[[0-9;]*m/g) ?? []
1544
+ let fg = ""
1545
+ let bg = ""
1546
+ for (const seq of matches) {
1547
+ const params = seq.slice(2, -1)
1548
+ if (params === "0") {
1549
+ fg = ""
1550
+ bg = ""
1551
+ } else if (params === "39") {
1552
+ fg = ""
1553
+ } else if (params.startsWith("38;")) {
1554
+ fg = seq
1555
+ } else if (params.startsWith("48;")) {
1556
+ bg = seq
1557
+ }
1558
+ }
1559
+ return bg + fg
1560
+ }
1561
+
1562
+ function normalizeShikiContrast(ansi: string): string {
1563
+ return ansi.replace(/\x1b\[([0-9;]*)m/g, (seq, params: string) => {
1564
+ if (params === "30" || params === "90" || params === "38;5;0" || params === "38;5;8") return FG_SAFE_MUTED
1565
+ if (!params.startsWith("38;2;")) return seq
1566
+ const parts = params.split(";").map(Number)
1567
+ if (parts.length !== 5 || parts.some((n) => !Number.isFinite(n))) return seq
1568
+ const [, , r, g, b] = parts
1569
+ const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
1570
+ return luminance < 72 ? FG_SAFE_MUTED : seq
1571
+ })
1572
+ }
1573
+
1574
+ function wrapAnsi(text: string, width: number, maxRows = adaptiveWrapRows(), fillBg = ""): string[] {
1575
+ if (width <= 0) return [""]
1576
+ const plain = diffStrip(text)
1577
+ if (plain.length <= width) {
1578
+ const pad = width - plain.length
1579
+ return pad > 0 ? [text + fillBg + " ".repeat(pad) + (fillBg ? D_RST : "")] : [text]
1580
+ }
1581
+
1582
+ const rows: string[] = []
1583
+ let row = ""
1584
+ let vis = 0
1585
+ let i = 0
1586
+ let onLastRow = false
1587
+ let effectiveWidth = width
1588
+
1589
+ while (i < text.length) {
1590
+ if (!onLastRow && rows.length >= maxRows - 1) {
1591
+ onLastRow = true
1592
+ effectiveWidth = width > 2 ? width - 1 : width
1593
+ }
1594
+ if (text[i] === "\x1b") {
1595
+ const end = text.indexOf("m", i)
1596
+ if (end !== -1) {
1597
+ row += text.slice(i, end + 1)
1598
+ i = end + 1
1599
+ continue
1600
+ }
1601
+ }
1602
+ if (vis >= effectiveWidth) {
1603
+ if (onLastRow) {
1604
+ let hasMore = false
1605
+ for (let j = i; j < text.length; j++) {
1606
+ if (text[j] === "\x1b") {
1607
+ const e2 = text.indexOf("m", j)
1608
+ if (e2 !== -1) {
1609
+ j = e2
1610
+ continue
1611
+ }
1612
+ }
1613
+ hasMore = true
1614
+ break
1615
+ }
1616
+ if (hasMore && width > 2) row += `${D_RST}${FG_DIM}›${D_RST}`
1617
+ else row += fillBg + " ".repeat(Math.max(0, width - vis)) + D_RST
1618
+ rows.push(row)
1619
+ return rows
1620
+ }
1621
+ const state = ansiState(row)
1622
+ rows.push(row + D_RST)
1623
+ row = state + fillBg
1624
+ vis = 0
1625
+ if (rows.length >= maxRows - 1) {
1626
+ onLastRow = true
1627
+ effectiveWidth = width > 2 ? width - 1 : width
1628
+ }
1629
+ }
1630
+ row += text[i]
1631
+ vis++
1632
+ i++
1633
+ }
1634
+
1635
+ if (row.length > 0 || rows.length === 0) {
1636
+ rows.push(row + fillBg + " ".repeat(Math.max(0, width - vis)) + D_RST)
1637
+ }
1638
+ return rows
1639
+ }
1640
+
1641
+ function lnum(n: number | null, width: number, fg = FG_LNUM): string {
1642
+ if (n === null) return " ".repeat(width)
1643
+ const value = String(n)
1644
+ return `${fg}${" ".repeat(Math.max(0, width - value.length))}${value}${D_RST}`
1645
+ }
1646
+
1647
+ function stripes(width: number): string {
1648
+ return BG_BASE + FG_STRIPE + "╱".repeat(width) + D_RST
1649
+ }
1650
+
1651
+ function renderDiffStatBar(added: number, removed: number, width = termW()): string {
1652
+ const total = added + removed
1653
+ if (total === 0 || width < 20) return ""
1654
+ const slots = Math.max(8, Math.min(20, Math.floor(width / 14)))
1655
+ let addSlots = Math.max(0, Math.min(slots, Math.round((added / total) * slots)))
1656
+ if (added > 0 && addSlots === 0) addSlots = 1
1657
+ if (removed > 0 && addSlots >= slots) addSlots = slots - 1
1658
+ const removeSlots = Math.max(0, slots - addSlots)
1659
+ const addBar = addSlots > 0 ? `${FG_ADD}${"━".repeat(addSlots)}${D_RST}` : ""
1660
+ const removeBar = removeSlots > 0 ? `${FG_DEL}${"━".repeat(removeSlots)}${D_RST}` : ""
1661
+ return `${FG_DIM}[${D_RST}${addBar}${removeBar}${FG_DIM}]${D_RST}`
1662
+ }
1663
+
1664
+ function summarizeDiff(added: number, removed: number): string {
1665
+ const parts: string[] = []
1666
+ if (added > 0) parts.push(`${FG_ADD}+${added}${D_RST}`)
1667
+ if (removed > 0) parts.push(`${FG_DEL}-${removed}${D_RST}`)
1668
+ if (!parts.length) return `${FG_DIM}no changes${D_RST}`
1669
+ const bar = renderDiffStatBar(added, removed)
1670
+ return bar ? `${parts.join(" ")} ${bar}` : parts.join(" ")
1671
+ }
1672
+
1673
+ function diffSummaryWithMeta(added: number, removed: number, hunks: number, mode: string): string {
1674
+ const base = summarizeDiff(added, removed)
1675
+ const extras: string[] = []
1676
+ if (hunks > 0) extras.push(`${FG_DIM}${hunks} hunk${hunks === 1 ? "" : "s"}${D_RST}`)
1677
+ if (mode) extras.push(`${FG_DIM}${mode}${D_RST}`)
1678
+ return extras.length ? `${base} ${FG_DIM}•${D_RST} ${extras.join(` ${FG_DIM}•${D_RST} `)}` : base
1679
+ }
1680
+
1681
+ function collapsedDiffHint(remainingLines: number, hiddenHunks: number): string {
1682
+ const width = termW()
1683
+ const candidates = [
1684
+ `… (${remainingLines} more diff lines${hiddenHunks > 0 ? ` • ${hiddenHunks} more hunks` : ""} • ctrl+o to expand)`,
1685
+ `… (${remainingLines} more lines${hiddenHunks > 0 ? ` • ${hiddenHunks} hunks` : ""})`,
1686
+ `… (+${remainingLines}${hiddenHunks > 0 ? ` • +${hiddenHunks}h` : ""})`,
1687
+ "…",
1688
+ ]
1689
+ for (const candidate of candidates) {
1690
+ if (visibleWidth(candidate) <= width) return candidate
1691
+ }
1692
+ return truncateToWidth("…", width, "")
1693
+ }
1694
+
1695
+ function diffRule(width: number): string {
1696
+ return `${BG_BASE}${FG_RULE}${"─".repeat(width)}${D_RST}`
1697
+ }
1698
+
1699
+ function shouldUseSplit(diff: ParsedDiff, tw: number, maxRows = MAX_PREVIEW_LINES): boolean {
1700
+ if (!diff.lines.length) return false
1701
+ if (tw < SPLIT_MIN_WIDTH) return false
1702
+ const nw = Math.max(2, String(Math.max(...diff.lines.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
1703
+ const half = Math.floor((tw - 1) / 2)
1704
+ const gw = nw + 5
1705
+ const cw = Math.max(12, half - gw)
1706
+ if (cw < SPLIT_MIN_CODE_WIDTH) return false
1707
+ const vis = diff.lines.slice(0, maxRows)
1708
+ let contentLines = 0
1709
+ let wrapCandidates = 0
1710
+ for (const line of vis) {
1711
+ if (line.type === "sep") continue
1712
+ contentLines++
1713
+ if (tabs(line.content).length > cw) wrapCandidates++
1714
+ }
1715
+ if (contentLines === 0) return true
1716
+ const wrapRatio = wrapCandidates / contentLines
1717
+ if (wrapCandidates >= SPLIT_MAX_WRAP_LINES) return false
1718
+ if (wrapRatio >= SPLIT_MAX_WRAP_RATIO) return false
1719
+ return true
1720
+ }
1721
+
1722
+ const EXT_LANG: Record<string, BundledLanguage> = {
1723
+ ts: "typescript",
1724
+ tsx: "tsx",
1725
+ js: "javascript",
1726
+ jsx: "jsx",
1727
+ mjs: "javascript",
1728
+ cjs: "javascript",
1729
+ py: "python",
1730
+ rb: "ruby",
1731
+ rs: "rust",
1732
+ go: "go",
1733
+ java: "java",
1734
+ c: "c",
1735
+ cpp: "cpp",
1736
+ h: "c",
1737
+ hpp: "cpp",
1738
+ cs: "csharp",
1739
+ swift: "swift",
1740
+ kt: "kotlin",
1741
+ html: "html",
1742
+ css: "css",
1743
+ scss: "scss",
1744
+ json: "json",
1745
+ yaml: "yaml",
1746
+ yml: "yaml",
1747
+ toml: "toml",
1748
+ md: "markdown",
1749
+ sql: "sql",
1750
+ sh: "bash",
1751
+ bash: "bash",
1752
+ zsh: "bash",
1753
+ lua: "lua",
1754
+ php: "php",
1755
+ dart: "dart",
1756
+ xml: "xml",
1757
+ graphql: "graphql",
1758
+ svelte: "svelte",
1759
+ vue: "vue",
1760
+ }
1761
+
1762
+ function lang(filePath: string): BundledLanguage | undefined {
1763
+ return EXT_LANG[extname(filePath).slice(1).toLowerCase()]
1764
+ }
1765
+
1766
+ async function codeToAnsiLazy(code: string, language: BundledLanguage, theme: BundledTheme): Promise<string> {
1767
+ if (!codeToAnsiLoader) {
1768
+ codeToAnsiLoader = import("@shikijs/cli").then((mod) => mod.codeToANSI)
1769
+ }
1770
+ const codeToAnsi = await codeToAnsiLoader
1771
+ return codeToAnsi(code, language, theme)
1772
+ }
1773
+
1774
+ const hlCache = new Map<string, string[]>()
1775
+
1776
+ function clearHighlightCache(): void {
1777
+ hlCache.clear()
1778
+ }
1779
+
1780
+ function touchCache(key: string, value: string[]): string[] {
1781
+ hlCache.delete(key)
1782
+ hlCache.set(key, value)
1783
+ while (hlCache.size > CACHE_LIMIT) {
1784
+ const first = hlCache.keys().next().value
1785
+ if (first === undefined) break
1786
+ hlCache.delete(first)
1787
+ }
1788
+ return value
1789
+ }
1790
+
1791
+ async function hlBlock(code: string, language: BundledLanguage | undefined): Promise<string[]> {
1792
+ if (!code) return [""]
1793
+ if (!language || code.length > MAX_HL_CHARS) return code.split("\n")
1794
+ const key = `${DIFF_THEME}\0${language}\0${code}`
1795
+ const hit = hlCache.get(key)
1796
+ if (hit) return touchCache(key, hit)
1797
+ try {
1798
+ const ansi = normalizeShikiContrast(await codeToAnsiLazy(code, language, DIFF_THEME))
1799
+ const out = (ansi.endsWith("\n") ? ansi.slice(0, -1) : ansi).split("\n")
1800
+ return touchCache(key, out)
1801
+ } catch {
1802
+ return code.split("\n")
1803
+ }
1804
+ }
1805
+
1806
+ function parseDiff(oldContent: string, newContent: string, ctxLines = 3): ParsedDiff {
1807
+ const patch = Diff.structuredPatch("", "", oldContent, newContent, "", "", { context: ctxLines })
1808
+ const lines: DiffLine[] = []
1809
+ let added = 0
1810
+ let removed = 0
1811
+ for (let hi = 0; hi < patch.hunks.length; hi++) {
1812
+ if (hi > 0) {
1813
+ const prev = patch.hunks[hi - 1]
1814
+ const gap = patch.hunks[hi].oldStart - (prev.oldStart + prev.oldLines)
1815
+ lines.push({ type: "sep", oldNum: null, newNum: gap > 0 ? gap : null, content: "" })
1816
+ }
1817
+ const hunk = patch.hunks[hi]
1818
+ let oldLine = hunk.oldStart
1819
+ let newLine = hunk.newStart
1820
+ for (const raw of hunk.lines) {
1821
+ if (raw === "\") continue
1822
+ const ch = raw[0]
1823
+ const text = raw.slice(1)
1824
+ if (ch === "+") {
1825
+ lines.push({ type: "add", oldNum: null, newNum: newLine++, content: text })
1826
+ added++
1827
+ } else if (ch === "-") {
1828
+ lines.push({ type: "del", oldNum: oldLine++, newNum: null, content: text })
1829
+ removed++
1830
+ } else {
1831
+ lines.push({ type: "ctx", oldNum: oldLine++, newNum: newLine++, content: text })
1832
+ }
1833
+ }
1834
+ }
1835
+ return { lines, added, removed, chars: oldContent.length + newContent.length }
1836
+ }
1837
+
1838
+ function getCachedParsedDiff(ctx: any, key: string, oldContent: string, newContent: string): ParsedDiff {
1839
+ if (ctx.state?._parsedDiffKey === key && ctx.state._parsedDiff) {
1840
+ return ctx.state._parsedDiff as ParsedDiff
1841
+ }
1842
+ const diff = parseDiff(oldContent, newContent)
1843
+ if (ctx.state) {
1844
+ ctx.state._parsedDiffKey = key
1845
+ ctx.state._parsedDiff = diff
1846
+ }
1847
+ return diff
1848
+ }
1849
+
1850
+ function wordDiffAnalysis(
1851
+ oldText: string,
1852
+ newText: string,
1853
+ ): { similarity: number; oldRanges: Array<[number, number]>; newRanges: Array<[number, number]> } {
1854
+ if (!oldText && !newText) return { similarity: 1, oldRanges: [], newRanges: [] }
1855
+ const parts = Diff.diffWords(oldText, newText)
1856
+ const oldRanges: Array<[number, number]> = []
1857
+ const newRanges: Array<[number, number]> = []
1858
+ let oldPos = 0
1859
+ let newPos = 0
1860
+ let same = 0
1861
+ for (const part of parts) {
1862
+ if (part.removed) {
1863
+ oldRanges.push([oldPos, oldPos + part.value.length])
1864
+ oldPos += part.value.length
1865
+ } else if (part.added) {
1866
+ newRanges.push([newPos, newPos + part.value.length])
1867
+ newPos += part.value.length
1868
+ } else {
1869
+ const len = part.value.length
1870
+ same += len
1871
+ oldPos += len
1872
+ newPos += len
1873
+ }
1874
+ }
1875
+ const maxLen = Math.max(oldText.length, newText.length)
1876
+ return { similarity: maxLen > 0 ? same / maxLen : 1, oldRanges, newRanges }
1877
+ }
1878
+
1879
+ function injectBg(ansiLine: string, ranges: Array<[number, number]>, baseBg: string, hlBg: string): string {
1880
+ if (!ranges.length) return baseBg + ansiLine + D_RST
1881
+ let out = baseBg
1882
+ let vis = 0
1883
+ let inHL = false
1884
+ let rangeIndex = 0
1885
+ let i = 0
1886
+ while (i < ansiLine.length) {
1887
+ if (ansiLine[i] === "\x1b") {
1888
+ const end = ansiLine.indexOf("m", i)
1889
+ if (end !== -1) {
1890
+ const seq = ansiLine.slice(i, end + 1)
1891
+ out += seq
1892
+ if (seq === "\x1b[0m") out += inHL ? hlBg : baseBg
1893
+ i = end + 1
1894
+ continue
1895
+ }
1896
+ }
1897
+ while (rangeIndex < ranges.length && vis >= ranges[rangeIndex][1]) rangeIndex++
1898
+ const want = rangeIndex < ranges.length && vis >= ranges[rangeIndex][0] && vis < ranges[rangeIndex][1]
1899
+ if (want !== inHL) {
1900
+ inHL = want
1901
+ out += inHL ? hlBg : baseBg
1902
+ }
1903
+ out += ansiLine[i]
1904
+ vis++
1905
+ i++
1906
+ }
1907
+ return out + D_RST
1908
+ }
1909
+
1910
+ function plainWordDiff(oldText: string, newText: string): { old: string; new: string } {
1911
+ const parts = Diff.diffWords(oldText, newText)
1912
+ let oldOut = ""
1913
+ let newOut = ""
1914
+ for (const part of parts) {
1915
+ if (part.removed) oldOut += `${BG_DEL_W}${part.value}${D_RST}${BG_DEL}`
1916
+ else if (part.added) newOut += `${BG_ADD_W}${part.value}${D_RST}${BG_ADD}`
1917
+ else {
1918
+ oldOut += part.value
1919
+ newOut += part.value
1920
+ }
1921
+ }
1922
+ return { old: oldOut, new: newOut }
1923
+ }
1924
+
1925
+ async function renderUnified(
1926
+ diff: ParsedDiff,
1927
+ language: BundledLanguage | undefined,
1928
+ max = MAX_RENDER_LINES,
1929
+ dc: DiffColors = DEFAULT_DIFF_COLORS,
1930
+ width = termW(),
1931
+ ): Promise<string> {
1932
+ if (!diff.lines.length) return ""
1933
+ const vis = diff.lines.slice(0, max)
1934
+ const tw = width
1935
+ const nw = Math.max(2, String(Math.max(...vis.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
1936
+ const gw = nw + 5
1937
+ const cw = Math.max(20, tw - gw)
1938
+ const canHL = diff.chars <= MAX_HL_CHARS && vis.length <= MAX_RENDER_LINES
1939
+
1940
+ const oldSrc: string[] = []
1941
+ const newSrc: string[] = []
1942
+ for (const line of vis) {
1943
+ if (line.type === "ctx" || line.type === "del") oldSrc.push(line.content)
1944
+ if (line.type === "ctx" || line.type === "add") newSrc.push(line.content)
1945
+ }
1946
+ const [oldHL, newHL] = canHL
1947
+ ? await Promise.all([hlBlock(oldSrc.join("\n"), language), hlBlock(newSrc.join("\n"), language)])
1948
+ : [oldSrc, newSrc]
1949
+
1950
+ let oldIndex = 0
1951
+ let newIndex = 0
1952
+ let index = 0
1953
+ const out: string[] = [diffRule(tw)]
1954
+
1955
+ function emitRow(
1956
+ num: number | null,
1957
+ sign: string,
1958
+ gutterBg: string,
1959
+ signFg: string,
1960
+ body: string,
1961
+ bodyBg = "",
1962
+ ): void {
1963
+ const borderFg = sign === "-" ? dc.fgDel : sign === "+" ? dc.fgAdd : ""
1964
+ const border = borderFg ? `${borderFg}▌${D_RST}` : `${BG_BASE} `
1965
+ const numFg = borderFg || FG_LNUM
1966
+ const gutter = `${border}${gutterBg}${lnum(num, nw, numFg)}${signFg}${sign}${D_RST} ${DIVIDER} `
1967
+ const cont = `${border}${gutterBg}${" ".repeat(nw + 1)}${D_RST} ${DIVIDER} `
1968
+ const rows = wrapAnsi(tabs(body), cw, adaptiveWrapRows(), bodyBg)
1969
+ out.push(`${gutter}${rows[0]}${D_RST}`)
1970
+ for (let r = 1; r < rows.length; r++) out.push(`${cont}${rows[r]}${D_RST}`)
1971
+ }
1972
+
1973
+ while (index < vis.length) {
1974
+ const line = vis[index]
1975
+ if (line.type === "sep") {
1976
+ const gap = line.newNum
1977
+ const label = gap && gap > 0 ? ` ${gap} unmodified lines ` : "···"
1978
+ const totalW = Math.min(tw, 72)
1979
+ const pad = Math.max(0, totalW - label.length - 2)
1980
+ const half1 = Math.floor(pad / 2)
1981
+ const half2 = pad - half1
1982
+ out.push(`${BG_BASE}${FG_DIM}${"─".repeat(half1)}${label}${"─".repeat(half2)}${D_RST}`)
1983
+ index++
1984
+ continue
1985
+ }
1986
+ if (line.type === "ctx") {
1987
+ const hl = oldHL[oldIndex] ?? line.content
1988
+ emitRow(line.newNum, " ", BG_BASE, dc.fgCtx, `${BG_BASE}${D_DIM}${hl}`, BG_BASE)
1989
+ oldIndex++
1990
+ newIndex++
1991
+ index++
1992
+ continue
1993
+ }
1994
+
1995
+ const dels: Array<{ l: DiffLine; hl: string }> = []
1996
+ while (index < vis.length && vis[index].type === "del") {
1997
+ dels.push({ l: vis[index], hl: oldHL[oldIndex] ?? vis[index].content })
1998
+ oldIndex++
1999
+ index++
2000
+ }
2001
+ const adds: Array<{ l: DiffLine; hl: string }> = []
2002
+ while (index < vis.length && vis[index].type === "add") {
2003
+ adds.push({ l: vis[index], hl: newHL[newIndex] ?? vis[index].content })
2004
+ newIndex++
2005
+ index++
2006
+ }
2007
+
2008
+ const isPaired = dels.length === 1 && adds.length === 1
2009
+ const wd = isPaired ? wordDiffAnalysis(dels[0].l.content, adds[0].l.content) : null
2010
+ if (isPaired && wd && wd.similarity >= WORD_DIFF_MIN_SIM && canHL) {
2011
+ emitRow(
2012
+ dels[0].l.oldNum,
2013
+ "-",
2014
+ BG_GUTTER_DEL,
2015
+ `${dc.fgDel}${D_BOLD}`,
2016
+ injectBg(dels[0].hl, wd.oldRanges, BG_DEL, BG_DEL_W),
2017
+ BG_DEL,
2018
+ )
2019
+ emitRow(
2020
+ adds[0].l.newNum,
2021
+ "+",
2022
+ BG_GUTTER_ADD,
2023
+ `${dc.fgAdd}${D_BOLD}`,
2024
+ injectBg(adds[0].hl, wd.newRanges, BG_ADD, BG_ADD_W),
2025
+ BG_ADD,
2026
+ )
2027
+ continue
2028
+ }
2029
+ if (isPaired && wd && wd.similarity >= WORD_DIFF_MIN_SIM && !canHL) {
2030
+ const pwd = plainWordDiff(dels[0].l.content, adds[0].l.content)
2031
+ emitRow(dels[0].l.oldNum, "-", BG_GUTTER_DEL, `${dc.fgDel}${D_BOLD}`, `${BG_DEL}${pwd.old}`, BG_DEL)
2032
+ emitRow(adds[0].l.newNum, "+", BG_GUTTER_ADD, `${dc.fgAdd}${D_BOLD}`, `${BG_ADD}${pwd.new}`, BG_ADD)
2033
+ continue
2034
+ }
2035
+ for (const d of dels)
2036
+ emitRow(d.l.oldNum, "-", BG_GUTTER_DEL, `${dc.fgDel}${D_BOLD}`, `${BG_DEL}${canHL ? d.hl : d.l.content}`, BG_DEL)
2037
+ for (const a of adds)
2038
+ emitRow(a.l.newNum, "+", BG_GUTTER_ADD, `${dc.fgAdd}${D_BOLD}`, `${BG_ADD}${canHL ? a.hl : a.l.content}`, BG_ADD)
2039
+ }
2040
+
2041
+ out.push(diffRule(tw))
2042
+ if (diff.lines.length > vis.length)
2043
+ out.push(`${BG_BASE}${FG_DIM} ${collapsedDiffHint(diff.lines.length - vis.length, 0)}${D_RST}`)
2044
+ return out.join("\n")
2045
+ }
2046
+
2047
+ async function renderSplit(
2048
+ diff: ParsedDiff,
2049
+ language: BundledLanguage | undefined,
2050
+ max = MAX_PREVIEW_LINES,
2051
+ dc: DiffColors = DEFAULT_DIFF_COLORS,
2052
+ width = termW(),
2053
+ ): Promise<string> {
2054
+ const tw = width
2055
+ if (!shouldUseSplit(diff, tw, max)) return renderUnified(diff, language, max, dc, width)
2056
+ if (!diff.lines.length) return ""
2057
+
2058
+ type Row = { left: DiffLine | null; right: DiffLine | null }
2059
+ const rows: Row[] = []
2060
+ let i = 0
2061
+ while (i < diff.lines.length) {
2062
+ const line = diff.lines[i]
2063
+ if (line.type === "sep" || line.type === "ctx") {
2064
+ rows.push({ left: line, right: line })
2065
+ i++
2066
+ continue
2067
+ }
2068
+ const dels: DiffLine[] = []
2069
+ const adds: DiffLine[] = []
2070
+ while (i < diff.lines.length && diff.lines[i].type === "del") dels.push(diff.lines[i++])
2071
+ while (i < diff.lines.length && diff.lines[i].type === "add") adds.push(diff.lines[i++])
2072
+ const n = Math.max(dels.length, adds.length)
2073
+ for (let j = 0; j < n; j++) rows.push({ left: dels[j] ?? null, right: adds[j] ?? null })
2074
+ }
2075
+
2076
+ const vis = rows.slice(0, max)
2077
+ const half = Math.floor((tw - 1) / 2)
2078
+ const nw = Math.max(2, String(Math.max(...diff.lines.map((l) => l.oldNum ?? l.newNum ?? 0), 0)).length)
2079
+ const gw = nw + 5
2080
+ const cw = Math.max(12, half - gw)
2081
+ const canHL = diff.chars <= MAX_HL_CHARS && vis.length * 2 <= MAX_RENDER_LINES * 2
2082
+
2083
+ const leftSrc: string[] = []
2084
+ const rightSrc: string[] = []
2085
+ for (const row of vis) {
2086
+ if (row.left && row.left.type !== "sep") leftSrc.push(row.left.content)
2087
+ if (row.right && row.right.type !== "sep") rightSrc.push(row.right.content)
2088
+ }
2089
+ const [leftHL, rightHL] = canHL
2090
+ ? await Promise.all([hlBlock(leftSrc.join("\n"), language), hlBlock(rightSrc.join("\n"), language)])
2091
+ : [leftSrc, rightSrc]
2092
+
2093
+ let leftIndex = 0
2094
+ let rightIndex = 0
2095
+
2096
+ type HalfResult = { gutter: string; contGutter: string; bodyRows: string[] }
2097
+ function halfBuild(
2098
+ line: DiffLine | null,
2099
+ hl: string,
2100
+ ranges: Array<[number, number]> | null,
2101
+ side: "left" | "right",
2102
+ ): HalfResult {
2103
+ if (!line) {
2104
+ const gPat = FG_STRIPE + "╱".repeat(nw + 2) + D_RST
2105
+ const gutter = ` ${gPat}${FG_RULE}│${D_RST} `
2106
+ return { gutter, contGutter: gutter, bodyRows: [stripes(cw)] }
2107
+ }
2108
+ if (line.type === "sep") {
2109
+ const gap = line.newNum
2110
+ const label = gap && gap > 0 ? `··· ${gap} lines ···` : "···"
2111
+ const gutter = `${BG_BASE} ${FG_DIM}${fit("", nw + 2)}${D_RST}${FG_RULE}│${D_RST} `
2112
+ return { gutter, contGutter: gutter, bodyRows: [`${BG_BASE}${FG_DIM}${fit(label, cw)}${D_RST}`] }
2113
+ }
2114
+ const isDel = line.type === "del"
2115
+ const isAdd = line.type === "add"
2116
+ const gBg = isDel ? BG_GUTTER_DEL : isAdd ? BG_GUTTER_ADD : BG_BASE
2117
+ const cBg = isDel ? BG_DEL : isAdd ? BG_ADD : BG_BASE
2118
+ const sFg = isDel ? dc.fgDel : isAdd ? dc.fgAdd : dc.fgCtx
2119
+ const sign = isDel ? "-" : isAdd ? "+" : " "
2120
+ const num = isDel ? line.oldNum : isAdd ? line.newNum : side === "left" ? line.oldNum : line.newNum
2121
+ const borderFg = isDel ? dc.fgDel : isAdd ? dc.fgAdd : ""
2122
+ const border = borderFg ? `${borderFg}▌${D_RST}` : ` ${BG_BASE}`
2123
+ const numFg = borderFg || FG_LNUM
2124
+ let body: string
2125
+ if (ranges && ranges.length > 0) body = injectBg(hl, ranges, cBg, isDel ? BG_DEL_W : BG_ADD_W)
2126
+ else if (isDel || isAdd) body = `${cBg}${hl}`
2127
+ else body = `${BG_BASE}${D_DIM}${hl}`
2128
+ const gutter = `${border}${gBg}${lnum(num, nw, numFg)}${sFg}${D_BOLD}${sign}${D_RST} ${FG_RULE}│${D_RST} `
2129
+ const contGutter = `${border}${gBg}${" ".repeat(nw + 1)}${D_RST} ${FG_RULE}│${D_RST} `
2130
+ return { gutter, contGutter, bodyRows: wrapAnsi(tabs(body), cw, adaptiveWrapRows(), cBg) }
2131
+ }
2132
+
2133
+ const out: string[] = []
2134
+ const hdrOld = `${BG_BASE}${" ".repeat(Math.max(0, nw - 2))}${dc.fgDel}${D_DIM}old${D_RST}`
2135
+ const hdrNew = `${BG_BASE}${" ".repeat(Math.max(0, nw - 2))}${dc.fgAdd}${D_DIM}new${D_RST}`
2136
+ out.push(`${BG_BASE}${hdrOld}${" ".repeat(Math.max(0, half - nw - 1))}${FG_RULE}┊${D_RST}${hdrNew}`)
2137
+ out.push(`${diffRule(half)}${FG_RULE}┊${D_RST}${diffRule(half)}`)
2138
+
2139
+ for (const row of vis) {
2140
+ const leftLine = row.left
2141
+ const rightLine = row.right
2142
+ const paired = Boolean(leftLine && rightLine && leftLine.type === "del" && rightLine.type === "add")
2143
+ const wd = paired && leftLine && rightLine ? wordDiffAnalysis(leftLine.content, rightLine.content) : null
2144
+ let leftResult: HalfResult
2145
+ let rightResult: HalfResult
2146
+ if (paired && wd && leftLine && rightLine && wd.similarity >= WORD_DIFF_MIN_SIM && canHL) {
2147
+ leftResult = halfBuild(leftLine, leftHL[leftIndex++] ?? leftLine.content, wd.oldRanges, "left")
2148
+ rightResult = halfBuild(rightLine, rightHL[rightIndex++] ?? rightLine.content, wd.newRanges, "right")
2149
+ } else if (paired && wd && leftLine && rightLine && wd.similarity >= WORD_DIFF_MIN_SIM && !canHL) {
2150
+ const pwd = plainWordDiff(leftLine.content, rightLine.content)
2151
+ leftIndex++
2152
+ rightIndex++
2153
+ leftResult = halfBuild(leftLine, pwd.old, null, "left")
2154
+ rightResult = halfBuild(rightLine, pwd.new, null, "right")
2155
+ } else {
2156
+ leftResult = halfBuild(
2157
+ row.left,
2158
+ row.left && row.left.type !== "sep" ? (leftHL[leftIndex++] ?? row.left.content) : "",
2159
+ null,
2160
+ "left",
2161
+ )
2162
+ rightResult = halfBuild(
2163
+ row.right,
2164
+ row.right && row.right.type !== "sep" ? (rightHL[rightIndex++] ?? row.right.content) : "",
2165
+ null,
2166
+ "right",
2167
+ )
2168
+ }
2169
+ const maxRows = Math.max(leftResult.bodyRows.length, rightResult.bodyRows.length)
2170
+ for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
2171
+ const lg = rowIndex === 0 ? leftResult.gutter : leftResult.contGutter
2172
+ const rg = rowIndex === 0 ? rightResult.gutter : rightResult.contGutter
2173
+ const lb = leftResult.bodyRows[rowIndex] ?? (!row.left ? stripes(cw) : `${BG_EMPTY}${" ".repeat(cw)}${D_RST}`)
2174
+ const rb = rightResult.bodyRows[rowIndex] ?? (!row.right ? stripes(cw) : `${BG_EMPTY}${" ".repeat(cw)}${D_RST}`)
2175
+ out.push(`${lg}${lb}${DIVIDER}${rg}${rb}`)
2176
+ }
2177
+ }
2178
+
2179
+ out.push(`${diffRule(half)}${FG_RULE}┊${D_RST}${diffRule(half)}`)
2180
+ if (rows.length > vis.length)
2181
+ out.push(`${BG_BASE}${FG_DIM} ${collapsedDiffHint(rows.length - vis.length, 0)}${D_RST}`)
2182
+ return out.join("\n")
2183
+ }
2184
+
2185
+ function getEditOperations(input: any): Array<{ oldText: string; newText: string }> {
2186
+ if (Array.isArray(input?.edits)) {
2187
+ return input.edits
2188
+ .map((edit: any) => ({
2189
+ oldText:
2190
+ typeof edit?.oldText === "string" ? edit.oldText : typeof edit?.old_text === "string" ? edit.old_text : "",
2191
+ newText:
2192
+ typeof edit?.newText === "string" ? edit.newText : typeof edit?.new_text === "string" ? edit.new_text : "",
2193
+ }))
2194
+ .filter((edit: { oldText: string; newText: string }) => edit.oldText && edit.oldText !== edit.newText)
2195
+ }
2196
+ const oldText =
2197
+ typeof input?.oldText === "string" ? input.oldText : typeof input?.old_text === "string" ? input.old_text : ""
2198
+ const newText =
2199
+ typeof input?.newText === "string" ? input.newText : typeof input?.new_text === "string" ? input.new_text : ""
2200
+ return oldText && oldText !== newText ? [{ oldText, newText }] : []
2201
+ }
2202
+
2203
+ function summarizeEditOperations(operations: Array<{ oldText: string; newText: string }>) {
2204
+ const diffs = operations.map((edit) => parseDiff(edit.oldText, edit.newText))
2205
+ const totalAdded = diffs.reduce((sum, diff) => sum + diff.added, 0)
2206
+ const totalRemoved = diffs.reduce((sum, diff) => sum + diff.removed, 0)
2207
+ const totalLines = diffs.reduce((sum, diff) => sum + diff.lines.length, 0)
2208
+ const totalHunks = diffs.reduce(
2209
+ (sum, diff) => sum + diff.lines.filter((l) => l.type === "sep").length + (diff.lines.length ? 1 : 0),
2210
+ 0,
2211
+ )
2212
+ return { diffs, totalAdded, totalRemoved, totalLines, totalHunks, summary: summarizeDiff(totalAdded, totalRemoved) }
2213
+ }
2214
+
2215
+ type EditOperationSummary = ReturnType<typeof summarizeEditOperations>
2216
+
2217
+ function getCachedEditOperationSummary(
2218
+ ctx: any,
2219
+ key: string,
2220
+ operations: Array<{ oldText: string; newText: string }>,
2221
+ ): EditOperationSummary {
2222
+ if (ctx.state?._editSummaryKey === key && ctx.state._editSummary) {
2223
+ return ctx.state._editSummary as EditOperationSummary
2224
+ }
2225
+ const summary = summarizeEditOperations(operations)
2226
+ if (ctx.state) {
2227
+ ctx.state._editSummaryKey = key
2228
+ ctx.state._editSummary = summary
2229
+ }
2230
+ return summary
2231
+ }
2232
+
2233
+ function normalizeToLf(text: string): string {
2234
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n")
2235
+ }
2236
+
2237
+ function stripBomText(text: string): string {
2238
+ return text.startsWith("\uFEFF") ? text.slice(1) : text
2239
+ }
2240
+
2241
+ function normalizeTextForFuzzyMatch(text: string): string {
2242
+ return text
2243
+ .normalize("NFKC")
2244
+ .split("\n")
2245
+ .map((line) => line.trimEnd())
2246
+ .join("\n")
2247
+ .replace(/[\u2018\u2019\u201A\u201B]/g, "'")
2248
+ .replace(/[\u201C\u201D\u201E\u201F]/g, '"')
2249
+ .replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-")
2250
+ .replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ")
2251
+ }
2252
+
2253
+ function findEditMatch(
2254
+ content: string,
2255
+ oldText: string,
2256
+ ): { found: boolean; index: number; matchLength: number; usedFuzzyMatch: boolean } {
2257
+ const exactIndex = content.indexOf(oldText)
2258
+ if (exactIndex !== -1) return { found: true, index: exactIndex, matchLength: oldText.length, usedFuzzyMatch: false }
2259
+ const fuzzyContent = normalizeTextForFuzzyMatch(content)
2260
+ const fuzzyOldText = normalizeTextForFuzzyMatch(oldText)
2261
+ const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText)
2262
+ return fuzzyIndex === -1
2263
+ ? { found: false, index: -1, matchLength: 0, usedFuzzyMatch: false }
2264
+ : { found: true, index: fuzzyIndex, matchLength: fuzzyOldText.length, usedFuzzyMatch: true }
2265
+ }
2266
+
2267
+ function countFuzzyOccurrences(content: string, oldText: string): number {
2268
+ const fuzzyContent = normalizeTextForFuzzyMatch(content)
2269
+ const fuzzyOldText = normalizeTextForFuzzyMatch(oldText)
2270
+ return fuzzyContent.split(fuzzyOldText).length - 1
2271
+ }
2272
+
2273
+ function lineNumberAtIndex(text: string, index: number): number {
2274
+ return text.slice(0, Math.max(0, index)).split("\n").length
2275
+ }
2276
+
2277
+ function countLineBreaks(text: string): number {
2278
+ return (text.match(/\n/g) ?? []).length
2279
+ }
2280
+
2281
+ function offsetParsedDiff(diff: ParsedDiff, oldOffset: number, newOffset = oldOffset): ParsedDiff {
2282
+ return {
2283
+ ...diff,
2284
+ lines: diff.lines.map((line) =>
2285
+ line.type === "sep"
2286
+ ? line
2287
+ : {
2288
+ ...line,
2289
+ oldNum: line.oldNum === null ? null : line.oldNum + oldOffset,
2290
+ newNum: line.newNum === null ? null : line.newNum + newOffset,
2291
+ },
2292
+ ),
2293
+ }
2294
+ }
2295
+
2296
+ function getFirstChangedNewLine(diff: ParsedDiff): number {
2297
+ let currentNewLine = 0
2298
+ for (let i = 0; i < diff.lines.length; i++) {
2299
+ const line = diff.lines[i]
2300
+ if (line.type === "sep") {
2301
+ currentNewLine = 0
2302
+ continue
2303
+ }
2304
+ if (line.type === "ctx") {
2305
+ currentNewLine = (line.newNum ?? currentNewLine) + 1
2306
+ continue
2307
+ }
2308
+ if (line.type === "add") return line.newNum ?? currentNewLine
2309
+ if (currentNewLine > 0) return currentNewLine
2310
+ const next = diff.lines.slice(i + 1).find((entry) => entry.type !== "sep" && entry.newNum !== null)
2311
+ if (next && next.newNum !== null) return next.newNum
2312
+ return line.oldNum ?? 0
2313
+ }
2314
+ return 0
2315
+ }
2316
+
2317
+ interface LocalizedEditDiff {
2318
+ diff: ParsedDiff
2319
+ line: number
2320
+ }
2321
+
2322
+ async function computeLocalizedEditDiffs(
2323
+ filePath: string,
2324
+ operations: Array<{ oldText: string; newText: string }>,
2325
+ cwd: string,
2326
+ ): Promise<LocalizedEditDiff[] | null> {
2327
+ if (!filePath || operations.length === 0) return null
2328
+ try {
2329
+ const rawContent = await readFileAsync(resolve(cwd, filePath), "utf8")
2330
+ const normalizedContent = normalizeToLf(stripBomText(rawContent))
2331
+ const normalizedOps = operations.map((edit) => ({
2332
+ oldText: normalizeToLf(edit.oldText),
2333
+ newText: normalizeToLf(edit.newText),
2334
+ }))
2335
+ const baseContent = normalizedOps.some((edit) => findEditMatch(normalizedContent, edit.oldText).usedFuzzyMatch)
2336
+ ? normalizeTextForFuzzyMatch(normalizedContent)
2337
+ : normalizedContent
2338
+ const matches = normalizedOps.map((edit, editIndex) => {
2339
+ const match = findEditMatch(baseContent, edit.oldText)
2340
+ if (!match.found || countFuzzyOccurrences(baseContent, edit.oldText) !== 1) return null
2341
+ return { editIndex, matchIndex: match.index, matchLength: match.matchLength, newText: edit.newText }
2342
+ })
2343
+ if (matches.some((match) => match === null)) return null
2344
+ const ordered = [
2345
+ ...(matches as Array<{ editIndex: number; matchIndex: number; matchLength: number; newText: string }>),
2346
+ ].sort((a, b) => a.matchIndex - b.matchIndex)
2347
+ for (let i = 1; i < ordered.length; i++) {
2348
+ const prev = ordered[i - 1]
2349
+ const current = ordered[i]
2350
+ if (prev.matchIndex + prev.matchLength > current.matchIndex) return null
2351
+ }
2352
+ const localized: Array<LocalizedEditDiff | null> = Array(operations.length).fill(null)
2353
+ let lineDelta = 0
2354
+ for (const match of ordered) {
2355
+ const oldChunk = baseContent.slice(match.matchIndex, match.matchIndex + match.matchLength)
2356
+ const oldStartLine = lineNumberAtIndex(baseContent, match.matchIndex)
2357
+ const newStartLine = oldStartLine + lineDelta
2358
+ const diff = offsetParsedDiff(parseDiff(oldChunk, match.newText), oldStartLine - 1, newStartLine - 1)
2359
+ localized[match.editIndex] = { diff, line: getFirstChangedNewLine(diff) }
2360
+ lineDelta += countLineBreaks(match.newText) - countLineBreaks(oldChunk)
2361
+ }
2362
+ return localized.every(Boolean) ? (localized as LocalizedEditDiff[]) : null
2363
+ } catch {
2364
+ return null
2365
+ }
2366
+ }
2367
+
2368
+ function renderEditPreviewBody(
2369
+ ctx: any,
2370
+ key: string,
2371
+ theme: Theme,
2372
+ language: BundledLanguage | undefined,
2373
+ operations: Array<{ oldText: string; newText: string }>,
2374
+ diffs: ParsedDiff[],
2375
+ lines: number[],
2376
+ summary: string,
2377
+ ): void {
2378
+ const dc = resolveDiffColors(theme)
2379
+ const branchWidth = branchDiffWidth()
2380
+ if (operations.length === 1) {
2381
+ const [diff] = diffs
2382
+ const line = lines[0] ?? getFirstChangedNewLine(diff)
2383
+ renderSplit(diff, language, ctx.expanded ? MAX_PREVIEW_LINES : 32, dc, branchWidth)
2384
+ .then((rendered) => {
2385
+ if (ctx.state._pk !== key) return
2386
+ ctx.state._ptBody = `${summarizeDiff(diff.added, diff.removed)}${formatLineMeta(line, theme)}\n${rendered}`
2387
+ ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
2388
+ ctx.invalidate()
2389
+ })
2390
+ .catch(() => {
2391
+ if (ctx.state._pk !== key) return
2392
+ ctx.state._ptBody = `${summarizeDiff(diff.added, diff.removed)}${formatLineMeta(line, theme)}`
2393
+ ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
2394
+ ctx.invalidate()
2395
+ })
2396
+ return
2397
+ }
2398
+ const maxShown = ctx.expanded ? operations.length : Math.min(operations.length, 3)
2399
+ const previewLines = ctx.expanded
2400
+ ? Math.max(6, Math.floor(MAX_RENDER_LINES / Math.max(1, maxShown)))
2401
+ : Math.max(8, Math.floor(MAX_PREVIEW_LINES / Math.max(1, maxShown)))
2402
+ void Promise.all(
2403
+ diffs.slice(0, maxShown).map((diff, index) => {
2404
+ const line = lines[index] ?? getFirstChangedNewLine(diff)
2405
+ return renderSplit(diff, language, previewLines, dc, branchWidth)
2406
+ .then((rendered) => `Edit ${index + 1}/${operations.length}${formatLineMeta(line, theme)}\n${rendered}`)
2407
+ .catch(
2408
+ () =>
2409
+ `Edit ${index + 1}/${operations.length}${formatLineMeta(line, theme)} ${summarizeDiff(diff.added, diff.removed)}`,
2410
+ )
2411
+ }),
2412
+ )
2413
+ .then((sections) => {
2414
+ if (ctx.state._pk !== key) return
2415
+ const remainder = operations.length - maxShown
2416
+ const suffix =
2417
+ remainder > 0
2418
+ ? `\n${theme.fg("muted", `… ${remainder} more edit blocks${ctx.expanded ? "" : " • ctrl+o to expand"}`)}`
2419
+ : ""
2420
+ ctx.state._ptBody = `${operations.length} edits ${summary}\n\n${sections.join("\n\n")}${suffix}`
2421
+ ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
2422
+ ctx.invalidate()
2423
+ })
2424
+ .catch(() => {
2425
+ if (ctx.state._pk !== key) return
2426
+ ctx.state._ptBody = `${operations.length} edits ${summary}`
2427
+ ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
2428
+ ctx.invalidate()
2429
+ })
2430
+ }
2431
+
2432
+ function stripThinkingPresentationArtifacts(text: string): string {
2433
+ if (!ANSI_PRESENT_RE.test(text) && !/^\s*thinking:\s*/i.test(text)) return text
2434
+ let current = ANSI_PRESENT_RE.test(text) ? text.replace(ANSI_RE, "") : text
2435
+ while (true) {
2436
+ const next = current.replace(/^(?:thinking:\s*)+/i, "").trimStart()
2437
+ if (next === current) return current
2438
+ current = next
2439
+ }
2440
+ }
2441
+
2442
+ function prefixThinkingLine(text: string, _theme: Theme | undefined): string {
2443
+ if (!ANSI_PRESENT_RE.test(text) && text.startsWith("Thinking: ") && !/^Thinking:\s*thinking:\s*/i.test(text)) {
2444
+ return text
2445
+ }
2446
+ const normalized = stripThinkingPresentationArtifacts(text).trim()
2447
+ if (!normalized) return text
2448
+ // Plain text — no ANSI colors, no theme. The ThinkingParagraph handles styling.
2449
+ return `Thinking: ${normalized}`
2450
+ }
2451
+
2452
+ function registerThinkingLabels(pi: ExtensionAPI): void {
2453
+ const patchMessage = (event: any, theme?: Theme) => {
2454
+ // Keep theme-derived border / dim text colors in sync with the
2455
+ // active pi theme. Cheap when the theme hasn't changed (identity check).
2456
+ if (theme) applyThemePaletteIfNeeded(theme)
2457
+ const message = event?.message
2458
+ if (!message || message.role !== "assistant" || !Array.isArray(message.content)) return
2459
+ for (const block of message.content) {
2460
+ if (block && block.type === "thinking" && typeof block.thinking === "string") {
2461
+ block.thinking = prefixThinkingLine(block.thinking, theme)
2462
+ }
2463
+ }
2464
+ }
2465
+ pi.on("before_agent_start", async () => {
2466
+ // Start once per top-level request. Steering/follow-up messages can be
2467
+ // injected while the agent is already active; those must not reset the
2468
+ // request timer.
2469
+ if (currentAgentWorkStartMs === undefined) {
2470
+ currentAgentWorkStartMs = Date.now()
2471
+ }
2472
+ currentAssistantMessageStartMs = undefined
2473
+ })
2474
+ pi.on("agent_start", async () => {
2475
+ if (currentAgentWorkStartMs === undefined) {
2476
+ currentAgentWorkStartMs = Date.now()
2477
+ }
2478
+ currentAssistantMessageStartMs = undefined
2479
+ })
2480
+ pi.on("message_start", async (event: any) => {
2481
+ const message = event?.message
2482
+ if (message?.role === "user" && currentAgentWorkStartMs === undefined) {
2483
+ currentAgentWorkStartMs = Date.now()
2484
+ }
2485
+ if (message?.role === "assistant") {
2486
+ currentAssistantMessageStartMs = Date.now()
2487
+ ;(message as any)[WORKED_START_KEY] = currentAssistantMessageStartMs
2488
+ }
2489
+ })
2490
+ pi.on("message_update", async (event, ctx) => patchMessage(event, ctx.ui?.theme))
2491
+ pi.on("message_end", async (event, ctx) => {
2492
+ const message = (event as any)?.message
2493
+ if (message?.role === "assistant") {
2494
+ const started =
2495
+ typeof currentAgentWorkStartMs === "number"
2496
+ ? currentAgentWorkStartMs
2497
+ : typeof (message as any)[WORKED_START_KEY] === "number"
2498
+ ? (message as any)[WORKED_START_KEY]
2499
+ : currentAssistantMessageStartMs
2500
+ const isFinalAssistantMessage = message.stopReason !== "toolUse"
2501
+ if (started !== undefined && isFinalAssistantMessage) {
2502
+ const durationMs = Date.now() - started
2503
+ // Store duration as metadata on the message object. The patched
2504
+ // AssistantMessageComponent.render() reads it and appends the widget
2505
+ // line outside of the message content blocks — never injected into
2506
+ // the text that gets sent to the model.
2507
+ ;(message as any)[WORKED_DURATION_KEY] = durationMs
2508
+ // Persist the duration as a sidecar entry in the JSONL session file
2509
+ // (type: "custom", does not participate in LLM context).
2510
+ pi.appendEntry("turn_duration", { durationMs })
2511
+ }
2512
+ currentAssistantMessageStartMs = undefined
2513
+ }
2514
+ patchMessage(event, ctx.ui?.theme)
2515
+ })
2516
+ pi.on("agent_end", async () => {
2517
+ currentAgentWorkStartMs = undefined
2518
+ currentAssistantMessageStartMs = undefined
2519
+ })
2520
+ pi.on("context", async (event) => {
2521
+ if (!Array.isArray((event as any).messages)) return
2522
+ for (const msg of (event as any).messages) {
2523
+ if (!msg || msg.role !== "assistant" || !Array.isArray(msg.content)) continue
2524
+ for (const block of msg.content) {
2525
+ if (block && block.type === "thinking" && typeof block.thinking === "string") {
2526
+ block.thinking = stripThinkingPresentationArtifacts(block.thinking)
2527
+ }
2528
+ // Legacy sessions written before this change may have the duration
2529
+ // text injected directly into content blocks. Strip it so it doesn't
2530
+ // appear twice alongside the widget.
2531
+ if (block && block.type === "text" && typeof block.text === "string") {
2532
+ const marker = "Worked for"
2533
+ if (block.text.includes(marker)) {
2534
+ block.text = block.text
2535
+ .split(/\r?\n/)
2536
+ .filter((l: string) => !(l.includes(marker) && /^✻ Worked for [^\r\n]+$/.test(l.replace(/\x1b\[[0-9;]*m/g, "").trim())))
2537
+ .join("\n")
2538
+ .replace(/\n{3,}/g, "\n\n")
2539
+ }
2540
+ }
2541
+ }
2542
+ }
2543
+ })
2544
+ }
2545
+
2546
+ function getMode<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {
2547
+ return typeof value === "string" && (allowed as readonly string[]).includes(value) ? (value as T) : fallback
2548
+ }
2549
+
2550
+ const CORE_TOOL_OVERRIDES = new Set(["read", "bash", "grep", "find", "ls", "write", "edit", "set_phase"])
2551
+
2552
+ const OPENAI_STYLE_TOOL_NAMES = new Set([
2553
+ "apply_patch",
2554
+ "webfetch",
2555
+ "question",
2556
+ "questionnaire",
2557
+ "context_tag",
2558
+ "context_log",
2559
+ "context_checkout",
2560
+ "annotate",
2561
+ "web_search",
2562
+ "code_search",
2563
+ "fetch_content",
2564
+ "get_search_content",
2565
+ "alpha_search",
2566
+ "alpha_get_paper",
2567
+ "alpha_ask_paper",
2568
+ "alpha_annotate_paper",
2569
+ "alpha_list_annotations",
2570
+ "alpha_read_code",
2571
+ "Skill",
2572
+ "EnterPlanMode",
2573
+ "ExitPlanMode",
2574
+ "Agent",
2575
+ "get_subagent_result",
2576
+ "steer_subagent",
2577
+ "TaskCreate",
2578
+ "TaskList",
2579
+ "TaskGet",
2580
+ "TaskUpdate",
2581
+ "TaskOutput",
2582
+ "TaskStop",
2583
+ "TaskExecute",
2584
+ ])
2585
+
2586
+ function isMcpToolCandidate(tool: unknown): boolean {
2587
+ const rec = tool as Record<string, unknown> | undefined
2588
+ const name = typeof rec?.name === "string" ? rec.name : ""
2589
+ const description = typeof rec?.description === "string" ? rec.description : ""
2590
+ return name === "mcp" || /\bmcp\b/i.test(description)
2591
+ }
2592
+
2593
+ function isOpenAiToolCandidate(tool: unknown): boolean {
2594
+ const rec = tool as Record<string, unknown> | undefined
2595
+ const name = typeof rec?.name === "string" ? rec.name : ""
2596
+ if (!name || CORE_TOOL_OVERRIDES.has(name) || isMcpToolCandidate(tool)) return false
2597
+ return OPENAI_STYLE_TOOL_NAMES.has(name)
2598
+ }
2599
+
2600
+ function humanizeToolName(name: string): string {
2601
+ return name
2602
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
2603
+ .replace(/[_-]+/g, " ")
2604
+ .replace(/\b\w/g, (char) => char.toUpperCase())
2605
+ }
2606
+
2607
+ export function isMcpToolName(name: string): boolean {
2608
+ return name === "mcp" || /^mcp[_:-]/i.test(name) || /[_:-]mcp[_:-]/i.test(name)
2609
+ }
2610
+
2611
+ function shouldUseGenericToolRenderer(name: unknown): boolean {
2612
+ return typeof name === "string" && name.length > 0 && !CORE_TOOL_OVERRIDES.has(name)
2613
+ }
2614
+
2615
+ function genericToolLabel(name: string): string {
2616
+ return isMcpToolName(name) ? "MCP" : humanizeToolName(name)
2617
+ }
2618
+
2619
+ function renderGenericToolCall(name: string, args: any, theme: Theme, ctx: any): Text {
2620
+ ctx.state._openAiPatchFiles = []
2621
+ const sp = (path: string) => shortPath(ctx.cwd ?? process.cwd(), path)
2622
+ if (isMcpToolName(name)) {
2623
+ // For MCP calls the summary may already contain ANSI color codes (muted
2624
+ // for the args suffix) so we build the header line directly instead of
2625
+ // passing it through toolHeader() which would re-wrap everything in accent.
2626
+ // The cache key includes expanded state so ctrl+o triggers a full re-render.
2627
+ const expanded = !!ctx.expanded
2628
+ const cacheKey = `_mcpLabelSummary:${expanded ? 1 : 0}`
2629
+ const packed = stableCallSummary(ctx, cacheKey, () => {
2630
+ const ls = mcpCallLabelAndSummary(args, theme, expanded)
2631
+ return `${ls.label}\x00${ls.summary}`
2632
+ })
2633
+ const sepIdx = packed.indexOf("\x00")
2634
+ const mcpLabel = sepIdx >= 0 ? packed.slice(0, sepIdx) : "MCP"
2635
+ const mcpSummary = sepIdx >= 0 ? packed.slice(sepIdx + 1) : ""
2636
+ const dot = toolStatusDot(ctx, theme)
2637
+ const labelPart = theme.fg("toolTitle", theme.bold(mcpLabel))
2638
+ const header = mcpSummary ? `${dot}${labelPart} ${WRAP_MARK}${mcpSummary}` : `${dot}${labelPart}`
2639
+ return makeText(ctx.lastComponent, header)
2640
+ }
2641
+ const summary = stableCallSummary(ctx, "_callSummary", () => summarizeGenericToolCall(name, args, theme, sp))
2642
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
2643
+ return makeText(ctx.lastComponent, toolHeader(genericToolLabel(name), summary, theme, toolStatusDot(ctx, theme), timer))
2644
+ }
2645
+
2646
+ function renderGenericToolResult(name: string, result: any, options: any, theme: Theme, ctx: any): Text {
2647
+ if (isMcpToolName(name)) {
2648
+ return renderMcpToolResult(result, !!options?.expanded, !!options?.isPartial, theme, ctx)
2649
+ }
2650
+ return renderOpenAiToolResult(
2651
+ name,
2652
+ { content: result.content, details: result.details },
2653
+ !!options?.expanded,
2654
+ !!options?.isPartial,
2655
+ theme,
2656
+ ctx,
2657
+ )
2658
+ }
2659
+
2660
+ function getTextContent(result: any): string {
2661
+ if (!Array.isArray(result?.content)) return ""
2662
+ return result.content
2663
+ .filter((block: any) => block?.type === "text" && typeof block.text === "string")
2664
+ .map((block: any) => block.text)
2665
+ .join("\n")
2666
+ }
2667
+
2668
+ function getStringArg(args: any, ...keys: string[]): string {
2669
+ for (const key of keys) {
2670
+ const value = args?.[key]
2671
+ if (typeof value === "string" && value.trim()) return value.trim()
2672
+ }
2673
+ return ""
2674
+ }
2675
+
2676
+ function getStringArrayArg(args: any, ...keys: string[]): string[] {
2677
+ for (const key of keys) {
2678
+ const value = args?.[key]
2679
+ if (!Array.isArray(value)) continue
2680
+ const items = value.filter((item): item is string => typeof item === "string" && item.trim().length > 0)
2681
+ if (items.length > 0) return items
2682
+ }
2683
+ return []
2684
+ }
2685
+
2686
+ function extractApplyPatchFiles(patchText: string): string[] {
2687
+ if (!patchText) return []
2688
+ const files = new Set<string>()
2689
+ for (const match of patchText.matchAll(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/gm)) {
2690
+ const filePath = match[1]?.trim()
2691
+ if (filePath) files.add(filePath)
2692
+ }
2693
+ return [...files]
2694
+ }
2695
+
2696
+ interface ApplyPatchChangePreview {
2697
+ kind: "add" | "update" | "delete"
2698
+ path: string
2699
+ displayPath: string
2700
+ moveTo?: string
2701
+ diff: ParsedDiff
2702
+ language: BundledLanguage | undefined
2703
+ hunks: number
2704
+ summary: string
2705
+ line: number
2706
+ }
2707
+
2708
+ interface ApplyPatchPreview {
2709
+ changes: ApplyPatchChangePreview[]
2710
+ totalAdded: number
2711
+ totalRemoved: number
2712
+ totalHunks: number
2713
+ totalLines: number
2714
+ summary: string
2715
+ }
2716
+
2717
+ interface ApplyPatchResultMeta {
2718
+ changeCount: number
2719
+ totalAdded: number
2720
+ totalRemoved: number
2721
+ totalHunks: number
2722
+ totalLines: number
2723
+ firstChange?: {
2724
+ displayPath: string
2725
+ kind: ApplyPatchChangePreview["kind"]
2726
+ hunks: number
2727
+ line: number
2728
+ added: number
2729
+ removed: number
2730
+ }
2731
+ }
2732
+
2733
+ function buildApplyPatchResultMeta(preview: ApplyPatchPreview): ApplyPatchResultMeta {
2734
+ const firstChange = preview.changes[0]
2735
+ return {
2736
+ changeCount: preview.changes.length,
2737
+ totalAdded: preview.totalAdded,
2738
+ totalRemoved: preview.totalRemoved,
2739
+ totalHunks: preview.totalHunks,
2740
+ totalLines: preview.totalLines,
2741
+ firstChange: firstChange
2742
+ ? {
2743
+ displayPath: firstChange.displayPath,
2744
+ kind: firstChange.kind,
2745
+ hunks: firstChange.hunks,
2746
+ line: firstChange.line,
2747
+ added: firstChange.diff.added,
2748
+ removed: firstChange.diff.removed,
2749
+ }
2750
+ : undefined,
2751
+ }
2752
+ }
2753
+
2754
+ function countDiffHunks(diff: ParsedDiff): number {
2755
+ return diff.lines.length === 0 ? 0 : diff.lines.filter((line) => line.type === "sep").length + 1
2756
+ }
2757
+
2758
+ function getApplyPatchLine(diff: ParsedDiff, kind: ApplyPatchChangePreview["kind"]): number {
2759
+ if (kind === "add") {
2760
+ return diff.lines.find((line) => line.type === "add" && line.newNum !== null)?.newNum ?? 1
2761
+ }
2762
+ if (kind === "delete") {
2763
+ return diff.lines.find((line) => line.type === "del" && line.oldNum !== null)?.oldNum ?? 1
2764
+ }
2765
+ for (const line of diff.lines) {
2766
+ if (line.type === "add" && line.newNum !== null) return line.newNum
2767
+ if (line.type === "del" && line.oldNum !== null) return line.oldNum
2768
+ }
2769
+ return 0
2770
+ }
2771
+
2772
+ function parsePatchBodyLine(rawLine: string): { marker: "+" | "-" | " "; content: string } {
2773
+ const marker = rawLine[0]
2774
+ if (marker === "+" || marker === "-" || marker === " ") return { marker, content: rawLine.slice(1) }
2775
+ return { marker: " ", content: rawLine }
2776
+ }
2777
+
2778
+ function findLineSequence(haystack: string[], needle: string[], fromIndex = 0): number {
2779
+ if (needle.length === 0) return Math.max(0, fromIndex)
2780
+ outer: for (let i = Math.max(0, fromIndex); i <= haystack.length - needle.length; i++) {
2781
+ for (let j = 0; j < needle.length; j++) {
2782
+ if (haystack[i + j] !== needle[j]) continue outer
2783
+ }
2784
+ return i
2785
+ }
2786
+ return -1
2787
+ }
2788
+
2789
+ function inferApplyPatchHunkStarts(
2790
+ lines: string[],
2791
+ sourceContent: string,
2792
+ ): Array<{ oldStart: number | null; newStart: number | null }> {
2793
+ const sourceLines = normalizeToLf(sourceContent).split("\n")
2794
+ const hunks: string[][] = []
2795
+ let currentHunk: string[] | null = null
2796
+ for (const rawLine of lines) {
2797
+ if (rawLine.startsWith("*** Move to: ")) continue
2798
+ if (rawLine.startsWith("@@")) {
2799
+ if (currentHunk) hunks.push(currentHunk)
2800
+ currentHunk = []
2801
+ continue
2802
+ }
2803
+ if (!currentHunk) currentHunk = []
2804
+ currentHunk.push(rawLine)
2805
+ }
2806
+ if (currentHunk) hunks.push(currentHunk)
2807
+
2808
+ const starts: Array<{ oldStart: number | null; newStart: number | null }> = []
2809
+ let searchFrom = 0
2810
+ let lineDelta = 0
2811
+ for (const hunk of hunks) {
2812
+ const oldLines = hunk
2813
+ .map((rawLine) => parsePatchBodyLine(rawLine))
2814
+ .filter((line) => line.marker !== "+")
2815
+ .map((line) => line.content)
2816
+ let matchIndex = findLineSequence(sourceLines, oldLines, searchFrom)
2817
+ if (matchIndex === -1) matchIndex = findLineSequence(sourceLines, oldLines, 0)
2818
+ const oldStart = matchIndex === -1 ? null : matchIndex + 1
2819
+ const newStart = oldStart === null ? null : oldStart + lineDelta
2820
+ starts.push({ oldStart, newStart })
2821
+ if (matchIndex === -1) continue
2822
+ searchFrom = matchIndex + oldLines.length
2823
+ const added = hunk.filter((rawLine) => parsePatchBodyLine(rawLine).marker === "+").length
2824
+ const removed = hunk.filter((rawLine) => parsePatchBodyLine(rawLine).marker === "-").length
2825
+ lineDelta += added - removed
2826
+ }
2827
+ return starts
2828
+ }
2829
+
2830
+ function stripPatchLinePrefix(line: string, prefix: "+" | "-"): string {
2831
+ return line.startsWith(prefix) ? line.slice(1) : line
2832
+ }
2833
+
2834
+ function trimDiffSeparators(lines: DiffLine[]): DiffLine[] {
2835
+ const trimmed = [...lines]
2836
+ while (trimmed[0]?.type === "sep") trimmed.shift()
2837
+ while (trimmed[trimmed.length - 1]?.type === "sep") trimmed.pop()
2838
+ return trimmed
2839
+ }
2840
+
2841
+ function parseApplyPatchUpdateDiff(lines: string[], sourceContent?: string): ParsedDiff {
2842
+ const diffLines: DiffLine[] = []
2843
+ let added = 0
2844
+ let removed = 0
2845
+ let chars = 0
2846
+ let oldLine: number | null = null
2847
+ let newLine: number | null = null
2848
+ let inHunk = false
2849
+ const inferredStarts = sourceContent ? inferApplyPatchHunkStarts(lines, sourceContent) : []
2850
+ let hunkIndex = 0
2851
+
2852
+ for (const rawLine of lines) {
2853
+ if (rawLine.startsWith("*** Move to: ")) continue
2854
+ if (rawLine.startsWith("@@")) {
2855
+ if (diffLines.length > 0 && diffLines[diffLines.length - 1]?.type !== "sep") {
2856
+ diffLines.push({ type: "sep", oldNum: null, newNum: null, content: "" })
2857
+ }
2858
+ const match = rawLine.match(/^@@\s*-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s*@@/)
2859
+ const inferred = inferredStarts[hunkIndex] ?? { oldStart: null, newStart: null }
2860
+ oldLine = match ? Number.parseInt(match[1], 10) : inferred.oldStart
2861
+ newLine = match ? Number.parseInt(match[2], 10) : inferred.newStart
2862
+ hunkIndex++
2863
+ inHunk = true
2864
+ continue
2865
+ }
2866
+ if (rawLine === "\") continue
2867
+ if (!inHunk) {
2868
+ const inferred = inferredStarts[hunkIndex] ?? { oldStart: null, newStart: null }
2869
+ oldLine = inferred.oldStart
2870
+ newLine = inferred.newStart
2871
+ hunkIndex++
2872
+ inHunk = true
2873
+ }
2874
+
2875
+ const { marker, content } = parsePatchBodyLine(rawLine)
2876
+
2877
+ chars += content.length
2878
+ if (marker === "+") {
2879
+ diffLines.push({ type: "add", oldNum: null, newNum: newLine, content })
2880
+ added++
2881
+ if (newLine !== null) newLine++
2882
+ continue
2883
+ }
2884
+ if (marker === "-") {
2885
+ diffLines.push({ type: "del", oldNum: oldLine, newNum: null, content })
2886
+ removed++
2887
+ if (oldLine !== null) oldLine++
2888
+ continue
2889
+ }
2890
+ diffLines.push({ type: "ctx", oldNum: oldLine, newNum: newLine, content })
2891
+ if (oldLine !== null) oldLine++
2892
+ if (newLine !== null) newLine++
2893
+ }
2894
+
2895
+ return {
2896
+ lines: trimDiffSeparators(diffLines),
2897
+ added,
2898
+ removed,
2899
+ chars,
2900
+ }
2901
+ }
2902
+
2903
+ function parseApplyPatchPreview(
2904
+ patchText: string,
2905
+ sp: (path: string) => string,
2906
+ cwd = process.cwd(),
2907
+ ): ApplyPatchPreview {
2908
+ const normalized = patchText.replace(/\r\n/g, "\n")
2909
+ const lines = normalized.split("\n")
2910
+ const changes: ApplyPatchChangePreview[] = []
2911
+ let index = 0
2912
+
2913
+ const fileHeader = /^\*\*\* (Add|Update|Delete) File: (.+)$/
2914
+ const endHeader = /^\*\*\* End Patch$/
2915
+
2916
+ while (index < lines.length) {
2917
+ const line = lines[index]
2918
+ if (!line || line === "*** Begin Patch") {
2919
+ index++
2920
+ continue
2921
+ }
2922
+ if (endHeader.test(line)) break
2923
+ const header = line.match(fileHeader)
2924
+ if (!header) {
2925
+ index++
2926
+ continue
2927
+ }
2928
+
2929
+ const kind = header[1].toLowerCase() as ApplyPatchChangePreview["kind"]
2930
+ const path = header[2].trim()
2931
+ index++
2932
+
2933
+ let moveTo: string | undefined
2934
+ const body: string[] = []
2935
+ while (index < lines.length && !fileHeader.test(lines[index]) && !endHeader.test(lines[index])) {
2936
+ if (lines[index].startsWith("*** Move to: ")) {
2937
+ moveTo = lines[index].slice("*** Move to: ".length).trim()
2938
+ index++
2939
+ continue
2940
+ }
2941
+ body.push(lines[index])
2942
+ index++
2943
+ }
2944
+
2945
+ const displayPath = moveTo ? `${sp(path)} ${BORDER_COLOR}→${TRANSPARENT_RESET} ${sp(moveTo)}` : sp(path)
2946
+ let sourceContent: string | undefined
2947
+ if (kind === "update") {
2948
+ try {
2949
+ sourceContent = readFileSync(resolve(cwd, path), "utf8")
2950
+ } catch {
2951
+ sourceContent = undefined
2952
+ }
2953
+ }
2954
+ const diff =
2955
+ kind === "add"
2956
+ ? parseDiff("", body.map((entry) => stripPatchLinePrefix(entry, "+")).join("\n"))
2957
+ : kind === "delete"
2958
+ ? parseDiff(body.map((entry) => stripPatchLinePrefix(entry, "-")).join("\n"), "")
2959
+ : parseApplyPatchUpdateDiff(body, sourceContent)
2960
+ changes.push({
2961
+ kind,
2962
+ path,
2963
+ displayPath,
2964
+ moveTo,
2965
+ diff,
2966
+ language: lang(moveTo || path),
2967
+ hunks: countDiffHunks(diff),
2968
+ summary: summarizeDiff(diff.added, diff.removed),
2969
+ line: getApplyPatchLine(diff, kind),
2970
+ })
2971
+ }
2972
+
2973
+ const totalAdded = changes.reduce((sum, change) => sum + change.diff.added, 0)
2974
+ const totalRemoved = changes.reduce((sum, change) => sum + change.diff.removed, 0)
2975
+ const totalHunks = changes.reduce((sum, change) => sum + change.hunks, 0)
2976
+ const totalLines = changes.reduce((sum, change) => sum + change.diff.lines.length, 0)
2977
+ return {
2978
+ changes,
2979
+ totalAdded,
2980
+ totalRemoved,
2981
+ totalHunks,
2982
+ totalLines,
2983
+ summary: summarizeDiff(totalAdded, totalRemoved),
2984
+ }
2985
+ }
2986
+
2987
+ function describeApplyPatchChange(change: ApplyPatchChangePreview): string {
2988
+ if (change.moveTo) return `Rename ${change.displayPath}`
2989
+ if (change.kind === "add") return `Create ${change.displayPath}`
2990
+ if (change.kind === "delete") return `Delete ${change.displayPath}`
2991
+ return `Update ${change.displayPath}`
2992
+ }
2993
+
2994
+ function formatLineMeta(line: number, theme: Theme): string {
2995
+ return line > 0 ? ` ${theme.fg("muted", `at line ${line}`)}` : ""
2996
+ }
2997
+
2998
+ function formatApplyPatchLine(change: ApplyPatchChangePreview, theme: Theme): string {
2999
+ return formatLineMeta(change.line, theme)
3000
+ }
3001
+
3002
+ function getCachedApplyPatchPreview(
3003
+ patchText: string,
3004
+ sp: (path: string) => string,
3005
+ ctx: any,
3006
+ ): ApplyPatchPreview | null {
3007
+ if (!patchText) return null
3008
+ const key = `apply-meta:${ctx.cwd ?? process.cwd()}:${hashText(patchText)}`
3009
+ if (ctx.state?._applyPatchMetaKey === key && ctx.state._applyPatchPreview) {
3010
+ return ctx.state._applyPatchPreview as ApplyPatchPreview
3011
+ }
3012
+ try {
3013
+ const preview = parseApplyPatchPreview(patchText, sp, ctx.cwd ?? process.cwd())
3014
+ if (ctx.state) {
3015
+ ctx.state._applyPatchMetaKey = key
3016
+ ctx.state._applyPatchPreview = preview
3017
+ ctx.state._applyPatchMeta = buildApplyPatchResultMeta(preview)
3018
+ }
3019
+ return preview
3020
+ } catch {
3021
+ return null
3022
+ }
3023
+ }
3024
+
3025
+ function getApplyPatchResultMeta(args: any, ctx: any, sp: (path: string) => string): ApplyPatchResultMeta | null {
3026
+ const patchText = getStringArg(args ?? ctx?.args, "patchText", "patch_text")
3027
+ if (!patchText) return null
3028
+ const preview = getCachedApplyPatchPreview(patchText, sp, ctx)
3029
+ return preview && ctx.state?._applyPatchMeta ? (ctx.state._applyPatchMeta as ApplyPatchResultMeta) : null
3030
+ }
3031
+
3032
+ function renderApplyPatchCall(args: any, theme: Theme, ctx: any, sp: (path: string) => string): Text {
3033
+ const patchText = getStringArg(args, "patchText", "patch_text")
3034
+ const summary = stableCallSummary(ctx, "_callSummary", () => summarizeOpenAiToolCall("apply_patch", args, theme, sp))
3035
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
3036
+ const hdr = toolHeader("Apply Patch", summary, theme, toolStatusDot(ctx, theme), timer)
3037
+
3038
+ if (!ctx.argsComplete) return makeText(ctx.lastComponent, hdr)
3039
+ const preview = getCachedApplyPatchPreview(patchText, sp, ctx)
3040
+ if (!preview || preview.changes.length === 0) {
3041
+ ctx.state._openAiPatchFiles = []
3042
+ return makeText(ctx.lastComponent, hdr)
3043
+ }
3044
+ ctx.state._openAiPatchFiles = preview.changes.map((change) => change.displayPath)
3045
+
3046
+ const diffWidth = branchDiffWidth()
3047
+ const key = `apply-preview:${ctx.state._applyPatchMetaKey ?? hashText(patchText)}:${diffWidth}:${ctx.expanded ? 1 : 0}`
3048
+ if (ctx.state._applyPatchPreviewKey !== key) {
3049
+ ctx.state._applyPatchPreviewKey = key
3050
+ ctx.state._applyPatchPreviewBody = theme.fg("muted", "(rendering…)")
3051
+ ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
3052
+ const dc = resolveDiffColors(theme)
3053
+ if (preview.changes.length === 1) {
3054
+ const [change] = preview.changes
3055
+ renderSplit(change.diff, change.language, ctx.expanded ? MAX_PREVIEW_LINES : 32, dc, diffWidth)
3056
+ .then((rendered) => {
3057
+ if (ctx.state._applyPatchPreviewKey !== key) return
3058
+ ctx.state._applyPatchPreviewBody = `${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}\n${rendered}`
3059
+ ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
3060
+ ctx.invalidate()
3061
+ })
3062
+ .catch(() => {
3063
+ if (ctx.state._applyPatchPreviewKey !== key) return
3064
+ ctx.state._applyPatchPreviewBody = `${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}`
3065
+ ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
3066
+ ctx.invalidate()
3067
+ })
3068
+ } else {
3069
+ const maxShown = ctx.expanded ? preview.changes.length : Math.min(preview.changes.length, 3)
3070
+ const previewLines = ctx.expanded
3071
+ ? Math.max(6, Math.floor(MAX_RENDER_LINES / Math.max(1, maxShown)))
3072
+ : Math.max(8, Math.floor(MAX_PREVIEW_LINES / Math.max(1, maxShown)))
3073
+ Promise.all(
3074
+ preview.changes.slice(0, maxShown).map((change, index) =>
3075
+ renderSplit(change.diff, change.language, previewLines, dc, diffWidth)
3076
+ .then(
3077
+ (rendered) =>
3078
+ `${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}\n${rendered}`,
3079
+ )
3080
+ .catch(
3081
+ () =>
3082
+ `${index + 1}. ${describeApplyPatchChange(change)} ${change.summary}${formatApplyPatchLine(change, theme)}`,
3083
+ ),
3084
+ ),
3085
+ )
3086
+ .then((sections) => {
3087
+ if (ctx.state._applyPatchPreviewKey !== key) return
3088
+ const remainder = preview.changes.length - maxShown
3089
+ const suffix =
3090
+ remainder > 0
3091
+ ? `\n${theme.fg("muted", `… ${remainder} more file patches${ctx.expanded ? "" : " • ctrl+o to expand"}`)}`
3092
+ : ""
3093
+ const summary = `${preview.changes.length} files ${preview.summary}`
3094
+ ctx.state._applyPatchPreviewBody = `${summary}\n\n${sections.join("\n\n")}${suffix}`
3095
+ ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
3096
+ ctx.invalidate()
3097
+ })
3098
+ .catch(() => {
3099
+ if (ctx.state._applyPatchPreviewKey !== key) return
3100
+ ctx.state._applyPatchPreviewBody = `${preview.changes.length} files ${preview.summary}`
3101
+ ctx.state._applyPatchPreviewDisplay = withBranch(ctx.state._applyPatchPreviewBody, theme, false, true)
3102
+ ctx.invalidate()
3103
+ })
3104
+ }
3105
+ }
3106
+
3107
+ const body = ctx.state._applyPatchPreviewDisplay as string | undefined
3108
+ return makeText(ctx.lastComponent, body ? `${hdr}\n${body}` : hdr)
3109
+ }
3110
+
3111
+ function renderApplyPatchResult(result: any, isPartial: boolean, theme: Theme, ctx: any): Text {
3112
+ if (isPartial) {
3113
+ setupBlinkTimer(ctx)
3114
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Applying Patch..."), theme))
3115
+ }
3116
+ clearBlinkTimer(ctx)
3117
+
3118
+ if (ctx.isError) {
3119
+ const raw = getTextContent(result).trim()
3120
+ const firstLine = raw ? raw.split("\n")[0] : "Apply patch failed"
3121
+ return makeText(ctx.lastComponent, withBranch(theme.fg("error", firstLine), theme))
3122
+ }
3123
+
3124
+ const meta = getApplyPatchResultMeta(ctx.args, ctx, (path: string) => shortPath(ctx.cwd ?? process.cwd(), path))
3125
+ if (!meta || meta.changeCount === 0) {
3126
+ return makeText(ctx.lastComponent, withBranch(theme.fg("success", "Applied"), theme))
3127
+ }
3128
+
3129
+ if (meta.changeCount === 1 && meta.firstChange) {
3130
+ const change = meta.firstChange
3131
+ const summary = diffSummaryWithMeta(
3132
+ change.added,
3133
+ change.removed,
3134
+ change.hunks,
3135
+ change.kind === "add" ? "new file" : change.kind === "delete" ? "delete" : "",
3136
+ )
3137
+ return makeText(
3138
+ ctx.lastComponent,
3139
+ withBranch(
3140
+ `${theme.fg("success", "Applied")} ${theme.fg("muted", change.displayPath)} ${summary}${formatLineMeta(change.line, theme)}`,
3141
+ theme,
3142
+ ),
3143
+ )
3144
+ }
3145
+
3146
+ const summary = diffSummaryWithMeta(meta.totalAdded, meta.totalRemoved, meta.totalHunks, "")
3147
+ return makeText(
3148
+ ctx.lastComponent,
3149
+ withBranch(
3150
+ `${theme.fg("success", "Applied")} ${meta.changeCount} files ${summary}${meta.totalLines ? ` ${theme.fg("muted", `(${meta.totalLines} diff lines)`)}` : ""}`,
3151
+ theme,
3152
+ ),
3153
+ )
3154
+ }
3155
+
3156
+ /** Max chars shown for a single arg value before truncation. */
3157
+ const MCP_ARG_VALUE_MAX = 60
3158
+ /** Max total chars for the entire (key=val, …) suffix. */
3159
+ const MCP_ARGS_SUFFIX_MAX = 120
3160
+
3161
+ /**
3162
+ * Keys whose values are typically long blobs (file paths list, prompt text,
3163
+ * raw content). These get truncated more aggressively or skipped when many
3164
+ * other keys are present.
3165
+ */
3166
+
3167
+ /**
3168
+ * For an MCP gateway call whose args contain `tool`, parse the nested args
3169
+ * JSON and return a compact `(key=val, key=val)` style plain string (no ANSI),
3170
+ * matching the style used by the `read` tool for offset/limit.
3171
+ *
3172
+ * When `expanded` is false (collapsed view) long values are truncated and the
3173
+ * whole suffix is capped at MCP_ARGS_SUFFIX_MAX chars so the header stays on
3174
+ * one line. When `expanded` is true all values are shown in full.
3175
+ */
3176
+ export function summarizeMcpToolInvocationArgs(args: any, expanded = false): string {
3177
+ const rawArgs = getStringArg(args, "args")
3178
+ if (!rawArgs) return ""
3179
+ try {
3180
+ const parsed = JSON.parse(rawArgs)
3181
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return ""
3182
+
3183
+ const parts: string[] = []
3184
+ // Always use original key order — collapsed mode just stops at the cap.
3185
+ const ordered = Object.entries(parsed as Record<string, unknown>)
3186
+ for (const [key, val] of ordered) {
3187
+ if (val === undefined || val === null) continue
3188
+ let display: string
3189
+ if (Array.isArray(val)) {
3190
+ if (val.length === 0) continue
3191
+ if (expanded) {
3192
+ display = val.map((v) => String(v)).join(", ")
3193
+ } else {
3194
+ const first = String(val[0])
3195
+ display =
3196
+ val.length === 1
3197
+ ? summarizeText(first, MCP_ARG_VALUE_MAX)
3198
+ : `${summarizeText(first, 30)} +${val.length - 1}`
3199
+ }
3200
+ } else if (typeof val === "object") {
3201
+ continue // skip nested objects
3202
+ } else {
3203
+ display = expanded ? String(val) : summarizeText(String(val), MCP_ARG_VALUE_MAX)
3204
+ }
3205
+ const part = `${key}=${display}`
3206
+ // In collapsed mode stop adding parts if we'd exceed the suffix cap.
3207
+ if (!expanded) {
3208
+ const currentLen = parts.reduce((n, p) => n + p.length + 2, 0)
3209
+ if (currentLen + part.length > MCP_ARGS_SUFFIX_MAX) break
3210
+ }
3211
+ parts.push(part)
3212
+ }
3213
+
3214
+ if (parts.length === 0) return ""
3215
+ return `(${parts.join(", ")})`
3216
+ } catch {
3217
+ // not valid JSON — ignore
3218
+ }
3219
+ return ""
3220
+ }
3221
+
3222
+ function summarizeMcpToolCall(args: any, theme: Theme, expanded = false): string {
3223
+ const tool = getStringArg(args, "tool")
3224
+ if (tool) {
3225
+ const argsSummary = summarizeMcpToolInvocationArgs(args, expanded)
3226
+ return argsSummary ? theme.fg("muted", argsSummary) : ""
3227
+ }
3228
+ const connect = getStringArg(args, "connect")
3229
+ if (connect) return connect
3230
+ const search = getStringArg(args, "search", "describe", "server", "action")
3231
+ if (search) return summarizeText(search, 72)
3232
+ return theme.fg("muted", "status")
3233
+ }
3234
+
3235
+ /**
3236
+ * Returns the display label and summary for an MCP gateway call.
3237
+ * - Tool invocation (`args.tool` present): label = humanized tool name, summary = args preview
3238
+ * - Discovery (`args.search` / `args.describe` / …): label = "Tool search" / "Tool describe" / …
3239
+ * - Connect: label = "Tool connect"
3240
+ */
3241
+ export function mcpCallLabelAndSummary(
3242
+ args: any,
3243
+ theme: Theme,
3244
+ expanded = false,
3245
+ ): { label: string; summary: string } {
3246
+ const tool = getStringArg(args, "tool")
3247
+ if (tool) {
3248
+ const server = getStringArg(args, "server")
3249
+ const toolDisplay = tool.replace(/_/g, " ")
3250
+ const label = server ? `${server} - ${toolDisplay}` : toolDisplay
3251
+ const rawSuffix = summarizeMcpToolInvocationArgs(args, expanded)
3252
+ const summary = rawSuffix ? theme.fg("muted", rawSuffix) : ""
3253
+ return { label, summary }
3254
+ }
3255
+ if (getStringArg(args, "connect")) {
3256
+ return { label: "Tool connect", summary: theme.fg("muted", `(server=${getStringArg(args, "connect")})`) }
3257
+ }
3258
+ if (getStringArg(args, "describe")) {
3259
+ return { label: "Tool describe", summary: theme.fg("muted", `(tool=${summarizeText(getStringArg(args, "describe"), 60)})`) }
3260
+ }
3261
+ if (getStringArg(args, "search")) {
3262
+ return { label: "Tool search", summary: theme.fg("muted", `(query=${summarizeText(getStringArg(args, "search"), 60)})`) }
3263
+ }
3264
+ if (getStringArg(args, "server")) {
3265
+ return { label: "Tool search", summary: theme.fg("muted", `(server=${summarizeText(getStringArg(args, "server"), 60)})`) }
3266
+ }
3267
+ if (getStringArg(args, "action")) {
3268
+ return { label: "Tool action", summary: theme.fg("muted", `(action=${summarizeText(getStringArg(args, "action"), 60)})`) }
3269
+ }
3270
+ return { label: "MCP", summary: theme.fg("muted", "(status)") }
3271
+ }
3272
+
3273
+ function summarizeGenericToolCall(name: string, args: any, theme: Theme, sp: (path: string) => string): string {
3274
+ if (isMcpToolName(name)) return summarizeMcpToolCall(args, theme)
3275
+ return summarizeOpenAiToolCall(name, args, theme, sp)
3276
+ }
3277
+
3278
+ function renderMcpToolResult(result: any, expanded: boolean, isPartial: boolean, theme: Theme, ctx: any): Text {
3279
+ if (isPartial) {
3280
+ setupBlinkTimer(ctx)
3281
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "MCP running..."), theme))
3282
+ }
3283
+ clearBlinkTimer(ctx)
3284
+
3285
+ const mode = getMode(readSettings().mcpOutputMode, ["hidden", "summary", "preview"] as const, "preview")
3286
+ if (mode === "hidden") return makeText(ctx.lastComponent, "")
3287
+
3288
+ const raw = getTextContent(result).trim()
3289
+ const lines = raw ? raw.split("\n") : []
3290
+ if (lines.length === 0) {
3291
+ return makeText(
3292
+ ctx.lastComponent,
3293
+ withBranch(theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Done"), theme),
3294
+ )
3295
+ }
3296
+
3297
+ const statusText = ctx.isError
3298
+ ? theme.fg("error", lines[0])
3299
+ : theme.fg("muted", `${lines.length} line${lines.length === 1 ? "" : "s"} returned`)
3300
+ if (mode === "summary") return makeText(ctx.lastComponent, withBranch(statusText, theme))
3301
+ if (!expanded && !ctx.isError)
3302
+ return makeText(ctx.lastComponent, withBranch(`${statusText}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
3303
+ const preview = buildPreviewText(
3304
+ lines.map((line) => theme.fg(ctx.isError ? "error" : "toolOutput", line || " ")),
3305
+ true,
3306
+ theme,
3307
+ previewLimit(),
3308
+ )
3309
+ return makeText(ctx.lastComponent, withBranch(`${statusText}\n${preview}`, theme))
3310
+ }
3311
+
3312
+ export function summarizeOpenAiToolCall(name: string, args: any, theme: Theme, sp: (path: string) => string): string {
3313
+ switch (name) {
3314
+ case "apply_patch": {
3315
+ const patchText = getStringArg(args, "patchText", "patch_text")
3316
+ const files = extractApplyPatchFiles(patchText)
3317
+ if (files.length === 0) return theme.fg("muted", "patch")
3318
+ if (files.length === 1) return sp(files[0])
3319
+ return `${sp(files[0])} ${theme.fg("muted", `(+${files.length - 1} files)`)}`
3320
+ }
3321
+ case "webfetch":
3322
+ return getStringArg(args, "url") || theme.fg("muted", "fetch page")
3323
+ case "fetch_content": {
3324
+ const url = getStringArg(args, "url")
3325
+ if (url) return url
3326
+ const urls = getStringArrayArg(args, "urls")
3327
+ if (urls.length === 0) return theme.fg("muted", "fetch content")
3328
+ if (urls.length === 1) return urls[0]
3329
+ return `${urls[0]} ${theme.fg("muted", `(+${urls.length - 1} urls)`)}`
3330
+ }
3331
+ case "get_search_content":
3332
+ return getStringArg(args, "responseId", "response_id") || theme.fg("muted", "load cached content")
3333
+ case "web_search": {
3334
+ const query = getStringArg(args, "query")
3335
+ if (query) return summarizeText(query, 72)
3336
+ const queries = getStringArrayArg(args, "queries")
3337
+ if (queries.length === 0) return theme.fg("muted", "search web")
3338
+ if (queries.length === 1) return summarizeText(queries[0], 72)
3339
+ return `${summarizeText(queries[0], 48)} ${theme.fg("muted", `(+${queries.length - 1} queries)`)}`
3340
+ }
3341
+ case "code_search":
3342
+ return summarizeText(getStringArg(args, "query") || "search code", 72)
3343
+ case "question":
3344
+ return summarizeText(getStringArg(args, "question") || "ask user", 72)
3345
+ case "questionnaire": {
3346
+ const qs = Array.isArray(args?.questions) ? (args.questions as Array<Record<string, unknown>>) : []
3347
+ if (qs.length === 0) return theme.fg("muted", "questionnaire")
3348
+ let firstText = ""
3349
+ for (const key of ["question", "prompt", "text"]) {
3350
+ const value = qs[0]?.[key]
3351
+ if (typeof value === "string") {
3352
+ firstText = value
3353
+ break
3354
+ }
3355
+ }
3356
+ if (!firstText) return `${qs.length} question${qs.length === 1 ? "" : "s"}`
3357
+ if (qs.length === 1) return summarizeText(firstText, 72)
3358
+ return `${summarizeText(firstText, 48)} ${theme.fg("muted", `(+${qs.length - 1} more)`)}`
3359
+ }
3360
+ case "context_tag":
3361
+ return getStringArg(args, "name") || theme.fg("muted", "save point")
3362
+ case "context_log":
3363
+ return theme.fg("muted", "history")
3364
+ case "context_checkout":
3365
+ return getStringArg(args, "target") || theme.fg("muted", "checkout context")
3366
+ case "annotate":
3367
+ return getStringArg(args, "url") || theme.fg("muted", "current tab")
3368
+ case "alpha_search":
3369
+ return summarizeText(getStringArg(args, "query") || "search papers", 72)
3370
+ case "alpha_get_paper":
3371
+ case "alpha_ask_paper":
3372
+ case "alpha_annotate_paper":
3373
+ return getStringArg(args, "paper") || theme.fg("muted", "paper")
3374
+ case "alpha_read_code":
3375
+ return getStringArg(args, "githubUrl", "github_url") || theme.fg("muted", "repository")
3376
+ case "Skill":
3377
+ // SkillToolSchema accepts both 'skill' (primary) and 'name' (alias for Claude Code compat).
3378
+ // The adapter passes 'skill'; direct tool calls may pass either. Check both before falling back.
3379
+ return getStringArg(args, "skill") || getStringArg(args, "name") || theme.fg("muted", "run skill")
3380
+ case "EnterPlanMode":
3381
+ return theme.fg("muted", "enable read-only planning")
3382
+ case "ExitPlanMode":
3383
+ return theme.fg("muted", "present plan")
3384
+ case "set_phase":
3385
+ return getStringArg(args, "phase") || theme.fg("muted", "set phase")
3386
+ case "Agent":
3387
+ return summarizeText(getStringArg(args, "description", "prompt") || "launch agent", 72)
3388
+ case "get_subagent_result":
3389
+ return getStringArg(args, "agent_id") || theme.fg("muted", "agent result")
3390
+ case "steer_subagent":
3391
+ return getStringArg(args, "agent_id") || theme.fg("muted", "steer agent")
3392
+ case "TaskCreate":
3393
+ return summarizeText(getStringArg(args, "subject") || "create task", 72)
3394
+ case "TaskList":
3395
+ return theme.fg("muted", "task list")
3396
+ case "TaskGet":
3397
+ case "TaskUpdate":
3398
+ return getStringArg(args, "taskId", "task_id") || theme.fg("muted", "task")
3399
+ case "TaskOutput":
3400
+ case "TaskStop":
3401
+ return getStringArg(args, "task_id", "taskId") || theme.fg("muted", "background task")
3402
+ case "TaskExecute": {
3403
+ const taskIds = getStringArrayArg(args, "task_ids", "taskIds")
3404
+ if (taskIds.length === 0) return theme.fg("muted", "start tasks")
3405
+ return taskIds.length === 1 ? taskIds[0] : `${taskIds[0]} ${theme.fg("muted", `(+${taskIds.length - 1} tasks)`)}`
3406
+ }
3407
+ default:
3408
+ return summarizeText(
3409
+ getStringArg(args, "path", "file_path", "url", "query", "name", "subject", "tool", "description", "prompt") ||
3410
+ humanizeToolName(name),
3411
+ 72,
3412
+ )
3413
+ }
3414
+ }
3415
+
3416
+ interface ParsedTaskListLine {
3417
+ id: string
3418
+ status: string
3419
+ subject: string
3420
+ }
3421
+
3422
+ function parseTaskListLine(line: string): ParsedTaskListLine | null {
3423
+ const match = line.match(/^#(\d+) \[([^\]]+)\] (.+)$/)
3424
+ if (!match) return null
3425
+ return {
3426
+ id: match[1],
3427
+ status: match[2],
3428
+ subject: match[3],
3429
+ }
3430
+ }
3431
+
3432
+ function formatTaskStatus(status: string, theme: Theme): string {
3433
+ if (status === "completed") return theme.fg("success", status)
3434
+ if (status === "in_progress") return theme.fg("warning", status)
3435
+ return theme.fg("muted", status)
3436
+ }
3437
+
3438
+ function formatOpenAiSuccessLine(name: string, line: string, theme: Theme): string {
3439
+ const trimmed = line.trim()
3440
+ if (!trimmed) return theme.fg("success", "Done")
3441
+
3442
+ if (name === "TaskCreate") {
3443
+ const match = trimmed.match(/^Task #(\d+) created successfully: (.+)$/)
3444
+ if (match) {
3445
+ return `${theme.fg("success", "Created task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`
3446
+ }
3447
+ }
3448
+
3449
+ if (name === "TaskUpdate") {
3450
+ const match = trimmed.match(/^Updated task #(\d+) (.+)$/)
3451
+ if (match) {
3452
+ return `${theme.fg("success", "Updated task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`
3453
+ }
3454
+ }
3455
+
3456
+ if (name === "TaskExecute") {
3457
+ return `${theme.fg("success", "Started")} ${theme.fg("muted", trimmed)}`
3458
+ }
3459
+
3460
+ if (name === "context_tag") {
3461
+ const match = trimmed.match(/^Created tag '([^']+)' at (.+)$/)
3462
+ if (match) {
3463
+ return `${theme.fg("success", "Created tag")} ${theme.fg("accent", match[1])} ${theme.fg("muted", match[2])}`
3464
+ }
3465
+ }
3466
+
3467
+ if (name === "context_checkout") {
3468
+ return `${theme.fg("success", "Checked out")} ${theme.fg("muted", trimmed.replace(/^Checked out\s*/i, ""))}`
3469
+ }
3470
+
3471
+ if (name === "TaskStop") {
3472
+ return `${theme.fg("success", "Stopped")} ${theme.fg("muted", trimmed)}`
3473
+ }
3474
+
3475
+ return theme.fg("muted", trimmed)
3476
+ }
3477
+
3478
+ function renderTaskListResult(lines: string[], expanded: boolean, theme: Theme, ctx: any): Text {
3479
+ const tasks = lines.map(parseTaskListLine).filter((task): task is ParsedTaskListLine => task !== null)
3480
+ if (tasks.length === 0) {
3481
+ const text =
3482
+ lines.length === 0
3483
+ ? theme.fg("muted", "no tasks")
3484
+ : buildPreviewText(
3485
+ lines.map((line) => theme.fg("dim", line)),
3486
+ expanded,
3487
+ theme,
3488
+ previewLimit(),
3489
+ )
3490
+ return makeText(ctx.lastComponent, withBranch(text, theme))
3491
+ }
3492
+
3493
+ const pending = tasks.filter((task) => task.status === "pending").length
3494
+ const inProgress = tasks.filter((task) => task.status === "in_progress").length
3495
+ const completed = tasks.filter((task) => task.status === "completed").length
3496
+ let summary = theme.fg("muted", `${tasks.length} tasks`)
3497
+ const parts: string[] = []
3498
+ if (inProgress > 0) parts.push(`${theme.fg("warning", String(inProgress))} in progress`)
3499
+ if (pending > 0) parts.push(`${theme.fg("muted", String(pending))} pending`)
3500
+ if (completed > 0) parts.push(`${theme.fg("success", String(completed))} completed`)
3501
+ if (parts.length > 0) summary += ` ${theme.fg("muted", "•")} ${parts.join(` ${theme.fg("muted", "•")} `)}`
3502
+
3503
+ if (!expanded) {
3504
+ return makeText(ctx.lastComponent, withBranch(`${summary}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
3505
+ }
3506
+
3507
+ const shown = tasks.slice(0, previewLimit())
3508
+ const preview = shown.map(
3509
+ (task) =>
3510
+ `${theme.fg("accent", `#${task.id}`)} ${formatTaskStatus(task.status, theme)} ${theme.fg("dim", task.subject)}`,
3511
+ )
3512
+ const remaining = tasks.length - shown.length
3513
+ if (remaining > 0) preview.push(theme.fg("muted", `… ${remaining} more tasks`))
3514
+ return makeText(ctx.lastComponent, withBranch(`${summary}\n${preview.join("\n")}`, theme))
3515
+ }
3516
+
3517
+ function getFirstImageBlock(result: any): { data: string; mimeType: string } | undefined {
3518
+ if (!Array.isArray(result?.content)) return undefined
3519
+ return result.content.find(
3520
+ (block: any) => block?.type === "image" && typeof block.data === "string" && typeof block.mimeType === "string",
3521
+ )
3522
+ }
3523
+
3524
+ function getReadImageFallback(result: any, ctx: any): string {
3525
+ const image = getFirstImageBlock(result)
3526
+ if (!image) return ""
3527
+ let dimensions
3528
+ try {
3529
+ dimensions = getImageDimensions(image.data, image.mimeType) ?? undefined
3530
+ } catch {
3531
+ dimensions = undefined
3532
+ }
3533
+ const path = getStringArg(ctx.args, "path", "file_path")
3534
+ const filename = path ? shortPath(ctx.cwd ?? process.cwd(), path) : undefined
3535
+ return imageFallback(image.mimeType, dimensions, filename)
3536
+ }
3537
+
3538
+ function renderReadImageResult(result: any, expanded: boolean, theme: Theme, ctx: any): Text {
3539
+ const image = getFirstImageBlock(result)
3540
+ const mimeType = image?.mimeType ?? "image"
3541
+ const summary = `${theme.fg("success", "Image loaded")} ${theme.fg("muted", `[${mimeType}]`)}`
3542
+ if (!expanded) {
3543
+ return makeText(ctx.lastComponent, withBranch(`${summary}${theme.fg("muted", " • ctrl+o to show")}`, theme))
3544
+ }
3545
+
3546
+ const noteLines = getTextContent(result)
3547
+ .split("\n")
3548
+ .map((line) => line.trim())
3549
+ .filter((line) => line && !/^Read image file\b/i.test(line))
3550
+ const lines = [summary, ...noteLines.map((line) => theme.fg("dim", line))]
3551
+ if (!getCapabilities().images || !ctx.showImages) {
3552
+ const fallback = getReadImageFallback(result, ctx)
3553
+ if (fallback) lines.push(theme.fg("toolOutput", fallback))
3554
+ }
3555
+ return makeText(ctx.lastComponent, withBranch(lines.join("\n"), theme))
3556
+ }
3557
+
3558
+ function renderOpenAiToolResult(
3559
+ name: string,
3560
+ result: any,
3561
+ expanded: boolean,
3562
+ isPartial: boolean,
3563
+ theme: Theme,
3564
+ ctx: any,
3565
+ ): Text {
3566
+ if (isPartial) {
3567
+ setupBlinkTimer(ctx)
3568
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", `${humanizeToolName(name)}...`), theme))
3569
+ }
3570
+ clearBlinkTimer(ctx)
3571
+
3572
+ const raw = getTextContent(result).trim()
3573
+ const lines = raw ? raw.split("\n") : []
3574
+ const patchFiles = Array.isArray(ctx.state?._openAiPatchFiles) ? ctx.state._openAiPatchFiles : []
3575
+
3576
+ if (lines.length === 0) {
3577
+ if (patchFiles.length > 0) {
3578
+ const suffix = patchFiles.length === 1 ? patchFiles[0] : `${patchFiles.length} files`
3579
+ return makeText(
3580
+ ctx.lastComponent,
3581
+ withBranch(
3582
+ `${theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Applied")} ${theme.fg("muted", suffix)}`,
3583
+ theme,
3584
+ ),
3585
+ )
3586
+ }
3587
+ return makeText(
3588
+ ctx.lastComponent,
3589
+ withBranch(theme.fg(ctx.isError ? "error" : "success", ctx.isError ? "Failed" : "Done"), theme),
3590
+ )
3591
+ }
3592
+
3593
+ if (!ctx.isError && name === "TaskList") {
3594
+ return renderTaskListResult(lines, expanded, theme, ctx)
3595
+ }
3596
+
3597
+ const statusText = ctx.isError
3598
+ ? theme.fg("error", lines[0])
3599
+ : theme.fg("muted", `${lines.length} line${lines.length === 1 ? "" : "s"} returned`)
3600
+ if (!expanded && !ctx.isError) {
3601
+ return makeText(ctx.lastComponent, withBranch(`${statusText}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
3602
+ }
3603
+
3604
+ if (!ctx.isError && lines.length === 1) {
3605
+ return makeText(ctx.lastComponent, withBranch(formatOpenAiSuccessLine(name, lines[0], theme), theme))
3606
+ }
3607
+
3608
+ const preview =
3609
+ lines.length === 1
3610
+ ? theme.fg(ctx.isError ? "error" : "dim", lines[0])
3611
+ : buildPreviewText(
3612
+ lines.map((line) => theme.fg(ctx.isError ? "error" : "dim", line || " ")),
3613
+ true,
3614
+ theme,
3615
+ previewLimit(),
3616
+ )
3617
+ return makeText(ctx.lastComponent, withBranch(`${statusText}\n${preview}`, theme))
3618
+ }
3619
+
3620
+ // ===========================================================================
3621
+ // Extension
3622
+ // ===========================================================================
3623
+
3624
+ export default function (pi: ExtensionAPI) {
3625
+ patchToolRenderCacheInvalidation()
3626
+ patchReadImageExpansion()
3627
+ patchGlobalToolBorders()
3628
+ patchToolExecutionRenderers()
3629
+ patchUserMessageRender()
3630
+ patchAssistantMessageRender()
3631
+ applyDiffPalette()
3632
+ registerThinkingLabels(pi)
3633
+
3634
+ // /cc-tools command — toggle tool border style at runtime
3635
+ const TOOL_MODES = ["outlines", "transparent", "default"] as const
3636
+ pi.registerCommand("cc-tools", {
3637
+ description:
3638
+ "Switch tool display style: outlines (lines around tools), transparent (no chrome), default (pi built-in backgrounds)",
3639
+ getArgumentCompletions(prefix) {
3640
+ return TOOL_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({
3641
+ value: m,
3642
+ label: m,
3643
+ description:
3644
+ m === "outlines"
3645
+ ? "Horizontal rules around each tool (default)"
3646
+ : m === "transparent"
3647
+ ? "No borders or backgrounds"
3648
+ : "Pi built-in tool backgrounds",
3649
+ }))
3650
+ },
3651
+ async handler(args, ctx) {
3652
+ const mode = args.trim().toLowerCase()
3653
+ if (!mode) {
3654
+ if (ctx.hasUI) ctx.ui.notify(`Tool style: ${toolBackgroundMode}`, "info")
3655
+ return
3656
+ }
3657
+ if (!(TOOL_MODES as readonly string[]).includes(mode)) {
3658
+ if (ctx.hasUI) ctx.ui.notify(`Unknown mode "${mode}". Options: ${TOOL_MODES.join(", ")}`, "error")
3659
+ return
3660
+ }
3661
+ toolBackgroundOverride = mode as typeof toolBackgroundMode
3662
+ toolBackgroundMode = toolBackgroundOverride
3663
+ writeSettingsKey("toolBackground", mode)
3664
+ if (ctx.hasUI) {
3665
+ applyToolBackgroundMode(ctx.ui.theme)
3666
+ ctx.ui.notify(`Tool style → ${mode}`, "info")
3667
+ }
3668
+ },
3669
+ })
3670
+
3671
+ // /cc-theme command — toggle pi-theme-adaptive coloring at runtime.
3672
+ const THEME_MODES = ["on", "off", "toggle", "status"] as const
3673
+ pi.registerCommand("cc-theme", {
3674
+ description: "Toggle whether tool borders / branch rules / diff colors follow the active pi theme",
3675
+ getArgumentCompletions(prefix) {
3676
+ return THEME_MODES.filter((m) => m.startsWith(prefix)).map((m) => ({
3677
+ value: m,
3678
+ label: m,
3679
+ description:
3680
+ m === "on"
3681
+ ? "Derive borders, branch rules, dim text and diff tints from the active pi theme (default)"
3682
+ : m === "off"
3683
+ ? "Keep the fixed Claude-style palette regardless of theme"
3684
+ : m === "toggle"
3685
+ ? "Flip between on and off"
3686
+ : "Show the current setting and a preview of the derived colors",
3687
+ }))
3688
+ },
3689
+ async handler(args, ctx) {
3690
+ const raw = args.trim().toLowerCase()
3691
+ const current = themeAdaptiveEnabled()
3692
+
3693
+ if (!raw || raw === "status") {
3694
+ if (!ctx.hasUI) return
3695
+ const theme = ctx.ui.theme as any
3696
+ const themeName = theme?.name ?? "unknown"
3697
+ const state = current ? "on" : "off"
3698
+ if (raw === "status" && current) {
3699
+ const settings = readSettings()
3700
+ const verbKey = settings.spinnerVerbColor || "borderAccent"
3701
+ const statusKey = settings.spinnerStatusColor || "muted"
3702
+ const verbAnsi = safeFgAnsi(theme, verbKey) ?? safeFgAnsi(theme, "accent")
3703
+ const statusAnsi = safeFgAnsi(theme, statusKey) ?? safeFgAnsi(theme, "muted")
3704
+ // Print a short preview of what we derived.
3705
+ const preview = [
3706
+ `borders : ${safeFgAnsi(theme, "borderMuted") ? `${safeFgAnsi(theme, "borderMuted")}────\x1b[39m` : "(unchanged)"}`,
3707
+ `branches : ${(safeFgAnsi(theme, "dim") ?? safeFgAnsi(theme, "muted")) ? `${safeFgAnsi(theme, "dim") ?? safeFgAnsi(theme, "muted")}├─ └─\x1b[39m` : "(unchanged)"}`,
3708
+ `muted text : ${safeFgAnsi(theme, "muted") ? `${safeFgAnsi(theme, "muted")}example dim text\x1b[39m` : "(unchanged)"}`,
3709
+ `diff add : ${safeFgAnsi(theme, "toolDiffAdded") ? `${safeFgAnsi(theme, "toolDiffAdded")}+ added line\x1b[39m` : "(unchanged)"}`,
3710
+ `diff del : ${safeFgAnsi(theme, "toolDiffRemoved") ? `${safeFgAnsi(theme, "toolDiffRemoved")}- removed line\x1b[39m` : "(unchanged)"}`,
3711
+ `spinner verb: ${verbAnsi ? `${verbAnsi}Cooking…\x1b[39m` : "(unchanged)"} (key: ${verbKey})`,
3712
+ `spinner stat: ${statusAnsi ? `${statusAnsi}(thinking · ↓ 10 tokens · 2s)\x1b[39m` : "(unchanged)"} (key: ${statusKey})`,
3713
+ ].join("\n ")
3714
+ ctx.ui.notify(`Theme adaptive: ${state} (theme "${themeName}")\n ${preview}`, "info")
3715
+ } else {
3716
+ ctx.ui.notify(`Theme adaptive: ${state} (theme "${themeName}")`, "info")
3717
+ }
3718
+ return
3719
+ }
3720
+
3721
+ let next: boolean
3722
+ if (raw === "on") next = true
3723
+ else if (raw === "off") next = false
3724
+ else if (raw === "toggle") next = !current
3725
+ else {
3726
+ if (ctx.hasUI) ctx.ui.notify(`Unknown option "${raw}". Options: ${THEME_MODES.join(", ")}`, "error")
3727
+ return
3728
+ }
3729
+
3730
+ writeSettingsKey("themeAdaptive", next)
3731
+ bustSpinnerSettingsCache()
3732
+ // Invalidate caches so the next render re-derives from the active
3733
+ // theme (or falls back to the fixed Claude palette).
3734
+ _themePaletteCacheTheme = null
3735
+ autoDerivePending = true
3736
+ if (next) {
3737
+ if (ctx.hasUI) applyThemePaletteIfNeeded(ctx.ui.theme)
3738
+ } else {
3739
+ resetThemePalette()
3740
+ }
3741
+ if (ctx.hasUI) {
3742
+ const label = next ? "on — colors follow pi theme" : "off — fixed Claude palette"
3743
+ ctx.ui.notify(`Theme adaptive: ${label}`, "info")
3744
+ }
3745
+ },
3746
+ })
3747
+
3748
+ // /cc-spinner command — pick which theme color keys drive the spinner verb
3749
+ // and status suffix.
3750
+ const COMMON_COLOR_KEYS: readonly string[] = [
3751
+ "accent",
3752
+ "borderAccent",
3753
+ "success",
3754
+ "error",
3755
+ "warning",
3756
+ "muted",
3757
+ "dim",
3758
+ "text",
3759
+ "thinkingText",
3760
+ "toolTitle",
3761
+ "mdHeading",
3762
+ "mdCode",
3763
+ "mdLink",
3764
+ "mdListBullet",
3765
+ "bashMode",
3766
+ "thinkingLow",
3767
+ "thinkingMedium",
3768
+ "thinkingHigh",
3769
+ "thinkingXhigh",
3770
+ "syntaxKeyword",
3771
+ "syntaxFunction",
3772
+ "syntaxString",
3773
+ "syntaxType",
3774
+ ]
3775
+ pi.registerCommand("cc-spinner", {
3776
+ description: "Set the spinner verb or status theme color, or preview current values",
3777
+ getArgumentCompletions(prefix) {
3778
+ const subCommands = ["verb", "status", "reset", "preview"]
3779
+ const parts = prefix.split(/\s+/)
3780
+ if (parts.length <= 1) {
3781
+ return subCommands
3782
+ .filter((c) => c.startsWith(parts[0] ?? ""))
3783
+ .map((c) => ({
3784
+ value: c,
3785
+ label: c,
3786
+ description:
3787
+ c === "verb"
3788
+ ? "Set the color key used for the spinner verb (e.g. 'Cooking…')"
3789
+ : c === "status"
3790
+ ? "Set the color key used for the spinner status suffix"
3791
+ : c === "reset"
3792
+ ? "Reset both verb and status to defaults (borderAccent, muted)"
3793
+ : "Preview every theme color key with its current sample",
3794
+ }))
3795
+ }
3796
+ // Second arg: color key completions for verb/status.
3797
+ if (parts[0] === "verb" || parts[0] === "status") {
3798
+ const keyPrefix = (parts[1] ?? "").toLowerCase()
3799
+ return COMMON_COLOR_KEYS.filter((k) => k.toLowerCase().startsWith(keyPrefix)).map((k) => ({
3800
+ value: k,
3801
+ label: k,
3802
+ description: `theme.fg("${k}", …)`,
3803
+ }))
3804
+ }
3805
+ return []
3806
+ },
3807
+ async handler(args, ctx) {
3808
+ const parts = args
3809
+ .trim()
3810
+ .split(/\s+/)
3811
+ .filter((p) => p.length > 0)
3812
+ const sub = (parts[0] ?? "").toLowerCase()
3813
+ const theme = ctx.hasUI ? ctx.ui.theme : null
3814
+ const settings = readSettings()
3815
+ const currentVerb = settings.spinnerVerbColor || "borderAccent"
3816
+ const currentStatus = settings.spinnerStatusColor || "muted"
3817
+
3818
+ if (!sub || sub === "preview") {
3819
+ if (!ctx.hasUI) return
3820
+ if (!theme) {
3821
+ ctx.ui.notify(`Spinner verb: ${currentVerb}, status: ${currentStatus} (no theme)`, "info")
3822
+ return
3823
+ }
3824
+ const lines: string[] = [
3825
+ `Current: verb=${currentVerb}, status=${currentStatus}`,
3826
+ "",
3827
+ "Preview of common theme keys (pick one for verb or status):",
3828
+ ]
3829
+ for (const key of COMMON_COLOR_KEYS) {
3830
+ const ansi = safeFgAnsi(theme, key)
3831
+ const marker = key === currentVerb ? "(verb)" : key === currentStatus ? "(status)" : ""
3832
+ const sample = ansi ? `${ansi}Cooking…\x1b[39m` : "(unmapped)"
3833
+ lines.push(` ${key.padEnd(16)} ${sample} ${marker}`)
3834
+ }
3835
+ ctx.ui.notify(lines.join("\n"), "info")
3836
+ return
3837
+ }
3838
+
3839
+ if (sub === "reset") {
3840
+ writeSettingsKey("spinnerVerbColor", undefined)
3841
+ writeSettingsKey("spinnerStatusColor", undefined)
3842
+ bustSpinnerSettingsCache()
3843
+ if (ctx.hasUI) ctx.ui.notify("Spinner colors reset to defaults (verb=borderAccent, status=muted)", "info")
3844
+ return
3845
+ }
3846
+
3847
+ if (sub !== "verb" && sub !== "status") {
3848
+ if (ctx.hasUI) ctx.ui.notify(`Usage: /cc-spinner verb <key> | status <key> | reset | preview`, "error")
3849
+ return
3850
+ }
3851
+
3852
+ const key = parts[1]
3853
+ if (!key) {
3854
+ if (ctx.hasUI) ctx.ui.notify(`Missing color key. Try /cc-spinner preview to see available keys.`, "error")
3855
+ return
3856
+ }
3857
+
3858
+ // Validate the key resolves to *some* color in the active theme;
3859
+ // accept anyway if the user insists so themes with custom keys work.
3860
+ const ansi = theme ? safeFgAnsi(theme, key) : null
3861
+ const settingKey = sub === "verb" ? "spinnerVerbColor" : "spinnerStatusColor"
3862
+ writeSettingsKey(settingKey, key)
3863
+ bustSpinnerSettingsCache()
3864
+ if (ctx.hasUI) {
3865
+ const sample = ansi ? `${ansi}sample\x1b[39m` : "(key unmapped in current theme)"
3866
+ ctx.ui.notify(`Spinner ${sub} → ${key} ${sample}`, "info")
3867
+ }
3868
+ },
3869
+ })
3870
+
3871
+ pi.on("session_start", async (_event, ctx) => {
3872
+ if (!ctx.hasUI) return
3873
+ applyToolBackgroundMode(ctx.ui.theme)
3874
+ applyThemePaletteIfNeeded(ctx.ui.theme)
3875
+ })
3876
+
3877
+ pi.on("turn_start", async (_event, ctx) => {
3878
+ if (!ctx.hasUI) return
3879
+ applyToolBackgroundMode(ctx.ui.theme)
3880
+ applyThemePaletteIfNeeded(ctx.ui.theme)
3881
+ })
3882
+
3883
+ const cwd = process.cwd()
3884
+ const sp = (path: string) => shortPath(cwd, path)
3885
+
3886
+ const readTool = createReadTool(cwd)
3887
+ pi.registerTool({
3888
+ name: "read",
3889
+ label: "read",
3890
+ description: readTool.description,
3891
+ parameters: readTool.parameters,
3892
+ async execute(toolCallId, params, signal, onUpdate) {
3893
+ return readTool.execute(toolCallId, params, signal, onUpdate)
3894
+ },
3895
+ renderCall(args, theme, ctx) {
3896
+ const summary = stableCallSummary(ctx, "_callSummary", () => {
3897
+ let value = sp(args.path ?? "")
3898
+ if (args.offset || args.limit) {
3899
+ const parts: string[] = []
3900
+ if (args.offset) parts.push(`offset=${args.offset}`)
3901
+ if (args.limit) parts.push(`limit=${args.limit}`)
3902
+ value += ` ${theme.fg("muted", `(${parts.join(", ")})`)}`
3903
+ }
3904
+ return value
3905
+ })
3906
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
3907
+ return makeText(ctx.lastComponent, toolHeader("Read", summary, theme, toolStatusDot(ctx, theme), timer))
3908
+ },
3909
+ renderResult(result, { expanded, isPartial }, theme, ctx) {
3910
+ if (isPartial) {
3911
+ setupBlinkTimer(ctx)
3912
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Reading..."), theme))
3913
+ }
3914
+ clearBlinkTimer(ctx)
3915
+ if (getFirstImageBlock(result)) return renderReadImageResult(result, expanded, theme, ctx)
3916
+ const details = result.details as ReadToolDetails | undefined
3917
+ const content = result.content.find((block: any) => block?.type === "text")
3918
+ if (content?.type !== "text")
3919
+ return makeText(ctx.lastComponent, withBranch(theme.fg("error", "No text content"), theme))
3920
+ const lines = content.text.split("\n")
3921
+ if (ctx.isError) {
3922
+ const header = theme.fg("muted", `${lines.length} lines loaded`)
3923
+ const body = lines.map((line) => theme.fg("error", line || " ")).join("\n")
3924
+ return makeText(ctx.lastComponent, withBranch(`${header}\n${body}`, theme))
3925
+ }
3926
+ let text = theme.fg("muted", `${lines.length} lines loaded`)
3927
+ if (details?.truncation?.truncated) text += theme.fg("warning", " (truncated)")
3928
+ if (!expanded)
3929
+ return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
3930
+ const shown = lines.slice(0, previewLimit())
3931
+ text += `\n${buildPreviewText(
3932
+ shown.map((line) => theme.fg("dim", line || " ")),
3933
+ false,
3934
+ theme,
3935
+ previewLimit(),
3936
+ )}`
3937
+ return makeText(ctx.lastComponent, withBranch(text, theme))
3938
+ },
3939
+ })
3940
+
3941
+ const bashTool = createBashTool(cwd)
3942
+ pi.registerTool({
3943
+ name: "bash",
3944
+ label: "bash",
3945
+ description: bashTool.description,
3946
+ parameters: bashTool.parameters,
3947
+ async execute(toolCallId, params, signal, onUpdate) {
3948
+ return bashTool.execute(toolCallId, params, signal, onUpdate)
3949
+ },
3950
+ renderCall(args, theme, ctx) {
3951
+ const command = getBashCommandForDisplay(args.command) ?? args.command
3952
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
3953
+ if (ctx.expanded && command) {
3954
+ // Expanded: show the tool name + timer on line 1, then the full
3955
+ // command (with real newlines) as a continued branch block below.
3956
+ const hdr = toolHeader("Bash", "", theme, toolStatusDot(ctx, theme), timer)
3957
+ const cmdBlock = withBranch(command.split("\n").map((l) => theme.fg("accent", l)).join("\n"), theme, false, true)
3958
+ return makeText(ctx.lastComponent, `${hdr}\n${cmdBlock}`)
3959
+ }
3960
+ const summary = summarizeText(command, 72)
3961
+ return makeText(ctx.lastComponent, toolHeader("Bash", summary, theme, toolStatusDot(ctx, theme), timer))
3962
+ },
3963
+ renderResult(result, { expanded, isPartial }, theme, ctx) {
3964
+ const details = result.details as BashToolDetails | undefined
3965
+ const output = result.content[0]?.type === "text" ? result.content[0].text : ""
3966
+ const nonEmpty = output.split("\n").filter((line) => line.trim().length > 0)
3967
+ if (isPartial) {
3968
+ setupBlinkTimer(ctx)
3969
+ return makeText(
3970
+ ctx.lastComponent,
3971
+ withBranch(theme.fg("warning", `Running... (${nonEmpty.length} lines)`), theme),
3972
+ )
3973
+ }
3974
+ clearBlinkTimer(ctx)
3975
+ const exitMatch = output.match(/exit code: (\d+)/)
3976
+ const exitCode = exitMatch ? Number.parseInt(exitMatch[1], 10) : null
3977
+ const isExitError = exitCode !== null && exitCode !== 0
3978
+ const isError = ctx.isError || isExitError
3979
+ let text = isError
3980
+ ? theme.fg("error", exitCode != null ? `Exit ${exitCode}` : "Failed")
3981
+ : theme.fg("success", "Done")
3982
+ text += theme.fg("muted", ` (${nonEmpty.length} lines)`)
3983
+ if (details?.truncation?.truncated) text += theme.fg("warning", " [truncated]")
3984
+ if (!expanded && !isError && nonEmpty.length > 0)
3985
+ return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
3986
+ if (!expanded && !isError) return makeText(ctx.lastComponent, withBranch(text, theme))
3987
+ const collapsed = bashCollapsedLimit()
3988
+ text += `\n${buildPreviewText(
3989
+ nonEmpty.map((line) => theme.fg("dim", line)),
3990
+ expanded,
3991
+ theme,
3992
+ collapsed,
3993
+ )}`
3994
+ return makeText(ctx.lastComponent, withBranch(text, theme))
3995
+ },
3996
+ })
3997
+
3998
+ const grepTool = createGrepTool(cwd)
3999
+ pi.registerTool({
4000
+ name: "grep",
4001
+ label: "grep",
4002
+ description: grepTool.description,
4003
+ parameters: grepTool.parameters,
4004
+ async execute(toolCallId, params, signal, onUpdate) {
4005
+ return grepTool.execute(toolCallId, params, signal, onUpdate)
4006
+ },
4007
+ renderCall(args, theme, ctx) {
4008
+ const summary = stableCallSummary(ctx, "_callSummary", () => {
4009
+ let value = `\"${summarizeText(args.pattern, 40)}\"`
4010
+ if (args.path) value += ` in ${args.path}`
4011
+ return value
4012
+ })
4013
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4014
+ return makeText(ctx.lastComponent, toolHeader("Grep", summary, theme, toolStatusDot(ctx, theme), timer))
4015
+ },
4016
+ renderResult(result, { expanded, isPartial }, theme, ctx) {
4017
+ if (isPartial) {
4018
+ setupBlinkTimer(ctx)
4019
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Searching..."), theme))
4020
+ }
4021
+ clearBlinkTimer(ctx)
4022
+ const details = result.details as GrepToolDetails | undefined
4023
+ const matches = (result.content[0]?.type === "text" ? result.content[0].text : "")
4024
+ .split("\n")
4025
+ .filter((line) => line.trim().length > 0)
4026
+ if (matches.length === 0) return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "no matches"), theme))
4027
+ let text = theme.fg("muted", `${matches.length} matches`)
4028
+ if (details?.truncation?.truncated) text += theme.fg("warning", " (truncated)")
4029
+ if (!expanded)
4030
+ return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
4031
+ text += `\n${buildPreviewText(
4032
+ matches.map((line) => theme.fg("dim", line)),
4033
+ false,
4034
+ theme,
4035
+ previewLimit(),
4036
+ )}`
4037
+ return makeText(ctx.lastComponent, withBranch(text, theme))
4038
+ },
4039
+ })
4040
+
4041
+ const findTool = createFindTool(cwd)
4042
+ pi.registerTool({
4043
+ name: "find",
4044
+ label: "find",
4045
+ description: findTool.description,
4046
+ parameters: findTool.parameters,
4047
+ async execute(toolCallId, params, signal, onUpdate) {
4048
+ return findTool.execute(toolCallId, params, signal, onUpdate)
4049
+ },
4050
+ renderCall(args, theme, ctx) {
4051
+ const summary = stableCallSummary(ctx, "_callSummary", () => {
4052
+ let value = `\"${summarizeText(args.pattern, 40)}\"`
4053
+ if (args.path) value += ` in ${args.path}`
4054
+ return value
4055
+ })
4056
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4057
+ return makeText(ctx.lastComponent, toolHeader("Find", summary, theme, toolStatusDot(ctx, theme), timer))
4058
+ },
4059
+ renderResult(result, { expanded, isPartial }, theme, ctx) {
4060
+ if (isPartial) {
4061
+ setupBlinkTimer(ctx)
4062
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Finding..."), theme))
4063
+ }
4064
+ clearBlinkTimer(ctx)
4065
+ const items = (result.content[0]?.type === "text" ? result.content[0].text : "")
4066
+ .split("\n")
4067
+ .filter((line) => line.trim().length > 0)
4068
+ if (items.length === 0) return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "no files found"), theme))
4069
+ let text = theme.fg("muted", `${items.length} files`)
4070
+ if (!expanded)
4071
+ return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
4072
+ // Expanded: grouped find results with icons
4073
+ const maxShow = previewLimit()
4074
+ const shown = items.slice(0, maxShow)
4075
+ const findLines: string[] = []
4076
+ for (let i = 0; i < shown.length; i++) {
4077
+ const item = shown[i].trim()
4078
+ const icon = fileIcon(item)
4079
+ findLines.push(` ${icon}${theme.fg("dim", item)}`)
4080
+ }
4081
+ const remaining = items.length - shown.length
4082
+ if (remaining > 0) {
4083
+ findLines.push(` ${theme.fg("muted", `… ${remaining} more files`)}`)
4084
+ }
4085
+ text += `\n${findLines.join("\n")}`
4086
+ return makeText(ctx.lastComponent, withBranch(text, theme))
4087
+ },
4088
+ })
4089
+
4090
+ const lsTool = createLsTool(cwd)
4091
+ pi.registerTool({
4092
+ name: "ls",
4093
+ label: "ls",
4094
+ description: lsTool.description,
4095
+ parameters: lsTool.parameters,
4096
+ async execute(toolCallId, params, signal, onUpdate) {
4097
+ return lsTool.execute(toolCallId, params, signal, onUpdate)
4098
+ },
4099
+ renderCall(args, theme, ctx) {
4100
+ const summary = stableCallSummary(ctx, "_callSummary", () => sp(args.path ?? "."))
4101
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4102
+ return makeText(ctx.lastComponent, toolHeader("List", summary, theme, toolStatusDot(ctx, theme), timer))
4103
+ },
4104
+ renderResult(result, { expanded, isPartial }, theme, ctx) {
4105
+ if (isPartial) {
4106
+ setupBlinkTimer(ctx)
4107
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Listing..."), theme))
4108
+ }
4109
+ clearBlinkTimer(ctx)
4110
+ const items = (result.content[0]?.type === "text" ? result.content[0].text : "")
4111
+ .split("\n")
4112
+ .filter((line) => line.trim().length > 0)
4113
+ if (items.length === 0)
4114
+ return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "empty directory"), theme))
4115
+ let text = theme.fg("muted", `${items.length} entries`)
4116
+ if (!expanded)
4117
+ return makeText(ctx.lastComponent, withBranch(`${text}${theme.fg("muted", " • ctrl+o to expand")}`, theme))
4118
+ // Expanded: tree-view with icons
4119
+ const maxShow = previewLimit()
4120
+ const shown = items.slice(0, maxShow)
4121
+ const treeLines: string[] = []
4122
+ for (let i = 0; i < shown.length; i++) {
4123
+ const item = shown[i]
4124
+ const isDir = item.endsWith("/")
4125
+ const isLast = i === shown.length - 1 && items.length <= maxShow
4126
+ const prefix = isLast ? `${FG_RULE}\u2514\u2500\u2500${D_RST} ` : `${FG_RULE}\u251c\u2500\u2500${D_RST} `
4127
+ const icon = isDir ? dirIcon() : fileIcon(item)
4128
+ const name = isDir ? theme.fg("accent", theme.bold(item)) : theme.fg("dim", item)
4129
+ treeLines.push(`${prefix}${icon}${name}`)
4130
+ }
4131
+ const remaining = items.length - shown.length
4132
+ if (remaining > 0) {
4133
+ treeLines.push(`${FG_RULE}\u2514\u2500\u2500${D_RST} ${theme.fg("muted", `\u2026 ${remaining} more entries`)}`)
4134
+ }
4135
+ text += `\n${treeLines.join("\n")}`
4136
+ return makeText(ctx.lastComponent, withBranch(text, theme))
4137
+ },
4138
+ })
4139
+
4140
+ const writeTool = createWriteTool(cwd)
4141
+ pi.registerTool({
4142
+ name: "write",
4143
+ label: "write",
4144
+ description: writeTool.description,
4145
+ parameters: writeTool.parameters,
4146
+ async execute(toolCallId, params, signal, onUpdate, _ctx) {
4147
+ const fp = params.path ?? (params as any).file_path ?? ""
4148
+ const fullPath = fp ? resolve(cwd, fp) : ""
4149
+ const existedBefore = !!fullPath && fileExistsForTool(cwd, fp)
4150
+ WRITE_EXISTED_BEFORE.set(toolCallId, existedBefore)
4151
+ let old: string | null = null
4152
+ try {
4153
+ if (fullPath && existedBefore) old = readFileSync(fullPath, "utf-8")
4154
+ } catch {
4155
+ old = null
4156
+ }
4157
+ const result = await writeTool.execute(toolCallId, params, signal, onUpdate)
4158
+ const content = params.content ?? ""
4159
+ if (old !== null && old !== content) {
4160
+ const diff = parseDiff(old, content)
4161
+ ;(result as any).details = {
4162
+ _type: "diff",
4163
+ summary: summarizeDiff(diff.added, diff.removed),
4164
+ diff,
4165
+ language: lang(fp),
4166
+ }
4167
+ } else if (old === null) {
4168
+ ;(result as any).details = { _type: "new", lines: lineCount(content), filePath: fp }
4169
+ } else if (old === content) {
4170
+ ;(result as any).details = { _type: "noChange" }
4171
+ }
4172
+ return result
4173
+ },
4174
+ renderCall(args, theme, ctx) {
4175
+ const fp = args?.path ?? (args as any)?.file_path ?? ""
4176
+ const revealSummary = shouldRevealCallArgs(ctx) || (!!fp && hasOwnArg(args, "content"))
4177
+ const wasNew = getWriteWasNewFile(ctx, cwd, fp, revealSummary)
4178
+ const label = wasNew === true ? "Create" : "Write"
4179
+ const summary = stableCallSummary(
4180
+ ctx,
4181
+ "_callSummary",
4182
+ () => {
4183
+ const base = sp(fp)
4184
+ return shouldRevealCallArgs(ctx)
4185
+ ? `${base} ${theme.fg("muted", `(${lineCount(args.content ?? "")} lines)`)}`
4186
+ : base
4187
+ },
4188
+ revealSummary,
4189
+ )
4190
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4191
+ const hdr = toolHeader(label, summary, theme, toolStatusDot(ctx, theme), timer)
4192
+ return makeText(ctx.lastComponent, hdr)
4193
+ },
4194
+ renderResult(result, { isPartial }, theme, ctx) {
4195
+ if (isPartial) {
4196
+ setupBlinkTimer(ctx)
4197
+ return makeText(ctx.lastComponent, withBranch(theme.fg("dim", "Writing..."), theme))
4198
+ }
4199
+ clearBlinkTimer(ctx)
4200
+ if (typeof ctx?.toolCallId === "string") WRITE_EXISTED_BEFORE.delete(ctx.toolCallId)
4201
+ if (ctx.isError) {
4202
+ const e =
4203
+ result.content
4204
+ ?.filter((c: any) => c.type === "text")
4205
+ .map((c: any) => c.text || "")
4206
+ .join("\n") ?? "Error"
4207
+ return makeText(ctx.lastComponent, withBranch(theme.fg("error", e), theme))
4208
+ }
4209
+ const d = (result as any).details
4210
+ if (d?._type === "diff") {
4211
+ const previewLines = ctx.expanded ? MAX_RENDER_LINES : diffCollapsedLimit()
4212
+ const hunks = d.diff?.lines?.filter((l: any) => l.type === "sep").length + (d.diff?.lines?.length ? 1 : 0)
4213
+ const diffWidth = branchDiffWidth()
4214
+ const mode = shouldUseSplit(d.diff, diffWidth, previewLines) ? "split" : "unified"
4215
+ const richSummary = diffSummaryWithMeta(d.diff.added, d.diff.removed, hunks, mode)
4216
+ const key = `wd:${diffWidth}:${d.summary}:${d.diff?.lines?.length ?? 0}:${d.language ?? ""}:${ctx.expanded ? 1 : 0}`
4217
+ if (ctx.state._wdk !== key) {
4218
+ ctx.state._wdk = key
4219
+ ctx.state._wdt = withFinalBranchBlock(`${richSummary}\n${theme.fg("muted", "rendering diff…")}`)
4220
+ const dc = resolveDiffColors(theme)
4221
+ renderSplit(d.diff, d.language, previewLines, dc, diffWidth)
4222
+ .then((rendered) => {
4223
+ if (ctx.state._wdk !== key) return
4224
+ ctx.state._wdt = withFinalBranchBlock(`${richSummary}\n${rendered}`)
4225
+ ctx.invalidate()
4226
+ })
4227
+ .catch(() => {
4228
+ if (ctx.state._wdk !== key) return
4229
+ ctx.state._wdt = withBranch(richSummary, theme)
4230
+ ctx.invalidate()
4231
+ })
4232
+ }
4233
+ return makeText(ctx.lastComponent, ctx.state._wdt ?? withBranch(richSummary, theme))
4234
+ }
4235
+ if (d?._type === "noChange")
4236
+ return makeText(ctx.lastComponent, withBranch(theme.fg("muted", "✓ no changes"), theme))
4237
+ if (d?._type === "new") {
4238
+ const content = typeof ctx.args?.content === "string" ? ctx.args.content : ""
4239
+ const lineTotal = typeof d.lines === "number" ? d.lines : lineCount(content)
4240
+ const contentHash = hashText(content)
4241
+ const syntheticDiff = getCachedParsedDiff(ctx, `nf-diff:${d.filePath}:${contentHash}`, "", content)
4242
+ const richSummary = diffSummaryWithMeta(syntheticDiff.added, 0, 1, "new file")
4243
+ const previewLines = ctx.expanded ? MAX_RENDER_LINES : diffCollapsedLimit()
4244
+ const diffWidth = branchDiffWidth()
4245
+ const pk = `nf:${d.filePath}:${contentHash}:${diffWidth}:${ctx.expanded ? 1 : 0}`
4246
+ if (ctx.state._nfk !== pk) {
4247
+ ctx.state._nfk = pk
4248
+ ctx.state._nft = withFinalBranchBlock(`${richSummary}\n${theme.fg("muted", "rendering diff…")}`)
4249
+ const dc = resolveDiffColors(theme)
4250
+ renderUnified(syntheticDiff, lang(d.filePath), previewLines, dc, diffWidth)
4251
+ .then((rendered) => {
4252
+ if (ctx.state._nfk !== pk) return
4253
+ ctx.state._nft = withFinalBranchBlock(`${richSummary}\n${rendered}`)
4254
+ ctx.invalidate()
4255
+ })
4256
+ .catch(() => {
4257
+ if (ctx.state._nfk !== pk) return
4258
+ ctx.state._nft = withBranch(`${richSummary} ${theme.fg("muted", `(${lineTotal} lines)`)}`, theme)
4259
+ ctx.invalidate()
4260
+ })
4261
+ }
4262
+ return makeText(
4263
+ ctx.lastComponent,
4264
+ ctx.state._nft ?? withBranch(`${richSummary} ${theme.fg("muted", `(${lineTotal} lines)`)}`, theme),
4265
+ )
4266
+ }
4267
+ return makeText(ctx.lastComponent, withBranch(theme.fg("success", "Written"), theme))
4268
+ },
4269
+ })
4270
+
4271
+ const editTool = createEditTool(cwd)
4272
+ pi.registerTool({
4273
+ name: "edit",
4274
+ label: "edit",
4275
+ description: editTool.description,
4276
+ parameters: editTool.parameters,
4277
+ async execute(toolCallId, params, signal, onUpdate, _ctx) {
4278
+ const fp = params.path ?? (params as any).file_path ?? ""
4279
+ const operations = getEditOperations(params)
4280
+ const localizedDiffs = operations.length === 1 ? await computeLocalizedEditDiffs(fp, operations, cwd) : null
4281
+ const result = await editTool.execute(toolCallId, params, signal, onUpdate)
4282
+ if (operations.length === 0) return result
4283
+ const { diffs, summary, totalLines, totalHunks } = summarizeEditOperations(operations)
4284
+ const baseDetails = ((result as any).details ?? {}) as Record<string, unknown>
4285
+ if (operations.length === 1) {
4286
+ const localized = localizedDiffs?.[0]
4287
+ const editLine =
4288
+ localized?.line ?? (typeof baseDetails.firstChangedLine === "number" ? baseDetails.firstChangedLine : 0)
4289
+ const diff = localized?.diff ?? diffs[0]
4290
+ ;(result as any).details = {
4291
+ ...baseDetails,
4292
+ _type: "editInfo",
4293
+ summary,
4294
+ editLine,
4295
+ hunks: countDiffHunks(diff),
4296
+ added: diff?.added ?? 0,
4297
+ removed: diff?.removed ?? 0,
4298
+ }
4299
+ return result
4300
+ }
4301
+ ;(result as any).details = {
4302
+ ...baseDetails,
4303
+ _type: "multiEditInfo",
4304
+ summary,
4305
+ editCount: operations.length,
4306
+ diffLineCount: totalLines,
4307
+ hunks: totalHunks,
4308
+ totalAdded: diffs.reduce((sum, diff) => sum + diff.added, 0),
4309
+ totalRemoved: diffs.reduce((sum, diff) => sum + diff.removed, 0),
4310
+ }
4311
+ return result
4312
+ },
4313
+ renderCall(args, theme, ctx) {
4314
+ const fp = args?.path ?? (args as any)?.file_path ?? ""
4315
+ const operations = getEditOperations(args)
4316
+ const revealSummary = shouldRevealCallArgs(ctx) || (!!fp && hasOwnArg(args, "edits"))
4317
+ const summary = stableCallSummary(
4318
+ ctx,
4319
+ "_callSummary",
4320
+ () =>
4321
+ shouldRevealCallArgs(ctx) && operations.length > 1
4322
+ ? `${sp(fp)} ${theme.fg("muted", `(${operations.length} edits)`)}`
4323
+ : sp(fp),
4324
+ revealSummary,
4325
+ )
4326
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4327
+ const hdr = toolHeader("Edit", summary, theme, ` ${toolStatusDot(ctx, theme)}`, timer)
4328
+ if (!(ctx.argsComplete && operations.length > 0)) return makeText(ctx.lastComponent, hdr)
4329
+ const diffWidth = branchDiffWidth()
4330
+ const key = `edit:${fp}:${hashText(operations.map((edit) => `${edit.oldText}\u0000${edit.newText}`).join("\u0001"))}:${diffWidth}:${ctx.expanded ? 1 : 0}`
4331
+ const { diffs: fallbackDiffs, summary: editSummary } = getCachedEditOperationSummary(ctx, key, operations)
4332
+ if (ctx.state._pk !== key) {
4333
+ ctx.state._pk = key
4334
+ ctx.state._ptBody = theme.fg("muted", "(rendering…)")
4335
+ ctx.state._ptDisplay = indentBranchBlock(withBranch(ctx.state._ptBody, theme, false, true))
4336
+ const lg = lang(fp)
4337
+ void computeLocalizedEditDiffs(fp, operations, cwd)
4338
+ .then((localizedDiffs) => {
4339
+ if (ctx.state._pk !== key) return
4340
+ const diffs = localizedDiffs?.map((entry) => entry.diff) ?? fallbackDiffs
4341
+ const lines =
4342
+ localizedDiffs?.map((entry) => entry.line) ?? diffs.map((diff) => getFirstChangedNewLine(diff))
4343
+ renderEditPreviewBody(ctx, key, theme, lg, operations, diffs, lines, editSummary)
4344
+ })
4345
+ .catch(() => {
4346
+ if (ctx.state._pk !== key) return
4347
+ renderEditPreviewBody(
4348
+ ctx,
4349
+ key,
4350
+ theme,
4351
+ lg,
4352
+ operations,
4353
+ fallbackDiffs,
4354
+ fallbackDiffs.map((diff) => getFirstChangedNewLine(diff)),
4355
+ editSummary,
4356
+ )
4357
+ })
4358
+ }
4359
+ const body = ctx.state._ptDisplay as string | undefined
4360
+ return makeText(ctx.lastComponent, body ? `${hdr}\n${body}` : hdr)
4361
+ },
4362
+ renderResult(result, { isPartial }, theme, ctx) {
4363
+ if (isPartial) {
4364
+ setupBlinkTimer(ctx)
4365
+ return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("dim", "Editing..."), theme)))
4366
+ }
4367
+ clearBlinkTimer(ctx)
4368
+ if (ctx.isError) {
4369
+ const e =
4370
+ result.content
4371
+ ?.filter((c: any) => c.type === "text")
4372
+ .map((c: any) => c.text || "")
4373
+ .join("\n") ?? "Error"
4374
+ return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("error", e), theme)))
4375
+ }
4376
+ if ((result as any).details?._type === "editInfo") {
4377
+ const { editLine, hunks, added, removed } = (result as any).details
4378
+ const loc = formatLineMeta(editLine ?? 0, theme)
4379
+ const summary = diffSummaryWithMeta(added ?? 0, removed ?? 0, hunks ?? 0, "")
4380
+ return makeText(ctx.lastComponent, indentBranchBlock(withBranch(`${summary}${loc}`, theme)))
4381
+ }
4382
+ if ((result as any).details?._type === "multiEditInfo") {
4383
+ const { editCount, diffLineCount, hunks, totalAdded, totalRemoved } = (result as any).details
4384
+ const summary = diffSummaryWithMeta(totalAdded ?? 0, totalRemoved ?? 0, hunks ?? 0, "")
4385
+ return makeText(
4386
+ ctx.lastComponent,
4387
+ indentBranchBlock(
4388
+ withBranch(
4389
+ `${editCount} edits ${summary}${typeof diffLineCount === "number" ? ` ${theme.fg("muted", `(${diffLineCount} diff lines)`)}` : ""}`,
4390
+ theme,
4391
+ ),
4392
+ ),
4393
+ )
4394
+ }
4395
+ return makeText(ctx.lastComponent, indentBranchBlock(withBranch(theme.fg("success", "Applied"), theme)))
4396
+ },
4397
+ })
4398
+
4399
+ const wrappedOpenAiTools = new Set<string>()
4400
+ const registerOpenAiToolOverrides = (): void => {
4401
+ let allTools: unknown[] = []
4402
+ try {
4403
+ allTools = typeof (pi as any).getAllTools === "function" ? (pi as any).getAllTools() : []
4404
+ } catch {
4405
+ allTools = []
4406
+ }
4407
+ for (const tool of allTools) {
4408
+ if (!isOpenAiToolCandidate(tool)) continue
4409
+ const record = tool as Record<string, unknown>
4410
+ const name = typeof record.name === "string" ? record.name : ""
4411
+ if (!name || wrappedOpenAiTools.has(name)) continue
4412
+ const execute = typeof record.execute === "function" ? (record.execute as any) : null
4413
+ if (!execute) continue
4414
+ const rawLabel = typeof record.label === "string" ? record.label.trim() : ""
4415
+ const label = rawLabel && rawLabel !== name && !rawLabel.includes("_") ? rawLabel : humanizeToolName(name)
4416
+ const description = typeof record.description === "string" ? record.description : label
4417
+ ;(pi as any).registerTool({
4418
+ name,
4419
+ label,
4420
+ description,
4421
+ parameters: record.parameters,
4422
+ prepareArguments: typeof record.prepareArguments === "function" ? record.prepareArguments : undefined,
4423
+ async execute(toolCallId: string, params: any, signal: AbortSignal | undefined, onUpdate: any, ctx: any) {
4424
+ return await Promise.resolve(execute(toolCallId, params, signal, onUpdate, ctx))
4425
+ },
4426
+ renderCall(args: any, theme: Theme, ctx: any) {
4427
+ if (name === "apply_patch") return renderApplyPatchCall(args, theme, ctx, sp)
4428
+ ctx.state._openAiPatchFiles = []
4429
+ const summary = stableCallSummary(ctx, "_callSummary", () => summarizeOpenAiToolCall(name, args, theme, sp))
4430
+ const timer = formatToolTimer(getToolElapsedMs(ctx))
4431
+ return makeText(ctx.lastComponent, toolHeader(label, summary, theme, toolStatusDot(ctx, theme), timer))
4432
+ },
4433
+ renderResult(result: any, { expanded, isPartial }: any, theme: Theme, ctx: any) {
4434
+ if (name === "apply_patch") return renderApplyPatchResult(result, isPartial, theme, ctx)
4435
+ return renderOpenAiToolResult(name, result, expanded, isPartial, theme, ctx)
4436
+ },
4437
+ })
4438
+ wrappedOpenAiTools.add(name)
4439
+ }
4440
+ }
4441
+
4442
+ const wrappedMcpTools = new Set<string>()
4443
+ const registerMcpToolOverrides = (): void => {
4444
+ let allTools: unknown[] = []
4445
+ try {
4446
+ allTools = typeof (pi as any).getAllTools === "function" ? (pi as any).getAllTools() : []
4447
+ } catch {
4448
+ allTools = []
4449
+ }
4450
+ for (const tool of allTools) {
4451
+ if (!isMcpToolCandidate(tool)) continue
4452
+ const record = tool as Record<string, unknown>
4453
+ const name = typeof record.name === "string" ? record.name : ""
4454
+ if (!name || wrappedMcpTools.has(name)) continue
4455
+ const execute = typeof record.execute === "function" ? (record.execute as any) : null
4456
+ if (!execute) continue
4457
+ const label = typeof record.label === "string" ? record.label : name === "mcp" ? "MCP" : `MCP ${name}`
4458
+ const description = typeof record.description === "string" ? record.description : "MCP tool"
4459
+ ;(pi as any).registerTool({
4460
+ name,
4461
+ label,
4462
+ description,
4463
+ parameters: record.parameters,
4464
+ prepareArguments: typeof record.prepareArguments === "function" ? record.prepareArguments : undefined,
4465
+ async execute(toolCallId: string, params: any, signal: AbortSignal | undefined, onUpdate: any, ctx: any) {
4466
+ return await Promise.resolve(execute(toolCallId, params, signal, onUpdate, ctx))
4467
+ },
4468
+ renderCall(args: any, theme: Theme, ctx: any) {
4469
+ return renderGenericToolCall(name, args, theme, ctx)
4470
+ },
4471
+ renderResult(result: any, { expanded, isPartial }: any, theme: Theme, ctx: any) {
4472
+ return renderMcpToolResult(result, expanded, isPartial, theme, ctx)
4473
+ },
4474
+ })
4475
+ wrappedMcpTools.add(name)
4476
+ }
4477
+ }
4478
+
4479
+ pi.on("session_start", async () => {
4480
+ registerOpenAiToolOverrides()
4481
+ registerMcpToolOverrides()
4482
+ })
4483
+ pi.on("before_agent_start", async () => {
4484
+ registerOpenAiToolOverrides()
4485
+ registerMcpToolOverrides()
4486
+ })
4487
+
4488
+ // Safety net: clear all blink timers on turn/session boundaries
4489
+ pi.on("turn_end", async () => {
4490
+ for (const entry of _blinkContexts.values()) {
4491
+ entry.key._blinkActive = false
4492
+ }
4493
+ _blinkContexts.clear()
4494
+ clearHighlightCache()
4495
+ if (_globalBlinkTimer) {
4496
+ clearTimeout(_globalBlinkTimer)
4497
+ _globalBlinkTimer = null
4498
+ }
4499
+ })
4500
+ pi.on("session_shutdown", async () => {
4501
+ for (const entry of _blinkContexts.values()) {
4502
+ entry.key._blinkActive = false
4503
+ }
4504
+ _blinkContexts.clear()
4505
+ clearHighlightCache()
4506
+ if (_globalBlinkTimer) {
4507
+ clearTimeout(_globalBlinkTimer)
4508
+ _globalBlinkTimer = null
4509
+ }
4510
+ })
4511
+ }