Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
d5bf8a7
feat: establish complete native Python SDK foundation
Aug 19, 2026
e5db11d
feat: add Python connector authoring
Aug 20, 2026
ef0cdc7
feat: add Python source and operator authoring
Aug 20, 2026
46bc2ea
feat: add source-aware transcription proof
Aug 20, 2026
8ae3910
test physical capture relay workflow
Aug 20, 2026
52431a4
test Python runtime resource bounds
Aug 20, 2026
6772022
test installed Python distributions
Aug 20, 2026
f658805
feat: simplify Python audio integrations
Aug 20, 2026
396b152
fix: bound Python control-plane requests
Aug 20, 2026
5e637ae
fix: bound Python relay requests
Aug 20, 2026
c92e525
fix: package Python runtime identities
Aug 20, 2026
18936d8
feat: complete bounded Python provider authoring
Aug 20, 2026
fb3bb48
feat: expose generic Python endpoint authoring
Aug 21, 2026
5ff52b5
feat: emit bounded PCM from Python operators
Aug 21, 2026
4e5fe07
feat: route streams directly to connectors
Aug 21, 2026
e37134d
feat: qualify bounded Python audio ingress
Aug 21, 2026
c1aa232
feat: ship the installed source-aware demo
Aug 22, 2026
fe29a8f
fix: preserve Core 1.1 SDK compatibility
Aug 22, 2026
e47f06f
build: consume immutable Core 1.1.2
Aug 24, 2026
047a333
feat: simplify application audio examples
Aug 26, 2026
8c0abca
docs: name transcription example honestly
Aug 26, 2026
62352c4
merge origin main documentation cleanup
Aug 27, 2026
480efa9
Add bounded conversation composition
Aug 27, 2026
e18df07
Expose Relay output cancellation counters
Aug 27, 2026
88205ce
Add direct streaming voice proof candidate
Aug 27, 2026
bbc57c6
Merge remote-tracking branch 'origin/main'
Aug 27, 2026
f641cd4
Keep Python output cancellation compatible
Aug 27, 2026
3b54e86
Add provider-neutral voice composition
Aug 28, 2026
a53e103
Align Python with Core 1.1.3
Aug 28, 2026
74e9687
Drain voice media during provider startup
Aug 31, 2026
752da1c
Accept recording manifest schema 2
Aug 31, 2026
a6c9fb6
Retain Realtime output by bounded audio duration
Aug 31, 2026
3c78819
Expose selectable capture frame duration
Aug 31, 2026
224b47b
Retain Realtime transcript revisions at 10 ms
Aug 31, 2026
6f5939e
Require PocketStation Core 1.1.4
Aug 31, 2026
9d3f5b3
Retry transient Relay readiness requests
Aug 31, 2026
abbbc00
Prepare the Python 0.1.0 public release
Aug 31, 2026
e857342
Publish Python through trusted GitHub releases
Aug 31, 2026
2d9c400
Pin Python CI actions
Aug 31, 2026
7fa1d2d
Complete the Python developer documentation
Aug 31, 2026
e930e6a
Package the Python guides and examples
Aug 31, 2026
ab6e1db
Document application audio and Session outcomes
Aug 31, 2026
76e6426
Build CI wheels before installing them
Aug 31, 2026
4698c04
Lock published native dependencies
Aug 31, 2026
e961145
Support bundled Opus with CMake 4
Aug 31, 2026
38ace34
Make Python tests standalone
Aug 31, 2026
93f42e2
Make interruption qualification deterministic
Aug 31, 2026
3200a9b
Format deterministic interruption test
Aug 31, 2026
22d8986
Pace transcription test at represented media time
Aug 31, 2026
07d381d
Respect Windows path and apartment semantics
Aug 31, 2026
147ac92
Fail closed for Windows permission observation
Aug 31, 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
5 changes: 2 additions & 3 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# Replace @raph with your GitHub username/team before pushing.
* @raph
/.github/ @raph
* @Raphjacksun7
/.github/ @Raphjacksun7
157 changes: 141 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,147 @@
name: ci-python
on: [pull_request, push]
name: python-sdk-ci

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

env:
CMAKE_POLICY_VERSION_MINIMUM: "3.5"

