Skip to content

Commit b8900f1

Browse files
committed
Remove unused functions from schemaCompressor.ts
- Removed TOKENS_PER_CHARACTER constant (unused) - Removed SchemaCompressionResult interface (only used by removed functions) - Removed estimateTokens() function (only used internally by removed functions) - Removed compressSchemaWithMetrics() function (only used in tests) - Removed compressToolSchemas() function (only used in tests) - Updated test file to remove corresponding test blocks and imports - Reduced file from 248 to ~150 lines, removing ~100 lines of unused code - Core functionality preserved: jsonSchemaToXml, escapeXml, getCompactType remain - All tests passing
1 parent 565d2e6 commit b8900f1

File tree

2 files changed

+1
-233
lines changed

2 files changed

+1
-233
lines changed

src/core/prompts/utils/__tests__/schemaCompressor.spec.ts

Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// npx vitest core/prompts/utils/__tests__/schemaCompressor.spec.ts
22

33
import { describe, it, expect } from "vitest"
4-
import { jsonSchemaToXml, compressSchemaWithMetrics, compressToolSchemas } from "../schemaCompressor"
4+
import { jsonSchemaToXml } from "../schemaCompressor"
55

66
describe("schemaCompressor", () => {
77
describe("jsonSchemaToXml", () => {
@@ -317,133 +317,6 @@ describe("schemaCompressor", () => {
317317
})
318318
})
319319

320-
describe("compressSchemaWithMetrics", () => {
321-
it("should calculate compression metrics", () => {
322-
const schema = {
323-
type: "object",
324-
properties: {
325-
query: {
326-
type: "string",
327-
description: "The natural language question to answer using web search.",
328-
},
329-
},
330-
required: ["query"],
331-
}
332-
333-
const result = compressSchemaWithMetrics(schema)
334-
335-
expect(result.compressed).toBe("<schema>query*:string</schema>")
336-
expect(result.originalTokens).toBeGreaterThan(result.compressedTokens)
337-
expect(result.reduction).toBeGreaterThan(50) // Should be significant reduction
338-
})
339-
340-
it("should handle null/undefined schemas", () => {
341-
const resultNull = compressSchemaWithMetrics(null)
342-
const resultUndefined = compressSchemaWithMetrics(undefined)
343-
344-
expect(resultNull.compressed).toBe("<schema></schema>")
345-
expect(resultUndefined.compressed).toBe("<schema></schema>")
346-
expect(resultNull.reduction).toBe(0)
347-
expect(resultUndefined.reduction).toBe(0)
348-
})
349-
350-
it("should provide accurate token estimation for various text lengths", () => {
351-
const shortSchema = { type: "string" }
352-
const mediumSchema = {
353-
type: "object",
354-
properties: {
355-
field1: { type: "string" },
356-
field2: { type: "number" },
357-
},
358-
}
359-
const longSchema = {
360-
type: "object",
361-
properties: {
362-
field1: { type: "string", description: "A very long description that adds many tokens" },
363-
field2: { type: "array", items: { type: "object", properties: { nested: { type: "boolean" } } } },
364-
field3: { type: "string", enum: ["option1", "option2", "option3", "option4"] },
365-
},
366-
}
367-
368-
const shortResult = compressSchemaWithMetrics(shortSchema)
369-
const mediumResult = compressSchemaWithMetrics(mediumSchema)
370-
const longResult = compressSchemaWithMetrics(longSchema)
371-
372-
// Token counts should increase with complexity
373-
expect(shortResult.originalTokens).toBeLessThan(mediumResult.originalTokens)
374-
expect(mediumResult.originalTokens).toBeLessThan(longResult.originalTokens)
375-
376-
// All should show reduction
377-
expect(shortResult.reduction).toBeGreaterThan(0)
378-
expect(mediumResult.reduction).toBeGreaterThan(0)
379-
expect(longResult.reduction).toBeGreaterThan(0)
380-
})
381-
})
382-
383-
describe("compressToolSchemas", () => {
384-
it("should compress multiple tools and calculate total metrics", () => {
385-
const tools = [
386-
{
387-
name: "search",
388-
inputSchema: {
389-
type: "object" as const,
390-
properties: {
391-
query: { type: "string" as const },
392-
},
393-
required: ["query"],
394-
},
395-
},
396-
{
397-
name: "translate",
398-
inputSchema: {
399-
type: "object" as const,
400-
properties: {
401-
text: { type: "string" as const },
402-
target_lang: { type: "string" as const },
403-
source_lang: { type: "string" as const },
404-
},
405-
required: ["text", "target_lang"],
406-
},
407-
},
408-
]
409-
410-
const result = compressToolSchemas(tools as Array<{ name: string; inputSchema?: any }>)
411-
412-
expect(result.compressedTools).toHaveLength(2)
413-
expect(result.compressedTools[0].compressedSchema).toBe("<schema>query*:string</schema>")
414-
expect(result.compressedTools[1].compressedSchema).toBe(
415-
"<schema>text*:string, target_lang*:string, source_lang?:string</schema>",
416-
)
417-
expect(result.totalReduction).toBeGreaterThan(0)
418-
expect(result.originalTokens).toBeGreaterThan(result.compressedTokens)
419-
})
420-
421-
it("should handle tools without schemas", () => {
422-
const tools = [
423-
{ name: "tool1", inputSchema: undefined },
424-
{ name: "tool2" },
425-
{ name: "tool3", inputSchema: null },
426-
]
427-
428-
const result = compressToolSchemas(tools as Array<{ name: string; inputSchema?: any }>)
429-
430-
expect(result.compressedTools).toHaveLength(3)
431-
result.compressedTools.forEach((tool) => {
432-
expect(tool.compressedSchema).toBe("<schema></schema>")
433-
})
434-
expect(result.totalReduction).toBe(0)
435-
})
436-
437-
it("should handle empty tools array", () => {
438-
const result = compressToolSchemas([])
439-
440-
expect(result.compressedTools).toHaveLength(0)
441-
expect(result.totalReduction).toBe(0)
442-
expect(result.originalTokens).toBe(0)
443-
expect(result.compressedTokens).toBe(0)
444-
})
445-
})
446-
447320
describe("real MCP server examples", () => {
448321
it("should compress google-ai-search-mcp tool schema", () => {
449322
const schema = {

src/core/prompts/utils/schemaCompressor.ts

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Constants for better maintainability
22
const ENUM_DISPLAY_THRESHOLD = 3
3-
const TOKENS_PER_CHARACTER = 4
43

54
// JSON Schema type definitions
65
interface JsonSchemaProperty {
@@ -21,13 +20,6 @@ interface JsonSchema {
2120
items?: JsonSchemaProperty
2221
}
2322

24-
export interface SchemaCompressionResult {
25-
compressed: string
26-
originalTokens: number
27-
compressedTokens: number
28-
reduction: number
29-
}
30-
3123
/**
3224
* Escapes special XML characters to prevent XSS vulnerabilities
3325
* @param text - The text to escape
@@ -148,100 +140,3 @@ function getCompactType(prop: JsonSchemaProperty | null | undefined): string {
148140
return prop.type || "any"
149141
}
150142
}
151-
152-
/**
153-
* Estimates the number of tokens in a text string
154-
* Uses a more sophisticated algorithm based on common tokenization patterns
155-
* @param text - The text to estimate tokens for
156-
* @returns The estimated number of tokens
157-
*/
158-
function estimateTokens(text: string): number {
159-
// Handle null/undefined/empty strings
160-
if (!text) {
161-
return 0
162-
}
163-
164-
// More accurate token estimation based on:
165-
// - Average English word length is ~4.7 characters
166-
// - Punctuation and whitespace add overhead
167-
// - JSON structure adds additional tokens
168-
169-
// Count words (rough approximation)
170-
const words = text.split(/\s+/).filter((w) => w.length > 0).length
171-
172-
// Count special JSON characters that typically become separate tokens
173-
const jsonTokens = (text.match(/[{}[\],:]/g) || []).length
174-
175-
// Estimate based on character count for very short strings
176-
if (text.length < 20) {
177-
return Math.ceil(text.length / 3)
178-
}
179-
180-
// Combined estimation
181-
return Math.ceil(words * 1.3 + jsonTokens * 0.5)
182-
}
183-
184-
/**
185-
* Compresses a JSON Schema and provides metrics about the compression
186-
* @param schema - The JSON Schema to compress
187-
* @returns Compression result with metrics
188-
*/
189-
export function compressSchemaWithMetrics(schema: JsonSchema | null | undefined): SchemaCompressionResult {
190-
const originalJson = JSON.stringify(schema, null, 2)
191-
const compressed = jsonSchemaToXml(schema)
192-
193-
const originalTokens = estimateTokens(originalJson)
194-
const compressedTokens = estimateTokens(compressed)
195-
196-
// Calculate reduction, ensuring it's never negative
197-
let reduction = 0
198-
if (originalTokens > 0 && compressedTokens < originalTokens) {
199-
reduction = ((originalTokens - compressedTokens) / originalTokens) * 100
200-
}
201-
202-
return {
203-
compressed,
204-
originalTokens,
205-
compressedTokens,
206-
reduction: Math.round(reduction),
207-
}
208-
}
209-
210-
/**
211-
* Compresses multiple tool schemas and calculates aggregate metrics
212-
* @param tools - Array of tools with optional input schemas
213-
* @returns Compressed tools with total reduction metrics
214-
*/
215-
export function compressToolSchemas(tools: Array<{ name: string; inputSchema?: JsonSchema }>): {
216-
compressedTools: Array<{ name: string; compressedSchema: string }>
217-
totalReduction: number
218-
originalTokens: number
219-
compressedTokens: number
220-
} {
221-
let totalOriginalTokens = 0
222-
let totalCompressedTokens = 0
223-
224-
const compressedTools = tools.map((tool) => {
225-
const result = compressSchemaWithMetrics(tool.inputSchema)
226-
totalOriginalTokens += result.originalTokens
227-
totalCompressedTokens += result.compressedTokens
228-
229-
return {
230-
name: tool.name,
231-
compressedSchema: result.compressed,
232-
}
233-
})
234-
235-
// Calculate total reduction, ensuring it's never negative
236-
let totalReduction = 0
237-
if (totalOriginalTokens > 0 && totalCompressedTokens < totalOriginalTokens) {
238-
totalReduction = Math.round(((totalOriginalTokens - totalCompressedTokens) / totalOriginalTokens) * 100)
239-
}
240-
241-
return {
242-
compressedTools,
243-
totalReduction,
244-
originalTokens: totalOriginalTokens,
245-
compressedTokens: totalCompressedTokens,
246-
}
247-
}

0 commit comments

Comments
 (0)