Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
42 changes: 42 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# OpenRTC environment variables
# Copy this file to .env and fill in the values for your setup.
# python-dotenv is used in the examples: `from dotenv import load_dotenv; load_dotenv()`

# ---------------------------------------------------------------------------
# LiveKit connection (required for dev / start / connect / console)
# ---------------------------------------------------------------------------
LIVEKIT_URL=ws://localhost:7880
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=secret
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reorder LiveKit keys to satisfy dotenv-linter.

dotenv-linter flags these lines for key ordering. Reordering avoids CI lint noise/failures.

Suggested fix
-LIVEKIT_URL=ws://localhost:7880
 LIVEKIT_API_KEY=devkey
 LIVEKIT_API_SECRET=secret
+LIVEKIT_URL=ws://localhost:7880
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 9-9: [UnorderedKey] The LIVEKIT_API_KEY key should go before the LIVEKIT_URL key

(UnorderedKey)


[warning] 10-10: [UnorderedKey] The LIVEKIT_API_SECRET key should go before the LIVEKIT_URL key

(UnorderedKey)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example around lines 8 - 10, Reorder the LIVEKIT environment variables
so they are alphabetically sorted to satisfy dotenv-linter: place
LIVEKIT_API_KEY and LIVEKIT_API_SECRET before LIVEKIT_URL (i.e.,
LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_URL) in the .env example; update
the block containing LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET
accordingly to remove the linter ordering warnings.


# ---------------------------------------------------------------------------
# Provider API keys — set only the keys for providers your agents use
# ---------------------------------------------------------------------------

# OpenAI (STT: gpt-4o-mini-transcribe, LLM: gpt-4.1-mini, TTS: gpt-4o-mini-tts)
OPENAI_API_KEY=

# Deepgram (STT: deepgram/nova-3:multi)
DEEPGRAM_API_KEY=

# Cartesia (TTS: cartesia/sonic-3)
CARTESIA_API_KEY=

# ElevenLabs (TTS: elevenlabs/*)
ELEVEN_API_KEY=

# Azure OpenAI (if using azure provider strings)
AZURE_OPENAI_API_KEY=
AZURE_OPENAI_ENDPOINT=

# ---------------------------------------------------------------------------
# Optional: remote end-of-turn model (LiveKit Cloud)
# Set this to enable multilingual remote turn detection via LIVEKIT_REMOTE_EOT_URL
# ---------------------------------------------------------------------------
LIVEKIT_REMOTE_EOT_URL=

# ---------------------------------------------------------------------------
# Logging level passed through to the LiveKit worker
# One of: DEBUG, INFO, WARNING, ERROR
# ---------------------------------------------------------------------------
LIVEKIT_LOG_LEVEL=INFO
83 changes: 83 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Bug report
description: Report a reproducible bug in OpenRTC
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a bug. Please fill in as much detail as possible so we can reproduce and fix it quickly.

- type: input
id: version
attributes:
label: OpenRTC version
description: Output of `python -c "import openrtc; print(openrtc.__version__)"`
placeholder: "e.g. 0.0.15"
validations:
required: true

- type: input
id: python-version
attributes:
label: Python version
description: Output of `python --version`
placeholder: "e.g. 3.12.2"
validations:
required: true

- type: input
id: livekit-agents-version
attributes:
label: livekit-agents version
description: Output of `python -c "import livekit.agents; print(livekit.agents.__version__)"`
placeholder: "e.g. 1.4.3"
validations:
required: false

- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true

- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Minimal steps to reproduce the issue.
placeholder: |
1. Create a pool with `AgentPool(...)`
2. Call `pool.add(...)`
3. Start with `pool.run()`
4. See error
validations:
required: true

- type: textarea
id: expected
attributes:
label: Expected behaviour
description: What did you expect to happen?
validations:
required: true

- type: textarea
id: actual
attributes:
label: Actual behaviour
description: What actually happened? Include the full traceback if applicable.
render: python
validations:
required: true

- type: textarea
id: extra
attributes:
label: Additional context
description: |
Any other context, environment details, or screenshots that may help.
For example: OS, deployment environment (Docker, bare metal, cloud), provider plugins in use.
validations:
required: false
58 changes: 58 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Feature request
description: Propose an improvement or new capability for OpenRTC
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for suggesting an improvement! Please describe the problem you're solving and the solution you have in mind.

- type: textarea
id: problem
attributes:
label: Problem statement
description: |
What problem are you trying to solve? Describe the use case that is not well-served today.
placeholder: "I'm trying to do X, but OpenRTC currently doesn't support it because..."
validations:
required: true

