Skip to content

fix: resolve circular imports, bump litellm, fix release tag format#286

Merged
Aureliolo merged 3 commits intomainfrom
fix/release-and-litellm-streaming
Mar 10, 2026
Merged

fix: resolve circular imports, bump litellm, fix release tag format#286
Aureliolo merged 3 commits intomainfrom
fix/release-and-litellm-streaming

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Fix circular imports: Move RetryConfig/RateLimiterConfig from config.schema to new core/resilience_config.py, and move BudgetExhaustedError/DailyLimitExceededError/QuotaExhaustedError from engine/errors.py to new budget/errors.py. Delete the providers/resilience/config.py re-export shim. Move routing module imports of config.schema behind TYPE_CHECKING guards (placed at end of import sections per convention).
  • Bump litellm 1.82.0 → 1.82.1 and fix streaming test types (ModelResponseModelResponseStream)
  • Fix release tag format: Add "include-component-in-tag": false to release-please config so tags are vX.Y.Z (not ai-company-vX.Y.Z), matching the Docker CI v* trigger
  • Update docs: DESIGN_SPEC.md §15.3 project structure updated (new files added, deleted file removed), CLAUDE.md package structure descriptions updated for budget/ and core/
  • Add test coverage: New tests/unit/budget/test_errors.py for budget error hierarchy assertions; QuotaExhaustedError added to engine budget handler parametrize

Test plan

  • ruff check — all checks passed
  • ruff format — no changes needed
  • mypy src/ tests/ — no issues (848 files)
  • pytest tests/ -n auto --cov=ai_company --cov-fail-under=80 — 6653 passed, 8 skipped, 94.80% coverage
  • Pre-commit hooks pass (commitizen, gitleaks, trailing whitespace, etc.)

Review coverage

Pre-reviewed by 9 agents (code-reviewer, python-reviewer, pr-test-analyzer, comment-analyzer, type-design-analyzer, logging-audit, resilience-audit, security-reviewer, docs-consistency). 11 findings identified and addressed. No CRITICAL code issues found — all findings were import ordering, docstring accuracy, docs drift, and test coverage gaps.

- Fix Release Please tag format: add `include-component-in-tag: false`
  to produce `vX.Y.Z` tags matching Docker workflow's `v*` trigger
- Bump litellm 1.82.0 → 1.82.1 and fix streaming test mocks:
  use `ModelResponseStream` instead of `ModelResponse(stream=True)`
- Break circular import chain (config.schema ↔ providers):
  - Extract RetryConfig/RateLimiterConfig to core/resilience_config.py
  - Extract budget errors to budget/errors.py
  - Move routing module imports to TYPE_CHECKING blocks (PEP 649)
  - Delete providers/resilience/config.py re-export module
  - Remove all backward-compatibility re-exports from engine/errors.py,
    engine/__init__.py, and providers/__init__.py
  - Update all consumers to import from canonical locations
- Move TYPE_CHECKING blocks to end of import sections in routing modules
- Fix inaccurate docstrings in budget/errors.py
- Update DESIGN_SPEC.md §15.3 project structure (add budget/errors.py,
  core/resilience_config.py; remove deleted providers/resilience/config.py)
- Update CLAUDE.md package structure descriptions for budget/ and core/
- Add tests/unit/budget/test_errors.py for budget error hierarchy
- Add QuotaExhaustedError to engine budget handler parametrize

Pre-reviewed by 9 agents, 11 findings addressed
Copilot AI review requested due to automatic review settings March 10, 2026 22:55
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 2026

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 1 package(s) with unknown licenses.
See the Details below.

License Issues

uv.lock

PackageVersionLicenseIssue Type
litellm1.82.1NullUnknown License
Allowed Licenses: MIT, MIT-0, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, MPL-2.0, PSF-2.0, Unlicense, 0BSD, CC0-1.0, Python-2.0, Python-2.0.1, LicenseRef-scancode-free-unknown

OpenSSF Scorecard

PackageVersionScoreDetails
pip/litellm 1.82.1 UnknownUnknown

Scanned Files

  • uv.lock

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e5dc9c66-15a8-4a8d-88a6-48128bda81bc

📥 Commits

Reviewing files that changed from the base of the PR and between 17eb317 and a7a5404.

📒 Files selected for processing (3)
  • DESIGN_SPEC.md
  • src/ai_company/budget/errors.py
  • tests/unit/budget/test_errors.py
