Skip to content

Commit f2aec01

Browse files
committed
Last Update on Apr 27, 2026: Welcome to the Agentic Era with MagicAI: Introducing GPT 5.5, GPT Image 2.0, Opus 4.7, Gemini 3.1 Flash Live, Lyria 3 Pro, Skills (Paid), Deep Research (Paid), AI Council Mode (Paid), GPT 5.4-Mini, GPT 5.4-Nano, Redesigned AI Chat Pro Experience, Smart Highlight, Chat Navigator, Redesigned Sidebar, Smart Image Display, All-new External Chatbot v3 and Inbox, Sales Agent for External Chatbot (Paid), Booking Agent for External Chatbot (Paid), Voice Chat for External Chatbot (Paid), Feedback for External Chatbot, Customer Segmentation for External Chatbot, Instagram for External Chatbot (Paid), GPT-5.3 Instant, GPT-5.4, Social Media Agent (Paid), AI Blogger Agent (Paid), Follow up Question for AI Chat Pro, Ability to Publish Stories with Social Media Suite & Agent, AI Integration for Creative Suite, Carousel Posts & Smart Prompts for Social Media, Youtube & Youtube Shorts Integration for Social Media, Nano Banana 2, Opus 4.6, Sonnet 4.6, Gemini 3.1 Pro, Kling 3, Kling 2.6, Kling Motion Control, Grok Imagine, ElevenLabs v3, AI Image Pro (Paid), Folders for AI Chat Pro, Memory for AI Chat Pro, AI Fashion Studio (Paid), Performance Boost, GPT 5.2, GPT 5.2 Pro, Gemini 3 Flash, GPT-Image 1.5, Gemini 3 Flash, Gemini 3 Pro, GPT 5.1, NanoBanana Pro, Grok 4.1 and more, AI Presentation Maker (Paid), Veo 3.1, Claude Sonnet 4.5, Claude Opus 4.1, Kling AI 2.5 Turbo, AI Music Pro (Paid), Cover and Emoji Support for AI Editor, Chat with Documents for AI Chat Pro, GPT-5 Pro, Sora 2, Sora 2 Pro, Seedream v4, Brand-New External Chatbot and Inbox, Facebook Messenger for External Chatbot (Paid), Multi-Model AI (Paid) and more..
Last Update on Apr 27, 2026: Welcome to the Agentic Era with MagicAI: Introducing GPT 5.5, GPT Image 2.0, Opus 4.7, Gemini 3.1 Flash Live, Lyria 3 Pro, Skills (Paid), Deep Research (Paid), AI Council Mode (Paid), GPT 5.4-Mini, GPT 5.4-Nano, Redesigned AI Chat Pro Experience, Smart Highlight, Chat Navigator, Redesigned Sidebar, Smart Image Display, All-new External Chatbot v3 and Inbox, Sales Agent for External Chatbot (Paid), Booking Agent for External Chatbot (Paid), Voice Chat for External Chatbot (Paid), Feedback for External Chatbot, Customer Segmentation for External Chatbot, Instagram for External Chatbot (Paid), GPT-5.3 Instant, GPT-5.4, Social Media Agent (Paid), AI Blogger Agent (Paid), Follow up Question for AI Chat Pro, Ability to Publish Stories with Social Media Suite & Agent, AI Integration for Creative Suite, Carousel Posts & Smart Prompts for Social Media, Youtube & Youtube Shorts Integration for Social Media, Nano Banana 2, Opus 4.6, Sonnet 4.6, Gemini 3.1 Pro, Kling 3, Kling 2.6, Kling Motion Control, Grok Imagine, ElevenLabs v3, AI Image Pro (Paid), Folders for AI Chat Pro, Memory for AI Chat Pro, AI Fashion Studio (Paid), Performance Boost, GPT 5.2, GPT 5.2 Pro, Gemini 3 Flash, GPT-Image 1.5, Gemini 3 Flash, Gemini 3 Pro, GPT 5.1, NanoBanana Pro, Grok 4.1 and more, AI Presentation Maker (Paid), Veo 3.1, Claude Sonnet 4.5, Claude Opus 4.1, Kling AI 2.5 Turbo, AI Music Pro (Paid), Cover and Emoji Support for AI Editor, Chat with Documents for AI Chat Pro, GPT-5 Pro, Sora 2, Sora 2 Pro, Seedream v4, Brand-New External Chatbot and Inbox, Facebook Messenger for External Chatbot (Paid), Multi-Model AI (Paid) and more..
1 parent 3071084 commit f2aec01

