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.

Files changed (69) hide show
  1. intuned_cli/__init__.py +15 -24
  2. intuned_cli/commands/__init__.py +5 -0
  3. intuned_cli/commands/attempt_api_command.py +8 -2
  4. intuned_cli/commands/attempt_authsession_check_command.py +8 -2
  5. intuned_cli/commands/attempt_authsession_command.py +4 -7
  6. intuned_cli/commands/attempt_authsession_create_command.py +9 -3
  7. intuned_cli/commands/attempt_command.py +4 -7
  8. intuned_cli/commands/authsession_command.py +9 -0
  9. intuned_cli/commands/authsession_record_command.py +52 -0
  10. intuned_cli/commands/command.py +6 -7
  11. intuned_cli/commands/deploy_command.py +2 -3
  12. intuned_cli/commands/init_command.py +2 -3
  13. intuned_cli/commands/run_api_command.py +9 -3
  14. intuned_cli/commands/run_authsession_command.py +4 -7
  15. intuned_cli/commands/run_authsession_create_command.py +32 -5
  16. intuned_cli/commands/run_authsession_update_command.py +31 -5
  17. intuned_cli/commands/run_authsession_validate_command.py +30 -4
  18. intuned_cli/commands/run_command.py +4 -7
  19. intuned_cli/commands/save_command.py +2 -3
  20. intuned_cli/controller/__test__/test_api.py +159 -18
  21. intuned_cli/controller/__test__/test_authsession.py +497 -6
  22. intuned_cli/controller/api.py +40 -39
  23. intuned_cli/controller/authsession.py +213 -110
  24. intuned_cli/controller/deploy.py +3 -5
  25. intuned_cli/controller/save.py +47 -66
  26. intuned_cli/types.py +14 -0
  27. intuned_cli/utils/__test__/test_browser.py +132 -0
  28. intuned_cli/utils/__test__/test_traces.py +27 -0
  29. intuned_cli/utils/api_helpers.py +54 -5
  30. intuned_cli/utils/auth_session_helpers.py +42 -7
  31. intuned_cli/utils/backend.py +4 -1
  32. intuned_cli/utils/browser.py +63 -0
  33. intuned_cli/utils/error.py +14 -0
  34. intuned_cli/utils/exclusions.py +1 -0
  35. intuned_cli/utils/help.py +9 -0
  36. intuned_cli/utils/traces.py +31 -0
  37. intuned_cli/utils/wrapper.py +68 -0
  38. intuned_internal_cli/__init__.py +7 -0
  39. intuned_internal_cli/commands/__init__.py +8 -16
  40. intuned_internal_cli/commands/browser/__init__.py +1 -1
  41. intuned_internal_cli/commands/browser/save_state.py +2 -3
  42. intuned_internal_cli/commands/project/__init__.py +7 -9
  43. intuned_internal_cli/commands/project/auth_session/__init__.py +3 -3
  44. intuned_internal_cli/commands/project/auth_session/check.py +2 -2
  45. intuned_internal_cli/commands/project/auth_session/create.py +2 -3
  46. intuned_internal_cli/commands/project/auth_session/load.py +2 -3
  47. intuned_internal_cli/commands/project/project.py +2 -2
  48. intuned_internal_cli/commands/project/run.py +2 -2
  49. intuned_internal_cli/commands/project/run_interface.py +75 -8
  50. intuned_internal_cli/commands/project/type_check.py +5 -5
  51. intuned_internal_cli/commands/root.py +2 -1
  52. intuned_internal_cli/utils/wrapper.py +15 -0
  53. {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/METADATA +4 -2
  54. intuned_runtime-1.3.3.dist-info/RECORD +115 -0
  55. runtime/browser/launch_browser.py +15 -0
  56. runtime/browser/launch_chromium.py +14 -1
  57. runtime/run/types.py +0 -5
  58. runtime/types/settings_types.py +13 -4
  59. runtime/utils/anyio.py +26 -0
  60. intuned_internal_cli/commands/ai_source/__init__.py +0 -4
  61. intuned_internal_cli/commands/ai_source/ai_source.py +0 -10
  62. intuned_internal_cli/commands/ai_source/deploy.py +0 -64
  63. intuned_internal_cli/commands/init.py +0 -127
  64. intuned_internal_cli/commands/project/upgrade.py +0 -92
  65. intuned_internal_cli/commands/publish_packages.py +0 -264
  66. intuned_runtime-1.3.1.dist-info/RECORD +0 -111
  67. {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/WHEEL +0 -0
  68. {intuned_runtime-1.3.1.dist-info → intuned_runtime-1.3.3.dist-info}/entry_points.txt +0 -0
  69. {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]]: ...
@@ -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
- class _AuthSessions(BaseModel):
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,4 +0,0 @@
1
- from .ai_source import ai_source # type: ignore
2
- from .deploy import ai_source__deploy # type: ignore
3
-
4
- __all__ = ["ai_source", "ai_source__deploy"]
@@ -1,10 +0,0 @@
1
- import arguably
2
-
3
-
4
- @arguably.command # type: ignore
5
- def ai_source():
6
- """
7
- Commands to run on AI source projects.
8
- """
9
-
10
- pass
@@ -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