Skip to content

Add request metadata and cache-aware usage to UniResponse#111

Merged
JohnRichard4096 merged 6 commits into
mainfrom
feat-fix
Jul 4, 2026
Merged

Add request metadata and cache-aware usage to UniResponse#111
JohnRichard4096 merged 6 commits into
mainfrom
feat-fix

Conversation

@JohnRichard4096

@JohnRichard4096 JohnRichard4096 commented Jul 4, 2026

Copy link
Copy Markdown
Member

Summary by Sourcery

Add per-request metadata and stop reason tracking to unified responses, extend usage statistics with cache information, and update adapters, tests, and documentation accordingly.

New Features:

  • Introduce RequestMetadata model and attach it to UniResponse to expose request identifiers, model name, stop sequence, and standardized stop reasons.
  • Add STOP_REASON type and provider-to-unified stop reason mapping for OpenAI and Anthropic adapters.

Enhancements:

  • Extend UniResponseUsage with cache_creation and cache_hit fields and propagate Anthropic prompt caching metrics through adapters.
  • Normalize message payload handling in adapters via model_dump and improve streaming request metadata handling for OpenAI.
  • Clarify migration notes in documentation about removed compatibility endpoints and update examples for streaming chat usage and suspend APIs.
  • Add API reference entries and navigation links for the new RequestMetadata type and document the extended UniResponse and UniResponseUsage fields.

Build:

  • Bump project version from 0.11.0 to 0.11.1.

Tests:

  • Update adapter tests to cover new RequestMetadata fields, usage cache metrics, and mocked provider request IDs in OpenAI and Anthropic flows.

@sourcery-ai

sourcery-ai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Introduce RequestMetadata and enhanced usage tracking into core response types and adapters, wiring OpenAI and Anthropic adapters to populate metadata/usage consistently and updating docs and tests to reflect the new behavior and recent API deprecations/removals.

File-Level Changes

Change Details Files
Add RequestMetadata and STOP_REASON to unified response types and propagate metadata through OpenAI and Anthropic adapters.
  • Define STOP_REASON literal union and RequestMetadata model with request/stop information and extra-allow config.
  • Extend UniResponseUsage with cache_creation/cache_hit fields and extra-allow config.
  • Add metadata field to UniResponse with default RequestMetadata.
  • Map OpenAI finish_reason values to STOP_REASON via R2R_MAP and use RequestMetadata in streaming and non-streaming paths.
  • Construct RequestMetadata in Anthropic adapter for streaming and non-streaming responses and pass through UniResponse.metadata.
