VOOZH about

URL: https://deepwiki.com/guanguans/ai-commit/9.2-generator-interface-api

⇱ Generator Interface API | guanguans/ai-commit | DeepWiki


Loading...
Menu

Generator Interface API

This document provides technical API reference for the generator interface system in ai-commit. It covers the GeneratorContract interface, the AbstractGenerator base class, required and helper methods, implementation patterns, and contract expectations for developers creating custom generators.

For architectural overview of the generator system, see Generator System Architecture. For implementation details of existing generators, see API-Based Generators and CLI-Based Generators. For a step-by-step guide to creating new generators, see Adding New Generators.


Core Generator Contract

The generator interface defines a single required method that all AI commit message generators must implement.

Interface Definition

App\Contracts\GeneratorContract
└── generate(string $prompt): string

The GeneratorContract interface specifies the fundamental contract that all generators must fulfill:

MethodParametersReturn TypePurpose
generate()string $promptstringTransform a prompt containing git diff and instructions into a commit message

Contract Expectations:

  • Input: A fully-formed prompt string containing git diff data, commit type information, and formatting instructions
  • Output: A sanitized, user-ready commit message string (subject line with optional body)
  • Exceptions: May throw framework-specific exceptions (RequestException, ProcessFailedException, etc.)
  • Side Effects: May write streaming output to console during generation

Sources: app/Contracts/GeneratorContract.php1-19


AbstractGenerator Base Class

All concrete generator implementations extend AbstractGenerator, which provides shared infrastructure for configuration management, process execution, output streaming, and common utilities.

Class Hierarchy

Full generator class tree


Sources: app/Contracts/GeneratorContract.php1-19 app/Generators/AbstractGenerator.php28-106 app/Generators/OpenAIGenerator.php22-88 app/Generators/OpenAIChatGenerator.php19-52 app/Generators/MoonshotGenerator.php23-71 app/Generators/ErnieBotGenerator.php23-78 app/Generators/ErnieBotTurboGenerator.php19-31 app/Generators/BitoCliGenerator.php18-33 app/Generators/GithubCopilotCliGenerator.php18-29 app/Generators/GithubModelsCliGenerator.php18-33

Constructor Pattern

All generators follow a standardized constructor pattern:

  • Accepts Repository $config and stores it as $this->config
  • AbstractGenerator.__construct resolves and clones the app-bound OutputStyle instance, sets verbosity to VERBOSITY_DEBUG, and retrieves the HelperSet from the Artisan kernel app/Generators/AbstractGenerator.php36-40
  • Subclasses that need an HTTP client initialize it here (e.g., OpenAIGenerator creates new OpenAI($config->all()) app/Generators/OpenAIGenerator.php26-30)

Base constructor side effects:

Property setValue
$this->configInjected Repository instance
$this->outputCloned OutputStyle at VERBOSITY_DEBUG
$this->helperSetHelperSet from Artisan kernel

Sources: app/Generators/AbstractGenerator.php36-40 app/Generators/OpenAIGenerator.php26-30


GeneratorManager

GeneratorManager app/GeneratorManager.php32-78 is the entry point used by CommitCommand to dispatch generation. It extends Illuminate\Support\Manager and implements GeneratorContract, so it can itself be used wherever a GeneratorContract is expected.

Traits mixed in: Conditionable, Dumpable, ForwardsCalls, Localizable, Macroable, Tappable

Method Reference

MethodSignatureDescription
getDefaultDriver(): stringReturns config('ai-commit.generator') — the active driver key
generator(?string $generator): GeneratorContractThin alias over driver($generator)
generate(string $prompt): stringDelegates to $this->generator()->generate($prompt)
createDriver(mixed $driver): GeneratorContractResolves and instantiates a concrete generator class
extend(string $driver, Closure $callback): staticInherited from Manager; registers a custom creator
driver(?string $driver): GeneratorContractInherited from Manager; returns cached or newly created driver

Driver Resolution in createDriver()

How createDriver maps a driver key to a class


