You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit d93dbf9
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,16 @@
2
2
3
3
## [Unreleased]
4
4
5
+
### Added
6
+
7
+
- Public Java 8 HTTP transport and per-attempt interceptor contracts for custom networking and tracing, without exposing OkHttp types. Cancellation reaches downstream transport futures; SSE bodies remain streaming. Storage downloads use the transport without API credentials or interceptors. WebSockets and SA Key exchange retain their existing transports.
8
+
- Synchronous/asynchronous `request(ApiRequest, RequestOptions)` for additional JSON endpoints, reusing authentication, retries, cancellation and response metadata with relative path segments.
9
+
- Synchronous/asynchronous `withOptions(...)` to derive independently closeable clients while retaining resolved authentication and unspecified settings. Caller-supplied credentials and transports remain caller-owned.
10
+
11
+
### Fixed
12
+
13
+
- Add typed image `file_id`, Memory Store creation-mount `access`, Schedule/Run `initial_events_version` and Pairing `created_at` / `updated_at` fields. Missing versions remain unknown rather than becoming zero.
14
+
5
15
## [0.1.0] - 2026-10-21
6
16
7
17
First stable release of the Java SDK for the Forward API, using `com.qoder.sdk:qoder-cloud-agents-sdk:0.1.0`.
Use the returned Pairing ID for revocation and Schedule sinks. Current API supports completion by pending Pairing ID as well as code; code-only older SDK types are not copied. An ID-based completion can be retried against the same binding without depending on code expiry. Used/expired codes cannot be treated as fresh pairing requests. Permission, ownership and concurrent-change errors remain server decisions.
104
104
105
+
The development SDK also exposes nullable `createdAt()` and `updatedAt()` strings on `ChannelPairing`, preserving timestamps returned by the service. These getters are not included in the published `0.1.0` JAR.
106
+
105
107
`delete` removes the Channel connection; it is distinct from `channelPairings().delete`, which revokes one binding. Already absent/unpaired bindings can return `deleted=true`. SDK keeps the declared deletion response and accepts an empty 204 without inventing a JSON body; use `withResponse()` for metadata in that case.
Copy file name to clipboardExpand all lines: docs/client-configuration.md
+69-1Lines changed: 69 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,7 +87,75 @@ com.qoder.cloudagents.core.ApiResponse<com.qoder.cloudagents.forward.Template> r
87
87
- Models provide `requestId()`, `field(name)` for unknown fields and `rawJson()`. Unknown fields and numeric precision are preserved; invalid typed field access raises `ResponseValidationException`. Request metadata is separate from the JSON body.
88
88
- Template list parameters support `limit`, `status`, `afterId` or `beforeId`. Use `page.data()` for one page, `getNextPage()` / `getNextPageAsync()` for manual pagination, or `for (Template template : page)` for lazy synchronous iteration. Server order is retained; filters and request options follow subsequent pages. Check `hasNextPage()` before fetching; an exhausted page or repeated cursor raises `PaginationException`.
89
89
90
-
## Template configuration
90
+
## Client extensions (unreleased)
91
+
92
+
The following client extensions are on the development branch and are not included in the published `0.1.0` JAR. Build and install the local SDK to try them.
`withOptions` retains the resolved BaseURL, authentication, headers, interceptors and custom transport unless changed. It does not reread environment credentials. Header setters replace matching names case-insensitively; interceptors append in registration order. Use `clearDefaultHeaders()` or `clearInterceptors()` to replace those collections. Per-request options still take precedence. `client.async().withOptions(...)` creates an independently owned async client.
106
+
107
+
Copies have separate default connection pools, retry timers and in-flight request lifecycles. Closing either client does not close the other. Custom transports and credentials are shared by reference and remain caller-owned; keep them open until all clients and streams finish. Changing `.pat(...)`, `.accessToken(...)` or `.credential(...)` on a copy replaces its inherited credential source. For a static SAT use `.authMode(AuthMode.SA).accessToken(token)`.
Pass unencoded path **segments**, for example `ApiRequest.builder("POST", "sessions", sessionId, "new-action")`; the SDK encodes each segment beneath its configured BaseURL. Absolute URLs, slash-separated paths, traversal and embedded queries/fragments are rejected. Use `RequestOptions.query(...)` and `header(...)` for query parameters and headers, and `.body(JsonValue)` for a JSON body. GET/HEAD cannot have a body. HEAD and 204/205 responses return JSON null.
123
+
124
+
The return type includes JSON, status and response headers; `client.async().request(...)` returns a cancellable `CompletableFuture<ApiResponse<JsonValue>>`. HTTP errors retain the existing exception mapping. This entry point uses business PAT/SAT credentials and the shared retry rules; it does not add resource-specific validation. Prefer typed resource methods where available, particularly SA Key token management and credential rotation. Use the existing resource APIs for multipart upload, downloads and SSE.
`HttpInterceptor` runs after authentication on **every attempt**, including SSE connection/reconnection and explicit SA Key token-management requests. It may inspect metadata, add ordinary headers or return a response, but may call `chain.proceed(...)` only once. It cannot change routing, method, body, timeout, Authorization or idempotency. Do not log headers, bodies or full URLs, or read a streaming body just to log it. Interceptor callbacks must return promptly. Their completion future measures response-header arrival, not SSE/download completion.
142
+
143
+
Implement `com.qoder.cloudagents.core.http.HttpTransport` and pass it to `.transport(...)` when an application needs its own HTTP library, proxy, TLS settings or connection pool. The SDK passes an immutable `HttpRequest` with URI, headers, connect/read/write timeouts and an optional streaming `Body`. Use `Body.contentType()`, `contentLength()` and `writeTo(OutputStream)` when sending uploads; do not buffer all uploads or close the destination from `writeTo`.
144
+
145
+
The transport must return a `CompletableFuture<HttpResponse>` promptly, perform one attempt without automatic redirects/retries/authentication, honor timeouts, and abort its I/O when its future is cancelled. Return an unconsumed `InputStream` in `HttpResponse`; the SDK closes it on completion, cancellation or failure. Transport implementations must release responses that lose a race with cancellation. Read timeout is zero for an accepted SSE stream; SDK header and optional total deadlines remain active. Cancelling an SDK request also cancels downstream transport futures even when an interceptor has wrapped them in `thenApply`/`whenComplete`.
146
+
147
+
| Operation | Custom transport | API interceptors |
| Session/Thread SSE, including resumption | Yes | Yes, per connection |
151
+
| File signed-URL storage download | Yes | No; no API headers/credentials copied |
152
+
| Realtime create/History HTTP | Yes | Yes |
153
+
| Realtime WebSocket | No | No |
154
+
|`ServiceAccountCredential` platform exchange | No | No |
155
+
156
+
The default HTTP implementation remains OkHttp. Injected transports and interceptors do not change the SDK's retry safety rules or grant additional API permissions.
Copy file name to clipboardExpand all lines: docs/memory-stores.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,7 +42,7 @@ MemoryStoreCreateMount mount = MemoryStoreCreateMount.builder()
42
42
// Supply .mount(mount) on MemoryStoreCreateParams.builder().
43
43
```
44
44
45
-
Both IDs are required when supplying `mount`. This is a read-only explicit mount, matching the separate Identity mount API. Store `bindingInfo().identityTemplateCount()` reports active mounts; unknown binding fields remain available through `field(...)`.
45
+
Both IDs are required when supplying `mount`. The development SDK also supports `.access("read_only")` or `.access("read_write")`; omitting it leaves the default to the service. This typed setter is not included in the published `0.1.0` JAR. Store `bindingInfo().identityTemplateCount()` reports active mounts; unknown binding fields remain available through `field(...)`.
46
46
47
47
Store metadata is a string map with at most 15 user keys. `created_by` is reserved and added by the service. Memory metadata allows 16 keys and does not reserve `created_by`. Key/value size rules and other business constraints are enforced by the service. The SDK does not insert reserved metadata.
Schedule initial events use string `content` as documented by this endpoint; ordinary Session events have their own content-block model. `ScheduleTriggerPolicyParams` exposes request fields (`type`, `expression`, `timezone`), while `ScheduleTriggerPolicy` includes computed response fields such as `upcomingRunsAt` and `lastRunAt`. Cron/timezone, once-time and interval rules are validated by the server.
26
26
27
+
The development SDK exposes `initialEventsVersion()` on both `Schedule` and `ScheduleRun`. It returns a nullable `Long`: an absent version remains unknown, distinct from an explicit zero. This getter is not included in the published `0.1.0` JAR.
28
+
27
29
-`schedules().list/create/retrieve/update/archive/archiveMany/pause/unpause/run` cover the nine Schedule operations.
- An omitted trigger policy or explicit `null` creates a manual Schedule. Updating `triggerPolicy(null)` switches to manual. Updating `sinks(null)` or an empty list clears delivery targets; omitting a field retains it. Execution fields merge. Metadata values of JSON `null` remove keys.
`EventContent.text(...)` creates the content-block array required for a user message. Use `EventContent.blocks(...)` with typed `ContentBlock` and `ImageSource` for text/image inputs. `EventContent.ofString(...)` represents string content for event types such as tool results; do not use it for a `user.message`.
68
68
69
+
The development SDK adds `ImageSource.builder().type("file").fileId(fileId)` and `fileId()` for images referenced by file ID. These typed methods are not included in the published `0.1.0` JAR; the service validates the image source and file permissions.
70
+
69
71
`SessionEventParam` also exposes tool confirmation/result fields, custom tool result IDs, interrupt reason and outcome definition. `OutcomeRubric` is an object with a type and text/file ID, matching the documented outcome contract. Event-specific validation and permissions remain server-side.
70
72
71
73
A successful send acknowledges accepted input; it does not mean the model finished. Reading history returns persisted events, not a live subscription:
Copy file name to clipboardExpand all lines: examples/README.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,8 @@ For SDK development or an unpublished version, install the local SDK first:
17
17
18
18
Verification uses a local fake service and asserts the SDK was loaded from a JAR. It does not use production credentials.
19
19
20
+
`ClientExtensionsExample` demonstrates a read-only generic JSON request, a per-attempt tracing interceptor and an independently closeable client copy. It also accepts an application-owned `HttpTransport`. These extension APIs are unreleased; install the development SDK first, then run with `-Dexec.mainClass=com.qoder.cloudagents.examples.ClientExtensionsExample`. The packaged-consumer test verifies an adapter built with Java 8 `HttpURLConnection`, without importing SDK internals.
21
+
20
22
To run against your environment, configure credentials in your shell and choose one mode:
0 commit comments