zen-cli 0.1.1__tar.gz → 0.1.2__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 (179) hide show
  1. {zen_cli-0.1.1 → zen_cli-0.1.2}/.gitignore +3 -0
  2. zen_cli-0.1.2/PKG-INFO +84 -0
  3. zen_cli-0.1.2/README.md +52 -0
  4. zen_cli-0.1.2/pyproject.toml +75 -0
  5. zen_cli-0.1.2/src/zen_cli/__init__.py +5 -0
  6. zen_cli-0.1.2/src/zen_cli/__main__.py +4 -0
  7. zen_cli-0.1.2/src/zen_cli/cli.py +176 -0
  8. zen_cli-0.1.2/src/zen_cli/cmds/activity/__init__.py +1 -0
  9. zen_cli-0.1.2/src/zen_cli/cmds/activity/get.py +20 -0
  10. zen_cli-0.1.2/src/zen_cli/cmds/activity/list.py +157 -0
  11. zen_cli-0.1.2/src/zen_cli/cmds/api.py +207 -0
  12. zen_cli-0.1.2/src/zen_cli/cmds/auth/__init__.py +1 -0
  13. zen_cli-0.1.2/src/zen_cli/cmds/auth/refresh.py +11 -0
  14. zen_cli-0.1.2/src/zen_cli/cmds/auth/status.py +19 -0
  15. zen_cli-0.1.2/src/zen_cli/cmds/auth/token.py +17 -0
  16. zen_cli-0.1.2/src/zen_cli/cmds/completion.py +29 -0
  17. zen_cli-0.1.2/src/zen_cli/cmds/credential/__init__.py +1 -0
  18. zen_cli-0.1.2/src/zen_cli/cmds/credential/get.py +19 -0
  19. zen_cli-0.1.2/src/zen_cli/cmds/credential/list.py +18 -0
  20. zen_cli-0.1.2/src/zen_cli/cmds/deployment/__init__.py +1 -0
  21. zen_cli-0.1.2/src/zen_cli/cmds/deployment/get.py +19 -0
  22. zen_cli-0.1.2/src/zen_cli/cmds/deployment/list.py +27 -0
  23. zen_cli-0.1.2/src/zen_cli/cmds/entitlement/__init__.py +1 -0
  24. zen_cli-0.1.2/src/zen_cli/cmds/entitlement/get.py +19 -0
  25. zen_cli-0.1.2/src/zen_cli/cmds/entitlement/list.py +19 -0
  26. zen_cli-0.1.2/src/zen_cli/cmds/group/__init__.py +1 -0
  27. zen_cli-0.1.2/src/zen_cli/cmds/group/get.py +19 -0
  28. zen_cli-0.1.2/src/zen_cli/cmds/group/list.py +26 -0
  29. zen_cli-0.1.2/src/zen_cli/cmds/login.py +364 -0
  30. zen_cli-0.1.2/src/zen_cli/cmds/logout.py +9 -0
  31. zen_cli-0.1.2/src/zen_cli/cmds/mcp.py +13 -0
  32. zen_cli-0.1.2/src/zen_cli/cmds/network/__init__.py +1 -0
  33. zen_cli-0.1.2/src/zen_cli/cmds/network/get.py +19 -0
  34. zen_cli-0.1.2/src/zen_cli/cmds/network/list.py +27 -0
  35. zen_cli-0.1.2/src/zen_cli/cmds/notification/__init__.py +1 -0
  36. zen_cli-0.1.2/src/zen_cli/cmds/notification/get.py +19 -0
  37. zen_cli-0.1.2/src/zen_cli/cmds/notification/list.py +66 -0
  38. zen_cli-0.1.2/src/zen_cli/cmds/org/__init__.py +1 -0
  39. zen_cli-0.1.2/src/zen_cli/cmds/org/get.py +51 -0
  40. zen_cli-0.1.2/src/zen_cli/cmds/org/list.py +33 -0
  41. zen_cli-0.1.2/src/zen_cli/cmds/org/use.py +46 -0
  42. zen_cli-0.1.2/src/zen_cli/cmds/pool/__init__.py +1 -0
  43. zen_cli-0.1.2/src/zen_cli/cmds/pool/delete.py +34 -0
  44. zen_cli-0.1.2/src/zen_cli/cmds/pool/get.py +19 -0
  45. zen_cli-0.1.2/src/zen_cli/cmds/pool/list.py +93 -0
  46. zen_cli-0.1.2/src/zen_cli/cmds/pool/use.py +35 -0
  47. zen_cli-0.1.2/src/zen_cli/cmds/profile/__init__.py +1 -0
  48. zen_cli-0.1.2/src/zen_cli/cmds/profile/init.py +10 -0
  49. zen_cli-0.1.2/src/zen_cli/cmds/provider/__init__.py +1 -0
  50. zen_cli-0.1.2/src/zen_cli/cmds/provider/get.py +27 -0
  51. zen_cli-0.1.2/src/zen_cli/cmds/provider/list.py +43 -0
  52. zen_cli-0.1.2/src/zen_cli/cmds/sag/__init__.py +1 -0
  53. zen_cli-0.1.2/src/zen_cli/cmds/sag/get.py +19 -0
  54. zen_cli-0.1.2/src/zen_cli/cmds/sag/list.py +20 -0
  55. zen_cli-0.1.2/src/zen_cli/cmds/task/__init__.py +1 -0
  56. zen_cli-0.1.2/src/zen_cli/cmds/task/cancel.py +27 -0
  57. zen_cli-0.1.2/src/zen_cli/cmds/task/delete.py +42 -0
  58. zen_cli-0.1.2/src/zen_cli/cmds/task/duplicate.py +75 -0
  59. zen_cli-0.1.2/src/zen_cli/cmds/task/get.py +20 -0
  60. zen_cli-0.1.2/src/zen_cli/cmds/task/list.py +132 -0
  61. zen_cli-0.1.2/src/zen_cli/cmds/task/log.py +60 -0
  62. zen_cli-0.1.2/src/zen_cli/cmds/task/namespaces.py +11 -0
  63. zen_cli-0.1.2/src/zen_cli/cmds/task/use.py +37 -0
  64. zen_cli-0.1.2/src/zen_cli/cmds/task/wait.py +28 -0
  65. zen_cli-0.1.2/src/zen_cli/cmds/upgrade.py +13 -0
  66. zen_cli-0.1.2/src/zen_cli/cmds/vm/__init__.py +1 -0
  67. zen_cli-0.1.2/src/zen_cli/cmds/vm/delete.py +39 -0
  68. zen_cli-0.1.2/src/zen_cli/cmds/vm/get.py +17 -0
  69. zen_cli-0.1.2/src/zen_cli/cmds/vm/list.py +184 -0
  70. zen_cli-0.1.2/src/zen_cli/cmds/vm/poweroff.py +29 -0
  71. zen_cli-0.1.2/src/zen_cli/cmds/vm/poweron.py +29 -0
  72. zen_cli-0.1.2/src/zen_cli/cmds/vm/restart.py +19 -0
  73. zen_cli-0.1.2/src/zen_cli/cmds/vm/shutdown.py +19 -0
  74. zen_cli-0.1.2/src/zen_cli/cmds/vm/use.py +48 -0
  75. zen_cli-0.1.2/src/zen_cli/cmds/vm/wait.py +48 -0
  76. zen_cli-0.1.2/src/zen_cli/config/default.yaml +31 -0
  77. zen_cli-0.1.2/src/zen_cli/config/int.yaml +21 -0
  78. zen_cli-0.1.2/src/zen_cli/config/prod.yaml +31 -0
  79. zen_cli-0.1.2/src/zen_cli/config/stg.yaml +31 -0
  80. zen_cli-0.1.2/src/zen_cli/ctxp/__init__.py +12 -0
  81. zen_cli-0.1.2/src/zen_cli/ctxp/_init.py +83 -0
  82. zen_cli-0.1.2/src/zen_cli/ctxp/built_in_cmds/__init__.py +0 -0
  83. zen_cli-0.1.2/src/zen_cli/ctxp/built_in_cmds/_ut.py +117 -0
  84. zen_cli-0.1.2/src/zen_cli/ctxp/built_in_cmds/context.py +92 -0
  85. zen_cli-0.1.2/src/zen_cli/ctxp/built_in_cmds/profile.py +156 -0
  86. zen_cli-0.1.2/src/zen_cli/ctxp/cli_options.py +135 -0
  87. zen_cli-0.1.2/src/zen_cli/ctxp/cli_processor.py +257 -0
  88. zen_cli-0.1.2/src/zen_cli/ctxp/cmd_util.py +88 -0
  89. zen_cli-0.1.2/src/zen_cli/ctxp/config.py +21 -0
  90. zen_cli-0.1.2/src/zen_cli/ctxp/context.py +116 -0
  91. zen_cli-0.1.2/src/zen_cli/ctxp/data_util.py +461 -0
  92. zen_cli-0.1.2/src/zen_cli/ctxp/dispatcher.py +84 -0
  93. zen_cli-0.1.2/src/zen_cli/ctxp/extension.py +32 -0
  94. zen_cli-0.1.2/src/zen_cli/ctxp/fn_util.py +61 -0
  95. zen_cli-0.1.2/src/zen_cli/ctxp/fstore.py +273 -0
  96. zen_cli-0.1.2/src/zen_cli/ctxp/jsondot.py +341 -0
  97. zen_cli-0.1.2/src/zen_cli/ctxp/logger.py +220 -0
  98. zen_cli-0.1.2/src/zen_cli/ctxp/profile.py +268 -0
  99. zen_cli-0.1.2/src/zen_cli/ctxp/profile_store.py +35 -0
  100. zen_cli-0.1.2/src/zen_cli/ctxp/recent.py +116 -0
  101. zen_cli-0.1.2/src/zen_cli/ctxp/state.py +42 -0
  102. zen_cli-0.1.2/src/zen_cli/ctxp/telemetry.py +150 -0
  103. zen_cli-0.1.2/src/zen_cli/ctxp/template_util.py +26 -0
  104. zen_cli-0.1.2/src/zen_cli/ctxp/timeutil.py +11 -0
  105. zen_cli-0.1.2/src/zen_cli/ctxp/util.py +482 -0
  106. zen_cli-0.1.2/src/zen_cli/ctxp/var_template.py +109 -0
  107. zen_cli-0.1.2/src/zen_cli/mcp/__init__.py +3 -0
  108. zen_cli-0.1.2/src/zen_cli/mcp/_util.py +41 -0
  109. zen_cli-0.1.2/src/zen_cli/mcp/resources/__init__.py +33 -0
  110. zen_cli-0.1.2/src/zen_cli/mcp/resources/activity.py +60 -0
  111. zen_cli-0.1.2/src/zen_cli/mcp/resources/api.py +53 -0
  112. zen_cli-0.1.2/src/zen_cli/mcp/resources/credential.py +18 -0
  113. zen_cli-0.1.2/src/zen_cli/mcp/resources/deployment.py +14 -0
  114. zen_cli-0.1.2/src/zen_cli/mcp/resources/entitlement.py +21 -0
  115. zen_cli-0.1.2/src/zen_cli/mcp/resources/group.py +24 -0
  116. zen_cli-0.1.2/src/zen_cli/mcp/resources/network.py +21 -0
  117. zen_cli-0.1.2/src/zen_cli/mcp/resources/notification.py +40 -0
  118. zen_cli-0.1.2/src/zen_cli/mcp/resources/org.py +21 -0
  119. zen_cli-0.1.2/src/zen_cli/mcp/resources/pool.py +30 -0
  120. zen_cli-0.1.2/src/zen_cli/mcp/resources/provider.py +29 -0
  121. zen_cli-0.1.2/src/zen_cli/mcp/resources/sag.py +19 -0
  122. zen_cli-0.1.2/src/zen_cli/mcp/resources/task.py +63 -0
  123. zen_cli-0.1.2/src/zen_cli/mcp/resources/vm.py +34 -0
  124. zen_cli-0.1.2/src/zen_cli/mcp/server.py +72 -0
  125. zen_cli-0.1.2/src/zen_cli/service/__init__.py +0 -0
  126. zen_cli-0.1.2/src/zen_cli/service/activity.py +52 -0
  127. zen_cli-0.1.2/src/zen_cli/service/api.py +198 -0
  128. zen_cli-0.1.2/src/zen_cli/service/broker/__init__.py +2 -0
  129. zen_cli-0.1.2/src/zen_cli/service/broker/entitlement.py +13 -0
  130. zen_cli-0.1.2/src/zen_cli/service/broker/pool_group.py +13 -0
  131. zen_cli-0.1.2/src/zen_cli/service/cockpit/__init__.py +3 -0
  132. zen_cli-0.1.2/src/zen_cli/service/cockpit/network.py +13 -0
  133. zen_cli-0.1.2/src/zen_cli/service/cockpit/pool.py +20 -0
  134. zen_cli-0.1.2/src/zen_cli/service/cockpit/provider.py +13 -0
  135. zen_cli-0.1.2/src/zen_cli/service/cockpit/sag.py +13 -0
  136. zen_cli-0.1.2/src/zen_cli/service/cockpit/vm.py +110 -0
  137. zen_cli-0.1.2/src/zen_cli/service/credential.py +13 -0
  138. zen_cli-0.1.2/src/zen_cli/service/deployment.py +31 -0
  139. zen_cli-0.1.2/src/zen_cli/service/notification.py +44 -0
  140. zen_cli-0.1.2/src/zen_cli/service/org.py +23 -0
  141. zen_cli-0.1.2/src/zen_cli/service/task.py +381 -0
  142. zen_cli-0.1.2/src/zen_cli/sglib/__init__.py +3 -0
  143. zen_cli-0.1.2/src/zen_cli/sglib/auth.py +322 -0
  144. zen_cli-0.1.2/src/zen_cli/sglib/cli_options.py +63 -0
  145. zen_cli-0.1.2/src/zen_cli/sglib/client_util.py +490 -0
  146. zen_cli-0.1.2/src/zen_cli/sglib/csp.py +199 -0
  147. zen_cli-0.1.2/src/zen_cli/sglib/ez_client.py +348 -0
  148. zen_cli-0.1.2/src/zen_cli/sglib/init.py +18 -0
  149. zen_cli-0.1.2/src/zen_cli/sglib/login_support.py +333 -0
  150. zen_cli-0.1.2/src/zen_cli/sglib/mdc.py +19 -0
  151. zen_cli-0.1.2/src/zen_cli/sglib/payload_util.py +29 -0
  152. zen_cli-0.1.2/src/zen_cli/sglib/requtil.py +40 -0
  153. zen_cli-0.1.2/src/zen_cli/sglib/utils.py +107 -0
  154. zen_cli-0.1.2/src/zen_cli/sglib/zds_client.py +8 -0
  155. zen_cli-0.1.2/src/zen_cli/support/auth.py +18 -0
  156. zen_cli-0.1.2/src/zen_cli/support/profile.py +49 -0
  157. zen_cli-0.1.2/src/zen_cli/support/task.py +312 -0
  158. zen_cli-0.1.2/src/zen_cli/support/use_util.py +103 -0
  159. zen_cli-0.1.2/src/zen_cli/support/vm.py +8 -0
  160. zen_cli-0.1.2/src/zen_cli/util/exec_util.py +263 -0
  161. zen_cli-0.1.2/src/zen_cli/util/exit.py +17 -0
  162. zen_cli-0.1.2/src/zen_cli/util/param_util.py +39 -0
  163. zen_cli-0.1.2/src/zen_cli/util/patch_util.py +38 -0
  164. zen_cli-0.1.2/src/zen_cli/util/query_util.py +98 -0
  165. zen_cli-0.1.2/src/zen_cli/util/readonly.py +8 -0
  166. zen_cli-0.1.2/src/zen_cli/util/versions.py +65 -0
  167. zen_cli-0.1.2/tests/test_cli.py +104 -0
  168. zen_cli-0.1.2/tests/test_device_login.py +127 -0
  169. zen_cli-0.1.2/tests/test_mcp.py +78 -0
  170. zen_cli-0.1.1/PKG-INFO +0 -57
  171. zen_cli-0.1.1/README.md +0 -37
  172. zen_cli-0.1.1/pyproject.toml +0 -40
  173. zen_cli-0.1.1/src/zen_cli/__init__.py +0 -1
  174. zen_cli-0.1.1/src/zen_cli/__main__.py +0 -4
  175. zen_cli-0.1.1/src/zen_cli/cli.py +0 -12
  176. zen_cli-0.1.1/src/zen_cli/commands/__init__.py +0 -1
  177. zen_cli-0.1.1/src/zen_cli/commands/hello.py +0 -7
  178. zen_cli-0.1.1/tests/test_cli.py +0 -24
  179. {zen_cli-0.1.1 → zen_cli-0.1.2}/LICENSE +0 -0
