Skip to content

Commit 400185f

Browse files
damianmomotgooglecopybara-github
authored andcommitted
refactor(caching): give ContextCacheConfig an ADK-owned HttpOptions type
`ContextCacheConfig.createHttpOptions` was typed with the GenAI SDK's `HttpOptions`, leaking a backend SDK type into ADK's public configuration API. Add `com.google.adk.kt.models.HttpOptions` and use that instead; PiperOrigin-RevId: 955731480
1 parent 9d2ebef commit 400185f

8 files changed

Lines changed: 63 additions & 13 deletions

File tree

core/src/commonMain/kotlin/com/google/adk/kt/agents/ContextCacheConfig.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package com.google.adk.kt.agents
1818

1919
import com.google.adk.kt.annotations.ExperimentalContextCachingFeature
20-
import com.google.genai.kotlin.types.HttpOptions
20+
import com.google.adk.kt.types.HttpOptions
2121
import kotlin.time.Duration
2222
import kotlin.time.Duration.Companion.seconds
2323

@@ -42,10 +42,10 @@ import kotlin.time.Duration.Companion.seconds
4242
* session; caching begins on the second turn once a previous token count is known. Context cache
4343
* storage may have a cost, so set this higher to avoid caching small requests where the overhead
4444
* may exceed the benefits. Must be non-negative. Defaults to 0.
45-
* @property createHttpOptions Optional HTTP options to pass to the GenAI client. Set this to add a
46-
* timeout on `CachedContent.create()` calls (e.g. `HttpOptions(timeout=10000)` for a 10-second
47-
* timeout in milliseconds). When the cache creation call exceeds the timeout, it fails and the
48-
* request proceeds without caching. `null` uses the client's default HTTP options.
45+
* @property createHttpOptions Optional HTTP options for the cache-creation call. Set this to add a
46+
* timeout on `CachedContent.create()` calls (e.g. `HttpOptions(timeout = 10.seconds)`). When the
47+
* cache creation call exceeds the timeout, it fails and the request proceeds without caching.
48+
* `null` uses the model backend's default HTTP options.
4949
*/
5050
data class ContextCacheConfig
5151
@ExperimentalContextCachingFeature

core/src/commonMain/kotlin/com/google/adk/kt/models/GeminiContextCacheManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ import com.google.adk.kt.crypto.sha256Hex
2020
import com.google.adk.kt.logging.LoggerFactory
2121
import com.google.adk.kt.serialization.adkJson
2222
import com.google.adk.kt.types.Content
23+
import com.google.adk.kt.types.HttpOptions
2324
import com.google.adk.kt.types.Role
2425
import com.google.adk.kt.types.Tool
2526
import com.google.adk.kt.types.ToolConfig
26-
import com.google.genai.kotlin.types.HttpOptions
2727
import kotlin.time.Clock
2828
import kotlin.time.Duration
2929
import kotlinx.serialization.json.JsonArray

core/src/commonMain/kotlin/com/google/adk/kt/models/GenaiCacheClient.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal class GenaiCacheClient(private val caches: Caches) :
3737
toolConfig = request.toolConfig?.toGenaiSdk(),
3838
ttl = request.ttl,
3939
displayName = request.displayName,
40-
httpOptions = request.httpOptions,
40+
httpOptions = request.httpOptions?.toGenaiSdk(),
4141
)
4242
val cachedContent = caches.create(request.model, config)
4343
return cachedContent.name ?: throw IllegalStateException("Created cache has no resource name.")

