@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,95 @@
1
+ import z from 'zod/v4'
2
+
3
+ export const CLIENT_ENV_PREFIX = 'NEXT_PUBLIC_'
4
+
5
+ export const clientEnvSchema = z.object({
6
+ NEXT_PUBLIC_CB_ENVIRONMENT: z.enum(['dev', 'test', 'prod']),
7
+ NEXT_PUBLIC_ANVIL_APP_URL: z.url().min(1),
8
+ NEXT_PUBLIC_SUPPORT_EMAIL: z.email().min(1),
9
+ NEXT_PUBLIC_POSTHOG_API_KEY: z.string().min(1),
10
+ NEXT_PUBLIC_POSTHOG_HOST_URL: z.url().min(1),
11
+ NEXT_PUBLIC_GRAVITY_PIXEL_ID: z.uuid().optional(),
12
+ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().min(1),
13
+ NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL: z.url().min(1),
14
+ NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION_ID: z.string().optional(),
15
+ NEXT_PUBLIC_WEB_PORT: z.coerce.number().min(1000),
16
+ /** Cloudflare Turnstile site key for the signup challenge. Public by design —
17
+ * the secret half is server-only (`TURNSTILE_SECRET_KEY`). Optional so a dev
18
+ * checkout without Turnstile configured still boots; the server gate decides
19
+ * whether a missing key means "skip" or "refuse". */
20
+ NEXT_PUBLIC_TURNSTILE_SITE_KEY: z.string().min(1).optional(),
21
+ /**
22
+ * Google reCAPTCHA site keys — BOTH versions, which run together rather than
23
+ * as alternatives. v3 scores the session invisibly; v2 asks the human to click
24
+ * a box. Public by design; the secret halves are `RECAPTCHA_V2_SECRET_KEY` and
25
+ * `RECAPTCHA_V3_SECRET_KEY`.
26
+ *
27
+ * These are two separate registrations in the reCAPTCHA console with two
28
+ * separate secrets, and the versions are NOT interchangeable: using a v2 key
29
+ * where a v3 one is expected throws `Invalid site key type`, mints no token,
30
+ * and is indistinguishable at the gate from a bot. Either may be omitted to
31
+ * run only the other; both optional so a dev checkout still boots.
32
+ */
33
+ NEXT_PUBLIC_RECAPTCHA_V2_SITE_KEY: z.string().min(1).optional(),
34
+ NEXT_PUBLIC_RECAPTCHA_V3_SITE_KEY: z.string().min(1).optional(),
35
+ /**
36
+ * Whether the v2 widget is a checkbox everyone clicks or an invisible check.
37
+ *
38
+ * `checkbox` buys nothing against bots that `invisible` does not: both are the
39
+ * same key type hitting the same risk engine, and both escalate to the same
40
+ * image challenge when Google is suspicious. The choice is purely how much
41
+ * friction to show a clean user, which is why it is one env value and not a
42
+ * design. NOTE that the key itself is registered as one or the other, so this
43
+ * has to match the registration — an invisible-registered key rejects
44
+ * `checkbox` outright.
45
+ *
46
+ * Optional rather than `.default('checkbox')`, with the default applied at the
47
+ * point of use. A `.default()` here would make this the only field in this
48
+ * schema whose OUTPUT type is required, and `clientEnv` is built as an object
49
+ * literal by fixtures across agent-runtime, evals and web — so it breaks all
50
+ * of them at the type level over a value none of them care about. Adding a
51
+ * DEFAULTED client env var is quietly a breaking change; an optional one is
52
+ * not.
53
+ */
54
+ NEXT_PUBLIC_RECAPTCHA_V2_SIZE: z.enum(['checkbox', 'invisible']).optional(),
55
+ /** Human Behavior session-replay write key for Anvil Web. Public by
56
+ * design — it only authorizes ingestion. Optional so a dev checkout without
57
+ * it boots with replay simply switched off. */
58
+ NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY: z.string().min(1).optional(),
59
+ /** Overrides the SDK's default ingestion host; only set to point a
60
+ * deployment at a non-default Human Behavior endpoint. */
61
+ NEXT_PUBLIC_HUMANBEHAVIOR_INGESTION_URL: z.url().optional(),
62
+ } satisfies Record<`${typeof CLIENT_ENV_PREFIX}${string}`, any>)
63
+ export const clientEnvVars = clientEnvSchema.keyof().options
64
+ export type ClientEnvVar = (typeof clientEnvVars)[number]
65
+ export type ClientInput = {
66
+ [K in (typeof clientEnvVars)[number]]: string | undefined
67
+ }
68
+ export type ClientEnv = z.infer<typeof clientEnvSchema>
69
+
70
+ // Bun will inject all these values, so we need to reference them individually (no for-loops)
71
+ export const clientProcessEnv: ClientInput = {
72
+ NEXT_PUBLIC_CB_ENVIRONMENT: process.env.NEXT_PUBLIC_CB_ENVIRONMENT,
73
+ NEXT_PUBLIC_ANVIL_APP_URL: process.env.NEXT_PUBLIC_ANVIL_APP_URL,
74
+ NEXT_PUBLIC_SUPPORT_EMAIL: process.env.NEXT_PUBLIC_SUPPORT_EMAIL,
75
+ NEXT_PUBLIC_POSTHOG_API_KEY: process.env.NEXT_PUBLIC_POSTHOG_API_KEY,
76
+ NEXT_PUBLIC_POSTHOG_HOST_URL: process.env.NEXT_PUBLIC_POSTHOG_HOST_URL,
77
+ NEXT_PUBLIC_GRAVITY_PIXEL_ID: process.env.NEXT_PUBLIC_GRAVITY_PIXEL_ID,
78
+ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY:
79
+ process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
80
+ NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL:
81
+ process.env.NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL,
82
+ NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION_ID:
83
+ process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION_ID,
84
+ NEXT_PUBLIC_WEB_PORT: process.env.NEXT_PUBLIC_WEB_PORT,
85
+ NEXT_PUBLIC_TURNSTILE_SITE_KEY: process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY,
86
+ NEXT_PUBLIC_RECAPTCHA_V2_SITE_KEY:
87
+ process.env.NEXT_PUBLIC_RECAPTCHA_V2_SITE_KEY,
88
+ NEXT_PUBLIC_RECAPTCHA_V3_SITE_KEY:
89
+ process.env.NEXT_PUBLIC_RECAPTCHA_V3_SITE_KEY,
90
+ NEXT_PUBLIC_RECAPTCHA_V2_SIZE: process.env.NEXT_PUBLIC_RECAPTCHA_V2_SIZE,
91
+ NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY:
92
+ process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY,
93
+ NEXT_PUBLIC_HUMANBEHAVIOR_INGESTION_URL:
94
+ process.env.NEXT_PUBLIC_HUMANBEHAVIOR_INGESTION_URL,
95
+ }
@@ -0,0 +1,24 @@
1
+ import { clientEnvSchema, clientProcessEnv } from './env-schema'
2
+
3
+ const parsedEnv = clientEnvSchema.safeParse(clientProcessEnv)
4
+ if (!parsedEnv.success) {
5
+ console.error('Environment validation failed:', parsedEnv.error.issues)
6
+ throw new Error(`Invalid environment configuration: ${parsedEnv.error.message}`)
7
+ }
8
+
9
+ export const env = parsedEnv.data
10
+
11
+ // Only log environment in non-production
12
+ if (env.NEXT_PUBLIC_CB_ENVIRONMENT !== 'prod') {
13
+ console.log('Using environment:', env.NEXT_PUBLIC_CB_ENVIRONMENT)
14
+ }
15
+
16
+ // Derived environment constants for convenience
17
+ export const IS_DEV = env.NEXT_PUBLIC_CB_ENVIRONMENT === 'dev'
18
+ export const IS_TEST = env.NEXT_PUBLIC_CB_ENVIRONMENT === 'test'
19
+ export const IS_PROD = env.NEXT_PUBLIC_CB_ENVIRONMENT === 'prod'
20
+ export const IS_CI = process.env.ANVIL_GITHUB_ACTIONS === 'true'
21
+
22
+ // Debug flag for logging analytics events in dev mode
23
+ // Set to true when actively debugging analytics - affects both CLI and backend
24
+ export const DEBUG_ANALYTICS = false
@@ -0,0 +1,207 @@
1
+ export const GRAVITY_CAPI_ENDPOINT = 'https://api.trygravity.ai/gateway/events'
2
+ export const GRAVITY_FIRST_MESSAGE_EVENT = 'FirstMessage'
3
+
4
+ export const ANVIL_GRAVITY_SURFACES = [
5
+ 'cli',
6
+ 'desktop',
7
+ 'web',
8
+ 'cloud',
9
+ 'chat',
10
+ ] as const
11
+ export type AnvilGravitySurface = (typeof ANVIL_GRAVITY_SURFACES)[number]
12
+ export type AnvilServiceGravitySurface = Extract<
13
+ AnvilGravitySurface,
14
+ 'web' | 'cloud' | 'chat'
15
+ >
16
+
17
+ export function isAnvilGravitySurface(
18
+ value: unknown,
19
+ ): value is AnvilGravitySurface {
20
+ return ANVIL_GRAVITY_SURFACES.includes(value as AnvilGravitySurface)
21
+ }
22
+
23
+ export function isAnvilServiceGravitySurface(
24
+ value: unknown,
25
+ ): value is AnvilServiceGravitySurface {
26
+ return value === 'web' || value === 'cloud' || value === 'chat'
27
+ }
28
+
29
+ export type GravityCapiUserData = {
30
+ click_id?: string | null
31
+ visitor_id?: string | null
32
+ session_id?: string | null
33
+ client_user_agent?: string | null
34
+ }
35
+
36
+ /** Attribution and device data returned by window.gravityPixel.getCAPIData(). */
37
+ export type GravityCapiData = {
38
+ user_data?: GravityCapiUserData | null
39
+ event_source_url?: string | null
40
+ client_context?: Record<string, unknown> | null
41
+ }
42
+
43
+ export type GravityConversionResult = {
44
+ event_id?: string
45
+ status?: string
46
+ attributed?: boolean
47
+ error?: unknown
48
+ }
49
+
50
+ function boundedString(value: unknown, maxLength: number): string | undefined {
51
+ return typeof value === 'string' && value.trim() && value.length <= maxLength
52
+ ? value
53
+ : undefined
54
+ }
55
+
56
+ function boundedObject(
57
+ value: unknown,
58
+ maxJsonLength: number,
59
+ ): Record<string, unknown> | undefined {
60
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
61
+ return undefined
62
+ }
63
+ try {
64
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength <=
65
+ maxJsonLength
66
+ ? (value as Record<string, unknown>)
67
+ : undefined
68
+ } catch {
69
+ return undefined
70
+ }
71
+ }
72
+
73
+ /** Sanitizes the untrusted browser result from gravityPixel.getCAPIData(). */
74
+ export function sanitizeGravityCapiData(
75
+ raw: unknown,
76
+ fallbackEventSourceUrl?: unknown,
77
+ ): GravityCapiData | undefined {
78
+ const value =
79
+ raw && typeof raw === 'object' && !Array.isArray(raw)
80
+ ? (raw as Record<string, unknown>)
81
+ : undefined
82
+ const rawUser =
83
+ value?.user_data &&
84
+ typeof value.user_data === 'object' &&
85
+ !Array.isArray(value.user_data)
86
+ ? (value.user_data as Record<string, unknown>)
87
+ : undefined
88
+ const eventSourceUrl =
89
+ boundedString(fallbackEventSourceUrl, 8192) ??
90
+ boundedString(value?.event_source_url, 8192)
91
+ const clientContext = boundedObject(value?.client_context, 32_768)
92
+
93
+ if (!value && !eventSourceUrl) return undefined
94
+ return {
95
+ user_data: rawUser
96
+ ? {
97
+ click_id: boundedString(rawUser.click_id, 4096),
98
+ visitor_id: boundedString(rawUser.visitor_id, 4096),
99
+ session_id: boundedString(rawUser.session_id, 4096),
100
+ client_user_agent: boundedString(rawUser.client_user_agent, 4096),
101
+ }
102
+ : undefined,
103
+ event_source_url: eventSourceUrl,
104
+ client_context: clientContext,
105
+ }
106
+ }
107
+
108
+ export function gravityFirstMessageEventId(userId: string): string {
109
+ return `anvil-first-message-${userId}`
110
+ }
111
+
112
+ export function buildGravityFirstMessagePayload(params: {
113
+ userId: string
114
+ email?: string | null
115
+ surface: AnvilGravitySurface
116
+ gravity?: GravityCapiData | null
117
+ userAgent?: string | null
118
+ eventTime?: number
119
+ }) {
120
+ const pixelUser = params.gravity?.user_data ?? {}
121
+ const userData = {
122
+ ...(pixelUser.click_id ? { click_id: pixelUser.click_id } : {}),
123
+ ...(pixelUser.visitor_id ? { visitor_id: pixelUser.visitor_id } : {}),
124
+ ...(pixelUser.session_id ? { session_id: pixelUser.session_id } : {}),
125
+ ...(pixelUser.client_user_agent || params.userAgent
126
+ ? {
127
+ client_user_agent:
128
+ pixelUser.client_user_agent ?? params.userAgent ?? undefined,
129
+ }
130
+ : {}),
131
+ ...(params.email ? { em: [params.email] } : {}),
132
+ external_id: [params.userId],
133
+ }
134
+
135
+ return {
136
+ data: [
137
+ {
138
+ event_name: GRAVITY_FIRST_MESSAGE_EVENT,
139
+ event_time: params.eventTime ?? Math.floor(Date.now() / 1000),
140
+ event_id: gravityFirstMessageEventId(params.userId),
141
+ action_source: 'website',
142
+ ...(params.gravity?.event_source_url
143
+ ? { event_source_url: params.gravity.event_source_url }
144
+ : {}),
145
+ user_data: userData,
146
+ ...(params.gravity?.client_context
147
+ ? { client_context: params.gravity.client_context }
148
+ : {}),
149
+ custom_data: {
150
+ content_name: 'Anvil first message',
151
+ content_category: params.surface,
152
+ },
153
+ },
154
+ ],
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Sends the account-level first-message conversion. The caller owns retry and
160
+ * persistence; this function throws unless Gravity confirms a terminal result.
161
+ */
162
+ export async function sendGravityFirstMessageConversion(params: {
163
+ apiKey: string
164
+ userId: string
165
+ email?: string | null
166
+ surface: AnvilGravitySurface
167
+ gravity?: GravityCapiData | null
168
+ userAgent?: string | null
169
+ fetchImpl?: typeof fetch
170
+ }): Promise<GravityConversionResult> {
171
+ const fetchImpl = params.fetchImpl ?? fetch
172
+ const response = await fetchImpl(GRAVITY_CAPI_ENDPOINT, {
173
+ method: 'POST',
174
+ headers: {
175
+ Authorization: `Bearer ${params.apiKey}`,
176
+ 'Content-Type': 'application/json',
177
+ 'User-Agent': 'anvil/1.0 (gravity-capi)',
178
+ },
179
+ body: JSON.stringify(buildGravityFirstMessagePayload(params)),
180
+ signal: AbortSignal.timeout(3_000),
181
+ })
182
+
183
+ const responseText = await response.text()
184
+ if (!response.ok) {
185
+ throw new Error(
186
+ `Gravity CAPI rejected FirstMessage (${response.status}): ${responseText.slice(0, 500)}`,
187
+ )
188
+ }
189
+
190
+ let body: { results?: GravityConversionResult[] }
191
+ try {
192
+ body = JSON.parse(responseText) as { results?: GravityConversionResult[] }
193
+ } catch {
194
+ throw new Error('Gravity CAPI returned invalid JSON for FirstMessage')
195
+ }
196
+
197
+ const result = body.results?.[0]
198
+ if (!result?.status) {
199
+ throw new Error('Gravity CAPI returned no result for FirstMessage')
200
+ }
201
+ if (!['ok', 'duplicate', 'test_ok', 'skipped'].includes(result.status)) {
202
+ throw new Error(
203
+ `Gravity CAPI failed FirstMessage with status ${result.status}`,
204
+ )
205
+ }
206
+ return result
207
+ }
@@ -0,0 +1,233 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
2
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
3
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
4
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
5
+
6
+ import { getErrorObject } from '../util/error'
7
+
8
+ import type { MCPConfig } from '../types/mcp'
9
+ import type { ToolResultOutput } from '../types/messages/content-part'
10
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'
11
+ import type {
12
+ BlobResourceContents,
13
+ CallToolResult,
14
+ TextResourceContents,
15
+ } from '@modelcontextprotocol/sdk/types.js'
16
+
17
+ // Cap on how much of a failed stdio server's stderr we retain for the error
18
+ // message — enough to show the real failure without unbounded growth.
19
+ const STDERR_BUFFER_CAP = 8192
20
+
21
+ const runningClients: Record<string, Client> = {}
22
+ const listToolsCache: Record<
23
+ string,
24
+ ReturnType<typeof Client.prototype.listTools>
25
+ > = {}
26
+
27
+ /**
28
+ * Substitutes environment variable references ($VAR_NAME) in a string with their values.
29
+ * Supports both simple replacement ("$VAR_NAME") and interpolation ("Bearer $VAR_NAME").
30
+ */
31
+ function substituteEnvInValue(value: string): string {
32
+ return value.replace(/\$([A-Z_][A-Z0-9_]*)/g, (match, varName) => {
33
+ const envValue = process.env[varName]
34
+ if (envValue === undefined) {
35
+ // Return original if env var not found
36
+ return match
37
+ }
38
+ return envValue
39
+ })
40
+ }
41
+
42
+ /**
43
+ * Substitutes environment variable references in all values of a record.
44
+ */
45
+ function substituteEnvInRecord(
46
+ record: Record<string, string>,
47
+ ): Record<string, string> {
48
+ const result: Record<string, string> = {}
49
+ for (const [key, value] of Object.entries(record)) {
50
+ result[key] = substituteEnvInValue(value)
51
+ }
52
+ return result
53
+ }
54
+
55
+ function hashConfig(config: MCPConfig): string {
56
+ if (config.type === 'stdio') {
57
+ return JSON.stringify({
58
+ command: config.command,
59
+ args: config.args,
60
+ env: config.env,
61
+ })
62
+ }
63
+ if (config.type === 'http') {
64
+ return JSON.stringify({
65
+ type: 'http',
66
+ url: config.url,
67
+ params: config.params,
68
+ })
69
+ }
70
+ if (config.type === 'sse') {
71
+ return JSON.stringify({
72
+ type: 'sse',
73
+ url: config.url,
74
+ params: config.params,
75
+ })
76
+ }
77
+ config.type satisfies never
78
+ throw new Error(
79
+ `Internal error in hashConfig: invalid MCP config type ${config.type}`,
80
+ )
81
+ }
82
+
83
+ export async function getMCPClient(config: MCPConfig): Promise<string> {
84
+ let key = hashConfig(config)
85
+ if (key in runningClients) {
86
+ return key
87
+ }
88
+
89
+ let transport: Transport
90
+ // Buffer the child process's stderr so that a server which crashes during
91
+ // startup produces an actionable error instead of the opaque MCP SDK message
92
+ // "MCP error -32000: Connection closed".
93
+ let stderrBuffer = ''
94
+ if (config.type === 'stdio') {
95
+ const stdioTransport = new StdioClientTransport({
96
+ command: config.command,
97
+ args: config.args,
98
+ env: substituteEnvInRecord(config.env),
99
+ stderr: 'pipe',
100
+ })
101
+ // When stderr is 'pipe' the SDK exposes a PassThrough immediately (before
102
+ // the process is spawned), so attaching here captures even early output
103
+ // from a child that dies during the connection handshake.
104
+ stdioTransport.stderr?.on('data', (chunk: Buffer) => {
105
+ if (stderrBuffer.length < STDERR_BUFFER_CAP) {
106
+ stderrBuffer += chunk.toString('utf8')
107
+ }
108
+ })
109
+ transport = stdioTransport
110
+ } else {
111
+ const url = new URL(config.url)
112
+ for (const [key, value] of Object.entries(config.params)) {
113
+ url.searchParams.set(key, value)
114
+ }
115
+ const headers = substituteEnvInRecord(config.headers)
116
+ if (config.type === 'http') {
117
+ transport = new StreamableHTTPClientTransport(url, {
118
+ requestInit: {
119
+ headers,
120
+ },
121
+ })
122
+ } else if (config.type === 'sse') {
123
+ transport = new SSEClientTransport(url, {
124
+ requestInit: {
125
+ headers,
126
+ },
127
+ })
128
+ } else {
129
+ config.type satisfies never
130
+ throw new Error(`Internal error: invalid MCP config type ${config.type}`)
131
+ }
132
+ }
133
+
134
+ const client = new Client({
135
+ name: 'anvil',
136
+ version: '1.0.0',
137
+ })
138
+
139
+ try {
140
+ await client.connect(transport)
141
+ } catch (error) {
142
+ const baseMessage = getErrorObject(error).message
143
+ if (config.type === 'stdio') {
144
+ const commandStr = [config.command, ...(config.args ?? [])].join(' ')
145
+ const detail = stderrBuffer.trim()
146
+ throw new Error(
147
+ `${baseMessage}. Failed to start MCP server via \`${commandStr}\`. ` +
148
+ `Ensure the command is installed and runnable (e.g. an up-to-date ` +
149
+ `node/npm/npx, or python/uvx) and that any required env vars are set.` +
150
+ (detail ? `\nServer stderr:\n${detail}` : ''),
151
+ )
152
+ }
153
+ throw new Error(
154
+ `${baseMessage}. Failed to connect to MCP server at ${config.url}.`,
155
+ )
156
+ }
157
+ runningClients[key] = client
158
+
159
+ return key
160
+ }
161
+
162
+ export function listMCPTools(
163
+ clientId: string,
164
+ ...args: Parameters<typeof Client.prototype.listTools>
165
+ ): ReturnType<typeof Client.prototype.listTools> {
166
+ const client = runningClients[clientId]
167
+ if (!client) {
168
+ throw new Error(`listTools: client not found with id: ${clientId}`)
169
+ }
170
+ if (!listToolsCache[clientId]) {
171
+ listToolsCache[clientId] = client.listTools(...args)
172
+ }
173
+ return listToolsCache[clientId]
174
+ }
175
+
176
+ function getResourceData(
177
+ resource: TextResourceContents | BlobResourceContents,
178
+ ): string {
179
+ if ('text' in resource) return resource.text as string
180
+ if ('blob' in resource) return resource.blob as string
181
+ return ''
182
+ }
183
+
184
+ export async function callMCPTool(
185
+ clientId: string,
186
+ ...args: Parameters<typeof Client.prototype.callTool>
187
+ ): Promise<ToolResultOutput[]> {
188
+ const client = runningClients[clientId]
189
+ if (!client) {
190
+ throw new Error(`callTool: client not found with id: ${clientId}`)
191
+ }
192
+ const callResult = await client.callTool(...args)
193
+ const result = callResult as CallToolResult
194
+ const content = result.content
195
+
196
+ return content.map((c: (typeof content)[number]) => {
197
+ if (c.type === 'text') {
198
+ return {
199
+ type: 'json',
200
+ value: c.text,
201
+ } satisfies ToolResultOutput
202
+ }
203
+ if (c.type === 'audio') {
204
+ return {
205
+ type: 'media',
206
+ data: c.data,
207
+ mediaType: c.mimeType,
208
+ } satisfies ToolResultOutput
209
+ }
210
+ if (c.type === 'image') {
211
+ return {
212
+ type: 'media',
213
+ data: c.data,
214
+ mediaType: c.mimeType,
215
+ } satisfies ToolResultOutput
216
+ }
217
+ if (c.type === 'resource') {
218
+ return {
219
+ type: 'media',
220
+ data: getResourceData(c.resource),
221
+ mediaType: c.resource.mimeType ?? 'text/plain',
222
+ } satisfies ToolResultOutput
223
+ }
224
+ const fallbackValue =
225
+ 'uri' in c && typeof (c as { uri: unknown }).uri === 'string'
226
+ ? (c as { uri: string }).uri
227
+ : JSON.stringify(c)
228
+ return {
229
+ type: 'json',
230
+ value: fallbackValue,
231
+ } satisfies ToolResultOutput
232
+ })
233
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @deprecated Import from '@anvil/common/constants' or specific files instead:
3
+ * - '@anvil/common/constants/model-config' for model-related constants
4
+ * - '@anvil/common/constants/limits' for billing and numeric limits
5
+ * - '@anvil/common/constants/ui' for auth/user state
6
+ * - '@anvil/common/constants/paths' for file paths and markers
7
+ *
8
+ * This file re-exports all constants for backwards compatibility.
9
+ */
10
+ export * from './constants'