@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
@@ -0,0 +1,82 @@
1
+ import type { AnvilIpPrivacySignal } from '../types/anvil-session'
2
+
3
+ export const ANVIL_HARD_BLOCKED_PRIVACY_SIGNALS = [
4
+ 'vpn',
5
+ 'proxy',
6
+ 'tor',
7
+ 'res_proxy',
8
+ ] as const satisfies readonly AnvilIpPrivacySignal[]
9
+
10
+ type AnvilHardBlockedPrivacySignal =
11
+ (typeof ANVIL_HARD_BLOCKED_PRIVACY_SIGNALS)[number]
12
+
13
+ const ANVIL_HARD_BLOCKED_PRIVACY_SIGNAL_SET =
14
+ new Set<AnvilIpPrivacySignal>(ANVIL_HARD_BLOCKED_PRIVACY_SIGNALS)
15
+
16
+ const ANVIL_HARD_BLOCKED_PRIVACY_SIGNAL_LABELS: Record<
17
+ AnvilHardBlockedPrivacySignal,
18
+ string
19
+ > = {
20
+ vpn: 'VPN',
21
+ proxy: 'proxy',
22
+ res_proxy: 'proxy',
23
+ tor: 'Tor',
24
+ }
25
+
26
+ export function isAnvilHardBlockedPrivacySignal(
27
+ signal: AnvilIpPrivacySignal,
28
+ ): signal is AnvilHardBlockedPrivacySignal {
29
+ return ANVIL_HARD_BLOCKED_PRIVACY_SIGNAL_SET.has(signal)
30
+ }
31
+
32
+ /**
33
+ * ipinfo's `as.type` classifies the owning ASN as one of: ISP, Hosting,
34
+ * Education, Government or Business (see ipinfo's "IPinfo Plus" sample DB).
35
+ * Only `hosting` is a meaningful abuse signal — that's where VPN/proxy exits
36
+ * and bot infrastructure live. The other classes are ordinary networks real
37
+ * users sit behind, so we treat them as benign even when other heuristics
38
+ * (e.g. ipinfo's `is_hosting` flag) would otherwise fire.
39
+ */
40
+ const ANVIL_BENIGN_AS_TYPES = new Set([
41
+ 'isp',
42
+ 'business',
43
+ 'education',
44
+ 'government',
45
+ ])
46
+
47
+ export function isAnvilBenignAsType(
48
+ asType: string | null | undefined,
49
+ ): boolean {
50
+ return asType != null && ANVIL_BENIGN_AS_TYPES.has(asType.toLowerCase())
51
+ }
52
+
53
+ export function isAnvilHostingAsType(
54
+ asType: string | null | undefined,
55
+ ): boolean {
56
+ return typeof asType === 'string' && asType.toLowerCase() === 'hosting'
57
+ }
58
+
59
+ export function formatAnvilHardBlockedPrivacySignals(
60
+ signals: readonly AnvilIpPrivacySignal[] | null | undefined,
61
+ ): string {
62
+ const labels = Array.from(
63
+ new Set(
64
+ (signals ?? []).flatMap((signal): string[] => {
65
+ if (!isAnvilHardBlockedPrivacySignal(signal)) return []
66
+ return [ANVIL_HARD_BLOCKED_PRIVACY_SIGNAL_LABELS[signal]]
67
+ }),
68
+ ),
69
+ )
70
+
71
+ if (labels.length === 0) return 'VPN, proxy, or Tor'
72
+ if (labels.length === 1) return labels[0]
73
+ return `${labels.slice(0, -1).join(', ')} or ${labels[labels.length - 1]}`
74
+ }
75
+
76
+ export function formatAnvilHardBlockedMessage(
77
+ signals: readonly AnvilIpPrivacySignal[] | null | undefined,
78
+ ): string {
79
+ return `Anvil cannot be used from ${formatAnvilHardBlockedPrivacySignals(
80
+ signals,
81
+ )} traffic. Please disable it and try again.`
82
+ }
@@ -0,0 +1,103 @@
1
+ import { ANVIL_STREAK_REWARDS_ENABLED } from '../constants/anvil-models'
2
+ import {
3
+ getAnvilStreakGlmWeeklyUnits,
4
+ isAnvilStreakGlmBonusActive,
5
+ } from './anvil-streak'
6
+
7
+ /** Days in a streak "week" — the milestone the progress dots fill toward. */
8
+ export const ANVIL_STREAK_WEEK = 7
9
+
10
+ export interface AnvilStreakLine {
11
+ /** Count label, e.g. "2 day streak". */
12
+ label: string
13
+ /** A week's worth of progress dots toward the 7-day milestone, e.g.
14
+ * "●●○○○○○". Fills to "●●●●●●●" at 7, then gains a trailing "+"
15
+ * ("●●●●●●●+") for any streak beyond the week so long runs read as
16
+ * "earned and still going" rather than just maxed out. */
17
+ dots: string
18
+ /** The same progress as counts, for a surface that draws its own dots rather
19
+ * than glyphs (the desktop app draws CSS circles). `total` is always
20
+ * ANVIL_STREAK_WEEK, carried so a renderer that can't import this module
21
+ * knows how many slots to draw; `beyond` is the trailing "+". */
22
+ progress: { filled: number; total: number; beyond: boolean }
23
+ }
24
+
25
+ /** Glyph pair used to draw the progress dots. */
26
+ export interface AnvilStreakDotChars {
27
+ filled: string
28
+ empty: string
29
+ }
30
+
31
+ /**
32
+ * Pure presentation logic for the streak line shown on the CLI landing screen
33
+ * and the desktop account popover: a plain count plus a week of filled/empty
34
+ * progress dots. Returns null for streak <= 0 so the caller hides the row
35
+ * entirely — new / lapsed users should be nudged to start using the product,
36
+ * not shown an empty streak.
37
+ *
38
+ * The glyphs default to ●/○, which is what a real UI font renders best; a
39
+ * surface whose font can't be trusted with those passes its own pair.
40
+ */
41
+ export function getAnvilStreakLine(
42
+ streak: number,
43
+ chars: AnvilStreakDotChars = { filled: '●', empty: '○' },
44
+ ): AnvilStreakLine | null {
45
+ if (streak <= 0) return null
46
+
47
+ // Fill toward the 7-day milestone, then stay full — a 19-day streak should
48
+ // read as fully earned, not roll back over into a partial second week. Past
49
+ // the week, a trailing "+" marks that the streak has run beyond the row.
50
+ const filled = Math.min(streak, ANVIL_STREAK_WEEK)
51
+ const beyond = streak > ANVIL_STREAK_WEEK
52
+ const dots =
53
+ chars.filled.repeat(filled) +
54
+ chars.empty.repeat(ANVIL_STREAK_WEEK - filled) +
55
+ (beyond ? '+' : '')
56
+
57
+ // "day" stays singular — it's a compound modifier ("7 day streak"), not a
58
+ // count of days on its own.
59
+ return {
60
+ label: `${streak} day streak`,
61
+ dots,
62
+ progress: { filled, total: ANVIL_STREAK_WEEK, beyond },
63
+ }
64
+ }
65
+
66
+ /**
67
+ * A short perk note for an active streak. Below the 7-day milestone it teases
68
+ * the countdown ("N more days to unlock …") so the reward motivates the users
69
+ * who haven't earned it yet; at 7+ it flips to describing the perk they're now
70
+ * receiving. Returns null with no streak at all (the streak row is hidden then
71
+ * too — a lapsed user needs a first day, not a countdown from seven).
72
+ *
73
+ * The daily-pool bonus (+1 session) recurs **every day** the streak stays at 7+,
74
+ * so it's framed as "every day". The GLM 5.2 bonus refills with the GLM pool —
75
+ * daily since 2026-07-29 (weekly before) — while the streak remains active and
76
+ * grows with the streak (one session per completed 7 days, max 4), so the
77
+ * earned line shows the current tier's count. The exact remaining GLM count
78
+ * lives in the referral banner; this line is the motivational why. GLM is
79
+ * full-access only, so limited users get the daily session bonus alone.
80
+ */
81
+ export function getAnvilStreakBonusNote(params: {
82
+ streak: number
83
+ accessTier: 'full' | 'limited'
84
+ }): string | null {
85
+ if (!ANVIL_STREAK_REWARDS_ENABLED) return null
86
+ if (params.streak <= 0) return null
87
+ // Only advertise GLM when the recurring full-access streak entitlement is
88
+ // active, so the copy never promises a perk the gate won't honor.
89
+ const includesGlm =
90
+ params.accessTier === 'full' && isAnvilStreakGlmBonusActive()
91
+ // Below the milestone this is the first tier being unlocked (1/day); at 7+
92
+ // it's whatever tier the current streak has earned (up to 4/day).
93
+ const glmDaily = Math.max(1, getAnvilStreakGlmWeeklyUnits(params.streak))
94
+ const perk = includesGlm
95
+ ? `+1 bonus session every day + ${glmDaily} GLM 5.2 ${glmDaily === 1 ? 'session' : 'sessions'} each day`
96
+ : '+1 bonus session every day'
97
+
98
+ if (params.streak < ANVIL_STREAK_WEEK) {
99
+ const remaining = ANVIL_STREAK_WEEK - params.streak
100
+ return `🎁 ${remaining} more ${remaining === 1 ? 'day' : 'days'} to unlock ${perk}`
101
+ }
102
+ return `🎁 Streak perk: ${perk}`
103
+ }
@@ -0,0 +1,156 @@
1
+ import {
2
+ ANVIL_GLM_V52_REFERRAL_ENABLED,
3
+ ANVIL_PREMIUM_SESSION_RESET_TIMEZONE,
4
+ ANVIL_STREAK_GLM_BONUS_ENABLED,
5
+ ANVIL_STREAK_GLM_BONUS_MAX_MULTIPLIER,
6
+ ANVIL_STREAK_BONUS_SESSION_UNITS,
7
+ ANVIL_STREAK_REWARD_INTERVAL_DAYS,
8
+ ANVIL_STREAK_REWARDS_ENABLED,
9
+ } from '../constants/anvil-models'
10
+
11
+ import type {
12
+ AnvilAccessTier,
13
+ AnvilStreakRewardPool,
14
+ } from '../constants/anvil-models'
15
+
16
+ export const ANVIL_STREAK_TIME_ZONE = ANVIL_PREMIUM_SESSION_RESET_TIMEZONE
17
+
18
+ const DAY_MS = 24 * 60 * 60 * 1000
19
+
20
+ function dateKeyFromParts(parts: Intl.DateTimeFormatPart[]): string {
21
+ const get = (type: Intl.DateTimeFormatPartTypes) =>
22
+ parts.find((part) => part.type === type)?.value
23
+
24
+ const year = get('year')
25
+ const month = get('month')
26
+ const day = get('day')
27
+
28
+ if (!year || !month || !day) {
29
+ throw new Error('Failed to format Anvil usage date')
30
+ }
31
+
32
+ return `${year}-${month}-${day}`
33
+ }
34
+
35
+ export function getAnvilUsageDateKey(
36
+ now: Date = new Date(),
37
+ timeZone = ANVIL_STREAK_TIME_ZONE,
38
+ ): string {
39
+ return dateKeyFromParts(
40
+ new Intl.DateTimeFormat('en-US', {
41
+ timeZone,
42
+ year: 'numeric',
43
+ month: '2-digit',
44
+ day: '2-digit',
45
+ }).formatToParts(now),
46
+ )
47
+ }
48
+
49
+ export function addDaysToDateKey(dateKey: string, days: number): string {
50
+ const date = new Date(`${dateKey}T00:00:00.000Z`)
51
+ if (Number.isNaN(date.getTime())) {
52
+ throw new Error(`Invalid date key: ${dateKey}`)
53
+ }
54
+
55
+ return new Date(date.getTime() + days * DAY_MS).toISOString().slice(0, 10)
56
+ }
57
+
58
+ export function calculateAnvilStreak(params: {
59
+ usageDates: readonly string[]
60
+ todayDateKey: string
61
+ }): {
62
+ streak: number
63
+ todayUsed: boolean
64
+ lastUsageDate: string | null
65
+ } {
66
+ const { usageDates, todayDateKey } = params
67
+ const usageDateSet = new Set(
68
+ usageDates.filter((date) => date <= todayDateKey),
69
+ )
70
+ const lastUsageDate = usageDates.reduce<string | null>((latest, date) => {
71
+ if (date > todayDateKey) return latest
72
+ return latest === null || date > latest ? date : latest
73
+ }, null)
74
+ const todayUsed = usageDateSet.has(todayDateKey)
75
+
76
+ let anchorDateKey = todayDateKey
77
+ if (!todayUsed) {
78
+ const yesterdayDateKey = addDaysToDateKey(todayDateKey, -1)
79
+ if (!usageDateSet.has(yesterdayDateKey)) {
80
+ return { streak: 0, todayUsed, lastUsageDate }
81
+ }
82
+ anchorDateKey = yesterdayDateKey
83
+ }
84
+
85
+ let streak = 0
86
+ for (
87
+ let cursor = anchorDateKey;
88
+ usageDateSet.has(cursor);
89
+ cursor = addDaysToDateKey(cursor, -1)
90
+ ) {
91
+ streak++
92
+ }
93
+
94
+ return { streak, todayUsed, lastUsageDate }
95
+ }
96
+
97
+ /**
98
+ * Whether the full-access GLM 5.2 streak bonus is currently active. Requires all
99
+ * three switches: streak rewards on, the GLM streak sub-switch on, AND the GLM
100
+ * program itself live — GLM is only launchable from the referral banner, which
101
+ * is hidden when the referral program is wound down, so a GLM bonus granted
102
+ * while it's off would be unusable. Keeping the grant and the advertised perk
103
+ * gated on the same predicate avoids that mismatch.
104
+ */
105
+ export function isAnvilStreakGlmBonusActive(): boolean {
106
+ return (
107
+ ANVIL_STREAK_REWARDS_ENABLED &&
108
+ ANVIL_STREAK_GLM_BONUS_ENABLED &&
109
+ ANVIL_GLM_V52_REFERRAL_ENABLED
110
+ )
111
+ }
112
+
113
+ /** GLM sessions per pool window earned by a streak of `streak` days, ignoring
114
+ * the feature gates: one per completed 7-day interval, capped at
115
+ * `ANVIL_STREAK_GLM_BONUS_MAX_MULTIPLIER` (a 28-day streak earns the max).
116
+ * The GLM pool resets daily since 2026-07-29 (weekly before), so these units
117
+ * refill at that cadence. The name keeps its historical "Weekly". */
118
+ export function getAnvilStreakGlmWeeklyUnits(streak: number): number {
119
+ const tiers = Math.min(
120
+ Math.floor(streak / ANVIL_STREAK_REWARD_INTERVAL_DAYS),
121
+ ANVIL_STREAK_GLM_BONUS_MAX_MULTIPLIER,
122
+ )
123
+ return tiers * ANVIL_STREAK_BONUS_SESSION_UNITS
124
+ }
125
+
126
+ /** Resolve the live GLM bonus directly from usage dates. The GLM pool gets +1
127
+ * per completed 7 days of the current streak (7 → 1, 14 → 2, capped at 4 for
128
+ * 28+) and refills at the pool reset (daily Pacific since 2026-07-29); once
129
+ * the streak breaks it gets 0. */
130
+ export function getAnvilStreakGlmBonusUnits(params: {
131
+ usageDates: readonly string[]
132
+ todayDateKey: string
133
+ }): number {
134
+ if (!isAnvilStreakGlmBonusActive()) return 0
135
+ const { streak } = calculateAnvilStreak(params)
136
+ return getAnvilStreakGlmWeeklyUnits(streak)
137
+ }
138
+
139
+ /**
140
+ * The daily streak-reward pool to persist after today's first usage, or `null`
141
+ * when nothing should be awarded. Full-access users receive a premium bonus;
142
+ * limited-access users receive a limited-pool bonus. GLM is intentionally not
143
+ * returned: its weekly +1 is derived live from usage dates, so it refills with
144
+ * the weekly quota and shuts off with the streak instead of becoming a one-time
145
+ * ledger grant.
146
+ */
147
+ export function getAnvilDailyStreakRewardPool(params: {
148
+ streak: number
149
+ todayUsed: boolean
150
+ accessTier: AnvilAccessTier
151
+ }): Exclude<AnvilStreakRewardPool, 'glm'> | null {
152
+ if (!ANVIL_STREAK_REWARDS_ENABLED) return null
153
+ if (!params.todayUsed) return null
154
+ if (params.streak < ANVIL_STREAK_REWARD_INTERVAL_DAYS) return null
155
+ return params.accessTier === 'limited' ? 'limited' : 'premium'
156
+ }
@@ -0,0 +1,125 @@
1
+ import { ANVIL_USAGE_MAP_DAYS } from '../constants/anvil-models'
2
+
3
+ import {
4
+ addDaysToDateKey,
5
+ calculateAnvilStreak,
6
+ ANVIL_STREAK_TIME_ZONE,
7
+ } from './anvil-streak'
8
+
9
+ import type {
10
+ AnvilRecentUsage,
11
+ AnvilUsageSessionsByModel,
12
+ AnvilUsageSummary,
13
+ } from '../types/anvil-usage'
14
+
15
+ /**
16
+ * The longest run of consecutive active days in `dateKeys`.
17
+ *
18
+ * Unlike the current streak this has no grace day: a gap ends the run outright.
19
+ * The current streak treats "used yesterday, not yet today" as alive because
20
+ * the day is not over; a historical run has no such ambiguity.
21
+ */
22
+ export function calculateLongestAnvilStreak(
23
+ dateKeys: readonly string[],
24
+ ): number {
25
+ const sorted = [...new Set(dateKeys)].sort()
26
+ let longest = 0
27
+ let run = 0
28
+ let previous: string | null = null
29
+
30
+ for (const dateKey of sorted) {
31
+ run =
32
+ previous !== null && addDaysToDateKey(previous, 1) === dateKey ? run + 1 : 1
33
+ previous = dateKey
34
+ if (run > longest) longest = run
35
+ }
36
+
37
+ return longest
38
+ }
39
+
40
+ /**
41
+ * Assemble the account hub's summary from the account's active dates.
42
+ *
43
+ * Pure, so the CLI, Desktop and web all describe usage identically and the
44
+ * arithmetic is testable without a database. `activeDates` may arrive in any
45
+ * order and may include days after `todayDateKey` (a client whose clock has run
46
+ * ahead of the Pacific date key); both are normalised here.
47
+ */
48
+ export function buildAnvilUsageSummary(params: {
49
+ activeDates: readonly string[]
50
+ todayDateKey: string
51
+ recent?: AnvilRecentUsage | null
52
+ sessionsByModel?: readonly AnvilUsageSessionsByModel[]
53
+ windowDays?: number
54
+ timeZone?: string
55
+ }): AnvilUsageSummary {
56
+ const windowDays = Math.max(1, params.windowDays ?? ANVIL_USAGE_MAP_DAYS)
57
+ const todayDateKey = params.todayDateKey
58
+
59
+ const allDates = [...new Set(params.activeDates)]
60
+ .filter((date) => date <= todayDateKey)
61
+ .sort()
62
+
63
+ const windowStart = addDaysToDateKey(todayDateKey, -(windowDays - 1))
64
+ const { streak, todayUsed, lastUsageDate } = calculateAnvilStreak({
65
+ usageDates: allDates,
66
+ todayDateKey,
67
+ })
68
+
69
+ return {
70
+ timeZone: params.timeZone ?? ANVIL_STREAK_TIME_ZONE,
71
+ todayDateKey,
72
+ streak: {
73
+ current: streak,
74
+ longest: calculateLongestAnvilStreak(allDates),
75
+ todayUsed,
76
+ lastUsageDate,
77
+ },
78
+ activeDates: allDates.filter((date) => date >= windowStart),
79
+ windowDays,
80
+ allTimeActiveDays: allDates.length,
81
+ recent: params.recent ?? null,
82
+ sessionsByModel: [...(params.sessionsByModel ?? [])],
83
+ }
84
+ }
85
+
86
+ /** One cell of the activity map: an active day, a quiet day, or padding. */
87
+ export type AnvilUsageCell =
88
+ | { date: string; active: boolean }
89
+ | null
90
+
91
+ /**
92
+ * Expand the active dates into the fixed grid the activity map draws: every day
93
+ * in the window, quiet days included, oldest first.
94
+ *
95
+ * The grid is laid out in columns of seven, so the first column is padded with
96
+ * `null` for the days before the window began and the last for the days after
97
+ * today. Callers render `null` as empty space, not as a quiet day — those days
98
+ * either predate the window or have not happened yet.
99
+ */
100
+ export function buildAnvilUsageGrid(params: {
101
+ activeDates: readonly string[]
102
+ todayDateKey: string
103
+ windowDays: number
104
+ /** 0 = Sunday. The weekday `todayDateKey` falls on, resolved by the caller
105
+ * in the streak time zone rather than from the viewer's clock. */
106
+ todayWeekday: number
107
+ }): AnvilUsageCell[] {
108
+ const active = new Set(params.activeDates)
109
+ const cells: AnvilUsageCell[] = []
110
+
111
+ // Pad to whole weeks so the last column ends on today's weekday and every row
112
+ // is one weekday throughout the grid.
113
+ const trailingPad = 6 - params.todayWeekday
114
+ const start = addDaysToDateKey(params.todayDateKey, -(params.windowDays - 1))
115
+ const leadingPad = (7 - ((params.windowDays + trailingPad) % 7)) % 7
116
+
117
+ for (let index = 0; index < leadingPad; index++) cells.push(null)
118
+ for (let index = 0; index < params.windowDays; index++) {
119
+ const date = addDaysToDateKey(start, index)
120
+ cells.push({ date, active: active.has(date) })
121
+ }
122
+ for (let index = 0; index < trailingPad; index++) cells.push(null)
123
+
124
+ return cells
125
+ }
@@ -0,0 +1,31 @@
1
+ import { compact, flattenDeep, isEqual } from 'lodash'
2
+
3
+ export function filterDefined<T>(array: (T | null | undefined)[]) {
4
+ return array.filter((item) => item !== null && item !== undefined) as T[]
5
+ }
6
+
7
+ type Falsey = false | undefined | null | 0 | ''
8
+ type FalseyValueArray<T> = T | Falsey | FalseyValueArray<T>[]
9
+
10
+ export function buildArray<T>(...params: FalseyValueArray<T>[]) {
11
+ return compact(flattenDeep(params)) as T[]
12
+ }
13
+
14
+ export function groupConsecutive<T, U>(xs: T[], key: (x: T) => U) {
15
+ if (!xs.length) {
16
+ return []
17
+ }
18
+ const result: any[] = []
19
+ let curr = { key: key(xs[0]), items: [xs[0]] }
20
+ for (const x of xs.slice(1)) {
21
+ const k = key(x)
22
+ if (!isEqual(k, curr.key)) {
23
+ result.push(curr)
24
+ curr = { key: k, items: [x] }
25
+ } else {
26
+ curr.items.push(x)
27
+ }
28
+ }
29
+ result.push(curr)
30
+ return result
31
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Operational events that belong in Axiom but not in product analytics.
3
+ *
4
+ * CLI logs normally redact structured info payloads before shipping and also
5
+ * mirror a sampled `cli_log` event to PostHog. This allowlist lets a small set
6
+ * of content-free operational events retain useful numeric/string/boolean
7
+ * metadata in Axiom without becoming product events or providing a general
8
+ * redaction bypass — each event declares an explicit field allowlist, and
9
+ * unknown keys or unexpected value types are always discarded.
10
+ */
11
+
12
+ export const CONTEXT_PRUNING_COMPLETED_EVENT =
13
+ 'context_pruning.completed' as const
14
+
15
+ /** Stream-cut / output-limit recovery (sdk/src/impl/stream-interruption.ts,
16
+ * packages/agent-runtime/src/tools/stream-parser.ts). `metric` distinguishes
17
+ * the log sites (stream_recovery_detected / _rescued) that share this one
18
+ * allowlisted event — `_gave_up` logs at error level, which already ships
19
+ * raw and doesn't need the allowlist. */
20
+ export const STREAM_RECOVERY_EVENT = 'stream_recovery' as const
21
+
22
+ type AxiomOnlyFieldType = 'string' | 'number' | 'boolean'
23
+ type AxiomOnlyFieldSchema = Record<string, AxiomOnlyFieldType>
24
+
25
+ const CONTEXT_PRUNING_FIELDS = {
26
+ agent_run_id: 'string',
27
+ parent_agent_run_id: 'string',
28
+ client_session_id: 'string',
29
+ client_request_id: 'string',
30
+ trigger_reason: 'string',
31
+ context_token_count: 'number',
32
+ max_context_length: 'number',
33
+ cache_gap_ms: 'number',
34
+ cache_expiry_ms: 'number',
35
+ previous_summary_entry_count: 'number',
36
+ user_budget: 'number',
37
+ user_entry_count: 'number',
38
+ dropped_user_entry_count: 'number',
39
+ assistant_tool_budget: 'number',
40
+ assistant_tool_entry_count: 'number',
41
+ dropped_assistant_tool_entry_count: 'number',
42
+ summary_estimated_tokens: 'number',
43
+ mid_turn: 'boolean',
44
+ live_user_prompt_found: 'boolean',
45
+ live_user_prompt_text_preserved: 'boolean',
46
+ newest_entry_forced: 'boolean',
47
+ } as const satisfies AxiomOnlyFieldSchema
48
+
49
+ const STREAM_RECOVERY_FIELDS = {
50
+ metric: 'string',
51
+ source: 'string',
52
+ model: 'string',
53
+ agentId: 'string',
54
+ runId: 'string',
55
+ userInputId: 'string',
56
+ finishReason: 'string',
57
+ hasYieldedContent: 'boolean',
58
+ consecutive: 'number',
59
+ } as const satisfies AxiomOnlyFieldSchema
60
+
61
+ export type AxiomOnlyLogEvent = {
62
+ event:
63
+ | typeof CONTEXT_PRUNING_COMPLETED_EVENT
64
+ | typeof STREAM_RECOVERY_EVENT
65
+ data: Record<string, string | number | boolean>
66
+ }
67
+
68
+ /** Keep only the allowlisted keys whose value matches the declared type
69
+ * (strings truncated); everything else is dropped. */
70
+ function sanitizeAllowlistedFields(
71
+ record: Record<string, unknown>,
72
+ fields: AxiomOnlyFieldSchema,
73
+ ): AxiomOnlyLogEvent['data'] {
74
+ const sanitized: AxiomOnlyLogEvent['data'] = {}
75
+ for (const [key, expectedType] of Object.entries(fields)) {
76
+ const value = record[key]
77
+ if (typeof value !== expectedType) continue
78
+ if (typeof value === 'string') {
79
+ sanitized[key] = value.slice(0, 200)
80
+ } else if (typeof value === 'number' && Number.isFinite(value)) {
81
+ sanitized[key] = value
82
+ } else if (typeof value === 'boolean') {
83
+ sanitized[key] = value
84
+ }
85
+ }
86
+ return sanitized
87
+ }
88
+
89
+ /**
90
+ * Return a sanitized Axiom-only event, or null for ordinary logger payloads.
91
+ * The event name comes from `data.axiomEvent` (the in-process marker set at
92
+ * the log call site) or the `event` param (the wire-format field a caller
93
+ * already extracted, e.g. the server-side sink re-checking a persisted
94
+ * `LogRow`). Unknown keys and unexpected value types are deliberately
95
+ * discarded.
96
+ *
97
+ * Matched by exact equality (not a lookup keyed on the caller-supplied name)
98
+ * so a value like 'constructor' can't resolve through an object's prototype.
99
+ */
100
+ export function getAxiomOnlyLogEvent(
101
+ data: unknown,
102
+ event?: string | null,
103
+ ): AxiomOnlyLogEvent | null {
104
+ const record =
105
+ data != null && typeof data === 'object' && !Array.isArray(data)
106
+ ? (data as Record<string, unknown>)
107
+ : {}
108
+ const eventName =
109
+ typeof record.axiomEvent === 'string' ? record.axiomEvent : event
110
+
111
+ if (eventName === CONTEXT_PRUNING_COMPLETED_EVENT) {
112
+ return {
113
+ event: eventName,
114
+ data: sanitizeAllowlistedFields(record, CONTEXT_PRUNING_FIELDS),
115
+ }
116
+ }
117
+ if (eventName === STREAM_RECOVERY_EVENT) {
118
+ return {
119
+ event: eventName,
120
+ data: sanitizeAllowlistedFields(record, STREAM_RECOVERY_FIELDS),
121
+ }
122
+ }
123
+ return null
124
+ }