@@ -8,5 +8,8 @@ build/
8
8
  __pycache__/
9
9
  *.py[cod]
10
10
  .pypirc
11
+ .env
11
12
  .coverage
12
13
  htmlcov/
14
+ temp/
15
+ cli-ref/
zen_cli-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.5
2
+ Name: zen-cli
3
+ Version: 0.1.2
4
+ Summary: Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server.
5
+ Project-URL: Homepage, https://pypi.org/project/zen-cli/
6
+ Author: zen-cli authors
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Python: >=3.12
10
+ Requires-Dist: authlib
11
+ Requires-Dist: click>=8.1
12
+ Requires-Dist: coloredlogs
13
+ Requires-Dist: httpx2
14
+ Requires-Dist: mcp>=2
15
+ Requires-Dist: portalocker[win32]
16
+ Requires-Dist: pydantic
17
+ Requires-Dist: pyjwt
18
+ Requires-Dist: python-dotenv
19
+ Requires-Dist: pyyaml
20
+ Requires-Dist: questionary
21
+ Requires-Dist: tabulate
22
+ Requires-Dist: yumako
23
+ Provides-Extra: dev
24
+ Requires-Dist: build; extra == 'dev'
25
+ Requires-Dist: mypy; extra == 'dev'
26
+ Requires-Dist: pre-commit; extra == 'dev'
27
+ Requires-Dist: ruff; extra == 'dev'
28
+ Provides-Extra: release
29
+ Requires-Dist: build; extra == 'release'
30
+ Requires-Dist: twine; extra == 'release'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # zen-cli
34
+
35
+ [![PyPI](https://img.shields.io/pypi/v/zen-cli?logo=pypi&logoColor=white)](https://pypi.org/project/zen-cli/) [![Python](https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![PyPI downloads](https://img.shields.io/pypi/dm/zen-cli)](https://pypi.org/project/zen-cli/) [![Wheel](https://img.shields.io/pypi/wheel/zen-cli)](https://pypi.org/project/zen-cli/) [![OS](https://img.shields.io/badge/OS-macOS%20%7C%20Linux%20%7C%20Windows-informational)](https://pypi.org/project/zen-cli/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Checked with mypy](https://img.shields.io/badge/mypy-checked-2A6DB2)](https://mypy-lang.org/) [![Click](https://img.shields.io/badge/cli-Click%208-4584b6)](https://click.palletsprojects.com/) [![Hatch](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5)](https://github.com/pypa/hatch)
36
+
37
+ Command-line toolbox for Zen Cloud PC, designed for AI and human.
38
+
39
+ ## Try it out
40
+
41
+ ### Prerequisites
42
+
43
+ * Python 3.12 or newer
44
+ * Pip
45
+
46
+ ### Installation
47
+
48
+ #### Mac & Linux
49
+
50
+ ```text
51
+ pip install zen-cli
52
+ ```
53
+
54
+ #### Windows
55
+
56
+ ```text
57
+ pip install zen-cli
58
+ ```
59
+
60
+ If Python was installed without “Add python to PATH”, add Python and its `Scripts` directory to PATH.
61
+
62
+ ### Use the CLI
63
+
64
+ ```text
65
+ zen login
66
+ zen auth status
67
+ ```
68
+
69
+ `zen login` reuses cached or configured credentials. Interactive login is `zen login --device-code`; machine login is `zen login --client-id` / `--client-secret`. Use `zen auth status` / `zen auth token` to inspect the session (`--service` for a per-service override). `zen auth refresh` refreshes the cached token.
70
+
71
+ Run a command, for example, list orgs:
72
+
73
+ ```text
74
+ zen org list
75
+ ```
76
+
77
+ ## Documentation
78
+
79
+ * [Cheatsheet](docs/cheatsheet.md)
80
+ * [Developer guide](docs/dev.md)
81
+
82
+ ## License
83
+
84
+ Licensed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,52 @@
1
+ # zen-cli
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/zen-cli?logo=pypi&logoColor=white)](https://pypi.org/project/zen-cli/) [![Python](https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![PyPI downloads](https://img.shields.io/pypi/dm/zen-cli)](https://pypi.org/project/zen-cli/) [![Wheel](https://img.shields.io/pypi/wheel/zen-cli)](https://pypi.org/project/zen-cli/) [![OS](https://img.shields.io/badge/OS-macOS%20%7C%20Linux%20%7C%20Windows-informational)](https://pypi.org/project/zen-cli/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Checked with mypy](https://img.shields.io/badge/mypy-checked-2A6DB2)](https://mypy-lang.org/) [![Click](https://img.shields.io/badge/cli-Click%208-4584b6)](https://click.palletsprojects.com/) [![Hatch](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5)](https://github.com/pypa/hatch)
4
+
5
+ Command-line toolbox for Zen Cloud PC, designed for AI and human.
6
+
7
+ ## Try it out
8
+
9
+ ### Prerequisites
10
+
11
+ * Python 3.12 or newer
12
+ * Pip
13
+
14
+ ### Installation
15
+
16
+ #### Mac & Linux
17
+
18
+ ```text
19
+ pip install zen-cli
20
+ ```
21
+
22
+ #### Windows
23
+
24
+ ```text
25
+ pip install zen-cli
26
+ ```
27
+
28
+ If Python was installed without “Add python to PATH”, add Python and its `Scripts` directory to PATH.
29
+
30
+ ### Use the CLI
31
+
32
+ ```text
33
+ zen login
34
+ zen auth status
35
+ ```
36
+
37
+ `zen login` reuses cached or configured credentials. Interactive login is `zen login --device-code`; machine login is `zen login --client-id` / `--client-secret`. Use `zen auth status` / `zen auth token` to inspect the session (`--service` for a per-service override). `zen auth refresh` refreshes the cached token.
38
+
39
+ Run a command, for example, list orgs:
40
+
41
+ ```text
42
+ zen org list
43
+ ```
44
+
45
+ ## Documentation
46
+
47
+ * [Cheatsheet](docs/cheatsheet.md)
48
+ * [Developer guide](docs/dev.md)
49
+
50
+ ## License
51
+
52
+ Licensed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "zen-cli"
7
+ version = "0.1.2"
8
+ description = "Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.12"
13
+ authors = [{ name = "zen-cli authors" }]
14
+ dependencies = [
15
+ "authlib",
16
+ "click>=8.1",
17
+ "coloredlogs",
18
+ "httpx2",
19
+ "mcp>=2",
20
+ "python-dotenv",
21
+ "pydantic",
22
+ "portalocker[win32]",
23
+ "PyJWT",
24
+ "pyyaml",
25
+ "questionary",
26
+ "tabulate",
27
+ "yumako",
28
+ ]
29
+
30
+ [project.optional-dependencies]
31
+ dev = ["build", "pre-commit", "ruff", "mypy"]
32
+ release = ["build", "twine"]
33
+
34
+ [project.scripts]
35
+ zen = "zen_cli.cli:main"
36
+
37
+ [project.urls]
38
+ Homepage = "https://pypi.org/project/zen-cli/"
39
+
40
+ [tool.hatch.build.targets.sdist]
41
+ include = ["src/zen_cli", "tests", "README.md", "LICENSE"]
42
+
43
+ [tool.ruff]
44
+ target-version = "py312"
45
+ line-length = 120
46
+ src = ["src"]
47
+ exclude = ["cli-ref"]
48
+
49
+ [tool.ruff.lint]
50
+ select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
51
+
52
+ [tool.mypy]
53
+ python_version = "3.12"
54
+ strict = true
55
+ files = ["src"]
56
+
57
+ [[tool.mypy.overrides]]
58
+ module = ["mcp", "mcp.*"]
59
+ ignore_missing_imports = true
60
+
61
+ [[tool.mypy.overrides]]
62
+ module = [
63
+ "yumako",
64
+ "yumako.*",
65
+ "authlib",
66
+ "authlib.*",
67
+ "yaml",
68
+ "httpx2",
69
+ "httpx2.*",
70
+ ]
71
+ ignore_missing_imports = true
72
+
73
+ [[tool.mypy.overrides]]
74
+ module = ["zen_cli.cmds", "zen_cli.cmds.*", "zen_cli.ctxp", "zen_cli.ctxp.*"]
75
+ disallow_untyped_decorators = false
@@ -0,0 +1,5 @@
1
+ """zen-cli package."""
2
+
3
+ import httpx2
4
+
5
+ httpx2.alias_httpx()
@@ -0,0 +1,4 @@
1
+ from zen_cli.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,176 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import click
8
+ from dotenv import load_dotenv
9
+ from yumako import env
10
+
11
+ import zen_cli.ctxp as ctxp
12
+ from zen_cli.ctxp.cli_processor import register_commands
13
+
14
+ _PACKAGE_DIR = Path(__file__).resolve().parent
15
+ _COMMANDS_DIR = _PACKAGE_DIR / "cmds"
16
+ _CONFIG_DIR = _PACKAGE_DIR / "config"
17
+ _commands_loaded = False
18
+
19
+
20
+ # -----------------------------------------------------------
21
+ import zen_cli.ctxp.logger as logger # noqa: E402
22
+
23
+ logger.setup()
24
+ logging.getLogger("charset_normalizer").setLevel(logging.WARN)
25
+ logging.getLogger("csp").setLevel(logging.INFO)
26
+ logging.getLogger("context").setLevel(logging.WARN)
27
+ logging.getLogger("init").setLevel(logging.WARN)
28
+ logging.getLogger("profile").setLevel(logging.WARN)
29
+ logging.getLogger("httpx").setLevel(logging.WARN)
30
+ logging.getLogger("httpx2").setLevel(logging.WARN)
31
+ logging.getLogger("urllib3").setLevel(logging.ERROR)
32
+ # logging.getLogger("zen_cli.sglib.login_support").setLevel(logging.DEBUG)
33
+ # logging.getLogger("login_support").setLevel(logging.DEBUG)
34
+ # -----------------------------------------------------------
35
+ import zen_cli.sglib.ez_client as ez_client # noqa: E402
36
+
37
+ ez_client._print_http_error = False
38
+
39
+ CONTEXT_SETTINGS = {
40
+ "help_option_names": ["-h", "--help"],
41
+ "max_content_width": 160,
42
+ }
43
+
44
+
45
+ def _apply_readonly() -> None:
46
+ data = ctxp.profile.current(exit_on_failure=False)
47
+ if not data:
48
+ return
49
+ is_readonly = data.get("readonly")
50
+ if isinstance(is_readonly, str):
51
+ is_readonly = is_readonly.strip().lower() in ("1", "true", "yes")
52
+ else:
53
+ is_readonly = bool(is_readonly)
54
+ if is_readonly:
55
+ from zen_cli.util import readonly as readonly_support
56
+
57
+ ez_client.set_readonly(True, readonly_support.ALLOW_PATHS)
58
+
59
+
60
+ def _enable_verbose() -> None:
61
+ root = logging.getLogger()
62
+ root.setLevel(logging.DEBUG)
63
+ for handler in root.handlers:
64
+ handler.setLevel(logging.DEBUG)
65
+ for name in (
66
+ "zen_cli",
67
+ "csp",
68
+ "profile",
69
+ "httpx",
70
+ "httpx2",
71
+ "httpcore",
72
+ "authlib",
73
+ ):
74
+ logging.getLogger(name).setLevel(logging.DEBUG)
75
+
76
+
77
+ def _check_upgrade() -> None:
78
+ check_flag_from_env = env.bool("HCS_CLI_CHECK_UPGRADE", True)
79
+ if not check_flag_from_env:
80
+ return
81
+ if os.environ.get("_ZEN_COMPLETE"):
82
+ return
83
+ if len(sys.argv) > 1 and sys.argv[1] in ("upgrade", "mcp", "completion"):
84
+ return
85
+ from zen_cli.util.versions import check_upgrade
86
+
87
+ check_upgrade()
88
+
89
+
90
+ @click.group(name="zen", context_settings=CONTEXT_SETTINGS)
91
+ @click.version_option(package_name="zen-cli", prog_name="zen")
92
+ @click.option(
93
+ "--profile",
94
+ "-p",
95
+ type=str,
96
+ required=False,
97
+ help="Specify the profile to use. Optional.",
98
+ )
99
+ @click.option(
100
+ "--mdc",
101
+ type=str,
102
+ required=False,
103
+ help=("MDC name from profile zds.mdcs (e.g. beijing, singapore). Default is the first zds.mdcs entry."),
104
+ )
105
+ @click.option(
106
+ "--check-upgrade/--no-check-upgrade",
107
+ default=None,
108
+ help="Check for a new zen-cli version. On by default. Or set HCS_CLI_CHECK_UPGRADE=false.",
109
+ )
110
+ @click.option(
111
+ "--telemetry/--no-telemetry",
112
+ default=None,
113
+ help="Send command telemetry. Off by default. Or set ZEN_CLI_TELEMETRY=true.",
114
+ )
115
+ @click.option(
116
+ "--verbose",
117
+ "-v",
118
+ is_flag=True,
119
+ default=False,
120
+ help="Print debug logs, including HTTP method and URL.",
121
+ )
122
+ def cli(
123
+ profile: str,
124
+ mdc: str,
125
+ check_upgrade: bool | None,
126
+ telemetry: bool | None,
127
+ verbose: bool,
128
+ **kwargs: Any,
129
+ ) -> None:
130
+ """zen command-line interface."""
131
+ if verbose:
132
+ _enable_verbose()
133
+
134
+ if check_upgrade is not False:
135
+ _check_upgrade()
136
+
137
+ if telemetry is True:
138
+ ctxp.telemetry.enable()
139
+ elif telemetry is False:
140
+ ctxp.telemetry.disable()
141
+
142
+ if profile:
143
+ ctxp.profile.activate(profile, persist=False)
144
+
145
+ from zen_cli.ctxp._init import _initialized_app_name
146
+
147
+ if not _initialized_app_name:
148
+ return
149
+ from zen_cli.support import profile as profile_support
150
+
151
+ profile_support.ensure_standard_profiles(interactive=False)
152
+
153
+ if mdc:
154
+ from zen_cli.sglib import mdc as mdc_session
155
+
156
+ mdc_session.set(mdc)
157
+
158
+ _apply_readonly()
159
+ load_commands()
160
+
161
+
162
+ def load_commands() -> None:
163
+ """Attach built-in and cmds/ commands without running Click."""
164
+ global _commands_loaded
165
+ if _commands_loaded:
166
+ return
167
+ register_commands(cli, str(_COMMANDS_DIR))
168
+ _commands_loaded = True
169
+
170
+
171
+ def main() -> None:
172
+ ctxp.init(app_name="zen", config_path=str(_CONFIG_DIR))
173
+ load_dotenv(".env")
174
+ if os.environ.get("_ZEN_COMPLETE"):
175
+ ctxp.telemetry.disable()
176
+ ctxp.init_cli(main_cli=cli, commands_dir=str(_COMMANDS_DIR))
@@ -0,0 +1 @@
1
+ help = "System activity commands."
@@ -0,0 +1,20 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service import activity
8
+
9
+
10
+ @click.command()
11
+ @cli.org_id
12
+ @click.argument("id", type=str, required=False)
13
+ def get(org: str, id: str) -> Any:
14
+ """Get a system activity by ID. Without an argument, use the recent activity."""
15
+ id = recent.require("activity", id)
16
+ org_id = None if org == "all" else cli.get_org_id(org)
17
+ ret = activity.get(id, org_id=org_id)
18
+ if ret:
19
+ return ret
20
+ return "", 1
@@ -0,0 +1,157 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent, util
7
+ from zen_cli.service import activity
8
+
9
+ _RESOURCE_TYPES = [
10
+ "ORG",
11
+ "ORG_PREFERENCE",
12
+ "DATACENTER",
13
+ "POOL",
14
+ "ENTITLEMENT",
15
+ "VM",
16
+ "EDGE",
17
+ "SAG",
18
+ "TASK",
19
+ "PROVIDER_INSTANCE",
20
+ "NET_INFRA",
21
+ "EXPRESS_DEPLOYMENT",
22
+ "POOL_GROUP",
23
+ "IMAGE",
24
+ "SITE",
25
+ "SPEC",
26
+ "SESSION",
27
+ "VMAGENT",
28
+ "NOTIFICATION",
29
+ ]
30
+
31
+ _TABLE_MAPPING = {
32
+ "code": "Code",
33
+ "severity": "Severity",
34
+ "initiator": "Initiator",
35
+ "serviceName": "Service",
36
+ "resourceId": "Resource",
37
+ "traceId": "Trace",
38
+ }
39
+
40
+
41
+ def _format_activity_table(data: Any) -> Any:
42
+ for d in data:
43
+ if d.get("timestamp") and not d.get("createdAt"):
44
+ d["createdAt"] = d["timestamp"]
45
+ if not d.get("name"):
46
+ d["name"] = d.get("resourceName") or d.get("code") or ""
47
+ if not d.get("type"):
48
+ d["type"] = d.get("resourceType")
49
+ return util.default_table_formatter(data, _TABLE_MAPPING)
50
+
51
+
52
+ @click.command(name="list")
53
+ @cli.org_id
54
+ @click.option("--service-name", type=str, required=False, help="Filter by service name.")
55
+ @click.option("--code", type=str, required=False, help="Filter by activity code.")
56
+ @click.option("--trace-id", type=str, required=False, help="Filter by trace ID.")
57
+ @click.option("--span-id", type=str, required=False, help="Filter by span ID.")
58
+ @click.option("--resource-id", type=str, required=False, help="Filter by resource ID.")
59
+ @click.option("--resource-name", type=str, required=False, help="Filter by resource name.")
60
+ @click.option("--task-id", type=str, required=False, help="Filter by task ID.")
61
+ @click.option("--parent-id", type=str, required=False, help="Filter by parent activity ID.")
62
+ @click.option("--initiator", type=str, required=False, help="Filter by initiator.")
63
+ @click.option(
64
+ "--initiator-type",
65
+ type=click.Choice(["SYSTEM", "OPS", "CUSTOMER_ADMIN", "USER"], case_sensitive=False),
66
+ required=False,
67
+ help="Filter by initiator type.",
68
+ )
69
+ @click.option(
70
+ "--resource-type",
71
+ type=click.Choice(_RESOURCE_TYPES, case_sensitive=False),
72
+ required=False,
73
+ help="Filter by resource type.",
74
+ )
75
+ @click.option(
76
+ "--severity",
77
+ type=click.Choice(["CRITICAL", "WARNING", "INFO", "TRIVIAL"], case_sensitive=False),
78
+ required=False,
79
+ help="Filter by severity.",
80
+ )
81
+ @click.option(
82
+ "--status",
83
+ type=click.Choice(
84
+ ["QUEUED", "START", "PROGRESS", "SUCCESS", "ERROR", "CANCELLED"],
85
+ case_sensitive=False,
86
+ ),
87
+ required=False,
88
+ help="Filter by status.",
89
+ )
90
+ @click.option(
91
+ "--timestamp-from",
92
+ type=str,
93
+ required=False,
94
+ help="Inclusive lower bound (ISO-8601).",
95
+ )
96
+ @click.option(
97
+ "--timestamp-to",
98
+ type=str,
99
+ required=False,
100
+ help="Inclusive upper bound (ISO-8601).",
101
+ )
102
+ @cli.sort
103
+ @cli.limit
104
+ @cli.formatter(_format_activity_table)
105
+ def list_activities(
106
+ org: str,
107
+ service_name: str,
108
+ code: str,
109
+ trace_id: str,
110
+ span_id: str,
111
+ resource_id: str,
112
+ resource_name: str,
113
+ task_id: str,
114
+ parent_id: str,
115
+ initiator: str,
116
+ initiator_type: str,
117
+ resource_type: str,
118
+ severity: str,
119
+ status: str,
120
+ timestamp_from: str,
121
+ timestamp_to: str,
122
+ sort: str,
123
+ limit: int,
124
+ ) -> Any:
125
+ """List system activities."""
126
+ org_id = None if org == "all" else cli.get_org_id(org)
127
+ if initiator_type:
128
+ initiator_type = initiator_type.upper()
129
+ if resource_type:
130
+ resource_type = resource_type.upper()
131
+ if severity:
132
+ severity = severity.upper()
133
+ if status:
134
+ status = status.upper()
135
+
136
+ ret = activity.list(
137
+ org_id=org_id,
138
+ service_name=service_name,
139
+ code=code,
140
+ trace_id=trace_id,
141
+ span_id=span_id,
142
+ resource_id=resource_id,
143
+ resource_name=resource_name,
144
+ task_id=task_id,
145
+ parent_id=parent_id,
146
+ initiator=initiator,
147
+ initiator_type=initiator_type,
148
+ resource_type=resource_type,
149
+ severity=severity,
150
+ status=status,
151
+ timestamp_from=timestamp_from,
152
+ timestamp_to=timestamp_to,
153
+ sort=sort,
154
+ limit=limit,
155
+ )
156
+ recent.helper.default_list(ret, "activity")
157
+ return ret