$modes resolved mode of every assistant: 'demo', 'explicit' or 'inherit' * @param bool $demoOn whether the simulated demo is switched on */ public static function assistants(array $modes, bool $demoOn): string { $demo = count(array_filter($modes, static fn(string $m): bool => $m === 'demo')); $external = count($modes) - $demo; if ($modes === []) { return __('No assistant is set up to answer yet.', 'aiwend'); } if ($external === 0) { return $demoOn ? __('Assistants answer with the simulated demo, a built-in stand-in. They contact no AI service and cost nothing.', 'aiwend') : __('Assistants are set to the simulated demo, but it is switched off, so they cannot answer.', 'aiwend'); } if ($demo === 0) { return __('Assistants use an AI connection: visitor messages and knowledge excerpts are sent to that provider, which may charge your account with the provider.', 'aiwend'); } $first = sprintf( /* translators: %d: number of assistants using the simulated demo */ _n('%d assistant uses the simulated demo (nothing is sent, no charge)', '%d assistants use the simulated demo (nothing is sent, no charge)', $demo, 'aiwend'), $demo ); $second = sprintf( /* translators: %d: number of assistants using an AI connection */ _n('%d uses an AI connection (its messages go to that provider, which may charge your account).', '%d use an AI connection (their messages go to that provider, which may charge your account).', $external, 'aiwend'), $external ); /* translators: 1: sentence part about assistants using the simulated demo, 2: sentence part about assistants using an AI connection */ return sprintf(__('%1$s and %2$s', 'aiwend'), $first, $second); } /** Content Studio, WooCommerce AI and AI Forms choose their connection per request, independent of any assistant. Empty when there is nothing to add. */ public static function otherFeatures(bool $realConnection): string { return $realConnection ? __('Content Studio, WooCommerce AI and AI Forms send text to the connection you choose only when you press Generate or Analyze; with a real provider that can incur cost.', 'aiwend') : ''; } /** One short sentence for the header indicator: the scope of the demo; the full explanation is on Settings and Diagnostics. */ public static function brief(): string { return __('Simulated responses apply only to assistants set to the demo. Assistants and features that use a live connection can still contact real AI services.', 'aiwend'); } /** True when an enabled connection of a real provider (not the simulated type) exists on this site. */ public static function hasRealConnection(Plugin $plugin): bool { $repo = $plugin->connections(); foreach ($repo === null ? [] : $repo->list(get_current_blog_id()) as $c) { if ((string) $c['provider'] !== 'mock' && (string) ($c['status'] ?? '') !== 'disabled') { return true; } } return false; } /** One sentence for the Settings screen: what the simulated demo covers and what it does not. */ public static function scope(bool $realConnection): string { return $realConnection ? __('The simulated demo applies only to assistants and choices set to it. Anything that uses a real AI connection still sends text to that provider.', 'aiwend') : __('The simulated demo applies only to assistants and choices set to it. No real AI connection exists on this site.', 'aiwend'); } }