core/src/commonMain/kotlin/com/google/adk/kt/types/GenaiConverters.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import com.google.genai.kotlin.types.GroundingChunkRetrievedContext as GenAiGrou
4646
import com.google.genai.kotlin.types.GroundingChunkWeb as GenAiGroundingChunkWeb
4747
import com.google.genai.kotlin.types.GroundingMetadata as GenAiGroundingMetadata
4848
import com.google.genai.kotlin.types.GroundingSupport as GenAiGroundingSupport
49+
import com.google.genai.kotlin.types.HttpOptions as GenAiHttpOptions
4950
import com.google.genai.kotlin.types.LogprobsResult as GenAiLogprobsResult
5051
import com.google.genai.kotlin.types.LogprobsResultCandidate as GenAiLogprobsResultCandidate
5152
import com.google.genai.kotlin.types.LogprobsResultTopCandidates as GenAiLogprobsResultTopCandidates
@@ -881,3 +882,13 @@ internal fun ThinkingConfig.toGenaiSdk(): GenAiThinkingConfig =
881882
thinkingBudget = thinkingBudget,
882883
thinkingLevel = thinkingLevel?.toGenaiSdk(),
883884
)
885+
886+
// --- HttpOptions ---
887+
/** Converts an ADK [HttpOptions] to a [GenAiHttpOptions] for the GenAI SDK. */
888+
internal fun HttpOptions.toGenaiSdk(): GenAiHttpOptions =
889+
GenAiHttpOptions(
890+
baseUrl = baseUrl,
891+
apiVersion = apiVersion,
892+
headers = headers,
893+
timeout = timeout?.inWholeMilliseconds?.toInt(),
894+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.adk.kt.types
17+
18+
import kotlin.time.Duration
19+
20+
/**
21+
* ADK-owned HTTP transport options for calls a [com.google.adk.kt.models.Model] makes to its
22+
* backend.
23+
*
24+
* This is ADK's own type rather than the backend SDK's, so that configuration surfaces such as
25+
* [com.google.adk.kt.agents.ContextCacheConfig] stay independent of any particular backend.
26+
* Implementations translate it to whatever their transport expects.
27+
*
28+
* @property baseUrl Base URL of the service endpoint. `null` uses the backend's default.
29+
* @property apiVersion Version of the API to use. `null` uses the backend's default.
30+
* @property headers Additional HTTP headers to send with the request.
31+
* @property timeout Request timeout, e.g. `10.seconds`. `null` uses the backend's default.
32+
*/
33+
data class HttpOptions(
34+
val baseUrl: String? = null,
35+
val apiVersion: String? = null,
36+
val headers: Map<String, String>? = null,
37+
val timeout: Duration? = null,
38+
)

core/src/commonTest/kotlin/com/google/adk/kt/agents/ContextCacheConfigTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
package com.google.adk.kt.agents
2020

21-
import com.google.genai.kotlin.types.HttpOptions
21+
import com.google.adk.kt.types.HttpOptions
2222
import kotlin.test.Test
2323
import kotlin.test.assertEquals
2424
import kotlin.test.assertFailsWith
@@ -49,7 +49,7 @@ class ContextCacheConfigTest {
4949

5050
@Test
5151
fun construct_customValues_exposesProperties() {
52-
val httpOptions = HttpOptions(timeout = 10_000)
52+
val httpOptions = HttpOptions(timeout = 10.seconds)
5353
val config =
5454
ContextCacheConfig(
5555
cacheIntervals = 5,

core/src/commonTest/kotlin/com/google/adk/kt/models/GeminiContextCacheManagerTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ import com.google.adk.kt.agents.ContextCacheConfig
2121
import com.google.adk.kt.types.Content
2222
import com.google.adk.kt.types.FunctionCall
2323
import com.google.adk.kt.types.GenerateContentConfig
24+
import com.google.adk.kt.types.HttpOptions
2425
import com.google.adk.kt.types.Part
2526
import com.google.adk.kt.types.Role
2627
import com.google.adk.kt.types.ToolConfig
27-
import com.google.genai.kotlin.types.HttpOptions
2828
import kotlin.test.Test
2929
import kotlin.test.assertEquals
3030
import kotlin.test.assertNull
3131
import kotlin.time.Clock
32+
import kotlin.time.Duration.Companion.seconds
3233
import kotlinx.coroutines.test.runTest
3334

3435
class GeminiContextCacheManagerTest {
@@ -202,7 +203,7 @@ class GeminiContextCacheManagerTest {
202203
fun handleContextCaching_createHttpOptionsConfigured_passedThroughToCreate() = runTest {
203204
val fake = FakeCacheClient(createdName = "cache/recreated")
204205
val manager = GeminiContextCacheManager("gemini-2.0-flash", fake)
205-
val httpOptions = HttpOptions(timeout = 5_000)
206+
val httpOptions = HttpOptions(timeout = 5.seconds)
206207
val request =
207208
baseRequest(tokenCount = 8000)
208209
.copy(cacheConfig = ContextCacheConfig(createHttpOptions = httpOptions))

examples/src/main/kotlin/com/google/adk/kt/examples/caching/ContextCachingDemoAgent.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import com.google.adk.kt.models.CacheMetadata
2727
import com.google.adk.kt.models.Gemini
2828
import com.google.adk.kt.runners.InMemoryRunner
2929
import com.google.adk.kt.types.Content
30+
import com.google.adk.kt.types.HttpOptions
3031
import com.google.adk.kt.types.Role
31-
import com.google.genai.kotlin.types.HttpOptions
3232
import kotlin.time.Duration.Companion.seconds
3333
import kotlinx.coroutines.delay
3434
import kotlinx.coroutines.runBlocking
@@ -189,7 +189,7 @@ fun main() = runBlocking {
189189
minTokens = 0,
190190
// Fail open if cache creation is slow: cap it at 30s, after which the request proceeds
191191
// uncached instead of blocking on cache creation.
192-
createHttpOptions = HttpOptions(timeout = 30_000),
192+
createHttpOptions = HttpOptions(timeout = 30.seconds),
193193
),
194194
)
195195
val runner = InMemoryRunner(app = app)

0 commit comments

Comments
 (0)