# SDK Component Generator

This directory contains scripts to automatically generate SDK components based on the schema definitions in the Component classes.

## Overview

The SDK generator scans all component classes in `src/Components/` and extracts their `schema` property to generate corresponding SDK wrapper functions with **strongly typed settings and inputs**. These generated components can then be used in the SmythOS SDK for building agents programmatically.

## Usage

To generate all SDK components, run:

```bash
npm run sdk:gen
```

This will:

1. Scan all `*.class.ts` files in `src/Components/`
2. Extract the `schema` property from each component
3. Generate TypeScript interfaces for strongly typed settings
4. Generate TypeScript types for strongly typed inputs
5. Generate corresponding SDK wrapper functions in `src/sdk/components/generated/`
6. Create an index file that exports all generated components

## Strongly Typed Settings & Inputs

Each generated component now includes strongly typed interfaces for both settings and inputs based on the component's schema, **with JSDoc documentation** extracted from the schema descriptions. For example:

```typescript
// Generated interface for GenAILLM settings
export interface TGenAILLMSettings {
    name?: string;
    model: string; // required: true
    /** Prompt */
    prompt?: string; // JSDoc from schema.label
    /** Temperature */
    temperature?: number; // JSDoc from schema.label
    /** Response Format */
    responseFormat?: 'json' | 'text'; // union type from valid array
    /** Passthrough */
    passthrough?: boolean; // JSDoc from schema.label
    // ... other settings
}

// Generated type for GenAILLM inputs
export type TGenAILLMInputs = {
    /** An input that you can pass to the LLM */
    Input?: any; // JSDoc from schema.description
    /** An attachment that you can pass to the LLM */
    Attachment?: any; // JSDoc from schema.description
    [key: string]: any;
};

// Usage with full type safety and IntelliSense documentation
export function GenAILLM(settings?: TGenAILLMSettings, agentMaker?: AgentMaker) {
    // Implementation with strongly typed wrapper
    const wrapper = {
        out: _out,
        in: component.inputs.bind(component) as (inputs: TGenAILLMInputs) => void,
    };
    return wrapper;
}
```

### JSDoc Documentation

The generator automatically extracts documentation from the schema and adds it as JSDoc comments:

- **Settings**: Uses `description` or `label` field from the schema
- **Inputs**: Uses `description` field from the schema
- **IntelliSense**: Provides rich hover documentation in IDEs
- **Type Safety**: Maintains full TypeScript type checking

Example schema with documentation:

```typescript
protected schema = {
    name: 'MyComponent',
    settings: {
        requiredField: {
            type: 'string',
            required: true,
            label: 'A required string field', // Used for JSDoc
        },
        optionalField: {
            type: 'number',
            description: 'An optional number field', // Used for JSDoc
        },
    },
    inputs: {
        Input: {
            type: 'Any',
            description: 'The main input for processing', // Used for JSDoc
        },
        OptionalInput: {
            type: 'string',
            optional: true,
            description: 'An optional string input', // Used for JSDoc
        },
    },
};
```

### Type Mapping Rules

#### Settings Types

- **Required Fields**: Settings with `required: true` are non-optional in TypeScript
- **Optional Fields**: All other settings are optional (marked with `?`)
- **Type Mapping**:
    - `string` → `string`
    - `number` → `number`
    - `boolean` → `boolean`
    - `object` → `object`
    - `array` → `any[]`
- **Union Types**: Settings with `valid: [...]` arrays become union types (e.g., `'json' | 'text'`)

#### Input Types

- **All Optional**: All inputs are marked as optional (`?`) in the type interface
- **Type Mapping**: Same as settings, with all schema types mapped to corresponding TypeScript types
- **Extensibility**: All types include `[key: string]: any` for additional properties

## Generated Structure

Each generated SDK component follows this pattern:

