feat(api): rebase JP's session turns/streams backend onto v0.105.5#5375
feat(api): rebase JP's session turns/streams backend onto v0.105.5#5375mmabrouk wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR replaces session-state APIs with session turns and root session lifecycle operations, adds stream headers and runner teardown, propagates agent and tracing identifiers, extends mount filtering, updates Python clients and SDK harness types, and removes web session-state exports. ChangesSession platform migration
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
api/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.py (1)
127-135: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssert
turn_idandspan_idare in the conflict update set.Both names already occur in the INSERT column list, so these assertions pass even if they are removed from
DO UPDATE SET.Proposed assertion
compiled = str(captured["stmt"]).lower() +update_clause = compiled.split("do update set", 1)[1] ... -assert "turn_id" in compiled -assert "span_id" in compiled +assert "turn_id = excluded.turn_id" in update_clause +assert "span_id = excluded.span_id" in update_clauseapi/oss/src/core/sessions/streams/service.py (1)
301-336: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winTreat a different durable turn as stale and never reacquire interrupted locks.
After steer, an old heartbeat sees a different
prior_stream.turn_id, leavesis_current_turn=True, and failedacquire_*calls do not correct it. After cancel, the code reportsFalsebut recreates the deleted locks. Return stale immediately for a different turn and only acquire locks during genuine first establishment.
🧹 Nitpick comments (3)
web/oss/src/components/SessionInspector/api.ts (1)
41-45: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDeduplicate identical functions.
With these changes,
fetchStateis now functionally identical tofetchStream(lines 28-34). Consider refactoringfetchStateto callfetchStreamdirectly to avoid code duplication, or removefetchStateentirely if the callers can be safely updated.♻️ Proposed refactor
export async function fetchState(sessionId: string, projectId?: string | null) { - const res = await client().sessions.fetchSessionStream( - {session_id: sessionId}, - scope(projectId), - ) - return res.stream ?? null + return fetchStream(sessionId, projectId) }api/oss/tests/pytest/unit/mounts/test_agent_id_backfill.py (1)
24-29: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy liftExercise the actual backfill SQL instead of a duplicated parser.
This helper can remain correct while the migration’s
substroffset or prefix condition drifts. Extract the SQL expression into an importable migration constant or add a Postgres migration test that executes it against representative slugs.api/oss/src/dbs/postgres/tracing/dbes.py (1)
43-47: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winConsider adding missing indexes for
user_idandagent_id.The table configuration introduces an index for
session_id, and a code comment inapi/oss/src/dbs/postgres/tracing/dao.pymentions thatuser_idis also an indexed root-only column. However,user_idandagent_idare missing their corresponding composite indexes here. To ensure optimal query performance when filtering by these newly added fields, consider adding them to the table arguments.⚡ Proposed indices
Index( "ix_spans_project_id_session_id", "project_id", "session_id", ), # for session filtering (root-only column) + Index( + "ix_spans_project_id_user_id", + "project_id", + "user_id", + ), + Index( + "ix_spans_project_id_agent_id", + "project_id", + "agent_id", + ),
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a05e1504-f63e-4440-9fec-8520dcf3cff6
⛔ Files ignored due to path filters (51)
api/uv.lockis excluded by!**/*.lockweb/packages/agenta-api-client/src/generated/api/resources/mounts/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/mounts/client/requests/MountQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/ArchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/DeleteSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/FetchTurnRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionDetachRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionHeartbeatRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionRecordIngestRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnAppendRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SetSessionStreamHeaderRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/UnarchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CommandMode.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessKind.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessSessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/Mount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountCreate.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResponseModel.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionInteraction.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionState.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateFlags.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateUpsertRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStream.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamHeaderEdit.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurn.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/WorkflowRequestData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/index.tsis excluded by!**/generated/**
📒 Files selected for processing (170)
api/entrypoints/routers.pyapi/oss/databases/postgres/migrations/core/env.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.pyapi/oss/src/apis/fastapi/mounts/router.pyapi/oss/src/apis/fastapi/mounts/utils.pyapi/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.pyapi/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.pyapi/oss/src/apis/fastapi/otlp/extractors/span_data_builders.pyapi/oss/src/apis/fastapi/otlp/utils/serialization.pyapi/oss/src/apis/fastapi/sessions/models.pyapi/oss/src/apis/fastapi/sessions/router.pyapi/oss/src/apis/fastapi/tracing/router.pyapi/oss/src/core/mounts/dtos.pyapi/oss/src/core/mounts/interfaces.pyapi/oss/src/core/mounts/service.pyapi/oss/src/core/sessions/dtos.pyapi/oss/src/core/sessions/interactions/dtos.pyapi/oss/src/core/sessions/interactions/interfaces.pyapi/oss/src/core/sessions/interactions/service.pyapi/oss/src/core/sessions/records/dtos.pyapi/oss/src/core/sessions/service.pyapi/oss/src/core/sessions/states/dtos.pyapi/oss/src/core/sessions/states/interfaces.pyapi/oss/src/core/sessions/states/service.pyapi/oss/src/core/sessions/streams/dtos.pyapi/oss/src/core/sessions/streams/interfaces.pyapi/oss/src/core/sessions/streams/runner_client.pyapi/oss/src/core/sessions/streams/service.pyapi/oss/src/core/sessions/turns/__init__.pyapi/oss/src/core/sessions/turns/dtos.pyapi/oss/src/core/sessions/turns/interfaces.pyapi/oss/src/core/sessions/turns/service.pyapi/oss/src/core/sessions/turns/types.pyapi/oss/src/core/tracing/dtos.pyapi/oss/src/core/tracing/service.pyapi/oss/src/core/tracing/utils/filtering.pyapi/oss/src/core/tracing/utils/trees.pyapi/oss/src/dbs/postgres/mounts/dao.pyapi/oss/src/dbs/postgres/mounts/dbas.pyapi/oss/src/dbs/postgres/mounts/dbes.pyapi/oss/src/dbs/postgres/mounts/mappings.pyapi/oss/src/dbs/postgres/sessions/interactions/dao.pyapi/oss/src/dbs/postgres/sessions/records/dao.pyapi/oss/src/dbs/postgres/sessions/records/dbas.pyapi/oss/src/dbs/postgres/sessions/records/dbes.pyapi/oss/src/dbs/postgres/sessions/records/mappings.pyapi/oss/src/dbs/postgres/sessions/states/dao.pyapi/oss/src/dbs/postgres/sessions/states/dbes.pyapi/oss/src/dbs/postgres/sessions/states/mappings.pyapi/oss/src/dbs/postgres/sessions/streams/dao.pyapi/oss/src/dbs/postgres/sessions/streams/dbes.pyapi/oss/src/dbs/postgres/sessions/streams/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/__init__.pyapi/oss/src/dbs/postgres/sessions/turns/dao.pyapi/oss/src/dbs/postgres/sessions/turns/dbas.pyapi/oss/src/dbs/postgres/sessions/turns/dbes.pyapi/oss/src/dbs/postgres/sessions/turns/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/utils.pyapi/oss/src/dbs/postgres/tracing/dao.pyapi/oss/src/dbs/postgres/tracing/dbas.pyapi/oss/src/dbs/postgres/tracing/dbes.pyapi/oss/src/dbs/postgres/tracing/mappings.pyapi/oss/src/dbs/postgres/tracing/utils.pyapi/oss/src/utils/env.pyapi/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.pyapi/oss/tests/pytest/acceptance/session_states/test_session_states_basics.pyapi/oss/tests/pytest/acceptance/sessions/__init__.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.pyapi/oss/tests/pytest/unit/mounts/test_agent_id_backfill.pyapi/oss/tests/pytest/unit/mounts/test_agent_mounts.pyapi/oss/tests/pytest/unit/otlp/test_logfire_adapter.pyapi/oss/tests/pytest/unit/session_states/__init__.pyapi/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.pyapi/oss/tests/pytest/unit/session_states/test_session_id_validation.pyapi/oss/tests/pytest/unit/sessions/conftest.pyapi/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.pyapi/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.pyapi/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.pyapi/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.pyapi/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.pyapi/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.pyapi/oss/tests/pytest/unit/sessions/test_runner_client_kill.pyapi/oss/tests/pytest/unit/sessions/test_sessions_root_service.pyapi/oss/tests/pytest/unit/sessions/test_stream_header_merge.pyapi/oss/tests/pytest/unit/sessions/test_turns_dao.pyapi/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.pyapi/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.pyapi/oss/tests/pytest/unit/sessions/test_wp5_root_router.pyapi/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.pyapi/oss/tests/pytest/unit/tracing/utils/test_trees.pyapi/pyproject.tomlclients/python/agenta_client/__init__.pyclients/python/agenta_client/mounts/client.pyclients/python/agenta_client/mounts/raw_client.pyclients/python/agenta_client/sessions/client.pyclients/python/agenta_client/sessions/raw_client.pyclients/python/agenta_client/types/__init__.pyclients/python/agenta_client/types/harness_kind.pyclients/python/agenta_client/types/harness_session_record.pyclients/python/agenta_client/types/mount.pyclients/python/agenta_client/types/mount_create.pyclients/python/agenta_client/types/mount_query.pyclients/python/agenta_client/types/session_heartbeat_result.pyclients/python/agenta_client/types/session_interaction.pyclients/python/agenta_client/types/session_mount.pyclients/python/agenta_client/types/session_mount_query.pyclients/python/agenta_client/types/session_record.pyclients/python/agenta_client/types/session_response.pyclients/python/agenta_client/types/session_state.pyclients/python/agenta_client/types/session_state_data.pyclients/python/agenta_client/types/session_state_upsert_request.pyclients/python/agenta_client/types/session_stream.pyclients/python/agenta_client/types/session_stream_command_response.pyclients/python/agenta_client/types/session_stream_header_edit.pyclients/python/agenta_client/types/session_stream_response.pyclients/python/agenta_client/types/session_streams_response.pyclients/python/agenta_client/types/session_turn.pyclients/python/agenta_client/types/session_turn_query.pyclients/python/agenta_client/types/session_turn_response.pyclients/python/agenta_client/types/session_turns_response.pyclients/python/agenta_client/types/sessions_response.pyclients/python/agenta_client/types/span_input.pyclients/python/agenta_client/types/span_output.pyclients/python/agenta_client/types/spans_node_input.pyclients/python/agenta_client/types/spans_node_output.pyclients/python/agenta_client/types/workflow_request_data.pydocs/docs/self-host/reference/01-configuration.mdxhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/ee/docker-compose.gh.ymlhosting/docker-compose/oss/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.gh.ymlhosting/kubernetes/helm/templates/api-deployment.yamlsdks/python/agenta/sdk/agents/__init__.pysdks/python/agenta/sdk/agents/adapters/harnesses.pysdks/python/agenta/sdk/agents/adapters/local.pysdks/python/agenta/sdk/agents/adapters/sandbox_agent.pysdks/python/agenta/sdk/agents/dtos.pysdks/python/agenta/sdk/agents/errors.pysdks/python/agenta/sdk/agents/interfaces.pysdks/python/agenta/sdk/agents/utils/wire.pysdks/python/agenta/sdk/engines/tracing/tracing.pysdks/python/agenta/sdk/middlewares/running/normalizer.pysdks/python/agenta/sdk/models/tracing.pysdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.pysdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.pysdks/python/oss/tests/pytest/unit/agents/conftest.pysdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.pysdks/python/oss/tests/pytest/unit/agents/skills/test_skills_e2e.pysdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.pysdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.pysdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.pysdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.pysdks/python/oss/tests/pytest/unit/agents/test_harness_identity.pysdks/python/oss/tests/pytest/unit/agents/test_wire_contract.pysdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.pysdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.pysdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.pysdks/python/oss/tests/pytest/unit/test_tracing_store_agent.pyservices/oss/tests/pytest/unit/agent/conftest.pyweb/oss/src/components/SessionInspector/api.tsweb/packages/agenta-entities/src/session/api/api.tsweb/packages/agenta-entities/src/session/core/liveness.tsweb/packages/agenta-entities/src/session/core/schema.tsweb/packages/agenta-entities/src/session/index.ts
💤 Files with no reviewable changes (18)
- clients/python/agenta_client/types/harness_session_record.py
- clients/python/agenta_client/types/session_state_upsert_request.py
- api/oss/src/core/sessions/states/interfaces.py
- clients/python/agenta_client/types/session_state.py
- api/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.py
- api/oss/tests/pytest/unit/session_states/test_session_id_validation.py
- api/oss/src/dbs/postgres/sessions/states/dbes.py
- api/oss/src/core/sessions/states/service.py
- api/oss/src/dbs/postgres/sessions/states/mappings.py
- api/oss/src/core/sessions/states/dtos.py
- api/oss/tests/pytest/acceptance/session_states/test_session_states_basics.py
- clients/python/agenta_client/types/session_state_data.py
- web/packages/agenta-entities/src/session/index.ts
- api/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.py
- api/oss/databases/postgres/migrations/core/env.py
- web/packages/agenta-entities/src/session/core/schema.ts
- api/oss/src/dbs/postgres/sessions/states/dao.py
- web/packages/agenta-entities/src/session/api/api.ts
| class SessionStreamResponse(BaseModel): | ||
| stream: Optional[SessionStream] = None |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Add count to the stream response envelope.
SessionStreamResponse omits the required response count, unlike the other new session response models.
Proposed fix
class SessionStreamResponse(BaseModel):
+ count: int = 0
stream: Optional[SessionStream] = NoneAs per coding guidelines, “include count plus payload in response envelopes.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| class SessionStreamResponse(BaseModel): | |
| stream: Optional[SessionStream] = None | |
| class SessionStreamResponse(BaseModel): | |
| count: int = 0 | |
| stream: Optional[SessionStream] = None |
Source: Coding guidelines
| self.router.add_api_route( | ||
| "/sessions/streams/header", | ||
| self.set_session_stream_header, | ||
| methods=["PUT", "POST"], | ||
| operation_id="set_session_stream_header", | ||
| tags=["Sessions"], | ||
| ) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
sed -n '228,243p' api/oss/src/apis/fastapi/sessions/router.py
rg -n -C2 'operation_id="set_session_stream_header"' .Repository: Agenta-AI/agenta
Length of output: 1078
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
path = Path("api/oss/src/apis/fastapi/sessions/router.py")
text = path.read_text()
# Print every add_api_route block with methods and operation_id in this file.
for m in re.finditer(r'self\.router\.add_api_route\(\n(.*?)\n\s*\)', text, re.S):
block = m.group(1)
if 'operation_id=' in block:
print("BLOCK:\n" + block + "\n---")
PY
# Search for other multi-method routes with explicit operation_id across the repo.
rg -n -U 'methods=\[[^]]*,[^]]*\].*?operation_id=' api/oss/src/apis/fastapiRepository: Agenta-AI/agenta
Length of output: 6743
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect FastAPI's route -> OpenAPI generation semantics if the package is available.
python3 - <<'PY'
import inspect
try:
import fastapi
from fastapi.routing import APIRoute
import fastapi.openapi.utils as u
print("fastapi", fastapi.__version__)
print("APIRoute has operation_id attr:", "operation_id" in APIRoute.__dict__ or hasattr(APIRoute, "operation_id"))
print("get_openapi_path source excerpt:")
src = inspect.getsource(u.get_openapi_path)
for i, line in enumerate(src.splitlines(), 1):
if "operation_id" in line or "route.methods" in line or "method" in line and "operation_id" in src:
print(f"{i}: {line}")
except Exception as e:
print("ERR", type(e).__name__, e)
PYRepository: Agenta-AI/agenta
Length of output: 204
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check whether this repo has any tests/docs explicitly expecting method-distinct operation IDs.
rg -n 'operation_id|operationId|OpenAPI' api/oss/src/apis/fastapi api/oss/src | head -n 200Repository: Agenta-AI/agenta
Length of output: 19700
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Probe whether FastAPI treats one APIRoute with multiple methods as one or multiple OpenAPI operations.
python3 - <<'PY'
try:
from fastapi import FastAPI
app = FastAPI()
`@app.api_route`("/x", methods=["PUT", "POST"], operation_id="same_id")
def handler():
return {}
schema = app.openapi()
ops = schema["paths"]["/x"]
print(list(ops.keys()))
print({method: ops[method].get("operationId") for method in ops})
except Exception as e:
print("ERR", type(e).__name__, e)
PYRepository: Agenta-AI/agenta
Length of output: 204
🌐 Web query:
FastAPI multi-method route same operationId OpenAPI duplicate operation_id methods list generated client collision
💡 Result:
In FastAPI, using the @app.api_route decorator with multiple HTTP methods (e.g., methods=['GET', 'POST']) has historically caused issues with OpenAPI schema generation [1][2][3]. Because OpenAPI requires every operation to have a unique operationId, the default behavior in older versions of FastAPI—which often assigned the same operationId to all methods on a multi-method route—resulted in duplicate ID warnings and potential client generation errors [1][2][4]. Technical Context and Solutions: 1. Root Cause: FastAPI's default unique ID generation logic historically selected an arbitrary method (often the first in a set) to suffix the operationId, causing all methods on a single route to share the same identifier [1][2][5]. Because route.methods is a set, this behavior was also non-deterministic across different Python runs, leading to unstable OpenAPI schemas [2][4][6]. 2. Recommended Fixes: * Use Explicit operation_id: The most reliable way to avoid collisions is to manually define a unique operation_id for each method [3][7]. @app.get("/items/", operation_id="get_items") @app.post("/items/", operation_id="create_items") async def items:... * Update FastAPI: Recent updates to the framework (including PRs #15698 and related fixes) have introduced logic to ensure that for multi-method routes, FastAPI now generates distinct operationIds by appending the specific HTTP method to each operation [2][8][4]. If you are experiencing this issue, ensure your FastAPI installation is up to date [2][4]. * Separate Routes: If your client generator continues to struggle with multi-method routes, the community-recommended best practice is to separate the functionality into individual route decorators (@app.get, @app.post, etc.) rather than using a single @app.api_route call [3][9][6]. * Custom ID Generation: You can globally override the default behavior by providing a custom generate_unique_id_function to the FastAPI app, which gives you full control over how operation IDs are constructed [7]. def custom_generate_unique_id(route: APIRoute) -> str: return f"{route.name}_{list(route.methods)}" app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
Citations:
- 1: Fix duplicate operationId when using add_api_route() with multiple HTTP methods fastapi/fastapi#15321
- 2: Fix duplicate operationId for routes registered with multiple HTTP methods fastapi/fastapi#15698
- 3: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#13175
- 4: fastapi/fastapi@707fd45
- 5: 🐛 Fix duplicate operation IDs for routes with multiple methods (#13175) fastapi/fastapi#15194
- 6: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#4740
- 7: https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/?h=operation_id
- 8: Fix duplicate OpenAPI operationIds for multi-method routes fastapi/fastapi#15222
- 9: Generate unique operation id with multiple methods (Fixes #4740) fastapi/fastapi#4851
🌐 Web query:
FastAPI add_api_route methods=["PUT", "POST"] operation_id same OpenAPI generated operationId duplicate
💡 Result:
The issue where add_api_route with multiple HTTP methods causes duplicate operationId values in FastAPI is a known limitation that stems from how FastAPI historically generated these IDs [1][2][3]. When a route is registered with multiple methods (e.g., methods=["POST", "PUT"]), FastAPI's default generate_unique_id function historically generated a single unique_id based on only the first method in the set, and the OpenAPI metadata generator applied this same ID to all methods on that route [1][4][5]. This violates the OpenAPI specification, which requires each operation to have a unique operationId [1][4][3]. As of mid-2026, improvements have been integrated into FastAPI to address this behavior [1][4]. If you are encountering this issue, you have the following options: 1. Use explicit operation IDs: The most reliable way to avoid collisions is to define a unique operation_id for each method explicitly [2][6]. When an explicit operation_id is provided, FastAPI will use it as-is for that operation [1][4][3]. python # Example of setting explicit IDs app.add_api_route("/items", handler_post, methods=["POST"], operation_id="create_item") app.add_api_route("/items", handler_put, methods=["PUT"], operation_id="update_item") 2. Separate the routes: Instead of using a single add_api_route call with multiple methods, you can define separate routes for each method [2][7]. This allows each path operation to have its own unique operationId automatically [2][3]. 3. Update FastAPI: Ensure you are using a recent version of FastAPI. Recent updates have introduced logic to automatically generate unique, per-method operationId values for multi-method routes by appending the specific method (e.g., _post, _put) to the route's base ID, ensuring compliance with the OpenAPI specification [1][4][3]. If you are using a custom generate_unique_id_function, ensure it is designed to produce unique IDs for each distinct operation, taking into account both the path and the HTTP method [2][6].
Citations:
- 1: Fix duplicate operationId for routes registered with multiple HTTP methods fastapi/fastapi#15698
- 2: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#13175
- 3: Fix duplicate operationId when using add_api_route() with multiple HTTP methods fastapi/fastapi#15321
- 4: fastapi/fastapi@707fd45
- 5: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#8449
- 6: https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/
- 7: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#4740
🌐 Web query:
FastAPI operation_id multi-method route OpenAPI same ID each method source
💡 Result:
According to the OpenAPI specification, the operationId field must be unique among all operations described in an API [1][2][3][4]. In FastAPI, previous versions had a known bug where routes registered with multiple HTTP methods (e.g., methods=["GET", "POST"]) incorrectly shared the same default operationId [5][6][7]. Recent updates to FastAPI (addressed in several pull requests such as #15698, #15321, #15194, and #15222) have implemented fixes for this behavior [5][6][8][9]. When using modern versions of FastAPI, the framework now automatically generates unique operationIds for routes with multiple methods by appending the specific HTTP method to the base identifier [5][6][9]. If you are experiencing duplicate operationId warnings or require specific naming, you have several options: 1. Use explicit identifiers: You can manually set a unique operation_id for each path operation using the operation_id parameter in your route decorator [10][11]. @app.get("/items/", operation_id="get_items_list") async def read_items:... @app.post("/items/", operation_id="create_item") async def create_item:... 2. Customize ID generation: You can provide a custom generate_unique_id_function to the FastAPI app, which allows you to define the logic used to create operationIds for all your routes [10][11]. This function receives the APIRoute object and must return a unique string [10]. If you are on an older version of FastAPI, upgrading to the latest version is the recommended path to resolve the default duplicate operationId behavior [5][9].
Citations:
- 1: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md
- 2: https://swagger.io/docs/specification/v3_0/paths-and-operations/
- 3: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md
- 4: https://spec.openapis.org/oas/v3.0
- 5: Fix duplicate operationId for routes registered with multiple HTTP methods fastapi/fastapi#15698
- 6: Fix duplicate operationId when using add_api_route() with multiple HTTP methods fastapi/fastapi#15321
- 7: Duplicated OperationID when adding route with multiple methods fastapi/fastapi#4740
- 8: 🐛 Fix duplicate operation IDs for routes with multiple methods (#13175) fastapi/fastapi#15194
- 9: Fix duplicate OpenAPI operationIds for multi-method routes fastapi/fastapi#15222
- 10: https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/
- 11: https://github.com/tiangolo/fastapi/blob/master/docs/en/docs/advanced/path-operation-advanced-configuration.md
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n 'fastapi[ =<~!].*|fastapi==' -g 'pyproject.toml' -g 'poetry.lock' -g 'requirements*.txt' -g 'uv.lock' -g 'Pipfile*' -g 'package*.json' api . | head -n 200Repository: Agenta-AI/agenta
Length of output: 154
🌐 Web query:
FastAPI explicit operation_id multi-method route same operationId for PUT POST
💡 Result:
In FastAPI, the operationId in the OpenAPI schema must be unique for every operation to comply with the OpenAPI 3.x specification [1][2]. If you explicitly define an operation_id for a route, FastAPI uses that exact value [3][4]. Consequently, if you assign the same operation_id to a path operation that handles multiple methods (e.g., both POST and PUT), it will result in a duplicate operationId in the generated OpenAPI schema, which often triggers a UserWarning during schema generation [3][5][6]. For routes where you do not explicitly set an operation_id, FastAPI automatically generates one based on the function name and the HTTP method [3][1]. Historically, multi-method routes caused issues where they shared the same generated ID, but recent updates (as of mid-2026) have introduced logic to ensure that these automatically generated IDs are unique per method (e.g., appending the method name) [5][1][4]. To maintain valid OpenAPI compliance when using multiple methods, you should follow these guidelines: 1. Avoid Explicit Duplicate IDs: Do not provide the same operation_id string to different HTTP methods on the same route [3]. If you must set them manually, ensure each method's ID is unique [3]. 2. Let FastAPI Handle It: If you omit the operation_id parameter, FastAPI's default generation logic will now handle the uniqueness for you, creating distinct IDs for each method [1][4]. 3. Custom Generators: If you use a custom generate_unique_id_function to define your own global ID naming convention, ensure that your function generates a unique string for every path operation, as FastAPI will use your function's output as the base for all operations on that route [3][4].
Citations:
- 1: Fix duplicate operationId for routes registered with multiple HTTP methods fastapi/fastapi#15698
- 2: fastapi/fastapi@707fd45
- 3: https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/
- 4: Fix duplicate OpenAPI operationIds for multi-method routes fastapi/fastapi#15222
- 5: Fix duplicate operationId when using add_api_route() with multiple HTTP methods fastapi/fastapi#15321
- 6: https://github.com/fastapi/fastapi/blob/e94028ab/fastapi/openapi/utils.py
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n 'methods=\["PUT", "POST"\]|methods=\["POST", "PUT"\]|operation_id="set_session_stream_header"|operationId' api/oss/src api/oss/tests api/oss | head -n 200Repository: Agenta-AI/agenta
Length of output: 2896
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the pinned FastAPI version in the API environment files.
fd -a 'pyproject.toml|poetry.lock|requirements*.txt|uv.lock|Pipfile*' api/oss api | while read -r f; do
rg -n 'fastapi' "$f" || true
doneRepository: Agenta-AI/agenta
Length of output: 977
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n 'generate_unique_id_function|unique_id' api/oss/src api/oss | head -n 100Repository: Agenta-AI/agenta
Length of output: 335
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the exact route block and nearby code to ensure there isn't a hidden workaround.
sed -n '232,246p' api/oss/src/apis/fastapi/sessions/router.pyRepository: Agenta-AI/agenta
Length of output: 597
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check whether this repo customizes FastAPI operation-id generation.
rg -n 'generate_unique_id_function|unique_id' api/oss/src api/oss | head -n 100Repository: Agenta-AI/agenta
Length of output: 335
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if any app-level OpenAPI customizations affect operationId generation.
rg -n 'openapi|operationId|operation_id|generate_unique_id' api/oss/src/utils api/oss/src/apis/fastapi api/oss/src | head -n 200Repository: Agenta-AI/agenta
Length of output: 19980
Give PUT and POST distinct operation IDs, or split this into separate routes. operation_id="set_session_stream_header" is shared by both verbs here, so the OpenAPI schema will contain duplicate operationIds and can confuse generated clients.
| references: Optional[List[Reference]] = query.references if query else None | ||
| if references: | ||
| matching_turns = await self.turns_service.query_turns( | ||
| project_id=project_id, | ||
| query=SessionTurnQuery(references=references), | ||
| ) | ||
| session_ids = sorted({turn.session_id for turn in matching_turns}) | ||
| if not session_ids: | ||
| return [] | ||
|
|
||
| return await self.streams_service.query_streams( | ||
| project_id=project_id, | ||
| filter=SessionStreamQuery(), | ||
| windowing=windowing, | ||
| session_ids=session_ids, | ||
| ) |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift
Resolve reference filters inside SQL instead of materializing every turn.
This unwindowed query loads all matching turn DTOs, deduplicates them in Python, then creates a potentially huge IN (...) filter before stream pagination applies. Use a distinct-session subquery or join between turns and streams.
| await self.turns_service.delete_by_session_id( | ||
| project_id=project_id, | ||
| session_id=session_id, | ||
| ) | ||
| await self.interactions_service.delete_by_session_id( | ||
| project_id=project_id, | ||
| session_id=session_id, | ||
| ) | ||
| await self.mounts_service.delete_session_mounts( | ||
| project_id=project_id, | ||
| session_id=session_id, | ||
| ) | ||
| await self.streams_service.hard_delete( | ||
| project_id=project_id, | ||
| session_id=session_id, | ||
| ) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Quiesce active sessions before hard-delete or archive fan-out.
Neither path clears Redis locks or tears down the runner. A heartbeat can recreate a hard-deleted stream, while an archived session may keep running against a hidden row. Call streams_service.kill(...) before deletion; reject active archives or explicitly tear them down first.
Also applies to: 118-126
| # A late-arriving lower-index write for a stale turn must never win — the | ||
| # resume pointer is ORDER BY turn_index DESC, not insertion order. | ||
| latest_overall = await dao.append( | ||
| project_id=project_id, | ||
| user_id=None, | ||
| turn=SessionTurnCreate( | ||
| session_id=session_id, | ||
| stream_id=stream_id, | ||
| turn_index=3, | ||
| harness_kind=HarnessKind.CLAUDE, | ||
| agent_session_id="claude-sess-3", | ||
| sandbox_id="sandbox-3", | ||
| ), | ||
| ) | ||
|
|
||
| latest = await dao.latest_turn(project_id=project_id, session_id=session_id) | ||
| assert latest is not None | ||
| assert latest.id == latest_overall.id | ||
| assert latest.turn_index == 3 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Actually append a stale lower-index turn after the latest turn.
The code inserts index 3 last, so both insertion-order and turn_index DESC implementations pass. Insert the expected latest turn at index 4, then append index 3, and assert that index 4 remains latest.
| async def test_delete_session_delegates_to_service_keyed_by_session_id(): | ||
| sessions_service = AsyncMock() | ||
| router = SessionsRootRouter(sessions_service=sessions_service) | ||
|
|
||
| project_id = uuid4() | ||
| user_id = uuid4() | ||
| app = FastAPI() | ||
| request = _make_authed_request(app, project_id, user_id, method="DELETE") | ||
|
|
||
| with _patched_access(True): | ||
| result = await router.delete_session(request=request, session_id="sess-1") | ||
|
|
||
| assert result == {"ok": True} | ||
| sessions_service.delete_session.assert_awaited_once() | ||
| call_kwargs = sessions_service.delete_session.await_args.kwargs | ||
| assert call_kwargs["project_id"] == project_id | ||
| assert call_kwargs["session_id"] == "sess-1" | ||
| assert "stream_id" not in call_kwargs |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Assert the complete mutation scope.
Line 117 should verify user_id; Lines 217-219 should verify both project_id and user_id. Because the service is an unspecced AsyncMock, dropping these scope arguments would otherwise pass and could permit cross-tenant mutation regressions.
Also applies to: 203-219
| @pytest.mark.anyio | ||
| async def test_ingest_child_span_leaves_identity_columns_null(anyio_backend): | ||
| assert anyio_backend == "asyncio" | ||
| engine = _FakeEngine() | ||
| dao = TracingDAO(engine=engine) | ||
|
|
||
| child = _flat_span(span_id=uuid4().hex, parent_id=uuid4().hex) | ||
|
|
||
| await dao.ingest(project_id=uuid4(), user_id=uuid4(), span_dtos=[child]) | ||
|
|
||
| values = engine.executed[0].compile().params | ||
|
|
||
| assert values["session_id"] is None | ||
| assert values["user_id"] is None | ||
| assert values["agent_id"] is None |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Supply identity fields when testing child-span suppression.
The current values are null at input, so the assertions pass even if child spans do no root-only filtering. Construct the child with session_id, user_id, and agent_id, then verify ingestion clears them.
Proposed change
-child = _flat_span(span_id=uuid4().hex, parent_id=uuid4().hex)
+child = _flat_span(
+ span_id=uuid4().hex,
+ parent_id=uuid4().hex,
+ session_id="sess-1",
+ user_id="user-1",
+ agent_id="agent-1",
+)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @pytest.mark.anyio | |
| async def test_ingest_child_span_leaves_identity_columns_null(anyio_backend): | |
| assert anyio_backend == "asyncio" | |
| engine = _FakeEngine() | |
| dao = TracingDAO(engine=engine) | |
| child = _flat_span(span_id=uuid4().hex, parent_id=uuid4().hex) | |
| await dao.ingest(project_id=uuid4(), user_id=uuid4(), span_dtos=[child]) | |
| values = engine.executed[0].compile().params | |
| assert values["session_id"] is None | |
| assert values["user_id"] is None | |
| assert values["agent_id"] is None | |
| `@pytest.mark.anyio` | |
| async def test_ingest_child_span_leaves_identity_columns_null(anyio_backend): | |
| assert anyio_backend == "asyncio" | |
| engine = _FakeEngine() | |
| dao = TracingDAO(engine=engine) | |
| child = _flat_span( | |
| span_id=uuid4().hex, | |
| parent_id=uuid4().hex, | |
| session_id="sess-1", | |
| user_id="user-1", | |
| agent_id="agent-1", | |
| ) | |
| await dao.ingest(project_id=uuid4(), user_id=uuid4(), span_dtos=[child]) | |
| values = engine.executed[0].compile().params | |
| assert values["session_id"] is None | |
| assert values["user_id"] is None | |
| assert values["agent_id"] is None |
| @@ -38,4 +38,4 @@ def __getattr__(attr_name: str) -> typing.Any: | |||
| def __dir__(): | |||
| lazy_attrs = list(_dynamic_imports.keys()) | |||
| return sorted(lazy_attrs) | |||
| __all__ = ["AdminAccountCreateOptions", "AdminAccountRead", "AdminAccountsCreate", "AdminAccountsDelete", "AdminAccountsDeleteTarget", "AdminAccountsResponse", "AdminApiKeyCreate", "AdminApiKeyResponse", "AdminDeleteResponse", "AdminDeletedEntities", "AdminDeletedEntity", "AdminOrganizationCreate", "AdminOrganizationMembershipCreate", "AdminOrganizationMembershipRead", "AdminOrganizationRead", "AdminProjectCreate", "AdminProjectMembershipCreate", "AdminProjectMembershipRead", "AdminProjectRead", "AdminSimpleAccountCreate", "AdminSimpleAccountDeleteEntry", "AdminSimpleAccountRead", "AdminSimpleAccountsApiKeysCreate", "AdminSimpleAccountsCreate", "AdminSimpleAccountsDelete", "AdminSimpleAccountsOrganizationsCreate", "AdminSimpleAccountsOrganizationsMembershipsCreate", "AdminSimpleAccountsOrganizationsTransferOwnership", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeProjects", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeProjectsZero", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeWorkspaces", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeWorkspacesZero", "AdminSimpleAccountsOrganizationsTransferOwnershipResponse", "AdminSimpleAccountsProjectsCreate", "AdminSimpleAccountsProjectsMembershipsCreate", "AdminSimpleAccountsResponse", "AdminSimpleAccountsUsersCreate", "AdminSimpleAccountsUsersIdentitiesCreate", "AdminSimpleAccountsUsersResetPassword", "AdminSimpleAccountsWorkspacesCreate", "AdminSimpleAccountsWorkspacesMembershipsCreate", "AdminStructuredError", "AdminSubscriptionCreate", "AdminSubscriptionRead", "AdminUserCreate", "AdminUserIdentityCreate", "AdminUserIdentityRead", "AdminUserIdentityReadStatus", "AdminUserRead", "AdminWorkspaceCreate", "AdminWorkspaceMembershipCreate", "AdminWorkspaceMembershipRead", "AdminWorkspaceRead", "AgentTemplateOverlay", "AgentaApi", "AgentaApiEnvironment", "Analytics", "AnalyticsResponse", "Annotation", "AnnotationCreate", "AnnotationCreateLinks", "AnnotationEdit", "AnnotationEditLinks", "AnnotationLinkResponse", "AnnotationLinks", "AnnotationQuery", "AnnotationQueryLinks", "AnnotationResponse", "AnnotationsResponse", "Application", "ApplicationArtifactFlags", "ApplicationArtifactQueryFlags", "ApplicationCatalogPreset", "ApplicationCatalogPresetResponse", "ApplicationCatalogPresetsResponse", "ApplicationCatalogTemplate", "ApplicationCatalogTemplateResponse", "ApplicationCatalogTemplatesResponse", "ApplicationCatalogType", "ApplicationCatalogTypesResponse", "ApplicationCreate", "ApplicationEdit", "ApplicationFlags", "ApplicationQuery", "ApplicationResponse", "ApplicationRevisionCommit", "ApplicationRevisionCreate", "ApplicationRevisionDataInput", "ApplicationRevisionDataInputHeadersValue", "ApplicationRevisionDataInputRuntime", "ApplicationRevisionDataOutput", "ApplicationRevisionDataOutputHeadersValue", "ApplicationRevisionDataOutputRuntime", "ApplicationRevisionEdit", "ApplicationRevisionFlags", "ApplicationRevisionInput", "ApplicationRevisionOutput", "ApplicationRevisionQuery", "ApplicationRevisionQueryFlags", "ApplicationRevisionResolveResponse", "ApplicationRevisionResponse", "ApplicationRevisionsLog", "ApplicationRevisionsResponse", "ApplicationVariant", "ApplicationVariantCreate", "ApplicationVariantEdit", "ApplicationVariantFlags", "ApplicationVariantFork", "ApplicationVariantResponse", "ApplicationVariantsResponse", "ApplicationsResponse", "AsyncAgentaApi", "BodyConfigsFetchVariantsConfigsFetchPost", "Bucket", "BuiltinToolConfig", "BuiltinToolConfigPermission", "CapabilitiesResult", "Capability", "CapabilityConnection", "CapabilityGuidance", "CollectStatusResponse", "CommandMode", "ComparisonOperator", "Condition", "ConditionOperator", "ConditionOptions", "ConditionValue", "ConfigResponseModel", "ConnectAffordance", "ConnectionRequirement", "CreateSimpleTestsetFromFileRequestFileType", "CreateTestsetRevisionFromFileRequestFileType", "CustomModelSettingsDto", "CustomProviderDto", "CustomProviderKind", "CustomProviderSettingsDto", "CustomSecretDto", "CustomSecretFormat", "CustomSecretSettingsDto", "CustomSecretSettingsDtoContent", "CustomSecretSettingsDtoContentOneValue", "DictOperator", "DiscoverResponse", "DiscoverResponseMethodsValue", "DiscoveredAlternative", "DiscoveredTool", "DiscoveredToolType", "DiscoveredTriggerAlternative", "DiscoveredTriggerEvent", "DiscoveredTriggerEventType", "EditSimpleTestsetFromFileRequestFileType", "EntityRef", "Environment", "EnvironmentCreate", "EnvironmentEdit", "EnvironmentFlags", "EnvironmentQueryFlags", "EnvironmentResponse", "EnvironmentRevisionCommit", "EnvironmentRevisionCreate", "EnvironmentRevisionData", "EnvironmentRevisionDelta", "EnvironmentRevisionEdit", "EnvironmentRevisionInput", "EnvironmentRevisionOutput", "EnvironmentRevisionResolveResponse", "EnvironmentRevisionResponse", "EnvironmentRevisionsLog", "EnvironmentRevisionsResponse", "EnvironmentVariant", "EnvironmentVariantCreate", "EnvironmentVariantEdit", "EnvironmentVariantFork", "EnvironmentVariantResponse", "EnvironmentVariantsResponse", "EnvironmentsResponse", "ErrorPolicy", "EvaluationMetrics", "EvaluationMetricsCreate", "EvaluationMetricsIdsResponse", "EvaluationMetricsQuery", "EvaluationMetricsQueryScenarioIds", "EvaluationMetricsQueryTimestamps", "EvaluationMetricsRefresh", "EvaluationMetricsResponse", "EvaluationMetricsSetRequest", "EvaluationQueue", "EvaluationQueueCreate", "EvaluationQueueData", "EvaluationQueueEdit", "EvaluationQueueFlags", "EvaluationQueueIdResponse", "EvaluationQueueIdsResponse", "EvaluationQueueQuery", "EvaluationQueueQueryFlags", "EvaluationQueueResponse", "EvaluationQueueScenariosQuery", "EvaluationQueuesResponse", "EvaluationResult", "EvaluationResultCreate", "EvaluationResultIdResponse", "EvaluationResultIdsResponse", "EvaluationResultQuery", "EvaluationResultResponse", "EvaluationResultsResponse", "EvaluationResultsSetRequest", "EvaluationRun", "EvaluationRunCreate", "EvaluationRunDataConcurrency", "EvaluationRunDataInput", "EvaluationRunDataMapping", "EvaluationRunDataMappingColumn", "EvaluationRunDataMappingStep", "EvaluationRunDataOutput", "EvaluationRunDataStepInput", "EvaluationRunDataStepInputKey", "EvaluationRunDataStepInputOrigin", "EvaluationRunDataStepInputType", "EvaluationRunDataStepOutput", "EvaluationRunDataStepOutputOrigin", "EvaluationRunDataStepOutputType", "EvaluationRunEdit", "EvaluationRunFlags", "EvaluationRunIdResponse", "EvaluationRunIdsRequest", "EvaluationRunIdsResponse", "EvaluationRunQuery", "EvaluationRunQueryFlags", "EvaluationRunResponse", "EvaluationRunsResponse", "EvaluationScenario", "EvaluationScenarioCreate", "EvaluationScenarioEdit", "EvaluationScenarioIdResponse", "EvaluationScenarioIdsResponse", "EvaluationScenarioQuery", "EvaluationScenarioResponse", "EvaluationScenariosResponse", "EvaluationStatus", "Evaluator", "EvaluatorArtifactFlags", "EvaluatorArtifactQueryFlags", "EvaluatorCatalogPreset", "EvaluatorCatalogPresetResponse", "EvaluatorCatalogPresetsResponse", "EvaluatorCatalogTemplate", "EvaluatorCatalogTemplateResponse", "EvaluatorCatalogTemplatesResponse", "EvaluatorCatalogType", "EvaluatorCatalogTypesResponse", "EvaluatorCreate", "EvaluatorEdit", "EvaluatorFlags", "EvaluatorQuery", "EvaluatorResponse", "EvaluatorRevisionCommit", "EvaluatorRevisionCreate", "EvaluatorRevisionDataInput", "EvaluatorRevisionDataInputHeadersValue", "EvaluatorRevisionDataInputRuntime", "EvaluatorRevisionDataOutput", "EvaluatorRevisionDataOutputHeadersValue", "EvaluatorRevisionDataOutputRuntime", "EvaluatorRevisionEdit", "EvaluatorRevisionFlags", "EvaluatorRevisionInput", "EvaluatorRevisionOutput", "EvaluatorRevisionQuery", "EvaluatorRevisionQueryFlags", "EvaluatorRevisionResolveResponse", "EvaluatorRevisionResponse", "EvaluatorRevisionsLog", "EvaluatorRevisionsResponse", "EvaluatorTemplate", "EvaluatorTemplatesResponse", "EvaluatorVariant", "EvaluatorVariantCreate", "EvaluatorVariantEdit", "EvaluatorVariantFlags", "EvaluatorVariantFork", "EvaluatorVariantResponse", "EvaluatorVariantsResponse", "EvaluatorsResponse", "Event", "EventQuery", "EventType", "EventsQueryResponse", "ExistenceOperator", "FetchLegacyAnalyticsRequestNewest", "FetchLegacyAnalyticsRequestOldest", "FetchSimpleTestsetToFileRequestFileType", "FetchTestsetRevisionToFileRequestFileType", "FilteringInput", "FilteringInputConditionsItem", "FilteringOutput", "FilteringOutputConditionsItem", "Focus", "Folder", "FolderCreate", "FolderEdit", "FolderIdResponse", "FolderKind", "FolderQuery", "FolderQueryKinds", "FolderResponse", "FoldersResponse", "Format", "Formatting", typing.Any, typing.Any, "GatewayToolConfig", "GatewayToolConfigPermission", "HarnessSessionRecord", "Header", "HttpValidationError", "InviteRequest", "Invocation", "InvocationCreate", "InvocationCreateLinks", "InvocationEdit", "InvocationEditLinks", "InvocationLinkResponse", "InvocationLinks", "InvocationQuery", "InvocationQueryLinks", "InvocationResponse", "InvocationsResponse", "JsonSchemasInput", "JsonSchemasOutput", typing.Any, typing.Any, "LegacyLifecycleDto", "ListApiKeysResponse", "ListOperator", "ListOptions", "LogicalOperator", "MetricSpec", "MetricType", "MetricsBucket", "Mount", "MountCreate", "MountCredentials", "MountCredentialsResponse", "MountData", "MountEdit", "MountFileDeletedResponse", "MountFileWrittenResponse", "MountFlags", "MountFolderCreatedResponse", "MountQuery", "MountResponse", "MountsResponse", "NumericOperator", "OTelEventInput", "OTelEventInputTimestamp", "OTelEventOutput", "OTelEventOutputTimestamp", "OTelHashInput", "OTelHashOutput", "OTelLinkInput", "OTelLinkOutput", "OTelLinksResponse", "OTelReferenceInput", "OTelReferenceOutput", "OTelSpanKind", "OTelStatusCode", "OTelTracingRequest", "OTelTracingResponse", "OldAnalyticsResponse", "Organization", "OrganizationDetails", "OrganizationDomainResponse", "OrganizationProviderResponse", "OrganizationUpdate", "Permission", "PlaygroundBuildKitContext", "ProjectsResponse", "QueriesResponse", "Query", "QueryApplicationVariantsRequestOrder", "QueryCreate", "QueryEdit", "QueryEnvironmentRevisionsRequestOrder", "QueryEnvironmentVariantsRequestOrder", "QueryEnvironmentsRequestOrder", "QueryEvaluatorVariantsRequestOrder", "QueryFlags", "QueryQueriesRequestOrder", "QueryQueryFlags", "QueryResponse", "QueryRevision", "QueryRevisionCommit", "QueryRevisionCreate", "QueryRevisionDataInput", "QueryRevisionDataOutput", "QueryRevisionEdit", "QueryRevisionQuery", "QueryRevisionResponse", "QueryRevisionsLog", "QueryRevisionsResponse", "QuerySpansAnalyticsRequestNewest", "QuerySpansAnalyticsRequestOldest", "QueryVariant", "QueryVariantCreate", "QueryVariantEdit", "QueryVariantFork", "QueryVariantQuery", "QueryVariantResponse", "QueryVariantsResponse", "QueryWorkflowRevisionsRequestOrder", "QueryWorkflowVariantsRequestOrder", "QueryWorkflowsRequestOrder", "Reference", "ReferenceRequestModelInput", "ReferenceRequestModelOutput", "RequestType", "ResolutionInfo", "ResolvedTool", "RetrievalInfo", "SecretDto", "SecretDtoData", "SecretKind", "SecretResponseDto", "SecretResponseDtoData", "Selector", "SessionHeartbeatResponseModel", "SessionIdsResponse", "SessionInteraction", "SessionInteractionData", "SessionInteractionFlags", "SessionInteractionKind", "SessionInteractionQuery", "SessionInteractionQueryFlags", "SessionInteractionResponse", "SessionInteractionStatus", "SessionInteractionsResponse", "SessionMount", "SessionMountQuery", "SessionMountsResponse", "SessionRecord", "SessionRecordResponse", "SessionRecordsQueryResponse", "SessionState", "SessionStateData", "SessionStateFlags", "SessionStateResponse", "SessionStateUpsertRequest", "SessionStream", "SessionStreamCommandResponseModel", "SessionStreamFlags", "SessionStreamResponseModel", "SessionStreamsResponseModel", "SimpleApplication", "SimpleApplicationAdditionalContext", "SimpleApplicationCreate", "SimpleApplicationDataInput", "SimpleApplicationDataInputHeadersValue", "SimpleApplicationDataInputRuntime", "SimpleApplicationDataOutput", "SimpleApplicationDataOutputHeadersValue", "SimpleApplicationDataOutputRuntime", "SimpleApplicationEdit", "SimpleApplicationFlags", "SimpleApplicationQuery", "SimpleApplicationQueryFlags", "SimpleApplicationResponse", "SimpleApplicationsResponse", "SimpleEnvironment", "SimpleEnvironmentCreate", "SimpleEnvironmentEdit", "SimpleEnvironmentQuery", "SimpleEnvironmentResponse", "SimpleEnvironmentsResponse", "SimpleEvaluation", "SimpleEvaluationCreate", "SimpleEvaluationData", "SimpleEvaluationDataApplicationSteps", "SimpleEvaluationDataApplicationStepsOneValue", "SimpleEvaluationDataEvaluatorSteps", "SimpleEvaluationDataEvaluatorStepsOneValue", "SimpleEvaluationDataQuerySteps", "SimpleEvaluationDataQueryStepsOneValue", "SimpleEvaluationDataTestsetSteps", "SimpleEvaluationDataTestsetStepsOneValue", "SimpleEvaluationEdit", "SimpleEvaluationIdResponse", "SimpleEvaluationQuery", "SimpleEvaluationResponse", "SimpleEvaluationsResponse", "SimpleEvaluator", "SimpleEvaluatorCreate", "SimpleEvaluatorDataInput", "SimpleEvaluatorDataInputHeadersValue", "SimpleEvaluatorDataInputRuntime", "SimpleEvaluatorDataOutput", "SimpleEvaluatorDataOutputHeadersValue", "SimpleEvaluatorDataOutputRuntime", "SimpleEvaluatorEdit", "SimpleEvaluatorFlags", "SimpleEvaluatorQuery", "SimpleEvaluatorQueryFlags", "SimpleEvaluatorResponse", "SimpleEvaluatorsResponse", "SimpleQueriesResponse", "SimpleQuery", "SimpleQueryCreate", "SimpleQueryEdit", "SimpleQueryQuery", "SimpleQueryResponse", "SimpleQueue", "SimpleQueueCreate", "SimpleQueueData", "SimpleQueueDataEvaluators", "SimpleQueueDataEvaluatorsOneValue", "SimpleQueueIdResponse", "SimpleQueueIdsResponse", "SimpleQueueKind", "SimpleQueueQuery", "SimpleQueueResponse", "SimpleQueueScenariosQuery", "SimpleQueueScenariosResponse", "SimpleQueueSettings", "SimpleQueuesResponse", "SimpleTestset", "SimpleTestsetCreate", "SimpleTestsetEdit", "SimpleTestsetQuery", "SimpleTestsetResponse", "SimpleTestsetsResponse", "SimpleTrace", "SimpleTraceChannel", "SimpleTraceCreate", "SimpleTraceCreateLinks", "SimpleTraceEdit", "SimpleTraceEditLinks", "SimpleTraceKind", "SimpleTraceLinkResponse", "SimpleTraceLinks", "SimpleTraceOrigin", "SimpleTraceQuery", "SimpleTraceQueryLinks", "SimpleTraceReferences", "SimpleTraceResponse", "SimpleTracesResponse", "SimpleWorkflow", "SimpleWorkflowCreate", "SimpleWorkflowDataInput", "SimpleWorkflowDataInputHeadersValue", "SimpleWorkflowDataInputRuntime", "SimpleWorkflowDataOutput", "SimpleWorkflowDataOutputHeadersValue", "SimpleWorkflowDataOutputRuntime", "SimpleWorkflowEdit", "SimpleWorkflowFlags", "SimpleWorkflowQuery", "SimpleWorkflowQueryFlags", "SimpleWorkflowResponse", "SimpleWorkflowsResponse", "SpanInput", "SpanInputEndTime", "SpanInputStartTime", "SpanOutput", "SpanOutputEndTime", "SpanOutputStartTime", "SpanResponse", "SpanType", "SpansNodeInput", "SpansNodeInputEndTime", "SpansNodeInputSpansValue", "SpansNodeInputStartTime", "SpansNodeOutput", "SpansNodeOutputEndTime", "SpansNodeOutputSpansValue", "SpansNodeOutputStartTime", "SpansResponse", "SpansTreeInput", "SpansTreeInputSpansValue", "SpansTreeOutput", "SpansTreeOutputSpansValue", "SsoProviderDto", "SsoProviderInfo", "SsoProviderSettingsDto", "SsoProviders", "StandardProviderDto", "StandardProviderKind", "StandardProviderSettingsDto", "Status", "StringOperator", "TestcaseInput", "TestcaseOutput", "TestcaseResponse", "TestcasesResponse", "Testset", "TestsetCreate", "TestsetEdit", "TestsetFlags", "TestsetQuery", "TestsetResponse", "TestsetRevision", "TestsetRevisionCommit", "TestsetRevisionCreate", "TestsetRevisionDataInput", "TestsetRevisionDataOutput", "TestsetRevisionDelta", "TestsetRevisionDeltaColumns", "TestsetRevisionDeltaRows", "TestsetRevisionEdit", "TestsetRevisionQuery", "TestsetRevisionResponse", "TestsetRevisionsLog", "TestsetRevisionsResponse", "TestsetVariant", "TestsetVariantCreate", "TestsetVariantEdit", "TestsetVariantFork", "TestsetVariantQuery", "TestsetVariantResponse", "TestsetVariantsResponse", "TestsetsResponse", "TextOptions", "ToolAuthScheme", "ToolCallData", "ToolCallFunction", "ToolCallResponse", "ToolCatalogAction", "ToolCatalogActionDetails", "ToolCatalogActionResponse", "ToolCatalogActionResponseAction", "ToolCatalogActionsResponse", "ToolCatalogActionsResponseActionsItem", "ToolCatalogCategoriesResponse", "ToolCatalogCategory", "ToolCatalogIntegration", "ToolCatalogIntegrationDetails", "ToolCatalogIntegrationResponse", "ToolCatalogIntegrationResponseIntegration", "ToolCatalogIntegrationsResponse", "ToolCatalogIntegrationsResponseIntegrationsItem", "ToolCatalogProvider", "ToolCatalogProviderDetails", "ToolCatalogProviderResponse", "ToolCatalogProviderResponseProvider", "ToolCatalogProvidersResponse", "ToolCatalogProvidersResponseProvidersItem", "ToolConnection", "ToolConnectionCreate", "ToolConnectionCreateData", "ToolConnectionResponse", "ToolConnectionState", "ToolConnectionStatus", "ToolConnectionsResponse", "ToolProviderKind", "ToolResolveRequestToolsItem", "ToolResolveRequestToolsItem_Builtin", "ToolResolveRequestToolsItem_Gateway", "ToolResolveResponse", "ToolResult", "ToolResultData", "TraceIdResponse", "TraceIdsResponse", "TraceInput", "TraceInputSpansValue", "TraceOutput", "TraceOutputSpansValue", "TraceRequest", "TraceResponse", "TraceType", "TracesRequest", "TracesResponse", "TracingQuery", "TriggerAuthScheme", "TriggerCapabilitiesResult", "TriggerCapability", "TriggerCapabilityConnection", "TriggerCatalogEvent", "TriggerCatalogEventDetails", "TriggerCatalogEventResponse", "TriggerCatalogEventsResponse", "TriggerCatalogIntegration", "TriggerCatalogIntegrationResponse", "TriggerCatalogIntegrationsResponse", "TriggerCatalogProvider", "TriggerCatalogProviderResponse", "TriggerCatalogProvidersResponse", "TriggerConnectAffordance", "TriggerConnection", "TriggerConnectionCreate", "TriggerConnectionCreateData", "TriggerConnectionRequirement", "TriggerConnectionResponse", "TriggerConnectionStatus", "TriggerConnectionsResponse", "TriggerDeliveriesResponse", "TriggerDelivery", "TriggerDeliveryData", "TriggerDeliveryQuery", "TriggerDeliveryResponse", "TriggerDiscoveryConnectionState", "TriggerDiscoveryGuidance", "TriggerEventAck", "TriggerProviderKind", "TriggerSchedule", "TriggerScheduleCreate", "TriggerScheduleData", "TriggerScheduleDataInputsFields", "TriggerScheduleEdit", "TriggerScheduleFlags", "TriggerScheduleQuery", "TriggerScheduleResponse", "TriggerSchedulesResponse", "TriggerSubscription", "TriggerSubscriptionCreate", "TriggerSubscriptionCreateRequest", "TriggerSubscriptionData", "TriggerSubscriptionDataInputsFields", "TriggerSubscriptionEdit", "TriggerSubscriptionFlags", "TriggerSubscriptionQuery", "TriggerSubscriptionResponse", "TriggerSubscriptionsResponse", "UnprocessableEntityError", "UserIdsResponse", "ValidationError", "ValidationErrorLocItem", "WebhookDeliveriesResponse", "WebhookDelivery", "WebhookDeliveryCreate", "WebhookDeliveryData", "WebhookDeliveryQuery", "WebhookDeliveryResponse", "WebhookDeliveryResponseInfo", "WebhookEventType", "WebhookProviderDto", "WebhookProviderSettingsDto", "WebhookSubscription", "WebhookSubscriptionCreate", "WebhookSubscriptionData", "WebhookSubscriptionDataAuthMode", "WebhookSubscriptionEdit", "WebhookSubscriptionFlags", "WebhookSubscriptionQuery", "WebhookSubscriptionResponse", "WebhookSubscriptionTestRequestSubscription", "WebhookSubscriptionsResponse", "Windowing", "WindowingOrder", "Workflow", "WorkflowArtifactFlags", "WorkflowCatalogFlags", "WorkflowCatalogHarness", "WorkflowCatalogHarnessResponse", "WorkflowCatalogHarnessesResponse", "WorkflowCatalogPreset", "WorkflowCatalogPresetResponse", "WorkflowCatalogPresetsResponse", "WorkflowCatalogTemplate", "WorkflowCatalogTemplateResponse", "WorkflowCatalogTemplatesResponse", "WorkflowCatalogType", "WorkflowCatalogTypeResponse", "WorkflowCatalogTypesResponse", "WorkflowCreate", "WorkflowEdit", "WorkflowFlags", "WorkflowResponse", "WorkflowRevisionCommit", "WorkflowRevisionCreate", "WorkflowRevisionDataInput", "WorkflowRevisionDataInputHeadersValue", "WorkflowRevisionDataInputRuntime", "WorkflowRevisionDataOutput", "WorkflowRevisionDataOutputHeadersValue", "WorkflowRevisionDataOutputRuntime", "WorkflowRevisionDelta", "WorkflowRevisionEdit", "WorkflowRevisionFlags", "WorkflowRevisionInput", "WorkflowRevisionOutput", "WorkflowRevisionResolveResponse", "WorkflowRevisionResponse", "WorkflowRevisionsLog", "WorkflowRevisionsResponse", "WorkflowVariant", "WorkflowVariantCreate", "WorkflowVariantEdit", "WorkflowVariantFlags", "WorkflowVariantFork", "WorkflowVariantResponse", "WorkflowVariantsResponse", "WorkflowsResponse", "Workspace", "WorkspaceMemberResponse", "WorkspacePermission", "WorkspaceResponse", "access", "annotations", "applications", "billing", "environments", "evaluations", "evaluators", "events", "folders", "invocations", "keys", "legacy", "mounts", "organizations", "projects", "queries", "secrets", "sessions", "status", "testcases", "testsets", "tools", "traces", "triggers", "users", "webhooks", "workflows", "workspaces"] | |||
| __all__ = ["AdminAccountCreateOptions", "AdminAccountRead", "AdminAccountsCreate", "AdminAccountsDelete", "AdminAccountsDeleteTarget", "AdminAccountsResponse", "AdminApiKeyCreate", "AdminApiKeyResponse", "AdminDeleteResponse", "AdminDeletedEntities", "AdminDeletedEntity", "AdminOrganizationCreate", "AdminOrganizationMembershipCreate", "AdminOrganizationMembershipRead", "AdminOrganizationRead", "AdminProjectCreate", "AdminProjectMembershipCreate", "AdminProjectMembershipRead", "AdminProjectRead", "AdminSimpleAccountCreate", "AdminSimpleAccountDeleteEntry", "AdminSimpleAccountRead", "AdminSimpleAccountsApiKeysCreate", "AdminSimpleAccountsCreate", "AdminSimpleAccountsDelete", "AdminSimpleAccountsOrganizationsCreate", "AdminSimpleAccountsOrganizationsMembershipsCreate", "AdminSimpleAccountsOrganizationsTransferOwnership", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeProjects", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeProjectsZero", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeWorkspaces", "AdminSimpleAccountsOrganizationsTransferOwnershipIncludeWorkspacesZero", "AdminSimpleAccountsOrganizationsTransferOwnershipResponse", "AdminSimpleAccountsProjectsCreate", "AdminSimpleAccountsProjectsMembershipsCreate", "AdminSimpleAccountsResponse", "AdminSimpleAccountsUsersCreate", "AdminSimpleAccountsUsersIdentitiesCreate", "AdminSimpleAccountsUsersResetPassword", "AdminSimpleAccountsWorkspacesCreate", "AdminSimpleAccountsWorkspacesMembershipsCreate", "AdminStructuredError", "AdminSubscriptionCreate", "AdminSubscriptionRead", "AdminUserCreate", "AdminUserIdentityCreate", "AdminUserIdentityRead", "AdminUserIdentityReadStatus", "AdminUserRead", "AdminWorkspaceCreate", "AdminWorkspaceMembershipCreate", "AdminWorkspaceMembershipRead", "AdminWorkspaceRead", "AgentTemplateOverlay", "AgentaApi", "AgentaApiEnvironment", "Analytics", "AnalyticsResponse", "Annotation", "AnnotationCreate", "AnnotationCreateLinks", "AnnotationEdit", "AnnotationEditLinks", "AnnotationLinkResponse", "AnnotationLinks", "AnnotationQuery", "AnnotationQueryLinks", "AnnotationResponse", "AnnotationsResponse", "Application", "ApplicationArtifactFlags", "ApplicationArtifactQueryFlags", "ApplicationCatalogPreset", "ApplicationCatalogPresetResponse", "ApplicationCatalogPresetsResponse", "ApplicationCatalogTemplate", "ApplicationCatalogTemplateResponse", "ApplicationCatalogTemplatesResponse", "ApplicationCatalogType", "ApplicationCatalogTypesResponse", "ApplicationCreate", "ApplicationEdit", "ApplicationFlags", "ApplicationQuery", "ApplicationResponse", "ApplicationRevisionCommit", "ApplicationRevisionCreate", "ApplicationRevisionDataInput", "ApplicationRevisionDataInputHeadersValue", "ApplicationRevisionDataInputRuntime", "ApplicationRevisionDataOutput", "ApplicationRevisionDataOutputHeadersValue", "ApplicationRevisionDataOutputRuntime", "ApplicationRevisionEdit", "ApplicationRevisionFlags", "ApplicationRevisionInput", "ApplicationRevisionOutput", "ApplicationRevisionQuery", "ApplicationRevisionQueryFlags", "ApplicationRevisionResolveResponse", "ApplicationRevisionResponse", "ApplicationRevisionsLog", "ApplicationRevisionsResponse", "ApplicationVariant", "ApplicationVariantCreate", "ApplicationVariantEdit", "ApplicationVariantFlags", "ApplicationVariantFork", "ApplicationVariantResponse", "ApplicationVariantsResponse", "ApplicationsResponse", "AsyncAgentaApi", "BodyConfigsFetchVariantsConfigsFetchPost", "Bucket", "BuiltinToolConfig", "BuiltinToolConfigPermission", "CapabilitiesResult", "Capability", "CapabilityConnection", "CapabilityGuidance", "CollectStatusResponse", "CommandMode", "ComparisonOperator", "Condition", "ConditionOperator", "ConditionOptions", "ConditionValue", "ConfigResponseModel", "ConnectAffordance", "ConnectionRequirement", "CreateSimpleTestsetFromFileRequestFileType", "CreateTestsetRevisionFromFileRequestFileType", "CustomModelSettingsDto", "CustomProviderDto", "CustomProviderKind", "CustomProviderSettingsDto", "CustomSecretDto", "CustomSecretFormat", "CustomSecretSettingsDto", "CustomSecretSettingsDtoContent", "CustomSecretSettingsDtoContentOneValue", "DictOperator", "DiscoverResponse", "DiscoverResponseMethodsValue", "DiscoveredAlternative", "DiscoveredTool", "DiscoveredToolType", "DiscoveredTriggerAlternative", "DiscoveredTriggerEvent", "DiscoveredTriggerEventType", "EditSimpleTestsetFromFileRequestFileType", "EntityRef", "Environment", "EnvironmentCreate", "EnvironmentEdit", "EnvironmentFlags", "EnvironmentQueryFlags", "EnvironmentResponse", "EnvironmentRevisionCommit", "EnvironmentRevisionCreate", "EnvironmentRevisionData", "EnvironmentRevisionDelta", "EnvironmentRevisionEdit", "EnvironmentRevisionInput", "EnvironmentRevisionOutput", "EnvironmentRevisionResolveResponse", "EnvironmentRevisionResponse", "EnvironmentRevisionsLog", "EnvironmentRevisionsResponse", "EnvironmentVariant", "EnvironmentVariantCreate", "EnvironmentVariantEdit", "EnvironmentVariantFork", "EnvironmentVariantResponse", "EnvironmentVariantsResponse", "EnvironmentsResponse", "ErrorPolicy", "EvaluationMetrics", "EvaluationMetricsCreate", "EvaluationMetricsIdsResponse", "EvaluationMetricsQuery", "EvaluationMetricsQueryScenarioIds", "EvaluationMetricsQueryTimestamps", "EvaluationMetricsRefresh", "EvaluationMetricsResponse", "EvaluationMetricsSetRequest", "EvaluationQueue", "EvaluationQueueCreate", "EvaluationQueueData", "EvaluationQueueEdit", "EvaluationQueueFlags", "EvaluationQueueIdResponse", "EvaluationQueueIdsResponse", "EvaluationQueueQuery", "EvaluationQueueQueryFlags", "EvaluationQueueResponse", "EvaluationQueueScenariosQuery", "EvaluationQueuesResponse", "EvaluationResult", "EvaluationResultCreate", "EvaluationResultIdResponse", "EvaluationResultIdsResponse", "EvaluationResultQuery", "EvaluationResultResponse", "EvaluationResultsResponse", "EvaluationResultsSetRequest", "EvaluationRun", "EvaluationRunCreate", "EvaluationRunDataConcurrency", "EvaluationRunDataInput", "EvaluationRunDataMapping", "EvaluationRunDataMappingColumn", "EvaluationRunDataMappingStep", "EvaluationRunDataOutput", "EvaluationRunDataStepInput", "EvaluationRunDataStepInputKey", "EvaluationRunDataStepInputOrigin", "EvaluationRunDataStepInputType", "EvaluationRunDataStepOutput", "EvaluationRunDataStepOutputOrigin", "EvaluationRunDataStepOutputType", "EvaluationRunEdit", "EvaluationRunFlags", "EvaluationRunIdResponse", "EvaluationRunIdsRequest", "EvaluationRunIdsResponse", "EvaluationRunQuery", "EvaluationRunQueryFlags", "EvaluationRunResponse", "EvaluationRunsResponse", "EvaluationScenario", "EvaluationScenarioCreate", "EvaluationScenarioEdit", "EvaluationScenarioIdResponse", "EvaluationScenarioIdsResponse", "EvaluationScenarioQuery", "EvaluationScenarioResponse", "EvaluationScenariosResponse", "EvaluationStatus", "Evaluator", "EvaluatorArtifactFlags", "EvaluatorArtifactQueryFlags", "EvaluatorCatalogPreset", "EvaluatorCatalogPresetResponse", "EvaluatorCatalogPresetsResponse", "EvaluatorCatalogTemplate", "EvaluatorCatalogTemplateResponse", "EvaluatorCatalogTemplatesResponse", "EvaluatorCatalogType", "EvaluatorCatalogTypesResponse", "EvaluatorCreate", "EvaluatorEdit", "EvaluatorFlags", "EvaluatorQuery", "EvaluatorResponse", "EvaluatorRevisionCommit", "EvaluatorRevisionCreate", "EvaluatorRevisionDataInput", "EvaluatorRevisionDataInputHeadersValue", "EvaluatorRevisionDataInputRuntime", "EvaluatorRevisionDataOutput", "EvaluatorRevisionDataOutputHeadersValue", "EvaluatorRevisionDataOutputRuntime", "EvaluatorRevisionEdit", "EvaluatorRevisionFlags", "EvaluatorRevisionInput", "EvaluatorRevisionOutput", "EvaluatorRevisionQuery", "EvaluatorRevisionQueryFlags", "EvaluatorRevisionResolveResponse", "EvaluatorRevisionResponse", "EvaluatorRevisionsLog", "EvaluatorRevisionsResponse", "EvaluatorTemplate", "EvaluatorTemplatesResponse", "EvaluatorVariant", "EvaluatorVariantCreate", "EvaluatorVariantEdit", "EvaluatorVariantFlags", "EvaluatorVariantFork", "EvaluatorVariantResponse", "EvaluatorVariantsResponse", "EvaluatorsResponse", "Event", "EventQuery", "EventType", "EventsQueryResponse", "ExistenceOperator", "FetchLegacyAnalyticsRequestNewest", "FetchLegacyAnalyticsRequestOldest", "FetchSimpleTestsetToFileRequestFileType", "FetchTestsetRevisionToFileRequestFileType", "FilteringInput", "FilteringInputConditionsItem", "FilteringOutput", "FilteringOutputConditionsItem", "Focus", "Folder", "FolderCreate", "FolderEdit", "FolderIdResponse", "FolderKind", "FolderQuery", "FolderQueryKinds", "FolderResponse", "FoldersResponse", "Format", "Formatting", typing.Any, typing.Any, "GatewayToolConfig", "GatewayToolConfigPermission", "HarnessKind", "Header", "HttpValidationError", "InviteRequest", "Invocation", "InvocationCreate", "InvocationCreateLinks", "InvocationEdit", "InvocationEditLinks", "InvocationLinkResponse", "InvocationLinks", "InvocationQuery", "InvocationQueryLinks", "InvocationResponse", "InvocationsResponse", "JsonSchemasInput", "JsonSchemasOutput", typing.Any, typing.Any, "LegacyLifecycleDto", "ListApiKeysResponse", "ListOperator", "ListOptions", "LogicalOperator", "MetricSpec", "MetricType", "MetricsBucket", "Mount", "MountCreate", "MountCredentials", "MountCredentialsResponse", "MountData", "MountEdit", "MountFileDeletedResponse", "MountFileWrittenResponse", "MountFlags", "MountFolderCreatedResponse", "MountQuery", "MountResponse", "MountsResponse", "NumericOperator", "OTelEventInput", "OTelEventInputTimestamp", "OTelEventOutput", "OTelEventOutputTimestamp", "OTelHashInput", "OTelHashOutput", "OTelLinkInput", "OTelLinkOutput", "OTelLinksResponse", "OTelReferenceInput", "OTelReferenceOutput", "OTelSpanKind", "OTelStatusCode", "OTelTracingRequest", "OTelTracingResponse", "OldAnalyticsResponse", "Organization", "OrganizationDetails", "OrganizationDomainResponse", "OrganizationProviderResponse", "OrganizationUpdate", "Permission", "PlaygroundBuildKitContext", "ProjectsResponse", "QueriesResponse", "Query", "QueryApplicationVariantsRequestOrder", "QueryCreate", "QueryEdit", "QueryEnvironmentRevisionsRequestOrder", "QueryEnvironmentVariantsRequestOrder", "QueryEnvironmentsRequestOrder", "QueryEvaluatorVariantsRequestOrder", "QueryFlags", "QueryQueriesRequestOrder", "QueryQueryFlags", "QueryResponse", "QueryRevision", "QueryRevisionCommit", "QueryRevisionCreate", "QueryRevisionDataInput", "QueryRevisionDataOutput", "QueryRevisionEdit", "QueryRevisionQuery", "QueryRevisionResponse", "QueryRevisionsLog", "QueryRevisionsResponse", "QuerySpansAnalyticsRequestNewest", "QuerySpansAnalyticsRequestOldest", "QueryVariant", "QueryVariantCreate", "QueryVariantEdit", "QueryVariantFork", "QueryVariantQuery", "QueryVariantResponse", "QueryVariantsResponse", "QueryWorkflowRevisionsRequestOrder", "QueryWorkflowVariantsRequestOrder", "QueryWorkflowsRequestOrder", "Reference", "ReferenceRequestModelInput", "ReferenceRequestModelOutput", "RequestType", "ResolutionInfo", "ResolvedTool", "RetrievalInfo", "SecretDto", "SecretDtoData", "SecretKind", "SecretResponseDto", "SecretResponseDtoData", "Selector", "SessionHeartbeatResult", "SessionIdsResponse", "SessionInteraction", "SessionInteractionData", "SessionInteractionFlags", "SessionInteractionKind", "SessionInteractionQuery", "SessionInteractionQueryFlags", "SessionInteractionResponse", "SessionInteractionStatus", "SessionInteractionsResponse", "SessionMount", "SessionMountQuery", "SessionMountsResponse", "SessionRecord", "SessionRecordResponse", "SessionRecordsQueryResponse", "SessionResponse", "SessionStream", "SessionStreamCommandResponse", "SessionStreamFlags", "SessionStreamHeaderEdit", "SessionStreamResponse", "SessionStreamsResponse", "SessionTurn", "SessionTurnQuery", "SessionTurnResponse", "SessionTurnsResponse", "SessionsResponse", "SimpleApplication", "SimpleApplicationAdditionalContext", "SimpleApplicationCreate", "SimpleApplicationDataInput", "SimpleApplicationDataInputHeadersValue", "SimpleApplicationDataInputRuntime", "SimpleApplicationDataOutput", "SimpleApplicationDataOutputHeadersValue", "SimpleApplicationDataOutputRuntime", "SimpleApplicationEdit", "SimpleApplicationFlags", "SimpleApplicationQuery", "SimpleApplicationQueryFlags", "SimpleApplicationResponse", "SimpleApplicationsResponse", "SimpleEnvironment", "SimpleEnvironmentCreate", "SimpleEnvironmentEdit", "SimpleEnvironmentQuery", "SimpleEnvironmentResponse", "SimpleEnvironmentsResponse", "SimpleEvaluation", "SimpleEvaluationCreate", "SimpleEvaluationData", "SimpleEvaluationDataApplicationSteps", "SimpleEvaluationDataApplicationStepsOneValue", "SimpleEvaluationDataEvaluatorSteps", "SimpleEvaluationDataEvaluatorStepsOneValue", "SimpleEvaluationDataQuerySteps", "SimpleEvaluationDataQueryStepsOneValue", "SimpleEvaluationDataTestsetSteps", "SimpleEvaluationDataTestsetStepsOneValue", "SimpleEvaluationEdit", "SimpleEvaluationIdResponse", "SimpleEvaluationQuery", "SimpleEvaluationResponse", "SimpleEvaluationsResponse", "SimpleEvaluator", "SimpleEvaluatorCreate", "SimpleEvaluatorDataInput", "SimpleEvaluatorDataInputHeadersValue", "SimpleEvaluatorDataInputRuntime", "SimpleEvaluatorDataOutput", "SimpleEvaluatorDataOutputHeadersValue", "SimpleEvaluatorDataOutputRuntime", "SimpleEvaluatorEdit", "SimpleEvaluatorFlags", "SimpleEvaluatorQuery", "SimpleEvaluatorQueryFlags", "SimpleEvaluatorResponse", "SimpleEvaluatorsResponse", "SimpleQueriesResponse", "SimpleQuery", "SimpleQueryCreate", "SimpleQueryEdit", "SimpleQueryQuery", "SimpleQueryResponse", "SimpleQueue", "SimpleQueueCreate", "SimpleQueueData", "SimpleQueueDataEvaluators", "SimpleQueueDataEvaluatorsOneValue", "SimpleQueueIdResponse", "SimpleQueueIdsResponse", "SimpleQueueKind", "SimpleQueueQuery", "SimpleQueueResponse", "SimpleQueueScenariosQuery", "SimpleQueueScenariosResponse", "SimpleQueueSettings", "SimpleQueuesResponse", "SimpleTestset", "SimpleTestsetCreate", "SimpleTestsetEdit", "SimpleTestsetQuery", "SimpleTestsetResponse", "SimpleTestsetsResponse", "SimpleTrace", "SimpleTraceChannel", "SimpleTraceCreate", "SimpleTraceCreateLinks", "SimpleTraceEdit", "SimpleTraceEditLinks", "SimpleTraceKind", "SimpleTraceLinkResponse", "SimpleTraceLinks", "SimpleTraceOrigin", "SimpleTraceQuery", "SimpleTraceQueryLinks", "SimpleTraceReferences", "SimpleTraceResponse", "SimpleTracesResponse", "SimpleWorkflow", "SimpleWorkflowCreate", "SimpleWorkflowDataInput", "SimpleWorkflowDataInputHeadersValue", "SimpleWorkflowDataInputRuntime", "SimpleWorkflowDataOutput", "SimpleWorkflowDataOutputHeadersValue", "SimpleWorkflowDataOutputRuntime", "SimpleWorkflowEdit", "SimpleWorkflowFlags", "SimpleWorkflowQuery", "SimpleWorkflowQueryFlags", "SimpleWorkflowResponse", "SimpleWorkflowsResponse", "SpanInput", "SpanInputEndTime", "SpanInputStartTime", "SpanOutput", "SpanOutputEndTime", "SpanOutputStartTime", "SpanResponse", "SpanType", "SpansNodeInput", "SpansNodeInputEndTime", "SpansNodeInputSpansValue", "SpansNodeInputStartTime", "SpansNodeOutput", "SpansNodeOutputEndTime", "SpansNodeOutputSpansValue", "SpansNodeOutputStartTime", "SpansResponse", "SpansTreeInput", "SpansTreeInputSpansValue", "SpansTreeOutput", "SpansTreeOutputSpansValue", "SsoProviderDto", "SsoProviderInfo", "SsoProviderSettingsDto", "SsoProviders", "StandardProviderDto", "StandardProviderKind", "StandardProviderSettingsDto", "Status", "StringOperator", "TestcaseInput", "TestcaseOutput", "TestcaseResponse", "TestcasesResponse", "Testset", "TestsetCreate", "TestsetEdit", "TestsetFlags", "TestsetQuery", "TestsetResponse", "TestsetRevision", "TestsetRevisionCommit", "TestsetRevisionCreate", "TestsetRevisionDataInput", "TestsetRevisionDataOutput", "TestsetRevisionDelta", "TestsetRevisionDeltaColumns", "TestsetRevisionDeltaRows", "TestsetRevisionEdit", "TestsetRevisionQuery", "TestsetRevisionResponse", "TestsetRevisionsLog", "TestsetRevisionsResponse", "TestsetVariant", "TestsetVariantCreate", "TestsetVariantEdit", "TestsetVariantFork", "TestsetVariantQuery", "TestsetVariantResponse", "TestsetVariantsResponse", "TestsetsResponse", "TextOptions", "ToolAuthScheme", "ToolCallData", "ToolCallFunction", "ToolCallResponse", "ToolCatalogAction", "ToolCatalogActionDetails", "ToolCatalogActionResponse", "ToolCatalogActionResponseAction", "ToolCatalogActionsResponse", "ToolCatalogActionsResponseActionsItem", "ToolCatalogCategoriesResponse", "ToolCatalogCategory", "ToolCatalogIntegration", "ToolCatalogIntegrationDetails", "ToolCatalogIntegrationResponse", "ToolCatalogIntegrationResponseIntegration", "ToolCatalogIntegrationsResponse", "ToolCatalogIntegrationsResponseIntegrationsItem", "ToolCatalogProvider", "ToolCatalogProviderDetails", "ToolCatalogProviderResponse", "ToolCatalogProviderResponseProvider", "ToolCatalogProvidersResponse", "ToolCatalogProvidersResponseProvidersItem", "ToolConnection", "ToolConnectionCreate", "ToolConnectionCreateData", "ToolConnectionResponse", "ToolConnectionState", "ToolConnectionStatus", "ToolConnectionsResponse", "ToolProviderKind", "ToolResolveRequestToolsItem", "ToolResolveRequestToolsItem_Builtin", "ToolResolveRequestToolsItem_Gateway", "ToolResolveResponse", "ToolResult", "ToolResultData", "TraceIdResponse", "TraceIdsResponse", "TraceInput", "TraceInputSpansValue", "TraceOutput", "TraceOutputSpansValue", "TraceRequest", "TraceResponse", "TraceType", "TracesRequest", "TracesResponse", "TracingQuery", "TriggerAuthScheme", "TriggerCapabilitiesResult", "TriggerCapability", "TriggerCapabilityConnection", "TriggerCatalogEvent", "TriggerCatalogEventDetails", "TriggerCatalogEventResponse", "TriggerCatalogEventsResponse", "TriggerCatalogIntegration", "TriggerCatalogIntegrationResponse", "TriggerCatalogIntegrationsResponse", "TriggerCatalogProvider", "TriggerCatalogProviderResponse", "TriggerCatalogProvidersResponse", "TriggerConnectAffordance", "TriggerConnection", "TriggerConnectionCreate", "TriggerConnectionCreateData", "TriggerConnectionRequirement", "TriggerConnectionResponse", "TriggerConnectionStatus", "TriggerConnectionsResponse", "TriggerDeliveriesResponse", "TriggerDelivery", "TriggerDeliveryData", "TriggerDeliveryQuery", "TriggerDeliveryResponse", "TriggerDiscoveryConnectionState", "TriggerDiscoveryGuidance", "TriggerEventAck", "TriggerProviderKind", "TriggerSchedule", "TriggerScheduleCreate", "TriggerScheduleData", "TriggerScheduleDataInputsFields", "TriggerScheduleEdit", "TriggerScheduleFlags", "TriggerScheduleQuery", "TriggerScheduleResponse", "TriggerSchedulesResponse", "TriggerSubscription", "TriggerSubscriptionCreate", "TriggerSubscriptionCreateRequest", "TriggerSubscriptionData", "TriggerSubscriptionDataInputsFields", "TriggerSubscriptionEdit", "TriggerSubscriptionFlags", "TriggerSubscriptionQuery", "TriggerSubscriptionResponse", "TriggerSubscriptionsResponse", "UnprocessableEntityError", "UserIdsResponse", "ValidationError", "ValidationErrorLocItem", "WebhookDeliveriesResponse", "WebhookDelivery", "WebhookDeliveryCreate", "WebhookDeliveryData", "WebhookDeliveryQuery", "WebhookDeliveryResponse", "WebhookDeliveryResponseInfo", "WebhookEventType", "WebhookProviderDto", "WebhookProviderSettingsDto", "WebhookSubscription", "WebhookSubscriptionCreate", "WebhookSubscriptionData", "WebhookSubscriptionDataAuthMode", "WebhookSubscriptionEdit", "WebhookSubscriptionFlags", "WebhookSubscriptionQuery", "WebhookSubscriptionResponse", "WebhookSubscriptionTestRequestSubscription", "WebhookSubscriptionsResponse", "Windowing", "WindowingOrder", "Workflow", "WorkflowArtifactFlags", "WorkflowCatalogFlags", "WorkflowCatalogHarness", "WorkflowCatalogHarnessResponse", "WorkflowCatalogHarnessesResponse", "WorkflowCatalogPreset", "WorkflowCatalogPresetResponse", "WorkflowCatalogPresetsResponse", "WorkflowCatalogTemplate", "WorkflowCatalogTemplateResponse", "WorkflowCatalogTemplatesResponse", "WorkflowCatalogType", "WorkflowCatalogTypeResponse", "WorkflowCatalogTypesResponse", "WorkflowCreate", "WorkflowEdit", "WorkflowFlags", "WorkflowRequestData", "WorkflowResponse", "WorkflowRevisionCommit", "WorkflowRevisionCreate", "WorkflowRevisionDataInput", "WorkflowRevisionDataInputHeadersValue", "WorkflowRevisionDataInputRuntime", "WorkflowRevisionDataOutput", "WorkflowRevisionDataOutputHeadersValue", "WorkflowRevisionDataOutputRuntime", "WorkflowRevisionDelta", "WorkflowRevisionEdit", "WorkflowRevisionFlags", "WorkflowRevisionInput", "WorkflowRevisionOutput", "WorkflowRevisionResolveResponse", "WorkflowRevisionResponse", "WorkflowRevisionsLog", "WorkflowRevisionsResponse", "WorkflowVariant", "WorkflowVariantCreate", "WorkflowVariantEdit", "WorkflowVariantFlags", "WorkflowVariantFork", "WorkflowVariantResponse", "WorkflowVariantsResponse", "WorkflowsResponse", "Workspace", "WorkspaceMemberResponse", "WorkspacePermission", "WorkspaceResponse", "access", "annotations", "applications", "billing", "environments", "evaluations", "evaluators", "events", "folders", "invocations", "keys", "legacy", "mounts", "organizations", "projects", "queries", "secrets", "sessions", "status", "testcases", "testsets", "tools", "traces", "triggers", "users", "webhooks", "workflows", "workspaces"] | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Invalid typing.Any elements in _dynamic_imports and __all__.
Both files contain unquoted typing.Any objects instead of strings in the __all__ lists and _dynamic_imports keys. In Python, __all__ must be a sequence of strings; including non-string objects causes a TypeError when from module import * is executed and will break static analysis and type checkers. This is likely a Fern generator issue where certain schemas (e.g., FullJsonInput, LabelJsonOutput) resolve to Any and are written verbatim.
clients/python/agenta_client/__init__.py#L41-L41: Fix the generator config or OpenAPI spec so that valid string aliases are produced instead oftyping.Any.clients/python/agenta_client/types/__init__.py#L797-L797: Update the generator configuration to avoid leakingtyping.Anyinto__all__here as well.
📍 Affects 2 files
clients/python/agenta_client/__init__.py#L41-L41(this comment)clients/python/agenta_client/types/__init__.py#L797-L797
| if agent_id: | ||
| span.set_attribute("id", agent_id, namespace="agent") | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add fallback for raw OpenTelemetry spans.
Similar to store_session, if span is a raw opentelemetry.trace.Span (which does not accept the namespace kwarg), set_attribute will raise a TypeError. This results in the agent_id attribute being silently dropped or causing a crash (depending on the implementation of suppress()).
Please add a try...except TypeError block to handle raw spans by setting "agent.id". Note that the store_user method appears to have this same issue and could also benefit from a similar fallback.
🐛 Proposed fix
- if agent_id:
- span.set_attribute("id", agent_id, namespace="agent")
+ if agent_id:
+ try:
+ span.set_attribute("id", agent_id, namespace="agent")
+ except TypeError:
+ span.set_attribute("agent.id", agent_id)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if agent_id: | |
| span.set_attribute("id", agent_id, namespace="agent") | |
| if agent_id: | |
| try: | |
| span.set_attribute("id", agent_id, namespace="agent") | |
| except TypeError: | |
| span.set_attribute("agent.id", agent_id) |
mmabrouk
left a comment
There was a problem hiding this comment.
Reviewed after the rebase, the live QA round, and the ingest fix. Verdict: the backend port is faithful and the append-only turns model is the right foundation. Three verified reconciliations with v0.105.x are correct (HarnessKind rename + model_ref threading, the EndpointResolutionError export, the surgical greenlet lock edit). The span-id contract fix is correctly typed at every layer with contract tests on both sides.
One substantive request (inline below): the (project_id, session_id, turn_index) index should be UNIQUE while the migration is still unreleased. Two other items already flagged in the body for JP's judgment, not blockers: the apply_windowing helper auto-picking the always-NULL span_id column as the turns cursor, and the 017 migration dropping session_states rows without conversion (should be a deliberate product decision).
| op.create_index( | ||
| "ix_session_turns_project_id_session_id_turn_index", | ||
| "session_turns", | ||
| ["project_id", "session_id", "turn_index"], |
There was a problem hiding this comment.
Recommend unique=True on this index while the migration is still unreleased. Append-only turns are the concurrency substrate for everything multi-surface (two writers racing the same turn index must conflict cleanly, with the loser retrying as the next index), and today nothing prevents a duplicate (session_id, turn_index) pair, which would make latest_turn reads ambiguous. As a bonus it also converts an at-least-once append retry that races its own success into a harmless conflict instead of a silent duplicate row. One-line change now; a data-dedup migration later.
9e2044c to
3f975df
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8c1a7f80-aad4-4ac5-b93c-f37a35c9853d
⛔ Files ignored due to path filters (51)
api/uv.lockis excluded by!**/*.lockweb/packages/agenta-api-client/src/generated/api/resources/mounts/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/mounts/client/requests/MountQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/ArchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/DeleteSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/FetchTurnRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionDetachRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionHeartbeatRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionRecordIngestRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnAppendRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SetSessionStreamHeaderRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/UnarchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CommandMode.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessKind.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessSessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/Mount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountCreate.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResponseModel.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionInteraction.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionState.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateFlags.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateUpsertRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStream.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamHeaderEdit.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurn.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/WorkflowRequestData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/index.tsis excluded by!**/generated/**
📒 Files selected for processing (174)
api/entrypoints/routers.pyapi/oss/databases/postgres/migrations/core/env.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.pyapi/oss/src/apis/fastapi/mounts/router.pyapi/oss/src/apis/fastapi/mounts/utils.pyapi/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.pyapi/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.pyapi/oss/src/apis/fastapi/otlp/extractors/span_data_builders.pyapi/oss/src/apis/fastapi/otlp/utils/serialization.pyapi/oss/src/apis/fastapi/sessions/models.pyapi/oss/src/apis/fastapi/sessions/router.pyapi/oss/src/apis/fastapi/tracing/router.pyapi/oss/src/core/mounts/dtos.pyapi/oss/src/core/mounts/interfaces.pyapi/oss/src/core/mounts/service.pyapi/oss/src/core/sessions/dtos.pyapi/oss/src/core/sessions/interactions/dtos.pyapi/oss/src/core/sessions/interactions/interfaces.pyapi/oss/src/core/sessions/interactions/service.pyapi/oss/src/core/sessions/records/dtos.pyapi/oss/src/core/sessions/service.pyapi/oss/src/core/sessions/states/dtos.pyapi/oss/src/core/sessions/states/interfaces.pyapi/oss/src/core/sessions/states/service.pyapi/oss/src/core/sessions/streams/dtos.pyapi/oss/src/core/sessions/streams/interfaces.pyapi/oss/src/core/sessions/streams/runner_client.pyapi/oss/src/core/sessions/streams/service.pyapi/oss/src/core/sessions/turns/__init__.pyapi/oss/src/core/sessions/turns/dtos.pyapi/oss/src/core/sessions/turns/interfaces.pyapi/oss/src/core/sessions/turns/service.pyapi/oss/src/core/sessions/turns/types.pyapi/oss/src/core/shared/dtos.pyapi/oss/src/core/tracing/dtos.pyapi/oss/src/core/tracing/service.pyapi/oss/src/core/tracing/utils/filtering.pyapi/oss/src/core/tracing/utils/trees.pyapi/oss/src/dbs/postgres/mounts/dao.pyapi/oss/src/dbs/postgres/mounts/dbas.pyapi/oss/src/dbs/postgres/mounts/dbes.pyapi/oss/src/dbs/postgres/mounts/mappings.pyapi/oss/src/dbs/postgres/sessions/interactions/dao.pyapi/oss/src/dbs/postgres/sessions/records/dao.pyapi/oss/src/dbs/postgres/sessions/records/dbas.pyapi/oss/src/dbs/postgres/sessions/records/dbes.pyapi/oss/src/dbs/postgres/sessions/records/mappings.pyapi/oss/src/dbs/postgres/sessions/states/dao.pyapi/oss/src/dbs/postgres/sessions/states/dbes.pyapi/oss/src/dbs/postgres/sessions/states/mappings.pyapi/oss/src/dbs/postgres/sessions/streams/dao.pyapi/oss/src/dbs/postgres/sessions/streams/dbes.pyapi/oss/src/dbs/postgres/sessions/streams/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/__init__.pyapi/oss/src/dbs/postgres/sessions/turns/dao.pyapi/oss/src/dbs/postgres/sessions/turns/dbas.pyapi/oss/src/dbs/postgres/sessions/turns/dbes.pyapi/oss/src/dbs/postgres/sessions/turns/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/utils.pyapi/oss/src/dbs/postgres/tracing/dao.pyapi/oss/src/dbs/postgres/tracing/dbas.pyapi/oss/src/dbs/postgres/tracing/dbes.pyapi/oss/src/dbs/postgres/tracing/mappings.pyapi/oss/src/dbs/postgres/tracing/utils.pyapi/oss/src/utils/env.pyapi/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.pyapi/oss/tests/pytest/acceptance/session_states/test_session_states_basics.pyapi/oss/tests/pytest/acceptance/sessions/__init__.pyapi/oss/tests/pytest/acceptance/sessions/test_archive_unarchive.pyapi/oss/tests/pytest/acceptance/sessions/test_records_ingest_contract.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.pyapi/oss/tests/pytest/unit/mounts/test_agent_id_backfill.pyapi/oss/tests/pytest/unit/mounts/test_agent_mounts.pyapi/oss/tests/pytest/unit/otlp/test_logfire_adapter.pyapi/oss/tests/pytest/unit/session_states/__init__.pyapi/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.pyapi/oss/tests/pytest/unit/session_states/test_session_id_validation.pyapi/oss/tests/pytest/unit/sessions/conftest.pyapi/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.pyapi/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.pyapi/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.pyapi/oss/tests/pytest/unit/sessions/test_mounts_agent_id_backfill.pyapi/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.pyapi/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.pyapi/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.pyapi/oss/tests/pytest/unit/sessions/test_runner_client_kill.pyapi/oss/tests/pytest/unit/sessions/test_sessions_root_service.pyapi/oss/tests/pytest/unit/sessions/test_stream_header_merge.pyapi/oss/tests/pytest/unit/sessions/test_turns_dao.pyapi/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.pyapi/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.pyapi/oss/tests/pytest/unit/sessions/test_wp5_root_router.pyapi/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.pyapi/oss/tests/pytest/unit/tracing/utils/test_trees.pyapi/pyproject.tomlclients/python/agenta_client/__init__.pyclients/python/agenta_client/mounts/client.pyclients/python/agenta_client/mounts/raw_client.pyclients/python/agenta_client/sessions/client.pyclients/python/agenta_client/sessions/raw_client.pyclients/python/agenta_client/types/__init__.pyclients/python/agenta_client/types/harness_kind.pyclients/python/agenta_client/types/harness_session_record.pyclients/python/agenta_client/types/mount.pyclients/python/agenta_client/types/mount_create.pyclients/python/agenta_client/types/mount_query.pyclients/python/agenta_client/types/session_heartbeat_result.pyclients/python/agenta_client/types/session_interaction.pyclients/python/agenta_client/types/session_mount.pyclients/python/agenta_client/types/session_mount_query.pyclients/python/agenta_client/types/session_record.pyclients/python/agenta_client/types/session_response.pyclients/python/agenta_client/types/session_state.pyclients/python/agenta_client/types/session_state_data.pyclients/python/agenta_client/types/session_state_upsert_request.pyclients/python/agenta_client/types/session_stream.pyclients/python/agenta_client/types/session_stream_command_response.pyclients/python/agenta_client/types/session_stream_header_edit.pyclients/python/agenta_client/types/session_stream_response.pyclients/python/agenta_client/types/session_streams_response.pyclients/python/agenta_client/types/session_turn.pyclients/python/agenta_client/types/session_turn_query.pyclients/python/agenta_client/types/session_turn_response.pyclients/python/agenta_client/types/session_turns_response.pyclients/python/agenta_client/types/sessions_response.pyclients/python/agenta_client/types/span_input.pyclients/python/agenta_client/types/span_output.pyclients/python/agenta_client/types/spans_node_input.pyclients/python/agenta_client/types/spans_node_output.pyclients/python/agenta_client/types/workflow_request_data.pydocs/docs/self-host/reference/01-configuration.mdxhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/ee/docker-compose.gh.ymlhosting/docker-compose/oss/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.gh.ymlhosting/kubernetes/helm/templates/api-deployment.yamlsdks/python/agenta/sdk/agents/__init__.pysdks/python/agenta/sdk/agents/adapters/harnesses.pysdks/python/agenta/sdk/agents/adapters/local.pysdks/python/agenta/sdk/agents/adapters/sandbox_agent.pysdks/python/agenta/sdk/agents/dtos.pysdks/python/agenta/sdk/agents/errors.pysdks/python/agenta/sdk/agents/interfaces.pysdks/python/agenta/sdk/agents/utils/wire.pysdks/python/agenta/sdk/engines/tracing/tracing.pysdks/python/agenta/sdk/middlewares/running/normalizer.pysdks/python/agenta/sdk/models/tracing.pysdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.pysdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.pysdks/python/oss/tests/pytest/unit/agents/conftest.pysdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.pysdks/python/oss/tests/pytest/unit/agents/skills/test_skills_e2e.pysdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.pysdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.pysdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.pysdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.pysdks/python/oss/tests/pytest/unit/agents/test_harness_identity.pysdks/python/oss/tests/pytest/unit/agents/test_wire_contract.pysdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.pysdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.pysdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.pysdks/python/oss/tests/pytest/unit/test_tracing_store_agent.pyservices/oss/tests/pytest/unit/agent/conftest.pyweb/oss/src/components/SessionInspector/api.tsweb/packages/agenta-entities/src/session/api/api.tsweb/packages/agenta-entities/src/session/core/liveness.tsweb/packages/agenta-entities/src/session/core/schema.tsweb/packages/agenta-entities/src/session/index.ts
💤 Files with no reviewable changes (18)
- web/packages/agenta-entities/src/session/index.ts
- api/oss/tests/pytest/unit/session_states/test_session_id_validation.py
- clients/python/agenta_client/types/session_state.py
- api/oss/src/core/sessions/states/service.py
- api/oss/src/core/sessions/states/interfaces.py
- api/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.py
- api/oss/databases/postgres/migrations/core/env.py
- api/oss/src/dbs/postgres/sessions/states/dbes.py
- clients/python/agenta_client/types/session_state_data.py
- api/oss/src/dbs/postgres/sessions/states/dao.py
- api/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.py
- api/oss/tests/pytest/acceptance/session_states/test_session_states_basics.py
- clients/python/agenta_client/types/session_state_upsert_request.py
- api/oss/src/dbs/postgres/sessions/states/mappings.py
- clients/python/agenta_client/types/harness_session_record.py
- api/oss/src/core/sessions/states/dtos.py
- web/packages/agenta-entities/src/session/api/api.ts
- web/packages/agenta-entities/src/session/core/schema.ts
🚧 Files skipped from review as they are similar to previous changes (130)
- api/oss/src/dbs/postgres/sessions/records/mappings.py
- sdks/python/agenta/sdk/agents/init.py
- clients/python/agenta_client/types/mount.py
- api/oss/src/core/sessions/interactions/interfaces.py
- api/oss/src/core/sessions/turns/types.py
- clients/python/agenta_client/types/span_output.py
- api/oss/src/core/sessions/interactions/service.py
- clients/python/agenta_client/types/mount_create.py
- api/oss/src/dbs/postgres/sessions/turns/dbes.py
- clients/python/agenta_client/types/session_heartbeat_result.py
- clients/python/agenta_client/types/session_record.py
- hosting/kubernetes/helm/templates/api-deployment.yaml
- sdks/python/agenta/sdk/agents/errors.py
- clients/python/agenta_client/types/session_stream_response.py
- web/packages/agenta-entities/src/session/core/liveness.ts
- sdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.py
- sdks/python/agenta/sdk/models/tracing.py
- api/oss/src/dbs/postgres/tracing/dbas.py
- api/oss/src/dbs/postgres/mounts/dbes.py
- clients/python/agenta_client/types/harness_kind.py
- clients/python/agenta_client/types/session_stream_command_response.py
- api/oss/src/apis/fastapi/tracing/router.py
- clients/python/agenta_client/types/session_mount.py
- api/oss/src/core/sessions/dtos.py
- sdks/python/agenta/sdk/agents/adapters/local.py
- api/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.py
- sdks/python/agenta/sdk/engines/tracing/tracing.py
- clients/python/agenta_client/types/session_mount_query.py
- api/oss/src/dbs/postgres/tracing/dbes.py
- api/oss/src/core/sessions/turns/interfaces.py
- api/oss/src/dbs/postgres/sessions/turns/utils.py
- api/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.py
- clients/python/agenta_client/types/session_turn.py
- clients/python/agenta_client/types/session_turn_query.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.py
- clients/python/agenta_client/types/mount_query.py
- sdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.py
- api/oss/src/dbs/postgres/sessions/turns/dbas.py
- clients/python/agenta_client/types/workflow_request_data.py
- api/oss/src/apis/fastapi/otlp/utils/serialization.py
- api/oss/src/dbs/postgres/mounts/dbas.py
- api/oss/src/dbs/postgres/tracing/utils.py
- api/oss/src/core/tracing/utils/trees.py
- sdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.py
- hosting/docker-compose/ee/docker-compose.dev.yml
- sdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.py
- api/oss/src/dbs/postgres/mounts/mappings.py
- api/oss/src/dbs/postgres/sessions/turns/mappings.py
- clients/python/agenta_client/types/span_input.py
- clients/python/agenta_client/types/session_stream_header_edit.py
- web/oss/src/components/SessionInspector/api.ts
- clients/python/agenta_client/types/session_response.py
- api/oss/src/dbs/postgres/sessions/records/dbes.py
- api/oss/tests/pytest/unit/sessions/conftest.py
- docs/docs/self-host/reference/01-configuration.mdx
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.py
- api/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.py
- clients/python/agenta_client/types/sessions_response.py
- api/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.py
- clients/python/agenta_client/types/session_turns_response.py
- api/oss/src/core/sessions/streams/runner_client.py
- sdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.py
- api/oss/src/core/sessions/interactions/dtos.py
- api/oss/tests/pytest/unit/otlp/test_logfire_adapter.py
- sdks/python/agenta/sdk/agents/utils/wire.py
- sdks/python/agenta/sdk/agents/adapters/sandbox_agent.py
- hosting/docker-compose/ee/docker-compose.gh.yml
- api/oss/src/core/sessions/records/dtos.py
- api/oss/src/apis/fastapi/otlp/extractors/span_data_builders.py
- api/oss/src/apis/fastapi/mounts/utils.py
- api/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.py
- api/oss/src/dbs/postgres/sessions/interactions/dao.py
- api/oss/src/core/tracing/utils/filtering.py
- hosting/docker-compose/oss/docker-compose.gh.yml
- api/oss/src/core/mounts/interfaces.py
- clients/python/agenta_client/types/session_stream.py
- api/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.py
- api/oss/src/core/sessions/turns/dtos.py
- clients/python/agenta_client/types/spans_node_output.py
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.py
- sdks/python/agenta/sdk/agents/interfaces.py
- api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
- api/oss/src/core/sessions/service.py
- api/oss/src/dbs/postgres/sessions/streams/mappings.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.py
- sdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.py
- api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
- clients/python/agenta_client/types/session_streams_response.py
- sdks/python/oss/tests/pytest/unit/test_tracing_store_agent.py
- api/oss/src/core/tracing/dtos.py
- api/oss/src/dbs/postgres/mounts/dao.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.py
- api/oss/src/core/mounts/service.py
- api/oss/src/core/mounts/dtos.py
- api/pyproject.toml
- clients/python/agenta_client/mounts/raw_client.py
- sdks/python/oss/tests/pytest/unit/agents/conftest.py
- api/oss/tests/pytest/unit/sessions/test_stream_header_merge.py
- api/oss/tests/pytest/unit/tracing/utils/test_trees.py
- api/oss/tests/pytest/unit/sessions/test_turns_dao.py
- api/oss/src/apis/fastapi/mounts/router.py
- api/oss/tests/pytest/unit/mounts/test_agent_mounts.py
- sdks/python/oss/tests/pytest/unit/agents/skills/test_skills_e2e.py
- clients/python/agenta_client/types/session_turn_response.py
- api/oss/src/dbs/postgres/sessions/records/dao.py
- sdks/python/agenta/sdk/middlewares/running/normalizer.py
- api/oss/src/dbs/postgres/tracing/mappings.py
- api/oss/src/dbs/postgres/sessions/turns/dao.py
- api/oss/src/utils/env.py
- api/oss/src/core/sessions/turns/service.py
- api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.py
- clients/python/agenta_client/types/init.py
- api/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.py
- api/oss/tests/pytest/unit/sessions/test_wp5_root_router.py
- api/oss/src/core/sessions/streams/dtos.py
- clients/python/agenta_client/types/session_interaction.py
- api/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.py
- sdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.py
- api/oss/tests/pytest/unit/mounts/test_agent_id_backfill.py
- sdks/python/agenta/sdk/agents/dtos.py
- sdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.py
- api/oss/src/dbs/postgres/sessions/streams/dao.py
- api/oss/src/apis/fastapi/sessions/models.py
- sdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.py
- api/entrypoints/routers.py
- sdks/python/oss/tests/pytest/unit/agents/test_harness_identity.py
- api/oss/src/core/sessions/streams/service.py
- api/oss/src/apis/fastapi/sessions/router.py
- clients/python/agenta_client/sessions/client.py
| # Verbatim from the migration: `left(slug, 13) = '__ag__agent__'` guards, and | ||
| # `split_part(substr(slug, 14), '__', 1)` extracts. | ||
| _BACKFILL_EXPR = ( | ||
| "CASE WHEN left(:slug, 13) = '__ag__agent__' " | ||
| "THEN split_part(substr(:slug, 14), '__', 1) ELSE NULL END" | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Exercise the migration rather than a copied SQL expression.
This test executes its own _BACKFILL_EXPR, so a later defect or drift in oss000000016_add_mounts_agent_id.py would still pass. Expose and reuse the migration SQL, or run the migration against a temporary mounts table.
3f975df to
b90e9e8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
api/oss/src/core/mounts/service.py (1)
418-426: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueN+1 queries during session mount state transitions.
Both archive and unarchive methods iterate over mounts and issue sequential database update queries for each mount, resulting in an N+1 query pattern. Consider introducing bulk update operations in
mounts_daoto process these transitions in a single database round-trip.
api/oss/src/core/mounts/service.py#L418-L426: Replace the sequential loop with a bulkarchive_by_session_iddatabase operation.api/oss/src/core/mounts/service.py#L441-L450: Replace the sequential loop with a bulkunarchive_by_session_iddatabase operation.api/oss/tests/pytest/unit/sessions/test_runner_client_kill.py (1)
21-27: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winCover each partially configured runner state.
The
(None, None)case would miss an incorrectandcheck that attempts/killwhen only the URL or token is configured. Parameterize all missing-value combinations and verify no client is created.Proposed test coverage
+@pytest.mark.parametrize( + ("internal_url", "token"), + [ + (None, None), + ("http://runner:8765", None), + (None, "shared-secret"), + ], +) `@pytest.mark.asyncio` -async def test_returns_false_when_not_configured(): - with patch("oss.src.core.sessions.streams.runner_client.env") as mock_env: - mock_env.runner = _FakeRunnerEnv(internal_url=None, token=None) +async def test_returns_false_when_not_configured(internal_url, token): + with ( + patch("oss.src.core.sessions.streams.runner_client.env") as mock_env, + patch( + "oss.src.core.sessions.streams.runner_client.httpx.AsyncClient" + ) as client_cls, + ): + mock_env.runner = _FakeRunnerEnv(internal_url=internal_url, token=token) result = await kill_runner_sandbox(project_id="proj-1", session_id="sess-1") assert result is False + client_cls.assert_not_called()
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 414064b1-3022-4e0a-8d8f-f0a8fac00980
⛔ Files ignored due to path filters (51)
api/uv.lockis excluded by!**/*.lockweb/packages/agenta-api-client/src/generated/api/resources/mounts/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/mounts/client/requests/MountQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/ArchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/DeleteSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/FetchTurnRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionDetachRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionHeartbeatRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionRecordIngestRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnAppendRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SetSessionStreamHeaderRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/UnarchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CommandMode.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessKind.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessSessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/Mount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountCreate.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResponseModel.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionInteraction.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionState.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateFlags.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateUpsertRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStream.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamHeaderEdit.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurn.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/WorkflowRequestData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/index.tsis excluded by!**/generated/**
📒 Files selected for processing (174)
api/entrypoints/routers.pyapi/oss/databases/postgres/migrations/core/env.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.pyapi/oss/src/apis/fastapi/mounts/router.pyapi/oss/src/apis/fastapi/mounts/utils.pyapi/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.pyapi/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.pyapi/oss/src/apis/fastapi/otlp/extractors/span_data_builders.pyapi/oss/src/apis/fastapi/otlp/utils/serialization.pyapi/oss/src/apis/fastapi/sessions/models.pyapi/oss/src/apis/fastapi/sessions/router.pyapi/oss/src/apis/fastapi/tracing/router.pyapi/oss/src/core/mounts/dtos.pyapi/oss/src/core/mounts/interfaces.pyapi/oss/src/core/mounts/service.pyapi/oss/src/core/sessions/dtos.pyapi/oss/src/core/sessions/interactions/dtos.pyapi/oss/src/core/sessions/interactions/interfaces.pyapi/oss/src/core/sessions/interactions/service.pyapi/oss/src/core/sessions/records/dtos.pyapi/oss/src/core/sessions/service.pyapi/oss/src/core/sessions/states/dtos.pyapi/oss/src/core/sessions/states/interfaces.pyapi/oss/src/core/sessions/states/service.pyapi/oss/src/core/sessions/streams/dtos.pyapi/oss/src/core/sessions/streams/interfaces.pyapi/oss/src/core/sessions/streams/runner_client.pyapi/oss/src/core/sessions/streams/service.pyapi/oss/src/core/sessions/turns/__init__.pyapi/oss/src/core/sessions/turns/dtos.pyapi/oss/src/core/sessions/turns/interfaces.pyapi/oss/src/core/sessions/turns/service.pyapi/oss/src/core/sessions/turns/types.pyapi/oss/src/core/shared/dtos.pyapi/oss/src/core/tracing/dtos.pyapi/oss/src/core/tracing/service.pyapi/oss/src/core/tracing/utils/filtering.pyapi/oss/src/core/tracing/utils/trees.pyapi/oss/src/dbs/postgres/mounts/dao.pyapi/oss/src/dbs/postgres/mounts/dbas.pyapi/oss/src/dbs/postgres/mounts/dbes.pyapi/oss/src/dbs/postgres/mounts/mappings.pyapi/oss/src/dbs/postgres/sessions/interactions/dao.pyapi/oss/src/dbs/postgres/sessions/records/dao.pyapi/oss/src/dbs/postgres/sessions/records/dbas.pyapi/oss/src/dbs/postgres/sessions/records/dbes.pyapi/oss/src/dbs/postgres/sessions/records/mappings.pyapi/oss/src/dbs/postgres/sessions/states/dao.pyapi/oss/src/dbs/postgres/sessions/states/dbes.pyapi/oss/src/dbs/postgres/sessions/states/mappings.pyapi/oss/src/dbs/postgres/sessions/streams/dao.pyapi/oss/src/dbs/postgres/sessions/streams/dbes.pyapi/oss/src/dbs/postgres/sessions/streams/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/__init__.pyapi/oss/src/dbs/postgres/sessions/turns/dao.pyapi/oss/src/dbs/postgres/sessions/turns/dbas.pyapi/oss/src/dbs/postgres/sessions/turns/dbes.pyapi/oss/src/dbs/postgres/sessions/turns/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/utils.pyapi/oss/src/dbs/postgres/tracing/dao.pyapi/oss/src/dbs/postgres/tracing/dbas.pyapi/oss/src/dbs/postgres/tracing/dbes.pyapi/oss/src/dbs/postgres/tracing/mappings.pyapi/oss/src/dbs/postgres/tracing/utils.pyapi/oss/src/utils/env.pyapi/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.pyapi/oss/tests/pytest/acceptance/session_states/test_session_states_basics.pyapi/oss/tests/pytest/acceptance/sessions/__init__.pyapi/oss/tests/pytest/acceptance/sessions/test_archive_unarchive.pyapi/oss/tests/pytest/acceptance/sessions/test_records_ingest_contract.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.pyapi/oss/tests/pytest/unit/mounts/test_agent_id_backfill.pyapi/oss/tests/pytest/unit/mounts/test_agent_mounts.pyapi/oss/tests/pytest/unit/otlp/test_logfire_adapter.pyapi/oss/tests/pytest/unit/session_states/__init__.pyapi/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.pyapi/oss/tests/pytest/unit/session_states/test_session_id_validation.pyapi/oss/tests/pytest/unit/sessions/conftest.pyapi/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.pyapi/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.pyapi/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.pyapi/oss/tests/pytest/unit/sessions/test_mounts_agent_id_backfill.pyapi/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.pyapi/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.pyapi/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.pyapi/oss/tests/pytest/unit/sessions/test_runner_client_kill.pyapi/oss/tests/pytest/unit/sessions/test_sessions_root_service.pyapi/oss/tests/pytest/unit/sessions/test_stream_header_merge.pyapi/oss/tests/pytest/unit/sessions/test_turns_dao.pyapi/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.pyapi/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.pyapi/oss/tests/pytest/unit/sessions/test_wp5_root_router.pyapi/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.pyapi/oss/tests/pytest/unit/tracing/utils/test_trees.pyapi/pyproject.tomlclients/python/agenta_client/__init__.pyclients/python/agenta_client/mounts/client.pyclients/python/agenta_client/mounts/raw_client.pyclients/python/agenta_client/sessions/client.pyclients/python/agenta_client/sessions/raw_client.pyclients/python/agenta_client/types/__init__.pyclients/python/agenta_client/types/harness_kind.pyclients/python/agenta_client/types/harness_session_record.pyclients/python/agenta_client/types/mount.pyclients/python/agenta_client/types/mount_create.pyclients/python/agenta_client/types/mount_query.pyclients/python/agenta_client/types/session_heartbeat_result.pyclients/python/agenta_client/types/session_interaction.pyclients/python/agenta_client/types/session_mount.pyclients/python/agenta_client/types/session_mount_query.pyclients/python/agenta_client/types/session_record.pyclients/python/agenta_client/types/session_response.pyclients/python/agenta_client/types/session_state.pyclients/python/agenta_client/types/session_state_data.pyclients/python/agenta_client/types/session_state_upsert_request.pyclients/python/agenta_client/types/session_stream.pyclients/python/agenta_client/types/session_stream_command_response.pyclients/python/agenta_client/types/session_stream_header_edit.pyclients/python/agenta_client/types/session_stream_response.pyclients/python/agenta_client/types/session_streams_response.pyclients/python/agenta_client/types/session_turn.pyclients/python/agenta_client/types/session_turn_query.pyclients/python/agenta_client/types/session_turn_response.pyclients/python/agenta_client/types/session_turns_response.pyclients/python/agenta_client/types/sessions_response.pyclients/python/agenta_client/types/span_input.pyclients/python/agenta_client/types/span_output.pyclients/python/agenta_client/types/spans_node_input.pyclients/python/agenta_client/types/spans_node_output.pyclients/python/agenta_client/types/workflow_request_data.pydocs/docs/self-host/reference/01-configuration.mdxhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/ee/docker-compose.gh.ymlhosting/docker-compose/oss/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.gh.ymlhosting/kubernetes/helm/templates/api-deployment.yamlsdks/python/agenta/sdk/agents/__init__.pysdks/python/agenta/sdk/agents/adapters/harnesses.pysdks/python/agenta/sdk/agents/adapters/local.pysdks/python/agenta/sdk/agents/adapters/sandbox_agent.pysdks/python/agenta/sdk/agents/dtos.pysdks/python/agenta/sdk/agents/errors.pysdks/python/agenta/sdk/agents/interfaces.pysdks/python/agenta/sdk/agents/utils/wire.pysdks/python/agenta/sdk/engines/tracing/tracing.pysdks/python/agenta/sdk/middlewares/running/normalizer.pysdks/python/agenta/sdk/models/tracing.pysdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.pysdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.pysdks/python/oss/tests/pytest/unit/agents/conftest.pysdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.pysdks/python/oss/tests/pytest/unit/agents/skills/test_skills_e2e.pysdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.pysdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.pysdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.pysdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.pysdks/python/oss/tests/pytest/unit/agents/test_harness_identity.pysdks/python/oss/tests/pytest/unit/agents/test_wire_contract.pysdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.pysdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.pysdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.pysdks/python/oss/tests/pytest/unit/test_tracing_store_agent.pyservices/oss/tests/pytest/unit/agent/conftest.pyweb/oss/src/components/SessionInspector/api.tsweb/packages/agenta-entities/src/session/api/api.tsweb/packages/agenta-entities/src/session/core/liveness.tsweb/packages/agenta-entities/src/session/core/schema.tsweb/packages/agenta-entities/src/session/index.ts
💤 Files with no reviewable changes (17)
- api/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.py
- api/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.py
- api/oss/src/core/sessions/states/dtos.py
- web/packages/agenta-entities/src/session/core/schema.ts
- clients/python/agenta_client/types/session_state.py
- api/oss/src/dbs/postgres/sessions/states/mappings.py
- api/oss/src/dbs/postgres/sessions/states/dbes.py
- api/oss/src/dbs/postgres/sessions/states/dao.py
- api/oss/src/core/sessions/states/service.py
- api/oss/databases/postgres/migrations/core/env.py
- clients/python/agenta_client/types/harness_session_record.py
- clients/python/agenta_client/types/session_state_data.py
- web/packages/agenta-entities/src/session/index.ts
- clients/python/agenta_client/types/session_state_upsert_request.py
- api/oss/tests/pytest/unit/session_states/test_session_id_validation.py
- api/oss/src/core/sessions/states/interfaces.py
- api/oss/tests/pytest/acceptance/session_states/test_session_states_basics.py
🚧 Files skipped from review as they are similar to previous changes (140)
- clients/python/agenta_client/types/session_mount.py
- clients/python/agenta_client/types/harness_kind.py
- api/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.py
- clients/python/agenta_client/types/session_heartbeat_result.py
- api/oss/src/dbs/postgres/sessions/records/mappings.py
- hosting/docker-compose/ee/docker-compose.dev.yml
- hosting/kubernetes/helm/templates/api-deployment.yaml
- clients/python/agenta_client/types/session_streams_response.py
- api/oss/src/core/sessions/interactions/service.py
- api/oss/src/core/sessions/dtos.py
- api/oss/tests/pytest/unit/sessions/test_mounts_agent_id_backfill.py
- api/oss/src/apis/fastapi/otlp/extractors/span_data_builders.py
- clients/python/agenta_client/types/mount_query.py
- sdks/python/oss/tests/pytest/unit/test_tracing_store_agent.py
- api/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.py
- clients/python/agenta_client/types/spans_node_output.py
- api/oss/src/core/sessions/interactions/interfaces.py
- clients/python/agenta_client/types/mount_create.py
- api/oss/src/dbs/postgres/sessions/turns/dbes.py
- sdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.py
- api/oss/src/dbs/postgres/tracing/dbes.py
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.py
- clients/python/agenta_client/types/session_turn_query.py
- api/oss/src/dbs/postgres/sessions/records/dbas.py
- api/oss/src/core/mounts/interfaces.py
- web/oss/src/components/SessionInspector/api.ts
- sdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.py
- clients/python/agenta_client/types/session_turns_response.py
- clients/python/agenta_client/types/sessions_response.py
- clients/python/agenta_client/types/session_stream_response.py
- sdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.py
- hosting/docker-compose/oss/docker-compose.dev.yml
- api/oss/src/core/mounts/dtos.py
- web/packages/agenta-entities/src/session/core/liveness.ts
- api/pyproject.toml
- clients/python/agenta_client/types/session_stream_header_edit.py
- api/oss/src/dbs/postgres/sessions/turns/utils.py
- sdks/python/agenta/sdk/agents/adapters/sandbox_agent.py
- clients/python/agenta_client/types/workflow_request_data.py
- sdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.py
- api/oss/src/core/sessions/interactions/dtos.py
- sdks/python/agenta/sdk/engines/tracing/tracing.py
- api/oss/src/dbs/postgres/tracing/mappings.py
- clients/python/agenta_client/types/session_stream_command_response.py
- clients/python/agenta_client/types/span_input.py
- clients/python/agenta_client/types/session_mount_query.py
- api/oss/tests/pytest/acceptance/sessions/test_archive_unarchive.py
- sdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.py
- sdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.py
- clients/python/agenta_client/types/session_turn.py
- api/oss/src/dbs/postgres/mounts/dbes.py
- sdks/python/agenta/sdk/agents/interfaces.py
- hosting/docker-compose/ee/docker-compose.gh.yml
- clients/python/agenta_client/types/spans_node_input.py
- api/oss/src/dbs/postgres/tracing/utils.py
- api/oss/src/apis/fastapi/mounts/utils.py
- api/oss/tests/pytest/unit/sessions/conftest.py
- api/oss/src/core/shared/dtos.py
- api/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.py
- api/oss/src/dbs/postgres/sessions/streams/mappings.py
- sdks/python/agenta/sdk/agents/init.py
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.py
- api/oss/tests/pytest/unit/otlp/test_logfire_adapter.py
- api/oss/src/dbs/postgres/mounts/dbas.py
- clients/python/agenta_client/types/session_stream.py
- api/oss/src/core/sessions/turns/types.py
- api/oss/src/dbs/postgres/sessions/turns/dbas.py
- api/oss/src/core/sessions/turns/interfaces.py
- sdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.py
- sdks/python/agenta/sdk/middlewares/running/normalizer.py
- api/oss/src/dbs/postgres/sessions/records/dbes.py
- clients/python/agenta_client/mounts/raw_client.py
- api/oss/tests/pytest/acceptance/sessions/test_records_ingest_contract.py
- api/oss/tests/pytest/unit/mounts/test_agent_mounts.py
- hosting/docker-compose/oss/docker-compose.gh.yml
- sdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.py
- api/oss/src/dbs/postgres/sessions/interactions/dao.py
- sdks/python/agenta/sdk/agents/utils/wire.py
- api/oss/tests/pytest/unit/mounts/test_agent_id_backfill.py
- clients/python/agenta_client/types/session_turn_response.py
- api/oss/src/dbs/postgres/sessions/streams/dbes.py
- api/oss/src/dbs/postgres/tracing/dao.py
- api/oss/src/core/sessions/turns/dtos.py
- sdks/python/agenta/sdk/agents/adapters/local.py
- sdks/python/oss/tests/pytest/unit/agents/conftest.py
- api/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.py
- api/oss/src/dbs/postgres/mounts/dao.py
- sdks/python/agenta/sdk/agents/adapters/harnesses.py
- clients/python/agenta_client/types/session_record.py
- api/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.py
- api/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.py
- api/oss/src/core/tracing/dtos.py
- clients/python/agenta_client/types/session_interaction.py
- sdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.py
- api/oss/src/dbs/postgres/tracing/dbas.py
- sdks/python/agenta/sdk/models/tracing.py
- api/oss/src/apis/fastapi/mounts/router.py
- api/oss/src/dbs/postgres/mounts/mappings.py
- docs/docs/self-host/reference/01-configuration.mdx
- api/oss/src/core/sessions/streams/runner_client.py
- sdks/python/agenta/sdk/agents/errors.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.py
- api/oss/src/core/tracing/utils/filtering.py
- api/oss/src/core/tracing/utils/trees.py
- clients/python/agenta_client/types/mount.py
- api/oss/src/core/sessions/service.py
- services/oss/tests/pytest/unit/agent/conftest.py
- api/oss/tests/pytest/unit/tracing/utils/test_trees.py
- api/oss/src/core/sessions/records/dtos.py
- api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
- api/oss/src/dbs/postgres/sessions/turns/dao.py
- sdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.py
- api/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.py
- clients/python/agenta_client/types/init.py
- api/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.py
- api/oss/tests/pytest/unit/sessions/test_sessions_root_service.py
- api/oss/src/core/tracing/service.py
- api/oss/tests/pytest/unit/sessions/test_stream_header_merge.py
- api/oss/src/core/sessions/streams/interfaces.py
- api/oss/src/utils/env.py
- api/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.py
- api/oss/src/dbs/postgres/sessions/turns/mappings.py
- api/oss/src/dbs/postgres/sessions/streams/dao.py
- sdks/python/agenta/sdk/agents/dtos.py
- api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
- sdks/python/oss/tests/pytest/unit/agents/test_wire_contract.py
- api/oss/src/apis/fastapi/sessions/models.py
- clients/python/agenta_client/mounts/client.py
- api/oss/src/core/sessions/streams/dtos.py
- api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
- api/oss/src/core/sessions/turns/service.py
- api/oss/tests/pytest/unit/sessions/test_wp5_root_router.py
- api/entrypoints/routers.py
- api/oss/src/core/sessions/streams/service.py
- api/oss/tests/pytest/unit/sessions/test_turns_dao.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.py
- clients/python/agenta_client/sessions/client.py
- api/oss/src/apis/fastapi/sessions/router.py
| if self.mounts_store is not None and self.bucket: | ||
| for mount in mounts: | ||
| prefix = self._storage_key(project_id=project_id, mount=mount) | ||
| await self.mounts_store.delete_prefix( | ||
| bucket=self.bucket, | ||
| prefix=prefix, | ||
| ) | ||
| return mounts |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Uncaught external call failures in a teardown flow.
If mounts_store.delete_prefix fails (e.g., due to a network timeout or missing permissions), the exception will propagate and halt the delete_session_mounts execution. Because this is called sequentially within the delete_session orchestration before streams_service.hard_delete, a failure here will prevent the streams row from being deleted, leaving a partially-deleted (zombie) session in the database.
Consider wrapping the external call in a try...except block and logging the error so the database deletion can complete, and/or use asyncio.gather(..., return_exceptions=True) to process multiple prefixes concurrently without failing the entire operation.
🛡️ Proposed defensive fix
+ import logging
if self.mounts_store is not None and self.bucket:
for mount in mounts:
prefix = self._storage_key(project_id=project_id, mount=mount)
- await self.mounts_store.delete_prefix(
- bucket=self.bucket,
- prefix=prefix,
- )
+ try:
+ await self.mounts_store.delete_prefix(
+ bucket=self.bucket,
+ prefix=prefix,
+ )
+ except Exception as e:
+ logging.error("Failed to delete object store prefix %s for mount %s: %s", prefix, mount.id, e)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if self.mounts_store is not None and self.bucket: | |
| for mount in mounts: | |
| prefix = self._storage_key(project_id=project_id, mount=mount) | |
| await self.mounts_store.delete_prefix( | |
| bucket=self.bucket, | |
| prefix=prefix, | |
| ) | |
| return mounts | |
| import logging | |
| if self.mounts_store is not None and self.bucket: | |
| for mount in mounts: | |
| prefix = self._storage_key(project_id=project_id, mount=mount) | |
| try: | |
| await self.mounts_store.delete_prefix( | |
| bucket=self.bucket, | |
| prefix=prefix, | |
| ) | |
| except Exception as e: | |
| logging.error("Failed to delete object store prefix %s for mount %s: %s", prefix, mount.id, e) | |
| return mounts |
Railway Preview Environment
|
|
Decision from Mahmoud (2026-07-19) on the migration-017 question flagged in this PR: discarding the old |
Rebases the backend two-thirds of JP's feat/sessions-extensions (PR #5363) onto current main (v0.105.5). Covers api, SDK, Fern python client, and the web generated client: the append-only session_turns domain replacing session_states, the stream command discriminator rename (prompt -> inputs/data), the root /sessions router and SessionsService, /kill teardown wiring, span identity columns plus ag.agent.id, and mounts agent_id. Ported from feat/sessions-extensions@1532ec7fe5 (JP). Reconciliations with the release main: - Kept main's pi-openai model_ref threading (PiHarness/AgentaHarness) and the EndpointResolutionError export alongside JP's HarnessType -> HarnessKind rename. - Kept main's 0.105.5 version in api/pyproject.toml while re-adding JP's greenlet dependency; api/uv.lock updated for greenlet only. - Kept main's sdks/python and services uv.lock (JP's were stale transitive bumps). Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
The record-ingest span_id is an OpenTelemetry span id (64-bit / 16 hex chars), not a UUID (128-bit / 32 hex). Typed as Optional[UUID], pydantic rejected every runner ingest with a 422 and session records silently dropped. Model it as what it is end to end: a validated 16-hex string (OTelSpanId) on the API model, core DTOs, and DAO column; varchar in the two unreleased migrations. trace_id stays UUID (genuinely the 32-hex OTel trace id). Adds contract + backfill + multi-turn tests. Claude-Session: https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
573e236 to
494cdd7
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
clients/python/agenta_client/__init__.py (1)
23-41: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winInvalid
typing.Anyelements in_dynamic_importsand__all__.Both files contain unquoted
typing.Anyobjects instead of strings in the__all__lists and_dynamic_importskeys. In Python,__all__must be a sequence of strings; including non-string objects causes aTypeErrorwhenfrom module import *is executed. Additionally, usingtyping.Anyas a dictionary key repeatedly causes prior entries to be overwritten, breaking lazy imports and static analysis. This is likely a generator configuration issue where certain schemas (e.g.,FullJsonInput,LabelJsonOutput) resolve toAnyand are written verbatim.
clients/python/agenta_client/__init__.py#L23-L41: Fix the generator config or OpenAPI spec so that valid string aliases are produced instead oftyping.Any.clients/python/agenta_client/types/__init__.py#L779-L797: Update the generator configuration to avoid leakingtyping.Anyinto_dynamic_importsand__all__here as well.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1d493f9c-d17c-4a92-9730-cf62e98788f7
⛔ Files ignored due to path filters (49)
api/uv.lockis excluded by!**/*.lockweb/packages/agenta-api-client/src/generated/api/resources/mounts/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/mounts/client/requests/MountQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/ArchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/DeleteSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/FetchTurnRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionDetachRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionHeartbeatRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionRecordIngestRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnAppendRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionTurnQueryRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SetSessionStreamHeaderRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/UnarchiveSessionRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CommandMode.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessKind.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/HarnessSessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/Mount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountCreate.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/MountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResponseModel.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionHeartbeatResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionInteraction.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMount.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionMountQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionRecord.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionState.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateData.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateFlags.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStateUpsertRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStream.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamHeaderEdit.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionStreamsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurn.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnQuery.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionTurnsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SessionsResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpanOutput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeInput.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SpansNodeOutput.tsis excluded by!**/generated/**
📒 Files selected for processing (171)
api/entrypoints/routers.pyapi/oss/databases/postgres/migrations/core/env.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.pyapi/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.pyapi/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.pyapi/oss/src/apis/fastapi/mounts/router.pyapi/oss/src/apis/fastapi/mounts/utils.pyapi/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.pyapi/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.pyapi/oss/src/apis/fastapi/otlp/extractors/span_data_builders.pyapi/oss/src/apis/fastapi/otlp/utils/serialization.pyapi/oss/src/apis/fastapi/sessions/models.pyapi/oss/src/apis/fastapi/sessions/router.pyapi/oss/src/apis/fastapi/tracing/router.pyapi/oss/src/core/mounts/dtos.pyapi/oss/src/core/mounts/interfaces.pyapi/oss/src/core/mounts/service.pyapi/oss/src/core/sessions/dtos.pyapi/oss/src/core/sessions/interactions/dtos.pyapi/oss/src/core/sessions/interactions/interfaces.pyapi/oss/src/core/sessions/interactions/service.pyapi/oss/src/core/sessions/records/dtos.pyapi/oss/src/core/sessions/service.pyapi/oss/src/core/sessions/states/dtos.pyapi/oss/src/core/sessions/states/interfaces.pyapi/oss/src/core/sessions/states/service.pyapi/oss/src/core/sessions/streams/dtos.pyapi/oss/src/core/sessions/streams/interfaces.pyapi/oss/src/core/sessions/streams/runner_client.pyapi/oss/src/core/sessions/streams/service.pyapi/oss/src/core/sessions/turns/__init__.pyapi/oss/src/core/sessions/turns/dtos.pyapi/oss/src/core/sessions/turns/interfaces.pyapi/oss/src/core/sessions/turns/service.pyapi/oss/src/core/sessions/turns/types.pyapi/oss/src/core/shared/dtos.pyapi/oss/src/core/tracing/dtos.pyapi/oss/src/core/tracing/service.pyapi/oss/src/core/tracing/utils/filtering.pyapi/oss/src/core/tracing/utils/trees.pyapi/oss/src/dbs/postgres/mounts/dao.pyapi/oss/src/dbs/postgres/mounts/dbas.pyapi/oss/src/dbs/postgres/mounts/dbes.pyapi/oss/src/dbs/postgres/mounts/mappings.pyapi/oss/src/dbs/postgres/sessions/interactions/dao.pyapi/oss/src/dbs/postgres/sessions/records/dao.pyapi/oss/src/dbs/postgres/sessions/records/dbas.pyapi/oss/src/dbs/postgres/sessions/records/dbes.pyapi/oss/src/dbs/postgres/sessions/records/mappings.pyapi/oss/src/dbs/postgres/sessions/states/dao.pyapi/oss/src/dbs/postgres/sessions/states/dbes.pyapi/oss/src/dbs/postgres/sessions/states/mappings.pyapi/oss/src/dbs/postgres/sessions/streams/dao.pyapi/oss/src/dbs/postgres/sessions/streams/dbes.pyapi/oss/src/dbs/postgres/sessions/streams/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/__init__.pyapi/oss/src/dbs/postgres/sessions/turns/dao.pyapi/oss/src/dbs/postgres/sessions/turns/dbas.pyapi/oss/src/dbs/postgres/sessions/turns/dbes.pyapi/oss/src/dbs/postgres/sessions/turns/mappings.pyapi/oss/src/dbs/postgres/sessions/turns/utils.pyapi/oss/src/dbs/postgres/tracing/dao.pyapi/oss/src/dbs/postgres/tracing/dbas.pyapi/oss/src/dbs/postgres/tracing/dbes.pyapi/oss/src/dbs/postgres/tracing/mappings.pyapi/oss/src/dbs/postgres/tracing/utils.pyapi/oss/src/utils/env.pyapi/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.pyapi/oss/tests/pytest/acceptance/session_states/test_session_states_basics.pyapi/oss/tests/pytest/acceptance/sessions/__init__.pyapi/oss/tests/pytest/acceptance/sessions/test_archive_unarchive.pyapi/oss/tests/pytest/acceptance/sessions/test_records_ingest_contract.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.pyapi/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.pyapi/oss/tests/pytest/unit/mounts/test_agent_id_backfill.pyapi/oss/tests/pytest/unit/mounts/test_agent_mounts.pyapi/oss/tests/pytest/unit/otlp/test_logfire_adapter.pyapi/oss/tests/pytest/unit/session_states/__init__.pyapi/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.pyapi/oss/tests/pytest/unit/session_states/test_session_id_validation.pyapi/oss/tests/pytest/unit/sessions/conftest.pyapi/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.pyapi/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.pyapi/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.pyapi/oss/tests/pytest/unit/sessions/test_mounts_agent_id_backfill.pyapi/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.pyapi/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.pyapi/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.pyapi/oss/tests/pytest/unit/sessions/test_runner_client_kill.pyapi/oss/tests/pytest/unit/sessions/test_sessions_root_service.pyapi/oss/tests/pytest/unit/sessions/test_stream_header_merge.pyapi/oss/tests/pytest/unit/sessions/test_turns_dao.pyapi/oss/tests/pytest/unit/sessions/test_turns_dao_conflict.pyapi/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.pyapi/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.pyapi/oss/tests/pytest/unit/sessions/test_wp5_root_router.pyapi/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.pyapi/oss/tests/pytest/unit/tracing/utils/test_trees.pyapi/pyproject.tomlclients/python/agenta_client/__init__.pyclients/python/agenta_client/mounts/client.pyclients/python/agenta_client/mounts/raw_client.pyclients/python/agenta_client/sessions/client.pyclients/python/agenta_client/sessions/raw_client.pyclients/python/agenta_client/types/__init__.pyclients/python/agenta_client/types/harness_kind.pyclients/python/agenta_client/types/harness_session_record.pyclients/python/agenta_client/types/mount.pyclients/python/agenta_client/types/mount_create.pyclients/python/agenta_client/types/mount_query.pyclients/python/agenta_client/types/session_heartbeat_result.pyclients/python/agenta_client/types/session_interaction.pyclients/python/agenta_client/types/session_mount.pyclients/python/agenta_client/types/session_mount_query.pyclients/python/agenta_client/types/session_record.pyclients/python/agenta_client/types/session_response.pyclients/python/agenta_client/types/session_state.pyclients/python/agenta_client/types/session_state_data.pyclients/python/agenta_client/types/session_state_upsert_request.pyclients/python/agenta_client/types/session_stream.pyclients/python/agenta_client/types/session_stream_command_response.pyclients/python/agenta_client/types/session_stream_header_edit.pyclients/python/agenta_client/types/session_stream_response.pyclients/python/agenta_client/types/session_streams_response.pyclients/python/agenta_client/types/session_turn.pyclients/python/agenta_client/types/session_turn_query.pyclients/python/agenta_client/types/session_turn_response.pyclients/python/agenta_client/types/session_turns_response.pyclients/python/agenta_client/types/sessions_response.pyclients/python/agenta_client/types/span_input.pyclients/python/agenta_client/types/span_output.pyclients/python/agenta_client/types/spans_node_input.pyclients/python/agenta_client/types/spans_node_output.pyclients/python/agenta_client/types/workflow_request_data.pydocs/docs/self-host/reference/01-configuration.mdxhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/ee/docker-compose.gh.ymlhosting/docker-compose/oss/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.gh.ymlhosting/kubernetes/helm/templates/api-deployment.yamlsdks/python/agenta/sdk/agents/__init__.pysdks/python/agenta/sdk/agents/adapters/harnesses.pysdks/python/agenta/sdk/agents/adapters/local.pysdks/python/agenta/sdk/agents/adapters/sandbox_agent.pysdks/python/agenta/sdk/agents/dtos.pysdks/python/agenta/sdk/agents/errors.pysdks/python/agenta/sdk/agents/interfaces.pysdks/python/agenta/sdk/agents/utils/wire.pysdks/python/agenta/sdk/engines/tracing/tracing.pysdks/python/agenta/sdk/middlewares/running/normalizer.pysdks/python/agenta/sdk/models/tracing.pysdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.pysdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.pysdks/python/oss/tests/pytest/unit/agents/conftest.pysdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.pysdks/python/oss/tests/pytest/unit/agents/skills/test_skills_e2e.pysdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.pysdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.pysdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.pysdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.pysdks/python/oss/tests/pytest/unit/agents/test_harness_identity.pysdks/python/oss/tests/pytest/unit/agents/test_wire_contract.pysdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.pysdks/python/oss/tests/pytest/unit/test_invoke_real_handlers_negotiation_routing.pysdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.pysdks/python/oss/tests/pytest/unit/test_tracing_store_agent.pyservices/oss/tests/pytest/unit/agent/conftest.pyweb/oss/src/components/SessionInspector/api.ts
💤 Files with no reviewable changes (15)
- api/oss/tests/pytest/unit/session_states/test_session_id_validation.py
- clients/python/agenta_client/types/session_state.py
- clients/python/agenta_client/types/harness_session_record.py
- api/oss/src/core/sessions/states/service.py
- api/oss/tests/pytest/acceptance/session_states/test_harness_sessions_roundtrip.py
- clients/python/agenta_client/types/session_state_upsert_request.py
- clients/python/agenta_client/types/session_state_data.py
- api/oss/tests/pytest/acceptance/session_states/test_session_states_basics.py
- api/oss/src/dbs/postgres/sessions/states/mappings.py
- api/oss/databases/postgres/migrations/core/env.py
- api/oss/src/core/sessions/states/interfaces.py
- api/oss/tests/pytest/unit/session_states/test_harness_sessions_mapping.py
- api/oss/src/dbs/postgres/sessions/states/dbes.py
- api/oss/src/dbs/postgres/sessions/states/dao.py
- api/oss/src/core/sessions/states/dtos.py
🚧 Files skipped from review as they are similar to previous changes (133)
- api/oss/src/apis/fastapi/otlp/utils/serialization.py
- clients/python/agenta_client/types/harness_kind.py
- hosting/kubernetes/helm/templates/api-deployment.yaml
- api/oss/src/dbs/postgres/sessions/records/mappings.py
- api/oss/src/dbs/postgres/sessions/records/dao.py
- api/oss/src/core/sessions/dtos.py
- api/oss/src/dbs/postgres/mounts/dbas.py
- api/oss/src/core/sessions/interactions/interfaces.py
- api/oss/tests/pytest/unit/sessions/test_mounts_agent_id_backfill.py
- clients/python/agenta_client/types/session_stream_command_response.py
- api/oss/src/core/mounts/interfaces.py
- clients/python/agenta_client/types/session_stream_response.py
- sdks/python/agenta/sdk/agents/init.py
- api/oss/tests/pytest/unit/sessions/conftest.py
- clients/python/agenta_client/types/session_mount_query.py
- sdks/python/oss/tests/pytest/unit/test_batch_fold_stream_contract_routing.py
- sdks/python/oss/tests/pytest/unit/agents/test_dtos_capabilities_events.py
- sdks/python/agenta/sdk/agents/utils/wire.py
- clients/python/agenta_client/types/session_heartbeat_result.py
- api/oss/src/apis/fastapi/tracing/router.py
- api/oss/src/apis/fastapi/otlp/extractors/span_data_builders.py
- api/oss/src/core/sessions/interactions/service.py
- api/oss/src/apis/fastapi/otlp/extractors/adapters/logfire_adapter.py
- api/pyproject.toml
- api/oss/databases/postgres/migrations/tracing_oss/versions/oss000000003_add_span_identity_columns.py
- clients/python/agenta_client/types/session_interaction.py
- api/oss/databases/postgres/migrations/tracing_oss/versions/oss000000004_add_records_turn_span.py
- clients/python/agenta_client/types/session_streams_response.py
- clients/python/agenta_client/types/workflow_request_data.py
- sdks/python/oss/tests/pytest/unit/test_tracing_store_agent.py
- clients/python/agenta_client/types/session_response.py
- hosting/docker-compose/ee/docker-compose.dev.yml
- api/oss/tests/pytest/acceptance/sessions/test_archive_unarchive.py
- sdks/python/oss/tests/pytest/unit/agents/connections/test_dtos_model_ref.py
- api/oss/src/dbs/postgres/sessions/turns/mappings.py
- api/oss/src/dbs/postgres/tracing/dao.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000015_add_session_streams_header.py
- api/oss/tests/pytest/acceptance/sessions/test_records_ingest_contract.py
- clients/python/agenta_client/types/spans_node_output.py
- sdks/python/agenta/sdk/models/tracing.py
- api/oss/tests/pytest/unit/sessions/test_records_mapping_upsert.py
- api/oss/src/apis/fastapi/otlp/extractors/canonical_attributes.py
- api/oss/src/dbs/postgres/sessions/turns/dbas.py
- clients/python/agenta_client/types/sessions_response.py
- api/oss/src/dbs/postgres/mounts/mappings.py
- clients/python/agenta_client/types/spans_node_input.py
- clients/python/agenta_client/types/session_turn_query.py
- clients/python/agenta_client/types/mount_query.py
- sdks/python/agenta/sdk/agents/adapters/local.py
- web/oss/src/components/SessionInspector/api.ts
- hosting/docker-compose/oss/docker-compose.dev.yml
- hosting/docker-compose/oss/docker-compose.gh.yml
- clients/python/agenta_client/types/mount.py
- api/oss/src/dbs/postgres/sessions/turns/dbes.py
- api/oss/tests/pytest/unit/sessions/test_turns_dao_conflict.py
- clients/python/agenta_client/types/mount_create.py
- sdks/python/oss/tests/pytest/unit/agents/conftest.py
- clients/python/agenta_client/mounts/client.py
- clients/python/agenta_client/types/session_turns_response.py
- api/oss/src/core/sessions/turns/dtos.py
- services/oss/tests/pytest/unit/agent/conftest.py
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_roundtrip.py
- api/oss/src/core/sessions/turns/interfaces.py
- api/oss/src/core/mounts/dtos.py
- api/oss/tests/pytest/acceptance/sessions/test_stream_header_basics.py
- docs/docs/self-host/reference/01-configuration.mdx
- api/oss/src/utils/env.py
- api/oss/src/core/shared/dtos.py
- api/oss/src/dbs/postgres/tracing/mappings.py
- sdks/python/oss/tests/pytest/integration/agents/_qa_transcripts.py
- api/oss/tests/pytest/unit/tracing/utils/test_trees.py
- clients/python/agenta_client/types/session_turn.py
- sdks/python/oss/tests/pytest/unit/agents/test_environment_lifecycle.py
- api/oss/src/dbs/postgres/tracing/dbas.py
- api/oss/src/apis/fastapi/mounts/router.py
- clients/python/agenta_client/types/session_record.py
- sdks/python/oss/tests/pytest/unit/agents/test_harness_identity.py
- sdks/python/agenta/sdk/agents/adapters/sandbox_agent.py
- api/oss/src/dbs/postgres/sessions/records/dbes.py
- api/oss/tests/pytest/unit/sessions/test_records_turn_span_dao.py
- api/oss/src/dbs/postgres/sessions/streams/dbes.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000014_add_session_turns.py
- clients/python/agenta_client/types/span_input.py
- api/oss/src/core/sessions/streams/runner_client.py
- sdks/python/agenta/sdk/engines/tracing/tracing.py
- sdks/python/oss/tests/pytest/integration/agents/_fake_runner_backend.py
- sdks/python/agenta/sdk/agents/adapters/harnesses.py
- sdks/python/oss/tests/pytest/unit/agents/test_agent_composition_seam.py
- api/oss/src/core/sessions/records/dtos.py
- api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
- api/oss/src/dbs/postgres/sessions/interactions/dao.py
- api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
- api/oss/src/apis/fastapi/mounts/utils.py
- clients/python/agenta_client/types/session_mount.py
- clients/python/agenta_client/mounts/raw_client.py
- api/oss/tests/pytest/unit/tracing/test_dao_ingest_identity_columns.py
- api/oss/tests/pytest/unit/sessions/test_wp5_mount_teardown.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000017_drop_session_states.py
- api/oss/tests/pytest/unit/sessions/test_record_ingest_endpoint.py
- api/oss/src/dbs/postgres/sessions/streams/mappings.py
- api/oss/databases/postgres/migrations/core_oss/versions/oss000000016_add_mounts_agent_id.py
- api/oss/tests/pytest/unit/sessions/test_wp5_root_router.py
- api/oss/src/core/sessions/interactions/dtos.py
- api/oss/src/dbs/postgres/mounts/dao.py
- clients/python/agenta_client/types/session_turn_response.py
- api/oss/tests/pytest/unit/sessions/test_sessions_root_service.py
- sdks/python/oss/tests/pytest/unit/agents/test_harness_adapters.py
- api/oss/tests/pytest/unit/mounts/test_agent_id_backfill.py
- clients/python/agenta_client/types/session_stream_header_edit.py
- api/oss/tests/pytest/unit/mounts/test_agent_mounts.py
- api/oss/src/core/sessions/service.py
- api/oss/src/core/tracing/service.py
- sdks/python/agenta/sdk/agents/interfaces.py
- api/oss/src/core/tracing/utils/trees.py
- api/oss/tests/pytest/unit/sessions/test_kill_runner_teardown.py
- api/oss/src/core/sessions/streams/interfaces.py
- sdks/python/agenta/sdk/agents/dtos.py
- api/oss/src/core/sessions/turns/service.py
- api/oss/src/dbs/postgres/sessions/turns/dao.py
- api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
- sdks/python/oss/tests/pytest/unit/test_normalizer_passthrough.py
- api/oss/tests/pytest/unit/otlp/test_logfire_adapter.py
- sdks/python/oss/tests/pytest/unit/agents/test_wire_contract.py
- api/oss/src/dbs/postgres/sessions/streams/dao.py
- api/oss/src/core/mounts/service.py
- api/oss/tests/pytest/unit/sessions/test_stream_header_merge.py
- api/oss/src/apis/fastapi/sessions/models.py
- api/oss/src/core/sessions/streams/service.py
- api/oss/tests/pytest/unit/sessions/test_turns_dao.py
- api/entrypoints/routers.py
- api/oss/src/core/sessions/streams/dtos.py
- api/oss/src/apis/fastapi/sessions/router.py
- clients/python/agenta_client/sessions/client.py
| elif condition.field == Fields.SESSION_ID: | ||
| _parse_string_field_condition(condition) | ||
| elif condition.field == Fields.USER_ID: | ||
| _parse_string_field_condition(condition) | ||
| elif condition.field == Fields.AGENT_ID: | ||
| _parse_string_field_condition(condition) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use the actual field name in string-field validation errors.
These branches make _parse_string_field_condition() reachable for SESSION_ID, USER_ID, and AGENT_ID, but that helper hardcodes status_message in its error messages. Invalid filters for the new fields will therefore report the wrong field.
Proposed fix
- "'status_message' only supports comparison, numeric, string, list, and existence operators.",
+ f"'{condition.field}' only supports comparison, numeric, string, list, and existence operators.",
...
- "'status_message' value is required and thus never null for numeric, string, and list operators.",
+ f"'{condition.field}' value is required and thus never null for numeric, string, and list operators.",
...
- "'status_message' value is not supported for existence operators.",
+ f"'{condition.field}' value is not supported for existence operators.",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| elif condition.field == Fields.SESSION_ID: | |
| _parse_string_field_condition(condition) | |
| elif condition.field == Fields.USER_ID: | |
| _parse_string_field_condition(condition) | |
| elif condition.field == Fields.AGENT_ID: | |
| _parse_string_field_condition(condition) | |
| f"'{condition.field}' only supports comparison, numeric, string, list, and existence operators.", | |
| f"'{condition.field}' value is required and thus never null for numeric, string, and list operators.", | |
| f"'{condition.field}' value is not supported for existence operators.", |
| for reference in turn.references: | ||
| _key = reference.id or reference.slug | ||
| _references[_key] = reference.model_dump( | ||
| mode="json", | ||
| exclude_none=True, | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Preserve reference versions during deduplication.
When id is absent, reference.id or reference.slug uses only the slug as the key. References such as the same slug at versions 1 and 2 therefore overwrite each other, causing the JSONB filter to omit one requested reference and return incorrect turns. Key by the complete (id, slug, version) identity or deduplicate only identical serialized dictionaries.
What this is
JP's sessions work (PR #5363,
feat/sessions-extensions) predated v0.105.4, v0.105.5, and the runner decomposition (#5369). This is the backend two-thirds of that work rebased onto currentmain(v0.105.5), on a new branch I own so JP's branch is untouched.Its parent,
big-agents-add-sessions, is already merged into main, so this PR carries only thefeat/sessions-extensionsdelta: the API, the Python SDK, the Fern Python client, and the web generated client.What it changes
session_statesread-modify-write model with an append-onlysession_turnsdomain (new migrations014–017, tracing003–004; the oldsession_statesmodule and its DTOs/DAO/tests are removed).prompt→inputs/data./sessionsrouter andSessionsService, session-scoped hard-delete/unarchive plumbing, and the API side of/killteardown.ag.agent.id, andmounts.agent_id.Ported from
feat/sessions-extensions@1532ec7fe5(JP); attribution is in the commit.Reconciliations with the release
Three places where JP's change met a v0.105.x fix. Both behaviors are kept:
sdks/python/agenta/sdk/agents/adapters/harnesses.py— JP renamedHarnessType→HarnessKindacross the SDK. Main (pi-openai, feat(agents): OpenAI-compatible endpoints for Pi via vault custom connections #5345) addedmodel_refthreading inPiHarnessandAgentaHarness. Kept both: the rename plus the twomodel_ref=config.agent.model_reflines.sdks/python/agenta/sdk/agents/__init__.py— kept JP'sHarnessKindrename and main's newEndpointResolutionErrorexport.api/pyproject.toml— kept main's0.105.5version and re-added JP'sgreenletdependency;api/uv.lockupdated for greenlet only (surgical, not a full re-resolve). Kept main'ssdks/pythonandservicesuv.lock(JP's were stale transitive bumps).Testing
test_harness_adapters.py+test_agent_composition_seam.py— 38 passed (validates the HarnessKind + model_ref merge);test_wire_contract.py— 34 passed.sdks/python/oss/tests/pytest/unit/agents/is 669/670. The one failure (test_bare_claude_alias_resolves_to_anthropic) is not from this branch: it comes from the separately-appliedfix/claude-fable-model-idlane editingclaude_models.curated.jsonin the shared dev worktree. This branch keeps main's catalog verbatim, so on a clean main base the test passes.For JP
This is a mechanical rebase of your #5363 onto v0.105.5, on a branch I own (
sessions-rebase/backend). Please review the three reconciliations and adopt or retarget as you see fit — I did not touch your branches.https://claude.ai/code/session_01DnWRxU3dCJ11hgDidm26vW
QA finding fixed: record-ingest 422 (span_id typed as UUID)
QA of this branch on the EE dev stack found session records never persisted: every runner→API
POST /sessions/records/ingestreturned HTTP 422 and dropped after retries (debug/qa-sessions-rebase/FINDING-record-ingest-422.md). Root cause:span_idis an OpenTelemetry span id (64-bit / 16 hex chars) but was typedOptional[UUID](128-bit / 32 hex), so pydantic rejected every real ingest.trace_id(32 hex) fits UUID and masked it.Fix (commit
9e2044c898): modelspan_idas what it is — a validated 16-hex string (OTelSpanIdincore/shared/dtos.py) — across the API model, core DTOs, and the DAO column, andvarcharin the two unreleased migrations (core_oss/014,tracing_oss/004, edited in place).trace_idstays UUID (genuinely the 32-hex OTel trace id:run.traceId()=spanContext().traceId). New/updated tests: a model-level 16-hex-accept / UUID-reject contract, an acceptance ingest-contract test, an archive/unarchive route test, a multi-turn turns-persist assertion, a mounts.agent_id backfill migration test; existing DAO/mapping tests moved to the 16-hex shape.Live re-verify (EE dev): after altering the two live span_id columns to varchar to match the corrected migration, the runner-shaped body (16-hex span_id) returns 200 and the record persists with span_id intact; a UUID span_id still returns 422; a real agent run's records ingested at 200 with no
uuid_parsingin the api log. Evidence underdebug/qa-sessions-rebase/fix-verify/.Pre-existing, unrelated finding (not fixed here):
apply_windowingtreatssession_turns.span_idas the uuid7 cursor, sotest_query_turns_windowed_newest_to_oldestorders by an all-NULL span_id and returns the wrong order. It is triggered by the column merely existing (type-independent), so it predates this fix. Flagged for a follow-up.Follow-up review fix (committed to this lane): made
ix_session_turns_project_id_session_id_turn_indexa UNIQUE index incore_oss/014and mirroredunique=Trueon the matchingIndexin the turns DBE, so(project_id, session_id, turn_index)can no longer hold duplicate turn rows. Migration is unreleased (edited in place); the dev DB had duplicate QA rows deduped before the unique index was built live (fresh deploys need no manual step). Sessions suites: pure-unit 120 green; full suite 140 green with the one pre-existing windowing failure above.Web build unblocked — stale
promptargument removed (this lane): the web image build failed to compile withsrc/session/api/api.ts(296,37): error TS2353: 'prompt' does not exist in type 'SessionStreamCommandRequest'. The rebased wire contract dropped thepromptfield fromSessionStreamCommandRequest(it now carriesdata?: WorkflowRequestData), butcommandSessionStreamstill passed the oldprompt. That function is dead on the product path today (zero callers outside its own module; its own doc comment notes steer/send is not wired into chat yet), so I removed the stalepromptparameter and request field to make it compile against the new type — no behavior change. I deliberately did NOT invent aprompt→data/inputs mapping; a one-line comment marks that the real mapping is yours to define (JP) when the send path is actually wired.The turns DAO now maps duplicate-key IntegrityError to EntityCreationConflict (HTTP 409); see #5376's description for the full context of the turn-counter amendment.