src/amrita_core/types/response.py
src/amrita_core/adapters/openai.py
src/amrita_core/adapters/anthropic.py
Normalize adapter inputs and improve OpenAI streaming handling.
  • Update model_dump helper to accept Iterable[BaseModel
Any] so non-dict items pass through.
  • Apply model_dump to messages in OpenAIAdapter.call_api and call_tools.
  • Add stop parameter to OpenAIAdapter.call_api and forward to OpenAI client.
  • Wrap OpenAI AsyncStream in async context manager, capture x-request-id header, and update metadata/model_name on finish_reason.
  • Adjust MockAsyncStream and related tests to support new response headers/context manager behavior and OpenAI _request_id usage.
  • Update documentation to reflect removed deprecated endpoints, new RequestMetadata/UniResponseUsage fields, and revised usage examples.
    • Remove deprecated init() and SuspendObjectStream docs and reindex sections in English and Chinese guides/API reference.
    • Document RequestMetadata class and link it from UniResponse docs; update VitePress config to list RequestMetadata instead of SuspendObjectStream.
    • Extend UniResponseUsage docs (EN/ZH) with cache_creation and cache_hit fields.
    • Update event, suspend, ModelAdapter, and dependency-intro docs to state that old amrita_core compatibility endpoints are removed in v0.10.x+ and recommend direct imports from amrita_sense.
    • Adjust agent-strategy examples to use chat.io_stream.get_response_generator() streaming pattern instead of full_response.
    docs/docs/guide/function-implementation.md
    docs/docs/zh/guide/function-implementation.md
    docs/docs/guide/api-reference/index.md
    docs/docs/guide/concepts/agent-strategy.md
    docs/docs/zh/guide/concepts/agent-strategy.md
    docs/docs/guide/concepts/event.md
    docs/docs/zh/guide/concepts/event.md
    docs/docs/guide/concepts/suspend.md
    docs/docs/zh/guide/concepts/suspend.md
    docs/docs/guide/api-reference/classes/ModelAdapter.md
    docs/docs/guide/api-reference/classes/UniResponseUsage.md
    docs/docs/zh/guide/api-reference/classes/UniResponseUsage.md
    docs/docs/guide/api-reference/classes/UniResponse.md
    docs/docs/zh/guide/api-reference/classes/UniResponse.md
    docs/docs/guide/dependency-intro.md
    docs/docs/.vitepress/config.mts
    docs/docs/guide/api-reference/classes/RequestMetadata.md
    docs/docs/zh/guide/api-reference/classes/RequestMetadata.md
    Bump package version for release.
    • Increment amrita_core version from 0.11.0 to 0.11.1 in pyproject.toml.
    • Update uv.lock to match new version (diff content not shown).
    pyproject.toml
    uv.lock

    Tips and commands

    Interacting with Sourcery

    • Trigger a new review: Comment @sourcery-ai review on the pull request.
    • Continue discussions: Reply directly to Sourcery's review comments.
    • Generate a GitHub issue from a review comment: Ask Sourcery to create an
      issue from a review comment by replying to it. You can also reply to a
      review comment with @sourcery-ai issue to create an issue from it.
    • Generate a pull request title: Write @sourcery-ai anywhere in the pull
      request title to generate a title at any time. You can also comment
      @sourcery-ai title on the pull request to (re-)generate the title at any time.
    • Generate a pull request summary: Write @sourcery-ai summary anywhere in
      the pull request body to generate a PR summary at any time exactly where you
      want it. You can also comment @sourcery-ai summary on the pull request to
      (re-)generate the summary at any time.
    • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
      request to (re-)generate the reviewer's guide at any time.
    • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
      pull request to resolve all Sourcery comments. Useful if you've already
      addressed all the comments and don't want to see them anymore.
    • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
      request to dismiss all existing Sourcery reviews. Especially useful if you
      want to start fresh with a new review - don't forget to comment
      @sourcery-ai review to trigger a new review!

    Customizing Your Experience

    Access your dashboard to:

    • Enable or disable review features such as the Sourcery-generated pull request
      summary, the reviewer's guide, and others.
    • Change the review language.
    • Add, remove or edit custom review instructions.
    • Adjust other review settings.

    Getting Help

    @JohnRichard4096

    Copy link
    Copy Markdown
    Member Author

    @sourcery-ai title

    @sourcery-ai sourcery-ai Bot changed the title Feat fix Add request metadata and cache-aware usage to UniResponse Jul 4, 2026

    @sourcery-ai sourcery-ai Bot left a comment

    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.

    Hey - I've found 3 issues

    Prompt for AI Agents
    Please address the comments from this code review:
    
    ## Individual Comments
    
    ### Comment 1
    <location path="src/amrita_core/adapters/openai.py" line_range="183" />
    <code_context>
                         )
    +                meta = RequestMetadata(
    +                    model=completion.model,
    +                    original_request_id=completion._request_id,
    +                    stop_sequence=None,
    +                    stop_reason=(
    </code_context>
    <issue_to_address>
    **issue (bug_risk):** Accessing the private `_request_id` attribute directly risks breaking if the OpenAI SDK changes.
    
    Since `_request_id` is private, future SDK changes could drop or rename it and cause `AttributeError`. Please either guard access with something like `getattr(completion, "_request_id", None)` so this fails gracefully when absent, or route this through a supported/public API once OpenAI provides one.
    </issue_to_address>
    
    ### Comment 2
    <location path="src/amrita_core/adapters/anthropic.py" line_range="289-295" />
    <code_context>
    +                        stop_reason=getattr(last_msg, "stop_reason", None),
    +                        model=getattr(last_msg, "model", "__NOT_GIVEN__"),
    +                    )
                         usage: UniResponseUsage[int] = UniResponseUsage[int](
                             prompt_tokens=last_msg.usage.input_tokens,
                             completion_tokens=last_msg.usage.output_tokens,
                             total_tokens=last_msg.usage.input_tokens
                             + last_msg.usage.output_tokens,
    +                        cache_creation=last_msg.usage.cache_creation_input_tokens,
    +                        cache_hit=last_msg.usage.cache_read_input_tokens,
                         )
                 else:
    </code_context>
    <issue_to_address>
    **issue:** Unconditional access to `cache_*` usage fields may fail on Anthropic responses that don’t include these attributes.
    
    In both streaming and non-streaming paths you access `last_msg.usage.cache_creation_input_tokens` and `last_msg.usage.cache_read_input_tokens` directly. On SDK versions or models without caching support these attributes may be missing, causing an `AttributeError`. Please use `getattr(last_msg.usage, "cache_creation_input_tokens", None)` and `getattr(last_msg.usage, "cache_read_input_tokens", None)` so the adapter remains compatible when these fields are absent.
    </issue_to_address>
    
    ### Comment 3
    <location path="src/amrita_core/adapters/anthropic.py" line_range="384-387" />
    <code_context>
                 ) = self._convert_tool_choice(tool_choice)
    
    -            response = await client.messages.create(
    +            response: Message = await client.messages.create(
                     model=preset.model,
                     messages=anthropic_msgs,
    </code_context>
    <issue_to_address>
    **issue (bug_risk):** The `cache_*` usage fields in the tools path have the same unconditional access risk as in `call_api`.
    
    In `call_tools`, `usage` reads `response.usage.cache_creation_input_tokens` and `response.usage.cache_read_input_tokens` directly. If the SDK/model doesn’t populate these fields, this will raise `AttributeError`. For consistency with `call_api` and better tolerance of missing cache stats, use `getattr(response.usage, "cache_creation_input_tokens", None)` and `getattr(response.usage, "cache_read_input_tokens", None)` when building `usage`.
    </issue_to_address>

    Sourcery is free for open source - if you like our reviews please consider sharing them ✨
    Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

    Comment thread src/amrita_core/adapters/openai.py
    Comment thread src/amrita_core/adapters/anthropic.py Outdated
    Comment thread src/amrita_core/adapters/anthropic.py
    @cloudflare-workers-and-pages

    cloudflare-workers-and-pages Bot commented Jul 4, 2026

    Copy link
    Copy Markdown

    Deploying amritacore with  Cloudflare Pages  Cloudflare Pages

    Latest commit: cedbe12
    Status: ✅  Deploy successful!
    Preview URL: https://74937379.amritacore.pages.dev
    Branch Preview URL: https://feat-fix.amritacore.pages.dev

    View logs

    @JohnRichard4096 JohnRichard4096 merged commit 634b273 into main Jul 4, 2026
    10 checks passed
    @JohnRichard4096 JohnRichard4096 deleted the feat-fix branch July 4, 2026 12:04
    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.

    1 participant