das-cli 1.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.
das/__init__.py ADDED
File without changes
@@ -0,0 +1,50 @@
1
+ import os
2
+ import logging
3
+ from dotenv import load_dotenv
4
+ import asyncio
5
+ from semantic_kernel import Kernel
6
+ from semantic_kernel.connectors.ai.open_ai import (
7
+ OpenAIChatCompletion,
8
+ )
9
+ from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
10
+ from semantic_kernel.contents.chat_history import ChatHistory
11
+ from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
12
+ from das.ai.plugins.entries.entries_plugin import GetEntryByCodePlugin
13
+ from das.common.config import load_openai_api_key
14
+
15
+ logger = logging.getLogger(__name__)
16
+ load_dotenv()
17
+
18
+ class DasAI:
19
+
20
+ def __init__(self):
21
+ self.kernel = Kernel()
22
+ api_key = os.getenv("OPENAI_API_KEY") or load_openai_api_key()
23
+ if not api_key:
24
+ raise ValueError("OpenAI API key is not configured.")
25
+ self.openai_chat_completion = OpenAIChatCompletion(ai_model_id="gpt-4o-mini", api_key=api_key)
26
+ self.kernel.add_service(self.openai_chat_completion)
27
+ self.kernel.add_plugin(GetEntryByCodePlugin(), plugin_name="get_entry_by_code")
28
+
29
+ async def main(self):
30
+ history = ChatHistory()
31
+ history.add_system_message("You are a laboratory assistent that helps researchers; phD students and any employee of NIOZ to find their answers in DAS (Data Archive System). Only answer questions about DAS.")
32
+ user_input = None
33
+ while user_input != "exit":
34
+ user_input = input("User > ")
35
+ history.add_user_message(user_input)
36
+ result = await self.openai_chat_completion.get_chat_message_content(
37
+ chat_history=history,
38
+ settings=PromptExecutionSettings(
39
+ api_key=os.getenv("OPENAI_API_KEY") or load_openai_api_key(),
40
+ function_choice_behavior=FunctionChoiceBehavior.Auto()
41
+ ),
42
+ kernel=self.kernel
43
+ )
44
+ print("Assistant >",str(result))
45
+ history.add_message(result)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ ai = DasAI()
50
+ asyncio.run(ai.main())
@@ -0,0 +1,16 @@
1
+ import logging
2
+ from semantic_kernel.functions.kernel_function_decorator import kernel_function
3
+ from semantic_kernel.functions.kernel_arguments import KernelArguments
4
+ from das.managers.entries_manager import EntryManager
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ class GetEntryByCodePlugin:
10
+ def __init__(self):
11
+ self.entry_manager = EntryManager()
12
+
13
+ @kernel_function(name="GetEntryByCode", description="Get an entry by its code.")
14
+ def get_entry_by_code(self, code: str):
15
+ """Get the entry code based on the entry name."""
16
+ return self.entry_manager.get(code=code)
das/app.py ADDED
@@ -0,0 +1,37 @@
1
+ from das.authentication.auth import Auth
2
+ from das.services.attributes import AttributesService
3
+ from das.services.cache import CacheService
4
+ from das.services.entries import EntriesService
5
+ from das.services.entry_fields import EntryFieldsService
6
+ from das.services.hangfire import HangfireService
7
+ from das.services.search import SearchService
8
+ from das.common.config import save_api_url
9
+
10
+ # $env:PYTHONPATH="C:\Workspace\das-cli"
11
+
12
+ class Das:
13
+ def __init__(self, base_url: str):
14
+ if base_url is None or base_url == "":
15
+ raise ValueError("You must be authenticated.")
16
+ save_api_url(base_url)
17
+ self.base_url = base_url
18
+ self.attributes = AttributesService(base_url)
19
+ self.cache = CacheService(base_url)
20
+ self.entries = EntriesService(base_url)
21
+ self.hangfire = HangfireService(base_url)
22
+ self.entry_fields = EntryFieldsService(base_url)
23
+ self.search = SearchService(base_url)
24
+
25
+ def authenticate(self, username: str, password: str) -> str:
26
+ """
27
+ Authenticate with the DAS API and return the token.
28
+
29
+ Args:
30
+ username (str): The username to authenticate with
31
+ password (str): The password to authenticate with
32
+
33
+ Returns:
34
+ str: The authentication token or None if authentication fails
35
+ """
36
+ auth = Auth(self.base_url, username, password)
37
+ return auth.token
@@ -0,0 +1,43 @@
1
+ from das.common.api import post_data
2
+ from das.common.config import save_token
3
+
4
+
5
+ class Auth:
6
+ def __init__(self, base_url, username, password):
7
+ self.base_url = base_url
8
+ self.username = username
9
+ # Don't store password as an instance variable for security
10
+ self.token = None
11
+
12
+ # Pass password directly to authenticate method
13
+ self.authenticate(password)
14
+
15
+ def authenticate(self, password):
16
+ """
17
+ Authenticate the user and obtain an access token.
18
+
19
+ Args:
20
+ password (str): The password to authenticate with
21
+ """
22
+ url = f"{self.base_url}/api/TokenAuth/Authenticate"
23
+ data = {
24
+ "userNameOrEmailAddress": self.username,
25
+ "password": password
26
+ }
27
+ response = post_data(url, data=data)
28
+ if response.get("error"):
29
+ print(f"Authentication failed: {response['error']}")
30
+ else:
31
+ self.token = response.get("result").get("accessToken")
32
+ save_token(self.token)
33
+ # Return silently, let the CLI handle success messages
34
+ return self.token
35
+
36
+ if __name__ == "__main__":
37
+ # Example for testing authentication
38
+ import getpass
39
+ base_url = input("Base URL: ")
40
+ username = input("Username: ")
41
+ password = getpass.getpass("Password: ")
42
+ auth = Auth(base_url=base_url, username=username, password=password)
43
+ print(f"Token obtained: {bool(auth.token)}")
@@ -0,0 +1,67 @@
1
+ import getpass
2
+ import keyring
3
+ import platform
4
+ import os
5
+
6
+ # Define service name for keyring
7
+ SERVICE_NAME = "das-cli"
8
+
9
+ def get_password(username, prompt="Password: "):
10
+ """
11
+ Get password securely using the appropriate method for the platform.
12
+
13
+ Args:
14
+ username (str): Username for associating with stored password
15
+ prompt (str): Prompt text to display when asking for password
16
+
17
+ Returns:
18
+ str: The password entered by user or retrieved from keyring
19
+ """
20
+ try:
21
+ # Try to get password from keyring first
22
+ stored_pass = keyring.get_password(SERVICE_NAME, username)
23
+ if stored_pass:
24
+ return stored_pass
25
+ except:
26
+ # If keyring fails, continue to manual input
27
+ pass
28
+
29
+ # Get password from user input
30
+ return getpass.getpass(prompt)
31
+
32
+ def store_credentials(username, password):
33
+ """
34
+ Store credentials securely in the system's keyring.
35
+
36
+ Args:
37
+ username (str): The username to store
38
+ password (str): The password to store
39
+
40
+ Returns:
41
+ bool: True if successful, False otherwise
42
+ """
43
+ try:
44
+ keyring.set_password(SERVICE_NAME, username, password)
45
+ return True
46
+ except Exception as e:
47
+ print(f"Warning: Could not store credentials securely ({e})")
48
+ return False
49
+
50
+ def clear_stored_credentials(username):
51
+ """
52
+ Remove stored credentials from the system's keyring.
53
+
54
+ Args:
55
+ username (str): The username whose credentials should be removed
56
+
57
+ Returns:
58
+ bool: True if successful, False otherwise
59
+ """
60
+ try:
61
+ keyring.delete_password(SERVICE_NAME, username)
62
+ return True
63
+ except keyring.errors.PasswordDeleteError:
64
+ # Password doesn't exist
65
+ return True
66
+ except Exception:
67
+ return False