yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
service_factory_browser.cc
Go to the documentation of this file.
2
3#include <fstream>
4#include <utility>
5
6#include "absl/flags/declare.h"
7#include "absl/flags/flag.h"
8#include "absl/strings/ascii.h"
9#include "absl/strings/match.h"
10#include "app/net/http_client.h"
15#include "rom/rom.h"
16#include "util/platform_paths.h"
17
18namespace {
19
20constexpr char kDefaultOpenAiBaseUrl[] = "https://api.openai.com";
21constexpr char kOraclePromptAsset[] = "agent/oracle_of_secrets_guide.txt";
22
23std::string NormalizeOpenAIApiBase(std::string base) {
24 if (base.empty()) {
25 return base;
26 }
28 if (!absl::EndsWith(base, "/v1")) {
29 base += "/v1";
30 }
31 return base;
32}
33
34bool IsLikelyOracleRomPath(absl::string_view rom_path) {
35 if (rom_path.empty()) {
36 return false;
37 }
38 const std::string lowered = absl::AsciiStrToLower(std::string(rom_path));
39 return absl::StrContains(lowered, "oracle") ||
40 absl::StrContains(lowered, "oos");
41}
42
43std::string NormalizeBrowserProviderAlias(std::string provider) {
44 provider = absl::AsciiStrToLower(std::move(provider));
45 if (provider == yaze::cli::kProviderGoogle ||
48 }
49 if (provider == yaze::cli::kProviderLmStudioDashed) {
51 }
52 if (provider == yaze::cli::kProviderChatGpt ||
53 provider == yaze::cli::kProviderGpt ||
57 }
58 return provider;
59}
60
61bool IsOpenAiCompatibleProvider(absl::string_view provider) {
62 return provider == yaze::cli::kProviderOpenAi ||
63 provider == yaze::cli::kProviderLmStudio ||
64 provider == yaze::cli::kProviderHalext ||
66}
67
68bool IsBrowserSupportedProvider(absl::string_view provider) {
69 return provider == yaze::cli::kProviderMock ||
70 provider == yaze::cli::kProviderGemini ||
72}
73
74std::string ReadAssetFile(absl::string_view relative_path) {
75 auto asset_path =
76 yaze::util::PlatformPaths::FindAsset(std::string(relative_path));
77 if (!asset_path.ok()) {
78 return "";
79 }
80 std::ifstream file(asset_path->string());
81 if (!file.good()) {
82 return "";
83 }
84 return std::string(std::istreambuf_iterator<char>(file),
85 std::istreambuf_iterator<char>());
86}
87
96
98 config.provider = NormalizeBrowserProviderAlias(std::move(config.provider));
99 if (config.provider.empty()) {
101 }
102 config.openai_base_url =
104 return config;
105}
106
107std::unique_ptr<yaze::cli::AIService> FinalizeService(
108 std::unique_ptr<yaze::cli::AIService> service,
109 const yaze::cli::AIServiceConfig& config) {
110 if (service != nullptr && config.rom_context != nullptr) {
111 service->SetRomContext(config.rom_context);
112 }
113 return service;
114}
115
116} // namespace
117
118#ifdef __EMSCRIPTEN__
120#endif
121
122ABSL_DECLARE_FLAG(std::string, ai_provider);
123ABSL_DECLARE_FLAG(std::string, ai_model);
124ABSL_DECLARE_FLAG(std::string, gemini_api_key);
125ABSL_DECLARE_FLAG(std::string, openai_base_url);
126ABSL_DECLARE_FLAG(std::string, rom);
127
128namespace yaze {
129namespace cli {
130
131AIServiceConfig BuildAIServiceConfigFromFlags() {
132 AIServiceConfig config;
133 config.provider = ::absl::GetFlag(FLAGS_ai_provider);
134 config.model = ::absl::GetFlag(FLAGS_ai_model);
135 config.gemini_api_key = ::absl::GetFlag(FLAGS_gemini_api_key);
136 config.openai_base_url = ::absl::GetFlag(FLAGS_openai_base_url);
137 config.rom_path_hint = ::absl::GetFlag(FLAGS_rom);
138 return NormalizeConfig(std::move(config));
139}
140
141AgentPromptProfile DetectPromptProfile(const AIServiceConfig& config) {
142 if (config.rom_context != nullptr &&
143 IsLikelyOracleRomPath(config.rom_context->filename())) {
145 }
146 return IsLikelyOracleRomPath(config.rom_path_hint)
149}
150
151std::vector<AIServiceConfig> DiscoverModelRegistryConfigs(
152 const AIServiceConfig& base_config) {
153 AIServiceConfig config = NormalizeConfig(base_config);
154 if (config.provider.empty() || config.provider == kProviderAuto) {
155 config.provider = kProviderGemini;
156 }
157 if (!IsBrowserSupportedProvider(config.provider)) {
158 return {};
159 }
160 return {config};
161}
162
163std::unique_ptr<AIService> CreateAIService() {
164 AIServiceConfig config = BuildAIServiceConfigFromFlags();
165 if (config.provider.empty() || config.provider == kProviderAuto) {
166 config.provider = kProviderGemini;
167 }
168 if (config.model.empty()) {
169 config.model = "gemini-2.5-flash";
170 }
171 return CreateAIService(config);
172}
173
174std::unique_ptr<AIService> CreateAIService(const AIServiceConfig& config) {
175 AIServiceConfig effective_config = NormalizeConfig(config);
176 if (effective_config.provider.empty() ||
177 effective_config.provider == kProviderAuto) {
178 effective_config.provider = kProviderGemini;
179 }
180
181 auto service_or = CreateAIServiceStrict(effective_config);
182 if (service_or.ok()) {
183 return std::move(service_or.value());
184 }
185
186 return FinalizeService(std::make_unique<MockAIService>(), effective_config);
187}
188
189::absl::StatusOr<std::unique_ptr<AIService>> CreateAIServiceStrict(
190 const AIServiceConfig& config) {
191 AIServiceConfig effective_config = NormalizeConfig(config);
192 if (effective_config.provider.empty() ||
193 effective_config.provider == kProviderAuto) {
194 return absl::InvalidArgumentError(
195 "CreateAIServiceStrict requires an explicit provider (not 'auto')");
196 }
197
198 if (effective_config.provider == kProviderMock) {
199 return FinalizeService(std::make_unique<MockAIService>(), effective_config);
200 }
201
202 if (!IsBrowserSupportedProvider(effective_config.provider)) {
203 return absl::FailedPreconditionError(
204 absl::StrFormat("Provider '%s' is not supported in the browser build",
205 effective_config.provider));
206 }
207
208 BrowserAIConfig browser_config;
209 browser_config.provider = effective_config.provider;
210 browser_config.model = effective_config.model;
211 browser_config.system_instruction =
212 ResolveOracleSystemInstruction(effective_config);
213 if (IsOpenAiCompatibleProvider(browser_config.provider)) {
214 browser_config.api_key = effective_config.openai_api_key;
215 browser_config.api_base =
216 effective_config.openai_base_url.empty()
218 : NormalizeOpenAIApiBase(effective_config.openai_base_url);
219 } else {
220 browser_config.api_key = effective_config.gemini_api_key;
221 }
222 browser_config.verbose = effective_config.verbose;
223
224#ifdef __EMSCRIPTEN__
225 auto http_client = std::make_unique<net::EmscriptenHttpClient>();
226#else
227 std::unique_ptr<net::IHttpClient> http_client = nullptr;
228#endif
229
230 return FinalizeService(std::make_unique<BrowserAIService>(
231 browser_config, std::move(http_client)),
232 effective_config);
233}
234
235} // namespace cli
236} // namespace yaze
static absl::StatusOr< std::filesystem::path > FindAsset(const std::string &relative_path)
Find an asset file in multiple standard locations.
yaze::cli::AIServiceConfig NormalizeConfig(yaze::cli::AIServiceConfig config)
std::unique_ptr< yaze::cli::AIService > FinalizeService(std::unique_ptr< yaze::cli::AIService > service, const yaze::cli::AIServiceConfig &config)
bool IsLikelyOracleRomPath(absl::string_view rom_path)
std::string ResolveOracleSystemInstruction(const yaze::cli::AIServiceConfig &config)
bool IsBrowserSupportedProvider(absl::string_view provider)
std::string NormalizeBrowserProviderAlias(std::string provider)
bool IsOpenAiCompatibleProvider(absl::string_view provider)
std::string ReadAssetFile(absl::string_view relative_path)
std::string ResolveOracleSystemInstruction(const yaze::cli::AIServiceConfig &config)
yaze::cli::AIServiceConfig NormalizeConfig(yaze::cli::AIServiceConfig config)
std::unique_ptr< yaze::cli::AIService > FinalizeService(std::unique_ptr< yaze::cli::AIService > service, const yaze::cli::AIServiceConfig &config)
constexpr char kProviderGemini[]
Definition provider_ids.h:9
constexpr char kProviderGpt[]
constexpr char kProviderGoogle[]
constexpr char kProviderCustomOpenAi[]
std::unique_ptr< AIService > CreateAIService()
AgentPromptProfile DetectPromptProfile(const AIServiceConfig &config)
absl::StatusOr< std::unique_ptr< AIService > > CreateAIServiceStrict(const AIServiceConfig &config)
constexpr char kProviderAuto[]
Definition provider_ids.h:6
constexpr char kProviderChatGpt[]
AIServiceConfig BuildAIServiceConfigFromFlags()
std::string NormalizeOpenAiBaseUrl(std::string base)
constexpr char kProviderHalext[]
constexpr char kProviderGoogleGemini[]
constexpr char kProviderMock[]
Definition provider_ids.h:7
constexpr char kProviderOpenAiCompatible[]
constexpr char kProviderAfsBridge[]
std::vector< AIServiceConfig > DiscoverModelRegistryConfigs(const AIServiceConfig &base_config)
constexpr char kProviderLmStudioDashed[]
constexpr char kProviderOpenAi[]
constexpr char kProviderLmStudio[]
ABSL_DECLARE_FLAG(std::string, ai_provider)