| @@ -223,9 +223,17 @@ | ||
| 223 | 223 | return null; // 404 we don't recognize — stay quiet |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | 226 | /** |
| 227 | - * The chat model plus the content model when different, non-empty only. | |
| 227 | + * Every model actually in use: the chat model, the content model, plus | |
| 228 | + * whatever add-ons route chats through (plan 202df5 — mxchat-multi-bot's | |
| 229 | + * per-bot overrides were invisible here, so a dead per-bot model produced | |
| 230 | + * no signal anywhere until a customer reported the bot silent). | |
| 231 | + * | |
| 232 | + * The `mxchat_models_in_use` filter receives and must return a flat array | |
| 233 | + * of model-id strings. Contributions are sanitized here (strings only, | |
| 234 | + * trimmed, de-duplicated); a filter that returns garbage is ignored rather | |
| 235 | + * than allowed to break the check. | |
| 228 | 236 | */ |
| 229 | 237 | private static function configured_models($options) { |
| 230 | 238 | $configured = array(); |
| 231 | 239 | foreach (array('model', 'content_model') as $key) { |
| @@ -233,9 +241,21 @@ | ||
| 233 | 241 | if ($model !== '') { |
| 234 | 242 | $configured[$model] = true; |
| 235 | 243 | } |
| 236 | 244 | } |
| 237 | - return array_keys($configured); | |
| 245 | + $models = array_keys($configured); | |
| 246 | + | |
| 247 | + $filtered = apply_filters('mxchat_models_in_use', $models); | |
| 248 | + if (!is_array($filtered)) { | |
| 249 | + return $models; // fail open on a broken filter return | |
| 250 | + } | |
| 251 | + $clean = array(); | |
| 252 | + foreach ($filtered as $model) { | |
| 253 | + if (is_string($model) && trim($model) !== '') { | |
| 254 | + $clean[trim($model)] = true; | |
| 255 | + } | |
| 256 | + } | |
| 257 | + return array_keys($clean); | |
| 238 | 258 | } |
| 239 | 259 | |
| 240 | 260 | /** |
| 241 | 261 | * Which checkable provider owns this model id. Catalog first; ids the |
| @@ -318,8 +338,20 @@ | ||
| 318 | 338 | |
| 319 | 339 | /* --------------------------------------------------------------------- |
| 320 | 340 | * The notice |
| 321 | 341 | * ------------------------------------------------------------------ */ |
| 342 | + | |
| 343 | + /** | |
| 344 | + * Public accessor for add-ons that render their own warning surfaces | |
| 345 | + * (plan 202df5 — mxchat-multi-bot badges flagged models on its bot list, | |
| 346 | + * because MxChat's branded admin shell buries core admin_notices there). | |
| 347 | + * Returns the same map the core notices render from: model id => info | |
| 348 | + * (provider, first_missing_at, checked_at), restricted to models still in | |
| 349 | + * use. Empty array = nothing is flagged. | |
| 350 | + */ | |
| 351 | + public static function flagged() { | |
| 352 | + return self::flagged_models(); | |
| 353 | + } | |
| 322 | 354 | |
| 323 | 355 | /** |
| 324 | 356 | * The models currently flagged AND still configured. Empty array = nothing |
| 325 | 357 | * to say. Shared by both rendering surfaces. |