Skip to content

Conversation

@sfc-gh-nbellante
Copy link
Contributor

@sfc-gh-nbellante sfc-gh-nbellante commented Oct 20, 2025

Describe your changes

Added python support for audio files in the chat input component.

Key changes:

  • Added audio field to ChatInputValue class to store a single audio file
  • Implemented _pop_audio_file function to extract audio files from protobuf messages
  • Updated serialization/deserialization logic to handle audio files
  • Added accept_audio flag to the ChatInput proto
  • Updated type annotations to accommodate the new audio file field
  • Added comprehensive tests for the audio file functionality

Testing Plan

  • Unit Tests: Added Python tests to verify the audio file handling in ChatInputValue, including:
    • Testing that audio files are properly handled and accessible
    • Verifying the behavior when audio is None
    • Testing the dict-like interface with the new audio field
    • Confirming that the to_dict method properly includes the audio field

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

@snyk-io
Copy link
Contributor

snyk-io bot commented Oct 20, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Licenses 0 0 0 0 0 issues
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Copy link
Contributor Author

sfc-gh-nbellante commented Oct 20, 2025

@github-actions
Copy link
Contributor

github-actions bot commented Oct 20, 2025

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-12832/streamlit-1.51.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-12832.streamlit.app (☁️ Deploy here if not accessible)

@github-actions
Copy link
Contributor

github-actions bot commented Oct 20, 2025

📉 Python coverage change detected

The Python unit test coverage has decreased by 0.0611%

  • Current PR: 92.7643% (20081 statements, 1453 missed)
  • Latest develop: 92.8254% (20057 statements, 1439 missed)

💡 Consider adding more unit tests to maintain or improve coverage.

Coverage by files
Name Stmts Miss Cover
streamlit/__init__.py 141 0 100%
streamlit/__main__.py 3 3 0%
streamlit/auth_util.py 100 25 75%
streamlit/cli_util.py 39 6 85%
streamlit/column_config.py 3 0 100%
streamlit/commands/__init__.py 0 0 100%
streamlit/commands/echo.py 54 11 80%
streamlit/commands/execution_control.py 59 10 83%
streamlit/commands/experimental_query_params.py 40 2 95%
streamlit/commands/logo.py 41 6 85%
streamlit/commands/navigation.py 106 2 98%
streamlit/commands/page_config.py 101 4 96%
streamlit/components/__init__.py 0 0 100%
streamlit/components/lib/__init__.py 0 0 100%
streamlit/components/lib/local_component_registry.py 35 2 94%
streamlit/components/types/__init__.py 0 0 100%
streamlit/components/types/base_component_registry.py 14 0 100%
streamlit/components/types/base_custom_component.py 49 6 88%
streamlit/components/v1/__init__.py 5 0 100%
streamlit/components/v1/component_arrow.py 33 8 76%
streamlit/components/v1/component_registry.py 41 3 93%
streamlit/components/v1/components.py 4 4 0%
streamlit/components/v1/custom_component.py 85 7 92%
streamlit/components/v2/__init__.py 24 0 100%
streamlit/components/v2/bidi_component/__init__.py 4 0 100%
streamlit/components/v2/bidi_component/constants.py 5 0 100%
streamlit/components/v2/bidi_component/main.py 109 12 89%
streamlit/components/v2/bidi_component/serialization.py 81 5 94%
streamlit/components/v2/bidi_component/state.py 13 0 100%
streamlit/components/v2/component_definition_resolver.py 30 0 100%
streamlit/components/v2/component_file_watcher.py 117 9 92%
streamlit/components/v2/component_manager.py 96 16 83%
streamlit/components/v2/component_manifest_handler.py 24 0 100%
streamlit/components/v2/component_path_utils.py 68 5 93%
streamlit/components/v2/component_registry.py 118 8 93%
streamlit/components/v2/get_bidi_component_manager.py 8 1 88%
streamlit/components/v2/manifest_scanner.py 224 25 89%
streamlit/components/v2/presentation.py 84 19 77%
streamlit/components/v2/types.py 8 8 0%
streamlit/config.py 412 12 97%
streamlit/config_option.py 79 3 96%
streamlit/config_util.py 288 7 98%
streamlit/connections/__init__.py 6 0 100%
streamlit/connections/base_connection.py 45 0 100%
streamlit/connections/snowflake_connection.py 60 13 78%
streamlit/connections/snowpark_connection.py 44 3 93%
streamlit/connections/sql_connection.py 56 6 89%
streamlit/connections/util.py 33 0 100%
streamlit/cursor.py 82 2 98%
streamlit/dataframe_util.py 501 45 91%
streamlit/delta_generator.py 205 6 97%
streamlit/delta_generator_singletons.py 76 8 89%
streamlit/deprecation_util.py 59 4 93%
streamlit/development.py 1 0 100%
streamlit/elements/__init__.py 0 0 100%
streamlit/elements/alert.py 60 0 100%
streamlit/elements/arrow.py 198 15 92%
streamlit/elements/balloons.py 10 0 100%
streamlit/elements/bokeh_chart.py 27 0 100%
streamlit/elements/code.py 20 1 95%
streamlit/elements/deck_gl_json_chart.py 104 10 90%
streamlit/elements/dialog_decorator.py 38 0 100%
streamlit/elements/doc_string.py 227 9 96%
streamlit/elements/empty.py 16 4 75%
streamlit/elements/exception.py 101 10 90%
streamlit/elements/form.py 54 2 96%
streamlit/elements/graphviz_chart.py 35 1 97%
streamlit/elements/heading.py 56 0 100%
streamlit/elements/html.py 48 0 100%
streamlit/elements/iframe.py 29 0 100%
streamlit/elements/image.py 32 0 100%
streamlit/elements/json.py 39 2 95%
streamlit/elements/layouts.py 140 3 98%
streamlit/elements/lib/__init__.py 0 0 100%
streamlit/elements/lib/built_in_chart_utils.py 387 26 93%
streamlit/elements/lib/color_util.py 100 4 96%
streamlit/elements/lib/column_config_utils.py 168 1 99%
streamlit/elements/lib/column_types.py 189 4 98%
streamlit/elements/lib/dialog.py 67 1 99%
streamlit/elements/lib/dicttools.py 39 2 95%
streamlit/elements/lib/file_uploader_utils.py 30 0 100%
streamlit/elements/lib/form_utils.py 26 0 100%
streamlit/elements/lib/image_utils.py 176 21 88%
streamlit/elements/lib/js_number.py 28 3 89%
streamlit/elements/lib/layout_utils.py 109 1 99%
streamlit/elements/lib/mutable_status_container.py 73 4 95%
streamlit/elements/lib/options_selector_utils.py 90 0 100%
streamlit/elements/lib/pandas_styler_utils.py 80 2 98%
streamlit/elements/lib/policies.py 56 1 98%
streamlit/elements/lib/streamlit_plotly_theme.py 49 0 100%
streamlit/elements/lib/subtitle_utils.py 76 13 83%
streamlit/elements/lib/utils.py 76 5 93%
streamlit/elements/map.py 110 1 99%
streamlit/elements/markdown.py 63 2 97%
streamlit/elements/media.py 181 8 96%
streamlit/elements/metric.py 91 0 100%
streamlit/elements/pdf.py 49 2 96%
streamlit/elements/plotly_chart.py 114 4 96%
streamlit/elements/progress.py 36 0 100%
streamlit/elements/pyplot.py 39 2 95%
streamlit/elements/snow.py 10 0 100%
streamlit/elements/space.py 12 0 100%
streamlit/elements/spinner.py 34 0 100%
streamlit/elements/text.py 16 0 100%
streamlit/elements/toast.py 26 0 100%
streamlit/elements/vega_charts.py 226 3 99%
streamlit/elements/widgets/__init__.py 0 0 100%
streamlit/elements/widgets/audio_input.py 68 10 85%
streamlit/elements/widgets/button.py 214 3 99%
streamlit/elements/widgets/button_group.py 161 1 99%
streamlit/elements/widgets/camera_input.py 62 10 84%
streamlit/elements/widgets/chat.py 193 54 72%
streamlit/elements/widgets/checkbox.py 52 0 100%
streamlit/elements/widgets/color_picker.py 56 2 96%
streamlit/elements/widgets/data_editor.py 239 14 94%
streamlit/elements/widgets/file_uploader.py 103 18 83%
streamlit/elements/widgets/multiselect.py 105 4 96%
streamlit/elements/widgets/number_input.py 143 5 97%
streamlit/elements/widgets/radio.py 83 5 94%
streamlit/elements/widgets/select_slider.py 97 0 100%
streamlit/elements/widgets/selectbox.py 91 2 98%
streamlit/elements/widgets/slider.py 241 8 97%
streamlit/elements/widgets/text_widgets.py 130 6 95%
streamlit/elements/widgets/time_widgets.py 248 15 94%
streamlit/elements/write.py 166 30 82%
streamlit/emojis.py 4 0 100%
streamlit/env_util.py 21 3 86%
streamlit/error_util.py 33 2 94%
streamlit/errors.py 188 25 87%
streamlit/external/__init__.py 0 0 100%
streamlit/external/langchain/__init__.py 2 0 100%
streamlit/external/langchain/streamlit_callback_handler.py 141 82 42%
streamlit/file_util.py 84 8 90%
streamlit/git_util.py 100 5 95%
streamlit/logger.py 54 0 100%
streamlit/material_icon_names.py 1 0 100%
streamlit/navigation/__init__.py 0 0 100%
streamlit/navigation/page.py 78 2 97%
streamlit/net_util.py 55 3 95%
streamlit/platform.py 10 1 90%
streamlit/runtime/__init__.py 8 0 100%
streamlit/runtime/app_session.py 447 94 79%
streamlit/runtime/caching/__init__.py 19 0 100%
streamlit/runtime/caching/cache_data_api.py 164 3 98%
streamlit/runtime/caching/cache_errors.py 45 4 91%
streamlit/runtime/caching/cache_resource_api.py 122 0 100%
streamlit/runtime/caching/cache_type.py 11 1 91%
streamlit/runtime/caching/cache_utils.py 165 9 95%
streamlit/runtime/caching/cached_message_replay.py 108 1 99%
streamlit/runtime/caching/hashing.py 311 25 92%
streamlit/runtime/caching/legacy_cache_api.py 14 0 100%
streamlit/runtime/caching/storage/__init__.py 2 0 100%
streamlit/runtime/caching/storage/cache_storage_protocol.py 31 2 94%
streamlit/runtime/caching/storage/dummy_cache_storage.py 21 0 100%
streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py 60 0 100%
streamlit/runtime/caching/storage/local_disk_cache_storage.py 86 4 95%
streamlit/runtime/connection_factory.py 85 9 89%
streamlit/runtime/context.py 140 0 100%
streamlit/runtime/context_util.py 18 0 100%
streamlit/runtime/credentials.py 139 4 97%
streamlit/runtime/forward_msg_cache.py 23 2 91%
streamlit/runtime/forward_msg_queue.py 63 4 94%
streamlit/runtime/fragment.py 112 2 98%
streamlit/runtime/media_file_manager.py 69 7 90%
streamlit/runtime/media_file_storage.py 15 0 100%
streamlit/runtime/memory_media_file_storage.py 68 0 100%
streamlit/runtime/memory_session_storage.py 15 0 100%
streamlit/runtime/memory_uploaded_file_manager.py 41 1 98%
streamlit/runtime/metrics_util.py 193 12 94%
streamlit/runtime/pages_manager.py 59 2 97%
streamlit/runtime/runtime.py 248 18 93%
streamlit/runtime/runtime_util.py 30 1 97%
streamlit/runtime/script_data.py 16 0 100%
streamlit/runtime/scriptrunner/__init__.py 5 0 100%
streamlit/runtime/scriptrunner/exec_code.py 49 5 90%
streamlit/runtime/scriptrunner/magic.py 83 1 99%
streamlit/runtime/scriptrunner/magic_funcs.py 10 1 90%
streamlit/runtime/scriptrunner/script_cache.py 27 0 100%
streamlit/runtime/scriptrunner/script_runner.py 230 27 88%
streamlit/runtime/scriptrunner_utils/__init__.py 0 0 100%
streamlit/runtime/scriptrunner_utils/exceptions.py 11 1 91%
streamlit/runtime/scriptrunner_utils/script_requests.py 106 5 95%
streamlit/runtime/scriptrunner_utils/script_run_context.py 135 2 99%
streamlit/runtime/secrets.py 242 25 90%
streamlit/runtime/session_manager.py 60 1 98%
streamlit/runtime/state/__init__.py 7 0 100%
streamlit/runtime/state/common.py 52 2 96%
streamlit/runtime/state/presentation.py 19 4 79%
streamlit/runtime/state/query_params.py 110 3 97%
streamlit/runtime/state/query_params_proxy.py 71 0 100%
streamlit/runtime/state/safe_session_state.py 77 11 86%
streamlit/runtime/state/session_state.py 433 29 93%
streamlit/runtime/state/session_state_proxy.py 62 8 87%
streamlit/runtime/state/widgets.py 15 1 93%
streamlit/runtime/stats.py 42 0 100%
streamlit/runtime/theme_util.py 46 1 98%
streamlit/runtime/uploaded_file_manager.py 39 3 92%
streamlit/runtime/websocket_session_manager.py 66 0 100%
streamlit/source_util.py 36 1 97%
streamlit/string_util.py 88 7 92%
streamlit/temporary_directory.py 18 1 94%
streamlit/testing/__init__.py 0 0 100%
streamlit/testing/v1/__init__.py 2 0 100%
streamlit/testing/v1/app_test.py 239 6 97%
streamlit/testing/v1/element_tree.py 1327 87 93%
streamlit/testing/v1/local_script_runner.py 71 2 97%
streamlit/testing/v1/util.py 17 0 100%
streamlit/time_util.py 28 1 96%
streamlit/type_util.py 138 12 91%
streamlit/url_util.py 39 5 87%
streamlit/user_info.py 87 8 91%
streamlit/util.py 38 1 97%
streamlit/version.py 3 0 100%
streamlit/watcher/__init__.py 3 0 100%
streamlit/watcher/event_based_path_watcher.py 181 24 87%
streamlit/watcher/folder_black_list.py 14 1 93%
streamlit/watcher/local_sources_watcher.py 127 9 93%
streamlit/watcher/path_watcher.py 43 3 93%
streamlit/watcher/polling_path_watcher.py 55 2 96%
streamlit/watcher/util.py 49 1 98%
streamlit/web/__init__.py 0 0 100%
streamlit/web/bootstrap.py 138 18 87%
streamlit/web/cache_storage_manager_config.py 5 0 100%
streamlit/web/cli.py 186 17 91%
streamlit/web/server/__init__.py 5 0 100%
streamlit/web/server/app_static_file_handler.py 29 3 90%
streamlit/web/server/authlib_tornado_integration.py 18 1 94%
streamlit/web/server/bidi_component_request_handler.py 65 8 88%
streamlit/web/server/browser_websocket_handler.py 115 31 73%
streamlit/web/server/component_file_utils.py 24 0 100%
streamlit/web/server/component_request_handler.py 55 4 93%
streamlit/web/server/media_file_handler.py 65 9 86%
streamlit/web/server/oauth_authlib_routes.py 118 18 85%
streamlit/web/server/oidc_mixin.py 44 0 100%
streamlit/web/server/routes.py 90 7 92%
streamlit/web/server/server.py 188 11 94%
streamlit/web/server/server_util.py 67 5 93%
streamlit/web/server/stats_request_handler.py 53 4 92%
streamlit/web/server/upload_file_request_handler.py 53 9 83%
streamlit/web/server/websocket_headers.py 19 1 95%
TOTAL 20081 1453 93%

