opsmith-cli 0.1.2a0__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.
Files changed (55) hide show
  1. opsmith/__init__.py +0 -0
  2. opsmith/agent.py +243 -0
  3. opsmith/cloud_providers/__init__.py +10 -0
  4. opsmith/cloud_providers/aws.py +46 -0
  5. opsmith/cloud_providers/base.py +57 -0
  6. opsmith/cloud_providers/gcp.py +67 -0
  7. opsmith/constants.py +175 -0
  8. opsmith/deployer.py +236 -0
  9. opsmith/git_repo.py +66 -0
  10. opsmith/main.py +269 -0
  11. opsmith/prompts.py +76 -0
  12. opsmith/queries/tree-sitter-languages/README.md +7 -0
  13. opsmith/queries/tree-sitter-languages/arduino-tags.scm +5 -0
  14. opsmith/queries/tree-sitter-languages/c-tags.scm +9 -0
  15. opsmith/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  16. opsmith/queries/tree-sitter-languages/chatito-tags.scm +16 -0
  17. opsmith/queries/tree-sitter-languages/commonlisp-tags.scm +122 -0
  18. opsmith/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  19. opsmith/queries/tree-sitter-languages/csharp-tags.scm +26 -0
  20. opsmith/queries/tree-sitter-languages/d-tags.scm +26 -0
  21. opsmith/queries/tree-sitter-languages/dart-tags.scm +92 -0
  22. opsmith/queries/tree-sitter-languages/elisp-tags.scm +5 -0
  23. opsmith/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  24. opsmith/queries/tree-sitter-languages/elm-tags.scm +19 -0
  25. opsmith/queries/tree-sitter-languages/gleam-tags.scm +41 -0
  26. opsmith/queries/tree-sitter-languages/go-tags.scm +42 -0
  27. opsmith/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  28. opsmith/queries/tree-sitter-languages/java-tags.scm +20 -0
  29. opsmith/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  30. opsmith/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  31. opsmith/queries/tree-sitter-languages/lua-tags.scm +34 -0
  32. opsmith/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  33. opsmith/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  34. opsmith/queries/tree-sitter-languages/php-tags.scm +26 -0
  35. opsmith/queries/tree-sitter-languages/pony-tags.scm +39 -0
  36. opsmith/queries/tree-sitter-languages/properties-tags.scm +5 -0
  37. opsmith/queries/tree-sitter-languages/python-tags.scm +14 -0
  38. opsmith/queries/tree-sitter-languages/ql-tags.scm +26 -0
  39. opsmith/queries/tree-sitter-languages/r-tags.scm +21 -0
  40. opsmith/queries/tree-sitter-languages/racket-tags.scm +12 -0
  41. opsmith/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  42. opsmith/queries/tree-sitter-languages/rust-tags.scm +60 -0
  43. opsmith/queries/tree-sitter-languages/scala-tags.scm +65 -0
  44. opsmith/queries/tree-sitter-languages/solidity-tags.scm +43 -0
  45. opsmith/queries/tree-sitter-languages/swift-tags.scm +51 -0
  46. opsmith/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  47. opsmith/queries/tree-sitter-languages/udev-tags.scm +20 -0
  48. opsmith/repo_map.py +572 -0
  49. opsmith/settings.py +26 -0
  50. opsmith/spinner.py +221 -0
  51. opsmith_cli-0.1.2a0.dist-info/METADATA +31 -0
  52. opsmith_cli-0.1.2a0.dist-info/RECORD +55 -0
  53. opsmith_cli-0.1.2a0.dist-info/WHEEL +4 -0
  54. opsmith_cli-0.1.2a0.dist-info/entry_points.txt +2 -0
  55. opsmith_cli-0.1.2a0.dist-info/licenses/LICENSE.txt +674 -0
