Skip to content

Latest commit

 

History

History
257 lines (208 loc) · 7.4 KB

File metadata and controls

257 lines (208 loc) · 7.4 KB

Architecture & Code Organization

This document describes the architecture and code organization of the AgentScript Migration Tool.

Overview

The codebase is organized into logical modules following the Single Responsibility Principle. Each module has a clear, focused purpose.

Directory Structure

src/
├── index.ts                    # Main exports (public API)
├── generator.ts                # Main orchestrator class (~120 lines)
├── types.ts                    # TypeScript type definitions
├── validation.ts               # Input validation utilities
├── validation.test.ts          # Validation tests
├── generator.test.ts          # Generator tests
├── js-yaml.d.ts               # Type declarations
│
├── builders/                   # Builder modules (single responsibility)
│   ├── index.ts               # Builder exports
│   ├── configBuilder.ts       # Config block builder
│   ├── systemBuilder.ts       # System block builder
│   ├── languageBuilder.ts     # Language block builder
│   ├── variablesBuilder.ts    # Variables block builder
│   ├── topicBuilder.ts        # Topic block builder
│   ├── actionBuilder.ts       # Action block builder
│   └── startAgentBuilder.ts   # Start agent builder
│
├── formatters/                 # YAML formatting modules
│   ├── index.ts               # Formatter exports
│   └── yamlFormatter.ts      # YAML conversion and formatting
│
└── utils/                      # Utility functions
    ├── index.ts               # Utility exports
    └── nameSanitizer.ts       # Name sanitization utilities

Module Responsibilities

Core Modules

generator.ts (~120 lines)

  • Purpose: Main orchestrator class
  • Responsibilities:
    • Validates input
    • Coordinates builders
    • Calls formatter
    • Error handling
  • Dependencies: builders, formatters, validation, utils

types.ts

  • Purpose: TypeScript type definitions
  • Responsibilities:
    • Define all interfaces
    • Export types for consumers
  • Dependencies: None

validation.ts

  • Purpose: Input validation
  • Responsibilities:
    • Validate planner structure
    • Validate topics and actions
    • Sanitize strings
    • Validate options
  • Dependencies: types

Builder Modules (builders/)

Each builder module is responsible for constructing a specific part of the Agent Script structure.

configBuilder.ts (~25 lines)

  • Builds the config block
  • Handles agent metadata

systemBuilder.ts (~20 lines)

  • Builds the system block
  • Handles global instructions and messages

languageBuilder.ts (~15 lines)

  • Builds the language block
  • Handles locale configuration

variablesBuilder.ts (~50 lines)

  • Builds the variables block
  • Converts planner variables to Agent Script variables
  • Handles type inference

topicBuilder.ts (~80 lines)

  • Builds individual topic blocks
  • Generates topic instructions
  • Handles topic actions

actionBuilder.ts (~120 lines)

  • Builds action definitions
  • Formats action targets
  • Handles inputs/outputs
  • Supports all action types (Flow, Apex, etc.)

startAgentBuilder.ts (~50 lines)

  • Builds the start_agent topic_selector block
  • Creates transition actions

Formatter Modules (formatters/)

yamlFormatter.ts (~350 lines)

  • Purpose: Convert Agent Script structure to YAML
  • Responsibilities:
    • YAML serialization
    • Format transformations (compact format, Python booleans, etc.)
    • Instruction formatting (-> syntax)
    • Variable formatting
    • Action formatting
  • Dependencies: types, js-yaml

Utility Modules (utils/)

nameSanitizer.ts (~100 lines)

  • Purpose: Sanitize names for Agent Script compatibility
  • Responsibilities:
    • Clean developer names (remove IDs)
    • Sanitize topic names
    • Sanitize action names
  • Dependencies: None

Design Principles

1. Single Responsibility Principle

Each module has one clear responsibility:

  • Builders build specific blocks
  • Formatters format YAML
  • Utils provide reusable functions
  • Validators validate input

2. Separation of Concerns

  • Building (builders/) - Construct data structures
  • Formatting (formatters/) - Convert to YAML
  • Validation (validation.ts) - Validate input
  • Utilities (utils/) - Reusable functions

3. Dependency Direction

generator.ts
  ├── builders/ (depends on types, utils)
  ├── formatters/ (depends on types)
  ├── validation.ts (depends on types)
  └── utils/ (no dependencies)

4. Testability

Each module can be tested independently:

  • Builders can be tested with mock data
  • Formatters can be tested with known structures
  • Validators can be tested with various inputs
  • Utils can be tested with unit tests

Code Size Comparison

Before Refactoring

  • generator.ts: ~888 lines (monolithic)

After Refactoring

  • generator.ts: ~120 lines (orchestrator)
  • builders/: ~360 lines (8 modules, ~45 lines each)
  • formatters/: ~350 lines (1 module)
  • utils/: ~100 lines (1 module)
  • validation.ts: ~150 lines

Total: ~1080 lines (slightly more due to module overhead, but much more maintainable)

Benefits of This Architecture

1. Maintainability

  • Easy to find code (clear module names)
  • Changes are isolated to specific modules
  • Reduced cognitive load

2. Testability

  • Each module can be tested independently
  • Mock dependencies easily
  • Clear test boundaries

3. Reusability

  • Builders can be reused in other contexts
  • Utils are framework-agnostic
  • Formatters can be extended

4. Scalability

  • Easy to add new builders
  • Easy to add new formatters
  • Easy to extend functionality

5. Readability

  • Small, focused files
  • Clear naming conventions
  • Self-documenting structure

Adding New Features

Adding a New Builder

  1. Create builders/newBuilder.ts
  2. Export from builders/index.ts
  3. Use in generator.ts
  4. Add tests

Adding a New Formatter

  1. Create formatters/newFormatter.ts
  2. Export from formatters/index.ts
  3. Use in yamlFormatter.ts
  4. Add tests

Adding a New Utility

  1. Create utils/newUtility.ts
  2. Export from utils/index.ts
  3. Use where needed
  4. Add tests

Module Dependencies Graph

generator.ts
  │
  ├─── validation.ts ──┐
  │                    │
  ├─── builders/ ──────┼─── types.ts
  │    ├── configBuilder.ts
  │    ├── systemBuilder.ts
  │    ├── languageBuilder.ts
  │    ├── variablesBuilder.ts
  │    ├── topicBuilder.ts
  │    ├── actionBuilder.ts
  │    └── startAgentBuilder.ts
  │
  ├─── formatters/ ────┘
  │    └── yamlFormatter.ts
  │
  └─── utils/
       └── nameSanitizer.ts

Best Practices

  1. Keep modules focused: Each module should do one thing well
  2. Minimize dependencies: Prefer composition over deep nesting
  3. Export explicitly: Use named exports for clarity
  4. Document interfaces: JSDoc comments for public APIs
  5. Test independently: Each module should have its own tests

Future Enhancements

Potential areas for further modularization:

  1. Parser Module: If we add YAML parsing
  2. Validator Module: More complex validation rules
  3. Transformer Module: Data transformations
  4. Plugin System: Extensible builders/formatters