@llmist/testing 16.0.4 → 16.2.0

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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Readable, PassThrough, Writable } from 'node:stream';
2
- import { LLMMessage, AbstractGadget, AudioMimeType, LLMGenerationOptions, ImageMimeType, ProviderAdapter, ModelDescriptor, LLMStream, ImageGenerationOptions, ImageGenerationResult, SpeechGenerationOptions, SpeechGenerationResult, LLMist, IConversationManager, LLMStreamChunk } from 'llmist';
2
+ import { LLMMessage, AbstractGadget, AudioMimeType, LLMGenerationOptions, ImageMimeType, ProviderAdapter, ModelDescriptor, LLMStream, ImageGenerationOptions, ImageGenerationResult, SpeechGenerationOptions, SpeechGenerationResult, LLMist, IConversationManager, Skill, SkillActivation, SkillMetadata, SkillActivationOptions, ParsedSkill, LLMStreamChunk } from 'llmist';
3
3
  import { ZodType } from 'zod';
4
4
 
5
5
  /**
@@ -648,25 +648,18 @@ declare class MockBuilder {
648
648
  /**
649
649
  * Match calls to a specific model (by name, supports partial matching).
650
650
  *
651
- * @example
652
- * mockLLM().forModel('gpt-5')
653
- * mockLLM().forModel('claude') // matches any Claude model
651
+ * @alias forModel
654
652
  */
655
653
  forModel(modelName: string): this;
656
654
  /**
657
655
  * Match calls to any model.
658
656
  * Useful when you want to mock responses regardless of the model used.
659
- *
660
- * @example
661
- * mockLLM().forAnyModel()
662
657
  */
663
658
  forAnyModel(): this;
664
659
  /**
665
660
  * Match calls to a specific provider.
666
661
  *
667
- * @example
668
- * mockLLM().forProvider('openai')
669
- * mockLLM().forProvider('anthropic')
662
+ * @alias forProvider
670
663
  */
671
664
  forProvider(provider: string): this;
672
665
  /**
@@ -722,6 +715,12 @@ declare class MockBuilder {
722
715
  * })
723
716
  */
724
717
  when(matcher: MockMatcher): this;
718
+ /**
719
+ * Match when any message contains an image.
720
+ *
721
+ * @alias whenMessageHasImage
722
+ */
723
+ forImage(): this;
725
724
  /**
726
725
  * Match when any message contains an image.
727
726
  *
@@ -729,6 +728,12 @@ declare class MockBuilder {
729
728
  * mockLLM().whenMessageHasImage().returns("I see an image of a sunset.")
730
729
  */
731
730
  whenMessageHasImage(): this;
731
+ /**
732
+ * Match when any message contains audio.
733
+ *
734
+ * @alias whenMessageHasAudio
735
+ */
736
+ forAudio(): this;
732
737
  /**
733
738
  * Match when any message contains audio.
734
739
  *
@@ -739,10 +744,34 @@ declare class MockBuilder {
739
744
  /**
740
745
  * Match based on the number of images in the last message.
741
746
  *
747
+ * @alias whenImageCount
748
+ */
749
+ withImageCount(predicate: (count: number) => boolean | number): this;
750
+ /**
751
+ * Match based on the number of images in the conversation.
752
+ *
742
753
  * @example
743
754
  * mockLLM().whenImageCount((n) => n >= 2).returns("Comparing multiple images...")
744
755
  */
745
756
  whenImageCount(predicate: (count: number) => boolean): this;
757
+ /**
758
+ * Return a sequence of responses. Each time the mock matches, it will return the next response in the sequence.
759
+ * If the sequence reaches the end, it will cycle back to the beginning.
760
+ *
761
+ * @example
762
+ * mockLLM().returnsSequence([
763
+ * { text: 'First response' },
764
+ * { text: 'Second response' }
765
+ * ])
766
+ */
767
+ returnsSequence(responses: MockResponse[]): this;
768
+ /**
769
+ * Set a dynamic response generator function.
770
+ * Equivalent to withResponse(fn).
771
+ *
772
+ * @alias withResponse
773
+ */
774
+ returnsDynamic(generator: (context: MockMatcherContext) => MockResponse | Promise<MockResponse>): this;
746
775
  /**
747
776
  * Set the text response to return.
748
777
  * Can be a static string or a function that returns a string dynamically.
@@ -1291,6 +1320,11 @@ declare class MockManager {
1291
1320
  * Helper function to get the global mock manager instance.
1292
1321
  */