The class name derivation at app/GeneratorManager.php70-72 works as follows:

  1. Read config.get("ai-commit.generators.$driver") to get the driver's config block
  2. Use the driver key inside that block (falling back to the driver key itself)
  3. Replace the literal string openai with OpenAI, then studly()-case the result
  4. Append Generator and check for class existence under App\Generators\
Input driver keyResolved class
openaiApp\Generators\OpenAIGenerator
openai_chatApp\Generators\OpenAIChatGenerator
moonshotApp\Generators\MoonshotGenerator
ernie_botApp\Generators\ErnieBotGenerator
ernie_bot_turboApp\Generators\ErnieBotTurboGenerator
bito_cliApp\Generators\BitoCliGenerator
github_copilot_cliApp\Generators\GithubCopilotCliGenerator
github_models_cliApp\Generators\GithubModelsCliGenerator

Sources: app/GeneratorManager.php41-78


Required Method: generate()

Method Signature


Method Contract

AspectSpecification
Visibilitypublic
Parameter Typestring $prompt - Complete prompt with diff, type, and instructions
Return Typestring - Generated commit message
ThrowsImplementation-specific exceptions (HTTP errors, process failures)
Side EffectsConsole output during streaming (optional)

Implementation Patterns

The generate() method follows different implementation strategies based on generator type:


Sources: app/Generators/OpenAIGenerator.php56-67 app/Generators/BitoCliGenerator.php20-32

API-Based Implementation Example

OpenAIGenerator Pattern:

  1. Parameter Construction app/Generators/OpenAIGenerator.php58-61

    • Merge prompt with UUID user identifier
    • Add configuration parameters from $this->config->get('parameters', [])
  2. API Request with Streaming app/Generators/OpenAIGenerator.php63

    • Call client method ($this->openAI->completions())
    • Pass writer closure for real-time output streaming
    • Handle both fake responses (for testing) and real responses
  3. Message Extraction app/Generators/OpenAIGenerator.php66-72

    • Return accumulated messages from writer OR
    • Extract from response using Arr::get($response, 'choices.0.text', '')

Sources: app/Generators/OpenAIGenerator.php56-72

CLI-Based Implementation Example

BitoCliGenerator Pattern:

  1. Command Construction app/Generators/BitoCliGenerator.php27

    • Retrieve binary path from configuration: $this->config->get('binary')
    • Wrap with options using $this->ensureWithOptions()
  2. Process Resolution app/Generators/BitoCliGenerator.php24-29

    • Use Laravel's resolve() to create Process instance
    • Pass command and parameters from configuration
    • Set process input to prompt string
  3. Execution app/Generators/BitoCliGenerator.php23

    • Execute via $this->mustRunProcess() helper
    • Extract output with ->getOutput()

GithubCopilotCliGenerator Pattern Differences:

Sources: app/Generators/BitoCliGenerator.php20-32 app/Generators/GithubCopilotCliGenerator.php20-28


Helper Methods and Properties

Protected Properties

PropertyTypePurpose
$configIlluminate\Config\RepositoryConfiguration repository for the driver's config block
$outputIlluminate\Console\OutputStyleConsole output interface, cloned and set to VERBOSITY_DEBUG
$helperSetSymfony\Component\Console\Helper\HelperSetArtisan's helper set, used to access ProcessHelper

Configuration Access Example:


Sources: app/Generators/OpenAIGenerator.php61 app/Generators/BitoCliGenerator.php27 app/Generators/GithubModelsCliGenerator.php27

Process Execution Helpers

ensureWithOptions()

protected function ensureWithOptions(array $command): array

Purpose: Append the result of hydratedOptions() to a CLI command array before passing it to Process.

Implementation Sites:

hydratedOptions()

protected function hydratedOptions(): array<string>

Purpose: Convert the options config key into a flat list of CLI flag strings. Each key-value pair is URL-encoded and then decoded to produce a string representation, filtered for non-empty values, and returned as a flat array alternating [$flag, $value, ...] app/Generators/AbstractGenerator.php97-105

