@alumbwe/anvil 1.0.20 → 1.0.22

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 (328) hide show
  1. package/package.json +74 -70
  2. package/src/agents/bundled-agents.generated.ts +4 -4
  3. package/src/chat.tsx +1703 -1698
  4. package/src/cli-args.ts +134 -134
  5. package/src/components/status-bar.tsx +331 -313
  6. package/src/hooks/helpers/send-message.ts +663 -654
  7. package/src/hooks/use-send-message.ts +806 -773
  8. package/src/index.tsx +473 -473
  9. package/src/state/chat-store.ts +553 -544
  10. package/src/utils/create-run-config.ts +121 -121
  11. package/src/utils/format-compact-number.ts +37 -0
  12. package/vendor/@anvil/common/package.json +27 -0
  13. package/vendor/@anvil/common/src/__tests__/agent-validation.test.ts +846 -0
  14. package/vendor/@anvil/common/src/__tests__/anvil-model-availability.test.ts +101 -0
  15. package/vendor/@anvil/common/src/__tests__/anvil-models.test.ts +1408 -0
  16. package/vendor/@anvil/common/src/__tests__/anvil-public-data-use-copy.test.ts +258 -0
  17. package/vendor/@anvil/common/src/__tests__/anvil-referral-tiers.test.ts +48 -0
  18. package/vendor/@anvil/common/src/__tests__/anvil-spend-ceilings.test.ts +282 -0
  19. package/vendor/@anvil/common/src/__tests__/anvil-trust.test.ts +526 -0
  20. package/vendor/@anvil/common/src/__tests__/deepseek-direct.test.ts +68 -0
  21. package/vendor/@anvil/common/src/__tests__/disposable-email.test.ts +132 -0
  22. package/vendor/@anvil/common/src/__tests__/dynamic-agent-template-schema.test.ts +422 -0
  23. package/vendor/@anvil/common/src/__tests__/env-ci.test.ts +167 -0
  24. package/vendor/@anvil/common/src/__tests__/env-process.test.ts +145 -0
  25. package/vendor/@anvil/common/src/__tests__/foreign-client-shipped-agents.test.ts +234 -0
  26. package/vendor/@anvil/common/src/__tests__/foreign-client-signals.test.ts +379 -0
  27. package/vendor/@anvil/common/src/__tests__/free-agents.test.ts +807 -0
  28. package/vendor/@anvil/common/src/__tests__/gravity-capi.test.ts +154 -0
  29. package/vendor/@anvil/common/src/__tests__/handlesteps-parsing.test.ts +246 -0
  30. package/vendor/@anvil/common/src/__tests__/kimi-k3-god-only.test.ts +77 -0
  31. package/vendor/@anvil/common/src/__tests__/model-config.test.ts +89 -0
  32. package/vendor/@anvil/common/src/__tests__/project-file-tree.test.ts +298 -0
  33. package/vendor/@anvil/common/src/__tests__/provisioned-model-tiers.test.ts +116 -0
  34. package/vendor/@anvil/common/src/__tests__/reasoning-effort.test.ts +167 -0
  35. package/vendor/@anvil/common/src/__tests__/reddit-capi.test.ts +132 -0
  36. package/vendor/@anvil/common/src/__tests__/response-ad-positions.test.ts +72 -0
  37. package/vendor/@anvil/common/src/__tests__/user-state.test.ts +30 -0
  38. package/vendor/@anvil/common/src/actions.ts +215 -0
  39. package/vendor/@anvil/common/src/analytics-core.ts +69 -0
  40. package/vendor/@anvil/common/src/analytics.ts +93 -0
  41. package/vendor/@anvil/common/src/api-keys/constants.ts +26 -0
  42. package/vendor/@anvil/common/src/browser-actions.ts +413 -0
  43. package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding-gate.test.ts +63 -0
  44. package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding.test.ts +246 -0
  45. package/vendor/@anvil/common/src/constants/__tests__/cf-worker-signals.test.ts +106 -0
  46. package/vendor/@anvil/common/src/constants/agents.ts +99 -0
  47. package/vendor/@anvil/common/src/constants/analytics-events.ts +435 -0
  48. package/vendor/@anvil/common/src/constants/anthropic.ts +73 -0
  49. package/vendor/@anvil/common/src/constants/anvil-data-use.ts +81 -0
  50. package/vendor/@anvil/common/src/constants/anvil-errors.ts +7 -0
  51. package/vendor/@anvil/common/src/constants/anvil-gemini-thinker.ts +21 -0
  52. package/vendor/@anvil/common/src/constants/anvil-model-ids.ts +11 -0
  53. package/vendor/@anvil/common/src/constants/anvil-models.ts +2130 -0
  54. package/vendor/@anvil/common/src/constants/anvil-onboarding-gate.ts +55 -0
  55. package/vendor/@anvil/common/src/constants/anvil-onboarding.ts +307 -0
  56. package/vendor/@anvil/common/src/constants/anvil-referral-tiers.ts +87 -0
  57. package/vendor/@anvil/common/src/constants/anvil-signup-block.ts +68 -0
  58. package/vendor/@anvil/common/src/constants/anvil-spend-ceilings.ts +450 -0
  59. package/vendor/@anvil/common/src/constants/anvil-trust.ts +976 -0
  60. package/vendor/@anvil/common/src/constants/auth.ts +18 -0
  61. package/vendor/@anvil/common/src/constants/byok.ts +2 -0
  62. package/vendor/@anvil/common/src/constants/cf-worker-signals.ts +132 -0
  63. package/vendor/@anvil/common/src/constants/composio.ts +34 -0
  64. package/vendor/@anvil/common/src/constants/deepseek-direct.ts +55 -0
  65. package/vendor/@anvil/common/src/constants/feedback.ts +13 -0
  66. package/vendor/@anvil/common/src/constants/foreign-client-signals.ts +272 -0
  67. package/vendor/@anvil/common/src/constants/free-agents.ts +777 -0
  68. package/vendor/@anvil/common/src/constants/gemini.ts +15 -0
  69. package/vendor/@anvil/common/src/constants/grant-priorities.ts +13 -0
  70. package/vendor/@anvil/common/src/constants/hosts.ts +6 -0
  71. package/vendor/@anvil/common/src/constants/images.ts +51 -0
  72. package/vendor/@anvil/common/src/constants/index.ts +7 -0
  73. package/vendor/@anvil/common/src/constants/knowledge.ts +35 -0
  74. package/vendor/@anvil/common/src/constants/limits.ts +23 -0
  75. package/vendor/@anvil/common/src/constants/model-config.ts +277 -0
  76. package/vendor/@anvil/common/src/constants/openrouter-attribution.ts +8 -0
  77. package/vendor/@anvil/common/src/constants/paths.ts +69 -0
  78. package/vendor/@anvil/common/src/constants/provider-routes.ts +317 -0
  79. package/vendor/@anvil/common/src/constants/reasoning-effort.ts +79 -0
  80. package/vendor/@anvil/common/src/constants/skills.ts +60 -0
  81. package/vendor/@anvil/common/src/constants/subscription-plans.ts +49 -0
  82. package/vendor/@anvil/common/src/constants/ui.ts +25 -0
  83. package/vendor/@anvil/common/src/env-ci.ts +36 -0
  84. package/vendor/@anvil/common/src/env-process.ts +95 -0
  85. package/vendor/@anvil/common/src/env-schema.ts +95 -0
  86. package/vendor/@anvil/common/src/env.ts +24 -0
  87. package/vendor/@anvil/common/src/gravity-capi.ts +207 -0
  88. package/vendor/@anvil/common/src/mcp/client.ts +233 -0
  89. package/vendor/@anvil/common/src/old-constants.ts +10 -0
  90. package/vendor/@anvil/common/src/project-file-tree.ts +355 -0
  91. package/vendor/@anvil/common/src/reddit-capi.ts +254 -0
  92. package/vendor/@anvil/common/src/schemas/feedback.ts +52 -0
  93. package/vendor/@anvil/common/src/schemas/logs.ts +66 -0
  94. package/vendor/@anvil/common/src/templates/agent-validation.ts +392 -0
  95. package/vendor/@anvil/common/src/templates/initial-agents-dir/LICENSE +202 -0
  96. package/vendor/@anvil/common/src/templates/initial-agents-dir/README.md +294 -0
  97. package/vendor/@anvil/common/src/templates/initial-agents-dir/examples/01-basic-diff-reviewer.ts +17 -0
  98. package/vendor/@anvil/common/src/templates/initial-agents-dir/examples/02-intermediate-git-committer.ts +78 -0
  99. package/vendor/@anvil/common/src/templates/initial-agents-dir/examples/03-advanced-file-explorer.ts +73 -0
  100. package/vendor/@anvil/common/src/templates/initial-agents-dir/my-custom-agent.ts +40 -0
  101. package/vendor/@anvil/common/src/templates/initial-agents-dir/package.json +6 -0
  102. package/vendor/@anvil/common/src/templates/initial-agents-dir/skills/README.md +65 -0
  103. package/vendor/@anvil/common/src/templates/initial-agents-dir/skills/example-skill/SKILL.md +29 -0
  104. package/vendor/@anvil/common/src/templates/initial-agents-dir/types/agent-definition.ts +497 -0
  105. package/vendor/@anvil/common/src/templates/initial-agents-dir/types/tools.ts +444 -0
  106. package/vendor/@anvil/common/src/templates/initial-agents-dir/types/util-types.ts +178 -0
  107. package/vendor/@anvil/common/src/testing/TESTING_PATTERNS.md +351 -0
  108. package/vendor/@anvil/common/src/testing/anvil-offer-invariants.ts +169 -0
  109. package/vendor/@anvil/common/src/testing/errors.ts +33 -0
  110. package/vendor/@anvil/common/src/testing/fixtures/agent-runtime.ts +334 -0
  111. package/vendor/@anvil/common/src/testing/impl/agent-runtime.ts +6 -0
  112. package/vendor/@anvil/common/src/testing/index.ts +84 -0
  113. package/vendor/@anvil/common/src/testing/mock-modules.ts +53 -0
  114. package/vendor/@anvil/common/src/testing/mock-types.ts +123 -0
  115. package/vendor/@anvil/common/src/testing/mocks/analytics.ts +261 -0
  116. package/vendor/@anvil/common/src/testing/mocks/child-process.ts +93 -0
  117. package/vendor/@anvil/common/src/testing/mocks/crypto.ts +218 -0
  118. package/vendor/@anvil/common/src/testing/mocks/database.ts +337 -0
  119. package/vendor/@anvil/common/src/testing/mocks/fetch.ts +219 -0
  120. package/vendor/@anvil/common/src/testing/mocks/filesystem.ts +166 -0
  121. package/vendor/@anvil/common/src/testing/mocks/index.ts +101 -0
  122. package/vendor/@anvil/common/src/testing/mocks/logger.ts +135 -0
  123. package/vendor/@anvil/common/src/testing/mocks/stream.ts +313 -0
  124. package/vendor/@anvil/common/src/testing/mocks/timers.ts +132 -0
  125. package/vendor/@anvil/common/src/testing/mocks/tree-sitter.ts +127 -0
  126. package/vendor/@anvil/common/src/testing/setup.ts +282 -0
  127. package/vendor/@anvil/common/src/testing-env-ci.ts +15 -0
  128. package/vendor/@anvil/common/src/testing-env-process.ts +78 -0
  129. package/vendor/@anvil/common/src/tools/__tests__/compile-tool-definitions.test.ts +34 -0
  130. package/vendor/@anvil/common/src/tools/compile-tool-definitions.ts +157 -0
  131. package/vendor/@anvil/common/src/tools/constants.ts +117 -0
  132. package/vendor/@anvil/common/src/tools/list.ts +190 -0
  133. package/vendor/@anvil/common/src/tools/params/__tests__/coerce-to-array.test.ts +213 -0
  134. package/vendor/@anvil/common/src/tools/params/__tests__/read-docs.test.ts +47 -0
  135. package/vendor/@anvil/common/src/tools/params/__tests__/render-ui.test.ts +65 -0
  136. package/vendor/@anvil/common/src/tools/params/tool/__tests__/run-terminal-command-timeout.test.ts +49 -0
  137. package/vendor/@anvil/common/src/tools/params/tool/add-message.ts +39 -0
  138. package/vendor/@anvil/common/src/tools/params/tool/add-subgoal.ts +57 -0
  139. package/vendor/@anvil/common/src/tools/params/tool/apply-patch.ts +110 -0
  140. package/vendor/@anvil/common/src/tools/params/tool/ask-user.ts +181 -0
  141. package/vendor/@anvil/common/src/tools/params/tool/browser-logs.ts +85 -0
  142. package/vendor/@anvil/common/src/tools/params/tool/cloud-plan-ready.ts +94 -0
  143. package/vendor/@anvil/common/src/tools/params/tool/code-search.ts +159 -0
  144. package/vendor/@anvil/common/src/tools/params/tool/composio.ts +131 -0
  145. package/vendor/@anvil/common/src/tools/params/tool/create-plan.ts +80 -0
  146. package/vendor/@anvil/common/src/tools/params/tool/end-turn.ts +57 -0
  147. package/vendor/@anvil/common/src/tools/params/tool/find-files.ts +60 -0
  148. package/vendor/@anvil/common/src/tools/params/tool/glob.ts +80 -0
  149. package/vendor/@anvil/common/src/tools/params/tool/gravity-index.ts +93 -0
  150. package/vendor/@anvil/common/src/tools/params/tool/list-directory.ts +58 -0
  151. package/vendor/@anvil/common/src/tools/params/tool/lookup-agent-info.ts +37 -0
  152. package/vendor/@anvil/common/src/tools/params/tool/propose-str-replace.ts +103 -0
  153. package/vendor/@anvil/common/src/tools/params/tool/propose-write-file.ts +71 -0
  154. package/vendor/@anvil/common/src/tools/params/tool/read-docs.ts +90 -0
  155. package/vendor/@anvil/common/src/tools/params/tool/read-files.ts +109 -0
  156. package/vendor/@anvil/common/src/tools/params/tool/read-subtree.ts +79 -0
  157. package/vendor/@anvil/common/src/tools/params/tool/read-url.ts +81 -0
  158. package/vendor/@anvil/common/src/tools/params/tool/render-ui.ts +168 -0
  159. package/vendor/@anvil/common/src/tools/params/tool/run-file-change-hooks.ts +57 -0
  160. package/vendor/@anvil/common/src/tools/params/tool/run-terminal-command.ts +211 -0
  161. package/vendor/@anvil/common/src/tools/params/tool/screenshot.ts +97 -0
  162. package/vendor/@anvil/common/src/tools/params/tool/set-messages.ts +44 -0
  163. package/vendor/@anvil/common/src/tools/params/tool/set-output.ts +61 -0
  164. package/vendor/@anvil/common/src/tools/params/tool/skill.ts +59 -0
  165. package/vendor/@anvil/common/src/tools/params/tool/spawn-agent-inline.ts +56 -0
  166. package/vendor/@anvil/common/src/tools/params/tool/spawn-agents.ts +154 -0
  167. package/vendor/@anvil/common/src/tools/params/tool/str-replace.ts +107 -0
  168. package/vendor/@anvil/common/src/tools/params/tool/suggest-followups.ts +97 -0
  169. package/vendor/@anvil/common/src/tools/params/tool/task-completed.ts +61 -0
  170. package/vendor/@anvil/common/src/tools/params/tool/think-deeply.ts +56 -0
  171. package/vendor/@anvil/common/src/tools/params/tool/update-subgoal.ts +89 -0
  172. package/vendor/@anvil/common/src/tools/params/tool/vision-analyze.ts +82 -0
  173. package/vendor/@anvil/common/src/tools/params/tool/web-search.ts +73 -0
  174. package/vendor/@anvil/common/src/tools/params/tool/write-file.ts +71 -0
  175. package/vendor/@anvil/common/src/tools/params/tool/write-todos.ts +67 -0
  176. package/vendor/@anvil/common/src/tools/params/utils.ts +150 -0
  177. package/vendor/@anvil/common/src/tools/utils.ts +24 -0
  178. package/vendor/@anvil/common/src/types/__tests__/dynamic-agent-template.test.ts +20 -0
  179. package/vendor/@anvil/common/src/types/agent-template.ts +215 -0
  180. package/vendor/@anvil/common/src/types/anvil-session.ts +535 -0
  181. package/vendor/@anvil/common/src/types/anvil-streak.ts +6 -0
  182. package/vendor/@anvil/common/src/types/anvil-usage.ts +64 -0
  183. package/vendor/@anvil/common/src/types/api/agents/publish.ts +61 -0
  184. package/vendor/@anvil/common/src/types/bun-test.d.ts +5 -0
  185. package/vendor/@anvil/common/src/types/contracts/agent-runtime.ts +75 -0
  186. package/vendor/@anvil/common/src/types/contracts/analytics.ts +9 -0
  187. package/vendor/@anvil/common/src/types/contracts/bigquery.ts +55 -0
  188. package/vendor/@anvil/common/src/types/contracts/billing.ts +46 -0
  189. package/vendor/@anvil/common/src/types/contracts/client.ts +53 -0
  190. package/vendor/@anvil/common/src/types/contracts/database.ts +112 -0
  191. package/vendor/@anvil/common/src/types/contracts/env.ts +203 -0
  192. package/vendor/@anvil/common/src/types/contracts/llm.ts +191 -0
  193. package/vendor/@anvil/common/src/types/contracts/logger.ts +14 -0
  194. package/vendor/@anvil/common/src/types/contracts/logs.ts +34 -0
  195. package/vendor/@anvil/common/src/types/contracts/trace.ts +21 -0
  196. package/vendor/@anvil/common/src/types/dynamic-agent-template.ts +328 -0
  197. package/vendor/@anvil/common/src/types/filesystem.ts +10 -0
  198. package/vendor/@anvil/common/src/types/function-params.ts +33 -0
  199. package/vendor/@anvil/common/src/types/grant.ts +20 -0
  200. package/vendor/@anvil/common/src/types/gravity-index.ts +170 -0
  201. package/vendor/@anvil/common/src/types/json.ts +29 -0
  202. package/vendor/@anvil/common/src/types/mcp.ts +24 -0
  203. package/vendor/@anvil/common/src/types/messages/anvil-message.ts +58 -0
  204. package/vendor/@anvil/common/src/types/messages/content-part.ts +59 -0
  205. package/vendor/@anvil/common/src/types/messages/data-content.ts +14 -0
  206. package/vendor/@anvil/common/src/types/messages/provider-metadata.ts +13 -0
  207. package/vendor/@anvil/common/src/types/organization.ts +118 -0
  208. package/vendor/@anvil/common/src/types/print-mode.ts +121 -0
  209. package/vendor/@anvil/common/src/types/publisher.ts +67 -0
  210. package/vendor/@anvil/common/src/types/session-state.ts +149 -0
  211. package/vendor/@anvil/common/src/types/skill.ts +86 -0
  212. package/vendor/@anvil/common/src/types/source.ts +11 -0
  213. package/vendor/@anvil/common/src/types/spawn.ts +13 -0
  214. package/vendor/@anvil/common/src/types/subscription.ts +67 -0
  215. package/vendor/@anvil/common/src/types/usage.ts +16 -0
  216. package/vendor/@anvil/common/src/types/util.ts +3 -0
  217. package/vendor/@anvil/common/src/util/__tests__/ad-user-agent.test.ts +26 -0
  218. package/vendor/@anvil/common/src/util/__tests__/analytics-dispatcher.test.ts +122 -0
  219. package/vendor/@anvil/common/src/util/__tests__/analytics-log.test.ts +102 -0
  220. package/vendor/@anvil/common/src/util/__tests__/analytics-sampling.test.ts +143 -0
  221. package/vendor/@anvil/common/src/util/__tests__/anvil-streak.test.ts +202 -0
  222. package/vendor/@anvil/common/src/util/__tests__/anvil-usage-summary.test.ts +193 -0
  223. package/vendor/@anvil/common/src/util/__tests__/axiom-only-log.test.ts +140 -0
  224. package/vendor/@anvil/common/src/util/__tests__/client-user-agent.test.ts +148 -0
  225. package/vendor/@anvil/common/src/util/__tests__/engagement-tracker.test.ts +115 -0
  226. package/vendor/@anvil/common/src/util/__tests__/env-file-path.test.ts +57 -0
  227. package/vendor/@anvil/common/src/util/__tests__/error-abort.test.ts +774 -0
  228. package/vendor/@anvil/common/src/util/__tests__/error-api-details.test.ts +206 -0
  229. package/vendor/@anvil/common/src/util/__tests__/file-read-limits.test.ts +173 -0
  230. package/vendor/@anvil/common/src/util/__tests__/format-code-search.test.ts +60 -0
  231. package/vendor/@anvil/common/src/util/__tests__/log-mirror.test.ts +31 -0
  232. package/vendor/@anvil/common/src/util/__tests__/messages.test.ts +1252 -0
  233. package/vendor/@anvil/common/src/util/__tests__/partial-json-delta.test.ts +505 -0
  234. package/vendor/@anvil/common/src/util/__tests__/path.test.ts +22 -0
  235. package/vendor/@anvil/common/src/util/__tests__/project-ignore.test.ts +90 -0
  236. package/vendor/@anvil/common/src/util/__tests__/promise.test.ts +325 -0
  237. package/vendor/@anvil/common/src/util/__tests__/rate-limit.test.ts +28 -0
  238. package/vendor/@anvil/common/src/util/__tests__/reddit-anvil-retention.test.ts +130 -0
  239. package/vendor/@anvil/common/src/util/__tests__/saxy.test.ts +1008 -0
  240. package/vendor/@anvil/common/src/util/__tests__/split-data.test.ts +289 -0
  241. package/vendor/@anvil/common/src/util/__tests__/string.test.ts +239 -0
  242. package/vendor/@anvil/common/src/util/__tests__/thread-title.test.ts +70 -0
  243. package/vendor/@anvil/common/src/util/__tests__/tool-result-media-order.test.ts +108 -0
  244. package/vendor/@anvil/common/src/util/__tests__/ttft-histogram.test.ts +180 -0
  245. package/vendor/@anvil/common/src/util/__tests__/with-timeout.test.ts +24 -0
  246. package/vendor/@anvil/common/src/util/__tests__/zoned-time.test.ts +88 -0
  247. package/vendor/@anvil/common/src/util/ad-user-agent.ts +25 -0
  248. package/vendor/@anvil/common/src/util/agent-file-utils.ts +110 -0
  249. package/vendor/@anvil/common/src/util/agent-id-parsing.ts +136 -0
  250. package/vendor/@anvil/common/src/util/agent-name-normalization.ts +38 -0
  251. package/vendor/@anvil/common/src/util/agent-name-resolver.ts +86 -0
  252. package/vendor/@anvil/common/src/util/analytics-dispatcher.ts +82 -0
  253. package/vendor/@anvil/common/src/util/analytics-log.ts +78 -0
  254. package/vendor/@anvil/common/src/util/analytics-sampling.ts +255 -0
  255. package/vendor/@anvil/common/src/util/anvil-model-availability.ts +102 -0
  256. package/vendor/@anvil/common/src/util/anvil-privacy.ts +82 -0
  257. package/vendor/@anvil/common/src/util/anvil-streak-line.ts +103 -0
  258. package/vendor/@anvil/common/src/util/anvil-streak.ts +156 -0
  259. package/vendor/@anvil/common/src/util/anvil-usage-summary.ts +125 -0
  260. package/vendor/@anvil/common/src/util/array.ts +31 -0
  261. package/vendor/@anvil/common/src/util/axiom-only-log.ts +124 -0
  262. package/vendor/@anvil/common/src/util/cache-debug.ts +171 -0
  263. package/vendor/@anvil/common/src/util/client-user-agent.ts +114 -0
  264. package/vendor/@anvil/common/src/util/credentials.ts +26 -0
  265. package/vendor/@anvil/common/src/util/currency.ts +25 -0
  266. package/vendor/@anvil/common/src/util/dates.ts +81 -0
  267. package/vendor/@anvil/common/src/util/disposable-email.ts +277 -0
  268. package/vendor/@anvil/common/src/util/engagement-tracker.ts +129 -0
  269. package/vendor/@anvil/common/src/util/env-file-path.ts +40 -0
  270. package/vendor/@anvil/common/src/util/error.ts +562 -0
  271. package/vendor/@anvil/common/src/util/file-read-limits.ts +236 -0
  272. package/vendor/@anvil/common/src/util/file.ts +339 -0
  273. package/vendor/@anvil/common/src/util/format-code-search.ts +115 -0
  274. package/vendor/@anvil/common/src/util/lazy-response-ads.ts +92 -0
  275. package/vendor/@anvil/common/src/util/log-data.ts +57 -0
  276. package/vendor/@anvil/common/src/util/log-ingest.ts +58 -0
  277. package/vendor/@anvil/common/src/util/log-mirror.ts +34 -0
  278. package/vendor/@anvil/common/src/util/lru-cache.ts +67 -0
  279. package/vendor/@anvil/common/src/util/messages.ts +685 -0
  280. package/vendor/@anvil/common/src/util/min-heap.ts +87 -0
  281. package/vendor/@anvil/common/src/util/model-utils.ts +4 -0
  282. package/vendor/@anvil/common/src/util/object.ts +128 -0
  283. package/vendor/@anvil/common/src/util/partial-json-delta.ts +89 -0
  284. package/vendor/@anvil/common/src/util/path.ts +15 -0
  285. package/vendor/@anvil/common/src/util/project-ignore.ts +119 -0
  286. package/vendor/@anvil/common/src/util/promise.ts +73 -0
  287. package/vendor/@anvil/common/src/util/random.ts +15 -0
  288. package/vendor/@anvil/common/src/util/rate-limit.ts +56 -0
  289. package/vendor/@anvil/common/src/util/reddit-anvil-retention.ts +60 -0
  290. package/vendor/@anvil/common/src/util/reddit-capi-events.ts +36 -0
  291. package/vendor/@anvil/common/src/util/response-ad-positions.ts +54 -0
  292. package/vendor/@anvil/common/src/util/saxy.ts +741 -0
  293. package/vendor/@anvil/common/src/util/skills.test.ts +44 -0
  294. package/vendor/@anvil/common/src/util/skills.ts +36 -0
  295. package/vendor/@anvil/common/src/util/split-data.ts +259 -0
  296. package/vendor/@anvil/common/src/util/stop-sequence.ts +61 -0
  297. package/vendor/@anvil/common/src/util/string.ts +426 -0
  298. package/vendor/@anvil/common/src/util/system-info.ts +53 -0
  299. package/vendor/@anvil/common/src/util/thread-title.ts +46 -0
  300. package/vendor/@anvil/common/src/util/ttft-histogram.ts +73 -0
  301. package/vendor/@anvil/common/src/util/xml-parser.ts +27 -0
  302. package/vendor/@anvil/common/src/util/xml.ts +17 -0
  303. package/vendor/@anvil/common/src/util/zod-schema.ts +25 -0
  304. package/vendor/@anvil/common/src/util/zoned-time.ts +136 -0
  305. package/vendor/@anvil/common/src/utils/ask-user-bridge.ts +44 -0
  306. package/vendor/@anvil/sdk/dist/index.cjs +52297 -0
  307. package/vendor/@anvil/sdk/dist/index.cjs.map +440 -0
  308. package/vendor/@anvil/sdk/dist/index.d.ts +4277 -0
  309. package/vendor/@anvil/sdk/dist/index.mjs +52290 -0
  310. package/vendor/@anvil/sdk/dist/index.mjs.map +440 -0
  311. package/vendor/@anvil/sdk/dist/vendor/ai.cjs +30886 -0
  312. package/vendor/@anvil/sdk/dist/vendor/ripgrep/arm64-darwin/rg +0 -0
  313. package/vendor/@anvil/sdk/dist/vendor/ripgrep/arm64-linux/rg +0 -0
  314. package/vendor/@anvil/sdk/dist/vendor/ripgrep/x64-darwin/rg +0 -0
  315. package/vendor/@anvil/sdk/dist/vendor/ripgrep/x64-linux/rg +0 -0
  316. package/vendor/@anvil/sdk/dist/vendor/ripgrep/x64-win32/rg.exe +0 -0
  317. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-c-sharp.wasm +0 -0
  318. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-cpp.wasm +0 -0
  319. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-go.wasm +0 -0
  320. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-java.wasm +0 -0
  321. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-javascript.wasm +0 -0
  322. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-python.wasm +0 -0
  323. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-ruby.wasm +0 -0
  324. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-rust.wasm +0 -0
  325. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-tsx.wasm +0 -0
  326. package/vendor/@anvil/sdk/dist/wasm/tree-sitter-typescript.wasm +0 -0
  327. package/vendor/@anvil/sdk/dist/wasm/tree-sitter.wasm +0 -0
  328. package/vendor/@anvil/sdk/package.json +21 -0
