From 28ec77629321bf0c36a6052fe4890302c739dee3 Mon Sep 17 00:00:00 2001 From: moonyue-w <300878504+moonyue-w@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:56:25 +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 wire contract and public type 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/forward/README.md | 1 + docs/api/forward/classes/Environments.md | 6 +- docs/api/forward/classes/Files.md | 6 +- docs/api/forward/classes/SkillVersions.md | 6 +- docs/api/forward/classes/Skills.md | 2 +- docs/api/forward/classes/VaultCredentials.md | 4 +- docs/api/forward/classes/Vaults.md | 4 +- docs/api/forward/interfaces/ChannelPairing.md | 30 +++ .../interfaces/ChannelPairingNewParams.md | 14 +- .../interfaces/EnvironmentListParams.md | 8 + .../interfaces/EnvironmentNewParams.md | 8 + .../interfaces/EnvironmentUpdateParams.md | 8 + docs/api/forward/interfaces/FileListParams.md | 8 + .../forward/interfaces/FileUploadParams.md | 8 + docs/api/forward/interfaces/Session.md | 4 +- docs/api/forward/interfaces/SessionUsage.md | 12 + docs/api/forward/interfaces/SkillGetParams.md | 8 + .../api/forward/interfaces/SkillListParams.md | 8 + docs/api/forward/interfaces/SkillNewParams.md | 8 + .../forward/interfaces/SkillUpdateParams.md | 8 + .../interfaces/SkillVersionListParams.md | 8 + .../interfaces/SkillVersionNewParams.md | 8 + .../interfaces/VaultCredentialListParams.md | 8 + .../interfaces/VaultCredentialNewParams.md | 8 + .../api/forward/interfaces/VaultListParams.md | 8 + docs/api/forward/interfaces/VaultNewParams.md | 8 + .../type-aliases/IdentityScopeOptions.md | 17 ++ .../managed/interfaces/DeploymentNewParams.md | 4 +- .../interfaces/DeploymentUpdateParams.md | 4 +- ...dAgentsAgentThreadContextCompactedEvent.md | 8 + .../interfaces/ManagedAgentsBudgetLimit.md | 10 +- .../ManagedAgentsBudgetLimitParam.md | 10 +- .../interfaces/ManagedAgentsDeployment.md | 4 +- .../interfaces/ManagedAgentsSession.md | 14 +- .../ManagedAgentsSessionEventUnionUsage.md | 6 + .../ManagedAgentsSessionUpdatedEvent.md | 4 +- .../interfaces/ManagedAgentsSessionUsage.md | 22 +- .../ManagedAgentsSessionUsageEvent.md | 34 ++- .../ManagedAgentsSpanModelRequestEndEvent.md | 6 +- .../interfaces/ManagedAgentsSpanModelUsage.md | 24 +- ...agedAgentsSpanOutcomeEvaluationEndEvent.md | 2 +- ...agedAgentsStreamSessionEventsUnionUsage.md | 6 + ...entsStreamSessionThreadEventsUnionUsage.md | 6 + .../managed/interfaces/SessionNewParams.md | 4 +- .../managed/interfaces/SessionUpdateParams.md | 4 +- src/forward/_utils.ts | 7 + src/forward/api-inventory.json | 254 ++++++++++++++++-- src/forward/environment.ts | 22 +- src/forward/file.ts | 18 +- src/forward/skill-version.ts | 19 +- src/forward/skill.ts | 16 +- src/forward/types.ts | 51 +++- src/forward/vault-credential.ts | 14 +- src/forward/vault.ts | 14 +- src/managed/types.ts | 94 ++++--- tests/identity-pairing-contract.test.mjs | 88 ++++++ tests/managed-field-parity.test.mjs | 4 +- tests/managed-types.ts | 14 + tests/session-credit-contract.test.mjs | 36 +++ tests/types-smoke.ts | 19 ++ 61 files changed, 911 insertions(+), 171 deletions(-) create mode 100644 docs/api/forward/type-aliases/IdentityScopeOptions.md create mode 100644 tests/identity-pairing-contract.test.mjs create mode 100644 tests/session-credit-contract.test.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cf79f4..929af27 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. +- Set `identity_id` in resource params; for methods without params, set it in the existing request-options argument. 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/forward/README.md b/docs/api/forward/README.md index d81a5a7..ca32561 100644 --- a/docs/api/forward/README.md +++ b/docs/api/forward/README.md @@ -251,6 +251,7 @@ - [EventContentUnionParam](type-aliases/EventContentUnionParam.md) - [ForwardClientOptions](type-aliases/ForwardClientOptions.md) - [IdentityCreateParams](type-aliases/IdentityCreateParams.md) +- [IdentityScopeOptions](type-aliases/IdentityScopeOptions.md) - [MemoryStoreCreateParams](type-aliases/MemoryStoreCreateParams.md) - [MemoryStoreMemoryCreateParams](type-aliases/MemoryStoreMemoryCreateParams.md) - [ModelConfig](type-aliases/ModelConfig.md) diff --git a/docs/api/forward/classes/Environments.md b/docs/api/forward/classes/Environments.md index b98e9b2..5a49461 100644 --- a/docs/api/forward/classes/Environments.md +++ b/docs/api/forward/classes/Environments.md @@ -56,7 +56,7 @@ Archive an environment retained by historical sessions or tool calls. ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -108,7 +108,7 @@ createEnvironment ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -160,7 +160,7 @@ listEnvironment ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/classes/Files.md b/docs/api/forward/classes/Files.md index c572314..db71f0a 100644 --- a/docs/api/forward/classes/Files.md +++ b/docs/api/forward/classes/Files.md @@ -56,7 +56,7 @@ ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -82,7 +82,7 @@ deleteFile ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -108,7 +108,7 @@ downloadFile ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/classes/SkillVersions.md b/docs/api/forward/classes/SkillVersions.md index ea9c447..0d75a72 100644 --- a/docs/api/forward/classes/SkillVersions.md +++ b/docs/api/forward/classes/SkillVersions.md @@ -90,7 +90,7 @@ createSkillVersion ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -120,7 +120,7 @@ deleteSkillVersion ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -180,7 +180,7 @@ listSkillVersion ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/classes/Skills.md b/docs/api/forward/classes/Skills.md index 767d183..32c217a 100644 --- a/docs/api/forward/classes/Skills.md +++ b/docs/api/forward/classes/Skills.md @@ -88,7 +88,7 @@ createSkill ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/classes/VaultCredentials.md b/docs/api/forward/classes/VaultCredentials.md index cfcf7df..93209c6 100644 --- a/docs/api/forward/classes/VaultCredentials.md +++ b/docs/api/forward/classes/VaultCredentials.md @@ -90,7 +90,7 @@ createVaultCredential ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -150,7 +150,7 @@ listVaultCredential ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/classes/Vaults.md b/docs/api/forward/classes/Vaults.md index df86ba5..1ac3fb9 100644 --- a/docs/api/forward/classes/Vaults.md +++ b/docs/api/forward/classes/Vaults.md @@ -88,7 +88,7 @@ createVault ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns @@ -140,7 +140,7 @@ listVault ##### options? -[`RequestOptions`](../../index/interfaces/RequestOptions.md) +[`IdentityScopeOptions`](../type-aliases/IdentityScopeOptions.md) #### Returns diff --git a/docs/api/forward/interfaces/ChannelPairing.md b/docs/api/forward/interfaces/ChannelPairing.md index 805be1c..aaa17f0 100644 --- a/docs/api/forward/interfaces/ChannelPairing.md +++ b/docs/api/forward/interfaces/ChannelPairing.md @@ -22,6 +22,12 @@ Channel ID。 *** +### created\_at? + +> `optional` **created\_at?**: `string` + +*** + ### id > **id**: `string` @@ -46,6 +52,24 @@ Pairing ID,解除配对时使用。 *** +### scope\_display\_name + +> **scope\_display\_name**: `string` + +*** + +### scope\_external\_id + +> **scope\_external\_id**: `string` + +*** + +### scope\_type + +> **scope\_type**: `string` + +*** + ### status > **status**: `string` @@ -67,3 +91,9 @@ Pairing ID,解除配对时使用。 > **type**: `string` 固定为 `channel_pairing`。 + +*** + +### updated\_at? + +> `optional` **updated\_at?**: `string` diff --git a/docs/api/forward/interfaces/ChannelPairingNewParams.md b/docs/api/forward/interfaces/ChannelPairingNewParams.md index a54e58d..94ba7d9 100644 --- a/docs/api/forward/interfaces/ChannelPairingNewParams.md +++ b/docs/api/forward/interfaces/ChannelPairingNewParams.md @@ -14,11 +14,19 @@ Additional fields are preserved verbatim by the SDK. ## Properties -### code +### channel\_pairing\_id? -> **code**: `string` +> `optional` **channel\_pairing\_id?**: `string` -Channel 消息中显示的 6 位配对码。 +Pending pairing ID. Supply exactly one of code or channel_pairing_id. + +*** + +### code? + +> `optional` **code?**: `string` + +Channel 消息中的配对码;与 channel_pairing_id 二选一。 *** diff --git a/docs/api/forward/interfaces/EnvironmentListParams.md b/docs/api/forward/interfaces/EnvironmentListParams.md index cb7aea7..ca90cf4 100644 --- a/docs/api/forward/interfaces/EnvironmentListParams.md +++ b/docs/api/forward/interfaces/EnvironmentListParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/EnvironmentNewParams.md b/docs/api/forward/interfaces/EnvironmentNewParams.md index df27262..ac1c2ca 100644 --- a/docs/api/forward/interfaces/EnvironmentNewParams.md +++ b/docs/api/forward/interfaces/EnvironmentNewParams.md @@ -38,6 +38,14 @@ Environment 运行时配置对象;省略时默认使用 `{"type":"cloud"}`。 *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/EnvironmentUpdateParams.md b/docs/api/forward/interfaces/EnvironmentUpdateParams.md index 69ebaac..169a3a0 100644 --- a/docs/api/forward/interfaces/EnvironmentUpdateParams.md +++ b/docs/api/forward/interfaces/EnvironmentUpdateParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/FileListParams.md b/docs/api/forward/interfaces/FileListParams.md index 3ab8471..c68eac8 100644 --- a/docs/api/forward/interfaces/FileListParams.md +++ b/docs/api/forward/interfaces/FileListParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/FileUploadParams.md b/docs/api/forward/interfaces/FileUploadParams.md index 8ddeef7..91b6e3c 100644 --- a/docs/api/forward/interfaces/FileUploadParams.md +++ b/docs/api/forward/interfaces/FileUploadParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/Session.md b/docs/api/forward/interfaces/Session.md index 5c56550..ac54157 100644 --- a/docs/api/forward/interfaces/Session.md +++ b/docs/api/forward/interfaces/Session.md @@ -110,6 +110,6 @@ Template 摘要。 *** -### usage +### usage? -> **usage**: [`SessionUsage`](SessionUsage.md) +> `optional` **usage?**: [`SessionUsage`](SessionUsage.md) diff --git a/docs/api/forward/interfaces/SessionUsage.md b/docs/api/forward/interfaces/SessionUsage.md index 25dd5e0..4f11291 100644 --- a/docs/api/forward/interfaces/SessionUsage.md +++ b/docs/api/forward/interfaces/SessionUsage.md @@ -14,6 +14,18 @@ Additional fields are preserved verbatim by the SDK. ## Properties +### model\_credits? + +> `optional` **model\_credits?**: `number` + +*** + +### sandbox\_runtime\_credits? + +> `optional` **sandbox\_runtime\_credits?**: `number` + +*** + ### total\_credits > **total\_credits**: `number` diff --git a/docs/api/forward/interfaces/SkillGetParams.md b/docs/api/forward/interfaces/SkillGetParams.md index 41eeb0d..b52f8f8 100644 --- a/docs/api/forward/interfaces/SkillGetParams.md +++ b/docs/api/forward/interfaces/SkillGetParams.md @@ -14,6 +14,14 @@ Additional fields are preserved verbatim by the SDK. ## Properties +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### include\_content? > `optional` **include\_content?**: `boolean` \| `null` diff --git a/docs/api/forward/interfaces/SkillListParams.md b/docs/api/forward/interfaces/SkillListParams.md index 24e070b..9d8e9a2 100644 --- a/docs/api/forward/interfaces/SkillListParams.md +++ b/docs/api/forward/interfaces/SkillListParams.md @@ -38,6 +38,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/SkillNewParams.md b/docs/api/forward/interfaces/SkillNewParams.md index d8e2f37..ca5d4b4 100644 --- a/docs/api/forward/interfaces/SkillNewParams.md +++ b/docs/api/forward/interfaces/SkillNewParams.md @@ -54,6 +54,14 @@ Forward Resource icon 公开 ID。 *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/SkillUpdateParams.md b/docs/api/forward/interfaces/SkillUpdateParams.md index 6810ccc..5d67a21 100644 --- a/docs/api/forward/interfaces/SkillUpdateParams.md +++ b/docs/api/forward/interfaces/SkillUpdateParams.md @@ -46,6 +46,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/SkillVersionListParams.md b/docs/api/forward/interfaces/SkillVersionListParams.md index 5eff7c6..d0ac360 100644 --- a/docs/api/forward/interfaces/SkillVersionListParams.md +++ b/docs/api/forward/interfaces/SkillVersionListParams.md @@ -14,6 +14,14 @@ Additional fields are preserved verbatim by the SDK. ## Properties +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/SkillVersionNewParams.md b/docs/api/forward/interfaces/SkillVersionNewParams.md index 9bbd97e..7d91d9d 100644 --- a/docs/api/forward/interfaces/SkillVersionNewParams.md +++ b/docs/api/forward/interfaces/SkillVersionNewParams.md @@ -19,3 +19,11 @@ Additional fields are preserved verbatim by the SDK. > **files**: [`Uploadable`](../../index/type-aliases/Uploadable.md)[] 上传字段,可**重复**出现多次。支持两种形态: • 单个 `.zip` 包; • 裸文件树——每个 part 独立上传一个文件,`filename` 携带相对路径(如 `customer-reply/SKILL.md`、`customer-reply/scripts/run.sh`)。 压缩包本身与解压后总大小均不超过 50 MB。 + +*** + +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. diff --git a/docs/api/forward/interfaces/VaultCredentialListParams.md b/docs/api/forward/interfaces/VaultCredentialListParams.md index 14a86d7..6eb0a62 100644 --- a/docs/api/forward/interfaces/VaultCredentialListParams.md +++ b/docs/api/forward/interfaces/VaultCredentialListParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/VaultCredentialNewParams.md b/docs/api/forward/interfaces/VaultCredentialNewParams.md index 0cc610b..cff4af6 100644 --- a/docs/api/forward/interfaces/VaultCredentialNewParams.md +++ b/docs/api/forward/interfaces/VaultCredentialNewParams.md @@ -38,6 +38,14 @@ Credential 认证信息,支持 `static_bearer`、`mcp_oauth`;响应只返回 *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/interfaces/VaultListParams.md b/docs/api/forward/interfaces/VaultListParams.md index ca81041..fd7f518 100644 --- a/docs/api/forward/interfaces/VaultListParams.md +++ b/docs/api/forward/interfaces/VaultListParams.md @@ -30,6 +30,14 @@ Additional fields are preserved verbatim by the SDK. *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### limit? > `optional` **limit?**: `number` \| `null` diff --git a/docs/api/forward/interfaces/VaultNewParams.md b/docs/api/forward/interfaces/VaultNewParams.md index 33997aa..d189a9b 100644 --- a/docs/api/forward/interfaces/VaultNewParams.md +++ b/docs/api/forward/interfaces/VaultNewParams.md @@ -30,6 +30,14 @@ Vault 展示名。 *** +### identity\_id? + +> `optional` **identity\_id?**: `string` + +Select identity ownership with a PAT. Omit when using a SAT. + +*** + ### metadata? > `optional` **metadata?**: `Record`\<`string`, `unknown`\> \| `null` diff --git a/docs/api/forward/type-aliases/IdentityScopeOptions.md b/docs/api/forward/type-aliases/IdentityScopeOptions.md new file mode 100644 index 0000000..816f205 --- /dev/null +++ b/docs/api/forward/type-aliases/IdentityScopeOptions.md @@ -0,0 +1,17 @@ +[**qca-sdk**](../../README.md) + +*** + +[qca-sdk](../../README.md) / [forward](../README.md) / IdentityScopeOptions + +# Type Alias: IdentityScopeOptions + +> **IdentityScopeOptions** = [`RequestOptions`](../../index/interfaces/RequestOptions.md) & `object` + +PAT identity ownership query. Omit identity_id when using a SAT. + +## Type Declaration + +### identity\_id? + +> `optional` **identity\_id?**: `string` diff --git a/docs/api/managed/interfaces/DeploymentNewParams.md b/docs/api/managed/interfaces/DeploymentNewParams.md index d67eced..b9563a7 100644 --- a/docs/api/managed/interfaces/DeploymentNewParams.md +++ b/docs/api/managed/interfaces/DeploymentNewParams.md @@ -30,8 +30,8 @@ Optional header to specify the beta version(s) you want to use. > `optional` **budget?**: [`ManagedAgentsBudgetLimitParam`](ManagedAgentsBudgetLimitParam.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/docs/api/managed/interfaces/DeploymentUpdateParams.md b/docs/api/managed/interfaces/DeploymentUpdateParams.md index 0c0e0c2..26a4ae8 100644 --- a/docs/api/managed/interfaces/DeploymentUpdateParams.md +++ b/docs/api/managed/interfaces/DeploymentUpdateParams.md @@ -30,8 +30,8 @@ Optional header to specify the beta version(s) you want to use. > `optional` **budget?**: [`ManagedAgentsBudgetLimitParam`](ManagedAgentsBudgetLimitParam.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsAgentThreadContextCompactedEvent.md b/docs/api/managed/interfaces/ManagedAgentsAgentThreadContextCompactedEvent.md index 0792eed..c2d9269 100644 --- a/docs/api/managed/interfaces/ManagedAgentsAgentThreadContextCompactedEvent.md +++ b/docs/api/managed/interfaces/ManagedAgentsAgentThreadContextCompactedEvent.md @@ -31,3 +31,11 @@ A timestamp in RFC 3339 format > **type**: `"agent.thread_context_compacted"` Any of "agent.thread_context_compacted". + +*** + +### usage? + +> `optional` **usage?**: [`ManagedAgentsSpanModelUsage`](ManagedAgentsSpanModelUsage.md) + +Credits for this compaction call, already included in Session usage. diff --git a/docs/api/managed/interfaces/ManagedAgentsBudgetLimit.md b/docs/api/managed/interfaces/ManagedAgentsBudgetLimit.md index 5f29093..1284318 100644 --- a/docs/api/managed/interfaces/ManagedAgentsBudgetLimit.md +++ b/docs/api/managed/interfaces/ManagedAgentsBudgetLimit.md @@ -6,16 +6,16 @@ # Interface: ManagedAgentsBudgetLimit -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. ## Properties -### max\_list\_cost +### max\_credit\_cost -> **max\_list\_cost**: [`MonetaryAmount`](MonetaryAmount.md) +> **max\_credit\_cost**: `string` -A monetary amount in a specific currency. +Positive decimal Credits with at most 12 integer and 2 fractional digits. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsBudgetLimitParam.md b/docs/api/managed/interfaces/ManagedAgentsBudgetLimitParam.md index d553b6e..90c9847 100644 --- a/docs/api/managed/interfaces/ManagedAgentsBudgetLimitParam.md +++ b/docs/api/managed/interfaces/ManagedAgentsBudgetLimitParam.md @@ -6,16 +6,16 @@ # Interface: ManagedAgentsBudgetLimitParam -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. ## Properties -### max\_list\_cost +### max\_credit\_cost -> **max\_list\_cost**: [`MonetaryAmountParam`](MonetaryAmountParam.md) +> **max\_credit\_cost**: `string` -A monetary amount in a specific currency. +Positive decimal Credits with at most 12 integer and 2 fractional digits. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsDeployment.md b/docs/api/managed/interfaces/ManagedAgentsDeployment.md index 7696519..6520629 100644 --- a/docs/api/managed/interfaces/ManagedAgentsDeployment.md +++ b/docs/api/managed/interfaces/ManagedAgentsDeployment.md @@ -32,8 +32,8 @@ A timestamp in RFC 3339 format > `optional` **budget?**: [`ManagedAgentsBudgetLimit`](ManagedAgentsBudgetLimit.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsSession.md b/docs/api/managed/interfaces/ManagedAgentsSession.md index 34cb417..6d41ba3 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSession.md +++ b/docs/api/managed/interfaces/ManagedAgentsSession.md @@ -27,12 +27,12 @@ A timestamp in RFC 3339 format *** -### budget +### budget? -> **budget**: [`ManagedAgentsBudgetLimit`](ManagedAgentsBudgetLimit.md) +> `optional` **budget?**: [`ManagedAgentsBudgetLimit`](ManagedAgentsBudgetLimit.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** @@ -132,11 +132,11 @@ A timestamp in RFC 3339 format *** -### usage +### usage? -> **usage**: [`ManagedAgentsSessionUsage`](ManagedAgentsSessionUsage.md) +> `optional` **usage?**: [`ManagedAgentsSessionUsage`](ManagedAgentsSessionUsage.md) -Cumulative token usage for a session across all turns. +Cumulative Credits snapshot. Legacy token and list-cost fields may appear in older responses. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsSessionEventUnionUsage.md b/docs/api/managed/interfaces/ManagedAgentsSessionEventUnionUsage.md index 2a8ebf4..ef19011 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSessionEventUnionUsage.md +++ b/docs/api/managed/interfaces/ManagedAgentsSessionEventUnionUsage.md @@ -38,6 +38,12 @@ This field is from variant `ManagedAgentsSpanModelUsage`. *** +### credits? + +> `optional` **credits?**: `number` + +*** + ### input\_tokens? > `optional` **input\_tokens?**: `number` diff --git a/docs/api/managed/interfaces/ManagedAgentsSessionUpdatedEvent.md b/docs/api/managed/interfaces/ManagedAgentsSessionUpdatedEvent.md index f57c74c..750d040 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSessionUpdatedEvent.md +++ b/docs/api/managed/interfaces/ManagedAgentsSessionUpdatedEvent.md @@ -25,8 +25,8 @@ Resolved `agent` definition for a `session`. Snapshot of the `agent` at > `optional` **budget?**: [`ManagedAgentsBudgetLimit`](ManagedAgentsBudgetLimit.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsSessionUsage.md b/docs/api/managed/interfaces/ManagedAgentsSessionUsage.md index ff532ea..0c3efe7 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSessionUsage.md +++ b/docs/api/managed/interfaces/ManagedAgentsSessionUsage.md @@ -6,7 +6,7 @@ # Interface: ManagedAgentsSessionUsage -Cumulative token usage for a session across all turns. +Cumulative Credits snapshot. Legacy token and list-cost fields may appear in older responses. ## Properties @@ -53,6 +53,14 @@ A monetary amount in a specific currency. *** +### model\_credits + +> **model\_credits**: `number` + +Cumulative Credits. Replace the previous snapshot instead of adding it. + +*** + ### output\_tokens? > `optional` **output\_tokens?**: `number` @@ -61,8 +69,20 @@ Total output tokens generated across all turns. *** +### sandbox\_runtime\_credits + +> **sandbox\_runtime\_credits**: `number` + +*** + ### server\_tool\_use? > `optional` **server\_tool\_use?**: [`ManagedAgentsServerToolUsage`](ManagedAgentsServerToolUsage.md) \| `null` Cumulative count of server-executed tool invocations, broken down by tool. + +*** + +### total\_credits + +> **total\_credits**: `number` diff --git a/docs/api/managed/interfaces/ManagedAgentsSessionUsageEvent.md b/docs/api/managed/interfaces/ManagedAgentsSessionUsageEvent.md index cc2c953..87687dc 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSessionUsageEvent.md +++ b/docs/api/managed/interfaces/ManagedAgentsSessionUsageEvent.md @@ -6,7 +6,7 @@ # Interface: ManagedAgentsSessionUsageEvent -Periodic snapshot of the session's cumulative usage and tracked list cost. +Cumulative Credits emitted before session.status_idle when usage is available. ## Properties @@ -14,8 +14,8 @@ Periodic snapshot of the session's cumulative usage and tracked list cost. > `optional` **budget?**: [`ManagedAgentsBudgetLimit`](ManagedAgentsBudgetLimit.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** @@ -27,6 +27,14 @@ Unique identifier for this event. *** +### model\_credits + +> **model\_credits**: `number` + +Cumulative Credits. Replace the previous snapshot instead of adding it. + +*** + ### processed\_at > **processed\_at**: `string` @@ -35,6 +43,18 @@ A timestamp in RFC 3339 format *** +### sandbox\_runtime\_credits + +> **sandbox\_runtime\_credits**: `number` + +*** + +### total\_credits + +> **total\_credits**: `number` + +*** + ### type > **type**: `"session.usage"` @@ -43,8 +63,10 @@ Any of "session.usage". *** -### usage +### ~~usage?~~ + +> `optional` **usage?**: [`ManagedAgentsSessionUsageSnapshot`](ManagedAgentsSessionUsageSnapshot.md) -> **usage**: [`ManagedAgentsSessionUsageSnapshot`](ManagedAgentsSessionUsageSnapshot.md) +#### Deprecated -Point-in-time snapshot of a session's cumulative usage. +Legacy nested usage; current events carry Credits at the top level. diff --git a/docs/api/managed/interfaces/ManagedAgentsSpanModelRequestEndEvent.md b/docs/api/managed/interfaces/ManagedAgentsSpanModelRequestEndEvent.md index 4e66e09..4f58d33 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSpanModelRequestEndEvent.md +++ b/docs/api/managed/interfaces/ManagedAgentsSpanModelRequestEndEvent.md @@ -34,11 +34,11 @@ The id of the corresponding `span.model_request_start` event. *** -### model\_usage +### model\_usage? -> **model\_usage**: [`ManagedAgentsSpanModelUsage`](ManagedAgentsSpanModelUsage.md) +> `optional` **model\_usage?**: [`ManagedAgentsSpanModelUsage`](ManagedAgentsSpanModelUsage.md) -Token usage for a single model request. +Credits for a single model request; legacy token fields may appear in older responses. *** diff --git a/docs/api/managed/interfaces/ManagedAgentsSpanModelUsage.md b/docs/api/managed/interfaces/ManagedAgentsSpanModelUsage.md index d681ca2..98568b0 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSpanModelUsage.md +++ b/docs/api/managed/interfaces/ManagedAgentsSpanModelUsage.md @@ -6,37 +6,43 @@ # Interface: ManagedAgentsSpanModelUsage -Token usage for a single model request. +Credits for a single model request; legacy token fields may appear in older responses. ## Properties -### cache\_creation\_input\_tokens +### cache\_creation\_input\_tokens? -> **cache\_creation\_input\_tokens**: `number` +> `optional` **cache\_creation\_input\_tokens?**: `number` Tokens used to create prompt cache in this request. *** -### cache\_read\_input\_tokens +### cache\_read\_input\_tokens? -> **cache\_read\_input\_tokens**: `number` +> `optional` **cache\_read\_input\_tokens?**: `number` Tokens read from prompt cache in this request. *** -### input\_tokens +### credits -> **input\_tokens**: `number` +> **credits**: `number` + +*** + +### input\_tokens? + +> `optional` **input\_tokens?**: `number` Input tokens consumed by this request. *** -### output\_tokens +### output\_tokens? -> **output\_tokens**: `number` +> `optional` **output\_tokens?**: `number` Output tokens generated by this request. diff --git a/docs/api/managed/interfaces/ManagedAgentsSpanOutcomeEvaluationEndEvent.md b/docs/api/managed/interfaces/ManagedAgentsSpanOutcomeEvaluationEndEvent.md index 538b047..588338b 100644 --- a/docs/api/managed/interfaces/ManagedAgentsSpanOutcomeEvaluationEndEvent.md +++ b/docs/api/managed/interfaces/ManagedAgentsSpanOutcomeEvaluationEndEvent.md @@ -89,4 +89,4 @@ Any of "span.outcome_evaluation_end". > **usage**: [`ManagedAgentsSpanModelUsage`](ManagedAgentsSpanModelUsage.md) -Token usage for a single model request. +Credits for a single model request; legacy token fields may appear in older responses. diff --git a/docs/api/managed/interfaces/ManagedAgentsStreamSessionEventsUnionUsage.md b/docs/api/managed/interfaces/ManagedAgentsStreamSessionEventsUnionUsage.md index b0762fc..74ce780 100644 --- a/docs/api/managed/interfaces/ManagedAgentsStreamSessionEventsUnionUsage.md +++ b/docs/api/managed/interfaces/ManagedAgentsStreamSessionEventsUnionUsage.md @@ -38,6 +38,12 @@ This field is from variant `ManagedAgentsSpanModelUsage`. *** +### credits? + +> `optional` **credits?**: `number` + +*** + ### input\_tokens? > `optional` **input\_tokens?**: `number` diff --git a/docs/api/managed/interfaces/ManagedAgentsStreamSessionThreadEventsUnionUsage.md b/docs/api/managed/interfaces/ManagedAgentsStreamSessionThreadEventsUnionUsage.md index 1d63f0b..80500ce 100644 --- a/docs/api/managed/interfaces/ManagedAgentsStreamSessionThreadEventsUnionUsage.md +++ b/docs/api/managed/interfaces/ManagedAgentsStreamSessionThreadEventsUnionUsage.md @@ -38,6 +38,12 @@ This field is from variant `ManagedAgentsSpanModelUsage`. *** +### credits? + +> `optional` **credits?**: `number` + +*** + ### input\_tokens? > `optional` **input\_tokens?**: `number` diff --git a/docs/api/managed/interfaces/SessionNewParams.md b/docs/api/managed/interfaces/SessionNewParams.md index 1c58420..b219bec 100644 --- a/docs/api/managed/interfaces/SessionNewParams.md +++ b/docs/api/managed/interfaces/SessionNewParams.md @@ -29,8 +29,8 @@ Optional header to specify the beta version(s) you want to use. > `optional` **budget?**: [`ManagedAgentsBudgetLimitParam`](ManagedAgentsBudgetLimitParam.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/docs/api/managed/interfaces/SessionUpdateParams.md b/docs/api/managed/interfaces/SessionUpdateParams.md index 1f9bb16..c9d9ecb 100644 --- a/docs/api/managed/interfaces/SessionUpdateParams.md +++ b/docs/api/managed/interfaces/SessionUpdateParams.md @@ -30,8 +30,8 @@ Optional header to specify the beta version(s) you want to use. > `optional` **budget?**: [`ManagedAgentsBudgetLimitParam`](ManagedAgentsBudgetLimitParam.md) \| `null` -A hard spend ceiling. The session stops issuing new model requests once the -tracked list cost reaches `max_list_cost`. +A total model and sandbox credit limit. Reaching it rejects the next user +message without interrupting the running turn. *** diff --git a/src/forward/_utils.ts b/src/forward/_utils.ts index 62b2184..f8db065 100644 --- a/src/forward/_utils.ts +++ b/src/forward/_utils.ts @@ -1,4 +1,5 @@ // Shared transport details for the Forward resources. +import type { IdentityScopeOptions } from './types.js'; import type { RequestOptions } from '../core/client.js'; /** Validate before invoking fetch, then escape the value as one path segment. */ @@ -27,3 +28,9 @@ export function requestHeaders(base: Record, } return headers; } + +/** Route identity ownership through query while preserving request overrides. */ +export function identityScopeOptions(options?: IdentityScopeOptions): RequestOptions { + const { identity_id, ...rest } = options ?? {}; + return { ...rest, query: { identity_id, ...rest.query } }; +} diff --git a/src/forward/api-inventory.json b/src/forward/api-inventory.json index b04a304..2a070d0 100644 --- a/src/forward/api-inventory.json +++ b/src/forward/api-inventory.json @@ -505,7 +505,7 @@ "name": "code", "wireName": "code", "location": "body", - "required": true, + "required": false, "type": "string" }, { @@ -528,6 +528,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "channel_pairing_id", + "wireName": "channel_pairing_id", + "location": "body", + "required": false, + "type": "string" } ] }, @@ -646,6 +653,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -697,6 +711,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -720,7 +741,15 @@ "pagination": "cursor", "itemType": "Environment", "path": "/environments/{id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "updateEnvironment", @@ -770,6 +799,13 @@ "location": "body", "required": false, "type": "Record | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -793,7 +829,15 @@ "pagination": "cursor", "itemType": "Environment", "path": "/environments/{id}/archive", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "deleteEnvironment", @@ -815,7 +859,15 @@ "pagination": "cursor", "itemType": "void", "path": "/environments/{id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "listFile", @@ -872,6 +924,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -923,6 +982,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -946,7 +1012,15 @@ "pagination": "cursor", "itemType": "FileMetadata", "path": "/files/{file_id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "deleteFile", @@ -968,7 +1042,15 @@ "pagination": "cursor", "itemType": "void", "path": "/files/{file_id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "downloadFile", @@ -990,7 +1072,15 @@ "pagination": "cursor", "itemType": "Response", "path": "/files/{file_id}/content", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "listIdentities", @@ -3472,6 +3562,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3544,6 +3641,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3574,6 +3678,13 @@ "location": "query", "required": false, "type": "boolean | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3639,6 +3750,13 @@ "location": "body", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3662,7 +3780,15 @@ "pagination": "cursor", "itemType": "void", "path": "/skills/{id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "listSkillVersion", @@ -3698,6 +3824,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3728,6 +3861,13 @@ "location": "body", "required": true, "type": "Array" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -3757,7 +3897,15 @@ "pagination": "cursor", "itemType": "SkillVersion", "path": "/skills/{id}/versions/{version}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "deleteSkillVersion", @@ -3785,7 +3933,15 @@ "pagination": "cursor", "itemType": "DeletedSkillVersion", "path": "/skills/{id}/versions/{version}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "downloadSkillVersion", @@ -3813,7 +3969,15 @@ "pagination": "cursor", "itemType": "Response", "path": "/skills/{id}/versions/{version}/content", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "listTemplates", @@ -4280,6 +4444,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -4317,6 +4488,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -4340,7 +4518,15 @@ "pagination": "cursor", "itemType": "Vault", "path": "/vaults/{id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "deleteVault", @@ -4362,7 +4548,15 @@ "pagination": "cursor", "itemType": "void", "path": "/vaults/{id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "listVaultCredential", @@ -4419,6 +4613,13 @@ "location": "query", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -4470,6 +4671,13 @@ "location": "header", "required": false, "type": "string | null" + }, + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" } ] }, @@ -4499,7 +4707,15 @@ "pagination": "cursor", "itemType": "VaultCredential", "path": "/vaults/{id}/credentials/{cred_id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "deleteVaultCredential", @@ -4527,7 +4743,15 @@ "pagination": "cursor", "itemType": "void", "path": "/vaults/{id}/credentials/{cred_id}", - "parameterFields": [] + "parameterFields": [ + { + "name": "identity_id", + "wireName": "identity_id", + "location": "query", + "required": false, + "type": "string" + } + ] }, { "operationId": "updateVaultCredential", diff --git a/src/forward/environment.ts b/src/forward/environment.ts index 4adbc9f..8d71393 100644 --- a/src/forward/environment.ts +++ b/src/forward/environment.ts @@ -1,9 +1,10 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { Environment, EnvironmentCreateParams, EnvironmentListParams, EnvironmentUpdateParams } from './types.js'; export class Environments extends APIResource { @@ -24,12 +25,13 @@ export class Environments extends APIResource { */ create(params: EnvironmentCreateParams, options?: RequestOptions): APIPromise { const path = "environments"; - const { idempotency_key, ...payload } = params; + const { identity_id, idempotency_key, ...payload } = params; return this._client.request({ method: "POST", path, body: payload, ...options, + query: { identity_id, ...options?.query }, headers: requestHeaders({ "Idempotency-Key": idempotency_key }, options?.headers), }); } @@ -39,12 +41,12 @@ export class Environments extends APIResource { * * @operation getEnvironment */ - retrieve(id: string, options?: RequestOptions): APIPromise { + retrieve(id: string, options?: IdentityScopeOptions): APIPromise { const path = `environments/${pathParam(id, "id")}`; return this._client.request({ method: "GET", path, - ...options, + ...identityScopeOptions(options), }); } @@ -59,11 +61,13 @@ export class Environments extends APIResource { options?: RequestOptions, ): APIPromise { const path = `environments/${pathParam(id, "id")}`; + const { identity_id, ...payload } = params; return this._client.request({ method: "POST", path, - body: params, + body: payload, ...options, + query: { identity_id, ...options?.query }, }); } @@ -72,12 +76,12 @@ export class Environments extends APIResource { * * @operation archiveEnvironment */ - archive(id: string, options?: RequestOptions): APIPromise { + archive(id: string, options?: IdentityScopeOptions): APIPromise { const path = `environments/${pathParam(id, "id")}/archive`; return this._client.request({ method: "POST", path, - ...options, + ...identityScopeOptions(options), }); } @@ -86,13 +90,13 @@ export class Environments extends APIResource { * * @operation deleteEnvironment */ - delete(id: string, options?: RequestOptions): APIPromise { + delete(id: string, options?: IdentityScopeOptions): APIPromise { const path = `environments/${pathParam(id, "id")}`; return this._client.request({ method: "DELETE", path, responseType: "void", - ...options, + ...identityScopeOptions(options), }); } diff --git a/src/forward/file.ts b/src/forward/file.ts index b50459f..c3fbf9c 100644 --- a/src/forward/file.ts +++ b/src/forward/file.ts @@ -1,10 +1,11 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; import { toMultipartForm } from '../core/uploads.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { FileListParams, FileMetadata, FileUploadParams } from './types.js'; export class Files extends APIResource { @@ -25,12 +26,13 @@ export class Files extends APIResource { */ upload(params: FileUploadParams, options?: RequestOptions): APIPromise { const path = "files"; - const { idempotency_key, ...payload } = params; + const { identity_id, idempotency_key, ...payload } = params; return this._client.request({ method: "POST", path, body: toMultipartForm(payload), ...options, + query: { identity_id, ...options?.query }, headers: requestHeaders({ "Idempotency-Key": idempotency_key }, options?.headers), }); } @@ -40,12 +42,12 @@ export class Files extends APIResource { * * @operation getFile */ - getMetadata(fileID: string, options?: RequestOptions): APIPromise { + getMetadata(fileID: string, options?: IdentityScopeOptions): APIPromise { const path = `files/${pathParam(fileID, "file_id")}`; return this._client.request({ method: "GET", path, - ...options, + ...identityScopeOptions(options), }); } @@ -54,13 +56,13 @@ export class Files extends APIResource { * * @operation deleteFile */ - delete(fileID: string, options?: RequestOptions): APIPromise { + delete(fileID: string, options?: IdentityScopeOptions): APIPromise { const path = `files/${pathParam(fileID, "file_id")}`; return this._client.request({ method: "DELETE", path, responseType: "void", - ...options, + ...identityScopeOptions(options), }); } @@ -69,9 +71,9 @@ export class Files extends APIResource { * * @operation downloadFile */ - download(fileID: string, options?: RequestOptions): APIPromise { + download(fileID: string, options?: IdentityScopeOptions): APIPromise { const path = `files/${pathParam(fileID, "file_id")}/content`; - return this._client.downloadFile(path, options); + return this._client.downloadFile(path, identityScopeOptions(options)); } } diff --git a/src/forward/skill-version.ts b/src/forward/skill-version.ts index e9304c6..0ee53f6 100644 --- a/src/forward/skill-version.ts +++ b/src/forward/skill-version.ts @@ -1,10 +1,11 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; import { toMultipartForm } from '../core/uploads.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { DeletedSkillVersion, SkillVersion, SkillVersionCreateParams, SkillVersionListParams } from './types.js'; export class SkillVersions extends APIResource { @@ -25,11 +26,13 @@ export class SkillVersions extends APIResource { */ create(id: string, params: SkillVersionCreateParams, options?: RequestOptions): APIPromise { const path = `skills/${pathParam(id, "id")}/versions`; + const { identity_id, ...payload } = params; return this._client.request({ method: "POST", path, - body: toMultipartForm(params), + body: toMultipartForm(payload), ...options, + query: { identity_id, ...options?.query }, }); } @@ -38,12 +41,12 @@ export class SkillVersions extends APIResource { * * @operation getSkillVersion */ - retrieve(id: string, version: string, options?: RequestOptions): APIPromise { + retrieve(id: string, version: string, options?: IdentityScopeOptions): APIPromise { const path = `skills/${pathParam(id, "id")}/versions/${pathParam(version, "version")}`; return this._client.request({ method: "GET", path, - ...options, + ...identityScopeOptions(options), }); } @@ -52,12 +55,12 @@ export class SkillVersions extends APIResource { * * @operation deleteSkillVersion */ - delete(id: string, version: string, options?: RequestOptions): APIPromise { + delete(id: string, version: string, options?: IdentityScopeOptions): APIPromise { const path = `skills/${pathParam(id, "id")}/versions/${pathParam(version, "version")}`; return this._client.request({ method: "DELETE", path, - ...options, + ...identityScopeOptions(options), }); } @@ -66,13 +69,13 @@ export class SkillVersions extends APIResource { * * @operation downloadSkillVersion */ - download(id: string, version: string, options?: RequestOptions): APIPromise { + download(id: string, version: string, options?: IdentityScopeOptions): APIPromise { const path = `skills/${pathParam(id, "id")}/versions/${pathParam(version, "version")}/content`; return this._client.request({ method: "GET", path, responseType: "response", - ...options, + ...identityScopeOptions(options), }); } diff --git a/src/forward/skill.ts b/src/forward/skill.ts index 5f1e162..f2e8c20 100644 --- a/src/forward/skill.ts +++ b/src/forward/skill.ts @@ -1,10 +1,11 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; import { toMultipartForm } from '../core/uploads.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { Skill, SkillCreateParams, SkillListParams, SkillRetrieveParams, SkillUpdateParams } from './types.js'; import { SkillVersions } from './skill-version.js'; @@ -28,12 +29,13 @@ export class Skills extends APIResource { */ create(params: SkillCreateParams = {}, options?: RequestOptions): APIPromise { const path = "skills"; - const { idempotency_key, ...payload } = params; + const { identity_id, idempotency_key, ...payload } = params; return this._client.request({ method: "POST", path, body: toMultipartForm(payload), ...options, + query: { identity_id, ...options?.query }, headers: requestHeaders({ "Idempotency-Key": idempotency_key }, options?.headers), }); } @@ -48,8 +50,8 @@ export class Skills extends APIResource { return this._client.request({ method: "GET", path, - query: params, ...options, + query: { ...params, ...options?.query }, }); } @@ -60,11 +62,13 @@ export class Skills extends APIResource { */ update(id: string, params: SkillUpdateParams = {}, options?: RequestOptions): APIPromise { const path = `skills/${pathParam(id, "id")}`; + const { identity_id, ...payload } = params; return this._client.request({ method: "PUT", path, - body: params, + body: payload, ...options, + query: { identity_id, ...options?.query }, }); } @@ -73,13 +77,13 @@ export class Skills extends APIResource { * * @operation deleteSkill */ - delete(id: string, options?: RequestOptions): APIPromise { + delete(id: string, options?: IdentityScopeOptions): APIPromise { const path = `skills/${pathParam(id, "id")}`; return this._client.request({ method: "DELETE", path, responseType: "void", - ...options, + ...identityScopeOptions(options), }); } diff --git a/src/forward/types.ts b/src/forward/types.ts index e33d55f..595e004 100644 --- a/src/forward/types.ts +++ b/src/forward/types.ts @@ -1,3 +1,8 @@ +import type { RequestOptions } from '../core/client.js'; + +/** PAT identity ownership query. Omit identity_id when using a SAT. */ +export type IdentityScopeOptions = RequestOptions & { identity_id?: string }; + // Generated wire types, verified against the API contracts. // Wire names and required/nullable fields follow the API's JSON, query and header contracts. import type { Uploadable } from '../core/uploads.js'; @@ -429,10 +434,12 @@ export interface ChannelIdentityResolution { } export interface ChannelPairingNewParams { + /** Pending pairing ID. Supply exactly one of code or channel_pairing_id. */ + channel_pairing_id?: string; /** - * Channel 消息中显示的 6 位配对码。 + * Channel 消息中的配对码;与 channel_pairing_id 二选一。 */ - code: string; + code?: string; /** * 要绑定的 Forward Identity ID。 */ @@ -463,6 +470,12 @@ export interface DeletedChannelPairing { } export interface ChannelPairing { + scope_type: string; + scope_external_id: string; + scope_display_name: string; + created_at?: string; + updated_at?: string; + /** * Pairing ID,解除配对时使用。 */ @@ -869,6 +882,8 @@ export interface SessionEventParam { } export interface EnvironmentListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100。 */ @@ -890,6 +905,8 @@ export interface EnvironmentListParams { } export interface EnvironmentNewParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * Environment 名称;去除首尾空白后不能为空。 */ @@ -915,6 +932,8 @@ export interface EnvironmentNewParams { } export interface EnvironmentUpdateParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 新名称。 */ @@ -970,6 +989,8 @@ export interface EnvironmentConfigPackages { } export interface FileListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100。 */ @@ -999,6 +1020,8 @@ export interface FileListParams { } export interface FileUploadParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 待上传文件内容。支持类型见[支持上传的文件类型](./schemas.md#支持上传的文件类型)。 */ @@ -2322,7 +2345,7 @@ export interface Session { config: SessionConfig; resources: Array; stats: SessionStats; - usage: SessionUsage; + usage?: SessionUsage; archived_at: string | null; created_at: string; updated_at: string; @@ -2331,6 +2354,8 @@ export interface Session { } export interface SessionUsage { + model_credits?: number; + sandbox_runtime_credits?: number; total_credits: number; /** Additional fields are preserved verbatim by the SDK. */ [key: string]: unknown; @@ -2602,6 +2627,8 @@ export interface SessionThreadEventStreamParams { } export interface SkillListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100。 */ @@ -2635,6 +2662,8 @@ export interface SkillListParams { } export interface SkillNewParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 推荐上传字段,可**重复出现**多次。支持两种形态: ① 单个 `.zip` 包; ② 裸文件树——每个 part 独立上传一个文件,`filename` 携带相对路径(如 `code-review/SKILL.md`、`code-review/scripts/run.sh`)。 压缩包本身与解压后总大小均不超过 50 MB。 */ @@ -2672,6 +2701,8 @@ export interface SkillNewParams { } export interface SkillGetParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * ⚠️ **已弃用**:为 `true` 时随响应返回 `content` 与 `content_encoding`(base64 zip)。命中时响应头会返回 `Deprecation: true`。请改用 [下载 Skill 版本内容](./Versions/download.md)。 */ @@ -2681,6 +2712,8 @@ export interface SkillGetParams { } export interface SkillUpdateParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 新描述。 */ @@ -2727,6 +2760,8 @@ export interface Skill { } export interface SkillVersionListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100,默认 20。 */ @@ -2740,6 +2775,8 @@ export interface SkillVersionListParams { } export interface SkillVersionNewParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 上传字段,可**重复**出现多次。支持两种形态: • 单个 `.zip` 包; • 裸文件树——每个 part 独立上传一个文件,`filename` 携带相对路径(如 `customer-reply/SKILL.md`、`customer-reply/scripts/run.sh`)。 压缩包本身与解压后总大小均不超过 50 MB。 */ @@ -3018,6 +3055,8 @@ export interface Template { } export interface VaultListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100。 */ @@ -3043,6 +3082,8 @@ export interface VaultListParams { } export interface VaultNewParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * Vault 展示名。 */ @@ -3093,6 +3134,8 @@ export interface Vault { } export interface VaultCredentialListParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * 分页大小,最大 100。 */ @@ -3118,6 +3161,8 @@ export interface VaultCredentialListParams { } export interface VaultCredentialNewParams { + /** Select identity ownership with a PAT. Omit when using a SAT. */ + identity_id?: string; /** * Credential 认证信息,支持 `static_bearer`、`mcp_oauth`;响应只返回脱敏后的非密文字段。 */ diff --git a/src/forward/vault-credential.ts b/src/forward/vault-credential.ts index b8ca42d..7520552 100644 --- a/src/forward/vault-credential.ts +++ b/src/forward/vault-credential.ts @@ -1,9 +1,10 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { VaultCredential, VaultCredentialCreateParams, VaultCredentialListParams, VaultCredentialUpdateParams } from './types.js'; export class VaultCredentials extends APIResource { @@ -41,12 +42,13 @@ export class VaultCredentials extends APIResource { options?: RequestOptions, ): APIPromise { const path = `vaults/${pathParam(id, "id")}/credentials`; - const { idempotency_key, ...payload } = params; + const { identity_id, idempotency_key, ...payload } = params; return this._client.request({ method: "POST", path, body: payload, ...options, + query: { identity_id, ...options?.query }, headers: requestHeaders({ "Idempotency-Key": idempotency_key }, options?.headers), }); } @@ -56,12 +58,12 @@ export class VaultCredentials extends APIResource { * * @operation getVaultCredential */ - retrieve(id: string, credID: string, options?: RequestOptions): APIPromise { + retrieve(id: string, credID: string, options?: IdentityScopeOptions): APIPromise { const path = `vaults/${pathParam(id, "id")}/credentials/${pathParam(credID, "cred_id")}`; return this._client.request({ method: "GET", path, - ...options, + ...identityScopeOptions(options), }); } @@ -70,13 +72,13 @@ export class VaultCredentials extends APIResource { * * @operation deleteVaultCredential */ - delete(id: string, credID: string, options?: RequestOptions): APIPromise { + delete(id: string, credID: string, options?: IdentityScopeOptions): APIPromise { const path = `vaults/${pathParam(id, "id")}/credentials/${pathParam(credID, "cred_id")}`; return this._client.request({ method: "DELETE", path, responseType: "void", - ...options, + ...identityScopeOptions(options), }); } diff --git a/src/forward/vault.ts b/src/forward/vault.ts index 32e189b..4398062 100644 --- a/src/forward/vault.ts +++ b/src/forward/vault.ts @@ -1,9 +1,10 @@ // Generated code, verified against the API contracts. import { APIResource } from '../core/resource.js'; import type { RequestOptions } from '../core/client.js'; +import type { IdentityScopeOptions } from './types.js'; import type { APIPromise } from '../core/api-promise.js'; import type { PagePromise } from '../core/pagination.js'; -import { pathParam, requestHeaders } from './_utils.js'; +import { pathParam, requestHeaders, identityScopeOptions } from './_utils.js'; import type { Vault, VaultCreateParams, VaultListParams } from './types.js'; import { VaultCredentials } from './vault-credential.js'; @@ -27,12 +28,13 @@ export class Vaults extends APIResource { */ create(params: VaultCreateParams, options?: RequestOptions): APIPromise { const path = "vaults"; - const { idempotency_key, ...payload } = params; + const { identity_id, idempotency_key, ...payload } = params; return this._client.request({ method: "POST", path, body: payload, ...options, + query: { identity_id, ...options?.query }, headers: requestHeaders({ "Idempotency-Key": idempotency_key }, options?.headers), }); } @@ -42,12 +44,12 @@ export class Vaults extends APIResource { * * @operation getVault */ - retrieve(id: string, options?: RequestOptions): APIPromise { + retrieve(id: string, options?: IdentityScopeOptions): APIPromise { const path = `vaults/${pathParam(id, "id")}`; return this._client.request({ method: "GET", path, - ...options, + ...identityScopeOptions(options), }); } @@ -56,13 +58,13 @@ export class Vaults extends APIResource { * * @operation deleteVault */ - delete(id: string, options?: RequestOptions): APIPromise { + delete(id: string, options?: IdentityScopeOptions): APIPromise { const path = `vaults/${pathParam(id, "id")}`; return this._client.request({ method: "DELETE", path, responseType: "void", - ...options, + ...identityScopeOptions(options), }); } diff --git a/src/managed/types.ts b/src/managed/types.ts index 51e3d2d..e936027 100644 --- a/src/managed/types.ts +++ b/src/managed/types.ts @@ -1668,8 +1668,8 @@ export interface ManagedAgentsDeployment { */ vault_ids: Array; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimit | null; } @@ -2160,8 +2160,8 @@ export interface DeploymentNewParams { description?: string | null; workspace_id?: string; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimitParam | null; /** @@ -2240,8 +2240,8 @@ export interface DeploymentUpdateParams { */ agent?: DeploymentUpdateParamsAgentUnion; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimitParam | null; /** @@ -6503,14 +6503,14 @@ export interface ManagedAgentsBranchCheckoutParam { } /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ export interface ManagedAgentsBudgetLimit { /** - * A monetary amount in a specific currency. + * Positive decimal Credits with at most 12 integer and 2 fractional digits. */ - max_list_cost: MonetaryAmount; + max_credit_cost: string; /** * Any of "limit". */ @@ -6520,14 +6520,14 @@ export interface ManagedAgentsBudgetLimit { export type ManagedAgentsBudgetLimitType = "limit"; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ export interface ManagedAgentsBudgetLimitParam { /** - * A monetary amount in a specific currency. + * Positive decimal Credits with at most 12 integer and 2 fractional digits. */ - max_list_cost: MonetaryAmountParam; + max_credit_cost: string; /** * Any of "limit". */ @@ -6836,10 +6836,10 @@ export interface ManagedAgentsSession { */ archived_at: string | null; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ - budget: ManagedAgentsBudgetLimit; + budget?: ManagedAgentsBudgetLimit | null; /** * A timestamp in RFC 3339 format */ @@ -6872,9 +6872,9 @@ export interface ManagedAgentsSession { */ updated_at: string; /** - * Cumulative token usage for a session across all turns. + * Cumulative Credits snapshot. Legacy token and list-cost fields may appear in older responses. */ - usage: ManagedAgentsSessionUsage; + usage?: ManagedAgentsSessionUsage; /** * Vault IDs attached to the session at creation. Empty when no vaults were * supplied. @@ -7056,8 +7056,8 @@ export interface ManagedAgentsSessionUpdatedEvent { */ agent?: ManagedAgentsSessionAgent | null; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimit | null; /** @@ -7074,9 +7074,13 @@ export interface ManagedAgentsSessionUpdatedEvent { export type ManagedAgentsSessionUpdatedEventType = "session.updated"; /** - * Cumulative token usage for a session across all turns. + * Cumulative Credits snapshot. Legacy token and list-cost fields may appear in older responses. */ export interface ManagedAgentsSessionUsage { + /** Cumulative Credits. Replace the previous snapshot instead of adding it. */ + model_credits: number; + sandbox_runtime_credits: number; + total_credits: number; /** * Cumulative time in seconds during which the session had at least one thread in * running status. Overlapping activity from concurrent threads is counted once, @@ -7111,9 +7115,13 @@ export interface ManagedAgentsSessionUsage { } /** - * Periodic snapshot of the session's cumulative usage and tracked list cost. + * Cumulative Credits emitted before session.status_idle when usage is available. */ export interface ManagedAgentsSessionUsageEvent { + /** Cumulative Credits. Replace the previous snapshot instead of adding it. */ + model_credits: number; + sandbox_runtime_credits: number; + total_credits: number; /** * Unique identifier for this event. */ @@ -7126,13 +7134,11 @@ export interface ManagedAgentsSessionUsageEvent { * Any of "session.usage". */ type: ManagedAgentsSessionUsageEventType; + /** @deprecated Legacy nested usage; current events carry Credits at the top level. */ + usage?: ManagedAgentsSessionUsageSnapshot; /** - * Point-in-time snapshot of a session's cumulative usage. - */ - usage: ManagedAgentsSessionUsageSnapshot; - /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimit | null; } @@ -7295,8 +7301,8 @@ export interface SessionNewParams { title?: string | null; workspace_id?: string; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimitParam | null; /** @@ -7356,8 +7362,8 @@ export interface SessionUpdateParams { */ agent?: ManagedAgentsSessionAgentUpdateParam | null; /** - * A hard spend ceiling. The session stops issuing new model requests once the - * tracked list cost reaches `max_list_cost`. + * A total model and sandbox credit limit. Reaching it rejects the next user + * message without interrupting the running turn. */ budget?: ManagedAgentsBudgetLimitParam | null; /** @@ -7650,6 +7656,8 @@ export type ManagedAgentsAgentThinkingEventType = "agent.thinking"; * Indicates that context compaction (summarization) occurred during the session. */ export interface ManagedAgentsAgentThreadContextCompactedEvent { + /** Credits for this compaction call, already included in Session usage. */ + usage?: ManagedAgentsSpanModelUsage; /** * Unique identifier for this event. */ @@ -8650,6 +8658,7 @@ export interface ManagedAgentsSessionEventUnionStopReason { } export interface ManagedAgentsSessionEventUnionUsage { + credits?: number; /** * This field is from variant `ManagedAgentsSpanModelUsage`. */ @@ -9017,9 +9026,9 @@ export interface ManagedAgentsSpanModelRequestEndEvent { */ model_request_start_id: string; /** - * Token usage for a single model request. + * Credits for a single model request; legacy token fields may appear in older responses. */ - model_usage: ManagedAgentsSpanModelUsage; + model_usage?: ManagedAgentsSpanModelUsage; /** * A timestamp in RFC 3339 format */ @@ -9053,25 +9062,26 @@ export interface ManagedAgentsSpanModelRequestStartEvent { export type ManagedAgentsSpanModelRequestStartEventType = "span.model_request_start"; /** - * Token usage for a single model request. + * Credits for a single model request; legacy token fields may appear in older responses. */ export interface ManagedAgentsSpanModelUsage { + credits: number; /** * Tokens used to create prompt cache in this request. */ - cache_creation_input_tokens: number; + cache_creation_input_tokens?: number; /** * Tokens read from prompt cache in this request. */ - cache_read_input_tokens: number; + cache_read_input_tokens?: number; /** * Input tokens consumed by this request. */ - input_tokens: number; + input_tokens?: number; /** * Output tokens generated by this request. */ - output_tokens: number; + output_tokens?: number; /** * Inference speed mode. `fast` provides significantly faster output token * generation at premium pricing. Not all models support `fast`; invalid @@ -9137,7 +9147,7 @@ export interface ManagedAgentsSpanOutcomeEvaluationEndEvent { */ type: ManagedAgentsSpanOutcomeEvaluationEndEventType; /** - * Token usage for a single model request. + * Credits for a single model request; legacy token fields may appear in older responses. */ usage: ManagedAgentsSpanModelUsage; } @@ -9220,6 +9230,7 @@ export interface ManagedAgentsStreamSessionEventsUnionStopReason { } export interface ManagedAgentsStreamSessionEventsUnionUsage { + credits?: number; /** * This field is from variant `ManagedAgentsSpanModelUsage`. */ @@ -10231,6 +10242,7 @@ export interface ManagedAgentsStreamSessionThreadEventsUnionStopReason { } export interface ManagedAgentsStreamSessionThreadEventsUnionUsage { + credits?: number; /** * This field is from variant `ManagedAgentsSpanModelUsage`. */ diff --git a/tests/identity-pairing-contract.test.mjs b/tests/identity-pairing-contract.test.mjs new file mode 100644 index 0000000..5122c32 --- /dev/null +++ b/tests/identity-pairing-contract.test.mjs @@ -0,0 +1,88 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { testClient, response } from './helpers.mjs'; +import { toFile } from '../dist/index.js'; + +// Official Forward resource ownership and pairing contracts (2026-10-20). +const operations = [ + ["GET", "environments", (c, scope, file) => c.environments.list({ ...scope })], + ["POST", "environments", (c, scope, file) => c.environments.create({ name: 'env', ...scope })], + ["GET", "environments/env", (c, scope, file) => c.environments.retrieve('env', scope)], + ["POST", "environments/env", (c, scope, file) => c.environments.update('env', { name: 'renamed', ...scope })], + ["POST", "environments/env/archive", (c, scope, file) => c.environments.archive('env', scope)], + ["DELETE", "environments/env", (c, scope, file) => c.environments.delete('env', scope)], + ["GET", "skills", (c, scope, file) => c.skills.list(scope)], + ["POST", "skills", (c, scope, file) => c.skills.create({ files: [file], ...scope })], + ["GET", "skills/skill", (c, scope, file) => c.skills.retrieve('skill', scope)], + ["PUT", "skills/skill", (c, scope, file) => c.skills.update('skill', { description: 'desc', ...scope })], + ["DELETE", "skills/skill", (c, scope, file) => c.skills.delete('skill', scope)], + ["GET", "skills/skill/versions", (c, scope, file) => c.skills.versions.list('skill', scope)], + ["POST", "skills/skill/versions", (c, scope, file) => c.skills.versions.create('skill', { files: [file], ...scope })], + ["GET", "skills/skill/versions/1", (c, scope, file) => c.skills.versions.retrieve('skill', '1', scope)], + ["DELETE", "skills/skill/versions/1", (c, scope, file) => c.skills.versions.delete('skill', '1', scope)], + ["GET", "skills/skill/versions/1/content", (c, scope, file) => c.skills.versions.download('skill', '1', scope)], + ["GET", "vaults", (c, scope, file) => c.vaults.list(scope)], + ["POST", "vaults", (c, scope, file) => c.vaults.create({ display_name: 'vault', ...scope })], + ["GET", "vaults/vault", (c, scope, file) => c.vaults.retrieve('vault', scope)], + ["DELETE", "vaults/vault", (c, scope, file) => c.vaults.delete('vault', scope)], + ["GET", "vaults/vault/credentials", (c, scope, file) => c.vaults.credentials.list('vault', scope)], + ["POST", "vaults/vault/credentials", (c, scope, file) => c.vaults.credentials.create('vault', { auth: { type: 'static_bearer', token: 'secret' }, ...scope })], + ["GET", "vaults/vault/credentials/cred", (c, scope, file) => c.vaults.credentials.retrieve('vault', 'cred', scope)], + ["POST", "vaults/vault/credentials/cred", (c, scope, file) => c.vaults.credentials.update('vault', 'cred', { metadata: { note: 'rotation' }, ...scope })], + ["DELETE", "vaults/vault/credentials/cred", (c, scope, file) => c.vaults.credentials.delete('vault', 'cred', scope)], + ["GET", "files", (c, scope, file) => c.files.list(scope)], + ["POST", "files", (c, scope, file) => c.files.upload({ file, ...scope })], + ["GET", "files/file", (c, scope, file) => c.files.getMetadata('file', scope)], + ["DELETE", "files/file", (c, scope, file) => c.files.delete('file', scope)], + ["GET", "files/file/content", (c, scope, file) => c.files.download('file', scope)], + ]; +for (const [method, path, call] of operations) { + for (const identity of ['idn_ /?&', '', undefined]) test(`${method} ${path} identity=${identity}`, async () => { + let apiCalls = 0; + const c = testClient('forward', async req => { + const url = new URL(req.url); + if (url.hostname === 'storage.test') { + assert.equal(url.search, '?signature=ok'); + assert.equal(req.headers.get('authorization'), null); + return new Response('content'); + } + apiCalls++; + assert.equal(req.method, method); + assert.equal(url.pathname, `/api/v1/forward/${path}`); + assert.equal(url.searchParams.get('identity_id'), identity ?? null); + assert.deepEqual([...url.searchParams.keys()], identity === undefined ? [] : ['identity_id']); + assert.ok(!(await req.text()).includes('identity_id')); + if (path === 'files/file/content') return response({ url: 'https://storage.test/content?signature=ok' }); + if (path.endsWith('/content')) return new Response('archive'); + return response({ id: 'resource', data: [], has_more: false }); + }); + const result = await call(c, identity === undefined ? {} : { identity_id: identity }, await toFile('# skill', 'SKILL.md')); + if (result instanceof Response) await result.arrayBuffer(); + assert.equal(apiCalls, 1); + }); +} + +test('Identity options keep explicit query overrides and pagination scope', async () => { + let calls = 0; + const c = testClient('forward', req => { + const url = new URL(req.url); + assert.equal(url.searchParams.get('identity_id'), 'idn_override'); + calls++; + return response({ data: [{ id: `env_${calls}` }], has_more: calls === 1, next_page: calls === 1 ? 'cursor' : null }); + }); + const items = []; for await (const e of c.environments.list({ identity_id: 'idn_typed' }, { query: { identity_id: 'idn_override' } })) items.push(e); + assert.equal(items.length, 2); + await c.environments.retrieve('env', { identity_id: 'idn_typed', query: { identity_id: 'idn_override' } }); + await c.environments.create({ name: 'env', identity_id: 'idn_typed' }, { query: { identity_id: 'idn_override' } }); +}); +const 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"}; +for (const selector of [{ code: 'K7MP92' }, { channel_pairing_id: 'pair_one' }]) test(`Pair channel with ${Object.keys(selector)[0]}`, async () => { + const c = testClient('forward', async req => { + assert.equal(new URL(req.url).search, ''); + assert.equal(req.headers.get('idempotency-key'), 'pair-once'); + assert.deepEqual(await req.json(), { ...selector, identity_id: 'idn_one', template_id: 'tmpl_one' }); + return response(pairing); + }); + const result = await c.channelPairings.create({ ...selector, identity_id: 'idn_one', template_id: 'tmpl_one', idempotency_key: 'pair-once' }); + assert.deepEqual(result, pairing); +}); diff --git a/tests/managed-field-parity.test.mjs b/tests/managed-field-parity.test.mjs index 3984070..4814c01 100644 --- a/tests/managed-field-parity.test.mjs +++ b/tests/managed-field-parity.test.mjs @@ -72,7 +72,9 @@ test('Managed wire parity: all 695 pinned types keep their 2569 wire properties, const type = declared(name); for (const wire of spec.properties ?? []) { properties++; - if (!explicitProperty(type, wire).length) failures.push(`${name}: explicit property ${wire} missing`); + // QCA budget uses decimal Credits: /cloud-agents/api/sessions/schemas#session-budget. + const currentWire = ["ManagedAgentsBudgetLimit", "ManagedAgentsBudgetLimitParam"].includes(name) && wire === "max_list_cost" ? "max_credit_cost" : wire; + if (!explicitProperty(type, currentWire).length) failures.push(`${name}: explicit property ${wire} missing`); } for (const notation of spec.variants ?? []) { variants++; diff --git a/tests/managed-types.ts b/tests/managed-types.ts index c39a342..6e89721 100644 --- a/tests/managed-types.ts +++ b/tests/managed-types.ts @@ -33,3 +33,17 @@ const customToolJSONSchema: M.ManagedAgentsCustomToolInputSchemaParam = { $defs: { label: { type: 'string', minLength: 1 } }, patternProperties: { '^x-': { $ref: '#/$defs/label' } }, }; + +// Official Credits contracts: no currency object or nested session.usage required. +const creditBudget: M.ManagedAgentsBudgetLimitParam = { type: 'limit', max_credit_cost: '100.00' }; +// @ts-expect-error Credits limits are decimal strings, not the former currency object. +const oldCreditBudget: M.ManagedAgentsBudgetLimitParam = { type: 'limit', max_list_cost: { amount: '100', currency: 'USD' } }; +const creditSnapshot: M.ManagedAgentsSessionUsage = { model_credits: 7.66, sandbox_runtime_credits: 0.34, total_credits: 8 }; +const creditEvent: M.ManagedAgentsSessionUsageEvent = { id: 'evt_one', processed_at: '2026-10-20T01:00:00Z', type: 'session.usage', ...creditSnapshot }; +const creditModelUsage: M.ManagedAgentsSpanModelUsage = { credits: 1.25 }; +const creditCompaction: M.ManagedAgentsAgentThreadContextCompactedEvent = { id: 'evt_two', processed_at: '2026-10-20T01:00:00Z', type: 'agent.thread_context_compacted', usage: { credits: 0 } }; +void [creditBudget, oldCreditBudget, creditSnapshot, creditEvent, creditModelUsage, creditCompaction]; + +const absentSessionBudget: Pick = {}; +const clearedSessionBudget: Pick = { budget: null }; +void [absentSessionBudget, clearedSessionBudget]; diff --git a/tests/session-credit-contract.test.mjs b/tests/session-credit-contract.test.mjs new file mode 100644 index 0000000..6d959b9 --- /dev/null +++ b/tests/session-credit-contract.test.mjs @@ -0,0 +1,36 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { testClient, response } from './helpers.mjs'; + +// https://docs.qoder.com/cloud-agents/api/sessions/schemas, 2026-10-20. +for (const body of [{ budget: { type: 'limit', max_credit_cost: '100.00' } }, {}, { budget: null }]) { + test(`Session budget preserves decimal/omission/null: ${JSON.stringify(body)}`, async () => { + const client = testClient('managed', async req => { + assert.deepEqual(await req.json(), body); + return response({ id: 'sess_one', ...body }); + }); + const session = await client.sessions.update('sess_one', body); + assert.deepEqual(session.budget, body.budget); + }); +} +for (const mode of ['managed', 'forward']) test(`${mode} cumulative Credits snapshot`, async () => { + const usage = { model_credits: 7.66, sandbox_runtime_credits: 0.34, total_credits: 8 }; + const client = testClient(mode, req => response({ id: 'sess_one', ...(req.url.endsWith('sess_one') ? { usage } : {}) })); + assert.deepEqual((await client.sessions.retrieve('sess_one')).usage, usage); + assert.equal((await client.sessions.retrieve('sess_empty')).usage, undefined); +}); +test('Managed history and SSE preserve top-level and per-call Credits', async () => { + const 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 } }, + ]; + const client = testClient('managed', req => req.url.endsWith('/stream') + ? new Response(events.map(e => `id: ${e.id}\nevent: ${e.type}\ndata: ${JSON.stringify(e)}\n\n`).join(''), { headers: { 'content-type': 'text/event-stream' } }) + : response({ data: events, has_more: false, next_page: null })); + assert.deepEqual((await client.sessions.events.list('sess_one')).data, events); + for (const stream of [await client.sessions.events.streamEvents('sess_one'), await client.sessions.threads.events.streamEvents('thread_one', { session_id: 'sess_one' })]) { + const actual = []; for await (const e of stream) actual.push(e); + assert.deepEqual(actual, events); + } +}); diff --git a/tests/types-smoke.ts b/tests/types-smoke.ts index 996c737..b87579f 100644 --- a/tests/types-smoke.ts +++ b/tests/types-smoke.ts @@ -216,3 +216,22 @@ forward.drives.listEntries({}); forward.drives.listEntries({ identity_id: 'idn', page: 'cursor' }); // @ts-expect-error Managed does not expose Forward Drive. managed.drives; + +async function ownershipAndPairingTypes() { + await forward.environments.create({ name: 'env', identity_id: 'idn_one' }); + await forward.environments.retrieve('env', { identity_id: 'idn_one', timeout: 1000 }); + await forward.environments.archive('env', { identity_id: 'idn_one' }); + await forward.skills.versions.retrieve('skill', '1', { identity_id: 'idn_one' }); + await forward.vaults.credentials.delete('vault', 'cred', { identity_id: 'idn_one' }); + await forward.files.download('file', { identity_id: 'idn_one' }); + // @ts-expect-error Identity scope is a string, not a number. + forward.files.download('file', { identity_id: 123 }); + const pairing = await forward.channelPairings.create({ channel_pairing_id: 'pair_one', identity_id: 'idn_one', template_id: 'tmpl_one' }); + const scope: string = pairing.scope_external_id; + const display: string = pairing.scope_display_name; + void [scope, display]; + const session = await forward.sessions.retrieve('sess_one'); + const credits: number | undefined = session.usage?.model_credits; + void credits; +} +void ownershipAndPairingTypes;