Skip to content

Conversation

@MH0386
Copy link
Contributor

@MH0386 MH0386 commented Nov 6, 2025

This pull request introduces several updates and improvements to CI/CD workflows, repository configuration, and project automation. The changes focus on enhancing Docker image builds, workflow flexibility, automation for versioning and releases, and repository hygiene.

CI/CD Workflow Enhancements:

  • Added support for dynamic Docker registry selection, improved build argument handling, and enhanced test reporting in .github/workflows/.docker.yaml. This includes using the correct credentials per registry, passing install source and Python version as build arguments, and summarizing Dockerfile check results. [1] [2] [3] [4] [5] [6] [7] [8] [9]
  • Improved the build and release process in .github/workflows/build.yaml by updating permissions, ensuring the project version matches the branch/tag, and automating commits and tags when versions diverge. [1] [2] [3]
  • Refined the release workflow in .github/workflows/release.yaml by removing the HuggingFace job and ensuring Docker images are built from the released version. [1] [2]
  • Updated test workflow to provide a dependency tree summary and to install from the current git commit. [1] [2]

Automation and Repository Management:

  • Added an "Opencode" job in .github/workflows/ci_tools.yaml to respond to specific issue comments and run the opencode action. [1] [2]
  • Adjusted concurrency settings and triggers for CI tools, and changed versioning workflow to trigger only for the renovate[bot] actor. [1] [2]
  • Updated Mergify rules to automate merging for Trunk updates, improved branch cleanup, and commented on merges. [1] [2]

Repository and Project Hygiene:

  • Added a .gitattributes file to enforce LF line endings.
  • Removed the .envrc file, likely to standardize environment management.
  • Updated .idea project files to exclude the logs directory and added a run configuration for "Vocalizr MCP". [1] [2]
  • Added "ckpts" to the project dictionary for spellchecking.
  • Minor update to trunk auto-commit to skip pre-commit hooks.

These changes collectively improve CI/CD reliability, automation, and maintainability across the project.

Summary by Sourcery

Refactor the Chattr application to leverage the Agno multi-agent framework, integrate advanced tooling and vector knowledge stores, and overhaul CI/CD, Docker, and project configuration for greater automation and maintainability.

New Features:

  • Replace custom orchestration with Agno Agent-based setup and inject MultiMCPTools, Qdrant vector DB, JSON persistence, and Poml prompts.
  • Introduce AGENTS.md with detailed guidelines for tool-driven workflows.
  • Add compose-dev.yaml for local development environment.

Enhancements:

  • Revamp GitHub workflows to support dynamic Docker registry selection, build args (install source, Python version), automated version syncing, test dependency tree summaries, and an Opencode trigger on issue comments.
  • Improve Docker Compose and Dockerfile with restart policies, permissions fixes, environment variables, and cache mounts.
  • Streamline settings initialization with Pydantic validators, directory setup, and Rich logging.
  • Update project dependencies in pyproject.toml to adopt Agno and related libraries and simplify main launcher.

Build:

  • Adjust Dockerfile to accept INSTALL_SOURCE and PYTHON_VERSION build arguments and install package accordingly.

CI:

  • Refine CI/CD pipelines (.docker.yaml, build.yaml, release.yaml, test.yaml, ci_tools.yaml, version.yaml) for automated versioning, tagging, Mergify rules, and dependency checking.

Documentation:

  • Add AGENTS.md for agent guidelines and create .gitattributes to enforce LF line endings.

Tests:

  • Enhance test workflow to include dependency tree summaries in step outputs.

Chores:

  • Remove legacy .envrc, obsolete MCP schema validation, and deprecated GUI/utils modules.
  • Add .idea and IDE config updates to ignore logs and define run configurations.

MH0386 and others added 30 commits October 2, 2025 03:32
This commit fixes the style issues introduced in 566e2b8 according to the output
from Ruff Formatter.

Details: #388
This commit fixes the style issues introduced in ec36f60 according to the output
from Ruff Formatter.

Details: #388
This PR refactors class attribute assignments by removing unsupported inline type declarations. The changes ensure compatibility with environments that do not support variable type annotations on assignment.