Sources: app/Generators/AbstractGenerator.php89-105 app/Generators/GithubCopilotCliGenerator.php25 app/Generators/BitoCliGenerator.php27 app/Generators/GithubModelsCliGenerator.php27

mustRunProcess()

protected function mustRunProcess(
 array|Process|string $cmd,
 ?string $error = null,
 ?callable $callback = null,
 int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE,
 ?OutputInterface $output = null
): Process

Purpose: Run a process via ProcessHelper and throw ProcessFailedException if the exit code is non-zero. Accepts a Process object, a command array, or a shell command string (converted via Process::fromShellCommandline()).

Parameters:

ParameterTypeDefaultDescription
$cmdarray|Process|stringCommand to run
$error?stringnullError message if process fails
$callback?callablenullPer-line output callback
$verbosityintVERBOSITY_VERY_VERBOSEConsole verbosity threshold
$output?OutputInterfacenullOverride output, defaults to $this->output

Delegates internally to runProcess(), then checks isSuccessful() app/Generators/AbstractGenerator.php42-56

runProcess()

protected function runProcess(
 array|Process|string $cmd,
 ?string $error = null,
 ?callable $callback = null,
 int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE,
 ?OutputInterface $output = null
): Process

Purpose: Lower-level variant that runs the process via $this->getHelper('process')->run() without enforcing success. String commands are converted via Process::fromShellCommandline() app/Generators/AbstractGenerator.php58-70

Error Handling for CLI generators: Throws ProcessFailedException (from mustRunProcess) if process exits with non-zero status. See tests/Unit/Generators/GithubCopilotCliGeneratorTest.php28-31

Sources: app/Generators/AbstractGenerator.php42-70 app/Generators/BitoCliGenerator.php23-31 app/Generators/GithubModelsCliGenerator.php23-31

getHelper()

protected function getHelper(string $name): HelperInterface

Purpose: Retrieve a Symfony HelperInterface instance from $this->helperSet. Used internally by runProcess to obtain ProcessHelper via $this->getHelper('process') app/Generators/AbstractGenerator.php77-80

runningCallback()


Purpose: Return a callback function for real-time process output streaming to console.

Usage Pattern:


Behavior: Streams process output to $this->output as it is generated, providing user feedback during long-running AI operations.

Sources: app/Generators/GithubCopilotCliGenerator.php27

Response Processing Helpers

buildWriter() Pattern (API Generators)


Purpose: Create a closure for streaming API response processing, accumulating messages while displaying real-time output.

Implementation Details app/Generators/OpenAIGenerator.php77-87:

  • Accepts reference parameter &$messages to accumulate text
  • Returns closure that processes streaming data line-by-line
  • Splits data on PHP_EOL, sanitizes, and JSON decodes each chunk
  • Extracts text from response and appends to $messages
  • Writes text to $this->output for user feedback

Data Flow:


Sources: app/Generators/OpenAIGenerator.php77-87

Message Extraction Methods

Generator-specific methods for extracting commit messages from API responses:


Purpose: Navigate response structure and extract the generated text.

Response paths vary by generator:

GeneratorStreamingResponse path
OpenAIGeneratorstream chunkchoices.0.text
OpenAIChatGeneratorstream deltachoices.0.delta.content
MoonshotGeneratorstream deltachoices.0.delta.content
MoonshotGeneratornon-streamchoices.0.message.content
ErnieBotGenerator / ErnieBotTurboGeneratorall modesresult

Sources: app/Generators/OpenAIGenerator.php69-72 app/Generators/OpenAIChatGenerator.php47-51 app/Generators/MoonshotGenerator.php50-55 app/Generators/ErnieBotGenerator.php74-77


Implementation Checklist

When implementing a new generator, ensure compliance with these requirements:

Required Implementation

  • Extend AbstractGenerator base class
  • Implement generate(string $prompt): string method
  • Call parent::__construct($config) in constructor
  • Access configuration via $this->config->get()
  • Return sanitized string (no JSON formatting)