1293
1322
  declare function getMockManager(options?: MockOptions): MockManager;
1323
+ /**
1324
+ * Reset the global MockManager instance.
1325
+ * Useful for clearing all mocks and state between tests.
1326
+ */
1327
+ declare function resetMocks(): void;
1294
1328
 
1295
1329
  /**
1296
1330
  * Create a mock LLM stream from a mock response.
@@ -1319,6 +1353,105 @@ declare function createTextMockStream(text: string, options?: {
1319
1353
  usage?: MockResponse["usage"];
1320
1354
  }): LLMStream;
1321
1355
 
1356
+ /**
1357
+ * Testing utilities for skills.
1358
+ *
1359
+ * Provides helpers for parsing, activating, and asserting on skills
1360
+ * without requiring filesystem setup.
1361
+ *
1362
+ * @module testing/skill-testing
1363
+ */
1364
+
1365
+ /**
1366
+ * Parse and validate a SKILL.md content string.
1367
+ *
1368
+ * @param content - Full SKILL.md content (frontmatter + body)
1369
+ * @param sourcePath - Optional source path (defaults to /test/SKILL.md)
1370
+ * @returns Parsed skill with instructions loaded
1371
+ *
1372
+ * @example
1373
+ * ```typescript
1374
+ * import { testSkillParse } from '@llmist/testing';
1375
+ *
1376
+ * const parsed = testSkillParse(`---
1377
+ * name: my-skill
1378
+ * description: A test skill
1379
+ * ---
1380
+ * Do the thing.`);
1381
+ *
1382
+ * expect(parsed.metadata.name).toBe('my-skill');
1383
+ * ```
1384
+ */
1385
+ declare function testSkillParse(content: string, sourcePath?: string): ParsedSkill;
1386
+ /**
1387
+ * Test a skill's activation with given arguments.
1388
+ *
1389
+ * @param skill - Skill instance to activate
1390
+ * @param options - Activation options (arguments, cwd, etc.)
1391
+ * @returns Activation result with resolved instructions
1392
+ *
1393
+ * @example
1394
+ * ```typescript
1395
+ * import { testSkillActivation, mockSkill } from '@llmist/testing';
1396
+ *
1397
+ * const skill = mockSkill({ name: 'search' });
1398
+ * const activation = await testSkillActivation(skill, { arguments: '*.ts' });
1399
+ * expect(activation.resolvedInstructions).toContain('*.ts');
1400
+ * ```
1401
+ */
1402
+ declare function testSkillActivation(skill: Skill, options?: SkillActivationOptions): Promise<SkillActivation>;
1403
+ /**
1404
+ * Assert that a skill's resolved instructions contain expected content.
1405
+ *
1406
+ * @param activation - The activation result to check
1407
+ * @param expected - Array of strings that must be present in the instructions
1408
+ * @throws AssertionError if any expected string is missing
1409
+ */
1410
+ declare function assertSkillContains(activation: SkillActivation, expected: string[]): void;
1411
+ /**
1412
+ * Validate a SKILL.md content string and return any issues.
1413
+ *
1414
+ * @param content - Full SKILL.md content
1415
+ * @returns Array of validation issues (empty if valid)
1416
+ */
1417
+ declare function validateSkill(content: string): string[];
1418
+ /**
1419
+ * Create a mock Skill instance for testing.
1420
+ *
1421
+ * @param overrides - Override any metadata fields
1422
+ * @param instructions - Custom instructions body
1423
+ */
1424
+ declare function mockSkill(overrides?: Partial<SkillMetadata>, instructions?: string): Skill;
1425
+ /**
1426
+ * Fluent builder for creating test skills.
1427
+ *
1428
+ * @example
1429
+ * ```typescript
1430
+ * import { MockSkillBuilder } from '@llmist/testing';
1431
+ *
1432
+ * const skill = new MockSkillBuilder()
1433
+ * .withName('gmail-read')
1434
+ * .withDescription('Read Gmail messages')
1435
+ * .withInstructions('Use gws to read emails.')
1436
+ * .build();
1437
+ * ```
1438
+ */
1439
+ declare class MockSkillBuilder {
1440
+ private _name;
1441
+ private _description;
1442
+ private _instructions;
1443
+ private _overrides;
1444
+ withName(name: string): this;
1445
+ withDescription(description: string): this;
1446
+ withInstructions(instructions: string): this;
1447
+ withModel(model: string): this;
1448
+ withContext(context: "fork" | "inline"): this;
1449
+ withPaths(paths: string[]): this;
1450
+ withAllowedTools(tools: string[]): this;
1451
+ withGadgets(gadgets: string[]): this;
1452
+ build(): Skill;
1453
+ }
1454
+
1322
1455
  /**
1323
1456
  * Stream testing utilities for llmist.
1324
1457
  * Provides helpers for creating and consuming test streams.
@@ -1419,4 +1552,43 @@ declare function createEmptyStream(): LLMStream;
1419
1552
  */
