intuned-runtime 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. intuned_runtime-1.0.0/LICENSE +42 -0
  2. intuned_runtime-1.0.0/PKG-INFO +113 -0
  3. intuned_runtime-1.0.0/README.md +78 -0
  4. intuned_runtime-1.0.0/cli/__init__.py +45 -0
  5. intuned_runtime-1.0.0/cli/commands/__init__.py +25 -0
  6. intuned_runtime-1.0.0/cli/commands/ai_source/__init__.py +4 -0
  7. intuned_runtime-1.0.0/cli/commands/ai_source/ai_source.py +10 -0
  8. intuned_runtime-1.0.0/cli/commands/ai_source/deploy.py +64 -0
  9. intuned_runtime-1.0.0/cli/commands/browser/__init__.py +3 -0
  10. intuned_runtime-1.0.0/cli/commands/browser/save_state.py +32 -0
  11. intuned_runtime-1.0.0/cli/commands/init.py +127 -0
  12. intuned_runtime-1.0.0/cli/commands/project/__init__.py +20 -0
  13. intuned_runtime-1.0.0/cli/commands/project/auth_session/__init__.py +5 -0
  14. intuned_runtime-1.0.0/cli/commands/project/auth_session/check.py +118 -0
  15. intuned_runtime-1.0.0/cli/commands/project/auth_session/create.py +96 -0
  16. intuned_runtime-1.0.0/cli/commands/project/auth_session/load.py +39 -0
  17. intuned_runtime-1.0.0/cli/commands/project/project.py +10 -0
  18. intuned_runtime-1.0.0/cli/commands/project/run.py +340 -0
  19. intuned_runtime-1.0.0/cli/commands/project/run_interface.py +265 -0
  20. intuned_runtime-1.0.0/cli/commands/project/type_check.py +86 -0
  21. intuned_runtime-1.0.0/cli/commands/project/upgrade.py +92 -0
  22. intuned_runtime-1.0.0/cli/commands/publish_packages.py +264 -0
  23. intuned_runtime-1.0.0/cli/logger.py +19 -0
  24. intuned_runtime-1.0.0/cli/utils/ai_source_project.py +31 -0
  25. intuned_runtime-1.0.0/cli/utils/code_tree.py +83 -0
  26. intuned_runtime-1.0.0/cli/utils/run_apis.py +147 -0
  27. intuned_runtime-1.0.0/cli/utils/unix_socket.py +55 -0
  28. intuned_runtime-1.0.0/pyproject.toml +60 -0
  29. intuned_runtime-1.0.0/runtime/__init__.py +3 -0
  30. intuned_runtime-1.0.0/runtime/backend_functions/__init__.py +5 -0
  31. intuned_runtime-1.0.0/runtime/backend_functions/_call_backend_function.py +86 -0
  32. intuned_runtime-1.0.0/runtime/backend_functions/get_auth_session_parameters.py +30 -0
  33. intuned_runtime-1.0.0/runtime/browser/__init__.py +3 -0
  34. intuned_runtime-1.0.0/runtime/browser/launch_chromium.py +212 -0
  35. intuned_runtime-1.0.0/runtime/browser/storage_state.py +106 -0
  36. intuned_runtime-1.0.0/runtime/context/__init__.py +5 -0
  37. intuned_runtime-1.0.0/runtime/context/context.py +51 -0
  38. intuned_runtime-1.0.0/runtime/env.py +13 -0
  39. intuned_runtime-1.0.0/runtime/errors/__init__.py +21 -0
  40. intuned_runtime-1.0.0/runtime/errors/auth_session_errors.py +9 -0
  41. intuned_runtime-1.0.0/runtime/errors/run_api_errors.py +120 -0
  42. intuned_runtime-1.0.0/runtime/errors/trace_errors.py +3 -0
  43. intuned_runtime-1.0.0/runtime/helpers/__init__.py +5 -0
  44. intuned_runtime-1.0.0/runtime/helpers/extend_payload.py +9 -0
  45. intuned_runtime-1.0.0/runtime/helpers/extend_timeout.py +13 -0
  46. intuned_runtime-1.0.0/runtime/helpers/get_auth_session_parameters.py +14 -0
  47. intuned_runtime-1.0.0/runtime/py.typed +0 -0
  48. intuned_runtime-1.0.0/runtime/run/__init__.py +3 -0
  49. intuned_runtime-1.0.0/runtime/run/intuned_settings.py +38 -0
  50. intuned_runtime-1.0.0/runtime/run/playwright_constructs.py +19 -0
  51. intuned_runtime-1.0.0/runtime/run/run_api.py +233 -0
  52. intuned_runtime-1.0.0/runtime/run/traces.py +36 -0
  53. intuned_runtime-1.0.0/runtime/types/__init__.py +15 -0
  54. intuned_runtime-1.0.0/runtime/types/payload.py +7 -0
  55. intuned_runtime-1.0.0/runtime/types/run_types.py +177 -0
  56. intuned_runtime-1.0.0/runtime_helpers/__init__.py +5 -0
  57. intuned_runtime-1.0.0/runtime_helpers/py.typed +0 -0
