intuned-runtime 1.3.1__py3-none-any.whl → 1.3.3__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/__init__.py +15 -24
- intuned_cli/commands/__init__.py +5 -0
- intuned_cli/commands/attempt_api_command.py +8 -2
- intuned_cli/commands/attempt_authsession_check_command.py +8 -2
- intuned_cli/commands/attempt_authsession_command.py +4 -7
- intuned_cli/commands/attempt_authsession_create_command.py +9 -3
- intuned_cli/commands/attempt_command.py +4 -7
- intuned_cli/commands/authsession_command.py +9 -0
- intuned_cli/commands/authsession_record_command.py +52 -0
- intuned_cli/commands/command.py +6 -7
- intuned_cli/commands/deploy_command.py +2 -3
- intuned_cli/commands/init_command.py +2 -3
- intuned_cli/commands/run_api_command.py +9 -3
- intuned_cli/commands/run_authsession_command.py +4 -7
- intuned_cli/commands/run_authsession_create_command.py +32 -5
- intuned_cli/commands/run_authsession_update_command.py +31 -5
- intuned_cli/commands/run_authsession_validate_command.py +30 -4
- intuned_cli/commands/run_command.py +4 -7
- intuned_cli/commands/save_command.py +2 -3
- intuned_cli/controller/__test__/test_api.py +159 -18
- intuned_cli/controller/__test__/test_authsession.py +497 -6
- intuned_cli/controller/api.py +40 -39
- intuned_cli/controller/authsession.py +213 -110
- intuned_cli/controller/deploy.py +3 -5
- intuned_cli/controller/save.py +47 -66
- intuned_cli/types.py +14 -0
- intuned_cli/utils/__test__/test_browser.py +132 -0
- intuned_cli/utils/__test__/test_traces.py +27 -0
- intuned_cli/utils/api_helpers.py +54 -5
- intuned_cli/utils/auth_session_helpers.py +42 -7
- intuned_cli/utils/backend.py +4 -1
- intuned_cli/utils/browser.py +63 -0
- intuned_cli/utils/error.py +14 -0
- intuned_cli/utils/exclusions.py +1 -0
- intuned_cli/utils/help.py +9 -0
- intuned_cli/utils/traces.py +31 -0
- intuned_cli/utils/wrapper.py +68 -0
- intuned_internal_cli/__init__.py +7 -0
- 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.1.dist-info → intuned_runtime-1.3.3.dist-info}/METADATA +4 -2
- intuned_runtime-1.3.3.dist-info/RECORD +115 -0
- runtime/browser/launch_browser.py +15 -0
- runtime/browser/launch_chromium.py +14 -1
- runtime/run/types.py +0 -5
- runtime/types/settings_types.py +13 -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.1.dist-info/RECORD +0 -111
- {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/WHEEL +0 -0
- {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/entry_points.txt +0 -0
- {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
intuned_cli/__init__.py,sha256=00r4AkrKFEzybNb4LWRZGSi3evyX9adVC6LoFItP5Ls,1208
|
|
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
|
+
intuned_cli/controller/__test__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
intuned_cli/controller/__test__/test_api.py,sha256=CgPUTsdQZ6r4it8yU1JG96TiN1WKyeUMh__7UICg36k,24489
|
|
22
|
+
intuned_cli/controller/__test__/test_authsession.py,sha256=fvkqm1B39kAxgb1iLXs4WlcVNzn3P6hvlvNS4IrdBgQ,52491
|
|
23
|
+
intuned_cli/controller/api.py,sha256=GDBSn7J0567ziBLNEk6tiguUDLwUTvDU6kmMqifYKMQ,7511
|
|
24
|
+
intuned_cli/controller/authsession.py,sha256=rx5qRaKp4ED3OArD8_qCDGjKqgy1Pc5s9YYfm6bxe-I,18688
|
|
25
|
+
intuned_cli/controller/deploy.py,sha256=nmXIWTunPMqx_fcuFhbstWVQiIhCnI3bkJ4oMVBZQH8,5436
|
|
26
|
+
intuned_cli/controller/save.py,sha256=LxIu6IznmTvAC5OpEQcnq1TnxYG6aCNBBdvmyVYs_Zg,8850
|
|
27
|
+
intuned_cli/types.py,sha256=1BKCukVvn2i37-onpZ9rFLrcVh4kWW_ui0DzOIKugtI,704
|
|
28
|
+
intuned_cli/utils/__test__/test_browser.py,sha256=NCv7OplirDxAjBpnfZharOa5O0fVNWA9xU3I1GVWB5M,4474
|
|
29
|
+
intuned_cli/utils/__test__/test_traces.py,sha256=4EfzwizBt7VT9-dANMdBYFKQTPzPWMDnodSVyT5F4dY,901
|
|
30
|
+
intuned_cli/utils/api_helpers.py,sha256=DKhBvri6lh6A4E86Wzo_eVcKZYTeWbTk3rjtj-8nGHc,2608
|
|
31
|
+
intuned_cli/utils/auth_session_helpers.py,sha256=92BL-UsP_dYSoGEsy7eDuDqMBrJ9Pucq-AL84IcpFAo,3593
|
|
32
|
+
intuned_cli/utils/backend.py,sha256=nl6ngRS0_nRPOc9FZWfcMol7twUCrdM1OiTue6LYZwA,1151
|
|
33
|
+
intuned_cli/utils/browser.py,sha256=l9n6JTupiG0QWUgyDbHTRO1VMwhlWOTJofzevgsOAfs,2004
|
|
34
|
+
intuned_cli/utils/confirmation.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
intuned_cli/utils/console.py,sha256=jgin2xB-0kpANPMoiDBOnWhrc8Ey5zT4IHRxQa8f5CQ,93
|
|
36
|
+
intuned_cli/utils/error.py,sha256=A6OZ5TX95RbOvQFWipAPCoxjZpT8j4oP8oKlTabqt6Q,1281
|
|
37
|
+
intuned_cli/utils/exclusions.py,sha256=bdjEnqqK1rPCkPLRYQzOPeFC0VANeMYRtEIHbAnL9sg,813
|
|
38
|
+
intuned_cli/utils/get_auth_parameters.py,sha256=HmMSjBE8bPulkUdX319Ipr383Ko2Gtz3y8_WT9CK3Kw,798
|
|
39
|
+
intuned_cli/utils/help.py,sha256=NKTQCzaIINQsGHljJH68HemAVThbkKU3IQfxyRyVaD0,223
|
|
40
|
+
intuned_cli/utils/import_function.py,sha256=UmE2yw5std1ENMFdBU-TUBuQ01qsv7Qr5ElnAhqE6Yc,453
|
|
41
|
+
intuned_cli/utils/timeout.py,sha256=DkoeoU9XvKKKSQ06CpwqcNvxWqLPAOVuAMw6kSr4Tuo,886
|
|
42
|
+
intuned_cli/utils/traces.py,sha256=Du_FnvSq-StLsAIQKSNyNSwkoMS-J93Tb6Ln4QgXVTE,793
|
|
43
|
+
intuned_cli/utils/wrapper.py,sha256=MRLtDhZLxQlOd0C44JrGV_WZJ3xbtZFaSsBTZGtd-oY,2269
|
|
44
|
+
intuned_internal_cli/__init__.py,sha256=bcL7-SPWCE0SmszoBoEvcyf-wAGRHAzIRe7vlCq3NPA,1760
|
|
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
|
|
58
|
+
intuned_internal_cli/logger.py,sha256=bZK3q-KUdGxk_qzDb6pn-n0LOhKJvi6a9p8oSwZtq3s,594
|
|
59
|
+
intuned_internal_cli/utils/ai_source_project.py,sha256=xUCM6p3i1XN4bJbuQz8LCzeI4BwqAdSvCl_vwDAEi0k,831
|
|
60
|
+
intuned_internal_cli/utils/code_tree.py,sha256=1wfxZoQ5kRCfqs2SEPAicbAIPTiD6P1LxSuwYu_eeaI,2790
|
|
61
|
+
intuned_internal_cli/utils/run_apis.py,sha256=Zee4zkgt9R8XY1XCGzj2Nc4zJ3jlRz1xnO493wotuWw,4690
|
|
62
|
+
intuned_internal_cli/utils/setup_ide_functions_token.py,sha256=72-hf5HOPO9hj_eo3MTSVEPIwtkaIma_NRepsw_FHQM,304
|
|
63
|
+
intuned_internal_cli/utils/unix_socket.py,sha256=UISmkJMHrir5iBLUm6vxC3uzTGIFyOk_wa0C9LUw4Cc,1889
|
|
64
|
+
intuned_internal_cli/utils/wrapper.py,sha256=Y0yAs2XrDHChUMUsEYcRT0AbSkZCfdgAvZs0Sdrbirg,366
|
|
65
|
+
intuned_runtime/__init__.py,sha256=1BPzEc-qC2WAYiCWDOJChpgnFyO3ZNYRKHEZqdHUGwM,322
|
|
66
|
+
runtime/__init__.py,sha256=87gDXuxUv_kGzQfuB1mh6DF-dDysJN8r684c7jGnHxc,144
|
|
67
|
+
runtime/backend_functions/__init__.py,sha256=j2EaK4FK8bmdFtqc5FxtFwx1KhIn_7qKPChrrAhJI3s,119
|
|
68
|
+
runtime/backend_functions/_call_backend_function.py,sha256=NpbQmEieuRan0fgbJQ0L_skU6MgjMmR99bWsQQYuFtI,3402
|
|
69
|
+
runtime/backend_functions/get_auth_session_parameters.py,sha256=pOvB7XiWpphEuBpazdKALw9EWgBU1PeY3gkzBfVLpkc,869
|
|
70
|
+
runtime/browser/__init__.py,sha256=EPWfa4ZmdR8GJqh2qcsx1ZvHmCYiUYrQ-zeHYVapH9s,285
|
|
71
|
+
runtime/browser/extensions/__init__.py,sha256=VGUFvkYUwuYc9UlYy1TD79veXuDhnLDcmbyHiVnf6dQ,80
|
|
72
|
+
runtime/browser/extensions/helpers.py,sha256=W3XiOf66J_xWpa4-U7hQjW0CfAucCYz12pBcIRnzLTQ,387
|
|
73
|
+
runtime/browser/extensions/intuned_extension.py,sha256=_La0ikQX2isdiBgZXkZt2iQ6eyW7Fe-9yjePFzpj0rk,2804
|
|
74
|
+
runtime/browser/helpers.py,sha256=CwgiBToawPgwAY9nIGkGHW544N7Db_OgKmS-SHkN2pU,1255
|
|
75
|
+
runtime/browser/launch_browser.py,sha256=MFo9Nb9eQgGO3w3ngRp9epzolcTBvekDQudZwIE6_74,2516
|
|
76
|
+
runtime/browser/launch_camoufox.py,sha256=TBOAwwipNGlbtMdFYnGkVM0ppLU44vWNkMGZA5uPZCE,1787
|
|
77
|
+
runtime/browser/launch_chromium.py,sha256=p3mpUwVGTOeKBjiaNJMlkW0a5ipQU-sFO2H2J0cTaW0,8832
|
|
78
|
+
runtime/browser/storage_state.py,sha256=fwLg8sP-H-vgt_6AJKNl03CpgyMVCQWWcN2cqswTQMs,3603
|
|
79
|
+
runtime/constants.py,sha256=YMYQgCWZdJXUpxz_IN2TvZO5rFye9k_Lk9CS8m-shLg,34
|
|
80
|
+
runtime/context/__init__.py,sha256=hg8ejm4bJy4tNkwmZ9lKgYJx6bU7OgOdBS684Uv5XGg,73
|
|
81
|
+
runtime/context/context.py,sha256=uZxt5cF7Q66Ng6F5J83LMCn9UG7swWOM3f-Wz4MYq7w,1805
|
|
82
|
+
runtime/env.py,sha256=DYEU5a-XtPbImdmLEDqdWn40JGSOvG-V7mIXrt0sM9A,660
|
|
83
|
+
runtime/errors/__init__.py,sha256=oqiBSvT_yFLQ3hG0AbCUA3WYFaxkTDVkDMSy59xvBCo,688
|
|
84
|
+
runtime/errors/auth_session_errors.py,sha256=6b4XTI8UCDHDPX4jEA8_HyrNUp4VZ1TrEA8DRh6Z3rM,228
|
|
85
|
+
runtime/errors/run_api_errors.py,sha256=D3zHsJnsjSOy0JUac_CDgHWOYEsOG2CUo7boVcteuCI,4070
|
|
86
|
+
runtime/errors/trace_errors.py,sha256=Lzfo0sH3zGaWz1kn5DHcAXQMn3aR2y2bnauj6xP1LYE,110
|
|
87
|
+
runtime/helpers/__init__.py,sha256=rkywrr_76AMaIsAAjsVmmfLh8BjB5_E6AeJY5sWFm6U,292
|
|
88
|
+
runtime/helpers/attempt_store.py,sha256=YPwGHkdJNbC8rSiQ1vOReKNOQrjPT1wpO9ZDcQf530I,339
|
|
89
|
+
runtime/helpers/extend_payload.py,sha256=towZF08WTpTTDBL4AV1bUU3XpKAQHEB66kGUfTICDe0,246
|
|
90
|
+
runtime/helpers/extend_timeout.py,sha256=KjfSLEUrqoz7v00rhnPAKq2OmUzEzcv-eQ3M8c2U46s,348
|
|
91
|
+
runtime/helpers/get_auth_session_parameters.py,sha256=7bopGhJ7vjKAn_UxnHSAah-k2rVOPbq0zi9FQOOCFds,472
|
|
92
|
+
runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
|
+
runtime/run/__init__.py,sha256=zxMYVb7hn147YTrhMLsrcX6-KTd71HLrYHstJOWeWXQ,52
|
|
94
|
+
runtime/run/intuned_settings.py,sha256=vy2-ktEzUfUp5Z90dp3l7jPKHNjgB-8GSMDgAY-rYaU,1074
|
|
95
|
+
runtime/run/playwright_context.py,sha256=pSTWIg_XpnuHtV5noApabAlZGZJYqtX82YW77n1FGFU,4675
|
|
96
|
+
runtime/run/playwright_tracing.py,sha256=oqr9b6xjqdYPCEOUvIVE1M7ord7LAvXAUQAz38Jwjw8,708
|
|
97
|
+
runtime/run/pydantic_encoder.py,sha256=wJCljwwINSICvCJ0i2izp2RLkQ15nYglUQCyyjM40Jk,332
|
|
98
|
+
runtime/run/run_api.py,sha256=AFhZerLTyHGznGCJl0fLbiTqhZ_WRmphaJK-RqrupTQ,8981
|
|
99
|
+
runtime/run/setup_context_hook.py,sha256=KTX4mRmeUEmYS9zrmobR1V09GakOk6uz81Uo_xXTJZk,1156
|
|
100
|
+
runtime/run/traces.py,sha256=fKzh11LqV47ujgq_9I2tdp-dgld566wffWaHwU_4gis,1123
|
|
101
|
+
runtime/run/types.py,sha256=-7ACaxa5vg2qHw14JunvUWt-AchanTQU4FRF57DxJWo,287
|
|
102
|
+
runtime/types/__init__.py,sha256=LWf5iOMgbve_BrpVP-LWWzDD3v2K4Y2sLxthOnVEqyY,539
|
|
103
|
+
runtime/types/payload.py,sha256=sty8HgDEn3nJbZrwEOMCXyuG7_ICGDwlBIIWSON5ABY,124
|
|
104
|
+
runtime/types/run_types.py,sha256=GcYLkL2BHxOjT4O3KvBP6xjBKsmJbjltMt_5bCVnfCI,4554
|
|
105
|
+
runtime/types/settings_types.py,sha256=lgu3O-LXSa1Gbv1j6Uzd5udpSFBl2KR9T4vRVWITVfk,2832
|
|
106
|
+
runtime/utils/__init__.py,sha256=v0qHjnc54YCkY1yPbXuihgymVZau_15xaEVyaFQj9ts,78
|
|
107
|
+
runtime/utils/anyio.py,sha256=KNemAQmmS425YKbVH_7DAE5lcDG_UziJHHTt9YJKS4o,697
|
|
108
|
+
runtime/utils/config_loader.py,sha256=yqk2eDGbgyw0Xslgd3dJbB28NjUe02L9LyCxzCmH9r4,482
|
|
109
|
+
runtime_helpers/__init__.py,sha256=1BPzEc-qC2WAYiCWDOJChpgnFyO3ZNYRKHEZqdHUGwM,322
|
|
110
|
+
runtime_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
111
|
+
intuned_runtime-1.3.3.dist-info/METADATA,sha256=mV8sOXqVgV0U5FsWnW_BoTihQAWXiyeDAi07ZtqklCE,5473
|
|
112
|
+
intuned_runtime-1.3.3.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
113
|
+
intuned_runtime-1.3.3.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
|
|
114
|
+
intuned_runtime-1.3.3.dist-info/licenses/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
|
|
115
|
+
intuned_runtime-1.3.3.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
|
|
|
@@ -56,6 +57,8 @@ async def launch_chromium(
|
|
|
56
57
|
*,
|
|
57
58
|
proxy: "ProxySettings | None" = None,
|
|
58
59
|
viewport: "ViewportSize | None" = None,
|
|
60
|
+
app_mode_initial_url: str | None = None,
|
|
61
|
+
executable_path: os.PathLike[str] | str | None = None,
|
|
59
62
|
**kwargs: Any,
|
|
60
63
|
):
|
|
61
64
|
from playwright.async_api import async_playwright
|
|
@@ -80,6 +83,9 @@ async def launch_chromium(
|
|
|
80
83
|
if cdp_port:
|
|
81
84
|
extra_args.append(f"--remote-debugging-port={cdp_port}")
|
|
82
85
|
|
|
86
|
+
if app_mode_initial_url:
|
|
87
|
+
extra_args.append(f"--app={app_mode_initial_url}")
|
|
88
|
+
|
|
83
89
|
args_to_ignore = [
|
|
84
90
|
"--disable-extensions",
|
|
85
91
|
"--disable-component-extensions-with-background-pages",
|
|
@@ -97,8 +103,15 @@ async def launch_chromium(
|
|
|
97
103
|
if headless:
|
|
98
104
|
args_to_ignore.append("--headless=old")
|
|
99
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
|
|
100
112
|
context = await playwright.chromium.launch_persistent_context(
|
|
101
113
|
os.fspath(user_preferences_dir),
|
|
114
|
+
executable_path=str(executable_path) if executable_path else None,
|
|
102
115
|
headless=headless,
|
|
103
116
|
viewport=viewport,
|
|
104
117
|
proxy=proxy,
|
|
@@ -167,7 +180,7 @@ async def dangerous_launch_chromium(
|
|
|
167
180
|
for page in context.pages:
|
|
168
181
|
await page.set_viewport_size(kwargs.get("viewport", {"width": 1280, "height": 800}))
|
|
169
182
|
|
|
170
|
-
async def set_viewport_size(page):
|
|
183
|
+
async def set_viewport_size(page: "Page"):
|
|
171
184
|
# check if the page is already closed
|
|
172
185
|
if page.is_closed():
|
|
173
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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from typing import List
|
|
2
|
+
from typing import Literal
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
from pydantic import Field
|
|
@@ -51,13 +52,21 @@ class CaptchaSolverSettings(BaseModel):
|
|
|
51
52
|
)
|
|
52
53
|
|
|
53
54
|
|
|
55
|
+
class IntunedJsonDisabledAuthSessions(BaseModel):
|
|
56
|
+
enabled: Literal[False]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class IntunedJsonEnabledAuthSessions(BaseModel):
|
|
60
|
+
enabled: Literal[True]
|
|
61
|
+
type: Literal["API", "MANUAL"]
|
|
62
|
+
start_url: str | None = Field(default=None, alias="startUrl")
|
|
63
|
+
finish_url: str | None = Field(default=None, alias="finishUrl")
|
|
64
|
+
|
|
65
|
+
|
|
54
66
|
class IntunedJson(BaseModel):
|
|
55
67
|
model_config = {"populate_by_name": True}
|
|
56
68
|
|
|
57
|
-
|
|
58
|
-
enabled: bool
|
|
59
|
-
|
|
60
|
-
auth_sessions: _AuthSessions = Field(alias="authSessions")
|
|
69
|
+
auth_sessions: IntunedJsonDisabledAuthSessions | IntunedJsonEnabledAuthSessions = Field(alias="authSessions")
|
|
61
70
|
project_name: str | None = Field(alias="projectName", default=None)
|
|
62
71
|
workspace_id: str | None = Field(alias="workspaceId", default=None)
|
|
63
72
|
captcha_solver: CaptchaSolverSettings | None = Field(alias="captchaSolver", default=None)
|
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")))
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
import arguably
|
|
6
|
-
import toml
|
|
7
|
-
from more_termcolor import bold # type: ignore
|
|
8
|
-
from more_termcolor import green # type: ignore
|
|
9
|
-
|
|
10
|
-
from ..utils.code_tree import get_project_name
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@arguably.command # type: ignore
|
|
14
|
-
def init(
|
|
15
|
-
*,
|
|
16
|
-
yes_to_all: bool = False,
|
|
17
|
-
no_to_all: bool = False,
|
|
18
|
-
project_name: str | None,
|
|
19
|
-
):
|
|
20
|
-
"""
|
|
21
|
-
Initializes current app, creating pyproject.toml and Intuned.json files. Will ask for confirmation before overwriting existing files.
|
|
22
|
-
|
|
23
|
-
Args:
|
|
24
|
-
yes_to_all (bool): [-y/--yes] Answer yes to all confirmation prompts
|
|
25
|
-
no_to_all (bool): [-n/--no] Answer no to any confirmation prompts
|
|
26
|
-
project_name (str | None): Name of the project. Will automatically resolve if not provided.
|
|
27
|
-
|
|
28
|
-
Returns:
|
|
29
|
-
None
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
if yes_to_all and no_to_all:
|
|
33
|
-
raise ValueError("Cannot specify both --yes and --no")
|
|
34
|
-
|
|
35
|
-
def should_write_file(file: str) -> bool:
|
|
36
|
-
if not os.path.exists(file):
|
|
37
|
-
return True
|
|
38
|
-
if no_to_all:
|
|
39
|
-
return False
|
|
40
|
-
elif yes_to_all:
|
|
41
|
-
print(bold(f"Overwriting {green(file)}"))
|
|
42
|
-
return True
|
|
43
|
-
return input(f"Overwrite {green(file)}? (y/N) ").lower().strip() == "y"
|
|
44
|
-
|
|
45
|
-
project_name = project_name or get_project_name(".")
|
|
46
|
-
print(bold("Initializing"), green(project_name))
|
|
47
|
-
|
|
48
|
-
def print_created(file: str) -> None:
|
|
49
|
-
print(bold("📦 Created"), green(file))
|
|
50
|
-
|
|
51
|
-
pyproject_name = "pyproject.toml"
|
|
52
|
-
if should_write_file(pyproject_name):
|
|
53
|
-
with open(pyproject_name, "w") as f:
|
|
54
|
-
toml.dump(_get_pyproject(project_name), f)
|
|
55
|
-
print_created(pyproject_name)
|
|
56
|
-
|
|
57
|
-
intuned_json_name = "Intuned.json"
|
|
58
|
-
if should_write_file(intuned_json_name):
|
|
59
|
-
with open(intuned_json_name, "w") as f:
|
|
60
|
-
json.dump(_get_intuned_json(project_name), f, indent=2)
|
|
61
|
-
print_created(intuned_json_name)
|
|
62
|
-
|
|
63
|
-
readme_name = "README.md"
|
|
64
|
-
if should_write_file(readme_name):
|
|
65
|
-
with open(readme_name, "w") as f:
|
|
66
|
-
f.write(_get_readme(project_name))
|
|
67
|
-
print_created(readme_name)
|
|
68
|
-
|
|
69
|
-
print(bold("✨ Done!"))
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _get_pyproject(project_name: str) -> dict[str, Any]:
|
|
73
|
-
return {
|
|
74
|
-
"build-system": {"requires": ["poetry-core>=1.2.0"], "build-backend": "poetry.core.masonry.api"},
|
|
75
|
-
"tool": {
|
|
76
|
-
"poetry": {
|
|
77
|
-
"package-mode": False,
|
|
78
|
-
"name": project_name,
|
|
79
|
-
"version": "0.0.1",
|
|
80
|
-
"description": f"Project {project_name}",
|
|
81
|
-
"authors": ["Intuned <service@intunedhq.com>"],
|
|
82
|
-
"readme": "README.md",
|
|
83
|
-
"dependencies": {
|
|
84
|
-
"python": ">=3.12,<3.13",
|
|
85
|
-
"intuned-runtime": {
|
|
86
|
-
"git": "ssh://git@github.com/Intuned/python-packages.git",
|
|
87
|
-
"tag": "runtime-latest",
|
|
88
|
-
"subdirectory": "runtime",
|
|
89
|
-
},
|
|
90
|
-
"intuned-sdk": {
|
|
91
|
-
"git": "ssh://git@github.com/Intuned/python-packages.git",
|
|
92
|
-
"tag": "sdk-latest",
|
|
93
|
-
"subdirectory": "sdk",
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def _get_intuned_json(_project_name: str) -> dict[str, Any]:
|
|
102
|
-
return {
|
|
103
|
-
"authSessions": {"enabled": False},
|
|
104
|
-
"scale": {"machineCount": 1, "softLimit": 1, "hardLimit": 5, "memory": 2048, "cpus": 6},
|
|
105
|
-
"proxy": {"enabled": False},
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def _get_readme(project_name: str) -> str:
|
|
110
|
-
return (
|
|
111
|
-
f"# `{project_name}` Intuned Automation Project\n"
|
|
112
|
-
f"\n"
|
|
113
|
-
f"\n"
|
|
114
|
-
f"## Getting started\n"
|
|
115
|
-
f"- Install dependencies: `poetry install`\n"
|
|
116
|
-
f"- Activate virtual environment: `poetry shell`\n"
|
|
117
|
-
f"- Project commands: `intuned project --help`\n"
|
|
118
|
-
f" - Run the project:\n"
|
|
119
|
-
f" - Sample mode: `intuned project run`\n"
|
|
120
|
-
f" - Full mode: `intuned project run --mode full`\n"
|
|
121
|
-
f" - Single mode: `intuned project run --mode single`\n"
|
|
122
|
-
f" - Deploy the project: `intuned project deploy`\n"
|
|
123
|
-
f" - Use `--help` for full details on each command.\n"
|
|
124
|
-
f"\n"
|
|
125
|
-
f"## SDK\n"
|
|
126
|
-
f"- If you want to use a specific version of the SDK, make sure to change the tag from `sdk-latest` to `sdk-<version>` in **pyproject.toml**.\n"
|
|
127
|
-
)
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import subprocess
|
|
3
|
-
from typing import List
|
|
4
|
-
from typing import Tuple
|
|
5
|
-
|
|
6
|
-
import arguably
|
|
7
|
-
import git
|
|
8
|
-
import git.cmd
|
|
9
|
-
import semver
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@arguably.command # type: ignore
|
|
13
|
-
def project__upgrade():
|
|
14
|
-
"""
|
|
15
|
-
Upgrade the project's Intuned runtime and Intuned SDK to the latest version.
|
|
16
|
-
"""
|
|
17
|
-
runtime_version, sdk_version = resolve_packages_versions()
|
|
18
|
-
print(f"Upgrading to runtime version {runtime_version} and SDK version {sdk_version}")
|
|
19
|
-
|
|
20
|
-
# Upgrade runtime and SDK using poetry
|
|
21
|
-
repo_url = "git+ssh://git@github.com/intuned/python-packages.git"
|
|
22
|
-
cwd = os.getcwd()
|
|
23
|
-
|
|
24
|
-
try:
|
|
25
|
-
# Upgrade runtime
|
|
26
|
-
subprocess.run(
|
|
27
|
-
["poetry", "add", f"{repo_url}@runtime-{runtime_version}#subdirectory=runtime"], check=True, cwd=cwd
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
# Upgrade SDK
|
|
31
|
-
subprocess.run(["poetry", "add", f"{repo_url}@sdk-{sdk_version}#subdirectory=sdk"], check=True, cwd=cwd)
|
|
32
|
-
|
|
33
|
-
except subprocess.CalledProcessError as e:
|
|
34
|
-
raise RuntimeError(f"Failed to upgrade packages: {e.stderr}") from e
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def get_latest_version(versions: List[str], prefix: str) -> str:
|
|
38
|
-
"""
|
|
39
|
-
Get the latest version from a list of versioned tags.
|
|
40
|
-
Filters out dev versions and returns the highest semver version.
|
|
41
|
-
"""
|
|
42
|
-
valid_versions: list[str] = []
|
|
43
|
-
for version in versions:
|
|
44
|
-
version_str = version.replace(f"{prefix}-", "")
|
|
45
|
-
try:
|
|
46
|
-
# Skip dev versions
|
|
47
|
-
if "dev" not in version_str:
|
|
48
|
-
semver.VersionInfo.parse(version_str)
|
|
49
|
-
valid_versions.append(version_str)
|
|
50
|
-
except ValueError:
|
|
51
|
-
continue
|
|
52
|
-
|
|
53
|
-
if not valid_versions:
|
|
54
|
-
raise ValueError(f"No valid versions found for {prefix}")
|
|
55
|
-
|
|
56
|
-
# Sort versions and get the latest
|
|
57
|
-
latest = str(max(map(semver.VersionInfo.parse, valid_versions)))
|
|
58
|
-
return latest
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def resolve_packages_versions() -> Tuple[str, str]:
|
|
62
|
-
"""
|
|
63
|
-
Resolves the latest versions of runtime and SDK packages using git ls-remote.
|
|
64
|
-
Returns a tuple of (runtime_version, sdk_version)
|
|
65
|
-
"""
|
|
66
|
-
try:
|
|
67
|
-
# Use GitPython to get remote tags
|
|
68
|
-
repo = git.cmd.Git()
|
|
69
|
-
refs = repo.ls_remote("--tags", "git@github.com:intuned/python-packages.git").split("\n")
|
|
70
|
-
|
|
71
|
-
# Parse the output which looks like:
|
|
72
|
-
# hash refs/tags/runtime-1.0.1
|
|
73
|
-
# hash refs/tags/sdk-0.1.1
|
|
74
|
-
tags: list[str] = []
|
|
75
|
-
for line in refs:
|
|
76
|
-
if not line.strip():
|
|
77
|
-
continue
|
|
78
|
-
_, ref = line.split(None, 1)
|
|
79
|
-
tag = ref.replace("refs/tags/", "")
|
|
80
|
-
tags.append(tag)
|
|
81
|
-
|
|
82
|
-
# Split into runtime and sdk versions
|
|
83
|
-
runtime_versions = [tag for tag in tags if tag.startswith("runtime-")]
|
|
84
|
-
sdk_versions = [tag for tag in tags if tag.startswith("sdk-")]
|
|
85
|
-
|
|
86
|
-
latest_runtime = get_latest_version(runtime_versions, "runtime")
|
|
87
|
-
latest_sdk = get_latest_version(sdk_versions, "sdk")
|
|
88
|
-
|
|
89
|
-
return latest_runtime, latest_sdk
|
|
90
|
-
|
|
91
|
-
except git.GitCommandError as e:
|
|
92
|
-
raise RuntimeError(f"Failed to fetch tags from git repository: {e.stderr}") from e
|