{"repo": "bolitupac/pr-ai", "files": {"app/Http/Controllers/ProfileAiKeyController.php": {"8f62265098b6a5b0c6930695a8495f1335950cae": {"t": 1785745765.8460703, "n": 5655, "h": "bb852ac39b5f6631", "c": "json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function save(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->openAiKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_openai_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function remove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_openai_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n\n public function setMode(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'mode' => ['required', 'string', 'in:developer,personal'],\n ]);\n\n $mode = (string) $payload['mode'];\n if ($mode === 'personal' && !$user->hasCustomOpenAiKey()) {\n return response()->json(['message' => 'Add a personal API key before switching to personal mode.'], 422);\n }\n\n $user->ai_key_mode = $mode;\n $user->save();\n\n return response()->json([\n 'message' => $mode === 'personal' ? 'Switched to personal API key.' : 'Switched to developer API key.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n // --- DeepSeek ---\n\n public function deepseekStatus(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekSave(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->deepSeekKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_deepseek_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekRemove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_deepseek_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n}\n"}, "9de6386fc34e8e087ed1e1d93a5b614aeb84d1a9": {"t": 1785756294.0762153, "n": 5655, "h": "bb852ac39b5f6631", "c": "json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function save(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->openAiKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_openai_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function remove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_openai_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n\n public function setMode(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'mode' => ['required', 'string', 'in:developer,personal'],\n ]);\n\n $mode = (string) $payload['mode'];\n if ($mode === 'personal' && !$user->hasCustomOpenAiKey()) {\n return response()->json(['message' => 'Add a personal API key before switching to personal mode.'], 422);\n }\n\n $user->ai_key_mode = $mode;\n $user->save();\n\n return response()->json([\n 'message' => $mode === 'personal' ? 'Switched to personal API key.' : 'Switched to developer API key.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n // --- DeepSeek ---\n\n public function deepseekStatus(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekSave(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->deepSeekKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_deepseek_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekRemove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_deepseek_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n}\n"}, "dddaf67557af1445aff74351cfe48dc16f40117b": {"t": 1785756297.026368, "n": 5652, "h": "e5a27528f12b5808", "c": "json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function save(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->openAiKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_openai_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function remove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_openai_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n\n public function setMode(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'mode' => ['required', 'string', 'in:developer,personal'],\n ]);\n\n $mode = (string) $payload['mode'];\n if ($mode === 'personal' && !$user->hasCustomOpenAiKey()) {\n return response()->json(['message' => 'Add a personal API key before switching to personal mode.'], 422);\n }\n\n $user->ai_key_mode = $mode;\n $user->save();\n\n return response()->json([\n 'message' => $mode === 'personal' ? 'Switched to personal API key.' : 'Switched to system API key.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n // --- DeepSeek ---\n\n public function deepseekStatus(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekSave(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->deepSeekKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_deepseek_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekRemove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_deepseek_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n}\n"}, "a4d7406bbdecd7d31e5827aa1a62859c9150c85c": {"t": 1785756299.2989068, "n": 5655, "h": "bb852ac39b5f6631", "c": "json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function save(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->openAiKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_openai_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function remove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_openai_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n\n public function setMode(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'mode' => ['required', 'string', 'in:developer,personal'],\n ]);\n\n $mode = (string) $payload['mode'];\n if ($mode === 'personal' && !$user->hasCustomOpenAiKey()) {\n return response()->json(['message' => 'Add a personal API key before switching to personal mode.'], 422);\n }\n\n $user->ai_key_mode = $mode;\n $user->save();\n\n return response()->json([\n 'message' => $mode === 'personal' ? 'Switched to personal API key.' : 'Switched to developer API key.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n // --- DeepSeek ---\n\n public function deepseekStatus(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekSave(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->deepSeekKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_deepseek_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomDeepSeekKey(),\n 'masked_key' => (string) $user->masked_deep_seek_key,\n ]);\n }\n\n public function deepseekRemove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_deepseek_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal DeepSeek API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n}\n"}, "7be4937aa5b295d547eb5e6317f2f927a1edabd3": {"t": 1785756300.5380697, "n": 3370, "h": "2614e8ce766add20", "c": "json(['message' => 'Unauthorized.'], 401);\n }\n\n return response()->json([\n 'mode' => (string) ($user->ai_key_mode ?? 'developer'),\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function save(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'api_key' => ['required', 'string', 'max:255'],\n ]);\n\n $result = $this->openAiKeyValidator->validate((string) $payload['api_key']);\n if (!$result['ok']) {\n return response()->json(['message' => $result['message']], 422);\n }\n\n $user->custom_openai_api_key = trim((string) $payload['api_key']);\n if (($user->ai_key_mode ?? 'developer') !== 'personal') {\n $user->ai_key_mode = 'personal';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key saved.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n\n public function remove(): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $user->custom_openai_api_key = null;\n if (($user->ai_key_mode ?? 'developer') === 'personal') {\n $user->ai_key_mode = 'developer';\n }\n $user->save();\n\n return response()->json([\n 'message' => 'Personal API key removed.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => false,\n 'masked_key' => '',\n ]);\n }\n\n public function setMode(Request $request): JsonResponse\n {\n $user = Auth::user();\n if (!$user) {\n return response()->json(['message' => 'Unauthorized.'], 401);\n }\n\n $payload = $request->validate([\n 'mode' => ['required', 'string', 'in:developer,personal'],\n ]);\n\n $mode = (string) $payload['mode'];\n if ($mode === 'personal' && !$user->hasCustomOpenAiKey()) {\n return response()->json(['message' => 'Add a personal API key before switching to personal mode.'], 422);\n }\n\n $user->ai_key_mode = $mode;\n $user->save();\n\n return response()->json([\n 'message' => $mode === 'personal' ? 'Switched to personal API key.' : 'Switched to developer API key.',\n 'mode' => (string) $user->ai_key_mode,\n 'has_personal_key' => $user->hasCustomOpenAiKey(),\n 'masked_key' => (string) $user->masked_open_ai_key,\n ]);\n }\n}\n\n"}}, "app/Models/User.php": {"8f62265098b6a5b0c6930695a8495f1335950cae": {"t": 1785745771.771322, "n": 3228, "h": "08f379534ba54d7d", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n 'ai_key_mode',\n 'ai_provider',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'custom_deepseek_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n 'tutorial_completed_at' => 'datetime',\n 'system_key_credits' => 'integer',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function hasCustomDeepSeekKey(): bool\n {\n return trim((string) $this->custom_deepseek_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function getMaskedDeepSeekKeyAttribute(): string\n {\n $key = trim((string) $this->custom_deepseek_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function conversations(): \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n {\n return $this->hasMany(ChatConversation::class)->latest();\n }\n}\n"}, "dddaf67557af1445aff74351cfe48dc16f40117b": {"t": 1785756292.8282108, "n": 3228, "h": "08f379534ba54d7d", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n 'ai_key_mode',\n 'ai_provider',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'custom_deepseek_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n 'tutorial_completed_at' => 'datetime',\n 'system_key_credits' => 'integer',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function hasCustomDeepSeekKey(): bool\n {\n return trim((string) $this->custom_deepseek_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function getMaskedDeepSeekKeyAttribute(): string\n {\n $key = trim((string) $this->custom_deepseek_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function conversations(): \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n {\n return $this->hasMany(ChatConversation::class)->latest();\n }\n}\n"}, "41eed95994e0f0531fa48b3e8e4bdc0f7e55213d": {"t": 1785756294.0723772, "n": 3181, "h": "fba0dbdd25f1f36a", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n 'ai_key_mode',\n 'ai_provider',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'custom_deepseek_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n 'tutorial_completed_at' => 'datetime',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function hasCustomDeepSeekKey(): bool\n {\n return trim((string) $this->custom_deepseek_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function getMaskedDeepSeekKeyAttribute(): string\n {\n $key = trim((string) $this->custom_deepseek_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function conversations(): \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n {\n return $this->hasMany(ChatConversation::class)->latest();\n }\n}\n"}, "eb4765b223294f820539eb51b78d2bfa9da9f4ff": {"t": 1785756297.037403, "n": 3130, "h": "eccf336262ecc2e9", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n 'ai_key_mode',\n 'ai_provider',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'custom_deepseek_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function hasCustomDeepSeekKey(): bool\n {\n return trim((string) $this->custom_deepseek_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function getMaskedDeepSeekKeyAttribute(): string\n {\n $key = trim((string) $this->custom_deepseek_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function conversations(): \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n {\n return $this->hasMany(ChatConversation::class)->latest();\n }\n}\n"}, "a4d7406bbdecd7d31e5827aa1a62859c9150c85c": {"t": 1785756299.0806246, "n": 2966, "h": "7815d3832290b66f", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n 'ai_key_mode',\n 'ai_provider',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n 'custom_deepseek_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'custom_deepseek_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function hasCustomDeepSeekKey(): bool\n {\n return trim((string) $this->custom_deepseek_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n\n public function getMaskedDeepSeekKeyAttribute(): string\n {\n $key = trim((string) $this->custom_deepseek_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n}\n"}, "796f8a62311a33e54d42f0ac4a91c3a1f7047ebe": {"t": 1785756300.4127493, "n": 2304, "h": "0d25957f9afa1c8a", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'gitlab_id',\n 'gitlab_username',\n 'gitlab_avatar_url',\n 'gitlab_base_url',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'gitlab_token_expires_at',\n 'custom_openai_api_key',\n 'ai_key_mode',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'gitlab_access_token',\n 'gitlab_refresh_token',\n 'custom_openai_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'gitlab_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n}\n"}, "ca7e65cf453e14432fb5e5de3e5dc639fdc76f30": {"t": 1785756301.7124465, "n": 1986, "h": "2941a5cd7ad89ce8", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'custom_openai_api_key',\n 'ai_key_mode',\n 'ai_preferences',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'custom_openai_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n 'ai_preferences' => 'array',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n}\n"}, "7be4937aa5b295d547eb5e6317f2f927a1edabd3": {"t": 1785756306.0527282, "n": 1919, "h": "d180e85f64fdecb3", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n 'custom_openai_api_key',\n 'ai_key_mode',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n 'custom_openai_api_key',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n 'custom_openai_api_key' => 'encrypted',\n ];\n }\n\n public function hasCustomOpenAiKey(): bool\n {\n return trim((string) $this->custom_openai_api_key) !== '';\n }\n\n public function getMaskedOpenAiKeyAttribute(): string\n {\n $key = trim((string) $this->custom_openai_api_key);\n if ($key === '') {\n return '';\n }\n\n if (strlen($key) <= 8) {\n return str_repeat('*', strlen($key));\n }\n\n return substr($key, 0, 4).str_repeat('*', max(4, strlen($key) - 8)).substr($key, -4);\n }\n}\n"}, "ccfcf63cbf2ad064c9225388cf15841053a5c49e": {"t": 1785756307.4819036, "n": 1271, "h": "e4b0a4387d8b0d39", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n 'github_id',\n 'github_username',\n 'github_access_token',\n 'github_refresh_token',\n 'github_token_expires_at',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n 'github_access_token',\n 'github_refresh_token',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n 'github_token_expires_at' => 'datetime',\n ];\n }\n}\n"}, "20388a0bdd114c19241cbb55ce0172368c2e23cd": {"t": 1785756308.8438547, "n": 1009, "h": "0de556dcaed737c4", "c": " */\n use HasFactory, Notifiable;\n\n /**\n * The attributes that are mass assignable.\n *\n * @var list\n */\n protected $fillable = [\n 'name',\n 'email',\n 'password',\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n *\n * @var list\n */\n protected $hidden = [\n 'password',\n 'remember_token',\n ];\n\n /**\n * Get the attributes that should be cast.\n *\n * @return array\n */\n protected function casts(): array\n {\n return [\n 'email_verified_at' => 'datetime',\n 'password' => 'hashed',\n ];\n }\n}\n"}}, "app/Services/Ai/DeepSeekKeyValidator.php": {"8f62265098b6a5b0c6930695a8495f1335950cae": {"t": 1785746178.1997862, "n": 2217, "h": "f5ebe40950a34f2b", "c": " false, 'message' => 'API key is required.'];\n }\n\n if (!str_starts_with($trimmed, 'sk-')) {\n return ['ok' => false, 'message' => 'Invalid key format. DeepSeek keys start with sk-.'];\n }\n\n $baseUrl = (string) config('deepseek.base_url', 'https://api.deepseek.com/v1');\n $model = (string) config('deepseek.model', 'deepseek-chat');\n $timeout = (int) config('deepseek.request_timeout', 30);\n $url = rtrim($baseUrl, '/') . '/chat/completions';\n\n try {\n $response = Http::timeout($timeout)->withToken($trimmed)->post($url, [\n 'model' => $model,\n 'messages' => [\n ['role' => 'user', 'content' => 'Hi'],\n ],\n 'max_tokens' => 5,\n 'temperature' => 0,\n ]);\n } catch (Throwable $e) {\n return [\n 'ok' => false,\n 'message' => 'Could not reach DeepSeek. Check your network and try again.',\n ];\n }\n\n if ($response->successful()) {\n $data = $response->json();\n $reply = trim((string) ($data['choices'][0]['message']['content'] ?? ''));\n if ($reply !== '') {\n return ['ok' => true, 'message' => 'API key is valid — DeepSeek responded.'];\n }\n return ['ok' => true, 'message' => 'API key is valid.'];\n }\n\n if ($response->status() === 401 || $response->status() === 403) {\n $body = $response->json();\n $errMsg = $body['error']['message'] ?? 'Invalid API key.';\n return ['ok' => false, 'message' => 'Not a valid DeepSeek key: ' . $errMsg];\n }\n\n if ($response->status() === 429) {\n return ['ok' => false, 'message' => 'DeepSeek rate limited. Try again in a moment.'];\n }\n\n return ['ok' => false, 'message' => 'Could not validate API key. Try again.'];\n }\n}\n"}, "9de6386fc34e8e087ed1e1d93a5b614aeb84d1a9": {"t": 1785756291.6416044, "n": 2217, "h": "f5ebe40950a34f2b", "c": " false, 'message' => 'API key is required.'];\n }\n\n if (!str_starts_with($trimmed, 'sk-')) {\n return ['ok' => false, 'message' => 'Invalid key format. DeepSeek keys start with sk-.'];\n }\n\n $baseUrl = (string) config('deepseek.base_url', 'https://api.deepseek.com/v1');\n $model = (string) config('deepseek.model', 'deepseek-chat');\n $timeout = (int) config('deepseek.request_timeout', 30);\n $url = rtrim($baseUrl, '/') . '/chat/completions';\n\n try {\n $response = Http::timeout($timeout)->withToken($trimmed)->post($url, [\n 'model' => $model,\n 'messages' => [\n ['role' => 'user', 'content' => 'Hi'],\n ],\n 'max_tokens' => 5,\n 'temperature' => 0,\n ]);\n } catch (Throwable $e) {\n return [\n 'ok' => false,\n 'message' => 'Could not reach DeepSeek. Check your network and try again.',\n ];\n }\n\n if ($response->successful()) {\n $data = $response->json();\n $reply = trim((string) ($data['choices'][0]['message']['content'] ?? ''));\n if ($reply !== '') {\n return ['ok' => true, 'message' => 'API key is valid — DeepSeek responded.'];\n }\n return ['ok' => true, 'message' => 'API key is valid.'];\n }\n\n if ($response->status() === 401 || $response->status() === 403) {\n $body = $response->json();\n $errMsg = $body['error']['message'] ?? 'Invalid API key.';\n return ['ok' => false, 'message' => 'Not a valid DeepSeek key: ' . $errMsg];\n }\n\n if ($response->status() === 429) {\n return ['ok' => false, 'message' => 'DeepSeek rate limited. Try again in a moment.'];\n }\n\n return ['ok' => false, 'message' => 'Could not validate API key. Try again.'];\n }\n}\n"}, "a4d7406bbdecd7d31e5827aa1a62859c9150c85c": {"t": 1785756293.0242474, "n": 1273, "h": "be5a3e1798de774d", "c": " false, 'message' => 'API key is required.'];\n }\n\n if (!str_starts_with($trimmed, 'sk-')) {\n return ['ok' => false, 'message' => 'Invalid key format. DeepSeek keys start with sk-.'];\n }\n\n $baseUrl = (string) config('deepseek.base_url', 'https://api.deepseek.com/v1');\n $timeout = (int) config('deepseek.request_timeout', 30);\n $url = rtrim($baseUrl, '/') . '/models';\n\n try {\n $response = Http::timeout($timeout)->withToken($trimmed)->get($url);\n } catch (Throwable) {\n return ['ok' => false, 'message' => 'Could not validate API key right now. Try again.'];\n }\n\n if ($response->successful()) {\n return ['ok' => true, 'message' => 'API key is valid.'];\n }\n\n if ($response->status() === 401) {\n return ['ok' => false, 'message' => 'Invalid API key.'];\n }\n\n return ['ok' => false, 'message' => 'Could not validate API key right now. Try again.'];\n }\n}\n"}}}}