📊 View detailed coverage comparison

@sfc-gh-nbellante sfc-gh-nbellante added security-assessment-completed Security assessment has been completed for PR impact:internal PR changes only affect internal code change:feature PR contains new feature or enhancement implementation labels Oct 21, 2025
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch 2 times, most recently from 22d8d70 to 0cee413 Compare October 23, 2025 14:18
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch 9 times, most recently from c16c9ee to e60cd27 Compare October 29, 2025 16:08
@sfc-gh-nbellante sfc-gh-nbellante changed the title Add backend infrastructure and proto for audio in ChatInput [feat] Add backend infrastructure and proto for audio in ChatInput Oct 29, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for audio recording in the chat input widget by extending the protobuf messages and backend implementation to handle audio files.

  • Adds audio_file_info field to ChatInputValue protobuf message
  • Adds accept_audio boolean field to ChatInput protobuf message
  • Implements audio file handling with WAV validation in the Python backend
  • Extends ChatInputValue dataclass with optional audio field and updates return types

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
proto/streamlit/proto/Common.proto Adds audio_file_info field to ChatInputValue message for storing audio recording metadata
proto/streamlit/proto/ChatInput.proto Adds accept_audio boolean field to control audio recording button visibility
lib/streamlit/elements/widgets/chat.py Implements audio file extraction and validation logic, updates ChatInputValue dataclass with audio field
lib/tests/streamlit/elements/chat_test.py Adds unit tests for audio file handling in chat input