HTTP-Based Generator Checklist

  • Initialize HTTP client in constructor
  • Build request parameters from config and prompt
  • Handle streaming responses if supported
  • Implement response message extraction method
  • Use $this->output->write() for streaming feedback
  • Handle connection and request exceptions

CLI-Based Generator Checklist

  • Retrieve binary path from $this->config->get('binary')
  • Build command array with sub-commands and arguments
  • Use ensureWithOptions() to augment command
  • Use resolve(Process::class, ...) for process creation
  • Set process input or arguments based on CLI tool requirements
  • Use mustRunProcess() or mustRun($this->runningCallback())
  • Extract output with ->getOutput()
  • Handle ProcessFailedException

Configuration Keys

KeyTypeRequiredPurpose
binarystringYes (CLI)Path to CLI executable
modelstringVariesAI model identifier
parametersarrayNoAdditional parameters/options
api_keystringYes (API)Authentication credential
base_urlstringVariesAPI endpoint override
http_optionsarrayNoGuzzle HTTP options

Sources: app/Generators/GithubCopilotCliGenerator.php25-27 app/Generators/BitoCliGenerator.php27-29 app/Generators/GithubModelsCliGenerator.php27-29 app/Generators/OpenAIGenerator.php58-61


Error Handling Contract

Exception Types

ExceptionSourceTrigger ConditionRecovery Strategy
ConnectionExceptionHTTP GeneratorsNetwork failure, timeoutRetry or fallback generator
RequestExceptionHTTP GeneratorsAPI error (4xx, 5xx)Check credentials, retry
ProcessFailedExceptionCLI GeneratorsNon-zero exit codeCheck binary path, permissions
Generic exceptionsAllConfiguration errorsValidate configuration

Exception Annotations

Generator implementations document potential exceptions in PHPDoc blocks:


Source: app/Generators/OpenAIGenerator.php53-56

Testing Error Conditions

The test suite verifies exception handling:


Expected to throw ProcessFailedException tests/Unit/Generators/GithubCopilotCliGeneratorTest.php28-31

Sources: app/Generators/OpenAIGenerator.php53-56 tests/Unit/Generators/GithubCopilotCliGeneratorTest.php28-31


Output Streaming Pattern

Streaming Architecture


Implementation Techniques

API Generators:

CLI Generators:

Benefits of Streaming

  1. User Feedback: Real-time display during slow AI operations (5-30 seconds)
  2. Debugging: Observe partial responses to diagnose prompt issues
  3. Transparency: Show AI thinking process rather than blocking silently

Sources: app/Generators/OpenAIGenerator.php63-87 app/Generators/GithubCopilotCliGenerator.php27


Type System and Configuration Injection

Dependency Injection Pattern

All generators receive a scoped Repository through constructor injection. The Repository is built by GeneratorManager.createDriver() from the driver's config block only (config("ai-commit.generators.$driver")), so generators do not have access to the full app config — only their own slice.

Configuration flow from app config to generator instance


Configuration Repository Access

$this->config is scoped to the driver's block, so keys are relative:

Access callRetrieves
$this->config->get('binary')CLI executable path
$this->config->get('parameters', [])Model/request parameters
$this->config->get('model')Model identifier
$this->config->get('options', [])Extra CLI flags
$this->config->all()Full driver config block (passed to HTTP clients)

Sources: app/GeneratorManager.php63-77 app/Generators/AbstractGenerator.php36-40 app/Generators/OpenAIGenerator.php29 app/Generators/BitoCliGenerator.php27 app/Generators/GithubModelsCliGenerator.php27


Testing Interface Implementations

Test Structure

Generator tests verify both successful execution and error handling:


Test Coverage Requirements

  • Success Path: Verify correct message generation
  • Error Handling: Confirm appropriate exceptions thrown
  • Configuration: Test various configuration scenarios
  • Streaming: Verify output appears during generation (where applicable)
  • Response Parsing: Test message extraction from various response formats

Sources: tests/Unit/Generators/GithubCopilotCliGeneratorTest.php28-31

Refresh this wiki

On this page