@@ -0,0 +1,42 @@
1
+ Acceptance
2
+ By using the software, you agree to all of the terms and conditions below.
3
+
4
+ Copyright License
5
+ The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below.
6
+
7
+ Limitations
8
+ You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software.
9
+
10
+ You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key.
11
+
12
+ You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
13
+
14
+ Patents
15
+ The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
16
+
17
+ Notices
18
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
19
+
20
+ If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
21
+
22
+ No Other Rights
23
+ These terms do not imply any licenses other than those expressly granted in these terms.
24
+
25
+ Termination
26
+ If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
27
+
28
+ No Liability
29
+ As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
30
+
31
+ Definitions
32
+ The licensor is the entity offering these terms, and the software is the software the licensor makes available under these terms, including any portion of it.
33
+
34
+ you refers to the individual or entity agreeing to these terms.
35
+
36
+ your company is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
37
+
38
+ your licenses are all the licenses granted to you for the software under these terms.
39
+
40
+ use means anything you do with the software requiring one of your licenses.
41
+
42
+ trademark means trademarks, service marks, and similar rights.
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.3
2
+ Name: intuned-runtime
3
+ Version: 1.0.0
4
+ Summary: Runtime commands for Intuned platform Python scrapers
5
+ License: Elastic-2.0
6
+ Keywords: runtime,intuned
7
+ Author: Intuned Developers
8
+ Author-email: engineering@intunedhq.com
9
+ Requires-Python: >=3.9,<4.0
10
+ Classifier: License :: Other/Proprietary License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
19
+ Requires-Dist: arguably (>=1.3.0,<2.0.0)
20
+ Requires-Dist: gitpython (>=3.1.43,<4.0.0)
21
+ Requires-Dist: httpx (>=0.23.0,<1)
22
+ Requires-Dist: more-termcolor (>=1.1.3,<2.0.0)
23
+ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
24
+ Requires-Dist: pydantic (>=2.10.6,<3.0.0)
25
+ Requires-Dist: pyright (>=1.1.387,<2.0.0)
26
+ Requires-Dist: python-dotenv (==1.0.1)
27
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
28
+ Requires-Dist: ruff (>=0.7.2,<0.8.0)
29
+ Requires-Dist: semver (>=3.0.4,<4.0.0)
30
+ Requires-Dist: tenacity (>=8.5.0,<9.0.0)
31
+ Requires-Dist: toml (>=0.10.2,<0.11.0)
32
+ Requires-Dist: waitress (>=3.0.1,<4.0.0)
33
+ Description-Content-Type: text/markdown
34
+
35
+ # Intuned Python Runtime
36
+
37
+ Runtime commands for Intuned platform Python automations.
38
+
39
+ ## Dependencies
40
+
41
+ - Requires Python 3.12 or higher.
42
+ - Install poetry: `pip install poetry`
43
+ - Install dependencies: `poetry install`
44
+ - Activate virtual environment: `poetry shell`
45
+ - Now you have access to `intuned` cli from within project.
46
+
47
+ ## Install globally
48
+
49
+ - This project can be installed globally on the system to use `intuned` cli anywhere
50
+ - Make sure you are not in a virtual environment. `which python` should point to system python.
51
+ - If you are, `deactivate` to exit virtual environment. Or open in an external terminal (from outside vscode if it doesn't work)
52
+ - Run `pip install -e .` from the root of the project.
53
+
54
+ ## Commands
55
+
56
+ All commands have `-h` flag to show help.
57
+
58
+ ### `intuned init`
59
+
60
+ - Initializes a project. Creates `pyproject.toml`, `Intuned.json` and `README.md` files.
61
+ - Prompts for confirmation for each file that already exists.
62
+ - Options:
63
+ - `--yes/-y` flag to overwrite all files.
64
+ - `--no/-n` flag to not overwrite any files.
65
+
66
+ ### `intuned publish-packages`
67
+
68
+ - Publishes packages to `python-packages` repository.
69
+ - Options:
70
+ - `--sdk` flag to publish SDK package. Creates `sdk-<version>` and `sdk-latest` tags for the published version.
71
+ - `--runtime` flag to publish runtime package. Creates `runtime-<version>` and `runtime-latest` tags for the published version.
72
+ - `--overwrite` flag to overwrite the existing version if it exists.
73
+ - `--show-diff` flag to show the diff of the package before publishing. You need to configure a diff tool to be used for `git difftool` command in your git config. [How to configure VS Code as a diff tool](https://www.roboleary.net/vscode/2020/09/15/vscode-git.html#tldr).
74
+ - `--no-latest` flag to not release `latest` tag for the published version.
75
+ - Uses the version specified in `pyproject.toml` of each package respectively.
76
+ - Uses WebApp directory specified in `WEBAPP_REPO` environment variable or tries to resolve it (only works if installed globally with `-e` flag).
77
+ - Uses `python-packages` directory to be sister to WebApp directory `<webapp path>/../python-packages`.
78
+ - These packages are used on deployed apps.
79
+
80
+ ### `intuned project run`
81
+
82
+ - Runs the project.
83
+ - `--mode` to specify the mode to run. Default is `sample`.
84
+ - `--mode sample` extends a sample of payloads to run.
85
+ - `--mode full` runs all extended payloads.
86
+ - `--mode single` runs the initial API only.
87
+ - `--api-name <name>` to specify the initial API to run. Defaults to `default`
88
+ - `--params <params json>` to specify the parameters to the initial API.
89
+ - `--sample-config-str '{<api name>: <sample size>, ...}` to specify the sample config. Only used with `--mode sample`.
90
+ - `--no-headless` to disable headless mode.
91
+
92
+ ### `intuned project deploy`
93
+
94
+ - Deploys a project and starts a default job.
95
+ - Options:
96
+ - `--workspace-info '{"environment_url": <>, "workspace_id": <>, "api_key": <>}'` to specify the workspace info.
97
+ - `--workspace-info-path` to specify the path to a JSON file containing workspace info.
98
+ - `-y/--yes` to skip confirmation.
99
+ - `--project-name` to specify the project name. Resolves the name if not provided.
100
+ - Resolves `.gitignore` from current/parent directories to decide what to deploy.
101
+ - Resolves `.env` from current/parent directories to get environment variables to deploy.
102
+ - Resolves project name from the current/parent directory name if not provided.
103
+
104
+ ### `intuned project serve`
105
+
106
+ - Serves the project as an HTTP server.
107
+ - Options:
108
+ - `--env development/production` to specify the environment to run the server.
109
+ - Development runs using Flask's development server.
110
+ - Production runs using Waitress.
111
+ - `--debug` to run the development server in debug mode. Not supported in production.
112
+ - This is used on deployed apps.
113
+
@@ -0,0 +1,78 @@
1
+ # Intuned Python Runtime
2
+
3
+ Runtime commands for Intuned platform Python automations.
4
+
5
+ ## Dependencies
6
+
7
+ - Requires Python 3.12 or higher.
8
+ - Install poetry: `pip install poetry`
9
+ - Install dependencies: `poetry install`
10
+ - Activate virtual environment: `poetry shell`
11
+ - Now you have access to `intuned` cli from within project.
12
+
13
+ ## Install globally
14
+
15
+ - This project can be installed globally on the system to use `intuned` cli anywhere
16
+ - Make sure you are not in a virtual environment. `which python` should point to system python.
17
+ - If you are, `deactivate` to exit virtual environment. Or open in an external terminal (from outside vscode if it doesn't work)
18
+ - Run `pip install -e .` from the root of the project.
19
+
20
+ ## Commands
21
+
22
+ All commands have `-h` flag to show help.
23
+
24
+ ### `intuned init`
25
+
26
+ - Initializes a project. Creates `pyproject.toml`, `Intuned.json` and `README.md` files.
27
+ - Prompts for confirmation for each file that already exists.
28
+ - Options:
29
+ - `--yes/-y` flag to overwrite all files.
30
+ - `--no/-n` flag to not overwrite any files.
31
+
32
+ ### `intuned publish-packages`
33
+
34
+ - Publishes packages to `python-packages` repository.
35
+ - Options:
36
+ - `--sdk` flag to publish SDK package. Creates `sdk-<version>` and `sdk-latest` tags for the published version.
37
+ - `--runtime` flag to publish runtime package. Creates `runtime-<version>` and `runtime-latest` tags for the published version.
38
+ - `--overwrite` flag to overwrite the existing version if it exists.
39
+ - `--show-diff` flag to show the diff of the package before publishing. You need to configure a diff tool to be used for `git difftool` command in your git config. [How to configure VS Code as a diff tool](https://www.roboleary.net/vscode/2020/09/15/vscode-git.html#tldr).
40
+ - `--no-latest` flag to not release `latest` tag for the published version.
41
+ - Uses the version specified in `pyproject.toml` of each package respectively.
42
+ - Uses WebApp directory specified in `WEBAPP_REPO` environment variable or tries to resolve it (only works if installed globally with `-e` flag).
43
+ - Uses `python-packages` directory to be sister to WebApp directory `<webapp path>/../python-packages`.
44
+ - These packages are used on deployed apps.
45
+
46
+ ### `intuned project run`
47
+
48
+ - Runs the project.
49
+ - `--mode` to specify the mode to run. Default is `sample`.
50
+ - `--mode sample` extends a sample of payloads to run.
51
+ - `--mode full` runs all extended payloads.
52
+ - `--mode single` runs the initial API only.
53
+ - `--api-name <name>` to specify the initial API to run. Defaults to `default`
54
+ - `--params <params json>` to specify the parameters to the initial API.
55
+ - `--sample-config-str '{<api name>: <sample size>, ...}` to specify the sample config. Only used with `--mode sample`.
56
+ - `--no-headless` to disable headless mode.
57
+
58
+ ### `intuned project deploy`
59
+
60
+ - Deploys a project and starts a default job.
61
+ - Options:
62
+ - `--workspace-info '{"environment_url": <>, "workspace_id": <>, "api_key": <>}'` to specify the workspace info.
63
+ - `--workspace-info-path` to specify the path to a JSON file containing workspace info.
64
+ - `-y/--yes` to skip confirmation.
65
+ - `--project-name` to specify the project name. Resolves the name if not provided.
66
+ - Resolves `.gitignore` from current/parent directories to decide what to deploy.
67
+ - Resolves `.env` from current/parent directories to get environment variables to deploy.
68
+ - Resolves project name from the current/parent directory name if not provided.
69
+
70
+ ### `intuned project serve`
71
+
72
+ - Serves the project as an HTTP server.
73
+ - Options:
74
+ - `--env development/production` to specify the environment to run the server.
75
+ - Development runs using Flask's development server.
76
+ - Production runs using Waitress.
77
+ - `--debug` to run the development server in debug mode. Not supported in production.
78
+ - This is used on deployed apps.
@@ -0,0 +1,45 @@
1
+ import sys
2
+ import traceback
3
+
4
+ import arguably
5
+ from dotenv import find_dotenv
6
+ from dotenv import load_dotenv
7
+ from more_termcolor import bold # type: ignore
8
+ from more_termcolor import red # type: ignore
9
+
10
+ from runtime.context.context import IntunedContext
11
+
12
+ from . import commands
13
+
14
+
15
+ def run():
16
+ dotenv = find_dotenv(usecwd=True)
17
+ if dotenv:
18
+ load_dotenv(dotenv, override=True)
19
+ try:
20
+ with IntunedContext():
21
+ arguably.run()
22
+ except ValueError as e:
23
+ print(bold(red(str(e))))
24
+ sys.exit(1)
25
+ except KeyboardInterrupt:
26
+ print(bold(red("\n🛑 Aborted")))
27
+ sys.exit(1)
28
+ except Exception as e:
29
+ tb_list = traceback.extract_tb(e.__traceback__)
30
+
31
+ DEPTH_THRESHOLD = 4
32
+
33
+ if len(tb_list) > DEPTH_THRESHOLD:
34
+ relevant_frames = tb_list[DEPTH_THRESHOLD:] # Show last 2 frames - adjust as needed
35
+ formatted_tb = "".join(traceback.format_list(relevant_frames))
36
+ print(f"Traceback (most recent call last):\n{formatted_tb}{type(e).__name__}: {str(e)}")
37
+ else:
38
+ # For shallow traces, show everything
39
+ print("".join(traceback.format_exception(type(e), e, e.__traceback__)))
40
+
41
+ print(red(bold(f"❌ An error occurred: {e}")))
42
+ sys.exit(1)
43
+
44
+
45
+ __all__ = ["commands", "run"]
@@ -0,0 +1,25 @@
1
+ from .ai_source import ai_source # type: ignore
2
+ from .ai_source import ai_source__deploy # type: ignore
3
+ from .browser import browser__save_state # type: ignore
4
+ from .init import init # type: ignore
5
+ from .project import project # type: ignore
6
+ from .project import project__run # type: ignore
7
+ from .project import project__type_check # type: ignore
8
+ from .project.auth_session import project__auth_session__check # type: ignore
9
+ from .project.auth_session import project__auth_session__create # type: ignore
10
+ from .project.auth_session import project__auth_session__load # type: ignore
11
+ from .publish_packages import publish_packages # type: ignore
12
+
13
+ __all__ = [
14
+ "project__run",
15
+ "publish_packages",
16
+ "init",
17
+ "project",
18
+ "ai_source__deploy",
19
+ "ai_source",
20
+ "project__auth_session__load",
21
+ "project__auth_session__create",
22
+ "project__auth_session__check",
23
+ "project__type_check",
24
+ "browser__save_state",
25
+ ]
@@ -0,0 +1,4 @@
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"]
@@ -0,0 +1,10 @@
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
@@ -0,0 +1,64 @@
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 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")))
@@ -0,0 +1,3 @@
1
+ from .save_state import browser__save_state # type: ignore
2
+
3
+ __all__ = ["browser__save_state"]
@@ -0,0 +1,32 @@
1
+ import json
2
+ import os
3
+
4
+ import arguably
5
+
6
+ from runtime.browser import launch_chromium
7
+ from runtime.browser.storage_state import get_storage_state
8
+
9
+
10
+ @arguably.command # type: ignore
11
+ async def browser__save_state(
12
+ *,
13
+ cdp_address: str,
14
+ output_path: str,
15
+ ):
16
+ """
17
+ Load an auth session to a browser.
18
+
19
+ Args:
20
+ cdp_address (str): The CDP address of the browser to save the state from.
21
+ output_path (str): Path to save browser state to.
22
+ """
23
+
24
+ async with launch_chromium(
25
+ cdp_address=cdp_address,
26
+ ) as (context, _):
27
+ storage_state = await get_storage_state(context)
28
+
29
+ path = os.path.join(os.getcwd(), output_path)
30
+ os.makedirs(os.path.dirname(path), exist_ok=True)
31
+ with open(path, "w") as f:
32
+ json.dump(storage_state.model_dump(by_alias=True), f, indent=2)
@@ -0,0 +1,127 @@
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
+ )
@@ -0,0 +1,20 @@
1
+ from .auth_session import project__auth_session__check # type: ignore
2
+ from .auth_session import project__auth_session__create # type: ignore
3
+ from .auth_session import project__auth_session__load # type: ignore
4
+ from .project import project # type: ignore
5
+ from .run import project__run # type: ignore
6
+ from .run_interface import project__run_interface # type: ignore
7
+ from .type_check import project__type_check # type: ignore
8
+ from .upgrade import project__upgrade # type: ignore
9
+
10
+ __all__ = [
11
+ "run",
12
+ "project__run",
13
+ "project__type_check",
14
+ "project",
15
+ "project__auth_session__load",
16
+ "project__auth_session__create",
17
+ "project__auth_session__check",
18
+ "project__upgrade",
19
+ "project__run_interface",
20
+ ]
@@ -0,0 +1,5 @@
1
+ from .check import project__auth_session__check # type: ignore
2
+ from .create import project__auth_session__create # type: ignore
3
+ from .load import project__auth_session__load # type: ignore
4
+
5
+ __all__ = ["project__auth_session__check", "project__auth_session__create", "project__auth_session__load"]