- Unsupported `Type` declaration: The code originally declared types inline (e.g., `cls._tools: list[BaseTool] = ...`), which is not supported in all Python versions. The fix removes the `: type` portion, leaving standard assignments for `_tools`, `_llm`, and `_model`, while preserving functionality.

> This Autofix was generated by AI. Please review the change before merging.
Refactor Docker workflows and improve CI configurations
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/chattr/app/settings.py (1)

40-65: Critical: MCPSettings.path as FilePath makes missing mcp.json a hard error

MCPSettings.path is annotated as FilePath with a default of Path.cwd() / "mcp.json", and you have validators that only warn when the file is missing:

path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json")

@model_validator(mode="after")
def is_exists(self) -> Self:
    if not self.path.exists():
        logger.warning("`mcp.json` not found.")

In Pydantic v2, FilePath is defined as Annotated[Path, PathType('file')], which requires that the path point to an existing file at validation time. (docs.pydantic.dev) If mcp.json is absent in the working directory, model construction will fail before your is_exists / is_valid_scheme validators run, contradicting the “just warn if missing” behavior and preventing Settings() from being created on a fresh install.

This also makes is_exists effectively unreachable in the missing‑file case.

I recommend changing the type to Path (or another non‑“must exist” path type) and leaving existence checks to your validators:

-from pydantic import (
-    ...,
-    FilePath,
-    ...
-)
+from pydantic import (
+    ...,
+    ...
+)
@@
-class MCPSettings(BaseModel):
-    """Settings for MCP configuration."""
-
-    path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json")
+class MCPSettings(BaseModel):
+    """Settings for MCP configuration."""
+
+    path: Path = Field(default_factory=lambda: Path.cwd() / "mcp.json")

With this change:

  • Settings() can be instantiated even when mcp.json is missing.
  • is_exists will log the warning as intended.
  • is_valid_scheme will still enforce structure when the file is present.

Because a very similar concern was already raised in an earlier review, this is both a confirmation and a reiteration.

To reproduce and verify the behavior locally:

#!/bin/bash
# Run in a clean directory with no mcp.json present.
python - << 'PY'
from pathlib import Path
from pydantic import BaseModel, FilePath, Field

class MCPSettings(BaseModel):
    path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json")

print("Attempting to construct MCPSettings without mcp.json present...")
try:
    MCPSettings()
except Exception as e:
    print("Got exception:", repr(e))
PY
🧹 Nitpick comments (4)
src/chattr/app/settings.py (4)

19-24: Consider avoiding load_dotenv() at import time

Calling load_dotenv() at module import mutates process environment for any importer and duplicates the .env handling you already configure via Settings.model_config.env_file. Consider moving load_dotenv() into the application entrypoint (or removing it and relying solely on env_file) so that importing chattr.app.settings is side‑effect free.


36-38: Verify HttpUrl default for http://localhost:6333

VectorDatabaseSettings.url uses HttpUrl("http://localhost:6333") as a default. In Pydantic, HttpUrl enforces http/https schemes and, per docs, may require a TLD on the host; some versions treat localhost as invalid in HttpUrl while AnyHttpUrl is more permissive for local hosts. (docs.pydantic.dev)

If you ever hit validation errors around this default, consider switching the type to AnyHttpUrl and using a plain string default:

-from pydantic import (
-    ...,
-    HttpUrl,
-    ...
-)
+from pydantic import (
+    ...,
+    AnyHttpUrl,
+    ...
+)

-class VectorDatabaseSettings(BaseModel):
-    ...
-    url: HttpUrl = HttpUrl("http://localhost:6333")
+class VectorDatabaseSettings(BaseModel):
+    ...
+    url: AnyHttpUrl = "http://localhost:6333"

60-65: Optionally wrap MCPScheme validation errors for a clearer message

is_valid_scheme currently does:

if self.path and self.path.exists():
    _ = MCPScheme.model_validate_json(self.path.read_text())

Any JSON parse or schema error will bubble up as a raw ValidationError from MCPScheme. That’s functionally fine, but you might consider catching it to add context like “invalid MCP config at {path}” while re‑raising the original error for easier debugging:

from pydantic import ValidationError

