mirror of
https://github.com/Egonex-AI/Understand-Anything.git
synced 2026-06-22 10:58:03 +08:00
feat(core): add knowledge graph type system and validation tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@understand-anything/core",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.0",
|
||||
"vitest": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./types.js";
|
||||
@@ -0,0 +1,117 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import type { KnowledgeGraph, GraphNode, GraphEdge } from "./types.js";
|
||||
|
||||
describe("KnowledgeGraph types", () => {
|
||||
it("should create a valid empty KnowledgeGraph", () => {
|
||||
const graph: KnowledgeGraph = {
|
||||
version: "1.0.0",
|
||||
project: {
|
||||
name: "test-project",
|
||||
languages: [],
|
||||
frameworks: [],
|
||||
description: "A test project",
|
||||
analyzedAt: new Date().toISOString(),
|
||||
gitCommitHash: "abc123",
|
||||
},
|
||||
nodes: [],
|
||||
edges: [],
|
||||
layers: [],
|
||||
tour: [],
|
||||
};
|
||||
|
||||
expect(graph.version).toBe("1.0.0");
|
||||
expect(graph.project.name).toBe("test-project");
|
||||
expect(graph.nodes).toHaveLength(0);
|
||||
expect(graph.edges).toHaveLength(0);
|
||||
expect(graph.layers).toHaveLength(0);
|
||||
expect(graph.tour).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should create valid GraphNodes with all fields", () => {
|
||||
const fileNode: GraphNode = {
|
||||
id: "node-1",
|
||||
type: "file",
|
||||
name: "index.ts",
|
||||
filePath: "src/index.ts",
|
||||
lineRange: [1, 50],
|
||||
summary: "Entry point of the application",
|
||||
tags: ["entry", "typescript"],
|
||||
complexity: "simple",
|
||||
languageNotes: "Uses ES module syntax",
|
||||
};
|
||||
|
||||
expect(fileNode.id).toBe("node-1");
|
||||
expect(fileNode.type).toBe("file");
|
||||
expect(fileNode.filePath).toBe("src/index.ts");
|
||||
expect(fileNode.lineRange).toEqual([1, 50]);
|
||||
expect(fileNode.tags).toContain("entry");
|
||||
expect(fileNode.complexity).toBe("simple");
|
||||
|
||||
const functionNode: GraphNode = {
|
||||
id: "node-2",
|
||||
type: "function",
|
||||
name: "processData",
|
||||
filePath: "src/utils.ts",
|
||||
lineRange: [10, 25],
|
||||
summary: "Processes raw data into structured format",
|
||||
tags: ["utility", "data"],
|
||||
complexity: "moderate",
|
||||
};
|
||||
|
||||
expect(functionNode.type).toBe("function");
|
||||
expect(functionNode.complexity).toBe("moderate");
|
||||
expect(functionNode.languageNotes).toBeUndefined();
|
||||
|
||||
const classNode: GraphNode = {
|
||||
id: "node-3",
|
||||
type: "class",
|
||||
name: "DataStore",
|
||||
summary: "Manages application state",
|
||||
tags: ["state", "core"],
|
||||
complexity: "complex",
|
||||
};
|
||||
|
||||
expect(classNode.type).toBe("class");
|
||||
expect(classNode.filePath).toBeUndefined();
|
||||
expect(classNode.lineRange).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should create valid GraphEdges with weight bounds", () => {
|
||||
const edge: GraphEdge = {
|
||||
source: "node-1",
|
||||
target: "node-2",
|
||||
type: "imports",
|
||||
direction: "forward",
|
||||
description: "index.ts imports processData from utils.ts",
|
||||
weight: 0.8,
|
||||
};
|
||||
|
||||
expect(edge.source).toBe("node-1");
|
||||
expect(edge.target).toBe("node-2");
|
||||
expect(edge.type).toBe("imports");
|
||||
expect(edge.direction).toBe("forward");
|
||||
expect(edge.weight).toBeGreaterThanOrEqual(0);
|
||||
expect(edge.weight).toBeLessThanOrEqual(1);
|
||||
|
||||
const minWeightEdge: GraphEdge = {
|
||||
source: "node-1",
|
||||
target: "node-3",
|
||||
type: "related",
|
||||
direction: "bidirectional",
|
||||
weight: 0,
|
||||
};
|
||||
|
||||
expect(minWeightEdge.weight).toBe(0);
|
||||
expect(minWeightEdge.description).toBeUndefined();
|
||||
|
||||
const maxWeightEdge: GraphEdge = {
|
||||
source: "node-2",
|
||||
target: "node-3",
|
||||
type: "calls",
|
||||
direction: "forward",
|
||||
weight: 1,
|
||||
};
|
||||
|
||||
expect(maxWeightEdge.weight).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
// Edge types (17 total in 5 categories: Structural, Behavioral, Data flow, Dependencies, Semantic)
|
||||
export type EdgeType =
|
||||
| "imports" | "exports" | "contains" | "inherits" | "implements" // Structural
|
||||
| "calls" | "subscribes" | "publishes" | "middleware" // Behavioral
|
||||
| "reads_from" | "writes_to" | "transforms" | "validates" // Data flow
|
||||
| "depends_on" | "tested_by" | "configures" // Dependencies
|
||||
| "related" | "similar_to"; // Semantic
|
||||
|
||||
// GraphNode with 5 types: file, function, class, module, concept
|
||||
export interface GraphNode {
|
||||
id: string;
|
||||
type: "file" | "function" | "class" | "module" | "concept";
|
||||
name: string;
|
||||
filePath?: string;
|
||||
lineRange?: [number, number];
|
||||
summary: string;
|
||||
tags: string[];
|
||||
complexity: "simple" | "moderate" | "complex";
|
||||
languageNotes?: string;
|
||||
}
|
||||
|
||||
// GraphEdge with rich relationship modeling
|
||||
export interface GraphEdge {
|
||||
source: string;
|
||||
target: string;
|
||||
type: EdgeType;
|
||||
direction: "forward" | "backward" | "bidirectional";
|
||||
description?: string;
|
||||
weight: number; // 0-1
|
||||
}
|
||||
|
||||
// Layer (logical grouping)
|
||||
export interface Layer {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
nodeIds: string[];
|
||||
}
|
||||
|
||||
// TourStep (for learn mode)
|
||||
export interface TourStep {
|
||||
order: number;
|
||||
title: string;
|
||||
description: string;
|
||||
nodeIds: string[];
|
||||
languageLesson?: string;
|
||||
}
|
||||
|
||||
// ProjectMeta
|
||||
export interface ProjectMeta {
|
||||
name: string;
|
||||
languages: string[];
|
||||
frameworks: string[];
|
||||
description: string;
|
||||
analyzedAt: string;
|
||||
gitCommitHash: string;
|
||||
}
|
||||
|
||||
// Root KnowledgeGraph
|
||||
export interface KnowledgeGraph {
|
||||
version: string;
|
||||
project: ProjectMeta;
|
||||
nodes: GraphNode[];
|
||||
edges: GraphEdge[];
|
||||
layers: Layer[];
|
||||
tour: TourStep[];
|
||||
}
|
||||
|
||||
// AnalysisMeta (for persistence)
|
||||
export interface AnalysisMeta {
|
||||
lastAnalyzedAt: string;
|
||||
gitCommitHash: string;
|
||||
version: string;
|
||||
analyzedFiles: number;
|
||||
}
|
||||
|
||||
// Plugin interfaces
|
||||
export interface StructuralAnalysis {
|
||||
functions: Array<{ name: string; lineRange: [number, number]; params: string[]; returnType?: string }>;
|
||||
classes: Array<{ name: string; lineRange: [number, number]; methods: string[]; properties: string[] }>;
|
||||
imports: Array<{ source: string; specifiers: string[]; lineNumber: number }>;
|
||||
exports: Array<{ name: string; lineNumber: number }>;
|
||||
}
|
||||
|
||||
export interface ImportResolution {
|
||||
source: string;
|
||||
resolvedPath: string;
|
||||
specifiers: string[];
|
||||
}
|
||||
|
||||
export interface CallGraphEntry {
|
||||
caller: string;
|
||||
callee: string;
|
||||
lineNumber: number;
|
||||
}
|
||||
|
||||
export interface AnalyzerPlugin {
|
||||
name: string;
|
||||
languages: string[];
|
||||
analyzeFile(filePath: string, content: string): StructuralAnalysis;
|
||||
resolveImports(filePath: string, content: string): ImportResolution[];
|
||||
extractCallGraph?(filePath: string, content: string): CallGraphEntry[];
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Generated
+9
@@ -15,6 +15,15 @@ importers:
|
||||
specifier: ^3.1.0
|
||||
version: 3.2.4
|
||||
|
||||
packages/core:
|
||||
devDependencies:
|
||||
typescript:
|
||||
specifier: ^5.7.0
|
||||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.1.0
|
||||
version: 3.2.4
|
||||
|
||||
packages:
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.4':
|
||||
|
||||
Reference in New Issue
Block a user