@@ -1,313 +1,331 @@
1
- import { getAnvilModel } from '@anvil/common/constants/anvil-models'
2
- import { TextAttributes } from '@opentui/core'
3
- import React, { useEffect, useState } from 'react'
4
-
5
- import { Button } from './button'
6
- import { ScrollToBottomButton } from './scroll-to-bottom-button'
7
- import { ShimmerText } from './shimmer-text'
8
- import { TerminalThinkingOrb } from './terminal-thinking-orb'
9
-
10
- import { useAnvilSessionProgress } from '../hooks/use-anvil-session-progress'
11
- import { useTheme } from '../hooks/use-theme'
12
- import { formatElapsedTime } from '../utils/format-elapsed-time'
13
- import {
14
- ANVIL_COUNTDOWN_VISIBLE_MS,
15
- formatAnvilSessionCountdown,
16
- formatAnvilSessionRemaining,
17
- } from '../utils/anvil-session-display'
18
-
19
- import type { AnvilSessionResponse } from '../types/anvil-session'
20
- import type { StatusIndicatorState } from '../utils/status-indicator-state'
21
-
22
- /** A small status-bar action button with hover-bold styling. */
23
- const StatusActionButton = ({
24
- children,
25
- onClick,
26
- }: {
27
- children: React.ReactNode
28
- onClick: () => void
29
- }) => {
30
- const theme = useTheme()
31
- const [hovered, setHovered] = useState(false)
32
-
33
- return (
34
- <Button
35
- style={{ paddingLeft: 1, paddingRight: 1 }}
36
- onClick={onClick}
37
- onMouseOver={() => setHovered(true)}
38
- onMouseOut={() => setHovered(false)}
39
- >
40
- <text>
41
- <span
42
- fg={theme.secondary}
43
- attributes={hovered ? TextAttributes.BOLD : TextAttributes.NONE}
44
- >
45
- {children}
46
- </span>
47
- </text>
48
- </Button>
49
- )
50
- }
51
-
52
- const SHIMMER_INTERVAL_MS = 160
53
-
54
- interface StatusBarProps {
55
- timerStartTime: number | null
56
- isAtBottom: boolean
57
- scrollToLatest: () => void
58
- statusIndicatorState: StatusIndicatorState
59
- onStop?: () => void
60
- onEndSession?: () => void
61
- anvilSession: AnvilSessionResponse | null
62
- }
63
-
64
- export const StatusBar = ({
65
- timerStartTime,
66
- isAtBottom,
67
- scrollToLatest,
68
- statusIndicatorState,
69
- onStop,
70
- onEndSession,
71
- anvilSession,
72
- }: StatusBarProps) => {
73
- const theme = useTheme()
74
- const [elapsedSeconds, setElapsedSeconds] = useState(0)
75
-
76
- // Show timer when actively working (streaming or waiting for response) or paused (ask_user)
77
- // This uses statusIndicatorState as the single source of truth for "is the LLM working?"
78
- const shouldShowTimer =
79
- statusIndicatorState?.kind === 'waiting' ||
80
- statusIndicatorState?.kind === 'streaming' ||
81
- statusIndicatorState?.kind === 'paused'
82
-
83
- useEffect(() => {
84
- if (!timerStartTime || !shouldShowTimer) {
85
- setElapsedSeconds(0)
86
- return
87
- }
88
-
89
- // When paused, don't update the timer - just keep the frozen value
90
- if (statusIndicatorState?.kind === 'paused') {
91
- // Calculate current elapsed time once and freeze it
92
- const now = Date.now()
93
- const elapsed = Math.floor((now - timerStartTime) / 1000)
94
- setElapsedSeconds(elapsed)
95
- return
96
- }
97
-
98
- const updateElapsed = () => {
99
- const now = Date.now()
100
- const elapsed = Math.floor((now - timerStartTime) / 1000)
101
- setElapsedSeconds(elapsed)
102
- }
103
-
104
- updateElapsed()
105
- const interval = setInterval(updateElapsed, 1000)
106
-
107
- return () => clearInterval(interval)
108
- }, [timerStartTime, shouldShowTimer, statusIndicatorState?.kind])
109
-
110
- const sessionProgress = useAnvilSessionProgress(anvilSession)
111
- const isUnlimited =
112
- anvilSession?.status === 'active' && !anvilSession.rateLimit
113
-
114
- const renderStatusIndicator = () => {
115
- switch (statusIndicatorState.kind) {
116
- case 'ctrlC':
117
- return <span fg={theme.secondary}>Press Ctrl-C again to exit</span>
118
-
119
- case 'clipboard':
120
- // Use green color for feedback success messages
121
- const isFeedbackSuccess =
122
- statusIndicatorState.message.includes('Feedback sent')
123
- return (
124
- <span fg={isFeedbackSuccess ? theme.success : theme.primary}>
125
- {statusIndicatorState.message}
126
- </span>
127
- )
128
-
129
- case 'reconnected':
130
- return <span fg={theme.success}>Back online</span>
131
-
132
- case 'retrying':
133
- return (
134
- <span>
135
- <TerminalThinkingOrb state="retrying" variant="spark" color={theme.warning} />{' '}
136
- <ShimmerText text="hiccup — retrying..." primaryColor={theme.warning} />
137
- </span>
138
- )
139
-
140
- case 'capacityWait':
141
- return (
142
- <span>
143
- <TerminalThinkingOrb state="waiting" variant="spark" color={theme.warning} />{' '}
144
- <ShimmerText
145
- text="peak traffic — you're in line, starting soon..."
146
- primaryColor={theme.warning}
147
- />
148
- </span>
149
- )
150
-
151
- case 'connecting':
152
- return (
153
- <span>
154
- <TerminalThinkingOrb state="connecting" variant="spark" />{' '}
155
- <ShimmerText text="dialing in..." />
156
- </span>
157
- )
158
-
159
- case 'waiting':
160
- return (
161
- <span>
162
- <TerminalThinkingOrb state="waiting" variant="spark" />{' '}
163
- <ShimmerText
164
- text="warming up..."
165
- interval={SHIMMER_INTERVAL_MS}
166
- primaryColor={theme.secondary}
167
- />
168
- </span>
169
- )
170
-
171
- case 'streaming':
172
- return (
173
- <span>
174
- <TerminalThinkingOrb state="working" variant="spark" />{' '}
175
- <ShimmerText
176
- text="on it..."
177
- interval={SHIMMER_INTERVAL_MS}
178
- primaryColor={theme.secondary}
179
- />
180
- </span>
181
- )
182
-
183
- case 'paused':
184
- return null
185
-
186
- case 'idle':
187
- if (sessionProgress !== null) {
188
- const isUrgent =
189
- sessionProgress.remainingMs < ANVIL_COUNTDOWN_VISIBLE_MS
190
- const modelName =
191
- anvilSession?.status === 'active'
192
- ? getAnvilModel(anvilSession.model).displayName
193
- : null
194
- return (
195
- <span
196
- fg={
197
- isUnlimited
198
- ? theme.secondary
199
- : isUrgent
200
- ? theme.warning
201
- : theme.secondary
202
- }
203
- >
204
- {modelName ? `${modelName} · ` : ''}
205
- {isUnlimited
206
- ? 'unlimited'
207
- : formatAnvilSessionRemaining(sessionProgress.remainingMs)}
208
- </span>
209
- )
210
- }
211
- return null
212
- }
213
- }
214
-
215
- const renderElapsedTime = () => {
216
- if (!shouldShowTimer || elapsedSeconds === 0) {
217
- return null
218
- }
219
-
220
- return (
221
- <span fg={theme.secondary}>
222
- worked for {formatElapsedTime(elapsedSeconds)}
223
- </span>
224
- )
225
- }
226
-
227
- const statusIndicatorContent = renderStatusIndicator()
228
- const elapsedTimeContent = renderElapsedTime()
229
-
230
- // Show gray background when there's status indicator, timer, or when the
231
- // anvil session fill is visible (otherwise the fill would float over
232
- // transparent space).
233
- const hasContent =
234
- statusIndicatorContent || elapsedTimeContent || sessionProgress !== null
235
-
236
- return (
237
- <box
238
- style={{
239
- width: '100%',
240
- flexDirection: 'row',
241
- alignItems: 'center',
242
- paddingLeft: 1,
243
- paddingRight: 1,
244
- gap: 1,
245
- backgroundColor: hasContent ? theme.surface : 'transparent',
246
- }}
247
- >
248
- {sessionProgress !== null && (
249
- <box
250
- style={{
251
- position: 'absolute',
252
- left: 0,
253
- top: 0,
254
- bottom: 0,
255
- // Fill anchors left and shrinks as time passes — the draining
256
- // bar is the countdown; no separate numeric readout needed.
257
- width: `${sessionProgress.fraction * 100}%`,
258
- backgroundColor: theme.surfaceHover,
259
- }}
260
- />
261
- )}
262
- <box
263
- style={{
264
- flexGrow: 1,
265
- flexShrink: 1,
266
- flexBasis: 0,
267
- }}
268
- >
269
- <text style={{ wrapMode: 'none' }}>{statusIndicatorContent}</text>
270
- </box>
271
-
272
- <box style={{ flexShrink: 0 }}>
273
- {!isAtBottom && <ScrollToBottomButton onClick={scrollToLatest} />}
274
- </box>
275
-
276
- <box
277
- style={{
278
- flexGrow: 1,
279
- flexShrink: 1,
280
- flexBasis: 0,
281
- flexDirection: 'row',
282
- justifyContent: 'flex-end',
283
- alignItems: 'center',
284
- gap: 1,
285
- }}
286
- >
287
- <text style={{ wrapMode: 'none' }}>{elapsedTimeContent}</text>
288
- {onStop &&
289
- (statusIndicatorState.kind === 'waiting' ||
290
- statusIndicatorState.kind === 'streaming') && (
291
- <StatusActionButton onClick={onStop}>■ Esc</StatusActionButton>
292
- )}
293
- {onEndSession &&
294
- statusIndicatorState.kind === 'idle' &&
295
- anvilSession?.status === 'active' && (
296
- <StatusActionButton onClick={onEndSession}>
297
- End session
298
- </StatusActionButton>
299
- )}
300
- {sessionProgress !== null &&
301
- sessionProgress.remainingMs < ANVIL_COUNTDOWN_VISIBLE_MS &&
302
- statusIndicatorState.kind !== 'idle' &&
303
- !isUnlimited && (
304
- <text style={{ wrapMode: 'none' }}>
305
- <span fg={theme.warning} attributes={TextAttributes.BOLD}>
306
- {formatAnvilSessionCountdown(sessionProgress.remainingMs)}
307
- </span>
308
- </text>
309
- )}
310
- </box>
311
- </box>
312
- )
313
- }
1
+ import { getAnvilModel } from '@anvil/common/constants/anvil-models'
2
+ import { TextAttributes } from '@opentui/core'
3
+ import React, { useEffect, useState } from 'react'
4
+
5
+ import { Button } from './button'
6
+ import { ScrollToBottomButton } from './scroll-to-bottom-button'
7
+ import { ShimmerText } from './shimmer-text'
8
+ import { TerminalThinkingOrb } from './terminal-thinking-orb'
9
+
10
+ import { useAnvilSessionProgress } from '../hooks/use-anvil-session-progress'
11
+ import { useTheme } from '../hooks/use-theme'
12
+ import { formatCompactNumber } from '../utils/format-compact-number'
13
+ import { formatElapsedTime } from '../utils/format-elapsed-time'
14
+ import {
15
+ ANVIL_COUNTDOWN_VISIBLE_MS,
16
+ formatAnvilSessionCountdown,
17
+ formatAnvilSessionRemaining,
18
+ } from '../utils/anvil-session-display'
19
+
20
+ import type { AnvilSessionResponse } from '../types/anvil-session'
21
+ import type { StatusIndicatorState } from '../utils/status-indicator-state'
22
+
23
+ /** A small status-bar action button with hover-bold styling. */
24
+ const StatusActionButton = ({
25
+ children,
26
+ onClick,
27
+ }: {
28
+ children: React.ReactNode
29
+ onClick: () => void
30
+ }) => {
31
+ const theme = useTheme()
32
+ const [hovered, setHovered] = useState(false)
33
+
34
+ return (
35
+ <Button
36
+ style={{ paddingLeft: 1, paddingRight: 1 }}
37
+ onClick={onClick}
38
+ onMouseOver={() => setHovered(true)}
39
+ onMouseOut={() => setHovered(false)}
40
+ >
41
+ <text>
42
+ <span
43
+ fg={theme.secondary}
44
+ attributes={hovered ? TextAttributes.BOLD : TextAttributes.NONE}
45
+ >
46
+ {children}
47
+ </span>
48
+ </text>
49
+ </Button>
50
+ )
51
+ }
52
+
53
+ const SHIMMER_INTERVAL_MS = 160
54
+
55
+ interface StatusBarProps {
56
+ timerStartTime: number | null
57
+ isAtBottom: boolean
58
+ scrollToLatest: () => void
59
+ statusIndicatorState: StatusIndicatorState
60
+ onStop?: () => void
61
+ onEndSession?: () => void
62
+ anvilSession: AnvilSessionResponse | null
63
+ sessionCreditsUsed?: number
64
+ contextTokensUsed?: number
65
+ }
66
+
67
+ export const StatusBar = ({
68
+ timerStartTime,
69
+ isAtBottom,
70
+ scrollToLatest,
71
+ statusIndicatorState,
72
+ onStop,
73
+ onEndSession,
74
+ anvilSession,
75
+ sessionCreditsUsed = 0,
76
+ contextTokensUsed = 0,
77
+ }: StatusBarProps) => {
78
+ const theme = useTheme()
79
+ const [elapsedSeconds, setElapsedSeconds] = useState(0)
80
+
81
+ // Show timer when actively working (streaming or waiting for response) or paused (ask_user)
82
+ // This uses statusIndicatorState as the single source of truth for "is the LLM working?"
83
+ const shouldShowTimer =
84
+ statusIndicatorState?.kind === 'waiting' ||
85
+ statusIndicatorState?.kind === 'streaming' ||
86
+ statusIndicatorState?.kind === 'paused'
87
+
88
+ useEffect(() => {
89
+ if (!timerStartTime || !shouldShowTimer) {
90
+ setElapsedSeconds(0)
91
+ return
92
+ }
93
+
94
+ // When paused, don't update the timer - just keep the frozen value
95
+ if (statusIndicatorState?.kind === 'paused') {
96
+ // Calculate current elapsed time once and freeze it
97
+ const now = Date.now()
98
+ const elapsed = Math.floor((now - timerStartTime) / 1000)
99
+ setElapsedSeconds(elapsed)
100
+ return
101
+ }
102
+
103
+ const updateElapsed = () => {
104
+ const now = Date.now()
105
+ const elapsed = Math.floor((now - timerStartTime) / 1000)
106
+ setElapsedSeconds(elapsed)
107
+ }
108
+
109
+ updateElapsed()
110
+ const interval = setInterval(updateElapsed, 1000)
111
+
112
+ return () => clearInterval(interval)
113
+ }, [timerStartTime, shouldShowTimer, statusIndicatorState?.kind])
114
+
115
+ const sessionProgress = useAnvilSessionProgress(anvilSession)
116
+ const isUnlimited =
117
+ anvilSession?.status === 'active' && !anvilSession.rateLimit
118
+
119
+ const renderStatusIndicator = () => {
120
+ switch (statusIndicatorState.kind) {
121
+ case 'ctrlC':
122
+ return <span fg={theme.secondary}>Press Ctrl-C again to exit</span>
123
+
124
+ case 'clipboard':
125
+ // Use green color for feedback success messages
126
+ const isFeedbackSuccess =
127
+ statusIndicatorState.message.includes('Feedback sent')
128
+ return (
129
+ <span fg={isFeedbackSuccess ? theme.success : theme.primary}>
130
+ {statusIndicatorState.message}
131
+ </span>
132
+ )
133
+
134
+ case 'reconnected':
135
+ return <span fg={theme.success}>Back online</span>
136
+
137
+ case 'retrying':
138
+ return (
139
+ <span>
140
+ <TerminalThinkingOrb state="retrying" variant="spark" color={theme.warning} />{' '}
141
+ <ShimmerText text="hiccup — retrying..." primaryColor={theme.warning} />
142
+ </span>
143
+ )
144
+
145
+ case 'capacityWait':
146
+ return (
147
+ <span>
148
+ <TerminalThinkingOrb state="waiting" variant="spark" color={theme.warning} />{' '}
149
+ <ShimmerText
150
+ text="peak traffic — you're in line, starting soon..."
151
+ primaryColor={theme.warning}
152
+ />
153
+ </span>
154
+ )
155
+
156
+ case 'connecting':
157
+ return (
158
+ <span>
159
+ <TerminalThinkingOrb state="connecting" variant="spark" />{' '}
160
+ <ShimmerText text="dialing in..." />
161
+ </span>
162
+ )
163
+
164
+ case 'waiting':
165
+ return (
166
+ <span>
167
+ <TerminalThinkingOrb state="waiting" variant="spark" />{' '}
168
+ <ShimmerText
169
+ text="warming up..."
170
+ interval={SHIMMER_INTERVAL_MS}
171
+ primaryColor={theme.secondary}
172
+ />
173
+ </span>
174
+ )
175
+
176
+ case 'streaming':
177
+ return (
178
+ <span>
179
+ <TerminalThinkingOrb state="working" variant="spark" />{' '}
180
+ <ShimmerText
181
+ text="on it..."
182
+ interval={SHIMMER_INTERVAL_MS}
183
+ primaryColor={theme.secondary}
184
+ />
185
+ </span>
186
+ )
187
+
188
+ case 'paused':
189
+ return null
190
+
191
+ case 'idle':
192
+ if (sessionProgress !== null) {
193
+ const isUrgent =
194
+ sessionProgress.remainingMs < ANVIL_COUNTDOWN_VISIBLE_MS
195
+ const modelName =
196
+ anvilSession?.status === 'active'
197
+ ? getAnvilModel(anvilSession.model).displayName
198
+ : null
199
+ return (
200
+ <span
201
+ fg={
202
+ isUnlimited
203
+ ? theme.secondary
204
+ : isUrgent
205
+ ? theme.warning
206
+ : theme.secondary
207
+ }
208
+ >
209
+ {modelName ? `${modelName} · ` : ''}
210
+ {isUnlimited
211
+ ? 'unlimited'
212
+ : formatAnvilSessionRemaining(sessionProgress.remainingMs)}
213
+ </span>
214
+ )
215
+ }
216
+ return null
217
+ }
218
+ }
219
+
220
+ const renderElapsedTime = () => {
221
+ if (!shouldShowTimer && sessionCreditsUsed === 0 && contextTokensUsed === 0) {
222
+ return null
223
+ }
224
+
225
+ const parts: string[] = []
226
+ if (shouldShowTimer && elapsedSeconds > 0) {
227
+ parts.push(`worked for ${formatElapsedTime(elapsedSeconds)}`)
228
+ }
229
+ if (contextTokensUsed > 0) {
230
+ parts.push(`${formatCompactNumber(contextTokensUsed)} tokens in context`)
231
+ }
232
+ if (sessionCreditsUsed > 0) {
233
+ parts.push(`${sessionCreditsUsed} credits`)
234
+ }
235
+
236
+ if (parts.length === 0) return null
237
+
238
+ return (
239
+ <span fg={theme.secondary}>
240
+ {parts.join(' · ')}
241
+ </span>
242
+ )
243
+ }
244
+
245
+ const statusIndicatorContent = renderStatusIndicator()
246
+ const elapsedTimeContent = renderElapsedTime()
247
+
248
+ // Show gray background when there's status indicator, timer, usage stats,
249
+ // or when the anvil session fill is visible.
250
+ const hasContent =
251
+ statusIndicatorContent || elapsedTimeContent || sessionProgress !== null ||
252
+ sessionCreditsUsed > 0 || contextTokensUsed > 0
253
+
254
+ return (
255
+ <box
256
+ style={{
257
+ width: '100%',
258
+ flexDirection: 'row',
259
+ alignItems: 'center',
260
+ paddingLeft: 1,
261
+ paddingRight: 1,
262
+ gap: 1,
263
+ backgroundColor: hasContent ? theme.surface : 'transparent',
264
+ }}
265
+ >
266
+ {sessionProgress !== null && (
267
+ <box
268
+ style={{
269
+ position: 'absolute',
270
+ left: 0,
271
+ top: 0,
272
+ bottom: 0,
273
+ // Fill anchors left and shrinks as time passes — the draining
274
+ // bar is the countdown; no separate numeric readout needed.
275
+ width: `${sessionProgress.fraction * 100}%`,
276
+ backgroundColor: theme.surfaceHover,
277
+ }}
278
+ />
279
+ )}
280
+ <box
281
+ style={{
282
+ flexGrow: 1,
283
+ flexShrink: 1,
284
+ flexBasis: 0,
285
+ }}
286
+ >
287
+ <text style={{ wrapMode: 'none' }}>{statusIndicatorContent}</text>
288
+ </box>
289
+
290
+ <box style={{ flexShrink: 0 }}>
291
+ {!isAtBottom && <ScrollToBottomButton onClick={scrollToLatest} />}
292
+ </box>
293
+
294
+ <box
295
+ style={{
296
+ flexGrow: 1,
297
+ flexShrink: 1,
298
+ flexBasis: 0,
299
+ flexDirection: 'row',
300
+ justifyContent: 'flex-end',
301
+ alignItems: 'center',
302
+ gap: 1,
303
+ }}
304
+ >
305
+ <text style={{ wrapMode: 'none' }}>{elapsedTimeContent}</text>
306
+ {onStop &&
307
+ (statusIndicatorState.kind === 'waiting' ||
308
+ statusIndicatorState.kind === 'streaming') && (
309
+ <StatusActionButton onClick={onStop}>■ Esc</StatusActionButton>
310
+ )}
311
+ {onEndSession &&
312
+ statusIndicatorState.kind === 'idle' &&
313
+ anvilSession?.status === 'active' && (
314
+ <StatusActionButton onClick={onEndSession}>
315
+ ✕ End session
316
+ </StatusActionButton>
317
+ )}
318
+ {sessionProgress !== null &&
319
+ sessionProgress.remainingMs < ANVIL_COUNTDOWN_VISIBLE_MS &&
320
+ statusIndicatorState.kind !== 'idle' &&
321
+ !isUnlimited && (
322
+ <text style={{ wrapMode: 'none' }}>
323
+ <span fg={theme.warning} attributes={TextAttributes.BOLD}>
324
+ {formatAnvilSessionCountdown(sessionProgress.remainingMs)}
325
+ </span>
326
+ </text>
327
+ )}
328
+ </box>
329
+ </box>
330
+ )
331
+ }