237 files changed

Lines changed: 33723 additions & 27030 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/Domains/Engine/Enums/EngineEnum.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ public function getDefaultModels(?Setting $setting, ?SettingTwo $settingTwo): ar
350350
};
351351
}
352352

353-
public function getDefaultWordModel(?Setting $setting): EntityEnum
353+
public function getDefaultWordModel(mixed $setting = null): EntityEnum
354354
{
355355
return match ($this) {
356356
self::OPEN_AI => EntityEnum::fromSlug($setting?->openai_default_model ?? EntityEnum::GPT_5_MINI->slug()),

app/Domains/Engine/Facades/Engine.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
namespace App\Domains\Engine\Facades;
66

7+
use App\Domains\Engine\BaseDriver;
78
use Illuminate\Support\Facades\Facade;
89

910
/**
1011
* @mixin \App\Domains\Engine\Engine
11-
* @mixin \App\Domains\Engine\BaseDriver
12+
* @mixin BaseDriver
1213
*/
1314
class Engine extends Facade
1415
{

app/Domains/Engine/Services/AnthropicService.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class AnthropicService
2121

2222
public ?string $system = null;
2323

24+
public array $tools = [];
25+
2426
public const ENDPOINT = 'https://api.anthropic.com/v1/messages';
2527

2628
public function stream(): PromiseInterface|Response
@@ -29,6 +31,8 @@ public function stream(): PromiseInterface|Response
2931

3032
$system = (bool) $this->system;
3133

34+
$hasTools = ! empty($this->tools);
35+
3236
$body = Helper::arrayMerge($system, [
3337
'model' => setting('anthropic_default_model'),
3438
'max_tokens' => (int) setting('anthropic_max_output_length', 1024),
@@ -38,6 +42,10 @@ public function stream(): PromiseInterface|Response
3842
'system' => $this->system,
3943
]);
4044

45+
if ($hasTools) {
46+
$body['tools'] = $this->tools;
47+
}
48+
4149
return $client->post(self::ENDPOINT, $body);
4250
}
4351

@@ -93,4 +101,11 @@ public function setSystem(?string $system): self
93101

94102
return $this;
95103
}
104+
105+
public function setTools(array $tools): self
106+
{
107+
$this->tools = $tools;
108+
109+
return $this;
110+
}
96111
}

app/Domains/Engine/Services/FalAIService.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use App\Domains\Entity\Enums\EntityEnum;
88
use App\Helpers\Classes\ApiHelper;
9+
use GuzzleHttp\Promise\PromiseInterface;
910
use Illuminate\Http\Client\Response;
1011
use Illuminate\Support\Arr;
1112
use Illuminate\Support\Facades\Http;
@@ -608,7 +609,7 @@ public static function lumaGenerate(string $prompt)
608609
return $response->json();
609610
}
610611