1420
1553
  declare function createErrorStream(chunksBeforeError: LLMStreamChunk[], error: Error): LLMStream;
1421
1554
 
1422
- export { type MockAudioData, MockBuilder, MockConversationManager, type MockGadget, MockGadgetBuilder, type MockGadgetConfig, type MockImageData, MockManager, type MockMatcher, type MockMatcherContext, type MockOptions, MockPromptRecorder, MockProviderAdapter, type MockRegistration, type MockResponse, type MockStats, type RecordedCall, type TestEnvironment, type TestEnvironmentOptions, type TestGadgetOptions, type TestGadgetResult, collectOutput, collectStream, collectStreamText, createAssistantMessage, createConversation, createConversationWithGadgets, createEmptyStream, createErrorStream, createLargeConversation, createMinimalConversation, createMockAdapter, createMockClient, createMockConversationManager, createMockGadget, createMockPrompt, createMockReadable, createMockStream, createMockWritable, createSystemMessage, createTestEnvironment, createTestStream, createTextMockStream, createTextStream, createUserMessage, estimateTokens, getBufferedOutput, getMockManager, getStreamFinalChunk, mockGadget, mockLLM, testGadget, testGadgetBatch, waitFor };
1555
+ /**
1556
+ * Mock TUI App interface.
1557
+ */
1558
+ interface MockTUIApp {
1559
+ setProfiles: any;
1560
+ setFocusMode: any;
1561
+ startWaitingForPrompt: any;
1562
+ destroy: any;
1563
+ onQuit: any;
1564
+ onCancel: any;
1565
+ showLLMCallStart: any;
1566
+ updateStreamingTokens: any;
1567
+ clearRetry: any;
1568
+ showThrottling: any;
1569
+ addSystemMessage: any;
1570
+ clearThrottling: any;
1571
+ showRetry: any;
1572
+ showApproval: any;
1573
+ waitForInput: any;
1574
+ subscribeToTree: any;
1575
+ handleEvent: any;
1576
+ addGadgetCost: any;
1577
+ flushText: any;
1578
+ resetAbort: any;
1579
+ startNewSession: any;
1580
+ showUserMessage: any;
1581
+ clearPreviousSession: any;
1582
+ clearStatusBar: any;
1583
+ onMidSessionInput: any;
1584
+ waitForPrompt: any;
1585
+ getAbortSignal: any;
1586
+ }
1587
+ /**
1588
+ * Creates a mock TUI app for testing.
1589
+ *
1590
+ * NOTE: This currently uses Vitest's `vi` for mocks.
1591
+ */
1592
+ declare const createMockTUIApp: () => MockTUIApp;
1593
+
1594
+ export { type MockAudioData, MockBuilder, MockConversationManager, type MockGadget, MockGadgetBuilder, type MockGadgetConfig, type MockImageData, MockManager, type MockMatcher, type MockMatcherContext, type MockOptions, MockPromptRecorder, MockProviderAdapter, type MockRegistration, type MockResponse, MockSkillBuilder, type MockStats, type MockTUIApp, type RecordedCall, type TestEnvironment, type TestEnvironmentOptions, type TestGadgetOptions, type TestGadgetResult, assertSkillContains, collectOutput, collectStream, collectStreamText, createAssistantMessage, createConversation, createConversationWithGadgets, createEmptyStream, createErrorStream, createLargeConversation, createMinimalConversation, createMockAdapter, createMockClient, createMockConversationManager, createMockGadget, createMockPrompt, createMockReadable, createMockStream, createMockTUIApp, createMockWritable, createSystemMessage, createTestEnvironment, createTestStream, createTextMockStream, createTextStream, createUserMessage, estimateTokens, getBufferedOutput, getMockManager, getStreamFinalChunk, mockGadget, mockLLM, mockSkill, resetMocks, testGadget, testGadgetBatch, testSkillActivation, testSkillParse, validateSkill, waitFor };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Readable, PassThrough, Writable } from 'node:stream';
2
- import { LLMMessage, AbstractGadget, AudioMimeType, LLMGenerationOptions, ImageMimeType, ProviderAdapter, ModelDescriptor, LLMStream, ImageGenerationOptions, ImageGenerationResult, SpeechGenerationOptions, SpeechGenerationResult, LLMist, IConversationManager, LLMStreamChunk } from 'llmist';
2
+ import { LLMMessage, AbstractGadget, AudioMimeType, LLMGenerationOptions, ImageMimeType, ProviderAdapter, ModelDescriptor, LLMStream, ImageGenerationOptions, ImageGenerationResult, SpeechGenerationOptions, SpeechGenerationResult, LLMist, IConversationManager, Skill, SkillActivation, SkillMetadata, SkillActivationOptions, ParsedSkill, LLMStreamChunk } from 'llmist';
3
3
  import { ZodType } from 'zod';
