intuned-runtime 1.3.2__py3-none-any.whl → 1.3.4__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.
Potentially problematic release.
This version of intuned-runtime might be problematic. Click here for more details.
- intuned_cli/commands/__init__.py +1 -1
- intuned_cli/commands/attempt_api_command.py +0 -2
- intuned_cli/commands/attempt_authsession_check_command.py +0 -2
- intuned_cli/commands/attempt_authsession_command.py +0 -3
- intuned_cli/commands/attempt_authsession_create_command.py +0 -2
- intuned_cli/commands/attempt_command.py +0 -3
- intuned_cli/commands/authsession_command.py +0 -3
- intuned_cli/commands/authsession_record_command.py +0 -2
- intuned_cli/commands/command.py +0 -3
- intuned_cli/commands/deploy_command.py +0 -3
- intuned_cli/commands/init_command.py +0 -3
- intuned_cli/commands/run_api_command.py +0 -2
- intuned_cli/commands/run_authsession_command.py +0 -3
- intuned_cli/commands/run_authsession_create_command.py +2 -5
- intuned_cli/commands/run_authsession_update_command.py +3 -6
- intuned_cli/commands/run_authsession_validate_command.py +2 -5
- intuned_cli/commands/run_command.py +0 -3
- intuned_cli/commands/save_command.py +0 -3
- intuned_cli/controller/deploy.py +0 -2
- intuned_cli/controller/save.py +0 -18
- intuned_cli/utils/wrapper.py +13 -3
- intuned_internal_cli/commands/__init__.py +8 -16
- intuned_internal_cli/commands/browser/__init__.py +1 -1
- intuned_internal_cli/commands/browser/save_state.py +2 -3
- intuned_internal_cli/commands/project/__init__.py +7 -9
- intuned_internal_cli/commands/project/auth_session/__init__.py +3 -3
- intuned_internal_cli/commands/project/auth_session/check.py +2 -2
- intuned_internal_cli/commands/project/auth_session/create.py +2 -3
- intuned_internal_cli/commands/project/auth_session/load.py +2 -3
- intuned_internal_cli/commands/project/project.py +2 -2
- intuned_internal_cli/commands/project/run.py +2 -2
- intuned_internal_cli/commands/project/run_interface.py +75 -8
- intuned_internal_cli/commands/project/type_check.py +5 -5
- intuned_internal_cli/commands/root.py +2 -1
- intuned_internal_cli/utils/wrapper.py +15 -0
- {intuned_runtime-1.3.2.dist-info → intuned_runtime-1.3.4.dist-info}/METADATA +1 -1
- {intuned_runtime-1.3.2.dist-info → intuned_runtime-1.3.4.dist-info}/RECORD +45 -49
- runtime/browser/launch_browser.py +15 -0
- runtime/browser/launch_chromium.py +10 -1
- runtime/run/types.py +0 -5
- runtime/types/settings_types.py +12 -4
- runtime/utils/anyio.py +26 -0
- intuned_internal_cli/commands/ai_source/__init__.py +0 -4
- intuned_internal_cli/commands/ai_source/ai_source.py +0 -10
- intuned_internal_cli/commands/ai_source/deploy.py +0 -64
- intuned_internal_cli/commands/init.py +0 -127
- intuned_internal_cli/commands/project/upgrade.py +0 -92
- intuned_internal_cli/commands/publish_packages.py +0 -264
- {intuned_runtime-1.3.2.dist-info → intuned_runtime-1.3.4.dist-info}/WHEEL +0 -0
- {intuned_runtime-1.3.2.dist-info → intuned_runtime-1.3.4.dist-info}/entry_points.txt +0 -0
- {intuned_runtime-1.3.2.dist-info → intuned_runtime-1.3.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,18 +2,21 @@ import asyncio
|
|
|
2
2
|
import os
|
|
3
3
|
import signal
|
|
4
4
|
import socket
|
|
5
|
+
import sys
|
|
5
6
|
import time
|
|
6
7
|
from collections.abc import AsyncGenerator
|
|
8
|
+
from pathlib import Path
|
|
7
9
|
from typing import Any
|
|
8
10
|
from typing import cast
|
|
9
11
|
from typing import Literal
|
|
10
12
|
|
|
11
|
-
import arguably
|
|
12
13
|
from pydantic import Field
|
|
13
14
|
from pydantic import ValidationError
|
|
14
15
|
|
|
16
|
+
from intuned_internal_cli.utils.wrapper import internal_cli_command
|
|
15
17
|
from runtime.backend_functions import get_auth_session_parameters
|
|
16
18
|
from runtime.context import IntunedContext
|
|
19
|
+
from runtime.errors.run_api_errors import ApiNotFoundError
|
|
17
20
|
from runtime.errors.run_api_errors import InternalInvalidInputError
|
|
18
21
|
from runtime.errors.run_api_errors import RunApiError
|
|
19
22
|
from runtime.run.run_api import import_function_from_api_dir
|
|
@@ -69,15 +72,18 @@ class MessageWrapper(CamelBaseModel):
|
|
|
69
72
|
)
|
|
70
73
|
|
|
71
74
|
|
|
72
|
-
@
|
|
75
|
+
@internal_cli_command
|
|
73
76
|
async def project__run_interface(
|
|
74
77
|
socket_path: str,
|
|
78
|
+
*,
|
|
79
|
+
jsonl: bool = False,
|
|
75
80
|
):
|
|
76
81
|
"""
|
|
77
82
|
Runs the current project. Project must contain an "api" directory with API functions.
|
|
78
83
|
|
|
79
84
|
Args:
|
|
80
85
|
socket_path (str): Path to the socket file.
|
|
86
|
+
jsonl (bool, optional): Use a JSONL client instead of socket. Defaults to False.
|
|
81
87
|
|
|
82
88
|
"""
|
|
83
89
|
|
|
@@ -86,7 +92,7 @@ async def project__run_interface(
|
|
|
86
92
|
raise Exception("socket_path is required")
|
|
87
93
|
|
|
88
94
|
timeout_timestamp = time.time()
|
|
89
|
-
client =
|
|
95
|
+
client = SocketClient(socket_path) if not jsonl else JSONLFileClient(socket_path)
|
|
90
96
|
connected = await client.connect()
|
|
91
97
|
if not connected:
|
|
92
98
|
raise Exception("Failed to connect to UDAS")
|
|
@@ -97,7 +103,9 @@ async def project__run_interface(
|
|
|
97
103
|
|
|
98
104
|
def done(exitCode: int = 0):
|
|
99
105
|
client.close()
|
|
100
|
-
|
|
106
|
+
loop.remove_signal_handler(signal.SIGTERM)
|
|
107
|
+
loop.remove_signal_handler(signal.SIGINT)
|
|
108
|
+
sys.exit(exitCode)
|
|
101
109
|
|
|
102
110
|
def interrupt_signal_handler():
|
|
103
111
|
async def _impl():
|
|
@@ -133,6 +141,11 @@ async def project__run_interface(
|
|
|
133
141
|
asyncio.Task[RunAutomationSuccessResult] | None, None
|
|
134
142
|
)
|
|
135
143
|
|
|
144
|
+
def import_function(file_path: str, automation_name: str | None = None):
|
|
145
|
+
return import_function_from_api_dir(
|
|
146
|
+
automation_function_name=automation_name, file_path=file_path, base_dir=os.getcwd()
|
|
147
|
+
)
|
|
148
|
+
|
|
136
149
|
async def handle_message(message: Message):
|
|
137
150
|
nonlocal run_api_task
|
|
138
151
|
if message.type == "start":
|
|
@@ -151,9 +164,7 @@ async def project__run_interface(
|
|
|
151
164
|
run_api_task = asyncio.create_task(
|
|
152
165
|
run_api(
|
|
153
166
|
message.parameters,
|
|
154
|
-
import_function=
|
|
155
|
-
automation_function_name=automation_name, file_path=file_path, base_dir=os.getcwd()
|
|
156
|
-
),
|
|
167
|
+
import_function=import_function,
|
|
157
168
|
),
|
|
158
169
|
)
|
|
159
170
|
return
|
|
@@ -191,6 +202,14 @@ async def project__run_interface(
|
|
|
191
202
|
await client.send_message({"type": "done", "success": False, "result": message.json})
|
|
192
203
|
break
|
|
193
204
|
if message.type == "ping":
|
|
205
|
+
api_files = await get_python_files_from_dir(Path() / "api")
|
|
206
|
+
apis = [f'api/{str(p.with_suffix("").as_posix())}' for p in api_files]
|
|
207
|
+
|
|
208
|
+
for api in [*apis, "auth-sessions/create", "auth-sessions/check"]:
|
|
209
|
+
try:
|
|
210
|
+
import_function(api)
|
|
211
|
+
except ApiNotFoundError:
|
|
212
|
+
pass
|
|
194
213
|
await client.send_message({"type": "pong"})
|
|
195
214
|
break
|
|
196
215
|
await handle_message(message)
|
|
@@ -231,7 +250,7 @@ async def project__run_interface(
|
|
|
231
250
|
done()
|
|
232
251
|
|
|
233
252
|
|
|
234
|
-
class
|
|
253
|
+
class SocketClient:
|
|
235
254
|
def __init__(self, socket_path: str):
|
|
236
255
|
self.socket_path = socket_path
|
|
237
256
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
@@ -263,3 +282,51 @@ class UDASClient:
|
|
|
263
282
|
return
|
|
264
283
|
self.sock.shutdown(socket.SHUT_RDWR)
|
|
265
284
|
self.sock.close()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class JSONLFileClient(SocketClient):
|
|
288
|
+
def __init__(self, socket_path: str):
|
|
289
|
+
self.socket_path = socket_path
|
|
290
|
+
self.fp = None
|
|
291
|
+
|
|
292
|
+
async def connect(self):
|
|
293
|
+
if not os.path.exists(self.socket_path):
|
|
294
|
+
return False
|
|
295
|
+
self.fp = open(self.socket_path, "r+b", buffering=0)
|
|
296
|
+
return True
|
|
297
|
+
|
|
298
|
+
def receive_messages(self) -> AsyncGenerator[dict[str, Any], None]:
|
|
299
|
+
import json
|
|
300
|
+
|
|
301
|
+
async def generator():
|
|
302
|
+
if self.fp is None:
|
|
303
|
+
raise Exception("Socket not connected")
|
|
304
|
+
while True:
|
|
305
|
+
line = self.fp.readline()
|
|
306
|
+
if not line:
|
|
307
|
+
break
|
|
308
|
+
yield json.loads(line.decode("utf-8"))
|
|
309
|
+
|
|
310
|
+
return generator()
|
|
311
|
+
|
|
312
|
+
async def send_message(self, message: dict[str, Any]):
|
|
313
|
+
print("Sending message", message)
|
|
314
|
+
|
|
315
|
+
def close(self):
|
|
316
|
+
if not self.fp:
|
|
317
|
+
return
|
|
318
|
+
self.fp.close()
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
async def get_python_files_from_dir(dir: Path) -> list[Path]:
|
|
322
|
+
"""Get all Python files under a directory, returning relative paths."""
|
|
323
|
+
python_files: list[Path] = []
|
|
324
|
+
|
|
325
|
+
file_tree = await asyncio.to_thread(os.walk, dir)
|
|
326
|
+
for root, _, files in file_tree:
|
|
327
|
+
for file in files:
|
|
328
|
+
if file.endswith(".py"):
|
|
329
|
+
full_path = Path(root) / file
|
|
330
|
+
relative_path = full_path.relative_to(dir)
|
|
331
|
+
python_files.append(relative_path)
|
|
332
|
+
return python_files
|
|
@@ -2,15 +2,15 @@ import json
|
|
|
2
2
|
import os
|
|
3
3
|
import subprocess
|
|
4
4
|
import sys
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
|
-
import
|
|
7
|
+
from intuned_internal_cli.utils.wrapper import internal_cli_command
|
|
7
8
|
|
|
8
9
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
-
PYRIGHT_CONFIG_PATH = os.path.join(current_dir, "..", "..", "pyright_type_check.json")
|
|
10
|
-
PYRIGHT_CONFIG_PATH = os.path.abspath(PYRIGHT_CONFIG_PATH)
|
|
10
|
+
PYRIGHT_CONFIG_PATH = os.path.abspath(os.path.join(current_dir, "..", "..", "pyright_type_check.json"))
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@
|
|
13
|
+
@internal_cli_command
|
|
14
14
|
async def project__type_check():
|
|
15
15
|
"""
|
|
16
16
|
Run type checking on the API directory using pyright.
|
|
@@ -39,7 +39,7 @@ async def project__type_check():
|
|
|
39
39
|
print("📦 Checking Types...")
|
|
40
40
|
|
|
41
41
|
try:
|
|
42
|
-
pyright_issues = []
|
|
42
|
+
pyright_issues: list[dict[str, Any]] = []
|
|
43
43
|
pyright_result = subprocess.run(
|
|
44
44
|
["pyright", "--outputjson", project_dir, "--project", PYRIGHT_CONFIG_PATH],
|
|
45
45
|
capture_output=True,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from collections.abc import Awaitable
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import ParamSpec
|
|
4
|
+
from typing import TypeVar
|
|
5
|
+
|
|
6
|
+
import arguably
|
|
7
|
+
|
|
8
|
+
from runtime.utils.anyio import run_sync
|
|
9
|
+
|
|
10
|
+
P = ParamSpec("P")
|
|
11
|
+
R = TypeVar("R")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def internal_cli_command(fn: Callable[P, R | Awaitable[R]]) -> Callable[P, R]:
|
|
15
|
+
return arguably.command(run_sync(fn)) # type: ignore
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
intuned_cli/__init__.py,sha256=00r4AkrKFEzybNb4LWRZGSi3evyX9adVC6LoFItP5Ls,1208
|
|
2
|
-
intuned_cli/commands/__init__.py,sha256=
|
|
3
|
-
intuned_cli/commands/attempt_api_command.py,sha256=
|
|
4
|
-
intuned_cli/commands/attempt_authsession_check_command.py,sha256=
|
|
5
|
-
intuned_cli/commands/attempt_authsession_command.py,sha256=
|
|
6
|
-
intuned_cli/commands/attempt_authsession_create_command.py,sha256=
|
|
7
|
-
intuned_cli/commands/attempt_command.py,sha256=
|
|
8
|
-
intuned_cli/commands/authsession_command.py,sha256=
|
|
9
|
-
intuned_cli/commands/authsession_record_command.py,sha256=
|
|
10
|
-
intuned_cli/commands/command.py,sha256=
|
|
11
|
-
intuned_cli/commands/deploy_command.py,sha256=
|
|
12
|
-
intuned_cli/commands/init_command.py,sha256=
|
|
13
|
-
intuned_cli/commands/run_api_command.py,sha256=
|
|
14
|
-
intuned_cli/commands/run_authsession_command.py,sha256=
|
|
15
|
-
intuned_cli/commands/run_authsession_create_command.py,sha256=
|
|
16
|
-
intuned_cli/commands/run_authsession_update_command.py,sha256=
|
|
17
|
-
intuned_cli/commands/run_authsession_validate_command.py,sha256=
|
|
18
|
-
intuned_cli/commands/run_command.py,sha256
|
|
19
|
-
intuned_cli/commands/save_command.py,sha256=
|
|
2
|
+
intuned_cli/commands/__init__.py,sha256=Z-a4JJmc67fqHW9bVML15MO1X8YPeHn-SIC_YBSsAP0,1781
|
|
3
|
+
intuned_cli/commands/attempt_api_command.py,sha256=bs_Sgyo1AxX-y3q-hWXD8lhXxdaAW8mPF8s0GfUK2oQ,2351
|
|
4
|
+
intuned_cli/commands/attempt_authsession_check_command.py,sha256=SZ_PvTi_Tsiyz_UPHhsPelH2oiAdwvIA90YNIotLZfw,1731
|
|
5
|
+
intuned_cli/commands/attempt_authsession_command.py,sha256=SqzeaTRz6d2Z2uantxnNaxlr9fAJNlSDTzkfKuAgzMQ,231
|
|
6
|
+
intuned_cli/commands/attempt_authsession_create_command.py,sha256=U8xBdkfkMzma_KKR7-m9p2klqg-BJul1RVei88h82Xo,2120
|
|
7
|
+
intuned_cli/commands/attempt_command.py,sha256=yLL9qxaPQJ9PjzNg95NUkghtf7Z6-EHujhcU8jyJY3I,207
|
|
8
|
+
intuned_cli/commands/authsession_command.py,sha256=0XMkiKfNIzwudVw99S5JhiJOYKiQ6CcQRpSHWGpj2GM,203
|
|
9
|
+
intuned_cli/commands/authsession_record_command.py,sha256=UR_sVTl6AgkTgXedasLa3RrQU189OfuwkA7dK-E1d8k,2373
|
|
10
|
+
intuned_cli/commands/command.py,sha256=IYvFDCxA-ioLrZNQVh7t-7Zi_9bNELQs-J2m9onyNFY,764
|
|
11
|
+
intuned_cli/commands/deploy_command.py,sha256=IJLxvmXuR0R0aBiYDRCZUK1XTWM0U0rIYRqfaetvX9k,1561
|
|
12
|
+
intuned_cli/commands/init_command.py,sha256=HHjwC20LshW1frbUncC4bH3GPh5cL6nzLQq7LThs9LY,504
|
|
13
|
+
intuned_cli/commands/run_api_command.py,sha256=CbXALVcsqI4HP-gcjR--6szrQdqhfw7Dc43QPLPjL00,3401
|
|
14
|
+
intuned_cli/commands/run_authsession_command.py,sha256=5-1a3q_0PuzAoEUEmnr9HBf5HTqkaUzzrssJG4vIa9g,223
|
|
15
|
+
intuned_cli/commands/run_authsession_create_command.py,sha256=YyzNJquHc9wsng1Pa7csmjmilRdgMP57gi_yjAPcQ4c,3158
|
|
16
|
+
intuned_cli/commands/run_authsession_update_command.py,sha256=GpRu3MvTOp-U5nl9oCYNuLvk9G3KvPORIBSfBHtVAFc,3211
|
|
17
|
+
intuned_cli/commands/run_authsession_validate_command.py,sha256=6bUl2FRR19b7_jAKuAENuO-ih_ygbBU_hg7fyM3Dgc8,3064
|
|
18
|
+
intuned_cli/commands/run_command.py,sha256=-ayHF-noiDsnIobbszAz4JEpIEZh-lf8fAWK0CoxiIU,199
|
|
19
|
+
intuned_cli/commands/save_command.py,sha256=H1X3SrRTBHCWiVr7PG94n-MIbW_bPtQWJaWrVvTk-5Y,1555
|
|
20
20
|
intuned_cli/controller/__test__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
intuned_cli/controller/__test__/test_api.py,sha256=CgPUTsdQZ6r4it8yU1JG96TiN1WKyeUMh__7UICg36k,24489
|
|
22
22
|
intuned_cli/controller/__test__/test_authsession.py,sha256=fvkqm1B39kAxgb1iLXs4WlcVNzn3P6hvlvNS4IrdBgQ,52491
|
|
23
23
|
intuned_cli/controller/api.py,sha256=GDBSn7J0567ziBLNEk6tiguUDLwUTvDU6kmMqifYKMQ,7511
|
|
24
24
|
intuned_cli/controller/authsession.py,sha256=rx5qRaKp4ED3OArD8_qCDGjKqgy1Pc5s9YYfm6bxe-I,18688
|
|
25
|
-
intuned_cli/controller/deploy.py,sha256=
|
|
26
|
-
intuned_cli/controller/save.py,sha256=
|
|
25
|
+
intuned_cli/controller/deploy.py,sha256=nmXIWTunPMqx_fcuFhbstWVQiIhCnI3bkJ4oMVBZQH8,5436
|
|
26
|
+
intuned_cli/controller/save.py,sha256=LxIu6IznmTvAC5OpEQcnq1TnxYG6aCNBBdvmyVYs_Zg,8850
|
|
27
27
|
intuned_cli/types.py,sha256=1BKCukVvn2i37-onpZ9rFLrcVh4kWW_ui0DzOIKugtI,704
|
|
28
28
|
intuned_cli/utils/__test__/test_browser.py,sha256=NCv7OplirDxAjBpnfZharOa5O0fVNWA9xU3I1GVWB5M,4474
|
|
29
29
|
intuned_cli/utils/__test__/test_traces.py,sha256=4EfzwizBt7VT9-dANMdBYFKQTPzPWMDnodSVyT5F4dY,901
|
|
@@ -40,33 +40,28 @@ intuned_cli/utils/help.py,sha256=NKTQCzaIINQsGHljJH68HemAVThbkKU3IQfxyRyVaD0,223
|
|
|
40
40
|
intuned_cli/utils/import_function.py,sha256=UmE2yw5std1ENMFdBU-TUBuQ01qsv7Qr5ElnAhqE6Yc,453
|
|
41
41
|
intuned_cli/utils/timeout.py,sha256=DkoeoU9XvKKKSQ06CpwqcNvxWqLPAOVuAMw6kSr4Tuo,886
|
|
42
42
|
intuned_cli/utils/traces.py,sha256=Du_FnvSq-StLsAIQKSNyNSwkoMS-J93Tb6Ln4QgXVTE,793
|
|
43
|
-
intuned_cli/utils/wrapper.py,sha256=
|
|
43
|
+
intuned_cli/utils/wrapper.py,sha256=MRLtDhZLxQlOd0C44JrGV_WZJ3xbtZFaSsBTZGtd-oY,2269
|
|
44
44
|
intuned_internal_cli/__init__.py,sha256=bcL7-SPWCE0SmszoBoEvcyf-wAGRHAzIRe7vlCq3NPA,1760
|
|
45
|
-
intuned_internal_cli/commands/__init__.py,sha256=
|
|
46
|
-
intuned_internal_cli/commands/
|
|
47
|
-
intuned_internal_cli/commands/
|
|
48
|
-
intuned_internal_cli/commands/
|
|
49
|
-
intuned_internal_cli/commands/
|
|
50
|
-
intuned_internal_cli/commands/
|
|
51
|
-
intuned_internal_cli/commands/
|
|
52
|
-
intuned_internal_cli/commands/project/
|
|
53
|
-
intuned_internal_cli/commands/project/
|
|
54
|
-
intuned_internal_cli/commands/project/
|
|
55
|
-
intuned_internal_cli/commands/project/
|
|
56
|
-
intuned_internal_cli/commands/project/
|
|
57
|
-
intuned_internal_cli/commands/
|
|
58
|
-
intuned_internal_cli/commands/project/run.py,sha256=7lqrFrTOaW0W5UF6WTVwwDauAoGbABNv6RVQ6_DEIfQ,12209
|
|
59
|
-
intuned_internal_cli/commands/project/run_interface.py,sha256=4RyR8WZriIF7Va4z1wt-q6zZDQOI31n62Ho2dyimzUY,8717
|
|
60
|
-
intuned_internal_cli/commands/project/type_check.py,sha256=QFnXL93Y-z250EQRln5sRqwkVqjGJ-eP_p1jGrXB7NA,3522
|
|
61
|
-
intuned_internal_cli/commands/project/upgrade.py,sha256=XmkZLflM4O-mwvhwcswlZpazRotwi3xesLgE0Zz8fTI,3061
|
|
62
|
-
intuned_internal_cli/commands/publish_packages.py,sha256=sijkaG7_s0I1EWgLekGy1qm8Aqi_gYY8poXbMX0B6Yw,10505
|
|
63
|
-
intuned_internal_cli/commands/root.py,sha256=o75rSb5WYa5JMD8HLN3eiNu4fM0mar3y15A63-Qm4s4,426
|
|
45
|
+
intuned_internal_cli/commands/__init__.py,sha256=WUC40iBg5ONoVFjhpLXMrNwgVVbmooUCT0Bm9tl8GAg,589
|
|
46
|
+
intuned_internal_cli/commands/browser/__init__.py,sha256=lFuoW-OysNTN8Toe4sy1rEZmnnfQSKPKtoFRFEmBMKc,79
|
|
47
|
+
intuned_internal_cli/commands/browser/save_state.py,sha256=sKVQ5558IYLNlNVokMvVrJcy7zlL5YZ9HvM9D6K4yZ4,878
|
|
48
|
+
intuned_internal_cli/commands/project/__init__.py,sha256=KJANCr-wxgCd0Fu4NQC0IYzApdU5hl3dVYIDekGhiKg,544
|
|
49
|
+
intuned_internal_cli/commands/project/auth_session/__init__.py,sha256=pjBR6l3NOhSByXG2xM6FpdveWzPj0Lg8-rfJ28VD2KM,252
|
|
50
|
+
intuned_internal_cli/commands/project/auth_session/check.py,sha256=TbEwndBRn04dc2dZsLLqO6hBXbCYfa6V9Hxn9Ia8MBo,4564
|
|
51
|
+
intuned_internal_cli/commands/project/auth_session/create.py,sha256=MG0JVJvEm0pFiQbMogqveOv1bs4STZKGhVt_rmHNB4Q,3413
|
|
52
|
+
intuned_internal_cli/commands/project/auth_session/load.py,sha256=lnW0CDODe9Bvo05zuTZQVqYUbANDNMYhyQBIkI2g_aQ,1238
|
|
53
|
+
intuned_internal_cli/commands/project/project.py,sha256=69XKffH5K4Y2xhWhUdSmYG9CR9E_qp_-3RZXG-v7fdE,177
|
|
54
|
+
intuned_internal_cli/commands/project/run.py,sha256=rJHY9lTKnk2tr7rWjLaCFdeHniM3YsDRF7n1fk4TOf8,12249
|
|
55
|
+
intuned_internal_cli/commands/project/run_interface.py,sha256=sMm74YpqufBThxOxT9RDd2zJjFfkuR6UXG7rDcR3_ZE,11011
|
|
56
|
+
intuned_internal_cli/commands/project/type_check.py,sha256=VYqbtnvD9UpiyP8qCW5fLx52PKIj66Rw_ZD7Xe9HWtw,3565
|
|
57
|
+
intuned_internal_cli/commands/root.py,sha256=HLW2JWAt_5y9rGB8iaciAY4w94krF2v1AwxS_n4y1h0,440
|
|
64
58
|
intuned_internal_cli/logger.py,sha256=bZK3q-KUdGxk_qzDb6pn-n0LOhKJvi6a9p8oSwZtq3s,594
|
|
65
59
|
intuned_internal_cli/utils/ai_source_project.py,sha256=xUCM6p3i1XN4bJbuQz8LCzeI4BwqAdSvCl_vwDAEi0k,831
|
|
66
60
|
intuned_internal_cli/utils/code_tree.py,sha256=1wfxZoQ5kRCfqs2SEPAicbAIPTiD6P1LxSuwYu_eeaI,2790
|
|
67
61
|
intuned_internal_cli/utils/run_apis.py,sha256=Zee4zkgt9R8XY1XCGzj2Nc4zJ3jlRz1xnO493wotuWw,4690
|
|
68
62
|
intuned_internal_cli/utils/setup_ide_functions_token.py,sha256=72-hf5HOPO9hj_eo3MTSVEPIwtkaIma_NRepsw_FHQM,304
|
|
69
63
|
intuned_internal_cli/utils/unix_socket.py,sha256=UISmkJMHrir5iBLUm6vxC3uzTGIFyOk_wa0C9LUw4Cc,1889
|
|
64
|
+
intuned_internal_cli/utils/wrapper.py,sha256=Y0yAs2XrDHChUMUsEYcRT0AbSkZCfdgAvZs0Sdrbirg,366
|
|
70
65
|
intuned_runtime/__init__.py,sha256=1BPzEc-qC2WAYiCWDOJChpgnFyO3ZNYRKHEZqdHUGwM,322
|
|
71
66
|
runtime/__init__.py,sha256=87gDXuxUv_kGzQfuB1mh6DF-dDysJN8r684c7jGnHxc,144
|
|
72
67
|
runtime/backend_functions/__init__.py,sha256=j2EaK4FK8bmdFtqc5FxtFwx1KhIn_7qKPChrrAhJI3s,119
|
|
@@ -77,9 +72,9 @@ runtime/browser/extensions/__init__.py,sha256=VGUFvkYUwuYc9UlYy1TD79veXuDhnLDcmb
|
|
|
77
72
|
runtime/browser/extensions/helpers.py,sha256=W3XiOf66J_xWpa4-U7hQjW0CfAucCYz12pBcIRnzLTQ,387
|
|
78
73
|
runtime/browser/extensions/intuned_extension.py,sha256=_La0ikQX2isdiBgZXkZt2iQ6eyW7Fe-9yjePFzpj0rk,2804
|
|
79
74
|
runtime/browser/helpers.py,sha256=CwgiBToawPgwAY9nIGkGHW544N7Db_OgKmS-SHkN2pU,1255
|
|
80
|
-
runtime/browser/launch_browser.py,sha256=
|
|
75
|
+
runtime/browser/launch_browser.py,sha256=MFo9Nb9eQgGO3w3ngRp9epzolcTBvekDQudZwIE6_74,2516
|
|
81
76
|
runtime/browser/launch_camoufox.py,sha256=TBOAwwipNGlbtMdFYnGkVM0ppLU44vWNkMGZA5uPZCE,1787
|
|
82
|
-
runtime/browser/launch_chromium.py,sha256=
|
|
77
|
+
runtime/browser/launch_chromium.py,sha256=p3mpUwVGTOeKBjiaNJMlkW0a5ipQU-sFO2H2J0cTaW0,8832
|
|
83
78
|
runtime/browser/storage_state.py,sha256=fwLg8sP-H-vgt_6AJKNl03CpgyMVCQWWcN2cqswTQMs,3603
|
|
84
79
|
runtime/constants.py,sha256=YMYQgCWZdJXUpxz_IN2TvZO5rFye9k_Lk9CS8m-shLg,34
|
|
85
80
|
runtime/context/__init__.py,sha256=hg8ejm4bJy4tNkwmZ9lKgYJx6bU7OgOdBS684Uv5XGg,73
|
|
@@ -103,17 +98,18 @@ runtime/run/pydantic_encoder.py,sha256=wJCljwwINSICvCJ0i2izp2RLkQ15nYglUQCyyjM40
|
|
|
103
98
|
runtime/run/run_api.py,sha256=AFhZerLTyHGznGCJl0fLbiTqhZ_WRmphaJK-RqrupTQ,8981
|
|
104
99
|
runtime/run/setup_context_hook.py,sha256=KTX4mRmeUEmYS9zrmobR1V09GakOk6uz81Uo_xXTJZk,1156
|
|
105
100
|
runtime/run/traces.py,sha256=fKzh11LqV47ujgq_9I2tdp-dgld566wffWaHwU_4gis,1123
|
|
106
|
-
runtime/run/types.py,sha256
|
|
101
|
+
runtime/run/types.py,sha256=-7ACaxa5vg2qHw14JunvUWt-AchanTQU4FRF57DxJWo,287
|
|
107
102
|
runtime/types/__init__.py,sha256=LWf5iOMgbve_BrpVP-LWWzDD3v2K4Y2sLxthOnVEqyY,539
|
|
108
103
|
runtime/types/payload.py,sha256=sty8HgDEn3nJbZrwEOMCXyuG7_ICGDwlBIIWSON5ABY,124
|
|
109
104
|
runtime/types/run_types.py,sha256=GcYLkL2BHxOjT4O3KvBP6xjBKsmJbjltMt_5bCVnfCI,4554
|
|
110
|
-
runtime/types/settings_types.py,sha256=
|
|
105
|
+
runtime/types/settings_types.py,sha256=pVVh67lv7iHAUUbovGHvbswEFtx_N-b7jTwFvk968Hg,3118
|
|
111
106
|
runtime/utils/__init__.py,sha256=v0qHjnc54YCkY1yPbXuihgymVZau_15xaEVyaFQj9ts,78
|
|
107
|
+
runtime/utils/anyio.py,sha256=KNemAQmmS425YKbVH_7DAE5lcDG_UziJHHTt9YJKS4o,697
|
|
112
108
|
runtime/utils/config_loader.py,sha256=yqk2eDGbgyw0Xslgd3dJbB28NjUe02L9LyCxzCmH9r4,482
|
|
113
109
|
runtime_helpers/__init__.py,sha256=1BPzEc-qC2WAYiCWDOJChpgnFyO3ZNYRKHEZqdHUGwM,322
|
|
114
110
|
runtime_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
|
-
intuned_runtime-1.3.
|
|
116
|
-
intuned_runtime-1.3.
|
|
117
|
-
intuned_runtime-1.3.
|
|
118
|
-
intuned_runtime-1.3.
|
|
119
|
-
intuned_runtime-1.3.
|
|
111
|
+
intuned_runtime-1.3.4.dist-info/METADATA,sha256=evPlfZys9C-YXh_s5UsQnqCSBtB4MX0szxNm_hkIcx4,5473
|
|
112
|
+
intuned_runtime-1.3.4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
113
|
+
intuned_runtime-1.3.4.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
|
|
114
|
+
intuned_runtime-1.3.4.dist-info/licenses/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
|
|
115
|
+
intuned_runtime-1.3.4.dist-info/RECORD,,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import shutil
|
|
1
3
|
from contextlib import asynccontextmanager
|
|
2
4
|
from contextlib import AsyncExitStack
|
|
3
5
|
from typing import AsyncContextManager
|
|
@@ -49,6 +51,19 @@ async def launch_browser(
|
|
|
49
51
|
if cdp_port:
|
|
50
52
|
raise AutomationError(ValueError("CDP port is not supported with Camoufox"))
|
|
51
53
|
context, page = await stack.enter_async_context(launch_camoufox(headless=headless, proxy=proxy))
|
|
54
|
+
case "brave":
|
|
55
|
+
brave_path = await asyncio.to_thread(shutil.which, "brave-browser-stable")
|
|
56
|
+
if brave_path is None:
|
|
57
|
+
raise RuntimeError("Brave browser not found")
|
|
58
|
+
context, page = await stack.enter_async_context(
|
|
59
|
+
launch_chromium(
|
|
60
|
+
headless=headless,
|
|
61
|
+
cdp_address=cdp_address,
|
|
62
|
+
cdp_port=cdp_port,
|
|
63
|
+
proxy=proxy,
|
|
64
|
+
executable_path=brave_path,
|
|
65
|
+
)
|
|
66
|
+
)
|
|
52
67
|
case "chromium" | _:
|
|
53
68
|
context, page = await stack.enter_async_context(
|
|
54
69
|
launch_chromium(headless=headless, cdp_address=cdp_address, cdp_port=cdp_port, proxy=proxy)
|
|
@@ -20,6 +20,7 @@ from .helpers import wait_on_cdp_address
|
|
|
20
20
|
logger = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
|
+
from playwright.async_api import Page
|
|
23
24
|
from playwright.async_api import ProxySettings
|
|
24
25
|
from playwright.async_api import ViewportSize
|
|
25
26
|
|
|
@@ -57,6 +58,7 @@ async def launch_chromium(
|
|
|
57
58
|
proxy: "ProxySettings | None" = None,
|
|
58
59
|
viewport: "ViewportSize | None" = None,
|
|
59
60
|
app_mode_initial_url: str | None = None,
|
|
61
|
+
executable_path: os.PathLike[str] | str | None = None,
|
|
60
62
|
**kwargs: Any,
|
|
61
63
|
):
|
|
62
64
|
from playwright.async_api import async_playwright
|
|
@@ -101,8 +103,15 @@ async def launch_chromium(
|
|
|
101
103
|
if headless:
|
|
102
104
|
args_to_ignore.append("--headless=old")
|
|
103
105
|
extra_args.append("--headless=new")
|
|
106
|
+
|
|
107
|
+
if executable_path is not None:
|
|
108
|
+
executable_path = await anyio.Path(executable_path).resolve()
|
|
109
|
+
if not await executable_path.exists():
|
|
110
|
+
logger.warning(f"Executable path {executable_path} does not exist. Falling back to default.")
|
|
111
|
+
executable_path = None
|
|
104
112
|
context = await playwright.chromium.launch_persistent_context(
|
|
105
113
|
os.fspath(user_preferences_dir),
|
|
114
|
+
executable_path=str(executable_path) if executable_path else None,
|
|
106
115
|
headless=headless,
|
|
107
116
|
viewport=viewport,
|
|
108
117
|
proxy=proxy,
|
|
@@ -171,7 +180,7 @@ async def dangerous_launch_chromium(
|
|
|
171
180
|
for page in context.pages:
|
|
172
181
|
await page.set_viewport_size(kwargs.get("viewport", {"width": 1280, "height": 800}))
|
|
173
182
|
|
|
174
|
-
async def set_viewport_size(page):
|
|
183
|
+
async def set_viewport_size(page: "Page"):
|
|
175
184
|
# check if the page is already closed
|
|
176
185
|
if page.is_closed():
|
|
177
186
|
return
|
runtime/run/types.py
CHANGED
|
@@ -4,11 +4,6 @@ from typing import Awaitable
|
|
|
4
4
|
from typing import Optional
|
|
5
5
|
from typing import Protocol
|
|
6
6
|
|
|
7
|
-
from git import TYPE_CHECKING
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
pass
|
|
11
|
-
|
|
12
7
|
|
|
13
8
|
class ImportFunction(Protocol):
|
|
14
9
|
def __call__(self, file_path: str, name: Optional[str] = None, /) -> Callable[..., Awaitable[Any]]: ...
|
runtime/types/settings_types.py
CHANGED
|
@@ -9,11 +9,21 @@ class CaptchaSettings(BaseModel):
|
|
|
9
9
|
enabled: bool = Field(default=False)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
12
|
+
class CaptchaSolverSolveSettings(BaseModel):
|
|
13
13
|
model_config = {
|
|
14
14
|
"populate_by_name": True,
|
|
15
15
|
"serialize_by_alias": True,
|
|
16
16
|
}
|
|
17
|
+
auto_solve: bool = Field(default=True, alias="autoSolve")
|
|
18
|
+
solve_delay: int = Field(default=2000, alias="solveDelay")
|
|
19
|
+
max_retries: int = Field(default=3, alias="maxRetries")
|
|
20
|
+
timeout: int = Field(default=30000)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CustomCaptchaSettings(CaptchaSettings):
|
|
24
|
+
model_config = {
|
|
25
|
+
"serialize_by_alias": True,
|
|
26
|
+
}
|
|
17
27
|
|
|
18
28
|
image_locators: List[str] = Field(alias="imageLocators", default=[])
|
|
19
29
|
submit_locators: List[str] = Field(alias="submitLocators", default=[])
|
|
@@ -47,9 +57,7 @@ class CaptchaSolverSettings(BaseModel):
|
|
|
47
57
|
lemin: CaptchaSettings = Field(default_factory=CaptchaSettings)
|
|
48
58
|
custom_captcha: CustomCaptchaSettings = Field(alias="customCaptcha", default_factory=CustomCaptchaSettings)
|
|
49
59
|
text: TextCaptchaSettings = Field(default_factory=TextCaptchaSettings)
|
|
50
|
-
settings:
|
|
51
|
-
default={"autoSolve": True, "solveDelay": 2000, "maxRetries": 3, "timeout": 30000}
|
|
52
|
-
)
|
|
60
|
+
settings: CaptchaSolverSolveSettings = Field(default_factory=CaptchaSolverSolveSettings)
|
|
53
61
|
|
|
54
62
|
|
|
55
63
|
class IntunedJsonDisabledAuthSessions(BaseModel):
|
runtime/utils/anyio.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import inspect
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Callable
|
|
6
|
+
from typing import TypeVar
|
|
7
|
+
|
|
8
|
+
import anyio
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def run_sync(func: Callable[..., T]) -> Callable[..., T]:
|
|
14
|
+
"""
|
|
15
|
+
Wrapper that runs a function synchronously.
|
|
16
|
+
If the function is async, it will be run using anyio.run instead of asyncio.run.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@wraps(func)
|
|
20
|
+
def wrapper(*args: Any, **kwargs: Any) -> T:
|
|
21
|
+
if inspect.iscoroutinefunction(func):
|
|
22
|
+
func_with_args_kwargs = functools.partial(func, *args, **kwargs)
|
|
23
|
+
return anyio.run(func_with_args_kwargs, backend="asyncio")
|
|
24
|
+
return func(*args, **kwargs)
|
|
25
|
+
|
|
26
|
+
return wrapper
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
import arguably
|
|
4
|
-
from more_termcolor import bold # type: ignore
|
|
5
|
-
from more_termcolor import cyan # type: ignore
|
|
6
|
-
from more_termcolor import green # type: ignore
|
|
7
|
-
from more_termcolor import red # type: ignore
|
|
8
|
-
|
|
9
|
-
from intuned_internal_cli.utils.code_tree import convert_project_to_code_tree
|
|
10
|
-
|
|
11
|
-
from ...utils.ai_source_project import AiSourceInfo
|
|
12
|
-
from ...utils.ai_source_project import deploy_ai_source
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@arguably.command # type: ignore
|
|
16
|
-
def ai_source__deploy(
|
|
17
|
-
*,
|
|
18
|
-
ai_source_info_str: str,
|
|
19
|
-
ai_source_info_path: str,
|
|
20
|
-
yes_to_all: bool = False,
|
|
21
|
-
):
|
|
22
|
-
"""
|
|
23
|
-
Commands to run on AI source projects.
|
|
24
|
-
|
|
25
|
-
Args:
|
|
26
|
-
ai_source_info_str (str): [--ai-source-info] JSON string containing the AI source project information.
|
|
27
|
-
ai_source_info_path (str): Path to the JSON file containing the AI source project information. Defaults to <current directory>/ai_source.json.
|
|
28
|
-
yes_to_all (bool): [-y/--yes] Skip confirmation prompts.
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
if ai_source_info_str and ai_source_info_path:
|
|
32
|
-
raise ValueError("Only one of ai_source_info or ai_source_info_path should be provided.")
|
|
33
|
-
|
|
34
|
-
if not (ai_source_info_str or ai_source_info_path):
|
|
35
|
-
ai_source_info_path = "ai_source.json"
|
|
36
|
-
|
|
37
|
-
try:
|
|
38
|
-
if ai_source_info_str:
|
|
39
|
-
ai_source_info_json = json.loads(ai_source_info_str)
|
|
40
|
-
else:
|
|
41
|
-
with open(ai_source_info_path) as f:
|
|
42
|
-
ai_source_info_json = json.load(f)
|
|
43
|
-
ai_source_info = AiSourceInfo(**ai_source_info_json)
|
|
44
|
-
except json.JSONDecodeError as e:
|
|
45
|
-
raise ValueError(f"Invalid JSON in ai_source_info: {e}") from e
|
|
46
|
-
except FileNotFoundError as e:
|
|
47
|
-
raise ValueError("AI source info file not found") from e
|
|
48
|
-
except OSError as e:
|
|
49
|
-
raise ValueError("Error reading AI source info file") from e
|
|
50
|
-
except TypeError as e:
|
|
51
|
-
raise ValueError("AI source info is invalid:", str(e)) from e
|
|
52
|
-
|
|
53
|
-
wait_for_confirm = not yes_to_all
|
|
54
|
-
|
|
55
|
-
code_tree = convert_project_to_code_tree(".", wait_for_confirm=wait_for_confirm)
|
|
56
|
-
|
|
57
|
-
success = deploy_ai_source(code_tree, ai_source_info)
|
|
58
|
-
|
|
59
|
-
if success:
|
|
60
|
-
print(
|
|
61
|
-
f"🚀 AI source deployment triggered for {bold(green(ai_source_info.id))} ({bold(green(ai_source_info.version_id))}). Check progress at {cyan(f"{ai_source_info.environment_url}/__internal-ai-sources/{ai_source_info.id}?version_id={ai_source_info.version_id}")}"
|
|
62
|
-
)
|
|
63
|
-
else:
|
|
64
|
-
print(red(bold("Deployment failed")))
|