diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml
new file mode 100644
index 000000000..86bc7ae67
--- /dev/null
+++ b/.github/workflows/generate-changelog.yml
@@ -0,0 +1,174 @@
+name: Generate Changelog for Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Release version (e.g., 0.0.97)"
+ required: true
+ type: string
+ date:
+ description: "Release date (YYYY-MM-DD format, defaults to today)"
+ required: false
+ type: string
+ default: ""
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ generate-changelog:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Install uv
+ uses: astral-sh/setup-uv@v4
+ with:
+ enable-cache: true
+
+ - name: Install dependencies
+ run: |
+ uv sync --group dev
+
+ - name: Set release date
+ id: set_date
+ run: |
+ if [ -z "${{ inputs.date }}" ]; then
+ RELEASE_DATE=$(date +%Y-%m-%d)
+ echo "Using today's date: $RELEASE_DATE"
+ else
+ RELEASE_DATE="${{ inputs.date }}"
+ echo "Using provided date: $RELEASE_DATE"
+ fi
+ echo "release_date=$RELEASE_DATE" >> $GITHUB_OUTPUT
+
+ - name: Validate inputs
+ run: |
+ # Validate version format (basic check)
+ if ! [[ "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
+ echo "Error: Version must be in format X.Y.Z (e.g., 0.0.97)"
+ exit 1
+ fi
+
+ # Validate date format if provided
+ if [ -n "${{ inputs.date }}" ]; then
+ if ! date -d "${{ inputs.date }}" >/dev/null 2>&1; then
+ # Try macOS date format
+ if ! date -j -f "%Y-%m-%d" "${{ inputs.date }}" >/dev/null 2>&1; then
+ echo "Error: Date must be in YYYY-MM-DD format (e.g., 2025-12-04)"
+ exit 1
+ fi
+ fi
+ fi
+
+ - name: Check for changelog fragments
+ id: check_fragments
+ run: |
+ FRAGMENT_COUNT=$(find changelog -name "*.md" ! -name "_template.md.j2" | wc -l | tr -d ' ')
+ echo "fragment_count=$FRAGMENT_COUNT" >> $GITHUB_OUTPUT
+
+ if [ "$FRAGMENT_COUNT" -eq "0" ]; then
+ echo "❌ Error: No changelog fragments found in changelog/"
+ echo ""
+ echo "Cannot create a release without changelog entries."
+ echo "Add changelog fragments to the changelog/ directory (e.g., 1234.added.md) and try again."
+ exit 1
+ fi
+
+ # Validate fragment types
+ VALID_TYPES="added changed deprecated removed fixed security"
+ INVALID_FRAGMENTS=""
+
+ for file in changelog/*.md; do
+ # Skip template
+ if [[ "$file" == "changelog/_template.md.j2" ]]; then
+ continue
+ fi
+
+ # Extract type from filename (e.g., 1234.added.md -> added)
+ filename=$(basename "$file")
+ # Handle both 1234.added.md and 1234.added.2.md patterns
+ type=$(echo "$filename" | sed -E 's/^[0-9]+\.([a-z]+)(\.[0-9]+)?\.md$/\1/')
+
+ # Check if type is valid
+ if ! echo "$VALID_TYPES" | grep -wq "$type"; then
+ INVALID_FRAGMENTS="$INVALID_FRAGMENTS\n - $filename (type: '$type')"
+ fi
+ done
+
+ if [ -n "$INVALID_FRAGMENTS" ]; then
+ echo "❌ Error: Invalid changelog fragment types found:"
+ echo -e "$INVALID_FRAGMENTS"
+ echo ""
+ echo "Valid types are: $VALID_TYPES"
+ echo "Example: 1234.added.md, 5678.fixed.md"
+ exit 1
+ fi
+
+ echo "✓ Found $FRAGMENT_COUNT changelog fragment(s)"
+ echo "has_fragments=true" >> $GITHUB_OUTPUT
+
+ - name: Preview changelog
+ run: |
+ echo "## Preview of changelog for version ${{ inputs.version }}"
+ echo ""
+ uv run towncrier build --draft --version "${{ inputs.version }}" --date "${{ steps.set_date.outputs.release_date }}"
+
+ - name: Build changelog
+ run: |
+ uv run towncrier build --version "${{ inputs.version }}" --date "${{ steps.set_date.outputs.release_date }}" --yes
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v7
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: "Update changelog for version ${{ inputs.version }}"
+ title: "Release ${{ inputs.version }} - Changelog Update"
+ body: |
+ ## Changelog Update for Release ${{ inputs.version }}
+
+ This PR updates the CHANGELOG.md with all changes for version **${{ inputs.version }}**.
+
+ ### Summary
+ - **Version:** ${{ inputs.version }}
+ - **Date:** ${{ steps.set_date.outputs.release_date }}
+ - **Fragments processed:** ${{ steps.check_fragments.outputs.fragment_count }}
+
+ ### What this PR does
+ - ✅ Adds new release section to CHANGELOG.md
+ - ✅ Removes processed changelog fragments
+ - ✅ Ready to merge for release
+
+ ### Next Steps
+ 1. Review the changelog entries below
+ 2. Make any necessary edits to CHANGELOG.md if needed
+ 3. Merge this PR
+ 4. Continue with your release process
+
+ ---
+
+
+ 📋 Preview of changes
+
+ The changelog has been updated with entries from the following fragments:
+
+ ```bash
+ ${{ steps.check_fragments.outputs.fragment_count }} fragments processed
+ ```
+
+
+ branch: changelog-${{ inputs.version }}
+ delete-branch: true
+ labels: |
+ changelog
+ release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7c7d8d58..7d7979bef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,99 +5,7 @@ All notable changes to **Pipecat** will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [Unreleased]
-
-### Added
-
-- Added new languages to AsyncAI in `AsyncAITTSService` and
- `AsyncAIHttpTTSService`. New `languages`: `pt`, `nl`, `ar`, `ru`, `ro`, `ja`,
- `he`, `hy`, `tr`, `hi`, `zh`.
-
-- Updated the default AsyncAI TTS model to `asyncflow_multilingual_v1.0` for
- improved accuracy and broader language coverage.
-
-- Added new Gradium services, `GradiumSTTService` and `GradiumTTSService`, for
- speech-to-text and text-to-speech functionality using Gradium's API.
-
-### Changed
-
-- Updated `CartesiaSTTService` to return the full transcription `result` in the
- `TranscriptionFrame` and `InterimTranscriptionFrame`. This provides access to
- word timestamp data.
-
-- If an unexpected exception is caught, or if `FrameProcessor.push_error()` is
- called with an exception, the file name and line number where the exception
- occured are now logged.
-
-- Improved interruption handling to prevent bots from repeating themselves.
- LLM services that return multiple sentences in a single response (e.g.,
- `GoogleLLMService`) are now split into individual sentences before being sent
- to TTS. This ensures interruptions occur at sentence boundaries, preventing
- the bot from repeating content after being interrupted during long responses.
-
-- Text Aggregation Improvements:
-
- - **Breaking Change**: `BaseTextAggregator.aggregate()` now returns
- `AsyncIterator[Aggregation]` instead of `Optional[Aggregation]`. This
- enables the aggregator to return multiple results based on the provided
- text.
- - Refactored text aggregators to use inheritance: `SkipTagsAggregator` and
- `PatternPairAggregator` now inherit from `SimpleTextAggregator`, reusing
- the base class's sentence detection logic.
-
-- Updated `AICFilter` to use Quail STT as the default model
- (`AICModelType.QUAIL_STT`). Quail STT is optimized for human-to-machine
- interaction (e.g., voice agents, speech-to-text) and operates at a native
- sample rate of 16 kHz with fixed enhancement parameters.
-
-- Updated Deepgram logging to include Deepgram request IDs for improved debugging.
-
-- Updated Smart Turn model weights to v3.1.
-
-- Smart Turn analyzer now uses the full context of the turn rather than just the
- audio since VAD last triggered.
-
-### Deprecated
-
-- Package `pipecat.sync` is deprecated, use `pipecat.utils.sync` instead.
-
-- The `noise_gate_enable` parameter in `AICFilter` is deprecated and no longer
- has any effect. Noise gating is now handled automatically by the AIC VAD
- system. Use `AICFilter.create_vad_analyzer()` for VAD functionality instead.
-
-- NVIDIA Services name changes (all functionality is unchanged):
-
- - `NimLLMService` is now deprecated, use `NvidiaLLMService` instead.
- - `RivaSTTService` is now deprecated, use `NvidiaSTTService` instead.
- - `RivaTTSService` is now deprecated, use `NvidiaTTSService` instead.
- - Use `uv pip install pipecat-ai[nvidia]` instead of
- `uv pip install pipecat-ai[riva]`
-
-### Fixed
-
-- Fixed an issue in `ElevenLabsTTSService` where character usage metrics were
- only reported on the first TTS generation per turn.
-
-- Fixed an issue where `LLMTextFrame.skip_tts` was being overwritten by LLM
- services.
-
-- Fixed sentence aggregation to correctly handle ambiguous punctuation in
- streaming text, such as currency ("$29.95") and abbreviations ("Mr. Smith").
-
-- Fixed bug in `PatternPairAggregator` where pattern handlers could be called
- multiple times for `KEEP` or `AGGREGATE` patterns.
-
-- Fixed an issue in `SarvamTTSService` where the last sentence was not being
- spoken. Now, audio is flushed when the TTS services receives the
- `LLMFullResponseEndFrame` or `EndFrame`.
-
-- Fixed an issue in `AWSTranscribeSTTService` where the `region` arg was
- always set to `us-east-1` when providing an AWS_REGION env var.
-
-- Fixed an issue in `DeepgramTTSService` where a `TTSStoppedFrame` was
- incorrectly pushed after a functional call. This caused an issue with the
- voice-ui-kit's conversational panel rending of the LLM output after a
- function call.
+
## [0.0.96] - 2025-11-26 🦃 "Happy Thanksgiving!" 🦃
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7a17dff7a..490966ddf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,24 +17,121 @@ We welcome contributions of all kinds! Your help is appreciated. Follow these st
git checkout -b your-branch-name
```
4. **Make your changes**: Edit or add files as necessary.
-5. **Test your changes**: Ensure that your changes look correct and follow the style set in the codebase.
-6. **Commit your changes**: Once you're satisfied with your changes, commit them with a meaningful message.
+5. **Add a changelog entry**: Create a changelog fragment file (see [Changelog Entries](#changelog-entries) below).
+6. **Test your changes**: Ensure that your changes look correct and follow the style set in the codebase.
+7. **Commit your changes**: Once you're satisfied with your changes, commit them with a meaningful message.
```bash
git commit -m "Description of your changes"
```
-7. **Push your changes**: Push your branch to your forked repository.
+8. **Push your changes**: Push your branch to your forked repository.
```bash
git push origin your-branch-name
```
-8. **Submit a Pull Request (PR)**: Open a PR from your forked repository to the main branch of this repo.
+9. **Submit a Pull Request (PR)**: Open a PR from your forked repository to the main branch of this repo.
> Important: Describe the changes you've made clearly!
Our maintainers will review your PR, and once everything is good, your contributions will be merged!
+## Changelog Entries
+
+Every pull request that makes a user-facing change should include a changelog entry. We use a changelog fragment system to avoid merge conflicts.
+
+### Creating a Changelog Fragment
+
+1. Create a new file in the `changelog/` directory with this naming pattern:
+
+ ```
+ ..md
+ ```
+
+2. Choose the appropriate type:
+
+ - `added.md` - New features
+ - `changed.md` - Changes in existing functionality
+ - `deprecated.md` - Soon-to-be removed features
+ - `removed.md` - Removed features
+ - `fixed.md` - Bug fixes
+ - `security.md` - Security fixes
+
+3. Write your changelog entry as a Markdown bullet point. Include the `-` at the start:
+
+**Example files:**
+
+`changelog/1234.added.md`:
+
+```markdown
+- Added support for Anthropic Claude 3.5 Sonnet with improved streaming performance.
+```
+
+`changelog/5678.fixed.md`:
+
+```markdown
+- Fixed an issue where audio frames were dropped during high-load scenarios.
+```
+
+**For entries with nested bullets:**
+
+`changelog/1234.changed.md`:
+
+```markdown
+- Updated service configuration:
+
+ - Changed default timeout to 30 seconds
+ - Added retry logic for failed connections
+```
+
+### Multiple Changes in One PR
+
+**Different types of changes:** Create separate fragment files for each type:
+
+```
+changelog/1234.added.md
+changelog/1234.fixed.md
+```
+
+**Multiple changes of the same type:** Create numbered fragment files:
+
+```
+changelog/1234.changed.md
+changelog/1234.changed.2.md
+```
+
+**Related changes:** Use nested bullets in a single fragment:
+
+```markdown
+- Updated service configuration:
+
+ - Changed default timeout to 30 seconds
+ - Added retry logic for failed connections
+```
+
+**Rule of thumb:** One logical change per fragment file. If changes are unrelated, use separate files.
+
+### Preview Your Changes
+
+To see what your changelog entry will look like:
+
+```bash
+towncrier build --draft --version Unreleased
+```
+
+This won't modify any files, just show you a preview.
+
+### When to Skip Changelog Entries
+
+You can skip adding a changelog entry for:
+
+- Documentation-only changes
+- Internal refactoring with no user-facing impact
+- Test-only changes
+- CI/build configuration changes
+
+If you're unsure whether your change needs a changelog entry, ask in your PR!
+
## Dependency Management
This project uses [uv](https://docs.astral.sh/uv/) for dependency management. The `uv.lock` file is committed to ensure reproducible builds.
diff --git a/changelog/3072.changed.md b/changelog/3072.changed.md
new file mode 100644
index 000000000..e81058b29
--- /dev/null
+++ b/changelog/3072.changed.md
@@ -0,0 +1 @@
+- Updated Deepgram logging to include Deepgram request IDs for improved debugging.
diff --git a/changelog/3130.deprecated.md b/changelog/3130.deprecated.md
new file mode 100644
index 000000000..c7a1c66f6
--- /dev/null
+++ b/changelog/3130.deprecated.md
@@ -0,0 +1,7 @@
+- NVIDIA Services name changes (all functionality is unchanged):
+
+ - `NimLLMService` is now deprecated, use `NvidiaLLMService` instead.
+ - `RivaSTTService` is now deprecated, use `NvidiaSTTService` instead.
+ - `RivaTTSService` is now deprecated, use `NvidiaTTSService` instead.
+ - Use `uv pip install pipecat-ai[nvidia]` instead of
+ `uv pip install pipecat-ai[riva]`
diff --git a/changelog/3132.changed.2.md b/changelog/3132.changed.2.md
new file mode 100644
index 000000000..d7e9c0a5c
--- /dev/null
+++ b/changelog/3132.changed.2.md
@@ -0,0 +1,9 @@
+- Text Aggregation Improvements:
+
+ - **Breaking Change**: `BaseTextAggregator.aggregate()` now returns
+ `AsyncIterator[Aggregation]` instead of `Optional[Aggregation]`. This
+ enables the aggregator to return multiple results based on the provided
+ text.
+ - Refactored text aggregators to use inheritance: `SkipTagsAggregator` and
+ `PatternPairAggregator` now inherit from `SimpleTextAggregator`, reusing
+ the base class's sentence detection logic.
diff --git a/changelog/3132.changed.md b/changelog/3132.changed.md
new file mode 100644
index 000000000..4df044f58
--- /dev/null
+++ b/changelog/3132.changed.md
@@ -0,0 +1 @@
+- Improved interruption handling to prevent bots from repeating themselves. LLM services that return multiple sentences in a single response (e.g., `GoogleLLMService`) are now split into individual sentences before being sent to TTS. This ensures interruptions occur at sentence boundaries, preventing the bot from repeating content after being interrupted during long responses.
diff --git a/changelog/3132.fixed.2.md b/changelog/3132.fixed.2.md
new file mode 100644
index 000000000..4124deee1
--- /dev/null
+++ b/changelog/3132.fixed.2.md
@@ -0,0 +1 @@
+- Fixed bug in `PatternPairAggregator` where pattern handlers could be called multiple times for `KEEP` or `AGGREGATE` patterns.
diff --git a/changelog/3132.fixed.md b/changelog/3132.fixed.md
new file mode 100644
index 000000000..7f063d281
--- /dev/null
+++ b/changelog/3132.fixed.md
@@ -0,0 +1 @@
+- Fixed sentence aggregation to correctly handle ambiguous punctuation in streaming text, such as currency ("$29.95") and abbreviations ("Mr. Smith").
diff --git a/changelog/3153.fixed.md b/changelog/3153.fixed.md
new file mode 100644
index 000000000..f6ffbe541
--- /dev/null
+++ b/changelog/3153.fixed.md
@@ -0,0 +1 @@
+- Fixed an issue in `AWSTranscribeSTTService` where the `region` arg was always set to `us-east-1` when providing an AWS_REGION env var.
diff --git a/changelog/3155.fixed.md b/changelog/3155.fixed.md
new file mode 100644
index 000000000..d45c7884f
--- /dev/null
+++ b/changelog/3155.fixed.md
@@ -0,0 +1 @@
+- Fixed an issue in `SarvamTTSService` where the last sentence was not being spoken. Now, audio is flushed when the TTS services receives the `LLMFullResponseEndFrame` or `EndFrame`.
diff --git a/changelog/3156.fixed.md b/changelog/3156.fixed.md
new file mode 100644
index 000000000..0704fb154
--- /dev/null
+++ b/changelog/3156.fixed.md
@@ -0,0 +1 @@
+- Fixed an issue in `DeepgramTTSService` where a `TTSStoppedFrame` was incorrectly pushed after a functional call. This caused an issue with the voice-ui-kit's conversational panel rending of the LLM output after a function call.
diff --git a/changelog/3162.changed.md b/changelog/3162.changed.md
new file mode 100644
index 000000000..ee0483bd1
--- /dev/null
+++ b/changelog/3162.changed.md
@@ -0,0 +1 @@
+- Updated `AICFilter` to use Quail STT as the default model (`AICModelType.QUAIL_STT`). Quail STT is optimized for human-to-machine interaction (e.g., voice agents, speech-to-text) and operates at a native sample rate of 16 kHz with fixed enhancement parameters.
diff --git a/changelog/3162.deprecated.md b/changelog/3162.deprecated.md
new file mode 100644
index 000000000..7d7c97810
--- /dev/null
+++ b/changelog/3162.deprecated.md
@@ -0,0 +1 @@
+- The `noise_gate_enable` parameter in `AICFilter` is deprecated and no longer has any effect. Noise gating is now handled automatically by the AIC VAD system. Use `AICFilter.create_vad_analyzer()` for VAD functionality instead.
diff --git a/changelog/3168.fixed.md b/changelog/3168.fixed.md
new file mode 100644
index 000000000..0a0826a82
--- /dev/null
+++ b/changelog/3168.fixed.md
@@ -0,0 +1 @@
+- Fixed an issue where `LLMTextFrame.skip_tts` was being overwritten by LLM services.
diff --git a/changelog/3176.added.md b/changelog/3176.added.md
new file mode 100644
index 000000000..ed3c87886
--- /dev/null
+++ b/changelog/3176.added.md
@@ -0,0 +1 @@
+- Added new Gradium services, `GradiumSTTService` and `GradiumTTSService`, for speech-to-text and text-to-speech functionality using Gradium's API.
diff --git a/changelog/3176.changed.md b/changelog/3176.changed.md
new file mode 100644
index 000000000..618837677
--- /dev/null
+++ b/changelog/3176.changed.md
@@ -0,0 +1 @@
+- If an unexpected exception is caught, or if `FrameProcessor.push_error()` is called with an exception, the file name and line number where the exception occured are now logged.
diff --git a/changelog/3177.changed.md b/changelog/3177.changed.md
new file mode 100644
index 000000000..5f0ad3e94
--- /dev/null
+++ b/changelog/3177.changed.md
@@ -0,0 +1 @@
+- Updated Smart Turn model weights to v3.1.
diff --git a/changelog/3181.deprecated.md b/changelog/3181.deprecated.md
new file mode 100644
index 000000000..ee6994373
--- /dev/null
+++ b/changelog/3181.deprecated.md
@@ -0,0 +1 @@
+- Package `pipecat.sync` is deprecated, use `pipecat.utils.sync` instead.
diff --git a/changelog/3183.changed.md b/changelog/3183.changed.md
new file mode 100644
index 000000000..6c152022d
--- /dev/null
+++ b/changelog/3183.changed.md
@@ -0,0 +1 @@
+- Smart Turn analyzer now uses the full context of the turn rather than just the audio since VAD last triggered.
diff --git a/changelog/3184.added.md b/changelog/3184.added.md
new file mode 100644
index 000000000..87c011039
--- /dev/null
+++ b/changelog/3184.added.md
@@ -0,0 +1,4 @@
+- Additions for `AsyncAITTSService` and `AsyncAIHttpTTSService`:
+
+ - Added new `languages`: `pt`, `nl`, `ar`, `ru`, `ro`, `ja`, `he`, `hy`, `tr`, `hi`, `zh`.
+ - Updated the default model to `asyncflow_multilingual_v1.0` for improved accuracy and broader language coverage.
diff --git a/changelog/3186.fixed.md b/changelog/3186.fixed.md
new file mode 100644
index 000000000..8c3dfc526
--- /dev/null
+++ b/changelog/3186.fixed.md
@@ -0,0 +1 @@
+- Fixed an issue in `ElevenLabsTTSService` where character usage metrics were only reported on the first TTS generation per turn.
diff --git a/changelog/3192.changed.md b/changelog/3192.changed.md
new file mode 100644
index 000000000..1770be384
--- /dev/null
+++ b/changelog/3192.changed.md
@@ -0,0 +1 @@
+- Updated `CartesiaSTTService` to return the full transcription `result` in the `TranscriptionFrame` and `InterimTranscriptionFrame`. This provides access to word timestamp data.
diff --git a/changelog/_template.md.j2 b/changelog/_template.md.j2
new file mode 100644
index 000000000..e9448e1e4
--- /dev/null
+++ b/changelog/_template.md.j2
@@ -0,0 +1,17 @@
+{% for section, _ in sections.items() %}
+{% if sections[section] %}
+{% for category, val in definitions.items() if category in sections[section]%}
+
+### {{ definitions[category]['name'] }}
+
+{% for text, values in sections[section][category].items() %}
+{{ text }}
+
+{% endfor %}
+{% endfor %}
+{% else %}
+No significant changes.
+
+{% endif %}
+{% endfor %}
+
diff --git a/pyproject.toml b/pyproject.toml
index ab6367c5e..bb72dba61 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -130,6 +130,7 @@ dev = [
"setuptools~=78.1.1",
"setuptools_scm~=8.3.1",
"python-dotenv>=1.0.1,<2.0.0",
+ "towncrier~=25.8.0",
]
docs = [
@@ -207,3 +208,44 @@ convention = "google"
command_line = "--module pytest"
source = ["src"]
omit = ["*/tests/*"]
+
+[tool.towncrier]
+package = "pipecat"
+package_dir = "src"
+filename = "CHANGELOG.md"
+directory = "changelog"
+start_string = "\n"
+template = "changelog/_template.md.j2"
+title_format = "## [{version}] - {project_date}"
+underlines = ["", "", ""]
+wrap = true
+
+[[tool.towncrier.type]]
+directory = "added"
+name = "Added"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "changed"
+name = "Changed"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "deprecated"
+name = "Deprecated"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "removed"
+name = "Removed"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "fixed"
+name = "Fixed"
+showcontent = true
+
+[[tool.towncrier.type]]
+directory = "security"
+name = "Security"
+showcontent = true
diff --git a/uv.lock b/uv.lock
index df5b46218..cdb084284 100644
--- a/uv.lock
+++ b/uv.lock
@@ -4658,6 +4658,7 @@ dev = [
{ name = "ruff" },
{ name = "setuptools" },
{ name = "setuptools-scm" },
+ { name = "towncrier" },
]
docs = [
{ name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
@@ -4792,6 +4793,7 @@ dev = [
{ name = "ruff", specifier = ">=0.12.11,<1" },
{ name = "setuptools", specifier = "~=78.1.1" },
{ name = "setuptools-scm", specifier = "~=8.3.1" },
+ { name = "towncrier", specifier = "~=25.8.0" },
]
docs = [
{ name = "sphinx", specifier = ">=8.1.3" },
@@ -7251,6 +7253,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/7b/30d423bdb2546250d719d7821aaf9058cc093d165565b245b159c788a9dd/torchvision-0.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e5d680162694fac4c8a374954e261ddfb4eb0ce103287b0f693e4e9c579ef957", size = 1638621, upload-time = "2025-04-23T14:41:46.06Z" },
]
+[[package]]
+name = "towncrier"
+version = "25.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "jinja2" },
+ { name = "tomli", marker = "python_full_version < '3.11'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c2/eb/5bf25a34123698d3bbab39c5bc5375f8f8bcbcc5a136964ade66935b8b9d/towncrier-25.8.0.tar.gz", hash = "sha256:eef16d29f831ad57abb3ae32a0565739866219f1ebfbdd297d32894eb9940eb1", size = 76322, upload-time = "2025-08-30T11:41:55.393Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/42/06/8ba22ec32c74ac1be3baa26116e3c28bc0e76a5387476921d20b6fdade11/towncrier-25.8.0-py3-none-any.whl", hash = "sha256:b953d133d98f9aeae9084b56a3563fd2519dfc6ec33f61c9cd2c61ff243fb513", size = 65101, upload-time = "2025-08-30T11:41:53.644Z" },
+]
+
[[package]]
name = "tqdm"
version = "4.67.1"