intuned-runtime 1.2.4__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/PKG-INFO +1 -1
  2. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/types.py +0 -12
  3. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/api_helpers.py +1 -1
  4. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/backend.py +1 -1
  5. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/pyproject.toml +1 -1
  6. intuned_runtime-1.3.0/runtime/browser/extensions/__init__.py +3 -0
  7. intuned_runtime-1.3.0/runtime/browser/extensions/helpers.py +11 -0
  8. intuned_runtime-1.3.0/runtime/browser/extensions/intuned_extension.py +87 -0
  9. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/launch_chromium.py +26 -0
  10. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/types/__init__.py +4 -0
  11. intuned_runtime-1.3.0/runtime/types/settings_types.py +63 -0
  12. intuned_runtime-1.3.0/runtime/utils/__init__.py +3 -0
  13. intuned_runtime-1.3.0/runtime/utils/config_loader.py +17 -0
  14. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/LICENSE +0 -0
  15. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/README.md +0 -0
  16. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/__init__.py +0 -0
  17. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/__init__.py +0 -0
  18. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/attempt_api_command.py +0 -0
  19. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/attempt_authsession_check_command.py +0 -0
  20. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/attempt_authsession_command.py +0 -0
  21. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/attempt_authsession_create_command.py +0 -0
  22. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/attempt_command.py +0 -0
  23. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/command.py +0 -0
  24. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/deploy_command.py +0 -0
  25. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/init_command.py +0 -0
  26. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_api_command.py +0 -0
  27. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_authsession_command.py +0 -0
  28. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_authsession_create_command.py +0 -0
  29. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_authsession_update_command.py +0 -0
  30. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_authsession_validate_command.py +0 -0
  31. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/run_command.py +0 -0
  32. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/commands/save_command.py +0 -0
  33. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/__test__/__init__.py +0 -0
  34. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/__test__/test_api.py +0 -0
  35. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/__test__/test_authsession.py +0 -0
  36. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/api.py +0 -0
  37. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/authsession.py +0 -0
  38. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/deploy.py +0 -0
  39. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/controller/save.py +0 -0
  40. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/auth_session_helpers.py +0 -0
  41. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/confirmation.py +0 -0
  42. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/console.py +0 -0
  43. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/error.py +0 -0
  44. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/exclusions.py +0 -0
  45. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/get_auth_parameters.py +0 -0
  46. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/import_function.py +0 -0
  47. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_cli/utils/timeout.py +0 -0
  48. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/__init__.py +0 -0
  49. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/__init__.py +0 -0
  50. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/ai_source/__init__.py +0 -0
  51. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/ai_source/ai_source.py +0 -0
  52. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/ai_source/deploy.py +0 -0
  53. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/browser/__init__.py +0 -0
  54. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/browser/save_state.py +0 -0
  55. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/init.py +0 -0
  56. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/__init__.py +0 -0
  57. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/auth_session/__init__.py +0 -0
  58. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/auth_session/check.py +0 -0
  59. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/auth_session/create.py +0 -0
  60. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/auth_session/load.py +0 -0
  61. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/project.py +0 -0
  62. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/run.py +0 -0
  63. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/run_interface.py +0 -0
  64. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/type_check.py +0 -0
  65. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/project/upgrade.py +0 -0
  66. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/publish_packages.py +0 -0
  67. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/commands/root.py +0 -0
  68. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/logger.py +0 -0
  69. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/utils/ai_source_project.py +0 -0
  70. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/utils/code_tree.py +0 -0
  71. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/utils/run_apis.py +0 -0
  72. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/utils/setup_ide_functions_token.py +0 -0
  73. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_internal_cli/utils/unix_socket.py +0 -0
  74. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/intuned_runtime/__init__.py +0 -0
  75. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/__init__.py +0 -0
  76. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/backend_functions/__init__.py +0 -0
  77. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/backend_functions/_call_backend_function.py +0 -0
  78. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/backend_functions/get_auth_session_parameters.py +0 -0
  79. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/__init__.py +0 -0
  80. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/helpers.py +0 -0
  81. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/launch_browser.py +0 -0
  82. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/launch_camoufox.py +0 -0
  83. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/browser/storage_state.py +0 -0
  84. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/constants.py +0 -0
  85. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/context/__init__.py +0 -0
  86. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/context/context.py +0 -0
  87. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/env.py +0 -0
  88. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/errors/__init__.py +0 -0
  89. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/errors/auth_session_errors.py +0 -0
  90. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/errors/run_api_errors.py +0 -0
  91. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/errors/trace_errors.py +0 -0
  92. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/helpers/__init__.py +0 -0
  93. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/helpers/attempt_store.py +0 -0
  94. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/helpers/extend_payload.py +0 -0
  95. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/helpers/extend_timeout.py +0 -0
  96. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/helpers/get_auth_session_parameters.py +0 -0
  97. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/py.typed +0 -0
  98. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/__init__.py +0 -0
  99. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/intuned_settings.py +0 -0
  100. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/playwright_context.py +0 -0
  101. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/playwright_tracing.py +0 -0
  102. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/pydantic_encoder.py +0 -0
  103. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/run_api.py +0 -0
  104. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/setup_context_hook.py +0 -0
  105. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/traces.py +0 -0
  106. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/run/types.py +0 -0
  107. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/types/payload.py +0 -0
  108. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime/types/run_types.py +0 -0
  109. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime_helpers/__init__.py +0 -0
  110. {intuned_runtime-1.2.4 → intuned_runtime-1.3.0}/runtime_helpers/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: intuned-runtime