📜 Recent review details
⏰ 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). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Python 3.14+ with PEP 649 native lazy annotations
Do NOT use from __future__ import annotations — Python 3.14 has PEP 649
Use PEP 758 except syntax: except A, B: (no parentheses) — ruff enforces this on Python 3.14
Include type hints on all public functions; enforce mypy strict mode
Use Google style docstrings, required on all public classes and functions (enforced by ruff D rules)
Create new objects instead of mutating existing ones — practice immutability
For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement
For dict/list fields in frozen Pydantic models, rely on frozen=True for field reassignment prevention and copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model
Use Pydantic v2 (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing + validating redundant fields. Use NotBlankStr (from core.types) for all identifier/name fields
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task. Existing code is being migrated incrementally
Limit line length to 88 characters (ruff enforced)
Keep functions under 50 lines; keep files under 800 lines
Handle errors explicitly; never silently swallow exceptions
Validate at system boundaries (user input, external APIs, config files)

Files:

  • src/ai_company/budget/errors.py
  • tests/unit/budget/test_errors.py
src/ai_company/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/ai_company/**/*.py: Every module with business logic MUST have from ai_company.observability import get_logger then logger = get_logger(__name__)
Never use import logging / logging.getLogger() / print() in application code — use the observability module
Always use variable name logger (not _logger, not log)
Use event name constants from domain-specific modules under ai_company.observability.events (e.g. PROVIDER_CALL_START from events.provider). Import directly: from ai_company.observability.events.<domain> import EVENT_CONSTANT
Use structured logging format: always logger.info(EVENT, key=value) — never logger.info('msg %s', val)
Log all error paths at WARNING or ERROR with context before raising exceptions
Log all state transitions at INFO level
Use DEBUG level for object creation, internal flow, entry/exit of key functions
Pure data models, enums, and re-exports do NOT need logging
All provider calls must go through BaseCompletionProvider which applies retry + rate limiting automatically — never implement retry logic in driver subclasses or calling code
Set RetryConfig and RateLimiterConfig per-provider in ProviderConfig
Retryable errors (is_retryable=True) include: RateLimitError, ProviderTimeoutError, ProviderConnectionError, ProviderInternalError. Non-retryable errors raise immediately without retry
The rate limiter automatically respects RateLimitError.retry_after from providers — automatically pauses future requests
NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, example-medium-001, example-small-001, large/medium/small as aliases

Files:

  • src/ai_company/budget/errors.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Mark tests with @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, or @pytest.mark.slow
Prefer @pytest.mark.parametrize for testing similar cases in test files
Use test-provider, test-small-001, etc. as generic vendor names in test files

Files:

  • tests/unit/budget/test_errors.py
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Retryable errors (`is_retryable=True`) include: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Retryable errors (`is_retryable=True`) include: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry

Applied to files:

  • src/ai_company/budget/errors.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Log all error paths at WARNING or ERROR with context before raising exceptions

Applied to files:

  • src/ai_company/budget/errors.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/engine/**/*.py : `RetryExhaustedError` signals that all retries failed — the engine layer must catch this to trigger fallback chains

Applied to files:

  • src/ai_company/budget/errors.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to tests/**/*.py : Prefer `pytest.mark.parametrize` for testing similar cases in test files

Applied to files:

  • tests/unit/budget/test_errors.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g. `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`

Applied to files:

  • DESIGN_SPEC.md
🧬 Code graph analysis (1)
tests/unit/budget/test_errors.py (2)
src/ai_company/budget/errors.py (3)
  • BudgetExhaustedError (9-20)
  • DailyLimitExceededError (23-24)
  • QuotaExhaustedError (27-32)
src/ai_company/engine/errors.py (1)
  • EngineError (4-5)
🔇 Additional comments (3)
src/ai_company/budget/errors.py (1)

9-32: Clean leaf error hierarchy for the import split.

This keeps the budget exhaustion types decoupled from the engine layer and makes the circular-import fix explicit in one canonical place.

DESIGN_SPEC.md (1)

2793-2795: Project-structure docs now match the refactor.

Updating the spec alongside the code move helps keep future imports and package discovery aligned with the canonical module locations.

Also applies to: 3177-3177

tests/unit/budget/test_errors.py (1)

21-63: Good regression coverage for the hierarchy split.

These parametrized checks lock in both the subtype behavior and the intentional separation from EngineError, which should help catch accidental re-coupling later.


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Adds explicit budget error types for clearer budget/quota signaling.
    • Introduces dedicated resilience configuration models for retry and rate-limiting.
  • Breaking Surface / Public API

    • Error and resilience config exports were reorganized — import locations for these types have moved.
  • Chores

    • Bumped litellm dependency to 1.82.1
  • Tests

    • Added/updated unit tests validating the new budget error hierarchy and resilience configs.

Walkthrough

This PR refactors budget error placement and resilience configuration locations. BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError are moved into a new ai_company.budget.errors module and re-exported from ai_company.budget. RetryConfig and RateLimiterConfig are relocated into a new ai_company.core.resilience_config module and imports updated across providers and tests; TYPE_CHECKING guards were added to routing modules.

Changes

Cohort / File(s) Summary
Budget error surface
src/ai_company/budget/errors.py, src/ai_company/budget/__init__.py, src/ai_company/budget/enforcer.py, src/ai_company/engine/errors.py, src/ai_company/engine/__init__.py, src/ai_company/engine/agent_engine.py
Added standalone budget error module and re-exports; removed budget-related error classes from engine layer and updated imports to ai_company.budget.errors.
Resilience config relocation
src/ai_company/core/resilience_config.py, src/ai_company/config/schema.py
New core module exposing RetryConfig and RateLimiterConfig; removed local definitions from config.schema and replaced them with imports from the new module.
Provider resilience adjustments
src/ai_company/providers/resilience/config.py (deleted), src/ai_company/providers/resilience/__init__.py, src/ai_company/providers/resilience/rate_limiter.py, src/ai_company/providers/resilience/retry.py, src/ai_company/providers/__init__.py
Deleted the providers re-export module; updated provider modules to import resilience config models from ai_company.core.resilience_config and removed their re-exports.
Routing import guards
src/ai_company/providers/routing/_strategy_helpers.py, src/ai_company/providers/routing/resolver.py, src/ai_company/providers/routing/router.py, src/ai_company/providers/routing/strategies.py
Introduced TYPE_CHECKING-guarded imports for routing/config types to avoid import-time cycles.
Tests updated
tests/unit/..., tests/integration/providers/conftest.py, tests/integration/providers/test_retry_integration.py (multiple files)
Updated many tests to import errors and resilience configs from their new modules; added tests/unit/budget/test_errors.py; adjusted streaming test helpers to use ModelResponseStream.
Docs & config tweaks
.github/release-please-config.json, CLAUDE.md, DESIGN_SPEC.md, pyproject.toml
Added "include-component-in-tag": false to release config; documentation updates reflecting module moves; bumped litellm dependency to 1.82.1.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the three main changes: circular imports resolution, litellm version bump, and release tag format fix.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing the objectives, implementation approach, testing results, and pre-review feedback.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/release-and-litellm-streaming
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/release-and-litellm-streaming

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on enhancing the modularity and maintainability of the codebase by resolving several circular import issues. By relocating shared configuration models and error classes to more appropriate, independent modules, the system's dependency graph is simplified, making it easier to understand and extend. Additionally, it incorporates an important dependency update for litellm and refines the automated release process to ensure consistent version tagging, alongside updating documentation to reflect these structural changes and adding new test coverage.

Highlights

  • Circular Import Resolution: Refactored RetryConfig and RateLimiterConfig from config.schema to a new core/resilience_config.py module. Similarly, BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError were moved from engine/errors.py to a new budget/errors.py module. This restructuring eliminates circular dependencies and improves module isolation.
  • Dependency Update and Type Fix: Updated the litellm library from version 1.82.0 to 1.82.1. This update included fixing streaming test types by changing ModelResponse to ModelResponseStream to align with the new library version's API.
  • Release Tag Format Correction: Modified the release-please configuration to ensure release tags follow the vX.Y.Z format, rather than ai-company-vX.Y.Z. This change standardizes the tagging convention and matches the Docker CI trigger.
  • Documentation and Test Coverage Enhancements: Updated DESIGN_SPEC.md and CLAUDE.md to reflect the new project structure, including the newly added core/resilience_config.py and budget/errors.py files, and the removal of providers/resilience/config.py. New unit tests were added for the budget error hierarchy to ensure correct inheritance and behavior.
Changelog
  • .github/release-please-config.json
    • Added include-component-in-tag configuration to prevent component names in release tags.
  • CLAUDE.md
    • Updated descriptions for the budget/ and core/ directories to reflect new error and resilience config locations.
  • DESIGN_SPEC.md
    • Updated project structure to include core/resilience_config.py and budget/errors.py.
    • Removed providers/resilience/config.py from the project structure documentation.
  • pyproject.toml
    • Updated litellm dependency from 1.82.0 to 1.82.1.
  • src/ai_company/budget/init.py
    • Imported and re-exported BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError from the new budget.errors module.
  • src/ai_company/budget/enforcer.py
    • Updated import path for BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError to ai_company.budget.errors.
  • src/ai_company/budget/errors.py
    • Added new file defining BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError.
  • src/ai_company/config/schema.py
    • Removed definitions of RetryConfig and RateLimiterConfig.
    • Imported RetryConfig and RateLimiterConfig from ai_company.core.resilience_config.
  • src/ai_company/core/resilience_config.py
    • Added new file defining RetryConfig and RateLimiterConfig models.
  • src/ai_company/engine/init.py
    • Removed imports and re-exports of BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError.
  • src/ai_company/engine/agent_engine.py
    • Updated import path for BudgetExhaustedError to ai_company.budget.errors.
  • src/ai_company/engine/errors.py
    • Removed definitions of BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError.
  • src/ai_company/providers/init.py
    • Removed re-exports of RateLimiterConfig and RetryConfig.
  • src/ai_company/providers/resilience/init.py
    • Removed imports and re-exports of RateLimiterConfig and RetryConfig.
  • src/ai_company/providers/resilience/config.py
    • Removed file, as its contents were moved to core/resilience_config.py.
  • src/ai_company/providers/resilience/rate_limiter.py
    • Updated import path for RateLimiterConfig to ai_company.core.resilience_config.
  • src/ai_company/providers/resilience/retry.py
    • Updated import path for RetryConfig to ai_company.core.resilience_config.
  • src/ai_company/providers/routing/_strategy_helpers.py
    • Moved imports of RoutingConfig and RoutingRuleConfig behind TYPE_CHECKING guards to prevent circular imports.
  • src/ai_company/providers/routing/resolver.py
    • Moved import of ProviderConfig behind a TYPE_CHECKING guard to prevent circular imports.
  • src/ai_company/providers/routing/router.py
    • Moved imports of ProviderConfig and RoutingConfig behind TYPE_CHECKING guards to prevent circular imports.
  • src/ai_company/providers/routing/strategies.py
    • Moved import of RoutingConfig behind a TYPE_CHECKING guard to prevent circular imports.
  • tests/integration/providers/conftest.py
    • Updated litellm streaming types from ModelResponse to ModelResponseStream.
    • Updated import path for RetryConfig to ai_company.core.resilience_config.
  • tests/integration/providers/test_retry_integration.py
    • Updated import paths for RateLimiterConfig and RetryConfig to ai_company.core.resilience_config.
  • tests/unit/budget/test_enforcer.py
    • Updated import paths for BudgetExhaustedError and DailyLimitExceededError to ai_company.budget.errors.
  • tests/unit/budget/test_enforcer_quota.py
    • Updated import path for QuotaExhaustedError to ai_company.budget.errors.
  • tests/unit/budget/test_errors.py
    • Added new file to test the budget error hierarchy and its inheritance.
  • tests/unit/config/conftest.py
    • Updated import paths for RateLimiterConfig and RetryConfig to ai_company.core.resilience_config.
  • tests/unit/engine/test_agent_engine_budget.py
    • Updated import paths for BudgetExhaustedError, DailyLimitExceededError, and QuotaExhaustedError to ai_company.budget.errors.
    • Added QuotaExhaustedError to parametrized test cases for pre-flight budget stops.
  • tests/unit/engine/test_errors.py
    • Updated import path for BudgetExhaustedError to ai_company.budget.errors.
    • Modified test to assert that BudgetExhaustedError is not a subclass of EngineError.
  • tests/unit/providers/drivers/conftest.py
    • Updated import paths for RateLimiterConfig and RetryConfig to ai_company.core.resilience_config.
  • tests/unit/providers/resilience/conftest.py
    • Updated import paths for RateLimiterConfig and RetryConfig to ai_company.core.resilience_config.
  • tests/unit/providers/resilience/test_config.py
    • Updated import paths for RateLimiterConfig and RetryConfig to ai_company.core.resilience_config.
  • tests/unit/providers/resilience/test_rate_limiter.py
    • Updated import path for RateLimiterConfig to ai_company.core.resilience_config.
  • tests/unit/providers/resilience/test_retry.py
    • Updated import path for RetryConfig to ai_company.core.resilience_config.
  • uv.lock
    • Updated litellm package version to 1.82.1.
Activity
  • The pull request was pre-reviewed by 9 agents (code-reviewer, python-reviewer, pr-test-analyzer, comment-analyzer, type-design-analyzer, logging-audit, resilience-audit, security-reviewer, docs-consistency).
  • 11 findings were identified and subsequently addressed by the author.
  • No CRITICAL code issues were found; findings primarily related to import ordering, docstring accuracy, documentation drift, and test coverage gaps.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

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 removes a couple of circular import edges by relocating shared configuration and error types into leaf modules, updates LiteLLM to align with upstream streaming types, and adjusts release-please tagging to match CI tag triggers.

Changes:

  • Moved RetryConfig/RateLimiterConfig into ai_company.core.resilience_config and updated imports across config, providers, and tests.
  • Moved budget exhaustion errors into ai_company.budget.errors and updated engine/budget wiring plus unit tests.
  • Bumped litellm to 1.82.1 and updated integration test streaming chunk types; fixed release-please tag format config.

Reviewed changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated no comments.

Show a summary per file
File Description
uv.lock Locks litellm to 1.82.1 to match updated test expectations.
pyproject.toml Bumps litellm dependency to 1.82.1.
.github/release-please-config.json Ensures tags are vX.Y.Z by disabling component-in-tag.
src/ai_company/core/resilience_config.py New canonical home for RetryConfig and RateLimiterConfig to avoid circular imports.
src/ai_company/config/schema.py Imports resilience configs from core.resilience_config instead of defining them inline.
src/ai_company/providers/resilience/retry.py Updates type-only import of RetryConfig to the new module.
src/ai_company/providers/resilience/rate_limiter.py Switches RateLimiterConfig import to the new module.
src/ai_company/providers/resilience/config.py Deletes the old re-export shim module.
src/ai_company/providers/resilience/__init__.py Removes config model re-exports from the resilience public surface.
src/ai_company/providers/__init__.py Stops re-exporting resilience config models from ai_company.providers.
src/ai_company/providers/routing/strategies.py Moves RoutingConfig import behind TYPE_CHECKING to break cycles.
src/ai_company/providers/routing/router.py Moves ProviderConfig/RoutingConfig imports behind TYPE_CHECKING to break cycles.
src/ai_company/providers/routing/resolver.py Moves ProviderConfig import behind TYPE_CHECKING to break cycles.
src/ai_company/providers/routing/_strategy_helpers.py Moves routing config imports behind TYPE_CHECKING to break cycles.
src/ai_company/budget/errors.py New leaf-module budget exception hierarchy.
src/ai_company/budget/enforcer.py Imports budget exceptions from ai_company.budget.errors.
src/ai_company/budget/__init__.py Re-exports budget errors at the budget package level.
src/ai_company/engine/errors.py Removes budget exceptions from the engine error hierarchy.
src/ai_company/engine/agent_engine.py Catches BudgetExhaustedError from the budget layer rather than engine errors.
src/ai_company/engine/__init__.py Removes budget error re-exports from engine package exports.
tests/unit/providers/resilience/test_retry.py Updates imports to new RetryConfig location.
tests/unit/providers/resilience/test_rate_limiter.py Updates imports to new RateLimiterConfig location.
tests/unit/providers/resilience/test_config.py Updates imports to new resilience config module.
tests/unit/providers/resilience/conftest.py Updates imports to new resilience config module.
tests/unit/providers/drivers/conftest.py Splits config imports to avoid pulling resilience configs from config.schema.
tests/integration/providers/test_retry_integration.py Splits config imports to use new resilience config module.
tests/integration/providers/conftest.py Updates streaming helper types to ModelResponseStream.
tests/unit/config/conftest.py Updates imports for resilience configs.
tests/unit/engine/test_errors.py Updates assertions to reflect budget errors no longer subclass EngineError.
tests/unit/engine/test_agent_engine_budget.py Adds quota exhaustion to parametrized budget stop behavior.
tests/unit/budget/test_errors.py New unit tests covering budget error hierarchy and behavior.
tests/unit/budget/test_enforcer_quota.py Updates quota exhaustion error import to new module.
tests/unit/budget/test_enforcer.py Updates budget error imports to new module.
DESIGN_SPEC.md Updates project structure docs for new/removed modules.
CLAUDE.md Updates package structure notes for budget/ and core/ additions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is an excellent refactoring pull request that successfully resolves circular import issues by moving shared configuration and error classes to more appropriate, central locations. The changes are well-structured, consistent across the codebase, and thoroughly tested. The documentation has also been updated to reflect the new file structure. The litellm dependency bump and the fix for the release tag format are also valuable improvements. I have one minor suggestion to improve the accuracy of a docstring in the new budget/errors.py file.

Comment on lines +15 to +16
when pre-flight budget checks fail (monthly hard stop or daily
limit exceeded).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The docstring for BudgetExhaustedError mentions it's raised for "monthly hard stop or daily limit exceeded". Since QuotaExhaustedError is now also a subclass and is raised in the same context, it would be more accurate to make this description more general or include quota exhaustion as an example. This would improve clarity for future developers.

Suggested change
when pre-flight budget checks fail (monthly hard stop or daily
limit exceeded).
when pre-flight budget checks fail (e.g., monthly hard stop, daily
limit, or provider quota exceeded).

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 10, 2026

Greptile Summary

This PR resolves circular import chains in the ai_company package by establishing clean dependency-graph layers: a new core/resilience_config.py leaf carries RetryConfig/RateLimiterConfig (previously living in config.schema, which created cycles with providers.resilience), and a new budget/errors.py leaf carries the three budget exception classes (previously in engine/errors.py, which forced engine and budget to mutually depend on each other). Routing modules break their remaining runtime import of config.schema by placing it behind TYPE_CHECKING guards — valid because the project targets Python ≥ 3.14, where PEP 649 makes annotations lazily evaluated by default. The PR also bumps litellm from 1.82.0 → 1.82.1, fixes the streaming test fixtures to use the new ModelResponseStream type, and corrects the release-please tag format so Docker CI's v* trigger fires correctly.

Key changes:

  • New core/resilience_config.py: RetryConfig + RateLimiterConfig extracted into a shared leaf module imported by both config.schema and providers.resilience
  • New budget/errors.py: Budget exceptions now live in a zero-dependency leaf; budget/__init__.py re-exports them; engine/__init__.py drops them from its public API
  • providers/resilience/config.py deleted: The re-export shim is gone; all consumers updated to import from core.resilience_config
  • TYPE_CHECKING guards in routing: resolver.py, router.py, strategies.py, _strategy_helpers.py all move config.schema imports behind TYPE_CHECKING to eliminate the runtime circular edge
  • litellm 1.82.1: Integration test conftest updated to construct streaming chunks with ModelResponseStream instead of ModelResponse; stream=True attribute removed (handled by the new type)
  • Release tag format: include-component-in-tag: false produces vX.Y.Z tags, matching the Docker CI v* glob
  • New test: tests/unit/budget/test_errors.py covers the full budget error hierarchy including cross-hierarchy isolation from EngineError

Confidence Score: 5/5

  • This PR is safe to merge — it is a well-scoped structural refactor with comprehensive test coverage and no logic changes.
  • All circular import fixes follow established Python patterns (leaf modules + TYPE_CHECKING guards). The Python 3.14 requirement makes the annotation-only TYPE_CHECKING pattern safe without from __future__ import annotations. Tests (6653 passed), mypy (848 files, no issues), and ruff all pass. The one minor note is an overly-broad type: ignore[attr-defined] in the integration test conftest, but it doesn't affect correctness.
  • No files require special attention. The tests/integration/providers/conftest.py has a minor style suggestion to narrow the type: ignore scope, but it is not blocking.

Important Files Changed

Filename Overview
src/ai_company/budget/errors.py New leaf module for budget error hierarchy. Clean, no intra-project imports — correctly breaks the circular dependency chain between engine and budget.
src/ai_company/core/resilience_config.py New core/ home for RetryConfig and RateLimiterConfig. Pydantic models are well-validated (frozen, no inf/nan, cross-field validator). Dependency on observability is the only intra-project import, avoiding the previous circular cycle with config.schema ↔ providers.resilience.
src/ai_company/providers/routing/strategies.py RoutingConfig moved behind TYPE_CHECKING; valid because requires-python = ">=3.14" enables PEP 649 lazy annotations by default. Strategy logic unchanged; # noqa: TC001/TC003 suppressions correctly retain runtime-needed imports (ModelResolver, Mapping).
src/ai_company/engine/errors.py Budget error classes correctly removed; only engine-specific errors remain. Clean separation of concerns.
src/ai_company/budget/init.py Budget errors correctly added to public exports (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError all present in __all__).
tests/integration/providers/conftest.py Streaming helpers updated from ModelResponse to ModelResponseStream for litellm 1.82.1 compatibility. type: ignore[attr-defined] is overly broad — suppresses potential future type errors across the entire multi-line import block, not just for ModelResponseStream.
tests/unit/budget/test_errors.py Solid new test suite for the budget error hierarchy. Tests cover: base class inheritance, subclass detection, message preservation, cross-hierarchy isolation (not EngineError), and polymorphic catching. Good parametrize usage.
.github/release-please-config.json include-component-in-tag: false correctly aligns release tag format (vX.Y.Z) with Docker CI v* glob trigger.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph core["core/ (shared leaf)"]
        RC["resilience_config.py\nRetryConfig\nRateLimiterConfig"]
    end

    subgraph budget["budget/ (leaf)"]
        BE["errors.py\nBudgetExhaustedError\nDailyLimitExceededError\nQuotaExhaustedError"]
        ENF["enforcer.py\nBudgetEnforcer"]
    end

    subgraph config["config/"]
        CS["schema.py\nRootConfig\nProviderConfig"]
    end

    subgraph providers["providers/"]
        PR["resilience/\nRetryHandler\nRateLimiter"]
        RT["routing/\nModelRouter\nstrategies.py\nresolver.py\n_strategy_helpers.py"]
    end

    subgraph engine["engine/"]
        AE["agent_engine.py\nAgentEngine"]
        EE["errors.py\nEngineError\n(no budget errors)"]
    end

    RC --> CS
    RC --> PR
    BE --> ENF
    BE --> AE
    CS -.->|"TYPE_CHECKING only"| RT
    ENF --> AE

    style core fill:#e8f5e9,stroke:#4caf50
    style budget fill:#e3f2fd,stroke:#2196f3
    style config fill:#fff3e0,stroke:#ff9800
    style providers fill:#f3e5f5,stroke:#9c27b0
    style engine fill:#fce4ec,stroke:#e91e63
Loading

Last reviewed commit: a7a5404

Copy link
Copy Markdown

@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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ai_company/budget/__init__.py`:
- Around line 41-45: Restore the deprecated aliases so existing imports keep
working: re-add the old re-exports that previously lived under ai_company.engine
and ai_company.engine.errors (i.e., ensure BudgetExhaustedError,
DailyLimitExceededError, QuotaExhaustedError are still importable from the old
paths) and mark them as deprecated (emit a DeprecationWarning when imported) so
consumers get one release to migrate; apply the same re-export+warning pattern
for the other affected symbols referenced in lines 108-145.

In `@src/ai_company/providers/resilience/__init__.py`:
- Around line 7-15: The package removed deprecated exports `RetryConfig` and
`RateLimiterConfig`, breaking callers that import them from the top-level;
restore compatibility by re-exporting those deprecated names: import
`RetryConfig` from `retry` and `RateLimiterConfig` from `rate_limiter` (or
create thin aliases if the originals moved/renamed), add them to the `__all__`
list alongside `RateLimiter`, `RetryExhaustedError`, and `RetryHandler`, and
include a short deprecation comment noting they will be removed in the next
release so callers can migrate.

In `@tests/unit/budget/test_errors.py`:
- Around line 21-29: Replace the two nearly identical tests with a single
parametrized pytest test: create one test (e.g.,
test_subtypes_are_budget_exhausted) annotated with `@pytest.mark.parametrize` over
the subclass types [DailyLimitExceededError, QuotaExhaustedError], and inside
assert both issubclass(sub, BudgetExhaustedError) and isinstance(sub("msg"),
BudgetExhaustedError); update or fold the similar repeated assertions later in
the file into the same pattern to keep tests DRY.

In `@tests/unit/providers/resilience/test_config.py`:
- Line 6: The removal of the old module path breaks downstream imports for
RetryConfig and RateLimiterConfig; restore a compatibility shim by re-adding
ai_company.providers.resilience.config that re-exports RateLimiterConfig and
RetryConfig from ai_company.core.resilience_config (i.e., export the same
symbols from the new module path), or if you prefer a breaking change, update
release notes to mark this as breaking—implement the shim so imports like from
ai_company.providers.resilience.config import RetryConfig continue to work
during the next release cycle.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87a4b88c-ac3b-446f-a8fb-a5fcbb7e8162

📥 Commits

Reviewing files that changed from the base of the PR and between b9907e8 and 17eb317.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (34)
  • .github/release-please-config.json
  • CLAUDE.md
  • DESIGN_SPEC.md
  • pyproject.toml
  • src/ai_company/budget/__init__.py
  • src/ai_company/budget/enforcer.py
  • src/ai_company/budget/errors.py
  • src/ai_company/config/schema.py
  • src/ai_company/core/resilience_config.py
  • src/ai_company/engine/__init__.py
  • src/ai_company/engine/agent_engine.py
  • src/ai_company/engine/errors.py
  • src/ai_company/providers/__init__.py
  • src/ai_company/providers/resilience/__init__.py
  • src/ai_company/providers/resilience/config.py
  • src/ai_company/providers/resilience/rate_limiter.py
  • src/ai_company/providers/resilience/retry.py
  • src/ai_company/providers/routing/_strategy_helpers.py
  • src/ai_company/providers/routing/resolver.py
  • src/ai_company/providers/routing/router.py
  • src/ai_company/providers/routing/strategies.py
  • tests/integration/providers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/budget/test_enforcer.py
  • tests/unit/budget/test_enforcer_quota.py
  • tests/unit/budget/test_errors.py
  • tests/unit/config/conftest.py
  • tests/unit/engine/test_agent_engine_budget.py
  • tests/unit/engine/test_errors.py
  • tests/unit/providers/drivers/conftest.py
  • tests/unit/providers/resilience/conftest.py
  • tests/unit/providers/resilience/test_config.py
  • tests/unit/providers/resilience/test_rate_limiter.py
  • tests/unit/providers/resilience/test_retry.py
💤 Files with no reviewable changes (4)
  • src/ai_company/providers/init.py
  • src/ai_company/providers/resilience/config.py
  • src/ai_company/engine/init.py
  • src/ai_company/engine/errors.py
📜 Review details
⏰ 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). (2)
  • GitHub Check: Agent
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Python 3.14+ with PEP 649 native lazy annotations
Do NOT use from __future__ import annotations — Python 3.14 has PEP 649
Use PEP 758 except syntax: except A, B: (no parentheses) — ruff enforces this on Python 3.14
Include type hints on all public functions; enforce mypy strict mode
Use Google style docstrings, required on all public classes and functions (enforced by ruff D rules)
Create new objects instead of mutating existing ones — practice immutability
For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement
For dict/list fields in frozen Pydantic models, rely on frozen=True for field reassignment prevention and copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model
Use Pydantic v2 (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing + validating redundant fields. Use NotBlankStr (from core.types) for all identifier/name fields
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task. Existing code is being migrated incrementally
Limit line length to 88 characters (ruff enforced)
Keep functions under 50 lines; keep files under 800 lines
Handle errors explicitly; never silently swallow exceptions
Validate at system boundaries (user input, external APIs, config files)

Files:

  • src/ai_company/config/schema.py
  • src/ai_company/engine/agent_engine.py
  • src/ai_company/core/resilience_config.py
  • src/ai_company/budget/errors.py
  • tests/unit/budget/test_enforcer_quota.py
  • tests/unit/providers/resilience/conftest.py
  • tests/unit/budget/test_errors.py
  • tests/unit/engine/test_agent_engine_budget.py
  • tests/unit/config/conftest.py
  • src/ai_company/providers/resilience/__init__.py
  • tests/unit/providers/resilience/test_config.py
  • src/ai_company/providers/routing/_strategy_helpers.py
  • tests/unit/budget/test_enforcer.py
  • tests/unit/providers/resilience/test_rate_limiter.py
  • src/ai_company/budget/__init__.py
  • src/ai_company/providers/routing/resolver.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • tests/integration/providers/conftest.py
  • tests/unit/engine/test_errors.py
  • src/ai_company/budget/enforcer.py
  • src/ai_company/providers/resilience/retry.py
  • src/ai_company/providers/resilience/rate_limiter.py
  • src/ai_company/providers/routing/strategies.py
  • src/ai_company/providers/routing/router.py
src/ai_company/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/ai_company/**/*.py: Every module with business logic MUST have from ai_company.observability import get_logger then logger = get_logger(__name__)
Never use import logging / logging.getLogger() / print() in application code — use the observability module
Always use variable name logger (not _logger, not log)
Use event name constants from domain-specific modules under ai_company.observability.events (e.g. PROVIDER_CALL_START from events.provider). Import directly: from ai_company.observability.events.<domain> import EVENT_CONSTANT
Use structured logging format: always logger.info(EVENT, key=value) — never logger.info('msg %s', val)
Log all error paths at WARNING or ERROR with context before raising exceptions
Log all state transitions at INFO level
Use DEBUG level for object creation, internal flow, entry/exit of key functions
Pure data models, enums, and re-exports do NOT need logging
All provider calls must go through BaseCompletionProvider which applies retry + rate limiting automatically — never implement retry logic in driver subclasses or calling code
Set RetryConfig and RateLimiterConfig per-provider in ProviderConfig
Retryable errors (is_retryable=True) include: RateLimitError, ProviderTimeoutError, ProviderConnectionError, ProviderInternalError. Non-retryable errors raise immediately without retry
The rate limiter automatically respects RateLimitError.retry_after from providers — automatically pauses future requests
NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, example-medium-001, example-small-001, large/medium/small as aliases

Files:

  • src/ai_company/config/schema.py
  • src/ai_company/engine/agent_engine.py
  • src/ai_company/core/resilience_config.py
  • src/ai_company/budget/errors.py
  • src/ai_company/providers/resilience/__init__.py
  • src/ai_company/providers/routing/_strategy_helpers.py
  • src/ai_company/budget/__init__.py
  • src/ai_company/providers/routing/resolver.py
  • src/ai_company/budget/enforcer.py
  • src/ai_company/providers/resilience/retry.py
  • src/ai_company/providers/resilience/rate_limiter.py
  • src/ai_company/providers/routing/strategies.py
  • src/ai_company/providers/routing/router.py
pyproject.toml

📄 CodeRabbit inference engine (CLAUDE.md)

pyproject.toml: All dependency versions use == in pyproject.toml (pinned versions)
Organize dependencies into groups: test (pytest + plugins), dev (includes test + ruff, mypy, pre-commit, commitizen). Install with uv sync (installs everything; dev group is default)

Files:

  • pyproject.toml
src/ai_company/engine/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

RetryExhaustedError signals that all retries failed — the engine layer must catch this to trigger fallback chains

Files:

  • src/ai_company/engine/agent_engine.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Mark tests with @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, or @pytest.mark.slow
Prefer @pytest.mark.parametrize for testing similar cases in test files
Use test-provider, test-small-001, etc. as generic vendor names in test files

Files:

  • tests/unit/budget/test_enforcer_quota.py
  • tests/unit/providers/resilience/conftest.py
  • tests/unit/budget/test_errors.py
  • tests/unit/engine/test_agent_engine_budget.py
  • tests/unit/config/conftest.py
  • tests/unit/providers/resilience/test_config.py
  • tests/unit/budget/test_enforcer.py
  • tests/unit/providers/resilience/test_rate_limiter.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • tests/integration/providers/conftest.py
  • tests/unit/engine/test_errors.py
🧠 Learnings (10)
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`

Applied to files:

  • src/ai_company/config/schema.py
  • src/ai_company/core/resilience_config.py
  • tests/unit/providers/resilience/conftest.py
  • tests/unit/config/conftest.py
  • src/ai_company/providers/resilience/__init__.py
  • tests/unit/providers/resilience/test_config.py
  • tests/unit/providers/resilience/test_rate_limiter.py
  • src/ai_company/providers/routing/resolver.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • src/ai_company/providers/resilience/retry.py
  • src/ai_company/providers/resilience/rate_limiter.py
  • src/ai_company/providers/routing/router.py
  • DESIGN_SPEC.md
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Retryable errors (`is_retryable=True`) include: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry

Applied to files:

  • src/ai_company/config/schema.py
  • CLAUDE.md
  • src/ai_company/engine/agent_engine.py
  • src/ai_company/core/resilience_config.py
  • tests/unit/budget/test_enforcer_quota.py
  • tests/unit/providers/resilience/conftest.py
  • src/ai_company/providers/resilience/__init__.py
  • tests/unit/providers/resilience/test_config.py
  • src/ai_company/budget/__init__.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • tests/unit/engine/test_errors.py
  • src/ai_company/providers/resilience/retry.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : The rate limiter automatically respects `RateLimitError.retry_after` from providers — automatically pauses future requests

Applied to files:

  • src/ai_company/config/schema.py
  • src/ai_company/core/resilience_config.py
  • tests/unit/providers/resilience/conftest.py
  • src/ai_company/providers/resilience/__init__.py
  • tests/unit/providers/resilience/test_config.py
  • tests/unit/providers/resilience/test_rate_limiter.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • src/ai_company/providers/resilience/rate_limiter.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to pyproject.toml : All dependency versions use `==` in `pyproject.toml` (pinned versions)

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Use Release Please (Google) for automated release management. Merging release PR creates git tag (`vX.Y.Z`) + GitHub Release with changelog. Config in `.github/release-please-config.json` and `.github/.release-please-manifest.json`

Applied to files:

  • .github/release-please-config.json
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/engine/**/*.py : `RetryExhaustedError` signals that all retries failed — the engine layer must catch this to trigger fallback chains

Applied to files:

  • src/ai_company/engine/agent_engine.py
  • src/ai_company/budget/errors.py
  • tests/unit/providers/resilience/test_retry.py
  • tests/unit/engine/test_errors.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Log all error paths at WARNING or ERROR with context before raising exceptions

Applied to files:

  • src/ai_company/engine/agent_engine.py
  • src/ai_company/budget/__init__.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g. `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`

Applied to files:

  • src/ai_company/engine/agent_engine.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to src/ai_company/**/*.py : All provider calls must go through `BaseCompletionProvider` which applies retry + rate limiting automatically — never implement retry logic in driver subclasses or calling code

Applied to files:

  • tests/unit/providers/resilience/conftest.py
  • tests/unit/providers/resilience/test_config.py
  • tests/unit/providers/drivers/conftest.py
  • tests/integration/providers/test_retry_integration.py
  • tests/unit/providers/resilience/test_retry.py
  • src/ai_company/providers/resilience/retry.py
📚 Learning: 2026-03-10T22:52:37.949Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T22:52:37.949Z
Learning: Applies to **/*.py : For non-Pydantic internal collections (registries, BaseTool), use `copy.deepcopy()` at construction + `MappingProxyType` wrapping for read-only enforcement

Applied to files:

  • src/ai_company/providers/routing/strategies.py
🧬 Code graph analysis (23)
src/ai_company/config/schema.py (1)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
src/ai_company/engine/agent_engine.py (2)
src/ai_company/budget/errors.py (1)
  • BudgetExhaustedError (9-20)
src/ai_company/engine/errors.py (1)
  • ExecutionStateError (12-13)
src/ai_company/core/resilience_config.py (1)
src/ai_company/observability/_logger.py (1)
  • get_logger (8-28)
tests/unit/budget/test_enforcer_quota.py (1)
src/ai_company/budget/errors.py (1)
  • QuotaExhaustedError (27-32)
tests/unit/providers/resilience/conftest.py (1)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
tests/unit/budget/test_errors.py (2)
src/ai_company/budget/errors.py (3)
  • BudgetExhaustedError (9-20)
  • DailyLimitExceededError (23-24)
  • QuotaExhaustedError (27-32)
src/ai_company/engine/errors.py (1)
  • EngineError (4-5)
tests/unit/config/conftest.py (1)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
tests/unit/providers/resilience/test_config.py (1)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
src/ai_company/providers/routing/_strategy_helpers.py (1)
src/ai_company/config/schema.py (1)
  • RoutingRuleConfig (157-202)
tests/unit/budget/test_enforcer.py (1)
src/ai_company/budget/errors.py (2)
  • BudgetExhaustedError (9-20)
  • DailyLimitExceededError (23-24)
tests/unit/providers/resilience/test_rate_limiter.py (1)
src/ai_company/core/resilience_config.py (1)
  • RateLimiterConfig (76-97)
src/ai_company/budget/__init__.py (1)
src/ai_company/budget/errors.py (3)
  • BudgetExhaustedError (9-20)
  • DailyLimitExceededError (23-24)
  • QuotaExhaustedError (27-32)
src/ai_company/providers/routing/resolver.py (1)
src/ai_company/config/schema.py (1)
  • ProviderConfig (81-154)
tests/unit/providers/drivers/conftest.py (2)
src/ai_company/config/schema.py (2)
  • ProviderConfig (81-154)
  • ProviderModelConfig (39-78)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
tests/integration/providers/test_retry_integration.py (2)
src/ai_company/config/schema.py (2)
  • ProviderConfig (81-154)
  • ProviderModelConfig (39-78)
src/ai_company/core/resilience_config.py (2)
  • RateLimiterConfig (76-97)
  • RetryConfig (17-73)
tests/unit/providers/resilience/test_retry.py (1)
src/ai_company/core/resilience_config.py (1)
  • RetryConfig (17-73)
tests/integration/providers/conftest.py (2)
src/ai_company/config/schema.py (2)
  • ProviderConfig (81-154)
  • ProviderModelConfig (39-78)
src/ai_company/core/resilience_config.py (1)
  • RetryConfig (17-73)
tests/unit/engine/test_errors.py (2)
src/ai_company/budget/errors.py (1)
  • BudgetExhaustedError (9-20)
src/ai_company/engine/errors.py (1)
  • EngineError (4-5)
src/ai_company/budget/enforcer.py (2)
src/ai_company/budget/errors.py (3)
  • BudgetExhaustedError (9-20)
  • DailyLimitExceededError (23-24)
  • QuotaExhaustedError (27-32)
src/ai_company/budget/quota.py (1)
  • QuotaCheckResult (285-314)
src/ai_company/providers/resilience/retry.py (1)
src/ai_company/core/resilience_config.py (1)
  • RetryConfig (17-73)
src/ai_company/providers/resilience/rate_limiter.py (1)
src/ai_company/core/resilience_config.py (1)
  • RateLimiterConfig (76-97)
src/ai_company/providers/routing/strategies.py (1)
src/ai_company/config/schema.py (1)
  • RoutingConfig (205-227)
src/ai_company/providers/routing/router.py (1)
src/ai_company/config/schema.py (2)
  • ProviderConfig (81-154)
  • RoutingConfig (205-227)
🔇 Additional comments (22)
.github/release-please-config.json (1)

7-7: No action needed—tag format change is safe for this repository.

The "include-component-in-tag": false setting is correct for plain vX.Y.Z tag format. Since this repository has no existing tags, there is no risk of historical tag conflicts. The configuration is ready for the first Release Please-managed release.

			> Likely an incorrect or invalid review comment.
pyproject.toml (1)

20-20: litellm version 1.82.1 is valid and secure.

Version 1.82.1 exists on PyPI as the latest release and has no known CVEs or security advisories. All dependencies follow the pinning guideline with ==, and the dependency groups (test, dev) are properly organized.

src/ai_company/core/resilience_config.py (1)

17-97: Good extraction target for the shared resilience models.

Moving these frozen config models into core removes the schema/provider cycle without duplicating validation logic, and the validator still logs invalid config with useful context before failing.

src/ai_company/config/schema.py (1)

21-21: Nice compatibility bridge.

Importing these types into config.schema keeps existing from ai_company.config.schema import RetryConfig call sites working while the canonical definitions move to core.

tests/integration/providers/conftest.py (1)

16-22: Streaming fixtures now match the updated LiteLLM surface.

Switching the chunk builders and async_iter_chunks() to ModelResponseStream keeps these integration helpers aligned with the stream-specific types used by the updated provider tests.

Also applies to: 170-259

src/ai_company/providers/routing/resolver.py (1)

10-24: TYPE_CHECKING is the right fix for this import cycle.

This keeps the from_config() type information intact without reintroducing a runtime dependency on ai_company.config.schema.

tests/unit/engine/test_agent_engine_budget.py (1)

53-60: Nice coverage addition for quota preflight failures.

Including QuotaExhaustedError here closes the gap introduced by the new budget-domain exception and keeps the engine contract pinned to TerminationReason.BUDGET_EXHAUSTED.

tests/unit/providers/resilience/conftest.py (1)

5-5: LGTM!

Import path correctly updated to the new canonical location ai_company.core.resilience_config. This aligns with the PR's refactoring of resilience configuration models to the core module.

src/ai_company/engine/agent_engine.py (2)

12-12: LGTM!

Import path correctly updated to ai_company.budget.errors for BudgetExhaustedError. This properly reflects the new module hierarchy where budget-related errors are now in the budget package.


22-22: Correct separation of concerns.

ExecutionStateError remains imported from ai_company.engine.errors as expected—it's an engine-layer error, not a budget error. The distinction between engine errors and budget errors is now properly reflected in the import structure.

tests/unit/budget/test_enforcer_quota.py (1)

14-14: LGTM!

Import path correctly updated to ai_company.budget.errors for QuotaExhaustedError. Test markers and generic provider names ("test-provider") are properly used per coding guidelines.

tests/unit/engine/test_errors.py (2)

5-5: LGTM!

Import path correctly updated to reflect the new module location for BudgetExhaustedError.


37-41: Test logic correctly updated for the new error hierarchy.

The test now properly verifies that BudgetExhaustedError is not a subclass of EngineError and inherits directly from Exception. This accurately reflects the architectural decision to decouple budget errors from the engine error hierarchy.

src/ai_company/providers/routing/strategies.py (1)

10-10: LGTM!

TYPE_CHECKING guard correctly added for RoutingConfig. Since RoutingConfig is only used in type annotations (method signatures), deferring the import to type-checking time avoids circular import issues at runtime. This works correctly with Python 3.14's PEP 649 lazy annotation evaluation.

Also applies to: 37-39

tests/unit/providers/resilience/test_rate_limiter.py (1)

10-10: LGTM!

Import path correctly updated to ai_company.core.resilience_config for RateLimiterConfig. This aligns with the PR's refactoring of resilience configuration models to the core module.

src/ai_company/providers/routing/_strategy_helpers.py (1)

7-8: LGTM!

TYPE_CHECKING guard correctly added for RoutingConfig and RoutingRuleConfig. Both types are used exclusively in function signatures (type annotations), so deferring imports to type-checking time properly resolves circular import issues without affecting runtime behavior.

Also applies to: 22-24

src/ai_company/providers/routing/router.py (1)

7-8: LGTM!

TYPE_CHECKING guard correctly added for ProviderConfig and RoutingConfig. Both types are used only in the __init__ signature annotations, so deferring imports to type-checking time properly resolves circular import issues. This completes the routing module's circular import fixes alongside strategies.py and _strategy_helpers.py.

Also applies to: 22-24

tests/unit/config/conftest.py (1)

23-23: Canonical resilience-config import looks right.

Pointing the fixtures at ai_company.core.resilience_config keeps the tests aligned with the new source of truth for provider retry and rate-limit settings.

tests/unit/providers/drivers/conftest.py (1)

8-9: Import split matches the new ownership boundary.

Keeping ProviderConfig in ai_company.config.schema and moving RetryConfig / RateLimiterConfig to ai_company.core.resilience_config makes the test fixture mirror the runtime model layout.

tests/unit/budget/test_errors.py (2)

11-15: Test markers are set up correctly.

The module timeout plus class-level @pytest.mark.unit keeps this file aligned with the suite’s test classification conventions.


31-42: Good coverage for the decoupling contract.

These assertions lock in the important behavioral change: budget exhaustion is now independent from EngineError, and the base exception still preserves its message payload.

src/ai_company/budget/errors.py (1)

1-32: Clean leaf-module split for the budget exceptions.

Defining this hierarchy in ai_company.budget.errors with no intra-project imports is a solid way to break the previous engine↔budget dependency cycle while keeping the subtype relationships explicit.

Comment on lines +41 to +45
from ai_company.budget.errors import (
BudgetExhaustedError,
DailyLimitExceededError,
QuotaExhaustedError,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Removing the old budget-error aliases is another patch-level API break.

These new exports are fine as the canonical budget namespace, but the PR summary also removes the previous ai_company.engine / ai_company.engine.errors re-exports. Existing consumers importing these exceptions from the old paths will start failing immediately on a fix: release. Keep deprecated aliases for one release, or ship this as an explicit breaking change.

Also applies to: 108-145

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ai_company/budget/__init__.py` around lines 41 - 45, Restore the
deprecated aliases so existing imports keep working: re-add the old re-exports
that previously lived under ai_company.engine and ai_company.engine.errors
(i.e., ensure BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError
are still importable from the old paths) and mark them as deprecated (emit a
DeprecationWarning when imported) so consumers get one release to migrate; apply
the same re-export+warning pattern for the other affected symbols referenced in
lines 108-145.

Comment on lines 7 to 15
from .errors import RetryExhaustedError
from .rate_limiter import RateLimiter
from .retry import RetryHandler

__all__ = [
"RateLimiter",
"RateLimiterConfig",
"RetryConfig",
"RetryExhaustedError",
"RetryHandler",
]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep deprecated config re-exports for one release cycle.

Removing RetryConfig and RateLimiterConfig from this package namespace will break any existing from ai_company.providers.resilience import ... callers immediately. Either keep deprecated aliases here for compatibility, or treat this as an explicit breaking release with migration notes.

♻️ Compatibility-preserving diff
+from ai_company.core.resilience_config import RateLimiterConfig, RetryConfig
 from .errors import RetryExhaustedError
 from .rate_limiter import RateLimiter
 from .retry import RetryHandler

 __all__ = [
     "RateLimiter",
+    "RateLimiterConfig",
     "RetryExhaustedError",
+    "RetryConfig",
     "RetryHandler",
 ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ai_company/providers/resilience/__init__.py` around lines 7 - 15, The
package removed deprecated exports `RetryConfig` and `RateLimiterConfig`,
breaking callers that import them from the top-level; restore compatibility by
re-exporting those deprecated names: import `RetryConfig` from `retry` and
`RateLimiterConfig` from `rate_limiter` (or create thin aliases if the originals
moved/renamed), add them to the `__all__` list alongside `RateLimiter`,
`RetryExhaustedError`, and `RetryHandler`, and include a short deprecation
comment noting they will be removed in the next release so callers can migrate.

from pydantic import ValidationError

from ai_company.providers.resilience.config import RateLimiterConfig, RetryConfig
from ai_company.core.resilience_config import RateLimiterConfig, RetryConfig
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Deleting the old resilience-config shim is a breaking API change.

This import update is fine internally, but the PR summary says ai_company.providers.resilience.config was removed rather than kept as a deprecation shim. Any downstream code still importing RetryConfig or RateLimiterConfig from the old path will fail on the next patch release. Keep the old module re-exporting the new symbols for one release, or mark the release as breaking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/providers/resilience/test_config.py` at line 6, The removal of the
old module path breaks downstream imports for RetryConfig and RateLimiterConfig;
restore a compatibility shim by re-adding ai_company.providers.resilience.config
that re-exports RateLimiterConfig and RetryConfig from
ai_company.core.resilience_config (i.e., export the same symbols from the new
module path), or if you prefer a breaking change, update release notes to mark
this as breaking—implement the shim so imports like from
ai_company.providers.resilience.config import RetryConfig continue to work
during the next release cycle.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is a well-executed pull request that successfully resolves circular dependencies through thoughtful refactoring. The updates to dependencies, documentation, and release configuration are also appreciated and correctly implemented. One critical issue was identified outside the scope of this diff: src/ai_company/budget/enforcer.py contains Python 2-style except syntax on lines 133 and 302 (e.g., except MemoryError, RecursionError:). This will cause a SyntaxError in Python 3. The correct syntax is except (MemoryError, RecursionError):. While I cannot comment directly on these lines as they are not part of the changes in this PR, this is a critical fix that is required for the code to be runnable.

- BudgetExhaustedError docstring: mention quota exhaustion, fix
  "converted into" → "used to build AgentRunResult"
- QuotaExhaustedError docstring: replace "tracked in M7" with
  "not yet implemented" (durable phrasing)
- Parametrize repeated subtype tests per project conventions
- Remove duplicate security.py entry in DESIGN_SPEC.md events tree
@Aureliolo Aureliolo merged commit a6659b5 into main Mar 10, 2026
12 checks passed
@Aureliolo Aureliolo deleted the fix/release-and-litellm-streaming branch March 10, 2026 23:11
Comment on lines 13 to 19
from litellm.types.utils import ( # type: ignore[attr-defined]
ChatCompletionToolCallChunk,
Delta,
ModelResponseStream,
StreamingChoices,
Usage,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Broad type: ignore suppresses all type errors on the import

The # type: ignore[attr-defined] is placed on the entire multi-line import block. This means any future missing or renamed symbol in the same import block will silently pass type checking without any indication. A narrower suppression (or a per-symbol comment) would be safer. If ModelResponseStream is the only symbol not yet in litellm's stubs, consider isolating it:

Suggested change
from litellm.types.utils import ( # type: ignore[attr-defined]
ChatCompletionToolCallChunk,
Delta,
ModelResponseStream,
StreamingChoices,
Usage,
)
from litellm.types.utils import (
ChatCompletionToolCallChunk,
Delta,
ModelResponseStream, # type: ignore[attr-defined] # not yet in litellm stubs
StreamingChoices,
Usage,
)
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/integration/providers/conftest.py
Line: 13-19

Comment:
**Broad `type: ignore` suppresses all type errors on the import**

The `# type: ignore[attr-defined]` is placed on the entire multi-line import block. This means any *future* missing or renamed symbol in the same import block will silently pass type checking without any indication. A narrower suppression (or a per-symbol comment) would be safer. If `ModelResponseStream` is the only symbol not yet in litellm's stubs, consider isolating it:

```suggestion
from litellm.types.utils import (
    ChatCompletionToolCallChunk,
    Delta,
    ModelResponseStream,  # type: ignore[attr-defined]  # not yet in litellm stubs
    StreamingChoices,
    Usage,
)
```

How can I resolve this? If you propose a fix, please make it concise.

Aureliolo added a commit that referenced this pull request Mar 11, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.1.0](v0.0.0...v0.1.0)
(2026-03-11)


### Features

* add autonomy levels and approval timeout policies
([#42](#42),
[#126](#126))
([#197](#197))
([eecc25a](eecc25a))
* add CFO cost optimization service with anomaly detection, reports, and
approval decisions
([#186](#186))
([a7fa00b](a7fa00b))
* add code quality toolchain (ruff, mypy, pre-commit, dependabot)
([#63](#63))
([36681a8](36681a8))
* add configurable cost tiers and subscription/quota-aware tracking
([#67](#67))
([#185](#185))
([9baedfa](9baedfa))
* add container packaging, Docker Compose, and CI pipeline
([#269](#269))
([435bdfe](435bdfe)),
closes [#267](#267)
* add coordination error taxonomy classification pipeline
([#146](#146))
([#181](#181))
([70c7480](70c7480))
* add cost-optimized, hierarchical, and auction assignment strategies
([#175](#175))
([ce924fa](ce924fa)),
closes [#173](#173)
* add design specification, license, and project setup
([8669a09](8669a09))
* add env var substitution and config file auto-discovery
([#77](#77))
([7f53832](7f53832))
* add FastestStrategy routing + vendor-agnostic cleanup
([#140](#140))
([09619cb](09619cb)),
closes [#139](#139)
* add HR engine and performance tracking
([#45](#45),
[#47](#47))
([#193](#193))
([2d091ea](2d091ea))
* add issue auto-search and resolution verification to PR review skill
([#119](#119))
([deecc39](deecc39))
* add mandatory JWT + API key authentication
([#256](#256))
([c279cfe](c279cfe))
* add memory retrieval, ranking, and context injection pipeline
([#41](#41))
([873b0aa](873b0aa))
* add pluggable MemoryBackend protocol with models, config, and events
([#180](#180))
([46cfdd4](46cfdd4))
* add pluggable MemoryBackend protocol with models, config, and events
([#32](#32))
([46cfdd4](46cfdd4))
* add pluggable output scan response policies
([#263](#263))
([b9907e8](b9907e8))
* add pluggable PersistenceBackend protocol with SQLite implementation
([#36](#36))
([f753779](f753779))
* add progressive trust and promotion/demotion subsystems
([#43](#43),
[#49](#49))
([3a87c08](3a87c08))
* add retry handler, rate limiter, and provider resilience
([#100](#100))
([b890545](b890545))
* add SecOps security agent with rule engine, audit log, and ToolInvoker
integration ([#40](#40))
([83b7b6c](83b7b6c))
* add shared org memory and memory consolidation/archival
([#125](#125),
[#48](#48))
([4a0832b](4a0832b))
* design unified provider interface
([#86](#86))
([3e23d64](3e23d64))
* expand template presets, rosters, and add inheritance
([#80](#80),
[#81](#81),
[#84](#84))
([15a9134](15a9134))
* implement agent runtime state vs immutable config split
([#115](#115))
([4cb1ca5](4cb1ca5))
* implement AgentEngine core orchestrator
([#11](#11))
([#143](#143))
([f2eb73a](f2eb73a))
* implement AuditRepository for security audit log persistence
([#279](#279))
([94bc29f](94bc29f))
* implement basic tool system (registry, invocation, results)
([#15](#15))
([c51068b](c51068b))
* implement built-in file system tools
([#18](#18))
([325ef98](325ef98))
* implement communication foundation — message bus, dispatcher, and
messenger ([#157](#157))
([8e71bfd](8e71bfd))
* implement company template system with 7 built-in presets
([#85](#85))
([cbf1496](cbf1496))
* implement conflict resolution protocol
([#122](#122))
([#166](#166))
([e03f9f2](e03f9f2))
* implement core entity and role system models
([#69](#69))
([acf9801](acf9801))
* implement crash recovery with fail-and-reassign strategy
([#149](#149))
([e6e91ed](e6e91ed))
* implement engine extensions — Plan-and-Execute loop and call
categorization
([#134](#134),
[#135](#135))
([#159](#159))
([9b2699f](9b2699f))
* implement enterprise logging system with structlog
([#73](#73))
([2f787e5](2f787e5))
* implement graceful shutdown with cooperative timeout strategy
([#130](#130))
([6592515](6592515))
* implement hierarchical delegation and loop prevention
([#12](#12),
[#17](#17))
([6be60b6](6be60b6))
* implement LiteLLM driver and provider registry
([#88](#88))
([ae3f18b](ae3f18b)),
closes [#4](#4)
* implement LLM decomposition strategy and workspace isolation
([#174](#174))
([aa0eefe](aa0eefe))
* implement meeting protocol system
([#123](#123))
([ee7caca](ee7caca))
* implement message and communication domain models
([#74](#74))
([560a5d2](560a5d2))
* implement model routing engine
([#99](#99))
([d3c250b](d3c250b))
* implement parallel agent execution
([#22](#22))
([#161](#161))
([65940b3](65940b3))
* implement per-call cost tracking service
([#7](#7))
([#102](#102))
([c4f1f1c](c4f1f1c))
* implement personality injection and system prompt construction
([#105](#105))
([934dd85](934dd85))
* implement single-task execution lifecycle
([#21](#21))
([#144](#144))
([c7e64e4](c7e64e4))
* implement subprocess sandbox for tool execution isolation
([#131](#131))
([#153](#153))
([3c8394e](3c8394e))
* implement task assignment subsystem with pluggable strategies
([#172](#172))
([c7f1b26](c7f1b26)),
closes [#26](#26)
[#30](#30)
* implement task decomposition and routing engine
([#14](#14))
([9c7fb52](9c7fb52))
* implement Task, Project, Artifact, Budget, and Cost domain models
([#71](#71))
([81eabf1](81eabf1))
* implement tool permission checking
([#16](#16))
([833c190](833c190))
* implement YAML config loader with Pydantic validation
([#59](#59))
([ff3a2ba](ff3a2ba))
* implement YAML config loader with Pydantic validation
([#75](#75))
([ff3a2ba](ff3a2ba))
* initialize project with uv, hatchling, and src layout
([39005f9](39005f9))
* initialize project with uv, hatchling, and src layout
([#62](#62))
([39005f9](39005f9))
* Litestar REST API, WebSocket feed, and approval queue (M6)
([#189](#189))
([29fcd08](29fcd08))
* make TokenUsage.total_tokens a computed field
([#118](#118))
([c0bab18](c0bab18)),
closes [#109](#109)
* parallel tool execution in ToolInvoker.invoke_all
([#137](#137))
([58517ee](58517ee))
* testing framework, CI pipeline, and M0 gap fixes
([#64](#64))
([f581749](f581749))
* wire all modules into observability system
([#97](#97))
([f7a0617](f7a0617))


### Bug Fixes

* address Greptile post-merge review findings from PRs
[#170](https://github.com/Aureliolo/ai-company/issues/170)-[#175](https://github.com/Aureliolo/ai-company/issues/175)
([#176](#176))
([c5ca929](c5ca929))
* address post-merge review feedback from PRs
[#164](https://github.com/Aureliolo/ai-company/issues/164)-[#167](https://github.com/Aureliolo/ai-company/issues/167)
([#170](#170))
([3bf897a](3bf897a)),
closes [#169](#169)
* enforce strict mypy on test files
([#89](#89))
([aeeff8c](aeeff8c))
* harden Docker sandbox, MCP bridge, and code runner
([#50](#50),
[#53](#53))
([d5e1b6e](d5e1b6e))
* harden git tools security + code quality improvements
([#150](#150))
([000a325](000a325))
* harden subprocess cleanup, env filtering, and shutdown resilience
([#155](#155))
([d1fe1fb](d1fe1fb))
* incorporate post-merge feedback + pre-PR review fixes
([#164](#164))
([c02832a](c02832a))
* pre-PR review fixes for post-merge findings
([#183](#183))
([26b3108](26b3108))
* resolve circular imports, bump litellm, fix release tag format
([#286](#286))
([a6659b5](a6659b5))
* strengthen immutability for BaseTool schema and ToolInvoker boundaries
([#117](#117))
([7e5e861](7e5e861))


### Performance

* harden non-inferable principle implementation
([#195](#195))
([02b5f4e](02b5f4e)),
closes [#188](#188)


### Refactoring

* adopt NotBlankStr across all models
([#108](#108))
([#120](#120))
([ef89b90](ef89b90))
* extract _SpendingTotals base class from spending summary models
([#111](#111))
([2f39c1b](2f39c1b))
* harden BudgetEnforcer with error handling, validation extraction, and
review fixes
([#182](#182))
([c107bf9](c107bf9))
* harden personality profiles, department validation, and template
rendering ([#158](#158))
([10b2299](10b2299))
* pre-PR review improvements for ExecutionLoop + ReAct loop
([#124](#124))
([8dfb3c0](8dfb3c0))
* split events.py into per-domain event modules
([#136](#136))
([e9cba89](e9cba89))


### Documentation

* add ADR-001 memory layer evaluation and selection
([#178](#178))
([db3026f](db3026f)),
closes [#39](#39)
* add agent scaling research findings to DESIGN_SPEC
([#145](#145))
([57e487b](57e487b))
* add CLAUDE.md, contributing guide, and dev documentation
([#65](#65))
([55c1025](55c1025)),
closes [#54](#54)
* add crash recovery, sandboxing, analytics, and testing decisions
([#127](#127))
([5c11595](5c11595))
* address external review feedback with MVP scope and new protocols
([#128](#128))
([3b30b9a](3b30b9a))
* expand design spec with pluggable strategy protocols
([#121](#121))
([6832db6](6832db6))
* finalize 23 design decisions (ADR-002)
([#190](#190))
([8c39742](8c39742))
* update project docs for M2.5 conventions and add docs-consistency
review agent
([#114](#114))
([99766ee](99766ee))


### Tests

* add e2e single agent integration tests
([#24](#24))
([#156](#156))
([f566fb4](f566fb4))
* add provider adapter integration tests
([#90](#90))
([40a61f4](40a61f4))


### CI/CD

* add Release Please for automated versioning and GitHub Releases
([#278](#278))
([a488758](a488758))
* bump actions/checkout from 4 to 6
([#95](#95))
([1897247](1897247))
* bump actions/upload-artifact from 4 to 7
([#94](#94))
([27b1517](27b1517))
* bump anchore/scan-action from 6.5.1 to 7.3.2
([#271](#271))
([80a1c15](80a1c15))
* bump docker/build-push-action from 6.19.2 to 7.0.0
([#273](#273))
([dd0219e](dd0219e))
* bump docker/login-action from 3.7.0 to 4.0.0
([#272](#272))
([33d6238](33d6238))
* bump docker/metadata-action from 5.10.0 to 6.0.0
([#270](#270))
([baee04e](baee04e))
* bump docker/setup-buildx-action from 3.12.0 to 4.0.0
([#274](#274))
([5fc06f7](5fc06f7))
* bump sigstore/cosign-installer from 3.9.1 to 4.1.0
([#275](#275))
([29dd16c](29dd16c))
* harden CI/CD pipeline
([#92](#92))
([ce4693c](ce4693c))
* split vulnerability scans into critical-fail and high-warn tiers
([#277](#277))
([aba48af](aba48af))


### Maintenance

* add /worktree skill for parallel worktree management
([#171](#171))
([951e337](951e337))
* add design spec context loading to research-link skill
([8ef9685](8ef9685))
* add post-merge-cleanup skill
([#70](#70))
([f913705](f913705))
* add pre-pr-review skill and update CLAUDE.md
([#103](#103))
([92e9023](92e9023))
* add research-link skill and rename skill files to SKILL.md
([#101](#101))
([651c577](651c577))
* bump aiosqlite from 0.21.0 to 0.22.1
([#191](#191))
([3274a86](3274a86))
* bump pyyaml from 6.0.2 to 6.0.3 in the minor-and-patch group
([#96](#96))
([0338d0c](0338d0c))
* bump ruff from 0.15.4 to 0.15.5
([a49ee46](a49ee46))
* fix M0 audit items
([#66](#66))
([c7724b5](c7724b5))
* **main:** release ai-company 0.1.1
([#282](#282))
([2f4703d](2f4703d))
* pin setup-uv action to full SHA
([#281](#281))
([4448002](4448002))
* post-audit cleanup — PEP 758, loggers, bug fixes, refactoring, tests,
hookify rules
([#148](#148))
([c57a6a9](c57a6a9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: Aurelio <19254254+Aureliolo@users.noreply.github.com>
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