Extract business logic from MCP tool handlers into 15 Action classes (Plan 5, Session 5, Phase 3, Task 2) following the Brain pattern. MCP tools become thin wrappers calling Action::run(). Add framework-level REST controllers and routes as sensible defaults for consumers. Co-Authored-By: Virgil <virgil@lethean.io>
69 lines
3.1 KiB
PHP
69 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use Core\Mod\Agentic\Controllers\Api\BrainController;
|
|
use Core\Mod\Agentic\Controllers\Api\PhaseController;
|
|
use Core\Mod\Agentic\Controllers\Api\PlanController;
|
|
use Core\Mod\Agentic\Controllers\Api\SessionController;
|
|
use Core\Mod\Agentic\Controllers\Api\TaskController;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Agentic API Routes
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Brain, Plans, Sessions, Phases, and Tasks endpoints.
|
|
| Auto-wrapped with 'api' middleware and /api prefix by ApiRoutesRegistering.
|
|
|
|
|
*/
|
|
|
|
// Health check (no auth required)
|
|
Route::get('health', fn () => response()->json(['status' => 'ok', 'timestamp' => now()->toIso8601String()]));
|
|
|
|
// Authenticated endpoints
|
|
Route::middleware(['api.auth', 'api.scope.enforce'])->group(function () {
|
|
|
|
// Brain (OpenBrain knowledge store)
|
|
Route::prefix('brain')->name('brain.')->group(function () {
|
|
Route::post('remember', [BrainController::class, 'remember'])->name('remember');
|
|
Route::post('recall', [BrainController::class, 'recall'])->name('recall');
|
|
Route::delete('forget/{id}', [BrainController::class, 'forget'])->name('forget')
|
|
->where('id', '[0-9a-f-]+');
|
|
Route::get('list', [BrainController::class, 'list'])->name('list');
|
|
});
|
|
|
|
// Plans
|
|
Route::prefix('plans')->name('plans.')->group(function () {
|
|
Route::get('/', [PlanController::class, 'index'])->name('index');
|
|
Route::get('{slug}', [PlanController::class, 'show'])->name('show');
|
|
Route::post('/', [PlanController::class, 'store'])->name('store');
|
|
Route::patch('{slug}', [PlanController::class, 'update'])->name('update');
|
|
Route::delete('{slug}', [PlanController::class, 'destroy'])->name('destroy');
|
|
|
|
// Phases (nested under plans)
|
|
Route::prefix('{slug}/phases')->name('phases.')->group(function () {
|
|
Route::get('{phase}', [PhaseController::class, 'show'])->name('show');
|
|
Route::patch('{phase}', [PhaseController::class, 'update'])->name('update');
|
|
Route::post('{phase}/checkpoint', [PhaseController::class, 'checkpoint'])->name('checkpoint');
|
|
|
|
// Tasks (nested under phases)
|
|
Route::prefix('{phase}/tasks')->name('tasks.')->group(function () {
|
|
Route::patch('{index}', [TaskController::class, 'update'])->name('update')
|
|
->where('index', '[0-9]+');
|
|
Route::post('{index}/toggle', [TaskController::class, 'toggle'])->name('toggle')
|
|
->where('index', '[0-9]+');
|
|
});
|
|
});
|
|
});
|
|
|
|
// Sessions
|
|
Route::prefix('sessions')->name('sessions.')->group(function () {
|
|
Route::get('/', [SessionController::class, 'index'])->name('index');
|
|
Route::get('{id}', [SessionController::class, 'show'])->name('show');
|
|
Route::post('/', [SessionController::class, 'store'])->name('store');
|
|
Route::post('{id}/end', [SessionController::class, 'end'])->name('end');
|
|
Route::post('{id}/continue', [SessionController::class, 'continue'])->name('continue');
|
|
});
|
|
});
|