3
- Version: 1.2.4
3
+ Version: 1.3.0
4
4
  Summary: Runtime commands for Intuned platform Python scrapers
5
5
  License: Elastic-2.0
6
6
  License-File: LICENSE
@@ -1,5 +1,4 @@
1
1
  from pydantic import BaseModel
2
- from pydantic import Field
3
2
  from pydantic import RootModel
4
3
 
5
4
 
@@ -20,14 +19,3 @@ class FileNode(BaseModel):
20
19
 
21
20
 
22
21
  FileSystemTree.model_rebuild()
23
-
24
-
25
- class IntunedJson(BaseModel):
26
- model_config = {"populate_by_name": True}
27
-
28
- class _AuthSessions(BaseModel):
29
- enabled: bool
30
-
31
- auth_sessions: _AuthSessions = Field(alias="authSessions")
32
- project_name: str | None = Field(alias="projectName", default=None)
33
- workspace_id: str | None = Field(alias="workspaceId", default=None)
@@ -3,8 +3,8 @@ from typing import overload
3
3
 
4
4
  from anyio import Path
5
5
 
6
- from intuned_cli.types import IntunedJson
7
6
  from intuned_cli.utils.error import CLIError
7
+ from runtime.types import IntunedJson
8
8
 
9
9
 
10
10
  @overload
@@ -1,7 +1,7 @@
1
1
  import os
2
2
 
3
- from intuned_cli.types import IntunedJson
4
3
  from intuned_cli.utils.error import CLIError
4
+ from runtime.types import IntunedJson
5
5
 
6
6
 
7
7
  def get_base_url():
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "intuned-runtime"
3
- version = "1.2.4"
3
+ version = "1.3.0"
4
4
  description = "Runtime commands for Intuned platform Python scrapers"
5
5
  authors = ["Intuned Developers <engineering@intunedhq.com>"]
6
6
  readme = "README.md"
