player2 0.0.1__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.
player2/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .core import APIClient
player2/core.py ADDED
@@ -0,0 +1,130 @@
1
+ import time
2
+ import threading
3
+ import requests
4
+ from typing import Optional, Dict, Any, List
5
+
6
+
7
+ class APIClient:
8
+ def __init__(self, game_id: str, base_url: Optional[str] = None):
9
+ self.game_id = game_id
10
+
11
+ # Fallback for base_url if not provided
12
+ if not base_url:
13
+ self.base_url = "http://127.0.0.1:4315/v1"
14
+ else:
15
+ self.base_url = base_url
16
+
17
+ # Automatically fetch the p2Key upon initialization
18
+ self.p2_key = self._login()
19
+
20
+ # Start the background health check loop
21
+ self._start_health_checker()
22
+
23
+ def _login(self) -> str:
24
+ login_url = f"http://localhost:4315/v1/login/web/{self.game_id}"
25
+
26
+ try:
27
+ response = requests.post(login_url, json={})
28
+ response.raise_for_status()
29
+ data = response.json()
30
+ return data["p2Key"]
31
+ except requests.exceptions.RequestException as e:
32
+ raise RuntimeError(f"Login failed: {e}")
33
+
34
+ def _start_health_checker(self):
35
+ """Starts a background thread that pings the health endpoint every 60 seconds."""
36
+
37
+ def health_loop():
38
+ health_url = "http://127.0.0.1:4315/v1/health"
39
+ while True:
40
+ try:
41
+ requests.get(health_url, timeout=5)
42
+ except requests.exceptions.RequestException:
43
+ pass
44
+ time.sleep(60)
45
+
46
+ thread = threading.Thread(target=health_loop, daemon=True)
47
+ thread.start()
48
+
49
+ def chat(self, user: str, system: Optional[str] = None, stream: bool = False) -> str:
50
+ endpoint = f"{self.base_url}/chat/completions"
51
+
52
+ messages: List[Dict[str, str]] = [
53
+ {"role": "user", "content": user}
54
+ ]
55
+
56
+ if system is not None:
57
+ messages.insert(0, {"role": "system", "content": system})
58
+
59
+ payload = {
60
+ "messages": messages,
61
+ "stream": stream
62
+ }
63
+
64
+ headers = {
65
+ "Authorization": f"Bearer {self.p2_key}"
66
+ }
67
+
68
+ try:
69
+ response = requests.post(endpoint, json=payload, headers=headers)
70
+ response.raise_for_status()
71
+ data = response.json()
72
+
73
+ return data["choices"][0]["message"]["content"]
74
+
75
+ except requests.exceptions.HTTPError as e:
76
+ error_body = e.response.text if e.response else "No error body"
77
+ raise RuntimeError(f"API request failed with status {e.response.status_code}: {error_body}")
78
+ except requests.exceptions.RequestException as e:
79
+ raise RuntimeError(f"Network error occurred: {e}")
80
+ except (KeyError, IndexError) as e:
81
+ raise RuntimeError(f"Unexpected response format from API: {e}")
82
+
83
+ def speak(
84
+ self,
85
+ text: str,
86
+ instructions: Optional[str] = "Speak with a sad tone",
87
+ voice_gender: str = "female",
88
+ voice_language: str = "en_US",
89
+ voice_ids: Optional[List[str]] = None,
90
+ speed: float = 1.0,
91
+ audio_format: str = "mp3",
92
+ play_in_app: bool = True
93
+ ) -> Dict[str, Any]:
94
+ """Sends a Text-to-Speech request to the local TTS endpoint."""
95
+ tts_url = "http://127.0.0.1:4315/v1/tts/speak"
96
+
97
+ # Use default voice ID from your curl example if none provided
98
+ if voice_ids is None:
99
+ voice_ids = ["01955d76-ed5b-73e0-a88d-cbeb3c5b499d"]
100
+
101
+ payload: Dict[str, Any] = {
102
+ "audio_format": audio_format,
103
+ "play_in_app": play_in_app,
104
+ "speed": speed,
105
+ "text": text,
106
+ "voice_gender": voice_gender,
107
+ "voice_ids": voice_ids,
108
+ "voice_language": voice_language
109
+ }
110
+
111
+ # Add advanced voice instructions if provided
112
+ if instructions is not None:
113
+ payload["advanced_voice"] = {
114
+ "instructions": instructions
115
+ }
116
+
117
+ headers = {
118
+ "accept": "application/json",
119
+ "Content-Type": "application/json"
120
+ }
121
+
122
+ try:
123
+ response = requests.post(tts_url, json=payload, headers=headers)
124
+ response.raise_for_status()
125
+ return response.json()
126
+ except requests.exceptions.HTTPError as e:
127
+ error_body = e.response.text if e.response else "No error body"
128
+ raise RuntimeError(f"TTS request failed with status {e.response.status_code}: {error_body}")
129
+ except requests.exceptions.RequestException as e:
130
+ raise RuntimeError(f"TTS network error occurred: {e}")
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: player2
3
+ Version: 0.0.1
4
+ Summary: A lightweight client for Player2
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Operating System :: OS Independent
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: requests
11
+
12
+ # Local API Client
13
+
14
+ A lightweight Python client designed to easily interact with Player2 Local Endpoints.
15
+
16
+ ## Installation
17
+
18
+ Install the package via pip:
19
+
20
+ ```bash
21
+ pip install player2
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### 1. Initialize the Client
27
+
28
+ When initializing the client, pass your `game_id`. It will automatically handle web login to fetch authorization keys and spin up a background health-check loop.
29
+
30
+ ```python
31
+ from player2 import APIClient
32
+
33
+ client = APIClient(game_id="your_game_id") # Get the gameID from the player2 website
34
+ ```
35
+
36
+ ### 2. Chat Completions
37
+
38
+ Send user queries with optional system instructions:
39
+
40
+ ```python
41
+ response = client.chat(
42
+ user="Hello, how are you doing today?",
43
+ system="You are a helpful and witty assistant."
44
+ )
45
+
46
+ print(response)
47
+
48
+ ```
49
+
50
+ ### 3. Text-to-Speech (TTS)
51
+
52
+ Trigger speech generation locally:
53
+
54
+ ```python
55
+ tts_response = client.speak(
56
+ text="Hello, how are you doing today?",
57
+ instructions="Speak with a cheerful tone",
58
+ speed=1.0
59
+ )
60
+
61
+ print(tts_response)
62
+ ```
@@ -0,0 +1,6 @@
1
+ player2/__init__.py,sha256=PsI5TL5RCdziUikX_zfngmRAE2GRX3ljIirRtjfmJmg,27
2
+ player2/core.py,sha256=CHDrKHaFH4LqsXkJTZDUqaJa0SBZFKn9Y5PZd1-dUF0,4547
3
+ player2-0.0.1.dist-info/METADATA,sha256=DvoMgHTiFojpZjBWUbB7tL879QkNSnJLqjHhojP6woQ,1319
4
+ player2-0.0.1.dist-info/WHEEL,sha256=a-udL2m4V_6Yn8b-uKzWb12RjRxwwMo6ohYFM24tpaY,91
5
+ player2-0.0.1.dist-info/top_level.txt,sha256=LykiWt7T8bwUYs9MFcsnmZZVlXTPqfVJbkzk-rtW9d4,8
6
+ player2-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ player2