mirror of
https://github.com/Egonex-AI/Understand-Anything.git
synced 2026-06-22 10:58:03 +08:00
feat(core): extend GraphNode/EdgeType/StructuralAnalysis for non-code file types
Add 8 new node types (config, document, service, table, endpoint, pipeline, schema, resource) and 8 new edge types (deploys, serves, migrates, documents, provisions, routes, defines_schema, triggers). Add StructuralAnalysis sub-interfaces: SectionInfo, DefinitionInfo, ServiceInfo, EndpointInfo, StepInfo, ResourceInfo, ReferenceResolution. Make resolveImports optional on AnalyzerPlugin and add extractReferences. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import type { KnowledgeGraph, GraphNode, GraphEdge } from "./types.js";
|
||||
import type { KnowledgeGraph, GraphNode, GraphEdge, EdgeType, StructuralAnalysis, AnalyzerPlugin, ReferenceResolution } from "./types.js";
|
||||
|
||||
describe("KnowledgeGraph types", () => {
|
||||
it("should create a valid empty KnowledgeGraph", () => {
|
||||
@@ -115,3 +115,78 @@ describe("KnowledgeGraph types", () => {
|
||||
expect(maxWeightEdge.weight).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Extended types", () => {
|
||||
it("accepts all 13 node types", () => {
|
||||
const nodeTypes: GraphNode["type"][] = [
|
||||
"file", "function", "class", "module", "concept",
|
||||
"config", "document", "service", "table", "endpoint",
|
||||
"pipeline", "schema", "resource",
|
||||
];
|
||||
expect(nodeTypes).toHaveLength(13);
|
||||
});
|
||||
|
||||
it("accepts all 26 edge types", () => {
|
||||
const edgeTypes: EdgeType[] = [
|
||||
"imports", "exports", "contains", "inherits", "implements",
|
||||
"calls", "subscribes", "publishes", "middleware",
|
||||
"reads_from", "writes_to", "transforms", "validates",
|
||||
"depends_on", "tested_by", "configures",
|
||||
"related", "similar_to",
|
||||
"deploys", "serves", "migrates", "documents",
|
||||
"provisions", "routes", "defines_schema", "triggers",
|
||||
];
|
||||
expect(edgeTypes).toHaveLength(26);
|
||||
});
|
||||
|
||||
it("StructuralAnalysis has optional non-code fields", () => {
|
||||
const analysis: StructuralAnalysis = {
|
||||
functions: [], classes: [], imports: [], exports: [],
|
||||
sections: [{ name: "Introduction", level: 1, lineRange: [1, 10] }],
|
||||
definitions: [{ name: "users", kind: "table", lineRange: [1, 20], fields: ["id", "name"] }],
|
||||
services: [{ name: "web", image: "node:22", ports: [3000] }],
|
||||
endpoints: [{ method: "GET", path: "/api/users", lineRange: [5, 15] }],
|
||||
steps: [{ name: "build", lineRange: [1, 5] }],
|
||||
resources: [{ name: "aws_s3_bucket.main", kind: "aws_s3_bucket", lineRange: [1, 10] }],
|
||||
};
|
||||
expect(analysis.sections).toHaveLength(1);
|
||||
expect(analysis.definitions).toHaveLength(1);
|
||||
expect(analysis.services).toHaveLength(1);
|
||||
expect(analysis.endpoints).toHaveLength(1);
|
||||
expect(analysis.steps).toHaveLength(1);
|
||||
expect(analysis.resources).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("StructuralAnalysis is backward compatible (non-code fields are optional)", () => {
|
||||
const analysis: StructuralAnalysis = {
|
||||
functions: [], classes: [], imports: [], exports: [],
|
||||
};
|
||||
expect(analysis.sections).toBeUndefined();
|
||||
expect(analysis.definitions).toBeUndefined();
|
||||
expect(analysis.services).toBeUndefined();
|
||||
});
|
||||
|
||||
it("AnalyzerPlugin allows optional resolveImports", () => {
|
||||
const plugin: AnalyzerPlugin = {
|
||||
name: "test-plugin",
|
||||
languages: ["markdown"],
|
||||
analyzeFile: () => ({ functions: [], classes: [], imports: [], exports: [] }),
|
||||
// resolveImports is optional — not provided
|
||||
};
|
||||
expect(plugin.resolveImports).toBeUndefined();
|
||||
expect(plugin.analyzeFile).toBeDefined();
|
||||
});
|
||||
|
||||
it("AnalyzerPlugin supports extractReferences", () => {
|
||||
const refs: ReferenceResolution[] = [
|
||||
{ source: "README.md", target: "./docs/guide.md", referenceType: "file", line: 5 },
|
||||
];
|
||||
const plugin: AnalyzerPlugin = {
|
||||
name: "test-plugin",
|
||||
languages: ["markdown"],
|
||||
analyzeFile: () => ({ functions: [], classes: [], imports: [], exports: [] }),
|
||||
extractReferences: () => refs,
|
||||
};
|
||||
expect(plugin.extractReferences!("README.md", "")).toEqual(refs);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
// Edge types (18 total in 5 categories: Structural, Behavioral, Data flow, Dependencies, Semantic)
|
||||
// Edge types (26 total in 6 categories: Structural, Behavioral, Data flow, Dependencies, Semantic, Infrastructure)
|
||||
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
|
||||
| "related" | "similar_to" // Semantic
|
||||
| "deploys" | "serves" | "migrates" | "documents" // Infrastructure
|
||||
| "provisions" | "routes" | "defines_schema" | "triggers"; // Infrastructure
|
||||
|
||||
// GraphNode with 5 types: file, function, class, module, concept
|
||||
// GraphNode with 13 types: 5 code + 8 non-code
|
||||
export interface GraphNode {
|
||||
id: string;
|
||||
type: "file" | "function" | "class" | "module" | "concept";
|
||||
type: "file" | "function" | "class" | "module" | "concept"
|
||||
| "config" | "document" | "service" | "table" | "endpoint"
|
||||
| "pipeline" | "schema" | "resource";
|
||||
name: string;
|
||||
filePath?: string;
|
||||
lineRange?: [number, number];
|
||||
@@ -86,12 +90,63 @@ export interface ProjectConfig {
|
||||
autoUpdate: boolean;
|
||||
}
|
||||
|
||||
// Non-code structural sub-interfaces
|
||||
export interface SectionInfo {
|
||||
name: string;
|
||||
level: number;
|
||||
lineRange: [number, number];
|
||||
}
|
||||
|
||||
export interface DefinitionInfo {
|
||||
name: string;
|
||||
kind: string; // "table", "message", "type", "schema"
|
||||
lineRange: [number, number];
|
||||
fields: string[];
|
||||
}
|
||||
|
||||
export interface ServiceInfo {
|
||||
name: string;
|
||||
image?: string;
|
||||
ports: number[];
|
||||
}
|
||||
|
||||
export interface EndpointInfo {
|
||||
method?: string;
|
||||
path: string;
|
||||
lineRange: [number, number];
|
||||
}
|
||||
|
||||
export interface StepInfo {
|
||||
name: string;
|
||||
lineRange: [number, number];
|
||||
}
|
||||
|
||||
export interface ResourceInfo {
|
||||
name: string;
|
||||
kind: string;
|
||||
lineRange: [number, number];
|
||||
}
|
||||
|
||||
export interface ReferenceResolution {
|
||||
source: string;
|
||||
target: string;
|
||||
referenceType: string; // "file", "image", "schema", "service"
|
||||
line?: 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 }>;
|
||||
// Non-code structural data (all optional for backward compat)
|
||||
sections?: SectionInfo[];
|
||||
definitions?: DefinitionInfo[];
|
||||
services?: ServiceInfo[];
|
||||
endpoints?: EndpointInfo[];
|
||||
steps?: StepInfo[];
|
||||
resources?: ResourceInfo[];
|
||||
}
|
||||
|
||||
export interface ImportResolution {
|
||||
@@ -110,6 +165,7 @@ export interface AnalyzerPlugin {
|
||||
name: string;
|
||||
languages: string[];
|
||||
analyzeFile(filePath: string, content: string): StructuralAnalysis;
|
||||
resolveImports(filePath: string, content: string): ImportResolution[];
|
||||
resolveImports?(filePath: string, content: string): ImportResolution[];
|
||||
extractCallGraph?(filePath: string, content: string): CallGraphEntry[];
|
||||
extractReferences?(filePath: string, content: string): ReferenceResolution[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user