Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/tools/advanced-caching/cache-compression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ export class CacheCompressionTool {
timestamp: Date.now(),
};

const metadataBuffer = JSON.stringify(metadata);
const metadataBuffer = Buffer.from(JSON.stringify(metadata), 'utf-8');
const metadataLength = Buffer.allocUnsafe(4);
metadataLength.writeUInt32LE(metadataBuffer.length, 0);

Expand Down Expand Up @@ -1011,7 +1011,7 @@ export class CacheCompressionTool {
// Replace repeated strings with dictionary references
const compressed = this.compressWithDictionary(obj, dict);

return JSON.stringify(compressed);
return Buffer.from(JSON.stringify(compressed), 'utf-8');
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Multiple instances of Buffer.from(JSON.stringify(...), 'utf-8') suggest a helper function could reduce duplication and make the code more maintainable. Consider extracting this pattern into a utility function like jsonToBuffer(obj: any): Buffer.

Copilot uses AI. Check for mistakes.
} catch {
// Not JSON, just use gzip
return Buffer.from(str);
Expand All @@ -1032,7 +1032,7 @@ export class CacheCompressionTool {
compressed.data,
dict,
);
return JSON.stringify(decompressed);
return Buffer.from(JSON.stringify(decompressed), 'utf-8');
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Multiple instances of Buffer.from(JSON.stringify(...), 'utf-8') suggest a helper function could reduce duplication and make the code more maintainable. Consider extracting this pattern into a utility function like jsonToBuffer(obj: any): Buffer.

Copilot uses AI. Check for mistakes.
}

return data;
Expand Down Expand Up @@ -1272,7 +1272,7 @@ export class CacheCompressionTool {
} else if (typeof data === "string") {
return Buffer.from(data, "utf-8");
} else {
return JSON.stringify(data);
return Buffer.from(JSON.stringify(data), 'utf-8');
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Multiple instances of Buffer.from(JSON.stringify(...), 'utf-8') suggest a helper function could reduce duplication and make the code more maintainable. Consider extracting this pattern into a utility function like jsonToBuffer(obj: any): Buffer.

Copilot uses AI. Check for mistakes.
}
}

Expand All @@ -1292,7 +1292,7 @@ export class CacheCompressionTool {
active: i % 2 === 0,
})),
};
return JSON.stringify(obj);
return Buffer.from(JSON.stringify(obj), 'utf-8');
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Multiple instances of Buffer.from(JSON.stringify(...), 'utf-8') suggest a helper function could reduce duplication and make the code more maintainable. Consider extracting this pattern into a utility function like jsonToBuffer(obj: any): Buffer.

Copilot uses AI. Check for mistakes.
}

