intuned-runtime 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
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.
- intuned_cli/__init__.py +40 -0
- intuned_cli/commands/__init__.py +18 -0
- intuned_cli/commands/attempt_api_command.py +51 -0
- intuned_cli/commands/attempt_authsession_check_command.py +38 -0
- intuned_cli/commands/attempt_authsession_command.py +12 -0
- intuned_cli/commands/attempt_authsession_create_command.py +44 -0
- intuned_cli/commands/attempt_command.py +12 -0
- intuned_cli/commands/command.py +26 -0
- intuned_cli/commands/deploy_command.py +47 -0
- intuned_cli/commands/init_command.py +21 -0
- intuned_cli/commands/run_api_command.py +69 -0
- intuned_cli/commands/run_authsession_command.py +12 -0
- intuned_cli/commands/run_authsession_create_command.py +50 -0
- intuned_cli/commands/run_authsession_update_command.py +52 -0
- intuned_cli/commands/run_authsession_validate_command.py +49 -0
- intuned_cli/commands/run_command.py +12 -0
- intuned_cli/constants/__init__.py +1 -0
- intuned_cli/constants/readme.py +134 -0
- intuned_cli/controller/__test__/__init__.py +0 -0
- intuned_cli/controller/__test__/test_api.py +529 -0
- intuned_cli/controller/__test__/test_authsession.py +907 -0
- intuned_cli/controller/api.py +212 -0
- intuned_cli/controller/authsession.py +458 -0
- intuned_cli/controller/deploy.py +352 -0
- intuned_cli/controller/init.py +97 -0
- intuned_cli/types.py +33 -0
- intuned_cli/utils/api_helpers.py +32 -0
- intuned_cli/utils/auth_session_helpers.py +57 -0
- intuned_cli/utils/backend.py +5 -0
- intuned_cli/utils/confirmation.py +0 -0
- intuned_cli/utils/console.py +6 -0
- intuned_cli/utils/error.py +27 -0
- intuned_cli/utils/exclusions.py +40 -0
- intuned_cli/utils/get_auth_parameters.py +18 -0
- intuned_cli/utils/import_function.py +15 -0
- intuned_cli/utils/timeout.py +25 -0
- {cli → intuned_internal_cli}/__init__.py +1 -1
- {cli → intuned_internal_cli}/commands/__init__.py +2 -0
- {cli → intuned_internal_cli}/commands/ai_source/deploy.py +1 -1
- {cli → intuned_internal_cli}/commands/project/type_check.py +39 -32
- intuned_internal_cli/commands/root.py +15 -0
- {intuned_runtime-1.0.0.dist-info → intuned_runtime-1.1.0.dist-info}/METADATA +3 -1
- intuned_runtime-1.1.0.dist-info/RECORD +96 -0
- intuned_runtime-1.1.0.dist-info/entry_points.txt +4 -0
- runtime/__init__.py +2 -1
- runtime/backend_functions/_call_backend_function.py +0 -5
- runtime/browser/__init__.py +2 -1
- runtime/browser/launch_chromium.py +68 -49
- runtime/browser/storage_state.py +11 -12
- runtime/errors/run_api_errors.py +14 -10
- runtime/run/playwright_constructs.py +4 -2
- runtime/run/pydantic_encoder.py +15 -0
- runtime/run/run_api.py +5 -4
- runtime/types/run_types.py +16 -0
- intuned_runtime-1.0.0.dist-info/RECORD +0 -58
- intuned_runtime-1.0.0.dist-info/entry_points.txt +0 -3
- {cli → intuned_internal_cli}/commands/ai_source/__init__.py +0 -0
- {cli → intuned_internal_cli}/commands/ai_source/ai_source.py +0 -0
- {cli → intuned_internal_cli}/commands/browser/__init__.py +0 -0
- {cli → intuned_internal_cli}/commands/browser/save_state.py +0 -0
- {cli → intuned_internal_cli}/commands/init.py +0 -0
- {cli → intuned_internal_cli}/commands/project/__init__.py +0 -0
- {cli → intuned_internal_cli}/commands/project/auth_session/__init__.py +0 -0
- {cli → intuned_internal_cli}/commands/project/auth_session/check.py +0 -0
- {cli → intuned_internal_cli}/commands/project/auth_session/create.py +0 -0
- {cli → intuned_internal_cli}/commands/project/auth_session/load.py +0 -0
- {cli → intuned_internal_cli}/commands/project/project.py +0 -0
- {cli → intuned_internal_cli}/commands/project/run.py +0 -0
- {cli → intuned_internal_cli}/commands/project/run_interface.py +0 -0
- {cli → intuned_internal_cli}/commands/project/upgrade.py +0 -0
- {cli → intuned_internal_cli}/commands/publish_packages.py +0 -0
- {cli → intuned_internal_cli}/logger.py +0 -0
- {cli → intuned_internal_cli}/utils/ai_source_project.py +0 -0
- {cli → intuned_internal_cli}/utils/code_tree.py +0 -0
- {cli → intuned_internal_cli}/utils/run_apis.py +0 -0
- {cli → intuned_internal_cli}/utils/unix_socket.py +0 -0
- {intuned_runtime-1.0.0.dist-info → intuned_runtime-1.1.0.dist-info}/LICENSE +0 -0
- {intuned_runtime-1.0.0.dist-info → intuned_runtime-1.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
from anyio import Path
|
2
|
+
|
3
|
+
from runtime.run.run_api import import_function_from_api_dir
|
4
|
+
from runtime.run.run_api import ImportFunction
|
5
|
+
|
6
|
+
|
7
|
+
async def get_cli_import_function() -> ImportFunction:
|
8
|
+
"""
|
9
|
+
Import a function from the API directory for CLI usage.
|
10
|
+
"""
|
11
|
+
cwd = await Path().resolve()
|
12
|
+
|
13
|
+
return lambda file_path, name=None: import_function_from_api_dir(
|
14
|
+
file_path=file_path, automation_function_name=name, base_dir=str(cwd)
|
15
|
+
)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import asyncio
|
2
|
+
from contextlib import asynccontextmanager
|
3
|
+
|
4
|
+
from runtime.context.context import IntunedContext
|
5
|
+
from runtime.errors.run_api_errors import AutomationError
|
6
|
+
|
7
|
+
|
8
|
+
@asynccontextmanager
|
9
|
+
async def extendable_timeout(timeout: float):
|
10
|
+
try:
|
11
|
+
async with asyncio.timeout(timeout) as tm:
|
12
|
+
existing_extend_timeout = IntunedContext.current().extend_timeout
|
13
|
+
|
14
|
+
async def extend_timeout():
|
15
|
+
tm.reschedule(asyncio.timeout(timeout).when())
|
16
|
+
if existing_extend_timeout:
|
17
|
+
await existing_extend_timeout()
|
18
|
+
|
19
|
+
IntunedContext.current().extend_timeout = extend_timeout
|
20
|
+
try:
|
21
|
+
yield
|
22
|
+
finally:
|
23
|
+
IntunedContext.current().extend_timeout = existing_extend_timeout
|
24
|
+
except asyncio.TimeoutError as e:
|
25
|
+
raise AutomationError(Exception("Timed out")) from e
|
@@ -9,6 +9,7 @@ from .project.auth_session import project__auth_session__check # type: ignore
|
|
9
9
|
from .project.auth_session import project__auth_session__create # type: ignore
|
10
10
|
from .project.auth_session import project__auth_session__load # type: ignore
|
11
11
|
from .publish_packages import publish_packages # type: ignore
|
12
|
+
from .root import __root__ # type: ignore
|
12
13
|
|
13
14
|
__all__ = [
|
14
15
|
"project__run",
|
@@ -22,4 +23,5 @@ __all__ = [
|
|
22
23
|
"project__auth_session__check",
|
23
24
|
"project__type_check",
|
24
25
|
"browser__save_state",
|
26
|
+
"__root__",
|
25
27
|
]
|
@@ -6,7 +6,7 @@ from more_termcolor import cyan # type: ignore
|
|
6
6
|
from more_termcolor import green # type: ignore
|
7
7
|
from more_termcolor import red # type: ignore
|
8
8
|
|
9
|
-
from
|
9
|
+
from intuned_internal_cli.utils.code_tree import convert_project_to_code_tree
|
10
10
|
|
11
11
|
from ...utils.ai_source_project import AiSourceInfo
|
12
12
|
from ...utils.ai_source_project import deploy_ai_source
|
@@ -9,6 +9,7 @@ current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
9
9
|
PYRIGHT_CONFIG_PATH = os.path.join(current_dir, "..", "..", "pyright_type_check.json")
|
10
10
|
PYRIGHT_CONFIG_PATH = os.path.abspath(PYRIGHT_CONFIG_PATH)
|
11
11
|
|
12
|
+
|
12
13
|
@arguably.command # type: ignore
|
13
14
|
async def project__type_check():
|
14
15
|
"""
|
@@ -37,44 +38,50 @@ async def project__type_check():
|
|
37
38
|
project_dir = os.getcwd()
|
38
39
|
print("📦 Checking Types...")
|
39
40
|
|
40
|
-
try:
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
try:
|
42
|
+
pyright_issues = []
|
43
|
+
pyright_result = subprocess.run(
|
44
|
+
["pyright", "--outputjson", project_dir, "--project", PYRIGHT_CONFIG_PATH],
|
45
|
+
capture_output=True,
|
46
|
+
text=True,
|
47
|
+
check=False,
|
48
|
+
)
|
49
|
+
|
50
|
+
if pyright_result.stdout:
|
51
|
+
pyright_data = json.loads(pyright_result.stdout)
|
52
|
+
for diagnostic in pyright_data.get("generalDiagnostics", []):
|
53
|
+
severity = diagnostic.get("severity", "").lower()
|
54
|
+
severity_emoji = "ℹ️" if severity == "information" else "⚠️" if severity == "warning" else "🔴"
|
55
|
+
|
56
|
+
pyright_issues.append(
|
57
|
+
{
|
58
|
+
"path": diagnostic.get("file", ""),
|
59
|
+
"line": diagnostic.get("range", {}).get("start", {}).get("line", 0) + 1,
|
60
|
+
"severity": diagnostic.get("severity", ""),
|
61
|
+
"message": diagnostic.get("message", ""),
|
62
|
+
"rule": "type-check",
|
63
|
+
}
|
64
|
+
)
|
48
65
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
pyright_issues.append(
|
56
|
-
{"path": diagnostic.get("file", ""), "line": diagnostic.get("range", {}).get("start", {}).get("line", 0) + 1, "severity": diagnostic.get("severity", ""), "message": diagnostic.get("message", ""), "rule": "type-check"}
|
57
|
-
)
|
58
|
-
|
59
|
-
file_path = diagnostic.get("file", "")
|
60
|
-
if "api/" in file_path:
|
61
|
-
file_path = file_path[file_path.index("api/"):]
|
62
|
-
line_num = diagnostic.get("range", {}).get("start", {}).get("line", 0) + 1
|
63
|
-
message = diagnostic.get("message", "")
|
64
|
-
print(f"{severity_emoji} {file_path}:{line_num} - {message}")
|
65
|
-
|
66
|
-
if severity.lower() == "error":
|
67
|
-
print("\n🔴 Type check failed")
|
68
|
-
sys.exit(1)
|
66
|
+
file_path = diagnostic.get("file", "")
|
67
|
+
if "api/" in file_path:
|
68
|
+
file_path = file_path[file_path.index("api/") :]
|
69
|
+
line_num = diagnostic.get("range", {}).get("start", {}).get("line", 0) + 1
|
70
|
+
message = diagnostic.get("message", "")
|
71
|
+
print(f"{severity_emoji} {file_path}:{line_num} - {message}")
|
69
72
|
|
70
|
-
|
73
|
+
if severity.lower() == "error":
|
74
|
+
print("\n🔴 Type check failed")
|
75
|
+
sys.exit(1)
|
76
|
+
|
77
|
+
if pyright_issues:
|
71
78
|
has_warnings = any(issue["severity"].lower() == "warning" for issue in pyright_issues)
|
72
79
|
if has_warnings:
|
73
80
|
print("\n⚠️ Type check passed with warnings")
|
74
81
|
sys.exit(0)
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
|
83
|
+
print("✨ Python type checking passed without errors.")
|
84
|
+
sys.exit(0)
|
78
85
|
except json.JSONDecodeError:
|
79
86
|
print("🔴 Failed to parse pyright output as JSON")
|
80
87
|
sys.exit(1)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import arguably
|
2
|
+
|
3
|
+
|
4
|
+
@arguably.command # type: ignore
|
5
|
+
async def __root__():
|
6
|
+
"""Internal Intuned CLI.
|
7
|
+
|
8
|
+
This command is intended for internal use by Intuned and is not intended for general users.
|
9
|
+
Breaking changes and experimental features may be present.
|
10
|
+
|
11
|
+
If you are not an Intuned developer, please use the main Intuned CLI instead.
|
12
|
+
"""
|
13
|
+
if arguably.is_target():
|
14
|
+
print("-h/--help")
|
15
|
+
exit(1)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: intuned-runtime
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Runtime commands for Intuned platform Python scrapers
|
5
5
|
License: Elastic-2.0
|
6
6
|
Keywords: runtime,intuned
|
@@ -24,7 +24,9 @@ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
|
|
24
24
|
Requires-Dist: pydantic (>=2.10.6,<3.0.0)
|
25
25
|
Requires-Dist: pyright (>=1.1.387,<2.0.0)
|
26
26
|
Requires-Dist: python-dotenv (==1.0.1)
|
27
|
+
Requires-Dist: pytimeparse (>=1.1.8,<2.0.0)
|
27
28
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
29
|
+
Requires-Dist: rich (>=14.1.0,<15.0.0)
|
28
30
|
Requires-Dist: ruff (>=0.7.2,<0.8.0)
|
29
31
|
Requires-Dist: semver (>=3.0.4,<4.0.0)
|
30
32
|
Requires-Dist: tenacity (>=8.5.0,<9.0.0)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
intuned_cli/__init__.py,sha256=SNcUoVkqPTmIxjEsp05GZBKaAzgCt-rBkvkzndjpfPo,1124
|
2
|
+
intuned_cli/commands/__init__.py,sha256=qndefhU1fGHYYu7f7wxcv03F27NPMIwsxUd3K-fmOD8,1236
|
3
|
+
intuned_cli/commands/attempt_api_command.py,sha256=f4Oi8vjNzGLMgk_1XXO5KzOIAw9sq9N8A62d3QIZxso,1954
|
4
|
+
intuned_cli/commands/attempt_authsession_check_command.py,sha256=RdKRltXIp51wnXamRB1Xr45TUBUs1AQCmAzW8tMQnxo,1334
|
5
|
+
intuned_cli/commands/attempt_authsession_command.py,sha256=hir9y1XyW9VYioOWT6C1-dH43f3JcHhIlfEEijMg2Lc,277
|
6
|
+
intuned_cli/commands/attempt_authsession_create_command.py,sha256=ynAKlNoHuaVPgx4gv2AJquIt7ZVIe8Nh1IIHwNiDeNA,1708
|
7
|
+
intuned_cli/commands/attempt_command.py,sha256=7NZC2dXA8GViCH3ZS2PMziR43hv2RmS6-jgW7l9bu40,253
|
8
|
+
intuned_cli/commands/command.py,sha256=b0OlQIFhoCjCo5QIerfysccBKcU9iIsvqiU7oxshA2M,727
|
9
|
+
intuned_cli/commands/deploy_command.py,sha256=0XG8lo5fGeorZMxMtEx12EaqLFMvmFYJ7Zu9sgJCmQ8,1540
|
10
|
+
intuned_cli/commands/init_command.py,sha256=MV5WR5o4KH1J_Zai6K5S84NG41KZbsJ-I8NPGXurt2o,671
|
11
|
+
intuned_cli/commands/run_api_command.py,sha256=Y6FkSFI9wybuoW204YqOAiQ794__hIw12Eaf9px_ovE,3013
|
12
|
+
intuned_cli/commands/run_authsession_command.py,sha256=kM_TANy8M3yx8iBUsgSDO42byzccikLOd9KJfytfLmQ,269
|
13
|
+
intuned_cli/commands/run_authsession_create_command.py,sha256=SiuIZ7LTMqT3gnd8DUt-VmP3cyuA0I_i27daI3IJ2tw,2089
|
14
|
+
intuned_cli/commands/run_authsession_update_command.py,sha256=Op7epDgvEhjp17qs2dIXerTckHz7wlOsZsBDp8UJLjI,2145
|
15
|
+
intuned_cli/commands/run_authsession_validate_command.py,sha256=5eET02paijq1f1rzsheINvAqVYj1JGUA_iGD5Py3LVM,2008
|
16
|
+
intuned_cli/commands/run_command.py,sha256=JN1yCewcyb4zFquMcv0wEZ_aRmhJZIBMheY8L9yBeDE,245
|
17
|
+
intuned_cli/constants/__init__.py,sha256=AIfIQYQ55zSdGKL2p15wv4H9ANeRjYEkeUiObu6JFt8,37
|
18
|
+
intuned_cli/constants/readme.py,sha256=3OUkZNmz9kss7hA3V2j5h49dv7ADy4LON5-iJkrJUA4,5240
|
19
|
+
intuned_cli/controller/__test__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
intuned_cli/controller/__test__/test_api.py,sha256=8Hk3V52qKhWIqjirKFwN68Tv5er70gTxemjI35HyZiU,19295
|
21
|
+
intuned_cli/controller/__test__/test_authsession.py,sha256=y7O3dkDPHZTf2W7WRLEhysYYRati0hg93-J8BvGjRUM,35110
|
22
|
+
intuned_cli/controller/api.py,sha256=1wHgatavA5zr6kYMf1BJ3lC5JR1IvlVBiab_ahOSVnY,7172
|
23
|
+
intuned_cli/controller/authsession.py,sha256=z8C97T-beEORNemLFx2x_JsHr2gXRakwKGV3Rgivnu8,14309
|
24
|
+
intuned_cli/controller/deploy.py,sha256=5cQgtpT2nDQ5XSUnIoeBR9xdyVoLWcY-2btuUxUD7Es,12343
|
25
|
+
intuned_cli/controller/init.py,sha256=TfkPkq9rbYam2-fchwrpMIt9GJIkY-TQnWpwvPomRZE,3774
|
26
|
+
intuned_cli/types.py,sha256=Lsykui4mbq5T1_1L7Gg5OZpJvCOmaz9EiQcZVfUEoLc,766
|
27
|
+
intuned_cli/utils/api_helpers.py,sha256=57gvXVYM_9hMGIkMqSEN_jzs3mYWlXzinPjYXzzqgg8,1122
|
28
|
+
intuned_cli/utils/auth_session_helpers.py,sha256=acKAPUjOfdybstLur4Lk3huaLFP2Ipl4AjPSqQPQLzY,1899
|
29
|
+
intuned_cli/utils/backend.py,sha256=NFMAqHFslxad9KYirUz3b0BsRz1aQqOGhZRUJdEiO8k,106
|
30
|
+
intuned_cli/utils/confirmation.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
intuned_cli/utils/console.py,sha256=jgin2xB-0kpANPMoiDBOnWhrc8Ey5zT4IHRxQa8f5CQ,93
|
32
|
+
intuned_cli/utils/error.py,sha256=DmNlXBb7zfpHDRya00ouEcRgUEZuGaTqIy1SIjDWVfo,842
|
33
|
+
intuned_cli/utils/exclusions.py,sha256=Qe7NkWA3lsX73dOC9WprdD0KyYc_vuiwkrUCwD105gk,796
|
34
|
+
intuned_cli/utils/get_auth_parameters.py,sha256=HmMSjBE8bPulkUdX319Ipr383Ko2Gtz3y8_WT9CK3Kw,798
|
35
|
+
intuned_cli/utils/import_function.py,sha256=UmE2yw5std1ENMFdBU-TUBuQ01qsv7Qr5ElnAhqE6Yc,453
|
36
|
+
intuned_cli/utils/timeout.py,sha256=DkoeoU9XvKKKSQ06CpwqcNvxWqLPAOVuAMw6kSr4Tuo,886
|
37
|
+
intuned_internal_cli/__init__.py,sha256=iz-mTdcPhNCknHZzdO5-9PHFSapbXiLCwg_cTaYfww4,1337
|
38
|
+
intuned_internal_cli/commands/__init__.py,sha256=gZ-r8UIXvRakeCfvmOZCNWr8CJHBcYzRzbMjyKYPXV0,1003
|
39
|
+
intuned_internal_cli/commands/ai_source/__init__.py,sha256=lg7owgcK8owNn2a4VBUP9RKxzFsLruhtnnQV0F_z6pc,149
|
40
|
+
intuned_internal_cli/commands/ai_source/ai_source.py,sha256=2woQtCmhxKvLfEz832eUoCT9gMsuSvEE6rMnHSYXC7w,138
|
41
|
+
intuned_internal_cli/commands/ai_source/deploy.py,sha256=NpomuP_2mo5SLKe7BZoY5H0Pp36aDtkYU_CyihqOvdI,2457
|
42
|
+
intuned_internal_cli/commands/browser/__init__.py,sha256=AuVbvh7aSBTFKYvewXZyPoIvfBTe2uHiPcnaAkzapas,95
|
43
|
+
intuned_internal_cli/commands/browser/save_state.py,sha256=eHKfvBfeFR_U9VQbsjOnIZjWepyDjNn9NL3naDYWP2s,841
|
44
|
+
intuned_internal_cli/commands/init.py,sha256=8rWBenWZfwNtLxOBqhEMbOATyQNEnmDUmrFJ1xBGyxI,4384
|
45
|
+
intuned_internal_cli/commands/project/__init__.py,sha256=t97wvhSenerYRdbSeCKXqHASA6EWA3lc1hnRhF9baOE,734
|
46
|
+
intuned_internal_cli/commands/project/auth_session/__init__.py,sha256=gt7mlaW6xmqAc_4-pfF_FiecsR51C6fqCaq_NFbcbwA,300
|
47
|
+
intuned_internal_cli/commands/project/auth_session/check.py,sha256=AFILp7m34nAO_RD3IfRpuJm5Zh0wnCRtBXqIrerdbwo,4565
|
48
|
+
intuned_internal_cli/commands/project/auth_session/create.py,sha256=r-eYu3uLUo2mzF836CbVgu4oBzcIIDekzzFwwekxmg0,3374
|
49
|
+
intuned_internal_cli/commands/project/auth_session/load.py,sha256=UUvg9Vyj15xiR44XlJzojLoFm5esv-o4E3qA3JqnBsE,1201
|
50
|
+
intuned_internal_cli/commands/project/project.py,sha256=_MSh6Xor2Cbh-ItifwgOPq_BP8UDuKB7S6w796FULKQ,137
|
51
|
+
intuned_internal_cli/commands/project/run.py,sha256=FDYYkU24aURYbljyYLFo8wLF-nvb86EVr9gMEjAfeE0,12274
|
52
|
+
intuned_internal_cli/commands/project/run_interface.py,sha256=4RyR8WZriIF7Va4z1wt-q6zZDQOI31n62Ho2dyimzUY,8717
|
53
|
+
intuned_internal_cli/commands/project/type_check.py,sha256=QFnXL93Y-z250EQRln5sRqwkVqjGJ-eP_p1jGrXB7NA,3522
|
54
|
+
intuned_internal_cli/commands/project/upgrade.py,sha256=XmkZLflM4O-mwvhwcswlZpazRotwi3xesLgE0Zz8fTI,3061
|
55
|
+
intuned_internal_cli/commands/publish_packages.py,sha256=sijkaG7_s0I1EWgLekGy1qm8Aqi_gYY8poXbMX0B6Yw,10505
|
56
|
+
intuned_internal_cli/commands/root.py,sha256=o75rSb5WYa5JMD8HLN3eiNu4fM0mar3y15A63-Qm4s4,426
|
57
|
+
intuned_internal_cli/logger.py,sha256=bZK3q-KUdGxk_qzDb6pn-n0LOhKJvi6a9p8oSwZtq3s,594
|
58
|
+
intuned_internal_cli/utils/ai_source_project.py,sha256=xUCM6p3i1XN4bJbuQz8LCzeI4BwqAdSvCl_vwDAEi0k,831
|
59
|
+
intuned_internal_cli/utils/code_tree.py,sha256=1wfxZoQ5kRCfqs2SEPAicbAIPTiD6P1LxSuwYu_eeaI,2790
|
60
|
+
intuned_internal_cli/utils/run_apis.py,sha256=Zee4zkgt9R8XY1XCGzj2Nc4zJ3jlRz1xnO493wotuWw,4690
|
61
|
+
intuned_internal_cli/utils/unix_socket.py,sha256=UISmkJMHrir5iBLUm6vxC3uzTGIFyOk_wa0C9LUw4Cc,1889
|
62
|
+
runtime/__init__.py,sha256=87gDXuxUv_kGzQfuB1mh6DF-dDysJN8r684c7jGnHxc,144
|
63
|
+
runtime/backend_functions/__init__.py,sha256=j2EaK4FK8bmdFtqc5FxtFwx1KhIn_7qKPChrrAhJI3s,119
|
64
|
+
runtime/backend_functions/_call_backend_function.py,sha256=zuaf4mwYHSm5RTedhMdU66jAMAzdPYPMmXJE_V1xoyk,2869
|
65
|
+
runtime/backend_functions/get_auth_session_parameters.py,sha256=pOvB7XiWpphEuBpazdKALw9EWgBU1PeY3gkzBfVLpkc,869
|
66
|
+
runtime/browser/__init__.py,sha256=CRBpMS319LBz2FLxDjjCvQdOUCgHLIrQFscr_Zi5Hm0,160
|
67
|
+
runtime/browser/launch_chromium.py,sha256=OVaE8ezjxCYA1NUSDdd3FczrfNCpG_528Vmsv4S6QGU,7916
|
68
|
+
runtime/browser/storage_state.py,sha256=fwLg8sP-H-vgt_6AJKNl03CpgyMVCQWWcN2cqswTQMs,3603
|
69
|
+
runtime/context/__init__.py,sha256=hg8ejm4bJy4tNkwmZ9lKgYJx6bU7OgOdBS684Uv5XGg,73
|
70
|
+
runtime/context/context.py,sha256=pl_0x77_d5CiAznz1qGSk6o9cW-msNvlCt-2eFoMKlA,1739
|
71
|
+
runtime/env.py,sha256=h4BJI-XVSZKgtTxjkzj2HsyN3DlY5Ml9GZqeH4CKDE8,238
|
72
|
+
runtime/errors/__init__.py,sha256=oqiBSvT_yFLQ3hG0AbCUA3WYFaxkTDVkDMSy59xvBCo,688
|
73
|
+
runtime/errors/auth_session_errors.py,sha256=6b4XTI8UCDHDPX4jEA8_HyrNUp4VZ1TrEA8DRh6Z3rM,228
|
74
|
+
runtime/errors/run_api_errors.py,sha256=LdmOEHoUk7wjWSk0HQYqslfJNNmxVgga_0bankzvX-s,3341
|
75
|
+
runtime/errors/trace_errors.py,sha256=Lzfo0sH3zGaWz1kn5DHcAXQMn3aR2y2bnauj6xP1LYE,110
|
76
|
+
runtime/helpers/__init__.py,sha256=jozYPKHgZJ7Na5U1Wjt83egzjPATMZ_OMInEI6swSbY,234
|
77
|
+
runtime/helpers/extend_payload.py,sha256=towZF08WTpTTDBL4AV1bUU3XpKAQHEB66kGUfTICDe0,246
|
78
|
+
runtime/helpers/extend_timeout.py,sha256=KjfSLEUrqoz7v00rhnPAKq2OmUzEzcv-eQ3M8c2U46s,348
|
79
|
+
runtime/helpers/get_auth_session_parameters.py,sha256=7bopGhJ7vjKAn_UxnHSAah-k2rVOPbq0zi9FQOOCFds,472
|
80
|
+
runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
|
+
runtime/run/__init__.py,sha256=zxMYVb7hn147YTrhMLsrcX6-KTd71HLrYHstJOWeWXQ,52
|
82
|
+
runtime/run/intuned_settings.py,sha256=vy2-ktEzUfUp5Z90dp3l7jPKHNjgB-8GSMDgAY-rYaU,1074
|
83
|
+
runtime/run/playwright_constructs.py,sha256=UZvP502fk4Hk8xtI9jMlyJ7jHLJsWt2SZyZjhet7L1A,576
|
84
|
+
runtime/run/pydantic_encoder.py,sha256=wJCljwwINSICvCJ0i2izp2RLkQ15nYglUQCyyjM40Jk,332
|
85
|
+
runtime/run/run_api.py,sha256=iYekBi-mkBuBNvLIBXQ6RWvEDN7JhjSlX3i7a2td2P8,8952
|
86
|
+
runtime/run/traces.py,sha256=fKzh11LqV47ujgq_9I2tdp-dgld566wffWaHwU_4gis,1123
|
87
|
+
runtime/types/__init__.py,sha256=IJkDfqsau8F8R_j8TO6j-JwW4ElQr6aU6LNaWRehg5U,401
|
88
|
+
runtime/types/payload.py,sha256=sty8HgDEn3nJbZrwEOMCXyuG7_ICGDwlBIIWSON5ABY,124
|
89
|
+
runtime/types/run_types.py,sha256=-j-XKXfRkzlyoW-Doe0og2jbqMMQWjOTIUqRFEc8lHA,4582
|
90
|
+
runtime_helpers/__init__.py,sha256=XBrEiE9yNC8Lgn8NgIkqNXbI6e4ap237E83Zj_nlhCQ,249
|
91
|
+
runtime_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
|
+
intuned_runtime-1.1.0.dist-info/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
|
93
|
+
intuned_runtime-1.1.0.dist-info/METADATA,sha256=SO-KZ2dpNlLDzqEQBZcOMC8_oie3r2wyw2D9ZSigXWQ,5217
|
94
|
+
intuned_runtime-1.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
95
|
+
intuned_runtime-1.1.0.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
|
96
|
+
intuned_runtime-1.1.0.dist-info/RECORD,,
|
runtime/__init__.py
CHANGED
@@ -32,11 +32,6 @@ async def call_backend_function[T: BaseModel](
|
|
32
32
|
# todo
|
33
33
|
raise Exception("No run context found.")
|
34
34
|
|
35
|
-
auth_session_id = context.run_context.auth_session_id
|
36
|
-
if auth_session_id is None:
|
37
|
-
# todo
|
38
|
-
raise Exception("No auth session ID found.")
|
39
|
-
|
40
35
|
async with AsyncClient() as client:
|
41
36
|
if context.functions_token:
|
42
37
|
client.headers["Authorization"] = f"Bearer {context.functions_token}"
|
runtime/browser/__init__.py
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
+
import asyncio
|
1
2
|
import json
|
3
|
+
import logging
|
2
4
|
import os
|
3
|
-
import tempfile
|
4
5
|
from contextlib import asynccontextmanager
|
5
|
-
from os.path import join
|
6
6
|
from typing import Any
|
7
7
|
from typing import Optional
|
8
|
-
from typing import
|
9
|
-
|
10
|
-
import
|
11
|
-
|
12
|
-
|
13
|
-
from playwright.async_api import ProxySettings
|
8
|
+
from typing import TYPE_CHECKING
|
9
|
+
|
10
|
+
import anyio
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from playwright.async_api import ProxySettings
|
14
14
|
|
15
15
|
logger = logging.getLogger(__name__)
|
16
16
|
|
17
17
|
|
18
|
-
def get_proxy_env() -> Optional[ProxySettings]:
|
18
|
+
def get_proxy_env() -> Optional["ProxySettings"]:
|
19
19
|
server = os.getenv("PROXY_SERVER")
|
20
20
|
username = os.getenv("PROXY_USERNAME")
|
21
21
|
password = os.getenv("PROXY_PASSWORD")
|
@@ -64,12 +64,12 @@ chromium_launch_args_to_ignore = [
|
|
64
64
|
|
65
65
|
async def create_user_dir_with_preferences():
|
66
66
|
# Create a temporary directory
|
67
|
-
playwright_temp_dir =
|
68
|
-
user_dir =
|
69
|
-
default_dir =
|
67
|
+
playwright_temp_dir = anyio.Path(await anyio.mkdtemp(prefix="pw-"))
|
68
|
+
user_dir = playwright_temp_dir / "userdir"
|
69
|
+
default_dir = user_dir / "Default"
|
70
70
|
|
71
71
|
# Create the default directory recursively
|
72
|
-
|
72
|
+
await default_dir.mkdir(parents=True, exist_ok=True)
|
73
73
|
|
74
74
|
# Preferences data
|
75
75
|
preferences = {
|
@@ -79,10 +79,10 @@ async def create_user_dir_with_preferences():
|
|
79
79
|
}
|
80
80
|
|
81
81
|
# Write preferences to file
|
82
|
-
async with
|
82
|
+
async with await (default_dir / "Preferences").open("w") as f:
|
83
83
|
await f.write(json.dumps(preferences))
|
84
84
|
|
85
|
-
return
|
85
|
+
return await user_dir.absolute(), await playwright_temp_dir.absolute()
|
86
86
|
|
87
87
|
|
88
88
|
extra_args = [
|
@@ -95,7 +95,9 @@ extra_args = [
|
|
95
95
|
"--disable-blink-features=AutomationControlled",
|
96
96
|
]
|
97
97
|
|
98
|
-
default_user_agent =
|
98
|
+
default_user_agent = (
|
99
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
|
100
|
+
)
|
99
101
|
|
100
102
|
|
101
103
|
@asynccontextmanager
|
@@ -105,13 +107,17 @@ async def launch_chromium(
|
|
105
107
|
cdp_address: str | None = None,
|
106
108
|
**kwargs: Any,
|
107
109
|
):
|
110
|
+
from playwright.async_api import async_playwright
|
111
|
+
from playwright.async_api import Browser
|
112
|
+
|
108
113
|
async with async_playwright() as playwright:
|
109
114
|
if cdp_address is not None:
|
110
115
|
browser: Browser = await playwright.chromium.connect_over_cdp(cdp_address)
|
111
116
|
context = browser.contexts[0]
|
112
|
-
|
117
|
+
user_preferences_dir = None
|
118
|
+
dir_to_clean = None
|
113
119
|
else:
|
114
|
-
|
120
|
+
user_preferences_dir, dir_to_clean = await create_user_dir_with_preferences()
|
115
121
|
if kwargs.get("proxy") is None:
|
116
122
|
proxy_env = get_proxy_env()
|
117
123
|
else:
|
@@ -126,7 +132,7 @@ async def launch_chromium(
|
|
126
132
|
extra_args.append("--headless=new")
|
127
133
|
|
128
134
|
context = await playwright.chromium.launch_persistent_context(
|
129
|
-
|
135
|
+
os.fspath(user_preferences_dir),
|
130
136
|
headless=headless,
|
131
137
|
viewport=viewport,
|
132
138
|
proxy=proxy_env,
|
@@ -138,9 +144,19 @@ async def launch_chromium(
|
|
138
144
|
context.set_default_timeout(timeout * 1000)
|
139
145
|
|
140
146
|
async def remove_dir_after_close(*_: Any, **__: Any) -> None:
|
141
|
-
if not
|
147
|
+
if not dir_to_clean:
|
148
|
+
return
|
149
|
+
if not await dir_to_clean.exists():
|
142
150
|
return
|
143
|
-
|
151
|
+
|
152
|
+
process = await asyncio.create_subprocess_exec(
|
153
|
+
"rm",
|
154
|
+
"-rf",
|
155
|
+
os.fspath(dir_to_clean), # Using subprocess to remove the directory
|
156
|
+
stdout=asyncio.subprocess.DEVNULL,
|
157
|
+
stderr=asyncio.subprocess.DEVNULL,
|
158
|
+
)
|
159
|
+
await process.wait()
|
144
160
|
|
145
161
|
context.once("close", remove_dir_after_close)
|
146
162
|
yield context, context.pages[0]
|
@@ -149,31 +165,25 @@ async def launch_chromium(
|
|
149
165
|
async def dangerous_launch_chromium(
|
150
166
|
headless: bool = True,
|
151
167
|
timeout: int = 10,
|
152
|
-
web_socket: str | None = None,
|
153
168
|
cdp_url: str | None = None,
|
154
|
-
|
169
|
+
port: int | None = None,
|
155
170
|
**kwargs: Any,
|
156
171
|
):
|
172
|
+
from playwright.async_api import async_playwright
|
173
|
+
from playwright.async_api import Browser
|
174
|
+
|
157
175
|
playwright = await async_playwright().start()
|
158
|
-
if
|
159
|
-
logging.info(f"Connecting to ws: {web_socket}")
|
160
|
-
browser: Browser = await playwright.chromium.connect(web_socket)
|
161
|
-
browser.on("disconnected", lambda: logging.info("Browser Session disconnected"))
|
162
|
-
await browser.new_context(
|
163
|
-
viewport={"width": 1280, "height": 800}, user_agent=default_user_agent
|
164
|
-
)
|
165
|
-
context = browser.contexts[0]
|
166
|
-
dir = None
|
167
|
-
elif cdp_url is not None and connection_method == "cdp":
|
176
|
+
if cdp_url is not None:
|
168
177
|
logging.info(f"Connecting to cdp: {cdp_url}")
|
169
178
|
browser: Browser = await playwright.chromium.connect_over_cdp(cdp_url)
|
170
|
-
browser.on("disconnected", lambda: logging.info("Browser Session disconnected"))
|
179
|
+
browser.on("disconnected", lambda _: logging.info("Browser Session disconnected"))
|
171
180
|
context = browser.contexts[0]
|
172
|
-
|
173
|
-
|
181
|
+
user_preferences_dir = None
|
182
|
+
dir_to_clean = None
|
183
|
+
else:
|
174
184
|
logging.info("Launching local browser")
|
175
|
-
|
176
|
-
logging.info(f"Using user data directory: {
|
185
|
+
user_preferences_dir, dir_to_clean = await create_user_dir_with_preferences()
|
186
|
+
logging.info(f"Using user data directory: {user_preferences_dir}")
|
177
187
|
if kwargs.get("proxy") is None:
|
178
188
|
proxy_env = get_proxy_env()
|
179
189
|
else:
|
@@ -187,8 +197,11 @@ async def dangerous_launch_chromium(
|
|
187
197
|
chromium_launch_args_to_ignore.append("--headless")
|
188
198
|
extra_args.append("--headless=new")
|
189
199
|
|
200
|
+
if port:
|
201
|
+
extra_args.append(f"--remote-debugging-port={port}")
|
202
|
+
|
190
203
|
context = await playwright.chromium.launch_persistent_context(
|
191
|
-
|
204
|
+
os.fspath(user_preferences_dir),
|
192
205
|
headless=headless,
|
193
206
|
viewport=viewport,
|
194
207
|
proxy=proxy_env,
|
@@ -197,16 +210,22 @@ async def dangerous_launch_chromium(
|
|
197
210
|
args=extra_args,
|
198
211
|
**kwargs,
|
199
212
|
)
|
200
|
-
|
201
|
-
raise ValueError(
|
202
|
-
"You have to provide method if you are launching a remote browser with ws or cdp"
|
203
|
-
)
|
204
|
-
context.set_default_timeout(timeout * 1000)
|
213
|
+
context.set_default_timeout(timeout * 1000)
|
205
214
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
215
|
+
async def remove_dir_after_close(*_: Any, **__: Any) -> None:
|
216
|
+
if not dir_to_clean:
|
217
|
+
return
|
218
|
+
if not await dir_to_clean.exists():
|
219
|
+
return
|
210
220
|
|
211
|
-
|
221
|
+
process = await asyncio.create_subprocess_exec(
|
222
|
+
"rm",
|
223
|
+
"-rf",
|
224
|
+
os.fspath(dir_to_clean), # Using subprocess to remove the directory
|
225
|
+
stdout=asyncio.subprocess.DEVNULL,
|
226
|
+
stderr=asyncio.subprocess.DEVNULL,
|
227
|
+
)
|
228
|
+
await process.wait()
|
229
|
+
|
230
|
+
context.once("close", remove_dir_after_close)
|
212
231
|
return playwright, context
|
runtime/browser/storage_state.py
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
from typing import Any
|
2
|
+
from typing import TYPE_CHECKING
|
2
3
|
|
3
|
-
|
4
|
-
from playwright.async_api import
|
4
|
+
if TYPE_CHECKING:
|
5
|
+
from playwright.async_api import BrowserContext
|
6
|
+
|
7
|
+
import logging
|
5
8
|
|
6
9
|
from ..types.run_types import Cookie
|
7
10
|
from ..types.run_types import Origin
|
8
11
|
from ..types.run_types import SessionStorageOrigin
|
9
12
|
from ..types.run_types import StorageState
|
10
13
|
|
11
|
-
import logging
|
12
|
-
|
13
14
|
logger = logging.getLogger(__name__)
|
14
15
|
|
15
16
|
|
16
|
-
async def set_storage_state(context: BrowserContext, state: StorageState):
|
17
|
+
async def set_storage_state(context: "BrowserContext", state: StorageState):
|
17
18
|
# Add cookies if they exist
|
18
|
-
await context.add_cookies(
|
19
|
-
[cookie.model_dump(by_alias=True) for cookie in state.cookies]
|
20
|
-
) # type: ignore
|
19
|
+
await context.add_cookies([cookie.model_dump(by_alias=True) for cookie in state.cookies]) # type: ignore
|
21
20
|
|
22
21
|
# Apply localStorage for each origin
|
23
22
|
page = await context.new_page()
|
@@ -67,7 +66,9 @@ async def set_storage_state(context: BrowserContext, state: StorageState):
|
|
67
66
|
await page.close()
|
68
67
|
|
69
68
|
|
70
|
-
async def get_storage_state(context: BrowserContext) -> StorageState:
|
69
|
+
async def get_storage_state(context: "BrowserContext") -> StorageState:
|
70
|
+
from playwright.async_api import Error as PlaywrightError
|
71
|
+
|
71
72
|
storage_state = await context.storage_state()
|
72
73
|
cookies = storage_state.get("cookies") or []
|
73
74
|
origins = storage_state.get("origins") or []
|
@@ -92,9 +93,7 @@ async def get_storage_state(context: BrowserContext) -> StorageState:
|
|
92
93
|
session_storage.append(SessionStorageOrigin(**session_data))
|
93
94
|
except PlaywrightError as e:
|
94
95
|
if "SecurityError" in e.message:
|
95
|
-
logger.warning(
|
96
|
-
f"Could not get storage state for page due '{page.url}' to security error."
|
97
|
-
)
|
96
|
+
logger.warning(f"Could not get storage state for page due '{page.url}' to security error.")
|
98
97
|
continue
|
99
98
|
raise e
|
100
99
|
|
runtime/errors/run_api_errors.py
CHANGED
@@ -66,22 +66,30 @@ class AutomationNotCoroutineError(RunApiError):
|
|
66
66
|
|
67
67
|
|
68
68
|
class AutomationError(RunApiError):
|
69
|
-
|
69
|
+
_error: BaseException
|
70
|
+
|
71
|
+
def __init__(self, error: BaseException):
|
70
72
|
# Get all public attributes of the exception
|
71
|
-
error_props = {key: str(value) for key, value in
|
73
|
+
error_props = {key: str(value) for key, value in error.__dict__.items() if not key.startswith("_")}
|
72
74
|
|
73
75
|
super().__init__(
|
74
|
-
str(
|
76
|
+
str(error),
|
75
77
|
"AutomationError",
|
76
78
|
)
|
77
79
|
|
80
|
+
self._error = error
|
81
|
+
|
78
82
|
self.details = {
|
79
83
|
"error_props": error_props,
|
80
|
-
"error_type":
|
81
|
-
"name":
|
82
|
-
"message": str(
|
84
|
+
"error_type": error.__class__.__name__,
|
85
|
+
"name": error.__class__.__name__,
|
86
|
+
"message": str(error),
|
83
87
|
}
|
84
88
|
|
89
|
+
@property
|
90
|
+
def error(self) -> BaseException:
|
91
|
+
return self._error
|
92
|
+
|
85
93
|
|
86
94
|
class AutomationTimeoutError(RunApiError):
|
87
95
|
def __init__(self):
|
@@ -111,10 +119,6 @@ class InternalInvalidInputError(RunApiError):
|
|
111
119
|
def __init__(self, message: str, details: Any | None = None):
|
112
120
|
super().__init__(
|
113
121
|
f"Internal error: {message}. Please report this issue to the Intuned team.",
|
114
|
-
RunApiResponse(
|
115
|
-
status_code=500,
|
116
|
-
response={"error": "Internal error", "message": f"Internal error: {message}"},
|
117
|
-
),
|
118
122
|
"InternalInvalidInputError",
|
119
123
|
)
|
120
124
|
self.details = details
|