@@ -0,0 +1,3 @@
1
+ from .helpers import build_extensions_list
2
+
3
+ __all__ = ["build_extensions_list"]
@@ -0,0 +1,11 @@
1
+ from .intuned_extension import get_intuned_extension_path
2
+ from .intuned_extension import is_intuned_extension_enabled
3
+
4
+
5
+ def build_extensions_list() -> list[str]:
6
+ extensions_list: list[str] = []
7
+
8
+ if is_intuned_extension_enabled():
9
+ intuned_extension_path = get_intuned_extension_path()
10
+ extensions_list.append(str(intuned_extension_path))
11
+ return extensions_list
@@ -0,0 +1,87 @@
1
+ import logging
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from playwright.async_api import BrowserContext
7
+
8
+ from runtime.context.context import IntunedContext
9
+ from runtime.env import get_functions_domain
10
+ from runtime.env import get_project_id
11
+ from runtime.env import get_workspace_id
12
+ from runtime.types import CaptchaSolverSettings
13
+ from runtime.utils.config_loader import load_intuned_json
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def get_intuned_extension_path() -> Path | None:
19
+ if "INTUNED_EXTENSION_PATH" not in os.environ:
20
+ return None
21
+ intuned_extension_path = Path(os.environ["INTUNED_EXTENSION_PATH"])
22
+ if not intuned_extension_path.exists():
23
+ return None
24
+ return intuned_extension_path
25
+
26
+
27
+ def is_intuned_extension_enabled() -> bool:
28
+ intuned_extension_path = get_intuned_extension_path()
29
+ if intuned_extension_path is None:
30
+ return False
31
+ else:
32
+ return True
33
+
34
+
35
+ async def get_intuned_worker(context: BrowserContext):
36
+ if not is_intuned_extension_enabled():
37
+ return None
38
+
39
+ for attempt in range(5):
40
+ for service_worker in context.service_workers:
41
+ if "intunedWorker.js" in service_worker.url:
42
+ return service_worker
43
+ try:
44
+ if attempt < 4:
45
+ await context.wait_for_event("serviceworker", timeout=3000)
46
+ except Exception as e:
47
+ logger.warning(f"Error accessing service workers (attempt {attempt + 1}): {e}")
48
+
49
+ logger.warning("Failed to get intuned worker after 5 attempts")
50
+ return None
51
+
52
+
53
+ async def get_intuned_extension_settings() -> dict[str, Any]:
54
+ intuned_json = await load_intuned_json()
55
+ captcha_settings: CaptchaSolverSettings = (
56
+ intuned_json.captcha_solver
57
+ if intuned_json and intuned_json.captcha_solver is not None
58
+ else CaptchaSolverSettings()
59
+ )
60
+ context = IntunedContext.current()
61
+ return {
62
+ **captcha_settings.model_dump(mode="json"),
63
+ "workspaceId": get_workspace_id(),
64
+ "projectId": get_project_id(),
65
+ "token": context.functions_token,
66
+ "baseUrl": get_functions_domain(),
67
+ }
68
+
69
+
70
+ async def setup_intuned_extension():
71
+ if not is_intuned_extension_enabled():
72
+ return
73
+ intuned_extension_path = get_intuned_extension_path()
74
+ if intuned_extension_path is None:
75
+ logger.warning("Intuned extension path not found, intuned extension might not work properly")
76
+ return
77
+
78
+ settings_path = intuned_extension_path / "intunedSettings.json"
79
+ settings_data = await get_intuned_extension_settings()
80
+
81
+ try:
82
+ with open(settings_path, "w") as f:
83
+ import json
84
+
85
+ json.dump(settings_data, f)
86
+ except Exception as e:
87
+ logger.warning(f"Failed to write intuned settings to {settings_path}: {e}")
@@ -8,6 +8,11 @@ from typing import TYPE_CHECKING
8
8
 
9
9
  import anyio
10
10
 
11
+ from runtime.browser.extensions import build_extensions_list
12
+ from runtime.browser.extensions.intuned_extension import get_intuned_worker
13
+ from runtime.browser.extensions.intuned_extension import is_intuned_extension_enabled
14
+ from runtime.browser.extensions.intuned_extension import setup_intuned_extension
15
+
11
16
  from .helpers import get_local_cdp_address
12
17
  from .helpers import get_proxy_env
13
18
  from .helpers import wait_on_cdp_address
