Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
4afbf3e
feat(voice): core voice pipeline + UI
Co-vengers Apr 14, 2026
495d25e
ci: limit unit workflow to tests/unit
Co-vengers Apr 18, 2026
b095be8
chore: remove duplicate voice model ignore patterns
Co-vengers Apr 18, 2026
784299f
docs: generalize voice extension provider wording
Co-vengers Apr 18, 2026
f0cd312
did: harden windows acl username fallback and rollback
Co-vengers Apr 18, 2026
506f3a3
voice: fix timeout fallback text and history trimming
Co-vengers Apr 18, 2026
a3eed5d
docs(voice): expand callback parameter docs
Co-vengers Apr 18, 2026
3bca990
voice(redis): pipeline active-session lookups
Co-vengers Apr 18, 2026
ad74f76
voice(tts): narrow fallback exceptions and log type
Co-vengers Apr 18, 2026
b4ce397
voice(session): remove redundant __aexit__ on __aenter__ failure
Co-vengers Apr 18, 2026
d19779d
grpc: guard optional client dependencies
Co-vengers Apr 18, 2026
c49a85c
grpc: guard optional server dependencies
Co-vengers Apr 18, 2026
4d816d7
grpc: guard optional service dependencies
Co-vengers Apr 18, 2026
fc5b300
penguin: trim and validate deployment url hostname
Co-vengers Apr 18, 2026
e822288
server: type voice session manager and tidy imports
Co-vengers Apr 18, 2026
17e6d25
voice(endpoints): validate context id and websocket token timeout
Co-vengers Apr 18, 2026
2e7e9c3
settings(voice): add websocket token read timeout
Co-vengers Apr 18, 2026
35d511b
notifications: enforce resolved-ip delivery with safer errors
Co-vengers Apr 18, 2026
d2c0079
worker: skip malformed file parts before mime checks
Co-vengers Apr 18, 2026
8276352
frontend(env): add public agent base url and normalize empty vars
Co-vengers Apr 18, 2026
6757f0d
frontend(chat): replace alert fallback with error store
Co-vengers Apr 18, 2026
c700b19
frontend(chat): clarify intentional stream consumption comment
Co-vengers Apr 18, 2026
97fca5f
frontend(voice): add aria live log attributes
Co-vengers Apr 18, 2026
a138890
frontend(voice): avoid float32 copy during playback
Co-vengers Apr 18, 2026
b9cd31c
frontend(migrations): use satisfies for semaphore insert
Co-vengers Apr 18, 2026
bf9d48d
frontend(migrations): avoid pipeline updateMany for reports
Co-vengers Apr 18, 2026
66dded8
frontend(config): expose default PUBLIC_AGENT_BASE_URL
Co-vengers Apr 18, 2026
2a6ac3c
frontend(db): reject pipeline updates and dedupe stream emits
Co-vengers Apr 18, 2026
faec536
frontend(files): attach upload listeners before write/end
Co-vengers Apr 18, 2026
6c5602a
frontend(api): expose typed base url accessor
Co-vengers Apr 18, 2026
dfd1f5b
frontend(voice): guard stop/start races and use base url helper
Co-vengers Apr 18, 2026
5cf3abc
frontend(chat): type message parts and combine text parts
Co-vengers Apr 18, 2026
f3a7515
frontend(voice): reset call state and invalidate stale starts
Co-vengers Apr 18, 2026
3115144
frontend(agent): read base url from public env
Co-vengers Apr 18, 2026
78ddac0
frontend(payment): read base url from public env
Co-vengers Apr 18, 2026
ff52b58
test: exclude integration marker from default run
Co-vengers Apr 18, 2026
e2f473f
test(grpc): narrow polling exceptions and improve timeout diagnostics
Co-vengers Apr 18, 2026
bbb2e12
test(voice): assert update_state no-op for missing session
Co-vengers Apr 18, 2026
77d2ec4
test(voice): extract shared pipecat fixture and allowlist token
Co-vengers Apr 18, 2026
f27fd49
test(penguin): keep non-callable handler case in utility class
Co-vengers Apr 18, 2026
f0e4efd
test(scheduler): assert send path blocks until release
Co-vengers Apr 18, 2026
94e07f1
test(minimax): mark integration suite
Co-vengers Apr 18, 2026
e1b6448
frontend(migrations): fix semaphore lock insert typing
Co-vengers Apr 18, 2026
3727ece
build: fix uv lock python-docx source ambiguity
Co-vengers Apr 18, 2026
35a6322
chore: apply pre-commit fixes
Co-vengers Apr 18, 2026
fb43b21
voice: fix websocket bridge typing
Co-vengers Apr 18, 2026
48cf5c1
fix voice endpoint safety and pre-commit follow-ups
Co-vengers Apr 18, 2026
767eca4
refactor: streamline voice agent settings and improve session management
Co-vengers Apr 18, 2026
22a769f
deps(voice): include piper extra and bump requests
Co-vengers Apr 18, 2026
435c7cf
test(voice): cover service factory branches
Co-vengers Apr 23, 2026
84063c6
refactor(voice): use piper nested settings
Co-vengers Apr 23, 2026
07b2904
security(voice): fix websocket handshake with fixed label and constan…
Co-vengers Apr 23, 2026
7b3e46a
fix(voice): avoid swallowing websocket close errors on stop frame
Co-vengers Apr 23, 2026
34a145c
fix(voice): end session on websocket handshake failures
Co-vengers Apr 23, 2026
4874c0e
fix(document-analyzer): skip empty extracted docs and log failures
Co-vengers Apr 23, 2026
2ddd23f
test(document-analyzer): add comprehensive analyzer test suite and er…
Co-vengers Apr 23, 2026
f6f844a
fix(document-analyzer): return run result content
Co-vengers Apr 23, 2026
7194ee6
fix(pdf-research-agent): configure allowed base dir for pdf paths
Co-vengers Apr 23, 2026
cd9c4f5
fix(pdf-research-agent): chain document read errors
Co-vengers Apr 23, 2026
8f1fd60
fix(pdf-research-agent): remove stale string error checks
Co-vengers Apr 23, 2026
448a3de
fix(pdf-research-agent): unwrap run result for response
Co-vengers Apr 23, 2026
d4e64c5
fix(voice): use nested Settings for azure/elevenlabs
Co-vengers Apr 23, 2026
52cc254
fix(voice): don"t retain denied redis rate-limit entries
Co-vengers Apr 23, 2026
14abb5b
fix(voice): ensure session cleanup on pipeline build errors
Co-vengers Apr 23, 2026
3e5c3fc
test(voice): use raw regex strings in service_factory tests
Co-vengers Apr 23, 2026
303a1fd
feat(voice): core voice pipeline + UI
Co-vengers Apr 14, 2026
0e06ea7
build: fix uv lock python-docx source ambiguity
Co-vengers Apr 18, 2026
2eaf65f
deps(voice): include piper extra and bump requests
Co-vengers Apr 18, 2026
4aa030a
examples: add voice agent example
Co-vengers Apr 14, 2026
7b78879
chore(examples): sync pdf/document agents with code-fixes
Co-vengers Apr 23, 2026
e640a9a
feat(voice): core voice pipeline + UI
Co-vengers Apr 14, 2026
053e476
ci: limit unit workflow to tests/unit
Co-vengers Apr 18, 2026
e1f0339
chore: remove duplicate voice model ignore patterns
Co-vengers Apr 18, 2026
41798c7
docs: generalize voice extension provider wording
Co-vengers Apr 18, 2026
2423007
did: harden windows acl username fallback and rollback
Co-vengers Apr 18, 2026
cee61de
voice: fix timeout fallback text and history trimming
Co-vengers Apr 18, 2026
c94dff8
docs(voice): expand callback parameter docs
Co-vengers Apr 18, 2026
14c86ac
voice(redis): pipeline active-session lookups
Co-vengers Apr 18, 2026
c2c1dd9
voice(tts): narrow fallback exceptions and log type
Co-vengers Apr 18, 2026
4c20eee
voice(session): remove redundant __aexit__ on __aenter__ failure
Co-vengers Apr 18, 2026
8023f4d
grpc: guard optional client dependencies
Co-vengers Apr 18, 2026
04e8415
grpc: guard optional server dependencies
Co-vengers Apr 18, 2026
70c6293
grpc: guard optional service dependencies
Co-vengers Apr 18, 2026
3c96660
penguin: trim and validate deployment url hostname
Co-vengers Apr 18, 2026
19fc579
server: type voice session manager and tidy imports
Co-vengers Apr 18, 2026
b75a366
voice(endpoints): validate context id and websocket token timeout
Co-vengers Apr 18, 2026
9120881
settings(voice): add websocket token read timeout
Co-vengers Apr 18, 2026
3b75e0b
notifications: enforce resolved-ip delivery with safer errors
Co-vengers Apr 18, 2026
bfb02fc
worker: skip malformed file parts before mime checks
Co-vengers Apr 18, 2026
b9e6a9f
frontend(env): add public agent base url and normalize empty vars
Co-vengers Apr 18, 2026
4802ebc
frontend(chat): replace alert fallback with error store
Co-vengers Apr 18, 2026
12cb6b8
frontend(chat): clarify intentional stream consumption comment
Co-vengers Apr 18, 2026
3a824ea
frontend(voice): add aria live log attributes
Co-vengers Apr 18, 2026
0ef810c
frontend(voice): avoid float32 copy during playback
Co-vengers Apr 18, 2026
38c2712
frontend(migrations): use satisfies for semaphore insert
Co-vengers Apr 18, 2026
909bcbc
frontend(migrations): avoid pipeline updateMany for reports
Co-vengers Apr 18, 2026
082937e
frontend(config): expose default PUBLIC_AGENT_BASE_URL
Co-vengers Apr 18, 2026
0bc1a1a
frontend(db): reject pipeline updates and dedupe stream emits
Co-vengers Apr 18, 2026
37dc168
frontend(files): attach upload listeners before write/end
Co-vengers Apr 18, 2026
02c5bc0
frontend(api): expose typed base url accessor
Co-vengers Apr 18, 2026
0bc663d
frontend(voice): guard stop/start races and use base url helper
Co-vengers Apr 18, 2026
ed408ce
frontend(chat): type message parts and combine text parts
Co-vengers Apr 18, 2026
3211f8e
frontend(voice): reset call state and invalidate stale starts
Co-vengers Apr 18, 2026
e48fbe2
frontend(agent): read base url from public env
Co-vengers Apr 18, 2026
8278a8f
frontend(payment): read base url from public env
Co-vengers Apr 18, 2026
0409f0b
test: exclude integration marker from default run
Co-vengers Apr 18, 2026
4786bf7
test(grpc): narrow polling exceptions and improve timeout diagnostics
Co-vengers Apr 18, 2026
f217c89
test(voice): assert update_state no-op for missing session
Co-vengers Apr 18, 2026
69258d7
test(voice): extract shared pipecat fixture and allowlist token
Co-vengers Apr 18, 2026
6095ede
test(penguin): keep non-callable handler case in utility class
Co-vengers Apr 18, 2026
b930867
test(scheduler): assert send path blocks until release
Co-vengers Apr 18, 2026
ef21973
test(minimax): mark integration suite
Co-vengers Apr 18, 2026
f55d70d
frontend(migrations): fix semaphore lock insert typing
Co-vengers Apr 18, 2026
885a526
build: fix uv lock python-docx source ambiguity
Co-vengers Apr 18, 2026
691b8f5
chore: apply pre-commit fixes
Co-vengers Apr 18, 2026
2b95b7c
voice: fix websocket bridge typing
Co-vengers Apr 18, 2026
9e99b86
fix voice endpoint safety and pre-commit follow-ups
Co-vengers Apr 18, 2026
904b600
refactor: streamline voice agent settings and improve session management
Co-vengers Apr 18, 2026
b4bb3d6
deps(voice): include piper extra and bump requests
Co-vengers Apr 18, 2026
639c6d5
test(voice): cover service factory branches
Co-vengers Apr 23, 2026
b780ba6
refactor(voice): use piper nested settings
Co-vengers Apr 23, 2026
9bc9e3a
security(voice): fix websocket handshake with fixed label and constan…
Co-vengers Apr 23, 2026
f69d13a
fix(voice): avoid swallowing websocket close errors on stop frame
Co-vengers Apr 23, 2026
25d4fd9
fix(voice): end session on websocket handshake failures
Co-vengers Apr 23, 2026
4fcf614
fix(document-analyzer): skip empty extracted docs and log failures
Co-vengers Apr 23, 2026
076b608
test(document-analyzer): add comprehensive analyzer test suite and er…
Co-vengers Apr 23, 2026
514c82e
fix(document-analyzer): return run result content
Co-vengers Apr 23, 2026
9e54265
fix(pdf-research-agent): configure allowed base dir for pdf paths
Co-vengers Apr 23, 2026
ce5e7e0
fix(pdf-research-agent): chain document read errors
Co-vengers Apr 23, 2026
724b9af
fix(pdf-research-agent): remove stale string error checks
Co-vengers Apr 23, 2026
de75f4b
fix(pdf-research-agent): unwrap run result for response
Co-vengers Apr 23, 2026
e31e9ee
fix(voice): use nested Settings for azure/elevenlabs
Co-vengers Apr 23, 2026
a787ac8
fix(voice): don"t retain denied redis rate-limit entries
Co-vengers Apr 23, 2026
7ac1b33
fix(voice): ensure session cleanup on pipeline build errors
Co-vengers Apr 23, 2026
706c688
test(voice): use raw regex strings in service_factory tests
Co-vengers Apr 23, 2026
d9050c7
Merge remote-tracking branch 'upstream/main' into feat(voice-agent)/e…
Co-vengers Apr 23, 2026
ca33431
chore: constrain pydantic-extra-types to non-yanked version
Co-vengers Apr 24, 2026
7fbd3d6
chore: constrain pydantic-extra-types to non-yanked version
Co-vengers Apr 24, 2026
25c99cf
chore: constrain pydantic-extra-types to non-yanked version
Co-vengers Apr 24, 2026
9d16f40
Update voice endpoint and document analyzer changes
Co-vengers Apr 24, 2026
eab2170
Update voice endpoint and document analyzer changes
Co-vengers Apr 24, 2026
43e7d8a
Update voice endpoint and document analyzer changes
Co-vengers Apr 24, 2026
dbf56be
Update voice endpoint and document analyzer changes
Co-vengers Apr 24, 2026
dedaff4
Merge branch 'feat(voice-agent)/code-fixes' into feat(voice-agent)/ex…
Co-vengers Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:

- name: Run unit tests with coverage
run: |
uv run pytest tests/unit/ \
uv run pytest tests/ \
--cov=bindu \
--cov-report=term-missing \
--cov-report=xml:coverage.xml \
Expand Down
38 changes: 37 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,42 @@ sdks/typescript/node_modules/
sdks/kotlin/build/
sdks/kotlin/.gradle/
sdks/kotlin/bin/
examples/gateway_test_fleet/pids/

# Frontend build/cache artifacts
frontend/.svelte-kit/
frontend/build/
frontend/.vite/
frontend/.vercel/

# Voice model artifacts downloaded at runtime (Piper)
en_US-*.onnx
en_US-*.onnx.json
examples/voice-agent/en_US-*.onnx
examples/voice-agent/en_US-*.onnx.json

# Runtime logs and provider test outputs
logs/

# Local tooling/worktree manager state
.kilo/
.idea/examples/gateway_test_fleet/pids/
examples/gateway_test_fleet/logs/
examples/gateway_test_fleet/.fleet.env

# Frontend build/cache artifacts
frontend/.svelte-kit/
frontend/build/
frontend/.vite/
frontend/.vercel/

# Voice model artifacts downloaded at runtime (Piper)
en_US-*.onnx
en_US-*.onnx.json

# Runtime logs and provider test outputs
logs/