611-
public static function veo2Generate(string $prompt): \GuzzleHttp\Promise\PromiseInterface|\Illuminate\Http\Client\Response
612+
public static function veo2Generate(string $prompt): PromiseInterface|Response
612613
{
613614
return Http::timeout(3000)->withHeaders([
614615
'Content-Type' => 'application/json',

app/Domains/Engine/Services/GeminiService.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class GeminiService
1313
{
1414
public array $history = [];
1515

16+
public array $tools = [];
17+
1618
public const ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/';
1719

1820
public function streamGenerateContent($entity = EntityEnum::GEMINI_3_FLASH->value): PromiseInterface|Response
@@ -24,6 +26,11 @@ public function streamGenerateContent($entity = EntityEnum::GEMINI_3_FLASH->valu
2426
'contents' => $this->getHistory(),
2527
];
2628

29+
if (! empty($this->tools)) {
30+
$body['tools'] = $this->tools;
31+
$body['toolConfig'] = ['functionCallingConfig' => ['mode' => 'AUTO']];
32+
}
33+
2734
$url = sprintf('%s%s:streamGenerateContent?key=%s', self::ENDPOINT, $entity, config('gemini.api_key'));
2835

2936
return $client->withOptions(['stream' => true])->post($url, $body);
@@ -111,4 +118,11 @@ public function setHistory(array $history): self
111118

112119
return $this;
113120
}
121+
122+
public function setTools(array $tools): self
123+
{
124+
$this->tools = $tools;
125+
126+
return $this;
127+
}
114128
}

app/Domains/Entity/Concerns/HasCreditLimit.php

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
namespace App\Domains\Entity\Concerns;
66

77
use App\Domains\Entity\Enums\EntityEnum;
8+
use App\Domains\Entity\Facades\Entity;
89
use App\Enums\MagicResponse;
910
use App\Helpers\Classes\Helper;
11+
use App\Helpers\Classes\MarketplaceHelper;
12+
use App\Helpers\Classes\RateLimiter\RateLimiter;
1013
use App\Models\Plan;
1114
use App\Models\Setting;
1215
use App\Models\SettingTwo;
@@ -113,6 +116,49 @@ public function isUnlimitedCredit(): bool
113116
};
114117
}
115118

119+
/**
120+
* Check if the current entity is a web search model.
121+
*/
122+
protected function isWebSearchModel(): bool
123+
{
124+
return in_array($this->enum(), [
125+
EntityEnum::GPT_4_O_SEARCH_PREVIEW,
126+
EntityEnum::GPT_4_O_MINI_SEARCH_PREVIEW,
127+
], true);
128+
}
129+
130+
/**
131+
* Get credit data from the default OpenAI chat model for web search model fallback.
132+
*
133+
* @return array{credit: float, isUnlimited: bool}|null
134+
*/
135+
protected function getDefaultChatModelCreditData(): ?array
136+
{
137+
$defaultModelSlug = Setting::getCache()?->openai_default_model ?? EntityEnum::GPT_5_MINI->slug();
138+
$defaultEnum = EntityEnum::fromSlug($defaultModelSlug);
139+
140+
if (! $defaultEnum || $defaultEnum === $this->enum()) {
141+
return null;
142+
}
143+
144+
$driver = Entity::driver($defaultEnum);
145+
146+
$user = $this->getUser();
147+
if ($user) {
148+
$driver = $driver->forUser($user);
149+
}
150+
151+
if ($this->plan?->exists) {
152+
$driver = $driver->forPlan($this->plan);
153+
}
154+
155+
if ($this->team?->exists) {
156+
$driver = $driver->forTeam($this->team);
157+
}
158+
159+
return $driver->getCredit();
160+
}
161+
116162
public function getCreditBalance(): float
117163
{
118164
$credit = $this->getCredit()['credit'];
@@ -129,11 +175,21 @@ public function getCreditBalance(): float
129175
$model && ! $model->is_selected &&
130176
! in_array($model->key, $engineDefaultModels, true) &&
131177
! in_array($model->id, $aiFinances, true) &&
132-
! $this->isInAiImageProSelectedModels($model->key->value)
178+
! $this->isInAiImageProSelectedModels($model->key->value) &&
179+
! $this->isWebSearchModel()
133180
) {
134181
return 0;
135182
}
136183

