diff --git a/.github/scripts/check_package.py b/.github/scripts/check_package.py index f267f0b..040cab8 100644 --- a/.github/scripts/check_package.py +++ b/.github/scripts/check_package.py @@ -33,7 +33,8 @@ def check(root): names = jar.namelist() classes = [name for name in names if name.endswith(".class")] require(classes, "SDK JAR has no classes") - require("com/qoder/cloudagents/ForwardClient.class" in names, "Missing Forward client") + for client in ("ForwardClient", "AsyncForwardClient", "ManagedClient", "AsyncManagedClient"): + require("com/qoder/cloudagents/" + client + ".class" in names, "Missing client: " + client) require(jar.read("META-INF/LICENSE") == (root / "LICENSE").read_bytes(), "License differs") properties = jar.read("com/qoder/cloudagents/version.properties").decode("utf-8") require("version=" + version in properties.splitlines(), "Embedded version differs from POM") @@ -47,9 +48,11 @@ def check(root): or Path(name).name.startswith(".env") for name in names), "Unexpected local or test data in SDK JAR") with zipfile.ZipFile(jars[1]) as jar: - require("com/qoder/cloudagents/ForwardClient.java" in jar.namelist(), "Missing source attachment") + for client in ("ForwardClient", "ManagedClient"): + require("com/qoder/cloudagents/" + client + ".java" in jar.namelist(), "Missing source attachment: " + client) with zipfile.ZipFile(jars[2]) as jar: - require("com/qoder/cloudagents/ForwardClient.html" in jar.namelist(), "Missing Javadoc attachment") + for client in ("ForwardClient", "ManagedClient"): + require("com/qoder/cloudagents/" + client + ".html" in jar.namelist(), "Missing Javadoc attachment: " + client) require(not any(name.startswith("com/qoder/cloudagents/core/internal/") for name in jar.namelist()), "Internal implementation leaked into public Javadoc") files = jars + [pom] diff --git a/CHANGELOG.md b/CHANGELOG.md index 61c0b15..1e31750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Added +- Add `ManagedClient` / `AsyncManagedClient` and 108 documented Managed operations: Agents and versions, Deployments and Runs, Sessions/Threads/events/resources, Environments/self-hosted Work, Files, Skills/Versions, Vaults/Credentials/OAuth, Memory Stores, Models and Dreams. +- Add typed Managed budget and Credits, Agent runtime patches, versioned multiagent references, OSS storage, repository resources and exact Session provenance markers. Preserve null/omitted values and unknown response fields; retain POST search filters and opaque cursors. +- Add Managed independent JAR examples, opt-in CN/Global PAT/SA integration groups, official-response contract fixtures and API coverage documentation. Forward and Managed additions target one combined 0.2.0 release. + - Add typed synchronous/asynchronous Forward resource Search for Environments, Files, Skills and Vaults, retaining body filters, Identity query scope and Beta selectors across cursor pages. - Add Forward Dream create/list/retrieve/cancel/archive, Channel Pairing list/retrieve/update, and Decision create/retrieve/list with typed input, output and precise score values. - Add Identity auto-memory configuration, independent mount access and pagination, Schedule file resources, optional Run input snapshots, and Credits accessors for Session events. diff --git a/README.md b/README.md index 53e83aa..e3cfead 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The Qoder Cloud Agents Java SDK provides typed synchronous and asynchronous clients, with shared authentication, timeouts, retries, pagination, streaming and error handling. -Version **0.1.0** supports the **Forward API**. **Managed API support is planned for a future release** and is not available in this version. +Version **0.1.0** supports the **Forward API**. The development branch adds [Managed API support](docs/managed.md) for the planned combined **0.2.0** release; it is not available in the published 0.1.0 JAR. | Capability | Resources | | --- | --- | @@ -18,7 +18,7 @@ Version **0.1.0** supports the **Forward API**. **Managed API support is planned See [API coverage and resource guides](docs/forward-api-coverage.md) for the supported operations. -The development branch also includes [Forward Search, Dreams, Decisions, pairing management and contract updates](docs/forward-parity.md), alongside Webhooks and client extensions. These additions are unreleased and are not included in the published `0.1.0` JAR. +The development branch also includes [Forward Search, Dreams, Decisions, pairing management and contract updates](docs/forward-parity.md), alongside Webhooks, client extensions and [108 Managed operations](docs/managed-api-coverage.md). These additions are unreleased and are not included in the published `0.1.0` JAR. - [Installation](#installation) - [Quick start](#quick-start) diff --git a/docs/forward-parity.md b/docs/forward-parity.md index 2fca12d..2e68fa7 100644 --- a/docs/forward-parity.md +++ b/docs/forward-parity.md @@ -1,6 +1,6 @@ # Forward API additions (unreleased) -This guide describes the development SDK after `0.1.0`, checked against the official Forward documentation on 2026-10-28. These additions are not available from the published `0.1.0` JAR. Both `ForwardClient` and `AsyncForwardClient` expose the same resources, including `withResponse()` for status, headers and request IDs. Managed remains a separate future scope. +This guide describes the development SDK after `0.1.0`, checked against the official Forward documentation on 2026-10-28. These additions are not available from the published `0.1.0` JAR. Both `ForwardClient` and `AsyncForwardClient` expose the same resources, including `withResponse()` for status, headers and request IDs. The same planned 0.2.0 release also includes [Managed support](managed.md). ## Search resources diff --git a/docs/maintaining.md b/docs/maintaining.md index 471e37f..44320f2 100644 --- a/docs/maintaining.md +++ b/docs/maintaining.md @@ -1,6 +1,6 @@ # Java SDK maintenance -The SDK covers Forward and targets Java 8. Use JDK 17 or later for maintenance tools; the runtime compatibility matrix remains Java 8, 11, 17, 21 and 25. +The development SDK covers Forward and Managed and targets Java 8. Use JDK 17 or later for maintenance tools; the runtime compatibility matrix remains Java 8, 11, 17, 21 and 25. ## Local checks and pull requests diff --git a/docs/managed-api-coverage.md b/docs/managed-api-coverage.md new file mode 100644 index 0000000..1f0cb0c --- /dev/null +++ b/docs/managed-api-coverage.md @@ -0,0 +1,118 @@ +# Managed API 覆盖基线 + +更新:2026-10-28。以当日官方文档为准,开发分支实现 **108 个协议操作:106 个普通 HTTP 操作、2 个 SSE 操作**。同步/异步/响应封装只计一个操作。目标与 Forward 更新合并为 **0.2.0**,公共 0.1.0 不包含本表能力。 + +Base URL:CN `https://api.qoder.com.cn/api/v1/cloud`,Global `https://api.qoder.com/api/v1/cloud`。使用方法见 [Managed 指南](managed.md);验收范围见 [真实环境测试](managed-live-testing.md)。接口存在与离线通过不等于线上权限或执行结果已验证。 + +OAuth 的浏览器重定向快捷入口 `/oauth/authorize` 不是 SDK JSON 方法;SDK 使用 `/oauth/start` 返回授权 URL。Forward 专用 Webhook、Identity、Channel 等不属于 Managed API。 + +| # | Java 资源方法 | HTTP | 相对路径 | 官方文档 | +| ---: | --- | --- | --- | --- | +| 1 | `agents().archive(...)` | `POST` | `/agents/{agent_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/agents/archive) | +| 2 | `agents().create(...)` | `POST` | `/agents` | [文档](https://docs.qoder.com/cloud-agents/api/agents/create) | +| 3 | `agents().retrieve(...)` | `GET` | `/agents/{agent_id}` | [文档](https://docs.qoder.com/cloud-agents/api/agents/get) | +| 4 | `agents().versions().list(...)` | `GET` | `/agents/{agent_id}/versions` | [文档](https://docs.qoder.com/cloud-agents/api/agents/list-versions) | +| 5 | `agents().list(...)` | `GET` | `/agents` | [文档](https://docs.qoder.com/cloud-agents/api/agents/list) | +| 6 | `agents().search(...)` | `POST` | `/agents/search` | [文档](https://docs.qoder.com/cloud-agents/api/agents/search) | +| 7 | `agents().update(...)` | `POST` | `/agents/{agent_id}` | [文档](https://docs.qoder.com/cloud-agents/api/agents/update) | +| 8 | `deployments().archive(...)` | `POST` | `/deployments/{id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/archive) | +| 9 | `deployments().create(...)` | `POST` | `/deployments` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/create) | +| 10 | `deploymentRuns().retrieve(...)` | `GET` | `/deployment_runs/{run_id}` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/get-run-global) | +| 11 | `deployments().runs().retrieve(...)` | `GET` | `/deployments/{id}/runs/{run_id}` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/get-run) | +| 12 | `deployments().retrieve(...)` | `GET` | `/deployments/{id}` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/get) | +| 13 | `deploymentRuns().list(...)` | `GET` | `/deployment_runs` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/list-all-runs) | +| 14 | `deployments().runs().list(...)` | `GET` | `/deployments/{id}/runs` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/list-runs) | +| 15 | `deployments().list(...)` | `GET` | `/deployments` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/list) | +| 16 | `deployments().pause(...)` | `POST` | `/deployments/{id}/pause` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/pause) | +| 17 | `deployments().run(...)` | `POST` | `/deployments/{id}/run` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/run) | +| 18 | `deployments().search(...)` | `POST` | `/deployments/search` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/search) | +| 19 | `deployments().unpause(...)` | `POST` | `/deployments/{id}/unpause` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/unpause) | +| 20 | `deployments().update(...)` | `POST` | `/deployments/{id}` | [文档](https://docs.qoder.com/cloud-agents/api/deployments/update) | +| 21 | `dreams().archive(...)` | `POST` | `/dreams/{id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/dreams/archive) | +| 22 | `dreams().cancel(...)` | `POST` | `/dreams/{id}/cancel` | [文档](https://docs.qoder.com/cloud-agents/api/dreams/cancel) | +| 23 | `dreams().create(...)` | `POST` | `/dreams` | [文档](https://docs.qoder.com/cloud-agents/api/dreams/create) | +| 24 | `dreams().retrieve(...)` | `GET` | `/dreams/{id}` | [文档](https://docs.qoder.com/cloud-agents/api/dreams/get) | +| 25 | `dreams().list(...)` | `GET` | `/dreams` | [文档](https://docs.qoder.com/cloud-agents/api/dreams/list) | +| 26 | `environments().archive(...)` | `POST` | `/environments/{environment_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/environments/archive) | +| 27 | `environments().create(...)` | `POST` | `/environments` | [文档](https://docs.qoder.com/cloud-agents/api/environments/create) | +| 28 | `environments().delete(...)` | `DELETE` | `/environments/{environment_id}` | [文档](https://docs.qoder.com/cloud-agents/api/environments/delete) | +| 29 | `environments().retrieve(...)` | `GET` | `/environments/{environment_id}` | [文档](https://docs.qoder.com/cloud-agents/api/environments/get) | +| 30 | `environments().list(...)` | `GET` | `/environments` | [文档](https://docs.qoder.com/cloud-agents/api/environments/list) | +| 31 | `environments().search(...)` | `POST` | `/environments/search` | [文档](https://docs.qoder.com/cloud-agents/api/environments/search) | +| 32 | `environments().update(...)` | `POST` | `/environments/{environment_id}` | [文档](https://docs.qoder.com/cloud-agents/api/environments/update) | +| 33 | `environments().work().ack(...)` | `POST` | `/environments/{environment_id}/work/{work_id}/ack` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/ack) | +| 34 | `environments().work().retrieve(...)` | `GET` | `/environments/{environment_id}/work/{work_id}` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/get) | +| 35 | `environments().work().heartbeat(...)` | `POST` | `/environments/{environment_id}/work/{work_id}/heartbeat` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/heartbeat) | +| 36 | `environments().work().list(...)` | `GET` | `/environments/{environment_id}/work` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/list) | +| 37 | `environments().work().poll(...)` | `GET` | `/environments/{environment_id}/work/poll` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/poll) | +| 38 | `environments().work().stats(...)` | `GET` | `/environments/{environment_id}/work/stats` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/stats) | +| 39 | `environments().work().stop(...)` | `POST` | `/environments/{environment_id}/work/{work_id}/stop` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/stop) | +| 40 | `environments().work().update(...)` | `POST` | `/environments/{environment_id}/work/{work_id}` | [文档](https://docs.qoder.com/cloud-agents/api/environments/work/update-metadata) | +| 41 | `files().delete(...)` | `DELETE` | `/files/{file_id}` | [文档](https://docs.qoder.com/cloud-agents/api/files/delete) | +| 42 | `files().getDownloadUrl(...)` | `GET` | `/files/{file_id}/content` | [文档](https://docs.qoder.com/cloud-agents/api/files/download) | +| 43 | `files().getMetadata(...)` | `GET` | `/files/{file_id}` | [文档](https://docs.qoder.com/cloud-agents/api/files/get) | +| 44 | `files().list(...)` | `GET` | `/files` | [文档](https://docs.qoder.com/cloud-agents/api/files/list) | +| 45 | `files().search(...)` | `POST` | `/files/search` | [文档](https://docs.qoder.com/cloud-agents/api/files/search) | +| 46 | `files().upload(...)` | `POST` | `/files` | [文档](https://docs.qoder.com/cloud-agents/api/files/upload) | +| 47 | `memoryStores().archive(...)` | `POST` | `/memory_stores/{memory_store_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/archive) | +| 48 | `memoryStores().memories().create(...)` | `POST` | `/memory_stores/{memory_store_id}/memories` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/create-memory) | +| 49 | `memoryStores().create(...)` | `POST` | `/memory_stores` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/create) | +| 50 | `memoryStores().memories().delete(...)` | `DELETE` | `/memory_stores/{memory_store_id}/memories/{memory_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/delete-memory) | +| 51 | `memoryStores().delete(...)` | `DELETE` | `/memory_stores/{memory_store_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/delete) | +| 52 | `memoryStores().memories().retrieve(...)` | `GET` | `/memory_stores/{memory_store_id}/memories/{memory_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/get-memory) | +| 53 | `memoryStores().versions().retrieve(...)` | `GET` | `/memory_stores/{memory_store_id}/memory_versions/{memory_version_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/get-version) | +| 54 | `memoryStores().retrieve(...)` | `GET` | `/memory_stores/{memory_store_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/get) | +| 55 | `memoryStores().memories().list(...)` | `GET` | `/memory_stores/{memory_store_id}/memories` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/list-memories) | +| 56 | `memoryStores().versions().list(...)` | `GET` | `/memory_stores/{memory_store_id}/memory_versions` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/list-versions) | +| 57 | `memoryStores().list(...)` | `GET` | `/memory_stores` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/list) | +| 58 | `memoryStores().versions().redact(...)` | `POST` | `/memory_stores/{memory_store_id}/memory_versions/{memory_version_id}/redact` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/redact-version) | +| 59 | `memoryStores().search(...)` | `POST` | `/memory_stores/search` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/search) | +| 60 | `memoryStores().memories().update(...)` | `POST` | `/memory_stores/{memory_store_id}/memories/{memory_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/update-memory) | +| 61 | `memoryStores().update(...)` | `POST` | `/memory_stores/{memory_store_id}` | [文档](https://docs.qoder.com/cloud-agents/api/memory-stores/update) | +| 62 | `models().list(...)` | `GET` | `/models` | [文档](https://docs.qoder.com/cloud-agents/api/models/list) | +| 63 | `sessions().archive(...)` | `POST` | `/sessions/{session_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/archive) | +| 64 | `sessions().cancel(...)` | `POST` | `/sessions/{session_id}/cancel` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/cancel) | +| 65 | `sessions().create(...)` | `POST` | `/sessions` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/create) | +| 66 | `sessions().delete(...)` | `DELETE` | `/sessions/{session_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/delete) | +| 67 | `sessions().events().list(...)` | `GET` | `/sessions/{session_id}/events` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/events/list) | +| 68 | `sessions().events().send(...)` | `POST` | `/sessions/{session_id}/events` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/events/send) | +| 69 | `sessions().events().streamEvents(...)` | `GET` | `/sessions/{session_id}/events/stream` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/events/stream) | +| 70 | `sessions().retrieve(...)` | `GET` | `/sessions/{session_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/get) | +| 71 | `sessions().list(...)` | `GET` | `/sessions` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/list) | +| 72 | `sessions().resources().create(...)` | `POST` | `/sessions/{session_id}/resources` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/resources/add) | +| 73 | `sessions().resources().delete(...)` | `DELETE` | `/sessions/{session_id}/resources/{resource_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/resources/delete) | +| 74 | `sessions().resources().retrieve(...)` | `GET` | `/sessions/{session_id}/resources/{resource_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/resources/get) | +| 75 | `sessions().resources().list(...)` | `GET` | `/sessions/{session_id}/resources` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/resources/list) | +| 76 | `sessions().resources().update(...)` | `POST` | `/sessions/{session_id}/resources/{resource_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/resources/update) | +| 77 | `sessions().search(...)` | `POST` | `/sessions/search` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/search) | +| 78 | `sessions().threads().archive(...)` | `POST` | `/sessions/{session_id}/threads/{thread_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/threads/archive) | +| 79 | `sessions().threads().events().list(...)` | `GET` | `/sessions/{session_id}/threads/{thread_id}/events` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/threads/events/list) | +| 80 | `sessions().threads().events().streamEvents(...)` | `GET` | `/sessions/{session_id}/threads/{thread_id}/stream` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/threads/events/stream) | +| 81 | `sessions().threads().retrieve(...)` | `GET` | `/sessions/{session_id}/threads/{thread_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/threads/get) | +| 82 | `sessions().threads().list(...)` | `GET` | `/sessions/{session_id}/threads` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/threads/list) | +| 83 | `sessions().update(...)` | `POST` | `/sessions/{session_id}` | [文档](https://docs.qoder.com/cloud-agents/api/sessions/update) | +| 84 | `skills().versions().create(...)` | `POST` | `/skills/{skill_id}/versions` | [文档](https://docs.qoder.com/cloud-agents/api/skills/create-version) | +| 85 | `skills().create(...)` | `POST` | `/skills` | [文档](https://docs.qoder.com/cloud-agents/api/skills/create) | +| 86 | `skills().versions().delete(...)` | `DELETE` | `/skills/{skill_id}/versions/{version}` | [文档](https://docs.qoder.com/cloud-agents/api/skills/delete-version) | +| 87 | `skills().delete(...)` | `DELETE` | `/skills/{skill_id}` | [文档](https://docs.qoder.com/cloud-agents/api/skills/delete) | +| 88 | `skills().versions().download(...)` | `GET` | `/skills/{skill_id}/versions/{version}/content` | [文档](https://docs.qoder.com/cloud-agents/api/skills/get-version-content) | +| 89 | `skills().versions().retrieve(...)` | `GET` | `/skills/{skill_id}/versions/{version}` | [文档](https://docs.qoder.com/cloud-agents/api/skills/get-version) | +| 90 | `skills().retrieve(...)` | `GET` | `/skills/{skill_id}` | [文档](https://docs.qoder.com/cloud-agents/api/skills/get) | +| 91 | `skills().versions().list(...)` | `GET` | `/skills/{skill_id}/versions` | [文档](https://docs.qoder.com/cloud-agents/api/skills/list-versions) | +| 92 | `skills().list(...)` | `GET` | `/skills` | [文档](https://docs.qoder.com/cloud-agents/api/skills/list) | +| 93 | `skills().search(...)` | `POST` | `/skills/search` | [文档](https://docs.qoder.com/cloud-agents/api/skills/search) | +| 94 | `skills().update(...)` | `PUT` | `/skills/{skill_id}` | [文档](https://docs.qoder.com/cloud-agents/api/skills/update) | +| 95 | `vaults().credentials().archive(...)` | `POST` | `/vaults/{vault_id}/credentials/{credential_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/archive-credential) | +| 96 | `vaults().archive(...)` | `POST` | `/vaults/{vault_id}/archive` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/archive) | +| 97 | `vaults().credentials().create(...)` | `POST` | `/vaults/{vault_id}/credentials` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/create-credential) | +| 98 | `vaults().create(...)` | `POST` | `/vaults` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/create) | +| 99 | `vaults().credentials().delete(...)` | `DELETE` | `/vaults/{vault_id}/credentials/{credential_id}` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/delete-credential) | +| 100 | `vaults().delete(...)` | `DELETE` | `/vaults/{vault_id}` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/delete) | +| 101 | `vaults().credentials().retrieve(...)` | `GET` | `/vaults/{vault_id}/credentials/{credential_id}` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/get-credential) | +| 102 | `vaults().retrieve(...)` | `GET` | `/vaults/{vault_id}` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/get) | +| 103 | `vaults().credentials().list(...)` | `GET` | `/vaults/{vault_id}/credentials` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/list-credentials) | +| 104 | `vaults().list(...)` | `GET` | `/vaults` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/list) | +| 105 | `vaults().search(...)` | `POST` | `/vaults/search` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/search) | +| 106 | `oauth().start(...)` | `POST` | `/oauth/start` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/start-oauth) | +| 107 | `vaults().credentials().update(...)` | `POST` | `/vaults/{vault_id}/credentials/{credential_id}` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/update-credential) | +| 108 | `vaults().credentials().validate(...)` | `POST` | `/vaults/{vault_id}/credentials/{credential_id}/mcp_oauth_validate` | [文档](https://docs.qoder.com/cloud-agents/api/vaults/validate-credential) | diff --git a/docs/managed-live-testing.md b/docs/managed-live-testing.md new file mode 100644 index 0000000..bd65639 --- /dev/null +++ b/docs/managed-live-testing.md @@ -0,0 +1,28 @@ +# Managed 真实环境验收 + +`ManagedLiveCheck` 是独立 examples 工程中的可选测试入口,使用已解析的 SDK JAR;普通测试不访问线上。开发构建先执行根项目 `./mvnw clean install`,再执行 `./mvnw -f examples/pom.xml clean verify`。验证内网 QA 包或公网发布包时,在独立消费者中锁定实际下载的包和摘要,不能用本地安装包替代。 + +配置 `QODER_BASE_URL`(CN 或 Global 的 `/api/v1/cloud`)、`QODER_AUTH_MODE=pat|sa`,以及 PAT、SA Key 或 SAT。SA Key 额外需要 `QODER_REGION=cn|global`,由 `ManagedExampleClient` 申请 `qca.access`。密钥通过环境注入,不写入命令或日志。可设置 `QODER_MODEL`,默认 `auto`。 + +```sh +export QODER_RUN_LIVE=true +./mvnw -B -ntp -f examples/pom.xml exec:java \ + -Dexec.mainClass=com.qoder.cloudagents.examples.ManagedLiveCheck \ + -Dexec.args=read +``` + +| 分组 | 验证内容 | 额外开关 | +| --- | --- | --- | +| `read` | Model、八类 Search、Dream list、异步响应 ID | 无 | +| `resources` | Agent 乐观版本更新及历史版本、Environment、Memory/Version、File 上传及 downloadable 权限(允许时下载)、Skill/Version、Vault/Credential archive/delete | `QODER_ALLOW_WRITE=true` | +| `session` | Agent + cloud Environment 创建 Session,预算与 metadata,动态 Agent 配置,短模型请求、SSE 回显与 idle、Credits、Thread 列表、取消预算 | write + `QODER_ALLOW_EXECUTION=true` | +| `deployment` | 手动 Deployment、pause/unpause、Run 的 scoped/global 读取、初始事件回显 | write + execution | +| `work` | 独立 self_hosted Environment 的 Work poll/ack/heartbeat/update/get/list/stats/stop | write + execution | + +写入分组仅创建 `sdk-contract-managed-java-` 前缀资源。通过 ID 仅清理本次创建的资源;Agent/Deployment archive 会保留历史记录。Session 不在终态时先取消,再尝试删除。Work 分组验证租约协议,不启动客户 worker,也不声称验证自托管容器执行。 + +每次 HTTP 请求最长 120 秒;模型回复只发一条短消息。记录方法、路径、状态和请求/资源 ID,日志不打印请求体、密钥、完整 URL query 或模型文本。失败退出非零,清理单独尝试并记录 `cleanup_failed`,不会掩盖业务异常。外部运行器应为每个分组设置进程超时,并保留首轮、后续复验及未清理资源记录。 + +需要分别记录 CN/Global × PAT/SA 的结果。五个 JDK 的离线回归不能代替真实链路结果。当前测试入口不是 108 项逐接口线上覆盖:OAuth 用户授权、OSS 挂载、Dream 模型执行、长稳及故障注入需专用配置和单独验收。已有 Forward 内网测试不会自动执行本入口;同步内部控制脚本时要显式加入相应分组,默认 `promote=false`。 + +上传文件不一定可下载;当响应 `downloadable=false` 时,资源分组检查 `/content` 返回官方规定的 403,并明确记录该路径未进行实际文件传输。Work 的 `block_ms` 必须在 1–999 之间;当前示例使用 999。 diff --git a/docs/managed.md b/docs/managed.md new file mode 100644 index 0000000..c2e397b --- /dev/null +++ b/docs/managed.md @@ -0,0 +1,96 @@ +# Managed API (development) + +Managed support is being prepared together with the unreleased Forward changes for **0.2.0**. It is not in the published 0.1.0 JAR. The [coverage inventory](managed-api-coverage.md) records 108 documented operations, including two SSE endpoints, checked against the [official documentation](https://docs.qoder.com/cloud-agents/overview) on 2026-10-28. + +## Client and authentication + +Use `ManagedClient` or `AsyncManagedClient`; resource models live in `com.qoder.cloudagents.managed`. The root client shares the existing Java 8 transport, credentials, request options, retry/cancellation handling and typed errors with Forward. Models are immutable, preserve unknown JSON fields, and keep omitted fields distinct from explicit JSON null. + +```java +import com.qoder.cloudagents.ManagedClient; +import com.qoder.cloudagents.core.RequestOptions; +import com.qoder.cloudagents.managed.*; + +try (ManagedClient client = ManagedClient.builder() + .baseUrl("https://api.qoder.com.cn/api/v1/cloud") + .pat(System.getenv("QODER_PAT")) + .build()) { + ModelListResponse models = client.models().list(); + Agent agent = client.agents().create(AgentCreateParams.builder() + .name("reviewer") + .model("auto") + .system("Review code and explain your findings.") + .build()); +} +``` + +The base URL is resolved from `.baseUrl(...)`, then `QODER_BASE_URL`, then Global `https://api.qoder.com/api/v1/cloud`. CN uses `https://api.qoder.com.cn/api/v1/cloud`. PAT and static SAT use the same configuration rules as Forward; `ServiceAccountCredential` exchanges an SA Key for a platform SAT with `qca.access`. The examples' `ManagedExampleClient` handles PAT, SA Key and static SAT selection. Managed does not expose Forward's Identity query selector. + +`client.async()` shares the parent's transport; closing that view is a no-op. `ManagedClient.builder().buildAsync()` owns its transport. `withOptions(...)` creates an independently closeable client. Ordinary HTTP methods also offer `withResponse()` for status, headers and request ID. SSE streams expose handshake metadata through `response()` and must be closed. + +## Agent versions and Session runtime + +Agent creation requires a name and model. Updates require the current `AgentUpdateParams.version(...)` for optimistic concurrency. `agents().retrieve(id, AgentRetrieveParams.builder().version(n).build())` reads a version snapshot, and `agents().versions().list(id)` lists snapshots. Use the returned opaque `next_page`: Agent snapshots share an Agent ID. + +Models accept an ID string or `ModelConfig` with `id`, `effort` and `contextWindow`. Managed does not accept Forward's `speed` setting. Session responses can additionally expose `effectiveContextWindow`. Multiagent rosters support string Agent references, `{type: agent, id, version}`, `self`, and an Advisor with a model ID. Child versions support numeric values and `latest`; preserve the server-resolved snapshot when reading sessions. + +```java +Session session = client.sessions().create(SessionCreateParams.builder() + .agent(AgentReference.builder().type("agent").id(agent.id()).version(agent.version()).build()) + .environmentId(environmentId) + .budget(SessionBudget.builder().type("limit").maxCreditCost("100.00").build()) + .build()); + +client.sessions().update(session.id(), SessionUpdateParams.builder() + .agent(SessionAgentPatch.builder().system("Use the updated review policy.").build()) + .build(), RequestOptions.builder() + .header("x-qoder-beta", "session-agent-patch-2026-07-21") + .build()); +``` + +`SessionAgentPatch` changes supported runtime fields (`model`, `system`, `tools`, `mcpServers`, `skills`, `name`, `description`). It does not repin an Agent ID/version or change the multiagent roster. Send the documented `session-agent-patch-2026-07-21` Beta header for model, prompt, skill, name or description changes. Browser tools additionally require their documented Beta header. See [official Session updates](https://docs.qoder.com/cloud-agents/api/sessions/update). + +Typed Session creation adds exactly three string metadata fields: `__qca_sdk_created=true`, `__qca_sdk_language=java`, and `__qca_sdk_version` from the installed JAR. Same-value markers are accepted; different values or types fail before HTTP. Custom fields and unknown prefixed keys remain unchanged, and caller maps are not mutated. These entries count toward the service's metadata limit. Updates and generic `request(...)` calls do not inject markers. + +Budget values are positive decimal strings with up to 12 integer and two fractional digits. Omit or pass null when creating an unlimited Session. When updating, omission preserves the budget and `.budget(null)` removes it. Credits use `BigDecimal`: Session usage and top-level `session.usage` events expose `modelCredits`, `sandboxRuntimeCredits` and `totalCredits`; model-request and compaction events expose nested `modelUsageCredits` and `usageCredits`. + +Session environment variables use `Map`. Deployment environment variables use a string of `KEY=VALUE` lines. Session metadata updates are merge patches; null values remove keys, while top-level null is a service no-op. Deployment metadata has its own merge-patch rules. The SDK preserves the submitted representation. + +## Events, resources and pagination + +`SessionEventParam` and `EventContent.text(...)` build user events as content-block arrays. List events with `SessionEventListParams.types(...)`, which sends the Managed `types` query key; Session lifecycle filters use `statuses`. Date comparisons use `createdAtGt/Gte/Lt/Lte` where supported. + +```java +SessionEventSendResponse sent = client.sessions().events().send(session.id(), + SessionEventSendParams.builder().events(java.util.Collections.singletonList( + SessionEventParam.builder().type("user.message") + .content(EventContent.text("Hello")).build())).build()); +try (com.qoder.cloudagents.streaming.EventStream stream = + client.sessions().events().streamEvents(session.id(), + SessionEventStreamParams.builder().lastEventId(sent.data().get(0).id()).build())) { + for (SessionEvent event : stream) { + if ("session.status_idle".equals(event.type())) break; + } +} +``` + +Session streams accept repeated `event_deltas[]` selectors; thread streams accept no query selectors and use `/sessions/{session}/threads/{thread}/stream`. Both put the resume cursor in `Last-Event-ID`. Per-call headers override parameter/default cursors. `resumableStream(...)` is explicit and never resends user messages. Closing a stream cancels the subscription, not the Session. + +Create-time resources support File, GitHub, generic Git and Memory Store attachments. `SessionResourceSpec` includes checkout, credentials, mount path and memory access as applicable. Existing Sessions can add File resources through `sessions().resources().create(...)`; resource updates rotate repository credentials. Credentials are request fields; responses do not expose them. + +Cursor lists retain supported filters and request options; `getNextPageAsync()` remains cancellable. Search uses POST JSON bodies and automatically adds `search-2026-08-31`, preserving other selected Betas and opaque page tokens. File scope filtering cannot be combined with cursor continuation. Models and Dreams return non-paginated collections; memory entry/version lists expose only the filters documented by Managed. + +## Deployments, Work and resources + +- `deployments()` supports create/retrieve/update/list/search, pause/unpause/archive and manual run. Omit `schedule` for manual-only execution. Use `deployments().runs()` for scoped runs and `deploymentRuns()` for global runs. +- `environments().work()` supports poll, ack, heartbeat, retrieve/list/stats, metadata update and stop for self-hosted environments. Poll may return null. Heartbeat parameters go in the query. Supply `Worker-ID` through `RequestOptions.header(...)`. Poll/ack/heartbeat are never automatically retried because they claim or advance a lease. +- Environment storage supports typed OSS buckets, RAM roles and access-key credentials. Set `x-qoder-beta: oss-bucket-2026-09-23` explicitly when required by the [storage contract](https://docs.qoder.com/cloud-agents/api/environments/schemas). No dedicated OSS live configuration is included in the test suite. +- Files support multipart upload, metadata, search, URL retrieval and isolated streaming download. Skill creation accepts `displayTitle`, repeatable files and metadata; Skill Versions support immutable upload/retrieve/list/delete and ZIP download. The deprecated Skill PUT update remains available for compatibility. +- Vaults support archives and credential CRUD/archive/validation. `oauth().start(...)` sends optional client secrets in the JSON body and returns `authorizationUrl`, `state` and `callbackOrigin`. User authorization still happens at the provider. Credential updates, OAuth startup and validation disable automatic retries to avoid replaying token rotations or OAuth state changes. +- Dream inputs support a single primary Memory Store plus optional Session IDs. Forward's `identity_template` input does not apply to Managed. `Dream.sessionId()` exposes the execution Session when available. + +## Verification and release + +The offline suite tests all 106 HTTP operations in four call styles, both SSE routes, exact wire placement, pagination, metadata/budget semantics, and response examples from the official docs. The independent examples project compiles and tests against the installed JAR. Run [the opt-in Managed integration entry](managed-live-testing.md) separately; offline coverage is not a claim that all operations passed against production. + +Both Forward and Managed remain under `Unreleased` until the combined 0.2.0 version PR. After merging implementation PRs, run internal integration tests from the merged GitHub SHA and accept that build's QA package before preparing the release. diff --git a/examples/README.md b/examples/README.md index e894ca2..39ae907 100644 --- a/examples/README.md +++ b/examples/README.md @@ -248,3 +248,7 @@ Forward Webhook listing and receiver verification: see [Webhook guide](../docs/w ## Forward additions (development JAR) [ForwardCapabilitiesExample](src/main/java/com/qoder/cloudagents/examples/ForwardCapabilitiesExample.java) demonstrates resource Search, Decision creation, Dream creation and Pairing listing. See [parameters, opt-in flags and side effects](../docs/forward-parity.md#verification-and-executable-example). It uses the installed development JAR; these APIs are not in Maven Central `0.1.0`. + +## Managed API (unreleased, planned for 0.2.0) + +`ManagedExampleClient` configures PAT / SA Key / SAT authentication with `QODER_BASE_URL` for `/api/v1/cloud`. `ManagedLiveCheck` provides explicit `read`, `resources`, `session`, `deployment` and `work` integration groups against the resolved JAR. See [Managed usage](../docs/managed.md) and [opt-in live testing](../docs/managed-live-testing.md) for permissions, test resources and cleanup. These classes are not in the published 0.1.0 SDK. diff --git a/examples/src/main/java/com/qoder/cloudagents/examples/ManagedExampleClient.java b/examples/src/main/java/com/qoder/cloudagents/examples/ManagedExampleClient.java new file mode 100644 index 0000000..3949e05 --- /dev/null +++ b/examples/src/main/java/com/qoder/cloudagents/examples/ManagedExampleClient.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.examples; + +import com.qoder.cloudagents.ManagedClient; +import com.qoder.cloudagents.auth.AuthMode; +import com.qoder.cloudagents.auth.Region; +import com.qoder.cloudagents.auth.ServiceAccountCredential; + +/** Example-only PAT, static SAT or SA Key configuration for the Managed API. */ +public final class ManagedExampleClient implements AutoCloseable { + private final ManagedClient client; + private final ServiceAccountCredential credential; + + private ManagedExampleClient(ManagedClient client, ServiceAccountCredential credential) { + this.client = client; + this.credential = credential; + } + + public static ManagedExampleClient fromEnvironment() { + ManagedClient.Builder builder = ManagedClient.builder(); + ServiceAccountCredential credential = null; + String mode = System.getenv("QODER_AUTH_MODE"); + if ("sa".equals(mode)) { + builder.authMode(AuthMode.SA); + String key = System.getenv("QODER_SA_KEY"); + if (key != null && !key.isEmpty()) { + String region = System.getenv("QODER_REGION"); + if (!"cn".equals(region) && !"global".equals(region)) + throw new IllegalArgumentException("Set QODER_REGION to cn or global"); + credential = + ServiceAccountCredential.builder() + .saKey(key) + .region("cn".equals(region) ? Region.CN : Region.GLOBAL) + .scopes("qca.access") + .build(); + builder.credential(credential); + } + } else if (mode != null && !"pat".equals(mode)) + throw new IllegalArgumentException("Set QODER_AUTH_MODE to pat or sa"); + try { + return new ManagedExampleClient(builder.build(), credential); + } catch (RuntimeException error) { + if (credential != null) credential.close(); + throw error; + } + } + + public ManagedClient client() { + return client; + } + + public void close() { + client.close(); + if (credential != null) credential.close(); + } +} diff --git a/examples/src/main/java/com/qoder/cloudagents/examples/ManagedLiveCheck.java b/examples/src/main/java/com/qoder/cloudagents/examples/ManagedLiveCheck.java new file mode 100644 index 0000000..0ac74c6 --- /dev/null +++ b/examples/src/main/java/com/qoder/cloudagents/examples/ManagedLiveCheck.java @@ -0,0 +1,505 @@ +package com.qoder.cloudagents.examples; + +import com.qoder.cloudagents.ManagedClient; +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ApiStatusException; +import com.qoder.cloudagents.managed.*; +import com.qoder.cloudagents.streaming.EventStream; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.*; + +/** Opt-in Managed integration checks. Creates only sdk-contract resources owned by this run. */ +public final class ManagedLiveCheck { + private final ManagedClient client; + private final PrintStream out; + private final String name = + "sdk-contract-managed-java-" + UUID.randomUUID().toString().substring(0, 8); + private final String model; + private final Deque cleanup = new ArrayDeque<>(); + + public ManagedLiveCheck(ManagedClient client, String model, PrintStream out) { + this.client = client; + this.model = model; + this.out = out; + } + + public static void main(String[] args) throws Exception { + String group = args.length == 1 ? args[0] : ""; + validate(group, System.getenv()); + try (ManagedExampleClient setup = ManagedExampleClient.fromEnvironment()) { + String model = System.getenv("QODER_MODEL"); + try (ManagedClient traced = + setup + .client() + .withOptions( + b -> + b.interceptor( + (request, chain) -> { + java.util.concurrent.CompletableFuture< + com.qoder.cloudagents.core.http.HttpResponse> + pending = chain.proceed(request); + pending.whenComplete( + (response, error) -> { + if (response != null) + System.out.println( + "http=" + + request.method() + + " " + + request.uri().getPath() + + " status=" + + response.statusCode()); + }); + return pending; + }))) { + new ManagedLiveCheck(traced, model == null ? "auto" : model, System.out).run(group); + } + } catch (ApiStatusException error) { + System.err.println( + "managed_failed status=" + error.statusCode() + " request_id=" + error.requestId()); + throw error; + } + } + + public static void validate(String group, Map env) { + check( + Arrays.asList("read", "resources", "session", "deployment", "work").contains(group), + "Choose read, resources, session, deployment or work"); + check("true".equals(env.get("QODER_RUN_LIVE")), "Set QODER_RUN_LIVE=true"); + if (!"read".equals(group)) + check("true".equals(env.get("QODER_ALLOW_WRITE")), "Set QODER_ALLOW_WRITE=true"); + if (Arrays.asList("session", "deployment", "work").contains(group)) + check("true".equals(env.get("QODER_ALLOW_EXECUTION")), "Set QODER_ALLOW_EXECUTION=true"); + } + + public void run(String group) throws Exception { + try { + if ("read".equals(group)) read(); + else if ("resources".equals(group)) resources(); + else if ("session".equals(group)) session(); + else if ("deployment".equals(group)) deployment(); + else if ("work".equals(group)) work(); + else throw new IllegalArgumentException("Unknown group"); + out.println("passed=" + group); + } finally { + while (!cleanup.isEmpty()) + try { + cleanup.pop().run(); + } catch (RuntimeException error) { + out.println("cleanup_failed type=" + error.getClass().getSimpleName()); + } + } + } + + private RequestOptions options(String step) { + return RequestOptions.builder() + .idempotencyKey(name + "-" + step) + .totalTimeout(Duration.ofSeconds(120)) + .build(); + } + + private void read() throws Exception { + check(!client.models().list().data().isEmpty(), "Model catalog is empty"); + check( + client + .agents() + .search(AgentSearchParams.builder().name(name).limit(1).build()) + .data() + .isEmpty(), + "Unexpected Agent match"); + client.deployments().search(DeploymentSearchParams.builder().name(name).limit(1).build()); + client + .sessions() + .search( + SessionSearchParams.builder() + .metadata(Collections.singletonMap("sdk_contract", name)) + .limit(1) + .build()); + client.environments().search(EnvironmentSearchParams.builder().name(name).limit(1).build()); + client.files().search(FileSearchParams.builder().name(name).limit(1).build()); + client.skills().search(SkillSearchParams.builder().displayTitle(name).limit(1).build()); + client.vaults().search(VaultSearchParams.builder().name(name).limit(1).build()); + client.memoryStores().search(MemoryStoreSearchParams.builder().name(name).limit(1).build()); + client.dreams().list(DreamListParams.builder().limit(1).build()); + check( + client.async().models().withResponse().list().get().requestId() != null, + "Missing request ID"); + } + + private Environment environment(String type) { + Environment e = + client + .environments() + .create( + EnvironmentCreateParams.builder() + .name(name) + .config(EnvironmentConfig.builder().type(type).build()) + .build(), + options("environment")); + cleanup.push(() -> client.environments().delete(e.id())); + out.println("environment=" + e.id()); + return e; + } + + private Agent agent() { + Agent a = + client + .agents() + .create( + AgentCreateParams.builder() + .name(name) + .model(model) + .system("Reply with exactly SDK_MANAGED_OK, no other text.") + .build(), + options("agent")); + cleanup.push(() -> client.agents().archive(a.id())); + out.println("agent=" + a.id()); + return a; + } + + private void resources() throws Exception { + Environment env = environment("self_hosted"); + Agent original = agent(); + Agent changed = + client + .agents() + .update( + original.id(), + AgentUpdateParams.builder().version(original.version()).description(name).build(), + options("agent-update")); + check(changed.version() > original.version(), "Agent version did not advance"); + check( + client + .agents() + .retrieve( + original.id(), AgentRetrieveParams.builder().version(original.version()).build()) + .version() + .equals(original.version()), + "Version retrieval mismatch"); + check( + !client + .agents() + .versions() + .list(original.id(), AgentVersionListParams.builder().limit(1).build()) + .data() + .isEmpty(), + "Version list is empty"); + client + .environments() + .update( + env.id(), + EnvironmentUpdateParams.builder().description(name).build(), + options("environment-update")); + MemoryStore store = + client + .memoryStores() + .create(MemoryStoreCreateParams.builder().name(name).build(), options("store")); + cleanup.push(() -> client.memoryStores().delete(store.id())); + Memory memory = + client + .memoryStores() + .memories() + .create( + store.id(), + MemoryCreateParams.builder().path("qa.md").content("sdk contract").build(), + options("memory")); + Memory updated = + client + .memoryStores() + .memories() + .update( + store.id(), + memory.id(), + MemoryUpdateParams.builder() + .content("updated sdk contract") + .contentSha256(memory.contentSha256()) + .build(), + options("memory-update")); + check(updated.version() > memory.version(), "Memory version did not advance"); + check( + !client + .memoryStores() + .versions() + .list(store.id(), MemoryVersionListParams.builder().memoryId(memory.id()).build()) + .data() + .isEmpty(), + "Memory versions missing"); + FileMetadata file = + client + .files() + .upload( + FileUploadParams.builder() + .file( + Upload.bytes( + "sdk contract".getBytes(StandardCharsets.UTF_8), + name + ".txt", + "text/plain")) + .build(), + options("file")); + cleanup.push(() -> client.files().delete(file.id())); + check(client.files().getMetadata(file.id()).sizeBytes() > 0, "File metadata has no size"); + if (Boolean.TRUE.equals(file.downloadable())) { + try (FileDownload download = client.files().download(file.id(), options("download"))) { + check(download.body().read() == 's', "Downloaded file mismatch"); + } + } else { + check(Boolean.FALSE.equals(file.downloadable()), "Missing downloadable capability flag"); + try { + client.files().getDownloadUrl(file.id()); + throw new IllegalStateException("A non-downloadable file unexpectedly returned a URL"); + } catch (ApiStatusException error) { + if (error.statusCode() != 403) throw error; + out.println("file_not_downloadable_expected_403"); + } + } + String skillName = name.toLowerCase(Locale.ROOT); + byte[] skill = + ("---\nname: " + + skillName + + "\ndescription: SDK acceptance\n---\n# Test\nOnly used for SDK acceptance.\n") + .getBytes(StandardCharsets.UTF_8); + Skill s = + client + .skills() + .create( + SkillCreateParams.builder() + .displayTitle(name) + .addFile(Upload.bytes(skill, skillName + "/SKILL.md", "text/markdown")) + .build(), + options("skill")); + cleanup.push(() -> client.skills().delete(s.id())); + check(s.latestVersion() != null, "Skill version missing"); + check( + client.skills().versions().retrieve(s.id(), s.latestVersion()).skillId().equals(s.id()), + "Skill version owner mismatch"); + Vault vault = + client + .vaults() + .create(VaultCreateParams.builder().displayName(name).build(), options("vault")); + cleanup.push(() -> client.vaults().delete(vault.id())); + VaultCredential credential = + client + .vaults() + .credentials() + .create( + vault.id(), + VaultCredentialCreateParams.builder() + .auth( + VaultCredentialCreateAuth.builder() + .type("environment_variable") + .secretName("SDK_CONTRACT_TEST") + .secretValue("temporary-nonsecret") + .build()) + .build(), + options("credential")); + client + .vaults() + .credentials() + .archive(vault.id(), credential.id(), options("credential-archive")); + client.vaults().credentials().delete(vault.id(), credential.id()); + } + + private Session createSession(Agent a, Environment e, String key) { + Map metadata = new LinkedHashMap<>(); + metadata.put("sdk_contract", JsonValue.of(name)); + metadata.put("__qca_sdk_future", JsonValue.of("kept")); + Session s = + client + .sessions() + .create( + SessionCreateParams.builder() + .agent( + AgentReference.builder() + .type("agent") + .id(a.id()) + .version(a.version()) + .build()) + .environmentId(e.id()) + .budget(SessionBudget.builder().type("limit").maxCreditCost("10.00").build()) + .metadata(metadata) + .build(), + options(key)); + cleanup.push(() -> closeSession(s.id())); + out.println("session=" + s.id()); + check( + s.metadata().get("__qca_sdk_created").asString().equals("true"), "Session marker missing"); + check(metadata.size() == 2, "Caller metadata changed"); + return s; + } + + private void session() throws Exception { + Environment e = environment("cloud"); + Agent a = agent(); + Session s = createSession(a, e, "session"); + client + .sessions() + .update( + s.id(), + SessionUpdateParams.builder() + .agent( + SessionAgentPatch.builder() + .system("Reply with exactly SDK_MANAGED_OK, no other text.") + .build()) + .build(), + options("session-patch").toBuilder() + .header("x-qoder-beta", "session-agent-patch-2026-07-21") + .build()); + SessionEventSendResponse sent = + client + .sessions() + .events() + .send( + s.id(), + SessionEventSendParams.builder() + .events(Collections.singletonList(message())) + .build(), + options("message")); + check(!sent.data().isEmpty(), "No input event ID"); + awaitReply(s.id(), sent.data().get(0).id()); + Session ended = client.sessions().retrieve(s.id()); + check(ended.usage() != null && ended.usage().totalCredits() != null, "Session Credits missing"); + check(!client.sessions().threads().list(s.id()).data().isEmpty(), "Session thread missing"); + client + .sessions() + .update( + s.id(), SessionUpdateParams.builder().budget(null).build(), options("remove-budget")); + } + + private SessionEventParam message() { + return SessionEventParam.builder() + .type("user.message") + .content(EventContent.text("Reply with exactly SDK_MANAGED_OK.")) + .build(); + } + + private void awaitReply(String id, String cursor) { + boolean replied = false, idle = false; + try (EventStream stream = + client + .sessions() + .events() + .streamEvents( + id, + SessionEventStreamParams.builder().lastEventId(cursor).build(), + options("stream"))) { + for (SessionEvent event : stream) { + if ("agent.message".equals(event.type()) && event.content() != null) + replied = event.content().toJsonValue().toJson().contains("SDK_MANAGED_OK"); + if ("session.error".equals(event.type())) + throw new IllegalStateException("Session emitted an error event"); + if ("session.status_idle".equals(event.type())) { + idle = true; + break; + } + } + } + check(replied && idle, "Session did not return the expected reply and idle event"); + } + + private void deployment() throws Exception { + Environment e = environment("cloud"); + Agent a = agent(); + Deployment d = + client + .deployments() + .create( + DeploymentCreateParams.builder() + .name(name) + .agent(a.id()) + .environmentId(e.id()) + .initialEvents(Collections.singletonList(message())) + .environmentVariables("SDK_CONTRACT_TEST=true") + .build(), + options("deployment")); + cleanup.push(() -> client.deployments().archive(d.id())); + out.println("deployment=" + d.id()); + client.deployments().pause(d.id(), options("pause")); + client.deployments().unpause(d.id(), options("unpause")); + DeploymentRun run = client.deployments().run(d.id(), options("run")); + check(run.error() == null && run.sessionId() != null, "Deployment failed to create a Session"); + cleanup.push(() -> closeSession(run.sessionId())); + check( + client.deploymentRuns().retrieve(run.id()).sessionId().equals(run.sessionId()), + "Global run differs"); + check( + client.deployments().runs().retrieve(d.id(), run.id()).id().equals(run.id()), + "Scoped run differs"); + check(!client.deployments().runs().list(d.id()).data().isEmpty(), "Run list missing"); + SessionEventListResponse events = + client + .sessions() + .events() + .list( + run.sessionId(), + SessionEventListParams.builder() + .types(Collections.singletonList("user.message")) + .limit(1) + .build()); + check(!events.data().isEmpty(), "Deployment initial event missing"); + awaitReply(run.sessionId(), events.data().get(0).id()); + } + + private void work() throws Exception { + Environment e = environment("self_hosted"); + Agent a = agent(); + Session s = createSession(a, e, "work-session"); + client + .sessions() + .events() + .send( + s.id(), + SessionEventSendParams.builder().events(Collections.singletonList(message())).build(), + options("work-message")); + RequestOptions worker = options("work").toBuilder().header("Worker-ID", name).build(); + WorkItem item = + client + .environments() + .work() + .poll(e.id(), WorkPollParams.builder().blockMs(999).build(), worker); + check(item != null, "No self-hosted work item"); + check(item.data().id().equals(s.id()), "Work references a different Session"); + client.environments().work().ack(e.id(), item.id(), worker); + client + .environments() + .work() + .heartbeat( + e.id(), + item.id(), + WorkHeartbeatParams.builder() + .expectedLastHeartbeat("NO_HEARTBEAT") + .desiredTtlSeconds(30) + .build(), + worker); + client + .environments() + .work() + .update( + e.id(), + item.id(), + WorkUpdateParams.builder() + .metadata(Collections.singletonMap("sdk_contract", name)) + .build(), + worker); + check( + client.environments().work().retrieve(e.id(), item.id()).id().equals(item.id()), + "Work retrieval mismatch"); + client.environments().work().list(e.id()); + client.environments().work().stats(e.id()); + client + .environments() + .work() + .stop(e.id(), item.id(), WorkStopParams.builder().force(true).build(), worker); + } + + private void closeSession(String id) { + Session s = client.sessions().retrieve(id); + if (!Arrays.asList("idle", "terminated").contains(s.status())) + client.sessions().cancel(id, options("cleanup-cancel-" + id)); + client.sessions().delete(id, options("cleanup-delete-" + id)); + } + + private static void check(boolean condition, String message) { + if (!condition) throw new IllegalStateException(message); + } +} diff --git a/examples/src/test/java/com/qoder/cloudagents/examples/ManagedConsumerTest.java b/examples/src/test/java/com/qoder/cloudagents/examples/ManagedConsumerTest.java new file mode 100644 index 0000000..b77dd17 --- /dev/null +++ b/examples/src/test/java/com/qoder/cloudagents/examples/ManagedConsumerTest.java @@ -0,0 +1,114 @@ +package com.qoder.cloudagents.examples; + +import static org.junit.jupiter.api.Assertions.*; + +import com.qoder.cloudagents.ManagedClient; +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.managed.*; +import java.io.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import okhttp3.mockwebserver.*; +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@Timeout(15) +class ManagedConsumerTest { + @Test + void compiledConsumerUsesJarAndCreatesBudgetedSession() throws Exception { + assertTrue( + ManagedClient.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toString() + .endsWith(".jar")); + try (MockWebServer server = new MockWebServer()) { + server.start(); + server.enqueue( + new MockResponse().setBody("{\"id\":\"sess_test\",\"usage\":{\"total_credits\":0.25}}")); + try (ManagedClient c = + ManagedClient.builder() + .pat("test-pat") + .baseUrl(server.url("/api/v1/cloud").toString()) + .build()) { + Session s = + c.sessions() + .create( + SessionCreateParams.builder() + .agent("agent_test") + .environmentId("env_test") + .budget( + SessionBudget.builder().type("limit").maxCreditCost("10.00").build()) + .build()); + assertEquals("sess_test", s.id()); + assertEquals("0.25", s.usage().totalCredits().toPlainString()); + RecordedRequest r = server.takeRequest(2, TimeUnit.SECONDS); + JsonValue body = JsonValue.parse(r.getBody().readUtf8()); + assertEquals("10.00", body.get("budget").get("max_credit_cost").asString()); + assertEquals("java", body.get("metadata").get("__qca_sdk_language").asString()); + } + } + } + + @Test + void readOnlyLiveEntryExercisesManagedResourcesThroughTheJar() throws Exception { + try (MockWebServer server = new MockWebServer()) { + server.start(); + for (int i = 0; i < 11; i++) + server.enqueue( + new MockResponse() + .setHeader("X-Request-ID", "req_live") + .setBody( + i == 0 + ? "{\"data\":[{\"id\":\"auto\"}]}" + : "{\"data\":[],\"has_more\":false}")); + try (ManagedClient c = + ManagedClient.builder() + .pat("test-pat") + .baseUrl(server.url("/api/v1/cloud").toString()) + .maxRetries(0) + .build()) { + ByteArrayOutputStream log = new ByteArrayOutputStream(); + new ManagedLiveCheck(c, "auto", new PrintStream(log)).run("read"); + assertTrue(log.toString("UTF-8").contains("passed=read")); + assertEquals(11, server.getRequestCount()); + for (int i = 0; i < 11; i++) { + RecordedRequest r = server.takeRequest(); + assertTrue(r.getPath().startsWith("/api/v1/cloud/")); + if (r.getPath().endsWith("/search")) + assertEquals("search-2026-08-31", r.getHeader("x-qoder-beta")); + } + } + } + } + + @ParameterizedTest + @ValueSource(strings = {"resources", "session", "deployment", "work"}) + void liveWritesRequireExplicitOptIn(String group) { + Map env = new HashMap<>(); + env.put("QODER_RUN_LIVE", "true"); + assertThrows(IllegalStateException.class, () -> ManagedLiveCheck.validate(group, env)); + env.put("QODER_ALLOW_WRITE", "true"); + if (!group.equals("resources")) + assertThrows(IllegalStateException.class, () -> ManagedLiveCheck.validate(group, env)); + env.put("QODER_ALLOW_EXECUTION", "true"); + assertDoesNotThrow(() -> ManagedLiveCheck.validate(group, env)); + } + + @Test + void liveReadRequiresOptInAndRejectsUnknownGroups() { + assertThrows( + IllegalStateException.class, + () -> ManagedLiveCheck.validate("read", Collections.emptyMap())); + assertThrows( + IllegalStateException.class, + () -> + ManagedLiveCheck.validate( + "delete-all", Collections.singletonMap("QODER_RUN_LIVE", "true"))); + assertDoesNotThrow( + () -> + ManagedLiveCheck.validate("read", Collections.singletonMap("QODER_RUN_LIVE", "true"))); + } +} diff --git a/src/main/java/com/qoder/cloudagents/AsyncManagedClient.java b/src/main/java/com/qoder/cloudagents/AsyncManagedClient.java new file mode 100644 index 0000000..8a548e5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/AsyncManagedClient.java @@ -0,0 +1,125 @@ +package com.qoder.cloudagents; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.ClientEngine; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.managed.*; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +/** Thread-safe Managed API client. Close owned clients after use. */ +public final class AsyncManagedClient implements AutoCloseable { + private final ClientEngine engine; + private final ManagedClient.Builder configuration; + private final boolean ownsEngine; + private final AsyncAgents agents; + private final AsyncDeployments deployments; + private final AsyncDeploymentRuns deploymentRuns; + private final AsyncSessions sessions; + private final AsyncEnvironments environments; + private final AsyncFiles files; + private final AsyncSkills skills; + private final AsyncVaults vaults; + private final AsyncOAuth oauth; + private final AsyncMemoryStores memoryStores; + private final AsyncModels models; + private final AsyncDreams dreams; + + AsyncManagedClient(ClientEngine engine, boolean ownsEngine, ManagedClient.Builder configuration) { + this.engine = engine; + this.configuration = configuration; + this.ownsEngine = ownsEngine; + agents = new AsyncAgents(engine); + deployments = new AsyncDeployments(engine); + deploymentRuns = new AsyncDeploymentRuns(engine); + sessions = new AsyncSessions(engine); + environments = new AsyncEnvironments(engine); + files = new AsyncFiles(engine); + skills = new AsyncSkills(engine); + vaults = new AsyncVaults(engine); + oauth = new AsyncOAuth(engine); + memoryStores = new AsyncMemoryStores(engine); + models = new AsyncModels(engine); + dreams = new AsyncDreams(engine); + } + + public AsyncAgents agents() { + return agents; + } + + public AsyncDeployments deployments() { + return deployments; + } + + public AsyncDeploymentRuns deploymentRuns() { + return deploymentRuns; + } + + public AsyncSessions sessions() { + return sessions; + } + + public AsyncEnvironments environments() { + return environments; + } + + public AsyncFiles files() { + return files; + } + + public AsyncSkills skills() { + return skills; + } + + public AsyncVaults vaults() { + return vaults; + } + + public AsyncOAuth oauth() { + return oauth; + } + + public AsyncMemoryStores memoryStores() { + return memoryStores; + } + + public AsyncModels models() { + return models; + } + + public AsyncDreams dreams() { + return dreams; + } + + public static ManagedClient.Builder builder() { + return ManagedClient.builder(); + } + + /** Creates an independently owned async client; the original client is unchanged. */ + public AsyncManagedClient withOptions(Consumer configure) { + if (configure == null) + throw new ConfigurationException("Configuration callback must not be null"); + ManagedClient.Builder copy = configuration.copy(); + configure.accept(copy); + return copy.buildAsync(); + } + + public CompletableFuture> request(ApiRequest request) { + return request(request, RequestOptions.DEFAULT); + } + + /** The returned future directly owns cancellation of the underlying operation. */ + public CompletableFuture> request( + ApiRequest request, RequestOptions options) { + if (request == null || options == null) + throw new ConfigurationException("Request and options must not be null"); + return engine.request( + request.method(), request.path(), Collections.emptyMap(), request.body(), true, options); + } + + @Override + public void close() { + if (ownsEngine) engine.close(); + } +} diff --git a/src/main/java/com/qoder/cloudagents/ManagedClient.java b/src/main/java/com/qoder/cloudagents/ManagedClient.java new file mode 100644 index 0000000..1e39456 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/ManagedClient.java @@ -0,0 +1,306 @@ +package com.qoder.cloudagents; + +import com.qoder.cloudagents.auth.AuthMode; +import com.qoder.cloudagents.auth.Credential; +import com.qoder.cloudagents.core.ApiRequest; +import com.qoder.cloudagents.core.ApiResponse; +import com.qoder.cloudagents.core.JsonValue; +import com.qoder.cloudagents.core.RequestOptions; +import com.qoder.cloudagents.core.http.HttpInterceptor; +import com.qoder.cloudagents.core.http.HttpTransport; +import com.qoder.cloudagents.core.internal.Authentication; +import com.qoder.cloudagents.core.internal.ClientEngine; +import com.qoder.cloudagents.core.internal.Futures; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.managed.*; +import java.time.Duration; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import okhttp3.HttpUrl; + +/** Thread-safe Managed API client. Close owned clients after use. */ +public final class ManagedClient implements AutoCloseable { + private final ClientEngine engine; + private final ManagedClient.Builder configuration; + private final AsyncManagedClient async; + private final Agents agents; + private final Deployments deployments; + private final DeploymentRuns deploymentRuns; + private final Sessions sessions; + private final Environments environments; + private final Files files; + private final Skills skills; + private final Vaults vaults; + private final OAuth oauth; + private final MemoryStores memoryStores; + private final Models models; + private final Dreams dreams; + + private ManagedClient(ClientEngine engine, ManagedClient.Builder configuration) { + this.engine = engine; + this.configuration = configuration; + async = new AsyncManagedClient(engine, false, configuration); + agents = new Agents(async.agents()); + deployments = new Deployments(async.deployments()); + deploymentRuns = new DeploymentRuns(async.deploymentRuns()); + sessions = new Sessions(async.sessions()); + environments = new Environments(async.environments()); + files = new Files(async.files()); + skills = new Skills(async.skills()); + vaults = new Vaults(async.vaults()); + oauth = new OAuth(async.oauth()); + memoryStores = new MemoryStores(async.memoryStores()); + models = new Models(async.models()); + dreams = new Dreams(async.dreams()); + } + + public Agents agents() { + return agents; + } + + public Deployments deployments() { + return deployments; + } + + public DeploymentRuns deploymentRuns() { + return deploymentRuns; + } + + public Sessions sessions() { + return sessions; + } + + public Environments environments() { + return environments; + } + + public Files files() { + return files; + } + + public Skills skills() { + return skills; + } + + public Vaults vaults() { + return vaults; + } + + public OAuth oauth() { + return oauth; + } + + public MemoryStores memoryStores() { + return memoryStores; + } + + public Models models() { + return models; + } + + public Dreams dreams() { + return dreams; + } + + public AsyncManagedClient async() { + return async; + } + + public static Builder builder() { + return new Builder(); + } + + /** Creates an independently closeable client, retaining unspecified resolved options. */ + public ManagedClient withOptions(Consumer configure) { + Builder copy = configuration.copy(); + Builder.required(configure).accept(copy); + return copy.build(); + } + + /** Calls an additional JSON API using the client's authentication, retries and error handling. */ + public ApiResponse request(ApiRequest request) { + return request(request, RequestOptions.DEFAULT); + } + + public ApiResponse request(ApiRequest request, RequestOptions options) { + return Futures.await(async.request(request, options)); + } + + @Override + public void close() { + engine.close(); + } + + public static final class Builder { + private String baseUrl, pat, accessToken; + private AuthMode authMode; + private Credential credential; + private Credential resolvedCredential; + private HttpTransport transport; + private final List interceptors = new ArrayList<>(); + private boolean derived, modeChanged; + private Duration timeout = Duration.ofMinutes(10); + private int maxRetries = 2; + private final Map headers = new LinkedHashMap<>(); + + public Builder baseUrl(String value) { + baseUrl = required(value); + return this; + } + + public Builder authMode(AuthMode value) { + authMode = required(value); + modeChanged = true; + return this; + } + + public Builder pat(String value) { + if (derived) { + credential = null; + accessToken = null; + if (!modeChanged) authMode = AuthMode.PAT; + } + pat = Authentication.validateToken(value); + return this; + } + + public Builder accessToken(String value) { + if (derived) { + credential = null; + pat = null; + } + accessToken = Authentication.validateToken(value); + return this; + } + + public Builder credential(Credential value) { + if (derived) { + pat = null; + accessToken = null; + if (!modeChanged) authMode = null; + } + credential = required(value); + return this; + } + + private static T required(T value) { + if (value == null) + throw new ConfigurationException("Explicit client options must be non-null"); + return value; + } + + public Builder timeout(Duration value) { + RequestOptions.positiveMillis(value); + timeout = value; + return this; + } + + public Builder maxRetries(int value) { + if (value < 0) throw new ConfigurationException("maxRetries must not be negative"); + maxRetries = value; + return this; + } + + public Builder defaultHeader(String name, String value) { + RequestOptions.builder().header(name, value); + headers.keySet().removeIf(key -> key.equalsIgnoreCase(name)); + headers.put(name, value); + return this; + } + + /** Caller-owned transport, also used for isolated storage downloads; not WebSockets. */ + public Builder transport(HttpTransport value) { + transport = required(value); + return this; + } + + /** Appends an API interceptor; storage downloads do not invoke it. */ + public Builder interceptor(HttpInterceptor value) { + interceptors.add(required(value)); + return this; + } + + public Builder clearInterceptors() { + interceptors.clear(); + return this; + } + + public Builder clearDefaultHeaders() { + headers.clear(); + return this; + } + + Builder copy() { + Builder copy = new Builder(); + copy.baseUrl = baseUrl; + copy.pat = pat; + copy.accessToken = accessToken; + copy.authMode = authMode; + copy.credential = credential; + copy.timeout = timeout; + copy.maxRetries = maxRetries; + copy.transport = transport; + copy.headers.putAll(headers); + copy.interceptors.addAll(interceptors); + copy.derived = derived; + return copy; + } + + private Builder resolve() { + String value = baseUrl; + if (value == null) value = System.getenv("QODER_BASE_URL"); + if (value == null || value.isEmpty()) value = "https://api.qoder.com/api/v1/cloud"; + HttpUrl url; + try { + url = HttpUrl.get(value); + } catch (IllegalArgumentException error) { + throw new ConfigurationException("Invalid Managed baseUrl"); + } + if (!url.username().isEmpty() + || !url.password().isEmpty() + || url.query() != null + || url.fragment() != null) + throw new ConfigurationException("baseUrl cannot contain credentials, query or fragment"); + Credential resolved = + Authentication.resolve( + authMode, pat, accessToken, credential, url.host(), System::getenv); + Builder snapshot = copy(); + snapshot.baseUrl = url.toString(); + snapshot.authMode = + authMode != null + ? authMode + : credential instanceof com.qoder.cloudagents.auth.ServiceAccountCredential + ? AuthMode.SA + : AuthMode.PAT; + snapshot.resolvedCredential = resolved; + if (pat == null && accessToken == null) snapshot.credential = resolved; + snapshot.derived = true; + return snapshot; + } + + private ClientEngine engine() { + return new ClientEngine( + HttpUrl.get(baseUrl), + resolvedCredential, + timeout, + maxRetries, + headers, + transport, + interceptors); + } + + public ManagedClient build() { + Builder snapshot = resolve(); + return new ManagedClient(snapshot.engine(), snapshot); + } + + /** Builds an independently owned async client with the same configuration options. */ + public AsyncManagedClient buildAsync() { + Builder snapshot = resolve(); + return new AsyncManagedClient(snapshot.engine(), true, snapshot); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Agent.java b/src/main/java/com/qoder/cloudagents/managed/Agent.java new file mode 100644 index 0000000..ccf020d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Agent.java @@ -0,0 +1,75 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Agent extends JsonModel { + public Agent(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Agent fromJson(JsonValue value) { + return new Agent(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public ModelConfig model() { + return optional("model", ModelConfig::fromJson); + } + + public String system() { + return optional("system", JsonValue::asString); + } + + public List tools() { + return optionalList("tools", Tool::fromJson); + } + + public List mcpServers() { + return optionalList("mcp_servers", MCPServer::fromJson); + } + + public List skills() { + return optionalList("skills", SkillBinding::fromJson); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public MultiagentConfig multiagent() { + return optional("multiagent", MultiagentConfig::fromJson); + } + + public Long version() { + return optional("version", JsonValue::asLong); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentCreateParams.java new file mode 100644 index 0000000..762ab7a --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentCreateParams.java @@ -0,0 +1,105 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class AgentCreateParams extends JsonObject { + private AgentCreateParams(JsonValue value) { + super(value); + } + + public static AgentCreateParams fromJson(JsonValue value) { + return new AgentCreateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public ModelConfig model() { + return optional("model", ModelConfig::fromJson); + } + + public String system() { + return optional("system", JsonValue::asString); + } + + public List tools() { + return optionalList("tools", Tool::fromJson); + } + + public List mcpServers() { + return optionalList("mcp_servers", MCPServer::fromJson); + } + + public List skills() { + return optionalList("skills", SkillBinding::fromJson); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public MultiagentConfig multiagent() { + return optional("multiagent", MultiagentConfig::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder model(ModelConfig value) { + return put("model", value); + } + + public Builder model(String value) { + return put("model", value == null ? null : ModelConfig.of(value)); + } + + public Builder system(String value) { + return put("system", value); + } + + public Builder tools(List value) { + return put("tools", value); + } + + public Builder mcpServers(List value) { + return put("mcp_servers", value); + } + + public Builder skills(List value) { + return put("skills", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder multiagent(MultiagentConfig value) { + return put("multiagent", value); + } + + public AgentCreateParams build() { + require("name", "model"); + + return new AgentCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentListParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentListParams.java new file mode 100644 index 0000000..fa11ac3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentListParams.java @@ -0,0 +1,63 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class AgentListParams { + private final Map query; + + private AgentListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public AgentListParams build() { + return new AgentListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentListResponse.java b/src/main/java/com/qoder/cloudagents/managed/AgentListResponse.java new file mode 100644 index 0000000..2467525 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class AgentListResponse extends CursorPage { + public AgentListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + AgentListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Agent(item, requestId), true); + } + + @Override + protected AgentListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentReference.java b/src/main/java/com/qoder/cloudagents/managed/AgentReference.java new file mode 100644 index 0000000..dc0dda9 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentReference.java @@ -0,0 +1,80 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.*; + +/** An Agent ID or an explicit version reference; preserves the wire representation. */ +public final class AgentReference implements JsonSerializable { + private final JsonValue value; + + private AgentReference(JsonValue value) { + if (value == null || (!value.isString() && !value.isObject())) + throw new ResponseValidationException("Expected an Agent ID or object"); + this.value = value; + } + + public static AgentReference of(String id) { + if (id == null || id.isEmpty()) throw new ConfigurationException("Agent ID must not be empty"); + return new AgentReference(JsonValue.of(id)); + } + + public static AgentReference fromJson(JsonValue value) { + return new AgentReference(value); + } + + public boolean isString() { + return value.isString(); + } + + public String id() { + return isString() ? value.asString() : value.get("id").asString(); + } + + public String type() { + JsonValue v = value.get("type"); + return v.isMissing() || v.isNull() ? null : v.asString(); + } + + public Long version() { + JsonValue v = value.get("version"); + return v.isMissing() || v.isNull() ? null : v.asLong(); + } + + public JsonValue field(String name) { + return value.get(name); + } + + public JsonValue toJsonValue() { + return value; + } + + public String toString() { + return "AgentReference"; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + public Builder id(String value) { + return put("id", value); + } + + public Builder type(String value) { + return put("type", value); + } + + public Builder version(long value) { + if (value < 0) throw new ConfigurationException("version must not be negative"); + return put("version", value); + } + + public AgentReference build() { + require("id", "type"); + if (!"agent".equals(json().get("type").asString())) + throw new ConfigurationException("Reference type must be agent"); + return new AgentReference(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentRetrieveParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentRetrieveParams.java new file mode 100644 index 0000000..f53703b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentRetrieveParams.java @@ -0,0 +1,41 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class AgentRetrieveParams { + private final Map query; + + private AgentRetrieveParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder version(long value) { + if (value <= 0) throw new ConfigurationException("Value must be positive"); + return put("version", String.valueOf(value)); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public AgentRetrieveParams build() { + return new AgentRetrieveParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentSearchParams.java new file mode 100644 index 0000000..00fe704 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentSearchParams.java @@ -0,0 +1,91 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class AgentSearchParams extends JsonObject { + private AgentSearchParams(JsonValue value) { + super(value); + } + + public static AgentSearchParams fromJson(JsonValue value) { + return new AgentSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public String createdAtGte() { + return optional("created_at[gte]", JsonValue::asString); + } + + public String createdAtLte() { + return optional("created_at[lte]", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + public AgentSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new AgentSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentUpdateParams.java new file mode 100644 index 0000000..eaf4686 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentUpdateParams.java @@ -0,0 +1,117 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class AgentUpdateParams extends JsonObject { + private AgentUpdateParams(JsonValue value) { + super(value); + } + + public static AgentUpdateParams fromJson(JsonValue value) { + return new AgentUpdateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public ModelConfig model() { + return optional("model", ModelConfig::fromJson); + } + + public String system() { + return optional("system", JsonValue::asString); + } + + public List tools() { + return optionalList("tools", Tool::fromJson); + } + + public List mcpServers() { + return optionalList("mcp_servers", MCPServer::fromJson); + } + + public List skills() { + return optionalList("skills", SkillBinding::fromJson); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public MultiagentConfig multiagent() { + return optional("multiagent", MultiagentConfig::fromJson); + } + + public Long version() { + return optional("version", JsonValue::asLong); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder model(ModelConfig value) { + return put("model", value); + } + + public Builder model(String value) { + return put("model", value == null ? null : ModelConfig.of(value)); + } + + public Builder system(String value) { + return put("system", value); + } + + public Builder tools(List value) { + return put("tools", value); + } + + public Builder mcpServers(List value) { + return put("mcp_servers", value); + } + + public Builder skills(List value) { + return put("skills", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder multiagent(MultiagentConfig value) { + return put("multiagent", value); + } + + public Builder version(Long value) { + return put("version", value); + } + + public Builder version(long value) { + return version(Long.valueOf(value)); + } + + public AgentUpdateParams build() { + require("version"); + + return new AgentUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentVersionListParams.java b/src/main/java/com/qoder/cloudagents/managed/AgentVersionListParams.java new file mode 100644 index 0000000..28eb33b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentVersionListParams.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class AgentVersionListParams { + private final Map query; + + private AgentVersionListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public AgentVersionListParams build() { + return new AgentVersionListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentVersionListResponse.java b/src/main/java/com/qoder/cloudagents/managed/AgentVersionListResponse.java new file mode 100644 index 0000000..ced1ddd --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentVersionListResponse.java @@ -0,0 +1,28 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class AgentVersionListResponse extends CursorPage { + public AgentVersionListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + AgentVersionListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Agent(item, requestId), true); + } + + @Override + protected AgentVersionListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AgentVersions.java b/src/main/java/com/qoder/cloudagents/managed/AgentVersions.java new file mode 100644 index 0000000..a4daaa6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AgentVersions.java @@ -0,0 +1,54 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class AgentVersions { + private final AsyncAgentVersions async; + + public AgentVersions(AsyncAgentVersions async) { + this.async = async; + } + + public AgentVersionListResponse list(String agentId) { + return list(agentId, AgentVersionListParams.builder().build()); + } + + public AgentVersionListResponse list(String agentId, RequestOptions options) { + return list(agentId, AgentVersionListParams.builder().build(), options); + } + + public AgentVersionListResponse list(String agentId, AgentVersionListParams params) { + return list(agentId, params, RequestOptions.DEFAULT); + } + + public AgentVersionListResponse list( + String agentId, AgentVersionListParams params, RequestOptions options) { + return Futures.await(async.list(agentId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse list(String agentId) { + return list(agentId, AgentVersionListParams.builder().build()); + } + + public ApiResponse list(String agentId, RequestOptions options) { + return list(agentId, AgentVersionListParams.builder().build(), options); + } + + public ApiResponse list( + String agentId, AgentVersionListParams params) { + return list(agentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String agentId, AgentVersionListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(agentId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Agents.java b/src/main/java/com/qoder/cloudagents/managed/Agents.java new file mode 100644 index 0000000..b353864 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Agents.java @@ -0,0 +1,169 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Agents { + private final AsyncAgents async; + + public Agents(AsyncAgents async) { + this.async = async; + } + + public AgentVersions versions() { + return new AgentVersions(async.versions()); + } + + public Agent archive(String agentId) { + return archive(agentId, RequestOptions.DEFAULT); + } + + public Agent archive(String agentId, RequestOptions options) { + return Futures.await(async.archive(agentId, options)); + } + + public Agent create(AgentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Agent create(AgentCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public Agent retrieve(String agentId) { + return retrieve(agentId, AgentRetrieveParams.builder().build()); + } + + public Agent retrieve(String agentId, RequestOptions options) { + return retrieve(agentId, AgentRetrieveParams.builder().build(), options); + } + + public Agent retrieve(String agentId, AgentRetrieveParams params) { + return retrieve(agentId, params, RequestOptions.DEFAULT); + } + + public Agent retrieve(String agentId, AgentRetrieveParams params, RequestOptions options) { + return Futures.await(async.retrieve(agentId, params, options)); + } + + public AgentListResponse list() { + return list(AgentListParams.builder().build()); + } + + public AgentListResponse list(RequestOptions options) { + return list(AgentListParams.builder().build(), options); + } + + public AgentListResponse list(AgentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public AgentListResponse list(AgentListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public AgentListResponse search() { + return search(AgentSearchParams.builder().build()); + } + + public AgentListResponse search(RequestOptions options) { + return search(AgentSearchParams.builder().build(), options); + } + + public AgentListResponse search(AgentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public AgentListResponse search(AgentSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public Agent update(String agentId, AgentUpdateParams params) { + return update(agentId, params, RequestOptions.DEFAULT); + } + + public Agent update(String agentId, AgentUpdateParams params, RequestOptions options) { + return Futures.await(async.update(agentId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String agentId) { + return archive(agentId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String agentId, RequestOptions options) { + return Futures.await(async.withResponse().archive(agentId, options)); + } + + public ApiResponse create(AgentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(AgentCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse retrieve(String agentId) { + return retrieve(agentId, AgentRetrieveParams.builder().build()); + } + + public ApiResponse retrieve(String agentId, RequestOptions options) { + return retrieve(agentId, AgentRetrieveParams.builder().build(), options); + } + + public ApiResponse retrieve(String agentId, AgentRetrieveParams params) { + return retrieve(agentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String agentId, AgentRetrieveParams params, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(agentId, params, options)); + } + + public ApiResponse list() { + return list(AgentListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(AgentListParams.builder().build(), options); + } + + public ApiResponse list(AgentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(AgentListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse search() { + return search(AgentSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(AgentSearchParams.builder().build(), options); + } + + public ApiResponse search(AgentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search(AgentSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse update(String agentId, AgentUpdateParams params) { + return update(agentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String agentId, AgentUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(agentId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncAgentVersions.java b/src/main/java/com/qoder/cloudagents/managed/AsyncAgentVersions.java new file mode 100644 index 0000000..cf27b6d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncAgentVersions.java @@ -0,0 +1,65 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncAgentVersions { + private final ClientEngine engine; + + public AsyncAgentVersions(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list(String agentId) { + return list(agentId, AgentVersionListParams.builder().build()); + } + + public CompletableFuture list(String agentId, RequestOptions options) { + return list(agentId, AgentVersionListParams.builder().build(), options); + } + + public CompletableFuture list( + String agentId, AgentVersionListParams params) { + return list(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String agentId, AgentVersionListParams params, RequestOptions options) { + return Futures.map(withResponse().list(agentId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> list(String agentId) { + return list(agentId, AgentVersionListParams.builder().build()); + } + + public CompletableFuture> list( + String agentId, RequestOptions options) { + return list(agentId, AgentVersionListParams.builder().build(), options); + } + + public CompletableFuture> list( + String agentId, AgentVersionListParams params) { + return list(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String agentId, AgentVersionListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"agents", agentId, "versions"}, + params.query(), + options, + AgentVersionListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncAgents.java b/src/main/java/com/qoder/cloudagents/managed/AsyncAgents.java new file mode 100644 index 0000000..5d4bc73 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncAgents.java @@ -0,0 +1,223 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncAgents { + private final ClientEngine engine; + + public AsyncAgents(ClientEngine engine) { + this.engine = engine; + } + + public AsyncAgentVersions versions() { + return new AsyncAgentVersions(engine); + } + + public CompletableFuture archive(String agentId) { + return archive(agentId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String agentId, RequestOptions options) { + return Futures.map(withResponse().archive(agentId, options), ApiResponse::data); + } + + public CompletableFuture create(AgentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create(AgentCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String agentId) { + return retrieve(agentId, AgentRetrieveParams.builder().build()); + } + + public CompletableFuture retrieve(String agentId, RequestOptions options) { + return retrieve(agentId, AgentRetrieveParams.builder().build(), options); + } + + public CompletableFuture retrieve(String agentId, AgentRetrieveParams params) { + return retrieve(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String agentId, AgentRetrieveParams params, RequestOptions options) { + return Futures.map(withResponse().retrieve(agentId, params, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(AgentListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(AgentListParams.builder().build(), options); + } + + public CompletableFuture list(AgentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list(AgentListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(AgentSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(AgentSearchParams.builder().build(), options); + } + + public CompletableFuture search(AgentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + AgentSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture update(String agentId, AgentUpdateParams params) { + return update(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String agentId, AgentUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(agentId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String agentId) { + return archive(agentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive(String agentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"agents", agentId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Agent(v, r.requestId()))); + } + + public CompletableFuture> create(AgentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + AgentCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"agents"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Agent(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String agentId) { + return retrieve(agentId, AgentRetrieveParams.builder().build()); + } + + public CompletableFuture> retrieve(String agentId, RequestOptions options) { + return retrieve(agentId, AgentRetrieveParams.builder().build(), options); + } + + public CompletableFuture> retrieve( + String agentId, AgentRetrieveParams params) { + return retrieve(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String agentId, AgentRetrieveParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "GET", new String[] {"agents", agentId}, params.query(), null, true, options), + r -> r.map(v -> v.isNull() ? null : new Agent(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(AgentListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(AgentListParams.builder().build(), options); + } + + public CompletableFuture> list(AgentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + AgentListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, new String[] {"agents"}, params.query(), options, AgentListResponse::new); + } + + public CompletableFuture> search() { + return search(AgentSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(AgentSearchParams.builder().build(), options); + } + + public CompletableFuture> search(AgentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + AgentSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"agents", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + AgentListResponse::new); + } + + public CompletableFuture> update(String agentId, AgentUpdateParams params) { + return update(agentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String agentId, AgentUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"agents", agentId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Agent(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentRuns.java b/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentRuns.java new file mode 100644 index 0000000..77e496c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentRuns.java @@ -0,0 +1,89 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncDeploymentRuns { + private final ClientEngine engine; + + public AsyncDeploymentRuns(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture retrieve(String runId) { + return retrieve(runId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String runId, RequestOptions options) { + return Futures.map(withResponse().retrieve(runId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(DeploymentRunListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(DeploymentRunListParams.builder().build(), options); + } + + public CompletableFuture list(DeploymentRunListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + DeploymentRunListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> retrieve(String runId) { + return retrieve(runId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String runId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"deployment_runs", runId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeploymentRun(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(DeploymentRunListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(DeploymentRunListParams.builder().build(), options); + } + + public CompletableFuture> list( + DeploymentRunListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + DeploymentRunListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"deployment_runs"}, + params.query(), + options, + DeploymentRunListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentScopedRuns.java b/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentScopedRuns.java new file mode 100644 index 0000000..3cdc7ee --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncDeploymentScopedRuns.java @@ -0,0 +1,95 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncDeploymentScopedRuns { + private final ClientEngine engine; + + public AsyncDeploymentScopedRuns(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture retrieve(String deploymentId, String runId) { + return retrieve(deploymentId, runId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String deploymentId, String runId, RequestOptions options) { + return Futures.map(withResponse().retrieve(deploymentId, runId, options), ApiResponse::data); + } + + public CompletableFuture list(String deploymentId) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build()); + } + + public CompletableFuture list( + String deploymentId, RequestOptions options) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build(), options); + } + + public CompletableFuture list( + String deploymentId, DeploymentScopedRunListParams params) { + return list(deploymentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String deploymentId, DeploymentScopedRunListParams params, RequestOptions options) { + return Futures.map(withResponse().list(deploymentId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> retrieve( + String deploymentId, String runId) { + return retrieve(deploymentId, runId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String deploymentId, String runId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"deployments", deploymentId, "runs", runId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeploymentRun(v, r.requestId()))); + } + + public CompletableFuture> list( + String deploymentId) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build()); + } + + public CompletableFuture> list( + String deploymentId, RequestOptions options) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build(), options); + } + + public CompletableFuture> list( + String deploymentId, DeploymentScopedRunListParams params) { + return list(deploymentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String deploymentId, DeploymentScopedRunListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"deployments", deploymentId, "runs"}, + params.query(), + options, + DeploymentScopedRunListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncDeployments.java b/src/main/java/com/qoder/cloudagents/managed/AsyncDeployments.java new file mode 100644 index 0000000..7ff8ea5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncDeployments.java @@ -0,0 +1,297 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncDeployments { + private final ClientEngine engine; + + public AsyncDeployments(ClientEngine engine) { + this.engine = engine; + } + + public AsyncDeploymentScopedRuns runs() { + return new AsyncDeploymentScopedRuns(engine); + } + + public CompletableFuture archive(String deploymentId) { + return archive(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String deploymentId, RequestOptions options) { + return Futures.map(withResponse().archive(deploymentId, options), ApiResponse::data); + } + + public CompletableFuture create(DeploymentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + DeploymentCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String deploymentId) { + return retrieve(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String deploymentId, RequestOptions options) { + return Futures.map(withResponse().retrieve(deploymentId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(DeploymentListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(DeploymentListParams.builder().build(), options); + } + + public CompletableFuture list(DeploymentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + DeploymentListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture pause(String deploymentId) { + return pause(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture pause(String deploymentId, RequestOptions options) { + return Futures.map(withResponse().pause(deploymentId, options), ApiResponse::data); + } + + public CompletableFuture run(String deploymentId) { + return run(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture run(String deploymentId, RequestOptions options) { + return Futures.map(withResponse().run(deploymentId, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(DeploymentSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(DeploymentSearchParams.builder().build(), options); + } + + public CompletableFuture search(DeploymentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + DeploymentSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture unpause(String deploymentId) { + return unpause(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture unpause(String deploymentId, RequestOptions options) { + return Futures.map(withResponse().unpause(deploymentId, options), ApiResponse::data); + } + + public CompletableFuture update(String deploymentId, DeploymentUpdateParams params) { + return update(deploymentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String deploymentId, DeploymentUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(deploymentId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String deploymentId) { + return archive(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String deploymentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments", deploymentId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + + public CompletableFuture> create(DeploymentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + DeploymentCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String deploymentId) { + return retrieve(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String deploymentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"deployments", deploymentId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(DeploymentListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(DeploymentListParams.builder().build(), options); + } + + public CompletableFuture> list( + DeploymentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + DeploymentListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"deployments"}, + params.query(), + options, + DeploymentListResponse::new); + } + + public CompletableFuture> pause(String deploymentId) { + return pause(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> pause( + String deploymentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments", deploymentId, "pause"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + + public CompletableFuture> run(String deploymentId) { + return run(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> run( + String deploymentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments", deploymentId, "run"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeploymentRun(v, r.requestId()))); + } + + public CompletableFuture> search() { + return search(DeploymentSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(DeploymentSearchParams.builder().build(), options); + } + + public CompletableFuture> search( + DeploymentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + DeploymentSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"deployments", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + DeploymentListResponse::new); + } + + public CompletableFuture> unpause(String deploymentId) { + return unpause(deploymentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> unpause( + String deploymentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments", deploymentId, "unpause"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + + public CompletableFuture> update( + String deploymentId, DeploymentUpdateParams params) { + return update(deploymentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String deploymentId, DeploymentUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"deployments", deploymentId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Deployment(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncDreams.java b/src/main/java/com/qoder/cloudagents/managed/AsyncDreams.java new file mode 100644 index 0000000..971a584 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncDreams.java @@ -0,0 +1,155 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncDreams { + private final ClientEngine engine; + + public AsyncDreams(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture archive(String dreamId) { + return archive(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String dreamId, RequestOptions options) { + return Futures.map(withResponse().archive(dreamId, options), ApiResponse::data); + } + + public CompletableFuture cancel(String dreamId) { + return cancel(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture cancel(String dreamId, RequestOptions options) { + return Futures.map(withResponse().cancel(dreamId, options), ApiResponse::data); + } + + public CompletableFuture create(DreamCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create(DreamCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String dreamId) { + return retrieve(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String dreamId, RequestOptions options) { + return Futures.map(withResponse().retrieve(dreamId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(DreamListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(DreamListParams.builder().build(), options); + } + + public CompletableFuture list(DreamListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list(DreamListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String dreamId) { + return archive(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive(String dreamId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"dreams", dreamId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Dream(v, r.requestId()))); + } + + public CompletableFuture> cancel(String dreamId) { + return cancel(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture> cancel(String dreamId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"dreams", dreamId, "cancel"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Dream(v, r.requestId()))); + } + + public CompletableFuture> create(DreamCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + DreamCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"dreams"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Dream(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String dreamId) { + return retrieve(dreamId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve(String dreamId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", new String[] {"dreams", dreamId}, Collections.emptyMap(), null, true, options), + r -> r.map(v -> v.isNull() ? null : new Dream(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(DreamListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(DreamListParams.builder().build(), options); + } + + public CompletableFuture> list(DreamListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + DreamListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request("GET", new String[] {"dreams"}, params.query(), null, true, options), + r -> r.map(v -> v.isNull() ? null : new DreamListResponse(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironmentWork.java b/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironmentWork.java new file mode 100644 index 0000000..a7930c3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironmentWork.java @@ -0,0 +1,320 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncEnvironmentWork { + private final ClientEngine engine; + + public AsyncEnvironmentWork(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture ack(String environmentId, String workId) { + return ack(environmentId, workId, RequestOptions.DEFAULT); + } + + public CompletableFuture ack( + String environmentId, String workId, RequestOptions options) { + return Futures.map(withResponse().ack(environmentId, workId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String environmentId, String workId) { + return retrieve(environmentId, workId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String environmentId, String workId, RequestOptions options) { + return Futures.map(withResponse().retrieve(environmentId, workId, options), ApiResponse::data); + } + + public CompletableFuture heartbeat(String environmentId, String workId) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build()); + } + + public CompletableFuture heartbeat( + String environmentId, String workId, RequestOptions options) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build(), options); + } + + public CompletableFuture heartbeat( + String environmentId, String workId, WorkHeartbeatParams params) { + return heartbeat(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture heartbeat( + String environmentId, String workId, WorkHeartbeatParams params, RequestOptions options) { + return Futures.map( + withResponse().heartbeat(environmentId, workId, params, options), ApiResponse::data); + } + + public CompletableFuture list(String environmentId) { + return list(environmentId, WorkListParams.builder().build()); + } + + public CompletableFuture list(String environmentId, RequestOptions options) { + return list(environmentId, WorkListParams.builder().build(), options); + } + + public CompletableFuture list(String environmentId, WorkListParams params) { + return list(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String environmentId, WorkListParams params, RequestOptions options) { + return Futures.map(withResponse().list(environmentId, params, options), ApiResponse::data); + } + + public CompletableFuture poll(String environmentId) { + return poll(environmentId, WorkPollParams.builder().build()); + } + + public CompletableFuture poll(String environmentId, RequestOptions options) { + return poll(environmentId, WorkPollParams.builder().build(), options); + } + + public CompletableFuture poll(String environmentId, WorkPollParams params) { + return poll(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture poll( + String environmentId, WorkPollParams params, RequestOptions options) { + return Futures.map(withResponse().poll(environmentId, params, options), ApiResponse::data); + } + + public CompletableFuture stats(String environmentId) { + return stats(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture stats(String environmentId, RequestOptions options) { + return Futures.map(withResponse().stats(environmentId, options), ApiResponse::data); + } + + public CompletableFuture stop(String environmentId, String workId) { + return stop(environmentId, workId, WorkStopParams.builder().build()); + } + + public CompletableFuture stop( + String environmentId, String workId, RequestOptions options) { + return stop(environmentId, workId, WorkStopParams.builder().build(), options); + } + + public CompletableFuture stop( + String environmentId, String workId, WorkStopParams params) { + return stop(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture stop( + String environmentId, String workId, WorkStopParams params, RequestOptions options) { + return Futures.map( + withResponse().stop(environmentId, workId, params, options), ApiResponse::data); + } + + public CompletableFuture update( + String environmentId, String workId, WorkUpdateParams params) { + return update(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String environmentId, String workId, WorkUpdateParams params, RequestOptions options) { + return Futures.map( + withResponse().update(environmentId, workId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> ack(String environmentId, String workId) { + return ack(environmentId, workId, RequestOptions.DEFAULT); + } + + public CompletableFuture> ack( + String environmentId, String workId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId, "work", workId, "ack"}, + Collections.emptyMap(), + null, + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new WorkItem(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String environmentId, String workId) { + return retrieve(environmentId, workId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String environmentId, String workId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"environments", environmentId, "work", workId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new WorkItem(v, r.requestId()))); + } + + public CompletableFuture> heartbeat( + String environmentId, String workId) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build()); + } + + public CompletableFuture> heartbeat( + String environmentId, String workId, RequestOptions options) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build(), options); + } + + public CompletableFuture> heartbeat( + String environmentId, String workId, WorkHeartbeatParams params) { + return heartbeat(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> heartbeat( + String environmentId, String workId, WorkHeartbeatParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId, "work", workId, "heartbeat"}, + params.query(), + null, + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new WorkHeartbeat(v, r.requestId()))); + } + + public CompletableFuture> list(String environmentId) { + return list(environmentId, WorkListParams.builder().build()); + } + + public CompletableFuture> list( + String environmentId, RequestOptions options) { + return list(environmentId, WorkListParams.builder().build(), options); + } + + public CompletableFuture> list( + String environmentId, WorkListParams params) { + return list(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String environmentId, WorkListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"environments", environmentId, "work"}, + params.query(), + options, + WorkListResponse::new); + } + + public CompletableFuture> poll(String environmentId) { + return poll(environmentId, WorkPollParams.builder().build()); + } + + public CompletableFuture> poll( + String environmentId, RequestOptions options) { + return poll(environmentId, WorkPollParams.builder().build(), options); + } + + public CompletableFuture> poll( + String environmentId, WorkPollParams params) { + return poll(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> poll( + String environmentId, WorkPollParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "GET", + new String[] {"environments", environmentId, "work", "poll"}, + params.query(), + null, + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new WorkItem(v, r.requestId()))); + } + + public CompletableFuture> stats(String environmentId) { + return stats(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> stats( + String environmentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"environments", environmentId, "work", "stats"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new WorkQueueStats(v, r.requestId()))); + } + + public CompletableFuture> stop(String environmentId, String workId) { + return stop(environmentId, workId, WorkStopParams.builder().build()); + } + + public CompletableFuture> stop( + String environmentId, String workId, RequestOptions options) { + return stop(environmentId, workId, WorkStopParams.builder().build(), options); + } + + public CompletableFuture> stop( + String environmentId, String workId, WorkStopParams params) { + return stop(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> stop( + String environmentId, String workId, WorkStopParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId, "work", workId, "stop"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new WorkItem(v, r.requestId()))); + } + + public CompletableFuture> update( + String environmentId, String workId, WorkUpdateParams params) { + return update(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String environmentId, String workId, WorkUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId, "work", workId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new WorkItem(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironments.java b/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironments.java new file mode 100644 index 0000000..c8d6faf --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncEnvironments.java @@ -0,0 +1,247 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncEnvironments { + private final ClientEngine engine; + + public AsyncEnvironments(ClientEngine engine) { + this.engine = engine; + } + + public AsyncEnvironmentWork work() { + return new AsyncEnvironmentWork(engine); + } + + public CompletableFuture archive(String environmentId) { + return archive(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String environmentId, RequestOptions options) { + return Futures.map(withResponse().archive(environmentId, options), ApiResponse::data); + } + + public CompletableFuture create(EnvironmentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + EnvironmentCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture delete(String environmentId) { + return delete(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String environmentId, RequestOptions options) { + return Futures.map(withResponse().delete(environmentId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String environmentId) { + return retrieve(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String environmentId, RequestOptions options) { + return Futures.map(withResponse().retrieve(environmentId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(EnvironmentListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(EnvironmentListParams.builder().build(), options); + } + + public CompletableFuture list(EnvironmentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + EnvironmentListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(EnvironmentSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(EnvironmentSearchParams.builder().build(), options); + } + + public CompletableFuture search(EnvironmentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + EnvironmentSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture update( + String environmentId, EnvironmentUpdateParams params) { + return update(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String environmentId, EnvironmentUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(environmentId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String environmentId) { + return archive(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String environmentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Environment(v, r.requestId()))); + } + + public CompletableFuture> create(EnvironmentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + EnvironmentCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Environment(v, r.requestId()))); + } + + public CompletableFuture> delete(String environmentId) { + return delete(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String environmentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"environments", environmentId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedEnvironment(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String environmentId) { + return retrieve(environmentId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String environmentId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"environments", environmentId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Environment(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(EnvironmentListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(EnvironmentListParams.builder().build(), options); + } + + public CompletableFuture> list( + EnvironmentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + EnvironmentListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"environments"}, + params.query(), + options, + EnvironmentListResponse::new); + } + + public CompletableFuture> search() { + return search(EnvironmentSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(EnvironmentSearchParams.builder().build(), options); + } + + public CompletableFuture> search( + EnvironmentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + EnvironmentSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"environments", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + EnvironmentListResponse::new); + } + + public CompletableFuture> update( + String environmentId, EnvironmentUpdateParams params) { + return update(environmentId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String environmentId, EnvironmentUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"environments", environmentId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Environment(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncFiles.java b/src/main/java/com/qoder/cloudagents/managed/AsyncFiles.java new file mode 100644 index 0000000..6b566ac --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncFiles.java @@ -0,0 +1,214 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; + +public final class AsyncFiles { + private final ClientEngine engine; + + public AsyncFiles(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list() { + return list(FileListParams.builder().build()); + } + + public CompletableFuture list(FileListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list(FileListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture upload(FileUploadParams params) { + return upload(params, RequestOptions.DEFAULT); + } + + public CompletableFuture upload(FileUploadParams params, RequestOptions options) { + return Futures.map(withResponse().upload(params, options), ApiResponse::data); + } + + public CompletableFuture getMetadata(String fileId) { + return getMetadata(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture getMetadata(String fileId, RequestOptions options) { + return Futures.map(withResponse().getMetadata(fileId, options), ApiResponse::data); + } + + public CompletableFuture delete(String fileId) { + return delete(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete(String fileId, RequestOptions options) { + return Futures.map(withResponse().delete(fileId, options), ApiResponse::data); + } + + public CompletableFuture getDownloadUrl(String fileId) { + return getDownloadUrl(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture getDownloadUrl(String fileId, RequestOptions options) { + return Futures.map(withResponse().getDownloadUrl(fileId, options), ApiResponse::data); + } + + public CompletableFuture download(String fileId) { + return download(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture download(String fileId, RequestOptions options) { + return Futures.mapOwned( + withResponse().download(fileId, options), ApiResponse::data, r -> r.data().close()); + } + + public CompletableFuture search(FileSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + FileSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(FileSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(FileSearchParams.builder().build(), options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> search() { + return search(FileSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(FileSearchParams.builder().build(), options); + } + + public CompletableFuture> search(FileSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + FileSearchParams params, RequestOptions options) { + if (options == null || params == null) + throw new ConfigurationException("Request parameters and options must not be null"); + return SearchRequests.search( + engine, + new String[] {"files", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + FileListResponse::new); + } + + public CompletableFuture> list() { + return list(FileListParams.builder().build()); + } + + public CompletableFuture> list(FileListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + FileListParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("List parameters are required"); + return CursorRequests.list( + engine, new String[] {"files"}, params.query(), options, FileListResponse::new); + } + + public CompletableFuture> upload(FileUploadParams params) { + return upload(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> upload( + FileUploadParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Upload parameters are required"); + Uploads upload = + new Uploads( + Collections.singletonMap("file", Collections.singletonList(params.file())), + params.fields()); + try { + CompletableFuture> pending = + engine.requestBody( + "POST", + new String[] {"files"}, + Collections.emptyMap(), + upload.body(), + upload.replayable(), + options); + pending.whenComplete((v, e) -> upload.close()); + return Futures.map(pending, r -> r.map(v -> new FileMetadata(v, r.requestId()))); + } catch (RuntimeException e) { + upload.close(); + throw e; + } + } + + public CompletableFuture> getMetadata(String fileId) { + return getMetadata(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture> getMetadata( + String fileId, RequestOptions options) { + return Futures.map( + engine.request( + "GET", new String[] {"files", fileId}, Collections.emptyMap(), null, true, options), + r -> r.map(v -> new FileMetadata(v, r.requestId()))); + } + + public CompletableFuture> delete(String fileId) { + return delete(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String fileId, RequestOptions options) { + return Futures.map( + engine.request( + "DELETE", + new String[] {"files", fileId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedFile(v, r.requestId()))); + } + + public CompletableFuture> getDownloadUrl(String fileId) { + return getDownloadUrl(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture> getDownloadUrl( + String fileId, RequestOptions options) { + return Futures.map( + engine.request( + "GET", + new String[] {"files", fileId, "content"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> new FileDownloadUrl(v, r.requestId()))); + } + + public CompletableFuture> download(String fileId) { + return download(fileId, RequestOptions.DEFAULT); + } + + public CompletableFuture> download( + String fileId, RequestOptions options) { + return engine.download(new String[] {"files", fileId, "content"}, options); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncMemories.java b/src/main/java/com/qoder/cloudagents/managed/AsyncMemories.java new file mode 100644 index 0000000..4088e1d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncMemories.java @@ -0,0 +1,183 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncMemories { + private final ClientEngine engine; + + public AsyncMemories(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture create(String memoryStoreId, MemoryCreateParams params) { + return create(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + String memoryStoreId, MemoryCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(memoryStoreId, params, options), ApiResponse::data); + } + + public CompletableFuture delete(String memoryStoreId, String memoryId) { + return delete(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.map(withResponse().delete(memoryStoreId, memoryId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String memoryStoreId, String memoryId) { + return retrieve(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.map( + withResponse().retrieve(memoryStoreId, memoryId, options), ApiResponse::data); + } + + public CompletableFuture list(String memoryStoreId) { + return list(memoryStoreId, MemoryListParams.builder().build()); + } + + public CompletableFuture list(String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryListParams.builder().build(), options); + } + + public CompletableFuture list(String memoryStoreId, MemoryListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String memoryStoreId, MemoryListParams params, RequestOptions options) { + return Futures.map(withResponse().list(memoryStoreId, params, options), ApiResponse::data); + } + + public CompletableFuture update( + String memoryStoreId, String memoryId, MemoryUpdateParams params) { + return update(memoryStoreId, memoryId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String memoryStoreId, String memoryId, MemoryUpdateParams params, RequestOptions options) { + return Futures.map( + withResponse().update(memoryStoreId, memoryId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> create( + String memoryStoreId, MemoryCreateParams params) { + return create(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + String memoryStoreId, MemoryCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"memory_stores", memoryStoreId, "memories"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Memory(v, r.requestId()))); + } + + public CompletableFuture> delete( + String memoryStoreId, String memoryId) { + return delete(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String memoryStoreId, String memoryId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"memory_stores", memoryStoreId, "memories", memoryId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedMemory(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String memoryStoreId, String memoryId) { + return retrieve(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String memoryStoreId, String memoryId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"memory_stores", memoryStoreId, "memories", memoryId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Memory(v, r.requestId()))); + } + + public CompletableFuture> list(String memoryStoreId) { + return list(memoryStoreId, MemoryListParams.builder().build()); + } + + public CompletableFuture> list( + String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryListParams.builder().build(), options); + } + + public CompletableFuture> list( + String memoryStoreId, MemoryListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String memoryStoreId, MemoryListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "GET", + new String[] {"memory_stores", memoryStoreId, "memories"}, + params.query(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryListResponse(v, r.requestId()))); + } + + public CompletableFuture> update( + String memoryStoreId, String memoryId, MemoryUpdateParams params) { + return update(memoryStoreId, memoryId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String memoryStoreId, String memoryId, MemoryUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"memory_stores", memoryStoreId, "memories", memoryId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Memory(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryStores.java b/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryStores.java new file mode 100644 index 0000000..e23e425 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryStores.java @@ -0,0 +1,251 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncMemoryStores { + private final ClientEngine engine; + + public AsyncMemoryStores(ClientEngine engine) { + this.engine = engine; + } + + public AsyncMemories memories() { + return new AsyncMemories(engine); + } + + public AsyncMemoryVersions versions() { + return new AsyncMemoryVersions(engine); + } + + public CompletableFuture archive(String memoryStoreId) { + return archive(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String memoryStoreId, RequestOptions options) { + return Futures.map(withResponse().archive(memoryStoreId, options), ApiResponse::data); + } + + public CompletableFuture create(MemoryStoreCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + MemoryStoreCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture delete(String memoryStoreId) { + return delete(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String memoryStoreId, RequestOptions options) { + return Futures.map(withResponse().delete(memoryStoreId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String memoryStoreId) { + return retrieve(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String memoryStoreId, RequestOptions options) { + return Futures.map(withResponse().retrieve(memoryStoreId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(MemoryStoreListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(MemoryStoreListParams.builder().build(), options); + } + + public CompletableFuture list(MemoryStoreListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + MemoryStoreListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(MemoryStoreSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(MemoryStoreSearchParams.builder().build(), options); + } + + public CompletableFuture search(MemoryStoreSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + MemoryStoreSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture update( + String memoryStoreId, MemoryStoreUpdateParams params) { + return update(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String memoryStoreId, MemoryStoreUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(memoryStoreId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String memoryStoreId) { + return archive(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String memoryStoreId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"memory_stores", memoryStoreId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryStore(v, r.requestId()))); + } + + public CompletableFuture> create(MemoryStoreCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + MemoryStoreCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"memory_stores"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryStore(v, r.requestId()))); + } + + public CompletableFuture> delete(String memoryStoreId) { + return delete(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String memoryStoreId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"memory_stores", memoryStoreId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedMemoryStore(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String memoryStoreId) { + return retrieve(memoryStoreId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String memoryStoreId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"memory_stores", memoryStoreId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryStore(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(MemoryStoreListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(MemoryStoreListParams.builder().build(), options); + } + + public CompletableFuture> list( + MemoryStoreListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + MemoryStoreListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"memory_stores"}, + params.query(), + options, + MemoryStoreListResponse::new); + } + + public CompletableFuture> search() { + return search(MemoryStoreSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(MemoryStoreSearchParams.builder().build(), options); + } + + public CompletableFuture> search( + MemoryStoreSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + MemoryStoreSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"memory_stores", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + MemoryStoreListResponse::new); + } + + public CompletableFuture> update( + String memoryStoreId, MemoryStoreUpdateParams params) { + return update(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String memoryStoreId, MemoryStoreUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"memory_stores", memoryStoreId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryStore(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryVersions.java b/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryVersions.java new file mode 100644 index 0000000..e0712eb --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncMemoryVersions.java @@ -0,0 +1,129 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncMemoryVersions { + private final ClientEngine engine; + + public AsyncMemoryVersions(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture retrieve(String memoryStoreId, String memoryVersionId) { + return retrieve(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.map( + withResponse().retrieve(memoryStoreId, memoryVersionId, options), ApiResponse::data); + } + + public CompletableFuture list(String memoryStoreId) { + return list(memoryStoreId, MemoryVersionListParams.builder().build()); + } + + public CompletableFuture list( + String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryVersionListParams.builder().build(), options); + } + + public CompletableFuture list( + String memoryStoreId, MemoryVersionListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String memoryStoreId, MemoryVersionListParams params, RequestOptions options) { + return Futures.map(withResponse().list(memoryStoreId, params, options), ApiResponse::data); + } + + public CompletableFuture redact(String memoryStoreId, String memoryVersionId) { + return redact(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public CompletableFuture redact( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.map( + withResponse().redact(memoryStoreId, memoryVersionId, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> retrieve( + String memoryStoreId, String memoryVersionId) { + return retrieve(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"memory_stores", memoryStoreId, "memory_versions", memoryVersionId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryVersion(v, r.requestId()))); + } + + public CompletableFuture> list(String memoryStoreId) { + return list(memoryStoreId, MemoryVersionListParams.builder().build()); + } + + public CompletableFuture> list( + String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryVersionListParams.builder().build(), options); + } + + public CompletableFuture> list( + String memoryStoreId, MemoryVersionListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String memoryStoreId, MemoryVersionListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "GET", + new String[] {"memory_stores", memoryStoreId, "memory_versions"}, + params.query(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryVersionListResponse(v, r.requestId()))); + } + + public CompletableFuture> redact( + String memoryStoreId, String memoryVersionId) { + return redact(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> redact( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] { + "memory_stores", memoryStoreId, "memory_versions", memoryVersionId, "redact" + }, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new MemoryVersion(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncModels.java b/src/main/java/com/qoder/cloudagents/managed/AsyncModels.java new file mode 100644 index 0000000..f4edfa0 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncModels.java @@ -0,0 +1,41 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncModels { + private final ClientEngine engine; + + public AsyncModels(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list() { + return list(RequestOptions.DEFAULT); + } + + public CompletableFuture list(RequestOptions options) { + return Futures.map(withResponse().list(options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> list() { + return list(RequestOptions.DEFAULT); + } + + public CompletableFuture> list(RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", new String[] {"models"}, Collections.emptyMap(), null, true, options), + r -> r.map(v -> v.isNull() ? null : new ModelListResponse(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncOAuth.java b/src/main/java/com/qoder/cloudagents/managed/AsyncOAuth.java new file mode 100644 index 0000000..9df5b49 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncOAuth.java @@ -0,0 +1,49 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncOAuth { + private final ClientEngine engine; + + public AsyncOAuth(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture start(OAuthStartParams params) { + return start(params, RequestOptions.DEFAULT); + } + + public CompletableFuture start( + OAuthStartParams params, RequestOptions options) { + return Futures.map(withResponse().start(params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> start(OAuthStartParams params) { + return start(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> start( + OAuthStartParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"oauth", "start"}, + Collections.emptyMap(), + params.toJsonValue(), + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new OAuthStartResponse(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSessionEvents.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionEvents.java new file mode 100644 index 0000000..9e05520 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionEvents.java @@ -0,0 +1,133 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.streaming.EventStream; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSessionEvents { + private final ClientEngine engine; + + public AsyncSessionEvents(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list(String sessionId) { + return list(sessionId, SessionEventListParams.builder().build()); + } + + public CompletableFuture list( + String sessionId, SessionEventListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String sessionId, SessionEventListParams params, RequestOptions options) { + return Futures.map(withResponse().list(sessionId, params, options), ApiResponse::data); + } + + public CompletableFuture send( + String sessionId, SessionEventSendParams params) { + return send(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture send( + String sessionId, SessionEventSendParams params, RequestOptions options) { + return Futures.map(withResponse().send(sessionId, params, options), ApiResponse::data); + } + + /** Opens one SSE connection. Close the returned stream after consumption. */ + public CompletableFuture> streamEvents(String sessionId) { + return streamEvents(sessionId, SessionEventStreamParams.builder().build()); + } + + public CompletableFuture> streamEvents( + String sessionId, SessionEventStreamParams params) { + return streamEvents(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> streamEvents( + String sessionId, SessionEventStreamParams params, RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return SessionStreams.create( + engine, + new String[] {"sessions", sessionId, "events", "stream"}, + params.query(), + params.lastEventId(), + options, + false, + false) + .openAsync(); + } + + /** Lazy, explicitly reconnecting subscription. It never resends user input. */ + public EventStream resumableStream(String sessionId) { + return resumableStream(sessionId, SessionEventStreamParams.builder().build()); + } + + public EventStream resumableStream( + String sessionId, SessionEventStreamParams params) { + return resumableStream(sessionId, params, RequestOptions.DEFAULT); + } + + public EventStream resumableStream( + String sessionId, SessionEventStreamParams params, RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return SessionStreams.create( + engine, + new String[] {"sessions", sessionId, "events", "stream"}, + params.query(), + params.lastEventId(), + options, + true, + false); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> list(String sessionId) { + return list(sessionId, SessionEventListParams.builder().build()); + } + + public CompletableFuture> list( + String sessionId, SessionEventListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String sessionId, SessionEventListParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters must not be null"); + return CursorRequests.list( + engine, + new String[] {"sessions", sessionId, "events"}, + params.query(), + options, + SessionEventListResponse::new); + } + + public CompletableFuture> send( + String sessionId, SessionEventSendParams params) { + return send(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> send( + String sessionId, SessionEventSendParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "events"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + response -> + response.map(value -> new SessionEventSendResponse(value, response.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSessionResources.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionResources.java new file mode 100644 index 0000000..f88aacc --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionResources.java @@ -0,0 +1,189 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSessionResources { + private final ClientEngine engine; + + public AsyncSessionResources(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture create( + String sessionId, SessionResourceCreateParams params) { + return create(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + String sessionId, SessionResourceCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(sessionId, params, options), ApiResponse::data); + } + + public CompletableFuture delete(String sessionId, String resourceId) { + return delete(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String sessionId, String resourceId, RequestOptions options) { + return Futures.map(withResponse().delete(sessionId, resourceId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String sessionId, String resourceId) { + return retrieve(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String sessionId, String resourceId, RequestOptions options) { + return Futures.map(withResponse().retrieve(sessionId, resourceId, options), ApiResponse::data); + } + + public CompletableFuture list(String sessionId) { + return list(sessionId, SessionResourceListParams.builder().build()); + } + + public CompletableFuture list( + String sessionId, RequestOptions options) { + return list(sessionId, SessionResourceListParams.builder().build(), options); + } + + public CompletableFuture list( + String sessionId, SessionResourceListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String sessionId, SessionResourceListParams params, RequestOptions options) { + return Futures.map(withResponse().list(sessionId, params, options), ApiResponse::data); + } + + public CompletableFuture update( + String sessionId, String resourceId, SessionResourceUpdateParams params) { + return update(sessionId, resourceId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String sessionId, + String resourceId, + SessionResourceUpdateParams params, + RequestOptions options) { + return Futures.map( + withResponse().update(sessionId, resourceId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> create( + String sessionId, SessionResourceCreateParams params) { + return create(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + String sessionId, SessionResourceCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "resources"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new SessionResource(v, r.requestId()))); + } + + public CompletableFuture> delete( + String sessionId, String resourceId) { + return delete(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String sessionId, String resourceId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"sessions", sessionId, "resources", resourceId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedSessionResource(v, r.requestId()))); + } + + public CompletableFuture> retrieve( + String sessionId, String resourceId) { + return retrieve(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String sessionId, String resourceId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"sessions", sessionId, "resources", resourceId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new SessionResource(v, r.requestId()))); + } + + public CompletableFuture> list(String sessionId) { + return list(sessionId, SessionResourceListParams.builder().build()); + } + + public CompletableFuture> list( + String sessionId, RequestOptions options) { + return list(sessionId, SessionResourceListParams.builder().build(), options); + } + + public CompletableFuture> list( + String sessionId, SessionResourceListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String sessionId, SessionResourceListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"sessions", sessionId, "resources"}, + params.query(), + options, + SessionResourceListResponse::new); + } + + public CompletableFuture> update( + String sessionId, String resourceId, SessionResourceUpdateParams params) { + return update(sessionId, resourceId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String sessionId, + String resourceId, + SessionResourceUpdateParams params, + RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "resources", resourceId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new SessionResource(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreadEvents.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreadEvents.java new file mode 100644 index 0000000..913840b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreadEvents.java @@ -0,0 +1,118 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.streaming.EventStream; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSessionThreadEvents { + private final ClientEngine engine; + + public AsyncSessionThreadEvents(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list(String sessionId, String threadId) { + return list(sessionId, threadId, SessionThreadEventListParams.builder().build()); + } + + public CompletableFuture list( + String sessionId, String threadId, SessionThreadEventListParams params) { + return list(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String sessionId, + String threadId, + SessionThreadEventListParams params, + RequestOptions options) { + return Futures.map( + withResponse().list(sessionId, threadId, params, options), ApiResponse::data); + } + + /** Opens one SSE connection. Close the returned stream after consumption. */ + public CompletableFuture> streamEvents( + String sessionId, String threadId) { + return streamEvents(sessionId, threadId, SessionThreadEventStreamParams.builder().build()); + } + + public CompletableFuture> streamEvents( + String sessionId, String threadId, SessionThreadEventStreamParams params) { + return streamEvents(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> streamEvents( + String sessionId, + String threadId, + SessionThreadEventStreamParams params, + RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return SessionStreams.create( + engine, + new String[] {"sessions", sessionId, "threads", threadId, "stream"}, + params.query(), + params.lastEventId(), + options, + false, + true) + .openAsync(); + } + + /** Lazy, explicitly reconnecting subscription. It never resends user input. */ + public EventStream resumableStream(String sessionId, String threadId) { + return resumableStream(sessionId, threadId, SessionThreadEventStreamParams.builder().build()); + } + + public EventStream resumableStream( + String sessionId, String threadId, SessionThreadEventStreamParams params) { + return resumableStream(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public EventStream resumableStream( + String sessionId, + String threadId, + SessionThreadEventStreamParams params, + RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return SessionStreams.create( + engine, + new String[] {"sessions", sessionId, "threads", threadId, "stream"}, + params.query(), + params.lastEventId(), + options, + true, + true); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> list( + String sessionId, String threadId) { + return list(sessionId, threadId, SessionThreadEventListParams.builder().build()); + } + + public CompletableFuture> list( + String sessionId, String threadId, SessionThreadEventListParams params) { + return list(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String sessionId, + String threadId, + SessionThreadEventListParams params, + RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters must not be null"); + return CursorRequests.list( + engine, + new String[] {"sessions", sessionId, "threads", threadId, "events"}, + params.query(), + options, + SessionEventListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreads.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreads.java new file mode 100644 index 0000000..7c3fea6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSessionThreads.java @@ -0,0 +1,126 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSessionThreads { + private final ClientEngine engine; + + public AsyncSessionThreads(ClientEngine engine) { + this.engine = engine; + } + + public AsyncSessionThreadEvents events() { + return new AsyncSessionThreadEvents(engine); + } + + public CompletableFuture archive(String sessionId, String threadId) { + return archive(sessionId, threadId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive( + String sessionId, String threadId, RequestOptions options) { + return Futures.map(withResponse().archive(sessionId, threadId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String sessionId, String threadId) { + return retrieve(sessionId, threadId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String sessionId, String threadId, RequestOptions options) { + return Futures.map(withResponse().retrieve(sessionId, threadId, options), ApiResponse::data); + } + + public CompletableFuture list(String sessionId) { + return list(sessionId, SessionThreadListParams.builder().build()); + } + + public CompletableFuture list( + String sessionId, RequestOptions options) { + return list(sessionId, SessionThreadListParams.builder().build(), options); + } + + public CompletableFuture list( + String sessionId, SessionThreadListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String sessionId, SessionThreadListParams params, RequestOptions options) { + return Futures.map(withResponse().list(sessionId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive( + String sessionId, String threadId) { + return archive(sessionId, threadId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String sessionId, String threadId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "threads", threadId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new SessionThread(v, r.requestId()))); + } + + public CompletableFuture> retrieve( + String sessionId, String threadId) { + return retrieve(sessionId, threadId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String sessionId, String threadId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"sessions", sessionId, "threads", threadId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new SessionThread(v, r.requestId()))); + } + + public CompletableFuture> list(String sessionId) { + return list(sessionId, SessionThreadListParams.builder().build()); + } + + public CompletableFuture> list( + String sessionId, RequestOptions options) { + return list(sessionId, SessionThreadListParams.builder().build(), options); + } + + public CompletableFuture> list( + String sessionId, SessionThreadListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String sessionId, SessionThreadListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"sessions", sessionId, "threads"}, + params.query(), + options, + SessionThreadListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSessions.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSessions.java new file mode 100644 index 0000000..db19d73 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSessions.java @@ -0,0 +1,272 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSessions { + private final ClientEngine engine; + + public AsyncSessions(ClientEngine engine) { + this.engine = engine; + } + + public AsyncSessionEvents events() { + return new AsyncSessionEvents(engine); + } + + public AsyncSessionThreads threads() { + return new AsyncSessionThreads(engine); + } + + public AsyncSessionResources resources() { + return new AsyncSessionResources(engine); + } + + public CompletableFuture archive(String sessionId) { + return archive(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String sessionId, RequestOptions options) { + return Futures.map(withResponse().archive(sessionId, options), ApiResponse::data); + } + + public CompletableFuture cancel(String sessionId) { + return cancel(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture cancel(String sessionId, RequestOptions options) { + return Futures.map(withResponse().cancel(sessionId, options), ApiResponse::data); + } + + public CompletableFuture create(SessionCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create(SessionCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture delete(String sessionId) { + return delete(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete(String sessionId, RequestOptions options) { + return Futures.map(withResponse().delete(sessionId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String sessionId) { + return retrieve(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String sessionId, RequestOptions options) { + return Futures.map(withResponse().retrieve(sessionId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(SessionListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(SessionListParams.builder().build(), options); + } + + public CompletableFuture list(SessionListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + SessionListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(SessionSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(SessionSearchParams.builder().build(), options); + } + + public CompletableFuture search(SessionSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + SessionSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture update(String sessionId, SessionUpdateParams params) { + return update(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String sessionId, SessionUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(sessionId, params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String sessionId) { + return archive(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String sessionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Session(v, r.requestId()))); + } + + public CompletableFuture> cancel(String sessionId) { + return cancel(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> cancel( + String sessionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId, "cancel"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Session(v, r.requestId()))); + } + + public CompletableFuture> create(SessionCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + SessionCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions"}, + Collections.emptyMap(), + SessionMetadata.created(params.toJsonValue()), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Session(v, r.requestId()))); + } + + public CompletableFuture> delete(String sessionId) { + return delete(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String sessionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"sessions", sessionId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedSession(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String sessionId) { + return retrieve(sessionId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String sessionId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"sessions", sessionId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Session(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(SessionListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(SessionListParams.builder().build(), options); + } + + public CompletableFuture> list(SessionListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + SessionListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, new String[] {"sessions"}, params.query(), options, SessionListResponse::new); + } + + public CompletableFuture> search() { + return search(SessionSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(SessionSearchParams.builder().build(), options); + } + + public CompletableFuture> search(SessionSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + SessionSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"sessions", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + SessionListResponse::new); + } + + public CompletableFuture> update( + String sessionId, SessionUpdateParams params) { + return update(sessionId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String sessionId, SessionUpdateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"sessions", sessionId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Session(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSkillVersions.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSkillVersions.java new file mode 100644 index 0000000..0776311 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSkillVersions.java @@ -0,0 +1,177 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSkillVersions { + private final ClientEngine engine; + + public AsyncSkillVersions(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture list(String skillId) { + return list(skillId, SkillVersionListParams.builder().build()); + } + + public CompletableFuture list(String skillId, RequestOptions options) { + return list(skillId, SkillVersionListParams.builder().build(), options); + } + + public CompletableFuture list( + String skillId, SkillVersionListParams params) { + return list(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String skillId, SkillVersionListParams params, RequestOptions options) { + return Futures.map(withResponse().list(skillId, params, options), ApiResponse::data); + } + + public CompletableFuture create(String skillId, SkillVersionCreateParams params) { + return create(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + String skillId, SkillVersionCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(skillId, params, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String skillId, String version) { + return retrieve(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String skillId, String version, RequestOptions options) { + return Futures.map(withResponse().retrieve(skillId, version, options), ApiResponse::data); + } + + public CompletableFuture delete(String skillId, String version) { + return delete(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String skillId, String version, RequestOptions options) { + return Futures.map(withResponse().delete(skillId, version, options), ApiResponse::data); + } + + public CompletableFuture download(String skillId, String version) { + return download(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture download( + String skillId, String version, RequestOptions options) { + return Futures.mapOwned( + withResponse().download(skillId, version, options), + ApiResponse::data, + r -> r.data().close()); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> list(String skillId) { + return list(skillId, SkillVersionListParams.builder().build()); + } + + public CompletableFuture> list( + String skillId, RequestOptions options) { + return list(skillId, SkillVersionListParams.builder().build(), options); + } + + public CompletableFuture> list( + String skillId, SkillVersionListParams params) { + return list(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String skillId, SkillVersionListParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + if (options.query().containsKey("after_id") || options.query().containsKey("before_id")) + throw new ConfigurationException("Skill versions use page only"); + return CursorRequests.list( + engine, + new String[] {"skills", skillId, "versions"}, + params.query(), + options, + SkillVersionListResponse::new); + } + + public CompletableFuture> create( + String skillId, SkillVersionCreateParams params) { + return create(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + String skillId, SkillVersionCreateParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + Uploads upload = + new Uploads(Collections.singletonMap("files", params.files()), params.fields()); + try { + CompletableFuture> pending = + engine.requestBody( + "POST", + new String[] {"skills", skillId, "versions"}, + Collections.emptyMap(), + upload.body(), + upload.replayable(), + options); + pending.whenComplete((v, e) -> upload.close()); + return Futures.map(pending, r -> r.map(v -> new SkillVersion(v, r.requestId()))); + } catch (RuntimeException e) { + upload.close(); + throw e; + } + } + + public CompletableFuture> retrieve(String skillId, String version) { + return retrieve(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String skillId, String version, RequestOptions options) { + return Futures.map( + engine.request( + "GET", + new String[] {"skills", skillId, "versions", version}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> new SkillVersion(v, r.requestId()))); + } + + public CompletableFuture> delete( + String skillId, String version) { + return delete(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String skillId, String version, RequestOptions options) { + return Futures.map( + engine.request( + "DELETE", + new String[] {"skills", skillId, "versions", version}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedSkillVersion(v, r.requestId()))); + } + + public CompletableFuture> download(String skillId, String version) { + return download(skillId, version, RequestOptions.DEFAULT); + } + + public CompletableFuture> download( + String skillId, String version, RequestOptions options) { + return engine.downloadContent( + new String[] {"skills", skillId, "versions", version, "content"}, options); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncSkills.java b/src/main/java/com/qoder/cloudagents/managed/AsyncSkills.java new file mode 100644 index 0000000..407b49f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncSkills.java @@ -0,0 +1,251 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncSkills { + private final ClientEngine engine; + + public AsyncSkills(ClientEngine engine) { + this.engine = engine; + } + + public AsyncSkillVersions versions() { + return new AsyncSkillVersions(engine); + } + + public CompletableFuture list() { + return list(SkillListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(SkillListParams.builder().build(), options); + } + + public CompletableFuture list(SkillListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list(SkillListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture create(SkillCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create(SkillCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String skillId) { + return retrieve(skillId, SkillRetrieveParams.builder().build()); + } + + public CompletableFuture retrieve(String skillId, RequestOptions options) { + return retrieve(skillId, SkillRetrieveParams.builder().build(), options); + } + + public CompletableFuture retrieve(String skillId, SkillRetrieveParams params) { + return retrieve(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String skillId, SkillRetrieveParams params, RequestOptions options) { + return Futures.map(withResponse().retrieve(skillId, params, options), ApiResponse::data); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public CompletableFuture update(String skillId, SkillUpdateParams params) { + return update(skillId, params, RequestOptions.DEFAULT); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public CompletableFuture update( + String skillId, SkillUpdateParams params, RequestOptions options) { + return Futures.map(withResponse().update(skillId, params, options), ApiResponse::data); + } + + public CompletableFuture delete(String skillId) { + return delete(skillId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete(String skillId, RequestOptions options) { + return Futures.map(withResponse().delete(skillId, options), ApiResponse::data); + } + + public CompletableFuture search(SkillSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + SkillSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(SkillSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(SkillSearchParams.builder().build(), options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> search() { + return search(SkillSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(SkillSearchParams.builder().build(), options); + } + + public CompletableFuture> search(SkillSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + SkillSearchParams params, RequestOptions options) { + if (options == null || params == null) + throw new ConfigurationException("Request parameters and options must not be null"); + return SearchRequests.search( + engine, + new String[] {"skills", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + SkillListResponse::new); + } + + public CompletableFuture> list() { + return list(SkillListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(SkillListParams.builder().build(), options); + } + + public CompletableFuture> list(SkillListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + SkillListParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + Map query = new LinkedHashMap<>(params.query()); + query.putAll(options.query()); + if (query.containsKey("source") && query.containsKey("before_id")) + throw new ConfigurationException("source does not support beforeId"); + return CursorRequests.list( + engine, new String[] {"skills"}, params.query(), options, SkillListResponse::new); + } + + public CompletableFuture> create(SkillCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + SkillCreateParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + Uploads upload = + new Uploads( + params.files().isEmpty() + ? Collections.singletonMap("file", Collections.singletonList(params.file())) + : Collections.singletonMap("files", params.files()), + params.fields()); + try { + CompletableFuture> pending = + engine.requestBody( + "POST", + new String[] {"skills"}, + Collections.emptyMap(), + upload.body(), + upload.replayable(), + options); + pending.whenComplete((v, e) -> upload.close()); + return Futures.map(pending, r -> r.map(v -> new Skill(v, r.requestId()))); + } catch (RuntimeException e) { + upload.close(); + throw e; + } + } + + public CompletableFuture> retrieve(String skillId) { + return retrieve(skillId, SkillRetrieveParams.builder().build()); + } + + public CompletableFuture> retrieve(String skillId, RequestOptions options) { + return retrieve(skillId, SkillRetrieveParams.builder().build(), options); + } + + public CompletableFuture> retrieve( + String skillId, SkillRetrieveParams params) { + return retrieve(skillId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String skillId, SkillRetrieveParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "GET", new String[] {"skills", skillId}, params.query(), null, true, options), + r -> r.map(v -> new Skill(v, r.requestId()))); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public CompletableFuture> update(String skillId, SkillUpdateParams params) { + return update(skillId, params, RequestOptions.DEFAULT); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public CompletableFuture> update( + String skillId, SkillUpdateParams params, RequestOptions options) { + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "PUT", + new String[] {"skills", skillId}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> new Skill(v, r.requestId()))); + } + + public CompletableFuture> delete(String skillId) { + return delete(skillId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String skillId, RequestOptions options) { + return Futures.map( + engine.request( + "DELETE", + new String[] {"skills", skillId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedSkill(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncVaultCredentials.java b/src/main/java/com/qoder/cloudagents/managed/AsyncVaultCredentials.java new file mode 100644 index 0000000..e965f16 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncVaultCredentials.java @@ -0,0 +1,246 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncVaultCredentials { + private final ClientEngine engine; + + public AsyncVaultCredentials(ClientEngine engine) { + this.engine = engine; + } + + public CompletableFuture archive(String vaultId, String credentialId) { + return archive(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive( + String vaultId, String credentialId, RequestOptions options) { + return Futures.map(withResponse().archive(vaultId, credentialId, options), ApiResponse::data); + } + + public CompletableFuture create( + String vaultId, VaultCredentialCreateParams params) { + return create(vaultId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture create( + String vaultId, VaultCredentialCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(vaultId, params, options), ApiResponse::data); + } + + public CompletableFuture delete(String vaultId, String credentialId) { + return delete(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete( + String vaultId, String credentialId, RequestOptions options) { + return Futures.map(withResponse().delete(vaultId, credentialId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String vaultId, String credentialId) { + return retrieve(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve( + String vaultId, String credentialId, RequestOptions options) { + return Futures.map(withResponse().retrieve(vaultId, credentialId, options), ApiResponse::data); + } + + public CompletableFuture list(String vaultId) { + return list(vaultId, VaultCredentialListParams.builder().build()); + } + + public CompletableFuture list( + String vaultId, RequestOptions options) { + return list(vaultId, VaultCredentialListParams.builder().build(), options); + } + + public CompletableFuture list( + String vaultId, VaultCredentialListParams params) { + return list(vaultId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture list( + String vaultId, VaultCredentialListParams params, RequestOptions options) { + return Futures.map(withResponse().list(vaultId, params, options), ApiResponse::data); + } + + public CompletableFuture update( + String vaultId, String credentialId, VaultCredentialUpdateParams params) { + return update(vaultId, credentialId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture update( + String vaultId, + String credentialId, + VaultCredentialUpdateParams params, + RequestOptions options) { + return Futures.map( + withResponse().update(vaultId, credentialId, params, options), ApiResponse::data); + } + + public CompletableFuture validate( + String vaultId, String credentialId) { + return validate(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture validate( + String vaultId, String credentialId, RequestOptions options) { + return Futures.map(withResponse().validate(vaultId, credentialId, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive( + String vaultId, String credentialId) { + return archive(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive( + String vaultId, String credentialId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults", vaultId, "credentials", credentialId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new VaultCredential(v, r.requestId()))); + } + + public CompletableFuture> create( + String vaultId, VaultCredentialCreateParams params) { + return create(vaultId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + String vaultId, VaultCredentialCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults", vaultId, "credentials"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new VaultCredential(v, r.requestId()))); + } + + public CompletableFuture> delete( + String vaultId, String credentialId) { + return delete(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String vaultId, String credentialId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"vaults", vaultId, "credentials", credentialId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedVaultCredential(v, r.requestId()))); + } + + public CompletableFuture> retrieve( + String vaultId, String credentialId) { + return retrieve(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve( + String vaultId, String credentialId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", + new String[] {"vaults", vaultId, "credentials", credentialId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new VaultCredential(v, r.requestId()))); + } + + public CompletableFuture> list(String vaultId) { + return list(vaultId, VaultCredentialListParams.builder().build()); + } + + public CompletableFuture> list( + String vaultId, RequestOptions options) { + return list(vaultId, VaultCredentialListParams.builder().build(), options); + } + + public CompletableFuture> list( + String vaultId, VaultCredentialListParams params) { + return list(vaultId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + String vaultId, VaultCredentialListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, + new String[] {"vaults", vaultId, "credentials"}, + params.query(), + options, + VaultCredentialListResponse::new); + } + + public CompletableFuture> update( + String vaultId, String credentialId, VaultCredentialUpdateParams params) { + return update(vaultId, credentialId, params, RequestOptions.DEFAULT); + } + + public CompletableFuture> update( + String vaultId, + String credentialId, + VaultCredentialUpdateParams params, + RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults", vaultId, "credentials", credentialId}, + Collections.emptyMap(), + params.toJsonValue(), + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new VaultCredential(v, r.requestId()))); + } + + public CompletableFuture> validate( + String vaultId, String credentialId) { + return validate(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public CompletableFuture> validate( + String vaultId, String credentialId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults", vaultId, "credentials", credentialId, "mcp_oauth_validate"}, + Collections.emptyMap(), + JsonValue.of(Collections.emptyMap()), + false, + options.toBuilder().maxRetries(0).build()), + r -> r.map(v -> v.isNull() ? null : new VaultCredentialValidation(v, r.requestId()))); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/AsyncVaults.java b/src/main/java/com/qoder/cloudagents/managed/AsyncVaults.java new file mode 100644 index 0000000..07837a0 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/AsyncVaults.java @@ -0,0 +1,201 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public final class AsyncVaults { + private final ClientEngine engine; + + public AsyncVaults(ClientEngine engine) { + this.engine = engine; + } + + public AsyncVaultCredentials credentials() { + return new AsyncVaultCredentials(engine); + } + + public CompletableFuture archive(String vaultId) { + return archive(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture archive(String vaultId, RequestOptions options) { + return Futures.map(withResponse().archive(vaultId, options), ApiResponse::data); + } + + public CompletableFuture create(VaultCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture create(VaultCreateParams params, RequestOptions options) { + return Futures.map(withResponse().create(params, options), ApiResponse::data); + } + + public CompletableFuture delete(String vaultId) { + return delete(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture delete(String vaultId, RequestOptions options) { + return Futures.map(withResponse().delete(vaultId, options), ApiResponse::data); + } + + public CompletableFuture retrieve(String vaultId) { + return retrieve(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture retrieve(String vaultId, RequestOptions options) { + return Futures.map(withResponse().retrieve(vaultId, options), ApiResponse::data); + } + + public CompletableFuture list() { + return list(VaultListParams.builder().build()); + } + + public CompletableFuture list(RequestOptions options) { + return list(VaultListParams.builder().build(), options); + } + + public CompletableFuture list(VaultListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture list(VaultListParams params, RequestOptions options) { + return Futures.map(withResponse().list(params, options), ApiResponse::data); + } + + public CompletableFuture search() { + return search(VaultSearchParams.builder().build()); + } + + public CompletableFuture search(RequestOptions options) { + return search(VaultSearchParams.builder().build(), options); + } + + public CompletableFuture search(VaultSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture search( + VaultSearchParams params, RequestOptions options) { + return Futures.map(withResponse().search(params, options), ApiResponse::data); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public CompletableFuture> archive(String vaultId) { + return archive(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture> archive(String vaultId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults", vaultId, "archive"}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new Vault(v, r.requestId()))); + } + + public CompletableFuture> create(VaultCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> create( + VaultCreateParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return Futures.map( + engine.request( + "POST", + new String[] {"vaults"}, + Collections.emptyMap(), + params.toJsonValue(), + true, + options), + r -> r.map(v -> v.isNull() ? null : new Vault(v, r.requestId()))); + } + + public CompletableFuture> delete(String vaultId) { + return delete(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture> delete( + String vaultId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "DELETE", + new String[] {"vaults", vaultId}, + Collections.emptyMap(), + null, + true, + options), + r -> r.map(v -> v.isNull() ? null : new DeletedVault(v, r.requestId()))); + } + + public CompletableFuture> retrieve(String vaultId) { + return retrieve(vaultId, RequestOptions.DEFAULT); + } + + public CompletableFuture> retrieve(String vaultId, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + return Futures.map( + engine.request( + "GET", new String[] {"vaults", vaultId}, Collections.emptyMap(), null, true, options), + r -> r.map(v -> v.isNull() ? null : new Vault(v, r.requestId()))); + } + + public CompletableFuture> list() { + return list(VaultListParams.builder().build()); + } + + public CompletableFuture> list(RequestOptions options) { + return list(VaultListParams.builder().build(), options); + } + + public CompletableFuture> list(VaultListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> list( + VaultListParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return CursorRequests.list( + engine, new String[] {"vaults"}, params.query(), options, VaultListResponse::new); + } + + public CompletableFuture> search() { + return search(VaultSearchParams.builder().build()); + } + + public CompletableFuture> search(RequestOptions options) { + return search(VaultSearchParams.builder().build(), options); + } + + public CompletableFuture> search(VaultSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public CompletableFuture> search( + VaultSearchParams params, RequestOptions options) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + if (params == null) throw new ConfigurationException("Request parameters are required"); + return SearchRequests.search( + engine, + new String[] {"vaults", "search"}, + params.toJsonValue(), + Collections.emptyMap(), + options, + VaultListResponse::new); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/ContentBlock.java b/src/main/java/com/qoder/cloudagents/managed/ContentBlock.java new file mode 100644 index 0000000..2892341 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/ContentBlock.java @@ -0,0 +1,60 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class ContentBlock extends JsonObject { + private ContentBlock(JsonValue value) { + super(value); + } + + public static ContentBlock fromJson(JsonValue value) { + return new ContentBlock(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String text() { + return optional("text", JsonValue::asString); + } + + public String thinking() { + return optional("thinking", JsonValue::asString); + } + + public ImageSource source() { + return optional("source", ImageSource::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder text(String value) { + return put("text", value); + } + + public Builder thinking(String value) { + return put("thinking", value); + } + + public Builder source(ImageSource value) { + return put("source", value); + } + + public ContentBlock build() { + require("type"); + return new ContentBlock(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/CredentialHttpResponse.java b/src/main/java/com/qoder/cloudagents/managed/CredentialHttpResponse.java new file mode 100644 index 0000000..7d419b6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/CredentialHttpResponse.java @@ -0,0 +1,64 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class CredentialHttpResponse extends JsonObject { + private CredentialHttpResponse(JsonValue value) { + super(value); + } + + public static CredentialHttpResponse fromJson(JsonValue value) { + return new CredentialHttpResponse(value); + } + + public Long statusCode() { + return optional("status_code", JsonValue::asLong); + } + + public String contentType() { + return optional("content_type", JsonValue::asString); + } + + public String body() { + return optional("body", JsonValue::asString); + } + + public Boolean bodyTruncated() { + return optional("body_truncated", JsonValue::asBoolean); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder statusCode(Long value) { + return put("status_code", value); + } + + public Builder statusCode(long value) { + return statusCode(Long.valueOf(value)); + } + + public Builder contentType(String value) { + return put("content_type", value); + } + + public Builder body(String value) { + return put("body", value); + } + + public Builder bodyTruncated(Boolean value) { + return put("body_truncated", value); + } + + public CredentialHttpResponse build() { + + return new CredentialHttpResponse(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/CredentialProbeResult.java b/src/main/java/com/qoder/cloudagents/managed/CredentialProbeResult.java new file mode 100644 index 0000000..fd53a8c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/CredentialProbeResult.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class CredentialProbeResult extends JsonObject { + private CredentialProbeResult(JsonValue value) { + super(value); + } + + public static CredentialProbeResult fromJson(JsonValue value) { + return new CredentialProbeResult(value); + } + + public String method() { + return optional("method", JsonValue::asString); + } + + public CredentialHttpResponse httpResponse() { + return optional("http_response", CredentialHttpResponse::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder method(String value) { + return put("method", value); + } + + public Builder httpResponse(CredentialHttpResponse value) { + return put("http_response", value); + } + + public CredentialProbeResult build() { + + return new CredentialProbeResult(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/CredentialRefreshResult.java b/src/main/java/com/qoder/cloudagents/managed/CredentialRefreshResult.java new file mode 100644 index 0000000..26d5024 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/CredentialRefreshResult.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class CredentialRefreshResult extends JsonObject { + private CredentialRefreshResult(JsonValue value) { + super(value); + } + + public static CredentialRefreshResult fromJson(JsonValue value) { + return new CredentialRefreshResult(value); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public CredentialHttpResponse httpResponse() { + return optional("http_response", CredentialHttpResponse::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder status(String value) { + return put("status", value); + } + + public Builder httpResponse(CredentialHttpResponse value) { + return put("http_response", value); + } + + public CredentialRefreshResult build() { + + return new CredentialRefreshResult(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedEnvironment.java b/src/main/java/com/qoder/cloudagents/managed/DeletedEnvironment.java new file mode 100644 index 0000000..bc59fc6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedEnvironment.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedEnvironment extends JsonModel { + public DeletedEnvironment(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedFile.java b/src/main/java/com/qoder/cloudagents/managed/DeletedFile.java new file mode 100644 index 0000000..51c6eee --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedFile.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedFile extends JsonModel { + public DeletedFile(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedMemory.java b/src/main/java/com/qoder/cloudagents/managed/DeletedMemory.java new file mode 100644 index 0000000..4372c43 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedMemory.java @@ -0,0 +1,22 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class DeletedMemory extends JsonModel { + public DeletedMemory(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedMemoryStore.java b/src/main/java/com/qoder/cloudagents/managed/DeletedMemoryStore.java new file mode 100644 index 0000000..598a0b3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedMemoryStore.java @@ -0,0 +1,22 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class DeletedMemoryStore extends JsonModel { + public DeletedMemoryStore(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedSession.java b/src/main/java/com/qoder/cloudagents/managed/DeletedSession.java new file mode 100644 index 0000000..127eddd --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedSession.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class DeletedSession extends JsonModel { + public DeletedSession(JsonValue value, String requestId) { + super(value, requestId); + } + + public static DeletedSession fromJson(JsonValue value) { + return new DeletedSession(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedSessionResource.java b/src/main/java/com/qoder/cloudagents/managed/DeletedSessionResource.java new file mode 100644 index 0000000..133421b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedSessionResource.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class DeletedSessionResource extends JsonModel { + public DeletedSessionResource(JsonValue value, String requestId) { + super(value, requestId); + } + + public static DeletedSessionResource fromJson(JsonValue value) { + return new DeletedSessionResource(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedSkill.java b/src/main/java/com/qoder/cloudagents/managed/DeletedSkill.java new file mode 100644 index 0000000..88df5ab --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedSkill.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedSkill extends JsonModel { + public DeletedSkill(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedSkillVersion.java b/src/main/java/com/qoder/cloudagents/managed/DeletedSkillVersion.java new file mode 100644 index 0000000..ef6bb72 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedSkillVersion.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedSkillVersion extends JsonModel { + public DeletedSkillVersion(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedVault.java b/src/main/java/com/qoder/cloudagents/managed/DeletedVault.java new file mode 100644 index 0000000..08f2a04 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedVault.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedVault extends JsonModel { + public DeletedVault(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeletedVaultCredential.java b/src/main/java/com/qoder/cloudagents/managed/DeletedVaultCredential.java new file mode 100644 index 0000000..8c6cc2b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeletedVaultCredential.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class DeletedVaultCredential extends JsonModel { + public DeletedVaultCredential(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Boolean deleted() { + return optional("deleted", JsonValue::asBoolean); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Deployment.java b/src/main/java/com/qoder/cloudagents/managed/Deployment.java new file mode 100644 index 0000000..d16f407 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Deployment.java @@ -0,0 +1,83 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Deployment extends JsonModel { + public Deployment(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Deployment fromJson(JsonValue value) { + return new Deployment(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public AgentReference agent() { + return optional("agent", AgentReference::fromJson); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public DeploymentSchedule schedule() { + return optional("schedule", DeploymentSchedule::fromJson); + } + + public List initialEvents() { + return optionalList("initial_events", SessionEventParam::fromJson); + } + + public List resources() { + return optionalList("resources", SessionResourceSpec::fromJson); + } + + public List vaultIds() { + return optionalList("vault_ids", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public String environmentVariables() { + return optional("environment_variables", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public DeploymentPauseReason pausedReason() { + return optional("paused_reason", DeploymentPauseReason::fromJson); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentCreateParams.java new file mode 100644 index 0000000..f1d903b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentCreateParams.java @@ -0,0 +1,118 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentCreateParams extends JsonObject { + private DeploymentCreateParams(JsonValue value) { + super(value); + } + + public static DeploymentCreateParams fromJson(JsonValue value) { + return new DeploymentCreateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public AgentReference agent() { + return optional("agent", AgentReference::fromJson); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public DeploymentSchedule schedule() { + return optional("schedule", DeploymentSchedule::fromJson); + } + + public List initialEvents() { + return optionalList("initial_events", SessionEventParam::fromJson); + } + + public List resources() { + return optionalList("resources", SessionResourceSpec::fromJson); + } + + public List vaultIds() { + return optionalList("vault_ids", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public String environmentVariables() { + return optional("environment_variables", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder agent(AgentReference value) { + return put("agent", value); + } + + public Builder agent(String value) { + return put("agent", value == null ? null : AgentReference.of(value)); + } + + public Builder environmentId(String value) { + return put("environment_id", value); + } + + public Builder schedule(DeploymentSchedule value) { + return put("schedule", value); + } + + public Builder initialEvents(List value) { + return put("initial_events", value); + } + + public Builder resources(List value) { + return put("resources", value); + } + + public Builder vaultIds(List value) { + return put("vault_ids", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder environmentVariables(String value) { + return put("environment_variables", value); + } + + public DeploymentCreateParams build() { + require("name", "agent", "environment_id", "initial_events"); + JsonValue events = json().get("initial_events"); + if (!events.isMissing() + && !events.isNull() + && (events.asArray().isEmpty() || events.asArray().size() > 50)) + throw new ConfigurationException("initialEvents requires 1-50 events"); + return new DeploymentCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentListParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentListParams.java new file mode 100644 index 0000000..452cd95 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentListParams.java @@ -0,0 +1,79 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class DeploymentListParams { + private final Map query; + + private DeploymentListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder status(String value) { + return put("status", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder agentId(String value) { + return put("agent_id", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public DeploymentListParams build() { + return new DeploymentListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentListResponse.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentListResponse.java new file mode 100644 index 0000000..8543338 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentListResponse.java @@ -0,0 +1,28 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class DeploymentListResponse extends CursorPage { + public DeploymentListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + DeploymentListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Deployment(item, requestId), true); + } + + @Override + protected DeploymentListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentPauseReason.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentPauseReason.java new file mode 100644 index 0000000..03f8432 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentPauseReason.java @@ -0,0 +1,52 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentPauseReason extends JsonObject { + private DeploymentPauseReason(JsonValue value) { + super(value); + } + + public static DeploymentPauseReason fromJson(JsonValue value) { + return new DeploymentPauseReason(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String message() { + return optional("message", JsonValue::asString); + } + + public String code() { + return optional("code", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder message(String value) { + return put("message", value); + } + + public Builder code(String value) { + return put("code", value); + } + + public DeploymentPauseReason build() { + + return new DeploymentPauseReason(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentRun.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentRun.java new file mode 100644 index 0000000..02a7717 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentRun.java @@ -0,0 +1,47 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class DeploymentRun extends JsonModel { + public DeploymentRun(JsonValue value, String requestId) { + super(value, requestId); + } + + public static DeploymentRun fromJson(JsonValue value) { + return new DeploymentRun(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String deploymentId() { + return optional("deployment_id", JsonValue::asString); + } + + public AgentReference agent() { + return optional("agent", AgentReference::fromJson); + } + + public DeploymentRunError error() { + return optional("error", DeploymentRunError::fromJson); + } + + public DeploymentTriggerContext triggerContext() { + return optional("trigger_context", DeploymentTriggerContext::fromJson); + } + + public String sessionId() { + return optional("session_id", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentRunError.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunError.java new file mode 100644 index 0000000..0947c40 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunError.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentRunError extends JsonObject { + private DeploymentRunError(JsonValue value) { + super(value); + } + + public static DeploymentRunError fromJson(JsonValue value) { + return new DeploymentRunError(value); + } + + public String message() { + return optional("message", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder message(String value) { + return put("message", value); + } + + public Builder type(String value) { + return put("type", value); + } + + public DeploymentRunError build() { + + return new DeploymentRunError(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListParams.java new file mode 100644 index 0000000..b0d91cb --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListParams.java @@ -0,0 +1,87 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class DeploymentRunListParams { + private final Map query; + + private DeploymentRunListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder deploymentId(String value) { + return put("deployment_id", value); + } + + public Builder triggerType(String value) { + return put("trigger_type", value); + } + + public Builder hasError(boolean value) { + return put("has_error", String.valueOf(value)); + } + + public Builder createdAtGt(String value) { + return put("created_at[gt]", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLt(String value) { + return put("created_at[lt]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public DeploymentRunListParams build() { + return new DeploymentRunListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListResponse.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListResponse.java new file mode 100644 index 0000000..bd4814d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentRunListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class DeploymentRunListResponse + extends CursorPage { + public DeploymentRunListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + DeploymentRunListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new DeploymentRun(item, requestId), true); + } + + @Override + protected DeploymentRunListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentRuns.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentRuns.java new file mode 100644 index 0000000..37e13f9 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentRuns.java @@ -0,0 +1,68 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class DeploymentRuns { + private final AsyncDeploymentRuns async; + + public DeploymentRuns(AsyncDeploymentRuns async) { + this.async = async; + } + + public DeploymentRun retrieve(String runId) { + return retrieve(runId, RequestOptions.DEFAULT); + } + + public DeploymentRun retrieve(String runId, RequestOptions options) { + return Futures.await(async.retrieve(runId, options)); + } + + public DeploymentRunListResponse list() { + return list(DeploymentRunListParams.builder().build()); + } + + public DeploymentRunListResponse list(RequestOptions options) { + return list(DeploymentRunListParams.builder().build(), options); + } + + public DeploymentRunListResponse list(DeploymentRunListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public DeploymentRunListResponse list(DeploymentRunListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse retrieve(String runId) { + return retrieve(runId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String runId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(runId, options)); + } + + public ApiResponse list() { + return list(DeploymentRunListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(DeploymentRunListParams.builder().build(), options); + } + + public ApiResponse list(DeploymentRunListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + DeploymentRunListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentSchedule.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentSchedule.java new file mode 100644 index 0000000..7e08aa7 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentSchedule.java @@ -0,0 +1,69 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentSchedule extends JsonObject { + private DeploymentSchedule(JsonValue value) { + super(value); + } + + public static DeploymentSchedule fromJson(JsonValue value) { + return new DeploymentSchedule(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String expression() { + return optional("expression", JsonValue::asString); + } + + public String timezone() { + return optional("timezone", JsonValue::asString); + } + + public List upcomingRunsAt() { + return optionalList("upcoming_runs_at", JsonValue::asString); + } + + public String lastRunAt() { + return optional("last_run_at", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder expression(String value) { + return put("expression", value); + } + + public Builder timezone(String value) { + return put("timezone", value); + } + + public Builder upcomingRunsAt(List value) { + return put("upcoming_runs_at", value); + } + + public Builder lastRunAt(String value) { + return put("last_run_at", value); + } + + public DeploymentSchedule build() { + require("type", "expression", "timezone"); + + return new DeploymentSchedule(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListParams.java new file mode 100644 index 0000000..589a8fa --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListParams.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class DeploymentScopedRunListParams { + private final Map query; + + private DeploymentScopedRunListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder triggeredAfter(String value) { + return put("triggered_after", value); + } + + public Builder triggeredBefore(String value) { + return put("triggered_before", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public DeploymentScopedRunListParams build() { + return new DeploymentScopedRunListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListResponse.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListResponse.java new file mode 100644 index 0000000..dd891aa --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRunListResponse.java @@ -0,0 +1,30 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class DeploymentScopedRunListResponse + extends CursorPage { + public DeploymentScopedRunListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + DeploymentScopedRunListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction< + Map, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new DeploymentRun(item, requestId), true); + } + + @Override + protected DeploymentScopedRunListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRuns.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRuns.java new file mode 100644 index 0000000..2ffa788 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentScopedRuns.java @@ -0,0 +1,73 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class DeploymentScopedRuns { + private final AsyncDeploymentScopedRuns async; + + public DeploymentScopedRuns(AsyncDeploymentScopedRuns async) { + this.async = async; + } + + public DeploymentRun retrieve(String deploymentId, String runId) { + return retrieve(deploymentId, runId, RequestOptions.DEFAULT); + } + + public DeploymentRun retrieve(String deploymentId, String runId, RequestOptions options) { + return Futures.await(async.retrieve(deploymentId, runId, options)); + } + + public DeploymentScopedRunListResponse list(String deploymentId) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build()); + } + + public DeploymentScopedRunListResponse list(String deploymentId, RequestOptions options) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build(), options); + } + + public DeploymentScopedRunListResponse list( + String deploymentId, DeploymentScopedRunListParams params) { + return list(deploymentId, params, RequestOptions.DEFAULT); + } + + public DeploymentScopedRunListResponse list( + String deploymentId, DeploymentScopedRunListParams params, RequestOptions options) { + return Futures.await(async.list(deploymentId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse retrieve(String deploymentId, String runId) { + return retrieve(deploymentId, runId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String deploymentId, String runId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(deploymentId, runId, options)); + } + + public ApiResponse list(String deploymentId) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build()); + } + + public ApiResponse list( + String deploymentId, RequestOptions options) { + return list(deploymentId, DeploymentScopedRunListParams.builder().build(), options); + } + + public ApiResponse list( + String deploymentId, DeploymentScopedRunListParams params) { + return list(deploymentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String deploymentId, DeploymentScopedRunListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(deploymentId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentSearchParams.java new file mode 100644 index 0000000..d2d47be --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentSearchParams.java @@ -0,0 +1,107 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentSearchParams extends JsonObject { + private DeploymentSearchParams(JsonValue value) { + super(value); + } + + public static DeploymentSearchParams fromJson(JsonValue value) { + return new DeploymentSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public String agentId() { + return optional("agent_id", JsonValue::asString); + } + + public String createdAtGte() { + return optional("created_at[gte]", JsonValue::asString); + } + + public String createdAtLte() { + return optional("created_at[lte]", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder status(String value) { + return put("status", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder agentId(String value) { + return put("agent_id", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + public DeploymentSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new DeploymentSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentTriggerContext.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentTriggerContext.java new file mode 100644 index 0000000..dd473e4 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentTriggerContext.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentTriggerContext extends JsonObject { + private DeploymentTriggerContext(JsonValue value) { + super(value); + } + + public static DeploymentTriggerContext fromJson(JsonValue value) { + return new DeploymentTriggerContext(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String scheduledAt() { + return optional("scheduled_at", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder scheduledAt(String value) { + return put("scheduled_at", value); + } + + public DeploymentTriggerContext build() { + + return new DeploymentTriggerContext(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DeploymentUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/DeploymentUpdateParams.java new file mode 100644 index 0000000..f726e42 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DeploymentUpdateParams.java @@ -0,0 +1,117 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DeploymentUpdateParams extends JsonObject { + private DeploymentUpdateParams(JsonValue value) { + super(value); + } + + public static DeploymentUpdateParams fromJson(JsonValue value) { + return new DeploymentUpdateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public AgentReference agent() { + return optional("agent", AgentReference::fromJson); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public DeploymentSchedule schedule() { + return optional("schedule", DeploymentSchedule::fromJson); + } + + public List initialEvents() { + return optionalList("initial_events", SessionEventParam::fromJson); + } + + public List resources() { + return optionalList("resources", SessionResourceSpec::fromJson); + } + + public List vaultIds() { + return optionalList("vault_ids", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public String environmentVariables() { + return optional("environment_variables", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder agent(AgentReference value) { + return put("agent", value); + } + + public Builder agent(String value) { + return put("agent", value == null ? null : AgentReference.of(value)); + } + + public Builder environmentId(String value) { + return put("environment_id", value); + } + + public Builder schedule(DeploymentSchedule value) { + return put("schedule", value); + } + + public Builder initialEvents(List value) { + return put("initial_events", value); + } + + public Builder resources(List value) { + return put("resources", value); + } + + public Builder vaultIds(List value) { + return put("vault_ids", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder environmentVariables(String value) { + return put("environment_variables", value); + } + + public DeploymentUpdateParams build() { + JsonValue events = json().get("initial_events"); + if (!events.isMissing() + && !events.isNull() + && (events.asArray().isEmpty() || events.asArray().size() > 50)) + throw new ConfigurationException("initialEvents requires 1-50 events"); + return new DeploymentUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Deployments.java b/src/main/java/com/qoder/cloudagents/managed/Deployments.java new file mode 100644 index 0000000..772e365 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Deployments.java @@ -0,0 +1,203 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Deployments { + private final AsyncDeployments async; + + public Deployments(AsyncDeployments async) { + this.async = async; + } + + public DeploymentScopedRuns runs() { + return new DeploymentScopedRuns(async.runs()); + } + + public Deployment archive(String deploymentId) { + return archive(deploymentId, RequestOptions.DEFAULT); + } + + public Deployment archive(String deploymentId, RequestOptions options) { + return Futures.await(async.archive(deploymentId, options)); + } + + public Deployment create(DeploymentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Deployment create(DeploymentCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public Deployment retrieve(String deploymentId) { + return retrieve(deploymentId, RequestOptions.DEFAULT); + } + + public Deployment retrieve(String deploymentId, RequestOptions options) { + return Futures.await(async.retrieve(deploymentId, options)); + } + + public DeploymentListResponse list() { + return list(DeploymentListParams.builder().build()); + } + + public DeploymentListResponse list(RequestOptions options) { + return list(DeploymentListParams.builder().build(), options); + } + + public DeploymentListResponse list(DeploymentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public DeploymentListResponse list(DeploymentListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public Deployment pause(String deploymentId) { + return pause(deploymentId, RequestOptions.DEFAULT); + } + + public Deployment pause(String deploymentId, RequestOptions options) { + return Futures.await(async.pause(deploymentId, options)); + } + + public DeploymentRun run(String deploymentId) { + return run(deploymentId, RequestOptions.DEFAULT); + } + + public DeploymentRun run(String deploymentId, RequestOptions options) { + return Futures.await(async.run(deploymentId, options)); + } + + public DeploymentListResponse search() { + return search(DeploymentSearchParams.builder().build()); + } + + public DeploymentListResponse search(RequestOptions options) { + return search(DeploymentSearchParams.builder().build(), options); + } + + public DeploymentListResponse search(DeploymentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public DeploymentListResponse search(DeploymentSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public Deployment unpause(String deploymentId) { + return unpause(deploymentId, RequestOptions.DEFAULT); + } + + public Deployment unpause(String deploymentId, RequestOptions options) { + return Futures.await(async.unpause(deploymentId, options)); + } + + public Deployment update(String deploymentId, DeploymentUpdateParams params) { + return update(deploymentId, params, RequestOptions.DEFAULT); + } + + public Deployment update( + String deploymentId, DeploymentUpdateParams params, RequestOptions options) { + return Futures.await(async.update(deploymentId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String deploymentId) { + return archive(deploymentId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String deploymentId, RequestOptions options) { + return Futures.await(async.withResponse().archive(deploymentId, options)); + } + + public ApiResponse create(DeploymentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(DeploymentCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse retrieve(String deploymentId) { + return retrieve(deploymentId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String deploymentId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(deploymentId, options)); + } + + public ApiResponse list() { + return list(DeploymentListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(DeploymentListParams.builder().build(), options); + } + + public ApiResponse list(DeploymentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + DeploymentListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse pause(String deploymentId) { + return pause(deploymentId, RequestOptions.DEFAULT); + } + + public ApiResponse pause(String deploymentId, RequestOptions options) { + return Futures.await(async.withResponse().pause(deploymentId, options)); + } + + public ApiResponse run(String deploymentId) { + return run(deploymentId, RequestOptions.DEFAULT); + } + + public ApiResponse run(String deploymentId, RequestOptions options) { + return Futures.await(async.withResponse().run(deploymentId, options)); + } + + public ApiResponse search() { + return search(DeploymentSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(DeploymentSearchParams.builder().build(), options); + } + + public ApiResponse search(DeploymentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search( + DeploymentSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse unpause(String deploymentId) { + return unpause(deploymentId, RequestOptions.DEFAULT); + } + + public ApiResponse unpause(String deploymentId, RequestOptions options) { + return Futures.await(async.withResponse().unpause(deploymentId, options)); + } + + public ApiResponse update(String deploymentId, DeploymentUpdateParams params) { + return update(deploymentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String deploymentId, DeploymentUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(deploymentId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Dream.java b/src/main/java/com/qoder/cloudagents/managed/Dream.java new file mode 100644 index 0000000..915b643 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Dream.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Dream extends JsonModel { + public Dream(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Dream fromJson(JsonValue value) { + return new Dream(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public String instructions() { + return optional("instructions", JsonValue::asString); + } + + public String sessionId() { + return optional("session_id", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String endedAt() { + return optional("ended_at", JsonValue::asString); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public List inputs() { + return optionalList("inputs", DreamInput::fromJson); + } + + public List outputs() { + return optionalList("outputs", DreamOutput::fromJson); + } + + public DreamModelConfig model() { + return optional("model", DreamModelConfig::fromJson); + } + + public DreamUsage usage() { + return optional("usage", DreamUsage::fromJson); + } + + public DreamError error() { + return optional("error", DreamError::fromJson); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/DreamCreateParams.java new file mode 100644 index 0000000..1a86862 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamCreateParams.java @@ -0,0 +1,63 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DreamCreateParams extends JsonObject { + private DreamCreateParams(JsonValue value) { + super(value); + } + + public static DreamCreateParams fromJson(JsonValue value) { + return new DreamCreateParams(value); + } + + public List inputs() { + return optionalList("inputs", DreamInput::fromJson); + } + + public DreamModelConfig model() { + return optional("model", DreamModelConfig::fromJson); + } + + public String instructions() { + return optional("instructions", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder inputs(List value) { + return put("inputs", value); + } + + public Builder model(DreamModelConfig value) { + return put("model", value); + } + + public Builder model(String value) { + return put("model", value == null ? null : DreamModelConfig.of(value)); + } + + public Builder instructions(String value) { + return put("instructions", value); + } + + public DreamCreateParams build() { + require("inputs"); + long primary = + json().get("inputs").asArray().stream() + .filter(v -> "memory_store".equals(v.get("type").stringOrNull())) + .count(); + if (primary != 1) + throw new ConfigurationException("Dream requires exactly one memory_store input"); + return new DreamCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamError.java b/src/main/java/com/qoder/cloudagents/managed/DreamError.java new file mode 100644 index 0000000..7a3d24c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamError.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DreamError extends JsonObject { + private DreamError(JsonValue value) { + super(value); + } + + public static DreamError fromJson(JsonValue value) { + return new DreamError(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String code() { + return optional("code", JsonValue::asString); + } + + public String message() { + return optional("message", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamInput.java b/src/main/java/com/qoder/cloudagents/managed/DreamInput.java new file mode 100644 index 0000000..2ccffb5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamInput.java @@ -0,0 +1,58 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DreamInput extends JsonObject { + private DreamInput(JsonValue value) { + super(value); + } + + public static DreamInput fromJson(JsonValue value) { + return new DreamInput(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public List sessionIds() { + return optionalList("session_ids", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder memoryStoreId(String value) { + return put("memory_store_id", value); + } + + public Builder sessionIds(List value) { + return put("session_ids", value); + } + + public DreamInput build() { + require("type"); + String type = json().get("type").asString(); + if ("memory_store".equals(type)) require("memory_store_id"); + else if ("sessions".equals(type)) require("session_ids"); + else + throw new ConfigurationException("Managed Dream inputs must be memory_store or sessions"); + return new DreamInput(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamListParams.java b/src/main/java/com/qoder/cloudagents/managed/DreamListParams.java new file mode 100644 index 0000000..fa930e3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamListParams.java @@ -0,0 +1,46 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class DreamListParams { + private final Map query; + + private DreamListParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public DreamListParams build() { + return new DreamListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamListResponse.java b/src/main/java/com/qoder/cloudagents/managed/DreamListResponse.java new file mode 100644 index 0000000..b42445d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamListResponse.java @@ -0,0 +1,15 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.List; + +/** A non-paginated collection returned by the Managed API. */ +public final class DreamListResponse extends JsonModel { + public DreamListResponse(JsonValue value, String requestId) { + super(value, requestId); + } + + public List data() { + return optionalList("data", v -> new Dream(v, requestId())); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamModelConfig.java b/src/main/java/com/qoder/cloudagents/managed/DreamModelConfig.java new file mode 100644 index 0000000..5f5121d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamModelConfig.java @@ -0,0 +1,86 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.errors.ResponseValidationException; + +/** A model ID string or a structured model configuration; wire shape is preserved. */ +public final class DreamModelConfig implements JsonSerializable { + private final JsonValue value; + + private DreamModelConfig(JsonValue value) { + if (value == null || (!value.isString() && !value.isObject())) + throw new ResponseValidationException("Expected a model string or object"); + this.value = value; + } + + public static DreamModelConfig of(String id) { + if (id == null) throw new ConfigurationException("Model ID must not be null"); + return new DreamModelConfig(JsonValue.of(id)); + } + + public static DreamModelConfig fromJson(JsonValue value) { + return new DreamModelConfig(value); + } + + public static Builder builder() { + return new Builder(); + } + + public boolean isString() { + return value.isString(); + } + + public String id() { + return isString() ? value.asString() : value.get("id").asString(); + } + + public String effort() { + return string("effort"); + } + + public Long contextWindow() { + JsonValue field = field("context_window"); + return field.isMissing() || field.isNull() ? null : field.asLong(); + } + + public JsonValue field(String name) { + return value.get(name); + } + + private String string(String name) { + JsonValue field = field(name); + return field.isMissing() || field.isNull() ? null : field.asString(); + } + + @Override + public JsonValue toJsonValue() { + return value; + } + + @Override + public String toString() { + return "DreamModelConfig"; + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder id(String value) { + return put("id", value); + } + + public Builder effort(String value) { + return put("effort", value); + } + + public Builder contextWindow(Long value) { + return put("context_window", value); + } + + public DreamModelConfig build() { + require("id"); + return new DreamModelConfig(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamOutput.java b/src/main/java/com/qoder/cloudagents/managed/DreamOutput.java new file mode 100644 index 0000000..2be4be5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamOutput.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DreamOutput extends JsonObject { + private DreamOutput(JsonValue value) { + super(value); + } + + public static DreamOutput fromJson(JsonValue value) { + return new DreamOutput(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public List filesTouched() { + return optionalList("files_touched", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/DreamUsage.java b/src/main/java/com/qoder/cloudagents/managed/DreamUsage.java new file mode 100644 index 0000000..56e8504 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/DreamUsage.java @@ -0,0 +1,31 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class DreamUsage extends JsonObject { + private DreamUsage(JsonValue value) { + super(value); + } + + public static DreamUsage fromJson(JsonValue value) { + return new DreamUsage(value); + } + + public Long inputTokens() { + return optional("input_tokens", JsonValue::asLong); + } + + public Long outputTokens() { + return optional("output_tokens", JsonValue::asLong); + } + + public Long cacheCreationInputTokens() { + return optional("cache_creation_input_tokens", JsonValue::asLong); + } + + public Long cacheReadInputTokens() { + return optional("cache_read_input_tokens", JsonValue::asLong); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Dreams.java b/src/main/java/com/qoder/cloudagents/managed/Dreams.java new file mode 100644 index 0000000..a3cc7ce --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Dreams.java @@ -0,0 +1,115 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Dreams { + private final AsyncDreams async; + + public Dreams(AsyncDreams async) { + this.async = async; + } + + public Dream archive(String dreamId) { + return archive(dreamId, RequestOptions.DEFAULT); + } + + public Dream archive(String dreamId, RequestOptions options) { + return Futures.await(async.archive(dreamId, options)); + } + + public Dream cancel(String dreamId) { + return cancel(dreamId, RequestOptions.DEFAULT); + } + + public Dream cancel(String dreamId, RequestOptions options) { + return Futures.await(async.cancel(dreamId, options)); + } + + public Dream create(DreamCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Dream create(DreamCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public Dream retrieve(String dreamId) { + return retrieve(dreamId, RequestOptions.DEFAULT); + } + + public Dream retrieve(String dreamId, RequestOptions options) { + return Futures.await(async.retrieve(dreamId, options)); + } + + public DreamListResponse list() { + return list(DreamListParams.builder().build()); + } + + public DreamListResponse list(RequestOptions options) { + return list(DreamListParams.builder().build(), options); + } + + public DreamListResponse list(DreamListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public DreamListResponse list(DreamListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String dreamId) { + return archive(dreamId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String dreamId, RequestOptions options) { + return Futures.await(async.withResponse().archive(dreamId, options)); + } + + public ApiResponse cancel(String dreamId) { + return cancel(dreamId, RequestOptions.DEFAULT); + } + + public ApiResponse cancel(String dreamId, RequestOptions options) { + return Futures.await(async.withResponse().cancel(dreamId, options)); + } + + public ApiResponse create(DreamCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(DreamCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse retrieve(String dreamId) { + return retrieve(dreamId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String dreamId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(dreamId, options)); + } + + public ApiResponse list() { + return list(DreamListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(DreamListParams.builder().build(), options); + } + + public ApiResponse list(DreamListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(DreamListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Environment.java b/src/main/java/com/qoder/cloudagents/managed/Environment.java new file mode 100644 index 0000000..1cb8380 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Environment.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Environment extends JsonModel { + public Environment(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Environment fromJson(JsonValue value) { + return new Environment(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } + + public EnvironmentConfig config() { + return optional("config", EnvironmentConfig::fromJson); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentConfig.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentConfig.java new file mode 100644 index 0000000..113bc48 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentConfig.java @@ -0,0 +1,61 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class EnvironmentConfig extends JsonObject { + private EnvironmentConfig(JsonValue value) { + super(value); + } + + public static EnvironmentConfig fromJson(JsonValue value) { + return new EnvironmentConfig(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String setupScript() { + return optional("setup_script", JsonValue::asString); + } + + public EnvironmentPackages packages() { + return optional("packages", EnvironmentPackages::fromJson); + } + + public EnvironmentStorage storage() { + return optional("storage", EnvironmentStorage::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder setupScript(String value) { + return put("setup_script", value); + } + + public Builder packages(EnvironmentPackages value) { + return put("packages", value); + } + + public Builder storage(EnvironmentStorage value) { + return put("storage", value); + } + + public EnvironmentConfig build() { + require("type"); + + return new EnvironmentConfig(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentCreateParams.java new file mode 100644 index 0000000..1c4314e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentCreateParams.java @@ -0,0 +1,60 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class EnvironmentCreateParams extends JsonObject { + private EnvironmentCreateParams(JsonValue value) { + super(value); + } + + public static EnvironmentCreateParams fromJson(JsonValue value) { + return new EnvironmentCreateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public EnvironmentConfig config() { + return optional("config", EnvironmentConfig::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder config(EnvironmentConfig value) { + return put("config", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public EnvironmentCreateParams build() { + require("name"); + return new EnvironmentCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentListParams.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentListParams.java new file mode 100644 index 0000000..71b813d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentListParams.java @@ -0,0 +1,63 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class EnvironmentListParams { + private final Map query; + + private EnvironmentListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public EnvironmentListParams build() { + return new EnvironmentListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentListResponse.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentListResponse.java new file mode 100644 index 0000000..0f331c1 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class EnvironmentListResponse + extends CursorPage { + public EnvironmentListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + EnvironmentListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Environment(item, requestId), true); + } + + @Override + protected EnvironmentListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentPackages.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentPackages.java new file mode 100644 index 0000000..deccd7d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentPackages.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class EnvironmentPackages extends JsonObject { + private EnvironmentPackages(JsonValue value) { + super(value); + } + + public static EnvironmentPackages fromJson(JsonValue value) { + return new EnvironmentPackages(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public List apt() { + return optionalList("apt", JsonValue::asString); + } + + public List npm() { + return optionalList("npm", JsonValue::asString); + } + + public List pip() { + return optionalList("pip", JsonValue::asString); + } + + public List cargo() { + return optionalList("cargo", JsonValue::asString); + } + + public List gem() { + return optionalList("gem", JsonValue::asString); + } + + public List go() { + return optionalList("go", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder apt(List value) { + return put("apt", value); + } + + public Builder npm(List value) { + return put("npm", value); + } + + public Builder pip(List value) { + return put("pip", value); + } + + public EnvironmentPackages build() { + return new EnvironmentPackages(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentSearchParams.java new file mode 100644 index 0000000..e6cfb5c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentSearchParams.java @@ -0,0 +1,91 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class EnvironmentSearchParams extends JsonObject { + private EnvironmentSearchParams(JsonValue value) { + super(value); + } + + public static EnvironmentSearchParams fromJson(JsonValue value) { + return new EnvironmentSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public String createdAtGte() { + return optional("created_at[gte]", JsonValue::asString); + } + + public String createdAtLte() { + return optional("created_at[lte]", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + public EnvironmentSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new EnvironmentSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorage.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorage.java new file mode 100644 index 0000000..3e48cd7 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorage.java @@ -0,0 +1,36 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class EnvironmentStorage extends JsonObject { + private EnvironmentStorage(JsonValue value) { + super(value); + } + + public static EnvironmentStorage fromJson(JsonValue value) { + return new EnvironmentStorage(value); + } + + public List buckets() { + return optionalList("buckets", EnvironmentStorageBucket::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder buckets(List value) { + return put("buckets", value); + } + + public EnvironmentStorage build() { + + return new EnvironmentStorage(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageBucket.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageBucket.java new file mode 100644 index 0000000..8eac6b1 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageBucket.java @@ -0,0 +1,93 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class EnvironmentStorageBucket extends JsonObject { + private EnvironmentStorageBucket(JsonValue value) { + super(value); + } + + public static EnvironmentStorageBucket fromJson(JsonValue value) { + return new EnvironmentStorageBucket(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String provider() { + return optional("provider", JsonValue::asString); + } + + public String region() { + return optional("region", JsonValue::asString); + } + + public String bucket() { + return optional("bucket", JsonValue::asString); + } + + public String prefix() { + return optional("prefix", JsonValue::asString); + } + + public String access() { + return optional("access", JsonValue::asString); + } + + public String acceleratorEndpoint() { + return optional("accelerator_endpoint", JsonValue::asString); + } + + public EnvironmentStorageCredential credential() { + return optional("credential", EnvironmentStorageCredential::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder provider(String value) { + return put("provider", value); + } + + public Builder region(String value) { + return put("region", value); + } + + public Builder bucket(String value) { + return put("bucket", value); + } + + public Builder prefix(String value) { + return put("prefix", value); + } + + public Builder access(String value) { + return put("access", value); + } + + public Builder acceleratorEndpoint(String value) { + return put("accelerator_endpoint", value); + } + + public Builder credential(EnvironmentStorageCredential value) { + return put("credential", value); + } + + public EnvironmentStorageBucket build() { + require("name", "provider", "region", "bucket"); + + return new EnvironmentStorageBucket(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageCredential.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageCredential.java new file mode 100644 index 0000000..b964531 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentStorageCredential.java @@ -0,0 +1,61 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class EnvironmentStorageCredential extends JsonObject { + private EnvironmentStorageCredential(JsonValue value) { + super(value); + } + + public static EnvironmentStorageCredential fromJson(JsonValue value) { + return new EnvironmentStorageCredential(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String roleArn() { + return optional("role_arn", JsonValue::asString); + } + + public String accessKeyId() { + return optional("access_key_id", JsonValue::asString); + } + + public String accessKeySecret() { + return optional("access_key_secret", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder roleArn(String value) { + return put("role_arn", value); + } + + public Builder accessKeyId(String value) { + return put("access_key_id", value); + } + + public Builder accessKeySecret(String value) { + return put("access_key_secret", value); + } + + public EnvironmentStorageCredential build() { + require("type"); + + return new EnvironmentStorageCredential(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentUpdateParams.java new file mode 100644 index 0000000..5782394 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentUpdateParams.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class EnvironmentUpdateParams extends JsonObject { + private EnvironmentUpdateParams(JsonValue value) { + super(value); + } + + public static EnvironmentUpdateParams fromJson(JsonValue value) { + return new EnvironmentUpdateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public EnvironmentConfig config() { + return optional("config", EnvironmentConfig::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder config(EnvironmentConfig value) { + return put("config", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public EnvironmentUpdateParams build() { + return new EnvironmentUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EnvironmentWork.java b/src/main/java/com/qoder/cloudagents/managed/EnvironmentWork.java new file mode 100644 index 0000000..33435e9 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EnvironmentWork.java @@ -0,0 +1,224 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class EnvironmentWork { + private final AsyncEnvironmentWork async; + + public EnvironmentWork(AsyncEnvironmentWork async) { + this.async = async; + } + + public WorkItem ack(String environmentId, String workId) { + return ack(environmentId, workId, RequestOptions.DEFAULT); + } + + public WorkItem ack(String environmentId, String workId, RequestOptions options) { + return Futures.await(async.ack(environmentId, workId, options)); + } + + public WorkItem retrieve(String environmentId, String workId) { + return retrieve(environmentId, workId, RequestOptions.DEFAULT); + } + + public WorkItem retrieve(String environmentId, String workId, RequestOptions options) { + return Futures.await(async.retrieve(environmentId, workId, options)); + } + + public WorkHeartbeat heartbeat(String environmentId, String workId) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build()); + } + + public WorkHeartbeat heartbeat(String environmentId, String workId, RequestOptions options) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build(), options); + } + + public WorkHeartbeat heartbeat(String environmentId, String workId, WorkHeartbeatParams params) { + return heartbeat(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public WorkHeartbeat heartbeat( + String environmentId, String workId, WorkHeartbeatParams params, RequestOptions options) { + return Futures.await(async.heartbeat(environmentId, workId, params, options)); + } + + public WorkListResponse list(String environmentId) { + return list(environmentId, WorkListParams.builder().build()); + } + + public WorkListResponse list(String environmentId, RequestOptions options) { + return list(environmentId, WorkListParams.builder().build(), options); + } + + public WorkListResponse list(String environmentId, WorkListParams params) { + return list(environmentId, params, RequestOptions.DEFAULT); + } + + public WorkListResponse list( + String environmentId, WorkListParams params, RequestOptions options) { + return Futures.await(async.list(environmentId, params, options)); + } + + public WorkItem poll(String environmentId) { + return poll(environmentId, WorkPollParams.builder().build()); + } + + public WorkItem poll(String environmentId, RequestOptions options) { + return poll(environmentId, WorkPollParams.builder().build(), options); + } + + public WorkItem poll(String environmentId, WorkPollParams params) { + return poll(environmentId, params, RequestOptions.DEFAULT); + } + + public WorkItem poll(String environmentId, WorkPollParams params, RequestOptions options) { + return Futures.await(async.poll(environmentId, params, options)); + } + + public WorkQueueStats stats(String environmentId) { + return stats(environmentId, RequestOptions.DEFAULT); + } + + public WorkQueueStats stats(String environmentId, RequestOptions options) { + return Futures.await(async.stats(environmentId, options)); + } + + public WorkItem stop(String environmentId, String workId) { + return stop(environmentId, workId, WorkStopParams.builder().build()); + } + + public WorkItem stop(String environmentId, String workId, RequestOptions options) { + return stop(environmentId, workId, WorkStopParams.builder().build(), options); + } + + public WorkItem stop(String environmentId, String workId, WorkStopParams params) { + return stop(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public WorkItem stop( + String environmentId, String workId, WorkStopParams params, RequestOptions options) { + return Futures.await(async.stop(environmentId, workId, params, options)); + } + + public WorkItem update(String environmentId, String workId, WorkUpdateParams params) { + return update(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public WorkItem update( + String environmentId, String workId, WorkUpdateParams params, RequestOptions options) { + return Futures.await(async.update(environmentId, workId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse ack(String environmentId, String workId) { + return ack(environmentId, workId, RequestOptions.DEFAULT); + } + + public ApiResponse ack(String environmentId, String workId, RequestOptions options) { + return Futures.await(async.withResponse().ack(environmentId, workId, options)); + } + + public ApiResponse retrieve(String environmentId, String workId) { + return retrieve(environmentId, workId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String environmentId, String workId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(environmentId, workId, options)); + } + + public ApiResponse heartbeat(String environmentId, String workId) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build()); + } + + public ApiResponse heartbeat( + String environmentId, String workId, RequestOptions options) { + return heartbeat(environmentId, workId, WorkHeartbeatParams.builder().build(), options); + } + + public ApiResponse heartbeat( + String environmentId, String workId, WorkHeartbeatParams params) { + return heartbeat(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public ApiResponse heartbeat( + String environmentId, String workId, WorkHeartbeatParams params, RequestOptions options) { + return Futures.await(async.withResponse().heartbeat(environmentId, workId, params, options)); + } + + public ApiResponse list(String environmentId) { + return list(environmentId, WorkListParams.builder().build()); + } + + public ApiResponse list(String environmentId, RequestOptions options) { + return list(environmentId, WorkListParams.builder().build(), options); + } + + public ApiResponse list(String environmentId, WorkListParams params) { + return list(environmentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String environmentId, WorkListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(environmentId, params, options)); + } + + public ApiResponse poll(String environmentId) { + return poll(environmentId, WorkPollParams.builder().build()); + } + + public ApiResponse poll(String environmentId, RequestOptions options) { + return poll(environmentId, WorkPollParams.builder().build(), options); + } + + public ApiResponse poll(String environmentId, WorkPollParams params) { + return poll(environmentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse poll( + String environmentId, WorkPollParams params, RequestOptions options) { + return Futures.await(async.withResponse().poll(environmentId, params, options)); + } + + public ApiResponse stats(String environmentId) { + return stats(environmentId, RequestOptions.DEFAULT); + } + + public ApiResponse stats(String environmentId, RequestOptions options) { + return Futures.await(async.withResponse().stats(environmentId, options)); + } + + public ApiResponse stop(String environmentId, String workId) { + return stop(environmentId, workId, WorkStopParams.builder().build()); + } + + public ApiResponse stop(String environmentId, String workId, RequestOptions options) { + return stop(environmentId, workId, WorkStopParams.builder().build(), options); + } + + public ApiResponse stop(String environmentId, String workId, WorkStopParams params) { + return stop(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public ApiResponse stop( + String environmentId, String workId, WorkStopParams params, RequestOptions options) { + return Futures.await(async.withResponse().stop(environmentId, workId, params, options)); + } + + public ApiResponse update( + String environmentId, String workId, WorkUpdateParams params) { + return update(environmentId, workId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String environmentId, String workId, WorkUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(environmentId, workId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Environments.java b/src/main/java/com/qoder/cloudagents/managed/Environments.java new file mode 100644 index 0000000..29d0d4b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Environments.java @@ -0,0 +1,171 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Environments { + private final AsyncEnvironments async; + + public Environments(AsyncEnvironments async) { + this.async = async; + } + + public EnvironmentWork work() { + return new EnvironmentWork(async.work()); + } + + public Environment archive(String environmentId) { + return archive(environmentId, RequestOptions.DEFAULT); + } + + public Environment archive(String environmentId, RequestOptions options) { + return Futures.await(async.archive(environmentId, options)); + } + + public Environment create(EnvironmentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Environment create(EnvironmentCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public DeletedEnvironment delete(String environmentId) { + return delete(environmentId, RequestOptions.DEFAULT); + } + + public DeletedEnvironment delete(String environmentId, RequestOptions options) { + return Futures.await(async.delete(environmentId, options)); + } + + public Environment retrieve(String environmentId) { + return retrieve(environmentId, RequestOptions.DEFAULT); + } + + public Environment retrieve(String environmentId, RequestOptions options) { + return Futures.await(async.retrieve(environmentId, options)); + } + + public EnvironmentListResponse list() { + return list(EnvironmentListParams.builder().build()); + } + + public EnvironmentListResponse list(RequestOptions options) { + return list(EnvironmentListParams.builder().build(), options); + } + + public EnvironmentListResponse list(EnvironmentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public EnvironmentListResponse list(EnvironmentListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public EnvironmentListResponse search() { + return search(EnvironmentSearchParams.builder().build()); + } + + public EnvironmentListResponse search(RequestOptions options) { + return search(EnvironmentSearchParams.builder().build(), options); + } + + public EnvironmentListResponse search(EnvironmentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public EnvironmentListResponse search(EnvironmentSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public Environment update(String environmentId, EnvironmentUpdateParams params) { + return update(environmentId, params, RequestOptions.DEFAULT); + } + + public Environment update( + String environmentId, EnvironmentUpdateParams params, RequestOptions options) { + return Futures.await(async.update(environmentId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String environmentId) { + return archive(environmentId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String environmentId, RequestOptions options) { + return Futures.await(async.withResponse().archive(environmentId, options)); + } + + public ApiResponse create(EnvironmentCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(EnvironmentCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse delete(String environmentId) { + return delete(environmentId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String environmentId, RequestOptions options) { + return Futures.await(async.withResponse().delete(environmentId, options)); + } + + public ApiResponse retrieve(String environmentId) { + return retrieve(environmentId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String environmentId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(environmentId, options)); + } + + public ApiResponse list() { + return list(EnvironmentListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(EnvironmentListParams.builder().build(), options); + } + + public ApiResponse list(EnvironmentListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + EnvironmentListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse search() { + return search(EnvironmentSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(EnvironmentSearchParams.builder().build(), options); + } + + public ApiResponse search(EnvironmentSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search( + EnvironmentSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse update(String environmentId, EnvironmentUpdateParams params) { + return update(environmentId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String environmentId, EnvironmentUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(environmentId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/EventContent.java b/src/main/java/com/qoder/cloudagents/managed/EventContent.java new file mode 100644 index 0000000..3a8a15e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/EventContent.java @@ -0,0 +1,63 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.errors.ResponseValidationException; +import java.util.*; +import java.util.stream.Collectors; + +/** Text or content blocks. Use text() for a user.message's required content-block array. */ +public final class EventContent implements JsonSerializable { + private final JsonValue value; + + private EventContent(JsonValue value) { + if (value == null || (!value.isString() && !value.isArray())) + throw new ResponseValidationException("Expected event content string or array"); + this.value = value; + } + + public static EventContent fromJson(JsonValue value) { + return new EventContent(value); + } + + public static EventContent blocks(List value) { + if (value == null || value.stream().anyMatch(Objects::isNull)) + throw new ConfigurationException("Content blocks must not be null"); + return fromJson(JsonValue.of(value)); + } + + public static EventContent text(String text) { + if (text == null) throw new ConfigurationException("Text must not be null"); + return blocks( + Collections.singletonList(ContentBlock.builder().type("text").text(text).build())); + } + + /** String content for event types that accept it; user.message requires blocks instead. */ + public static EventContent ofString(String text) { + if (text == null) throw new ConfigurationException("Text must not be null"); + return fromJson(JsonValue.of(text)); + } + + public boolean isString() { + return value.isString(); + } + + public String asString() { + return value.asString(); + } + + public List asBlocks() { + return Collections.unmodifiableList( + value.asArray().stream().map(ContentBlock::fromJson).collect(Collectors.toList())); + } + + @Override + public JsonValue toJsonValue() { + return value; + } + + @Override + public String toString() { + return "EventContent"; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileDownloadUrl.java b/src/main/java/com/qoder/cloudagents/managed/FileDownloadUrl.java new file mode 100644 index 0000000..274246f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileDownloadUrl.java @@ -0,0 +1,23 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class FileDownloadUrl extends JsonModel { + public FileDownloadUrl(JsonValue value, String requestId) { + super(value, requestId); + } + + public String url() { + return optional("url", JsonValue::asString); + } + + public String expiresAt() { + return optional("expires_at", JsonValue::asString); + } + + public String filename() { + return optional("filename", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileListParams.java b/src/main/java/com/qoder/cloudagents/managed/FileListParams.java new file mode 100644 index 0000000..ba75317 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileListParams.java @@ -0,0 +1,69 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class FileListParams { + private final Map query; + + private FileListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + if (cursors > 0 && b.values.containsKey("scope_id")) + throw new ConfigurationException("scopeId cannot be combined with cursors"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder scopeId(String value) { + return put("scope_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public FileListParams build() { + return new FileListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileListResponse.java b/src/main/java/com/qoder/cloudagents/managed/FileListResponse.java new file mode 100644 index 0000000..5d261b6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class FileListResponse extends CursorPage { + public FileListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + FileListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new FileMetadata(item, requestId), true); + } + + @Override + protected FileListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileMetadata.java b/src/main/java/com/qoder/cloudagents/managed/FileMetadata.java new file mode 100644 index 0000000..83c67ec --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileMetadata.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class FileMetadata extends JsonModel { + public FileMetadata(JsonValue value, String requestId) { + super(value, requestId); + } + + public static FileMetadata fromJson(JsonValue value) { + return new FileMetadata(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String filename() { + return optional("filename", JsonValue::asString); + } + + public String mimeType() { + return optional("mime_type", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public FileScope scope() { + return optional("scope", FileScope::fromJson); + } + + public Long sizeBytes() { + return optional("size_bytes", JsonValue::asLong); + } + + public Boolean downloadable() { + return optional("downloadable", JsonValue::asBoolean); + } + + public Map metadata() { + return optionalNullableMap("metadata", v -> v); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileScope.java b/src/main/java/com/qoder/cloudagents/managed/FileScope.java new file mode 100644 index 0000000..bdafbf5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileScope.java @@ -0,0 +1,22 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; + +/** The resource to which a file belongs. */ +public final class FileScope extends JsonObject { + private FileScope(JsonValue value) { + super(value); + } + + public static FileScope fromJson(JsonValue value) { + return new FileScope(value); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/FileSearchParams.java new file mode 100644 index 0000000..9a3934f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileSearchParams.java @@ -0,0 +1,75 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class FileSearchParams extends JsonObject { + private FileSearchParams(JsonValue value) { + super(value); + } + + public static FileSearchParams fromJson(JsonValue value) { + return new FileSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String scopeId() { + return optional("scope_id", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder scopeId(String value) { + return put("scope_id", value); + } + + public FileSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new FileSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/FileUploadParams.java b/src/main/java/com/qoder/cloudagents/managed/FileUploadParams.java new file mode 100644 index 0000000..67881c4 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/FileUploadParams.java @@ -0,0 +1,61 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.Map; + +/** Multipart fields and an upload source; headers/query are supplied through RequestOptions. */ +public final class FileUploadParams { + private final Upload file; + private final JsonValue fields; + + private FileUploadParams(Upload file, JsonValue fields) { + this.file = file; + this.fields = fields; + } + + public Upload file() { + return file; + } + + public JsonValue fields() { + return fields; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Upload file; + + public Builder file(Upload value) { + file = value; + return this; + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder metadata(JsonValue value) { + return put("metadata", value); + } + + public FileUploadParams build() { + if (file == null) throw new ConfigurationException("Upload file is required"); + if (!json().get("file").isMissing()) + throw new ConfigurationException("Use file(Upload) for the multipart file"); + return new FileUploadParams(file, json()); + } + } + + @Override + public String toString() { + return "FileUploadParams([redacted])"; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Files.java b/src/main/java/com/qoder/cloudagents/managed/Files.java new file mode 100644 index 0000000..491cc80 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Files.java @@ -0,0 +1,154 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; + +public final class Files { + private final AsyncFiles async; + + public Files(AsyncFiles async) { + this.async = async; + } + + public FileListResponse list() { + return list(FileListParams.builder().build()); + } + + public FileListResponse list(FileListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public FileListResponse list(FileListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public FileMetadata upload(FileUploadParams params) { + return upload(params, RequestOptions.DEFAULT); + } + + public FileMetadata upload(FileUploadParams params, RequestOptions options) { + return Futures.await(async.upload(params, options)); + } + + public FileMetadata getMetadata(String fileId) { + return getMetadata(fileId, RequestOptions.DEFAULT); + } + + public FileMetadata getMetadata(String fileId, RequestOptions options) { + return Futures.await(async.getMetadata(fileId, options)); + } + + public DeletedFile delete(String fileId) { + return delete(fileId, RequestOptions.DEFAULT); + } + + public DeletedFile delete(String fileId, RequestOptions options) { + return Futures.await(async.delete(fileId, options)); + } + + public FileDownloadUrl getDownloadUrl(String fileId) { + return getDownloadUrl(fileId, RequestOptions.DEFAULT); + } + + public FileDownloadUrl getDownloadUrl(String fileId, RequestOptions options) { + return Futures.await(async.getDownloadUrl(fileId, options)); + } + + public FileDownload download(String fileId) { + return download(fileId, RequestOptions.DEFAULT); + } + + public FileDownload download(String fileId, RequestOptions options) { + return Futures.await(async.download(fileId, options)); + } + + public FileListResponse search(FileSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public FileListResponse search(FileSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public FileListResponse search() { + return search(FileSearchParams.builder().build()); + } + + public FileListResponse search(RequestOptions options) { + return search(FileSearchParams.builder().build(), options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse search() { + return search(FileSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(FileSearchParams.builder().build(), options); + } + + public ApiResponse search(FileSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search(FileSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse list() { + return list(FileListParams.builder().build()); + } + + public ApiResponse list(FileListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(FileListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse upload(FileUploadParams params) { + return upload(params, RequestOptions.DEFAULT); + } + + public ApiResponse upload(FileUploadParams params, RequestOptions options) { + return Futures.await(async.withResponse().upload(params, options)); + } + + public ApiResponse getMetadata(String fileId) { + return getMetadata(fileId, RequestOptions.DEFAULT); + } + + public ApiResponse getMetadata(String fileId, RequestOptions options) { + return Futures.await(async.withResponse().getMetadata(fileId, options)); + } + + public ApiResponse delete(String fileId) { + return delete(fileId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String fileId, RequestOptions options) { + return Futures.await(async.withResponse().delete(fileId, options)); + } + + public ApiResponse getDownloadUrl(String fileId) { + return getDownloadUrl(fileId, RequestOptions.DEFAULT); + } + + public ApiResponse getDownloadUrl(String fileId, RequestOptions options) { + return Futures.await(async.withResponse().getDownloadUrl(fileId, options)); + } + + public ApiResponse download(String fileId) { + return download(fileId, RequestOptions.DEFAULT); + } + + public ApiResponse download(String fileId, RequestOptions options) { + return Futures.await(async.withResponse().download(fileId, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/ImageSource.java b/src/main/java/com/qoder/cloudagents/managed/ImageSource.java new file mode 100644 index 0000000..021daed --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/ImageSource.java @@ -0,0 +1,68 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class ImageSource extends JsonObject { + private ImageSource(JsonValue value) { + super(value); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public static ImageSource fromJson(JsonValue value) { + return new ImageSource(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String mediaType() { + return optional("media_type", JsonValue::asString); + } + + public String data() { + return optional("data", JsonValue::asString); + } + + public String url() { + return optional("url", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder mediaType(String value) { + return put("media_type", value); + } + + public Builder data(String value) { + return put("data", value); + } + + public Builder url(String value) { + return put("url", value); + } + + public Builder fileId(String value) { + return put("file_id", value); + } + + public ImageSource build() { + require("type"); + return new ImageSource(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MCPServer.java b/src/main/java/com/qoder/cloudagents/managed/MCPServer.java new file mode 100644 index 0000000..959a17f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MCPServer.java @@ -0,0 +1,53 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; + +/** Immutable MCPServer configuration. Unknown fields are retained through field(). */ +public final class MCPServer extends JsonObject { + private MCPServer(JsonValue value) { + super(value); + } + + public static MCPServer fromJson(JsonValue value) { + return new MCPServer(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String url() { + return optional("url", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder url(String value) { + return put("url", value); + } + + public Builder type(String value) { + return put("type", value); + } + + public MCPServer build() { + require("name", "url"); + return new MCPServer(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Memories.java b/src/main/java/com/qoder/cloudagents/managed/Memories.java new file mode 100644 index 0000000..68eb67d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Memories.java @@ -0,0 +1,123 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Memories { + private final AsyncMemories async; + + public Memories(AsyncMemories async) { + this.async = async; + } + + public Memory create(String memoryStoreId, MemoryCreateParams params) { + return create(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public Memory create(String memoryStoreId, MemoryCreateParams params, RequestOptions options) { + return Futures.await(async.create(memoryStoreId, params, options)); + } + + public DeletedMemory delete(String memoryStoreId, String memoryId) { + return delete(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public DeletedMemory delete(String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.await(async.delete(memoryStoreId, memoryId, options)); + } + + public Memory retrieve(String memoryStoreId, String memoryId) { + return retrieve(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public Memory retrieve(String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.await(async.retrieve(memoryStoreId, memoryId, options)); + } + + public MemoryListResponse list(String memoryStoreId) { + return list(memoryStoreId, MemoryListParams.builder().build()); + } + + public MemoryListResponse list(String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryListParams.builder().build(), options); + } + + public MemoryListResponse list(String memoryStoreId, MemoryListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public MemoryListResponse list( + String memoryStoreId, MemoryListParams params, RequestOptions options) { + return Futures.await(async.list(memoryStoreId, params, options)); + } + + public Memory update(String memoryStoreId, String memoryId, MemoryUpdateParams params) { + return update(memoryStoreId, memoryId, params, RequestOptions.DEFAULT); + } + + public Memory update( + String memoryStoreId, String memoryId, MemoryUpdateParams params, RequestOptions options) { + return Futures.await(async.update(memoryStoreId, memoryId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse create(String memoryStoreId, MemoryCreateParams params) { + return create(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public ApiResponse create( + String memoryStoreId, MemoryCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(memoryStoreId, params, options)); + } + + public ApiResponse delete(String memoryStoreId, String memoryId) { + return delete(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public ApiResponse delete( + String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.await(async.withResponse().delete(memoryStoreId, memoryId, options)); + } + + public ApiResponse retrieve(String memoryStoreId, String memoryId) { + return retrieve(memoryStoreId, memoryId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String memoryStoreId, String memoryId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(memoryStoreId, memoryId, options)); + } + + public ApiResponse list(String memoryStoreId) { + return list(memoryStoreId, MemoryListParams.builder().build()); + } + + public ApiResponse list(String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryListParams.builder().build(), options); + } + + public ApiResponse list(String memoryStoreId, MemoryListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String memoryStoreId, MemoryListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(memoryStoreId, params, options)); + } + + public ApiResponse update( + String memoryStoreId, String memoryId, MemoryUpdateParams params) { + return update(memoryStoreId, memoryId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String memoryStoreId, String memoryId, MemoryUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(memoryStoreId, memoryId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Memory.java b/src/main/java/com/qoder/cloudagents/managed/Memory.java new file mode 100644 index 0000000..540b21e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Memory.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.Map; + +/** Immutable API response; unknown fields are preserved. */ +public final class Memory extends JsonModel { + public Memory(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public Long version() { + return optional("version", JsonValue::asLong); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public String path() { + return optional("path", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public Long contentSizeBytes() { + return optional("content_size_bytes", JsonValue::asLong); + } + + public String contentSha256() { + return optional("content_sha256", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryCreateParams.java new file mode 100644 index 0000000..476995d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryCreateParams.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.Map; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class MemoryCreateParams extends JsonObject { + private MemoryCreateParams(JsonValue value) { + super(value); + } + + public static MemoryCreateParams fromJson(JsonValue value) { + return new MemoryCreateParams(value); + } + + public String path() { + return optional("path", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder path(String value) { + return put("path", value); + } + + public Builder content(String value) { + return put("content", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public MemoryCreateParams build() { + require("path"); + if (!json().get("content").isString()) + throw new ConfigurationException("content must be a non-null string (empty is allowed)"); + return new MemoryCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryListParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryListParams.java new file mode 100644 index 0000000..231cfc6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryListParams.java @@ -0,0 +1,40 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class MemoryListParams { + private final Map query; + + private MemoryListParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder pathPrefix(String value) { + return put("path_prefix", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public MemoryListParams build() { + return new MemoryListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryListResponse.java b/src/main/java/com/qoder/cloudagents/managed/MemoryListResponse.java new file mode 100644 index 0000000..f3ed6c5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class MemoryListResponse extends CursorPage { + public MemoryListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + MemoryListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Memory(item, requestId), true); + } + + @Override + protected MemoryListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStore.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStore.java new file mode 100644 index 0000000..f3c73cf --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStore.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class MemoryStore extends JsonModel { + public MemoryStore(JsonValue value, String requestId) { + super(value, requestId); + } + + public static MemoryStore fromJson(JsonValue value) { + return new MemoryStore(value, null); + } + + public Long entryCount() { + return optional("entry_count", JsonValue::asLong); + } + + public Long totalSize() { + return optional("total_size", JsonValue::asLong); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStoreCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreCreateParams.java new file mode 100644 index 0000000..2dcaf2c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreCreateParams.java @@ -0,0 +1,53 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class MemoryStoreCreateParams extends JsonObject { + private MemoryStoreCreateParams(JsonValue value) { + super(value); + } + + public static MemoryStoreCreateParams fromJson(JsonValue value) { + return new MemoryStoreCreateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public MemoryStoreCreateParams build() { + require("name"); + + return new MemoryStoreCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListParams.java new file mode 100644 index 0000000..848c721 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListParams.java @@ -0,0 +1,75 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class MemoryStoreListParams { + private final Map query; + + private MemoryStoreListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public MemoryStoreListParams build() { + return new MemoryStoreListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListResponse.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListResponse.java new file mode 100644 index 0000000..1f21f7a --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class MemoryStoreListResponse + extends CursorPage { + public MemoryStoreListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + MemoryStoreListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new MemoryStore(item, requestId), true); + } + + @Override + protected MemoryStoreListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStoreSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreSearchParams.java new file mode 100644 index 0000000..9b0ee61 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreSearchParams.java @@ -0,0 +1,91 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class MemoryStoreSearchParams extends JsonObject { + private MemoryStoreSearchParams(JsonValue value) { + super(value); + } + + public static MemoryStoreSearchParams fromJson(JsonValue value) { + return new MemoryStoreSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public String createdAtGte() { + return optional("created_at[gte]", JsonValue::asString); + } + + public String createdAtLte() { + return optional("created_at[lte]", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + public MemoryStoreSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new MemoryStoreSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStoreUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreUpdateParams.java new file mode 100644 index 0000000..bd1dd06 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStoreUpdateParams.java @@ -0,0 +1,52 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class MemoryStoreUpdateParams extends JsonObject { + private MemoryStoreUpdateParams(JsonValue value) { + super(value); + } + + public static MemoryStoreUpdateParams fromJson(JsonValue value) { + return new MemoryStoreUpdateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public MemoryStoreUpdateParams build() { + + return new MemoryStoreUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryStores.java b/src/main/java/com/qoder/cloudagents/managed/MemoryStores.java new file mode 100644 index 0000000..572e9ae --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryStores.java @@ -0,0 +1,175 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class MemoryStores { + private final AsyncMemoryStores async; + + public MemoryStores(AsyncMemoryStores async) { + this.async = async; + } + + public Memories memories() { + return new Memories(async.memories()); + } + + public MemoryVersions versions() { + return new MemoryVersions(async.versions()); + } + + public MemoryStore archive(String memoryStoreId) { + return archive(memoryStoreId, RequestOptions.DEFAULT); + } + + public MemoryStore archive(String memoryStoreId, RequestOptions options) { + return Futures.await(async.archive(memoryStoreId, options)); + } + + public MemoryStore create(MemoryStoreCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public MemoryStore create(MemoryStoreCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public DeletedMemoryStore delete(String memoryStoreId) { + return delete(memoryStoreId, RequestOptions.DEFAULT); + } + + public DeletedMemoryStore delete(String memoryStoreId, RequestOptions options) { + return Futures.await(async.delete(memoryStoreId, options)); + } + + public MemoryStore retrieve(String memoryStoreId) { + return retrieve(memoryStoreId, RequestOptions.DEFAULT); + } + + public MemoryStore retrieve(String memoryStoreId, RequestOptions options) { + return Futures.await(async.retrieve(memoryStoreId, options)); + } + + public MemoryStoreListResponse list() { + return list(MemoryStoreListParams.builder().build()); + } + + public MemoryStoreListResponse list(RequestOptions options) { + return list(MemoryStoreListParams.builder().build(), options); + } + + public MemoryStoreListResponse list(MemoryStoreListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public MemoryStoreListResponse list(MemoryStoreListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public MemoryStoreListResponse search() { + return search(MemoryStoreSearchParams.builder().build()); + } + + public MemoryStoreListResponse search(RequestOptions options) { + return search(MemoryStoreSearchParams.builder().build(), options); + } + + public MemoryStoreListResponse search(MemoryStoreSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public MemoryStoreListResponse search(MemoryStoreSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public MemoryStore update(String memoryStoreId, MemoryStoreUpdateParams params) { + return update(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public MemoryStore update( + String memoryStoreId, MemoryStoreUpdateParams params, RequestOptions options) { + return Futures.await(async.update(memoryStoreId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String memoryStoreId) { + return archive(memoryStoreId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String memoryStoreId, RequestOptions options) { + return Futures.await(async.withResponse().archive(memoryStoreId, options)); + } + + public ApiResponse create(MemoryStoreCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(MemoryStoreCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse delete(String memoryStoreId) { + return delete(memoryStoreId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String memoryStoreId, RequestOptions options) { + return Futures.await(async.withResponse().delete(memoryStoreId, options)); + } + + public ApiResponse retrieve(String memoryStoreId) { + return retrieve(memoryStoreId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String memoryStoreId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(memoryStoreId, options)); + } + + public ApiResponse list() { + return list(MemoryStoreListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(MemoryStoreListParams.builder().build(), options); + } + + public ApiResponse list(MemoryStoreListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + MemoryStoreListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse search() { + return search(MemoryStoreSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(MemoryStoreSearchParams.builder().build(), options); + } + + public ApiResponse search(MemoryStoreSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search( + MemoryStoreSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse update(String memoryStoreId, MemoryStoreUpdateParams params) { + return update(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String memoryStoreId, MemoryStoreUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(memoryStoreId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryUpdateParams.java new file mode 100644 index 0000000..bf16c15 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryUpdateParams.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.Map; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class MemoryUpdateParams extends JsonObject { + private MemoryUpdateParams(JsonValue value) { + super(value); + } + + public static MemoryUpdateParams fromJson(JsonValue value) { + return new MemoryUpdateParams(value); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public String contentSha256() { + return optional("content_sha256", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder content(String value) { + return put("content", value); + } + + public Builder contentSha256(String value) { + return put("content_sha256", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public MemoryUpdateParams build() { + + if (!json().get("content").isString()) + throw new ConfigurationException("content must be a non-null string (empty is allowed)"); + return new MemoryUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryVersion.java b/src/main/java/com/qoder/cloudagents/managed/MemoryVersion.java new file mode 100644 index 0000000..fd52dc7 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryVersion.java @@ -0,0 +1,58 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class MemoryVersion extends JsonModel { + public MemoryVersion(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return field("id").asString(); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public String memoryId() { + return optional("memory_id", JsonValue::asString); + } + + public String path() { + return optional("path", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public Long contentSizeBytes() { + return optional("content_size_bytes", JsonValue::asLong); + } + + public String contentSha256() { + return optional("content_sha256", JsonValue::asString); + } + + public String operation() { + return optional("operation", JsonValue::asString); + } + + public Boolean redacted() { + return optional("redacted", JsonValue::asBoolean); + } + + public String redactedAt() { + return optional("redacted_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListParams.java b/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListParams.java new file mode 100644 index 0000000..a7af05b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListParams.java @@ -0,0 +1,40 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class MemoryVersionListParams { + private final Map query; + + private MemoryVersionListParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder memoryId(String value) { + return put("memory_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public MemoryVersionListParams build() { + return new MemoryVersionListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListResponse.java b/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListResponse.java new file mode 100644 index 0000000..0ef823c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryVersionListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class MemoryVersionListResponse + extends CursorPage { + public MemoryVersionListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + MemoryVersionListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new MemoryVersion(item, requestId), true); + } + + @Override + protected MemoryVersionListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MemoryVersions.java b/src/main/java/com/qoder/cloudagents/managed/MemoryVersions.java new file mode 100644 index 0000000..725bbcf --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MemoryVersions.java @@ -0,0 +1,91 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class MemoryVersions { + private final AsyncMemoryVersions async; + + public MemoryVersions(AsyncMemoryVersions async) { + this.async = async; + } + + public MemoryVersion retrieve(String memoryStoreId, String memoryVersionId) { + return retrieve(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public MemoryVersion retrieve( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.await(async.retrieve(memoryStoreId, memoryVersionId, options)); + } + + public MemoryVersionListResponse list(String memoryStoreId) { + return list(memoryStoreId, MemoryVersionListParams.builder().build()); + } + + public MemoryVersionListResponse list(String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryVersionListParams.builder().build(), options); + } + + public MemoryVersionListResponse list(String memoryStoreId, MemoryVersionListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public MemoryVersionListResponse list( + String memoryStoreId, MemoryVersionListParams params, RequestOptions options) { + return Futures.await(async.list(memoryStoreId, params, options)); + } + + public MemoryVersion redact(String memoryStoreId, String memoryVersionId) { + return redact(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public MemoryVersion redact( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.await(async.redact(memoryStoreId, memoryVersionId, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse retrieve(String memoryStoreId, String memoryVersionId) { + return retrieve(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(memoryStoreId, memoryVersionId, options)); + } + + public ApiResponse list(String memoryStoreId) { + return list(memoryStoreId, MemoryVersionListParams.builder().build()); + } + + public ApiResponse list( + String memoryStoreId, RequestOptions options) { + return list(memoryStoreId, MemoryVersionListParams.builder().build(), options); + } + + public ApiResponse list( + String memoryStoreId, MemoryVersionListParams params) { + return list(memoryStoreId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String memoryStoreId, MemoryVersionListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(memoryStoreId, params, options)); + } + + public ApiResponse redact(String memoryStoreId, String memoryVersionId) { + return redact(memoryStoreId, memoryVersionId, RequestOptions.DEFAULT); + } + + public ApiResponse redact( + String memoryStoreId, String memoryVersionId, RequestOptions options) { + return Futures.await(async.withResponse().redact(memoryStoreId, memoryVersionId, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Model.java b/src/main/java/com/qoder/cloudagents/managed/Model.java new file mode 100644 index 0000000..6f0d84c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Model.java @@ -0,0 +1,64 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Model extends JsonModel { + public Model(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Model fromJson(JsonValue value) { + return new Model(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String displayName() { + return optional("display_name", JsonValue::asString); + } + + public String source() { + return optional("source", JsonValue::asString); + } + + public String defaultEffort() { + return optional("default_effort", JsonValue::asString); + } + + public Boolean isEnabled() { + return optional("is_enabled", JsonValue::asBoolean); + } + + public Boolean isNew() { + return optional("is_new", JsonValue::asBoolean); + } + + public BigDecimal priceFactor() { + return optional("price_factor", JsonValue::asDecimal); + } + + public List efforts() { + return optionalList("efforts", JsonValue::asString); + } + + public Long maxInputTokens() { + return optional("max_input_tokens", JsonValue::asLong); + } + + public Long defaultContextWindow() { + return optional("default_context_window", JsonValue::asLong); + } + + public List availableContextWindows() { + return optionalList("available_context_windows", JsonValue::asLong); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/ModelConfig.java b/src/main/java/com/qoder/cloudagents/managed/ModelConfig.java new file mode 100644 index 0000000..4b1b6d5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/ModelConfig.java @@ -0,0 +1,96 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.errors.ResponseValidationException; + +/** A model ID string or a structured model configuration; wire shape is preserved. */ +public final class ModelConfig implements JsonSerializable { + private final JsonValue value; + + private ModelConfig(JsonValue value) { + if (value == null || (!value.isString() && !value.isObject())) + throw new ResponseValidationException("Expected a model string or object"); + this.value = value; + } + + public static ModelConfig of(String id) { + if (id == null || id.isEmpty()) throw new ConfigurationException("Model ID must not be empty"); + return new ModelConfig(JsonValue.of(id)); + } + + public static ModelConfig fromJson(JsonValue value) { + return new ModelConfig(value); + } + + public static Builder builder() { + return new Builder(); + } + + public boolean isString() { + return value.isString(); + } + + public String id() { + return isString() ? value.asString() : value.get("id").asString(); + } + + public String effort() { + return string("effort"); + } + + public Long contextWindow() { + JsonValue field = field("context_window"); + return field.isMissing() || field.isNull() ? null : field.asLong(); + } + + public Long effectiveContextWindow() { + JsonValue f = field("effective_context_window"); + return f.isMissing() || f.isNull() ? null : f.asLong(); + } + + public JsonValue field(String name) { + return value.get(name); + } + + private String string(String name) { + JsonValue field = field(name); + return field.isMissing() || field.isNull() ? null : field.asString(); + } + + @Override + public JsonValue toJsonValue() { + return value; + } + + @Override + public String toString() { + return "ModelConfig"; + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder id(String value) { + return put("id", value); + } + + public Builder effort(String value) { + return put("effort", value); + } + + public Builder contextWindow(Long value) { + return put("context_window", value); + } + + public ModelConfig build() { + require("id"); + if (!json().get("speed").isMissing()) + throw new ConfigurationException("Managed models do not accept speed"); + JsonValue context = json().get("context_window"); + if (!context.isMissing() && !context.isNull() && context.asLong() <= 0) + throw new ConfigurationException("contextWindow must be positive"); + return new ModelConfig(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/ModelListResponse.java b/src/main/java/com/qoder/cloudagents/managed/ModelListResponse.java new file mode 100644 index 0000000..5fc571f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/ModelListResponse.java @@ -0,0 +1,15 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.List; + +/** A non-paginated collection returned by the Managed API. */ +public final class ModelListResponse extends JsonModel { + public ModelListResponse(JsonValue value, String requestId) { + super(value, requestId); + } + + public List data() { + return optionalList("data", v -> new Model(v, requestId())); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Models.java b/src/main/java/com/qoder/cloudagents/managed/Models.java new file mode 100644 index 0000000..d099d3f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Models.java @@ -0,0 +1,35 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Models { + private final AsyncModels async; + + public Models(AsyncModels async) { + this.async = async; + } + + public ModelListResponse list() { + return list(RequestOptions.DEFAULT); + } + + public ModelListResponse list(RequestOptions options) { + return Futures.await(async.list(options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse list() { + return list(RequestOptions.DEFAULT); + } + + public ApiResponse list(RequestOptions options) { + return Futures.await(async.withResponse().list(options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MultiagentConfig.java b/src/main/java/com/qoder/cloudagents/managed/MultiagentConfig.java new file mode 100644 index 0000000..863dcc9 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MultiagentConfig.java @@ -0,0 +1,46 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; +import java.util.List; + +/** Immutable MultiagentConfig configuration. Unknown fields are retained through field(). */ +public final class MultiagentConfig extends JsonObject { + private MultiagentConfig(JsonValue value) { + super(value); + } + + public static MultiagentConfig fromJson(JsonValue value) { + return new MultiagentConfig(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public List agents() { + return optionalList("agents", MultiagentEntry::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder agents(List value) { + return put("agents", value); + } + + public MultiagentConfig build() { + require("type", "agents"); + return new MultiagentConfig(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/MultiagentEntry.java b/src/main/java/com/qoder/cloudagents/managed/MultiagentEntry.java new file mode 100644 index 0000000..16aadee --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/MultiagentEntry.java @@ -0,0 +1,103 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.*; + +/** String Agent shorthand or an Agent, self, or Advisor roster entry. */ +public final class MultiagentEntry implements JsonSerializable { + private final JsonValue value; + + private MultiagentEntry(JsonValue value) { + if (value == null || (!value.isString() && !value.isObject())) + throw new ResponseValidationException("Expected an Agent ID or roster object"); + this.value = value; + } + + public static MultiagentEntry of(String id) { + if (id == null || id.isEmpty()) throw new ConfigurationException("Agent ID must not be empty"); + return new MultiagentEntry(JsonValue.of(id)); + } + + public static MultiagentEntry fromJson(JsonValue value) { + return new MultiagentEntry(value); + } + + public boolean isString() { + return value.isString(); + } + + private String string(String name) { + JsonValue v = value.get(name); + return v.isMissing() || v.isNull() ? null : v.asString(); + } + + public String type() { + return string("type"); + } + + public String id() { + return isString() ? value.asString() : string("id"); + } + + public JsonValue version() { + return value.get("version"); + } + + public ModelConfig model() { + JsonValue v = value.get("model"); + return v.isMissing() || v.isNull() ? null : ModelConfig.fromJson(v); + } + + public Agent agent() { + return isString() ? null : new Agent(value, null); + } + + public JsonValue field(String name) { + return value.get(name); + } + + public JsonValue toJsonValue() { + return value; + } + + public String toString() { + return "MultiagentEntry"; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + public Builder type(String value) { + return put("type", value); + } + + public Builder id(String value) { + return put("id", value); + } + + public Builder version(long value) { + if (value <= 0) throw new ConfigurationException("version must be positive"); + return put("version", value); + } + + public Builder version(String value) { + if (value == null || (!"latest".equals(value) && !value.matches("[1-9][0-9]*"))) + throw new ConfigurationException("version must be latest or a positive integer string"); + return put("version", value); + } + + public Builder model(String value) { + return put("model", value); + } + + public MultiagentEntry build() { + require("type"); + String t = json().get("type").asString(); + if ("agent".equals(t)) require("id"); + if ("advisor".equals(t)) require("model"); + return new MultiagentEntry(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/OAuth.java b/src/main/java/com/qoder/cloudagents/managed/OAuth.java new file mode 100644 index 0000000..d45fe87 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/OAuth.java @@ -0,0 +1,35 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class OAuth { + private final AsyncOAuth async; + + public OAuth(AsyncOAuth async) { + this.async = async; + } + + public OAuthStartResponse start(OAuthStartParams params) { + return start(params, RequestOptions.DEFAULT); + } + + public OAuthStartResponse start(OAuthStartParams params, RequestOptions options) { + return Futures.await(async.start(params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse start(OAuthStartParams params) { + return start(params, RequestOptions.DEFAULT); + } + + public ApiResponse start(OAuthStartParams params, RequestOptions options) { + return Futures.await(async.withResponse().start(params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/OAuthStartParams.java b/src/main/java/com/qoder/cloudagents/managed/OAuthStartParams.java new file mode 100644 index 0000000..21394c3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/OAuthStartParams.java @@ -0,0 +1,61 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class OAuthStartParams extends JsonObject { + private OAuthStartParams(JsonValue value) { + super(value); + } + + public static OAuthStartParams fromJson(JsonValue value) { + return new OAuthStartParams(value); + } + + public String vaultId() { + return optional("vault_id", JsonValue::asString); + } + + public String mcpServerUrl() { + return optional("mcp_server_url", JsonValue::asString); + } + + public String clientId() { + return optional("client_id", JsonValue::asString); + } + + public String clientSecret() { + return optional("client_secret", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder vaultId(String value) { + return put("vault_id", value); + } + + public Builder mcpServerUrl(String value) { + return put("mcp_server_url", value); + } + + public Builder clientId(String value) { + return put("client_id", value); + } + + public Builder clientSecret(String value) { + return put("client_secret", value); + } + + public OAuthStartParams build() { + require("vault_id", "mcp_server_url"); + + return new OAuthStartParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/OAuthStartResponse.java b/src/main/java/com/qoder/cloudagents/managed/OAuthStartResponse.java new file mode 100644 index 0000000..997669e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/OAuthStartResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class OAuthStartResponse extends JsonModel { + public OAuthStartResponse(JsonValue value, String requestId) { + super(value, requestId); + } + + public static OAuthStartResponse fromJson(JsonValue value) { + return new OAuthStartResponse(value, null); + } + + public String authorizationUrl() { + return optional("authorization_url", JsonValue::asString); + } + + public String callbackOrigin() { + return optional("callback_origin", JsonValue::asString); + } + + public String state() { + return optional("state", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/OutcomeEvaluation.java b/src/main/java/com/qoder/cloudagents/managed/OutcomeEvaluation.java new file mode 100644 index 0000000..acd72ca --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/OutcomeEvaluation.java @@ -0,0 +1,43 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class OutcomeEvaluation extends JsonObject { + private OutcomeEvaluation(JsonValue value) { + super(value); + } + + public static OutcomeEvaluation fromJson(JsonValue value) { + return new OutcomeEvaluation(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String outcomeId() { + return optional("outcome_id", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public Long iteration() { + return optional("iteration", JsonValue::asLong); + } + + public String result() { + return optional("result", JsonValue::asString); + } + + public String explanation() { + return optional("explanation", JsonValue::asString); + } + + public String completedAt() { + return optional("completed_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/OutcomeRubric.java b/src/main/java/com/qoder/cloudagents/managed/OutcomeRubric.java new file mode 100644 index 0000000..65584e3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/OutcomeRubric.java @@ -0,0 +1,68 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class OutcomeRubric extends JsonObject { + private OutcomeRubric(JsonValue value) { + super(value); + } + + public static OutcomeRubric fromJson(JsonValue value) { + return new OutcomeRubric(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + /** + * @deprecated Use {@link #content()}. + */ + @Deprecated + public String text() { + return content(); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder content(String value) { + return put("content", value); + } + + /** + * @deprecated Use {@link #content(String)}; this alias also writes content. + */ + @Deprecated + public Builder text(String value) { + return content(value); + } + + public Builder fileId(String value) { + return put("file_id", value); + } + + public OutcomeRubric build() { + require("type"); + return new OutcomeRubric(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/PermissionPolicy.java b/src/main/java/com/qoder/cloudagents/managed/PermissionPolicy.java new file mode 100644 index 0000000..8845a8c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/PermissionPolicy.java @@ -0,0 +1,37 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; + +/** Immutable PermissionPolicy configuration. Unknown fields are retained through field(). */ +public final class PermissionPolicy extends JsonObject { + private PermissionPolicy(JsonValue value) { + super(value); + } + + public static PermissionPolicy fromJson(JsonValue value) { + return new PermissionPolicy(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public PermissionPolicy build() { + require("type"); + return new PermissionPolicy(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/RepositoryCheckout.java b/src/main/java/com/qoder/cloudagents/managed/RepositoryCheckout.java new file mode 100644 index 0000000..8c9d2f4 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/RepositoryCheckout.java @@ -0,0 +1,45 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class RepositoryCheckout extends JsonObject { + private RepositoryCheckout(JsonValue value) { + super(value); + } + + public static RepositoryCheckout fromJson(JsonValue value) { + return new RepositoryCheckout(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public RepositoryCheckout build() { + require("type", "name"); + + return new RepositoryCheckout(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Session.java b/src/main/java/com/qoder/cloudagents/managed/Session.java new file mode 100644 index 0000000..95c467c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Session.java @@ -0,0 +1,87 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class Session extends JsonModel { + public Session(JsonValue value, String requestId) { + super(value, requestId); + } + + public static Session fromJson(JsonValue value) { + return new Session(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Agent agent() { + return optional("agent", v -> new Agent(v, null)); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public SessionBudget budget() { + return optional("budget", SessionBudget::fromJson); + } + + public String title() { + return optional("title", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", v -> v); + } + + public Map environmentVariables() { + return optionalNullableMap("environment_variables", JsonValue::asString); + } + + public List resources() { + return optionalList("resources", v -> new SessionResource(v, null)); + } + + public List vaultIds() { + return optionalList("vault_ids", JsonValue::asString); + } + + public String deploymentId() { + return optional("deployment_id", JsonValue::asString); + } + + public List outcomeEvaluations() { + return optionalList("outcome_evaluations", OutcomeEvaluation::fromJson); + } + + public SessionStats stats() { + return optional("stats", SessionStats::fromJson); + } + + public SessionUsage usage() { + return optional("usage", SessionUsage::fromJson); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionAgentPatch.java b/src/main/java/com/qoder/cloudagents/managed/SessionAgentPatch.java new file mode 100644 index 0000000..9e953a7 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionAgentPatch.java @@ -0,0 +1,94 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.*; +import java.util.List; + +/** + * Runtime configuration patch for an existing Session. Beta fields require the x-qoder-beta request + * header. + */ +public final class SessionAgentPatch extends JsonObject { + private SessionAgentPatch(JsonValue value) { + super(value); + } + + public static SessionAgentPatch fromJson(JsonValue value) { + return new SessionAgentPatch(value); + } + + public ModelConfig model() { + return optional("model", ModelConfig::fromJson); + } + + public String system() { + return optional("system", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public List tools() { + return optionalList("tools", Tool::fromJson); + } + + public List mcpServers() { + return optionalList("mcp_servers", MCPServer::fromJson); + } + + public List skills() { + return optionalList("skills", SkillBinding::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + public Builder model(ModelConfig value) { + return put("model", value); + } + + public Builder model(String value) { + return put("model", value == null ? null : ModelConfig.of(value)); + } + + public Builder system(String value) { + return put("system", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder tools(List value) { + return put("tools", value); + } + + public Builder mcpServers(List value) { + return put("mcp_servers", value); + } + + public Builder skills(List value) { + return put("skills", value); + } + + public SessionAgentPatch build() { + if (json().asObject().isEmpty()) + throw new ConfigurationException("An agent patch must contain a runtime field"); + for (String field : new String[] {"id", "version", "type", "multiagent", "metadata"}) + if (!json().get(field).isMissing()) + throw new ConfigurationException("Session runtime patches cannot contain " + field); + return new SessionAgentPatch(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionBudget.java b/src/main/java/com/qoder/cloudagents/managed/SessionBudget.java new file mode 100644 index 0000000..10a7123 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionBudget.java @@ -0,0 +1,53 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionBudget extends JsonObject { + private SessionBudget(JsonValue value) { + super(value); + } + + public static SessionBudget fromJson(JsonValue value) { + return new SessionBudget(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String maxCreditCost() { + return optional("max_credit_cost", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder maxCreditCost(String value) { + return put("max_credit_cost", value); + } + + public SessionBudget build() { + require("type", "max_credit_cost"); + if (!"limit".equals(json().get("type").asString())) + throw new ConfigurationException("Budget type must be limit"); + String cost = json().get("max_credit_cost").asString(); + if (!cost.matches("[0-9]{1,12}(\\.[0-9]{1,2})?") || new BigDecimal(cost).signum() <= 0) + throw new ConfigurationException( + "maxCreditCost must be a positive decimal string with at most 12 integer and 2" + + " fractional digits"); + return new SessionBudget(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionCreateParams.java new file mode 100644 index 0000000..b4e4cea --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionCreateParams.java @@ -0,0 +1,97 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionCreateParams extends JsonObject { + private SessionCreateParams(JsonValue value) { + super(value); + } + + public static SessionCreateParams fromJson(JsonValue value) { + return new SessionCreateParams(value); + } + + public AgentReference agent() { + return optional("agent", AgentReference::fromJson); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public SessionBudget budget() { + return optional("budget", SessionBudget::fromJson); + } + + public String title() { + return optional("title", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", v -> v); + } + + public Map environmentVariables() { + return optionalNullableMap("environment_variables", JsonValue::asString); + } + + public List resources() { + return optionalList("resources", SessionResourceSpec::fromJson); + } + + public List vaultIds() { + return optionalList("vault_ids", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder agent(AgentReference value) { + return put("agent", value); + } + + public Builder agent(String value) { + return put("agent", value == null ? null : AgentReference.of(value)); + } + + public Builder environmentId(String value) { + return put("environment_id", value); + } + + public Builder budget(SessionBudget value) { + return put("budget", value); + } + + public Builder title(String value) { + return put("title", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder environmentVariables(Map value) { + return put("environment_variables", value); + } + + public Builder resources(List value) { + return put("resources", value); + } + + public Builder vaultIds(List value) { + return put("vault_ids", value); + } + + public SessionCreateParams build() { + require("agent", "environment_id"); + + return new SessionCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEvent.java b/src/main/java/com/qoder/cloudagents/managed/SessionEvent.java new file mode 100644 index 0000000..137a491 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEvent.java @@ -0,0 +1,216 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class SessionEvent extends JsonModel { + public SessionEvent(JsonValue value, String requestId) { + super(value, requestId); + } + + public BigDecimal totalCredits() { + return optional("total_credits", JsonValue::asDecimal); + } + + public BigDecimal sandboxRuntimeCredits() { + return optional("sandbox_runtime_credits", JsonValue::asDecimal); + } + + public BigDecimal modelCredits() { + return optional("model_credits", JsonValue::asDecimal); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String sessionId() { + return optional("session_id", JsonValue::asString); + } + + public String processedAt() { + return optional("processed_at", JsonValue::asString); + } + + public String sessionThreadId() { + return optional("session_thread_id", JsonValue::asString); + } + + public String thinking() { + return optional("thinking", JsonValue::asString); + } + + public String text() { + return optional("text", JsonValue::asString); + } + + public String toolUseId() { + return optional("tool_use_id", JsonValue::asString); + } + + public String customToolUseId() { + return optional("custom_tool_use_id", JsonValue::asString); + } + + public String mcpToolUseId() { + return optional("mcp_tool_use_id", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String mcpServerName() { + return optional("mcp_server_name", JsonValue::asString); + } + + public String result() { + return optional("result", JsonValue::asString); + } + + public String denyMessage() { + return optional("deny_message", JsonValue::asString); + } + + public String reason() { + return optional("reason", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String outcomeId() { + return optional("outcome_id", JsonValue::asString); + } + + public String messageId() { + return optional("message_id", JsonValue::asString); + } + + public String eventId() { + return optional("event_id", JsonValue::asString); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public String originalFilename() { + return optional("original_filename", JsonValue::asString); + } + + public String contentType() { + return optional("content_type", JsonValue::asString); + } + + public String title() { + return optional("title", JsonValue::asString); + } + + public String modelRequestStartId() { + return optional("model_request_start_id", JsonValue::asString); + } + + public String explanation() { + return optional("explanation", JsonValue::asString); + } + + public String outcomeEvaluationStartId() { + return optional("outcome_evaluation_start_id", JsonValue::asString); + } + + public EventContent content() { + return optional("content", EventContent::fromJson); + } + + public Boolean isError() { + return optional("is_error", JsonValue::asBoolean); + } + + public OutcomeRubric rubric() { + return optional("rubric", OutcomeRubric::fromJson); + } + + public Long maxIterations() { + return optional("max_iterations", JsonValue::asLong); + } + + public Long index() { + return optional("index", JsonValue::asLong); + } + + public Long size() { + return optional("size", JsonValue::asLong); + } + + public Long iteration() { + return optional("iteration", JsonValue::asLong); + } + + public Map input() { + return optionalMap("input", item -> item); + } + + /** Credits for context compaction, when usage.credits is present. */ + public BigDecimal usageCredits() { + JsonValue value = field("usage").get("credits"); + return value.isMissing() || value.isNull() ? null : value.asDecimal(); + } + + /** Incremental credits for a model request, when model_usage.credits is present. */ + public BigDecimal modelUsageCredits() { + JsonValue value = field("model_usage").get("credits"); + return value.isMissing() || value.isNull() ? null : value.asDecimal(); + } + + public Map usage() { + return optionalMap("usage", item -> item); + } + + public Map stopReason() { + return optionalMap("stop_reason", item -> item); + } + + public Map error() { + return optionalMap("error", item -> item); + } + + public Map evaluatedPermission() { + return optionalMap("evaluated_permission", item -> item); + } + + public Agent agent() { + return optional("agent", Agent::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", item -> item); + } + + public Map modelUsage() { + return optionalMap("model_usage", item -> item); + } + + public JsonValue message() { + return optional("message", item -> item); + } + + public JsonValue contentBlock() { + return optional("content_block", item -> item); + } + + public JsonValue delta() { + return optional("delta", item -> item); + } + + public JsonValue event() { + return optional("event", item -> item); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventListParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventListParams.java new file mode 100644 index 0000000..8456401 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventListParams.java @@ -0,0 +1,92 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SessionEventListParams { + private final Map query; + + private SessionEventListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder order(String value) { + return put("order", value); + } + + public Builder types(String value) { + return put("types", value); + } + + public Builder types(List values) { + if (values == null || values.isEmpty()) + throw new ConfigurationException("types must not be empty"); + for (String value : values) + if (value == null || value.isEmpty() || value.contains(",")) + throw new ConfigurationException("Filter values must be nonempty and contain no comma"); + return put("types", String.join(",", values)); + } + + public Builder createdAtGt(String value) { + return put("created_at[gt]", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLt(String value) { + return put("created_at[lt]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SessionEventListParams build() { + return new SessionEventListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventListResponse.java new file mode 100644 index 0000000..4f0d40d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SessionEventListResponse + extends CursorPage { + public SessionEventListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SessionEventListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new SessionEvent(item, requestId), true); + } + + @Override + protected SessionEventListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventParam.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventParam.java new file mode 100644 index 0000000..966abd6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventParam.java @@ -0,0 +1,124 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionEventParam extends JsonObject { + private SessionEventParam(JsonValue value) { + super(value); + } + + public static SessionEventParam fromJson(JsonValue value) { + return new SessionEventParam(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public EventContent content() { + return optional("content", EventContent::fromJson); + } + + public String toolUseId() { + return optional("tool_use_id", JsonValue::asString); + } + + public String customToolUseId() { + return optional("custom_tool_use_id", JsonValue::asString); + } + + public String result() { + return optional("result", JsonValue::asString); + } + + public String denyMessage() { + return optional("deny_message", JsonValue::asString); + } + + public Boolean isError() { + return optional("is_error", JsonValue::asBoolean); + } + + public String reason() { + return optional("reason", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public OutcomeRubric rubric() { + return optional("rubric", OutcomeRubric::fromJson); + } + + public String outcomeId() { + return optional("outcome_id", JsonValue::asString); + } + + public Long maxIterations() { + return optional("max_iterations", JsonValue::asLong); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder content(EventContent value) { + return put("content", value); + } + + public Builder toolUseId(String value) { + return put("tool_use_id", value); + } + + public Builder customToolUseId(String value) { + return put("custom_tool_use_id", value); + } + + public Builder result(String value) { + return put("result", value); + } + + public Builder denyMessage(String value) { + return put("deny_message", value); + } + + public Builder isError(Boolean value) { + return put("is_error", value); + } + + public Builder reason(String value) { + return put("reason", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder rubric(OutcomeRubric value) { + return put("rubric", value); + } + + public Builder outcomeId(String value) { + return put("outcome_id", value); + } + + public Builder maxIterations(Long value) { + return put("max_iterations", value); + } + + public SessionEventParam build() { + require("type"); + return new SessionEventParam(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventSendParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventSendParams.java new file mode 100644 index 0000000..09526a5 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventSendParams.java @@ -0,0 +1,36 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionEventSendParams extends JsonObject { + private SessionEventSendParams(JsonValue value) { + super(value); + } + + public static SessionEventSendParams fromJson(JsonValue value) { + return new SessionEventSendParams(value); + } + + public List events() { + return optionalList("events", SessionEventParam::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder events(List value) { + return put("events", value); + } + + public SessionEventSendParams build() { + require("events"); + return new SessionEventSendParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventSendResponse.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventSendResponse.java new file mode 100644 index 0000000..f60d0bf --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventSendResponse.java @@ -0,0 +1,15 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class SessionEventSendResponse extends JsonModel { + public SessionEventSendResponse(JsonValue value, String requestId) { + super(value, requestId); + } + + public List data() { + return optionalList("data", item -> new SessionEvent(item, requestId())); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEventStreamParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionEventStreamParams.java new file mode 100644 index 0000000..7ba27f7 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEventStreamParams.java @@ -0,0 +1,54 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.RequestOptions; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable SSE subscription parameters. The cursor is sent as a header, never as a query. */ +public final class SessionEventStreamParams { + private final String lastEventId; + private final List eventDeltas; + + private SessionEventStreamParams(Builder b) { + lastEventId = b.lastEventId; + eventDeltas = Collections.unmodifiableList(new ArrayList<>(b.eventDeltas)); + } + + public static Builder builder() { + return new Builder(); + } + + public String lastEventId() { + return lastEventId; + } + + Map> query() { + Map> values = new LinkedHashMap<>(); + if (!eventDeltas.isEmpty()) values.put("event_deltas[]", eventDeltas); + return values; + } + + public static final class Builder { + private String lastEventId; + private List eventDeltas = Collections.emptyList(); + + public Builder eventDeltas(List values) { + if (values == null) throw new ConfigurationException("eventDeltas must not be null"); + for (String value : values) + if (value == null || value.isEmpty()) + throw new ConfigurationException("eventDeltas values must not be empty"); + eventDeltas = new ArrayList<>(values); + return this; + } + + public Builder lastEventId(String value) { + RequestOptions.builder().header("Last-Event-ID", value); + lastEventId = value; + return this; + } + + public SessionEventStreamParams build() { + return new SessionEventStreamParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionEvents.java b/src/main/java/com/qoder/cloudagents/managed/SessionEvents.java new file mode 100644 index 0000000..e6dc98d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionEvents.java @@ -0,0 +1,97 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.streaming.EventStream; +import java.util.*; + +public final class SessionEvents { + private final AsyncSessionEvents async; + + public SessionEvents(AsyncSessionEvents async) { + this.async = async; + } + + public SessionEventListResponse list(String sessionId) { + return list(sessionId, SessionEventListParams.builder().build()); + } + + public SessionEventListResponse list(String sessionId, SessionEventListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public SessionEventListResponse list( + String sessionId, SessionEventListParams params, RequestOptions options) { + return Futures.await(async.list(sessionId, params, options)); + } + + public SessionEventSendResponse send(String sessionId, SessionEventSendParams params) { + return send(sessionId, params, RequestOptions.DEFAULT); + } + + public SessionEventSendResponse send( + String sessionId, SessionEventSendParams params, RequestOptions options) { + return Futures.await(async.send(sessionId, params, options)); + } + + /** Opens one SSE connection. Close the returned stream after consumption. */ + public EventStream streamEvents(String sessionId) { + return streamEvents(sessionId, SessionEventStreamParams.builder().build()); + } + + public EventStream streamEvents(String sessionId, SessionEventStreamParams params) { + return streamEvents(sessionId, params, RequestOptions.DEFAULT); + } + + public EventStream streamEvents( + String sessionId, SessionEventStreamParams params, RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return Futures.await(async.streamEvents(sessionId, params, options)); + } + + /** Lazy, explicitly reconnecting subscription. It never resends user input. */ + public EventStream resumableStream(String sessionId) { + return resumableStream(sessionId, SessionEventStreamParams.builder().build()); + } + + public EventStream resumableStream( + String sessionId, SessionEventStreamParams params) { + return resumableStream(sessionId, params, RequestOptions.DEFAULT); + } + + public EventStream resumableStream( + String sessionId, SessionEventStreamParams params, RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return async.resumableStream(sessionId, params, options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse list(String sessionId) { + return list(sessionId, SessionEventListParams.builder().build()); + } + + public ApiResponse list( + String sessionId, SessionEventListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String sessionId, SessionEventListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(sessionId, params, options)); + } + + public ApiResponse send( + String sessionId, SessionEventSendParams params) { + return send(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse send( + String sessionId, SessionEventSendParams params, RequestOptions options) { + return Futures.await(async.withResponse().send(sessionId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionListParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionListParams.java new file mode 100644 index 0000000..8c07df4 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionListParams.java @@ -0,0 +1,105 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SessionListParams { + private final Map query; + + private SessionListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder order(String value) { + return put("order", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder statuses(String value) { + return put("statuses", value); + } + + public Builder statuses(List values) { + if (values == null || values.isEmpty()) + throw new ConfigurationException("statuses must not be empty"); + for (String value : values) + if (value == null || value.isEmpty() || value.contains(",")) + throw new ConfigurationException("Filter values must be nonempty and contain no comma"); + return put("statuses", String.join(",", values)); + } + + public Builder agentId(String value) { + return put("agent_id", value); + } + + public Builder agentVersion(long value) { + if (value <= 0) throw new ConfigurationException("Value must be positive"); + return put("agent_version", String.valueOf(value)); + } + + public Builder deploymentId(String value) { + return put("deployment_id", value); + } + + public Builder memoryStoreId(String value) { + return put("memory_store_id", value); + } + + public Builder createdAtGt(String value) { + return put("created_at[gt]", value); + } + + public Builder createdAtGte(String value) { + return put("created_at[gte]", value); + } + + public Builder createdAtLt(String value) { + return put("created_at[lt]", value); + } + + public Builder createdAtLte(String value) { + return put("created_at[lte]", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SessionListParams build() { + return new SessionListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SessionListResponse.java new file mode 100644 index 0000000..0b5d9e0 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionListResponse.java @@ -0,0 +1,28 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SessionListResponse extends CursorPage { + public SessionListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SessionListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Session(item, requestId), true); + } + + @Override + protected SessionListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResource.java b/src/main/java/com/qoder/cloudagents/managed/SessionResource.java new file mode 100644 index 0000000..c043565 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResource.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class SessionResource extends JsonModel { + public SessionResource(JsonValue value, String requestId) { + super(value, requestId); + } + + public static SessionResource fromJson(JsonValue value) { + return new SessionResource(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public String mountPath() { + return optional("mount_path", JsonValue::asString); + } + + public String url() { + return optional("url", JsonValue::asString); + } + + public RepositoryCheckout checkout() { + return optional("checkout", RepositoryCheckout::fromJson); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public String access() { + return optional("access", JsonValue::asString); + } + + public String instructions() { + return optional("instructions", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResourceCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionResourceCreateParams.java new file mode 100644 index 0000000..70ee5d1 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResourceCreateParams.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionResourceCreateParams extends JsonObject { + private SessionResourceCreateParams(JsonValue value) { + super(value); + } + + public static SessionResourceCreateParams fromJson(JsonValue value) { + return new SessionResourceCreateParams(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public String mountPath() { + return optional("mount_path", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder fileId(String value) { + return put("file_id", value); + } + + public Builder mountPath(String value) { + return put("mount_path", value); + } + + public SessionResourceCreateParams build() { + require("type", "file_id"); + if (!"file".equals(json().get("type").asString())) + throw new ConfigurationException("Only file resources can be added to an existing session"); + return new SessionResourceCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResourceListParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionResourceListParams.java new file mode 100644 index 0000000..04e4a12 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResourceListParams.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SessionResourceListParams { + private final Map query; + + private SessionResourceListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SessionResourceListParams build() { + return new SessionResourceListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResourceListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SessionResourceListResponse.java new file mode 100644 index 0000000..7d861bb --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResourceListResponse.java @@ -0,0 +1,30 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SessionResourceListResponse + extends CursorPage { + public SessionResourceListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SessionResourceListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super( + value, requestId, query, seen, fetcher, item -> new SessionResource(item, requestId), true); + } + + @Override + protected SessionResourceListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResourceSpec.java b/src/main/java/com/qoder/cloudagents/managed/SessionResourceSpec.java new file mode 100644 index 0000000..25dcdd9 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResourceSpec.java @@ -0,0 +1,112 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionResourceSpec extends JsonObject { + private SessionResourceSpec(JsonValue value) { + super(value); + } + + public static SessionResourceSpec fromJson(JsonValue value) { + return new SessionResourceSpec(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String fileId() { + return optional("file_id", JsonValue::asString); + } + + public String mountPath() { + return optional("mount_path", JsonValue::asString); + } + + public String url() { + return optional("url", JsonValue::asString); + } + + public String authorizationToken() { + return optional("authorization_token", JsonValue::asString); + } + + public String password() { + return optional("password", JsonValue::asString); + } + + public RepositoryCheckout checkout() { + return optional("checkout", RepositoryCheckout::fromJson); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public String access() { + return optional("access", JsonValue::asString); + } + + public String instructions() { + return optional("instructions", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder fileId(String value) { + return put("file_id", value); + } + + public Builder mountPath(String value) { + return put("mount_path", value); + } + + public Builder url(String value) { + return put("url", value); + } + + public Builder authorizationToken(String value) { + return put("authorization_token", value); + } + + public Builder password(String value) { + return put("password", value); + } + + public Builder checkout(RepositoryCheckout value) { + return put("checkout", value); + } + + public Builder memoryStoreId(String value) { + return put("memory_store_id", value); + } + + public Builder access(String value) { + return put("access", value); + } + + public Builder instructions(String value) { + return put("instructions", value); + } + + public SessionResourceSpec build() { + require("type"); + String type = json().get("type").asString(); + if ("file".equals(type)) require("file_id"); + else if ("github_repository".equals(type) || "git_repository".equals(type)) require("url"); + else if ("memory_store".equals(type)) require("memory_store_id"); + return new SessionResourceSpec(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResourceUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionResourceUpdateParams.java new file mode 100644 index 0000000..a660e0d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResourceUpdateParams.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionResourceUpdateParams extends JsonObject { + private SessionResourceUpdateParams(JsonValue value) { + super(value); + } + + public static SessionResourceUpdateParams fromJson(JsonValue value) { + return new SessionResourceUpdateParams(value); + } + + public String authorizationToken() { + return optional("authorization_token", JsonValue::asString); + } + + public String password() { + return optional("password", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder authorizationToken(String value) { + return put("authorization_token", value); + } + + public Builder password(String value) { + return put("password", value); + } + + public SessionResourceUpdateParams build() { + + return new SessionResourceUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionResources.java b/src/main/java/com/qoder/cloudagents/managed/SessionResources.java new file mode 100644 index 0000000..0b70f8b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionResources.java @@ -0,0 +1,134 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class SessionResources { + private final AsyncSessionResources async; + + public SessionResources(AsyncSessionResources async) { + this.async = async; + } + + public SessionResource create(String sessionId, SessionResourceCreateParams params) { + return create(sessionId, params, RequestOptions.DEFAULT); + } + + public SessionResource create( + String sessionId, SessionResourceCreateParams params, RequestOptions options) { + return Futures.await(async.create(sessionId, params, options)); + } + + public DeletedSessionResource delete(String sessionId, String resourceId) { + return delete(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public DeletedSessionResource delete( + String sessionId, String resourceId, RequestOptions options) { + return Futures.await(async.delete(sessionId, resourceId, options)); + } + + public SessionResource retrieve(String sessionId, String resourceId) { + return retrieve(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public SessionResource retrieve(String sessionId, String resourceId, RequestOptions options) { + return Futures.await(async.retrieve(sessionId, resourceId, options)); + } + + public SessionResourceListResponse list(String sessionId) { + return list(sessionId, SessionResourceListParams.builder().build()); + } + + public SessionResourceListResponse list(String sessionId, RequestOptions options) { + return list(sessionId, SessionResourceListParams.builder().build(), options); + } + + public SessionResourceListResponse list(String sessionId, SessionResourceListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public SessionResourceListResponse list( + String sessionId, SessionResourceListParams params, RequestOptions options) { + return Futures.await(async.list(sessionId, params, options)); + } + + public SessionResource update( + String sessionId, String resourceId, SessionResourceUpdateParams params) { + return update(sessionId, resourceId, params, RequestOptions.DEFAULT); + } + + public SessionResource update( + String sessionId, + String resourceId, + SessionResourceUpdateParams params, + RequestOptions options) { + return Futures.await(async.update(sessionId, resourceId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse create( + String sessionId, SessionResourceCreateParams params) { + return create(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse create( + String sessionId, SessionResourceCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(sessionId, params, options)); + } + + public ApiResponse delete(String sessionId, String resourceId) { + return delete(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public ApiResponse delete( + String sessionId, String resourceId, RequestOptions options) { + return Futures.await(async.withResponse().delete(sessionId, resourceId, options)); + } + + public ApiResponse retrieve(String sessionId, String resourceId) { + return retrieve(sessionId, resourceId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String sessionId, String resourceId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(sessionId, resourceId, options)); + } + + public ApiResponse list(String sessionId) { + return list(sessionId, SessionResourceListParams.builder().build()); + } + + public ApiResponse list(String sessionId, RequestOptions options) { + return list(sessionId, SessionResourceListParams.builder().build(), options); + } + + public ApiResponse list( + String sessionId, SessionResourceListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String sessionId, SessionResourceListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(sessionId, params, options)); + } + + public ApiResponse update( + String sessionId, String resourceId, SessionResourceUpdateParams params) { + return update(sessionId, resourceId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String sessionId, + String resourceId, + SessionResourceUpdateParams params, + RequestOptions options) { + return Futures.await(async.withResponse().update(sessionId, resourceId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionSearchParams.java new file mode 100644 index 0000000..31c73f1 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionSearchParams.java @@ -0,0 +1,127 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionSearchParams extends JsonObject { + private SessionSearchParams(JsonValue value) { + super(value); + } + + public static SessionSearchParams fromJson(JsonValue value) { + return new SessionSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String order() { + return optional("order", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public List statuses() { + return optionalList("statuses", JsonValue::asString); + } + + public String agentId() { + return optional("agent_id", JsonValue::asString); + } + + public Long agentVersion() { + return optional("agent_version", JsonValue::asLong); + } + + public String deploymentId() { + return optional("deployment_id", JsonValue::asString); + } + + public String memoryStoreId() { + return optional("memory_store_id", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder order(String value) { + return put("order", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder statuses(List value) { + return put("statuses", value); + } + + public Builder agentId(String value) { + return put("agent_id", value); + } + + public Builder agentVersion(Long value) { + return put("agent_version", value); + } + + public Builder agentVersion(long value) { + return agentVersion(Long.valueOf(value)); + } + + public Builder deploymentId(String value) { + return put("deployment_id", value); + } + + public Builder memoryStoreId(String value) { + return put("memory_store_id", value); + } + + public SessionSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new SessionSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionStats.java b/src/main/java/com/qoder/cloudagents/managed/SessionStats.java new file mode 100644 index 0000000..da05b91 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionStats.java @@ -0,0 +1,24 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionStats extends JsonObject { + private SessionStats(JsonValue value) { + super(value); + } + + public static SessionStats fromJson(JsonValue value) { + return new SessionStats(value); + } + + public BigDecimal activeSeconds() { + return optional("active_seconds", JsonValue::asDecimal); + } + + public BigDecimal durationSeconds() { + return optional("duration_seconds", JsonValue::asDecimal); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionStreams.java b/src/main/java/com/qoder/cloudagents/managed/SessionStreams.java new file mode 100644 index 0000000..f0774e6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionStreams.java @@ -0,0 +1,41 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.ClientEngine; +import com.qoder.cloudagents.errors.ConfigurationException; +import com.qoder.cloudagents.streaming.EventStream; +import java.util.*; + +final class SessionStreams { + private SessionStreams() {} + + static EventStream create( + ClientEngine engine, + String[] path, + Map> query, + String initialId, + RequestOptions options, + boolean resumable, + boolean thread) { + if (options == null) throw new ConfigurationException("Request options must not be null"); + for (String segment : path) + if (segment == null || segment.isEmpty() || segment.equals(".") || segment.equals("..")) + throw new ConfigurationException("Invalid API path segment"); + if (thread && !options.query().isEmpty()) + throw new ConfigurationException("Thread streams do not accept query selectors"); + String cursor = initialId == null ? engine.defaultHeader("Last-Event-ID") : initialId; + for (Map.Entry header : options.headers().entrySet()) + if (header.getKey().equalsIgnoreCase("Last-Event-ID")) cursor = header.getValue(); + return new EventStream<>( + engine, + path, + query, + options, + cursor, + SessionEvent::new, + event -> + "session.status_terminated".equals(event.type()) + || "session.deleted".equals(event.type()), + resumable); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThread.java b/src/main/java/com/qoder/cloudagents/managed/SessionThread.java new file mode 100644 index 0000000..ca9d2f1 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThread.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class SessionThread extends JsonModel { + public SessionThread(JsonValue value, String requestId) { + super(value, requestId); + } + + public static SessionThread fromJson(JsonValue value) { + return new SessionThread(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String sessionId() { + return optional("session_id", JsonValue::asString); + } + + public String parentThreadId() { + return optional("parent_thread_id", JsonValue::asString); + } + + public Agent agent() { + return optional("agent", v -> new Agent(v, null)); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public SessionThreadStats stats() { + return optional("stats", SessionThreadStats::fromJson); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventListParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventListParams.java new file mode 100644 index 0000000..b55a15c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventListParams.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SessionThreadEventListParams { + private final Map query; + + private SessionThreadEventListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SessionThreadEventListParams build() { + return new SessionThreadEventListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventStreamParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventStreamParams.java new file mode 100644 index 0000000..43d68ad --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEventStreamParams.java @@ -0,0 +1,39 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.RequestOptions; +import java.util.*; + +/** Immutable SSE subscription parameters. The cursor is sent as a header, never as a query. */ +public final class SessionThreadEventStreamParams { + private final String lastEventId; + + private SessionThreadEventStreamParams(Builder b) { + lastEventId = b.lastEventId; + } + + public static Builder builder() { + return new Builder(); + } + + public String lastEventId() { + return lastEventId; + } + + Map> query() { + return Collections.emptyMap(); + } + + public static final class Builder { + private String lastEventId; + + public Builder lastEventId(String value) { + RequestOptions.builder().header("Last-Event-ID", value); + lastEventId = value; + return this; + } + + public SessionThreadEventStreamParams build() { + return new SessionThreadEventStreamParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadEvents.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEvents.java new file mode 100644 index 0000000..d45539e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadEvents.java @@ -0,0 +1,92 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import com.qoder.cloudagents.streaming.EventStream; +import java.util.*; + +public final class SessionThreadEvents { + private final AsyncSessionThreadEvents async; + + public SessionThreadEvents(AsyncSessionThreadEvents async) { + this.async = async; + } + + public SessionEventListResponse list(String sessionId, String threadId) { + return list(sessionId, threadId, SessionThreadEventListParams.builder().build()); + } + + public SessionEventListResponse list( + String sessionId, String threadId, SessionThreadEventListParams params) { + return list(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public SessionEventListResponse list( + String sessionId, + String threadId, + SessionThreadEventListParams params, + RequestOptions options) { + return Futures.await(async.list(sessionId, threadId, params, options)); + } + + /** Opens one SSE connection. Close the returned stream after consumption. */ + public EventStream streamEvents(String sessionId, String threadId) { + return streamEvents(sessionId, threadId, SessionThreadEventStreamParams.builder().build()); + } + + public EventStream streamEvents( + String sessionId, String threadId, SessionThreadEventStreamParams params) { + return streamEvents(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public EventStream streamEvents( + String sessionId, + String threadId, + SessionThreadEventStreamParams params, + RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return Futures.await(async.streamEvents(sessionId, threadId, params, options)); + } + + /** Lazy, explicitly reconnecting subscription. It never resends user input. */ + public EventStream resumableStream(String sessionId, String threadId) { + return resumableStream(sessionId, threadId, SessionThreadEventStreamParams.builder().build()); + } + + public EventStream resumableStream( + String sessionId, String threadId, SessionThreadEventStreamParams params) { + return resumableStream(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public EventStream resumableStream( + String sessionId, + String threadId, + SessionThreadEventStreamParams params, + RequestOptions options) { + java.util.Objects.requireNonNull(params, "params"); + return async.resumableStream(sessionId, threadId, params, options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse list(String sessionId, String threadId) { + return list(sessionId, threadId, SessionThreadEventListParams.builder().build()); + } + + public ApiResponse list( + String sessionId, String threadId, SessionThreadEventListParams params) { + return list(sessionId, threadId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String sessionId, + String threadId, + SessionThreadEventListParams params, + RequestOptions options) { + return Futures.await(async.withResponse().list(sessionId, threadId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadListParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadListParams.java new file mode 100644 index 0000000..77e5a77 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadListParams.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SessionThreadListParams { + private final Map query; + + private SessionThreadListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SessionThreadListParams build() { + return new SessionThreadListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadListResponse.java new file mode 100644 index 0000000..f046771 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SessionThreadListResponse + extends CursorPage { + public SessionThreadListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SessionThreadListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new SessionThread(item, requestId), true); + } + + @Override + protected SessionThreadListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreadStats.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreadStats.java new file mode 100644 index 0000000..aa1a5d4 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreadStats.java @@ -0,0 +1,28 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionThreadStats extends JsonObject { + private SessionThreadStats(JsonValue value) { + super(value); + } + + public static SessionThreadStats fromJson(JsonValue value) { + return new SessionThreadStats(value); + } + + public BigDecimal activeSeconds() { + return optional("active_seconds", JsonValue::asDecimal); + } + + public BigDecimal durationSeconds() { + return optional("duration_seconds", JsonValue::asDecimal); + } + + public BigDecimal startupSeconds() { + return optional("startup_seconds", JsonValue::asDecimal); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionThreads.java b/src/main/java/com/qoder/cloudagents/managed/SessionThreads.java new file mode 100644 index 0000000..64cc8c2 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionThreads.java @@ -0,0 +1,92 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class SessionThreads { + private final AsyncSessionThreads async; + + public SessionThreads(AsyncSessionThreads async) { + this.async = async; + } + + public SessionThreadEvents events() { + return new SessionThreadEvents(async.events()); + } + + public SessionThread archive(String sessionId, String threadId) { + return archive(sessionId, threadId, RequestOptions.DEFAULT); + } + + public SessionThread archive(String sessionId, String threadId, RequestOptions options) { + return Futures.await(async.archive(sessionId, threadId, options)); + } + + public SessionThread retrieve(String sessionId, String threadId) { + return retrieve(sessionId, threadId, RequestOptions.DEFAULT); + } + + public SessionThread retrieve(String sessionId, String threadId, RequestOptions options) { + return Futures.await(async.retrieve(sessionId, threadId, options)); + } + + public SessionThreadListResponse list(String sessionId) { + return list(sessionId, SessionThreadListParams.builder().build()); + } + + public SessionThreadListResponse list(String sessionId, RequestOptions options) { + return list(sessionId, SessionThreadListParams.builder().build(), options); + } + + public SessionThreadListResponse list(String sessionId, SessionThreadListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public SessionThreadListResponse list( + String sessionId, SessionThreadListParams params, RequestOptions options) { + return Futures.await(async.list(sessionId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String sessionId, String threadId) { + return archive(sessionId, threadId, RequestOptions.DEFAULT); + } + + public ApiResponse archive( + String sessionId, String threadId, RequestOptions options) { + return Futures.await(async.withResponse().archive(sessionId, threadId, options)); + } + + public ApiResponse retrieve(String sessionId, String threadId) { + return retrieve(sessionId, threadId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String sessionId, String threadId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(sessionId, threadId, options)); + } + + public ApiResponse list(String sessionId) { + return list(sessionId, SessionThreadListParams.builder().build()); + } + + public ApiResponse list(String sessionId, RequestOptions options) { + return list(sessionId, SessionThreadListParams.builder().build(), options); + } + + public ApiResponse list( + String sessionId, SessionThreadListParams params) { + return list(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String sessionId, SessionThreadListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(sessionId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/SessionUpdateParams.java new file mode 100644 index 0000000..42942ae --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionUpdateParams.java @@ -0,0 +1,71 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionUpdateParams extends JsonObject { + private SessionUpdateParams(JsonValue value) { + super(value); + } + + public static SessionUpdateParams fromJson(JsonValue value) { + return new SessionUpdateParams(value); + } + + public SessionAgentPatch agent() { + return optional("agent", SessionAgentPatch::fromJson); + } + + public SessionBudget budget() { + return optional("budget", SessionBudget::fromJson); + } + + public String title() { + return optional("title", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", v -> v); + } + + public Map environmentVariables() { + return optionalNullableMap("environment_variables", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder agent(SessionAgentPatch value) { + return put("agent", value); + } + + public Builder budget(SessionBudget value) { + return put("budget", value); + } + + public Builder title(String value) { + return put("title", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder environmentVariables(Map value) { + return put("environment_variables", value); + } + + public SessionUpdateParams build() { + JsonValue agent = json().get("agent"); + if (!agent.isMissing() && !agent.isNull() && !agent.isObject()) + throw new ConfigurationException("Session agent updates require a runtime patch"); + return new SessionUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SessionUsage.java b/src/main/java/com/qoder/cloudagents/managed/SessionUsage.java new file mode 100644 index 0000000..c4307c0 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SessionUsage.java @@ -0,0 +1,28 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.math.BigDecimal; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SessionUsage extends JsonObject { + private SessionUsage(JsonValue value) { + super(value); + } + + public static SessionUsage fromJson(JsonValue value) { + return new SessionUsage(value); + } + + public BigDecimal totalCredits() { + return optional("total_credits", JsonValue::asDecimal); + } + + public BigDecimal modelCredits() { + return optional("model_credits", JsonValue::asDecimal); + } + + public BigDecimal sandboxRuntimeCredits() { + return optional("sandbox_runtime_credits", JsonValue::asDecimal); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Sessions.java b/src/main/java/com/qoder/cloudagents/managed/Sessions.java new file mode 100644 index 0000000..a21a7fb --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Sessions.java @@ -0,0 +1,193 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Sessions { + private final AsyncSessions async; + + public Sessions(AsyncSessions async) { + this.async = async; + } + + public SessionEvents events() { + return new SessionEvents(async.events()); + } + + public SessionThreads threads() { + return new SessionThreads(async.threads()); + } + + public SessionResources resources() { + return new SessionResources(async.resources()); + } + + public Session archive(String sessionId) { + return archive(sessionId, RequestOptions.DEFAULT); + } + + public Session archive(String sessionId, RequestOptions options) { + return Futures.await(async.archive(sessionId, options)); + } + + public Session cancel(String sessionId) { + return cancel(sessionId, RequestOptions.DEFAULT); + } + + public Session cancel(String sessionId, RequestOptions options) { + return Futures.await(async.cancel(sessionId, options)); + } + + public Session create(SessionCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Session create(SessionCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public DeletedSession delete(String sessionId) { + return delete(sessionId, RequestOptions.DEFAULT); + } + + public DeletedSession delete(String sessionId, RequestOptions options) { + return Futures.await(async.delete(sessionId, options)); + } + + public Session retrieve(String sessionId) { + return retrieve(sessionId, RequestOptions.DEFAULT); + } + + public Session retrieve(String sessionId, RequestOptions options) { + return Futures.await(async.retrieve(sessionId, options)); + } + + public SessionListResponse list() { + return list(SessionListParams.builder().build()); + } + + public SessionListResponse list(RequestOptions options) { + return list(SessionListParams.builder().build(), options); + } + + public SessionListResponse list(SessionListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public SessionListResponse list(SessionListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public SessionListResponse search() { + return search(SessionSearchParams.builder().build()); + } + + public SessionListResponse search(RequestOptions options) { + return search(SessionSearchParams.builder().build(), options); + } + + public SessionListResponse search(SessionSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public SessionListResponse search(SessionSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public Session update(String sessionId, SessionUpdateParams params) { + return update(sessionId, params, RequestOptions.DEFAULT); + } + + public Session update(String sessionId, SessionUpdateParams params, RequestOptions options) { + return Futures.await(async.update(sessionId, params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String sessionId) { + return archive(sessionId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String sessionId, RequestOptions options) { + return Futures.await(async.withResponse().archive(sessionId, options)); + } + + public ApiResponse cancel(String sessionId) { + return cancel(sessionId, RequestOptions.DEFAULT); + } + + public ApiResponse cancel(String sessionId, RequestOptions options) { + return Futures.await(async.withResponse().cancel(sessionId, options)); + } + + public ApiResponse create(SessionCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(SessionCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse delete(String sessionId) { + return delete(sessionId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String sessionId, RequestOptions options) { + return Futures.await(async.withResponse().delete(sessionId, options)); + } + + public ApiResponse retrieve(String sessionId) { + return retrieve(sessionId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String sessionId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(sessionId, options)); + } + + public ApiResponse list() { + return list(SessionListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(SessionListParams.builder().build(), options); + } + + public ApiResponse list(SessionListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(SessionListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse search() { + return search(SessionSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(SessionSearchParams.builder().build(), options); + } + + public ApiResponse search(SessionSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search( + SessionSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse update(String sessionId, SessionUpdateParams params) { + return update(sessionId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String sessionId, SessionUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(sessionId, params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Skill.java b/src/main/java/com/qoder/cloudagents/managed/Skill.java new file mode 100644 index 0000000..e257bd0 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Skill.java @@ -0,0 +1,55 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class Skill extends JsonModel { + public Skill(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String displayTitle() { + return optional("display_title", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String source() { + return optional("source", JsonValue::asString); + } + + public String latestVersion() { + return optional("latest_version", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public String contentEncoding() { + return optional("content_encoding", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillBinding.java b/src/main/java/com/qoder/cloudagents/managed/SkillBinding.java new file mode 100644 index 0000000..7a2d40c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillBinding.java @@ -0,0 +1,61 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; + +/** Immutable SkillBinding configuration. Unknown fields are retained through field(). */ +public final class SkillBinding extends JsonObject { + private SkillBinding(JsonValue value) { + super(value); + } + + public static SkillBinding fromJson(JsonValue value) { + return new SkillBinding(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String skillId() { + return optional("skill_id", JsonValue::asString); + } + + public String version() { + return optional("version", JsonValue::asString); + } + + public Boolean enabled() { + return optional("enabled", JsonValue::asBoolean); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder skillId(String value) { + return put("skill_id", value); + } + + public Builder version(String value) { + return put("version", value); + } + + public Builder enabled(Boolean value) { + return put("enabled", value); + } + + public SkillBinding build() { + require("type", "skill_id"); + return new SkillBinding(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillCreateParams.java new file mode 100644 index 0000000..2af3d53 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillCreateParams.java @@ -0,0 +1,108 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Multipart Skill package. Upload files keep their relative path in the filename. */ +public final class SkillCreateParams { + private final List files; + private final Upload file; + private final JsonValue fields; + + private SkillCreateParams(Builder b, JsonValue fields) { + files = Collections.unmodifiableList(new ArrayList<>(b.files)); + file = b.file; + this.fields = fields; + } + + public List files() { + return files; + } + + public Upload file() { + return file; + } + + public JsonValue fields() { + return fields; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private final List files = new ArrayList<>(); + private Upload file; + + public Builder files(List value) { + if (value == null || value.stream().anyMatch(Objects::isNull)) + throw new ConfigurationException("files cannot contain null"); + files.clear(); + files.addAll(value); + return this; + } + + public Builder addFile(Upload value) { + if (value == null) throw new ConfigurationException("file cannot be null"); + files.add(value); + return this; + } + + /** + * @deprecated Use addFile or files instead. + */ + @Deprecated + public Builder file(Upload value) { + if (value == null) throw new ConfigurationException("file cannot be null"); + file = value; + return this; + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder displayTitle(String value) { + return put("display_title", value); + } + + /** + * @deprecated The canonical name is read from SKILL.md. + */ + @Deprecated + public Builder name(String value) { + return put("name", value); + } + + /** + * @deprecated The description is read from SKILL.md. + */ + @Deprecated + public Builder description(String value) { + return put("description", value); + } + + /** + * @deprecated Use custom package creation. + */ + @Deprecated + public Builder type(String value) { + return put("type", value); + } + + public SkillCreateParams build() { + if (files.isEmpty() && file == null) + throw new ConfigurationException("Supply Skill package files"); + if (!json().get("file").isMissing() || !json().get("files").isMissing()) + throw new ConfigurationException("Use Upload setters for multipart files"); + return new SkillCreateParams(this, json()); + } + } + + @Override + public String toString() { + return "SkillCreateParams([redacted])"; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillListParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillListParams.java new file mode 100644 index 0000000..3b9893e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillListParams.java @@ -0,0 +1,71 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SkillListParams { + private final Map query; + + private SkillListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder source(String value) { + return put("source", value); + } + + public Builder displayTitle(String value) { + return put("display_title", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SkillListParams build() { + return new SkillListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SkillListResponse.java new file mode 100644 index 0000000..064d5ec --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SkillListResponse extends CursorPage { + public SkillListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SkillListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Skill(item, requestId), true); + } + + @Override + protected SkillListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillRetrieveParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillRetrieveParams.java new file mode 100644 index 0000000..1e93008 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillRetrieveParams.java @@ -0,0 +1,40 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SkillRetrieveParams { + private final Map query; + + private SkillRetrieveParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder includeContent(boolean value) { + return put("include_content", String.valueOf(value)); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SkillRetrieveParams build() { + return new SkillRetrieveParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillSearchParams.java new file mode 100644 index 0000000..62fc6a2 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillSearchParams.java @@ -0,0 +1,83 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SkillSearchParams extends JsonObject { + private SkillSearchParams(JsonValue value) { + super(value); + } + + public static SkillSearchParams fromJson(JsonValue value) { + return new SkillSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public String source() { + return optional("source", JsonValue::asString); + } + + public String displayTitle() { + return optional("display_title", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder source(String value) { + return put("source", value); + } + + public Builder displayTitle(String value) { + return put("display_title", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public SkillSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new SkillSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillUpdateParams.java new file mode 100644 index 0000000..0aa02ca --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillUpdateParams.java @@ -0,0 +1,68 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class SkillUpdateParams extends JsonObject { + private SkillUpdateParams(JsonValue value) { + super(value); + } + + public static SkillUpdateParams fromJson(JsonValue value) { + return new SkillUpdateParams(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String content() { + return optional("content", JsonValue::asString); + } + + public String contentEncoding() { + return optional("content_encoding", JsonValue::asString); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder content(String value) { + return put("content", value); + } + + public Builder contentEncoding(String value) { + return put("content_encoding", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public SkillUpdateParams build() { + + return new SkillUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillVersion.java b/src/main/java/com/qoder/cloudagents/managed/SkillVersion.java new file mode 100644 index 0000000..7c2419c --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillVersion.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class SkillVersion extends JsonModel { + public SkillVersion(JsonValue value, String requestId) { + super(value, requestId); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String skillId() { + return optional("skill_id", JsonValue::asString); + } + + public String version() { + return optional("version", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public String directory() { + return optional("directory", JsonValue::asString); + } + + public String contentSha256() { + return optional("content_sha256", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public Long contentSize() { + return optional("content_size", JsonValue::asLong); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillVersionCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillVersionCreateParams.java new file mode 100644 index 0000000..791cb65 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillVersionCreateParams.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Multipart Skill package. Upload files keep their relative path in the filename. */ +public final class SkillVersionCreateParams { + private final List files; + + private final JsonValue fields; + + private SkillVersionCreateParams(Builder b, JsonValue fields) { + files = Collections.unmodifiableList(new ArrayList<>(b.files)); + this.fields = fields; + } + + public List files() { + return files; + } + + public JsonValue fields() { + return fields; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private final List files = new ArrayList<>(); + + public Builder files(List value) { + if (value == null || value.stream().anyMatch(Objects::isNull)) + throw new ConfigurationException("files cannot contain null"); + files.clear(); + files.addAll(value); + return this; + } + + public Builder addFile(Upload value) { + if (value == null) throw new ConfigurationException("file cannot be null"); + files.add(value); + return this; + } + + public SkillVersionCreateParams build() { + if (files.isEmpty()) throw new ConfigurationException("Supply Skill package files"); + if (!json().get("file").isMissing() || !json().get("files").isMissing()) + throw new ConfigurationException("Use Upload setters for multipart files"); + return new SkillVersionCreateParams(this, json()); + } + } + + @Override + public String toString() { + return "SkillVersionCreateParams([redacted])"; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillVersionListParams.java b/src/main/java/com/qoder/cloudagents/managed/SkillVersionListParams.java new file mode 100644 index 0000000..0dffafa --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillVersionListParams.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class SkillVersionListParams { + private final Map query; + + private SkillVersionListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public SkillVersionListParams build() { + return new SkillVersionListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillVersionListResponse.java b/src/main/java/com/qoder/cloudagents/managed/SkillVersionListResponse.java new file mode 100644 index 0000000..a56e02d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillVersionListResponse.java @@ -0,0 +1,29 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class SkillVersionListResponse + extends CursorPage { + public SkillVersionListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + SkillVersionListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super(value, requestId, query, seen, fetcher, item -> new SkillVersion(item, requestId), true); + } + + @Override + protected SkillVersionListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/SkillVersions.java b/src/main/java/com/qoder/cloudagents/managed/SkillVersions.java new file mode 100644 index 0000000..600fd7d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/SkillVersions.java @@ -0,0 +1,123 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class SkillVersions { + private final AsyncSkillVersions async; + + public SkillVersions(AsyncSkillVersions async) { + this.async = async; + } + + public SkillVersionListResponse list(String skillId) { + return list(skillId, SkillVersionListParams.builder().build()); + } + + public SkillVersionListResponse list(String skillId, RequestOptions options) { + return list(skillId, SkillVersionListParams.builder().build(), options); + } + + public SkillVersionListResponse list(String skillId, SkillVersionListParams params) { + return list(skillId, params, RequestOptions.DEFAULT); + } + + public SkillVersionListResponse list( + String skillId, SkillVersionListParams params, RequestOptions options) { + return Futures.await(async.list(skillId, params, options)); + } + + public SkillVersion create(String skillId, SkillVersionCreateParams params) { + return create(skillId, params, RequestOptions.DEFAULT); + } + + public SkillVersion create( + String skillId, SkillVersionCreateParams params, RequestOptions options) { + return Futures.await(async.create(skillId, params, options)); + } + + public SkillVersion retrieve(String skillId, String version) { + return retrieve(skillId, version, RequestOptions.DEFAULT); + } + + public SkillVersion retrieve(String skillId, String version, RequestOptions options) { + return Futures.await(async.retrieve(skillId, version, options)); + } + + public DeletedSkillVersion delete(String skillId, String version) { + return delete(skillId, version, RequestOptions.DEFAULT); + } + + public DeletedSkillVersion delete(String skillId, String version, RequestOptions options) { + return Futures.await(async.delete(skillId, version, options)); + } + + public FileDownload download(String skillId, String version) { + return download(skillId, version, RequestOptions.DEFAULT); + } + + public FileDownload download(String skillId, String version, RequestOptions options) { + return Futures.await(async.download(skillId, version, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse list(String skillId) { + return list(skillId, SkillVersionListParams.builder().build()); + } + + public ApiResponse list(String skillId, RequestOptions options) { + return list(skillId, SkillVersionListParams.builder().build(), options); + } + + public ApiResponse list( + String skillId, SkillVersionListParams params) { + return list(skillId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String skillId, SkillVersionListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(skillId, params, options)); + } + + public ApiResponse create(String skillId, SkillVersionCreateParams params) { + return create(skillId, params, RequestOptions.DEFAULT); + } + + public ApiResponse create( + String skillId, SkillVersionCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(skillId, params, options)); + } + + public ApiResponse retrieve(String skillId, String version) { + return retrieve(skillId, version, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String skillId, String version, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(skillId, version, options)); + } + + public ApiResponse delete(String skillId, String version) { + return delete(skillId, version, RequestOptions.DEFAULT); + } + + public ApiResponse delete( + String skillId, String version, RequestOptions options) { + return Futures.await(async.withResponse().delete(skillId, version, options)); + } + + public ApiResponse download(String skillId, String version) { + return download(skillId, version, RequestOptions.DEFAULT); + } + + public ApiResponse download( + String skillId, String version, RequestOptions options) { + return Futures.await(async.withResponse().download(skillId, version, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Skills.java b/src/main/java/com/qoder/cloudagents/managed/Skills.java new file mode 100644 index 0000000..e8bcfba --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Skills.java @@ -0,0 +1,185 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Skills { + private final AsyncSkills async; + + public Skills(AsyncSkills async) { + this.async = async; + } + + public SkillVersions versions() { + return new SkillVersions(async.versions()); + } + + public SkillListResponse list() { + return list(SkillListParams.builder().build()); + } + + public SkillListResponse list(RequestOptions options) { + return list(SkillListParams.builder().build(), options); + } + + public SkillListResponse list(SkillListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public SkillListResponse list(SkillListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public Skill create(SkillCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Skill create(SkillCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public Skill retrieve(String skillId) { + return retrieve(skillId, SkillRetrieveParams.builder().build()); + } + + public Skill retrieve(String skillId, RequestOptions options) { + return retrieve(skillId, SkillRetrieveParams.builder().build(), options); + } + + public Skill retrieve(String skillId, SkillRetrieveParams params) { + return retrieve(skillId, params, RequestOptions.DEFAULT); + } + + public Skill retrieve(String skillId, SkillRetrieveParams params, RequestOptions options) { + return Futures.await(async.retrieve(skillId, params, options)); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public Skill update(String skillId, SkillUpdateParams params) { + return update(skillId, params, RequestOptions.DEFAULT); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public Skill update(String skillId, SkillUpdateParams params, RequestOptions options) { + return Futures.await(async.update(skillId, params, options)); + } + + public DeletedSkill delete(String skillId) { + return delete(skillId, RequestOptions.DEFAULT); + } + + public DeletedSkill delete(String skillId, RequestOptions options) { + return Futures.await(async.delete(skillId, options)); + } + + public SkillListResponse search(SkillSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public SkillListResponse search(SkillSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public SkillListResponse search() { + return search(SkillSearchParams.builder().build()); + } + + public SkillListResponse search(RequestOptions options) { + return search(SkillSearchParams.builder().build(), options); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse search() { + return search(SkillSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(SkillSearchParams.builder().build(), options); + } + + public ApiResponse search(SkillSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search(SkillSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + + public ApiResponse list() { + return list(SkillListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(SkillListParams.builder().build(), options); + } + + public ApiResponse list(SkillListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(SkillListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse create(SkillCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(SkillCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse retrieve(String skillId) { + return retrieve(skillId, SkillRetrieveParams.builder().build()); + } + + public ApiResponse retrieve(String skillId, RequestOptions options) { + return retrieve(skillId, SkillRetrieveParams.builder().build(), options); + } + + public ApiResponse retrieve(String skillId, SkillRetrieveParams params) { + return retrieve(skillId, params, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String skillId, SkillRetrieveParams params, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(skillId, params, options)); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public ApiResponse update(String skillId, SkillUpdateParams params) { + return update(skillId, params, RequestOptions.DEFAULT); + } + + /** + * @deprecated Append an immutable Skill version instead. + */ + @Deprecated + public ApiResponse update( + String skillId, SkillUpdateParams params, RequestOptions options) { + return Futures.await(async.withResponse().update(skillId, params, options)); + } + + public ApiResponse delete(String skillId) { + return delete(skillId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String skillId, RequestOptions options) { + return Futures.await(async.withResponse().delete(skillId, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Tool.java b/src/main/java/com/qoder/cloudagents/managed/Tool.java new file mode 100644 index 0000000..bd6b799 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Tool.java @@ -0,0 +1,94 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; +import java.util.List; + +/** Immutable Tool configuration. Unknown fields are retained through field(). */ +public final class Tool extends JsonObject { + private Tool(JsonValue value) { + super(value); + } + + public static Tool fromJson(JsonValue value) { + return new Tool(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public List enabledTools() { + return optionalList("enabled_tools", JsonValue::asString); + } + + public List disallowedTools() { + return optionalList("disallowed_tools", JsonValue::asString); + } + + public List configs() { + return optionalList("configs", ToolConfig::fromJson); + } + + public String mcpServerName() { + return optional("mcp_server_name", JsonValue::asString); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public String description() { + return optional("description", JsonValue::asString); + } + + public JsonValue inputSchema() { + return field("input_schema"); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder enabledTools(List value) { + return put("enabled_tools", value); + } + + public Builder disallowedTools(List value) { + return put("disallowed_tools", value); + } + + public Builder configs(List value) { + return put("configs", value); + } + + public Builder mcpServerName(String value) { + return put("mcp_server_name", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public Builder description(String value) { + return put("description", value); + } + + public Builder inputSchema(JsonValue value) { + return put("input_schema", value); + } + + public Tool build() { + require("type"); + return new Tool(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/ToolConfig.java b/src/main/java/com/qoder/cloudagents/managed/ToolConfig.java new file mode 100644 index 0000000..f4d6483 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/ToolConfig.java @@ -0,0 +1,53 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.JsonObject; +import com.qoder.cloudagents.core.JsonObjectBuilder; +import com.qoder.cloudagents.core.JsonValue; + +/** Immutable ToolConfig configuration. Unknown fields are retained through field(). */ +public final class ToolConfig extends JsonObject { + private ToolConfig(JsonValue value) { + super(value); + } + + public static ToolConfig fromJson(JsonValue value) { + return new ToolConfig(value); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public Boolean enabled() { + return optional("enabled", JsonValue::asBoolean); + } + + public PermissionPolicy permissionPolicy() { + return optional("permission_policy", PermissionPolicy::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder name(String value) { + return put("name", value); + } + + public Builder enabled(Boolean value) { + return put("enabled", value); + } + + public Builder permissionPolicy(PermissionPolicy value) { + return put("permission_policy", value); + } + + public ToolConfig build() { + require("name"); + return new ToolConfig(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Vault.java b/src/main/java/com/qoder/cloudagents/managed/Vault.java new file mode 100644 index 0000000..13ad80e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Vault.java @@ -0,0 +1,43 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class Vault extends JsonModel { + public Vault(JsonValue value, String requestId) { + super(value, requestId); + } + + public List credentials() { + return optionalList("credentials", v -> new VaultCredential(v, requestId())); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String displayName() { + return optional("display_name", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultCreateParams.java new file mode 100644 index 0000000..3c55588 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCreateParams.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCreateParams extends JsonObject { + private VaultCreateParams(JsonValue value) { + super(value); + } + + public static VaultCreateParams fromJson(JsonValue value) { + return new VaultCreateParams(value); + } + + public String displayName() { + return optional("display_name", JsonValue::asString); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder displayName(String value) { + return put("display_name", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public VaultCreateParams build() { + require("display_name"); + return new VaultCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredential.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredential.java new file mode 100644 index 0000000..22ea34b --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredential.java @@ -0,0 +1,47 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response preserving unknown fields. */ +public final class VaultCredential extends JsonModel { + public VaultCredential(JsonValue value, String requestId) { + super(value, requestId); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String vaultId() { + return optional("vault_id", JsonValue::asString); + } + + public String displayName() { + return optional("display_name", JsonValue::asString); + } + + public String archivedAt() { + return optional("archived_at", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String updatedAt() { + return optional("updated_at", JsonValue::asString); + } + + public VaultCredentialAuth auth() { + return optional("auth", VaultCredentialAuth::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialAuth.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialAuth.java new file mode 100644 index 0000000..2cc1fb2 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialAuth.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialAuth extends JsonObject { + private VaultCredentialAuth(JsonValue value) { + super(value); + } + + public static VaultCredentialAuth fromJson(JsonValue value) { + return new VaultCredentialAuth(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String mcpServerUrl() { + return optional("mcp_server_url", JsonValue::asString); + } + + public String secretName() { + return optional("secret_name", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder mcpServerUrl(String value) { + return put("mcp_server_url", value); + } + + public Builder secretName(String value) { + return put("secret_name", value); + } + + public VaultCredentialAuth build() { + return new VaultCredentialAuth(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateAuth.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateAuth.java new file mode 100644 index 0000000..139a375 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateAuth.java @@ -0,0 +1,92 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialCreateAuth extends JsonObject { + private VaultCredentialCreateAuth(JsonValue value) { + super(value); + } + + public static VaultCredentialCreateAuth fromJson(JsonValue value) { + return new VaultCredentialCreateAuth(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String mcpServerUrl() { + return optional("mcp_server_url", JsonValue::asString); + } + + public String token() { + return optional("token", JsonValue::asString); + } + + public String accessToken() { + return optional("access_token", JsonValue::asString); + } + + public String expiresAt() { + return optional("expires_at", JsonValue::asString); + } + + public String secretName() { + return optional("secret_name", JsonValue::asString); + } + + public String secretValue() { + return optional("secret_value", JsonValue::asString); + } + + public VaultCredentialOAuthRefresh refresh() { + return optional("refresh", VaultCredentialOAuthRefresh::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder mcpServerUrl(String value) { + return put("mcp_server_url", value); + } + + public Builder token(String value) { + return put("token", value); + } + + public Builder accessToken(String value) { + return put("access_token", value); + } + + public Builder expiresAt(String value) { + return put("expires_at", value); + } + + public Builder secretName(String value) { + return put("secret_name", value); + } + + public Builder secretValue(String value) { + return put("secret_value", value); + } + + public Builder refresh(VaultCredentialOAuthRefresh value) { + return put("refresh", value); + } + + public VaultCredentialCreateAuth build() { + require("type"); + return new VaultCredentialCreateAuth(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateParams.java new file mode 100644 index 0000000..2a3b6ba --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialCreateParams.java @@ -0,0 +1,52 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialCreateParams extends JsonObject { + private VaultCredentialCreateParams(JsonValue value) { + super(value); + } + + public static VaultCredentialCreateParams fromJson(JsonValue value) { + return new VaultCredentialCreateParams(value); + } + + public VaultCredentialCreateAuth auth() { + return optional("auth", VaultCredentialCreateAuth::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } + + public String displayName() { + return optional("display_name", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder auth(VaultCredentialCreateAuth value) { + return put("auth", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder displayName(String value) { + return put("display_name", value); + } + + public VaultCredentialCreateParams build() { + require("auth"); + return new VaultCredentialCreateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListParams.java new file mode 100644 index 0000000..22e54e6 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListParams.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class VaultCredentialListParams { + private final Map query; + + private VaultCredentialListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder name(String value) { + return put("name", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public VaultCredentialListParams build() { + return new VaultCredentialListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListResponse.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListResponse.java new file mode 100644 index 0000000..efbeccf --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialListResponse.java @@ -0,0 +1,30 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class VaultCredentialListResponse + extends CursorPage { + public VaultCredentialListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + VaultCredentialListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> + fetcher) { + super( + value, requestId, query, seen, fetcher, item -> new VaultCredential(item, requestId), true); + } + + @Override + protected VaultCredentialListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefresh.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefresh.java new file mode 100644 index 0000000..7a69a39 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefresh.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialOAuthRefresh extends JsonObject { + private VaultCredentialOAuthRefresh(JsonValue value) { + super(value); + } + + public static VaultCredentialOAuthRefresh fromJson(JsonValue value) { + return new VaultCredentialOAuthRefresh(value); + } + + public String refreshToken() { + return optional("refresh_token", JsonValue::asString); + } + + public String clientId() { + return optional("client_id", JsonValue::asString); + } + + public String tokenEndpoint() { + return optional("token_endpoint", JsonValue::asString); + } + + public String scope() { + return optional("scope", JsonValue::asString); + } + + public JsonValue tokenEndpointAuth() { + return field("token_endpoint_auth"); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder refreshToken(String value) { + return put("refresh_token", value); + } + + public Builder clientId(String value) { + return put("client_id", value); + } + + public Builder tokenEndpoint(String value) { + return put("token_endpoint", value); + } + + public Builder scope(String value) { + return put("scope", value); + } + + public Builder tokenEndpointAuth(JsonValue value) { + return put("token_endpoint_auth", value); + } + + public VaultCredentialOAuthRefresh build() { + return new VaultCredentialOAuthRefresh(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefreshUpdate.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefreshUpdate.java new file mode 100644 index 0000000..bea0ff3 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialOAuthRefreshUpdate.java @@ -0,0 +1,51 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialOAuthRefreshUpdate extends JsonObject { + private VaultCredentialOAuthRefreshUpdate(JsonValue value) { + super(value); + } + + public static VaultCredentialOAuthRefreshUpdate fromJson(JsonValue value) { + return new VaultCredentialOAuthRefreshUpdate(value); + } + + public String refreshToken() { + return optional("refresh_token", JsonValue::asString); + } + + public String scope() { + return optional("scope", JsonValue::asString); + } + + public JsonValue tokenEndpointAuth() { + return field("token_endpoint_auth"); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder refreshToken(String value) { + return put("refresh_token", value); + } + + public Builder scope(String value) { + return put("scope", value); + } + + public Builder tokenEndpointAuth(JsonValue value) { + return put("token_endpoint_auth", value); + } + + public VaultCredentialOAuthRefreshUpdate build() { + return new VaultCredentialOAuthRefreshUpdate(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateAuth.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateAuth.java new file mode 100644 index 0000000..5b37f48 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateAuth.java @@ -0,0 +1,76 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialUpdateAuth extends JsonObject { + private VaultCredentialUpdateAuth(JsonValue value) { + super(value); + } + + public static VaultCredentialUpdateAuth fromJson(JsonValue value) { + return new VaultCredentialUpdateAuth(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String token() { + return optional("token", JsonValue::asString); + } + + public String accessToken() { + return optional("access_token", JsonValue::asString); + } + + public String expiresAt() { + return optional("expires_at", JsonValue::asString); + } + + public String secretValue() { + return optional("secret_value", JsonValue::asString); + } + + public VaultCredentialOAuthRefreshUpdate refresh() { + return optional("refresh", VaultCredentialOAuthRefreshUpdate::fromJson); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder token(String value) { + return put("token", value); + } + + public Builder accessToken(String value) { + return put("access_token", value); + } + + public Builder expiresAt(String value) { + return put("expires_at", value); + } + + public Builder secretValue(String value) { + return put("secret_value", value); + } + + public Builder refresh(VaultCredentialOAuthRefreshUpdate value) { + return put("refresh", value); + } + + public VaultCredentialUpdateAuth build() { + require("type"); + return new VaultCredentialUpdateAuth(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateParams.java new file mode 100644 index 0000000..8265c28 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialUpdateParams.java @@ -0,0 +1,47 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable API configuration preserving unknown fields. */ +public final class VaultCredentialUpdateParams extends JsonObject { + private VaultCredentialUpdateParams(JsonValue value) { + super(value); + } + + public static VaultCredentialUpdateParams fromJson(JsonValue value) { + return new VaultCredentialUpdateParams(value); + } + + public VaultCredentialUpdateAuth auth() { + return optional("auth", VaultCredentialUpdateAuth::fromJson); + } + + public Map metadata() { + return optionalMap("metadata", v -> v); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder auth(VaultCredentialUpdateAuth value) { + return put("auth", value); + } + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public VaultCredentialUpdateParams build() { + if (json().get("auth").isMissing() && json().get("metadata").isMissing()) + throw new ConfigurationException("Supply auth or metadata"); + if (json().get("auth").isNull()) throw new ConfigurationException("auth cannot be null"); + return new VaultCredentialUpdateParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentialValidation.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialValidation.java new file mode 100644 index 0000000..ce3957f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentialValidation.java @@ -0,0 +1,47 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class VaultCredentialValidation extends JsonModel { + public VaultCredentialValidation(JsonValue value, String requestId) { + super(value, requestId); + } + + public static VaultCredentialValidation fromJson(JsonValue value) { + return new VaultCredentialValidation(value, null); + } + + public String credentialId() { + return optional("credential_id", JsonValue::asString); + } + + public String vaultId() { + return optional("vault_id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String status() { + return optional("status", JsonValue::asString); + } + + public String validatedAt() { + return optional("validated_at", JsonValue::asString); + } + + public Boolean hasRefreshToken() { + return optional("has_refresh_token", JsonValue::asBoolean); + } + + public CredentialRefreshResult refresh() { + return optional("refresh", CredentialRefreshResult::fromJson); + } + + public CredentialProbeResult mcpProbe() { + return optional("mcp_probe", CredentialProbeResult::fromJson); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultCredentials.java b/src/main/java/com/qoder/cloudagents/managed/VaultCredentials.java new file mode 100644 index 0000000..660e279 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultCredentials.java @@ -0,0 +1,168 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class VaultCredentials { + private final AsyncVaultCredentials async; + + public VaultCredentials(AsyncVaultCredentials async) { + this.async = async; + } + + public VaultCredential archive(String vaultId, String credentialId) { + return archive(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public VaultCredential archive(String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.archive(vaultId, credentialId, options)); + } + + public VaultCredential create(String vaultId, VaultCredentialCreateParams params) { + return create(vaultId, params, RequestOptions.DEFAULT); + } + + public VaultCredential create( + String vaultId, VaultCredentialCreateParams params, RequestOptions options) { + return Futures.await(async.create(vaultId, params, options)); + } + + public DeletedVaultCredential delete(String vaultId, String credentialId) { + return delete(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public DeletedVaultCredential delete( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.delete(vaultId, credentialId, options)); + } + + public VaultCredential retrieve(String vaultId, String credentialId) { + return retrieve(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public VaultCredential retrieve(String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.retrieve(vaultId, credentialId, options)); + } + + public VaultCredentialListResponse list(String vaultId) { + return list(vaultId, VaultCredentialListParams.builder().build()); + } + + public VaultCredentialListResponse list(String vaultId, RequestOptions options) { + return list(vaultId, VaultCredentialListParams.builder().build(), options); + } + + public VaultCredentialListResponse list(String vaultId, VaultCredentialListParams params) { + return list(vaultId, params, RequestOptions.DEFAULT); + } + + public VaultCredentialListResponse list( + String vaultId, VaultCredentialListParams params, RequestOptions options) { + return Futures.await(async.list(vaultId, params, options)); + } + + public VaultCredential update( + String vaultId, String credentialId, VaultCredentialUpdateParams params) { + return update(vaultId, credentialId, params, RequestOptions.DEFAULT); + } + + public VaultCredential update( + String vaultId, + String credentialId, + VaultCredentialUpdateParams params, + RequestOptions options) { + return Futures.await(async.update(vaultId, credentialId, params, options)); + } + + public VaultCredentialValidation validate(String vaultId, String credentialId) { + return validate(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public VaultCredentialValidation validate( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.validate(vaultId, credentialId, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String vaultId, String credentialId) { + return archive(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public ApiResponse archive( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.withResponse().archive(vaultId, credentialId, options)); + } + + public ApiResponse create(String vaultId, VaultCredentialCreateParams params) { + return create(vaultId, params, RequestOptions.DEFAULT); + } + + public ApiResponse create( + String vaultId, VaultCredentialCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(vaultId, params, options)); + } + + public ApiResponse delete(String vaultId, String credentialId) { + return delete(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public ApiResponse delete( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.withResponse().delete(vaultId, credentialId, options)); + } + + public ApiResponse retrieve(String vaultId, String credentialId) { + return retrieve(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(vaultId, credentialId, options)); + } + + public ApiResponse list(String vaultId) { + return list(vaultId, VaultCredentialListParams.builder().build()); + } + + public ApiResponse list(String vaultId, RequestOptions options) { + return list(vaultId, VaultCredentialListParams.builder().build(), options); + } + + public ApiResponse list( + String vaultId, VaultCredentialListParams params) { + return list(vaultId, params, RequestOptions.DEFAULT); + } + + public ApiResponse list( + String vaultId, VaultCredentialListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(vaultId, params, options)); + } + + public ApiResponse update( + String vaultId, String credentialId, VaultCredentialUpdateParams params) { + return update(vaultId, credentialId, params, RequestOptions.DEFAULT); + } + + public ApiResponse update( + String vaultId, + String credentialId, + VaultCredentialUpdateParams params, + RequestOptions options) { + return Futures.await(async.withResponse().update(vaultId, credentialId, params, options)); + } + + public ApiResponse validate(String vaultId, String credentialId) { + return validate(vaultId, credentialId, RequestOptions.DEFAULT); + } + + public ApiResponse validate( + String vaultId, String credentialId, RequestOptions options) { + return Futures.await(async.withResponse().validate(vaultId, credentialId, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultListParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultListParams.java new file mode 100644 index 0000000..14f1bef --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultListParams.java @@ -0,0 +1,67 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class VaultListParams { + private final Map query; + + private VaultListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder includeArchived(boolean value) { + return put("include_archived", String.valueOf(value)); + } + + public Builder name(String value) { + return put("name", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public VaultListParams build() { + return new VaultListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultListResponse.java b/src/main/java/com/qoder/cloudagents/managed/VaultListResponse.java new file mode 100644 index 0000000..01ddf79 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class VaultListResponse extends CursorPage { + public VaultListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + VaultListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new Vault(item, requestId), true); + } + + @Override + protected VaultListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/VaultSearchParams.java b/src/main/java/com/qoder/cloudagents/managed/VaultSearchParams.java new file mode 100644 index 0000000..53ffa8e --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/VaultSearchParams.java @@ -0,0 +1,75 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class VaultSearchParams extends JsonObject { + private VaultSearchParams(JsonValue value) { + super(value); + } + + public static VaultSearchParams fromJson(JsonValue value) { + return new VaultSearchParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public Long limit() { + return optional("limit", JsonValue::asLong); + } + + public String page() { + return optional("page", JsonValue::asString); + } + + public Boolean includeArchived() { + return optional("include_archived", JsonValue::asBoolean); + } + + public String name() { + return optional("name", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public Builder limit(Long value) { + return put("limit", value); + } + + public Builder limit(long value) { + return limit(Long.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder includeArchived(Boolean value) { + return put("include_archived", value); + } + + public Builder name(String value) { + return put("name", value); + } + + public VaultSearchParams build() { + JsonValue limit = json().get("limit"); + if (!limit.isMissing() && !limit.isNull() && (limit.asLong() < 1 || limit.asLong() > 100)) + throw new ConfigurationException("limit must be between 1 and 100"); + return new VaultSearchParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/Vaults.java b/src/main/java/com/qoder/cloudagents/managed/Vaults.java new file mode 100644 index 0000000..4571feb --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/Vaults.java @@ -0,0 +1,151 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.core.internal.*; +import java.util.*; + +public final class Vaults { + private final AsyncVaults async; + + public Vaults(AsyncVaults async) { + this.async = async; + } + + public VaultCredentials credentials() { + return new VaultCredentials(async.credentials()); + } + + public Vault archive(String vaultId) { + return archive(vaultId, RequestOptions.DEFAULT); + } + + public Vault archive(String vaultId, RequestOptions options) { + return Futures.await(async.archive(vaultId, options)); + } + + public Vault create(VaultCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public Vault create(VaultCreateParams params, RequestOptions options) { + return Futures.await(async.create(params, options)); + } + + public DeletedVault delete(String vaultId) { + return delete(vaultId, RequestOptions.DEFAULT); + } + + public DeletedVault delete(String vaultId, RequestOptions options) { + return Futures.await(async.delete(vaultId, options)); + } + + public Vault retrieve(String vaultId) { + return retrieve(vaultId, RequestOptions.DEFAULT); + } + + public Vault retrieve(String vaultId, RequestOptions options) { + return Futures.await(async.retrieve(vaultId, options)); + } + + public VaultListResponse list() { + return list(VaultListParams.builder().build()); + } + + public VaultListResponse list(RequestOptions options) { + return list(VaultListParams.builder().build(), options); + } + + public VaultListResponse list(VaultListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public VaultListResponse list(VaultListParams params, RequestOptions options) { + return Futures.await(async.list(params, options)); + } + + public VaultListResponse search() { + return search(VaultSearchParams.builder().build()); + } + + public VaultListResponse search(RequestOptions options) { + return search(VaultSearchParams.builder().build(), options); + } + + public VaultListResponse search(VaultSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public VaultListResponse search(VaultSearchParams params, RequestOptions options) { + return Futures.await(async.search(params, options)); + } + + public WithResponse withResponse() { + return new WithResponse(); + } + + public final class WithResponse { + public ApiResponse archive(String vaultId) { + return archive(vaultId, RequestOptions.DEFAULT); + } + + public ApiResponse archive(String vaultId, RequestOptions options) { + return Futures.await(async.withResponse().archive(vaultId, options)); + } + + public ApiResponse create(VaultCreateParams params) { + return create(params, RequestOptions.DEFAULT); + } + + public ApiResponse create(VaultCreateParams params, RequestOptions options) { + return Futures.await(async.withResponse().create(params, options)); + } + + public ApiResponse delete(String vaultId) { + return delete(vaultId, RequestOptions.DEFAULT); + } + + public ApiResponse delete(String vaultId, RequestOptions options) { + return Futures.await(async.withResponse().delete(vaultId, options)); + } + + public ApiResponse retrieve(String vaultId) { + return retrieve(vaultId, RequestOptions.DEFAULT); + } + + public ApiResponse retrieve(String vaultId, RequestOptions options) { + return Futures.await(async.withResponse().retrieve(vaultId, options)); + } + + public ApiResponse list() { + return list(VaultListParams.builder().build()); + } + + public ApiResponse list(RequestOptions options) { + return list(VaultListParams.builder().build(), options); + } + + public ApiResponse list(VaultListParams params) { + return list(params, RequestOptions.DEFAULT); + } + + public ApiResponse list(VaultListParams params, RequestOptions options) { + return Futures.await(async.withResponse().list(params, options)); + } + + public ApiResponse search() { + return search(VaultSearchParams.builder().build()); + } + + public ApiResponse search(RequestOptions options) { + return search(VaultSearchParams.builder().build(), options); + } + + public ApiResponse search(VaultSearchParams params) { + return search(params, RequestOptions.DEFAULT); + } + + public ApiResponse search(VaultSearchParams params, RequestOptions options) { + return Futures.await(async.withResponse().search(params, options)); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkData.java b/src/main/java/com/qoder/cloudagents/managed/WorkData.java new file mode 100644 index 0000000..900c97f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkData.java @@ -0,0 +1,44 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class WorkData extends JsonObject { + private WorkData(JsonValue value) { + super(value); + } + + public static WorkData fromJson(JsonValue value) { + return new WorkData(value); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder type(String value) { + return put("type", value); + } + + public Builder id(String value) { + return put("id", value); + } + + public WorkData build() { + + return new WorkData(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeat.java b/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeat.java new file mode 100644 index 0000000..1175108 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeat.java @@ -0,0 +1,35 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class WorkHeartbeat extends JsonModel { + public WorkHeartbeat(JsonValue value, String requestId) { + super(value, requestId); + } + + public static WorkHeartbeat fromJson(JsonValue value) { + return new WorkHeartbeat(value, null); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String lastHeartbeat() { + return optional("last_heartbeat", JsonValue::asString); + } + + public Boolean leaseExtended() { + return optional("lease_extended", JsonValue::asBoolean); + } + + public String state() { + return optional("state", JsonValue::asString); + } + + public Long ttlSeconds() { + return optional("ttl_seconds", JsonValue::asLong); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeatParams.java b/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeatParams.java new file mode 100644 index 0000000..9926ef2 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkHeartbeatParams.java @@ -0,0 +1,45 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class WorkHeartbeatParams { + private final Map query; + + private WorkHeartbeatParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder expectedLastHeartbeat(String value) { + return put("expected_last_heartbeat", value); + } + + public Builder desiredTtlSeconds(long value) { + if (value <= 0) throw new ConfigurationException("Value must be positive"); + return put("desired_ttl_seconds", String.valueOf(value)); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public WorkHeartbeatParams build() { + return new WorkHeartbeatParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkItem.java b/src/main/java/com/qoder/cloudagents/managed/WorkItem.java new file mode 100644 index 0000000..a18e97d --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkItem.java @@ -0,0 +1,63 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class WorkItem extends JsonModel { + public WorkItem(JsonValue value, String requestId) { + super(value, requestId); + } + + public static WorkItem fromJson(JsonValue value) { + return new WorkItem(value, null); + } + + public String id() { + return optional("id", JsonValue::asString); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public String environmentId() { + return optional("environment_id", JsonValue::asString); + } + + public String state() { + return optional("state", JsonValue::asString); + } + + public String createdAt() { + return optional("created_at", JsonValue::asString); + } + + public String acknowledgedAt() { + return optional("acknowledged_at", JsonValue::asString); + } + + public String startedAt() { + return optional("started_at", JsonValue::asString); + } + + public String latestHeartbeatAt() { + return optional("latest_heartbeat_at", JsonValue::asString); + } + + public String stopRequestedAt() { + return optional("stop_requested_at", JsonValue::asString); + } + + public String stoppedAt() { + return optional("stopped_at", JsonValue::asString); + } + + public WorkData data() { + return optional("data", WorkData::fromJson); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkListParams.java b/src/main/java/com/qoder/cloudagents/managed/WorkListParams.java new file mode 100644 index 0000000..b5c533a --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkListParams.java @@ -0,0 +1,59 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class WorkListParams { + private final Map query; + + private WorkListParams(Builder b) { + int cursors = 0; + for (String key : Arrays.asList("page", "after_id", "before_id")) + if (b.values.containsKey(key)) cursors++; + if (cursors > 1) + throw new ConfigurationException("page, afterId and beforeId are mutually exclusive"); + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder limit(long value) { + if (value < 1 || value > 100) + throw new ConfigurationException("limit must be between 1 and 100"); + return put("limit", String.valueOf(value)); + } + + public Builder page(String value) { + return put("page", value); + } + + public Builder beforeId(String value) { + return put("before_id", value); + } + + public Builder afterId(String value) { + return put("after_id", value); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public WorkListParams build() { + return new WorkListParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkListResponse.java b/src/main/java/com/qoder/cloudagents/managed/WorkListResponse.java new file mode 100644 index 0000000..4e9e977 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkListResponse.java @@ -0,0 +1,27 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +/** Cursor page with lazy iteration and cancellable next-page requests. */ +public final class WorkListResponse extends CursorPage { + public WorkListResponse(JsonValue value, String requestId) { + this(value, requestId, Collections.emptyMap(), Collections.emptySet(), null); + } + + WorkListResponse( + JsonValue value, + String requestId, + Map query, + Set seen, + BiFunction, Set, CompletableFuture> fetcher) { + super(value, requestId, query, seen, fetcher, item -> new WorkItem(item, requestId), true); + } + + @Override + protected WorkListResponse self() { + return this; + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkPollParams.java b/src/main/java/com/qoder/cloudagents/managed/WorkPollParams.java new file mode 100644 index 0000000..6cae106 --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkPollParams.java @@ -0,0 +1,47 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.ConfigurationException; +import java.util.*; + +/** Immutable query parameters for the Managed API. */ +public final class WorkPollParams { + private final Map query; + + private WorkPollParams(Builder b) { + query = Collections.unmodifiableMap(new LinkedHashMap<>(b.values)); + } + + Map query() { + return query; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map values = new LinkedHashMap<>(); + + public Builder blockMs(long value) { + if (value < 1 || value > 999) + throw new ConfigurationException("blockMs must be between 1 and 999"); + return put("block_ms", String.valueOf(value)); + } + + public Builder reclaimOlderThanMs(long value) { + if (value < 0) throw new ConfigurationException("Value must not be negative"); + return put("reclaim_older_than_ms", String.valueOf(value)); + } + + private Builder put(String key, String value) { + if (value == null) throw new ConfigurationException("Query parameters cannot be null"); + values.put(key, value); + return this; + } + + public WorkPollParams build() { + return new WorkPollParams(this); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkQueueStats.java b/src/main/java/com/qoder/cloudagents/managed/WorkQueueStats.java new file mode 100644 index 0000000..b70c39f --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkQueueStats.java @@ -0,0 +1,35 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable API response; unknown fields are preserved. */ +public final class WorkQueueStats extends JsonModel { + public WorkQueueStats(JsonValue value, String requestId) { + super(value, requestId); + } + + public static WorkQueueStats fromJson(JsonValue value) { + return new WorkQueueStats(value, null); + } + + public String type() { + return optional("type", JsonValue::asString); + } + + public Long depth() { + return optional("depth", JsonValue::asLong); + } + + public Long pending() { + return optional("pending", JsonValue::asLong); + } + + public String oldestQueuedAt() { + return optional("oldest_queued_at", JsonValue::asString); + } + + public Long workersPolling() { + return optional("workers_polling", JsonValue::asLong); + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkStopParams.java b/src/main/java/com/qoder/cloudagents/managed/WorkStopParams.java new file mode 100644 index 0000000..202d22a --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkStopParams.java @@ -0,0 +1,36 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class WorkStopParams extends JsonObject { + private WorkStopParams(JsonValue value) { + super(value); + } + + public static WorkStopParams fromJson(JsonValue value) { + return new WorkStopParams(value); + } + + public Boolean force() { + return optional("force", JsonValue::asBoolean); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder force(Boolean value) { + return put("force", value); + } + + public WorkStopParams build() { + + return new WorkStopParams(json()); + } + } +} diff --git a/src/main/java/com/qoder/cloudagents/managed/WorkUpdateParams.java b/src/main/java/com/qoder/cloudagents/managed/WorkUpdateParams.java new file mode 100644 index 0000000..50c28ed --- /dev/null +++ b/src/main/java/com/qoder/cloudagents/managed/WorkUpdateParams.java @@ -0,0 +1,36 @@ +package com.qoder.cloudagents.managed; + +import com.qoder.cloudagents.core.*; +import java.util.*; + +/** Immutable JSON configuration; unknown fields are preserved. */ +public final class WorkUpdateParams extends JsonObject { + private WorkUpdateParams(JsonValue value) { + super(value); + } + + public static WorkUpdateParams fromJson(JsonValue value) { + return new WorkUpdateParams(value); + } + + public Map metadata() { + return optionalNullableMap("metadata", JsonValue::asString); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends JsonObjectBuilder { + private Builder() {} + + public Builder metadata(Map value) { + return put("metadata", value); + } + + public WorkUpdateParams build() { + + return new WorkUpdateParams(json()); + } + } +} diff --git a/src/test/java/com/qoder/cloudagents/ManagedContractsTest.java b/src/test/java/com/qoder/cloudagents/ManagedContractsTest.java new file mode 100644 index 0000000..d203e4a --- /dev/null +++ b/src/test/java/com/qoder/cloudagents/ManagedContractsTest.java @@ -0,0 +1,621 @@ +package com.qoder.cloudagents; + +import static org.junit.jupiter.api.Assertions.*; + +import com.qoder.cloudagents.auth.AuthMode; +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.errors.*; +import com.qoder.cloudagents.managed.*; +import com.qoder.cloudagents.streaming.EventStream; +import java.io.*; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.*; +import okhttp3.mockwebserver.*; +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.*; + +@Timeout(15) +class ManagedContractsTest { + private MockWebServer server; + private ManagedClient client; + + @BeforeEach + void setup() throws Exception { + server = new MockWebServer(); + server.start(); + client = + ManagedClient.builder() + .baseUrl(server.url("/api/v1/cloud").toString()) + .pat("test-pat") + .maxRetries(0) + .build(); + } + + @AfterEach + void close() throws Exception { + client.close(); + server.close(); + } + + void respond(String body) { + server.enqueue(new MockResponse().setHeader("X-Request-ID", "req_contract").setBody(body)); + } + + RecordedRequest request() throws Exception { + RecordedRequest r = server.takeRequest(2, TimeUnit.SECONDS); + assertNotNull(r); + return r; + } + + JsonValue body() throws Exception { + return JsonValue.parse(request().getBody().readUtf8()); + } + + @ParameterizedTest + @ValueSource(strings = {"0.01", "100.00", "999999999999.99", "1"}) + void budgetUsesAnExactDecimalString(String cost) throws Exception { + respond("{\"id\":\"sess_test\"}"); + client + .sessions() + .create( + SessionCreateParams.builder() + .agent("agent_test") + .environmentId("env_test") + .budget(SessionBudget.builder().type("limit").maxCreditCost(cost).build()) + .build()); + JsonValue b = body().get("budget"); + assertEquals(cost, b.get("max_credit_cost").asString()); + assertTrue(b.get("max_list_cost").isMissing()); + } + + @ParameterizedTest + @ValueSource(strings = {"0", "0.00", "-1", "1.001", "1000000000000", "1e2", "NaN", "", ".5"}) + void invalidBudgetCannotBeSent(String cost) { + assertThrows( + ConfigurationException.class, + () -> SessionBudget.builder().type("limit").maxCreditCost(cost).build()); + assertEquals(0, server.getRequestCount()); + } + + @Test + void omissionNullAndMergePatchRemainDistinct() throws Exception { + Map patch = new LinkedHashMap<>(); + patch.put("remove", JsonValue.of(null)); + respond("{\"id\":\"sess_test\"}"); + client + .sessions() + .update( + "sess_test", + SessionUpdateParams.builder() + .budget(null) + .title(null) + .metadata(patch) + .environmentVariables(null) + .build()); + JsonValue b = body(); + assertTrue(b.get("budget").isNull()); + assertTrue(b.get("title").isNull()); + assertTrue(b.get("metadata").get("remove").isNull()); + assertTrue(b.get("environment_variables").isNull()); + assertTrue(SessionUpdateParams.builder().build().field("budget").isMissing()); + assertEquals(1, patch.size()); + DeploymentUpdateParams deployment = + DeploymentUpdateParams.builder() + .schedule(null) + .environmentVariables(null) + .metadata(Collections.singletonMap("remove", (String) null)) + .build(); + assertTrue(deployment.field("schedule").isNull()); + assertNull(deployment.metadata().get("remove")); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 3}) + void creationMarksOnlyReservedKeysWithoutMutatingCallerMetadata(int mode) throws Exception { + Map custom = new LinkedHashMap<>(); + custom.put("ticket", JsonValue.of("sdk-contract")); + custom.put("__qca_sdk_future", JsonValue.of("kept")); + custom.put("__qca_sdk_created", JsonValue.of("true")); + SessionCreateParams params = + SessionCreateParams.builder() + .agent("agent_test") + .environmentId("env_test") + .metadata(custom) + .build(); + respond("{\"id\":\"sess_test\"}"); + if (mode == 0) client.sessions().create(params); + else if (mode == 1) client.async().sessions().create(params).get(); + else if (mode == 2) client.sessions().withResponse().create(params); + else client.async().sessions().withResponse().create(params).get(); + RecordedRequest r = request(); + JsonValue m = JsonValue.parse(r.getBody().readUtf8()).get("metadata"); + assertEquals(5, m.asObject().size()); + assertEquals("java", m.get("__qca_sdk_language").asString()); + assertEquals(r.getHeader("X-Qoder-Package-Version"), m.get("__qca_sdk_version").asString()); + assertEquals("kept", m.get("__qca_sdk_future").asString()); + assertEquals(3, custom.size()); + assertEquals(3, params.metadata().size()); + } + + @ParameterizedTest + @ValueSource(strings = {"__qca_sdk_created", "__qca_sdk_language", "__qca_sdk_version"}) + void conflictingProvenanceFailsBeforeHttp(String key) { + SessionCreateParams params = + SessionCreateParams.builder() + .agent("agent_test") + .environmentId("env_test") + .metadata(Collections.singletonMap(key, JsonValue.of(false))) + .build(); + assertThrows(ConfigurationException.class, () -> client.sessions().create(params)); + assertThrows(ConfigurationException.class, () -> client.async().sessions().create(params)); + assertThrows( + ConfigurationException.class, () -> client.sessions().withResponse().create(params)); + assertThrows( + ConfigurationException.class, + () -> client.async().sessions().withResponse().create(params)); + assertEquals(0, server.getRequestCount()); + } + + @Test + void agentVersionsUseOpaqueCursorNotRepeatedAgentId() throws Exception { + respond( + "{\"data\":[{\"id\":\"agent_same\",\"version\":1}],\"last_id\":\"agent_same\",\"has_more\":true,\"next_page\":\"opaque-v1\"}"); + respond( + "{\"data\":[{\"id\":\"agent_same\",\"version\":2}],\"last_id\":\"agent_same\",\"has_more\":false,\"next_page\":null}"); + AgentVersionListResponse first = + client + .agents() + .versions() + .list("agent_same", AgentVersionListParams.builder().limit(1).build()); + assertTrue(first.hasNextPage()); + AgentVersionListResponse second = first.getNextPageAsync().get(); + assertEquals(Long.valueOf(2), second.data().get(0).version()); + assertFalse(second.hasNextPage()); + request(); + RecordedRequest next = request(); + assertEquals("opaque-v1", next.getRequestUrl().queryParameter("page")); + assertEquals("1", next.getRequestUrl().queryParameter("limit")); + assertNull(next.getRequestUrl().queryParameter("after_id")); + } + + @Test + void searchKeepsFiltersAndBetaAcrossPagesAndRejectsRepeatedCursor() throws Exception { + String page = + "{\"data\":[{\"id\":\"agent_a\"}],\"last_id\":\"agent_a\",\"has_more\":true,\"next_page\":\"opaque\"}"; + respond(page); + respond(page); + AgentListResponse first = + client + .agents() + .search( + AgentSearchParams.builder() + .name("qa") + .metadata(Collections.singletonMap("team", "sdk")) + .limit(1) + .build(), + RequestOptions.builder() + .header("x-qoder-beta", "other-beta") + .header("X-Test", "kept") + .build()); + AgentListResponse second = first.getNextPage(); + RecordedRequest a = request(), b = request(); + JsonValue body = JsonValue.parse(b.getBody().readUtf8()); + assertEquals("opaque", body.get("page").asString()); + assertEquals("qa", body.get("name").asString()); + assertEquals("sdk", body.get("metadata").get("team").asString()); + assertEquals(0, b.getRequestUrl().querySize()); + assertTrue(b.getHeader("x-qoder-beta").contains("other-beta")); + assertTrue(b.getHeader("x-qoder-beta").contains("search-2026-08-31")); + assertEquals("kept", b.getHeader("X-Test")); + assertThrows(PaginationException.class, second::getNextPage); + assertEquals(2, server.getRequestCount()); + } + + @Test + void managedFiltersUseStatusesAndTypesWithDateComparisons() throws Exception { + respond("{\"data\":[],\"has_more\":false}"); + client + .sessions() + .list( + SessionListParams.builder() + .statuses(Arrays.asList("idle", "running")) + .agentVersion(2) + .createdAtGt("2026-10-01T00:00:00Z") + .build()); + RecordedRequest sessions = request(); + assertEquals("idle,running", sessions.getRequestUrl().queryParameter("statuses")); + assertEquals("2", sessions.getRequestUrl().queryParameter("agent_version")); + respond("{\"data\":[],\"has_more\":false}"); + client + .sessions() + .events() + .list( + "sess_test", + SessionEventListParams.builder() + .types(Arrays.asList("user.message", "session.usage")) + .createdAtLte("2026-10-28T00:00:00Z") + .order("desc") + .build()); + RecordedRequest events = request(); + assertEquals("user.message,session.usage", events.getRequestUrl().queryParameter("types")); + assertNull(events.getRequestUrl().queryParameter("type")); + assertNotNull(events.getRequestUrl().queryParameter("created_at[lte]")); + } + + @Test + void sessionRuntimePatchUsesFieldsAndExplicitBeta() throws Exception { + SessionAgentPatch patch = + SessionAgentPatch.builder() + .model( + ModelConfig.builder().id("ultimate").effort("low").contextWindow(200000L).build()) + .system("new prompt") + .skills(Collections.emptyList()) + .build(); + respond( + "{\"id\":\"sess_test\",\"agent\":{\"version\":2,\"model\":{\"id\":\"ultimate\",\"effective_context_window\":200000}}}"); + Session s = + client + .sessions() + .update( + "sess_test", + SessionUpdateParams.builder().agent(patch).build(), + RequestOptions.builder() + .header("x-qoder-beta", "session-agent-patch-2026-07-21") + .build()); + RecordedRequest r = request(); + assertEquals("session-agent-patch-2026-07-21", r.getHeader("x-qoder-beta")); + JsonValue b = JsonValue.parse(r.getBody().readUtf8()).get("agent"); + assertTrue(b.get("id").isMissing()); + assertTrue(b.get("version").isMissing()); + assertEquals(Long.valueOf(200000), s.agent().model().effectiveContextWindow()); + assertEquals(Long.valueOf(2), s.agent().version()); + assertThrows( + ConfigurationException.class, + () -> + SessionAgentPatch.builder().additionalField("id", JsonValue.of("agent_wrong")).build()); + } + + @Test + void agentReferencesMultiagentAndVersionConcurrencyAreTyped() { + assertEquals("\"agent_a\"", AgentReference.of("agent_a").toJsonValue().toJson()); + assertEquals( + Long.valueOf(0), + AgentReference.builder().type("agent").id("agent_a").version(0).build().version()); + assertThrows( + ConfigurationException.class, () -> AgentReference.builder().id("agent_a").build()); + assertThrows( + ConfigurationException.class, () -> AgentUpdateParams.builder().name("changed").build()); + MultiagentConfig roster = + MultiagentConfig.builder() + .type("coordinator") + .agents( + Arrays.asList( + MultiagentEntry.of("agent_a"), + MultiagentEntry.builder().type("agent").id("agent_b").version("latest").build(), + MultiagentEntry.builder().type("self").build(), + MultiagentEntry.builder().type("advisor").model("ultimate").build())) + .build(); + assertTrue(roster.agents().get(0).isString()); + assertEquals("latest", roster.agents().get(1).version().asString()); + assertEquals("ultimate", roster.agents().get(3).model().id()); + assertThrows( + ConfigurationException.class, + () -> + ModelConfig.builder() + .id("ultimate") + .additionalField("speed", JsonValue.of("fast")) + .build()); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 3}) + void bothSseRoutesDecodeCreditsAndResumeHeaders(int mode) throws Exception { + boolean thread = mode >= 2, async = mode % 2 == 1; + server.enqueue( + new MockResponse() + .setHeader("Content-Type", "text/event-stream") + .setHeader("X-Request-ID", "req_sse") + .setBody( + "id: evt_usage\n" + + "data:" + + " {\"id\":\"evt_usage\",\"type\":\"session.usage\",\"model_credits\":0.123456789,\"sandbox_runtime_credits\":0.01,\"total_credits\":0.133456789}\n\n" + + "id: evt_end\n" + + "data: {\"id\":\"evt_end\",\"type\":\"session.status_terminated\"}\n\n")); + RequestOptions options = + RequestOptions.builder().header("Last-Event-ID", "evt_override").build(); + SessionEventStreamParams params = + SessionEventStreamParams.builder() + .lastEventId("evt_old") + .eventDeltas(Arrays.asList("agent.message", "agent.thinking")) + .build(); + SessionThreadEventStreamParams tp = + SessionThreadEventStreamParams.builder().lastEventId("evt_old").build(); + EventStream stream = + thread + ? (async + ? client + .async() + .sessions() + .threads() + .events() + .streamEvents("sess_test", "sth_test", tp, options) + .get() + : client + .sessions() + .threads() + .events() + .streamEvents("sess_test", "sth_test", tp, options)) + : (async + ? client + .async() + .sessions() + .events() + .streamEvents("sess_test", params, options) + .get() + : client.sessions().events().streamEvents("sess_test", params, options)); + try (EventStream owned = stream) { + Iterator events = owned.iterator(); + SessionEvent usage = events.next(); + assertEquals(new BigDecimal("0.123456789"), usage.modelCredits()); + assertEquals(new BigDecimal("0.133456789"), usage.totalCredits()); + assertEquals("session.status_terminated", events.next().type()); + assertFalse(events.hasNext()); + assertEquals("req_sse", owned.response().requestId()); + assertEquals("evt_end", owned.lastEventId()); + } + RecordedRequest r = request(); + assertEquals("evt_override", r.getHeader("Last-Event-ID")); + assertEquals( + thread + ? "/api/v1/cloud/sessions/sess_test/threads/sth_test/stream" + : "/api/v1/cloud/sessions/sess_test/events/stream", + r.getRequestUrl().encodedPath()); + assertEquals(thread ? 0 : 2, r.getRequestUrl().querySize()); + } + + @Test + void usageNestedCreditsAndUnknownFieldsArePreserved() { + Session s = + Session.fromJson( + JsonValue.parse( + "{\"usage\":{\"model_credits\":1.25,\"sandbox_runtime_credits\":0.5,\"total_credits\":1.75},\"future\":{\"enabled\":true}}")); + assertEquals(new BigDecimal("1.75"), s.usage().totalCredits()); + assertTrue(s.field("future").get("enabled").asBoolean()); + SessionEvent e = + new SessionEvent( + JsonValue.parse( + "{\"model_usage\":{\"credits\":0.0000123},\"usage\":{\"credits\":0.00123}}"), + null); + assertEquals(new BigDecimal("0.0000123"), e.modelUsageCredits()); + assertEquals(new BigDecimal("0.00123"), e.usageCredits()); + } + + @Test + void selfHostedPollMayReturnNullAndHeartbeatUsesQueryAndWorkerHeader() throws Exception { + respond("null"); + assertNull( + client + .environments() + .work() + .poll( + "env_test", + WorkPollParams.builder().blockMs(5).reclaimOlderThanMs(1000).build(), + RequestOptions.builder().header("Worker-ID", "worker_test").build())); + RecordedRequest poll = request(); + assertEquals("worker_test", poll.getHeader("Worker-ID")); + assertEquals("5", poll.getRequestUrl().queryParameter("block_ms")); + respond("{\"type\":\"work_heartbeat\",\"lease_extended\":true,\"ttl_seconds\":30}"); + WorkHeartbeat h = + client + .environments() + .work() + .heartbeat( + "env_test", + "work_test", + WorkHeartbeatParams.builder() + .expectedLastHeartbeat("NO_HEARTBEAT") + .desiredTtlSeconds(30) + .build()); + RecordedRequest r = request(); + assertEquals("", r.getBody().readUtf8()); + assertEquals("NO_HEARTBEAT", r.getRequestUrl().queryParameter("expected_last_heartbeat")); + assertTrue(h.leaseExtended()); + assertEquals(Long.valueOf(30), h.ttlSeconds()); + } + + @Test + void retryCannotReplayWorkerClaimsOrCredentialRotation() throws Exception { + try (ManagedClient retry = client.withOptions(b -> b.maxRetries(2))) { + server.enqueue( + new MockResponse() + .setResponseCode(500) + .setBody("{\"error\":{\"type\":\"api_error\",\"message\":\"failed\"}}")); + assertThrows(ApiStatusException.class, () -> retry.environments().work().poll("env_test")); + request(); + assertEquals(1, server.getRequestCount()); + } + } + + @Test + void oauthSecretStaysInBodyAndResponseProvidesCallbackOrigin() throws Exception { + respond( + "{\"authorization_url\":\"https://provider.example.com/authorize\",\"state\":\"test-state\",\"callback_origin\":\"https://api.qoder.com\"}"); + OAuthStartResponse result = + client + .oauth() + .start( + OAuthStartParams.builder() + .vaultId("vault_test") + .mcpServerUrl("https://mcp.example.com") + .clientId("test-client") + .clientSecret("test-secret") + .build()); + RecordedRequest r = request(); + assertEquals(0, r.getRequestUrl().querySize()); + assertEquals( + "test-secret", JsonValue.parse(r.getBody().readUtf8()).get("client_secret").asString()); + assertEquals("https://api.qoder.com", result.callbackOrigin()); + assertFalse(result.toString().contains("test-state")); + } + + @Test + void environmentStorageGitCredentialsAndResourceUpdatesHaveCorrectShapes() { + EnvironmentStorageBucket bucket = + EnvironmentStorageBucket.builder() + .name("docs") + .provider("aliyun-oss") + .region("cn-hangzhou") + .bucket("test-bucket") + .access("read_only") + .credential( + EnvironmentStorageCredential.builder() + .type("ram_role") + .roleArn("acs:ram::test:role/qa") + .build()) + .build(); + EnvironmentConfig env = + EnvironmentConfig.builder() + .type("cloud") + .storage( + EnvironmentStorage.builder().buckets(Collections.singletonList(bucket)).build()) + .build(); + assertEquals( + "ram_role", + env.field("storage") + .get("buckets") + .asArray() + .get(0) + .get("credential") + .get("type") + .asString()); + SessionResourceSpec git = + SessionResourceSpec.builder() + .type("git_repository") + .url("https://user@git.example.com/repo.git") + .password("test-secret") + .checkout(RepositoryCheckout.builder().type("branch").name("main").build()) + .build(); + assertEquals("test-secret", git.password()); + assertFalse(git.toString().contains("test-secret")); + assertThrows( + ConfigurationException.class, + () -> + SessionResourceCreateParams.builder() + .type("git_repository") + .fileId("file_test") + .build()); + } + + @Test + void nonPaginatedModelsAndDreamsDoNotRequireCursorFields() throws Exception { + respond( + "{\"data\":[{\"id\":\"ultimate\",\"source\":\"qoder\",\"available_context_windows\":[200000]}]}"); + Model m = client.models().list().data().get(0); + assertNull(m.priceFactor()); + assertEquals(Long.valueOf(200000), m.availableContextWindows().get(0)); + request(); + respond("{\"data\":[{\"id\":\"drm_test\",\"session_id\":\"sess_dream\"}]}"); + assertEquals("sess_dream", client.dreams().list().data().get(0).sessionId()); + request(); + } + + @Test + void fileScopeAndMemoryStoreCountersDecodeWithoutStringCoercion() { + FileMetadata f = + FileMetadata.fromJson( + JsonValue.parse( + "{\"scope\":{\"id\":\"sess_test\",\"type\":\"session\"},\"metadata\":{\"number\":1}}")); + assertEquals("sess_test", f.scope().id()); + assertEquals(1L, f.metadata().get("number").asLong()); + MemoryStore m = + MemoryStore.fromJson( + JsonValue.parse("{\"entry_count\":2,\"total_size\":123,\"status\":\"active\"}")); + assertEquals(Long.valueOf(2), m.entryCount()); + assertEquals(Long.valueOf(123), m.totalSize()); + assertEquals("active", m.status()); + } + + @Test + void asyncCancellationAndDerivedClientsKeepOwnership() throws Exception { + server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.NO_RESPONSE)); + CompletableFuture pending = client.async().models().list(); + request(); + assertTrue(pending.cancel(true)); + assertTrue(pending.isCancelled()); + client.async().close(); + respond("{\"data\":[]}"); + assertNotNull(client.models().list()); + request(); + try (ManagedClient derived = client.withOptions(b -> b.pat("other-pat"))) { + respond("{\"data\":[]}"); + derived.models().list(); + assertEquals("Bearer other-pat", request().getHeader("Authorization")); + } + respond("{\"data\":[]}"); + client.models().list(); + assertEquals("Bearer test-pat", request().getHeader("Authorization")); + } + + @Test + void staticSatAuthenticationAndTypedErrorContextAreRetained() throws Exception { + try (AsyncManagedClient sat = + ManagedClient.builder() + .baseUrl(server.url("/api/v1/cloud").toString()) + .authMode(AuthMode.SA) + .accessToken("test-sat") + .maxRetries(0) + .buildAsync()) { + server.enqueue( + new MockResponse() + .setResponseCode(409) + .setHeader("X-Request-ID", "req_conflict") + .setBody( + "{\"error\":{\"type\":\"conflict_error\",\"message\":\"version changed\"}}")); + ExecutionException ex = + assertThrows( + ExecutionException.class, + () -> + sat.agents() + .update( + "agent_test", AgentUpdateParams.builder().version(1).name("new").build()) + .get()); + assertTrue(ex.getCause() instanceof ApiStatusException); + assertEquals("Bearer test-sat", request().getHeader("Authorization")); + } + } + + @ParameterizedTest + @ValueSource(longs = {0, -1, 1000, 5000}) + void invalidLongPollingWindowIsRejected(long value) { + assertThrows( + ConfigurationException.class, () -> WorkPollParams.builder().blockMs(value).build()); + } + + @Test + void storageDownloadDoesNotForwardApiAuthenticationOrInterceptors() throws Exception { + try (MockWebServer storage = new MockWebServer()) { + storage.start(); + respond("{\"url\":\"" + storage.url("/file?signature=test") + "\"}"); + storage.enqueue(new MockResponse().setBody("contents")); + try (ManagedClient custom = + client.withOptions( + b -> + b.defaultHeader("X-Private", "private") + .interceptor( + (r, chain) -> chain.proceed(r.withHeader("X-Intercepted", "api")))); + FileDownload download = custom.files().download("file_test")) { + assertEquals('c', download.body().read()); + } + RecordedRequest api = request(); + assertEquals("Bearer test-pat", api.getHeader("Authorization")); + assertEquals("api", api.getHeader("X-Intercepted")); + RecordedRequest unsigned = storage.takeRequest(2, TimeUnit.SECONDS); + assertNotNull(unsigned); + assertNull(unsigned.getHeader("Authorization")); + assertNull(unsigned.getHeader("X-Private")); + assertNull(unsigned.getHeader("X-Intercepted")); + } + } +} diff --git a/src/test/java/com/qoder/cloudagents/ManagedDocumentationTest.java b/src/test/java/com/qoder/cloudagents/ManagedDocumentationTest.java new file mode 100644 index 0000000..e42b8b7 --- /dev/null +++ b/src/test/java/com/qoder/cloudagents/ManagedDocumentationTest.java @@ -0,0 +1,79 @@ +package com.qoder.cloudagents; + +import static org.junit.jupiter.api.Assertions.*; + +import com.qoder.cloudagents.core.*; +import java.io.*; +import java.lang.reflect.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.*; + +class ManagedDocumentationTest { + static Stream responses() throws Exception { + try (BufferedReader reader = + new BufferedReader( + new InputStreamReader( + ManagedDocumentationTest.class.getResourceAsStream( + "/managed-documentation-responses.json"), + StandardCharsets.UTF_8))) { + return JsonValue.parse(reader.lines().collect(Collectors.joining("\n"))).asArray().stream() + .map(f -> Arguments.of(f.get("source").asString(), f)); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("responses") + void officialResponseExamplesDecodeThroughTypedAccessors(String source, JsonValue fixture) + throws Exception { + Class type = + Class.forName("com.qoder.cloudagents.managed." + fixture.get("model").asString()); + JsonValue original = fixture.get("value"); + Object model = + type.getConstructor(JsonValue.class, String.class).newInstance(original, "req_docs"); + assertEquals(original.toJson(), ((JsonSerializable) model).toJsonValue().toJson()); + walk(model, 0); + } + + private void walk(Object value, int depth) throws Exception { + if (value == null || depth > 5) return; + if (value instanceof CursorPage) { + for (Object item : ((CursorPage) value).data()) walk(item, depth + 1); + return; + } + if (value instanceof com.qoder.cloudagents.managed.EventContent) { + com.qoder.cloudagents.managed.EventContent content = + (com.qoder.cloudagents.managed.EventContent) value; + if (content.isString()) assertNotNull(content.asString()); + else walk(content.asBlocks(), depth + 1); + return; + } + if (value instanceof Iterable && !(value instanceof CursorPage)) { + for (Object item : (Iterable) value) walk(item, depth + 1); + return; + } + if (value instanceof Map) { + for (Object item : ((Map) value).values()) walk(item, depth + 1); + return; + } + if (!value.getClass().getName().startsWith("com.qoder.cloudagents.managed.")) return; + for (Method method : value.getClass().getDeclaredMethods()) { + if (!Modifier.isPublic(method.getModifiers()) + || Modifier.isStatic(method.getModifiers()) + || method.getParameterCount() != 0 + || method.getName().equals("toJsonValue")) continue; + try { + walk(method.invoke(value), depth + 1); + } catch (InvocationTargetException e) { + throw new AssertionError( + value.getClass().getSimpleName() + + "." + + method.getName() + + " cannot decode official response", + e.getCause()); + } + } + } +} diff --git a/src/test/java/com/qoder/cloudagents/ManagedRoutesTest.java b/src/test/java/com/qoder/cloudagents/ManagedRoutesTest.java new file mode 100644 index 0000000..7f4e8dd --- /dev/null +++ b/src/test/java/com/qoder/cloudagents/ManagedRoutesTest.java @@ -0,0 +1,171 @@ +package com.qoder.cloudagents; + +import static org.junit.jupiter.api.Assertions.*; + +import com.qoder.cloudagents.core.*; +import com.qoder.cloudagents.managed.*; +import java.io.*; +import java.lang.reflect.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.*; +import okhttp3.mockwebserver.*; +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.*; + +@Timeout(15) +class ManagedRoutesTest { + private MockWebServer server; + private ManagedClient client; + + @BeforeEach + void setup() throws Exception { + server = new MockWebServer(); + server.start(); + client = + ManagedClient.builder() + .baseUrl(server.url("/api/v1/cloud").toString()) + .pat("test-pat") + .maxRetries(0) + .build(); + } + + @AfterEach + void close() throws Exception { + client.close(); + server.close(); + } + + static Stream routes() throws Exception { + try (BufferedReader r = + new BufferedReader( + new InputStreamReader( + ManagedRoutesTest.class.getResourceAsStream("/managed-routes.json"), + StandardCharsets.UTF_8))) { + return JsonValue.parse(r.lines().collect(Collectors.joining("\n"))).asArray().stream() + .flatMap( + f -> + IntStream.range(0, 4) + .mapToObj( + mode -> + Arguments.of( + f.get("resource").asString() + + "." + + f.get("operation").asString(), + mode, + f))); + } + } + + @ParameterizedTest(name = "{0}, mode={1}") + @MethodSource("routes") + void officialEndpointsUseTheirDocumentedMethodAndParameterLocation( + String name, int mode, JsonValue f) throws Exception { + boolean download = "download".equals(f.get("operation").asString()); + server.enqueue( + new MockResponse() + .setHeader("X-Request-ID", "req_managed") + .setBody(download ? "zip-content" : f.get("response").toJson())); + Object service = (mode % 2 == 1) ? client.async() : client; + for (String step : f.get("resource").asString().split("\\.")) + service = service.getClass().getMethod(step).invoke(service); + if (mode >= 2) service = service.getClass().getMethod("withResponse").invoke(service); + List> types = new ArrayList<>(); + List args = new ArrayList<>(); + for (JsonValue id : f.get("ids").asArray()) { + types.add(String.class); + args.add(id.asString()); + } + if (!f.get("param").isNull()) { + Class type = Class.forName("com.qoder.cloudagents.managed." + f.get("param").asString()); + types.add(type); + if ("query".equals(f.get("mode").asString())) { + Object builder = type.getMethod("builder").invoke(null); + for (Map.Entry e : f.get("query").asObject().entrySet()) { + String t = f.get("query_types").get(e.getKey()).asString(); + Class jt = + "long".equals(t) ? long.class : "boolean".equals(t) ? boolean.class : String.class; + Object v = + "long".equals(t) + ? e.getValue().asLong() + : "boolean".equals(t) ? e.getValue().asBoolean() : e.getValue().asString(); + builder.getClass().getMethod(camel(e.getKey()), jt).invoke(builder, v); + } + args.add(builder.getClass().getMethod("build").invoke(builder)); + } else if ("multipart".equals(f.get("mode").asString())) { + Upload upload = + Upload.bytes("hello".getBytes(StandardCharsets.UTF_8), "qa/SKILL.md", "text/plain"); + if (type == FileUploadParams.class) + args.add(FileUploadParams.builder().file(upload).name("qa.txt").build()); + else if (type == SkillCreateParams.class) + args.add( + SkillCreateParams.builder() + .files(Collections.singletonList(upload)) + .displayTitle("QA") + .build()); + else + args.add( + SkillVersionCreateParams.builder().files(Collections.singletonList(upload)).build()); + } else args.add(type.getMethod("fromJson", JsonValue.class).invoke(null, f.get("body"))); + } + Object result = + service + .getClass() + .getMethod(f.get("operation").asString(), types.toArray(new Class[0])) + .invoke(service, args.toArray()); + if (result instanceof CompletableFuture) + result = ((CompletableFuture) result).get(3, TimeUnit.SECONDS); + if (result instanceof ApiResponse) { + assertEquals("req_managed", ((ApiResponse) result).requestId()); + result = ((ApiResponse) result).data(); + } + if (result instanceof FileDownload) { + try (FileDownload file = (FileDownload) result) { + assertEquals('z', file.body().read()); + } + } + RecordedRequest r = server.takeRequest(2, TimeUnit.SECONDS); + assertNotNull(r); + assertEquals(f.get("method").asString(), r.getMethod()); + assertEquals(f.get("path").asString(), r.getRequestUrl().encodedPath()); + assertEquals("Bearer test-pat", r.getHeader("Authorization")); + assertEquals("java", r.getHeader("X-Qoder-Lang")); + assertEquals(f.get("query").asObject().size(), r.getRequestUrl().querySize()); + for (Map.Entry e : f.get("query").asObject().entrySet()) + assertEquals( + e.getValue().isString() ? e.getValue().asString() : e.getValue().toJson(), + r.getRequestUrl().queryParameter(e.getKey())); + if ("search".equals(f.get("mode").asString())) + assertEquals("search-2026-08-31", r.getHeader("x-qoder-beta")); + String body = r.getBody().readUtf8(); + if ("multipart".equals(f.get("mode").asString())) { + assertTrue(r.getHeader("Content-Type").startsWith("multipart/form-data")); + assertTrue(body.contains("hello")); + assertTrue(body.contains("qa/SKILL.md")); + } else if (f.get("body").isNull()) assertEquals("", body); + else { + JsonValue expected = f.get("body"), actual = JsonValue.parse(body); + if ("sessions.create".equals(name)) { + Map metadata = new LinkedHashMap<>(expected.get("metadata").asObject()); + metadata.put("__qca_sdk_created", JsonValue.of("true")); + metadata.put("__qca_sdk_language", JsonValue.of("java")); + metadata.put("__qca_sdk_version", JsonValue.of(r.getHeader("X-Qoder-Package-Version"))); + Map copy = new LinkedHashMap<>(expected.asObject()); + copy.put("metadata", JsonValue.of(metadata)); + expected = JsonValue.of(copy); + } + assertEquals(expected.toJson(), actual.toJson()); + } + } + + static String camel(String s) { + String[] p = s.split("[^a-zA-Z0-9]+"); + StringBuilder r = new StringBuilder(p[0]); + for (int i = 1; i < p.length; i++) + if (!p[i].isEmpty()) + r.append(Character.toUpperCase(p[i].charAt(0))).append(p[i].substring(1)); + return r.toString(); + } +} diff --git a/src/test/resources/managed-documentation-responses.json b/src/test/resources/managed-documentation-responses.json new file mode 100644 index 0000000..8578558 --- /dev/null +++ b/src/test/resources/managed-documentation-responses.json @@ -0,0 +1,2318 @@ +[ + { + "source": "api__agents__archive.md", + "model": "Agent", + "value": { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent-updated", + "description": "Used for API documentation testing", + "model": "ultimate", + "system": "You are an updated documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 2, + "archived_at": "2026-05-18T15:27:22.698411Z", + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:27:22.698411Z" + } + }, + { + "source": "api__agents__create.md", + "model": "Agent", + "value": { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent", + "description": "", + "model": "ultimate", + "system": "You are a documentation testing assistant.", + "tools": [ + { + "type": "agent_toolset_20260401", + "enabled_tools": [ + "Bash", + "Read", + "Write", + "Edit", + "Glob", + "Grep", + "WebFetch", + "WebSearch" + ] + } + ], + "mcp_servers": [ + { + "type": "url", + "name": "weather-service", + "url": "https://mcp.example.com/mcp" + } + ], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 1, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:26:39.61669Z" + } + }, + { + "source": "api__agents__get.md", + "model": "Agent", + "value": { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent", + "description": "", + "model": "ultimate", + "system": "You are a documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [ + { + "type": "custom", + "skill_id": "skill_019e5d133c057536872f745e0b6dbd5d" + } + ], + "metadata": {}, + "multiagent": null, + "version": 1, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:26:39.61669Z" + } + }, + { + "source": "api__agents__list-versions.md", + "model": "AgentVersionListResponse", + "value": { + "data": [ + { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent-updated", + "description": "Used for API documentation testing", + "model": "ultimate", + "system": "You are an updated documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 2, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:27:07.967138Z" + }, + { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent", + "description": "", + "model": "ultimate", + "system": "You are a documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 1, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:26:39.61669Z" + } + ], + "first_id": "2", + "last_id": "1", + "has_more": false, + "next_page": null + } + }, + { + "source": "api__agents__list.md", + "model": "AgentListResponse", + "value": { + "data": [ + { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent", + "description": "", + "model": "ultimate", + "system": "You are a documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 1, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:26:39.61669Z" + }, + { + "type": "agent", + "id": "agent_019eYYYYYYYYYYYYYYYYYYYYYYYYYYYY", + "name": "test-agent-e2e", + "description": "Agent used for end-to-end testing", + "model": "ultimate", + "system": "You are a testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 2, + "archived_at": null, + "created_at": "2026-05-18T03:04:33.952256Z", + "updated_at": "2026-05-18T03:05:28.023697Z" + } + ], + "first_id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "last_id": "agent_019eYYYYYYYYYYYYYYYYYYYYYYYYYYYY", + "has_more": true, + "next_page": "agent_019eYYYYYYYYYYYYYYYYYYYYYYYYYYYY" + } + }, + { + "source": "api__agents__update.md", + "model": "Agent", + "value": { + "type": "agent", + "id": "agent_019eXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "name": "doc-test-agent-updated", + "description": "Used for API documentation testing", + "model": "ultimate", + "system": "You are an updated documentation testing assistant.", + "tools": [], + "mcp_servers": [], + "skills": [], + "metadata": {}, + "multiagent": null, + "version": 2, + "archived_at": null, + "created_at": "2026-05-18T15:26:39.61669Z", + "updated_at": "2026-05-18T15:27:07.967138Z" + } + }, + { + "source": "api__deployments__archive.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "archived_at": "2026-06-14T08:58:42Z", + "created_at": "2026-06-14T08:58:01Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e49a1780171daac1e6b01f290ac2b", + "environment_variables": "", + "id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment-v2_archived_1781427523", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "30 9 * * 1-5", + "last_run_at": "2026-06-14T08:58:17Z", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:58:42Z", + "vault_ids": [] + } + }, + { + "source": "api__deployments__create.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:53:32Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "environment_variables": "FEATURE_FLAG=on\nLOG_LEVEL=info", + "id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": { + "team": "platform" + }, + "name": "api-doc-verification-deployment", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "0 9 * * *", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:00:00Z", + "2026-06-16T01:00:00Z", + "2026-06-17T01:00:00Z", + "2026-06-18T01:00:00Z", + "2026-06-19T01:00:00Z" + ] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:53:32Z", + "vault_ids": [] + } + }, + { + "source": "api__deployments__get-run-global.md", + "model": "DeploymentRun", + "value": { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:58:17Z", + "deployment_id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "error": null, + "id": "drun_019ec55a68af73028afa5b87931cb2f3", + "session_id": "sess_019ec55a68b37e1e8d660691af161ab4", + "trigger_context": { + "type": "manual" + }, + "type": "deployment_run" + } + }, + { + "source": "api__deployments__get-run.md", + "model": "DeploymentRun", + "value": { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:58:17Z", + "deployment_id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "error": null, + "id": "drun_019ec55a68af73028afa5b87931cb2f3", + "session_id": "sess_019ec55a68b37e1e8d660691af161ab4", + "trigger_context": { + "type": "manual" + }, + "type": "deployment_run" + } + }, + { + "source": "api__deployments__get.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:53:32Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "environment_variables": "", + "id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "0 9 * * *", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:00:00Z", + "2026-06-16T01:00:00Z", + "2026-06-17T01:00:00Z", + "2026-06-18T01:00:00Z", + "2026-06-19T01:00:00Z" + ] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:53:32Z", + "vault_ids": [] + } + }, + { + "source": "api__deployments__list-all-runs.md", + "model": "DeploymentRunListResponse", + "value": { + "data": [ + { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:58:17Z", + "deployment_id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "error": null, + "id": "drun_019ec55a68af73028afa5b87931cb2f3", + "session_id": "sess_019ec55a68b37e1e8d660691af161ab4", + "trigger_context": { + "type": "manual" + }, + "type": "deployment_run" + }, + { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:58:04Z", + "deployment_id": "dep_019ec53748f7784bac33f208c0f66982", + "error": null, + "id": "drun_019ec55a371470969dd48ce41fb2a7da", + "session_id": "sess_019ec55a37157b049f3e7f3681b5ec15", + "trigger_context": { + "scheduled_at": "2026-06-14T08:58:04Z", + "type": "schedule" + }, + "type": "deployment_run" + } + ], + "first_id": "drun_019ec55a68af73028afa5b87931cb2f3", + "has_more": true, + "last_id": "drun_019ec55a371470969dd48ce41fb2a7da", + "next_page": "drun_019ec55a371470969dd48ce41fb2a7da" + } + }, + { + "source": "api__deployments__list-runs.md", + "model": "DeploymentScopedRunListResponse", + "value": { + "data": [ + { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:58:17Z", + "deployment_id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "error": null, + "id": "drun_019ec55a68af73028afa5b87931cb2f3", + "session_id": "sess_019ec55a68b37e1e8d660691af161ab4", + "trigger_context": { + "type": "manual" + }, + "type": "deployment_run" + } + ], + "first_id": "drun_019ec55a68af73028afa5b87931cb2f3", + "has_more": false, + "last_id": "drun_019ec55a68af73028afa5b87931cb2f3", + "next_page": null + } + }, + { + "source": "api__deployments__list.md", + "model": "DeploymentListResponse", + "value": { + "data": [ + { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:53:32Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "environment_variables": "", + "id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "0 9 * * *", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:00:00Z", + "2026-06-16T01:00:00Z", + "2026-06-17T01:00:00Z", + "2026-06-18T01:00:00Z", + "2026-06-19T01:00:00Z" + ] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:53:32Z", + "vault_ids": [] + } + ], + "first_id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "has_more": true, + "last_id": "dep_019ec51604b87aaea12568c9ab7b7025", + "next_page": "dep_019ec51604b87aaea12568c9ab7b7025" + } + }, + { + "source": "api__deployments__pause.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:53:32Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "environment_variables": "", + "id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment-v2", + "paused_reason": { + "type": "manual" + }, + "resources": [], + "schedule": { + "expression": "30 9 * * 1-5", + "last_run_at": "2026-06-14T08:54:06Z", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:30:00Z", + "2026-06-16T01:30:00Z", + "2026-06-17T01:30:00Z", + "2026-06-18T01:30:00Z", + "2026-06-19T01:30:00Z" + ] + }, + "status": "paused", + "type": "deployment", + "updated_at": "2026-06-14T08:54:22Z", + "vault_ids": [] + } + }, + { + "source": "api__deployments__run.md", + "model": "DeploymentRun", + "value": { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "created_at": "2026-06-14T08:54:06Z", + "deployment_id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "error": null, + "id": "drun_019ec55694c07f2a9b402ffb4448ec18", + "session_id": "sess_019ec55694c47605a8904c8f3d842ccb", + "trigger_context": { + "type": "manual" + }, + "type": "deployment_run" + } + }, + { + "source": "api__deployments__unpause.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019ebb21ef8e7df6a559052c94875160", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:58:01Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e49a1780171daac1e6b01f290ac2b", + "environment_variables": "", + "id": "dep_019ec55a2b687b3f94eee77dd77e4b2a", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment-v2", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "30 9 * * 1-5", + "last_run_at": "2026-06-14T08:58:17Z", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:30:00Z", + "2026-06-16T01:30:00Z", + "2026-06-17T01:30:00Z", + "2026-06-18T01:30:00Z", + "2026-06-19T01:30:00Z" + ] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:58:27Z", + "vault_ids": [] + } + }, + { + "source": "api__deployments__update.md", + "model": "Deployment", + "value": { + "agent": { + "id": "agent_019eb4d4a06d747c865d5800b9c57ae2", + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-14T08:53:32Z", + "description": "Deployment created for API documentation verification", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "environment_variables": "", + "id": "dep_019ec556114c78f8b60ee34fcb98bf59", + "initial_events": [ + { + "content": [ + { + "type": "text", + "text": "Generate today's status report" + } + ], + "type": "user.message" + } + ], + "metadata": {}, + "name": "api-doc-verification-deployment-v2", + "paused_reason": null, + "resources": [], + "schedule": { + "expression": "30 9 * * 1-5", + "timezone": "Asia/Shanghai", + "type": "cron", + "upcoming_runs_at": [ + "2026-06-15T01:30:00Z", + "2026-06-16T01:30:00Z", + "2026-06-17T01:30:00Z", + "2026-06-18T01:30:00Z", + "2026-06-19T01:30:00Z" + ] + }, + "status": "active", + "type": "deployment", + "updated_at": "2026-06-14T08:54:05Z", + "vault_ids": [] + } + }, + { + "source": "api__dreams__archive.md", + "model": "Dream", + "value": { + "id": "drm_019e86b4a8f070a3b6c5d4e3f2a1b0c9", + "type": "dream", + "status": "completed", + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4" + } + ], + "outputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e86b4b10578059435632bb357c5ed", + "files_touched": [ + "preferences.md" + ] + } + ], + "model": { + "id": "auto" + }, + "instructions": "", + "session_id": "sess_019e86b4b10578059435632bb357c5ed", + "usage": { + "input_tokens": 12500, + "output_tokens": 3200, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 8000 + }, + "error": null, + "created_at": "2026-06-15T10:00:00Z", + "ended_at": "2026-06-15T10:03:42Z", + "archived_at": "2026-06-15T12:00:00Z" + } + }, + { + "source": "api__dreams__cancel.md", + "model": "Dream", + "value": { + "id": "drm_019e86b4a8f070a3b6c5d4e3f2a1b0c9", + "type": "dream", + "status": "canceled", + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4" + } + ], + "outputs": [], + "model": { + "id": "auto" + }, + "instructions": "", + "session_id": "sess_019e86b4b10578059435632bb357c5ed", + "usage": { + "input_tokens": 0, + "output_tokens": 0, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0 + }, + "error": null, + "created_at": "2026-06-15T10:00:00Z", + "ended_at": "2026-06-15T10:01:15Z", + "archived_at": null + } + }, + { + "source": "api__dreams__create.md", + "model": "Dream", + "value": { + "id": "drm_019e86b4a8f070a3b6c5d4e3f2a1b0c9", + "type": "dream", + "status": "pending", + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4" + }, + { + "type": "sessions", + "session_ids": [ + "sess_019e7a1b2c3d4e5f6a7b8c9d0e1f2a3b" + ] + } + ], + "outputs": [], + "model": { + "id": "dfmodel", + "effort": "high", + "context_window": 400000 + }, + "instructions": "Focus on user preferences for code style", + "session_id": null, + "usage": { + "input_tokens": 0, + "output_tokens": 0, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0 + }, + "error": null, + "created_at": "2026-06-15T10:00:00Z", + "ended_at": null, + "archived_at": null + } + }, + { + "source": "api__dreams__get.md", + "model": "Dream", + "value": { + "id": "drm_019e86b4a8f070a3b6c5d4e3f2a1b0c9", + "type": "dream", + "status": "completed", + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4" + } + ], + "outputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e86b4b10578059435632bb357c5ed", + "files_touched": [ + "preferences.md", + "project/arch.md" + ] + } + ], + "model": { + "id": "auto" + }, + "instructions": "", + "session_id": "sess_019e86b4b10578059435632bb357c5ed", + "usage": { + "input_tokens": 12500, + "output_tokens": 3200, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 8000 + }, + "error": null, + "created_at": "2026-06-15T10:00:00Z", + "ended_at": "2026-06-15T10:03:42Z", + "archived_at": null + } + }, + { + "source": "api__dreams__list.md", + "model": "DreamListResponse", + "value": { + "data": [ + { + "id": "drm_019e86b4a8f070a3b6c5d4e3f2a1b0c9", + "type": "dream", + "status": "completed", + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4" + } + ], + "outputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_019e86b4b10578059435632bb357c5ed", + "files_touched": [ + "preferences.md" + ] + } + ], + "model": { + "id": "auto" + }, + "instructions": "", + "session_id": "sess_019e86b4b10578059435632bb357c5ed", + "usage": { + "input_tokens": 12500, + "output_tokens": 3200, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 8000 + }, + "error": null, + "created_at": "2026-06-15T10:00:00Z", + "ended_at": "2026-06-15T10:03:42Z", + "archived_at": null + } + ] + } + }, + { + "source": "api__environments__archive.md", + "model": "Environment", + "value": { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment", + "name": "doc-test-env", + "description": "Environment used for API documentation testing", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [ + "curl" + ], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": "2026-05-18T15:28:08.459536Z", + "created_at": "2026-05-18T15:28:07.017808Z", + "updated_at": "2026-05-18T15:28:08.459536Z" + } + }, + { + "source": "api__environments__create.md", + "model": "Environment", + "value": { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment", + "name": "doc-test-env", + "description": "", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [ + "curl" + ], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:28:07.017808Z", + "updated_at": "2026-05-18T15:28:07.017808Z" + } + }, + { + "source": "api__environments__delete.md", + "model": "DeletedEnvironment", + "value": { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment_deleted" + } + }, + { + "source": "api__environments__get.md", + "model": "Environment", + "value": { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment", + "name": "doc-test-env", + "description": "", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [ + "curl" + ], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:28:07.017808Z", + "updated_at": "2026-05-18T15:28:07.017808Z" + } + }, + { + "source": "api__environments__list.md", + "model": "EnvironmentListResponse", + "value": { + "data": [ + { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment", + "name": "doc-test-env", + "description": "", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [ + "curl" + ], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:28:07.017808Z", + "updated_at": "2026-05-18T15:28:07.017808Z" + }, + { + "id": "env_019e2590d33f711fabf42f2857cecd8a", + "type": "environment", + "name": "default", + "description": "", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-14T08:18:28.800813Z", + "updated_at": "2026-05-14T08:18:28.800813Z" + } + ], + "first_id": "env_019e3bb39b6774d8878cd0b9d237574b", + "has_more": false, + "last_id": "env_019e2590d33f711fabf42f2857cecd8a", + "next_page": null + } + }, + { + "source": "api__environments__update.md", + "model": "Environment", + "value": { + "id": "env_019e3bb39b6774d8878cd0b9d237574b", + "type": "environment", + "name": "doc-test-env", + "description": "Environment used for API documentation testing", + "config": { + "type": "cloud", + "packages": { + "type": "packages", + "apt": [ + "curl" + ], + "cargo": [], + "gem": [], + "go": [], + "npm": [], + "pip": [] + } + }, + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:28:07.017808Z", + "updated_at": "2026-05-18T15:28:08.093156Z" + } + }, + { + "source": "api__environments__work__ack.md", + "model": "WorkItem", + "value": { + "id": "work_019f3be4fd2475d9a784bf2c739e1194", + "type": "work", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "data": { + "type": "session", + "id": "sess_019f3be3fa66750bb9a1fbcde85b5fe1" + }, + "state": "starting", + "created_at": "2026-07-01T08:15:01Z", + "acknowledged_at": "2026-07-01T08:15:04Z", + "started_at": null, + "latest_heartbeat_at": null, + "stop_requested_at": null, + "stopped_at": null, + "metadata": {} + } + }, + { + "source": "api__environments__work__get.md", + "model": "WorkItem", + "value": { + "id": "work_019f3be4fd2475d9a784bf2c739e1194", + "type": "work", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "data": { + "type": "session", + "id": "sess_019f3be3fa66750bb9a1fbcde85b5fe1" + }, + "state": "active", + "created_at": "2026-07-01T08:15:01Z", + "acknowledged_at": "2026-07-01T08:15:04Z", + "started_at": "2026-07-01T08:15:06Z", + "latest_heartbeat_at": "2026-07-01T08:16:06.120394Z", + "stop_requested_at": null, + "stopped_at": null, + "metadata": { + "job": "daily-report" + } + } + }, + { + "source": "api__environments__work__heartbeat.md", + "model": "WorkHeartbeat", + "value": { + "type": "work_heartbeat", + "last_heartbeat": "2026-07-01T08:15:06.120394Z", + "lease_extended": true, + "state": "active", + "ttl_seconds": 60 + } + }, + { + "source": "api__environments__work__list.md", + "model": "WorkListResponse", + "value": { + "data": [ + { + "id": "work_019f3be4fd2475d9a784bf2c739e1194", + "type": "work", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "data": { + "type": "session", + "id": "sess_019f3be3fa66750bb9a1fbcde85b5fe1" + }, + "state": "queued", + "created_at": "2026-07-01T08:15:01Z", + "acknowledged_at": null, + "started_at": null, + "latest_heartbeat_at": null, + "stop_requested_at": null, + "stopped_at": null, + "metadata": { + "job": "daily-report" + } + } + ], + "first_id": "work_019f3be4fd2475d9a784bf2c739e1194", + "last_id": "work_019f3be4fd2475d9a784bf2c739e1194", + "has_more": false, + "next_page": null + } + }, + { + "source": "api__environments__work__stats.md", + "model": "WorkQueueStats", + "value": { + "type": "work_queue_stats", + "depth": 3, + "pending": 1, + "oldest_queued_at": "2026-07-01T08:15:01Z", + "workers_polling": 2 + } + }, + { + "source": "api__environments__work__stop.md", + "model": "WorkItem", + "value": { + "id": "work_019f3be4fd2475d9a784bf2c739e1194", + "type": "work", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "data": { + "type": "session", + "id": "sess_019f3be3fa66750bb9a1fbcde85b5fe1" + }, + "state": "stopping", + "created_at": "2026-07-01T08:15:01Z", + "acknowledged_at": "2026-07-01T08:15:04Z", + "started_at": "2026-07-01T08:15:06Z", + "latest_heartbeat_at": "2026-07-01T08:16:06.120394Z", + "stop_requested_at": "2026-07-01T08:16:30Z", + "stopped_at": null, + "metadata": {} + } + }, + { + "source": "api__environments__work__update-metadata.md", + "model": "WorkItem", + "value": { + "id": "work_019f3be4fd2475d9a784bf2c739e1194", + "type": "work", + "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c", + "data": { + "type": "session", + "id": "sess_019f3be3fa66750bb9a1fbcde85b5fe1" + }, + "state": "active", + "created_at": "2026-07-01T08:15:01Z", + "acknowledged_at": "2026-07-01T08:15:04Z", + "started_at": "2026-07-01T08:15:06Z", + "latest_heartbeat_at": "2026-07-01T08:16:06.120394Z", + "stop_requested_at": null, + "stopped_at": null, + "metadata": { + "job": "daily-report", + "worker": "byoc-worker-01" + } + } + }, + { + "source": "api__files__delete.md", + "model": "DeletedFile", + "value": { + "id": "file_019e3bb8c1387743bf4ef115aae5acb1", + "type": "file_deleted" + } + }, + { + "source": "api__files__download.md", + "model": "FileDownloadUrl", + "value": { + "expires_at": "2026-05-18T16:34:52Z", + "url": "https://storage.qoder.com/files/..." + } + }, + { + "source": "api__files__get.md", + "model": "FileMetadata", + "value": { + "id": "file_019e3bb8c1387743bf4ef115aae5acb1", + "type": "file", + "filename": "qoder-test-upload.txt", + "mime_type": "text/plain", + "size_bytes": 110, + "downloadable": true, + "scope": { + "id": "sess_019e3bb8e6c47d18", + "type": "session" + }, + "metadata": { + "project": "demo" + }, + "created_at": "2026-05-18T15:33:44Z" + } + }, + { + "source": "api__files__list.md", + "model": "FileListResponse", + "value": { + "data": [ + { + "id": "file_019e3bb8e6c47d189212a79642136696", + "type": "file", + "filename": "report.txt", + "mime_type": "text/plain", + "size_bytes": 110, + "downloadable": true, + "scope": { + "id": "sess_019e3bb8e6c47d18", + "type": "session" + }, + "metadata": { + "project": "demo" + }, + "created_at": "2026-05-18T15:33:53Z" + } + ], + "next_page": null, + "first_id": "file_019e3bb8e6c47d189212a79642136696", + "has_more": false, + "last_id": "file_019e3bb8e6c47d189212a79642136696" + } + }, + { + "source": "api__files__upload.md", + "model": "FileMetadata", + "value": { + "id": "file_019e3bb8c1387743bf4ef115aae5acb1", + "type": "file", + "filename": "my-document.txt", + "mime_type": "text/plain", + "size_bytes": 110, + "downloadable": false, + "scope": null, + "metadata": { + "project": "demo" + }, + "created_at": "2026-05-18T15:33:44Z" + } + }, + { + "source": "api__memory-stores__archive.md", + "model": "MemoryStore", + "value": { + "id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "created_at": "2026-05-18T15:33:49.449Z", + "name": "doc-test-store", + "type": "memory_store", + "updated_at": "2026-05-18T15:34:00.007Z", + "archived_at": "2026-05-18T15:34:00.007Z", + "description": "Test store", + "metadata": {}, + "status": "archived", + "entry_count": 0, + "total_size": 0 + } + }, + { + "source": "api__memory-stores__create.md", + "model": "MemoryStore", + "value": { + "id": "memstore_019e5cdb9c3f71c3b6505eba937a40b4", + "created_at": "2026-05-18T08:00:00.000Z", + "name": "project-alpha-memory", + "type": "memory_store", + "updated_at": "2026-05-18T08:00:00.000Z", + "archived_at": null, + "description": "Agent knowledge base for project Alpha", + "metadata": { + "team": "backend" + }, + "status": "active", + "entry_count": 0, + "total_size": 0 + } + }, + { + "source": "api__memory-stores__delete.md", + "model": "DeletedMemoryStore", + "value": { + "id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "type": "memory_store_deleted" + } + }, + { + "source": "api__memory-stores__get.md", + "model": "MemoryStore", + "value": { + "id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "created_at": "2026-05-18T15:33:49.449Z", + "name": "doc-test-store", + "type": "memory_store", + "updated_at": "2026-05-18T15:33:49.449Z", + "archived_at": null, + "description": "Test store", + "metadata": {}, + "status": "active", + "entry_count": 0, + "total_size": 0 + } + }, + { + "source": "api__memory-stores__list-versions.md", + "model": "MemoryVersionListResponse", + "value": { + "data": [ + { + "id": "memver_...", + "type": "memory_version", + "memory_store_id": "memstore_...", + "memory_id": "mem_...", + "path": "decisions/arch-choice.md", + "content_size_bytes": 46, + "content_sha256": "a1b2c3...", + "operation": "updated", + "redacted": false, + "created_at": "2026-05-18T09:30:00.000Z" + } + ], + "has_more": false, + "first_id": "memver_...", + "last_id": "memver_..." + } + }, + { + "source": "api__memory-stores__list.md", + "model": "MemoryStoreListResponse", + "value": { + "data": [ + { + "id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "created_at": "2026-05-18T15:33:49.449Z", + "name": "doc-test-store", + "type": "memory_store", + "updated_at": "2026-05-18T15:33:49.449Z", + "archived_at": null, + "description": "Test store", + "metadata": {}, + "status": "active", + "entry_count": 0, + "total_size": 0 + } + ], + "has_more": false, + "first_id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "last_id": "memstore_019e3bb8d50674d9b082b73709c29c87", + "next_page": null + } + }, + { + "source": "api__models__list.md", + "model": "ModelListResponse", + "value": { + "data": [ + { + "id": "ultimate", + "type": "model", + "display_name": "Ultimate", + "source": "system", + "is_enabled": true, + "is_new": false, + "price_factor": 1.6, + "efforts": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_effort": "high", + "max_input_tokens": 1000000, + "default_context_window": 200000, + "available_context_windows": [ + 200000, + 400000, + 1000000 + ] + } + ], + "has_more": false + } + }, + { + "source": "api__sessions__archive.md", + "model": "Session", + "value": { + "id": "sess_019ef30a4f0275678965d496ab542ef0", + "type": "session", + "agent": { + "id": "agent_019eda46c02b754499cdd3e282dbb8f1", + "type": "agent", + "version": 1, + "name": "dev-agent", + "description": "", + "model": { + "id": "ultimate", + "effective_context_window": 200000 + }, + "system": "You are an expert software engineer.", + "tools": [ + { + "enabled_tools": [ + "Bash", + "Read", + "Write", + "Edit", + "Glob", + "Grep" + ], + "type": "agent_toolset_20260401" + } + ], + "skills": [], + "mcp_servers": [] + }, + "archived_at": "2026-06-23T05:53:07.524734Z", + "created_at": "2026-06-22T02:38:23.006797Z", + "deployment_id": null, + "environment_id": "env_019eed3178647ceb92c821573e9f9bad", + "metadata": {}, + "outcome_evaluations": [], + "resources": [], + "stats": { + "active_seconds": 0, + "duration_seconds": 0 + }, + "status": "idle", + "title": "test-patch-title", + "updated_at": "2026-06-23T05:53:07.524734Z", + "usage": { + "model_credits": 2, + "sandbox_runtime_credits": 0.5, + "total_credits": 2.5 + }, + "environment_variables": {}, + "vault_ids": [] + } + }, + { + "source": "api__sessions__cancel.md", + "model": "Session", + "value": { + "id": "sess_019ef30a4f0275678965d496ab542ef0", + "type": "session", + "status": "canceling" + } + }, + { + "source": "api__sessions__create.md", + "model": "Session", + "value": { + "id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc", + "type": "session", + "agent": { + "id": "agent_019e390add9f7bac9b6cc806db46fcbd", + "type": "agent", + "name": "doc-test-agent", + "description": "Documentation example Agent", + "model": { + "id": "ultimate", + "effective_context_window": 200000 + }, + "system": "You are a test assistant.", + "tools": [], + "skills": [], + "mcp_servers": [], + "version": 2 + }, + "environment_id": "env_019e2590d33f711fabf42f2857cecd8a", + "title": "Code review session", + "status": "idle", + "metadata": { + "purpose": "review" + }, + "environment_variables": { + "FEATURE_FLAG": "on", + "LOG_LEVEL": "debug" + }, + "resources": [], + "vault_ids": [ + "vault_019eed0519807975983d0ffc4b4b4c79" + ], + "deployment_id": null, + "outcome_evaluations": [], + "stats": { + "active_seconds": 0, + "duration_seconds": 0 + }, + "archived_at": null, + "created_at": "2026-05-18T15:26:15.747298Z", + "updated_at": "2026-05-18T15:26:15.747298Z", + "usage": { + "model_credits": 0, + "sandbox_runtime_credits": 0, + "total_credits": 0 + } + } + }, + { + "source": "api__sessions__delete.md", + "model": "DeletedSession", + "value": { + "id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc", + "type": "session_deleted" + } + }, + { + "source": "api__sessions__events__list.md", + "model": "SessionEventListResponse", + "value": { + "data": [ + { + "id": "evt_019e392c0d787cfaa21bda98e06cd913", + "type": "user.message", + "content": [ + { + "type": "text", + "text": "Hello, this is a test message." + } + ], + "processed_at": "2026-05-18T03:40:48.888851795Z" + }, + { + "id": "evt_771c1195bcbd4a07834d4ed4dd6450ca", + "type": "agent.message", + "content": [ + { + "type": "text", + "text": "Hello! How can I help you today?" + } + ], + "processed_at": "2026-05-18T03:40:55.123Z" + } + ], + "first_id": "evt_019e392c0d787cfaa21bda98e06cd913", + "has_more": false, + "last_id": "evt_771c1195bcbd4a07834d4ed4dd6450ca", + "next_page": null + } + }, + { + "source": "api__sessions__events__send.md", + "model": "SessionEventSendResponse", + "value": { + "data": [ + { + "id": "evt_019e3bb2c153764da54e4d3acbef52b6", + "type": "user.message", + "content": [ + { + "type": "text", + "text": "Help me analyze the performance of this code." + } + ], + "processed_at": "2026-05-18T15:27:11.187413896Z" + } + ] + } + }, + { + "source": "api__sessions__get.md", + "model": "Session", + "value": { + "id": "sess_019ef30a4f0275678965d496ab542ef0", + "type": "session", + "agent": { + "description": "", + "id": "agent_019eda46c02b754499cdd3e282dbb8f1", + "mcp_servers": [], + "model": { + "id": "ultimate", + "effective_context_window": 200000 + }, + "name": "dev-agent", + "skills": [], + "system": "You are an expert software engineer.", + "tools": [ + { + "enabled_tools": [ + "Bash", + "Read", + "Write", + "Edit", + "Glob", + "Grep" + ], + "type": "agent_toolset_20260401" + } + ], + "type": "agent", + "version": 1 + }, + "archived_at": null, + "created_at": "2026-06-23T05:53:19.77484Z", + "deployment_id": null, + "environment_id": "env_019eed3178647ceb92c821573e9f9bad", + "environment_variables": {}, + "metadata": { + "purpose": "doc-verification" + }, + "outcome_evaluations": [], + "resources": [], + "stats": { + "active_seconds": 0, + "duration_seconds": 0 + }, + "status": "idle", + "title": "doc-review-test", + "updated_at": "2026-06-23T05:53:19.77484Z", + "usage": { + "model_credits": 1, + "sandbox_runtime_credits": 0.25, + "total_credits": 1.25 + }, + "vault_ids": [] + } + }, + { + "source": "api__sessions__list.md", + "model": "SessionListResponse", + "value": { + "data": [ + { + "id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc", + "type": "session", + "agent": { + "id": "agent_019e390add9f7bac9b6cc806db46fcbd", + "type": "agent", + "version": 2, + "name": "doc-verification-agent", + "description": "", + "model": { + "id": "ultimate", + "effective_context_window": 200000 + }, + "system": "You are an expert software engineer.", + "tools": [ + { + "enabled_tools": [ + "Bash", + "Read", + "Write", + "Edit", + "Glob", + "Grep" + ], + "type": "agent_toolset_20260401" + } + ], + "skills": [], + "mcp_servers": [] + }, + "environment_id": "env_019e2590d33f711fabf42f2857cecd8a", + "title": "API-doc-verification-session", + "status": "idle", + "metadata": {}, + "resources": [], + "vault_ids": [], + "deployment_id": null, + "outcome_evaluations": [], + "stats": { + "active_seconds": 0, + "duration_seconds": 0 + }, + "environment_variables": {}, + "archived_at": null, + "created_at": "2026-05-18T15:26:15.747298Z", + "updated_at": "2026-05-18T15:26:15.747298Z", + "usage": { + "model_credits": 1, + "sandbox_runtime_credits": 0.25, + "total_credits": 1.25 + } + } + ], + "first_id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc", + "has_more": false, + "last_id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc", + "next_page": null + } + }, + { + "source": "api__sessions__resources__add.md", + "model": "SessionResource", + "value": { + "id": "sesr_0e4323e8f47ba34853f5409e", + "type": "file", + "file_id": "file_019ef2a07a06704fb899908c29eed779", + "mount_path": "/mnt/session/uploads/file_019ef2a07a06704fb899908c29eed779", + "created_at": "2026-06-23T05:53:19.77484Z", + "updated_at": "2026-06-23T05:53:38.185714Z" + } + }, + { + "source": "api__sessions__resources__delete.md", + "model": "DeletedSessionResource", + "value": { + "id": "sesr_0e4323e8f47ba34853f5409e", + "type": "session_resource_deleted" + } + }, + { + "source": "api__sessions__resources__get.md", + "model": "SessionResource", + "value": { + "id": "sesr_0e4323e8f47ba34853f5409e", + "type": "file", + "file_id": "file_019ef2a07a06704fb899908c29eed779", + "mount_path": "/mnt/session/uploads/file_019ef2a07a06704fb899908c29eed779", + "created_at": "2026-06-23T05:53:19.77484Z", + "updated_at": "2026-06-23T05:53:44.995459Z" + } + }, + { + "source": "api__sessions__resources__list.md", + "model": "SessionResourceListResponse", + "value": { + "data": [ + { + "id": "sesr_0e4323e8f47ba34853f5409e", + "type": "file", + "file_id": "file_019ef2a07a06704fb899908c29eed779", + "mount_path": "/mnt/session/uploads/file_019ef2a07a06704fb899908c29eed779", + "created_at": "2026-06-23T05:53:19.77484Z", + "updated_at": "2026-06-23T05:53:38.185714Z" + } + ], + "first_id": "sesr_0e4323e8f47ba34853f5409e", + "last_id": "sesr_0e4323e8f47ba34853f5409e", + "has_more": false, + "next_page": null + } + }, + { + "source": "api__sessions__resources__update.md", + "model": "SessionResource", + "value": { + "id": "sesr_0e4323e8f47ba34853f5409e", + "type": "github_repository", + "url": "https://github.com/your-org/your-repo", + "mount_path": "/data/workspace/your-repo", + "checkout": { + "type": "branch", + "name": "main" + }, + "created_at": "2026-06-23T05:53:19.774840Z", + "updated_at": "2026-06-23T06:01:42.124501Z" + } + }, + { + "source": "api__sessions__threads__archive.md", + "model": "SessionThread", + "value": { + "id": "sthr_019ef2a07a06704fb899908c29eed779", + "type": "session_thread", + "session_id": "sess_019ef2a07a0670b3b68a84f0f3c5c98e", + "parent_thread_id": "sthr_019ef2a07a06704fb899908c29eed778", + "agent": { + "id": "agent_019e390add9f7bac9b6cc806db46fcbd", + "type": "agent", + "version": 2, + "name": "doc-test-agent", + "description": "", + "model": { + "id": "ultimate", + "effective_context_window": 200000 + }, + "system": "You are an expert software engineer.", + "tools": [ + { + "enabled_tools": [ + "Bash", + "Read", + "Write", + "Edit", + "Glob", + "Grep" + ], + "type": "agent_toolset_20260401" + } + ], + "skills": [], + "mcp_servers": [] + }, + "status": "terminated", + "stats": null, + "archived_at": "2026-06-23T06:00:00.000Z", + "created_at": "2026-06-23T05:53:19.774840Z", + "updated_at": "2026-06-23T06:00:00.000Z" + } + }, + { + "source": "api__sessions__threads__events__list.md", + "model": "SessionEventListResponse", + "value": { + "data": [ + { + "id": "evt_019f00000000000000000000000003cc", + "type": "agent.message", + "content": [ + { + "type": "text", + "text": "Thread response" + } + ], + "processed_at": "2026-06-15T08:02:00.000Z" + } + ], + "first_id": "evt_019f00000000000000000000000003cc", + "has_more": false, + "last_id": "evt_019f00000000000000000000000003cc", + "next_page": null + } + }, + { + "source": "api__sessions__threads__get.md", + "model": "SessionThread", + "value": { + "id": "sthr_019f00000000000000000000000002bb", + "type": "session_thread", + "session_id": "sess_019f00000000000000000000000000aa", + "parent_thread_id": "sthr_019f00000000000000000000000001aa", + "agent": { + "id": "agent_019f000000000000000000000000002b", + "type": "agent", + "version": 2 + }, + "status": "running", + "stats": null, + "archived_at": null, + "created_at": "2026-06-15T08:01:00.000Z", + "updated_at": "2026-06-15T08:01:00.000Z" + } + }, + { + "source": "api__sessions__threads__list.md", + "model": "SessionThreadListResponse", + "value": { + "data": [ + { + "id": "sthr_019f00000000000000000000000001aa", + "type": "session_thread", + "session_id": "sess_019f00000000000000000000000000aa", + "parent_thread_id": null, + "agent": { + "id": "agent_019f000000000000000000000000001a", + "type": "agent", + "version": 1 + }, + "status": "idle", + "stats": null, + "archived_at": null, + "created_at": "2026-06-15T08:00:00.000Z", + "updated_at": "2026-06-15T08:05:00.000Z" + } + ], + "first_id": "sthr_019f00000000000000000000000001aa", + "has_more": false, + "last_id": "sthr_019f00000000000000000000000001aa", + "next_page": null + } + }, + { + "source": "api__skills__create-version.md", + "model": "SkillVersion", + "value": { + "id": "skillver_019e3bbb6a25768b9b50ca2f52aa4345", + "type": "skill_version", + "skill_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "version": "1759264410332875", + "name": "my-custom-skill", + "description": "Custom skill example (second revision)", + "directory": "my-custom-skill", + "created_at": "2026-05-19T10:12:07.332875Z" + } + }, + { + "source": "api__skills__create.md", + "model": "Skill", + "value": { + "id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "type": "skill", + "display_title": "My Custom Skill", + "source": "custom", + "latest_version": "1759178010641129", + "metadata": { + "team": "docs" + }, + "created_at": "2026-05-18T15:35:24.248164Z", + "updated_at": "2026-05-18T15:35:24.248164Z" + } + }, + { + "source": "api__skills__delete-version.md", + "model": "DeletedSkillVersion", + "value": { + "id": "1759264410332875", + "type": "skill_version_deleted" + } + }, + { + "source": "api__skills__delete.md", + "model": "DeletedSkill", + "value": { + "id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "type": "skill_deleted" + } + }, + { + "source": "api__skills__get-version.md", + "model": "SkillVersion", + "value": { + "id": "skillver_019e3bba474b7f10a3c2b4d5e6f70123", + "type": "skill_version", + "skill_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "version": "1759178010641129", + "name": "my-custom-skill", + "description": "Custom skill example", + "directory": "my-custom-skill", + "created_at": "2026-05-18T15:35:24.248164Z" + } + }, + { + "source": "api__skills__get.md", + "model": "Skill", + "value": { + "id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "type": "skill", + "display_title": "test-skill-api-doc", + "source": "custom", + "latest_version": "1759178010641129", + "metadata": { + "team": "docs" + }, + "created_at": "2026-05-18T15:35:24.248164Z", + "updated_at": "2026-05-18T15:35:24.248164Z" + } + }, + { + "source": "api__skills__list-versions.md", + "model": "SkillVersionListResponse", + "value": { + "data": [ + { + "id": "skillver_019e3bbb6a25768b9b50ca2f52aa4345", + "type": "skill_version", + "skill_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "version": "1759264410332875", + "name": "my-custom-skill", + "description": "Custom skill example (second revision)", + "directory": "my-custom-skill", + "created_at": "2026-05-19T10:12:07.332875Z" + }, + { + "id": "skillver_019e3bba474b7f10a3c2b4d5e6f70123", + "type": "skill_version", + "skill_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "version": "1759178010641129", + "name": "my-custom-skill", + "description": "Custom skill example", + "directory": "my-custom-skill", + "created_at": "2026-05-18T15:35:24.248164Z" + } + ], + "has_more": false, + "next_page": null + } + }, + { + "source": "api__skills__list.md", + "model": "SkillListResponse", + "value": { + "data": [ + { + "id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "type": "skill", + "display_title": "test-skill-api-doc", + "source": "custom", + "latest_version": "1759178010641129", + "metadata": { + "team": "docs" + }, + "created_at": "2026-05-18T15:35:24.248164Z", + "updated_at": "2026-05-18T15:35:24.248164Z" + } + ], + "next_page": null, + "first_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "last_id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "has_more": false + } + }, + { + "source": "api__skills__list.md", + "model": "SkillListResponse", + "value": { + "data": [], + "next_page": null, + "first_id": null, + "last_id": null, + "has_more": false + } + }, + { + "source": "api__skills__update.md", + "model": "Skill", + "value": { + "id": "skill_019e3bba474b73cfaf19eae9b5f5e66d", + "type": "skill", + "display_title": "test-skill-api-doc", + "description": "Updated skill description", + "source": "custom", + "latest_version": "1759178010641129", + "metadata": { + "team": "docs", + "stage": "updated" + }, + "created_at": "2026-05-18T15:35:24.248164Z", + "updated_at": "2026-05-18T15:36:01.767469Z" + } + }, + { + "source": "api__vaults__archive-credential.md", + "model": "VaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "static_bearer", + "mcp_server_url": "https://example.com/mcp-stream" + }, + "display_name": null, + "metadata": { + "team": "docs" + }, + "archived_at": "2026-05-18T15:45:35.387093Z", + "created_at": "2026-05-18T15:34:35.387093Z", + "updated_at": "2026-05-18T15:45:35.387093Z" + } + }, + { + "source": "api__vaults__archive.md", + "model": "Vault", + "value": { + "id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault", + "display_name": "my-mcp-vault", + "metadata": {}, + "archived_at": "2026-05-18T15:34:35.630693Z", + "created_at": "2026-05-18T15:34:16.874877Z", + "updated_at": "2026-05-18T15:34:35.630693Z" + } + }, + { + "source": "api__vaults__create-credential.md", + "model": "VaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "static_bearer", + "mcp_server_url": "https://example.com/mcp-stream" + }, + "display_name": null, + "metadata": { + "team": "docs" + }, + "archived_at": null, + "created_at": "2026-05-18T15:34:35.387093Z", + "updated_at": "2026-05-18T15:34:35.387093Z" + } + }, + { + "source": "api__vaults__create-credential.md", + "model": "VaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "mcp_oauth", + "mcp_server_url": "https://mcp.example.com/mcp", + "expires_at": "2026-08-16T08:00:00Z", + "refresh": { + "client_id": "oauth-client-id", + "token_endpoint": "https://auth.example.com/oauth/token", + "token_endpoint_auth": { + "type": "client_secret_basic" + }, + "resource": "https://mcp.example.com/mcp", + "scope": "mcp.read mcp.write" + } + }, + "display_name": null, + "metadata": { + "team": "docs" + }, + "archived_at": null, + "created_at": "2026-05-18T15:34:35.387093Z", + "updated_at": "2026-05-18T15:34:35.387093Z" + } + }, + { + "source": "api__vaults__create.md", + "model": "Vault", + "value": { + "id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault", + "display_name": "my-mcp-vault", + "metadata": { + "team": "docs" + }, + "credentials": [], + "archived_at": null, + "created_at": "2026-05-18T15:34:16.874877Z", + "updated_at": "2026-05-18T15:34:16.874877Z" + } + }, + { + "source": "api__vaults__delete-credential.md", + "model": "DeletedVaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential_deleted" + } + }, + { + "source": "api__vaults__delete.md", + "model": "DeletedVault", + "value": { + "id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault_deleted" + } + }, + { + "source": "api__vaults__get-credential.md", + "model": "VaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "static_bearer", + "mcp_server_url": "https://example.com/mcp-stream" + }, + "display_name": null, + "metadata": { + "team": "docs" + }, + "archived_at": null, + "created_at": "2026-05-18T15:34:35.387093Z", + "updated_at": "2026-05-18T15:34:35.387093Z" + } + }, + { + "source": "api__vaults__get.md", + "model": "Vault", + "value": { + "id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault", + "display_name": "my-mcp-vault", + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:34:16.874877Z", + "updated_at": "2026-05-18T15:34:16.874877Z" + } + }, + { + "source": "api__vaults__list-credentials.md", + "model": "VaultCredentialListResponse", + "value": { + "data": [ + { + "id": "vcred_019e3bb940297658a632dbf920057eff", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "static_bearer", + "mcp_server_url": "https://example.com/mcp" + }, + "display_name": null, + "metadata": { + "team": "docs" + }, + "archived_at": null, + "created_at": "2026-05-18T15:34:16.876188Z", + "updated_at": "2026-05-18T15:34:16.876188Z" + } + ], + "next_page": null, + "first_id": "vcred_019e3bb940297658a632dbf920057eff", + "last_id": "vcred_019e3bb940297658a632dbf920057eff", + "has_more": false + } + }, + { + "source": "api__vaults__list.md", + "model": "VaultListResponse", + "value": { + "data": [ + { + "id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault", + "display_name": "my-mcp-vault", + "metadata": {}, + "archived_at": null, + "created_at": "2026-05-18T15:34:16.874877Z", + "updated_at": "2026-05-18T15:34:16.874877Z" + } + ], + "next_page": null, + "first_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "last_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "has_more": false + } + }, + { + "source": "api__vaults__list.md", + "model": "VaultListResponse", + "value": { + "data": [], + "next_page": null, + "first_id": null, + "last_id": null, + "has_more": false + } + }, + { + "source": "api__vaults__start-oauth.md", + "model": "OAuthStartResponse", + "value": { + "authorization_url": "https://auth.example.com/authorize?client_id=cloud-agent&code_challenge=...&code_challenge_method=S256&redirect_uri=...&response_type=code&state=...", + "state": "65eec7b8e79aa61c249d971678cf9201", + "callback_origin": "https://api.qoder.com" + } + }, + { + "source": "api__vaults__update-credential.md", + "model": "VaultCredential", + "value": { + "id": "vcred_019e3bb98877759e862750b495c1fce8", + "type": "vault_credential", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "auth": { + "type": "mcp_oauth", + "mcp_server_url": "https://mcp.example.com/mcp", + "expires_at": "2026-08-20T08:00:00Z" + }, + "display_name": null, + "metadata": { + "rotated_by": "ops" + }, + "archived_at": null, + "created_at": "2026-05-18T15:34:35.387093Z", + "updated_at": "2026-08-19T02:58:10.114532Z" + } + }, + { + "source": "api__vaults__validate-credential.md", + "model": "VaultCredentialValidation", + "value": { + "credential_id": "vcred_019e3bb98877759e862750b495c1fce8", + "vault_id": "vault_019e3bb940277f0db05ab74291acf6ef", + "type": "vault_credential_validation", + "status": "invalid", + "validated_at": "2026-08-19T02:58:16Z", + "has_refresh_token": false, + "refresh": { + "status": "no_refresh_token", + "http_response": null + }, + "mcp_probe": { + "method": "initialize", + "http_response": { + "status_code": 401, + "content_type": "application/json", + "body": "{\"error\":\"invalid_token\"}", + "body_truncated": false + } + } + } + } +] diff --git a/src/test/resources/managed-routes.json b/src/test/resources/managed-routes.json new file mode 100644 index 0000000..eb108fa --- /dev/null +++ b/src/test/resources/managed-routes.json @@ -0,0 +1,2651 @@ +[ + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/archive", + "method": "POST", + "path": "/api/v1/cloud/agents/segment_0%2Fencoded/archive", + "resource": "agents", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/create", + "method": "POST", + "path": "/api/v1/cloud/agents", + "resource": "agents", + "operation": "create", + "param": "AgentCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "name": "sdk-contract", + "model": { + "id": "ultimate", + "effort": "low", + "context_window": 200000 + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/get", + "method": "GET", + "path": "/api/v1/cloud/agents/segment_0%2Fencoded", + "resource": "agents", + "operation": "retrieve", + "param": "AgentRetrieveParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "version": 1 + }, + "query_types": { + "version": "long" + }, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/list-versions", + "method": "GET", + "path": "/api/v1/cloud/agents/segment_0%2Fencoded/versions", + "resource": "agents.versions", + "operation": "list", + "param": "AgentVersionListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/list", + "method": "GET", + "path": "/api/v1/cloud/agents", + "resource": "agents", + "operation": "list", + "param": "AgentListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "include_archived": true, + "created_at[gte]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "include_archived": "boolean", + "created_at[gte]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/search", + "method": "POST", + "path": "/api/v1/cloud/agents/search", + "resource": "agents", + "operation": "search", + "param": "AgentSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/agents/update", + "method": "POST", + "path": "/api/v1/cloud/agents/segment_0%2Fencoded", + "resource": "agents", + "operation": "update", + "param": "AgentUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "version": 1, + "system": "Updated system" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/archive", + "method": "POST", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/archive", + "resource": "deployments", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/create", + "method": "POST", + "path": "/api/v1/cloud/deployments", + "resource": "deployments", + "operation": "create", + "param": "DeploymentCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "name": "sdk-contract", + "agent": "agent_test", + "environment_id": "env_test", + "initial_events": [ + { + "type": "user.message", + "content": [ + { + "type": "text", + "text": "hello" + } + ] + } + ], + "environment_variables": "LOG_LEVEL=debug" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/get-run-global", + "method": "GET", + "path": "/api/v1/cloud/deployment_runs/segment_0%2Fencoded", + "resource": "deploymentRuns", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/get-run", + "method": "GET", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/runs/segment_1%2Fencoded", + "resource": "deployments.runs", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/get", + "method": "GET", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded", + "resource": "deployments", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/list-all-runs", + "method": "GET", + "path": "/api/v1/cloud/deployment_runs", + "resource": "deploymentRuns", + "operation": "list", + "param": "DeploymentRunListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "deployment_id": "test/value", + "trigger_type": "test/value", + "has_error": true, + "created_at[gt]": "test/value", + "created_at[gte]": "test/value", + "created_at[lt]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "deployment_id": "String", + "trigger_type": "String", + "has_error": "boolean", + "created_at[gt]": "String", + "created_at[gte]": "String", + "created_at[lt]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/list-runs", + "method": "GET", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/runs", + "resource": "deployments.runs", + "operation": "list", + "param": "DeploymentScopedRunListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1, + "triggered_after": "test/value", + "triggered_before": "test/value" + }, + "query_types": { + "limit": "long", + "triggered_after": "String", + "triggered_before": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/list", + "method": "GET", + "path": "/api/v1/cloud/deployments", + "resource": "deployments", + "operation": "list", + "param": "DeploymentListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "status": "test/value", + "include_archived": true, + "agent_id": "test/value", + "created_at[gte]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "status": "String", + "include_archived": "boolean", + "agent_id": "String", + "created_at[gte]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/pause", + "method": "POST", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/pause", + "resource": "deployments", + "operation": "pause", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/run", + "method": "POST", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/run", + "resource": "deployments", + "operation": "run", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/search", + "method": "POST", + "path": "/api/v1/cloud/deployments/search", + "resource": "deployments", + "operation": "search", + "param": "DeploymentSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/unpause", + "method": "POST", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded/unpause", + "resource": "deployments", + "operation": "unpause", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/deployments/update", + "method": "POST", + "path": "/api/v1/cloud/deployments/segment_0%2Fencoded", + "resource": "deployments", + "operation": "update", + "param": "DeploymentUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "schedule": null, + "environment_variables": null, + "metadata": { + "remove": null + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/dreams/archive", + "method": "POST", + "path": "/api/v1/cloud/dreams/segment_0%2Fencoded/archive", + "resource": "dreams", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/dreams/cancel", + "method": "POST", + "path": "/api/v1/cloud/dreams/segment_0%2Fencoded/cancel", + "resource": "dreams", + "operation": "cancel", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/dreams/create", + "method": "POST", + "path": "/api/v1/cloud/dreams", + "resource": "dreams", + "operation": "create", + "param": "DreamCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "inputs": [ + { + "type": "memory_store", + "memory_store_id": "memstore_test" + } + ] + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/dreams/get", + "method": "GET", + "path": "/api/v1/cloud/dreams/segment_0%2Fencoded", + "resource": "dreams", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/dreams/list", + "method": "GET", + "path": "/api/v1/cloud/dreams", + "resource": "dreams", + "operation": "list", + "param": "DreamListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "include_archived": true + }, + "query_types": { + "limit": "long", + "include_archived": "boolean" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/archive", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/archive", + "resource": "environments", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/create", + "method": "POST", + "path": "/api/v1/cloud/environments", + "resource": "environments", + "operation": "create", + "param": "EnvironmentCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "name": "sdk-contract", + "config": { + "type": "self_hosted" + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/delete", + "method": "DELETE", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded", + "resource": "environments", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/get", + "method": "GET", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded", + "resource": "environments", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/list", + "method": "GET", + "path": "/api/v1/cloud/environments", + "resource": "environments", + "operation": "list", + "param": "EnvironmentListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "include_archived": true, + "created_at[gte]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "include_archived": "boolean", + "created_at[gte]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/search", + "method": "POST", + "path": "/api/v1/cloud/environments/search", + "resource": "environments", + "operation": "search", + "param": "EnvironmentSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/update", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded", + "resource": "environments", + "operation": "update", + "param": "EnvironmentUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "description": "changed" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/ack", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/segment_1%2Fencoded/ack", + "resource": "environments.work", + "operation": "ack", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/get", + "method": "GET", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/segment_1%2Fencoded", + "resource": "environments.work", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/heartbeat", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/segment_1%2Fencoded/heartbeat", + "resource": "environments.work", + "operation": "heartbeat", + "param": "WorkHeartbeatParams", + "mode": "query", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": { + "expected_last_heartbeat": "test/value", + "desired_ttl_seconds": 1 + }, + "query_types": { + "expected_last_heartbeat": "String", + "desired_ttl_seconds": "long" + }, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/list", + "method": "GET", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work", + "resource": "environments.work", + "operation": "list", + "param": "WorkListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/poll", + "method": "GET", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/poll", + "resource": "environments.work", + "operation": "poll", + "param": "WorkPollParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "block_ms": 1, + "reclaim_older_than_ms": 1 + }, + "query_types": { + "block_ms": "long", + "reclaim_older_than_ms": "long" + }, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/stats", + "method": "GET", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/stats", + "resource": "environments.work", + "operation": "stats", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/stop", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/segment_1%2Fencoded/stop", + "resource": "environments.work", + "operation": "stop", + "param": "WorkStopParams", + "mode": "body", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "force": true + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/environments/work/update-metadata", + "method": "POST", + "path": "/api/v1/cloud/environments/segment_0%2Fencoded/work/segment_1%2Fencoded", + "resource": "environments.work", + "operation": "update", + "param": "WorkUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "worker": "java", + "remove": null + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/delete", + "method": "DELETE", + "path": "/api/v1/cloud/files/segment_0%2Fencoded", + "resource": "files", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/download", + "method": "GET", + "path": "/api/v1/cloud/files/segment_0%2Fencoded/content", + "resource": "files", + "operation": "getDownloadUrl", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "url": "https://storage.example.com/file", + "expires_at": "2026-12-01T00:00:00Z" + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/get", + "method": "GET", + "path": "/api/v1/cloud/files/segment_0%2Fencoded", + "resource": "files", + "operation": "getMetadata", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/list", + "method": "GET", + "path": "/api/v1/cloud/files", + "resource": "files", + "operation": "list", + "param": "FileListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "name": "test/value" + }, + "query_types": { + "limit": "long", + "name": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/search", + "method": "POST", + "path": "/api/v1/cloud/files/search", + "resource": "files", + "operation": "search", + "param": "FileSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/files/upload", + "method": "POST", + "path": "/api/v1/cloud/files", + "resource": "files", + "operation": "upload", + "param": "FileUploadParams", + "mode": "multipart", + "ids": [], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/archive", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/archive", + "resource": "memoryStores", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/create-memory", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memories", + "resource": "memoryStores.memories", + "operation": "create", + "param": "MemoryCreateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "path": "/qa.md", + "content": "hello" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/create", + "method": "POST", + "path": "/api/v1/cloud/memory_stores", + "resource": "memoryStores", + "operation": "create", + "param": "MemoryStoreCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "name": "sdk-contract" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/delete-memory", + "method": "DELETE", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memories/segment_1%2Fencoded", + "resource": "memoryStores.memories", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/delete", + "method": "DELETE", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded", + "resource": "memoryStores", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/get-memory", + "method": "GET", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memories/segment_1%2Fencoded", + "resource": "memoryStores.memories", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/get-version", + "method": "GET", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memory_versions/segment_1%2Fencoded", + "resource": "memoryStores.versions", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/get", + "method": "GET", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded", + "resource": "memoryStores", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/list-memories", + "method": "GET", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memories", + "resource": "memoryStores.memories", + "operation": "list", + "param": "MemoryListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "path_prefix": "test/value" + }, + "query_types": { + "path_prefix": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/list-versions", + "method": "GET", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memory_versions", + "resource": "memoryStores.versions", + "operation": "list", + "param": "MemoryVersionListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "memory_id": "test/value" + }, + "query_types": { + "memory_id": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/list", + "method": "GET", + "path": "/api/v1/cloud/memory_stores", + "resource": "memoryStores", + "operation": "list", + "param": "MemoryStoreListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "include_archived": true, + "name": "test/value", + "created_at[gte]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "include_archived": "boolean", + "name": "String", + "created_at[gte]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/redact-version", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memory_versions/segment_1%2Fencoded/redact", + "resource": "memoryStores.versions", + "operation": "redact", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/search", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/search", + "resource": "memoryStores", + "operation": "search", + "param": "MemoryStoreSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/update-memory", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded/memories/segment_1%2Fencoded", + "resource": "memoryStores.memories", + "operation": "update", + "param": "MemoryUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "content": "updated", + "content_sha256": "test-hash" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/memory-stores/update", + "method": "POST", + "path": "/api/v1/cloud/memory_stores/segment_0%2Fencoded", + "resource": "memoryStores", + "operation": "update", + "param": "MemoryStoreUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "description": null + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/models/list", + "method": "GET", + "path": "/api/v1/cloud/models", + "resource": "models", + "operation": "list", + "param": null, + "mode": "none", + "ids": [], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/archive", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/archive", + "resource": "sessions", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/cancel", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/cancel", + "resource": "sessions", + "operation": "cancel", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/create", + "method": "POST", + "path": "/api/v1/cloud/sessions", + "resource": "sessions", + "operation": "create", + "param": "SessionCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "agent": { + "type": "agent", + "id": "agent_test", + "version": 2 + }, + "environment_id": "env_test", + "budget": { + "type": "limit", + "max_credit_cost": "100.00" + }, + "metadata": { + "ticket": "sdk-contract", + "__qca_sdk_future": "kept" + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/delete", + "method": "DELETE", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded", + "resource": "sessions", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/events/list", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/events", + "resource": "sessions.events", + "operation": "list", + "param": "SessionEventListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1, + "order": "test/value", + "types": "test/value", + "created_at[gt]": "test/value", + "created_at[gte]": "test/value", + "created_at[lt]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "order": "String", + "types": "String", + "created_at[gt]": "String", + "created_at[gte]": "String", + "created_at[lt]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/events/send", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/events", + "resource": "sessions.events", + "operation": "send", + "param": "SessionEventSendParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "events": [ + { + "type": "user.message", + "content": [ + { + "type": "text", + "text": "hello" + } + ] + } + ] + }, + "response": { + "data": [ + { + "id": "evt_test", + "type": "user.message", + "content": [ + { + "type": "text", + "text": "hello" + } + ] + } + ] + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/get", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded", + "resource": "sessions", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/list", + "method": "GET", + "path": "/api/v1/cloud/sessions", + "resource": "sessions", + "operation": "list", + "param": "SessionListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "order": "test/value", + "include_archived": true, + "statuses": "test/value", + "agent_id": "test/value", + "agent_version": 1, + "deployment_id": "test/value", + "memory_store_id": "test/value", + "created_at[gt]": "test/value", + "created_at[gte]": "test/value", + "created_at[lt]": "test/value", + "created_at[lte]": "test/value" + }, + "query_types": { + "limit": "long", + "order": "String", + "include_archived": "boolean", + "statuses": "String", + "agent_id": "String", + "agent_version": "long", + "deployment_id": "String", + "memory_store_id": "String", + "created_at[gt]": "String", + "created_at[gte]": "String", + "created_at[lt]": "String", + "created_at[lte]": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/resources/add", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/resources", + "resource": "sessions.resources", + "operation": "create", + "param": "SessionResourceCreateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "type": "file", + "file_id": "file_test", + "mount_path": "/qa.txt" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/resources/delete", + "method": "DELETE", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/resources/segment_1%2Fencoded", + "resource": "sessions.resources", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/resources/get", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/resources/segment_1%2Fencoded", + "resource": "sessions.resources", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/resources/list", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/resources", + "resource": "sessions.resources", + "operation": "list", + "param": "SessionResourceListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/resources/update", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/resources/segment_1%2Fencoded", + "resource": "sessions.resources", + "operation": "update", + "param": "SessionResourceUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "password": "test-password" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/search", + "method": "POST", + "path": "/api/v1/cloud/sessions/search", + "resource": "sessions", + "operation": "search", + "param": "SessionSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/threads/archive", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/threads/segment_1%2Fencoded/archive", + "resource": "sessions.threads", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/threads/events/list", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/threads/segment_1%2Fencoded/events", + "resource": "sessions.threads.events", + "operation": "list", + "param": "SessionThreadEventListParams", + "mode": "query", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/threads/get", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/threads/segment_1%2Fencoded", + "resource": "sessions.threads", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/threads/list", + "method": "GET", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded/threads", + "resource": "sessions.threads", + "operation": "list", + "param": "SessionThreadListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/sessions/update", + "method": "POST", + "path": "/api/v1/cloud/sessions/segment_0%2Fencoded", + "resource": "sessions", + "operation": "update", + "param": "SessionUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "budget": null, + "agent": { + "system": "updated runtime", + "skills": [] + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/create-version", + "method": "POST", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded/versions", + "resource": "skills.versions", + "operation": "create", + "param": "SkillVersionCreateParams", + "mode": "multipart", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/create", + "method": "POST", + "path": "/api/v1/cloud/skills", + "resource": "skills", + "operation": "create", + "param": "SkillCreateParams", + "mode": "multipart", + "ids": [], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/delete-version", + "method": "DELETE", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded/versions/segment_1%2Fencoded", + "resource": "skills.versions", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/delete", + "method": "DELETE", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded", + "resource": "skills", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/get-version-content", + "method": "GET", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded/versions/segment_1%2Fencoded/content", + "resource": "skills.versions", + "operation": "download", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/get-version", + "method": "GET", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded/versions/segment_1%2Fencoded", + "resource": "skills.versions", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/get", + "method": "GET", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded", + "resource": "skills", + "operation": "retrieve", + "param": "SkillRetrieveParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "include_content": true + }, + "query_types": { + "include_content": "boolean" + }, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/list-versions", + "method": "GET", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded/versions", + "resource": "skills.versions", + "operation": "list", + "param": "SkillVersionListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1 + }, + "query_types": { + "limit": "long" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/list", + "method": "GET", + "path": "/api/v1/cloud/skills", + "resource": "skills", + "operation": "list", + "param": "SkillListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "source": "test/value", + "display_title": "test/value", + "name": "test/value" + }, + "query_types": { + "limit": "long", + "source": "String", + "display_title": "String", + "name": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/search", + "method": "POST", + "path": "/api/v1/cloud/skills/search", + "resource": "skills", + "operation": "search", + "param": "SkillSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/skills/update", + "method": "PUT", + "path": "/api/v1/cloud/skills/segment_0%2Fencoded", + "resource": "skills", + "operation": "update", + "param": "SkillUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/archive-credential", + "method": "POST", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials/segment_1%2Fencoded/archive", + "resource": "vaults.credentials", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/archive", + "method": "POST", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/archive", + "resource": "vaults", + "operation": "archive", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/create-credential", + "method": "POST", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials", + "resource": "vaults.credentials", + "operation": "create", + "param": "VaultCredentialCreateParams", + "mode": "body", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "auth": { + "type": "environment_variable", + "name": "EXAMPLE_KEY", + "secret_value": "test-secret" + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/create", + "method": "POST", + "path": "/api/v1/cloud/vaults", + "resource": "vaults", + "operation": "create", + "param": "VaultCreateParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "display_name": "sdk-contract" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/delete-credential", + "method": "DELETE", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials/segment_1%2Fencoded", + "resource": "vaults.credentials", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/delete", + "method": "DELETE", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded", + "resource": "vaults", + "operation": "delete", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/get-credential", + "method": "GET", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials/segment_1%2Fencoded", + "resource": "vaults.credentials", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/get", + "method": "GET", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded", + "resource": "vaults", + "operation": "retrieve", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded" + ], + "query": {}, + "query_types": {}, + "body": null, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/list-credentials", + "method": "GET", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials", + "resource": "vaults.credentials", + "operation": "list", + "param": "VaultCredentialListParams", + "mode": "query", + "ids": [ + "segment_0/encoded" + ], + "query": { + "limit": 1, + "include_archived": true, + "name": "test/value" + }, + "query_types": { + "limit": "long", + "include_archived": "boolean", + "name": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/list", + "method": "GET", + "path": "/api/v1/cloud/vaults", + "resource": "vaults", + "operation": "list", + "param": "VaultListParams", + "mode": "query", + "ids": [], + "query": { + "limit": 1, + "include_archived": true, + "name": "test/value" + }, + "query_types": { + "limit": "long", + "include_archived": "boolean", + "name": "String" + }, + "body": null, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/search", + "method": "POST", + "path": "/api/v1/cloud/vaults/search", + "resource": "vaults", + "operation": "search", + "param": "VaultSearchParams", + "mode": "search", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "metadata": { + "team": "sdk" + }, + "limit": 1, + "page": "opaque-page" + }, + "response": { + "data": [], + "has_more": false, + "next_page": null, + "total": 0 + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/start-oauth", + "method": "POST", + "path": "/api/v1/cloud/oauth/start", + "resource": "oauth", + "operation": "start", + "param": "OAuthStartParams", + "mode": "body", + "ids": [], + "query": {}, + "query_types": {}, + "body": { + "vault_id": "vault_test", + "mcp_server_url": "https://mcp.example.com", + "client_id": "test-client", + "client_secret": "test-secret" + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/update-credential", + "method": "POST", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials/segment_1%2Fencoded", + "resource": "vaults.credentials", + "operation": "update", + "param": "VaultCredentialUpdateParams", + "mode": "body", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": { + "auth": { + "type": "environment_variable", + "secret_value": "new-test-secret" + } + }, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + }, + { + "source": "https://docs.qoder.com/cloud-agents/api/vaults/validate-credential", + "method": "POST", + "path": "/api/v1/cloud/vaults/segment_0%2Fencoded/credentials/segment_1%2Fencoded/mcp_oauth_validate", + "resource": "vaults.credentials", + "operation": "validate", + "param": null, + "mode": "none", + "ids": [ + "segment_0/encoded", + "segment_1/encoded" + ], + "query": {}, + "query_types": {}, + "body": {}, + "response": { + "id": "object_test", + "type": "test", + "future": { + "accepted": true + } + } + } +]