Improve agent autonomy and diff view readability
Agent behavior improvements: - Add project context detection (tsconfig.json, pom.xml, etc.) - Enforce validation after changes (tsc --noEmit, mvn compile, etc.) - Run tests automatically - never ask "do you want me to run tests" - Complete full loop: create → type-check → test → confirm - Add command detection for direct execution (run tree, run ls) Diff view improvements: - Use darker backgrounds for added/removed lines - Add diffLineBgAdded, diffLineBgRemoved, diffLineText theme colors - Improve text visibility with white text on dark backgrounds - Update both React/Ink and SolidJS diff components Streaming fixes: - Fix tool call argument accumulation using OpenAI index field - Fix streaming content display after tool calls - Add consecutive error tracking to prevent token waste Other changes: - ESC to abort operations, Ctrl+C to exit - Fix model selection when provider changes in cascade mode - Add debug logging for troubleshooting - Move tests to root tests/ folder - Fix banner test GRADIENT_COLORS reference
This commit is contained in:
@@ -1,231 +0,0 @@
|
||||
/**
|
||||
* Unit tests for Vector Store
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "bun:test";
|
||||
|
||||
import {
|
||||
cosineSimilarity,
|
||||
euclideanDistance,
|
||||
upsertEmbedding,
|
||||
removeEmbedding,
|
||||
hasEmbedding,
|
||||
getEmbedding,
|
||||
findSimilar,
|
||||
findAboveThreshold,
|
||||
getIndexStats,
|
||||
} from "@services/learning/vector-store";
|
||||
|
||||
import { createEmptyIndex } from "@/types/embeddings";
|
||||
|
||||
describe("Vector Store", () => {
|
||||
describe("cosineSimilarity", () => {
|
||||
it("should return 1 for identical vectors", () => {
|
||||
const a = [1, 0, 0];
|
||||
const b = [1, 0, 0];
|
||||
|
||||
expect(cosineSimilarity(a, b)).toBeCloseTo(1);
|
||||
});
|
||||
|
||||
it("should return 0 for orthogonal vectors", () => {
|
||||
const a = [1, 0, 0];
|
||||
const b = [0, 1, 0];
|
||||
|
||||
expect(cosineSimilarity(a, b)).toBeCloseTo(0);
|
||||
});
|
||||
|
||||
it("should return -1 for opposite vectors", () => {
|
||||
const a = [1, 0, 0];
|
||||
const b = [-1, 0, 0];
|
||||
|
||||
expect(cosineSimilarity(a, b)).toBeCloseTo(-1);
|
||||
});
|
||||
|
||||
it("should handle normalized vectors", () => {
|
||||
const a = [0.6, 0.8, 0];
|
||||
const b = [0.8, 0.6, 0];
|
||||
|
||||
const similarity = cosineSimilarity(a, b);
|
||||
expect(similarity).toBeGreaterThan(0);
|
||||
expect(similarity).toBeLessThan(1);
|
||||
});
|
||||
|
||||
it("should return 0 for mismatched lengths", () => {
|
||||
const a = [1, 0, 0];
|
||||
const b = [1, 0];
|
||||
|
||||
expect(cosineSimilarity(a, b)).toBe(0);
|
||||
});
|
||||
|
||||
it("should handle zero vectors", () => {
|
||||
const a = [0, 0, 0];
|
||||
const b = [1, 0, 0];
|
||||
|
||||
expect(cosineSimilarity(a, b)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("euclideanDistance", () => {
|
||||
it("should return 0 for identical vectors", () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3];
|
||||
|
||||
expect(euclideanDistance(a, b)).toBe(0);
|
||||
});
|
||||
|
||||
it("should compute correct distance", () => {
|
||||
const a = [0, 0, 0];
|
||||
const b = [3, 4, 0];
|
||||
|
||||
expect(euclideanDistance(a, b)).toBe(5);
|
||||
});
|
||||
|
||||
it("should return Infinity for mismatched lengths", () => {
|
||||
const a = [1, 0, 0];
|
||||
const b = [1, 0];
|
||||
|
||||
expect(euclideanDistance(a, b)).toBe(Infinity);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Index Operations", () => {
|
||||
it("should create empty index", () => {
|
||||
const index = createEmptyIndex("test-model");
|
||||
|
||||
expect(index.version).toBe(1);
|
||||
expect(index.model).toBe("test-model");
|
||||
expect(Object.keys(index.embeddings)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should upsert embedding", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
const embedding = [0.1, 0.2, 0.3];
|
||||
|
||||
index = upsertEmbedding(index, "learn_1", embedding);
|
||||
|
||||
expect(hasEmbedding(index, "learn_1")).toBe(true);
|
||||
expect(getEmbedding(index, "learn_1")?.embedding).toEqual(embedding);
|
||||
});
|
||||
|
||||
it("should update existing embedding", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
const embedding1 = [0.1, 0.2, 0.3];
|
||||
const embedding2 = [0.4, 0.5, 0.6];
|
||||
|
||||
index = upsertEmbedding(index, "learn_1", embedding1);
|
||||
index = upsertEmbedding(index, "learn_1", embedding2);
|
||||
|
||||
expect(getEmbedding(index, "learn_1")?.embedding).toEqual(embedding2);
|
||||
});
|
||||
|
||||
it("should remove embedding", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
index = upsertEmbedding(index, "learn_1", [0.1, 0.2, 0.3]);
|
||||
index = upsertEmbedding(index, "learn_2", [0.4, 0.5, 0.6]);
|
||||
|
||||
index = removeEmbedding(index, "learn_1");
|
||||
|
||||
expect(hasEmbedding(index, "learn_1")).toBe(false);
|
||||
expect(hasEmbedding(index, "learn_2")).toBe(true);
|
||||
});
|
||||
|
||||
it("should return null for missing embedding", () => {
|
||||
const index = createEmptyIndex("test-model");
|
||||
|
||||
expect(getEmbedding(index, "nonexistent")).toBeNull();
|
||||
});
|
||||
|
||||
it("should track index stats", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
index = upsertEmbedding(index, "learn_1", [0.1, 0.2, 0.3]);
|
||||
index = upsertEmbedding(index, "learn_2", [0.4, 0.5, 0.6]);
|
||||
|
||||
const stats = getIndexStats(index);
|
||||
|
||||
expect(stats.count).toBe(2);
|
||||
expect(stats.model).toBe("test-model");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Similarity Search", () => {
|
||||
it("should find similar embeddings", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
|
||||
// Add embeddings with known similarities
|
||||
index = upsertEmbedding(index, "a", [1, 0, 0]);
|
||||
index = upsertEmbedding(index, "b", [0.9, 0.1, 0]);
|
||||
index = upsertEmbedding(index, "c", [0, 1, 0]);
|
||||
|
||||
const query = [1, 0, 0];
|
||||
const results = findSimilar(index, query, 2, 0);
|
||||
|
||||
expect(results).toHaveLength(2);
|
||||
expect(results[0].id).toBe("a");
|
||||
expect(results[0].score).toBeCloseTo(1);
|
||||
expect(results[1].id).toBe("b");
|
||||
});
|
||||
|
||||
it("should respect minSimilarity threshold", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
|
||||
index = upsertEmbedding(index, "a", [1, 0, 0]);
|
||||
index = upsertEmbedding(index, "b", [0, 1, 0]);
|
||||
|
||||
const query = [1, 0, 0];
|
||||
const results = findSimilar(index, query, 10, 0.5);
|
||||
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0].id).toBe("a");
|
||||
});
|
||||
|
||||
it("should limit results to topK", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const embedding = [Math.random(), Math.random(), Math.random()];
|
||||
index = upsertEmbedding(index, `learn_${i}`, embedding);
|
||||
}
|
||||
|
||||
const query = [0.5, 0.5, 0.5];
|
||||
const results = findSimilar(index, query, 3, 0);
|
||||
|
||||
expect(results.length).toBeLessThanOrEqual(3);
|
||||
});
|
||||
|
||||
it("should find all above threshold", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
|
||||
index = upsertEmbedding(index, "a", [1, 0, 0]);
|
||||
index = upsertEmbedding(index, "b", [0.95, 0.05, 0]);
|
||||
index = upsertEmbedding(index, "c", [0.9, 0.1, 0]);
|
||||
index = upsertEmbedding(index, "d", [0, 1, 0]);
|
||||
|
||||
const query = [1, 0, 0];
|
||||
const results = findAboveThreshold(index, query, 0.85);
|
||||
|
||||
expect(results.length).toBe(3);
|
||||
expect(results.map((r) => r.id)).toContain("a");
|
||||
expect(results.map((r) => r.id)).toContain("b");
|
||||
expect(results.map((r) => r.id)).toContain("c");
|
||||
});
|
||||
|
||||
it("should return empty array for no matches", () => {
|
||||
let index = createEmptyIndex("test-model");
|
||||
|
||||
index = upsertEmbedding(index, "a", [1, 0, 0]);
|
||||
|
||||
const query = [-1, 0, 0];
|
||||
const results = findSimilar(index, query, 10, 0.5);
|
||||
|
||||
expect(results).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should handle empty index", () => {
|
||||
const index = createEmptyIndex("test-model");
|
||||
const query = [1, 0, 0];
|
||||
const results = findSimilar(index, query, 10, 0);
|
||||
|
||||
expect(results).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user