4
4
 
5
5
  /**
@@ -648,25 +648,18 @@ declare class MockBuilder {
648
648
  /**
649
649
  * Match calls to a specific model (by name, supports partial matching).
650
650
  *
651
- * @example
652
- * mockLLM().forModel('gpt-5')
653
- * mockLLM().forModel('claude') // matches any Claude model
651
+ * @alias forModel
654
652
  */
655
653
  forModel(modelName: string): this;
656
654
  /**
657
655
  * Match calls to any model.
658
656
  * Useful when you want to mock responses regardless of the model used.
659
- *
660
- * @example
661
- * mockLLM().forAnyModel()
662
657
  */
663
658
  forAnyModel(): this;
664
659
  /**
665
660
  * Match calls to a specific provider.
666
661
  *
667
- * @example
668
- * mockLLM().forProvider('openai')
669
- * mockLLM().forProvider('anthropic')
662
+ * @alias forProvider
670
663
  */
671
664
  forProvider(provider: string): this;
672
665
  /**
@@ -722,6 +715,12 @@ declare class MockBuilder {
722
715
  * })
723
716
  */
724
717
  when(matcher: MockMatcher): this;
718
+ /**
719
+ * Match when any message contains an image.
720
+ *
721
+ * @alias whenMessageHasImage
722
+ */
723
+ forImage(): this;
725
724
  /**
726
725
  * Match when any message contains an image.
727
726
  *
@@ -729,6 +728,12 @@ declare class MockBuilder {
729
728
  * mockLLM().whenMessageHasImage().returns("I see an image of a sunset.")
730
729
  */
731
730
  whenMessageHasImage(): this;
731
+ /**
732
+ * Match when any message contains audio.
733
+ *
734
+ * @alias whenMessageHasAudio
735
+ */
736
+ forAudio(): this;
732
737
  /**
733
738
  * Match when any message contains audio.
734
739
  *
@@ -739,10 +744,34 @@ declare class MockBuilder {
739
744
  /**
740
745
  * Match based on the number of images in the last message.
741
746
  *
747
+ * @alias whenImageCount
748
+ */
749
+ withImageCount(predicate: (count: number) => boolean | number): this;
750
+ /**
751
+ * Match based on the number of images in the conversation.
752
+ *
742
753
  * @example
743
754
  * mockLLM().whenImageCount((n) => n >= 2).returns("Comparing multiple images...")
744
755
  */
745
756
  whenImageCount(predicate: (count: number) => boolean): this;
757
+ /**
758
+ * Return a sequence of responses. Each time the mock matches, it will return the next response in the sequence.
759
+ * If the sequence reaches the end, it will cycle back to the beginning.
760
+ *
761
+ * @example
762
+ * mockLLM().returnsSequence([
763
+ * { text: 'First response' },
764
+ * { text: 'Second response' }
765
+ * ])
766
+ */
767
+ returnsSequence(responses: MockResponse[]): this;
768
+ /**
769
+ * Set a dynamic response generator function.
770
+ * Equivalent to withResponse(fn).
771
+ *
772
+ * @alias withResponse
773
+ */
774
+ returnsDynamic(generator: (context: MockMatcherContext) => MockResponse | Promise<MockResponse>): this;
746
775
  /**
747
776
  * Set the text response to return.
748
777
  * Can be a static string or a function that returns a string dynamically.
@@ -1291,6 +1320,11 @@ declare class MockManager {
1291
1320
  * Helper function to get the global mock manager instance.
1292
1321
  */
