intuned-runtime 1.1.3__py3-none-any.whl → 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,21 @@
1
+ from typing import Any
2
+
1
3
  import arguably
2
4
 
3
- from intuned_cli.controller.init import check_empty_directory
4
- from intuned_cli.controller.init import python_template_name
5
- from intuned_cli.controller.init import write_project_from_file_tree
5
+ from intuned_cli.utils.error import CLIError
6
6
 
7
7
 
8
8
  @arguably.command # type: ignore
9
- async def init():
9
+ async def init(
10
+ *args: Any,
11
+ ):
10
12
  """
11
- Initializes current app, creating pyproject.toml and Intuned.json files. Will ask for confirmation before overwriting existing files.
12
-
13
- Args:
14
- template_name (str | None): Name of the template to use.
13
+ Deprecated: Initialize a new Intuned project in the current directory.
15
14
 
16
15
  Returns:
17
16
  None
18
17
  """
19
- is_target_directory_empty = await check_empty_directory()
20
-
21
- await write_project_from_file_tree(python_template_name, is_target_directory_empty)
18
+ raise CLIError(
19
+ "[red bold]The init command has been deprecated. Please use[/red bold] [cyan italic]npx create-intuned-project[/cyan italic] [red bold]instead.[/red bold]",
20
+ auto_color=False,
21
+ )
@@ -2,4 +2,4 @@ import os
2
2
 
3
3
 
4
4
  def get_base_url():
5
- return os.environ.get("INTUNED_API_DOMAIN", "https://app.intuned.io")
5
+ return os.environ.get("INTUNED_API_BASE_URL") or os.environ.get("INTUNED_API_DOMAIN") or "https://app.intuned.io"
@@ -7,6 +7,7 @@ from dotenv import load_dotenv
7
7
  from more_termcolor import bold # type: ignore
8
8
  from more_termcolor import red # type: ignore
9
9
 
10
+ from intuned_internal_cli.utils.setup_ide_functions_token import setup_ide_functions_token
10
11
  from runtime.context.context import IntunedContext
11
12
 
12
13
  from . import commands
@@ -18,6 +19,7 @@ def run():
18
19
  load_dotenv(dotenv, override=True)
19
20
  try:
20
21
  with IntunedContext():
22
+ setup_ide_functions_token()
21
23
  arguably.run(name="intuned-internal")
22
24
  except ValueError as e:
23
25
  print(bold(red(str(e))))