# Local tooling/worktree manager state
.kilo/
.idea/
.local/
5 changes: 3 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exclude: ^\.agents/
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
Expand All @@ -21,15 +22,15 @@ repos:
hooks:
- id: ty
name: ty type checker
entry: uv run ty check bindu/ tests/ --exclude bindu/grpc/generated/
entry: uv run ty check bindu/ --exclude bindu/grpc/generated/
language: system
types: [python]
pass_filenames: false
exclude: ^(examples/|bindu/grpc/generated/)

- id: pytest
name: pytest with coverage
entry: bash -c 'uv run pytest -n auto --cov=bindu --cov-report= && coverage report --skip-covered --fail-under=60'
entry: bash -c 'uv run pytest -n auto --cov=bindu --cov-report= && uv run coverage report --skip-covered --fail-under=60'
language: system
pass_filenames: false
always_run: true
Expand Down
9 changes: 8 additions & 1 deletion bindu/common/protocol/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,15 @@ class FilePart(TextPart):
file: Required[FileWithBytes | FileWithUri]
"""The file of the part."""

metadata: NotRequired[dict[str, Any]]
"""Metadata about the file part."""

embeddings: NotRequired[list[float]]
"""The embeddings of File. <NotPartOfA2A>"""


class DataPart(TextPart):
@pydantic.with_config(ConfigDict(alias_generator=to_camel))
class DataPart(TypedDict):
"""Represents a structured data segment (e.g., JSON) within a message or artifact."""