1293
1322
  declare function getMockManager(options?: MockOptions): MockManager;
1323
+ /**
1324
+ * Reset the global MockManager instance.
1325
+ * Useful for clearing all mocks and state between tests.
1326
+ */
1327
+ declare function resetMocks(): void;
1294
1328
 
1295
1329
  /**
1296
1330
  * Create a mock LLM stream from a mock response.
@@ -1319,6 +1353,105 @@ declare function createTextMockStream(text: string, options?: {
1319
1353
  usage?: MockResponse["usage"];
1320
1354
  }): LLMStream;
1321
1355
 
1356
+ /**
1357
+ * Testing utilities for skills.
1358
+ *
1359
+ * Provides helpers for parsing, activating, and asserting on skills
1360
+ * without requiring filesystem setup.
1361
+ *
1362
+ * @module testing/skill-testing
1363
+ */
1364
+
1365
+ /**
1366
+ * Parse and validate a SKILL.md content string.
1367
+ *
1368
+ * @param content - Full SKILL.md content (frontmatter + body)
1369
+ * @param sourcePath - Optional source path (defaults to /test/SKILL.md)
1370
+ * @returns Parsed skill with instructions loaded
1371
+ *
1372
+ * @example
1373
+ * ```typescript
1374
+ * import { testSkillParse } from '@llmist/testing';
1375
+ *
1376
+ * const parsed = testSkillParse(`---
1377
+ * name: my-skill
1378
+ * description: A test skill
1379
+ * ---
1380
+ * Do the thing.`);
1381
+ *
1382
+ * expect(parsed.metadata.name).toBe('my-skill');
1383
+ * ```
1384
+ */
1385
+ declare function testSkillParse(content: string, sourcePath?: string): ParsedSkill;
1386
+ /**
1387
+ * Test a skill's activation with given arguments.
1388
+ *
1389
+ * @param skill - Skill instance to activate
1390
+ * @param options - Activation options (arguments, cwd, etc.)
1391
+ * @returns Activation result with resolved instructions
1392
+ *
1393
+ * @example
1394
+ * ```typescript
1395
+ * import { testSkillActivation, mockSkill } from '@llmist/testing';
1396
+ *
1397
+ * const skill = mockSkill({ name: 'search' });
1398
+ * const activation = await testSkillActivation(skill, { arguments: '*.ts' });
1399
+ * expect(activation.resolvedInstructions).toContain('*.ts');
1400
+ * ```
1401
+ */
1402
+ declare function testSkillActivation(skill: Skill, options?: SkillActivationOptions): Promise<SkillActivation>;
1403
+ /**
1404
+ * Assert that a skill's resolved instructions contain expected content.
1405
+ *
1406
+ * @param activation - The activation result to check
1407
+ * @param expected - Array of strings that must be present in the instructions
1408
+ * @throws AssertionError if any expected string is missing
1409
+ */
1410
+ declare function assertSkillContains(activation: SkillActivation, expected: string[]): void;
1411
+ /**
1412
+ * Validate a SKILL.md content string and return any issues.
1413
+ *
1414
+ * @param content - Full SKILL.md content
1415
+ * @returns Array of validation issues (empty if valid)
1416
+ */
1417
+ declare function validateSkill(content: string): string[];
1418
+ /**
1419
+ * Create a mock Skill instance for testing.
1420
+ *
1421
+ * @param overrides - Override any metadata fields
1422
+ * @param instructions - Custom instructions body
1423
+ */
1424
+ declare function mockSkill(overrides?: Partial<SkillMetadata>, instructions?: string): Skill;
1425
+ /**
1426
+ * Fluent builder for creating test skills.
1427
+ *
1428
+ * @example
1429
+ * ```typescript
1430
+ * import { MockSkillBuilder } from '@llmist/testing';
1431
+ *
1432
+ * const skill = new MockSkillBuilder()
1433
+ * .withName('gmail-read')
1434
+ * .withDescription('Read Gmail messages')
1435
+ * .withInstructions('Use gws to read emails.')
1436
+ * .build();
1437
+ * ```
1438
+ */
1439
+ declare class MockSkillBuilder {
1440
+ private _name;
1441
+ private _description;
1442
+ private _instructions;
1443
+ private _overrides;
1444
+ withName(name: string): this;
1445
+ withDescription(description: string): this;
1446
+ withInstructions(instructions: string): this;
1447
+ withModel(model: string): this;
1448
+ withContext(context: "fork" | "inline"): this;
1449
+ withPaths(paths: string[]): this;
1450
+ withAllowedTools(tools: string[]): this;
1451
+ withGadgets(gadgets: string[]): this;
1452
+ build(): Skill;
1453
+ }
1454
+
1322
1455
  /**
1323
1456
  * Stream testing utilities for llmist.
1324
1457
  * Provides helpers for creating and consuming test streams.
@@ -1419,4 +1552,43 @@ declare function createEmptyStream(): LLMStream;
1419
1552
  */