- type: textarea
id: proposed-solution
attributes:
label: Proposed solution
description: |
Describe the feature or change you'd like. Include example code if helpful.
placeholder: |
Add a `pool.add_async()` method that accepts an async factory so providers
can be lazily initialised on first call.
validations:
required: true

- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: |
Are there workarounds you've already tried? Why aren't they sufficient?
validations:
required: false

- type: dropdown
id: breaking
attributes:
label: Does this require a breaking API change?
options:
- "No — purely additive"
- "Yes — existing callers would need to update"
- "Not sure"
validations:
required: true

- type: textarea
id: extra
attributes:
label: Additional context
description: Links, prior art, related issues, or any other context.
validations:
required: false
19 changes: 9 additions & 10 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,21 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
python-version: "3.11"

- name: Install lint dependencies
run: |
python -m pip install --upgrade pip
python -m pip install ruff "mypy>=1.19.1"
python -m pip install -e ".[cli,tui]"
- name: Install dependencies
run: uv sync --group dev

- name: Check formatting
run: ruff format --check .
run: uv run ruff format --check .

- name: Run lint checks
run: ruff check .
run: uv run ruff check .

- name: Run mypy
run: mypy src/
run: uv run mypy src/
61 changes: 52 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,66 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
# Use a PAT so the changelog commit can trigger deploy-docs.yml.
# Falls back to GITHUB_TOKEN if the secret is absent (docs won't
# auto-deploy in that case, but the publish still succeeds).
token: ${{ secrets.CHANGELOG_PUSH_TOKEN || secrets.GITHUB_TOKEN }}

Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actions/checkout on a release event checks out the tag commit (detached HEAD). The later git push origin HEAD:main can fail with a non-fast-forward if main has moved since the tag was created. Consider checking out main explicitly (e.g. ref: main) or git fetch origin main && git switch main && git pull --ff-only before modifying/committing docs/changelog.md so the push is reliably fast-forward.

Copilot uses AI. Check for mistakes.
- name: Set up Python
uses: actions/setup-python@v5
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
python-version: "3.12"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build

- name: Build package
run: |
python -m build
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
packages-dir: dist/

- name: Update docs/changelog.md
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
RELEASE_BODY: ${{ github.event.release.body }}
RELEASE_DATE: ${{ github.event.release.published_at }}
run: |
python3 - <<'PYEOF'
import os, re
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re is imported in the embedded Python script but never used. Removing it keeps the workflow script minimal and avoids unused-import lint noise if this script is later moved into the repository proper.

Suggested change
import os, re
import os

Copilot uses AI. Check for mistakes.

tag = os.environ["RELEASE_TAG"]
body = os.environ["RELEASE_BODY"].strip()
# published_at is ISO-8601; keep only the date part
date = os.environ["RELEASE_DATE"][:10]

new_section = f"## [{tag}] - {date}\n\n{body}\n\n---\n\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Strip the v prefix from the tag to match existing changelog format.