184+
if ($credit == 0 && $this->isWebSearchModel()) {
185+
$defaultCredit = $this->getDefaultChatModelCreditData();
186+
if ($defaultCredit) {
187+
$fallback = $defaultCredit['credit'];
188+
189+
return is_string($fallback) ? (float) $fallback : $fallback;
190+
}
191+
}
192+
137193
return $credit;
138194
}
139195

@@ -152,12 +208,22 @@ public function getIsUnlimitedCredit(): bool
152208
$model && ! $model->is_selected &&
153209
! in_array($model->key, $engineDefaultModels, true) &&
154210
! in_array($model->id, $aiFinances, true) &&
155-
! $this->isInAiImageProSelectedModels($model->key->value)
211+
! $this->isInAiImageProSelectedModels($model->key->value) &&
212+
! $this->isWebSearchModel()
156213
) {
157214
return false;
158215
}
159216

160-
return $this->getCredit()['isUnlimited'];
217+
$isUnlimited = $this->getCredit()['isUnlimited'];
218+
219+
if (! $isUnlimited && $this->isWebSearchModel()) {
220+
$defaultCredit = $this->getDefaultChatModelCreditData();
221+
if ($defaultCredit) {
222+
return $defaultCredit['isUnlimited'];
223+
}
224+
}
225+
226+
return $isUnlimited;
161227
}
162228

