@alumbwe/anvil 1.0.41 → 1.0.49

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 (241) hide show
  1. package/bin/anvil.js +18 -0
  2. package/package.json +13 -6
  3. package/src/agents/bundled-agents.generated.ts +1 -1
  4. package/src/entry.ts +5 -0
  5. package/src/index.tsx +27 -4
  6. package/src/login/plain-login.ts +60 -0
  7. package/src/login/supabase-auth.ts +346 -0
  8. package/src/pre-init/client-env.ts +17 -0
  9. package/src/utils/anvil-client.ts +4 -0
  10. package/src/utils/auth.ts +16 -4
  11. package/src/utils/client-env-defaults.ts +28 -0
  12. package/src/utils/config-dir.ts +1 -1
  13. package/vendor/@anvil/common/src/constants/deepseek-direct.ts +30 -1
  14. package/vendor/@anvil/common/src/util/project-ignore.ts +4 -3
  15. package/vendor/@anvil/sdk/dist/index.cjs +46 -10
  16. package/vendor/@anvil/sdk/dist/index.mjs +46 -10
  17. package/src/commands/__tests__/anvil-command-aliases.test.ts +0 -56
  18. package/src/commands/__tests__/bash-command.test.ts +0 -445
  19. package/src/commands/__tests__/command-args.test.ts +0 -349
  20. package/src/commands/__tests__/copy-conversation-clipboard.test.ts +0 -108
  21. package/src/commands/__tests__/copy-conversation.test.ts +0 -226
  22. package/src/commands/__tests__/diagnostics-command.test.ts +0 -35
  23. package/src/commands/__tests__/image.test.ts +0 -99
  24. package/src/commands/__tests__/init.test.ts +0 -456
  25. package/src/commands/__tests__/new-command-rotates-chat.test.ts +0 -91
  26. package/src/commands/__tests__/process-diagnostics.test.ts +0 -54
  27. package/src/commands/__tests__/prompt-builders.test.ts +0 -28
  28. package/src/commands/__tests__/router-input.test.ts +0 -298
  29. package/src/components/__tests__/ad-banner.test.tsx +0 -83
  30. package/src/components/__tests__/anvil-landing-heading-row.test.tsx +0 -91
  31. package/src/components/__tests__/anvil-model-selector.test.tsx +0 -519
  32. package/src/components/__tests__/anvil-offer-invariants.test.ts +0 -54
  33. package/src/components/__tests__/anvil-takeover-prompt.test.tsx +0 -212
  34. package/src/components/__tests__/chat-input-bar.test.tsx +0 -130
  35. package/src/components/__tests__/grid-layout.integration.test.tsx +0 -304
  36. package/src/components/__tests__/grid-layout.test.tsx +0 -1051
  37. package/src/components/__tests__/message-block.completion.test.tsx +0 -104
  38. package/src/components/__tests__/message-block.streaming.test.tsx +0 -78
  39. package/src/components/__tests__/message-with-agents.test.tsx +0 -579
  40. package/src/components/__tests__/multiline-input.test.tsx +0 -1132
  41. package/src/components/__tests__/queue-panel.test.tsx +0 -398
  42. package/src/components/__tests__/selectable-list.test.ts +0 -232
  43. package/src/components/__tests__/status-bar.test.tsx +0 -44
  44. package/src/components/__tests__/status-indicator.test.tsx +0 -204
  45. package/src/components/__tests__/terminal-thinking-orb.test.tsx +0 -111
  46. package/src/components/__tests__/user-error-banner.test.tsx +0 -102
  47. package/src/components/ask-user/__tests__/multiple-choice-form.test.ts +0 -432
  48. package/src/components/ask-user/__tests__/validation.test.ts +0 -213
  49. package/src/components/tools/__tests__/apply-patch.test.tsx +0 -84
  50. package/src/components/tools/__tests__/code-search.test.tsx +0 -45
  51. package/src/components/tools/__tests__/gravity-index.test.ts +0 -76
  52. package/src/components/tools/__tests__/render-ui.test.tsx +0 -92
  53. package/src/components/tools/__tests__/run-terminal-command.test.ts +0 -233
  54. package/src/contexts/__tests__/chat-runtime-context.test.tsx +0 -149
  55. package/src/data/slash-commands.test.ts +0 -24
  56. package/src/hooks/__tests__/holds-live-anvil-slot.test.ts +0 -49
  57. package/src/hooks/__tests__/session-fetch-signal.test.ts +0 -63
  58. package/src/hooks/__tests__/use-activity-query.test.ts +0 -1000
  59. package/src/hooks/__tests__/use-ask-user-bridge.test.ts +0 -176
  60. package/src/hooks/__tests__/use-auth-query.test.ts +0 -21
  61. package/src/hooks/__tests__/use-chat-input-remount.test.tsx +0 -66
  62. package/src/hooks/__tests__/use-clipboard.test.tsx +0 -73
  63. package/src/hooks/__tests__/use-connection-status.test.ts +0 -112
  64. package/src/hooks/__tests__/use-directory-browser.test.ts +0 -203
  65. package/src/hooks/__tests__/use-gravity-ad.test.ts +0 -73
  66. package/src/hooks/__tests__/use-grid-layout.test.ts +0 -349
  67. package/src/hooks/__tests__/use-input-history.test.ts +0 -699
  68. package/src/hooks/__tests__/use-message-queue-editing.test.tsx +0 -209
  69. package/src/hooks/__tests__/use-message-queue.test.tsx +0 -71
  70. package/src/hooks/__tests__/use-path-tab-completion.test.ts +0 -315
  71. package/src/hooks/__tests__/use-queue-controls.test.ts +0 -68
  72. package/src/hooks/__tests__/use-queue-ui.test.tsx +0 -83
  73. package/src/hooks/__tests__/use-searchable-list.test.ts +0 -359
  74. package/src/hooks/__tests__/use-send-message-timer.test.ts +0 -146
  75. package/src/hooks/__tests__/use-suggestion-engine-mention.test.ts +0 -361
  76. package/src/hooks/__tests__/use-suggestion-engine.test.ts +0 -485
  77. package/src/hooks/__tests__/use-terminal-focus.test.ts +0 -66
  78. package/src/hooks/__tests__/use-terminal-layout.test.ts +0 -675
  79. package/src/hooks/__tests__/use-timeout.test.ts +0 -330
  80. package/src/hooks/__tests__/use-usage-query.test.ts +0 -502
  81. package/src/hooks/__tests__/use-user-details-query.test.ts +0 -195
  82. package/src/hooks/helpers/__tests__/send-message.test.ts +0 -1918
  83. package/src/init/__tests__/init-direnv.test.ts +0 -526
  84. package/src/state/__tests__/chat-store-focus.test.ts +0 -22
  85. package/src/state/__tests__/feedback-store.test.ts +0 -257
  86. package/src/utils/__tests__/active-run.test.ts +0 -140
  87. package/src/utils/__tests__/activity-tracker.test.ts +0 -440
  88. package/src/utils/__tests__/agent-display.test.ts +0 -139
  89. package/src/utils/__tests__/analytics-client.test.ts +0 -262
  90. package/src/utils/__tests__/anonymous-id.test.ts +0 -74
  91. package/src/utils/__tests__/anvil-api.test.ts +0 -578
  92. package/src/utils/__tests__/anvil-instance-owner.test.ts +0 -69
  93. package/src/utils/__tests__/anvil-model-navigation.test.ts +0 -102
  94. package/src/utils/__tests__/anvil-premium-reset.test.ts +0 -79
  95. package/src/utils/__tests__/anvil-referral-cache.test.ts +0 -116
  96. package/src/utils/__tests__/anvil-session-api.test.ts +0 -215
  97. package/src/utils/__tests__/anvil-session-display.test.ts +0 -23
  98. package/src/utils/__tests__/anvil-streak-line.test.ts +0 -217
  99. package/src/utils/__tests__/arrays.test.ts +0 -264
  100. package/src/utils/__tests__/bash-context-processor.test.ts +0 -38
  101. package/src/utils/__tests__/block-processor.test.ts +0 -810
  102. package/src/utils/__tests__/chat-history.test.ts +0 -203
  103. package/src/utils/__tests__/chat-input-key-intercept.test.ts +0 -40
  104. package/src/utils/__tests__/chat-meta.test.ts +0 -130
  105. package/src/utils/__tests__/clipboard-linux.test.ts +0 -359
  106. package/src/utils/__tests__/clipboard.test.ts +0 -910
  107. package/src/utils/__tests__/code-search-summary.test.ts +0 -84
  108. package/src/utils/__tests__/collapse-helpers.test.ts +0 -1109
  109. package/src/utils/__tests__/error-handling.test.ts +0 -658
  110. package/src/utils/__tests__/exit-cleanly.test.ts +0 -110
  111. package/src/utils/__tests__/feedback-helpers.test.ts +0 -444
  112. package/src/utils/__tests__/feedback-submission.test.ts +0 -26
  113. package/src/utils/__tests__/fetch-usage.test.ts +0 -355
  114. package/src/utils/__tests__/fingerprint.test.ts +0 -144
  115. package/src/utils/__tests__/fixtures/terminal-command-broker-child.ts +0 -7
  116. package/src/utils/__tests__/fixtures/terminal-command-broker-entry.ts +0 -3
  117. package/src/utils/__tests__/fixtures/terminal-command-broker-owner.ts +0 -33
  118. package/src/utils/__tests__/format-elapsed-time.test.ts +0 -103
  119. package/src/utils/__tests__/format-timeout.test.ts +0 -87
  120. package/src/utils/__tests__/image-dimensions.test.ts +0 -249
  121. package/src/utils/__tests__/image-processor.test.ts +0 -209
  122. package/src/utils/__tests__/implementor-helpers.test.ts +0 -1458
  123. package/src/utils/__tests__/keyboard-actions.test.ts +0 -660
  124. package/src/utils/__tests__/layout-helpers.test.ts +0 -36
  125. package/src/utils/__tests__/lazy-response-ads.test.ts +0 -167
  126. package/src/utils/__tests__/log-shipper.test.ts +0 -53
  127. package/src/utils/__tests__/markdown-renderer.test.tsx +0 -421
  128. package/src/utils/__tests__/message-block-helpers.test.ts +0 -1263
  129. package/src/utils/__tests__/message-updater.test.ts +0 -645
  130. package/src/utils/__tests__/osc-timeout-scenarios.test.ts +0 -172
  131. package/src/utils/__tests__/pending-attachments.test.ts +0 -277
  132. package/src/utils/__tests__/polling-backoff.test.ts +0 -51
  133. package/src/utils/__tests__/queue-panel-actions.test.ts +0 -148
  134. package/src/utils/__tests__/run-state-storage.test.ts +0 -919
  135. package/src/utils/__tests__/safe-json.test.ts +0 -77
  136. package/src/utils/__tests__/sdk-event-handlers.test.ts +0 -685
  137. package/src/utils/__tests__/send-message-helpers.test.ts +0 -1898
  138. package/src/utils/__tests__/send-message-timer.test.ts +0 -64
  139. package/src/utils/__tests__/settings.test.ts +0 -99
  140. package/src/utils/__tests__/strings.test.ts +0 -192
  141. package/src/utils/__tests__/terminal-color-detection.test.ts +0 -425
  142. package/src/utils/__tests__/terminal-command-broker.test.ts +0 -528
  143. package/src/utils/__tests__/terminal-enter-detection.test.ts +0 -77
  144. package/src/utils/__tests__/terminal-io.test.ts +0 -137
  145. package/src/utils/__tests__/terminal-protocol-controller.test.ts +0 -119
  146. package/src/utils/__tests__/text-layout.test.ts +0 -82
  147. package/src/utils/__tests__/theme-platform-detection.test.ts +0 -125
  148. package/src/utils/__tests__/think-tag-parser.test.ts +0 -159
  149. package/src/utils/__tests__/trace-writer.test.ts +0 -223
  150. package/src/utils/__tests__/trim-chat-logs.test.ts +0 -78
  151. package/src/utils/__tests__/usage-banner-state.test.ts +0 -298
  152. package/src/utils/__tests__/validation-error-formatting.test.ts +0 -126
  153. package/src/utils/__tests__/windows-terminal-health.test.ts +0 -101
  154. package/src/utils/__tests__/write-file-atomic.test.ts +0 -127
  155. package/vendor/@anvil/common/src/__tests__/agent-validation.test.ts +0 -846
  156. package/vendor/@anvil/common/src/__tests__/anvil-model-availability.test.ts +0 -101
  157. package/vendor/@anvil/common/src/__tests__/anvil-models.test.ts +0 -1408
  158. package/vendor/@anvil/common/src/__tests__/anvil-public-data-use-copy.test.ts +0 -258
  159. package/vendor/@anvil/common/src/__tests__/anvil-referral-tiers.test.ts +0 -48
  160. package/vendor/@anvil/common/src/__tests__/anvil-spend-ceilings.test.ts +0 -282
  161. package/vendor/@anvil/common/src/__tests__/anvil-trust.test.ts +0 -526
  162. package/vendor/@anvil/common/src/__tests__/deepseek-direct.test.ts +0 -68
  163. package/vendor/@anvil/common/src/__tests__/disposable-email.test.ts +0 -132
  164. package/vendor/@anvil/common/src/__tests__/dynamic-agent-template-schema.test.ts +0 -422
  165. package/vendor/@anvil/common/src/__tests__/env-ci.test.ts +0 -167
  166. package/vendor/@anvil/common/src/__tests__/env-process.test.ts +0 -145
  167. package/vendor/@anvil/common/src/__tests__/foreign-client-shipped-agents.test.ts +0 -234
  168. package/vendor/@anvil/common/src/__tests__/foreign-client-signals.test.ts +0 -379
  169. package/vendor/@anvil/common/src/__tests__/free-agents.test.ts +0 -807
  170. package/vendor/@anvil/common/src/__tests__/gravity-capi.test.ts +0 -154
  171. package/vendor/@anvil/common/src/__tests__/handlesteps-parsing.test.ts +0 -246
  172. package/vendor/@anvil/common/src/__tests__/kimi-k3-god-only.test.ts +0 -77
  173. package/vendor/@anvil/common/src/__tests__/model-config.test.ts +0 -89
  174. package/vendor/@anvil/common/src/__tests__/project-file-tree.test.ts +0 -298
  175. package/vendor/@anvil/common/src/__tests__/provisioned-model-tiers.test.ts +0 -116
  176. package/vendor/@anvil/common/src/__tests__/reasoning-effort.test.ts +0 -167
  177. package/vendor/@anvil/common/src/__tests__/reddit-capi.test.ts +0 -132
  178. package/vendor/@anvil/common/src/__tests__/response-ad-positions.test.ts +0 -72
  179. package/vendor/@anvil/common/src/__tests__/user-state.test.ts +0 -30
  180. package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding-gate.test.ts +0 -63
  181. package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding.test.ts +0 -246
  182. package/vendor/@anvil/common/src/constants/__tests__/cf-worker-signals.test.ts +0 -106
  183. package/vendor/@anvil/common/src/testing/TESTING_PATTERNS.md +0 -351
  184. package/vendor/@anvil/common/src/testing/anvil-offer-invariants.ts +0 -169
  185. package/vendor/@anvil/common/src/testing/errors.ts +0 -33
  186. package/vendor/@anvil/common/src/testing/fixtures/agent-runtime.ts +0 -334
  187. package/vendor/@anvil/common/src/testing/impl/agent-runtime.ts +0 -6
  188. package/vendor/@anvil/common/src/testing/index.ts +0 -84
  189. package/vendor/@anvil/common/src/testing/mock-modules.ts +0 -53
  190. package/vendor/@anvil/common/src/testing/mock-types.ts +0 -123
  191. package/vendor/@anvil/common/src/testing/mocks/analytics.ts +0 -261
  192. package/vendor/@anvil/common/src/testing/mocks/child-process.ts +0 -93
  193. package/vendor/@anvil/common/src/testing/mocks/crypto.ts +0 -218
  194. package/vendor/@anvil/common/src/testing/mocks/database.ts +0 -337
  195. package/vendor/@anvil/common/src/testing/mocks/fetch.ts +0 -219
  196. package/vendor/@anvil/common/src/testing/mocks/filesystem.ts +0 -166
  197. package/vendor/@anvil/common/src/testing/mocks/index.ts +0 -101
  198. package/vendor/@anvil/common/src/testing/mocks/logger.ts +0 -135
  199. package/vendor/@anvil/common/src/testing/mocks/stream.ts +0 -313
  200. package/vendor/@anvil/common/src/testing/mocks/timers.ts +0 -132
  201. package/vendor/@anvil/common/src/testing/mocks/tree-sitter.ts +0 -127
  202. package/vendor/@anvil/common/src/testing/setup.ts +0 -282
  203. package/vendor/@anvil/common/src/tools/__tests__/compile-tool-definitions.test.ts +0 -34
  204. package/vendor/@anvil/common/src/tools/params/__tests__/coerce-to-array.test.ts +0 -213
  205. package/vendor/@anvil/common/src/tools/params/__tests__/read-docs.test.ts +0 -47
  206. package/vendor/@anvil/common/src/tools/params/__tests__/render-ui.test.ts +0 -65
  207. package/vendor/@anvil/common/src/tools/params/tool/__tests__/run-terminal-command-timeout.test.ts +0 -49
  208. package/vendor/@anvil/common/src/types/__tests__/dynamic-agent-template.test.ts +0 -20
  209. package/vendor/@anvil/common/src/util/__tests__/ad-user-agent.test.ts +0 -26
  210. package/vendor/@anvil/common/src/util/__tests__/analytics-dispatcher.test.ts +0 -122
  211. package/vendor/@anvil/common/src/util/__tests__/analytics-log.test.ts +0 -102
  212. package/vendor/@anvil/common/src/util/__tests__/analytics-sampling.test.ts +0 -143
  213. package/vendor/@anvil/common/src/util/__tests__/anvil-streak.test.ts +0 -202
  214. package/vendor/@anvil/common/src/util/__tests__/anvil-usage-summary.test.ts +0 -193
  215. package/vendor/@anvil/common/src/util/__tests__/axiom-only-log.test.ts +0 -140
  216. package/vendor/@anvil/common/src/util/__tests__/client-user-agent.test.ts +0 -148
  217. package/vendor/@anvil/common/src/util/__tests__/engagement-tracker.test.ts +0 -115
  218. package/vendor/@anvil/common/src/util/__tests__/env-file-path.test.ts +0 -57
  219. package/vendor/@anvil/common/src/util/__tests__/error-abort.test.ts +0 -774
  220. package/vendor/@anvil/common/src/util/__tests__/error-api-details.test.ts +0 -206
  221. package/vendor/@anvil/common/src/util/__tests__/file-read-limits.test.ts +0 -173
  222. package/vendor/@anvil/common/src/util/__tests__/format-code-search.test.ts +0 -60
  223. package/vendor/@anvil/common/src/util/__tests__/log-mirror.test.ts +0 -31
  224. package/vendor/@anvil/common/src/util/__tests__/messages.test.ts +0 -1252
  225. package/vendor/@anvil/common/src/util/__tests__/partial-json-delta.test.ts +0 -505
  226. package/vendor/@anvil/common/src/util/__tests__/path.test.ts +0 -22
  227. package/vendor/@anvil/common/src/util/__tests__/project-ignore.test.ts +0 -90
  228. package/vendor/@anvil/common/src/util/__tests__/promise.test.ts +0 -325
  229. package/vendor/@anvil/common/src/util/__tests__/rate-limit.test.ts +0 -28
  230. package/vendor/@anvil/common/src/util/__tests__/reddit-anvil-retention.test.ts +0 -130
  231. package/vendor/@anvil/common/src/util/__tests__/saxy.test.ts +0 -1008
  232. package/vendor/@anvil/common/src/util/__tests__/split-data.test.ts +0 -289
  233. package/vendor/@anvil/common/src/util/__tests__/string.test.ts +0 -239
  234. package/vendor/@anvil/common/src/util/__tests__/thread-title.test.ts +0 -70
  235. package/vendor/@anvil/common/src/util/__tests__/tool-result-media-order.test.ts +0 -108
  236. package/vendor/@anvil/common/src/util/__tests__/ttft-histogram.test.ts +0 -180
  237. package/vendor/@anvil/common/src/util/__tests__/with-timeout.test.ts +0 -24
  238. package/vendor/@anvil/common/src/util/__tests__/zoned-time.test.ts +0 -88
  239. package/vendor/@anvil/common/src/util/skills.test.ts +0 -44
  240. package/vendor/@anvil/sdk/dist/index.cjs.map +0 -440
  241. package/vendor/@anvil/sdk/dist/index.mjs.map +0 -440
