Skip to content

Commit

Permalink
Merge pull request #67 from JarbasHiveMind/release-0.4.2a1
Browse files Browse the repository at this point in the history
Release 0.4.2a1
  • Loading branch information
JarbasAl authored Jan 8, 2025
2 parents 89f4b2c + a8b418e commit e40d840
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 642 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish_stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: "3.11"
- name: Install Build Tools
run: |
python -m pip install build wheel
Expand Down
58 changes: 0 additions & 58 deletions .github/workflows/unit_tests.yml

This file was deleted.

26 changes: 17 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
# Changelog

## [0.4.0a1](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.4.0a1) (2025-01-08)
## [0.4.2a1](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.4.2a1) (2025-01-08)

[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.3.0a2...0.4.0a1)
[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.4.1a2...0.4.2a1)

**Closed issues:**

- Execution example in the readme raises an error [\#22](https://github.com/JarbasHiveMind/hivemind-websocket-client/issues/22)

**Merged pull requests:**

- feat:http client [\#60](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/60) ([JarbasAl](https://github.com/JarbasAl))
- fix: no auto connect [\#66](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/66) ([JarbasAl](https://github.com/JarbasAl))

## [0.3.0a2](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.3.0a2) (2025-01-03)
## [0.4.1a2](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.4.1a2) (2025-01-08)

[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.3.0a1...0.3.0a2)
[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.4.1a1...0.4.1a2)

**Merged pull requests:**

- chore:benchmark [\#57](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/57) ([JarbasAl](https://github.com/JarbasAl))
- bring http client closes to websocket client [\#64](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/64) ([JarbasAl](https://github.com/JarbasAl))

## [0.4.1a1](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.4.1a1) (2025-01-08)

[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.4.0...0.4.1a1)

## [0.3.0a1](https://github.com/JarbasHiveMind/hivemind-websocket-client/tree/0.3.0a1) (2025-01-03)
**Closed issues:**

[Full Changelog](https://github.com/JarbasHiveMind/hivemind-websocket-client/compare/0.2.1...0.3.0a1)
- Faster encodings [\#59](https://github.com/JarbasHiveMind/hivemind-websocket-client/issues/59)

**Merged pull requests:**

- feat:more encodings [\#55](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/55) ([JarbasAl](https://github.com/JarbasAl))
- refactor: move to z85base91 package [\#62](https://github.com/JarbasHiveMind/hivemind-websocket-client/pull/62) ([JarbasAl](https://github.com/JarbasAl))



Expand Down
94 changes: 73 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Hivemind Websocket Client
# Hivemind Bus Client

![logo](./logo.png)
Python client library for [hivemind-core](https://github.com/JarbasHiveMind/HiveMind-core)

## Install

Expand All @@ -10,36 +10,88 @@ pip install hivemind_bus_client

## Usage

via [hivemind-http-protocol](https://github.com/JarbasHiveMind/hivemind-http-protocol)

```python
from time import sleep
from ovos_bus_client import Message
from hivemind_bus_client import HiveMessageBusClient
from hivemind_bus_client.decorators import on_escalate, \
on_shared_bus, on_ping, on_broadcast, on_propagate, on_mycroft_message, \
on_registry_opcode, on_third_party, on_cascade, on_handshake, on_hello, \
on_rendezvous, on_hive_message, on_third_party, on_payload
from hivemind_bus_client.http_client import HiveMindHTTPClient

key = "super_secret_access_key"
crypto_key = "ivf1NQSkQNogWYyr"
# not passing key etc so it uses identity file
client = HiveMindHTTPClient(host="http://localhost", port=5679)
client.connect() # establish a secure end-to-end encrypted connection
```

bus = HiveMessageBusClient(key, crypto_key=crypto_key, ssl=False)
via [hivemind-websocket-protocol](https://github.com/JarbasHiveMind/hivemind-websocket-protocol)
```python
from hivemind_bus_client.client import HiveMessageBusClient

bus.run_in_thread()
# not passing key etc so it uses identity file
client = HiveMessageBusClient(host="ws://localhost", port=5678)
client.connect() # establish a secure end-to-end encrypted connection
```

### Example: Simple Chat

```python
import threading
from ovos_bus_client.message import Message
from hivemind_bus_client.message import HiveMessage, HiveMessageType
from hivemind_bus_client.http_client import HiveMindHTTPClient

# not passing key etc so it uses identity file
client = HiveMindHTTPClient(host="http://localhost", port=5679)

@on_mycroft_message(payload_type="speak", bus=bus)
def on_speak(msg):
print(msg.data["utterance"])
# to handle agent responses, use client.on_mycroft("event", handler)
answered = threading.Event()

def handle_speak(message: Message):
print(message.data['utterance'])

mycroft_msg = Message("recognizer_loop:utterance",
{"utterances": ["tell me a joke"]})
bus.emit_mycroft(mycroft_msg)
def utt_handled(message: Message):
answered.set()

client.on_mycroft("speak", handle_speak)
client.on_mycroft("ovos.utterance.handled", utt_handled)

sleep(50)

bus.close()
while True:
utt = input("> ")
answered.clear()
client.emit(HiveMessage(HiveMessageType.BUS,
Message("recognizer_loop:utterance", {"utterances": [utt]})))
answered.wait()
```

### Example: Remote TTS

if server is running [hivemind-audio-binary-protocol](https://github.com/JarbasHiveMind/hivemind-audio-binary-protocol)

```python
from ovos_bus_client.message import Message
from hivemind_bus_client.client import BinaryDataCallbacks
from hivemind_bus_client.message import HiveMessage, HiveMessageType
from hivemind_bus_client.http_client import HiveMindHTTPClient

# To handle binary data subclass BinaryDataCallbacks
class BinaryDataHandler(BinaryDataCallbacks):
def handle_receive_tts(self, bin_data: bytes,
utterance: str,
lang: str,
file_name: str):
# we can play it or save to file or whatever
print(f"got {len(bin_data)} bytes of TTS audio")
print(f"utterance: {utterance}", f"lang: {lang}", f"file_name: {file_name}")
# got 33836 bytes of TTS audio
# utterance: hello world lang: en-US file_name: 5eb63bbbe01eeed093cb22bb8f5acdc3.wav


# not passing key etc so it uses identity file
client = HiveMindHTTPClient(host="http://localhost", port=5679,
bin_callbacks=BinaryDataHandler())

# send HiveMessages as usual
client.emit(HiveMessage(HiveMessageType.BUS,
Message("speak:synth", {"utterance": "hello world"})))

```

## Cli Usage
Expand Down
13 changes: 10 additions & 3 deletions hivemind_bus_client/encodings/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
from hivemind_bus_client.encodings.z85b import Z85B
from hivemind_bus_client.encodings.z85p import Z85P
from hivemind_bus_client.encodings.b91 import B91
from z85base91 import Z85B, Z85P, B91
import warnings

# Deprecation warning
warnings.warn(
"Importing from hivemind_bus_client.encodings is deprecated and will be removed in a future release. "
"Please update your code to use the new package 'z85base91'",
DeprecationWarning,
stacklevel=2,
)
110 changes: 10 additions & 100 deletions hivemind_bus_client/encodings/b91.py
Original file line number Diff line number Diff line change
@@ -1,100 +1,10 @@
from typing import Union


class B91:
ALPHABET = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
'%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
'>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
]

DECODE_TABLE = {char: idx for idx, char in enumerate(ALPHABET)}

@classmethod
def decode(cls, encoded_data: Union[str, bytes], encoding: str = "utf-8") -> bytes:
"""
Decodes a Base91-encoded string into its original binary form.
Args:
encoded_data (Union[str, bytes]): Base91-encoded input data. If `bytes`, it is decoded as UTF-8.
encoding (str): The encoding to use if `encoded_data` is provided as a string. Default is 'utf-8'.
Returns:
bytes: The decoded binary data.
Raises:
ValueError: If the input contains invalid Base91 characters.
"""
if isinstance(encoded_data, bytes):
encoded_data = encoded_data.decode(encoding)

v = -1
b = 0
n = 0
out = bytearray()

for char in encoded_data:
if char not in cls.DECODE_TABLE:
raise ValueError(f"Invalid Base91 character: {char}")
c = cls.DECODE_TABLE[char]
if v < 0:
v = c
else:
v += c * 91
b |= v << n
n += 13 if (v & 8191) > 88 else 14
while n >= 8:
out.append(b & 255)
b >>= 8
n -= 8
v = -1

if v >= 0:
out.append((b | v << n) & 255)

return bytes(out)

@classmethod
def encode(cls, data: Union[bytes, str], encoding: str = "utf-8") -> bytes:
"""
Encodes binary data into a Base91-encoded string.
Args:
data (Union[bytes, str]): Input binary data to encode. If `str`, it is encoded as UTF-8.
encoding (str): The encoding to use if `data` is provided as a string. Default is 'utf-8'.
Returns:
str: The Base91-encoded string.
"""
if isinstance(data, str):
data = data.encode(encoding)

b = 0
n = 0
out = []

for byte in data:
b |= byte << n
n += 8
if n > 13:
v = b & 8191
if v > 88:
b >>= 13
n -= 13
else:
v = b & 16383
b >>= 14
n -= 14
out.append(cls.ALPHABET[v % 91])
out.append(cls.ALPHABET[v // 91])

if n:
out.append(cls.ALPHABET[b % 91])
if n > 7 or b > 90:
out.append(cls.ALPHABET[b // 91])

return ''.join(out).encode(encoding)
from z85base91 import B91
import warnings

# Deprecation warning
warnings.warn(
"Importing from hivemind_bus_client.encodings is deprecated and will be removed in a future release. "
"Please update your code to use the new package 'z85base91'",
DeprecationWarning,
stacklevel=2,
)
2 changes: 1 addition & 1 deletion hivemind_bus_client/encodings/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import click
import pybase64

from hivemind_bus_client.encodings import Z85B, B91, Z85P
from z85base91 import Z85B, B91, Z85P
from hivemind_bus_client.exceptions import InvalidEncoding

performance_weight = 0.5
Expand Down
Loading

0 comments on commit e40d840

Please sign in to comment.