@alumbwe/anvil 1.0.20 → 1.0.21

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 +6 -2
  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,132 @@
1
+ import { createHash } from 'node:crypto'
2
+
3
+ import { describe, expect, test } from 'bun:test'
4
+
5
+ import {
6
+ buildRedditCustomConversionBody,
7
+ redditConversionId,
8
+ RedditCapiDeliveryError,
9
+ sendRedditCustomConversion,
10
+ } from '../reddit-capi'
11
+
12
+ const sha256 = (value: string) =>
13
+ createHash('sha256').update(value).digest('hex')
14
+
15
+ describe('Reddit CAPI', () => {
16
+ test('builds a documented v3 custom-event payload', () => {
17
+ const body = buildRedditCustomConversionBody({
18
+ customEventName: 'FirstPrompt',
19
+ conversionId: 'conversion-1',
20
+ actionSource: 'WEBSITE',
21
+ eventSourceUrl: 'https://anvil.com/chat?utm_source=reddit',
22
+ testId: 'test-123',
23
+ eventAt: 123,
24
+ user: {
25
+ email: 'Al.ice+Apple@Example.Com',
26
+ externalId: ' user-123 ',
27
+ ipAddress: '203.0.113.10',
28
+ userAgent: 'Browser',
29
+ clickId: 'reddit-click',
30
+ uuid: 'pixel-uuid',
31
+ },
32
+ })
33
+
34
+ expect(body).toEqual({
35
+ data: {
36
+ test_id: 'test-123',
37
+ events: [
38
+ {
39
+ event_at: 123,
40
+ action_source: 'WEBSITE',
41
+ event_source_url:
42
+ 'https://anvil.com/chat?utm_source=reddit&rdt_cid=reddit-click',
43
+ type: {
44
+ tracking_type: 'CUSTOM',
45
+ custom_event_name: 'FirstPrompt',
46
+ },
47
+ click_id: 'reddit-click',
48
+ metadata: { conversion_id: 'conversion-1' },
49
+ user: {
50
+ email: sha256('alice@example.com'),
51
+ external_id: sha256('user-123'),
52
+ ip_address: '203.0.113.10',
53
+ user_agent: 'Browser',
54
+ uuid: 'pixel-uuid',
55
+ },
56
+ },
57
+ ],
58
+ },
59
+ })
60
+ expect(body.data.events[0]?.user).not.toHaveProperty('click_id')
61
+ expect(body.data).not.toHaveProperty('partner')
62
+ })
63
+
64
+ test('uses a stable opaque conversion id per user and event', () => {
65
+ expect(redditConversionId('FirstPrompt', 'user-123')).toBe(
66
+ sha256('FirstPrompt:user-123'),
67
+ )
68
+ expect(redditConversionId('Retention1d', 'user-123')).not.toBe(
69
+ redditConversionId('FirstPrompt', 'user-123'),
70
+ )
71
+ })
72
+
73
+ test('retries one transient failure', async () => {
74
+ let attempts = 0
75
+ const result = await sendRedditCustomConversion({
76
+ enabled: true,
77
+ accessToken: 'secret',
78
+ customEventName: 'Retention1d',
79
+ conversionId: 'conversion-1',
80
+ actionSource: 'OTHER',
81
+ user: { externalId: 'user-1' },
82
+ sleepImpl: async () => {},
83
+ fetchImpl: (async () => {
84
+ attempts += 1
85
+ return attempts === 1
86
+ ? new Response('retry', { status: 503 })
87
+ : Response.json({ data: { message: 'ok' } })
88
+ }) as unknown as typeof fetch,
89
+ })
90
+
91
+ expect(result).toBe('sent')
92
+ expect(attempts).toBe(2)
93
+ })
94
+
95
+ test('does not retry permanent failures', async () => {
96
+ let attempts = 0
97
+ await expect(
98
+ sendRedditCustomConversion({
99
+ enabled: true,
100
+ accessToken: 'secret',
101
+ customEventName: 'FirstPrompt',
102
+ conversionId: 'conversion-1',
103
+ actionSource: 'WEBSITE',
104
+ user: { externalId: 'user-1' },
105
+ sleepImpl: async () => {},
106
+ fetchImpl: (async () => {
107
+ attempts += 1
108
+ return new Response('invalid', { status: 400 })
109
+ }) as unknown as typeof fetch,
110
+ }),
111
+ ).rejects.toBeInstanceOf(RedditCapiDeliveryError)
112
+ expect(attempts).toBe(1)
113
+ })
114
+
115
+ test('is disabled without production enablement or a token', async () => {
116
+ let called = false
117
+ const result = await sendRedditCustomConversion({
118
+ enabled: false,
119
+ accessToken: 'secret',
120
+ customEventName: 'FirstPrompt',
121
+ conversionId: 'conversion-1',
122
+ actionSource: 'WEBSITE',
123
+ user: {},
124
+ fetchImpl: (async () => {
125
+ called = true
126
+ return Response.json({})
127
+ }) as unknown as typeof fetch,
128
+ })
129
+ expect(result).toBe('disabled')
130
+ expect(called).toBe(false)
131
+ })
132
+ })
@@ -0,0 +1,72 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+
3
+ import {
4
+ responseAdNodePositions,
5
+ responseAdSlotCount,
6
+ RESPONSE_AD_FIRST_NODE_COUNT,
7
+ RESPONSE_AD_NODE_STEP,
8
+ } from '../util/response-ad-positions'
9
+
10
+ describe('responseAdNodePositions', () => {
11
+ test('places nothing in a response too short to intersperse', () => {
12
+ expect(responseAdNodePositions({ nodeCount: 0, adCount: 3 })).toEqual([])
13
+ expect(responseAdNodePositions({ nodeCount: 1, adCount: 3 })).toEqual([])
14
+ expect(responseAdNodePositions({ nodeCount: 2, adCount: 3 })).toEqual([])
15
+ })
16
+
17
+ test('keeps the first ad after two nodes, then spaces ads every three nodes', () => {
18
+ expect(RESPONSE_AD_FIRST_NODE_COUNT).toBe(2)
19
+ expect(RESPONSE_AD_NODE_STEP).toBe(3)
20
+ expect(responseAdNodePositions({ nodeCount: 2, adCount: 4 })).toEqual([])
21
+ expect(responseAdNodePositions({ nodeCount: 3, adCount: 4 })).toEqual([1])
22
+ expect(responseAdNodePositions({ nodeCount: 4, adCount: 4 })).toEqual([1])
23
+ expect(responseAdNodePositions({ nodeCount: 6, adCount: 4 })).toEqual([1, 4])
24
+ expect(responseAdNodePositions({ nodeCount: 9, adCount: 4 })).toEqual([1, 4, 7])
25
+ })
26
+
27
+ test('eligible display slots are not capped at eight', () => {
28
+ expect(responseAdSlotCount({ nodeCount: 2 })).toBe(0)
29
+ expect(responseAdSlotCount({ nodeCount: 3 })).toBe(1)
30
+ expect(responseAdSlotCount({ nodeCount: 24 })).toBe(8)
31
+ expect(responseAdSlotCount({ nodeCount: 27 })).toBe(9)
32
+ expect(responseAdNodePositions({ nodeCount: 27, adCount: 9 })).toEqual([
33
+ 1, 4, 7, 10, 13, 16, 19, 22, 25,
34
+ ])
35
+ })
36
+
37
+ test('never places more ads than provided', () => {
38
+ expect(responseAdNodePositions({ nodeCount: 20, adCount: 2 })).toEqual([1, 4])
39
+ expect(responseAdNodePositions({ nodeCount: 20, adCount: 0 })).toEqual([])
40
+ })
41
+
42
+ test('positions are stable as the streaming response appends nodes', () => {
43
+ let previous: number[] = []
44
+ for (let nodeCount = 0; nodeCount <= 12; nodeCount++) {
45
+ const next = responseAdNodePositions({ nodeCount, adCount: 3 })
46
+ expect(next.slice(0, previous.length)).toEqual(previous)
47
+ previous = next
48
+ }
49
+ })
50
+
51
+ test('allows the first-ad offset to differ from recurring spacing', () => {
52
+ expect(
53
+ responseAdNodePositions({
54
+ nodeCount: 8,
55
+ adCount: 3,
56
+ firstAdAfterNodes: 3,
57
+ step: 2,
58
+ }),
59
+ ).toEqual([2, 4, 6])
60
+ })
61
+
62
+ test('clamps non-positive placement settings to one', () => {
63
+ expect(
64
+ responseAdNodePositions({
65
+ nodeCount: 4,
66
+ adCount: 3,
67
+ firstAdAfterNodes: 0,
68
+ step: 0,
69
+ }),
70
+ ).toEqual([0, 1, 2])
71
+ })
72
+ })
@@ -0,0 +1,30 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+
3
+ import { getUserState, UserState } from '../old-constants'
4
+
5
+ describe('getUserState', () => {
6
+ test('returns LOGGED_OUT for unauthenticated users regardless of credits', () => {
7
+ expect(getUserState(false, 1000)).toBe(UserState.LOGGED_OUT)
8
+ expect(getUserState(false, 0)).toBe(UserState.LOGGED_OUT)
9
+ })
10
+
11
+ test('returns GOOD_STANDING for users with >= 100 credits', () => {
12
+ expect(getUserState(true, 100)).toBe(UserState.GOOD_STANDING)
13
+ expect(getUserState(true, 500)).toBe(UserState.GOOD_STANDING)
14
+ })
15
+
16
+ test('returns ATTENTION_NEEDED for users with 20-99 credits', () => {
17
+ expect(getUserState(true, 99)).toBe(UserState.ATTENTION_NEEDED)
18
+ expect(getUserState(true, 20)).toBe(UserState.ATTENTION_NEEDED)
19
+ })
20
+
21
+ test('returns CRITICAL for users with 1-19 credits', () => {
22
+ expect(getUserState(true, 19)).toBe(UserState.CRITICAL)
23
+ expect(getUserState(true, 1)).toBe(UserState.CRITICAL)
24
+ })
25
+
26
+ test('returns DEPLETED for users with 0 or fewer credits', () => {
27
+ expect(getUserState(true, 0)).toBe(UserState.DEPLETED)
28
+ expect(getUserState(true, -100)).toBe(UserState.DEPLETED)
29
+ })
30
+ })
@@ -0,0 +1,215 @@
1
+ import { z } from 'zod/v4'
2
+
3
+ import type { GrantType } from './types/grant'
4
+ import type { MCPConfig } from './types/mcp'
5
+ import type { ToolMessage } from './types/messages/anvil-message'
6
+ import type {
7
+ TextPart,
8
+ ImagePart,
9
+ ToolResultOutput,
10
+ } from './types/messages/content-part'
11
+ import type { PrintModeEvent } from './types/print-mode'
12
+ import type { AgentOutput, SessionState, ToolCall } from './types/session-state'
13
+ import type { ProjectFileContext } from './util/file'
14
+
15
+ export const FileChangeSchema = z.object({
16
+ type: z.enum(['patch', 'file']),
17
+ path: z.string(),
18
+ content: z.string(),
19
+ })
20
+ export type FileChange = z.infer<typeof FileChangeSchema>
21
+ export const CHANGES = z.array(FileChangeSchema)
22
+ export type FileChanges = z.infer<typeof CHANGES>
23
+
24
+ type ClientActionPrompt = {
25
+ type: 'prompt'
26
+ promptId: string
27
+ prompt: string | undefined
28
+ content?: (TextPart | ImagePart)[]
29
+ promptParams?: Record<string, any> // Additional json params.
30
+ fingerprintId: string
31
+ authToken?: string
32
+ costMode?: string
33
+ sessionState: SessionState
34
+ toolResults: ToolMessage[]
35
+ model?: string
36
+ repoUrl?: string
37
+ agentId?: string
38
+ }
39
+
40
+ type ClientActionReadFilesResponse = {
41
+ type: 'read-files-response'
42
+ files: Record<string, string | null>
43
+ requestId?: string
44
+ }
45
+
46
+ type ClientActionInit = {
47
+ type: 'init'
48
+ fingerprintId: string
49
+ authToken?: string
50
+ fileContext: ProjectFileContext
51
+ repoUrl?: string
52
+ }
53
+
54
+ type ClientActionToolCallResponse = {
55
+ type: 'tool-call-response'
56
+ requestId: string
57
+ output: ToolResultOutput[]
58
+ }
59
+
60
+ type ClientActionCancelUserInput = {
61
+ type: 'cancel-user-input'
62
+ authToken: string
63
+ promptId: string
64
+ }
65
+
66
+ type ClientActionMcpToolData = {
67
+ type: 'mcp-tool-data'
68
+ requestId: string
69
+ tools: {
70
+ name: string
71
+ description?: string
72
+ inputSchema: { type: 'object';[k: string]: unknown }
73
+ }[]
74
+ }
75
+
76
+ type ClientActionAny =
77
+ | ClientActionPrompt
78
+ | ClientActionReadFilesResponse
79
+ | ClientActionInit
80
+ | ClientActionToolCallResponse
81
+ | ClientActionCancelUserInput
82
+ | ClientActionMcpToolData
83
+ type ClientActionType = ClientActionAny['type']
84
+ export type ClientAction<T extends ClientActionType = ClientActionType> = {
85
+ [K in ClientActionType]: Extract<
86
+ ClientActionAny,
87
+ {
88
+ type: K
89
+ }
90
+ >
91
+ }[T]
92
+
93
+ type ServerActionResponseChunk = {
94
+ type: 'response-chunk'
95
+ userInputId: string
96
+ chunk: string | PrintModeEvent
97
+ }
98
+
99
+ type ServerActionSubagentResponseChunk = {
100
+ type: 'subagent-response-chunk'
101
+ userInputId: string
102
+ agentId: string
103
+ agentType: string
104
+ chunk: string
105
+ prompt?: string
106
+ forwardToPrompt?: boolean
107
+ }
108
+
109
+ type ServerActionHandleStepsLogChunk = {
110
+ type: 'handlesteps-log-chunk'
111
+ userInputId: string
112
+ agentId: string
113
+ level: 'debug' | 'info' | 'warn' | 'error'
114
+ data: any
115
+ message?: string
116
+ }
117
+
118
+ export type PromptResponse = {
119
+ type: 'prompt-response'
120
+ promptId: string
121
+ sessionState: SessionState
122
+ toolCalls?: ToolCall[]
123
+ toolResults?: ToolMessage[]
124
+ output?: AgentOutput
125
+ }
126
+
127
+ type ServerActionReadFiles = {
128
+ type: 'read-files'
129
+ filePaths: string[]
130
+ requestId: string
131
+ }
132
+
133
+ type ServerActionToolCallRequest = {
134
+ type: 'tool-call-request'
135
+ userInputId: string
136
+ requestId: string
137
+ toolName: string
138
+ input: Record<string, any>
139
+ timeout?: number
140
+ mcpConfig?: MCPConfig
141
+ }
142
+
143
+ export type InitResponse = {
144
+ type: 'init-response'
145
+ message?: string
146
+ agentNames?: Record<string, string>
147
+ } & Omit<UsageResponse, 'type'>
148
+
149
+ export type UsageResponse = {
150
+ type: 'usage-response'
151
+ usage: number
152
+ remainingBalance: number
153
+ balanceBreakdown?: Record<GrantType, number>
154
+ next_quota_reset: Date | null
155
+ autoTopupAdded?: number
156
+ autoTopupEnabled?: boolean
157
+ }
158
+
159
+ export type MessageCostResponse = {
160
+ type: 'message-cost-response'
161
+ promptId: string
162
+ credits: number
163
+ agentId?: string
164
+ }
165
+
166
+ type ServerActionActionError = {
167
+ type: 'action-error'
168
+ message: string
169
+ error?: string
170
+ remainingBalance?: number
171
+ }
172
+
173
+ type ServerActionPromptError = {
174
+ type: 'prompt-error'
175
+ userInputId: string
176
+ message: string
177
+ error?: string
178
+ remainingBalance?: number
179
+ }
180
+
181
+ type ServerActionRequestReconnect = {
182
+ // The server is imminently going to shutdown, and the client should reconnect
183
+ type: 'request-reconnect'
184
+ }
185
+
186
+ type ServerActionRequestMcpToolData = {
187
+ type: 'request-mcp-tool-data'
188
+ requestId: string
189
+ mcpConfig: MCPConfig
190
+ toolNames?: string[]
191
+ }
192
+
193
+ type ServerActionAny =
194
+ | ServerActionResponseChunk
195
+ | ServerActionSubagentResponseChunk
196
+ | ServerActionHandleStepsLogChunk
197
+ | PromptResponse
198
+ | ServerActionReadFiles
199
+ | ServerActionToolCallRequest
200
+ | InitResponse
201
+ | UsageResponse
202
+ | MessageCostResponse
203
+ | ServerActionActionError
204
+ | ServerActionPromptError
205
+ | ServerActionRequestReconnect
206
+ | ServerActionRequestMcpToolData
207
+ type ServerActionType = ServerActionAny['type']
208
+ export type ServerAction<T extends ServerActionType = ServerActionType> = {
209
+ [K in ServerActionType]: Extract<
210
+ ServerActionAny,
211
+ {
212
+ type: K
213
+ }
214
+ >
215
+ }[T]
@@ -0,0 +1,69 @@
1
+ import { PostHog } from 'posthog-node'
2
+
3
+ /**
4
+ * Shared analytics core module.
5
+ * Provides common interfaces, types, and utilities used by both
6
+ * server-side (common/src/analytics.ts) and CLI (cli/src/utils/analytics.ts) analytics.
7
+ */
8
+
9
+ /** Interface for PostHog client methods used for event capture */
10
+ export interface AnalyticsClient {
11
+ capture: (params: {
12
+ distinctId: string
13
+ event: string
14
+ properties?: Record<string, any>
15
+ }) => void
16
+ flush: () => Promise<void>
17
+ }
18
+
19
+ /** Extended client interface with identify, alias, and exception capture (used by CLI) */
20
+ export interface AnalyticsClientWithIdentify extends AnalyticsClient {
21
+ identify: (params: {
22
+ distinctId: string
23
+ properties?: Record<string, any>
24
+ }) => void
25
+ /** Links an alias (previous anonymous ID) to a distinctId (real user ID) */
26
+ alias: (data: { distinctId: string; alias: string }) => void
27
+ captureException: (
28
+ error: any,
29
+ distinctId: string,
30
+ properties?: Record<string, any>,
31
+ ) => void
32
+ }
33
+
34
+ /** Environment name type */
35
+ export type AnalyticsEnvName = 'dev' | 'test' | 'prod'
36
+
37
+ /** Base analytics configuration */
38
+ export interface AnalyticsConfig {
39
+ envName: AnalyticsEnvName
40
+ posthogApiKey: string
41
+ posthogHostUrl: string
42
+ }
43
+
44
+ /** Options for creating a PostHog client */
45
+ export interface PostHogClientOptions {
46
+ host: string
47
+ flushAt?: number
48
+ flushInterval?: number
49
+ enableExceptionAutocapture?: boolean
50
+ }
51
+
52
+ /**
53
+ * Default PostHog client factory.
54
+ * Creates a real PostHog client instance.
55
+ */
56
+ export function createPostHogClient(
57
+ apiKey: string,
58
+ options: PostHogClientOptions,
59
+ ): AnalyticsClientWithIdentify {
60
+ return new PostHog(apiKey, options) as AnalyticsClientWithIdentify
61
+ }
62
+
63
+ /**
64
+ * Generates a unique anonymous ID for pre-login tracking.
65
+ * Uses crypto.randomUUID() for uniqueness.
66
+ */
67
+ export function generateAnonymousId(): string {
68
+ return `anon_${crypto.randomUUID()}`
69
+ }
@@ -0,0 +1,93 @@
1
+ import { env, DEBUG_ANALYTICS } from '@anvil/common/env'
2
+
3
+ import { createPostHogClient, type AnalyticsClient } from './analytics-core'
4
+ import { AnalyticsEvent } from './constants/analytics-events'
5
+
6
+ import type { TrackEventFn } from '@anvil/common/types/contracts/analytics'
7
+ import type { Logger } from '@anvil/common/types/contracts/logger'
8
+
9
+ let client: AnalyticsClient | undefined
10
+
11
+ export async function flushAnalytics(logger?: Logger) {
12
+ if (!client) {
13
+ return
14
+ }
15
+ try {
16
+ await client.flush()
17
+ } catch (error) {
18
+ // Log the error but don't throw - flushing is best-effort
19
+ logger?.warn({ error }, 'Failed to flush analytics')
20
+
21
+ // Track the flush failure event (will be queued for next successful flush)
22
+ try {
23
+ client.capture({
24
+ distinctId: 'system',
25
+ event: AnalyticsEvent.FLUSH_FAILED,
26
+ properties: {
27
+ error: error instanceof Error ? error.message : String(error),
28
+ },
29
+ })
30
+ } catch {
31
+ // Silently ignore if we can't even track the failure
32
+ }
33
+ }
34
+ }
35
+
36
+ export function withDefaultProperties(
37
+ trackEventFn: TrackEventFn,
38
+ defaultProperties: Record<string, unknown>,
39
+ ): TrackEventFn {
40
+ return (params) => {
41
+ trackEventFn({
42
+ ...params,
43
+ properties: { ...defaultProperties, ...params.properties },
44
+ })
45
+ }
46
+ }
47
+
48
+ export function trackEvent({
49
+ event,
50
+ userId,
51
+ properties,
52
+ logger,
53
+ }: {
54
+ event: AnalyticsEvent
55
+ userId: string
56
+ properties?: Record<string, any>
57
+ logger: Logger
58
+ }) {
59
+ // Don't track events in non-production environments
60
+ if (env.NEXT_PUBLIC_CB_ENVIRONMENT !== 'prod') {
61
+ if (DEBUG_ANALYTICS) {
62
+ logger.debug({ event, userId, properties }, `[analytics] ${event}`)
63
+ }
64
+ return
65
+ }
66
+
67
+ if (!client) {
68
+ try {
69
+ client = createPostHogClient(env.NEXT_PUBLIC_POSTHOG_API_KEY, {
70
+ host: env.NEXT_PUBLIC_POSTHOG_HOST_URL,
71
+ flushAt: 1,
72
+ flushInterval: 0,
73
+ })
74
+ } catch (error) {
75
+ logger.warn({ error }, 'Failed to initialize analytics client')
76
+ return
77
+ }
78
+ logger.info(
79
+ { envName: env.NEXT_PUBLIC_CB_ENVIRONMENT },
80
+ 'Analytics client initialized',
81
+ )
82
+ }
83
+
84
+ try {
85
+ client.capture({
86
+ distinctId: userId,
87
+ event,
88
+ properties,
89
+ })
90
+ } catch (error) {
91
+ logger.error({ error }, 'Failed to track event')
92
+ }
93
+ }
@@ -0,0 +1,26 @@
1
+ export const ALGORITHM = 'aes-256-gcm'
2
+ export const IV_LENGTH = 12
3
+ export const AUTH_TAG_LENGTH = 16
4
+
5
+ // --- Define valid API Key Types ---
6
+ // Used by db/schema.ts to define the pgEnum
7
+ // and by crypto.ts for type safety.
8
+ export const API_KEY_TYPES = ['anthropic', 'gemini', 'openai'] as const
9
+ export type ApiKeyType = (typeof API_KEY_TYPES)[number] // Derive the type from the constant
10
+
11
+ export const KEY_PREFIXES: Record<ApiKeyType, string> = {
12
+ anthropic: 'sk-ant-api03-',
13
+ gemini: 'AIzaSy',
14
+ openai: 'sk-proj-',
15
+ }
16
+ export const KEY_LENGTHS: Record<ApiKeyType, number> = {
17
+ anthropic: 108,
18
+ gemini: 39,
19
+ openai: 164,
20
+ }
21
+
22
+ export const READABLE_NAME: Record<ApiKeyType, string> = {
23
+ anthropic: 'Anthropic',
24
+ gemini: 'Gemini',
25
+ openai: 'Open AI',
26
+ }