case "text": {
Expand Down
30 changes: 15 additions & 15 deletions src/tools/api-database/smart-cache-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ export class SmartCacheAPI {
}

const cacheKey = this.generateCacheKey(options.request, options);
const cachedBuffer = this.cache.get(cacheKey);
const cached = cachedBuffer
? this.deserializeCachedResponse(cachedBuffer)
const cachedString = this.cache.get(cacheKey);
const cached = cachedString
? this.deserializeCachedResponse(Buffer.from(cachedString, 'utf-8'))
: null;

// Update stats
Expand Down Expand Up @@ -379,9 +379,9 @@ export class SmartCacheAPI {

for (const key of allKeys) {
if (regex.test(key)) {
const cachedBuffer = this.cache.get(key);
const cached = cachedBuffer
? this.deserializeCachedResponse(cachedBuffer)
const cachedString = this.cache.get(key);
const cached = cachedString
? this.deserializeCachedResponse(Buffer.from(cachedString, 'utf-8'))
: null;
if (cached) {
totalSize += cached.size;
Expand All @@ -402,9 +402,9 @@ export class SmartCacheAPI {
const allKeysForTags = this.getAllCacheKeys();

for (const key of allKeysForTags) {
const cachedBuffer = this.cache.get(key);
const cached = cachedBuffer
? this.deserializeCachedResponse(cachedBuffer)
const cachedString = this.cache.get(key);
const cached = cachedString
? this.deserializeCachedResponse(Buffer.from(cachedString, 'utf-8'))
: null;
if (cached && cached.tags) {
const hasMatchingTag = cached.tags.some((tag: string) =>
Expand All @@ -422,9 +422,9 @@ export class SmartCacheAPI {
case "manual":
if (options.request) {
const cacheKey = this.generateCacheKey(options.request, options);
const cachedBuffer = this.cache.get(cacheKey);
const cached = cachedBuffer
? this.deserializeCachedResponse(cachedBuffer)
const cachedString = this.cache.get(cacheKey);
const cached = cachedString
? this.deserializeCachedResponse(Buffer.from(cachedString, 'utf-8'))
: null;
if (cached) {
totalSize += cached.size;
Expand All @@ -440,9 +440,9 @@ export class SmartCacheAPI {
const now = Date.now();

for (const key of allKeysForTime) {
const cachedBuffer = this.cache.get(key);
const cached = cachedBuffer
? this.deserializeCachedResponse(cachedBuffer)
const cachedString = this.cache.get(key);
const cached = cachedString
? this.deserializeCachedResponse(Buffer.from(cachedString, 'utf-8'))
: null;
if (cached) {
const age = Math.floor((now - cached.timestamp) / 1000);
Expand Down
194 changes: 194 additions & 0 deletions src/tools/api-database/smart-migration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/**
* Unit Tests for Smart Migration Tool
* Testing import corrections and core functionality
*/

import { describe, it, expect, beforeEach } from '@jest/globals';
import { SmartMigration, getSmartMigration, runSmartMigration } from './smart-migration';
import { CacheEngine } from '../../core/cache-engine';
import { TokenCounter } from '../../core/token-counter';
import { MetricsCollector } from '../../core/metrics';
import { tmpdir } from 'os';
import { join } from 'path';

describe('Smart Migration - Import Type Corrections', () => {
let cacheEngine: CacheEngine;
let tokenCounter: TokenCounter;
let metricsCollector: MetricsCollector;
let smartMigration: SmartMigration;

beforeEach(() => {
// Initialize dependencies - verifying that imports work as values
cacheEngine = new CacheEngine(join(tmpdir(), '.test-cache', 'test.db'), 100);
tokenCounter = new TokenCounter();
metricsCollector = new MetricsCollector();
smartMigration = new SmartMigration(cacheEngine, tokenCounter, metricsCollector);
});

describe('Class Instantiation', () => {
it('should instantiate SmartMigration with TokenCounter as value', () => {
expect(smartMigration).toBeInstanceOf(SmartMigration);
expect(tokenCounter).toBeInstanceOf(TokenCounter);
});

it('should instantiate SmartMigration with MetricsCollector as value', () => {
expect(metricsCollector).toBeInstanceOf(MetricsCollector);
});

it('should instantiate SmartMigration with CacheEngine as value', () => {
expect(cacheEngine).toBeInstanceOf(CacheEngine);
});
});

describe('Factory Function', () => {
it('should create SmartMigration instance via factory function', () => {
const instance = getSmartMigration(cacheEngine, tokenCounter, metricsCollector);
expect(instance).toBeInstanceOf(SmartMigration);
});
});

describe('Migration List Action', () => {
it('should list migrations', async () => {
const result = await smartMigration.run({ action: 'list', limit: 5 });

expect(result).toBeDefined();
expect(result.result).toBeDefined();
expect(result.tokens).toBeDefined();
expect(result.tokens.baseline).toBeGreaterThan(0);
expect(result.tokens.actual).toBeGreaterThan(0);
});

it('should return token reduction metrics', async () => {
const result = await smartMigration.run({ action: 'list' });

expect(result.tokens.reduction).toBeGreaterThanOrEqual(0);
expect(result.tokens.saved).toBeGreaterThanOrEqual(0);
});
});

describe('Migration Status Action', () => {
it('should return migration status summary', async () => {
const result = await smartMigration.run({ action: 'status' });

expect(result).toBeDefined();
expect(result.result).toContain('Status');
expect(result.cached).toBe(false);
});
});

describe('Migration History Action', () => {
it('should return migration history', async () => {
const result = await smartMigration.run({ action: 'history', limit: 10 });

expect(result).toBeDefined();
expect(result.result).toBeDefined();
expect(result.executionTime).toBeGreaterThanOrEqual(0);
});
});

describe('Generate Migration Action', () => {
it('should generate migration file', async () => {
const result = await smartMigration.run({
action: 'generate',
migrationId: 'test_migration'
});

expect(result).toBeDefined();
expect(result.result).toContain('test_migration');
});
});

describe('Rollback Migration Action', () => {
it('should rollback migration', async () => {
const result = await smartMigration.run({
action: 'rollback',
migrationId: 'test_rollback',
direction: 'down'
});

expect(result).toBeDefined();
expect(result.result).toContain('Rollback');
});
});

describe('Caching Behavior', () => {
it('should cache read-only operations', async () => {
const result1 = await smartMigration.run({ action: 'list' });
const result2 = await smartMigration.run({ action: 'list' });

expect(result1).toBeDefined();
expect(result2).toBeDefined();
// Second call may be cached (implementation-dependent)
});

it('should respect force flag to bypass cache', async () => {
const result1 = await smartMigration.run({ action: 'list', force: false });
const result2 = await smartMigration.run({ action: 'list', force: true });

expect(result1).toBeDefined();
expect(result2).toBeDefined();
expect(result2.cached).toBe(false);
});
});

describe('Error Handling', () => {
it('should throw error for invalid action', async () => {
await expect(
smartMigration.run({ action: 'invalid' as any })
).rejects.toThrow();
});

it('should throw error when migrationId missing for rollback', async () => {
await expect(
smartMigration.run({ action: 'rollback' })
).rejects.toThrow('migrationId is required');
});

it('should throw error when migrationId missing for generate', async () => {
await expect(
smartMigration.run({ action: 'generate' })
).rejects.toThrow('migrationId is required');
});
});

describe('CLI Function', () => {
it('should run migration via CLI function', async () => {
const result = await runSmartMigration({ action: 'status' });

expect(result).toBeDefined();
expect(typeof result).toBe('string');
expect(result).toContain('Status');
});
});
});

describe('Import Type Verification', () => {
it('should verify TokenCounter can be instantiated', () => {
const counter = new TokenCounter();
expect(counter).toBeInstanceOf(TokenCounter);

const result = counter.count('test string');
expect(result).toBeDefined();
expect(result.tokens).toBeGreaterThan(0);
});

it('should verify MetricsCollector can be instantiated', () => {
const metrics = new MetricsCollector();
expect(metrics).toBeInstanceOf(MetricsCollector);

metrics.record({
operation: 'test',
duration: 100,
success: true,
cacheHit: false,
inputTokens: 10,
outputTokens: 5,
savedTokens: 0
});
});

it('should verify CacheEngine can be instantiated', () => {
const cache = new CacheEngine(join(tmpdir(), '.test-cache-verify', 'test.db'), 100);
expect(cache).toBeInstanceOf(CacheEngine);
});
});
5 changes: 1 addition & 4 deletions src/tools/api-database/smart-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
*/

import { createHash } from "crypto";
import type { CacheEngine } from "../../core/cache-engine";
import type { TokenCounter } from "../../core/token-counter";
import type { MetricsCollector } from "../../core/metrics";
import { CacheEngine as CacheEngineClass } from "../../core/cache-engine";
import { CacheEngine, CacheEngine as CacheEngineClass } from "../../core/cache-engine";
import { TokenCounter } from "../../core/token-counter";
import { MetricsCollector } from "../../core/metrics";

Expand Down
Loading