Development¶
This page describes the development workflow for Buddy, including source preservation, documentation comments, logging integration, validation, and MkDocs build practices.
Buddy combines a Streamlit application, provider wrapper modules, local storage utilities, and source-driven documentation. Changes should be made conservatively because UI state, provider request construction, and document workflows depend on shared session-state keys and provider-specific wrapper contracts.
๐งญ Purpose¶
The development process has four objectives:
- Preserve existing application behavior.
- Keep provider wrappers isolated and predictable.
- Maintain MkDocs-compatible Google-style docstrings.
- Validate source files before building or publishing documentation.
Buddy documentation is built from source files, so source comments are part of the product. A documentation change should not introduce runtime changes unless the behavior change is intentional and tested.
๐งฑ Source Layout¶
The core project files are organized around the Streamlit application and provider wrappers.
| File | Role |
|---|---|
app.py |
Main Streamlit application, mode routing, session-state initialization, local database utilities, data-management workflows, prompt handling, document workflows, and export logic. |
gpt.py |
OpenAI wrapper for chat, images, text-to-speech, transcription, translation, embeddings, files, and vector stores. |
gemini.py |
Gemini wrapper for chat, image workflows, embeddings, speech, transcription, translation, files, file search, and cloud buckets. |
grok.py |
xAI Grok wrapper for chat, text-to-speech, transcription, translation, images, files, and collection-style retrieval workflows. |
config.py |
Application configuration, API keys, constants, paths, logos, provider defaults, and UI settings. |
requirements.txt |
Runtime and documentation dependencies. |
mkdocs.yml |
MkDocs configuration for the generated documentation site. |
docs/ |
Markdown documentation pages, assets, API pages, and generated diagrams. |
๐งฌ Development Principles¶
Buddy development should follow a preservation-first model.
| Principle | Rule |
|---|---|
| Preserve behavior | Do not change control flow, provider calls, session-state keys, or return behavior during documentation-only work. |
| Preserve signatures | Do not change function, method, or constructor signatures unless a feature requires it. |
| Preserve layout | Do not move Streamlit widgets, columns, tabs, expanders, or state writes unless a UI change is requested. |
| Keep providers isolated | Provider-specific API logic belongs in gpt.py, gemini.py, or grok.py, not in unrelated UI code. |
| Validate early | Compile and inspect files before running MkDocs. |
| Treat warnings as defects | Griffe and MkDocs warnings usually indicate malformed docstrings, missing nav entries, or broken links. |
๐ Google-Style Docstring Standard¶
Buddy uses Google-style docstrings because the API reference is generated by mkdocstrings and
parsed by griffe.
Use this section order when applicable:
Do not use underline-style headings such as:
Do not document self or cls.
Do not add a Returns: section to __init__.
Do not add Returns: None to constructors or procedures that only mutate state.
Function Example¶
def build_input(self, prompt: str, context: list[dict[str, str]] | None = None) -> list[dict[str, object]]:
"""Build a provider input payload.
Purpose:
Creates the provider request input structure from the current prompt and optional
prior conversation context while preserving the message roles expected by the API.
Args:
prompt: User prompt submitted to the provider.
context: Optional prior user, assistant, system, or developer messages.
Returns:
list[dict[str, object]]: Provider-ready message payload.
Raises:
Error: Raised when validation or payload construction fails.
"""
Property Example¶
@property
def model_options(self) -> list[str]:
"""Return supported model names.
Purpose:
Provides model names used by the Streamlit selector for the current provider mode.
Returns:
list[str]: Supported model option names.
"""
๐จ Logging and Exception Handling¶
Buddy wraps provider and workflow exceptions with the project Error object. Where existing
exception handlers catch and re-raise wrapped errors, they should also write to the project logger.
Recommended pattern:
except Exception as e:
exception = Error(e)
exception.module = 'gpt'
exception.cause = 'Chat'
exception.method = 'generate_text( self, prompt: str ) -> str | None'
Logger().write(exception)
raise exception
The exception.method value should be a stable signature string. It must not include:
- API keys.
- User prompts.
- File contents.
- DataFrame contents.
- Full local file paths.
- Tokens.
- Provider responses.
- Object memory addresses.
- Other sensitive or volatile runtime values.
๐ Configuration Practices¶
Provider credentials and runtime defaults should come from configuration or environment variables. Do not hard-code secrets in source files.
Common environment variables include:
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
OpenAI provider access. |
GOOGLE_API_KEY |
Google Gemini access. |
GEMINI_API_KEY |
Gemini-specific provider access where separately configured. |
XAI_API_KEY |
xAI Grok access. |
GOOGLE_CSE_ID |
Search-related workflows where enabled. |
GOOGLEMAPS_API_KEY |
Maps-related workflows where enabled. |
GEOCODING_API_KEY |
Geocoding workflows where enabled. |
๐งช Local Development Setup¶
Create a clean virtual environment and install dependencies.
python -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Run the Streamlit application:
Run from the repository root so imports, configuration paths, and SQLite paths resolve consistently.
โ Source Validation¶
Before building documentation, validate the Python files.
python -m py_compile .\app.py
python -m py_compile .\gpt.py
python -m py_compile .\gemini.py
python -m py_compile .\grok.py
Then run a project-wide compile check:
If a compile check fails, fix source syntax first. Do not troubleshoot MkDocs until the source files compile.
๐ MkDocs Build Workflow¶
Build the documentation locally:
Serve the documentation locally:
Then open the local site in a browser and verify:
- The home page renders.
- The user guide pages are listed in navigation.
- API reference pages render with source-driven content.
- Search works.
- Dark-mode styling loads.
- Tables are readable.
- No broken local links appear.
- No missing image or asset warnings appear.
๐งพ MkDocs Configuration Checklist¶
The mkdocs.yml file should include only pages and assets that exist.
Required sections:
theme:
name: material
plugins:
- search
- mkdocstrings:
handlers:
python:
paths:
- .
options:
docstring_style: google
If CSS or JavaScript assets are added, confirm the files exist before referencing them:
๐งฉ API Reference Pattern¶
API pages should be simple and source-driven.
Example docs/api/gpt.md:
Example docs/api/gemini.md:
Example docs/api/grok.md:
Example docs/api/app.md:
Manual prose should stay in user-guide and architecture pages. API pages should rely on the Python docstrings.
๐งญ Session-State Discipline¶
app.py uses session-state keys to coordinate modes. When changing UI or mode logic:
- Ensure keys are written before they are read.
- Do not reuse unrelated keys across modes.
- Do not clear upstream state unless the reset action is explicit.
- Keep reset functions scoped to their mode.
- Preserve compatibility aliases where existing workflows expect them.
Mode-state functions should remain defensive because widgets may render in different orders after reruns.
๐๏ธ Data and Storage Practices¶
Buddy uses SQLite-backed workflows for prompts, history, embeddings, and data-management utilities.
Development rules:
- Validate table and column names before dynamic SQL.
- Quote SQLite identifiers where needed.
- Avoid destructive operations unless explicitly requested.
- Keep user-uploaded data separate from prompt and history storage.
- Preserve export paths and generated artifact behavior.
- Keep retrieval data traceable to the active document or vector-store source.
๐ Retrieval and Grounding Practices¶
Retrieval workflows should keep answer generation close to source material.
Recommended pattern:
- Load or upload source material.
- Extract text.
- Normalize and chunk text.
- Generate embeddings or provider file references.
- Retrieve relevant chunks or sources.
- Submit grounded prompt context.
- Display answer and source information.
- Export results when needed.
Source attribution should remain visible when the provider or local workflow exposes it.
๐ ๏ธ Provider Wrapper Practices¶
Provider wrappers should expose similar high-level workflows even when provider APIs differ.
| Wrapper | Development Rule |
|---|---|
gpt.py |
Keep OpenAI Responses, Files, Images, Audio, Embeddings, and Vector Stores logic inside OpenAI wrapper classes. |
gemini.py |
Keep Gemini SDK, file search, cloud bucket, safety, grounding, and multimodal request logic inside Gemini wrapper classes. |
grok.py |
Keep xAI model, image, audio, file, and collection-style retrieval logic inside Grok wrapper classes. |
The UI should ask wrappers for available options through properties such as model_options,
tool_options, format_options, and related option lists.
๐ฆ Pull Request Review Checklist¶
Use this checklist before merging changes.
| Check | Required |
|---|---|
| Python files compile | Yes |
| MkDocs builds | Yes |
| No avoidable griffe warnings | Yes |
| No broken docs links | Yes |
No missing assets referenced by mkdocs.yml |
Yes |
| Public docstrings use Google style | Yes |
Constructors do not include Returns: |
Yes |
| Logging handlers avoid sensitive runtime values | Yes |
| Session-state keys are preserved | Yes |
| Provider behavior is preserved | Yes |
| UI layout changes are intentional | Yes |
๐งฏ Common Issues¶
| Issue | Likely Cause | Fix |
|---|---|---|
No type or annotation for returned value 'None' |
Constructor or procedure has malformed Returns: section. |
Remove Returns: from __init__ and avoid Returns: None. |
| API page is empty | Module path is wrong or source file fails import. | Confirm paths: - . and run py_compile. |
| Page exists but is not in nav | Markdown file was created but not listed in mkdocs.yml. |
Add the file to nav or remove it. |
| CSS/JS warning | Asset referenced but missing. | Create the asset or remove the reference. |
| Broken image link | Image path is incorrect or image was not copied into docs/images/. |
Fix the relative path or copy the image. |
| Streamlit key error | Session-state key is read before initialization. | Add or repair the relevant ensure_*_mode_state function. |
โ Release Build Sequence¶
Use this sequence for a clean documentation release:
After visual review, commit source and documentation changes together.
Recommended commit groups:
- Source docstring and logging updates.
- Documentation Markdown pages.
- CSS and JavaScript assets.
- Diagrams and images.
- MkDocs configuration.
โ ๏ธ Review Standard¶
Buddy supports analysis and documentation workflows, but AI-generated outputs still require professional review. Treat generated responses, extracted summaries, and exported reports as draft analytical products until validated against authoritative source material.