6#include <emscripten/val.h>
8#include "absl/strings/str_cat.h"
9#include "absl/strings/str_format.h"
18EM_JS(
void, js_session_storage_set, (
const char* key,
const char* value), {
20 if (typeof(Storage) !==
"undefined" && sessionStorage) {
21 sessionStorage.setItem(UTF8ToString(key), UTF8ToString(value));
24 console.error(
'Failed to set sessionStorage:', e);
28EM_JS(
char*, js_session_storage_get, (
const char* key), {
30 if (typeof(Storage) !==
"undefined" && sessionStorage) {
31 const value = sessionStorage.getItem(UTF8ToString(key));
32 if (value === null)
return null;
33 const len = lengthBytesUTF8(value) + 1;
34 const ptr = _malloc(len);
35 stringToUTF8(value, ptr, len);
39 console.error(
'Failed to get from sessionStorage:', e);
44EM_JS(
void, js_session_storage_remove, (
const char* key), {
46 if (typeof(Storage) !==
"undefined" && sessionStorage) {
47 sessionStorage.removeItem(UTF8ToString(key));
50 console.error(
'Failed to remove from sessionStorage:', e);
54EM_JS(
int, js_session_storage_has, (
const char* key), {
56 if (typeof(Storage) !==
"undefined" && sessionStorage) {
57 return sessionStorage.getItem(UTF8ToString(key)) !== null ? 1 : 0;
60 console.error(
'Failed to check sessionStorage:', e);
66EM_JS(
void, js_local_storage_set, (
const char* key,
const char* value), {
68 if (typeof(Storage) !==
"undefined" && localStorage) {
69 localStorage.setItem(UTF8ToString(key), UTF8ToString(value));
72 console.error(
'Failed to set localStorage:', e);
76EM_JS(
char*, js_local_storage_get, (
const char* key), {
78 if (typeof(Storage) !==
"undefined" && localStorage) {
79 const value = localStorage.getItem(UTF8ToString(key));
80 if (value === null)
return null;
81 const len = lengthBytesUTF8(value) + 1;
82 const ptr = _malloc(len);
83 stringToUTF8(value, ptr, len);
87 console.error(
'Failed to get from localStorage:', e);
92EM_JS(
void, js_local_storage_remove, (
const char* key), {
94 if (typeof(Storage) !==
"undefined" && localStorage) {
95 localStorage.removeItem(UTF8ToString(key));
98 console.error(
'Failed to remove from localStorage:', e);
102EM_JS(
int, js_local_storage_has, (
const char* key), {
104 if (typeof(Storage) !==
"undefined" && localStorage) {
105 return localStorage.getItem(UTF8ToString(key)) !== null ? 1 : 0;
108 console.error(
'Failed to check localStorage:', e);
114EM_JS(
char*, js_session_storage_keys, (), {
116 if (typeof(Storage) !==
"undefined" && sessionStorage) {
118 for (let i = 0; i < sessionStorage.length; i++) {
119 keys.push(sessionStorage.key(i));
121 const keysStr = keys.join(
'|');
122 const len = lengthBytesUTF8(keysStr) + 1;
123 const ptr = _malloc(len);
124 stringToUTF8(keysStr, ptr, len);
128 console.error(
'Failed to get sessionStorage keys:', e);
133EM_JS(
char*, js_local_storage_keys, (), {
135 if (typeof(Storage) !==
"undefined" && localStorage) {
137 for (let i = 0; i < localStorage.length; i++) {
138 keys.push(localStorage.key(i));
140 const keysStr = keys.join(
'|');
141 const len = lengthBytesUTF8(keysStr) + 1;
142 const ptr = _malloc(len);
143 stringToUTF8(keysStr, ptr, len);
147 console.error(
'Failed to get localStorage keys:', e);
153EM_JS(
void, js_session_storage_clear_prefix, (
const char* prefix), {
155 if (typeof(Storage) !==
"undefined" && sessionStorage) {
156 const prefixStr = UTF8ToString(prefix);
157 const keysToRemove = [];
158 for (let i = 0; i < sessionStorage.length; i++) {
159 const key = sessionStorage.key(i);
160 if (key &&
key.startsWith(prefixStr)) {
161 keysToRemove.push(key);
164 keysToRemove.forEach(key => sessionStorage.removeItem(key));
167 console.error(
'Failed to clear sessionStorage prefix:', e);
171EM_JS(
void, js_local_storage_clear_prefix, (
const char* prefix), {
173 if (typeof(Storage) !==
"undefined" && localStorage) {
174 const prefixStr = UTF8ToString(prefix);
175 const keysToRemove = [];
176 for (let i = 0; i < localStorage.length; i++) {
177 const key = localStorage.key(i);
178 if (key &&
key.startsWith(prefixStr)) {
179 keysToRemove.push(key);
182 keysToRemove.forEach(key => localStorage.removeItem(key));
185 console.error(
'Failed to clear localStorage prefix:', e);
190EM_JS(
int, js_is_storage_available, (), {
192 if (typeof(Storage) !==
"undefined") {
194 const testKey =
'__yaze_storage_test__';
197 if (sessionStorage) {
198 sessionStorage.setItem(testKey,
'test');
199 sessionStorage.removeItem(testKey);
204 localStorage.setItem(testKey,
'test');
205 localStorage.removeItem(testKey);
211 console.error(
'Storage not available:', e);
217std::vector<std::string> SplitString(
const std::string& str,
char delimiter) {
218 std::vector<std::string> result;
220 size_t end = str.find(delimiter);
222 while (end != std::string::npos) {
223 result.push_back(str.substr(start, end - start));
225 end = str.find(delimiter, start);
228 if (start < str.length()) {
229 result.push_back(str.substr(start));
240 const std::string& key,
241 StorageType storage_type) {
242 if (service.empty()) {
243 return absl::InvalidArgumentError(
"Service name cannot be empty");
246 return absl::InvalidArgumentError(
"API key cannot be empty");
249 std::string storage_key = BuildApiKeyStorageKey(service);
252 js_session_storage_set(storage_key.c_str(),
key.c_str());
254 js_local_storage_set(storage_key.c_str(),
key.c_str());
257 return absl::OkStatus();
261 const std::string& service,
262 StorageType storage_type) {
263 if (service.empty()) {
264 return absl::InvalidArgumentError(
"Service name cannot be empty");
267 std::string storage_key = BuildApiKeyStorageKey(service);
268 char* value =
nullptr;
271 value = js_session_storage_get(storage_key.c_str());
273 value = js_local_storage_get(storage_key.c_str());
276 if (value ==
nullptr) {
277 return absl::NotFoundError(
278 absl::StrFormat(
"No API key found for service: %s", service));
281 std::string result(value);
287 StorageType storage_type) {
288 if (service.empty()) {
289 return absl::InvalidArgumentError(
"Service name cannot be empty");
292 std::string storage_key = BuildApiKeyStorageKey(service);
295 js_session_storage_remove(storage_key.c_str());
297 js_local_storage_remove(storage_key.c_str());
300 return absl::OkStatus();
304 StorageType storage_type) {
305 if (service.empty()) {
309 std::string storage_key = BuildApiKeyStorageKey(service);
312 return js_session_storage_has(storage_key.c_str()) != 0;
314 return js_local_storage_has(storage_key.c_str()) != 0;
319 const std::string& value,
320 StorageType storage_type) {
322 return absl::InvalidArgumentError(
"Key cannot be empty");
325 return absl::InvalidArgumentError(
"Value cannot be empty");
328 std::string storage_key = BuildSecretStorageKey(key);
331 js_session_storage_set(storage_key.c_str(), value.c_str());
333 js_local_storage_set(storage_key.c_str(), value.c_str());
336 return absl::OkStatus();
340 const std::string& key,
341 StorageType storage_type) {
343 return absl::InvalidArgumentError(
"Key cannot be empty");
346 std::string storage_key = BuildSecretStorageKey(key);
347 char* value =
nullptr;
350 value = js_session_storage_get(storage_key.c_str());
352 value = js_local_storage_get(storage_key.c_str());
355 if (value ==
nullptr) {
356 return absl::NotFoundError(absl::StrFormat(
"No secret found for key: %s", key));
359 std::string result(value);
365 StorageType storage_type) {
367 return absl::InvalidArgumentError(
"Key cannot be empty");
370 std::string storage_key = BuildSecretStorageKey(key);
373 js_session_storage_remove(storage_key.c_str());
375 js_local_storage_remove(storage_key.c_str());
378 return absl::OkStatus();
382 StorageType storage_type) {
383 std::vector<std::string> services;
384 char* keys_str =
nullptr;
387 keys_str = js_session_storage_keys();
389 keys_str = js_local_storage_keys();
392 if (keys_str !=
nullptr) {
393 std::string keys(keys_str);
397 auto all_keys = SplitString(keys,
'|');
398 std::string api_prefix = kApiKeyPrefix;
400 for (
const auto& key : all_keys) {
401 if (
key.find(api_prefix) == 0) {
403 std::string service = ExtractServiceFromKey(key);
404 if (!service.empty()) {
405 services.push_back(service);
416 js_session_storage_clear_prefix(kApiKeyPrefix);
418 js_local_storage_clear_prefix(kApiKeyPrefix);
421 return absl::OkStatus();
425 return js_is_storage_available() != 0;
429 StorageType storage_type) {
436 quota.available_bytes = 5 * 1024 * 1024;
439 quota.available_bytes = 10 * 1024 * 1024;
443 char* keys_str =
nullptr;
445 keys_str = js_session_storage_keys();
447 keys_str = js_local_storage_keys();
451 if (keys_str !=
nullptr) {
452 std::string keys(keys_str);
455 auto all_keys = SplitString(keys,
'|');
456 for (
const auto& key : all_keys) {
457 char* value =
nullptr;
459 value = js_session_storage_get(
key.c_str());
461 value = js_local_storage_get(
key.c_str());
464 if (value !=
nullptr) {
465 used += strlen(value) +
key.length();
471 quota.used_bytes = used;
477std::string WasmSecureStorage::BuildApiKeyStorageKey(
const std::string& service) {
478 return absl::StrCat(kApiKeyPrefix, service);
481std::string WasmSecureStorage::BuildSecretStorageKey(
const std::string& key) {
482 return absl::StrCat(kSecretPrefix, key);
485std::string WasmSecureStorage::ExtractServiceFromKey(
const std::string& storage_key) {
486 std::string prefix = kApiKeyPrefix;
487 if (storage_key.find(prefix) == 0) {
488 return storage_key.substr(prefix.length());
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })