taist 0.1.0 → 0.1.1

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.
package/README.md CHANGED
@@ -13,6 +13,7 @@ Version: 0.1.0 | January 2025 | [Technical Specification](./SPEC.md)
13
13
  5. [Test Integration](#test-integration)
14
14
  6. [Configuration Reference](#configuration-reference)
15
15
  7. [Usage Examples](#usage-examples)
16
+ 8. [TypeScript Support](#typescript-support)
16
17
 
17
18
  ---
18
19
 
@@ -236,6 +237,63 @@ const tracedFn = tracer.wrapMethod(myFunction, 'myFunction');
236
237
  - Custom trace collection logic
237
238
  - Maximum flexibility needed
238
239
 
240
+ ### Side-Effect Import vs Direct Function Calls
241
+
242
+ The `import 'taist/instrument'` side-effect import is **optional**. It provides convenience features but is not required for basic instrumentation.
243
+
244
+ #### What the Side-Effect Import Does
245
+
246
+ When you add `import 'taist/instrument'` to your entry point, it:
247
+
248
+ 1. **Creates a global ServiceTracer** - Initialized from environment variables
249
+ 2. **Sets up signal handlers** - Outputs trace summary on SIGINT/SIGTERM
250
+ 3. **Configures periodic output** - Writes trace summaries at intervals
251
+ 4. **Exports a pre-configured `tracer`** - Ready for immediate use
252
+
253
+ #### When to Use the Side-Effect Import
254
+
255
+ **Use `import 'taist/instrument'`** when:
256
+ - You want automatic trace output on process shutdown
257
+ - You're instrumenting at application startup
258
+ - You want environment-variable-based configuration
259
+ - You need the global tracer instance
260
+
261
+ ```javascript
262
+ // Entry point - loads global tracer and signal handlers
263
+ import 'taist/instrument';
264
+ import { instrumentExpress, instrumentService } from 'taist/instrument';
265
+ ```
266
+
267
+ #### When to Skip the Side-Effect Import
268
+
269
+ **Skip the side-effect import** when:
270
+ - You're instrumenting post-startup (e.g., in tests)
271
+ - You want more control over tracer lifecycle
272
+ - You don't want signal handlers registered
273
+ - You're creating multiple independent tracers
274
+
275
+ ```javascript
276
+ // Direct function imports - no side effects
277
+ import { instrumentExpress, instrumentService } from 'taist/instrument';
278
+
279
+ // Or use the programmatic API for full control
280
+ import { ServiceTracer } from 'taist';
281
+ const tracer = new ServiceTracer({ enabled: true });
282
+ ```
283
+
284
+ #### Post-Startup Instrumentation
285
+
286
+ The instrumentation functions (`instrumentExpress`, `instrumentService`, etc.) work independently of the side-effect import. You can instrument services after your application has started:
287
+
288
+ ```javascript
289
+ // No side-effect import needed
290
+ import { instrumentService } from 'taist/instrument';
291
+
292
+ // Instrument a service created dynamically
293
+ const service = new DynamicService();
294
+ const traced = instrumentService(service, 'DynamicService');
295
+ ```
296
+
239
297
  ---
240
298
 
241
299
  ## Test Integration
@@ -310,6 +368,139 @@ session.printTraces({
310
368
  });
311
369
  ```
312
370
 
371
+ ### Vitest Reporter Plugin
372
+
373
+ The taist Vitest reporter replaces Vitest's default output with TOON format and adds execution tracing. When you run `vitest`, you get:
374
+ - Token-optimized test results (90% fewer tokens than default output)
375
+ - Automatic execution traces from instrumented code
376
+ - Call hierarchy with timing, arguments, and return values
377
+
378
+ #### Step 1: Configure vitest.config.js
379
+
380
+ ```javascript
381
+ // vitest.config.js
382
+ import { defineConfig } from 'vitest/config';
383
+
384
+ export default defineConfig({
385
+ test: {
386
+ reporters: ['taist/vitest-reporter']
387
+ }
388
+ });
389
+ ```
390
+
391
+ #### Step 2: Instrument Your Code
392
+
393
+ In your test file or setup file, instrument the services you want to trace:
394
+
395
+ ```javascript
396
+ // test/my-service.test.js
397
+ import { describe, it, expect } from 'vitest';
398
+ import { instrumentService } from 'taist/instrument';
399
+ import { UserService } from '../src/user-service.js';
400
+
401
+ // Wrap the service with instrumentation
402
+ const userService = instrumentService(new UserService(), 'UserService');
403
+
404
+ describe('UserService', () => {
405
+ it('should create a user', async () => {
406
+ // Calls to userService methods are now traced
407
+ const user = await userService.create({ name: 'Alice' });
408
+ expect(user.id).toBeDefined();
409
+ });
410
+ });
411
+ ```
412
+
413
+ #### Step 3: Run Tests
414
+
415
+ ```bash
416
+ vitest run
417
+ ```
418
+
419
+ #### Example Output
420
+
421
+ ```
422
+ ===TESTS: 5/5===
423
+
424
+ ============================================================
425
+ TRACE OUTPUT
426
+ ============================================================
427
+ Traces: 12 | Requests: 5
428
+
429
+ --- UserService.create ---
430
+ fn:UserService.create depth:0 45ms
431
+ fn:UserService.validate depth:1 5ms
432
+ fn:UserService.hashPassword depth:1 30ms
433
+ fn:UserService.save depth:1 10ms
434
+
435
+ --- UserService.getById ---
436
+ fn:UserService.getById depth:0 8ms
437
+ fn:Cache.get depth:1 2ms
438
+ ```
439
+
440
+ #### Reporter Options
441
+
442
+ ```javascript
443
+ export default defineConfig({
444
+ test: {
445
+ reporters: [['taist/vitest-reporter', {
446
+ format: 'toon', // Output format: 'toon' | 'json' | 'compact'
447
+ traceEnabled: true, // Start trace collector (default: true)
448
+ traceDepth: 3, // Max depth to trace (default: 3)
449
+ showTrace: true, // Include trace output (default: true)
450
+ maxTraceGroups: 10, // Max trace groups to show (default: 10)
451
+ silent: false, // Suppress all output (default: false)
452
+ outputFile: null // Write to file instead of stdout
453
+ }]]
454
+ }
455
+ });
456
+ ```
457
+
458
+ #### How Trace Collection Works
459
+
460
+ 1. **Reporter starts** → Creates a TraceCollector (Unix socket server)
461
+ 2. **Environment set** → Sets `TAIST_ENABLED=true` and `TAIST_COLLECTOR_SOCKET=/tmp/taist-collector-xxx.sock`
462
+ 3. **Tests run** → Instrumented code sends traces to the collector via the socket
463
+ 4. **Tests finish** → Reporter collects traces and outputs them with test results
464
+
465
+ **Note:** Traces are collected from code instrumented with `instrumentService()` or `instrumentExpress()`. Code that isn't instrumented won't appear in the trace output.
466
+
467
+ #### Using with Test Setup Files
468
+
469
+ For larger projects, instrument services in a setup file:
470
+
471
+ ```javascript
472
+ // test/setup.js
473
+ import { instrumentService } from 'taist/instrument';
474
+ import { UserService } from '../src/services/user-service.js';
475
+ import { OrderService } from '../src/services/order-service.js';
476
+
477
+ // Export instrumented services for use in tests
478
+ export const userService = instrumentService(new UserService(), 'UserService');
479
+ export const orderService = instrumentService(new OrderService(), 'OrderService');
480
+ ```
481
+
482
+ ```javascript
483
+ // vitest.config.js
484
+ export default defineConfig({
485
+ test: {
486
+ reporters: ['taist/vitest-reporter'],
487
+ setupFiles: ['./test/setup.js']
488
+ }
489
+ });
490
+ ```
491
+
492
+ ```javascript
493
+ // test/user.test.js
494
+ import { userService } from './setup.js';
495
+
496
+ describe('UserService', () => {
497
+ it('should get user by id', async () => {
498
+ const user = await userService.getById(123);
499
+ expect(user).toBeDefined();
500
+ });
501
+ });
502
+ ```
503
+
313
504
  ### Example Output
314
505
 
315
506
  When tests complete, you'll see the execution tree grouped by HTTP request:
@@ -461,6 +652,39 @@ npm install --save-dev taist
461
652
 
462
653
  ---
463
654
 
655
+ ## TypeScript Support
656
+
657
+ Taist includes TypeScript type definitions out of the box. No additional `@types` packages needed.
658
+
659
+ ```typescript
660
+ import { Taist, TestResults } from 'taist';
661
+ import { instrumentExpress, instrumentService } from 'taist/instrument';
662
+ import { TraceSession, TraceCollector } from 'taist/testing';
663
+
664
+ // Full type safety
665
+ const taist = new Taist({ format: 'toon', depth: 3 });
666
+ const results: TestResults = await taist.run();
667
+
668
+ // Typed instrumentation
669
+ import express from 'express';
670
+ const app = express();
671
+ instrumentExpress(app);
672
+
673
+ class MyService {
674
+ getData(): string { return 'data'; }
675
+ }
676
+ const service = instrumentService(new MyService(), 'MyService');
677
+ ```
678
+
679
+ Types are available for all exports:
680
+ - `taist` - Main API (Taist class, TestResults, etc.)
681
+ - `taist/instrument` - Instrumentation functions
682
+ - `taist/testing` - Test utilities (TraceSession, TraceCollector)
683
+ - `taist/vitest-reporter` - Vitest reporter
684
+ - `taist/types` - All types re-exported
685
+
686
+ ---
687
+
464
688
  ## License
465
689
 
466
690
  MIT License - Open source and free for commercial use
package/instrument.js CHANGED
@@ -1,11 +1,40 @@
1
1
  /**
2
2
  * Taist Auto-Instrumentation Module
3
3
  *
4
- * Add this line at the top of your service to enable tracing:
5
- * import 'taist/instrument';
4
+ * This module can be used in two ways:
6
5
  *
7
- * Or use require:
8
- * require('taist/instrument');
6
+ * 1. SIDE-EFFECT IMPORT (optional):
7
+ * Add `import 'taist/instrument';` at the top of your entry point.
8
+ * This initializes a global tracer, sets up signal handlers for graceful
9
+ * shutdown, and configures periodic trace output based on environment variables.
10
+ *
11
+ * @example
12
+ * // Entry point - loads global tracer and signal handlers
13
+ * import 'taist/instrument';
14
+ * import { instrumentExpress } from 'taist/instrument';
15
+ *
16
+ * 2. DIRECT FUNCTION IMPORTS (no side effects):
17
+ * Import only the functions you need:
18
+ * `import { instrumentExpress, instrumentService } from 'taist/instrument';`
19
+ * This is useful for post-startup instrumentation or when you want more
20
+ * control over the tracer lifecycle.
21
+ *
22
+ * @example
23
+ * // Direct imports for post-startup instrumentation
24
+ * import { instrumentService } from 'taist/instrument';
25
+ * const traced = instrumentService(myService, 'MyService');
26
+ *
27
+ * Environment Variables (used by side-effect import):
28
+ * - TAIST_ENABLED: Enable/disable tracing (default: true)
29
+ * - TAIST_DEPTH: Trace depth level (default: 3)
30
+ * - TAIST_FORMAT: Output format: toon, json, compact (default: toon)
31
+ * - TAIST_OUTPUT_FILE: Write traces to file instead of stdout
32
+ * - TAIST_OUTPUT_INTERVAL: Output interval in ms (default: 30000)
33
+ * - TAIST_INCLUDE: Only trace modules matching patterns (comma-separated)
34
+ * - TAIST_EXCLUDE: Skip modules matching patterns
35
+ * - TAIST_SLOW_THRESHOLD: Slow operation threshold in ms (default: 100)
36
+ *
37
+ * @module taist/instrument
9
38
  */
10
39
 
11
40
  import { ServiceTracer, autoInstrument } from './lib/service-tracer.js';
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Vitest TOON Reporter
3
+ *
4
+ * A native Vitest reporter that outputs test results in TOON format
5
+ * with integrated trace collection for execution visibility.
6
+ *
7
+ * The reporter automatically:
8
+ * - Starts a TraceCollector to receive traces from instrumented code
9
+ * - Sets environment variables so instrumented code can connect
10
+ * - Collects and outputs execution traces alongside test results
11
+ *
12
+ * Usage in vitest.config.js:
13
+ * reporters: ['taist/vitest-reporter']
14
+ *
15
+ * With options:
16
+ * reporters: [['taist/vitest-reporter', { format: 'toon', traceDepth: 3 }]]
17
+ *
18
+ * Your test setup should instrument code that will be tested:
19
+ * import { instrumentService } from 'taist/instrument';
20
+ * const service = instrumentService(new MyService(), 'MyService');
21
+ */
22
+
23
+ import { ToonFormatter } from './toon-formatter.js';
24
+ import { TraceCollector } from './trace-collector.js';
25
+ import fs from 'fs';
26
+
27
+ /**
28
+ * @typedef {Object} TaistReporterOptions
29
+ * @property {'toon' | 'json' | 'compact'} [format='toon'] - Output format
30
+ * @property {boolean} [traceEnabled=true] - Enable execution tracing
31
+ * @property {number} [traceDepth=3] - Trace depth level
32
+ * @property {boolean} [showTrace=true] - Include traces in output
33
+ * @property {boolean} [silent=false] - Suppress output
34
+ * @property {string | null} [outputFile=null] - Write to file instead of stdout
35
+ * @property {number} [maxTraceGroups=10] - Max request groups to show in trace output
36
+ */
37
+
38
+ export class TaistReporter {
39
+ /**
40
+ * @param {TaistReporterOptions} options
41
+ */
42
+ constructor(options = {}) {
43
+ this.options = {
44
+ format: options.format || 'toon',
45
+ traceEnabled: options.traceEnabled !== false,
46
+ traceDepth: options.traceDepth || 3,
47
+ showTrace: options.showTrace !== false,
48
+ silent: options.silent || false,
49
+ outputFile: options.outputFile || null,
50
+ maxTraceGroups: options.maxTraceGroups || 10,
51
+ ...options
52
+ };
53
+
54
+ this.formatter = new ToonFormatter(this.options);
55
+ this.vitest = null;
56
+ this.startTime = 0;
57
+ this.collector = null;
58
+ this.collectorReady = null;
59
+ this.taskResults = new Map(); // Map task id to result
60
+ this.results = {
61
+ stats: { total: 0, passed: 0, failed: 0, skipped: 0 },
62
+ failures: [],
63
+ duration: 0,
64
+ trace: []
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Called when Vitest is initialized
70
+ * @param {import('vitest/node').Vitest} vitest
71
+ */
72
+ onInit(vitest) {
73
+ this.vitest = vitest;
74
+ this.startTime = performance.now();
75
+
76
+ // Start trace collector if tracing is enabled
77
+ if (this.options.traceEnabled) {
78
+ this.collector = new TraceCollector({
79
+ maxTraces: 10000
80
+ });
81
+
82
+ // Start collector and store the promise
83
+ this.collectorReady = this.collector.start().then(() => {
84
+ // Set environment variables so instrumented code can connect
85
+ process.env.TAIST_ENABLED = 'true';
86
+ process.env.TAIST_DEPTH = String(this.options.traceDepth);
87
+ process.env.TAIST_COLLECTOR_SOCKET = this.collector.getSocketPath();
88
+ }).catch(err => {
89
+ console.error('[taist] Failed to start trace collector:', err.message);
90
+ this.collector = null;
91
+ });
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Called when task results are updated (Vitest 2.x)
97
+ * @param {Array} packs - Array of [taskId, result, meta]
98
+ */
99
+ onTaskUpdate(packs) {
100
+ if (!packs) return;
101
+
102
+ for (const pack of packs) {
103
+ const [taskId, result] = pack;
104
+ if (result) {
105
+ this.taskResults.set(taskId, result);
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Called when test run finishes (Vitest 2.x)
112
+ * @param {Array} files - Test files with results
113
+ * @param {Array} errors - Unhandled errors
114
+ */
115
+ async onFinished(files, errors) {
116
+ this.results.duration = performance.now() - this.startTime;
117
+
118
+ // Reset stats
119
+ this.results.stats = { total: 0, passed: 0, failed: 0, skipped: 0 };
120
+ this.results.failures = [];
121
+
122
+ // Process all test files
123
+ if (files) {
124
+ for (const file of files) {
125
+ this._processFile(file);
126
+ }
127
+ }
128
+
129
+ // Add unhandled errors as failures
130
+ if (errors) {
131
+ for (const error of errors) {
132
+ this.results.failures.push({
133
+ test: 'Unhandled Error',
134
+ error: error.message || String(error),
135
+ stack: error.stack
136
+ });
137
+ this.results.stats.total++;
138
+ this.results.stats.failed++;
139
+ }
140
+ }
141
+
142
+ // Collect traces if enabled
143
+ if (this.options.traceEnabled && this.collector) {
144
+ // Wait for collector to be ready
145
+ if (this.collectorReady) {
146
+ await this.collectorReady;
147
+ }
148
+
149
+ // Give a small delay for any final traces to arrive
150
+ await new Promise(resolve => setTimeout(resolve, 100));
151
+
152
+ // Get collected traces
153
+ if (this.options.showTrace) {
154
+ this.results.trace = this.collector.getTraces();
155
+ }
156
+
157
+ // Stop the collector
158
+ await this.collector.stop();
159
+ this.collector = null;
160
+ }
161
+
162
+ // Output results
163
+ this._outputResults();
164
+ }
165
+
166
+ /**
167
+ * Process a test file and its tasks recursively
168
+ * @private
169
+ */
170
+ _processFile(file) {
171
+ if (file.tasks) {
172
+ for (const task of file.tasks) {
173
+ this._processTask(task, file);
174
+ }
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Process a task (test or suite) recursively
180
+ * @private
181
+ */
182
+ _processTask(task, file) {
183
+ if (task.type === 'test') {
184
+ this.results.stats.total++;
185
+
186
+ const state = task.result?.state;
187
+ if (state === 'pass') {
188
+ this.results.stats.passed++;
189
+ } else if (state === 'fail') {
190
+ this.results.stats.failed++;
191
+ this.results.failures.push(this._formatFailure(task, file));
192
+ } else if (state === 'skip') {
193
+ this.results.stats.skipped++;
194
+ }
195
+ } else if (task.type === 'suite' && task.tasks) {
196
+ // Process nested tasks
197
+ for (const subtask of task.tasks) {
198
+ this._processTask(subtask, file);
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Format a test failure for TOON output
205
+ * @private
206
+ */
207
+ _formatFailure(task, file) {
208
+ const failure = {
209
+ test: this._getTestName(task),
210
+ location: this._getLocation(task, file)
211
+ };
212
+
213
+ const error = task.result?.errors?.[0];
214
+ if (error) {
215
+ failure.error = error.message || String(error);
216
+ failure.stack = error.stack;
217
+
218
+ // Extract diff if available
219
+ if (error.expected !== undefined || error.actual !== undefined) {
220
+ failure.diff = {
221
+ expected: error.expected,
222
+ actual: error.actual
223
+ };
224
+ }
225
+ }
226
+
227
+ return failure;
228
+ }
229
+
230
+ /**
231
+ * Get full test name including suite hierarchy
232
+ * @private
233
+ */
234
+ _getTestName(task) {
235
+ const names = [];
236
+ let current = task;
237
+
238
+ while (current) {
239
+ if (current.name && current.type !== 'file') {
240
+ names.unshift(current.name);
241
+ }
242
+ current = current.suite;
243
+ }
244
+
245
+ return names.join(' > ') || task.name;
246
+ }
247
+
248
+ /**
249
+ * Get test location
250
+ * @private
251
+ */
252
+ _getLocation(task, file) {
253
+ if (task.location) {
254
+ return {
255
+ file: file?.filepath || file?.name || '',
256
+ line: task.location.line,
257
+ column: task.location.column
258
+ };
259
+ }
260
+ return file?.filepath || file?.name || '';
261
+ }
262
+
263
+ /**
264
+ * Output formatted results
265
+ * @private
266
+ */
267
+ _outputResults() {
268
+ if (this.options.silent) {
269
+ return;
270
+ }
271
+
272
+ // Format test results
273
+ let output = this.formatter.format(this.results);
274
+
275
+ // Add trace tree if we have traces
276
+ if (this.options.showTrace && this.results.trace && this.results.trace.length > 0) {
277
+ output += '\n\n';
278
+ output += this.formatter.formatTraceTree(this.results.trace, {
279
+ maxGroups: this.options.maxTraceGroups,
280
+ showHeader: true
281
+ });
282
+ }
283
+
284
+ if (this.options.outputFile) {
285
+ fs.writeFileSync(this.options.outputFile, output);
286
+ } else {
287
+ console.log(output);
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Get the collected results (for programmatic access)
293
+ * @returns {Object} Test results
294
+ */
295
+ getResults() {
296
+ return this.results;
297
+ }
298
+
299
+ /**
300
+ * Get the trace collector socket path (for manual instrumentation setup)
301
+ * @returns {string|null} Socket path or null if collector not running
302
+ */
303
+ getSocketPath() {
304
+ return this.collector?.getSocketPath() || null;
305
+ }
306
+ }
307
+
308
+ // Default export for Vitest reporter configuration
309
+ export default TaistReporter;
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "taist",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Token-Optimized Testing Framework for AI-Assisted Development",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "taist": "./taist.js"
9
9
  },
10
+ "types": "./types/index.d.ts",
10
11
  "files": [
11
12
  "lib/",
13
+ "types/",
12
14
  "index.js",
13
15
  "taist.js",
14
16
  "instrument.js",
@@ -18,11 +20,28 @@
18
20
  ".taistrc.json"
19
21
  ],
20
22
  "exports": {
21
- ".": "./index.js",
22
- "./instrument": "./instrument.js",
23
- "./testing": "./testing.js",
23
+ ".": {
24
+ "types": "./types/index.d.ts",
25
+ "default": "./index.js"
26
+ },
27
+ "./instrument": {
28
+ "types": "./types/instrument.d.ts",
29
+ "default": "./instrument.js"
30
+ },
31
+ "./testing": {
32
+ "types": "./types/testing.d.ts",
33
+ "default": "./testing.js"
34
+ },
35
+ "./vitest-reporter": {
36
+ "types": "./types/vitest-reporter.d.ts",
37
+ "default": "./lib/vitest-reporter.js"
38
+ },
39
+ "./types": "./types/index.d.ts",
24
40
  "./module-patcher": "./lib/module-patcher.js",
25
- "./trace-collector": "./lib/trace-collector.js",
41
+ "./trace-collector": {
42
+ "types": "./types/trace-collector.d.ts",
43
+ "default": "./lib/trace-collector.js"
44
+ },
26
45
  "./trace-reporter": "./lib/trace-reporter.js",
27
46
  "./trace-context": "./lib/trace-context.js",
28
47
  "./instrument-all": "./lib/instrument-all.js",
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Taist - Token-Optimized Testing Framework
3
+ * Main type definitions
4
+ */
5
+
6
+ // Main entry point exports
7
+ export {
8
+ Taist,
9
+ TaistOptions,
10
+ RunConfig,
11
+ WatchConfig,
12
+ TestResults,
13
+ TestStats,
14
+ TestFailure,
15
+ TraceEntry,
16
+ CoverageInfo,
17
+ LocationInfo,
18
+ DiffInfo
19
+ } from './taist';
20
+
21
+ export { VitestRunner, VitestRunnerOptions } from './vitest-runner';
22
+ export { OutputFormatter, OutputFormatterOptions } from './output-formatter';
23
+ export { WatchHandler, WatchHandlerOptions } from './watch-handler';
24
+ export { ExecutionTracer, ExecutionTracerOptions } from './execution-tracer';
25
+ export {
26
+ ToonFormatter,
27
+ ToonFormatterOptions,
28
+ FormatTraceTreeOptions
29
+ } from './toon-formatter';
30
+
31
+ // Re-export instrument types
32
+ export * from './instrument';
33
+
34
+ // Re-export testing types
35
+ export * from './testing';
36
+
37
+ // Re-export trace-collector types
38
+ export * from './trace-collector';
39
+
40
+ // Re-export vitest-reporter types
41
+ export { TaistReporter, TaistReporterOptions } from './vitest-reporter';