opsmith/spinner.py ADDED
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ Thread-based, killable spinner utility.
5
+
6
+ Use it like:
7
+
8
+ from aider.waiting import WaitingSpinner
9
+
10
+ spinner = WaitingSpinner("Waiting for LLM")
11
+ spinner.start()
12
+ ... # long task
13
+ spinner.stop()
14
+ """
15
+
16
+ import sys
17
+ import threading
18
+ import time
19
+
20
+ from rich.console import Console
21
+
22
+
23
+ class Spinner:
24
+ """
25
+ Minimal spinner that scans a single marker back and forth across a line.
26
+
27
+ The animation is pre-rendered into a list of frames. If the terminal
28
+ cannot display unicode the frames are converted to plain ASCII.
29
+ """
30
+
31
+ last_frame_idx = 0 # Class variable to store the last frame index
32
+
33
+ def __init__(self, text: str, width: int = 7):
34
+ self.text = text
35
+ self.start_time = time.time()
36
+ self.last_update = 0.0
37
+ self.visible = False
38
+ self.is_tty = sys.stdout.isatty()
39
+ self.console = Console()
40
+
41
+ # Pre-render the animation frames using pure ASCII so they will
42
+ # always display, even on very limited terminals.
43
+ ascii_frames = [
44
+ "#= ", # C1 C2 space(8)
45
+ "=# ", # C2 C1 space(8)
46
+ " =# ", # space(1) C2 C1 space(7)
47
+ " =# ", # space(2) C2 C1 space(6)
48
+ " =# ", # space(3) C2 C1 space(5)
49
+ " =# ", # space(4) C2 C1 space(4)
50
+ " =# ", # space(5) C2 C1 space(3)
51
+ " =# ", # space(6) C2 C1 space(2)
52
+ " =# ", # space(7) C2 C1 space(1)
53
+ " =#", # space(8) C2 C1
54
+ " #=", # space(8) C1 C2
55
+ " #= ", # space(7) C1 C2 space(1)
56
+ " #= ", # space(6) C1 C2 space(2)
57
+ " #= ", # space(5) C1 C2 space(3)
58
+ " #= ", # space(4) C1 C2 space(4)
59
+ " #= ", # space(3) C1 C2 space(5)
60
+ " #= ", # space(2) C1 C2 space(6)
61
+ " #= ", # space(1) C1 C2 space(7)
62
+ ]
63
+
64
+ self.unicode_palette = "░█"
65
+ xlate_from, xlate_to = ("=#", self.unicode_palette)
66
+
67
+ # If unicode is supported, swap the ASCII chars for nicer glyphs.
68
+ if self._supports_unicode():
69
+ translation_table = str.maketrans(xlate_from, xlate_to)
70
+ frames = [f.translate(translation_table) for f in ascii_frames]
71
+ self.scan_char = xlate_to[xlate_from.find("#")]
72
+ else:
73
+ frames = ascii_frames
74
+ self.scan_char = "#"
75
+
76
+ # Bounce the scanner back and forth.
77
+ self.frames = frames
78
+ self.frame_idx = Spinner.last_frame_idx # Initialize from class variable
79
+ self.width = len(frames[0]) - 2 # number of chars between the brackets
80
+ self.animation_len = len(frames[0])
81
+ self.last_display_len = 0 # Length of the last spinner line (frame + text)
82
+
83
+ def _supports_unicode(self) -> bool:
84
+ if not self.is_tty:
85
+ return False
86
+ try:
87
+ out = self.unicode_palette
88
+ out += "\b" * len(self.unicode_palette)
89
+ out += " " * len(self.unicode_palette)
90
+ out += "\b" * len(self.unicode_palette)
91
+ sys.stdout.write(out)
92
+ sys.stdout.flush()
93
+ return True
94
+ except UnicodeEncodeError:
95
+ return False
96
+ except Exception:
97
+ return False
98
+
99
+ def _next_frame(self) -> str:
100
+ frame = self.frames[self.frame_idx]
101
+ self.frame_idx = (self.frame_idx + 1) % len(self.frames)
102
+ Spinner.last_frame_idx = self.frame_idx # Update class variable
103
+ return frame
104
+
105
+ def step(self, text: str = None) -> None:
106
+ if text is not None:
107
+ self.text = text
108
+
109
+ if not self.is_tty:
110
+ return
111
+
112
+ now = time.time()
113
+ if not self.visible and now - self.start_time >= 0.5:
114
+ self.visible = True
115
+ self.last_update = 0.0
116
+ if self.is_tty:
117
+ self.console.show_cursor(False)
118
+
119
+ if not self.visible or now - self.last_update < 0.1:
120
+ return
121
+
122
+ self.last_update = now
123
+ frame_str = self._next_frame()
124
+
125
+ # Determine the maximum width for the spinner line
126
+ # Subtract 2 as requested, to leave a margin or prevent cursor wrapping issues
127
+ max_spinner_width = self.console.width - 2
128
+ if max_spinner_width < 0: # Handle extremely narrow terminals
129
+ max_spinner_width = 0
130
+
131
+ current_text_payload = f" {self.text}"
132
+ line_to_display = f"{frame_str}{current_text_payload}"
133
+
134
+ # Truncate the line if it's too long for the console width
135
+ if len(line_to_display) > max_spinner_width:
136
+ line_to_display = line_to_display[:max_spinner_width]
137
+
138
+ len_line_to_display = len(line_to_display)
139
+
140
+ # Calculate padding to clear any remnants from a longer previous line
141
+ padding_to_clear = " " * max(0, self.last_display_len - len_line_to_display)
142
+
143
+ # Write the spinner frame, text, and any necessary clearing spaces
144
+ sys.stdout.write(f"\r{line_to_display}{padding_to_clear}")
145
+ self.last_display_len = len_line_to_display
146
+
147
+ # Calculate number of backspaces to position cursor at the scanner character
148
+ scan_char_abs_pos = frame_str.find(self.scan_char)
149
+
150
+ # Total characters written to the line (frame + text + padding)
151
+ total_chars_written_on_line = len_line_to_display + len(padding_to_clear)
152
+
153
+ # num_backspaces will be non-positive if scan_char_abs_pos is beyond
154
+ # total_chars_written_on_line (e.g., if the scan char itself was truncated).
155
+ # (e.g., if the scan char itself was truncated).
156
+ # In such cases, (effectively) 0 backspaces are written,
157
+ # and the cursor stays at the end of the line.
158
+ num_backspaces = total_chars_written_on_line - scan_char_abs_pos
159
+ sys.stdout.write("\b" * num_backspaces)
160
+ sys.stdout.flush()
161
+
162
+ def end(self) -> None:
163
+ if self.visible and self.is_tty:
164
+ clear_len = self.last_display_len # Use the length of the last displayed content
165
+ sys.stdout.write("\r" + " " * clear_len + "\r")
166
+ sys.stdout.flush()
167
+ self.console.show_cursor(True)
168
+ self.visible = False
169
+
170
+
171
+ class WaitingSpinner:
172
+ """Background spinner that can be started/stopped safely."""
173
+
174
+ def __init__(self, text: str = "Waiting for LLM", delay: float = 0.15):
175
+ self.spinner = Spinner(text)
176
+ self.delay = delay
177
+ self._stop_event = threading.Event()
178
+ self._thread = threading.Thread(target=self._spin, daemon=True)
179
+
180
+ def _spin(self):
181
+ while not self._stop_event.is_set():
182
+ self.spinner.step()
183
+ time.sleep(self.delay)
184
+ self.spinner.end()
185
+
186
+ def start(self):
187
+ """Start the spinner in a background thread."""
188
+ if not self._thread.is_alive():
189
+ self._thread.start()
190
+
191
+ def stop(self):
192
+ """Request the spinner to stop and wait briefly for the thread to exit."""
193
+ self._stop_event.set()
194
+ if self._thread.is_alive():
195
+ self._thread.join(timeout=self.delay)
196
+ self.spinner.end()
197
+
198
+ # Allow use as a context-manager
199
+ def __enter__(self):
200
+ self.start()
201
+ return self
202
+
203
+ def __exit__(self, exc_type, exc_val, exc_tb):
204
+ self.stop()
205
+
206
+
207
+ def main():
208
+ spinner = Spinner("Running spinner...")
209
+ try:
210
+ for _ in range(100):
211
+ time.sleep(0.15)
212
+ spinner.step()
213
+ print("Success!")
214
+ except KeyboardInterrupt:
215
+ print("\nInterrupted by user.")
216
+ finally:
217
+ spinner.end()
218
+
219
+
220
+ if __name__ == "__main__":
221
+ main()
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.4
2
+ Name: opsmith-cli
3
+ Version: 0.1.2a0
4
+ Summary: Opsmith is an AI devops engineer in your terminal
5
+ License-Expression: GPL-3.0-only
6
+ License-File: LICENSE.txt
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: black>=25.1.0
19
+ Requires-Dist: boto3-stubs==1.38.36
20
+ Requires-Dist: gitpython>=3.1.44
21
+ Requires-Dist: google-cloud-resource-manager>=1.14.2
22
+ Requires-Dist: grep-ast>=0.9.0
23
+ Requires-Dist: inquirer>=3.4.0
24
+ Requires-Dist: networkx>=3.4.2
25
+ Requires-Dist: pick>=2.4.0
26
+ Requires-Dist: pydantic-ai[logfire]>=0.2.16
27
+ Requires-Dist: pydantic>=2.11.5
28
+ Requires-Dist: pyyaml>=6.0.2
29
+ Requires-Dist: tqdm>=4.67.1
30
+ Requires-Dist: tree-sitter-language-pack>=0.7.3
31
+ Requires-Dist: typer>=0.16.0
@@ -0,0 +1,55 @@
1
+ opsmith/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ opsmith/agent.py,sha256=rPnzpZtbReXU9EE_5YvcAi_TlTT0lh11CwkQ_oa_Rhc,9864
3
+ opsmith/constants.py,sha256=vCvE5zpp8tSgTGeoEyU-LGQy20_QXTxJf7dJ6vtIQ3Y,3554
4
+ opsmith/deployer.py,sha256=LnozCrvAPfl90cW6wrZh-6y5dUxk_YyLLohkxl0_gQg,8639
5
+ opsmith/git_repo.py,sha256=-8GMiCoHfAQ7DYTos7CJETtvHaSpmwB61eKFhl1ai0k,2803
6
+ opsmith/main.py,sha256=vZoapkT4xa3mF-Q1f5WAMCmZxB3FdbJ3kS4ASQn26CA,9481
7
+ opsmith/prompts.py,sha256=ZGwTs5u4Dg-br_sRlgrR5Wm0m-whHSqLZtrTczgGVMw,5159
8
+ opsmith/repo_map.py,sha256=TPwnP-Kldkx-tQKmoY7H7G-lD8eWynITIcXJdV8vLUE,22962
9
+ opsmith/settings.py,sha256=nfVA_1cdNHiPe5MSuIVu8t5vy-Qr9Fxv3aoVXI7Nkbk,778
10
+ opsmith/spinner.py,sha256=55uw6FYlJNnfCVZaOQNKi_f0twzA5xcJS38fryq-agY,7646
11
+ opsmith/cloud_providers/__init__.py,sha256=JOCbnSYE4oIu6ZYlOONEUM9WAeIUZjOvhL7LNgZxP8E,305
12
+ opsmith/cloud_providers/aws.py,sha256=SUR2L5I94-vca0gEn7ilC3CEEHBuFbluJcF3_WSjSAM,1815
13
+ opsmith/cloud_providers/base.py,sha256=Jx4b27XQSvntKfIlwLn6INinG-pt1qb9B2cpdC9bhm8,1590
14
+ opsmith/cloud_providers/gcp.py,sha256=TI831rvSfZp609dZnF3OwmC-0vVxg4mJGNq5cbCLtco,2545
15
+ opsmith/queries/tree-sitter-languages/README.md,sha256=ivZSEuWqYfUVLZl2AZZGRlm0bQsaG-VTBKBwACyM07k,291
16
+ opsmith/queries/tree-sitter-languages/arduino-tags.scm,sha256=HbgdothT9Jjk56COXTtUkVAdZ14rZNnqzLbWVLeRs5U,177
17
+ opsmith/queries/tree-sitter-languages/c-tags.scm,sha256=EIz45o5hBh8yEuck5ZR_4IpcGyWSeNrzxFmtkKZGt2k,461
18
+ opsmith/queries/tree-sitter-languages/c_sharp-tags.scm,sha256=wKyFtOFIk-kqIFB2yJBbu1VGRUhdkAnDpxo8sXubkjw,1025
19
+ opsmith/queries/tree-sitter-languages/chatito-tags.scm,sha256=ISkmrp5gIVxoYIPnoqxxqBlZj5G9tzhwJMx6b0dEKnQ,338
20
+ opsmith/queries/tree-sitter-languages/commonlisp-tags.scm,sha256=GYJlluTPEdrxn4jpYTX5YQAqk171rVBw7IBiCygMgtw,4713
21
+ opsmith/queries/tree-sitter-languages/cpp-tags.scm,sha256=2fSqTUcc01ABMHkA0JeG8axEOEXRfEIul8UKc9_tKGI,809
22
+ opsmith/queries/tree-sitter-languages/csharp-tags.scm,sha256=KORfK3ehKor6Pf6T5iniuoQr16EcHtUe0q3XIsCjPJs,1162
23
+ opsmith/queries/tree-sitter-languages/d-tags.scm,sha256=LDP3orqZ98TTFSkV_PODEs8LspTcCqUMvKcLdZwtgkc,1420
24
+ opsmith/queries/tree-sitter-languages/dart-tags.scm,sha256=Pa_leZjxxXQO7mH_zF5o-kZ5lqVxgvbyp8oQb_nZ9KA,2267
25
+ opsmith/queries/tree-sitter-languages/elisp-tags.scm,sha256=1r8iOMM_DEpXEvlA1rE7KlhGEzcqa2W6eH4F2d1iu7Y,246
26
+ opsmith/queries/tree-sitter-languages/elixir-tags.scm,sha256=fg9TDpbCixLr8UXNcNnfgFlR3Y7d3vtzLRb3LK84UaQ,1682
27
+ opsmith/queries/tree-sitter-languages/elm-tags.scm,sha256=Wp1D5wEGzFa_2biBWRaKbghDs57lDGqqsZd7DbPkdn4,953
28
+ opsmith/queries/tree-sitter-languages/gleam-tags.scm,sha256=wdFVAkepPAZ10-5sBIVQSl45v95wZP9Foi_iYvM4YII,1416
29
+ opsmith/queries/tree-sitter-languages/go-tags.scm,sha256=TE4fQ7PtQvHKPetrhHeDqjMz01KFKFsxFjypnJMv8pI,1339
30
+ opsmith/queries/tree-sitter-languages/hcl-tags.scm,sha256=yOVCBeF4C3ZrFG-gg0adWg2QkxylPcI2dbVeEgD7EPE,2137
31
+ opsmith/queries/tree-sitter-languages/java-tags.scm,sha256=Xid8cnOPL1v5SOtxfq8dOi98bWrUPL7XeO8_I2qBrfE,624
32
+ opsmith/queries/tree-sitter-languages/javascript-tags.scm,sha256=0qlZIwDdsvoEGM0cYD3s2ez27FbYuz8epZAo-cLP1uI,2306
33
+ opsmith/queries/tree-sitter-languages/kotlin-tags.scm,sha256=ugk8v7Or3PXiBk-_HfZznwLuV-b-s3TYm03Wm3q2h_o,632
34
+ opsmith/queries/tree-sitter-languages/lua-tags.scm,sha256=lqhCVn7KnBVhW8oo_wY9me15nEBTu9BS5YlF1zUTOPs,945
35
+ opsmith/queries/tree-sitter-languages/ocaml-tags.scm,sha256=NAcyzmQuQPUjkchrQvcfhsvKqdcqbAt5eFb1chfEhMA,2695
36
+ opsmith/queries/tree-sitter-languages/ocaml_interface-tags.scm,sha256=2Vtp9o9EgQ0_kLUkIDXLOAkX9wp5cj_NwdovlwhiidQ,2009
37
+ opsmith/queries/tree-sitter-languages/php-tags.scm,sha256=vmE5CH2N46HiQxUpR_FL41ilQqsWsigojiacWXtwTuE,714
38
+ opsmith/queries/tree-sitter-languages/pony-tags.scm,sha256=gGNWmiHzv8Ge0HZo81tev-xIqHIQqjRxPR52G048-zs,2191
39
+ opsmith/queries/tree-sitter-languages/properties-tags.scm,sha256=AbcjxhGpG6F6lpCHs83HRXD223b-wrHQYv-i9j09wtc,135
40
+ opsmith/queries/tree-sitter-languages/python-tags.scm,sha256=KDCrM7iaUwXZ_hb2wVHrE2_EVCq_ASo3-BmbzsLtFk0,437
41
+ opsmith/queries/tree-sitter-languages/ql-tags.scm,sha256=9qVpBGSgFC9fSK4E_5sO2gYe4_jPvN-D18SD6S5lNR8,707
42
+ opsmith/queries/tree-sitter-languages/r-tags.scm,sha256=3cb2Wt-8Tt1RGBNDPgo4nI9qROf00ONNVqPHv8Th-Mk,461
43
+ opsmith/queries/tree-sitter-languages/racket-tags.scm,sha256=iri2aFEabiim-geb-t3ClDVp1Zi8T_rX1H9L0tlpqK8,224
44
+ opsmith/queries/tree-sitter-languages/ruby-tags.scm,sha256=vIidsCeE2A0vdFN18yXKqUWmpXMrGXyo4un_0Mxqr6s,1290
45
+ opsmith/queries/tree-sitter-languages/rust-tags.scm,sha256=3rz1XqKaOPKPWRUNPTW5OX_TYEDj5tQZfMxBH3EMB6g,1451
46
+ opsmith/queries/tree-sitter-languages/scala-tags.scm,sha256=UxQjz80JIrrJ7Pm56uUnQyThfmQNvwk7aQzPNypB-Ao,1761
47
+ opsmith/queries/tree-sitter-languages/solidity-tags.scm,sha256=3uCJsbhwp-dVTiSsrGLt-PQ0uAnjmqUeHFPSEXd2JvM,1395
48
+ opsmith/queries/tree-sitter-languages/swift-tags.scm,sha256=ZvJcfjmUDZ9w14AXKSPPxf4gvpdE_qzBxDjfCczYrIQ,1439
49
+ opsmith/queries/tree-sitter-languages/typescript-tags.scm,sha256=OMdCeedPiA24ky82DpgTMKXK_l2ySTuF2zrQ2fJAi9E,1253
50
+ opsmith/queries/tree-sitter-languages/udev-tags.scm,sha256=avj3u4prIR7o8hymHezOsqrOqjPSLGYo7C_lOL4Dxlg,417
51
+ opsmith_cli-0.1.2a0.dist-info/METADATA,sha256=t8S5WyYsHicz5nXo0q4eYqo8BiubJYW7tspWUoFGsPI,1139
52
+ opsmith_cli-0.1.2a0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
+ opsmith_cli-0.1.2a0.dist-info/entry_points.txt,sha256=zd4pvSO9DScobHaYjQh2IvgMF9MFDIwNHjgXUo2zoqU,45
54
+ opsmith_cli-0.1.2a0.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
55
+ opsmith_cli-0.1.2a0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ opsmith = opsmith.main:app