jobs:
py:
test:
name: ${{ matrix.os }} / Python ${{ matrix.python }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python: ["3.11", "3.13"]

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Upgrade pip
run: python -m pip install --upgrade pip
- name: Install package (non-Windows)
if: runner.os != 'Windows'
run: python -m pip install -e ".[dev]"
- name: Install package (Windows)
if: runner.os == 'Windows'
run: python -m pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org -e ".[dev]"
- run: python -m pytest
- name: Check out Python SDK
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
with:
path: sdk-python

- name: Install Rust 1.95
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0
components: clippy, rustfmt

- name: Install Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: ${{ matrix.python }}

- name: Install Linux native dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install --yes libasound2-dev libpipewire-0.3-dev

- name: Install SDK and development gates
working-directory: sdk-python
run: |
python -m pip install --upgrade pip
python -m pip install "maturin>=1.9.4,<2.0" "pytest>=8.0" "pytest-asyncio>=0.23" "mypy>=1.15" "ruff>=0.11" "websockets>=17.0,<18"
maturin build --release --locked --features conformance-fixtures --out dist-conformance
python -c "from pathlib import Path; import subprocess, sys; wheel = next(Path('dist-conformance').glob('*.whl')); subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--force-reinstall', str(wheel)])"

- name: Rust formatting
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.11'
working-directory: sdk-python
run: cargo fmt --manifest-path native/Cargo.toml -- --check

- name: Native conformance
working-directory: sdk-python
run: cargo test --manifest-path native/Cargo.toml --all-features --locked

- name: Native lint
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.11'
working-directory: sdk-python
run: cargo clippy --manifest-path native/Cargo.toml --all-targets --all-features --locked -- -D warnings

- name: Python lint and formatting
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.11'
working-directory: sdk-python
run: |
ruff check python tests examples
ruff format --check python tests examples

- name: Python type contract
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.11'
working-directory: sdk-python
run: mypy python examples tests/qualification

- name: Python tests
working-directory: sdk-python
run: python -m pytest

- name: Build wheel
working-directory: sdk-python
run: maturin build --release --locked --out dist

- name: Test isolated release wheel
working-directory: sdk-python
run: >-
python tests/run_artifact_consumer.py
--artifact-kind wheel
--artifact-dir dist

- name: Upload wheel for inspection
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: pocketstation-${{ matrix.os }}-py${{ matrix.python }}
path: sdk-python/dist/*.whl
if-no-files-found: error

sdist:
name: source distribution / Python 3.11
runs-on: ubuntu-latest

steps:
- name: Check out Python SDK
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
with:
path: sdk-python

- name: Install Rust 1.95
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0

- name: Install Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.11"

- name: Install Linux native dependencies
run: |
sudo apt-get update
sudo apt-get install --yes libasound2-dev libpipewire-0.3-dev

- name: Build source distribution
working-directory: sdk-python
run: |
python -m pip install --upgrade pip
python -m pip install "maturin>=1.9.4,<2.0"
maturin sdist --manifest-path native/Cargo.toml --out dist

- name: Rebuild and test isolated source distribution
working-directory: sdk-python
run: >-
python tests/run_artifact_consumer.py
--artifact-kind sdist
--artifact-dir dist

- name: Upload source distribution for inspection
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: pocketstation-sdist
path: sdk-python/dist/*.tar.gz
if-no-files-found: error
34 changes: 0 additions & 34 deletions .github/workflows/publish.yml

This file was deleted.

194 changes: 194 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
name: release-python

'on':
release:
types: [published]
workflow_dispatch:
inputs:
release_tag:
description: Existing version-matched release tag to resume
required: true
type: string

permissions:
contents: read

env:
CMAKE_POLICY_VERSION_MINIMUM: "3.5"

concurrency:
group: pypi-publish
cancel-in-progress: false

jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
fetch-depth: 0
ref: ${{ github.event.release.tag_name || inputs.release_tag }}

- name: Validate the release tag
env:
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }}
run: |
set -euo pipefail
version="$(
python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])'
)"
expected_tag="pocketstation-v${version}"
if [[ "${RELEASE_TAG}" != "${expected_tag}" ]]; then
echo "release tag ${RELEASE_TAG} must equal ${expected_tag}" >&2
exit 1
fi
tag_commit="$(git rev-list -n 1 "${RELEASE_TAG}")"
git fetch origin main
if ! git merge-base --is-ancestor "${tag_commit}" origin/main; then
echo "release commit is not contained in origin/main" >&2
exit 1
fi
if [[ "${EVENT_NAME}" == "release" && "${tag_commit}" != "${GITHUB_SHA}" ]]; then
echo "release tag does not resolve to the checked-out commit" >&2
exit 1
fi

wheels:
needs: validate
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- name: Linux x86-64 wheel
os: ubuntu-24.04
target: x86_64-unknown-linux-gnu
manylinux: "2_28"
before_script: dnf install -y alsa-lib-devel pipewire-devel clang cmake ninja-build
- name: Linux ARM64 wheel
os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
manylinux: "2_28"
before_script: dnf install -y alsa-lib-devel pipewire-devel clang cmake ninja-build
- name: macOS Apple silicon wheel
os: macos-15
target: aarch64-apple-darwin
manylinux: "off"
before_script: ""
- name: macOS Intel wheel
os: macos-15-intel
target: x86_64-apple-darwin
manylinux: "off"
before_script: ""
- name: Windows x86-64 wheel
os: windows-latest
target: x86_64-pc-windows-msvc
manylinux: "off"
before_script: ""
- name: Windows ARM64 wheel
os: windows-11-arm
target: aarch64-pc-windows-msvc
manylinux: "off"
before_script: ""
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.release.tag_name || inputs.release_tag }}

- name: Install Python 3.13
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.13"

- name: Build the wheel
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b
with:
command: build
maturin-version: v1.13.0
rust-toolchain: 1.95.0
target: ${{ matrix.target }}
manylinux: ${{ matrix.manylinux }}
before-script-linux: ${{ matrix.before_script }}
args: --release --locked --compatibility pypi --out dist

- name: Test the installed wheel
run: >-
python tests/run_artifact_consumer.py
--artifact-kind wheel
--artifact-dir dist

- name: Upload the wheel
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: wheel-${{ matrix.target }}
path: dist/*.whl
if-no-files-found: error

sdist:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.release.tag_name || inputs.release_tag }}

- name: Install Rust 1.95
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0

- name: Install Python 3.13
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.13"

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install --yes libasound2-dev libpipewire-0.3-dev
python -m pip install --disable-pip-version-check "maturin==1.13.0"

- name: Build and test the source distribution
run: |
maturin sdist --manifest-path native/Cargo.toml --out dist
python tests/run_artifact_consumer.py \
--artifact-kind sdist \
--artifact-dir dist

- name: Upload the source distribution
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: source-distribution
path: dist/*.tar.gz
if-no-files-found: error

publish:
needs: [wheels, sdist]
runs-on: ubuntu-latest
timeout-minutes: 15
environment:
name: pypi
url: https://pypi.org/p/pocketstation
permissions:
id-token: write
steps:
- name: Download wheels
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: wheel-*
path: dist
merge-multiple: true

- name: Download the source distribution
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: source-distribution
path: dist

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
Loading
Loading