kind: Required[Literal["data"]]
Expand All @@ -198,6 +202,9 @@ class DataPart(TextPart):
data: Required[dict[str, Any]]
"""The data of the part."""

metadata: NotRequired[dict[str, Any]]
"""Metadata about the data part."""

embeddings: NotRequired[list[float]]
"""The embeddings of Data. <NotPartOfA2A>"""

Expand Down
7 changes: 7 additions & 0 deletions bindu/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
negotiate prices, request payments, and execute transactions based on cryptographic
mandates, creating a true agent economy.

**Voice (Real-time Voice Conversations)**
Adds Vapi-like real-time voice capability to Bindu agents via WebSocket.
The pipeline uses Pipecat with configurable provider-based STT and TTS to provide
bidirectional voice conversations. Providers can be selected via the ``voice``
config passed to ``bindufy()`` or through ``VOICE__ENABLED``-based environment
settings.


Each extension follows the A2A protocol specification for extensions:
https://a2a-protocol.org/v0.3.0/topics/extensions/
Expand Down
65 changes: 56 additions & 9 deletions bindu/extensions/did/did_agent_extension.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
# |---------------------------------------------------------|
# | |
# | Give Feedback / Get Help |
# | https://github.com/getbindu/Bindu/issues/new/choose |
# | |
# |---------------------------------------------------------|
#
# Thank you users! We ❤️ you! - 🌻

