option('request-days') ?: config('ai-editing.retention.request_days', 90))); $ledgerRetentionDays = max(1, (int) ($this->option('ledger-days') ?: config('ai-editing.retention.usage_ledger_days', 365))); $pretend = (bool) $this->option('pretend'); $requestCutoff = now()->subDays($requestRetentionDays); $ledgerCutoff = now()->subDays($ledgerRetentionDays); $requestQuery = AiEditRequest::query() ->where(function (Builder $query) use ($requestCutoff): void { $query->where(function (Builder $completedQuery) use ($requestCutoff): void { $completedQuery->whereNotNull('completed_at') ->where('completed_at', '<=', $requestCutoff); })->orWhere(function (Builder $expiredQuery): void { $expiredQuery->whereNotNull('expires_at') ->where('expires_at', '<=', now()); }); }); $ledgerQuery = AiUsageLedger::query() ->where('recorded_at', '<=', $ledgerCutoff); $requestCount = (clone $requestQuery)->count(); $ledgerCount = (clone $ledgerQuery)->count(); $this->line(sprintf( 'AI prune candidates -> requests: %d (<= %s), ledgers: %d (<= %s)', $requestCount, $requestCutoff->toDateString(), $ledgerCount, $ledgerCutoff->toDateString() )); if ($pretend) { $this->info('Pretend mode enabled. No records were deleted.'); return self::SUCCESS; } $deletedRequests = $requestQuery->delete(); $deletedLedgers = $ledgerQuery->delete(); $this->info(sprintf( 'Pruned AI data -> requests: %d, ledgers: %d.', $deletedRequests, $deletedLedgers )); return self::SUCCESS; } }