jvcli 2.0.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.
- jvcli/__init__.py +8 -0
- jvcli/api.py +318 -0
- jvcli/auth.py +45 -0
- jvcli/cli.py +36 -0
- jvcli/client/assets/index-BtFItD2q.js +156 -0
- jvcli/client/assets/index-CIEsu-TC.css +1 -0
- jvcli/client/index.html +15 -0
- jvcli/client/jac_logo.png +0 -0
- jvcli/client/tauri.svg +6 -0
- jvcli/client/vite.svg +1 -0
- jvcli/commands/__init__.py +1 -0
- jvcli/commands/auth.py +46 -0
- jvcli/commands/create.py +452 -0
- jvcli/commands/download.py +111 -0
- jvcli/commands/info.py +91 -0
- jvcli/commands/publish.py +207 -0
- jvcli/commands/studio.py +96 -0
- jvcli/commands/update.py +67 -0
- jvcli/templates/2.0.0/action_info.yaml +14 -0
- jvcli/templates/2.0.0/agent_descriptor.yaml +30 -0
- jvcli/templates/2.0.0/agent_info.yaml +10 -0
- jvcli/templates/2.0.0/agent_knowledge.yaml +14 -0
- jvcli/templates/2.0.0/agent_memory.yaml +1 -0
- jvcli/templates/CHANGELOG.md +2 -0
- jvcli/templates/README.md +4 -0
- jvcli/utils.py +209 -0
- jvcli-2.0.0.dist-info/LICENSE +201 -0
- jvcli-2.0.0.dist-info/METADATA +24 -0
- jvcli-2.0.0.dist-info/RECORD +32 -0
- jvcli-2.0.0.dist-info/WHEEL +5 -0
- jvcli-2.0.0.dist-info/entry_points.txt +2 -0
- jvcli-2.0.0.dist-info/top_level.txt +1 -0
jvcli/__init__.py
ADDED
jvcli/api.py
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
"""This module contains the API class for interacting with the Jivas Package Repository."""
|
2
|
+
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import click
|
6
|
+
import requests
|
7
|
+
|
8
|
+
|
9
|
+
class RegistryAPI:
|
10
|
+
"""Class for interacting with the Jivas Package Repository API."""
|
11
|
+
|
12
|
+
url = "https://api-jpr.trueselph.com/"
|
13
|
+
|
14
|
+
@staticmethod
|
15
|
+
def signup(username: str, email: str, password: str) -> dict:
|
16
|
+
"""Sign up for a Jivas Package Repository account."""
|
17
|
+
endpoint = "signup"
|
18
|
+
|
19
|
+
try:
|
20
|
+
data = {"username": username, "email": email, "password": password}
|
21
|
+
response = requests.post(RegistryAPI.url + endpoint, json=data)
|
22
|
+
|
23
|
+
# Check if the response is successful
|
24
|
+
if response.status_code == 200:
|
25
|
+
# Include email in the response
|
26
|
+
response_data = response.json()
|
27
|
+
response_data["email"] = email
|
28
|
+
return response_data
|
29
|
+
else:
|
30
|
+
click.secho(f"Error signing up: {response.json()['error']}", fg="red")
|
31
|
+
return {}
|
32
|
+
except Exception as e:
|
33
|
+
click.secho(f"Error signing up: {e}", fg="red")
|
34
|
+
return {}
|
35
|
+
|
36
|
+
@staticmethod
|
37
|
+
def login(email: str, password: str) -> dict:
|
38
|
+
"""Log in to your Jivas Package Repository account."""
|
39
|
+
endpoint = "login"
|
40
|
+
|
41
|
+
try:
|
42
|
+
data = {"emailOrUsername": email, "password": password}
|
43
|
+
response = requests.post(RegistryAPI.url + endpoint, json=data)
|
44
|
+
|
45
|
+
# Check if the response is successful
|
46
|
+
if response.status_code == 200:
|
47
|
+
# Include email in the response
|
48
|
+
response_data = response.json()
|
49
|
+
response_data["email"] = email
|
50
|
+
return response_data
|
51
|
+
else:
|
52
|
+
click.secho(f"Error logging in: {response.json()['error']}", fg="red")
|
53
|
+
return {}
|
54
|
+
except Exception as e:
|
55
|
+
click.secho(f"Error logging in: {e}", fg="red")
|
56
|
+
return {}
|
57
|
+
|
58
|
+
@staticmethod
|
59
|
+
def get_package_info(
|
60
|
+
name: str, version: str = "", token: Optional[str] = None
|
61
|
+
) -> dict:
|
62
|
+
"""Get action info.yaml content as json"""
|
63
|
+
endpoint = "info"
|
64
|
+
|
65
|
+
try:
|
66
|
+
headers = {"Authorization": f"Bearer {token}"} if token else None
|
67
|
+
data = {
|
68
|
+
"name": name,
|
69
|
+
"version": "" if version == "latest" else version,
|
70
|
+
}
|
71
|
+
response = requests.get(
|
72
|
+
RegistryAPI.url + endpoint, params=data, headers=headers
|
73
|
+
)
|
74
|
+
# Check if the response is successful
|
75
|
+
if response.status_code == 200:
|
76
|
+
return response.json()
|
77
|
+
else:
|
78
|
+
click.secho(
|
79
|
+
f"Error retrieving action: {response.json()['error']}",
|
80
|
+
fg="red",
|
81
|
+
)
|
82
|
+
return {}
|
83
|
+
except Exception as e:
|
84
|
+
click.secho(f"Error retrieving action: {e}", fg="red")
|
85
|
+
return {}
|
86
|
+
|
87
|
+
@staticmethod
|
88
|
+
def download_package(
|
89
|
+
name: str,
|
90
|
+
version: str = "",
|
91
|
+
info: bool = False,
|
92
|
+
suppress_error: bool = False,
|
93
|
+
token: Optional[str] = None,
|
94
|
+
) -> dict:
|
95
|
+
"""Download a Jivas Package."""
|
96
|
+
endpoint = "download"
|
97
|
+
|
98
|
+
try:
|
99
|
+
headers = {"Authorization": f"Bearer {token}"} if token else None
|
100
|
+
|
101
|
+
data = {
|
102
|
+
"name": name,
|
103
|
+
"info": "true" if info else "false",
|
104
|
+
"version": "" if version == "latest" else version,
|
105
|
+
}
|
106
|
+
response = requests.get(
|
107
|
+
RegistryAPI.url + endpoint,
|
108
|
+
params=data,
|
109
|
+
headers=headers,
|
110
|
+
)
|
111
|
+
# Check if the response is successful
|
112
|
+
if response.status_code == 200:
|
113
|
+
return response.json()
|
114
|
+
else:
|
115
|
+
if not suppress_error:
|
116
|
+
click.secho(
|
117
|
+
f"Error downloading package: {response.json()['error']}",
|
118
|
+
fg="red",
|
119
|
+
)
|
120
|
+
return {}
|
121
|
+
except Exception as e:
|
122
|
+
click.secho(f"Error downloading package: {e}", fg="red")
|
123
|
+
return {}
|
124
|
+
|
125
|
+
@staticmethod
|
126
|
+
def get_action_info(
|
127
|
+
name: str, version: str = "", token: Optional[str] = None
|
128
|
+
) -> dict:
|
129
|
+
"""Get action info.yaml content as json"""
|
130
|
+
endpoint = "info"
|
131
|
+
|
132
|
+
try:
|
133
|
+
headers = {"Authorization": f"Bearer {token}"} if token else None
|
134
|
+
data = {
|
135
|
+
"name": name,
|
136
|
+
"version": "" if version == "latest" else version,
|
137
|
+
}
|
138
|
+
response = requests.get(
|
139
|
+
RegistryAPI.url + endpoint, params=data, headers=headers
|
140
|
+
)
|
141
|
+
# Check if the response is successful
|
142
|
+
if response.status_code == 200:
|
143
|
+
return response.json()
|
144
|
+
else:
|
145
|
+
click.secho(
|
146
|
+
f"Error retrieving action: {response.json()['error']}",
|
147
|
+
fg="red",
|
148
|
+
)
|
149
|
+
return {}
|
150
|
+
except Exception as e:
|
151
|
+
click.secho(f"Error retrieving action: {e}", fg="red")
|
152
|
+
return {}
|
153
|
+
|
154
|
+
@staticmethod
|
155
|
+
def create_namespace(name: str, token: str) -> dict:
|
156
|
+
"""Create a namespace."""
|
157
|
+
endpoint = "namespace"
|
158
|
+
|
159
|
+
try:
|
160
|
+
headers = {"Authorization": f"Bearer {token}"}
|
161
|
+
|
162
|
+
data = {"name": name}
|
163
|
+
|
164
|
+
response = requests.post(
|
165
|
+
RegistryAPI.url + endpoint, headers=headers, json=data
|
166
|
+
)
|
167
|
+
# Check if the response is successful
|
168
|
+
if response.status_code == 200:
|
169
|
+
return response.json()
|
170
|
+
else:
|
171
|
+
click.secho(
|
172
|
+
f"Error creating namespace: {response.json()['message']}", fg="red"
|
173
|
+
)
|
174
|
+
return {}
|
175
|
+
except Exception as e:
|
176
|
+
click.secho(f"Error creating namespace: {e}", fg="red")
|
177
|
+
return {}
|
178
|
+
|
179
|
+
@staticmethod
|
180
|
+
def invite_user_to_namespace(
|
181
|
+
namespace_name: str, user_email: str, token: str
|
182
|
+
) -> dict:
|
183
|
+
"""Invite a user to a namespace."""
|
184
|
+
endpoint = f"namespace/{namespace_name}/invite"
|
185
|
+
|
186
|
+
try:
|
187
|
+
headers = {"Authorization": f"Bearer {token}"}
|
188
|
+
|
189
|
+
data = {"emailOrUsername": user_email}
|
190
|
+
|
191
|
+
response = requests.post(
|
192
|
+
RegistryAPI.url + endpoint, headers=headers, json=data
|
193
|
+
)
|
194
|
+
# Check if the response is successful
|
195
|
+
if response.status_code == 200:
|
196
|
+
return response.json()
|
197
|
+
else:
|
198
|
+
click.secho(
|
199
|
+
f"Error inviting user to namespace: {response.json()['message']}",
|
200
|
+
fg="red",
|
201
|
+
)
|
202
|
+
return {}
|
203
|
+
except Exception as e:
|
204
|
+
click.secho(f"Error inviting user to namespace: {e}", fg="red")
|
205
|
+
return {}
|
206
|
+
|
207
|
+
@staticmethod
|
208
|
+
def transfer_namespace_ownership(
|
209
|
+
namespace_name: str, new_owner_email: str, token: str
|
210
|
+
) -> dict:
|
211
|
+
"""Transfer ownership of a namespace."""
|
212
|
+
endpoint = f"namespace/{namespace_name}/transfer-ownership"
|
213
|
+
|
214
|
+
try:
|
215
|
+
headers = {"Authorization": f"Bearer {token}"}
|
216
|
+
|
217
|
+
data = {"emailOrUsername": new_owner_email}
|
218
|
+
|
219
|
+
response = requests.post(
|
220
|
+
RegistryAPI.url + endpoint, headers=headers, json=data
|
221
|
+
)
|
222
|
+
# Check if the response is successful
|
223
|
+
if response.status_code == 200:
|
224
|
+
return response.json()
|
225
|
+
else:
|
226
|
+
click.secho(
|
227
|
+
f"Error transferring ownership of namespace: {response.json()['message']}",
|
228
|
+
fg="red",
|
229
|
+
)
|
230
|
+
return {}
|
231
|
+
except Exception as e:
|
232
|
+
click.secho(f"Error transferring ownership of namespace: {e}", fg="red")
|
233
|
+
return {}
|
234
|
+
|
235
|
+
@staticmethod
|
236
|
+
def package_search(
|
237
|
+
query: str,
|
238
|
+
version: Optional[str] = None,
|
239
|
+
operator: Optional[str] = None,
|
240
|
+
limit: int = 15,
|
241
|
+
offset: int = 0,
|
242
|
+
) -> dict:
|
243
|
+
"""Search for packages in the Jivas Package Repository."""
|
244
|
+
endpoint = "packages/search"
|
245
|
+
|
246
|
+
try:
|
247
|
+
data = {
|
248
|
+
"q": query,
|
249
|
+
# "version": version, # TODO: Implement version filtering
|
250
|
+
# "operator": operator, # TODO: Implement operator filtering
|
251
|
+
"limit": limit,
|
252
|
+
"offset": offset,
|
253
|
+
}
|
254
|
+
response = requests.post(RegistryAPI.url + endpoint, json=data)
|
255
|
+
# Check if the response is successful
|
256
|
+
if response.status_code == 200:
|
257
|
+
return response.json()
|
258
|
+
else:
|
259
|
+
click.secho(
|
260
|
+
f"Error searching for packages: {response.json()['error']}",
|
261
|
+
fg="red",
|
262
|
+
)
|
263
|
+
return {}
|
264
|
+
except Exception as e:
|
265
|
+
click.secho(f"Error searching for packages: {e}", fg="red")
|
266
|
+
return {}
|
267
|
+
|
268
|
+
@staticmethod
|
269
|
+
def publish_action(
|
270
|
+
tgz_file_path: str, visibility: str, token: str, namespace: str
|
271
|
+
) -> dict:
|
272
|
+
"""Publish a Jivas Action to the repository."""
|
273
|
+
endpoint = "publish"
|
274
|
+
|
275
|
+
try:
|
276
|
+
headers = {
|
277
|
+
"Authorization": f"Bearer {token}",
|
278
|
+
}
|
279
|
+
|
280
|
+
# Open the .tgz file using a context manager to ensure it's closed after use
|
281
|
+
with open(tgz_file_path, "rb") as tgz_file:
|
282
|
+
files = {"file": tgz_file}
|
283
|
+
data = {
|
284
|
+
"visibility": visibility.capitalize(), # Ensure correct capitalization
|
285
|
+
"namespace": namespace,
|
286
|
+
}
|
287
|
+
|
288
|
+
# Send POST request
|
289
|
+
response = requests.post(
|
290
|
+
RegistryAPI.url + endpoint, headers=headers, files=files, data=data
|
291
|
+
)
|
292
|
+
|
293
|
+
if response.status_code == 401:
|
294
|
+
click.secho(
|
295
|
+
"Error publishing package: Invalid token. Please login again.",
|
296
|
+
fg="red",
|
297
|
+
)
|
298
|
+
return {}
|
299
|
+
|
300
|
+
# Check if the response is successful
|
301
|
+
if response.status_code == 200:
|
302
|
+
return response.json() # Return the response data if successful
|
303
|
+
else:
|
304
|
+
if response.json()["error"] == "VERSION_CONFLICT":
|
305
|
+
click.secho(
|
306
|
+
f"Error publishing package: {response.json()['message']}",
|
307
|
+
fg="red",
|
308
|
+
)
|
309
|
+
return {}
|
310
|
+
else:
|
311
|
+
# Print and show error message
|
312
|
+
click.secho(
|
313
|
+
f"Error publishing package: {response.json()}", fg="red"
|
314
|
+
)
|
315
|
+
return {}
|
316
|
+
except Exception as e:
|
317
|
+
click.secho(f"Error publishing package: {e}", fg="red")
|
318
|
+
return {}
|
jvcli/auth.py
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
"""Authentication module for the CLI."""
|
2
|
+
|
3
|
+
import json
|
4
|
+
import os
|
5
|
+
|
6
|
+
TOKEN_FILE = os.path.expanduser("~/.jvcli_token")
|
7
|
+
|
8
|
+
|
9
|
+
def save_token(token: str, namespaces: dict, email: str) -> None:
|
10
|
+
"""Save the token to a file."""
|
11
|
+
data = {"token": token, "namespaces": clean_namespaces(namespaces), "email": email}
|
12
|
+
with open(TOKEN_FILE, "w") as f:
|
13
|
+
json.dump(data, f)
|
14
|
+
|
15
|
+
|
16
|
+
def load_token() -> dict:
|
17
|
+
"""Load the token from a file."""
|
18
|
+
if os.path.exists(TOKEN_FILE):
|
19
|
+
with open(TOKEN_FILE, "r") as f:
|
20
|
+
data = json.load(f)
|
21
|
+
return data
|
22
|
+
return {}
|
23
|
+
|
24
|
+
|
25
|
+
def delete_token() -> None:
|
26
|
+
"""Delete the token file."""
|
27
|
+
if os.path.exists(TOKEN_FILE):
|
28
|
+
os.remove(TOKEN_FILE)
|
29
|
+
|
30
|
+
|
31
|
+
def clean_namespaces(namespaces: dict) -> dict:
|
32
|
+
"""Clean up the namespaces dict."""
|
33
|
+
for k, v in namespaces.items():
|
34
|
+
if k == "default":
|
35
|
+
namespaces[k] = v.replace("@", "")
|
36
|
+
if k == "groups":
|
37
|
+
v = [group.replace("@", "") for group in v]
|
38
|
+
namespaces[k] = v
|
39
|
+
return namespaces
|
40
|
+
|
41
|
+
|
42
|
+
def load_namespaces() -> str:
|
43
|
+
"""Load the namespaces from the token."""
|
44
|
+
token = load_token()
|
45
|
+
return token.get("namespaces", {}).get("default", "anonymous")
|
jvcli/cli.py
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
"""Jivas Package Repository CLI tool."""
|
2
|
+
|
3
|
+
import click
|
4
|
+
|
5
|
+
from jvcli import __version__
|
6
|
+
from jvcli.commands.auth import login, logout, signup
|
7
|
+
from jvcli.commands.create import create
|
8
|
+
from jvcli.commands.download import download
|
9
|
+
from jvcli.commands.info import info
|
10
|
+
from jvcli.commands.publish import publish
|
11
|
+
from jvcli.commands.studio import studio
|
12
|
+
from jvcli.commands.update import update
|
13
|
+
|
14
|
+
|
15
|
+
@click.group()
|
16
|
+
@click.version_option(__version__, prog_name="jvcli")
|
17
|
+
def jvcli() -> None:
|
18
|
+
"""Jivas Package Repository CLI tool."""
|
19
|
+
pass # pragma: no cover
|
20
|
+
|
21
|
+
|
22
|
+
# Register command groups
|
23
|
+
jvcli.add_command(create)
|
24
|
+
jvcli.add_command(update)
|
25
|
+
jvcli.add_command(download)
|
26
|
+
jvcli.add_command(publish)
|
27
|
+
jvcli.add_command(info)
|
28
|
+
jvcli.add_command(studio)
|
29
|
+
|
30
|
+
# Register standalone commands
|
31
|
+
jvcli.add_command(signup)
|
32
|
+
jvcli.add_command(login)
|
33
|
+
jvcli.add_command(logout)
|
34
|
+
|
35
|
+
if __name__ == "__main__":
|
36
|
+
jvcli() # pragma: no cover
|