"""DID (Decentralized Identifier) Extension for Bindu Agents.

Why is DID an Extension?
Expand All @@ -29,6 +20,8 @@

import os
import platform
import subprocess
import getpass

from datetime import datetime, timezone
from functools import cached_property
Expand Down Expand Up @@ -222,25 +215,79 @@ def generate_and_save_key_pair(self) -> dict[str, str]:
# Windows does not enforce POSIX permissions — write directly
self.private_key_path.write_bytes(private_pem)
self.public_key_path.write_bytes(public_pem)
try:
self._harden_windows_key_file_acl(self.private_key_path)
self._harden_windows_key_file_acl(self.public_key_path)
except Exception:
for key_path in (self.private_key_path, self.public_key_path):
try:
key_path.unlink(missing_ok=True)
except OSError:
logger.warning(
f"Failed to remove key file during ACL hardening rollback: {key_path}"
)
raise
else:
# POSIX: use os.open to set permissions atomically on creation
fd = os.open(
str(self.private_key_path), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600
)
os.fchmod(fd, 0o600)
with os.fdopen(fd, "wb") as f:
f.write(private_pem)
os.chmod(self.private_key_path, 0o600)

fd = os.open(
str(self.public_key_path), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644
)
os.fchmod(fd, 0o644)
with os.fdopen(fd, "wb") as f:
f.write(public_pem)
os.chmod(self.public_key_path, 0o644)

return {
"private_key_path": str(self.private_key_path),
"public_key_path": str(self.public_key_path),
}

@staticmethod
def _harden_windows_key_file_acl(path: Path) -> None:
"""Restrict Windows ACLs to current user for key file confidentiality."""
username = (os.getenv("USERNAME") or "").strip()
if not username:
try:
username = os.getlogin().strip()
except Exception:
username = ""
if not username:
try:
username = (getpass.getuser() or "").strip()
except Exception:
username = ""
if not username:
raise RuntimeError(
"Unable to determine Windows username for key ACL hardening"
)

# Remove inherited ACLs and grant full control to current user only.
cmd = [
"icacls",
str(path),
"/inheritance:r",
"/grant:r",
f"{username}:F",
"/remove:g",
"Users",
"Authenticated Users",
"Everyone",
]
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
if result.returncode != 0:
raise RuntimeError(
"Failed to harden ACL for key file "
f"{path}: {result.stderr.strip() or result.stdout.strip()}"
)

def _load_key_from_file(self, key_path: Path, key_type: str) -> bytes:
"""Load key PEM data from file.

Expand Down
19 changes: 19 additions & 0 deletions bindu/extensions/voice/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Voice Agent extension for real-time voice conversations.

Provides Vapi-like voice capabilities (STT → Agent → TTS) integrated
into Bindu's A2A protocol and extension system.

Usage::

from bindu.extensions.voice import VoiceAgentExtension

voice = VoiceAgentExtension(
stt_provider="deepgram",
tts_provider="elevenlabs",
tts_voice_id="21m00Tcm4TlvDq8ikWAM",
)
"""

from .voice_agent_extension import VoiceAgentExtension

__all__ = ["VoiceAgentExtension"]
Loading
Loading