Skip to content

Commit 330c278

Browse files
committed
improvement(copilot): hold the in-band turn context in an lru-cache
1 parent c3d66f0 commit 330c278

1 file changed

Lines changed: 9 additions & 29 deletions

File tree

  • apps/sim/app/api/copilot/tools/execute

‎apps/sim/app/api/copilot/tools/execute/route.ts‎

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createLogger } from '@sim/logger'
22
import { getErrorMessage } from '@sim/utils/errors'
3+
import { LRUCache } from 'lru-cache'
34
import { type NextRequest, NextResponse } from 'next/server'
45
import { copilotToolExecuteInternalBodySchema } from '@/lib/api/contracts/copilot'
56
import { validationErrorResponse } from '@/lib/api/server'
@@ -33,21 +34,15 @@ const logger = createLogger('CopilotToolExecuteInternalAPI')
3334
* provenance activated by one tool call must stay visible to the next call's
3435
* egress projection, exactly as the request-lifecycle registry accumulates
3536
* across a turn. Keyed by the turn (messageId) so one background lane shares
36-
* one registry; TTL-evicted since nothing signals turn end on this route.
37+
* one registry; idle-evicted since nothing signals turn end on this route.
3738
*
3839
* The turn's secret authority, which Go's body cannot carry, is cached beside it
3940
* (see {@link getRunSecretAuthority}).
4041
*/
41-
const TURN_REGISTRY_TTL_MS = 10 * 60 * 1000
42-
const TURN_REGISTRY_CACHE_MAX = 256
43-
const turnRegistryCache = new Map<
42+
const turnContextCache = new LRUCache<
4443
string,
45-
{
46-
registry: ResolvedSecretTraceRegistry
47-
secretAuthority: TurnSecretAuthority
48-
expiresAt: number
49-
}
50-
>()
44+
{ registry: ResolvedSecretTraceRegistry; secretAuthority: TurnSecretAuthority }
45+
>({ max: 256, ttl: 10 * 60 * 1000, updateAgeOnGet: true })
5146

5247
async function getTurnToolContext(
5348
userId: string,
@@ -58,12 +53,8 @@ async function getTurnToolContext(
5853
organizationId?: string
5954
): Promise<{ registry: ResolvedSecretTraceRegistry; secretAuthority: TurnSecretAuthority }> {
6055
const key = `${userId}\u0000${workspaceId ?? ''}\u0000${organizationId ?? ''}\u0000${chatId ?? ''}\u0000${messageId ?? ''}\u0000${requestMode ?? ''}`
61-
const now = Date.now()
62-
const hit = turnRegistryCache.get(key)
63-
if (hit && hit.expiresAt > now) {
64-
hit.expiresAt = now + TURN_REGISTRY_TTL_MS
65-
return hit
66-
}
56+
const hit = turnContextCache.get(key)
57+
if (hit) return hit
6758
const [environmentContext, secretAuthority] = await Promise.all([
6859
prepareCopilotEnvironmentContext(userId, workspaceId, {
6960
includeSecrets: requestMode !== 'assistant',
@@ -72,19 +63,8 @@ async function getTurnToolContext(
7263
? getRunSecretAuthority({ streamId: messageId, userId, chatId })
7364
: NO_SECRET_AUTHORITY,
7465
])
75-
for (const [cachedKey, cached] of turnRegistryCache) {
76-
if (cached.expiresAt <= now) turnRegistryCache.delete(cachedKey)
77-
}
78-
if (turnRegistryCache.size >= TURN_REGISTRY_CACHE_MAX) {
79-
const oldest = turnRegistryCache.keys().next().value
80-
if (oldest !== undefined) turnRegistryCache.delete(oldest)
81-
}
82-
const entry = {
83-
registry: environmentContext.resolvedSecretTraceRegistry,
84-
secretAuthority,
85-
expiresAt: now + TURN_REGISTRY_TTL_MS,
86-
}
87-
turnRegistryCache.set(key, entry)
66+
const entry = { registry: environmentContext.resolvedSecretTraceRegistry, secretAuthority }
67+
turnContextCache.set(key, entry)
8868
return entry
8969
}
9070

0 commit comments

Comments
 (0)