@output.ai/llm 0.3.0-dev.pr341-1d6ac82 → 0.3.0-dev.pr341-fd8527e

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@output.ai/llm",
3
- "version": "0.3.0-dev.pr341-1d6ac82",
3
+ "version": "0.3.0-dev.pr341-fd8527e",
4
4
  "description": "Framework abstraction to interact with LLM models",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/ai_model.js CHANGED
@@ -2,10 +2,16 @@ import { anthropic } from '@ai-sdk/anthropic';
2
2
  import { azure } from '@ai-sdk/azure';
3
3
  import { vertex } from '@ai-sdk/google-vertex';
4
4
  import { openai } from '@ai-sdk/openai';
5
+ import { ValidationError, z } from '@output.ai/core';
5
6
 
6
7
  const builtInProviders = { azure, anthropic, openai, vertex };
7
8
  const providers = { ...builtInProviders };
8
9
 
10
+ const registerProviderSchema = z.object( {
11
+ name: z.string().min( 1, 'Provider name must be a non-empty string' ),
12
+ providerFn: z.function()
13
+ } );
14
+
9
15
  /** @internal Resets providers to built-in state. For testing only. */
10
16
  export function _resetProviders() {
11
17
  for ( const key of Object.keys( providers ) ) {
@@ -15,11 +21,12 @@ export function _resetProviders() {
15
21
  }
16
22
 
17
23
  export function registerProvider( name, providerFn ) {
18
- if ( typeof name !== 'string' || name.length === 0 ) {
19
- throw new Error( 'Provider name must be a non-empty string' );
20
- }
21
- if ( typeof providerFn !== 'function' ) {
22
- throw new Error( `Provider "${name}" must be a function that creates a model` );
24
+ const result = registerProviderSchema.safeParse( { name, providerFn } );
25
+ if ( !result.success ) {
26
+ throw new ValidationError(
27
+ `Invalid provider registration: ${z.prettifyError( result.error )}`,
28
+ { cause: result.error }
29
+ );
23
30
  }
24
31
  providers[name] = providerFn;
25
32
  }
@@ -630,15 +630,15 @@ describe( 'registerProvider', () => {
630
630
  } );
631
631
 
632
632
  it( 'throws when name is not a string', () => {
633
- expect( () => registerProvider( 123, vi.fn() ) ).toThrow( 'non-empty string' );
633
+ expect( () => registerProvider( 123, vi.fn() ) ).toThrow( 'expected string, received number' );
634
634
  } );
635
635
 
636
636
  it( 'throws when providerFn is not a function', () => {
637
- expect( () => registerProvider( 'bad', 'not-a-function' ) ).toThrow( 'must be a function' );
637
+ expect( () => registerProvider( 'bad', 'not-a-function' ) ).toThrow( 'expected function, received string' );
638
638
  } );
639
639
 
640
640
  it( 'throws when providerFn is null', () => {
641
- expect( () => registerProvider( 'bad', null ) ).toThrow( 'must be a function' );
641
+ expect( () => registerProvider( 'bad', null ) ).toThrow( 'expected function, received null' );
642
642
  } );
643
643
  } );
644
644
 
@@ -34,12 +34,12 @@ const SNAKE_CASE_WARNINGS = {
34
34
 
35
35
  function warnSnakeCaseFields( config ) {
36
36
  for ( const [ snake, camel ] of Object.entries( SNAKE_CASE_WARNINGS ) ) {
37
- if ( snake in config ) {
37
+ if ( Object.hasOwn( config, snake ) ) {
38
38
  console.warn( `[output-llm] "${snake}" found in prompt config. Did you mean "${camel}"?` );
39
39
  }
40
40
  }
41
41
  const thinking = config.providerOptions?.thinking;
42
- if ( thinking && 'budget_tokens' in thinking ) {
42
+ if ( thinking && Object.hasOwn( thinking, 'budget_tokens' ) ) {
43
43
  console.warn( '[output-llm] "budget_tokens" found in providerOptions.thinking. Did you mean "budgetTokens"?' );
44
44
  }
45
45
  }