feat: add comprehensive framework features and deployment improvements

Major additions:
- Storage abstraction layer with filesystem and in-memory implementations
- Gitea API integration with MCP tools for repository management
- Console dialog mode with interactive command execution
- WireGuard VPN DNS fix implementation and documentation
- HTTP client streaming response support
- Router generic result type
- Parameter type validator for framework core

Framework enhancements:
- Console command registry improvements
- Console dialog components
- Method signature analyzer updates
- Route mapper refinements
- MCP server and tool mapper updates
- Queue job chain and dependency commands
- Discovery tokenizer improvements

Infrastructure:
- Deployment architecture documentation
- Ansible playbook updates for WireGuard client regeneration
- Production environment configuration updates
- Docker Compose local configuration updates
- Remove obsolete docker-compose.yml (replaced by environment-specific configs)

Documentation:
- PERMISSIONS.md for access control guidelines
- WireGuard DNS fix implementation details
- Console dialog mode usage guide
- Deployment architecture overview

Testing:
- Multi-purpose attribute tests
- Gitea Actions integration tests (typed and untyped)
This commit is contained in:
2025-11-04 20:39:48 +01:00
parent 700fe8118b
commit 3ed2685e74
80 changed files with 9891 additions and 850 deletions

View File

@@ -4,12 +4,22 @@ declare(strict_types=1);
namespace App\Framework\Console;
use App\Framework\Attributes\Route;
use App\Framework\Core\AttributeMapper;
use App\Framework\Core\ParameterTypeValidator;
use App\Framework\Mcp\McpTool;
use App\Framework\Reflection\WrappedReflectionClass;
use App\Framework\Reflection\WrappedReflectionMethod;
final readonly class ConsoleCommandMapper implements AttributeMapper
{
private ParameterTypeValidator $typeValidator;
public function __construct()
{
$this->typeValidator = new ParameterTypeValidator();
}
public function getAttributeClass(): string
{
return ConsoleCommand::class;
@@ -21,6 +31,26 @@ final readonly class ConsoleCommandMapper implements AttributeMapper
return null; // ConsoleCommand can only be applied to methods
}
// Check if method has multiple attributes (multi-purpose)
$hasMultipleAttributes = $this->hasMultiplePurposeAttributes($reflectionTarget);
// If multi-purpose, validate that all parameters are builtin types
if ($hasMultipleAttributes) {
$parameters = $reflectionTarget->getParameters()->toArray();
$reflectionParameters = [];
foreach ($parameters as $param) {
$reflectionParameters[] = $param->getType();
}
if (! $this->typeValidator->hasOnlyBuiltinParameters($reflectionParameters)) {
// Skip this attribute if parameters are not all builtin
return null;
}
}
// Get other attributes for metadata
$otherAttributes = $this->getOtherPurposeAttributes($reflectionTarget);
return [
'attribute_data' => [
'name' => $attributeInstance->name,
@@ -28,6 +58,53 @@ final readonly class ConsoleCommandMapper implements AttributeMapper
],
'class' => $reflectionTarget->getDeclaringClass(),
'method' => $reflectionTarget->getName(),
'multi_purpose' => $hasMultipleAttributes,
'other_attributes' => $otherAttributes,
];
}
/**
* Check if method has multiple purpose attributes (McpTool, ConsoleCommand, Route)
*/
private function hasMultiplePurposeAttributes(WrappedReflectionMethod $method): bool
{
$attributes = $method->getAttributes();
$purposeAttributeCount = 0;
foreach ($attributes as $attribute) {
$attributeName = $attribute->getName();
if (in_array($attributeName, [
McpTool::class,
ConsoleCommand::class,
Route::class,
], true)) {
$purposeAttributeCount++;
}
}
return $purposeAttributeCount > 1;
}
/**
* Get other purpose attributes on the same method
*
* @return array<string>
*/
private function getOtherPurposeAttributes(WrappedReflectionMethod $method): array
{
$attributes = $method->getAttributes();
$otherAttributes = [];
foreach ($attributes as $attribute) {
$attributeName = $attribute->getName();
if (in_array($attributeName, [
McpTool::class,
Route::class,
], true)) {
$otherAttributes[] = $attributeName;
}
}
return $otherAttributes;
}
}