mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
* feat(interactions): continue requires_continuation long decodes with continuation_token hops A foreground Interactions request stops at Google's per-hop output cap with status requires_continuation and a continuation_token. litellm now re-posts the request with previous_interaction_id and continuation_token until the status moves on, merging the hops into one interaction (last id, every hop's steps, summed usage with initial_input_tokens from hop 1), for non-streaming and streaming calls. continuation_token is accepted as a request param, and requires_continuation is a known status for billing. * refactor(gemini interactions): validate streaming chunks with model_validate * fix(interactions): keep the held completion across stream hops, stop on a repeated continuation_token, follow the spec redirect * fix(interactions): add grounding_tool_count per tool type, stop on any seen continuation_token, keep streaming past a [DONE] frame when a hop is pending * ci(interactions): point the spec canary at aistudio.google.com, where Google moved the Interactions OpenAPI spec * test(interactions): scripted Google ends each long decode hop with a [DONE] frame * refactor(interactions): pass requires_continuation and continuation_token through instead of looping hops in the proxy The caller drives the continuation, the same as against Google directly. /interactions accepts continuation_token in place of input so a resume request needs no input. * test(proxy): assert the accepted /interactions bodies pass the required-param check * fix(proxy): keep the router default fallback for input on /interactions, continuation_token stands in for it --------- Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
94 lines
3.9 KiB
YAML
94 lines
3.9 KiB
YAML
name: Interactions spec canary
|
|
|
|
on:
|
|
schedule:
|
|
- cron: "17 7 * * *"
|
|
pull_request:
|
|
paths:
|
|
- .github/workflows/interactions-spec-canary.yml
|
|
- tests/unit/interactions/**
|
|
- litellm/types/interactions/**
|
|
workflow_dispatch:
|
|
|
|
permissions: {}
|
|
|
|
concurrency: interactions-spec-canary
|
|
|
|
jobs:
|
|
interactions-spec-canary:
|
|
name: interactions-spec-canary
|
|
if: github.repository == 'BerriAI/litellm'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
permissions:
|
|
contents: read
|
|
outputs:
|
|
compliance: ${{ steps.compliance.outcome }}
|
|
steps:
|
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Set up uv
|
|
uses: ./.github/actions/setup-uv-with-retries
|
|
with:
|
|
version: "0.10.9"
|
|
|
|
- name: Set up the Rust bridge
|
|
uses: ./.github/actions/rust-bridge
|
|
|
|
- name: Install dependencies
|
|
run: .github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra proxy
|
|
|
|
- name: Run the compliance tests against Google's live spec
|
|
id: compliance
|
|
run: |
|
|
uv run --no-sync pytest tests/unit/interactions/test_openapi_compliance.py \
|
|
--interactions-spec-url=https://aistudio.google.com/api-reference/interactions.openapi.json \
|
|
--tb=short -vv -p no:rerunfailures -p no:pytest-retry \
|
|
--allow-hosts=127.0.0.1,::1,localhost,ai.google.dev,aistudio.google.com
|
|
|
|
tracking-issue:
|
|
name: tracking-issue
|
|
needs: interactions-spec-canary
|
|
if: always() && github.event_name != 'pull_request' && github.ref_name == github.event.repository.default_branch && github.repository == 'BerriAI/litellm'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
permissions:
|
|
issues: write
|
|
steps:
|
|
- name: File the tracking issue unless the compliance step passed, close it when it did
|
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
env:
|
|
COMPLIANCE_OUTCOME: ${{ needs.interactions-spec-canary.outputs.compliance }}
|
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
with:
|
|
script: |
|
|
const title = "Interactions spec canary is red";
|
|
const outcome = process.env.COMPLIANCE_OUTCOME;
|
|
const runUrl = process.env.RUN_URL;
|
|
const query = `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open in:title "${title}"`;
|
|
const { data: found } = await github.rest.search.issuesAndPullRequests({ q: query, per_page: 20 });
|
|
const open = found.items.find((issue) => issue.title === title);
|
|
if (outcome === "success") {
|
|
if (open === undefined) return;
|
|
await github.rest.issues.createComment({ ...context.repo, issue_number: open.number, body: `Green again: ${runUrl}` });
|
|
await github.rest.issues.update({ ...context.repo, issue_number: open.number, state: "closed" });
|
|
return;
|
|
}
|
|
const state = outcome === "failure" ? "red" : `not run (compliance step outcome: ${outcome || "none"})`;
|
|
if (open !== undefined) {
|
|
await github.rest.issues.createComment({ ...context.repo, issue_number: open.number, body: `Still ${state}: ${runUrl}` });
|
|
return;
|
|
}
|
|
await github.rest.issues.create({
|
|
...context.repo,
|
|
title,
|
|
assignees: ["mateo-berri"],
|
|
body: `The scheduled run of tests/unit/interactions/test_openapi_compliance.py against Google's live Interactions spec is ${state}: ${runUrl}\n\nlitellm/types/interactions/README.md says how to refresh the snapshot and regenerate the types.`,
|
|
});
|