@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch from 8fd6b69 to 893fc6a Compare October 30, 2025 00:14
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as ready for review October 30, 2025 00:56
@sfc-gh-nbellante sfc-gh-nbellante requested a review from a team as a code owner October 30, 2025 00:56
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch from 893fc6a to a97701e Compare October 30, 2025 03:40
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch 6 times, most recently from 6fbbc3e to 73aa243 Compare October 31, 2025 21:19
This PR adds the foundational backend plumbing and protocol definitions
to support audio recording in chat_input, without exposing the feature
to users yet.

**Backend changes:**
- Add `audio` field to `ChatInputValue` type to hold recorded audio files
- Add `_pop_audio_file()` helper to extract audio from proto messages
- Update `ChatInputSerde.deserialize()` to handle audio file uploads
- Add comprehensive Python unit tests for audio handling

**Proto changes:**
- Add `ChatInputValue.audio_file_info` field (Common.proto)
- Add `ChatInput.accept_audio` field (ChatInput.proto)

The feature remains dark-shipped: the Python API parameter `accept_audio`
is not included in this PR and will be added separately. The protocol and
backend can handle audio, but users cannot enable it yet.

Testing: New Python unit tests validate audio file handling in
ChatInputValue and deserialization logic.
Validates both file extension (.wav) and MIME type (audio/wav, audio/wave,
audio/x-wav) when processing audio files in chat input. Raises clear
StreamlitAPIException if validation fails to provide better error messages
and prevent non-WAV files from being processed.

