Welcome to the Symfony Console Agent, your new bestie for turning natural language into command-line magic. This nifty agent understands your human babble and translates it into console commands. It's like having a super-smart CLI assistant right at your fingertips!
Ever wished you could just tell your console what to do in plain English? Well, now you can! This agent takes your casual requests and figures out which Symfony command to run. It's perfect for devs who are new to a project, can't remember exact command syntax, or just feeling a bit lazy (we've all been there).
Here's a short video to show you how it works:
- PHP 8.3 or higher (we're living in the future, baby!)
- Symfony Console component
- A sense of humor (optional, but highly recommended)
First, make sure you've got Composer installed. Then, run this command to add the Symfony Console Agent to your project:
composer require llm-agents/agent-symfony-console
- Open up your
app/src/Application/Kernel.php
file. - Add the bootloader like this:
public function defineBootloaders(): array { return [ // ... other bootloaders ... \LLM\Agents\Agent\SymfonyConsole\Integrations\Spiral\SymfonyConsoleBootloader::class, ]; }
And that's it! Your Spiral app is now ready to use the agent.
For Laravel, there's a service provider you can use:
// bootstrap/providers.php
return [
// ... other providers ...
LLM\Agents\Agent\SymfonyConsole\Integrations\Laravel\SymfonyConsoleServiceProvider::class,
];
To start using the Symfony Console Agent, you'll need to implement the
LLM\Agents\Agent\SymfonyConsole\CommandManagerInterface
. interface. This interface is responsible for fetching command
help, listing available commands, and executing commands.
Here's an example of how you might use it in a Laravel application:
<?php
declare(strict_types=1);
namespace LLM\Agents\Agent\SymfonyConsole\Integrations\Laravel;
use Illuminate\Contracts\Console\Kernel;
use LLM\Agents\Agent\SymfonyConsole\CommandManagerInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
final readonly class ArtisanCommandManager implements CommandManagerInterface
{
public function __construct(
private Kernel $application,
private array $enabledNamespaces = [
'make:',
'db:',
'migrate',
'route:list',
],
) {}
public function getCommandHelp(string $command): string
{
$output = new BufferedOutput();
$this->application->call($command, ['--help' => true], $output);
return $output->fetch();
}
public function getCommands(): array
{
$commands = $this->application->all();
$availableCommands = [];
foreach ($this->enabledNamespaces as $namespace) {
foreach ($commands as $name => $command) {
if (\str_starts_with($name, $namespace)) {
$availableCommands[$name] = $command;
}
}
}
return $availableCommands;
}
public function call(\Stringable|string $command, array $parameters = [], ?OutputInterface $output = null): int
{
return $this->application->call($command, $parameters, $output);
}
}
classDiagram
class SymfonyConsoleAgent {
+NAME: string
+create(frameworkName: string): self
-addMetadata(SolutionMetadata): void
-addAssociation(Solution): void
}
class AgentAggregate {
<<interface>>
+getKey(): string
+getName(): string
+getDescription(): string
+getInstruction(): string
+getTools(): array
+getAgents(): array
+getModel(): Model
+getMemory(): array
+getPrompts(): array
+getConfiguration(): array
}
class GetCommandsListTool {
+NAME: string
-application: CommandManagerInterface
+__construct(CommandManagerInterface)
+execute(input: object): string
}
class GetCommandDetailsTool {
+NAME: string
-application: CommandManagerInterface
+__construct(CommandManagerInterface)
+execute(input: object): string
}
class ExecuteCommandTool {
+NAME: string
-application: CommandManagerInterface
+__construct(CommandManagerInterface)
+execute(input: object): string
}
class ReadFileTool {
+NAME: string
-basePath: string
+__construct(string)
+execute(input: object): string
}
class WriteFileTool {
+NAME: string
-basePath: string
+__construct(string)
+execute(input: object): string
}
class CommandManagerInterface {
<<interface>>
+getCommandHelp(command: string): string
+getCommands(): array
+call(command: string, parameters: array, output: OutputInterface): int
}
class Tool {
<<abstract>>
+getName(): string
+getDescription(): string
+getInputSchema(): string
+getLanguage(): ToolLanguage
+execute(input: object): string|Stringable
}
class ToolInterface {
<<interface>>
+getName(): string
+getDescription(): string
+getInputSchema(): string
+getLanguage(): ToolLanguage
+execute(input: object): string|Stringable
}
class SymfonyConsoleAgentFactory {
-frameworkName: string
+__construct(frameworkName: string)
+create(): AgentInterface
}
class AgentFactoryInterface {
<<interface>>
+create(): AgentInterface
}
class GetCommandsListInput {
+namespace: string
}
class GetCommandDetailsInput {
+command: string
}
class ExecuteCommandInput {
+command: string
+arguments: array
+options: array
}
class ReadFileInput {
+path: string
}
class WriteFileInput {
+path: string
+content: string
}
SymfonyConsoleAgent --|> AgentAggregate
SymfonyConsoleAgent ..> GetCommandsListTool
SymfonyConsoleAgent ..> GetCommandDetailsTool
SymfonyConsoleAgent ..> ExecuteCommandTool
SymfonyConsoleAgent ..> ReadFileTool
SymfonyConsoleAgent ..> WriteFileTool
GetCommandsListTool --|> Tool
GetCommandDetailsTool --|> Tool
ExecuteCommandTool --|> Tool
ReadFileTool --|> Tool
WriteFileTool --|> Tool
Tool ..|> ToolInterface
GetCommandsListTool ..> CommandManagerInterface
GetCommandDetailsTool ..> CommandManagerInterface
ExecuteCommandTool ..> CommandManagerInterface
SymfonyConsoleAgentFactory ..|> AgentFactoryInterface
SymfonyConsoleAgentFactory ..> SymfonyConsoleAgent
GetCommandsListTool ..> GetCommandsListInput
GetCommandDetailsTool ..> GetCommandDetailsInput
ExecuteCommandTool ..> ExecuteCommandInput
ReadFileTool ..> ReadFileInput
WriteFileTool ..> WriteFileInput
We love contributions! If you've got ideas to make this agent even cooler, here's how you can chip in:
- Fork the repo
- Make your changes
- Create a new Pull Request
Just make sure your code is clean, well-commented, and follows PSR-12 coding standards.
This project is licensed under the MIT License - see the LICENSE file for details.
That's all, folks! If you've got any questions or run into any trouble, don't hesitate to open an issue.