yaver 0.1.0__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.
- yaver-0.1.0/PKG-INFO +77 -0
- yaver-0.1.0/README.md +54 -0
- yaver-0.1.0/pyproject.toml +35 -0
- yaver-0.1.0/setup.cfg +4 -0
- yaver-0.1.0/yaver.egg-info/PKG-INFO +77 -0
- yaver-0.1.0/yaver.egg-info/SOURCES.txt +7 -0
- yaver-0.1.0/yaver.egg-info/dependency_links.txt +1 -0
- yaver-0.1.0/yaver.egg-info/top_level.txt +1 -0
- yaver-0.1.0/yaver.py +273 -0
yaver-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yaver
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Yaver SDK — embed P2P AI agent connectivity into your Python apps
|
|
5
|
+
Author-email: Kivanc Cakmak <kivanc@yaver.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://yaver.io
|
|
8
|
+
Project-URL: Repository, https://github.com/kivanccakmak/yaver.io
|
|
9
|
+
Project-URL: Documentation, https://github.com/kivanccakmak/yaver.io/tree/main/sdk/python
|
|
10
|
+
Keywords: yaver,ai,agent,p2p,speech-to-text,tts,sdk
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Yaver Python SDK
|
|
25
|
+
|
|
26
|
+
Embed Yaver's P2P AI agent connectivity into your Python applications. Zero dependencies (stdlib only).
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install yaver
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from yaver import YaverClient
|
|
38
|
+
|
|
39
|
+
client = YaverClient("http://localhost:18080", "your-auth-token")
|
|
40
|
+
|
|
41
|
+
# Create a task
|
|
42
|
+
task = client.create_task("Fix the login bug")
|
|
43
|
+
print(f"Task {task['id']} created")
|
|
44
|
+
|
|
45
|
+
# Stream output
|
|
46
|
+
for chunk in client.stream_output(task["id"]):
|
|
47
|
+
print(chunk, end="")
|
|
48
|
+
|
|
49
|
+
# List all tasks
|
|
50
|
+
tasks = client.list_tasks()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Task management**: create, list, get, stop, delete, continue tasks
|
|
56
|
+
- **Output streaming**: poll-based streaming with configurable interval
|
|
57
|
+
- **Auth client**: validate tokens, list devices, manage settings via Convex backend
|
|
58
|
+
- **Verbosity control**: set response detail level 0-10
|
|
59
|
+
- **Native mode**: optional ctypes bindings via C shared library (libyaver.so)
|
|
60
|
+
- **Zero dependencies**: uses only Python stdlib
|
|
61
|
+
|
|
62
|
+
## Auth Client
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from yaver import YaverAuthClient
|
|
66
|
+
|
|
67
|
+
auth = YaverAuthClient("your-token")
|
|
68
|
+
user = auth.validate_token()
|
|
69
|
+
devices = auth.list_devices()
|
|
70
|
+
settings = auth.get_settings()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Links
|
|
74
|
+
|
|
75
|
+
- [Yaver](https://yaver.io) — main site
|
|
76
|
+
- [GitHub](https://github.com/kivanccakmak/yaver.io) — source code
|
|
77
|
+
- [SDK docs](https://github.com/kivanccakmak/yaver.io/tree/main/sdk) — all SDKs
|
yaver-0.1.0/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Yaver Python SDK
|
|
2
|
+
|
|
3
|
+
Embed Yaver's P2P AI agent connectivity into your Python applications. Zero dependencies (stdlib only).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install yaver
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from yaver import YaverClient
|
|
15
|
+
|
|
16
|
+
client = YaverClient("http://localhost:18080", "your-auth-token")
|
|
17
|
+
|
|
18
|
+
# Create a task
|
|
19
|
+
task = client.create_task("Fix the login bug")
|
|
20
|
+
print(f"Task {task['id']} created")
|
|
21
|
+
|
|
22
|
+
# Stream output
|
|
23
|
+
for chunk in client.stream_output(task["id"]):
|
|
24
|
+
print(chunk, end="")
|
|
25
|
+
|
|
26
|
+
# List all tasks
|
|
27
|
+
tasks = client.list_tasks()
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- **Task management**: create, list, get, stop, delete, continue tasks
|
|
33
|
+
- **Output streaming**: poll-based streaming with configurable interval
|
|
34
|
+
- **Auth client**: validate tokens, list devices, manage settings via Convex backend
|
|
35
|
+
- **Verbosity control**: set response detail level 0-10
|
|
36
|
+
- **Native mode**: optional ctypes bindings via C shared library (libyaver.so)
|
|
37
|
+
- **Zero dependencies**: uses only Python stdlib
|
|
38
|
+
|
|
39
|
+
## Auth Client
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from yaver import YaverAuthClient
|
|
43
|
+
|
|
44
|
+
auth = YaverAuthClient("your-token")
|
|
45
|
+
user = auth.validate_token()
|
|
46
|
+
devices = auth.list_devices()
|
|
47
|
+
settings = auth.get_settings()
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Links
|
|
51
|
+
|
|
52
|
+
- [Yaver](https://yaver.io) — main site
|
|
53
|
+
- [GitHub](https://github.com/kivanccakmak/yaver.io) — source code
|
|
54
|
+
- [SDK docs](https://github.com/kivanccakmak/yaver.io/tree/main/sdk) — all SDKs
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "yaver"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Yaver SDK — embed P2P AI agent connectivity into your Python apps"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Kivanc Cakmak", email = "kivanc@yaver.io"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["yaver", "ai", "agent", "p2p", "speech-to-text", "tts", "sdk"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Libraries",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://yaver.io"
|
|
31
|
+
Repository = "https://github.com/kivanccakmak/yaver.io"
|
|
32
|
+
Documentation = "https://github.com/kivanccakmak/yaver.io/tree/main/sdk/python"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools]
|
|
35
|
+
py-modules = ["yaver"]
|
yaver-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yaver
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Yaver SDK — embed P2P AI agent connectivity into your Python apps
|
|
5
|
+
Author-email: Kivanc Cakmak <kivanc@yaver.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://yaver.io
|
|
8
|
+
Project-URL: Repository, https://github.com/kivanccakmak/yaver.io
|
|
9
|
+
Project-URL: Documentation, https://github.com/kivanccakmak/yaver.io/tree/main/sdk/python
|
|
10
|
+
Keywords: yaver,ai,agent,p2p,speech-to-text,tts,sdk
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Yaver Python SDK
|
|
25
|
+
|
|
26
|
+
Embed Yaver's P2P AI agent connectivity into your Python applications. Zero dependencies (stdlib only).
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install yaver
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from yaver import YaverClient
|
|
38
|
+
|
|
39
|
+
client = YaverClient("http://localhost:18080", "your-auth-token")
|
|
40
|
+
|
|
41
|
+
# Create a task
|
|
42
|
+
task = client.create_task("Fix the login bug")
|
|
43
|
+
print(f"Task {task['id']} created")
|
|
44
|
+
|
|
45
|
+
# Stream output
|
|
46
|
+
for chunk in client.stream_output(task["id"]):
|
|
47
|
+
print(chunk, end="")
|
|
48
|
+
|
|
49
|
+
# List all tasks
|
|
50
|
+
tasks = client.list_tasks()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Task management**: create, list, get, stop, delete, continue tasks
|
|
56
|
+
- **Output streaming**: poll-based streaming with configurable interval
|
|
57
|
+
- **Auth client**: validate tokens, list devices, manage settings via Convex backend
|
|
58
|
+
- **Verbosity control**: set response detail level 0-10
|
|
59
|
+
- **Native mode**: optional ctypes bindings via C shared library (libyaver.so)
|
|
60
|
+
- **Zero dependencies**: uses only Python stdlib
|
|
61
|
+
|
|
62
|
+
## Auth Client
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from yaver import YaverAuthClient
|
|
66
|
+
|
|
67
|
+
auth = YaverAuthClient("your-token")
|
|
68
|
+
user = auth.validate_token()
|
|
69
|
+
devices = auth.list_devices()
|
|
70
|
+
settings = auth.get_settings()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Links
|
|
74
|
+
|
|
75
|
+
- [Yaver](https://yaver.io) — main site
|
|
76
|
+
- [GitHub](https://github.com/kivanccakmak/yaver.io) — source code
|
|
77
|
+
- [SDK docs](https://github.com/kivanccakmak/yaver.io/tree/main/sdk) — all SDKs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
yaver
|
yaver-0.1.0/yaver.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Yaver Python SDK — embed Yaver's P2P connectivity into your Python applications.
|
|
3
|
+
|
|
4
|
+
Supports two backends:
|
|
5
|
+
1. Native (ctypes) — loads the C shared library built from Go SDK
|
|
6
|
+
2. HTTP — direct HTTP calls to a Yaver agent (no shared library needed)
|
|
7
|
+
|
|
8
|
+
Quick start (HTTP mode — no build step):
|
|
9
|
+
|
|
10
|
+
from yaver import YaverClient
|
|
11
|
+
|
|
12
|
+
client = YaverClient("http://localhost:18080", "your-auth-token")
|
|
13
|
+
task = client.create_task("Fix the login bug")
|
|
14
|
+
for line in client.stream_output(task["id"]):
|
|
15
|
+
print(line, end="")
|
|
16
|
+
|
|
17
|
+
Quick start (native mode — requires libyaver.so):
|
|
18
|
+
|
|
19
|
+
from yaver import YaverNativeClient
|
|
20
|
+
|
|
21
|
+
client = YaverNativeClient("http://localhost:18080", "your-auth-token")
|
|
22
|
+
task = client.create_task("Fix the login bug")
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import json
|
|
26
|
+
import time
|
|
27
|
+
from typing import Optional, Iterator, Any
|
|
28
|
+
from urllib.request import Request, urlopen
|
|
29
|
+
from urllib.error import HTTPError
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class YaverClient:
|
|
33
|
+
"""HTTP-based Yaver client. No shared library needed."""
|
|
34
|
+
|
|
35
|
+
def __init__(self, base_url: str, auth_token: str, timeout: float = 30.0):
|
|
36
|
+
self.base_url = base_url.rstrip("/")
|
|
37
|
+
self.auth_token = auth_token
|
|
38
|
+
self.timeout = timeout
|
|
39
|
+
|
|
40
|
+
def _request(self, method: str, path: str, body: Any = None) -> dict:
|
|
41
|
+
url = f"{self.base_url}{path}"
|
|
42
|
+
data = json.dumps(body).encode() if body else None
|
|
43
|
+
req = Request(url, data=data, method=method)
|
|
44
|
+
req.add_header("Authorization", f"Bearer {self.auth_token}")
|
|
45
|
+
if data:
|
|
46
|
+
req.add_header("Content-Type", "application/json")
|
|
47
|
+
try:
|
|
48
|
+
with urlopen(req, timeout=self.timeout) as resp:
|
|
49
|
+
return json.loads(resp.read())
|
|
50
|
+
except HTTPError as e:
|
|
51
|
+
error_body = e.read().decode() if e.fp else str(e)
|
|
52
|
+
raise RuntimeError(f"HTTP {e.code}: {error_body}")
|
|
53
|
+
|
|
54
|
+
def health(self) -> dict:
|
|
55
|
+
"""Check if the agent is reachable."""
|
|
56
|
+
return self._request("GET", "/health")
|
|
57
|
+
|
|
58
|
+
def ping(self) -> float:
|
|
59
|
+
"""Measure round-trip time in milliseconds."""
|
|
60
|
+
start = time.monotonic()
|
|
61
|
+
self.health()
|
|
62
|
+
return (time.monotonic() - start) * 1000
|
|
63
|
+
|
|
64
|
+
def info(self) -> dict:
|
|
65
|
+
"""Get agent status information."""
|
|
66
|
+
return self._request("GET", "/info")
|
|
67
|
+
|
|
68
|
+
def create_task(
|
|
69
|
+
self,
|
|
70
|
+
prompt: str,
|
|
71
|
+
model: Optional[str] = None,
|
|
72
|
+
runner: Optional[str] = None,
|
|
73
|
+
custom_command: Optional[str] = None,
|
|
74
|
+
verbosity: Optional[int] = None,
|
|
75
|
+
) -> dict:
|
|
76
|
+
"""Create a new task on the remote agent."""
|
|
77
|
+
body: dict = {"title": prompt}
|
|
78
|
+
if model:
|
|
79
|
+
body["model"] = model
|
|
80
|
+
if runner:
|
|
81
|
+
body["runner"] = runner
|
|
82
|
+
if custom_command:
|
|
83
|
+
body["customCommand"] = custom_command
|
|
84
|
+
if verbosity is not None:
|
|
85
|
+
body["speechContext"] = {"verbosity": verbosity}
|
|
86
|
+
result = self._request("POST", "/tasks", body)
|
|
87
|
+
if not result.get("ok"):
|
|
88
|
+
raise RuntimeError(result.get("error", "Unknown error"))
|
|
89
|
+
return {
|
|
90
|
+
"id": result["taskId"],
|
|
91
|
+
"status": result["status"],
|
|
92
|
+
"runner_id": result.get("runnerId", ""),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
def get_task(self, task_id: str) -> dict:
|
|
96
|
+
"""Get task details by ID."""
|
|
97
|
+
result = self._request("GET", f"/tasks/{task_id}")
|
|
98
|
+
return result.get("task", result)
|
|
99
|
+
|
|
100
|
+
def list_tasks(self) -> list:
|
|
101
|
+
"""List all tasks."""
|
|
102
|
+
result = self._request("GET", "/tasks")
|
|
103
|
+
return result.get("tasks", [])
|
|
104
|
+
|
|
105
|
+
def stop_task(self, task_id: str) -> None:
|
|
106
|
+
"""Stop a running task."""
|
|
107
|
+
result = self._request("POST", f"/tasks/{task_id}/stop")
|
|
108
|
+
if not result.get("ok"):
|
|
109
|
+
raise RuntimeError(result.get("error", "Failed to stop task"))
|
|
110
|
+
|
|
111
|
+
def delete_task(self, task_id: str) -> None:
|
|
112
|
+
"""Delete a task."""
|
|
113
|
+
self._request("DELETE", f"/tasks/{task_id}")
|
|
114
|
+
|
|
115
|
+
def continue_task(self, task_id: str, message: str) -> None:
|
|
116
|
+
"""Send a follow-up message to a running task."""
|
|
117
|
+
result = self._request("POST", f"/tasks/{task_id}/continue", {"message": message})
|
|
118
|
+
if not result.get("ok"):
|
|
119
|
+
raise RuntimeError(result.get("error", "Failed to continue task"))
|
|
120
|
+
|
|
121
|
+
def stream_output(self, task_id: str, poll_interval: float = 0.5) -> Iterator[str]:
|
|
122
|
+
"""Stream task output. Yields new output as it arrives."""
|
|
123
|
+
last_len = 0
|
|
124
|
+
while True:
|
|
125
|
+
task = self.get_task(task_id)
|
|
126
|
+
output = task.get("output", "")
|
|
127
|
+
if len(output) > last_len:
|
|
128
|
+
yield output[last_len:]
|
|
129
|
+
last_len = len(output)
|
|
130
|
+
status = task.get("status", "")
|
|
131
|
+
if status in ("completed", "failed", "stopped"):
|
|
132
|
+
return
|
|
133
|
+
time.sleep(poll_interval)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class YaverAuthClient:
|
|
137
|
+
"""Auth client for the Convex backend."""
|
|
138
|
+
|
|
139
|
+
DEFAULT_CONVEX_URL = "https://perceptive-minnow-557.eu-west-1.convex.site"
|
|
140
|
+
|
|
141
|
+
def __init__(self, auth_token: str, convex_url: Optional[str] = None, timeout: float = 10.0):
|
|
142
|
+
self.convex_url = (convex_url or self.DEFAULT_CONVEX_URL).rstrip("/")
|
|
143
|
+
self.auth_token = auth_token
|
|
144
|
+
self.timeout = timeout
|
|
145
|
+
|
|
146
|
+
def _request(self, method: str, path: str, body: Any = None) -> dict:
|
|
147
|
+
url = f"{self.convex_url}{path}"
|
|
148
|
+
data = json.dumps(body).encode() if body else None
|
|
149
|
+
req = Request(url, data=data, method=method)
|
|
150
|
+
req.add_header("Authorization", f"Bearer {self.auth_token}")
|
|
151
|
+
if data:
|
|
152
|
+
req.add_header("Content-Type", "application/json")
|
|
153
|
+
with urlopen(req, timeout=self.timeout) as resp:
|
|
154
|
+
return json.loads(resp.read())
|
|
155
|
+
|
|
156
|
+
def validate_token(self) -> dict:
|
|
157
|
+
"""Validate the auth token and return user info."""
|
|
158
|
+
return self._request("GET", "/auth/validate")
|
|
159
|
+
|
|
160
|
+
def list_devices(self) -> list:
|
|
161
|
+
"""List registered devices."""
|
|
162
|
+
result = self._request("GET", "/devices")
|
|
163
|
+
return result.get("devices", [])
|
|
164
|
+
|
|
165
|
+
def get_settings(self) -> dict:
|
|
166
|
+
"""Get user settings."""
|
|
167
|
+
result = self._request("GET", "/settings")
|
|
168
|
+
return result.get("settings", {})
|
|
169
|
+
|
|
170
|
+
def save_settings(self, settings: dict) -> None:
|
|
171
|
+
"""Save user settings."""
|
|
172
|
+
self._request("POST", "/settings", settings)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ── Native (ctypes) client ────────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
import ctypes
|
|
179
|
+
import ctypes.util
|
|
180
|
+
import os
|
|
181
|
+
import platform
|
|
182
|
+
|
|
183
|
+
def _find_lib():
|
|
184
|
+
"""Find the libyaver shared library."""
|
|
185
|
+
# Check common locations
|
|
186
|
+
for name in ["libyaver.so", "libyaver.dylib", "libyaver.dll"]:
|
|
187
|
+
# Same directory as this file
|
|
188
|
+
here = os.path.join(os.path.dirname(__file__), name)
|
|
189
|
+
if os.path.exists(here):
|
|
190
|
+
return here
|
|
191
|
+
# SDK build directory
|
|
192
|
+
sdk_path = os.path.join(os.path.dirname(__file__), "..", "go", "clib", name)
|
|
193
|
+
if os.path.exists(sdk_path):
|
|
194
|
+
return sdk_path
|
|
195
|
+
# System library path
|
|
196
|
+
path = ctypes.util.find_library("yaver")
|
|
197
|
+
if path:
|
|
198
|
+
return path
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
class YaverNativeClient:
|
|
202
|
+
"""Native Yaver client using the C shared library (libyaver.so/dylib/dll)."""
|
|
203
|
+
|
|
204
|
+
def __init__(self, base_url: str, auth_token: str, lib_path: Optional[str] = None):
|
|
205
|
+
path = lib_path or _find_lib()
|
|
206
|
+
if not path:
|
|
207
|
+
raise FileNotFoundError(
|
|
208
|
+
"libyaver shared library not found. "
|
|
209
|
+
"Build it: cd sdk/go/clib && go build -buildmode=c-shared -o libyaver.so ."
|
|
210
|
+
)
|
|
211
|
+
self._lib = ctypes.CDLL(path)
|
|
212
|
+
|
|
213
|
+
# Set up function signatures
|
|
214
|
+
self._lib.YaverNewClient.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
|
|
215
|
+
self._lib.YaverNewClient.restype = ctypes.c_int
|
|
216
|
+
self._lib.YaverFreeClient.argtypes = [ctypes.c_int]
|
|
217
|
+
self._lib.YaverHealth.argtypes = [ctypes.c_int]
|
|
218
|
+
self._lib.YaverHealth.restype = ctypes.c_char_p
|
|
219
|
+
self._lib.YaverPing.argtypes = [ctypes.c_int]
|
|
220
|
+
self._lib.YaverPing.restype = ctypes.c_char_p
|
|
221
|
+
self._lib.YaverCreateTask.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p]
|
|
222
|
+
self._lib.YaverCreateTask.restype = ctypes.c_char_p
|
|
223
|
+
self._lib.YaverGetTask.argtypes = [ctypes.c_int, ctypes.c_char_p]
|
|
224
|
+
self._lib.YaverGetTask.restype = ctypes.c_char_p
|
|
225
|
+
self._lib.YaverListTasks.argtypes = [ctypes.c_int]
|
|
226
|
+
self._lib.YaverListTasks.restype = ctypes.c_char_p
|
|
227
|
+
self._lib.YaverStopTask.argtypes = [ctypes.c_int, ctypes.c_char_p]
|
|
228
|
+
self._lib.YaverStopTask.restype = ctypes.c_char_p
|
|
229
|
+
self._lib.YaverTranscribe.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
|
|
230
|
+
self._lib.YaverTranscribe.restype = ctypes.c_char_p
|
|
231
|
+
self._lib.YaverSpeak.argtypes = [ctypes.c_char_p]
|
|
232
|
+
self._lib.YaverSpeak.restype = ctypes.c_char_p
|
|
233
|
+
|
|
234
|
+
self._id = self._lib.YaverNewClient(
|
|
235
|
+
base_url.encode(), auth_token.encode()
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
def __del__(self):
|
|
239
|
+
if hasattr(self, "_lib") and hasattr(self, "_id"):
|
|
240
|
+
self._lib.YaverFreeClient(self._id)
|
|
241
|
+
|
|
242
|
+
def _call(self, result_bytes: bytes) -> dict:
|
|
243
|
+
return json.loads(result_bytes.decode())
|
|
244
|
+
|
|
245
|
+
def health(self) -> dict:
|
|
246
|
+
return self._call(self._lib.YaverHealth(self._id))
|
|
247
|
+
|
|
248
|
+
def ping(self) -> dict:
|
|
249
|
+
return self._call(self._lib.YaverPing(self._id))
|
|
250
|
+
|
|
251
|
+
def create_task(self, prompt: str, opts: Optional[dict] = None) -> dict:
|
|
252
|
+
opts_json = json.dumps(opts).encode() if opts else None
|
|
253
|
+
return self._call(self._lib.YaverCreateTask(self._id, prompt.encode(), opts_json))
|
|
254
|
+
|
|
255
|
+
def get_task(self, task_id: str) -> dict:
|
|
256
|
+
return self._call(self._lib.YaverGetTask(self._id, task_id.encode()))
|
|
257
|
+
|
|
258
|
+
def list_tasks(self) -> list:
|
|
259
|
+
return self._call(self._lib.YaverListTasks(self._id))
|
|
260
|
+
|
|
261
|
+
def stop_task(self, task_id: str) -> dict:
|
|
262
|
+
return self._call(self._lib.YaverStopTask(self._id, task_id.encode()))
|
|
263
|
+
|
|
264
|
+
def transcribe(self, audio_path: str, provider: str = "whisper", api_key: str = "") -> dict:
|
|
265
|
+
return self._call(self._lib.YaverTranscribe(
|
|
266
|
+
audio_path.encode(), provider.encode(), api_key.encode()
|
|
267
|
+
))
|
|
268
|
+
|
|
269
|
+
def speak(self, text: str) -> dict:
|
|
270
|
+
return self._call(self._lib.YaverSpeak(text.encode()))
|
|
271
|
+
|
|
272
|
+
except ImportError:
|
|
273
|
+
pass # ctypes not available — native client disabled
|