Addresses PR feedback comment #1.
Added explanatory comment for the hasattr check when calling remove_file.
The check exists because remove_file is not part of the UploadedFileManager
Protocol definition, but is implemented by MemoryUploadedFileManager. This
maintains compatibility with potential alternative implementations.

Addresses PR feedback comment #2.
Moved the accept_file validation back to its original position (after
check_widget_policies) to keep the PR diff focused on the audio input
feature. This removes unnecessary code churn that makes review harder.

Addresses PR feedback comment #3.
Moved the type: ignore[misc] comment back to the register_widget( line
instead of the closing paren. This was an unintentional move that added
noise to the diff.

Addresses PR feedback comment #4.
- Add Numpydoc-style docstring with Parameters and Returns sections
- Add explicit audio_file_info check to file removal guard for safety

Addresses Graphite Agent feedback on PR #12832
Extract magic strings for audio file validation into module-level constants
(_ACCEPTED_AUDIO_EXTENSION and _ACCEPTED_AUDIO_MIME_TYPES) to improve
maintainability and make it easier to support additional audio formats.

Resolves comment 1
Add comprehensive Numpydoc-style docstring to ChatInputValue dataclass,
documenting its purpose, attributes (text, files, audio), and dict-like
interface for users of the public API.

Resolves comment 2
Add "Raises" section to _pop_audio_file docstring to document the
StreamlitAPIException that can be raised during audio file validation,
following Numpydoc conventions.

Resolves comment 3
Replace hasattr() checks with isinstance(MemoryUploadedFileManager)
for explicit type safety, ensuring only approved manager types use
the cleanup logic.

Resolves comment 1
@sfc-gh-nbellante sfc-gh-nbellante force-pushed the nico/pr5-wire-audioinput-chatinput branch from 73aa243 to 11a99ff Compare October 31, 2025 22:01
@sfc-gh-nbellante sfc-gh-nbellante merged commit 209efa5 into develop Nov 1, 2025
37 checks passed
Copy link
Contributor Author

Merge activity

@sfc-gh-nbellante sfc-gh-nbellante deleted the nico/pr5-wire-audioinput-chatinput branch November 1, 2025 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation impact:internal PR changes only affect internal code security-assessment-completed Security assessment has been completed for PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants