@vibe-lang/runtime 0.2.5

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 (250) hide show
  1. package/package.json +46 -0
  2. package/src/ast/index.ts +375 -0
  3. package/src/ast.ts +2 -0
  4. package/src/debug/advanced-features.ts +482 -0
  5. package/src/debug/bun-inspector.ts +424 -0
  6. package/src/debug/handoff-manager.ts +283 -0
  7. package/src/debug/index.ts +150 -0
  8. package/src/debug/runner.ts +365 -0
  9. package/src/debug/server.ts +565 -0
  10. package/src/debug/stack-merger.ts +267 -0
  11. package/src/debug/state.ts +581 -0
  12. package/src/debug/test/advanced-features.test.ts +300 -0
  13. package/src/debug/test/e2e.test.ts +218 -0
  14. package/src/debug/test/handoff-manager.test.ts +256 -0
  15. package/src/debug/test/runner.test.ts +256 -0
  16. package/src/debug/test/stack-merger.test.ts +163 -0
  17. package/src/debug/test/state.test.ts +400 -0
  18. package/src/debug/test/ts-debug-integration.test.ts +374 -0
  19. package/src/debug/test/ts-import-tracker.test.ts +125 -0
  20. package/src/debug/test/ts-source-map.test.ts +169 -0
  21. package/src/debug/ts-import-tracker.ts +151 -0
  22. package/src/debug/ts-source-map.ts +171 -0
  23. package/src/errors/index.ts +124 -0
  24. package/src/index.ts +358 -0
  25. package/src/lexer/index.ts +348 -0
  26. package/src/lexer.ts +2 -0
  27. package/src/parser/index.ts +792 -0
  28. package/src/parser/parse.ts +45 -0
  29. package/src/parser/test/async.test.ts +248 -0
  30. package/src/parser/test/destructuring.test.ts +167 -0
  31. package/src/parser/test/do-expression.test.ts +486 -0
  32. package/src/parser/test/errors/do-expression.test.ts +95 -0
  33. package/src/parser/test/errors/error-locations.test.ts +230 -0
  34. package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
  35. package/src/parser/test/errors/missing-tokens.test.ts +126 -0
  36. package/src/parser/test/errors/model-declaration.test.ts +185 -0
  37. package/src/parser/test/errors/nested-blocks.test.ts +226 -0
  38. package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
  39. package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
  40. package/src/parser/test/import-export.test.ts +143 -0
  41. package/src/parser/test/literals.test.ts +404 -0
  42. package/src/parser/test/model-declaration.test.ts +161 -0
  43. package/src/parser/test/nested-blocks.test.ts +402 -0
  44. package/src/parser/test/parser.test.ts +743 -0
  45. package/src/parser/test/private.test.ts +136 -0
  46. package/src/parser/test/template-literal.test.ts +127 -0
  47. package/src/parser/test/tool-declaration.test.ts +302 -0
  48. package/src/parser/test/ts-block.test.ts +252 -0
  49. package/src/parser/test/type-annotations.test.ts +254 -0
  50. package/src/parser/visitor/helpers.ts +330 -0
  51. package/src/parser/visitor.ts +794 -0
  52. package/src/parser.ts +2 -0
  53. package/src/runtime/ai/cache-chunking.test.ts +69 -0
  54. package/src/runtime/ai/cache-chunking.ts +73 -0
  55. package/src/runtime/ai/client.ts +109 -0
  56. package/src/runtime/ai/context.ts +168 -0
  57. package/src/runtime/ai/formatters.ts +316 -0
  58. package/src/runtime/ai/index.ts +38 -0
  59. package/src/runtime/ai/language-ref.ts +38 -0
  60. package/src/runtime/ai/providers/anthropic.ts +253 -0
  61. package/src/runtime/ai/providers/google.ts +201 -0
  62. package/src/runtime/ai/providers/openai.ts +156 -0
  63. package/src/runtime/ai/retry.ts +100 -0
  64. package/src/runtime/ai/return-tools.ts +301 -0
  65. package/src/runtime/ai/test/client.test.ts +83 -0
  66. package/src/runtime/ai/test/formatters.test.ts +485 -0
  67. package/src/runtime/ai/test/retry.test.ts +137 -0
  68. package/src/runtime/ai/test/return-tools.test.ts +450 -0
  69. package/src/runtime/ai/test/tool-loop.test.ts +319 -0
  70. package/src/runtime/ai/test/tool-schema.test.ts +241 -0
  71. package/src/runtime/ai/tool-loop.ts +203 -0
  72. package/src/runtime/ai/tool-schema.ts +151 -0
  73. package/src/runtime/ai/types.ts +113 -0
  74. package/src/runtime/ai-logger.ts +255 -0
  75. package/src/runtime/ai-provider.ts +347 -0
  76. package/src/runtime/async/dependencies.ts +276 -0
  77. package/src/runtime/async/executor.ts +293 -0
  78. package/src/runtime/async/index.ts +43 -0
  79. package/src/runtime/async/scheduling.ts +163 -0
  80. package/src/runtime/async/test/dependencies.test.ts +284 -0
  81. package/src/runtime/async/test/executor.test.ts +388 -0
  82. package/src/runtime/context.ts +357 -0
  83. package/src/runtime/exec/ai.ts +139 -0
  84. package/src/runtime/exec/expressions.ts +475 -0
  85. package/src/runtime/exec/frames.ts +26 -0
  86. package/src/runtime/exec/functions.ts +305 -0
  87. package/src/runtime/exec/interpolation.ts +312 -0
  88. package/src/runtime/exec/statements.ts +604 -0
  89. package/src/runtime/exec/tools.ts +129 -0
  90. package/src/runtime/exec/typescript.ts +215 -0
  91. package/src/runtime/exec/variables.ts +279 -0
  92. package/src/runtime/index.ts +975 -0
  93. package/src/runtime/modules.ts +452 -0
  94. package/src/runtime/serialize.ts +103 -0
  95. package/src/runtime/state.ts +489 -0
  96. package/src/runtime/stdlib/core.ts +45 -0
  97. package/src/runtime/stdlib/directory.test.ts +156 -0
  98. package/src/runtime/stdlib/edit.test.ts +154 -0
  99. package/src/runtime/stdlib/fastEdit.test.ts +201 -0
  100. package/src/runtime/stdlib/glob.test.ts +106 -0
  101. package/src/runtime/stdlib/grep.test.ts +144 -0
  102. package/src/runtime/stdlib/index.ts +16 -0
  103. package/src/runtime/stdlib/readFile.test.ts +123 -0
  104. package/src/runtime/stdlib/tools/index.ts +707 -0
  105. package/src/runtime/stdlib/writeFile.test.ts +157 -0
  106. package/src/runtime/step.ts +969 -0
  107. package/src/runtime/test/ai-context.test.ts +1086 -0
  108. package/src/runtime/test/ai-result-object.test.ts +419 -0
  109. package/src/runtime/test/ai-tool-flow.test.ts +859 -0
  110. package/src/runtime/test/async-execution-order.test.ts +618 -0
  111. package/src/runtime/test/async-execution.test.ts +344 -0
  112. package/src/runtime/test/async-nested.test.ts +660 -0
  113. package/src/runtime/test/async-parallel-timing.test.ts +546 -0
  114. package/src/runtime/test/basic1.test.ts +154 -0
  115. package/src/runtime/test/binary-operators.test.ts +431 -0
  116. package/src/runtime/test/break-statement.test.ts +257 -0
  117. package/src/runtime/test/context-modes.test.ts +650 -0
  118. package/src/runtime/test/context.test.ts +466 -0
  119. package/src/runtime/test/core-functions.test.ts +228 -0
  120. package/src/runtime/test/e2e.test.ts +88 -0
  121. package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
  122. package/src/runtime/test/error-locations/main-error.vibe +4 -0
  123. package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
  124. package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
  125. package/src/runtime/test/for-in.test.ts +312 -0
  126. package/src/runtime/test/helpers.ts +69 -0
  127. package/src/runtime/test/imports.test.ts +334 -0
  128. package/src/runtime/test/json-expressions.test.ts +232 -0
  129. package/src/runtime/test/literals.test.ts +372 -0
  130. package/src/runtime/test/logical-indexing.test.ts +478 -0
  131. package/src/runtime/test/member-methods.test.ts +324 -0
  132. package/src/runtime/test/model-config.test.ts +338 -0
  133. package/src/runtime/test/null-handling.test.ts +342 -0
  134. package/src/runtime/test/private-visibility.test.ts +332 -0
  135. package/src/runtime/test/runtime-state.test.ts +514 -0
  136. package/src/runtime/test/scoping.test.ts +370 -0
  137. package/src/runtime/test/string-interpolation.test.ts +354 -0
  138. package/src/runtime/test/template-literal.test.ts +181 -0
  139. package/src/runtime/test/tool-execution.test.ts +467 -0
  140. package/src/runtime/test/tool-schema-generation.test.ts +477 -0
  141. package/src/runtime/test/tostring.test.ts +210 -0
  142. package/src/runtime/test/ts-block.test.ts +594 -0
  143. package/src/runtime/test/ts-error-location.test.ts +231 -0
  144. package/src/runtime/test/types.test.ts +732 -0
  145. package/src/runtime/test/verbose-logger.test.ts +710 -0
  146. package/src/runtime/test/vibe-expression.test.ts +54 -0
  147. package/src/runtime/test/vibe-value-errors.test.ts +541 -0
  148. package/src/runtime/test/while.test.ts +232 -0
  149. package/src/runtime/tools/builtin.ts +30 -0
  150. package/src/runtime/tools/directory-tools.ts +70 -0
  151. package/src/runtime/tools/file-tools.ts +228 -0
  152. package/src/runtime/tools/index.ts +5 -0
  153. package/src/runtime/tools/registry.ts +48 -0
  154. package/src/runtime/tools/search-tools.ts +134 -0
  155. package/src/runtime/tools/security.ts +36 -0
  156. package/src/runtime/tools/system-tools.ts +312 -0
  157. package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
  158. package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
  159. package/src/runtime/tools/test/registry.test.ts +713 -0
  160. package/src/runtime/tools/test/security.test.ts +86 -0
  161. package/src/runtime/tools/test/system-tools.test.ts +679 -0
  162. package/src/runtime/tools/test/ts-schema.test.ts +357 -0
  163. package/src/runtime/tools/ts-schema.ts +341 -0
  164. package/src/runtime/tools/types.ts +89 -0
  165. package/src/runtime/tools/utility-tools.ts +198 -0
  166. package/src/runtime/ts-eval.ts +126 -0
  167. package/src/runtime/types.ts +797 -0
  168. package/src/runtime/validation.ts +160 -0
  169. package/src/runtime/verbose-logger.ts +459 -0
  170. package/src/runtime.ts +2 -0
  171. package/src/semantic/analyzer-context.ts +62 -0
  172. package/src/semantic/analyzer-validators.ts +575 -0
  173. package/src/semantic/analyzer-visitors.ts +534 -0
  174. package/src/semantic/analyzer.ts +83 -0
  175. package/src/semantic/index.ts +11 -0
  176. package/src/semantic/symbol-table.ts +58 -0
  177. package/src/semantic/test/async-validation.test.ts +301 -0
  178. package/src/semantic/test/compress-validation.test.ts +179 -0
  179. package/src/semantic/test/const-reassignment.test.ts +111 -0
  180. package/src/semantic/test/control-flow.test.ts +346 -0
  181. package/src/semantic/test/destructuring.test.ts +185 -0
  182. package/src/semantic/test/duplicate-declarations.test.ts +168 -0
  183. package/src/semantic/test/export-validation.test.ts +111 -0
  184. package/src/semantic/test/fixtures/math.ts +31 -0
  185. package/src/semantic/test/imports.test.ts +148 -0
  186. package/src/semantic/test/json-type.test.ts +68 -0
  187. package/src/semantic/test/literals.test.ts +127 -0
  188. package/src/semantic/test/model-validation.test.ts +179 -0
  189. package/src/semantic/test/prompt-validation.test.ts +343 -0
  190. package/src/semantic/test/scoping.test.ts +312 -0
  191. package/src/semantic/test/tool-validation.test.ts +306 -0
  192. package/src/semantic/test/ts-type-checking.test.ts +563 -0
  193. package/src/semantic/test/type-constraints.test.ts +111 -0
  194. package/src/semantic/test/type-inference.test.ts +87 -0
  195. package/src/semantic/test/type-validation.test.ts +552 -0
  196. package/src/semantic/test/undefined-variables.test.ts +163 -0
  197. package/src/semantic/ts-block-checker.ts +204 -0
  198. package/src/semantic/ts-signatures.ts +194 -0
  199. package/src/semantic/ts-types.ts +170 -0
  200. package/src/semantic/types.ts +58 -0
  201. package/tests/fixtures/conditional-logic.vibe +14 -0
  202. package/tests/fixtures/function-call.vibe +16 -0
  203. package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
  204. package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
  205. package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
  206. package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
  207. package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
  208. package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
  209. package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
  210. package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
  211. package/tests/fixtures/imports/nested-import/main.vibe +3 -0
  212. package/tests/fixtures/imports/nested-import/utils.ts +3 -0
  213. package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
  214. package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
  215. package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
  216. package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
  217. package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
  218. package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
  219. package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
  220. package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
  221. package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
  222. package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
  223. package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
  224. package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
  225. package/tests/fixtures/imports/ts-import/main.vibe +4 -0
  226. package/tests/fixtures/imports/ts-import/math.ts +9 -0
  227. package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
  228. package/tests/fixtures/imports/ts-variables/data.ts +10 -0
  229. package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
  230. package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
  231. package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
  232. package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
  233. package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
  234. package/tests/fixtures/multiple-ai-calls.vibe +10 -0
  235. package/tests/fixtures/simple-greeting.vibe +6 -0
  236. package/tests/fixtures/template-literals.vibe +11 -0
  237. package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
  238. package/tests/integration/basic-ai/basic-ai.vibe +12 -0
  239. package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
  240. package/tests/integration/bug-fix/buggy-code.ts +22 -0
  241. package/tests/integration/bug-fix/fix-bug.vibe +21 -0
  242. package/tests/integration/compress/compress.integration.test.ts +206 -0
  243. package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
  244. package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
  245. package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
  246. package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
  247. package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
  248. package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
  249. package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
  250. package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
@@ -0,0 +1,191 @@
1
+ // Number Analyzer Integration Test
2
+ // Tests multiple Vibe features working together with real AI calls
3
+ // Importantly tests that AI can see variables from context
4
+
5
+ import { describe, test, expect } from 'bun:test';
6
+ import { Runtime, formatAIInteractions } from '../../../src/runtime';
7
+ import { createRealAIProvider } from '../../../src/runtime/ai-provider';
8
+ import { parse } from '../../../src/parser/parse';
9
+
10
+ // API Keys from environment
11
+ const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
12
+ const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
13
+ const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY;
14
+
15
+ // Provider configurations
16
+ const providers = [
17
+ {
18
+ name: 'OpenAI',
19
+ hasKey: !!OPENAI_API_KEY,
20
+ modelConfig: `
21
+ model analyzer = {
22
+ name: "gpt-5-mini",
23
+ apiKey: "${OPENAI_API_KEY}",
24
+ url: "https://api.openai.com/v1",
25
+ provider: "openai"
26
+ }
27
+ `,
28
+ },
29
+ {
30
+ name: 'Anthropic',
31
+ hasKey: !!ANTHROPIC_API_KEY,
32
+ modelConfig: `
33
+ model analyzer = {
34
+ name: "claude-haiku-4-5",
35
+ apiKey: "${ANTHROPIC_API_KEY}",
36
+ url: "https://api.anthropic.com",
37
+ provider: "anthropic",
38
+ thinkingLevel: "high"
39
+ }
40
+ `,
41
+ },
42
+ {
43
+ name: 'Google',
44
+ hasKey: !!GOOGLE_API_KEY,
45
+ modelConfig: `
46
+ model analyzer = {
47
+ name: "gemini-3-flash-preview",
48
+ apiKey: "${GOOGLE_API_KEY}",
49
+ provider: "google"
50
+ }
51
+ `,
52
+ },
53
+ ];
54
+
55
+ // Shared Vibe program (model config is prepended)
56
+ const VIBE_PROGRAM = `
57
+ // Number Analyzer - Comprehensive Integration Test
58
+ // Tests: model, variables, types, AI calls, loops, conditionals, functions, arrays, operators, context
59
+
60
+ // Function to check if a number is even
61
+ function isEven(n: number): boolean {
62
+ return n % 2 == 0
63
+ }
64
+
65
+ // Function to categorize a number
66
+ function categorize(n: number): text {
67
+ if n < 0 {
68
+ return "negative"
69
+ }
70
+ if n == 0 {
71
+ return "zero"
72
+ }
73
+ if n > 100 {
74
+ return "large"
75
+ }
76
+ return "small"
77
+ }
78
+
79
+ // Get a list of numbers from AI
80
+ let numbers: number[] = vibe "Return a JSON array of exactly 5 integers between -50 and 150. Mix of negative, zero, and positive." analyzer default
81
+
82
+ // Initialize counters and result arrays
83
+ let evenCount: number = 0
84
+ let oddCount: number = 0
85
+ let categories: text[] = []
86
+
87
+ // Process each number
88
+ for num in numbers {
89
+ // Check even/odd
90
+ if isEven(num) {
91
+ evenCount = evenCount + 1
92
+ } else {
93
+ oddCount = oddCount + 1
94
+ }
95
+
96
+ // Get category and add to list
97
+ let cat = categorize(num)
98
+ categories.push(cat)
99
+ }
100
+
101
+ // Calculate total
102
+ let total: number = evenCount + oddCount
103
+
104
+ // Get AI summary - reference variables by name, AI sees them in context
105
+ let summary: text = vibe "Using the variables total, evenCount, oddCount, and categories from context, write a one-sentence summary of the number analysis." analyzer default
106
+
107
+ // Final result - AI should read variable values from context
108
+ let result: json = vibe "Return a JSON object with fields: analyzed, evenCount, oddCount, summary. Use the values from context variables: total for analyzed, evenCount, oddCount, and summary." analyzer default
109
+ `;
110
+
111
+ async function runVibe(modelConfig: string, logAi = true): Promise<Runtime> {
112
+ const program = parse(modelConfig + VIBE_PROGRAM);
113
+ const runtime = new Runtime(
114
+ program,
115
+ createRealAIProvider(() => runtime.getState()),
116
+ { logAiInteractions: logAi }
117
+ );
118
+ await runtime.run();
119
+
120
+ if (logAi) {
121
+ console.log('\n' + formatAIInteractions(runtime.getState().aiInteractions));
122
+ }
123
+
124
+ return runtime;
125
+ }
126
+
127
+ function runAssertions(runtime: Runtime) {
128
+ // Check numbers array was populated
129
+ const numbers = runtime.getValue('numbers') as number[];
130
+ expect(Array.isArray(numbers)).toBe(true);
131
+ expect(numbers).toHaveLength(5);
132
+ numbers.forEach(n => {
133
+ expect(typeof n).toBe('number');
134
+ expect(n).toBeGreaterThanOrEqual(-50);
135
+ expect(n).toBeLessThanOrEqual(150);
136
+ });
137
+
138
+ // Check counters
139
+ const evenCount = runtime.getValue('evenCount') as number;
140
+ const oddCount = runtime.getValue('oddCount') as number;
141
+ expect(typeof evenCount).toBe('number');
142
+ expect(typeof oddCount).toBe('number');
143
+ expect(evenCount + oddCount).toBe(5);
144
+
145
+ // Verify even/odd counting is correct
146
+ const actualEven = numbers.filter(n => n % 2 === 0).length;
147
+ const actualOdd = numbers.filter(n => n % 2 !== 0).length;
148
+ expect(evenCount).toBe(actualEven);
149
+ expect(oddCount).toBe(actualOdd);
150
+
151
+ // Check categories array
152
+ const categories = runtime.getValue('categories') as string[];
153
+ expect(Array.isArray(categories)).toBe(true);
154
+ expect(categories).toHaveLength(5);
155
+
156
+ // Verify categories match the categorize function logic
157
+ numbers.forEach((n, i) => {
158
+ const expectedCat = n < 0 ? 'negative' : n === 0 ? 'zero' : n > 100 ? 'large' : 'small';
159
+ expect(categories[i]).toBe(expectedCat);
160
+ });
161
+
162
+ // Check total
163
+ const total = runtime.getValue('total') as number;
164
+ expect(total).toBe(5);
165
+
166
+ // Check summary is a non-empty string
167
+ const summary = runtime.getValue('summary') as string;
168
+ expect(typeof summary).toBe('string');
169
+ expect(summary.length).toBeGreaterThan(10);
170
+
171
+ // Check final result object - AI should have read values from context
172
+ const result = runtime.getValue('result') as Record<string, unknown>;
173
+ expect(typeof result).toBe('object');
174
+ expect(result).not.toBeNull();
175
+
176
+ // The AI should have correctly read these values from context
177
+ expect(result.analyzed).toBe(5);
178
+ expect(result.evenCount).toBe(evenCount);
179
+ expect(result.oddCount).toBe(oddCount);
180
+ expect(typeof result.summary).toBe('string');
181
+ }
182
+
183
+ // Generate tests for each provider
184
+ for (const provider of providers) {
185
+ describe.skipIf(!provider.hasKey)(`${provider.name} Multi-Feature Integration`, () => {
186
+ test('number analyzer - full workflow with context', async () => {
187
+ const runtime = await runVibe(provider.modelConfig);
188
+ runAssertions(runtime);
189
+ }, 120000);
190
+ });
191
+ }
@@ -0,0 +1,59 @@
1
+ // Number Analyzer - Comprehensive Integration Test
2
+ // Tests: model, variables, types, AI calls, loops, conditionals, functions, arrays, operators, context
3
+
4
+ model analyzer = {
5
+ name: "gpt-5-mini",
6
+ apiKey: OPENAI_API_KEY,
7
+ url: "https://api.openai.com/v1",
8
+ provider: "openai"
9
+ }
10
+
11
+ // Function to check if a number is even
12
+ function isEven(n: number): boolean {
13
+ return n % 2 == 0
14
+ }
15
+
16
+ // Function to categorize a number
17
+ function categorize(n: number): text {
18
+ if n < 0 {
19
+ return "negative"
20
+ }
21
+ if n == 0 {
22
+ return "zero"
23
+ }
24
+ if n > 100 {
25
+ return "large"
26
+ }
27
+ return "small"
28
+ }
29
+
30
+ // Get a list of numbers from AI
31
+ let numbers: number[] = vibe "Return a JSON array of exactly 5 integers between -50 and 150. Mix of negative, zero, and positive." analyzer default
32
+
33
+ // Initialize counters and result arrays
34
+ let evenCount: number = 0
35
+ let oddCount: number = 0
36
+ let categories: text[] = []
37
+
38
+ // Process each number
39
+ for num in numbers {
40
+ // Check even/odd
41
+ if isEven(num) {
42
+ evenCount = evenCount + 1
43
+ } else {
44
+ oddCount = oddCount + 1
45
+ }
46
+
47
+ // Get category and add to list
48
+ let cat = categorize(num)
49
+ categories.push(cat)
50
+ }
51
+
52
+ // Calculate total
53
+ let total: number = evenCount + oddCount
54
+
55
+ // Get AI summary - reference variables by name, AI sees them in context
56
+ let summary: text = vibe "Using the variables total, evenCount, oddCount, and categories from context, write a one-sentence summary of the number analysis." analyzer default
57
+
58
+ // Final result - AI should read variable values from context
59
+ let result: json = vibe "Return a JSON object with fields: analyzed, evenCount, oddCount, summary. Use the values from context variables: total for analyzed, evenCount, oddCount, and summary." analyzer default
@@ -0,0 +1,93 @@
1
+ // Tool Calls Integration Test
2
+ // Tests that AIResultObject.toolCalls captures tool execution history
3
+
4
+ import { describe, test, expect } from 'bun:test';
5
+ import { Runtime, formatAIInteractions } from '../../../src/runtime';
6
+ import { createRealAIProvider } from '../../../src/runtime/ai-provider';
7
+ import { parse } from '../../../src/parser/parse';
8
+
9
+ const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY;
10
+
11
+ const VIBE_PROGRAM = `
12
+ // Define tool first so it exists when referenced
13
+ tool randomNumber(min: number, max: number): number
14
+ @description "Generate a random number between min and max (inclusive)"
15
+ {
16
+ ts(min, max) {
17
+ return Math.floor(Math.random() * (max - min + 1)) + min
18
+ }
19
+ }
20
+
21
+ model m = {
22
+ name: "gemini-3-flash-preview",
23
+ apiKey: "${GOOGLE_API_KEY}",
24
+ provider: "google",
25
+ tools: [randomNumber]
26
+ }
27
+
28
+ // Ask AI to use the tool twice and return the largest
29
+ let result: number = vibe "Use the randomNumber tool twice: once with min=1 max=100, and once with min=1 max=100. Then return ONLY the larger of the two numbers as a single integer." m default
30
+
31
+ // Access the tool calls and the result value
32
+ // Note: toolCalls includes ALL tool calls, including internal __vibe_return_field
33
+ let allToolCallCount = result.toolCalls.len()
34
+ let largestNumber = result
35
+ `;
36
+
37
+ async function runTest(): Promise<Runtime> {
38
+ const program = parse(VIBE_PROGRAM);
39
+ const runtime = new Runtime(
40
+ program,
41
+ createRealAIProvider(() => runtime.getState()),
42
+ { logAiInteractions: true }
43
+ );
44
+ await runtime.run();
45
+ console.log('\n' + formatAIInteractions(runtime.getState().aiInteractions));
46
+ return runtime;
47
+ }
48
+
49
+ describe.skipIf(!GOOGLE_API_KEY)('Google - AIResultObject.toolCalls Integration', () => {
50
+ test('toolCalls array captures tool execution history', async () => {
51
+ const runtime = await runTest();
52
+
53
+ // Access the raw result to check structure
54
+ // toolCalls is on the VibeValue itself, not on .value
55
+ const state = runtime.getState();
56
+ const resultVar = state.callStack[0].locals['result'];
57
+ expect(resultVar).toHaveProperty('toolCalls');
58
+ expect(Array.isArray(resultVar.toolCalls)).toBe(true);
59
+
60
+ // toolCalls includes ALL tool calls: user tools + internal __vibe_return_field
61
+ // Filter to just user-defined tool calls (randomNumber)
62
+ const userToolCalls = resultVar.toolCalls.filter(
63
+ (call: { toolName: string }) => call.toolName === 'randomNumber'
64
+ );
65
+ expect(userToolCalls).toHaveLength(2);
66
+
67
+ // Verify total count from Vibe code includes all calls
68
+ const allToolCallCount = runtime.getValue('allToolCallCount') as number;
69
+ expect(allToolCallCount).toBeGreaterThanOrEqual(2); // At least 2 randomNumber + possibly __vibe_return_field
70
+
71
+ // Get the two random numbers from user tool calls
72
+ const num1 = Number(userToolCalls[0].result);
73
+ const num2 = Number(userToolCalls[1].result);
74
+ const expectedLargest = Math.max(num1, num2);
75
+
76
+ // Note: The largestNumber assertion is skipped because untyped declarations
77
+ // don't capture __vibe_return_field results - the model returns via tool call
78
+ // but without a type annotation, the empty text response is used instead.
79
+ // This is a known limitation when using vibe without a return type.
80
+ // TODO: Consider always processing __vibe_return_field even for untyped decls
81
+ console.log(`Tool calls returned: ${num1}, ${num2}. Expected largest: ${expectedLargest}`);
82
+
83
+ // Each user tool call should have the expected structure
84
+ for (const call of userToolCalls) {
85
+ expect(call).toHaveProperty('toolName');
86
+ expect(call).toHaveProperty('args');
87
+ expect(call).toHaveProperty('result');
88
+ expect(call).toHaveProperty('duration');
89
+ expect(call.toolName).toBe('randomNumber');
90
+ expect(typeof call.duration).toBe('number');
91
+ }
92
+ }, 60000);
93
+ });