1420
1553
  declare function createErrorStream(chunksBeforeError: LLMStreamChunk[], error: Error): LLMStream;
1421
1554
 
1422
- export { type MockAudioData, MockBuilder, MockConversationManager, type MockGadget, MockGadgetBuilder, type MockGadgetConfig, type MockImageData, MockManager, type MockMatcher, type MockMatcherContext, type MockOptions, MockPromptRecorder, MockProviderAdapter, type MockRegistration, type MockResponse, type MockStats, type RecordedCall, type TestEnvironment, type TestEnvironmentOptions, type TestGadgetOptions, type TestGadgetResult, collectOutput, collectStream, collectStreamText, createAssistantMessage, createConversation, createConversationWithGadgets, createEmptyStream, createErrorStream, createLargeConversation, createMinimalConversation, createMockAdapter, createMockClient, createMockConversationManager, createMockGadget, createMockPrompt, createMockReadable, createMockStream, createMockWritable, createSystemMessage, createTestEnvironment, createTestStream, createTextMockStream, createTextStream, createUserMessage, estimateTokens, getBufferedOutput, getMockManager, getStreamFinalChunk, mockGadget, mockLLM, testGadget, testGadgetBatch, waitFor };
1555
+ /**
1556
+ * Mock TUI App interface.
1557
+ */
1558
+ interface MockTUIApp {
1559
+ setProfiles: any;
1560
+ setFocusMode: any;
1561
+ startWaitingForPrompt: any;
1562
+ destroy: any;
1563
+ onQuit: any;
1564
+ onCancel: any;
1565
+ showLLMCallStart: any;
1566
+ updateStreamingTokens: any;
1567
+ clearRetry: any;
1568
+ showThrottling: any;
1569
+ addSystemMessage: any;
1570
+ clearThrottling: any;
1571
+ showRetry: any;
1572
+ showApproval: any;
1573
+ waitForInput: any;
1574
+ subscribeToTree: any;
1575
+ handleEvent: any;
1576
+ addGadgetCost: any;
1577
+ flushText: any;
1578
+ resetAbort: any;
1579
+ startNewSession: any;
1580
+ showUserMessage: any;
1581
+ clearPreviousSession: any;
1582
+ clearStatusBar: any;
1583
+ onMidSessionInput: any;
1584
+ waitForPrompt: any;
1585
+ getAbortSignal: any;
1586
+ }
1587
+ /**
1588
+ * Creates a mock TUI app for testing.
1589
+ *
1590
+ * NOTE: This currently uses Vitest's `vi` for mocks.
1591
+ */
1592
+ declare const createMockTUIApp: () => MockTUIApp;
1593
+
1594
+ export { type MockAudioData, MockBuilder, MockConversationManager, type MockGadget, MockGadgetBuilder, type MockGadgetConfig, type MockImageData, MockManager, type MockMatcher, type MockMatcherContext, type MockOptions, MockPromptRecorder, MockProviderAdapter, type MockRegistration, type MockResponse, MockSkillBuilder, type MockStats, type MockTUIApp, type RecordedCall, type TestEnvironment, type TestEnvironmentOptions, type TestGadgetOptions, type TestGadgetResult, assertSkillContains, collectOutput, collectStream, collectStreamText, createAssistantMessage, createConversation, createConversationWithGadgets, createEmptyStream, createErrorStream, createLargeConversation, createMinimalConversation, createMockAdapter, createMockClient, createMockConversationManager, createMockGadget, createMockPrompt, createMockReadable, createMockStream, createMockTUIApp, createMockWritable, createSystemMessage, createTestEnvironment, createTestStream, createTextMockStream, createTextStream, createUserMessage, estimateTokens, getBufferedOutput, getMockManager, getStreamFinalChunk, mockGadget, mockLLM, mockSkill, resetMocks, testGadget, testGadgetBatch, testSkillActivation, testSkillParse, validateSkill, waitFor };