2026-09-20 03:45:04 +00:00
< ? php
use App\Models\ServerConfig ;
use Flux\Flux ;
use Illuminate\Validation\Rule ;
use Livewire\Attributes\Layout ;
use Livewire\Component ;
new #[Layout('components.layouts.app')] class extends Component {
public ? int $editingId = null ;
public string $name = '' ;
public string $engine = 'llama.cpp' ;
public string $config_yaml = '' ;
public function create () : void
{
$this -> reset ([ 'editingId' , 'name' , 'config_yaml' ]);
$this -> engine = 'llama.cpp' ;
$this -> modal ( 'config-form' ) -> show ();
}
public function edit ( int $id ) : void
{
$config = ServerConfig :: where ( 'user_id' , auth () -> id ()) -> findOrFail ( $id );
$this -> editingId = $config -> id ;
$this -> name = $config -> name ;
$this -> engine = $config -> engine ;
$this -> config_yaml = $config -> config_yaml ;
$this -> modal ( 'config-form' ) -> show ();
}
public function save () : void
{
$validated = $this -> validate ([
'name' => [ 'required' , 'string' , 'max:128' ,
Rule :: unique ( 'server_configs' , 'name' ) -> where ( 'user_id' , auth () -> id ()) -> ignore ( $this -> editingId )],
'engine' => [ 'required' , 'string' , 'max:64' ],
'config_yaml' => [ 'nullable' , 'string' , 'max:65535' ],
]);
ServerConfig :: updateOrCreate (
[ 'id' => $this -> editingId , 'user_id' => auth () -> id ()],
$validated
);
$this -> modal ( 'config-form' ) -> close ();
2026-09-21 12:02:34 +00:00
Flux :: toast ( variant : 'success' , text : __ ( 'Inference args saved.' ));
2026-09-20 03:45:04 +00:00
// Config identity is part of the session grouping key — re-summarize
// so linked runs regroup immediately.
Illuminate\Support\Facades\Artisan :: call ( 'festbench:summary' );
}
public function delete ( int $id ) : void
{
ServerConfig :: where ( 'user_id' , auth () -> id ()) -> whereKey ( $id ) -> firstOrFail () -> delete ();
2026-09-21 12:02:34 +00:00
Flux :: toast ( variant : 'success' , text : __ ( 'Inference args deleted.' ));
2026-09-20 03:45:04 +00:00
Illuminate\Support\Facades\Artisan :: call ( 'festbench:summary' );
}
public function with () : array
{
return [
'configs' => ServerConfig :: where ( 'user_id' , auth () -> id ()) -> orderBy ( 'name' ) -> get (),
];
}
};
?>
< div class = " flex flex-col gap-6 " >
< div class = " flex items-center justify-between " >
< div >
2026-09-21 12:02:34 +00:00
< flux : heading size = " xl " > {{ __ ( 'Inference Args' ) }} </ flux : heading >
< flux : subheading > {{ __ ( 'Named inference server invocations. Runs link to them; the identity keeps differently-tuned sessions in their own groups.' ) }} </ flux : subheading >
2026-09-20 03:45:04 +00:00
</ div >
2026-09-21 12:02:34 +00:00
< flux : button variant = " primary " icon = " plus " wire : click = " create " > {{ __ ( 'New inference args' ) }} </ flux : button >
2026-09-20 03:45:04 +00:00
</ div >
@ if ( $configs -> isNotEmpty ())
< flux : table >
< flux : table . columns >
< flux : table . column > {{ __ ( 'Name' ) }} </ flux : table . column >
< flux : table . column > {{ __ ( 'Engine' ) }} </ flux : table . column >
< flux : table . column class = " text-right " > {{ __ ( 'Linked runs' ) }} </ flux : table . column >
< flux : table . column ></ flux : table . column >
</ flux : table . columns >
< flux : table . rows >
@ foreach ( $configs as $config )
< flux : table . row : key = " $config->id " >
< flux : table . cell > {{ $config -> name }} </ flux : table . cell >
< flux : table . cell >< flux : badge size = " xs " color = " sky " > {{ $config -> engine }} </ flux : badge ></ flux : table . cell >
< flux : table . cell class = " text-right font-mono text-sm " > {{ $config -> runs () -> count () }} </ flux : table . cell >
< flux : table . cell >
< div class = " flex justify-end gap-1 " >
< flux : button size = " xs " variant = " ghost " icon = " pencil-square " wire : click = " edit( { { $config->id }}) " > {{ __ ( 'Edit' ) }} </ flux : button >
< flux : button size = " xs " variant = " ghost " color = " danger " icon = " trash-2 " wire : click = " delete( { { $config->id }}) " > {{ __ ( 'Delete' ) }} </ flux : button >
</ div >
</ flux : table . cell >
</ flux : table . row >
@ endforeach
</ flux : table . rows >
</ flux : table >
@ else
< flux : callout variant = " brand " >
2026-09-21 12:02:34 +00:00
< flux : callout . heading > {{ __ ( 'No inference args yet' ) }} </ flux : callout . heading >
< flux : callout . text > {{ __ ( 'Save your llama.cpp / vllm / hosted-provider invocation as a named entry so runs group by their tuning.' ) }} </ flux : callout . text >
2026-09-20 03:45:04 +00:00
</ flux : callout >
@ endif
< flux : modal name = " config-form " class = " w-2xl " >
< div class = " flex flex-col gap-4 " >
< div >
2026-09-21 12:02:34 +00:00
< flux : heading size = " lg " > {{ $editingId ? __ ( 'Edit config' ) : __ ( 'New inference args' ) }} </ flux : heading >
< flux : subheading > {{ __ ( 'Paste the full inference server invocation (YAML or argv list), or how a hosted model was addressed.' ) }} </ flux : subheading >
2026-09-20 03:45:04 +00:00
</ div >
< flux : input wire : model = " name " : label = " __('Name') " placeholder = " { { __('llama.cpp DFlash spec-decode, 131k ctx') }} " />
< flux : select wire : model = " engine " : label = " __('Engine') " >
@ foreach ([ 'llama.cpp' , 'vllm' , 'unknown' , 'other' ] as $engine )
< flux : select . option value = " { { $engine }} " > {{ $engine }} </ flux : select . option >
@ endforeach
</ flux : select >
2026-09-21 12:02:34 +00:00
< flux : textarea wire : model = " config_yaml " : label = " __('Inference args') " rows = " 12 " class = " font-mono text-xs " placeholder = " --host 0.0.0.0 --port 8000 -hf model:Q5_K_M -ngl 99 ... " />
2026-09-20 03:45:04 +00:00
< div class = " flex justify-end gap-2 " >
< flux : button variant = " ghost " wire : click = " $toggle ('config-form') " > {{ __ ( 'Cancel' ) }} </ flux : button >
< flux : button variant = " primary " wire : click = " save " > {{ __ ( 'Save config' ) }} </ flux : button >
</ div >
</ div >
</ flux : modal >
</ div >