@@ -80,15 +85,36 @@ async def launch_chromium(
80
85
  if cdp_port:
81
86
  extra_args.append(f"--remote-debugging-port={cdp_port}")
82
87
 
88
+ args_to_ignore = [
89
+ "--disable-extensions",
90
+ "--disable-component-extensions-with-background-pages",
91
+ "--disable-background-networking",
92
+ "--disable-backgrounding-occluded-windows",
93
+ "--disable-background-timer-throttling",
94
+ ]
95
+ if is_intuned_extension_enabled():
96
+ extensions_list = build_extensions_list()
97
+ extensions = ",".join(extensions_list)
98
+ extra_args.append("--disable-extensions-except=" + extensions)
99
+ extra_args.append(f"--load-extension={extensions}")
100
+ await setup_intuned_extension()
101
+
102
+ if headless:
103
+ args_to_ignore.append("--headless=old")
104
+ extra_args.append("--headless=new")
83
105
  context = await playwright.chromium.launch_persistent_context(
84
106
  os.fspath(user_preferences_dir),
85
107
  headless=headless,
86
108
  viewport=viewport,
87
109
  proxy=proxy,
110
+ ignore_default_args=args_to_ignore,
88
111
  user_agent=os.environ.get("USER_AGENT", default_user_agent),
89
112
  args=extra_args,
90
113
  **kwargs,
91
114
  )
115
+ if is_intuned_extension_enabled():
116
+ # wait for intuned extension to be ready
117
+ await get_intuned_worker(context)
92
118
  if cdp_port:
93
119
  await wait_on_cdp_address(get_local_cdp_address(cdp_port))
94
120
 
@@ -4,6 +4,8 @@ from .run_types import RunAutomationErrorResult
4
4
  from .run_types import RunAutomationResult
5
5
  from .run_types import RunAutomationSuccessResult
6
6
  from .run_types import RunBody
7
+ from .settings_types import CaptchaSolverSettings
8
+ from .settings_types import IntunedJson
7
9
 
8
10
  __all__ = [
9
11
  "Payload",
@@ -12,4 +14,6 @@ __all__ = [
12
14
  "RunAutomationErrorResult",
13
15
  "RunAutomationSuccessResult",
14
16
  "PayloadToAppend",
17
+ "IntunedJson",
18
+ "CaptchaSolverSettings",
15
19
  ]
@@ -0,0 +1,63 @@
1
+ from typing import List
2
+
3
+ from pydantic import BaseModel
4
+ from pydantic import Field
5
+
6
+
7
+ class CaptchaSettings(BaseModel):
8
+ enabled: bool = Field(default=False)
9
+
10
+
11
+ class CustomCaptchaSettings(CaptchaSettings):
12
+ model_config = {
13
+ "populate_by_name": True,
14
+ "serialize_by_alias": True,
15
+ }
16
+
17
+ image_locators: List[str] = Field(alias="imageLocators", default=[])
18
+ submit_locators: List[str] = Field(alias="submitLocators", default=[])
19
+ input_locators: List[str] = Field(alias="inputLocators", default=[])
20
+
21
+
22
+ class TextCaptchaSettings(CaptchaSettings):
23
+ model_config = {
24
+ "populate_by_name": True,
25
+ "serialize_by_alias": True,
26
+ }
27
+ label_locators: List[str] = Field(alias="labelLocators", default=[])
28
+ submit_locators: List[str] = Field(alias="submitLocators", default=[])
29
+ input_locators: List[str] = Field(alias="inputLocators", default=[])
30
+
31
+
32
+ class CaptchaSolverSettings(BaseModel):
33
+ model_config = {
34
+ "populate_by_name": True,
35
+ "serialize_by_alias": True,
36
+ }
37
+
38
+ enabled: bool = Field(default=False)
39
+ cloudflare: CaptchaSettings = Field(default_factory=CaptchaSettings)
40
+ google_recaptcha_v2: CaptchaSettings = Field(alias="googleRecaptchaV2", default_factory=CaptchaSettings)
41
+ google_recaptcha_v3: CaptchaSettings = Field(alias="googleRecaptchaV3", default_factory=CaptchaSettings)
42
+ awscaptcha: CaptchaSettings = Field(default_factory=CaptchaSettings)
43
+ hcaptcha: CaptchaSettings = Field(default_factory=CaptchaSettings)
44
+ funcaptcha: CaptchaSettings = Field(default_factory=CaptchaSettings)
45
+ geetest: CaptchaSettings = Field(default_factory=CaptchaSettings)
46
+ lemin: CaptchaSettings = Field(default_factory=CaptchaSettings)
47
+ custom_captcha: CustomCaptchaSettings = Field(alias="customCaptcha", default_factory=CustomCaptchaSettings)
48
+ text: TextCaptchaSettings = Field(default_factory=TextCaptchaSettings)
49
+ settings: dict[str, int | bool] = Field(
50
+ default={"autoSolve": True, "solveDelay": 2000, "maxRetries": 3, "timeout": 30000}
51
+ )
52
+
53
+
54
+ class IntunedJson(BaseModel):
55
+ model_config = {"populate_by_name": True}
56
+
57
+ class _AuthSessions(BaseModel):
58
+ enabled: bool
59
+
60
+ auth_sessions: _AuthSessions = Field(alias="authSessions")
61
+ project_name: str | None = Field(alias="projectName", default=None)
62
+ workspace_id: str | None = Field(alias="workspaceId", default=None)
63
+ captcha_solver: CaptchaSolverSettings | None = Field(alias="captchaSolver", default=None)
@@ -0,0 +1,3 @@
1
+ from .config_loader import load_intuned_json
2
+
3
+ __all__ = ["load_intuned_json"]
@@ -0,0 +1,17 @@
1
+ from anyio import Path
2
+
3
+ from runtime.types import IntunedJson
4
+
5
+
6
+ async def load_intuned_json() -> IntunedJson | None:
7
+ """
8
+ Load the Intuned.json configuration file.
9
+ Returns None if file doesn't exist or fails to parse.
10
+ """
11
+ intuned_json_path = Path("Intuned.json")
12
+ if not await intuned_json_path.exists():
13
+ return None
14
+ try:
15
+ return IntunedJson.model_validate_json(await intuned_json_path.read_text())
16
+ except Exception:
17
+ return None
File without changes