*/ public array $blocked_terms = []; public ?string $status_message = null; public function mount(): void { $settings = AiEditingSetting::current(); $this->is_enabled = (bool) $settings->is_enabled; $this->default_provider = (string) ($settings->default_provider ?: 'runware'); $this->fallback_provider = $settings->fallback_provider ? (string) $settings->fallback_provider : null; $this->runware_mode = (string) ($settings->runware_mode ?: 'live'); $this->queue_auto_dispatch = (bool) $settings->queue_auto_dispatch; $this->queue_name = (string) ($settings->queue_name ?: 'default'); $this->queue_max_polls = max(1, (int) ($settings->queue_max_polls ?: 6)); $this->blocked_terms = array_values(array_filter(array_map( static fn (mixed $term): string => trim((string) $term), (array) $settings->blocked_terms ))); $this->status_message = $settings->status_message ? (string) $settings->status_message : null; } public function form(Schema $schema): Schema { return $schema->schema([ Section::make('Global Availability') ->schema([ Forms\Components\Toggle::make('is_enabled') ->label('Enable AI editing globally'), Forms\Components\Textarea::make('status_message') ->label('Disabled message') ->maxLength(255) ->rows(2) ->helperText('Shown to guest and tenant clients when the feature is disabled.') ->nullable(), ]), Section::make('Provider') ->schema([ Forms\Components\Select::make('default_provider') ->label('Default provider') ->options([ 'runware' => 'runware.ai', ]) ->required(), Forms\Components\TextInput::make('fallback_provider') ->label('Fallback provider') ->maxLength(40) ->helperText('Reserved for provider failover.'), Forms\Components\Select::make('runware_mode') ->label('Runware mode') ->options([ 'live' => 'Live API', 'fake' => 'Fake mode (internal testing)', ]) ->required(), ]) ->columns(2), Section::make('Queue Orchestration') ->schema([ Forms\Components\Toggle::make('queue_auto_dispatch') ->label('Auto-dispatch jobs after request creation'), Forms\Components\TextInput::make('queue_name') ->label('Queue name') ->required() ->maxLength(60), Forms\Components\TextInput::make('queue_max_polls') ->label('Max provider polls') ->numeric() ->minValue(1) ->maxValue(50) ->required(), ]) ->columns(2), Section::make('Prompt Safety') ->schema([ Forms\Components\TagsInput::make('blocked_terms') ->label('Blocked prompt terms') ->helperText('Case-insensitive term match before queue dispatch.') ->placeholder('Add blocked term'), ]), ]); } public function save(): void { $this->validate(); $settings = AiEditingSetting::query()->firstOrNew(['id' => 1]); $settings->is_enabled = $this->is_enabled; $settings->default_provider = $this->default_provider; $settings->fallback_provider = $this->nullableString($this->fallback_provider); $settings->runware_mode = $this->runware_mode; $settings->queue_auto_dispatch = $this->queue_auto_dispatch; $settings->queue_name = $this->queue_name; $settings->queue_max_polls = max(1, $this->queue_max_polls); $settings->blocked_terms = array_values(array_filter(array_map( static fn (mixed $term): string => trim((string) $term), $this->blocked_terms ))); $settings->status_message = $this->nullableString($this->status_message); $settings->save(); $changed = $settings->getChanges(); if ($changed !== []) { app(SuperAdminAuditLogger::class)->record( 'ai_editing.settings_updated', $settings, SuperAdminAuditLogger::fieldsMetadata(array_keys($changed)), source: static::class ); } Notification::make() ->title('AI editing settings saved.') ->success() ->send(); } private function nullableString(?string $value): ?string { $trimmed = trim((string) $value); return $trimmed !== '' ? $trimmed : null; } }