@@ -1,127 +0,0 @@
1
- import { mock } from 'bun:test'
2
-
3
- export interface MockTreeNode {
4
- text: string
5
- type?: string
6
- startPosition?: { row: number; column: number }
7
- endPosition?: { row: number; column: number }
8
- children?: MockTreeNode[]
9
- }
10
-
11
- export interface MockTree {
12
- rootNode: MockTreeNode
13
- }
14
-
15
- export interface MockCapture {
16
- name: string
17
- node: MockTreeNode
18
- }
19
-
20
- export interface MockParser {
21
- parse: (input: string) => MockTree | null
22
- }
23
-
24
- export interface MockQuery {
25
- captures: (node: MockTreeNode) => MockCapture[]
26
- }
27
-
28
- export interface CreateMockParserOptions {
29
- tree?: MockTree | null
30
- parseImpl?: (input: string) => MockTree | null
31
- }
32
-
33
- export interface CreateMockQueryOptions {
34
- captures?: MockCapture[]
35
- capturesImpl?: (node: MockTreeNode) => MockCapture[]
36
- }
37
-
38
- export function createMockCapture(name: string, text: string): MockCapture {
39
- return {
40
- name,
41
- node: { text },
42
- }
43
- }
44
-
45
- export function createMockTreeSitterCaptures(
46
- items: Array<{ name: string; text: string }>,
47
- ): MockCapture[] {
48
- return items.map(({ name, text }) => createMockCapture(name, text))
49
- }
50
-
51
- export function createMockTree(rootNodeText: string = 'mock tree'): MockTree {
52
- return {
53
- rootNode: { text: rootNodeText },
54
- }
55
- }
56
-
57
- export function createMockTreeSitterParser(
58
- options: CreateMockParserOptions = {},
59
- ): MockParser {
60
- const { tree, parseImpl } = options
61
- const defaultTree = createMockTree()
62
- const parseFn = parseImpl ?? (() => tree ?? defaultTree)
63
-
64
- return {
65
- parse: mock(parseFn),
66
- }
67
- }
68
-
69
- export function createMockTreeSitterQuery(
70
- options: CreateMockQueryOptions = {},
71
- ): MockQuery {
72
- const { captures = [], capturesImpl } = options
73
- const capturesFn = capturesImpl ?? (() => captures)
74
-
75
- return {
76
- captures: mock(capturesFn),
77
- }
78
- }
79
-
80
- export interface CreateMockLanguageConfigOptions {
81
- extensions?: string[]
82
- wasmFile?: string
83
- queryText?: string
84
- parser?: MockParser | null
85
- query?: MockQuery | null
86
- captures?: MockCapture[]
87
- tree?: MockTree | null
88
- }
89
-
90
- export function createMockLanguageConfig(
91
- options: CreateMockLanguageConfigOptions = {},
92
- ): {
93
- extensions: string[]
94
- wasmFile: string
95
- queryText: string
96
- parser: MockParser | null
97
- query: MockQuery | null
98
- } {
99
- const {
100
- extensions = ['.ts'],
101
- wasmFile = 'tree-sitter-typescript.wasm',
102
- queryText = 'mock query',
103
- parser,
104
- query,
105
- captures,
106
- tree,
107
- } = options
108
-
109
- const finalQuery =
110
- query ??
111
- (captures
112
- ? createMockTreeSitterQuery({ captures })
113
- : createMockTreeSitterQuery())
114
- const finalParser =
115
- parser ??
116
- (tree !== undefined
117
- ? createMockTreeSitterParser({ tree })
118
- : createMockTreeSitterParser())
119
-
120
- return {
121
- extensions,
122
- wasmFile,
123
- queryText,
124
- parser: finalParser,
125
- query: finalQuery,
126
- }
127
- }
@@ -1,282 +0,0 @@
1
- /**
2
- * Test setup utilities for common patterns.
3
- *
4
- * Provides helper functions for setting up and tearing down test fixtures
5
- * in a consistent way across the codebase.
6
- *
7
- * @example
8
- * ```typescript
9
- * import { createTestSetup, TestSetupResult } from '@anvil/common/testing/setup'
10
- *
11
- * describe('my test', () => {
12
- * const setup = createTestSetup()
13
- *
14
- * beforeEach(() => setup.beforeEach())
15
- * afterEach(() => setup.afterEach())
16
- * })
17
- * ```
18
- */
19
-
20
- import { setupAnalyticsMocks } from './mocks/analytics'
21
- import { setupCryptoMocks } from './mocks/crypto'
22
- import { setupDbSpies } from './mocks/database'
23
- import { createMockLogger } from './mocks/logger'
24
- import { resetToolCallIdCounter } from './mocks/stream'
25
-
26
- import type {
27
- AnalyticsSpies,
28
- TrackEventFn,
29
- FlushAnalyticsFn,
30
- } from './mocks/analytics'
31
- import type { CryptoMockSpies } from './mocks/crypto'
32
- import type { DbSpies } from './mocks/database'
33
- import type { MockLogger } from './mocks/logger'
34
-
35
- /**
36
- * Options for creating a test setup.
37
- */
38
- export interface CreateTestSetupOptions {
39
- /**
40
- * Whether to set up analytics mocks.
41
- * @default true
42
- */
43
- analytics?: boolean
44
-
45
- /**
46
- * Whether to set up crypto mocks.
47
- * @default true
48
- */
49
- crypto?: boolean
50
-
51
- /**
52
- * Whether to set up database mocks.
53
- * Requires passing the db module.
54
- * @default false
55
- */
56
- database?: boolean
57
-
58
- /**
59
- * The database module to mock (required if database is true).
60
- * Must have insert and update methods that are functions.
61
- */
62
- dbModule?: {
63
- insert: (...args: unknown[]) => unknown
64
- update: (...args: unknown[]) => unknown
65
- }
66
-
67
- /**
68
- * The analytics module to mock (required if analytics is true).
69
- */
70
- analyticsModule?: {
71
- trackEvent: TrackEventFn
72
- flushAnalytics: FlushAnalyticsFn
73
- }
74
-
75
- /**
76
- * Prefix for crypto mock UUIDs.
77
- * @default 'test'
78
- */
79
- cryptoPrefix?: string
80
- }
81
-
82
- /**
83
- * Result of creating a test setup.
84
- */
85
- export interface TestSetupResult {
86
- /** The mock logger instance */
87
- logger: MockLogger
88
-
89
- /** Analytics spies (if enabled) */
90
- analyticsSpy?: AnalyticsSpies
91
-
92
- /** Crypto spies (if enabled) */
93
- cryptoSpy?: CryptoMockSpies
94
-
95
- /** Database spies (if enabled) */
96
- dbSpy?: DbSpies
97
-
98
- /** Call this in beforeEach */
99
- beforeEach: () => void
100
-
101
- /** Call this in afterEach */
102
- afterEach: () => void
103
-
104
- /** Restore all mocks */
105
- restore: () => void
106
- }
107
-
108
- /**
109
- * Creates a test setup with common mocks pre-configured.
110
- *
111
- * @param options - Configuration options
112
- * @returns A test setup result with mocks and lifecycle methods
113
- *
114
- * @example
115
- * ```typescript
116
- * import * as analytics from '@anvil/common/analytics'
117
- * const db = createMockDbOperations()
118
- *
119
- * describe('my test', () => {
120
- * const setup = createTestSetup({
121
- * analytics: true,
122
- * analyticsModule: analytics,
123
- * database: true,
124
- * dbModule: db,
125
- * })
126
- *
127
- * beforeEach(() => setup.beforeEach())
128
- * afterEach(() => setup.afterEach())
129
- *
130
- * it('does something', () => {
131
- * expect(setup.analyticsSpy.trackEvent).toHaveBeenCalled()
132
- * })
133
- * })
134
- * ```
135
- */
136
- export function createTestSetup(
137
- options: CreateTestSetupOptions = {},
138
- ): TestSetupResult {
139
- const {
140
- analytics = true,
141
- crypto = true,
142
- database = false,
143
- dbModule,
144
- analyticsModule,
145
- cryptoPrefix = 'test',
146
- } = options
147
-
148
- const logger = createMockLogger()
149
- let analyticsSpy: AnalyticsSpies | undefined
150
- let cryptoSpy: CryptoMockSpies | undefined
151
- let dbSpy: DbSpies | undefined
152
-
153
- const beforeEach = (): void => {
154
- // Reset tool call ID counter for deterministic tests
155
- resetToolCallIdCounter()
156
-
157
- // Set up analytics mocks
158
- if (analytics && analyticsModule) {
159
- analyticsSpy = setupAnalyticsMocks(analyticsModule)
160
- }
161
-
162
- // Set up crypto mocks
163
- if (crypto) {
164
- cryptoSpy = setupCryptoMocks({ prefix: cryptoPrefix, sequential: true })
165
- }
166
-
167
- // Set up database mocks
168
- if (database && dbModule) {
169
- dbSpy = setupDbSpies(dbModule)
170
- }
171
- }
172
-
173
- const afterEach = (): void => {
174
- // Restore all mocks
175
- analyticsSpy?.restore()
176
- cryptoSpy?.restore()
177
- dbSpy?.restore()
178
-
179
- // Reset the spies
180
- analyticsSpy = undefined
181
- cryptoSpy = undefined
182
- dbSpy = undefined
183
- }
184
-
185
- const restore = afterEach
186
-
187
- return {
188
- logger,
189
- get analyticsSpy() {
190
- return analyticsSpy
191
- },
192
- get cryptoSpy() {
193
- return cryptoSpy
194
- },
195
- get dbSpy() {
196
- return dbSpy
197
- },
198
- beforeEach,
199
- afterEach,
200
- restore,
201
- }
202
- }
203
-
204
- /**
205
- * A simple sleep function for async tests.
206
- *
207
- * @param ms - Milliseconds to sleep
208
- * @returns A promise that resolves after the specified time
209
- *
210
- * @example
211
- * ```typescript
212
- * await sleep(100) // Wait 100ms
213
- * ```
214
- */
215
- export function sleep(ms: number): Promise<void> {
216
- return new Promise((resolve) => setTimeout(resolve, ms))
217
- }
218
-
219
- /**
220
- * Waits for a condition to be true, polling at the specified interval.
221
- *
222
- * @param condition - Function that returns true when the condition is met
223
- * @param timeout - Maximum time to wait in ms
224
- * @param interval - Polling interval in ms
225
- * @returns A promise that resolves when the condition is met
226
- * @throws Error if the timeout is reached
227
- *
228
- * @example
229
- * ```typescript
230
- * await waitFor(() => document.querySelector('.loaded') !== null)
231
- * ```
232
- */
233
- export async function waitFor(
234
- condition: () => boolean | Promise<boolean>,
235
- timeout: number = 5000,
236
- interval: number = 50,
237
- ): Promise<void> {
238
- const start = Date.now()
239
-
240
- while (Date.now() - start < timeout) {
241
- const result = await condition()
242
- if (result) {
243
- return
244
- }
245
- await sleep(interval)
246
- }
247
-
248
- throw new Error(`waitFor timed out after ${timeout}ms`)
249
- }
250
-
251
- /**
252
- * Wraps a function to capture its call arguments.
253
- * Useful for verifying function calls in tests.
254
- *
255
- * @param fn - The function to wrap
256
- * @returns An object with the wrapped function and captured calls
257
- *
258
- * @example
259
- * ```typescript
260
- * const { fn, calls } = captureCallArgs((a: number, b: string) => a + b.length)
261
- *
262
- * fn(1, 'hello')
263
- * fn(2, 'world')
264
- *
265
- * expect(calls).toEqual([
266
- * [1, 'hello'],
267
- * [2, 'world'],
268
- * ])
269
- * ```
270
- */
271
- export function captureCallArgs<T extends unknown[], R>(
272
- fn: (...args: T) => R,
273
- ): { fn: (...args: T) => R; calls: T[] } {
274
- const calls: T[] = []
275
-
276
- const wrappedFn = (...args: T): R => {
277
- calls.push(args)
278
- return fn(...args)
279
- }
280
-
281
- return { fn: wrappedFn, calls }
282
- }
@@ -1,34 +0,0 @@
1
- import { describe, expect, test } from 'bun:test'
2
- import z from 'zod/v4'
3
-
4
- import { compileToolDefinitions } from '../compile-tool-definitions'
5
-
6
- // These tests feed synthetic schemas so they exercise the compile logic
7
- // directly and stay stable as real tools are added, removed, or reshaped.
8
- describe('compileToolDefinitions', () => {
9
- test('emits gravity index action enum values', () => {
10
- const definitions = compileToolDefinitions()
11
-
12
- expect(definitions).toContain('export interface GravityIndexParams {')
13
- expect(definitions).not.toContain('export type GravityIndexParams =')
14
- expect(definitions).toContain(
15
- '"action": "search" | "browse" | "list_categories" | "get_service" | "report_integration"',
16
- )
17
- })
18
-
19
- test('keeps object tool schemas as interfaces', () => {
20
- const objectSchema = z.object({ query: z.string() })
21
- const definitions = compileToolDefinitions([
22
- { name: 'web_search', inputSchema: objectSchema },
23
- ])
24
-
25
- expect(definitions).toContain('export interface WebSearchParams {')
26
- })
27
-
28
- test('compiles every published tool by default', () => {
29
- const definitions = compileToolDefinitions()
30
-
31
- expect(definitions).toContain('export type ToolName =')
32
- expect(definitions).toContain('export interface ToolParamsMap {')
33
- })
34
- })
@@ -1,213 +0,0 @@
1
- import { describe, expect, it } from 'bun:test'
2
- import z from 'zod/v4'
3
-
4
- import {
5
- coerceToArray,
6
- coerceToObject,
7
- normalizeReplacementAliases,
8
- } from '../utils'
9
-
10
- describe('coerceToArray', () => {
11
- it('passes through arrays unchanged', () => {
12
- expect(coerceToArray(['a', 'b'])).toEqual(['a', 'b'])
13
- expect(coerceToArray([{ old: 'x', new: 'y' }])).toEqual([
14
- { old: 'x', new: 'y' },
15
- ])
16
- expect(coerceToArray([])).toEqual([])
17
- })
18
-
19
- it('wraps a single string in an array', () => {
20
- expect(coerceToArray('file.ts')).toEqual(['file.ts'])
21
- })
22
-
23
- it('wraps a single object in an array', () => {
24
- expect(coerceToArray({ old: 'x', new: 'y' })).toEqual([
25
- { old: 'x', new: 'y' },
26
- ])
27
- })
28
-
29
- it('wraps a single number in an array', () => {
30
- expect(coerceToArray(42)).toEqual([42])
31
- })
32
-
33
- it('parses a stringified JSON array', () => {
34
- expect(coerceToArray('["file1.ts", "file2.ts"]')).toEqual([
35
- 'file1.ts',
36
- 'file2.ts',
37
- ])
38
- })
39
-
40
- it('wraps a non-JSON string (does not parse as array)', () => {
41
- expect(coerceToArray('not-json')).toEqual(['not-json'])
42
- })
43
-
44
- it('wraps a stringified JSON object (not an array) in an array', () => {
45
- expect(coerceToArray('{"key": "value"}')).toEqual(['{"key": "value"}'])
46
- })
47
-
48
- it('passes through null', () => {
49
- expect(coerceToArray(null)).toBeNull()
50
- })
51
-
52
- it('passes through undefined', () => {
53
- expect(coerceToArray(undefined)).toBeUndefined()
54
- })
55
- })
56
-
57
- describe('coerceToObject', () => {
58
- it('passes through objects unchanged', () => {
59
- expect(coerceToObject({ key: 'value' })).toEqual({ key: 'value' })
60
- })
61
-
62
- it('parses a stringified JSON object', () => {
63
- expect(coerceToObject('{"key": "value"}')).toEqual({ key: 'value' })
64
- })
65
-
66
- it('leaves non-JSON strings untouched', () => {
67
- expect(coerceToObject('not-json')).toBe('not-json')
68
- })
69
-
70
- it('passes through arrays and primitives so validation can reject them', () => {
71
- expect(coerceToObject(['a'])).toEqual(['a'])
72
- expect(coerceToObject(1)).toBe(1)
73
- })
74
- })
75
-
76
- describe('coerceToArray with Zod schemas', () => {
77
- it('coerces a single string into an array for z.array(z.string())', () => {
78
- const schema = z.object({
79
- paths: z.preprocess(coerceToArray, z.array(z.string())),
80
- })
81
- const result = schema.safeParse({ paths: 'file.ts' })
82
- expect(result.success).toBe(true)
83
- if (result.success) {
84
- expect(result.data.paths).toEqual(['file.ts'])
85
- }
86
- })
87
-
88
- it('coerces a single object into an array for z.array(z.object(...))', () => {
89
- const schema = z.object({
90
- replacements: z.preprocess(
91
- coerceToArray,
92
- z.array(z.object({ old: z.string(), new: z.string() })),
93
- ),
94
- })
95
- const result = schema.safeParse({ replacements: { old: 'x', new: 'y' } })
96
- expect(result.success).toBe(true)
97
- if (result.success) {
98
- expect(result.data.replacements).toEqual([{ old: 'x', new: 'y' }])
99
- }
100
- })
101
-
102
- it('still validates correctly when already an array', () => {
103
- const schema = z.object({
104
- paths: z.preprocess(coerceToArray, z.array(z.string())),
105
- })
106
- const result = schema.safeParse({ paths: ['a.ts', 'b.ts'] })
107
- expect(result.success).toBe(true)
108
- if (result.success) {
109
- expect(result.data.paths).toEqual(['a.ts', 'b.ts'])
110
- }
111
- })
112
-
113
- it('still rejects invalid inner types after coercion', () => {
114
- const schema = z.object({
115
- paths: z.preprocess(coerceToArray, z.array(z.string())),
116
- })
117
- const result = schema.safeParse({ paths: 123 })
118
- expect(result.success).toBe(false)
119
- })
120
-
121
- it('works with optional arrays', () => {
122
- const schema = z.object({
123
- paths: z.preprocess(coerceToArray, z.array(z.string())).optional(),
124
- })
125
- const withValue = schema.safeParse({ paths: 'file.ts' })
126
- expect(withValue.success).toBe(true)
127
- if (withValue.success) {
128
- expect(withValue.data.paths).toEqual(['file.ts'])
129
- }
130
-
131
- const withoutValue = schema.safeParse({})
132
- expect(withoutValue.success).toBe(true)
133
- if (withoutValue.success) {
134
- expect(withoutValue.data.paths).toBeUndefined()
135
- }
136
- })
137
-
138
- it('produces identical JSON schema with or without preprocess', () => {
139
- const plain = z.object({ paths: z.array(z.string()) })
140
- const coerced = z.object({
141
- paths: z.preprocess(coerceToArray, z.array(z.string())),
142
- })
143
-
144
- const plainSchema = z.toJSONSchema(plain, { io: 'input' })
145
- const coercedSchema = z.toJSONSchema(coerced, { io: 'input' })
146
- expect(coercedSchema).toEqual(plainSchema)
147
- })
148
- })
149
-
150
- describe('coerceToObject with Zod schemas', () => {
151
- it('produces identical JSON schema with or without preprocess', () => {
152
- const plain = z.object({
153
- params: z.record(z.string(), z.any()).optional(),
154
- })
155
- const coerced = z.object({
156
- params: z
157
- .preprocess(coerceToObject, z.record(z.string(), z.any()))
158
- .optional(),
159
- })
160
-
161
- const plainSchema = z.toJSONSchema(plain, { io: 'input' })
162
- const coercedSchema = z.toJSONSchema(coerced, { io: 'input' })
163
- expect(coercedSchema).toEqual(plainSchema)
164
- })
165
- })
166
-
167
- describe('normalizeReplacementAliases', () => {
168
- it('maps old_str and new_str onto the documented replacement keys', () => {
169
- expect(
170
- normalizeReplacementAliases({
171
- old_str: 'before',
172
- new_str: 'after',
173
- allowMultiple: true,
174
- }),
175
- ).toEqual({
176
- old_str: 'before',
177
- new_str: 'after',
178
- oldString: 'before',
179
- newString: 'after',
180
- allowMultiple: true,
181
- })
182
- })
183
-
184
- it('maps old_string and new_string onto the documented replacement keys', () => {
185
- expect(
186
- normalizeReplacementAliases({
187
- old_string: 'before',
188
- new_string: 'after',
189
- }),
190
- ).toEqual({
191
- old_string: 'before',
192
- new_string: 'after',
193
- oldString: 'before',
194
- newString: 'after',
195
- })
196
- })
197
-
198
- it('does not overwrite documented replacement keys', () => {
199
- expect(
200
- normalizeReplacementAliases({
201
- oldString: 'before',
202
- newString: 'after',
203
- old_str: 'ignored',
204
- new_str: 'ignored',
205
- }),
206
- ).toEqual({
207
- oldString: 'before',
208
- newString: 'after',
209
- old_str: 'ignored',
210
- new_str: 'ignored',
211
- })
212
- })
213
- })
@@ -1,47 +0,0 @@
1
- import { describe, expect, test } from 'bun:test'
2
-
3
- import { readDocsParams } from '../tool/read-docs'
4
-
5
- describe('read_docs parameters', () => {
6
- test('trims text inputs and defaults max_tokens', () => {
7
- const result = readDocsParams.inputSchema.parse({
8
- libraryTitle: ' React ',
9
- topic: ' hooks ',
10
- })
11
-
12
- expect(result).toEqual({
13
- libraryTitle: 'React',
14
- topic: 'hooks',
15
- max_tokens: 10_000,
16
- })
17
- })
18
-
19
- test('rejects empty text and invalid token counts', () => {
20
- expect(
21
- readDocsParams.inputSchema.safeParse({
22
- libraryTitle: ' ',
23
- topic: 'hooks',
24
- }).success,
25
- ).toBe(false)
26
- expect(
27
- readDocsParams.inputSchema.safeParse({
28
- libraryTitle: 'React',
29
- topic: ' ',
30
- }).success,
31
- ).toBe(false)
32
- expect(
33
- readDocsParams.inputSchema.safeParse({
34
- libraryTitle: 'React',
35
- topic: 'hooks',
36
- max_tokens: -1,
37
- }).success,
38
- ).toBe(false)
39
- expect(
40
- readDocsParams.inputSchema.safeParse({
41
- libraryTitle: 'React',
42
- topic: 'hooks',
43
- max_tokens: 1.5,
44
- }).success,
45
- ).toBe(false)
46
- })
47
- })