163229
/**
@@ -180,7 +246,7 @@ protected function getAiImageProSelectedModels(): array
180246
$models = [];
181247

182248
// Check AI Image Pro selected models (only if extension is registered)
183-
if (\App\Helpers\Classes\MarketplaceHelper::isRegistered('ai-image-pro')) {
249+
if (MarketplaceHelper::isRegistered('ai-image-pro')) {
184250
$aiImageProModels = setting('ai_image_selected_models', null);
185251
if (! empty($aiImageProModels)) {
186252
$slugs = is_string($aiImageProModels)
@@ -191,7 +257,7 @@ protected function getAiImageProSelectedModels(): array
191257
}
192258

193259
// Check AI Chat Pro Image Chat selected models (only if extension is registered)
194-
if (\App\Helpers\Classes\MarketplaceHelper::isRegistered('ai-chat-pro-image-chat')) {
260+
if (MarketplaceHelper::isRegistered('ai-chat-pro-image-chat')) {
195261
$aiChatImageModels = setting('ai_chat_pro_image_chat_selected_models', null);
196262
if (! empty($aiChatImageModels)) {
197263
$slugs = is_string($aiChatImageModels)
@@ -221,7 +287,7 @@ public function hasCreditBalance(): bool
221287
public function guestHasAttempts(): bool
222288
{
223289
$clientIp = Helper::getRequestIp();
224-
$rateLimiter = new \App\Helpers\Classes\RateLimiter\RateLimiter('guest-chat-attempt', (int) setting('guest_user_daily_message_limit', '10'));
290+
$rateLimiter = new RateLimiter('guest-chat-attempt', (int) setting('guest_user_daily_message_limit', '10'));
225291
if ($rateLimiter->attempt($clientIp)) {
226292
return true;
227293
}
@@ -312,11 +378,45 @@ public function decreaseCredit(float $value = 1.00): bool
312378
'total' => $value * $unitPrice,
313379
]);
314380

381+
if ($this->isWebSearchModel() && $this->getCredit()['credit'] == 0) {
382+
return $this->decreaseCreditFromDefaultChatModel($value);
383+
}
384+
315385
return $this->updateUserCredit($value, function ($creditBalance, $credit) {
316386
return max(0, $creditBalance - $credit);
317387
});
318388
}
319389

390+
/**
391+
* Decrease credit from the default OpenAI chat model's pool for web search models.
392+
*
393+
* @throws Exception
394+
*/
395+
private function decreaseCreditFromDefaultChatModel(float $value): bool
396+
{
397+
$defaultModelSlug = Setting::getCache()?->openai_default_model ?? EntityEnum::GPT_5_MINI->slug();
398+
$defaultEnum = EntityEnum::fromSlug($defaultModelSlug);
399+
400+
if (! $defaultEnum || $defaultEnum === $this->enum()) {
401+
return $this->updateUserCredit($value, function ($creditBalance, $credit) {
402+
return max(0, $creditBalance - $credit);
403+
});
404+
}
405+
406+
$driver = Entity::driver($defaultEnum);
407+
408+
$user = $this->getUser();
409+
if ($user) {
410+
$driver = $driver->forUser($user);
411+
}
412+
413+
if ($this->team?->exists) {
414+
$driver = $driver->forTeam($this->team);
415+
}
416+
417+
return $driver->decreaseCredit($value);
418+
}
419+
320420
/**
321421
* @throws Exception
322422
*/
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domains\Entity\Drivers\Gemini;
6+
7+
use App\Domains\Entity\BaseDriver;
8+
use App\Domains\Entity\Concerns\Calculate\HasWords;
9+
use App\Domains\Entity\Concerns\Input\HasInput;
10+
use App\Domains\Entity\Contracts\Calculate\WithWordsInterface;
11+
use App\Domains\Entity\Contracts\Input\WithInputInterface;
12+
use App\Domains\Entity\Enums\EntityEnum;
13+
14+
class GeminiDeepResearchDriver extends BaseDriver implements WithInputInterface, WithWordsInterface
15+
{
16+
use HasInput;
17+
use HasWords;
18+
19+
public function enum(): EntityEnum
20+
{
21+
return EntityEnum::GEMINI_DEEP_RESEARCH;
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domains\Entity\Drivers\OpenAI;
6+
7+
use App\Domains\Entity\BaseDriver;
8+
use App\Domains\Entity\Concerns\Calculate\HasWords;
9+
use App\Domains\Entity\Concerns\Input\HasInput;
10+
use App\Domains\Entity\Contracts\Calculate\WithWordsInterface;
11+
use App\Domains\Entity\Contracts\Input\WithInputInterface;
12+
use App\Domains\Entity\Enums\EntityEnum;
13+
14+
class GPT54MiniDriver extends BaseDriver implements WithInputInterface, WithWordsInterface
15+
{
16+
use HasInput;
17+
use HasWords;
18+
19+
public function enum(): EntityEnum
20+
{
21+
return EntityEnum::GPT_5_4_MINI;
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domains\Entity\Drivers\OpenAI;
6+
7+
use App\Domains\Entity\BaseDriver;
8+
use App\Domains\Entity\Concerns\Calculate\HasWords;
9+
use App\Domains\Entity\Concerns\Input\HasInput;
10+
use App\Domains\Entity\Contracts\Calculate\WithWordsInterface;
11+
use App\Domains\Entity\Contracts\Input\WithInputInterface;
12+
use App\Domains\Entity\Enums\EntityEnum;
13+
14+
class GPT54NanoDriver extends BaseDriver implements WithInputInterface, WithWordsInterface
15+
{
16+
use HasInput;
17+
use HasWords;
18+
19+
public function enum(): EntityEnum
20+
{
21+
return EntityEnum::GPT_5_4_NANO;
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domains\Entity\Drivers\OpenAI;
6+
7+
use App\Domains\Entity\BaseDriver;
8+
use App\Domains\Entity\Concerns\Calculate\HasWords;
9+
use App\Domains\Entity\Concerns\Input\HasInput;
10+
use App\Domains\Entity\Contracts\Calculate\WithWordsInterface;
11+
use App\Domains\Entity\Contracts\Input\WithInputInterface;
12+
use App\Domains\Entity\Enums\EntityEnum;
13+
14+
class O3DeepResearchDriver extends BaseDriver implements WithInputInterface, WithWordsInterface
15+
{
16+
use HasInput;
17+
use HasWords;
18+
19+
public function enum(): EntityEnum
20+
{
21+
return EntityEnum::O3_DEEP_RESEARCH;
22+
}
23+
}

0 commit comments

Comments
 (0)