```typescript
//!!! DO NOT EDIT THIS FILE, IT IS AUTO-GENERATED !!!//

import { AgentMaker, ComponentWrapper, createSafeAccessor } from '../../sdk.index';
import { ComponentInput } from '../../types/SDKTypes';

export interface TComponentNameSettings {
    name?: string;
    requiredSetting: string;
    optionalSetting?: number;
    unionSetting?: 'option1' | 'option2';
}

export type TComponentNameInputs = {
    InputName?: any;
    OptionalInput?: string;
    [key: string]: any;
};

export function ComponentName(settings?: TComponentNameSettings, agentMaker?: AgentMaker) {
    const { name, ...settingsWithoutName } = settings || {};
    const dataObject: any = {
        name: settings?.name || 'ComponentName',
        settings: {
            ...settingsWithoutName,
        },
    };
    const component = new ComponentWrapper(dataObject, agentMaker);

    if (agentMaker) {
        agentMaker.structure.components.push(component);
    }

    const _out: { OutputName: any; [key: string]: any } = {
        OutputName: createSafeAccessor({}, component, 'OutputName', { ...outputDef }),
    };

    const _in: { [key: string]: ComponentInput } = {
        InputName: {
            component,
            type: 'Any',
            optional: false,
            default: false,
        },
    };

    dataObject.outputs = _out;
    dataObject.inputs = _in;

    component.inputs(_in);

    const wrapper = {
        out: _out,
        in: component.inputs.bind(component) as (inputs: TComponentNameInputs) => void,
    };

    return wrapper;
}
```

## Schema Requirements

For a component to be included in the SDK generation, it must:

1. Have a `protected schema` property defined
2. The schema must include a `name` field
3. The schema should have either `inputs` or `outputs` defined (or both)
4. **Settings and inputs are optional** but when present, they will generate strongly typed interfaces

Example schema structure:

```typescript
protected schema = {
    name: 'MyComponent',
    settings: {
        requiredField: {
            type: 'string',
            required: true,
        },
        optionalField: {
            type: 'number',
            label: 'Optional Number',
        },
        unionField: {
            type: 'string',
            valid: ['option1', 'option2'],
        },
    },
    inputs: {
        Input: {
            type: 'Any',
            optional: false,
            default: false,
        },
        OptionalInput: {
            type: 'string',
            optional: true,
        },
    },
    outputs: {
        Output: {
            type: 'Any',
        },
    },
};
```

## Files

- `generate-components.js` - Main generator script
- `templates/Component.ts.tpl` - Component template with settings and inputs type placeholders
- `templates/index.ts.tpl` - Index file template
- `README.md` - This documentation

## Output

Generated files are placed in:

- `src/sdk/components/generated/[ComponentName].ts` - Individual component files with types
- `src/sdk/components/generated/index.generated.ts` - Barrel export file

## Integration

The generated components are automatically available through the SDK and can be imported like:

```typescript
import { GenAILLM, Classifier } from 'smyth-runtime/sdk/components/generated';

// Type-safe usage for settings
const llm = GenAILLM({
    model: 'gpt-4', // ✅ Required field
    temperature: 0.7, // ✅ Optional, correct type
    responseFormat: 'json', // ✅ Union type
    // invalidField: 'test'   // ❌ TypeScript error for unknown fields
});

// Type-safe usage for inputs
llm.in({
    Input: 'Hello world', // ✅ Correct input
    Attachment: binaryData, // ✅ Optional input
    // invalidInput: 'test'   // ❌ TypeScript error for unknown inputs
});
```

## Development

When adding new components or modifying existing component schemas, simply run `npm run sdk:gen` to regenerate the SDK components with updated types.

The generator will:

- ✅ Generate components with valid schemas and strongly typed settings & inputs
- ⚠️ Skip components without schemas or with empty inputs/outputs
- 📊 Provide a summary of generated and skipped components
- 🔒 Add auto-generation warnings to prevent manual editing
- 🎯 Create clean, minimal console output with progress indicators
