From 789103f398c87c6b55ca9ca30ea0c39dde13cbe6 Mon Sep 17 00:00:00 2001 From: reaatech Date: Mon, 8 Jun 2026 00:13:00 +0000 Subject: [PATCH] fix(tighten-type-usage-replace-lazy-any-unknown-with-true-types): close #5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Changes across 6 files (30 insertions, 8 deletions):** Added `JsonValue` and `ToolDefinition` types to `packages/core/src/types/index.ts`, replacing lazy `unknown` with precise types in all layers — `CacheEntry.response` uses `JsonValue` (the full JSON-serializable type), `CacheOptions.tools` uses `ToolDefinition[]`, and adapter deserializers (`DynamoDBAdapter`, `QdrantAdapter`) were tightened accordingly. The `CacheEngine.set`/`setBatch` signatures and `app.ts` route handler body were also updated. Genuinely dynamic boundaries (`readBody`, `sendJson`, `safeParseJson`, adapter `Record` for SDK interop) were left as `unknown` per the issue's own carve-outs. --- ...lazy-any-unknown-with-true-types-issue5.md | 10 +++++++++ .../adapters/dynamodb/src/DynamoDBAdapter.ts | 3 ++- packages/adapters/qdrant/src/QdrantAdapter.ts | 3 ++- packages/core/src/cache/CacheEngine.ts | 5 +++-- packages/core/src/types/index.ts | 21 +++++++++++++++++-- packages/core/src/utils/hash.ts | 3 ++- packages/server/src/app.ts | 3 ++- 7 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 .changeset/repobot-tighten-type-usage-replace-lazy-any-unknown-with-true-types-issue5.md diff --git a/.changeset/repobot-tighten-type-usage-replace-lazy-any-unknown-with-true-types-issue5.md b/.changeset/repobot-tighten-type-usage-replace-lazy-any-unknown-with-true-types-issue5.md new file mode 100644 index 0000000..a103bf0 --- /dev/null +++ b/.changeset/repobot-tighten-type-usage-replace-lazy-any-unknown-with-true-types-issue5.md @@ -0,0 +1,10 @@ +--- +"@reaatech/llm-cache-adapters-dynamodb": patch +"@reaatech/llm-cache-adapters-qdrant": patch +"@reaatech/llm-cache": patch +"@reaatech/llm-cache-server": patch +--- + +Fix: Tighten type usage: replace lazy any/unknown with true types + +Closes #5 diff --git a/packages/adapters/dynamodb/src/DynamoDBAdapter.ts b/packages/adapters/dynamodb/src/DynamoDBAdapter.ts index 58d0f3d..816a8c5 100644 --- a/packages/adapters/dynamodb/src/DynamoDBAdapter.ts +++ b/packages/adapters/dynamodb/src/DynamoDBAdapter.ts @@ -13,6 +13,7 @@ import type { CacheEntry, HealthStatus, InvalidationCriteria, + JsonValue, StorageAdapter, StorageStats, } from '@reaatech/llm-cache'; @@ -341,7 +342,7 @@ export class DynamoDBAdapter implements StorageAdapter { private deserialize(item: Record): CacheEntry { const metadata = item.metadata as Record; - let response: unknown = null; + let response: JsonValue = null; try { response = JSON.parse(String(item.response ?? 'null')); } catch { diff --git a/packages/adapters/qdrant/src/QdrantAdapter.ts b/packages/adapters/qdrant/src/QdrantAdapter.ts index bb2c3f5..dca8627 100644 --- a/packages/adapters/qdrant/src/QdrantAdapter.ts +++ b/packages/adapters/qdrant/src/QdrantAdapter.ts @@ -3,6 +3,7 @@ import type { CacheEntry, HealthStatus, InvalidationCriteria, + JsonValue, SimilarityResult, StorageStats, VectorSearchFilters, @@ -375,7 +376,7 @@ export class QdrantAdapter implements VectorStorageAdapter { private deserializeEntry(payload: Record, vector: number[]): CacheEntry { const metadata = payload.metadata as Record; - let response: unknown = null; + let response: JsonValue = null; try { response = JSON.parse(String(payload.response)); } catch { diff --git a/packages/core/src/cache/CacheEngine.ts b/packages/core/src/cache/CacheEngine.ts index 8df9fcf..5b67cc0 100644 --- a/packages/core/src/cache/CacheEngine.ts +++ b/packages/core/src/cache/CacheEngine.ts @@ -9,6 +9,7 @@ import type { CacheResult, CostCalculatorLike, InvalidateResult, + JsonValue, VectorSearchFilters, } from '../types/index.js'; import type { EncryptedPayload, EncryptionService } from '../utils/encryption.js'; @@ -142,7 +143,7 @@ export class CacheEngine { async set( prompt: string, - response: unknown, + response: JsonValue, options?: CacheOptions, metadata?: CacheMetadata, ): Promise { @@ -218,7 +219,7 @@ export class CacheEngine { async setBatch( items: Array<{ prompt: string; - response: unknown; + response: JsonValue; options?: CacheOptions; metadata?: CacheMetadata; }>, diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index 20de575..a6b5404 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -1,8 +1,25 @@ +export type JsonValue = + | string + | number + | boolean + | null + | JsonValue[] + | { [key: string]: JsonValue }; + +export interface ToolDefinition { + type?: string; + function: { + name: string; + description?: string; + parameters: Record; + }; +} + export interface CacheEntry { id: string; prompt: string; promptHash: string; - response: unknown; + response: JsonValue; embedding: number[]; model: string; modelVersion: string; @@ -56,7 +73,7 @@ export interface CacheOptions { topP?: number; maxTokens?: number; systemPrompt?: string; - tools?: unknown[]; + tools?: ToolDefinition[]; responseFormat?: 'text' | 'json_object' | 'json_schema'; } diff --git a/packages/core/src/utils/hash.ts b/packages/core/src/utils/hash.ts index 5733dac..b5ee084 100644 --- a/packages/core/src/utils/hash.ts +++ b/packages/core/src/utils/hash.ts @@ -1,4 +1,5 @@ import { createHash } from 'node:crypto'; +import type { ToolDefinition } from '../types/index.js'; export function sha256(input: string): string { return createHash('sha256').update(input).digest('hex'); @@ -31,7 +32,7 @@ export function buildCacheFingerprint(options: { topP?: number; maxTokens?: number; systemPrompt?: string; - tools?: unknown[]; + tools?: ToolDefinition[]; responseFormat?: string; }): string { const canonical = JSON.stringify({ diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index f183f81..ef12d92 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -6,6 +6,7 @@ import { type CacheOptions, type EmbeddingProvider, InMemoryAdapter, + type JsonValue, OpenAIEmbedder, } from '@reaatech/llm-cache'; import { DynamoDBAdapter } from '@reaatech/llm-cache-adapters-dynamodb'; @@ -255,7 +256,7 @@ export async function createApp(): Promise { if (url.pathname === '/cache/set' && req.method === 'POST') { const body = (await readBody(req)) as { prompt: string; - response: unknown; + response: JsonValue; options?: CacheOptions; metadata?: { queryType?: 'factual' | 'creative' | 'analytical';