Existing changelog entries use version numbers without the v prefix (e.g., ## [0.0.15] - 2026-03-22), but github.event.release.tag_name includes the prefix (e.g., v0.0.16). This will create inconsistent headings.

Proposed fix
         tag  = os.environ["RELEASE_TAG"]
+        # Strip leading 'v' to match existing changelog format (e.g., [0.0.15])
+        if tag.startswith("v"):
+            tag = tag[1:]
         body = os.environ["RELEASE_BODY"].strip()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tag = os.environ["RELEASE_TAG"]
body = os.environ["RELEASE_BODY"].strip()
# published_at is ISO-8601; keep only the date part
date = os.environ["RELEASE_DATE"][:10]
new_section = f"## [{tag}] - {date}\n\n{body}\n\n---\n\n"
tag = os.environ["RELEASE_TAG"]
# Strip leading 'v' to match existing changelog format (e.g., [0.0.15])
if tag.startswith("v"):
tag = tag[1:]
body = os.environ["RELEASE_BODY"].strip()
# published_at is ISO-8601; keep only the date part
date = os.environ["RELEASE_DATE"][:10]
new_section = f"## [{tag}] - {date}\n\n{body}\n\n---\n\n"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish.yml around lines 51 - 56, The tag variable
currently comes directly from RELEASE_TAG and may include a leading "v", causing
inconsistent changelog headings; update the code that sets tag (the variable
assigned from os.environ["RELEASE_TAG"]) to remove a leading "v" (only if
present) before constructing new_section so new_section uses a bare semantic
version (e.g., "0.0.16") instead of "v0.0.16".


Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job only runs for tags starting with v, so RELEASE_TAG will typically be like v0.0.16, but docs/changelog.md uses headings like ## [0.0.15] ... (no v). Consider normalizing the tag (e.g. stripping a leading v) before writing the new section to keep the changelog format consistent.

Copilot uses AI. Check for mistakes.
path = "docs/changelog.md"
with open(path) as f:
content = f.read()

marker = "<!-- releases -->"
if marker not in content:
raise SystemExit(f"Marker '{marker}' not found in {path}")

# Insert the new release section right after the marker line
content = content.replace(
marker + "\n",
marker + "\n\n" + new_section,
1,
)
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog update script is not idempotent: re-running the workflow for the same release will prepend the same section again. Consider checking whether a heading for this tag already exists in docs/changelog.md and skipping the update (and subsequent commit) if it does.

Copilot uses AI. Check for mistakes.

with open(path, "w") as f:
f.write(content)

print(f"Prepended {tag} ({date}) to {path}")
PYEOF

- name: Commit and push changelog
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/changelog.md
git commit -m "docs(changelog): add ${{ github.event.release.tag_name }} release notes [skip ci]"
git push origin HEAD:main
12 changes: 6 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[cli,tui]" pytest pytest-asyncio pytest-cov
run: uv sync --group dev

- name: Run tests with coverage
run: pytest --cov=openrtc --cov-report=xml --cov-fail-under=80
run: uv run pytest --cov=openrtc --cov-report=xml --cov-fail-under=80

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
Expand Down
40 changes: 40 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# OpenRTC developer convenience targets.
# All commands delegate to `uv run` so they pick up the locked dev environment.
# Run `uv sync --group dev` once to set up the environment, then use these targets.

.PHONY: help install test lint format typecheck dev clean
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.PHONY doesn’t include the test-fast and format-check targets that are defined below. If files/directories with those names ever exist, make will treat them as up-to-date and skip the recipes. Add them to .PHONY to ensure the targets always run.

Suggested change
.PHONY: help install test lint format typecheck dev clean
.PHONY: help install test test-fast lint format format-check typecheck dev clean

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add test-fast and format-check to .PHONY.

These targets are defined but missing from the .PHONY declaration, which could cause unexpected behavior if files with those names exist.

Proposed fix
-.PHONY: help install test lint format typecheck dev clean
+.PHONY: help install test test-fast lint format format-check typecheck dev clean
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.PHONY: help install test lint format typecheck dev clean
.PHONY: help install test test-fast lint format format-check typecheck dev clean
🧰 Tools
🪛 checkmake (0.2.2)

[warning] 5-5: Missing required phony target "all"

(minphony)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` at line 5, Update the .PHONY declaration to include the missing
targets so make treats them as phony: add test-fast and format-check to the
existing .PHONY line (which currently lists help install test lint format
typecheck dev clean) so the Makefile's .PHONY includes test-fast and
format-check.


help: ## Show this help message
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'

install: ## Install package and dev dependencies via uv
uv sync --group dev

test: ## Run the test suite with coverage
uv run pytest --cov=openrtc --cov-report=term-missing --cov-fail-under=80

test-fast: ## Run tests without coverage (faster feedback loop)
uv run pytest -q

lint: ## Run Ruff lint checks
uv run ruff check .

format: ## Auto-format code with Ruff
uv run ruff format .

format-check: ## Check formatting without making changes (used in CI)
uv run ruff format --check .

typecheck: ## Run mypy type checks on the source tree
uv run mypy src/

dev: ## Validate agent discovery without a LiveKit server (set --agents-dir as needed)
uv run openrtc list ./examples/agents \
--default-stt "deepgram/nova-3:multi" \
--default-llm "openai/gpt-4.1-mini" \
--default-tts "cartesia/sonic-3"

clean: ## Remove build artefacts and __pycache__ directories
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
rm -rf dist build .coverage coverage.xml htmlcov .mypy_cache .ruff_cache
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default defineConfig({
{ text: 'AgentPool API', link: '/api/pool' },
{ text: 'CLI', link: '/cli' },
{ text: 'Examples', link: '/examples' },
{ text: 'Changelog', link: '/changelog' },
{ text: 'GitHub Pages Deployment', link: '/deployment/github-pages' },
],
},
Expand Down
Loading
Loading