From b2afc1c70e2a231c230d4c596529df9dcd6d10d4 Mon Sep 17 00:00:00 2001 From: moonyue-w <300878504+moonyue-w@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:56:15 +0800 Subject: [PATCH] fix(api)!: align credits, ownership, and pairing contracts Match QCA Session budget and usage schemas, route Forward identity ownership through query parameters, and support pairing by record ID. Include sync and async wire contract tests, generated references, and migration notes. BREAKING CHANGE: replace max_list_cost currency objects with max_credit_cost decimal strings. --- CHANGELOG.md | 14 + docs/api/reference.md | 380 +++++++++++++++++- src/qca/forward/resources/channel_pairings.py | 30 +- src/qca/forward/resources/environments.py | 108 +++-- src/qca/forward/resources/files.py | 78 +++- src/qca/forward/resources/skills/skills.py | 78 +++- src/qca/forward/resources/skills/versions.py | 80 +++- .../forward/resources/vaults/credentials.py | 78 +++- src/qca/forward/resources/vaults/vaults.py | 78 +++- src/qca/forward/types/channel_pairing.py | 5 + .../types/channel_pairing_create_params.py | 4 +- .../types/environment_create_params.py | 2 + .../forward/types/environment_list_params.py | 2 + .../types/environment_update_params.py | 2 + src/qca/forward/types/file_list_params.py | 2 + src/qca/forward/types/file_upload_params.py | 2 + src/qca/forward/types/session_usage.py | 2 + src/qca/forward/types/skill_create_params.py | 2 + src/qca/forward/types/skill_list_params.py | 2 + .../forward/types/skill_retrieve_params.py | 2 + src/qca/forward/types/skill_update_params.py | 2 + .../types/skill_version_create_params.py | 2 + .../types/skill_version_list_params.py | 2 + src/qca/forward/types/vault_create_params.py | 2 + .../types/vault_credential_create_params.py | 2 + .../types/vault_credential_list_params.py | 2 + src/qca/forward/types/vault_list_params.py | 2 + src/qca/managed/types/budget_limit.py | 8 +- src/qca/managed/types/budget_limit_param.py | 8 +- src/qca/managed/types/session_event.py | 4 + src/qca/managed/types/session_event_usage.py | 1 + src/qca/managed/types/session_stream_event.py | 4 + .../types/session_stream_event_usage.py | 1 + src/qca/managed/types/session_usage.py | 4 + src/qca/managed/types/span_model_usage.py | 1 + .../stream_session_thread_events_union.py | 4 + ...tream_session_thread_events_union_usage.py | 1 + tests/_surface.py | 8 +- tests/test_identity_pairing_contract.py | 183 +++++++++ tests/test_session_credit_contract.py | 96 +++++ 40 files changed, 1152 insertions(+), 136 deletions(-) create mode 100644 tests/test_identity_pairing_contract.py create mode 100644 tests/test_session_credit_contract.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 444078d..474fabc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ existing `0.1.0` release; earlier development prereleases are not listed. ## [Unreleased] +### Fixed + +- Align Managed Session budgets with the official decimal-string `max_credit_cost` contract, shared by Deployment budgets. The limit covers cumulative model and sandbox Credits; reaching it rejects the next user message without interrupting the current turn. +- Expose Managed and Forward Session `model_credits`, `sandbox_runtime_credits`, and `total_credits`; decode top-level `session.usage` Credits and per-call `model_usage.credits` / compaction `usage.credits`. Session usage may be absent. Legacy response token/list-cost fields remain available. +- Route Identity ownership through query parameters on existing Forward Environment, Skill/Version, Vault/Credential, and File operations, including multipart uploads and content downloads. +- Allow existing channel pairing creation with either a code or `channel_pairing_id`, and expose pairing scope details. No additional API endpoints are introduced. + +### Migration + +- **Breaking budget field change:** Replace `{"type": "limit", "max_list_cost": {...}}` with `{"type": "limit", "max_credit_cost": "100.00"}`. Amounts are positive decimal strings, not currency objects. Omitting a budget update preserves the limit; explicit null removes it. +- Consume the three top-level Credits fields from `session.usage` events. Replace cumulative snapshots rather than adding them; compaction Credits are already included in Session totals. +- Pass the keyword argument `identity_id="idn_..."` to resource methods. Use this only with a PAT. With a SAT, omit `identity_id`; the server infers ownership from the token and rejects explicit values (including an empty string). +- Channel pairing requests must provide exactly one of `code` or `channel_pairing_id`; existing code-based calls remain supported. + ## [0.6.0] ### Added diff --git a/docs/api/reference.md b/docs/api/reference.md index cf3ab65..93de0b9 100644 --- a/docs/api/reference.md +++ b/docs/api/reference.md @@ -2860,7 +2860,8 @@ class ChannelPairings(SyncAPIResource) ```python def create( *, - code: str, + code: Union[str, NotGiven] = NOT_GIVEN, + channel_pairing_id: Union[str, NotGiven] = NOT_GIVEN, identity_id: str, template_id: str, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, @@ -2875,6 +2876,8 @@ def create( POST /channel_pairings. +Supply exactly one of code or channel_pairing_id. + #### delete @@ -2911,7 +2914,8 @@ class AsyncChannelPairings(AsyncAPIResource) ```python async def create( *, - code: str, + code: Union[str, NotGiven] = NOT_GIVEN, + channel_pairing_id: Union[str, NotGiven] = NOT_GIVEN, identity_id: str, template_id: str, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, @@ -2926,6 +2930,8 @@ async def create( POST /channel_pairings. +Supply exactly one of code or channel_pairing_id. + #### delete @@ -3586,6 +3592,7 @@ def list( page: Union[str, None, NotGiven] = NOT_GIVEN, after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3597,6 +3604,8 @@ def list( GET /environments. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -3609,6 +3618,7 @@ def create( config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3620,6 +3630,8 @@ def create( POST /environments. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -3628,6 +3640,7 @@ POST /environments. def retrieve( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3639,6 +3652,8 @@ def retrieve( GET /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### update @@ -3651,6 +3666,7 @@ def update( description: Union[str, None, NotGiven] = NOT_GIVEN, config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3662,6 +3678,8 @@ def update( POST /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### archive @@ -3670,6 +3688,7 @@ POST /environments/{environment_id}. def archive( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3681,6 +3700,8 @@ def archive( POST /environments/{environment_id}/archive. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -3689,6 +3710,7 @@ POST /environments/{environment_id}/archive. def delete( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3699,6 +3721,8 @@ def delete( DELETE /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncEnvironments @@ -3720,6 +3744,7 @@ def list( page: Union[str, None, NotGiven] = NOT_GIVEN, after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3731,6 +3756,8 @@ def list( GET /environments. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -3743,6 +3770,7 @@ async def create( config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3754,6 +3782,8 @@ async def create( POST /environments. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -3762,6 +3792,7 @@ POST /environments. async def retrieve( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3773,6 +3804,8 @@ async def retrieve( GET /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### update @@ -3785,6 +3818,7 @@ async def update( description: Union[str, None, NotGiven] = NOT_GIVEN, config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3796,6 +3830,8 @@ async def update( POST /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### archive @@ -3804,6 +3840,7 @@ POST /environments/{environment_id}. async def archive( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3815,6 +3852,8 @@ async def archive( POST /environments/{environment_id}/archive. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -3823,6 +3862,7 @@ POST /environments/{environment_id}/archive. async def delete( environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3833,6 +3873,8 @@ async def delete( DELETE /environments/{environment_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.resources.files @@ -3860,6 +3902,7 @@ def list( before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, scope_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3871,6 +3914,8 @@ def list( GET /files. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### upload @@ -3883,6 +3928,7 @@ def upload( purpose: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3894,6 +3940,8 @@ def upload( POST /files. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve\_metadata @@ -3902,6 +3950,7 @@ POST /files. def retrieve_metadata( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3913,6 +3962,8 @@ def retrieve_metadata( GET /files/{file_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -3921,6 +3972,7 @@ GET /files/{file_id}. def delete( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3931,6 +3983,8 @@ def delete( DELETE /files/{file_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### download @@ -3939,6 +3993,7 @@ DELETE /files/{file_id}. def download( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3950,6 +4005,8 @@ def download( GET /files/{file_id}/content. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncFiles @@ -3973,6 +4030,7 @@ def list( before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, scope_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -3984,6 +4042,8 @@ def list( GET /files. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### upload @@ -3996,6 +4056,7 @@ async def upload( purpose: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -4007,6 +4068,8 @@ async def upload( POST /files. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve\_metadata @@ -4015,6 +4078,7 @@ POST /files. async def retrieve_metadata( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -4026,6 +4090,8 @@ async def retrieve_metadata( GET /files/{file_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -4034,6 +4100,7 @@ GET /files/{file_id}. async def delete( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -4044,6 +4111,8 @@ async def delete( DELETE /files/{file_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### download @@ -4052,6 +4121,7 @@ DELETE /files/{file_id}. async def download( file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -4063,6 +4133,8 @@ async def download( GET /files/{file_id}/content. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.resources.identities.configs @@ -8230,6 +8302,7 @@ def list( display_title: Union[str, None, NotGiven] = NOT_GIVEN, source: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8241,6 +8314,8 @@ def list( GET /skills. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -8256,6 +8331,7 @@ def create( description: Union[str, None, NotGiven] = NOT_GIVEN, type: Union[str, None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8266,6 +8342,8 @@ def create( POST /skills. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -8275,6 +8353,7 @@ def retrieve( skill_id: str, *, include_content: Union[bool, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8285,6 +8364,8 @@ def retrieve( GET /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### update @@ -8299,6 +8380,7 @@ def update( metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, icon_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8309,6 +8391,8 @@ def update( PUT /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -8317,6 +8401,7 @@ PUT /skills/{skill_id}. def delete( skill_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8327,6 +8412,8 @@ def delete( DELETE /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncSkills @@ -8362,6 +8449,7 @@ def list( display_title: Union[str, None, NotGiven] = NOT_GIVEN, source: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8373,6 +8461,8 @@ def list( GET /skills. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -8388,6 +8478,7 @@ async def create( description: Union[str, None, NotGiven] = NOT_GIVEN, type: Union[str, None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8398,6 +8489,8 @@ async def create( POST /skills. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -8407,6 +8500,7 @@ async def retrieve( skill_id: str, *, include_content: Union[bool, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8417,6 +8511,8 @@ async def retrieve( GET /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### update @@ -8431,6 +8527,7 @@ async def update( metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, icon_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8441,6 +8538,8 @@ async def update( PUT /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -8449,6 +8548,7 @@ PUT /skills/{skill_id}. async def delete( skill_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8459,6 +8559,8 @@ async def delete( DELETE /skills/{skill_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.resources.skills.versions @@ -8483,6 +8585,7 @@ def list( *, limit: Union[int, None, NotGiven] = NOT_GIVEN, page: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8494,6 +8597,8 @@ def list( GET /skills/{skill_id}/versions. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -8503,6 +8608,7 @@ def create( skill_id: str, *, files: List[FileTypes], + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8514,6 +8620,8 @@ def create( POST /skills/{skill_id}/versions. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -8523,6 +8631,7 @@ def retrieve( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8534,6 +8643,8 @@ def retrieve( GET /skills/{skill_id}/versions/{version}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -8543,6 +8654,7 @@ def delete( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8554,6 +8666,8 @@ def delete( DELETE /skills/{skill_id}/versions/{version}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### download @@ -8563,6 +8677,7 @@ def download( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8574,6 +8689,8 @@ def download( GET /skills/{skill_id}/versions/{version}/content. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncVersions @@ -8594,6 +8711,7 @@ def list( *, limit: Union[int, None, NotGiven] = NOT_GIVEN, page: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8605,6 +8723,8 @@ def list( GET /skills/{skill_id}/versions. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -8614,6 +8734,7 @@ async def create( skill_id: str, *, files: List[FileTypes], + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8625,6 +8746,8 @@ async def create( POST /skills/{skill_id}/versions. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -8634,6 +8757,7 @@ async def retrieve( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8645,6 +8769,8 @@ async def retrieve( GET /skills/{skill_id}/versions/{version}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -8654,6 +8780,7 @@ async def delete( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8665,6 +8792,8 @@ async def delete( DELETE /skills/{skill_id}/versions/{version}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### download @@ -8674,6 +8803,7 @@ async def download( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -8685,6 +8815,8 @@ async def download( GET /skills/{skill_id}/versions/{version}/content. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.resources.templates @@ -9229,6 +9361,7 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9240,6 +9373,8 @@ def list( GET /vaults/{vault_id}/credentials. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -9252,6 +9387,7 @@ def create( display_name: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9263,6 +9399,8 @@ def create( POST /vaults/{vault_id}/credentials. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -9272,6 +9410,7 @@ def retrieve( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9283,6 +9422,8 @@ def retrieve( GET /vaults/{vault_id}/credentials/{credential_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -9292,6 +9433,7 @@ def delete( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9302,6 +9444,8 @@ def delete( DELETE /vaults/{vault_id}/credentials/{credential_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncCredentials @@ -9350,6 +9494,7 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9361,6 +9506,8 @@ def list( GET /vaults/{vault_id}/credentials. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -9373,6 +9520,7 @@ async def create( display_name: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9384,6 +9532,8 @@ async def create( POST /vaults/{vault_id}/credentials. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -9393,6 +9543,7 @@ async def retrieve( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9404,6 +9555,8 @@ async def retrieve( GET /vaults/{vault_id}/credentials/{credential_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -9413,6 +9566,7 @@ async def delete( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9423,6 +9577,8 @@ async def delete( DELETE /vaults/{vault_id}/credentials/{credential_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.resources.vaults.vaults @@ -9460,6 +9616,7 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9471,6 +9628,8 @@ def list( GET /vaults. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -9481,6 +9640,7 @@ def create( display_name: str, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9491,6 +9651,8 @@ def create( POST /vaults. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -9499,6 +9661,7 @@ POST /vaults. def retrieve( vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9509,6 +9672,8 @@ def retrieve( GET /vaults/{vault_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -9517,6 +9682,7 @@ GET /vaults/{vault_id}. def delete( vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9527,6 +9693,8 @@ def delete( DELETE /vaults/{vault_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + ## AsyncVaults @@ -9560,6 +9728,7 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9571,6 +9740,8 @@ def list( GET /vaults. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### create @@ -9581,6 +9752,7 @@ async def create( display_name: str, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9591,6 +9763,8 @@ async def create( POST /vaults. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### retrieve @@ -9599,6 +9773,7 @@ POST /vaults. async def retrieve( vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9609,6 +9784,8 @@ async def retrieve( GET /vaults/{vault_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + #### delete @@ -9617,6 +9794,7 @@ GET /vaults/{vault_id}. async def delete( vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, @@ -9627,6 +9805,8 @@ async def delete( DELETE /vaults/{vault_id}. +identity_id selects identity ownership with a PAT; omit it with a SAT. + # qca.forward.types.batch @@ -10281,6 +10461,26 @@ class ChannelPairing(BaseModel) #### paired\_at + + +#### scope\_type + + + +#### scope\_external\_id + + + +#### scope\_display\_name + + + +#### created\_at + + + +#### updated\_at + # qca.forward.types.channel\_pairing\_create\_params @@ -10299,6 +10499,12 @@ class ChannelPairingCreateParams(TypedDict) #### code +Supply exactly one of code or channel_pairing_id. + + + +#### channel\_pairing\_id + #### identity\_id @@ -11199,6 +11405,12 @@ class EnvironmentCreateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/environment_create_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### name @@ -11233,6 +11445,12 @@ class EnvironmentListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/environment_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -11263,6 +11481,12 @@ class EnvironmentUpdateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/environment_update_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### name @@ -11337,6 +11561,12 @@ class FileListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/file_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -11433,6 +11663,12 @@ class FileUploadParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/file_upload_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### file @@ -15545,6 +15781,14 @@ class SessionUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/session_usage.py) + + +#### model\_credits + + + +#### sandbox\_runtime\_credits + #### total\_credits @@ -15685,6 +15929,12 @@ class SkillCreateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_create_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### files @@ -15731,6 +15981,12 @@ class SkillListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -15825,6 +16081,12 @@ class SkillRetrieveParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_retrieve_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### include\_content @@ -15843,6 +16105,12 @@ class SkillUpdateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_update_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### description @@ -15939,6 +16207,12 @@ class SkillVersionCreateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_version_create_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### files @@ -15957,6 +16231,12 @@ class SkillVersionListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/skill_version_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -16675,6 +16955,12 @@ class VaultCreateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/vault_create_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### display\_name @@ -16777,6 +17063,12 @@ class VaultCredentialCreateParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/vault_credential_create_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### auth @@ -16807,6 +17099,12 @@ class VaultCredentialListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/vault_credential_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -16957,6 +17255,12 @@ class VaultListParams(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/forward/types/vault_list_params.py) + + +#### identity\_id + +Select identity ownership with a PAT. Omit when using a SAT. + #### limit @@ -23883,9 +24187,9 @@ class BudgetLimit(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/budget_limit.py) - + -#### max\_list\_cost +#### max\_credit\_cost @@ -23905,9 +24209,9 @@ class BudgetLimitParam(TypedDict) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/budget_limit_param.py) - + -#### max\_list\_cost +#### max\_credit\_cost @@ -29919,6 +30223,18 @@ class SessionEvent(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/session_event.py) + + +#### model\_credits + + + +#### sandbox\_runtime\_credits + + + +#### total\_credits + #### id @@ -30217,6 +30533,10 @@ class SessionEventUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/session_event_usage.py) + + +#### credits + #### cache\_creation\_input\_tokens @@ -30851,6 +31171,18 @@ class SessionStreamEvent(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/session_stream_event.py) + + +#### model\_credits + + + +#### sandbox\_runtime\_credits + + + +#### total\_credits + #### id @@ -31043,6 +31375,10 @@ class SessionStreamEventUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/session_stream_event_usage.py) + + +#### credits + #### cache\_creation\_input\_tokens @@ -31573,6 +31909,18 @@ class SessionUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/session_usage.py) + + +#### model\_credits + + + +#### sandbox\_runtime\_credits + + + +#### total\_credits + #### active\_seconds @@ -31997,6 +32345,10 @@ class SpanModelUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/span_model_usage.py) + + +#### credits + #### cache\_creation\_input\_tokens @@ -32101,6 +32453,18 @@ class StreamSessionThreadEventsUnion(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/stream_session_thread_events_union.py) + + +#### model\_credits + + + +#### sandbox\_runtime\_credits + + + +#### total\_credits + #### id @@ -32293,6 +32657,10 @@ class StreamSessionThreadEventsUnionUsage(BaseModel) [[view_source]](https://github.com/QoderAI/qoder-cloud-agents-sdk-python/blob/main/src/qca/managed/types/stream_session_thread_events_union_usage.py) + + +#### credits + #### cache\_creation\_input\_tokens diff --git a/src/qca/forward/resources/channel_pairings.py b/src/qca/forward/resources/channel_pairings.py index 354ce02..1bd6d45 100644 --- a/src/qca/forward/resources/channel_pairings.py +++ b/src/qca/forward/resources/channel_pairings.py @@ -17,7 +17,8 @@ class ChannelPairings(SyncAPIResource): def create( self, *, - code: str, + code: Union[str, NotGiven] = NOT_GIVEN, + channel_pairing_id: Union[str, NotGiven] = NOT_GIVEN, identity_id: str, template_id: str, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, @@ -26,10 +27,18 @@ def create( extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ChannelPairing: - """POST /channel_pairings.""" + """POST /channel_pairings. + + Supply exactly one of code or channel_pairing_id. + """ _path = path_template("/channel_pairings") options = make_request_options( - body={"code": code, "identity_id": identity_id, "template_id": template_id}, + body={ + "code": code, + "channel_pairing_id": channel_pairing_id, + "identity_id": identity_id, + "template_id": template_id, + }, query={}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, @@ -66,7 +75,8 @@ class AsyncChannelPairings(AsyncAPIResource): async def create( self, *, - code: str, + code: Union[str, NotGiven] = NOT_GIVEN, + channel_pairing_id: Union[str, NotGiven] = NOT_GIVEN, identity_id: str, template_id: str, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, @@ -75,10 +85,18 @@ async def create( extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ChannelPairing: - """POST /channel_pairings.""" + """POST /channel_pairings. + + Supply exactly one of code or channel_pairing_id. + """ _path = path_template("/channel_pairings") options = make_request_options( - body={"code": code, "identity_id": identity_id, "template_id": template_id}, + body={ + "code": code, + "channel_pairing_id": channel_pairing_id, + "identity_id": identity_id, + "template_id": template_id, + }, query={}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, diff --git a/src/qca/forward/resources/environments.py b/src/qca/forward/resources/environments.py index df62580..eaab6c7 100644 --- a/src/qca/forward/resources/environments.py +++ b/src/qca/forward/resources/environments.py @@ -21,16 +21,26 @@ def list( page: Union[str, None, NotGiven] = NOT_GIVEN, after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[Environment]: - """GET /environments.""" + """GET /environments. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments") options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -47,16 +57,20 @@ def create( config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments.""" + """POST /environments. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments") options = make_request_options( body={"name": name, "description": description, "config": config, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -69,16 +83,20 @@ def retrieve( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """GET /environments/{environment_id}.""" + """GET /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -95,16 +113,20 @@ def update( description: Union[str, None, NotGiven] = NOT_GIVEN, config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments/{environment_id}.""" + """POST /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={"name": name, "description": description, "config": config, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -117,16 +139,20 @@ def archive( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments/{environment_id}/archive.""" + """POST /environments/{environment_id}/archive. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}/archive", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -139,16 +165,20 @@ def delete( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /environments/{environment_id}.""" + """DELETE /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -166,16 +196,26 @@ def list( page: Union[str, None, NotGiven] = NOT_GIVEN, after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[Environment]: - """GET /environments.""" + """GET /environments. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments") options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -194,16 +234,20 @@ async def create( config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments.""" + """POST /environments. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments") options = make_request_options( body={"name": name, "description": description, "config": config, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -216,16 +260,20 @@ async def retrieve( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """GET /environments/{environment_id}.""" + """GET /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -242,16 +290,20 @@ async def update( description: Union[str, None, NotGiven] = NOT_GIVEN, config: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments/{environment_id}.""" + """POST /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={"name": name, "description": description, "config": config, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -264,16 +316,20 @@ async def archive( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Environment: - """POST /environments/{environment_id}/archive.""" + """POST /environments/{environment_id}/archive. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}/archive", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -286,16 +342,20 @@ async def delete( self, environment_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /environments/{environment_id}.""" + """DELETE /environments/{environment_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/environments/{environment_id}", environment_id=environment_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/resources/files.py b/src/qca/forward/resources/files.py index 3d5d8fe..bc5688f 100644 --- a/src/qca/forward/resources/files.py +++ b/src/qca/forward/resources/files.py @@ -24,16 +24,21 @@ def list( before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, scope_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[FileMetadata]: - """GET /files.""" + """GET /files. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files") options = make_request_options( body={}, query={ + "identity_id": identity_id, "limit": limit, "page": page, "after_id": after_id, @@ -57,16 +62,20 @@ def upload( purpose: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> FileMetadata: - """POST /files.""" + """POST /files. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files") options = make_request_options( body={"file": file, "name": name, "purpose": purpose, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -79,16 +88,20 @@ def retrieve_metadata( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> FileMetadata: - """GET /files/{file_id}.""" + """GET /files/{file_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -101,16 +114,20 @@ def delete( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /files/{file_id}.""" + """DELETE /files/{file_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -123,16 +140,20 @@ def download( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BinaryAPIResponse: - """GET /files/{file_id}/content.""" + """GET /files/{file_id}/content. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}/content", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -152,16 +173,21 @@ def list( before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, scope_id: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[FileMetadata]: - """GET /files.""" + """GET /files. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files") options = make_request_options( body={}, query={ + "identity_id": identity_id, "limit": limit, "page": page, "after_id": after_id, @@ -187,16 +213,20 @@ async def upload( purpose: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> FileMetadata: - """POST /files.""" + """POST /files. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files") options = make_request_options( body={"file": file, "name": name, "purpose": purpose, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -209,16 +239,20 @@ async def retrieve_metadata( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> FileMetadata: - """GET /files/{file_id}.""" + """GET /files/{file_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -231,16 +265,20 @@ async def delete( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /files/{file_id}.""" + """DELETE /files/{file_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -253,16 +291,20 @@ async def download( self, file_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncBinaryAPIResponse: - """GET /files/{file_id}/content.""" + """GET /files/{file_id}/content. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/files/{file_id}/content", file_id=file_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/resources/skills/skills.py b/src/qca/forward/resources/skills/skills.py index ec1f94c..e9f2676 100644 --- a/src/qca/forward/resources/skills/skills.py +++ b/src/qca/forward/resources/skills/skills.py @@ -30,16 +30,21 @@ def list( display_title: Union[str, None, NotGiven] = NOT_GIVEN, source: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[Skill]: - """GET /skills.""" + """GET /skills. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills") options = make_request_options( body={}, query={ + "identity_id": identity_id, "limit": limit, "page": page, "after_id": after_id, @@ -67,12 +72,16 @@ def create( description: Union[str, None, NotGiven] = NOT_GIVEN, type: Union[str, None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """POST /skills.""" + """POST /skills. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills") options = make_request_options( body={ @@ -84,7 +93,7 @@ def create( "description": description, "type": type, }, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -98,16 +107,20 @@ def retrieve( skill_id: str, *, include_content: Union[bool, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """GET /skills/{skill_id}.""" + """GET /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={}, - query={"include_content": include_content}, + query={"identity_id": identity_id, "include_content": include_content}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -126,12 +139,16 @@ def update( metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, icon_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """PUT /skills/{skill_id}.""" + """PUT /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={ @@ -142,7 +159,7 @@ def update( "icon_id": icon_id, "name": name, }, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -155,16 +172,20 @@ def delete( self, skill_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /skills/{skill_id}.""" + """DELETE /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -189,16 +210,21 @@ def list( display_title: Union[str, None, NotGiven] = NOT_GIVEN, source: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[Skill]: - """GET /skills.""" + """GET /skills. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills") options = make_request_options( body={}, query={ + "identity_id": identity_id, "limit": limit, "page": page, "after_id": after_id, @@ -228,12 +254,16 @@ async def create( description: Union[str, None, NotGiven] = NOT_GIVEN, type: Union[str, None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """POST /skills.""" + """POST /skills. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills") options = make_request_options( body={ @@ -245,7 +275,7 @@ async def create( "description": description, "type": type, }, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -259,16 +289,20 @@ async def retrieve( skill_id: str, *, include_content: Union[bool, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """GET /skills/{skill_id}.""" + """GET /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={}, - query={"include_content": include_content}, + query={"identity_id": identity_id, "include_content": include_content}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -287,12 +321,16 @@ async def update( metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, icon_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Skill: - """PUT /skills/{skill_id}.""" + """PUT /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={ @@ -303,7 +341,7 @@ async def update( "icon_id": icon_id, "name": name, }, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -316,16 +354,20 @@ async def delete( self, skill_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /skills/{skill_id}.""" + """DELETE /skills/{skill_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}", skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/resources/skills/versions.py b/src/qca/forward/resources/skills/versions.py index 19cefbe..f1023f0 100644 --- a/src/qca/forward/resources/skills/versions.py +++ b/src/qca/forward/resources/skills/versions.py @@ -22,16 +22,20 @@ def list( *, limit: Union[int, None, NotGiven] = NOT_GIVEN, page: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[SkillVersion]: - """GET /skills/{skill_id}/versions.""" + """GET /skills/{skill_id}/versions. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions", skill_id=skill_id) options = make_request_options( body={}, - query={"limit": limit, "page": page}, + query={"identity_id": identity_id, "limit": limit, "page": page}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -45,16 +49,20 @@ def create( skill_id: str, *, files: List[FileTypes], + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SkillVersion: - """POST /skills/{skill_id}/versions.""" + """POST /skills/{skill_id}/versions. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions", skill_id=skill_id) options = make_request_options( body={"files": files}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -68,16 +76,20 @@ def retrieve( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SkillVersion: - """GET /skills/{skill_id}/versions/{version}.""" + """GET /skills/{skill_id}/versions/{version}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -91,16 +103,20 @@ def delete( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> DeletedSkillVersion: - """DELETE /skills/{skill_id}/versions/{version}.""" + """DELETE /skills/{skill_id}/versions/{version}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -114,16 +130,20 @@ def download( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BinaryAPIResponse: - """GET /skills/{skill_id}/versions/{version}/content.""" + """GET /skills/{skill_id}/versions/{version}/content. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}/content", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -140,16 +160,20 @@ def list( *, limit: Union[int, None, NotGiven] = NOT_GIVEN, page: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[SkillVersion]: - """GET /skills/{skill_id}/versions.""" + """GET /skills/{skill_id}/versions. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions", skill_id=skill_id) options = make_request_options( body={}, - query={"limit": limit, "page": page}, + query={"identity_id": identity_id, "limit": limit, "page": page}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -165,16 +189,20 @@ async def create( skill_id: str, *, files: List[FileTypes], + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SkillVersion: - """POST /skills/{skill_id}/versions.""" + """POST /skills/{skill_id}/versions. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions", skill_id=skill_id) options = make_request_options( body={"files": files}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -188,16 +216,20 @@ async def retrieve( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SkillVersion: - """GET /skills/{skill_id}/versions/{version}.""" + """GET /skills/{skill_id}/versions/{version}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -211,16 +243,20 @@ async def delete( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> DeletedSkillVersion: - """DELETE /skills/{skill_id}/versions/{version}.""" + """DELETE /skills/{skill_id}/versions/{version}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -234,16 +270,20 @@ async def download( version: str, *, skill_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncBinaryAPIResponse: - """GET /skills/{skill_id}/versions/{version}/content.""" + """GET /skills/{skill_id}/versions/{version}/content. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/skills/{skill_id}/versions/{version}/content", version=version, skill_id=skill_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/resources/vaults/credentials.py b/src/qca/forward/resources/vaults/credentials.py index 644742a..bb5708a 100644 --- a/src/qca/forward/resources/vaults/credentials.py +++ b/src/qca/forward/resources/vaults/credentials.py @@ -56,16 +56,27 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[VaultCredential]: - """GET /vaults/{vault_id}/credentials.""" + """GET /vaults/{vault_id}/credentials. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}/credentials", vault_id=vault_id) options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id, "name": name}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + "name": name, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -82,16 +93,20 @@ def create( display_name: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VaultCredential: - """POST /vaults/{vault_id}/credentials.""" + """POST /vaults/{vault_id}/credentials. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}/credentials", vault_id=vault_id) options = make_request_options( body={"auth": auth, "display_name": display_name, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -105,18 +120,22 @@ def retrieve( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VaultCredential: - """GET /vaults/{vault_id}/credentials/{credential_id}.""" + """GET /vaults/{vault_id}/credentials/{credential_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template( "/vaults/{vault_id}/credentials/{credential_id}", credential_id=credential_id, vault_id=vault_id ) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -130,18 +149,22 @@ def delete( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /vaults/{vault_id}/credentials/{credential_id}.""" + """DELETE /vaults/{vault_id}/credentials/{credential_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template( "/vaults/{vault_id}/credentials/{credential_id}", credential_id=credential_id, vault_id=vault_id ) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -193,16 +216,27 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[VaultCredential]: - """GET /vaults/{vault_id}/credentials.""" + """GET /vaults/{vault_id}/credentials. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}/credentials", vault_id=vault_id) options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id, "name": name}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + "name": name, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -223,16 +257,20 @@ async def create( display_name: Union[str, None, NotGiven] = NOT_GIVEN, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VaultCredential: - """POST /vaults/{vault_id}/credentials.""" + """POST /vaults/{vault_id}/credentials. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}/credentials", vault_id=vault_id) options = make_request_options( body={"auth": auth, "display_name": display_name, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -246,18 +284,22 @@ async def retrieve( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VaultCredential: - """GET /vaults/{vault_id}/credentials/{credential_id}.""" + """GET /vaults/{vault_id}/credentials/{credential_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template( "/vaults/{vault_id}/credentials/{credential_id}", credential_id=credential_id, vault_id=vault_id ) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -271,18 +313,22 @@ async def delete( credential_id: str, *, vault_id: str, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /vaults/{vault_id}/credentials/{credential_id}.""" + """DELETE /vaults/{vault_id}/credentials/{credential_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template( "/vaults/{vault_id}/credentials/{credential_id}", credential_id=credential_id, vault_id=vault_id ) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/resources/vaults/vaults.py b/src/qca/forward/resources/vaults/vaults.py index a8f0f00..ea4a585 100644 --- a/src/qca/forward/resources/vaults/vaults.py +++ b/src/qca/forward/resources/vaults/vaults.py @@ -28,16 +28,27 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncPage[Vault]: - """GET /vaults.""" + """GET /vaults. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults") options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id, "name": name}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + "name": name, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -52,16 +63,20 @@ def create( display_name: str, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Vault: - """POST /vaults.""" + """POST /vaults. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults") options = make_request_options( body={"display_name": display_name, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -74,16 +89,20 @@ def retrieve( self, vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Vault: - """GET /vaults/{vault_id}.""" + """GET /vaults/{vault_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}", vault_id=vault_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -96,16 +115,20 @@ def delete( self, vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /vaults/{vault_id}.""" + """DELETE /vaults/{vault_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}", vault_id=vault_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -128,16 +151,27 @@ def list( after_id: Union[str, None, NotGiven] = NOT_GIVEN, before_id: Union[str, None, NotGiven] = NOT_GIVEN, name: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[Vault]: - """GET /vaults.""" + """GET /vaults. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults") options = make_request_options( body={}, - query={"limit": limit, "page": page, "after_id": after_id, "before_id": before_id, "name": name}, + query={ + "identity_id": identity_id, + "limit": limit, + "page": page, + "after_id": after_id, + "before_id": before_id, + "name": name, + }, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -154,16 +188,20 @@ async def create( display_name: str, metadata: Union[Dict[str, Any], None, NotGiven] = NOT_GIVEN, idempotency_key: Union[str, None, NotGiven] = NOT_GIVEN, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Vault: - """POST /vaults.""" + """POST /vaults. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults") options = make_request_options( body={"display_name": display_name, "metadata": metadata}, - query={}, + query={"identity_id": identity_id}, headers={"Idempotency-Key": idempotency_key}, extra_headers=extra_headers, extra_query=extra_query, @@ -176,16 +214,20 @@ async def retrieve( self, vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> Vault: - """GET /vaults/{vault_id}.""" + """GET /vaults/{vault_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}", vault_id=vault_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, @@ -198,16 +240,20 @@ async def delete( self, vault_id: str, *, + identity_id: Union[str, NotGiven] = NOT_GIVEN, extra_headers: Dict[str, str] | None = None, extra_query: Dict[str, Any] | None = None, extra_body: Dict[str, Any] | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """DELETE /vaults/{vault_id}.""" + """DELETE /vaults/{vault_id}. + + identity_id selects identity ownership with a PAT; omit it with a SAT. + """ _path = path_template("/vaults/{vault_id}", vault_id=vault_id) options = make_request_options( body={}, - query={}, + query={"identity_id": identity_id}, headers={}, extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/qca/forward/types/channel_pairing.py b/src/qca/forward/types/channel_pairing.py index aa8efa3..74f7964 100644 --- a/src/qca/forward/types/channel_pairing.py +++ b/src/qca/forward/types/channel_pairing.py @@ -15,3 +15,8 @@ class ChannelPairing(BaseModel): template_id: Optional[str] = None status: Optional[str] = None paired_at: Optional[str] = None + scope_type: Optional[str] = None + scope_external_id: Optional[str] = None + scope_display_name: Optional[str] = None + created_at: Optional[str] = None + updated_at: Optional[str] = None diff --git a/src/qca/forward/types/channel_pairing_create_params.py b/src/qca/forward/types/channel_pairing_create_params.py index 939225a..662204b 100644 --- a/src/qca/forward/types/channel_pairing_create_params.py +++ b/src/qca/forward/types/channel_pairing_create_params.py @@ -8,7 +8,9 @@ class ChannelPairingCreateParams(TypedDict, total=False): - code: Required[str] + code: str + """Supply exactly one of code or channel_pairing_id.""" + channel_pairing_id: str identity_id: Required[str] template_id: Required[str] idempotency_key: Optional[str] diff --git a/src/qca/forward/types/environment_create_params.py b/src/qca/forward/types/environment_create_params.py index 28d5ade..671e0e2 100644 --- a/src/qca/forward/types/environment_create_params.py +++ b/src/qca/forward/types/environment_create_params.py @@ -8,6 +8,8 @@ class EnvironmentCreateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" name: Required[str] description: Optional[str] config: Dict[str, Any] diff --git a/src/qca/forward/types/environment_list_params.py b/src/qca/forward/types/environment_list_params.py index a44cd1a..87b4479 100644 --- a/src/qca/forward/types/environment_list_params.py +++ b/src/qca/forward/types/environment_list_params.py @@ -8,6 +8,8 @@ class EnvironmentListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] after_id: Optional[str] diff --git a/src/qca/forward/types/environment_update_params.py b/src/qca/forward/types/environment_update_params.py index 2dc9053..769f868 100644 --- a/src/qca/forward/types/environment_update_params.py +++ b/src/qca/forward/types/environment_update_params.py @@ -8,6 +8,8 @@ class EnvironmentUpdateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" name: Optional[str] description: Optional[str] config: Dict[str, Any] diff --git a/src/qca/forward/types/file_list_params.py b/src/qca/forward/types/file_list_params.py index cb39c14..a148d07 100644 --- a/src/qca/forward/types/file_list_params.py +++ b/src/qca/forward/types/file_list_params.py @@ -8,6 +8,8 @@ class FileListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] after_id: Optional[str] diff --git a/src/qca/forward/types/file_upload_params.py b/src/qca/forward/types/file_upload_params.py index d7d8525..bd4f4ce 100644 --- a/src/qca/forward/types/file_upload_params.py +++ b/src/qca/forward/types/file_upload_params.py @@ -10,6 +10,8 @@ class FileUploadParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" file: Required[FileTypes] name: Optional[str] purpose: Optional[str] diff --git a/src/qca/forward/types/session_usage.py b/src/qca/forward/types/session_usage.py index cb1e9c2..5c57bb9 100644 --- a/src/qca/forward/types/session_usage.py +++ b/src/qca/forward/types/session_usage.py @@ -8,4 +8,6 @@ class SessionUsage(BaseModel): + model_credits: Optional[float] = None + sandbox_runtime_credits: Optional[float] = None total_credits: Optional[float] = None diff --git a/src/qca/forward/types/skill_create_params.py b/src/qca/forward/types/skill_create_params.py index 998883f..45d8c4a 100644 --- a/src/qca/forward/types/skill_create_params.py +++ b/src/qca/forward/types/skill_create_params.py @@ -10,6 +10,8 @@ class SkillCreateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" files: List[FileTypes] metadata: Dict[str, Any] icon_id: Optional[str] diff --git a/src/qca/forward/types/skill_list_params.py b/src/qca/forward/types/skill_list_params.py index 749ba2e..e302b6e 100644 --- a/src/qca/forward/types/skill_list_params.py +++ b/src/qca/forward/types/skill_list_params.py @@ -8,6 +8,8 @@ class SkillListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] after_id: Optional[str] diff --git a/src/qca/forward/types/skill_retrieve_params.py b/src/qca/forward/types/skill_retrieve_params.py index 658e816..f9976e0 100644 --- a/src/qca/forward/types/skill_retrieve_params.py +++ b/src/qca/forward/types/skill_retrieve_params.py @@ -8,4 +8,6 @@ class SkillRetrieveParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" include_content: Optional[bool] diff --git a/src/qca/forward/types/skill_update_params.py b/src/qca/forward/types/skill_update_params.py index ebbf3fe..85f60ef 100644 --- a/src/qca/forward/types/skill_update_params.py +++ b/src/qca/forward/types/skill_update_params.py @@ -8,6 +8,8 @@ class SkillUpdateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" description: Optional[str] content: Optional[str] content_encoding: Optional[str] diff --git a/src/qca/forward/types/skill_version_create_params.py b/src/qca/forward/types/skill_version_create_params.py index 693baf7..71a852e 100644 --- a/src/qca/forward/types/skill_version_create_params.py +++ b/src/qca/forward/types/skill_version_create_params.py @@ -10,4 +10,6 @@ class SkillVersionCreateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" files: Required[List[FileTypes]] diff --git a/src/qca/forward/types/skill_version_list_params.py b/src/qca/forward/types/skill_version_list_params.py index e6fa340..b0e243c 100644 --- a/src/qca/forward/types/skill_version_list_params.py +++ b/src/qca/forward/types/skill_version_list_params.py @@ -8,5 +8,7 @@ class SkillVersionListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] diff --git a/src/qca/forward/types/vault_create_params.py b/src/qca/forward/types/vault_create_params.py index 5ef21e0..661fef9 100644 --- a/src/qca/forward/types/vault_create_params.py +++ b/src/qca/forward/types/vault_create_params.py @@ -8,6 +8,8 @@ class VaultCreateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" display_name: Required[str] metadata: Dict[str, Any] idempotency_key: Optional[str] diff --git a/src/qca/forward/types/vault_credential_create_params.py b/src/qca/forward/types/vault_credential_create_params.py index bd5ea18..f1fd256 100644 --- a/src/qca/forward/types/vault_credential_create_params.py +++ b/src/qca/forward/types/vault_credential_create_params.py @@ -8,6 +8,8 @@ class VaultCredentialCreateParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" auth: Required[Dict[str, Any]] display_name: Optional[str] metadata: Dict[str, Any] diff --git a/src/qca/forward/types/vault_credential_list_params.py b/src/qca/forward/types/vault_credential_list_params.py index 3d71b59..0caaba1 100644 --- a/src/qca/forward/types/vault_credential_list_params.py +++ b/src/qca/forward/types/vault_credential_list_params.py @@ -8,6 +8,8 @@ class VaultCredentialListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] after_id: Optional[str] diff --git a/src/qca/forward/types/vault_list_params.py b/src/qca/forward/types/vault_list_params.py index 53a96ec..b444cc9 100644 --- a/src/qca/forward/types/vault_list_params.py +++ b/src/qca/forward/types/vault_list_params.py @@ -8,6 +8,8 @@ class VaultListParams(TypedDict, total=False): + identity_id: str + """Select identity ownership with a PAT. Omit when using a SAT.""" limit: Optional[int] page: Optional[str] after_id: Optional[str] diff --git a/src/qca/managed/types/budget_limit.py b/src/qca/managed/types/budget_limit.py index ffc3af7..b8c257e 100644 --- a/src/qca/managed/types/budget_limit.py +++ b/src/qca/managed/types/budget_limit.py @@ -1,15 +1,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional +from typing import Optional from qca.common._models import BaseModel -if TYPE_CHECKING: - from .monetary_amount import MonetaryAmount - __all__ = ["BudgetLimit"] class BudgetLimit(BaseModel): - max_list_cost: Optional[MonetaryAmount] = None + # Positive decimal Credits, at most 12 integer and 2 fractional digits. + max_credit_cost: Optional[str] = None type: Optional[str] = None diff --git a/src/qca/managed/types/budget_limit_param.py b/src/qca/managed/types/budget_limit_param.py index 6547695..8c1b439 100644 --- a/src/qca/managed/types/budget_limit_param.py +++ b/src/qca/managed/types/budget_limit_param.py @@ -1,15 +1,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Literal +from typing import Literal from typing_extensions import Required, TypedDict -if TYPE_CHECKING: - from .monetary_amount_param import MonetaryAmountParam - __all__ = ["BudgetLimitParam"] class BudgetLimitParam(TypedDict, total=False): - max_list_cost: Required[MonetaryAmountParam] + # Positive decimal Credits, at most 12 integer and 2 fractional digits. + max_credit_cost: Required[str] type: Required[Literal["limit"]] diff --git a/src/qca/managed/types/session_event.py b/src/qca/managed/types/session_event.py index b2ff8ca..32bc88a 100644 --- a/src/qca/managed/types/session_event.py +++ b/src/qca/managed/types/session_event.py @@ -27,6 +27,10 @@ class SessionEvent(BaseModel): + model_credits: Optional[float] = None + sandbox_runtime_credits: Optional[float] = None + total_credits: Optional[float] = None + id: Optional[str] = None content: Optional[ Union[ diff --git a/src/qca/managed/types/session_event_usage.py b/src/qca/managed/types/session_event_usage.py index 7d77f49..855a114 100644 --- a/src/qca/managed/types/session_event_usage.py +++ b/src/qca/managed/types/session_event_usage.py @@ -13,6 +13,7 @@ class SessionEventUsage(BaseModel): + credits: Optional[float] = None cache_creation_input_tokens: Optional[int] = None cache_read_input_tokens: Optional[int] = None input_tokens: Optional[int] = None diff --git a/src/qca/managed/types/session_stream_event.py b/src/qca/managed/types/session_stream_event.py index 8f17c76..4840077 100644 --- a/src/qca/managed/types/session_stream_event.py +++ b/src/qca/managed/types/session_stream_event.py @@ -29,6 +29,10 @@ class SessionStreamEvent(BaseModel): + model_credits: Optional[float] = None + sandbox_runtime_credits: Optional[float] = None + total_credits: Optional[float] = None + id: Optional[str] = None content: Optional[ Union[ diff --git a/src/qca/managed/types/session_stream_event_usage.py b/src/qca/managed/types/session_stream_event_usage.py index 307c7f9..60dea98 100644 --- a/src/qca/managed/types/session_stream_event_usage.py +++ b/src/qca/managed/types/session_stream_event_usage.py @@ -13,6 +13,7 @@ class SessionStreamEventUsage(BaseModel): + credits: Optional[float] = None cache_creation_input_tokens: Optional[int] = None cache_read_input_tokens: Optional[int] = None input_tokens: Optional[int] = None diff --git a/src/qca/managed/types/session_usage.py b/src/qca/managed/types/session_usage.py index c2213ef..4ee07b7 100644 --- a/src/qca/managed/types/session_usage.py +++ b/src/qca/managed/types/session_usage.py @@ -13,6 +13,10 @@ class SessionUsage(BaseModel): + model_credits: Optional[float] = None + sandbox_runtime_credits: Optional[float] = None + total_credits: Optional[float] = None + active_seconds: Optional[float] = None cache_creation: Optional[CacheCreationUsage] = None cache_read_input_tokens: Optional[int] = None diff --git a/src/qca/managed/types/span_model_usage.py b/src/qca/managed/types/span_model_usage.py index be2348a..b9a30f8 100644 --- a/src/qca/managed/types/span_model_usage.py +++ b/src/qca/managed/types/span_model_usage.py @@ -8,6 +8,7 @@ class SpanModelUsage(BaseModel): + credits: Optional[float] = None cache_creation_input_tokens: Optional[int] = None cache_read_input_tokens: Optional[int] = None input_tokens: Optional[int] = None diff --git a/src/qca/managed/types/stream_session_thread_events_union.py b/src/qca/managed/types/stream_session_thread_events_union.py index a8e2fd2..c515aae 100644 --- a/src/qca/managed/types/stream_session_thread_events_union.py +++ b/src/qca/managed/types/stream_session_thread_events_union.py @@ -29,6 +29,10 @@ class StreamSessionThreadEventsUnion(BaseModel): + model_credits: Optional[float] = None + sandbox_runtime_credits: Optional[float] = None + total_credits: Optional[float] = None + id: Optional[str] = None content: Optional[ Union[ diff --git a/src/qca/managed/types/stream_session_thread_events_union_usage.py b/src/qca/managed/types/stream_session_thread_events_union_usage.py index 6f877e3..d718847 100644 --- a/src/qca/managed/types/stream_session_thread_events_union_usage.py +++ b/src/qca/managed/types/stream_session_thread_events_union_usage.py @@ -13,6 +13,7 @@ class StreamSessionThreadEventsUnionUsage(BaseModel): + credits: Optional[float] = None cache_creation_input_tokens: Optional[int] = None cache_read_input_tokens: Optional[int] = None input_tokens: Optional[int] = None diff --git a/tests/_surface.py b/tests/_surface.py index abcebaa..ab5aa38 100644 --- a/tests/_surface.py +++ b/tests/_surface.py @@ -145,7 +145,13 @@ def _endpoint(mode: str, attribute: str, function: Any) -> Endpoint: for name, parameter in signature.parameters.items() if name not in ("self", *CONTROL_PARAMS) and parameter.default is inspect.Parameter.empty } - assert sorted(arguments) == contract["required"], f"{endpoint_id} required parameters drifted" + required = contract["required"] + if endpoint_id == "forward.channel_pairings.create": + # Official 2026-10-20 contract allows code OR channel_pairing_id. + required = [name for name in required if name != "code"] + assert sorted(arguments) == required, f"{endpoint_id} required parameters drifted" + if endpoint_id == "forward.channel_pairings.create": + arguments["code"] = "K7MP92" # Keep generic transport fixtures valid. placeholders = tuple(re.findall(r"\{(\w+)\}", contract["path"])) missing = [name for name in placeholders if name not in arguments] assert not missing, f"{endpoint_id} does not accept path parameters {missing}" diff --git a/tests/test_identity_pairing_contract.py b/tests/test_identity_pairing_contract.py new file mode 100644 index 0000000..2415ee0 --- /dev/null +++ b/tests/test_identity_pairing_contract.py @@ -0,0 +1,183 @@ +"""Official Forward ownership and pairing wire contracts (2026-10-20).""" + +import inspect +import json + +import httpx +import pytest + +from qca import AsyncForward, Forward + + +async def resolve(value): + return await value if inspect.isawaitable(value) else value + + +OPERATIONS = [ + ("GET", "environments", lambda c, scope, file: c.environments.list(**scope)), + ("POST", "environments", lambda c, scope, file: c.environments.create(name="env", **scope)), + ("GET", "environments/env", lambda c, scope, file: c.environments.retrieve("env", **scope)), + ("POST", "environments/env", lambda c, scope, file: c.environments.update("env", name="renamed", **scope)), + ("POST", "environments/env/archive", lambda c, scope, file: c.environments.archive("env", **scope)), + ("DELETE", "environments/env", lambda c, scope, file: c.environments.delete("env", **scope)), + ("GET", "skills", lambda c, scope, file: c.skills.list(**scope)), + ("POST", "skills", lambda c, scope, file: c.skills.create(files=[file], **scope)), + ("GET", "skills/skill", lambda c, scope, file: c.skills.retrieve("skill", **scope)), + ("PUT", "skills/skill", lambda c, scope, file: c.skills.update("skill", description="desc", **scope)), + ("DELETE", "skills/skill", lambda c, scope, file: c.skills.delete("skill", **scope)), + ("GET", "skills/skill/versions", lambda c, scope, file: c.skills.versions.list("skill", **scope)), + ("POST", "skills/skill/versions", lambda c, scope, file: c.skills.versions.create("skill", files=[file], **scope)), + ( + "GET", + "skills/skill/versions/1", + lambda c, scope, file: c.skills.versions.retrieve("1", skill_id="skill", **scope), + ), + ( + "DELETE", + "skills/skill/versions/1", + lambda c, scope, file: c.skills.versions.delete("1", skill_id="skill", **scope), + ), + ( + "GET", + "skills/skill/versions/1/content", + lambda c, scope, file: c.skills.versions.download("1", skill_id="skill", **scope), + ), + ("GET", "vaults", lambda c, scope, file: c.vaults.list(**scope)), + ("POST", "vaults", lambda c, scope, file: c.vaults.create(display_name="vault", **scope)), + ("GET", "vaults/vault", lambda c, scope, file: c.vaults.retrieve("vault", **scope)), + ("DELETE", "vaults/vault", lambda c, scope, file: c.vaults.delete("vault", **scope)), + ("GET", "vaults/vault/credentials", lambda c, scope, file: c.vaults.credentials.list("vault", **scope)), + ( + "POST", + "vaults/vault/credentials", + lambda c, scope, file: c.vaults.credentials.create( + "vault", auth={"type": "static_bearer", "token": "secret"}, **scope + ), + ), + ( + "GET", + "vaults/vault/credentials/cred", + lambda c, scope, file: c.vaults.credentials.retrieve("cred", vault_id="vault", **scope), + ), + ( + "POST", + "vaults/vault/credentials/cred", + lambda c, scope, file: c.vaults.credentials.update( + "cred", vault_id="vault", metadata={"note": "rotation"}, **scope + ), + ), + ( + "DELETE", + "vaults/vault/credentials/cred", + lambda c, scope, file: c.vaults.credentials.delete("cred", vault_id="vault", **scope), + ), + ("GET", "files", lambda c, scope, file: c.files.list(**scope)), + ("POST", "files", lambda c, scope, file: c.files.upload(file=file, **scope)), + ("GET", "files/file", lambda c, scope, file: c.files.retrieve_metadata("file", **scope)), + ("DELETE", "files/file", lambda c, scope, file: c.files.delete("file", **scope)), + ("GET", "files/file/content", lambda c, scope, file: c.files.download("file", **scope)), +] + + +@pytest.mark.parametrize("async_", [False, True]) +@pytest.mark.parametrize("identity", ["idn_ /?&", "", None]) +@pytest.mark.parametrize("method,path,call", OPERATIONS) +async def test_identity_query_scope(async_, identity, method, path, call): + api_calls = 0 + + def handle(req): + nonlocal api_calls + if req.url.host == "storage.test": + assert req.url.query == b"signature=ok" + assert "authorization" not in req.headers + return httpx.Response(200, content=b"content") + api_calls += 1 + assert req.method == method + assert req.url.path == "/api/v1/forward/" + path + assert req.url.params.get("identity_id") == identity + assert list(req.url.params.keys()) == ([] if identity is None else ["identity_id"]) + assert b"identity_id" not in req.read() + if path == "files/file/content": + return httpx.Response(200, json={"url": "https://storage.test/content?signature=ok"}) + if path.endswith("/content"): + return httpx.Response(200, content=b"archive") + return httpx.Response(200, json={"id": "resource", "data": [], "has_more": False}) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + c = (AsyncForward if async_ else Forward)(pat="test", http_client=http) + try: + result = await resolve(call(c, {} if identity is None else {"identity_id": identity}, ("SKILL.md", b"# skill"))) + if path.endswith("/content"): + await resolve(result.close()) + assert api_calls == 1 + finally: + await resolve(c.close()) + + +@pytest.mark.parametrize("async_", [False, True]) +async def test_identity_query_overrides_and_pagination(async_): + calls = 0 + + def handle(req): + nonlocal calls + assert req.url.params["identity_id"] == "idn_override" + calls += 1 + return httpx.Response( + 200, + json={ + "data": [{"id": f"env_{calls}"}], + "has_more": calls == 1, + "next_page": "cursor" if calls == 1 else None, + }, + ) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + c = (AsyncForward if async_ else Forward)(pat="test", http_client=http) + try: + page = await resolve(c.environments.list(identity_id="idn_typed", extra_query={"identity_id": "idn_override"})) + items = [e async for e in page] if async_ else list(page) + assert len(items) == 2 + await resolve( + c.environments.retrieve("env", identity_id="idn_typed", extra_query={"identity_id": "idn_override"}) + ) + finally: + await resolve(c.close()) + + +PAIRING = { + "id": "pair_one", + "type": "channel_pairing", + "channel_id": "channel_one", + "scope_type": "room", + "scope_external_id": "room_one", + "scope_display_name": "Team", + "identity_id": "idn_one", + "template_id": "tmpl_one", + "status": "active", + "paired_at": "2026-10-20T01:00:00Z", +} + + +@pytest.mark.parametrize("async_", [False, True]) +@pytest.mark.parametrize("selector", [{"code": "K7MP92"}, {"channel_pairing_id": "pair_one"}]) +async def test_pair_by_code_or_id(async_, selector): + def handle(req): + assert not req.url.query + assert req.headers["idempotency-key"] == "pair-once" + assert json.loads(req.content) == {**selector, "identity_id": "idn_one", "template_id": "tmpl_one"} + return httpx.Response(200, json=PAIRING) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + c = (AsyncForward if async_ else Forward)(pat="test", http_client=http, _strict_response_validation=True) + try: + result = await resolve( + c.channel_pairings.create( + **selector, identity_id="idn_one", template_id="tmpl_one", idempotency_key="pair-once" + ) + ) + assert result.scope_type == "room" + assert result.scope_external_id == "room_one" + assert result.scope_display_name == "Team" + assert {"scope_type", "scope_external_id", "scope_display_name"} <= type(result).model_fields.keys() + finally: + await resolve(c.close()) diff --git a/tests/test_session_credit_contract.py b/tests/test_session_credit_contract.py new file mode 100644 index 0000000..24f045a --- /dev/null +++ b/tests/test_session_credit_contract.py @@ -0,0 +1,96 @@ +"""Official session schemas, retrieved 2026-10-20; no service credentials needed.""" + +import inspect +import json + +import httpx +import pytest + +from qca import AsyncForward, AsyncManaged, Forward, Managed + + +async def resolve(value): + return await value if inspect.isawaitable(value) else value + + +@pytest.mark.parametrize("async_", [False, True]) +@pytest.mark.parametrize("body", [{"budget": {"type": "limit", "max_credit_cost": "100.00"}}, {}, {"budget": None}]) +async def test_budget_decimal_omission_and_clear(async_, body): + def handle(req): + assert json.loads(req.content) == body + return httpx.Response(200, json={"id": "sess_one", **body}) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + client = (AsyncManaged if async_ else Managed)(pat="test", http_client=http, _strict_response_validation=True) + try: + session = await resolve(client.sessions.update("sess_one", **body)) + if body.get("budget"): + assert session.budget.max_credit_cost == "100.00" + finally: + await resolve(client.close()) + + +@pytest.mark.parametrize("async_", [False, True]) +@pytest.mark.parametrize("forward", [False, True]) +async def test_session_credit_snapshot_and_absence(async_, forward): + usage = {"model_credits": 7.66, "sandbox_runtime_credits": 0.34, "total_credits": 8} + + def handle(req): + return httpx.Response( + 200, json={"id": "sess_one", **({"usage": usage} if req.url.path.endswith("sess_one") else {})} + ) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + client_type = (AsyncForward if async_ else Forward) if forward else (AsyncManaged if async_ else Managed) + client = client_type(pat="test", http_client=http, _strict_response_validation=True) + try: + session = await resolve(client.sessions.retrieve("sess_one")) + assert session.usage.model_credits == 7.66 + assert session.usage.sandbox_runtime_credits == 0.34 + assert session.usage.total_credits == 8 + assert "model_credits" in type(session.usage).model_fields + empty = await resolve(client.sessions.retrieve("sess_empty")) + assert empty.usage is None + finally: + await resolve(client.close()) + + +@pytest.mark.parametrize("async_", [False, True]) +async def test_credit_events_in_history_and_streams(async_): + events = [ + { + "id": "evt_1", + "type": "session.usage", + "model_credits": 7.66, + "sandbox_runtime_credits": 0.34, + "total_credits": 8, + }, + {"id": "evt_2", "type": "agent.thread_context_compacted", "usage": {"credits": 0}}, + {"id": "evt_3", "type": "span.model_request_end", "model_usage": {"credits": 1.25}}, + ] + + def handle(req): + if req.url.path.endswith("/stream"): + wire = "".join(f"id: {e['id']}\nevent: {e['type']}\ndata: {json.dumps(e)}\n\n" for e in events) + return httpx.Response(200, text=wire, headers={"Content-Type": "text/event-stream"}) + return httpx.Response(200, json={"data": events, "has_more": False, "next_page": None}) + + http = (httpx.AsyncClient if async_ else httpx.Client)(transport=httpx.MockTransport(handle)) + client = (AsyncManaged if async_ else Managed)(pat="test", http_client=http, _strict_response_validation=True) + + def check(items): + assert items[0].model_credits == 7.66 and items[0].total_credits == 8 + assert "total_credits" in type(items[0]).model_fields + assert items[1].usage.credits == 0 + assert "credits" in type(items[1].usage).model_fields + assert items[2].model_usage.credits == 1.25 + + try: + page = await resolve(client.sessions.events.list("sess_one")) + check(page.data) + stream = await resolve(client.sessions.events.stream("sess_one")) + check([e async for e in stream] if async_ else list(stream)) + thread_stream = await resolve(client.sessions.threads.events.stream("thread_one", session_id="sess_one")) + check([e async for e in thread_stream] if async_ else list(thread_stream)) + finally: + await resolve(client.close())