@@ -0,0 +1,10 @@
1
+ import os
2
+
3
+ from runtime.context.context import IntunedContext
4
+
5
+
6
+ def setup_ide_functions_token():
7
+ ide_functions_token = os.getenv("INTUNED_AUTHORING_SESSION_BACKEND_FUNCTIONS_TOKEN")
8
+ if ide_functions_token is None:
9
+ return
10
+ IntunedContext.current().functions_token = ide_functions_token
@@ -0,0 +1,5 @@
1
+ from runtime.helpers import extend_payload
2
+ from runtime.helpers import extend_timeout
3
+ from runtime.helpers.get_auth_session_parameters import get_auth_session_parameters
4
+
5
+ __all__ = ["extend_payload", "extend_timeout", "get_auth_session_parameters"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: intuned-runtime
3
- Version: 1.1.3
3
+ Version: 1.2.0
4
4
  Summary: Runtime commands for Intuned platform Python scrapers
5
5
  License: Elastic-2.0
6
6
  Keywords: runtime,intuned
@@ -7,26 +7,23 @@ intuned_cli/commands/attempt_authsession_create_command.py,sha256=ynAKlNoHuaVPgx
7
7
  intuned_cli/commands/attempt_command.py,sha256=7NZC2dXA8GViCH3ZS2PMziR43hv2RmS6-jgW7l9bu40,253
8
8
  intuned_cli/commands/command.py,sha256=b0OlQIFhoCjCo5QIerfysccBKcU9iIsvqiU7oxshA2M,727
9
9
  intuned_cli/commands/deploy_command.py,sha256=0XG8lo5fGeorZMxMtEx12EaqLFMvmFYJ7Zu9sgJCmQ8,1540
10
- intuned_cli/commands/init_command.py,sha256=MV5WR5o4KH1J_Zai6K5S84NG41KZbsJ-I8NPGXurt2o,671
10
+ intuned_cli/commands/init_command.py,sha256=JIDr9vY_SRKCvVbXE_lCEeHQlmC48LMZz0cghMPAs90,492
11
11
  intuned_cli/commands/run_api_command.py,sha256=Y6FkSFI9wybuoW204YqOAiQ794__hIw12Eaf9px_ovE,3013
12
12
  intuned_cli/commands/run_authsession_command.py,sha256=kM_TANy8M3yx8iBUsgSDO42byzccikLOd9KJfytfLmQ,269
13
13
  intuned_cli/commands/run_authsession_create_command.py,sha256=SiuIZ7LTMqT3gnd8DUt-VmP3cyuA0I_i27daI3IJ2tw,2089
14
14
  intuned_cli/commands/run_authsession_update_command.py,sha256=Op7epDgvEhjp17qs2dIXerTckHz7wlOsZsBDp8UJLjI,2145
15
15
  intuned_cli/commands/run_authsession_validate_command.py,sha256=5eET02paijq1f1rzsheINvAqVYj1JGUA_iGD5Py3LVM,2008
16
16
  intuned_cli/commands/run_command.py,sha256=JN1yCewcyb4zFquMcv0wEZ_aRmhJZIBMheY8L9yBeDE,245
17
- intuned_cli/constants/__init__.py,sha256=AIfIQYQ55zSdGKL2p15wv4H9ANeRjYEkeUiObu6JFt8,37
18
- intuned_cli/constants/readme.py,sha256=3OUkZNmz9kss7hA3V2j5h49dv7ADy4LON5-iJkrJUA4,5240
19
17
  intuned_cli/controller/__test__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
18
  intuned_cli/controller/__test__/test_api.py,sha256=8Hk3V52qKhWIqjirKFwN68Tv5er70gTxemjI35HyZiU,19295
21
19
  intuned_cli/controller/__test__/test_authsession.py,sha256=y7O3dkDPHZTf2W7WRLEhysYYRati0hg93-J8BvGjRUM,35110
22
20
  intuned_cli/controller/api.py,sha256=1wHgatavA5zr6kYMf1BJ3lC5JR1IvlVBiab_ahOSVnY,7172
23
21
  intuned_cli/controller/authsession.py,sha256=z8C97T-beEORNemLFx2x_JsHr2gXRakwKGV3Rgivnu8,14309
24
22
  intuned_cli/controller/deploy.py,sha256=5cQgtpT2nDQ5XSUnIoeBR9xdyVoLWcY-2btuUxUD7Es,12343
25
- intuned_cli/controller/init.py,sha256=TfkPkq9rbYam2-fchwrpMIt9GJIkY-TQnWpwvPomRZE,3774
26
23
  intuned_cli/types.py,sha256=Lsykui4mbq5T1_1L7Gg5OZpJvCOmaz9EiQcZVfUEoLc,766
27
24
  intuned_cli/utils/api_helpers.py,sha256=57gvXVYM_9hMGIkMqSEN_jzs3mYWlXzinPjYXzzqgg8,1122
28
25
  intuned_cli/utils/auth_session_helpers.py,sha256=acKAPUjOfdybstLur4Lk3huaLFP2Ipl4AjPSqQPQLzY,1899
29
- intuned_cli/utils/backend.py,sha256=NFMAqHFslxad9KYirUz3b0BsRz1aQqOGhZRUJdEiO8k,106
26
+ intuned_cli/utils/backend.py,sha256=9HmaIvyKRkybUL-lEiJYHbIclinEZEBNBFLUG0hNC0A,150
30
27
  intuned_cli/utils/confirmation.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
28
  intuned_cli/utils/console.py,sha256=jgin2xB-0kpANPMoiDBOnWhrc8Ey5zT4IHRxQa8f5CQ,93
32
29
  intuned_cli/utils/error.py,sha256=DmNlXBb7zfpHDRya00ouEcRgUEZuGaTqIy1SIjDWVfo,842
@@ -34,7 +31,7 @@ intuned_cli/utils/exclusions.py,sha256=Qe7NkWA3lsX73dOC9WprdD0KyYc_vuiwkrUCwD105
34
31
  intuned_cli/utils/get_auth_parameters.py,sha256=HmMSjBE8bPulkUdX319Ipr383Ko2Gtz3y8_WT9CK3Kw,798
35
32
  intuned_cli/utils/import_function.py,sha256=UmE2yw5std1ENMFdBU-TUBuQ01qsv7Qr5ElnAhqE6Yc,453
36
33
  intuned_cli/utils/timeout.py,sha256=DkoeoU9XvKKKSQ06CpwqcNvxWqLPAOVuAMw6kSr4Tuo,886
37
- intuned_internal_cli/__init__.py,sha256=iz-mTdcPhNCknHZzdO5-9PHFSapbXiLCwg_cTaYfww4,1337
34
+ intuned_internal_cli/__init__.py,sha256=MLkUSYcMp4qMvCHeRgsPDzUlz10XwiAHAsgoNvzl6MA,1468
38
35
  intuned_internal_cli/commands/__init__.py,sha256=gZ-r8UIXvRakeCfvmOZCNWr8CJHBcYzRzbMjyKYPXV0,1003
39
36
  intuned_internal_cli/commands/ai_source/__init__.py,sha256=lg7owgcK8owNn2a4VBUP9RKxzFsLruhtnnQV0F_z6pc,149
40
37
  intuned_internal_cli/commands/ai_source/ai_source.py,sha256=2woQtCmhxKvLfEz832eUoCT9gMsuSvEE6rMnHSYXC7w,138
@@ -58,10 +55,12 @@ intuned_internal_cli/logger.py,sha256=bZK3q-KUdGxk_qzDb6pn-n0LOhKJvi6a9p8oSwZtq3
58
55
  intuned_internal_cli/utils/ai_source_project.py,sha256=xUCM6p3i1XN4bJbuQz8LCzeI4BwqAdSvCl_vwDAEi0k,831
59
56
  intuned_internal_cli/utils/code_tree.py,sha256=1wfxZoQ5kRCfqs2SEPAicbAIPTiD6P1LxSuwYu_eeaI,2790
60
57
  intuned_internal_cli/utils/run_apis.py,sha256=Zee4zkgt9R8XY1XCGzj2Nc4zJ3jlRz1xnO493wotuWw,4690
58
+ intuned_internal_cli/utils/setup_ide_functions_token.py,sha256=72-hf5HOPO9hj_eo3MTSVEPIwtkaIma_NRepsw_FHQM,304
61
59
  intuned_internal_cli/utils/unix_socket.py,sha256=UISmkJMHrir5iBLUm6vxC3uzTGIFyOk_wa0C9LUw4Cc,1889
60
+ intuned_runtime/__init__.py,sha256=XBrEiE9yNC8Lgn8NgIkqNXbI6e4ap237E83Zj_nlhCQ,249
62
61
  runtime/__init__.py,sha256=87gDXuxUv_kGzQfuB1mh6DF-dDysJN8r684c7jGnHxc,144
63
62
  runtime/backend_functions/__init__.py,sha256=j2EaK4FK8bmdFtqc5FxtFwx1KhIn_7qKPChrrAhJI3s,119
64
- runtime/backend_functions/_call_backend_function.py,sha256=zuaf4mwYHSm5RTedhMdU66jAMAzdPYPMmXJE_V1xoyk,2869
63
+ runtime/backend_functions/_call_backend_function.py,sha256=h6UUsQ2pLUTbEQNYM1TLdesc5yWWaUrPUaTbCtCIxlU,2769
65
64
  runtime/backend_functions/get_auth_session_parameters.py,sha256=pOvB7XiWpphEuBpazdKALw9EWgBU1PeY3gkzBfVLpkc,869
66
65
  runtime/browser/__init__.py,sha256=EPWfa4ZmdR8GJqh2qcsx1ZvHmCYiUYrQ-zeHYVapH9s,285
67
66
  runtime/browser/helpers.py,sha256=b1Xp005adbl7ZeJrSEYgH2OPzrZEHxTPgGTsnS3OqS0,554
@@ -74,7 +73,7 @@ runtime/context/context.py,sha256=pl_0x77_d5CiAznz1qGSk6o9cW-msNvlCt-2eFoMKlA,17
74
73
  runtime/env.py,sha256=OXxzLpM56AJVlX0gmG7Ph82xAfqZboW3kv2232lzXb4,306
75
74
  runtime/errors/__init__.py,sha256=oqiBSvT_yFLQ3hG0AbCUA3WYFaxkTDVkDMSy59xvBCo,688
76
75
  runtime/errors/auth_session_errors.py,sha256=6b4XTI8UCDHDPX4jEA8_HyrNUp4VZ1TrEA8DRh6Z3rM,228
77
- runtime/errors/run_api_errors.py,sha256=LdmOEHoUk7wjWSk0HQYqslfJNNmxVgga_0bankzvX-s,3341
76
+ runtime/errors/run_api_errors.py,sha256=Bjs_gsgdIUbVLN67E_s-804qB2lyzIljDEaAcymgwK0,3906
78
77
  runtime/errors/trace_errors.py,sha256=Lzfo0sH3zGaWz1kn5DHcAXQMn3aR2y2bnauj6xP1LYE,110
79
78
  runtime/helpers/__init__.py,sha256=jozYPKHgZJ7Na5U1Wjt83egzjPATMZ_OMInEI6swSbY,234
80
79
  runtime/helpers/extend_payload.py,sha256=towZF08WTpTTDBL4AV1bUU3XpKAQHEB66kGUfTICDe0,246
@@ -85,15 +84,15 @@ runtime/run/__init__.py,sha256=zxMYVb7hn147YTrhMLsrcX6-KTd71HLrYHstJOWeWXQ,52
85
84
  runtime/run/intuned_settings.py,sha256=vy2-ktEzUfUp5Z90dp3l7jPKHNjgB-8GSMDgAY-rYaU,1074
86
85
  runtime/run/playwright_constructs.py,sha256=EIfnRlAi1k1wRiTT2OpPFVmrWwEeeiryuORibaLD1Xw,573
87
86
  runtime/run/pydantic_encoder.py,sha256=wJCljwwINSICvCJ0i2izp2RLkQ15nYglUQCyyjM40Jk,332
88
- runtime/run/run_api.py,sha256=vSf7kNmiUrmO4iXiqdLsZsNc0-vC8nm4r3HK2OAN0DY,8984
87
+ runtime/run/run_api.py,sha256=JiO-UBpCBP7H4TZbKXmYmGZmYrkqidqEg7epaxj_3jA,10105
89
88
  runtime/run/traces.py,sha256=fKzh11LqV47ujgq_9I2tdp-dgld566wffWaHwU_4gis,1123
90
89
  runtime/types/__init__.py,sha256=IJkDfqsau8F8R_j8TO6j-JwW4ElQr6aU6LNaWRehg5U,401
91
90
  runtime/types/payload.py,sha256=sty8HgDEn3nJbZrwEOMCXyuG7_ICGDwlBIIWSON5ABY,124
92
91
  runtime/types/run_types.py,sha256=-j-XKXfRkzlyoW-Doe0og2jbqMMQWjOTIUqRFEc8lHA,4582
93
92
  runtime_helpers/__init__.py,sha256=XBrEiE9yNC8Lgn8NgIkqNXbI6e4ap237E83Zj_nlhCQ,249
94
93
  runtime_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
- intuned_runtime-1.1.3.dist-info/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
96
- intuned_runtime-1.1.3.dist-info/METADATA,sha256=TKO1oRYe4tlBXONrqGiMOlcyYjIwx74ZdKwAoNlkh9g,5299
97
- intuned_runtime-1.1.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
98
- intuned_runtime-1.1.3.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
99
- intuned_runtime-1.1.3.dist-info/RECORD,,
94
+ intuned_runtime-1.2.0.dist-info/LICENSE,sha256=9LIjQdgyU_ptzNIfItNCR7VmEHqYnrY1f1XwOreKFI0,3714
95
+ intuned_runtime-1.2.0.dist-info/METADATA,sha256=-aElUUcnS5RP8i05pbZ6fe2JEINpwjTXWxnAjhv6DzI,5299
96
+ intuned_runtime-1.2.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
97
+ intuned_runtime-1.2.0.dist-info/entry_points.txt,sha256=ToMS2cqDeRmF1FGkflwoeD-Xz6jJV5p1zIbw9G7IxMg,85
98
+ intuned_runtime-1.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -28,9 +28,6 @@ async def call_backend_function[T: BaseModel](
28
28
  raise Exception("No workspace ID or project ID found.")
29
29
 
30
30
  context = IntunedContext.current()
31
- if context.run_context is None:
32
- # todo
33
- raise Exception("No run context found.")
34
31
 
35
32
  async with AsyncClient() as client:
36
33
  if context.functions_token:
@@ -14,6 +14,7 @@ RunErrorCode = Literal[
14
14
  "MaxLevelsExceededError",
15
15
  "AutomationError",
16
16
  "InternalInvalidInputError",
17
+ "ResultTooBigError",
17
18
  ]
18
19
 
19
20
 
@@ -122,3 +123,18 @@ class InternalInvalidInputError(RunApiError):
122
123
  "InternalInvalidInputError",
123
124
  )
124
125
  self.details = details
126
+
127
+
128
+ class ResultTooBigError(RunApiError):
129
+ def __init__(self, size_in_bytes: int, max_size_in_bytes: int):
130
+ size_mb = round((size_in_bytes / 1024 / 1024) * 100) / 100
131
+ max_size_mb = round((max_size_in_bytes / 1024 / 1024) * 100) / 100
132
+
133
+ super().__init__(
134
+ f"Automation result is too big. Size: {size_mb}MB, Max allowed: {max_size_mb}MB",
135
+ "ResultTooBigError",
136
+ )
137
+ self.details = {
138
+ "sizeInBytes": size_in_bytes,
139
+ "maxSizeInBytes": max_size_in_bytes,
140
+ }
runtime/run/run_api.py CHANGED
@@ -21,6 +21,7 @@ from runtime.browser.storage_state import get_storage_state
21
21
  from runtime.browser.storage_state import set_storage_state
22
22
  from runtime.context import IntunedContext
23
23
  from runtime.errors.run_api_errors import InvalidSessionError
24
+ from runtime.errors.run_api_errors import ResultTooBigError
24
25
  from runtime.errors.run_api_errors import RunApiError
25
26
  from runtime.types import RunAutomationSuccessResult
26
27
  from runtime.types.run_types import PayloadToAppend
@@ -34,6 +35,15 @@ from .playwright_constructs import get_production_playwright_constructs
34
35
  from .pydantic_encoder import PydanticEncoder
35
36
 
36
37
 
38
+ def get_object_size_in_bytes(obj: Any) -> int:
39
+ """Calculate the approximate size of an object in bytes."""
40
+ try:
41
+ return len(json.dumps(obj, cls=PydanticEncoder).encode("utf-8"))
42
+ except (TypeError, ValueError):
43
+ # If JSON serialization fails, return a conservative estimate
44
+ return len(str(obj).encode("utf-8"))
45
+
46
+
37
47
  def import_function_from_api_dir(
38
48
  *,
39
49
  file_path: str,
@@ -186,11 +196,22 @@ async def run_api(
186
196
  except TypeError as e:
187
197
  raise AutomationError(TypeError("Result is not JSON serializable")) from e
188
198
 
199
+ # Check if result size exceeds 2MB limit
200
+ MAX_RESULT_SIZE_BYTES = 2 * 1024 * 1024 # 2MB
201
+ result_size_in_bytes = get_object_size_in_bytes(automation_result)
202
+ if result_size_in_bytes > MAX_RESULT_SIZE_BYTES:
203
+ raise ResultTooBigError(result_size_in_bytes, MAX_RESULT_SIZE_BYTES)
204
+
189
205
  response = RunAutomationSuccessResult(
190
206
  result=automation_result,
191
207
  )
192
208
  extended_payloads = IntunedContext.current().extended_payloads
193
209
  if extended_payloads:
210
+ for payload in extended_payloads:
211
+ try:
212
+ payload["parameters"] = json.loads(json.dumps(payload["parameters"], cls=PydanticEncoder))
213
+ except TypeError as e:
214
+ raise AutomationError(TypeError("Parameters are not JSON serializable")) from e
194
215
  response.payload_to_append = [
195
216
  PayloadToAppend(
196
217
  api_name=payload["api"],
@@ -1 +0,0 @@
1
- from .readme import readme as readme
@@ -1,134 +0,0 @@
1
- readme = r"""# Intuned CLI
2
-
3
- ## Development Commands
4
-
5
- For each command, add `--help` to see more details and options.
6
-
7
- ### Initialize a Project
8
- `pipx run --spec intuned-runtime intuned init`
9
-
10
- Once you install the dependencies, you will have `intuned` command available in your environment.
11
-
12
- ### Run an API
13
- `intuned run api <api-name> <parameters>`
14
-
15
-
16
- ### Deploy a Project
17
- `intuned deploy [project-name]`
18
-
19
-
20
-
21
- ### Create an auth session
22
- `intuned run authsession create <parameters>`
23
-
24
-
25
-
26
- ### Validate an auth session
27
- `intuned run authsession validate <auth-session-name>`
28
-
29
- ## Configuration
30
-
31
- ### Environment Variables and Settings
32
- - `workspaceId`: Your Intuned workspace ID ([How to get your workspaceId](https://docs.intunedhq.com/docs/guides/platform/how-to-get-a-workspace-id))
33
- - Set in `intuned.json` file under the `workspaceId` property
34
- - Or provide via CLI with `--workspace-id` flag during deployment
35
-
36
- - `projectName`: The name of your Intuned project
37
- - Set in `intuned.json` file under the `projectName` property
38
- - Or override via command line when deploying with `yarn intuned deploy my-project-name` or `npm run intuned deploy my-project-name`
39
-
40
- - `INTUNED_API_KEY`: Your Intuned API key
41
- - Set as an environment variable: `export INTUNED_API_KEY=your_api_key_here`
42
- - Or include in your .env file for development
43
- - Or provide via CLI with `--api-key` flag during deployment
44
-
45
- ## Project Structure
46
-
47
- ### Generated Artifacts
48
- - `./intuned.json`: Project configuration file
49
- - `./api`: Folder containing API implementation files
50
- - `./auth-sessions`: Folder containing auth-session APIs if you use them
51
- - `./auth-sessions-instances`: Folder containing auth session instances
52
-
53
- ## Types of auth sessions
54
- - `MANUAL`: Manual auth session, records the session using a recorder and stores it in the `auth-sessions-instances` folder
55
- - `API`: Auth session created via create API, stores the session in the `auth-sessions-instances` folder
56
-
57
- ### Notes
58
- - All commands should be run from the project root directory
59
- - Verify you're in the correct location by confirming the presence of package.json and intuned.json
60
- - Running commands from subdirectories may result in errors
61
- - You can manage your deployed projects through the Intuned platform
62
-
63
- ## `Intuned.json` Reference
64
- ```jsonc
65
- {
66
- // Your Intuned workspace ID.
67
- // Optional - If not provided here, it must be supplied via the \`--workspace-id\` flag during deployment.
68
- "workspaceId": "your_workspace_id",
69
-
70
- // The name of your Intuned project.
71
- // Optional - If not provided here, it must be supplied via the command line when deploying.
72
- "projectName": "your_project_name",
73
-
74
- // Replication settings
75
- "replication": {
76
- // The maximum number of concurrent executions allowed via Intuned API. This does not affect jobs.
77
- // A number of machines equal to this will be allocated to handle API requests.
78
- // Not applicable if api access is disabled.
79
- "maxConcurrentRequests": 1,
80
-
81
- // The machine size to use for this project. This is applicable for both API requests and jobs.
82
- // "standard": Standard machine size (6 shared vCPUs, 2GB RAM)
83
- // "large": Large machine size (8 shared vCPUs, 4GB RAM)
84
- // "xlarge": Extra large machine size (1 performance vCPU, 8GB RAM)
85
- "size": "standard"
86
- }
87
-
88
- // Auth session settings
89
- "authSessions": {
90
- // Whether auth sessions are enabled for this project.
91
- // If enabled, "auth-sessions/check.py" API must be implemented to validate the auth session.
92
- "enabled": true,
93
-
94
- // Whether to save Playwright traces for auth session runs.
95
- "saveTraces": false,
96
-
97
- // The type of auth session to use.
98
- // "API" type requires implementing "auth-sessions/create.py" API to create/recreate the auth session programmatically.
99
- // "MANUAL" type uses a recorder to manually create the auth session.
100
- "type": "API",
101
-
102
- // Recorder start URL for the recorder to navigate to when creating the auth session.
103
- // Required if "type" is "MANUAL". Not used if "type" is "API".
104
- "startUrl": "https://example.com/login",
105
-
106
- // Recorder finish URL for the recorder. Once this URL is reached, the recorder stops and saves the auth session.
107
- // Required if "type" is "MANUAL". Not used if "type" is "API".
108
- "finishUrl": "https://example.com/dashboard",
109
-
110
- // Recorder browser mode
111
- // "fullscreen": Launches the browser in fullscreen mode.
112
- // "kiosk": Launches the browser in kiosk mode (no address bar, no navigation controls).
113
- // Only applicable for "MANUAL" type.
114
- "browserMode": "fullscreen"
115
- }
116
-
117
- // API access settings
118
- "apiAccess": {
119
- // Whether to enable consumption through Intuned API. If this is false, the project can only be consumed through jobs.
120
- // This is required for projects that use auth sessions.
121
- "enabled": true
122
- },
123
-
124
- // Whether to run the deployed API in a headful browser. Running in headful can help with some anti-bot detections. However, it requires more resources and may work slower or crash if the machine size is "standard".
125
- "headful": false,
126
-
127
- // The region where your Intuned project is hosted.
128
- // For a list of available regions, contact support or refer to the documentation.
129
- // Optional - Default: "us"
130
- "region": "us"
131
- }
132
- ```
133
-
134
- """
@@ -1,97 +0,0 @@
1
- from typing import Literal
2
-
3
- import httpx
4
- from anyio import Path
5
-
6
- from intuned_cli.constants import readme
7
- from intuned_cli.types import DirectoryNode
8
- from intuned_cli.types import FileNode
9
- from intuned_cli.types import FileNodeContent
10
- from intuned_cli.types import FileSystemTree
11
- from intuned_cli.utils.backend import get_base_url
12
- from intuned_cli.utils.console import console
13
- from intuned_cli.utils.error import CLIError
14
- from intuned_cli.utils.exclusions import exclusions as default_excludes
15
-
16
- PythonTemplateName = Literal["python-empty"]
17
-
18
- python_template_name: PythonTemplateName = "python-empty"
19
-
20
-
21
- async def check_empty_directory() -> bool:
22
- cwd = await Path().resolve()
23
- try:
24
- if not await cwd.is_dir():
25
- raise CLIError("The current path is not a directory.")
26
-
27
- files = [f async for f in cwd.iterdir() if await f.is_file()]
28
- significant_files = [f for f in files if f.name not in default_excludes]
29
-
30
- return len(significant_files) == 0
31
- except FileNotFoundError as e:
32
- raise CLIError("The specified directory does not exist.") from e
33
-
34
-
35
- async def fetch_project_template(template_name: PythonTemplateName) -> FileSystemTree:
36
- """
37
- Fetch the project template from the templates directory.
38
-
39
- Args:
40
- template_name (PythonTemplateName): The name of the template to fetch.
41
-
42
- Returns:
43
- FileSystemTree: The fetched template.
44
- """
45
- base_url = get_base_url()
46
- url = f"{base_url}/api/templates/{template_name}"
47
- async with httpx.AsyncClient() as client:
48
- response = await client.get(url)
49
- if response.status_code != 200:
50
- raise CLIError(f"Failed to fetch template '{template_name}': {response.text}")
51
- template_data = response.json()
52
- return FileSystemTree.model_validate(template_data["template"])
53
-
54
-
55
- def prepare_cli_template(file_tree: FileSystemTree):
56
- file_tree.root["parameters"] = DirectoryNode(directory=FileSystemTree(root={}))
57
-
58
- file_tree.root["README.md"] = FileNode(file=FileNodeContent(contents=readme))
59
-
60
-
61
- async def mount_file_tree(file_tree: FileSystemTree, working_directory: Path | None = None):
62
- working_directory = working_directory or await Path().resolve()
63
- if not await working_directory.is_dir():
64
- raise CLIError(f"The specified working directory '{working_directory}' is not a directory.")
65
- for name, node in file_tree.root.items():
66
- node_path = working_directory / name
67
- if isinstance(node, DirectoryNode):
68
- await node_path.mkdir(parents=True, exist_ok=True)
69
- await mount_file_tree(node.directory, working_directory=node_path)
70
- else:
71
- await node_path.write_text(node.file.contents)
72
-
73
-
74
- async def write_project_from_file_tree(template_name: PythonTemplateName, is_target_directory_empty: bool):
75
- if not is_target_directory_empty:
76
- response = (
77
- console.input(
78
- "[bold]The current directory is not empty. Do you want to proceed and override files?[/bold] (y/N)"
79
- )
80
- .strip()
81
- .lower()
82
- )
83
- confirmed = response in ["y", "yes"]
84
- if not confirmed:
85
- raise CLIError("Project initialization cancelled")
86
-
87
- console.print(f"[cyan]🚀 Initializing[/cyan] [bold]{template_name}[/bold] [cyan]project...[/cyan]")
88
-
89
- project_template = await fetch_project_template(template_name)
90
- console.print("[cyan]🔨 Creating project files...[/cyan]")
91
-
92
- prepare_cli_template(project_template)
93
- await mount_file_tree(project_template)
94
-
95
- console.print(
96
- "[green][bold]🎉 Project initialized successfully![/bold][/green] [bright_green]Run[/bright_green] [bold]poetry install[/bold] [bright_green]to install dependencies and start coding![/bright_green]"
97
- )