@model_validator(mode="after")
def is_valid_scheme(self) -> Self:
    if self.path and self.path.exists():
        try:
            MCPScheme.model_validate_json(self.path.read_text())
        except ValidationError as exc:
            raise ValueError(f"Invalid MCP config in {self.path}") from exc
    return self

Not required, but improves UX when the config is malformed.


68-128: Clarify DirectorySettings.base semantics and computed field types

Overall, DirectorySettings is nicely structured and create_missing_dirs is clear. A couple of points worth considering:

  1. base: DirectoryPath vs creating a new base directory

    base is typed as DirectoryPath:

    base: DirectoryPath = Field(default_factory=Path.cwd, frozen=True)

    In Pydantic, DirectoryPath requires that the path already exist and be a directory. (docs.pydantic.dev) That means if a user sets DIRECTORY__BASE to a path that does not exist yet, validation will fail before create_missing_dirs can run, even though the docstring says “Ensure that all specified directories exist, creating them if necessary.”

    If you intend DirectorySettings to be able to create a new base directory, switching base to a plain Path (or NewPath if you want “must not exist yet”) and leaving creation logic in create_missing_dirs would better match the documented behavior:

    from pydantic import (
  • DirectoryPath,
  • DirectoryPath,
  • NewPath, # optionally, if you want "new path" semantics

    ...
    )

class DirectorySettings(BaseModel):
"""Settings for application directories."""

  •  base: DirectoryPath = Field(default_factory=Path.cwd, frozen=True)
    
  •  base: Path = Field(default_factory=Path.cwd, frozen=True)
    
    
    
  1. Computed fields annotated as DirectoryPath

    The log, assets, audio, video, and prompts properties are @computed_fields annotated as DirectoryPath but are created by create_missing_dirs later. In practice, Pydantic doesn’t enforce DirectoryPath’s “must exist” constraint on computed fields, so this works, but the annotation can be slightly misleading to readers.

    If you want the type hints to reflect actual semantics without implying pre‑existence, consider annotating these as Path instead while keeping the creation logic as‑is.

Neither of these is blocking, but aligning the types with the creation behavior will make the model less surprising.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 942d9e7 and fbbab0e.

📒 Files selected for processing (2)
  • .envrc (1 hunks)
  • src/chattr/app/settings.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .envrc
🧰 Additional context used
🧬 Code graph analysis (1)
src/chattr/app/settings.py (1)
src/chattr/app/scheme.py (1)
  • MCPScheme (35-41)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Image / Build and push Docker image to ghcr.io
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (6)
src/chattr/app/settings.py (6)

26-38: Memory and vector DB settings definitions look solid

MemorySettings and VectorDatabaseSettings are straightforward and readable. The defaults (collection_name, embedding_dims, name) look reasonable for a local setup.


113-128: Directory creation + logging behavior looks good

The create_missing_dirs loop over base, assets, log, audio, video, and prompts is clear and guarded with try/except OSError, logging both successful creation and failures before re‑raising. That fail‑fast behavior makes sense for an app‑level settings object.


131-168: Model credential validation logic is consistent

ModelSettings cleanly enforces that if url is set, both api_key and name must be provided, with clear error messages that match your env_nested_delimiter convention (MODEL__API_KEY, MODEL__NAME). Temperature bounds are also correctly constrained via ge/le.

No functional issues spotted here.


170-175: CharacterSettings is a minimal, flexible extension point

Introducing CharacterSettings with an optional name is a reasonable way to keep persona/character configuration separate from model and memory settings, and leaves room for future fields without impacting core config.


179-194: Settings aggregation and env config look coherent

The Settings class wires together directory, model, memory, vector_database, mcp, character, and debug with sensible default_factory usage and a model_config that matches the documented env key patterns (e.g., MODEL__NAME, DIRECTORY__BASE).

This structure should make it straightforward to reason about and override each sub‑settings group via environment variables.


197-200: Rich-based self-inspection in __main__ is handy

Using rich.print on Settings().model_dump_json(indent=4) behind if __name__ == "__main__": is a convenient, low‑friction way to inspect the effective configuration, and keeps the Rich dependency out of import‑time side effects.

Copilot AI review requested due to automatic review settings December 6, 2025 20:10
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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 6, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants