Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
/**
* Cypher statement generator for Neo4j
*/
import { GraphData, CypherStatement, CypherBatch } from './types.js';
export declare class CypherGenerator {
/**
* Generate Cypher statements from graph data
*/
generate(data: GraphData): CypherBatch;
/**
* Generate CREATE statement for a node
*/
private generateNodeStatement;
/**
* Generate CREATE statement for an edge
*/
private generateEdgeStatement;
/**
* Generate MERGE statements (upsert)
*/
generateMergeStatements(data: GraphData): CypherBatch;
/**
* Generate MERGE statement for a node
*/
private generateNodeMergeStatement;
/**
* Generate MERGE statement for an edge
*/
private generateEdgeMergeStatement;
/**
* Generate index creation statements
*/
generateIndexStatements(data: GraphData): CypherStatement[];
/**
* Generate constraint creation statements
*/
generateConstraintStatements(data: GraphData): CypherStatement[];
/**
* Generate complete setup script
*/
generateSetupScript(data: GraphData, options?: {
useConstraints?: boolean;
useIndexes?: boolean;
useMerge?: boolean;
}): string;
/**
* Format a statement for output
*/
private formatStatement;
/**
* Escape label names for Cypher
*/
private escapeLabel;
/**
* Generate batch insert with transactions
*/
generateBatchInsert(data: GraphData, batchSize?: number): CypherStatement[];
}
/**
* Create a Cypher generator
*/
export declare function createCypherGenerator(): CypherGenerator;
//# sourceMappingURL=cypher-generator.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cypher-generator.d.ts","sourceRoot":"","sources":["cypher-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,SAAS,EAGT,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,qBAAa,eAAe;IAC1B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW;IA+BtC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW;IA8BrD;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAqBlC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAuBlC;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,EAAE;IAoC3D;;OAEG;IACH,4BAA4B,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,EAAE;IAgBhE;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE;QAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GAAG,MAAM;IAkCV;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,GAAE,MAAa,GAAG,eAAe,EAAE;CAkDlF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD"}

View File

@@ -0,0 +1,312 @@
"use strict";
/**
* Cypher statement generator for Neo4j
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CypherGenerator = void 0;
exports.createCypherGenerator = createCypherGenerator;
class CypherGenerator {
/**
* Generate Cypher statements from graph data
*/
generate(data) {
const statements = [];
// Generate node creation statements
for (const node of data.nodes) {
statements.push(this.generateNodeStatement(node));
}
// Generate relationship creation statements
for (const edge of data.edges) {
statements.push(this.generateEdgeStatement(edge));
}
// Collect metadata
const labels = new Set();
const relationshipTypes = new Set();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
data.edges.forEach(edge => relationshipTypes.add(edge.type));
return {
statements,
metadata: {
total_nodes: data.nodes.length,
total_relationships: data.edges.length,
labels: Array.from(labels),
relationship_types: Array.from(relationshipTypes)
}
};
}
/**
* Generate CREATE statement for a node
*/
generateNodeStatement(node) {
const labels = node.labels.map(l => `:${this.escapeLabel(l)}`).join('');
const propsVar = 'props';
return {
query: `CREATE (n${labels} $${propsVar})`,
parameters: {
[propsVar]: {
id: node.id,
...node.properties,
...(node.embedding ? { embedding: node.embedding } : {})
}
}
};
}
/**
* Generate CREATE statement for an edge
*/
generateEdgeStatement(edge) {
const type = this.escapeLabel(edge.type);
const propsVar = 'props';
return {
query: `
MATCH (source { id: $sourceId })
MATCH (target { id: $targetId })
CREATE (source)-[r:${type} $${propsVar}]->(target)
`.trim(),
parameters: {
sourceId: edge.source,
targetId: edge.target,
[propsVar]: {
id: edge.id,
...edge.properties,
...(edge.embedding ? { embedding: edge.embedding } : {})
}
}
};
}
/**
* Generate MERGE statements (upsert)
*/
generateMergeStatements(data) {
const statements = [];
// Generate node merge statements
for (const node of data.nodes) {
statements.push(this.generateNodeMergeStatement(node));
}
// Generate relationship merge statements
for (const edge of data.edges) {
statements.push(this.generateEdgeMergeStatement(edge));
}
const labels = new Set();
const relationshipTypes = new Set();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
data.edges.forEach(edge => relationshipTypes.add(edge.type));
return {
statements,
metadata: {
total_nodes: data.nodes.length,
total_relationships: data.edges.length,
labels: Array.from(labels),
relationship_types: Array.from(relationshipTypes)
}
};
}
/**
* Generate MERGE statement for a node
*/
generateNodeMergeStatement(node) {
const primaryLabel = node.labels[0];
const additionalLabels = node.labels.slice(1).map(l => `:${this.escapeLabel(l)}`).join('');
const propsVar = 'props';
return {
query: `
MERGE (n:${this.escapeLabel(primaryLabel)} { id: $id })
SET n${additionalLabels}
SET n += $${propsVar}
`.trim(),
parameters: {
id: node.id,
[propsVar]: {
...node.properties,
...(node.embedding ? { embedding: node.embedding } : {})
}
}
};
}
/**
* Generate MERGE statement for an edge
*/
generateEdgeMergeStatement(edge) {
const type = this.escapeLabel(edge.type);
const propsVar = 'props';
return {
query: `
MATCH (source { id: $sourceId })
MATCH (target { id: $targetId })
MERGE (source)-[r:${type} { id: $id }]->(target)
SET r += $${propsVar}
`.trim(),
parameters: {
sourceId: edge.source,
targetId: edge.target,
id: edge.id,
[propsVar]: {
...edge.properties,
...(edge.embedding ? { embedding: edge.embedding } : {})
}
}
};
}
/**
* Generate index creation statements
*/
generateIndexStatements(data) {
const statements = [];
const labels = new Set();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
// Create index on id for each label
for (const label of labels) {
statements.push({
query: `CREATE INDEX IF NOT EXISTS FOR (n:${this.escapeLabel(label)}) ON (n.id)`
});
}
// Create vector indexes if embeddings are present
const hasEmbeddings = data.nodes.some(node => node.embedding);
if (hasEmbeddings) {
for (const label of labels) {
statements.push({
query: `
CREATE VECTOR INDEX IF NOT EXISTS ${this.escapeLabel(label)}_embedding
FOR (n:${this.escapeLabel(label)})
ON (n.embedding)
OPTIONS {
indexConfig: {
\`vector.dimensions\`: ${data.nodes.find(n => n.embedding)?.embedding?.length || 1536},
\`vector.similarity_function\`: 'cosine'
}
}
`.trim()
});
}
}
return statements;
}
/**
* Generate constraint creation statements
*/
generateConstraintStatements(data) {
const statements = [];
const labels = new Set();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
// Create unique constraint on id for each label
for (const label of labels) {
statements.push({
query: `CREATE CONSTRAINT IF NOT EXISTS FOR (n:${this.escapeLabel(label)}) REQUIRE n.id IS UNIQUE`
});
}
return statements;
}
/**
* Generate complete setup script
*/
generateSetupScript(data, options) {
const statements = [];
// Add constraints
if (options?.useConstraints !== false) {
statements.push('// Create constraints');
this.generateConstraintStatements(data).forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
statements.push('');
}
// Add indexes
if (options?.useIndexes !== false) {
statements.push('// Create indexes');
this.generateIndexStatements(data).forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
statements.push('');
}
// Add data
statements.push('// Create data');
const batch = options?.useMerge
? this.generateMergeStatements(data)
: this.generate(data);
batch.statements.forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
return statements.join('\n');
}
/**
* Format a statement for output
*/
formatStatement(stmt) {
if (!stmt.parameters || Object.keys(stmt.parameters).length === 0) {
return stmt.query;
}
let formatted = stmt.query;
for (const [key, value] of Object.entries(stmt.parameters)) {
const jsonValue = JSON.stringify(value);
formatted = formatted.replace(new RegExp(`\\$${key}\\b`, 'g'), jsonValue);
}
return formatted;
}
/**
* Escape label names for Cypher
*/
escapeLabel(label) {
// Remove special characters and use backticks if needed
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(label)) {
return label;
}
return `\`${label.replace(/`/g, '``')}\``;
}
/**
* Generate batch insert with transactions
*/
generateBatchInsert(data, batchSize = 1000) {
const statements = [];
// Batch nodes
for (let i = 0; i < data.nodes.length; i += batchSize) {
const batch = data.nodes.slice(i, i + batchSize);
statements.push({
query: `
UNWIND $nodes AS node
CREATE (n)
SET n = node.properties
SET n.id = node.id
WITH n, node.labels AS labels
CALL apoc.create.addLabels(n, labels) YIELD node AS labeled
RETURN count(labeled)
`.trim(),
parameters: {
nodes: batch.map(node => ({
id: node.id,
labels: node.labels,
properties: node.properties
}))
}
});
}
// Batch edges
for (let i = 0; i < data.edges.length; i += batchSize) {
const batch = data.edges.slice(i, i + batchSize);
statements.push({
query: `
UNWIND $edges AS edge
MATCH (source { id: edge.source })
MATCH (target { id: edge.target })
CALL apoc.create.relationship(source, edge.type, edge.properties, target) YIELD rel
RETURN count(rel)
`.trim(),
parameters: {
edges: batch.map(edge => ({
source: edge.source,
target: edge.target,
type: edge.type,
properties: edge.properties
}))
}
});
}
return statements;
}
}
exports.CypherGenerator = CypherGenerator;
/**
* Create a Cypher generator
*/
function createCypherGenerator() {
return new CypherGenerator();
}
//# sourceMappingURL=cypher-generator.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,362 @@
/**
* Cypher statement generator for Neo4j
*/
import {
GraphData,
GraphNode,
GraphEdge,
CypherStatement,
CypherBatch
} from './types.js';
export class CypherGenerator {
/**
* Generate Cypher statements from graph data
*/
generate(data: GraphData): CypherBatch {
const statements: CypherStatement[] = [];
// Generate node creation statements
for (const node of data.nodes) {
statements.push(this.generateNodeStatement(node));
}
// Generate relationship creation statements
for (const edge of data.edges) {
statements.push(this.generateEdgeStatement(edge));
}
// Collect metadata
const labels = new Set<string>();
const relationshipTypes = new Set<string>();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
data.edges.forEach(edge => relationshipTypes.add(edge.type));
return {
statements,
metadata: {
total_nodes: data.nodes.length,
total_relationships: data.edges.length,
labels: Array.from(labels),
relationship_types: Array.from(relationshipTypes)
}
};
}
/**
* Generate CREATE statement for a node
*/
private generateNodeStatement(node: GraphNode): CypherStatement {
const labels = node.labels.map(l => `:${this.escapeLabel(l)}`).join('');
const propsVar = 'props';
return {
query: `CREATE (n${labels} $${propsVar})`,
parameters: {
[propsVar]: {
id: node.id,
...node.properties,
...(node.embedding ? { embedding: node.embedding } : {})
}
}
};
}
/**
* Generate CREATE statement for an edge
*/
private generateEdgeStatement(edge: GraphEdge): CypherStatement {
const type = this.escapeLabel(edge.type);
const propsVar = 'props';
return {
query: `
MATCH (source { id: $sourceId })
MATCH (target { id: $targetId })
CREATE (source)-[r:${type} $${propsVar}]->(target)
`.trim(),
parameters: {
sourceId: edge.source,
targetId: edge.target,
[propsVar]: {
id: edge.id,
...edge.properties,
...(edge.embedding ? { embedding: edge.embedding } : {})
}
}
};
}
/**
* Generate MERGE statements (upsert)
*/
generateMergeStatements(data: GraphData): CypherBatch {
const statements: CypherStatement[] = [];
// Generate node merge statements
for (const node of data.nodes) {
statements.push(this.generateNodeMergeStatement(node));
}
// Generate relationship merge statements
for (const edge of data.edges) {
statements.push(this.generateEdgeMergeStatement(edge));
}
const labels = new Set<string>();
const relationshipTypes = new Set<string>();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
data.edges.forEach(edge => relationshipTypes.add(edge.type));
return {
statements,
metadata: {
total_nodes: data.nodes.length,
total_relationships: data.edges.length,
labels: Array.from(labels),
relationship_types: Array.from(relationshipTypes)
}
};
}
/**
* Generate MERGE statement for a node
*/
private generateNodeMergeStatement(node: GraphNode): CypherStatement {
const primaryLabel = node.labels[0];
const additionalLabels = node.labels.slice(1).map(l => `:${this.escapeLabel(l)}`).join('');
const propsVar = 'props';
return {
query: `
MERGE (n:${this.escapeLabel(primaryLabel)} { id: $id })
SET n${additionalLabels}
SET n += $${propsVar}
`.trim(),
parameters: {
id: node.id,
[propsVar]: {
...node.properties,
...(node.embedding ? { embedding: node.embedding } : {})
}
}
};
}
/**
* Generate MERGE statement for an edge
*/
private generateEdgeMergeStatement(edge: GraphEdge): CypherStatement {
const type = this.escapeLabel(edge.type);
const propsVar = 'props';
return {
query: `
MATCH (source { id: $sourceId })
MATCH (target { id: $targetId })
MERGE (source)-[r:${type} { id: $id }]->(target)
SET r += $${propsVar}
`.trim(),
parameters: {
sourceId: edge.source,
targetId: edge.target,
id: edge.id,
[propsVar]: {
...edge.properties,
...(edge.embedding ? { embedding: edge.embedding } : {})
}
}
};
}
/**
* Generate index creation statements
*/
generateIndexStatements(data: GraphData): CypherStatement[] {
const statements: CypherStatement[] = [];
const labels = new Set<string>();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
// Create index on id for each label
for (const label of labels) {
statements.push({
query: `CREATE INDEX IF NOT EXISTS FOR (n:${this.escapeLabel(label)}) ON (n.id)`
});
}
// Create vector indexes if embeddings are present
const hasEmbeddings = data.nodes.some(node => node.embedding);
if (hasEmbeddings) {
for (const label of labels) {
statements.push({
query: `
CREATE VECTOR INDEX IF NOT EXISTS ${this.escapeLabel(label)}_embedding
FOR (n:${this.escapeLabel(label)})
ON (n.embedding)
OPTIONS {
indexConfig: {
\`vector.dimensions\`: ${data.nodes.find(n => n.embedding)?.embedding?.length || 1536},
\`vector.similarity_function\`: 'cosine'
}
}
`.trim()
});
}
}
return statements;
}
/**
* Generate constraint creation statements
*/
generateConstraintStatements(data: GraphData): CypherStatement[] {
const statements: CypherStatement[] = [];
const labels = new Set<string>();
data.nodes.forEach(node => node.labels.forEach(label => labels.add(label)));
// Create unique constraint on id for each label
for (const label of labels) {
statements.push({
query: `CREATE CONSTRAINT IF NOT EXISTS FOR (n:${this.escapeLabel(label)}) REQUIRE n.id IS UNIQUE`
});
}
return statements;
}
/**
* Generate complete setup script
*/
generateSetupScript(data: GraphData, options?: {
useConstraints?: boolean;
useIndexes?: boolean;
useMerge?: boolean;
}): string {
const statements: string[] = [];
// Add constraints
if (options?.useConstraints !== false) {
statements.push('// Create constraints');
this.generateConstraintStatements(data).forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
statements.push('');
}
// Add indexes
if (options?.useIndexes !== false) {
statements.push('// Create indexes');
this.generateIndexStatements(data).forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
statements.push('');
}
// Add data
statements.push('// Create data');
const batch = options?.useMerge
? this.generateMergeStatements(data)
: this.generate(data);
batch.statements.forEach(stmt => {
statements.push(this.formatStatement(stmt) + ';');
});
return statements.join('\n');
}
/**
* Format a statement for output
*/
private formatStatement(stmt: CypherStatement): string {
if (!stmt.parameters || Object.keys(stmt.parameters).length === 0) {
return stmt.query;
}
let formatted = stmt.query;
for (const [key, value] of Object.entries(stmt.parameters)) {
const jsonValue = JSON.stringify(value);
formatted = formatted.replace(new RegExp(`\\$${key}\\b`, 'g'), jsonValue);
}
return formatted;
}
/**
* Escape label names for Cypher
*/
private escapeLabel(label: string): string {
// Remove special characters and use backticks if needed
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(label)) {
return label;
}
return `\`${label.replace(/`/g, '``')}\``;
}
/**
* Generate batch insert with transactions
*/
generateBatchInsert(data: GraphData, batchSize: number = 1000): CypherStatement[] {
const statements: CypherStatement[] = [];
// Batch nodes
for (let i = 0; i < data.nodes.length; i += batchSize) {
const batch = data.nodes.slice(i, i + batchSize);
statements.push({
query: `
UNWIND $nodes AS node
CREATE (n)
SET n = node.properties
SET n.id = node.id
WITH n, node.labels AS labels
CALL apoc.create.addLabels(n, labels) YIELD node AS labeled
RETURN count(labeled)
`.trim(),
parameters: {
nodes: batch.map(node => ({
id: node.id,
labels: node.labels,
properties: node.properties
}))
}
});
}
// Batch edges
for (let i = 0; i < data.edges.length; i += batchSize) {
const batch = data.edges.slice(i, i + batchSize);
statements.push({
query: `
UNWIND $edges AS edge
MATCH (source { id: edge.source })
MATCH (target { id: edge.target })
CALL apoc.create.relationship(source, edge.type, edge.properties, target) YIELD rel
RETURN count(rel)
`.trim(),
parameters: {
edges: batch.map(edge => ({
source: edge.source,
target: edge.target,
type: edge.type,
properties: edge.properties
}))
}
});
}
return statements;
}
}
/**
* Create a Cypher generator
*/
export function createCypherGenerator(): CypherGenerator {
return new CypherGenerator();
}

View File

@@ -0,0 +1,82 @@
/**
* Vector embedding enrichment for graph nodes and edges
*/
import { OpenRouterClient } from './openrouter-client.js';
import { GraphData, GraphNode, EmbeddingConfig } from './types.js';
export declare class EmbeddingEnrichment {
private client;
private config;
constructor(client: OpenRouterClient, config?: Partial<EmbeddingConfig>);
/**
* Enrich graph data with vector embeddings
*/
enrichGraphData(data: GraphData): Promise<GraphData>;
/**
* Enrich nodes with embeddings
*/
private enrichNodes;
/**
* Enrich edges with embeddings
*/
private enrichEdges;
/**
* Generate embedding for a node
*/
private generateNodeEmbedding;
/**
* Generate embedding for an edge
*/
private generateEdgeEmbedding;
/**
* Convert node to text for embedding
*/
private nodeToText;
/**
* Convert edge to text for embedding
*/
private edgeToText;
/**
* Generate embedding using OpenRouter or local model
*/
private generateEmbedding;
/**
* Generate semantic embedding using chat model
*/
private generateSemanticEmbedding;
/**
* Generate local embedding (placeholder)
*/
private generateLocalEmbedding;
/**
* Generate random embedding (fallback)
*/
private generateRandomEmbedding;
/**
* Calculate similarity between embeddings
*/
calculateSimilarity(embedding1: number[], embedding2: number[], metric?: 'cosine' | 'euclidean' | 'dot'): number;
/**
* Calculate cosine similarity
*/
private cosineSimilarity;
/**
* Calculate Euclidean distance
*/
private euclideanDistance;
/**
* Calculate dot product
*/
private dotProduct;
/**
* Find similar nodes using embeddings
*/
findSimilarNodes(node: GraphNode, allNodes: GraphNode[], topK?: number, metric?: 'cosine' | 'euclidean' | 'dot'): Array<{
node: GraphNode;
similarity: number;
}>;
}
/**
* Create an embedding enrichment instance
*/
export declare function createEmbeddingEnrichment(client: OpenRouterClient, config?: Partial<EmbeddingConfig>): EmbeddingEnrichment;
//# sourceMappingURL=embedding-enrichment.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"embedding-enrichment.d.ts","sourceRoot":"","sources":["embedding-enrichment.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,SAAS,EAET,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,MAAM;IAHhB,OAAO,CAAC,MAAM,CAAkB;gBAGtB,MAAM,EAAE,gBAAgB,EAChC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAUvC;;OAEG;IACG,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAc1D;;OAEG;YACW,WAAW;IAgBzB;;OAEG;YACW,WAAW;IAgBzB;;OAEG;YACW,qBAAqB;IAanC;;OAEG;YACW,qBAAqB;IAanC;;OAEG;IACH,OAAO,CAAC,UAAU;IAgBlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAgBlB;;OAEG;YACW,iBAAiB;IAiB/B;;OAEG;YACW,yBAAyB;IA6CvC;;OAEG;YACW,sBAAsB;IAUpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,mBAAmB,CACjB,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,GAAE,QAAQ,GAAG,WAAW,GAAG,KAAgB,GAChD,MAAM;IAiBT;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;IACH,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,SAAS,EAAE,EACrB,IAAI,GAAE,MAAW,EACjB,MAAM,GAAE,QAAQ,GAAG,WAAW,GAAG,KAAgB,GAChD,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAgBlD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,gBAAgB,EACxB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,mBAAmB,CAErB"}

View File

@@ -0,0 +1,257 @@
"use strict";
/**
* Vector embedding enrichment for graph nodes and edges
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmbeddingEnrichment = void 0;
exports.createEmbeddingEnrichment = createEmbeddingEnrichment;
class EmbeddingEnrichment {
constructor(client, config = {}) {
this.client = client;
this.config = {
provider: 'openrouter',
dimensions: 1536,
batchSize: 100,
...config
};
}
/**
* Enrich graph data with vector embeddings
*/
async enrichGraphData(data) {
// Generate embeddings for nodes
const enrichedNodes = await this.enrichNodes(data.nodes);
// Generate embeddings for edges (optional)
const enrichedEdges = await this.enrichEdges(data.edges);
return {
...data,
nodes: enrichedNodes,
edges: enrichedEdges
};
}
/**
* Enrich nodes with embeddings
*/
async enrichNodes(nodes) {
const enriched = [];
// Process in batches
for (let i = 0; i < nodes.length; i += this.config.batchSize) {
const batch = nodes.slice(i, i + this.config.batchSize);
const batchResults = await Promise.all(batch.map(node => this.generateNodeEmbedding(node)));
enriched.push(...batchResults);
}
return enriched;
}
/**
* Enrich edges with embeddings
*/
async enrichEdges(edges) {
const enriched = [];
// Process in batches
for (let i = 0; i < edges.length; i += this.config.batchSize) {
const batch = edges.slice(i, i + this.config.batchSize);
const batchResults = await Promise.all(batch.map(edge => this.generateEdgeEmbedding(edge)));
enriched.push(...batchResults);
}
return enriched;
}
/**
* Generate embedding for a node
*/
async generateNodeEmbedding(node) {
// Create text representation of node
const text = this.nodeToText(node);
// Generate embedding
const embedding = await this.generateEmbedding(text);
return {
...node,
embedding: embedding.embedding
};
}
/**
* Generate embedding for an edge
*/
async generateEdgeEmbedding(edge) {
// Create text representation of edge
const text = this.edgeToText(edge);
// Generate embedding
const embedding = await this.generateEmbedding(text);
return {
...edge,
embedding: embedding.embedding
};
}
/**
* Convert node to text for embedding
*/
nodeToText(node) {
const parts = [];
// Add labels
parts.push(`Type: ${node.labels.join(', ')}`);
// Add properties
for (const [key, value] of Object.entries(node.properties)) {
if (typeof value === 'string' || typeof value === 'number') {
parts.push(`${key}: ${value}`);
}
}
return parts.join('. ');
}
/**
* Convert edge to text for embedding
*/
edgeToText(edge) {
const parts = [];
// Add relationship type
parts.push(`Relationship: ${edge.type}`);
// Add properties
for (const [key, value] of Object.entries(edge.properties)) {
if (typeof value === 'string' || typeof value === 'number') {
parts.push(`${key}: ${value}`);
}
}
return parts.join('. ');
}
/**
* Generate embedding using OpenRouter or local model
*/
async generateEmbedding(text) {
if (this.config.provider === 'local') {
return this.generateLocalEmbedding(text);
}
// Use OpenRouter with embedding-capable model
// Note: Kimi K2 may not support embeddings, so we use a workaround
// by generating semantic vectors through the chat API
const embedding = await this.generateSemanticEmbedding(text);
return {
embedding,
model: this.config.model || 'moonshot/kimi-k2-instruct',
dimensions: embedding.length
};
}
/**
* Generate semantic embedding using chat model
*/
async generateSemanticEmbedding(text) {
// Use the chat API to generate a semantic representation
// This is a workaround for models without native embedding support
const systemPrompt = `You are a semantic encoder. Convert the input text into a semantic representation by analyzing its key concepts, entities, and relationships. Output ONLY a JSON array of ${this.config.dimensions} floating point numbers between -1 and 1 representing the semantic vector.`;
const userPrompt = `Encode this text into a ${this.config.dimensions}-dimensional semantic vector:\n\n${text}`;
try {
const response = await this.client.createCompletion([
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
], {
temperature: 0.3,
max_tokens: this.config.dimensions * 10
});
const content = response.choices[0]?.message?.content;
if (!content) {
throw new Error('No content in embedding response');
}
// Extract JSON array
const match = content.match(/\[([\s\S]*?)\]/);
if (match) {
const embedding = JSON.parse(`[${match[1]}]`);
// Ensure correct dimensions
if (embedding.length !== this.config.dimensions) {
return this.generateRandomEmbedding();
}
return embedding;
}
// Fallback to random embedding
return this.generateRandomEmbedding();
}
catch (error) {
console.warn('Failed to generate semantic embedding, using random:', error);
return this.generateRandomEmbedding();
}
}
/**
* Generate local embedding (placeholder)
*/
async generateLocalEmbedding(_text) {
// This would use a local embedding model
// For now, return a random embedding
return {
embedding: this.generateRandomEmbedding(),
model: 'local',
dimensions: this.config.dimensions
};
}
/**
* Generate random embedding (fallback)
*/
generateRandomEmbedding() {
const embedding = [];
for (let i = 0; i < this.config.dimensions; i++) {
embedding.push((Math.random() * 2) - 1); // Random value between -1 and 1
}
// Normalize to unit length
const magnitude = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
return embedding.map(val => val / magnitude);
}
/**
* Calculate similarity between embeddings
*/
calculateSimilarity(embedding1, embedding2, metric = 'cosine') {
if (embedding1.length !== embedding2.length) {
throw new Error('Embeddings must have the same dimensions');
}
switch (metric) {
case 'cosine':
return this.cosineSimilarity(embedding1, embedding2);
case 'euclidean':
return this.euclideanDistance(embedding1, embedding2);
case 'dot':
return this.dotProduct(embedding1, embedding2);
default:
return this.cosineSimilarity(embedding1, embedding2);
}
}
/**
* Calculate cosine similarity
*/
cosineSimilarity(a, b) {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
/**
* Calculate Euclidean distance
*/
euclideanDistance(a, b) {
return Math.sqrt(a.reduce((sum, val, i) => sum + Math.pow(val - b[i], 2), 0));
}
/**
* Calculate dot product
*/
dotProduct(a, b) {
return a.reduce((sum, val, i) => sum + val * b[i], 0);
}
/**
* Find similar nodes using embeddings
*/
findSimilarNodes(node, allNodes, topK = 10, metric = 'cosine') {
if (!node.embedding) {
throw new Error('Node does not have an embedding');
}
const similarities = allNodes
.filter(n => n.id !== node.id && n.embedding)
.map(n => ({
node: n,
similarity: this.calculateSimilarity(node.embedding, n.embedding, metric)
}))
.sort((a, b) => b.similarity - a.similarity)
.slice(0, topK);
return similarities;
}
}
exports.EmbeddingEnrichment = EmbeddingEnrichment;
/**
* Create an embedding enrichment instance
*/
function createEmbeddingEnrichment(client, config) {
return new EmbeddingEnrichment(client, config);
}
//# sourceMappingURL=embedding-enrichment.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,331 @@
/**
* Vector embedding enrichment for graph nodes and edges
*/
import { OpenRouterClient } from './openrouter-client.js';
import {
GraphData,
GraphNode,
GraphEdge,
EmbeddingConfig,
EmbeddingResult
} from './types.js';
export class EmbeddingEnrichment {
private config: EmbeddingConfig;
constructor(
private client: OpenRouterClient,
config: Partial<EmbeddingConfig> = {}
) {
this.config = {
provider: 'openrouter',
dimensions: 1536,
batchSize: 100,
...config
};
}
/**
* Enrich graph data with vector embeddings
*/
async enrichGraphData(data: GraphData): Promise<GraphData> {
// Generate embeddings for nodes
const enrichedNodes = await this.enrichNodes(data.nodes);
// Generate embeddings for edges (optional)
const enrichedEdges = await this.enrichEdges(data.edges);
return {
...data,
nodes: enrichedNodes,
edges: enrichedEdges
};
}
/**
* Enrich nodes with embeddings
*/
private async enrichNodes(nodes: GraphNode[]): Promise<GraphNode[]> {
const enriched: GraphNode[] = [];
// Process in batches
for (let i = 0; i < nodes.length; i += this.config.batchSize!) {
const batch = nodes.slice(i, i + this.config.batchSize!);
const batchResults = await Promise.all(
batch.map(node => this.generateNodeEmbedding(node))
);
enriched.push(...batchResults);
}
return enriched;
}
/**
* Enrich edges with embeddings
*/
private async enrichEdges(edges: GraphEdge[]): Promise<GraphEdge[]> {
const enriched: GraphEdge[] = [];
// Process in batches
for (let i = 0; i < edges.length; i += this.config.batchSize!) {
const batch = edges.slice(i, i + this.config.batchSize!);
const batchResults = await Promise.all(
batch.map(edge => this.generateEdgeEmbedding(edge))
);
enriched.push(...batchResults);
}
return enriched;
}
/**
* Generate embedding for a node
*/
private async generateNodeEmbedding(node: GraphNode): Promise<GraphNode> {
// Create text representation of node
const text = this.nodeToText(node);
// Generate embedding
const embedding = await this.generateEmbedding(text);
return {
...node,
embedding: embedding.embedding
};
}
/**
* Generate embedding for an edge
*/
private async generateEdgeEmbedding(edge: GraphEdge): Promise<GraphEdge> {
// Create text representation of edge
const text = this.edgeToText(edge);
// Generate embedding
const embedding = await this.generateEmbedding(text);
return {
...edge,
embedding: embedding.embedding
};
}
/**
* Convert node to text for embedding
*/
private nodeToText(node: GraphNode): string {
const parts: string[] = [];
// Add labels
parts.push(`Type: ${node.labels.join(', ')}`);
// Add properties
for (const [key, value] of Object.entries(node.properties)) {
if (typeof value === 'string' || typeof value === 'number') {
parts.push(`${key}: ${value}`);
}
}
return parts.join('. ');
}
/**
* Convert edge to text for embedding
*/
private edgeToText(edge: GraphEdge): string {
const parts: string[] = [];
// Add relationship type
parts.push(`Relationship: ${edge.type}`);
// Add properties
for (const [key, value] of Object.entries(edge.properties)) {
if (typeof value === 'string' || typeof value === 'number') {
parts.push(`${key}: ${value}`);
}
}
return parts.join('. ');
}
/**
* Generate embedding using OpenRouter or local model
*/
private async generateEmbedding(text: string): Promise<EmbeddingResult> {
if (this.config.provider === 'local') {
return this.generateLocalEmbedding(text);
}
// Use OpenRouter with embedding-capable model
// Note: Kimi K2 may not support embeddings, so we use a workaround
// by generating semantic vectors through the chat API
const embedding = await this.generateSemanticEmbedding(text);
return {
embedding,
model: this.config.model || 'moonshot/kimi-k2-instruct',
dimensions: embedding.length
};
}
/**
* Generate semantic embedding using chat model
*/
private async generateSemanticEmbedding(text: string): Promise<number[]> {
// Use the chat API to generate a semantic representation
// This is a workaround for models without native embedding support
const systemPrompt = `You are a semantic encoder. Convert the input text into a semantic representation by analyzing its key concepts, entities, and relationships. Output ONLY a JSON array of ${this.config.dimensions} floating point numbers between -1 and 1 representing the semantic vector.`;
const userPrompt = `Encode this text into a ${this.config.dimensions}-dimensional semantic vector:\n\n${text}`;
try {
const response = await this.client.createCompletion(
[
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
],
{
temperature: 0.3,
max_tokens: this.config.dimensions! * 10
}
);
const content = response.choices[0]?.message?.content;
if (!content) {
throw new Error('No content in embedding response');
}
// Extract JSON array
const match = content.match(/\[([\s\S]*?)\]/);
if (match) {
const embedding = JSON.parse(`[${match[1]}]`) as number[];
// Ensure correct dimensions
if (embedding.length !== this.config.dimensions) {
return this.generateRandomEmbedding();
}
return embedding;
}
// Fallback to random embedding
return this.generateRandomEmbedding();
} catch (error) {
console.warn('Failed to generate semantic embedding, using random:', error);
return this.generateRandomEmbedding();
}
}
/**
* Generate local embedding (placeholder)
*/
private async generateLocalEmbedding(_text: string): Promise<EmbeddingResult> {
// This would use a local embedding model
// For now, return a random embedding
return {
embedding: this.generateRandomEmbedding(),
model: 'local',
dimensions: this.config.dimensions!
};
}
/**
* Generate random embedding (fallback)
*/
private generateRandomEmbedding(): number[] {
const embedding: number[] = [];
for (let i = 0; i < this.config.dimensions!; i++) {
embedding.push((Math.random() * 2) - 1); // Random value between -1 and 1
}
// Normalize to unit length
const magnitude = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
return embedding.map(val => val / magnitude);
}
/**
* Calculate similarity between embeddings
*/
calculateSimilarity(
embedding1: number[],
embedding2: number[],
metric: 'cosine' | 'euclidean' | 'dot' = 'cosine'
): number {
if (embedding1.length !== embedding2.length) {
throw new Error('Embeddings must have the same dimensions');
}
switch (metric) {
case 'cosine':
return this.cosineSimilarity(embedding1, embedding2);
case 'euclidean':
return this.euclideanDistance(embedding1, embedding2);
case 'dot':
return this.dotProduct(embedding1, embedding2);
default:
return this.cosineSimilarity(embedding1, embedding2);
}
}
/**
* Calculate cosine similarity
*/
private cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
/**
* Calculate Euclidean distance
*/
private euclideanDistance(a: number[], b: number[]): number {
return Math.sqrt(a.reduce((sum, val, i) => sum + Math.pow(val - b[i], 2), 0));
}
/**
* Calculate dot product
*/
private dotProduct(a: number[], b: number[]): number {
return a.reduce((sum, val, i) => sum + val * b[i], 0);
}
/**
* Find similar nodes using embeddings
*/
findSimilarNodes(
node: GraphNode,
allNodes: GraphNode[],
topK: number = 10,
metric: 'cosine' | 'euclidean' | 'dot' = 'cosine'
): Array<{ node: GraphNode; similarity: number }> {
if (!node.embedding) {
throw new Error('Node does not have an embedding');
}
const similarities = allNodes
.filter(n => n.id !== node.id && n.embedding)
.map(n => ({
node: n,
similarity: this.calculateSimilarity(node.embedding!, n.embedding!, metric)
}))
.sort((a, b) => b.similarity - a.similarity)
.slice(0, topK);
return similarities;
}
}
/**
* Create an embedding enrichment instance
*/
export function createEmbeddingEnrichment(
client: OpenRouterClient,
config?: Partial<EmbeddingConfig>
): EmbeddingEnrichment {
return new EmbeddingEnrichment(client, config);
}

View File

@@ -0,0 +1,49 @@
/**
* Entity relationship generator for domain-specific graphs
*/
import { OpenRouterClient } from '../openrouter-client.js';
import { EntityRelationshipOptions, GraphData, GraphGenerationResult } from '../types.js';
export declare class EntityRelationshipGenerator {
private client;
constructor(client: OpenRouterClient);
/**
* Generate entity-relationship graph
*/
generate(options: EntityRelationshipOptions): Promise<GraphGenerationResult<GraphData>>;
/**
* Generate domain-specific entities
*/
private generateEntities;
/**
* Generate relationships between entities
*/
private generateRelationships;
/**
* Generate schema-aware entities and relationships
*/
generateWithSchema(schema: {
entities: Record<string, {
properties: Record<string, string>;
relationships?: string[];
}>;
relationships: Record<string, {
from: string;
to: string;
properties?: Record<string, string>;
}>;
}, count: number): Promise<GraphData>;
/**
* Analyze entity-relationship patterns
*/
analyzeERPatterns(data: GraphData): Promise<{
entityTypeDistribution: Record<string, number>;
relationshipTypeDistribution: Record<string, number>;
avgRelationshipsPerEntity: number;
densityScore: number;
}>;
}
/**
* Create an entity relationship generator
*/
export declare function createEntityRelationshipGenerator(client: OpenRouterClient): EntityRelationshipGenerator;
//# sourceMappingURL=entity-relationships.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"entity-relationships.d.ts","sourceRoot":"","sources":["entity-relationships.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,yBAAyB,EACzB,SAAS,EAGT,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAerB,qBAAa,2BAA2B;IAC1B,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IA6C7F;;OAEG;YACW,gBAAgB;IA2C9B;;OAEG;YACW,qBAAqB;IA6DnC;;OAEG;IACG,kBAAkB,CACtB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACnC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;SAC1B,CAAC,CAAC;QACH,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;YAC5B,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;YACX,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SACrC,CAAC,CAAC;KACJ,EACD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,CAAC;IA+BrB;;OAEG;IACG,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAChD,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,yBAAyB,EAAE,MAAM,CAAC;QAClC,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CAoCH;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,gBAAgB,GAAG,2BAA2B,CAEvG"}

View File

@@ -0,0 +1,217 @@
"use strict";
/**
* Entity relationship generator for domain-specific graphs
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityRelationshipGenerator = void 0;
exports.createEntityRelationshipGenerator = createEntityRelationshipGenerator;
class EntityRelationshipGenerator {
constructor(client) {
this.client = client;
}
/**
* Generate entity-relationship graph
*/
async generate(options) {
const startTime = Date.now();
// Generate entities
const entities = await this.generateEntities(options);
// Generate relationships
const relationships = await this.generateRelationships(entities, options);
// Convert to graph structure
const nodes = entities.map(entity => ({
id: entity.id,
labels: entity.labels || ['Entity'],
properties: entity.properties
}));
const edges = relationships.map((rel, idx) => ({
id: `rel_${idx}`,
type: rel.type,
source: rel.source,
target: rel.target,
properties: rel.properties || {}
}));
const data = {
nodes,
edges,
metadata: {
domain: options.domain,
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate domain-specific entities
*/
async generateEntities(options) {
const systemPrompt = `You are an expert in ${options.domain} domain modeling. Generate realistic entities following best practices for ${options.domain} data models.`;
const schemaInfo = options.entitySchema
? `\n\nEntity schema to follow:\n${JSON.stringify(options.entitySchema, null, 2)}`
: '';
const userPrompt = `Generate ${options.entityCount} diverse entities for a ${options.domain} domain model.${schemaInfo}
Each entity should have:
- id: unique identifier (use snake_case)
- labels: array of entity type labels (e.g., ["Product", "Digital"])
- properties: object with entity properties (at least 3-5 meaningful properties)
Make entities realistic and relevant to ${options.domain}. Include variety in types and attributes.
Return a JSON array of entities.
Example format:
\`\`\`json
[
{
"id": "product_laptop_001",
"labels": ["Product", "Electronics", "Computer"],
"properties": {
"name": "UltraBook Pro 15",
"category": "Laptops",
"price": 1299.99,
"brand": "TechCorp",
"release_date": "2024-01-15",
"stock": 45,
"rating": 4.7
}
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.8,
maxTokens: Math.min(8000, options.entityCount * 150)
});
}
/**
* Generate relationships between entities
*/
async generateRelationships(entities, options) {
// Calculate target relationship count based on density
const maxPossibleRelationships = entities.length * (entities.length - 1);
const targetRelationships = Math.floor(maxPossibleRelationships * options.relationshipDensity);
const relationshipTypes = options.relationshipTypes || [
'RELATES_TO',
'PART_OF',
'DEPENDS_ON',
'SIMILAR_TO',
'CONTAINS'
];
const systemPrompt = `You are an expert in ${options.domain} domain modeling. Create meaningful, realistic relationships between entities.`;
const entityList = entities.slice(0, 100).map(e => `- ${e.id} (${e.labels.join(', ')}): ${JSON.stringify(e.properties).substring(0, 100)}`).join('\n');
const userPrompt = `Given these entities from a ${options.domain} domain:
${entityList}
Generate ${targetRelationships} meaningful relationships between them.
Relationship types to use: ${relationshipTypes.join(', ')}
Each relationship should have:
- source: source entity id
- target: target entity id
- type: relationship type (use UPPER_SNAKE_CASE)
- properties: optional properties describing the relationship
Make relationships logical and realistic for ${options.domain}. Avoid creating too many relationships from/to the same entity.
Return a JSON array of relationships.
Example format:
\`\`\`json
[
{
"source": "product_laptop_001",
"target": "category_electronics",
"type": "BELONGS_TO",
"properties": {
"primary": true,
"added_date": "2024-01-15"
}
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, targetRelationships * 80)
});
}
/**
* Generate schema-aware entities and relationships
*/
async generateWithSchema(schema, count) {
const systemPrompt = 'You are an expert at generating synthetic data that conforms to strict schemas.';
const userPrompt = `Generate ${count} instances of entities and relationships following this exact schema:
${JSON.stringify(schema, null, 2)}
Return a JSON object with:
- nodes: array of entities matching the entity types in the schema
- edges: array of relationships matching the relationship types in the schema
Ensure all properties match their specified types and all relationships connect valid entity types.
Example format:
\`\`\`json
{
"nodes": [...],
"edges": [...]
}
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, count * 200)
});
}
/**
* Analyze entity-relationship patterns
*/
async analyzeERPatterns(data) {
const entityTypeDistribution = {};
const relationshipTypeDistribution = {};
const entityDegrees = new Map();
// Count entity types
for (const node of data.nodes) {
for (const label of node.labels) {
entityTypeDistribution[label] = (entityTypeDistribution[label] || 0) + 1;
}
}
// Count relationship types and degrees
for (const edge of data.edges) {
relationshipTypeDistribution[edge.type] = (relationshipTypeDistribution[edge.type] || 0) + 1;
entityDegrees.set(edge.source, (entityDegrees.get(edge.source) || 0) + 1);
entityDegrees.set(edge.target, (entityDegrees.get(edge.target) || 0) + 1);
}
const degrees = Array.from(entityDegrees.values());
const avgRelationshipsPerEntity = degrees.length > 0
? degrees.reduce((a, b) => a + b, 0) / degrees.length
: 0;
const maxPossibleEdges = data.nodes.length * (data.nodes.length - 1);
const densityScore = maxPossibleEdges > 0
? data.edges.length / maxPossibleEdges
: 0;
return {
entityTypeDistribution,
relationshipTypeDistribution,
avgRelationshipsPerEntity,
densityScore
};
}
}
exports.EntityRelationshipGenerator = EntityRelationshipGenerator;
/**
* Create an entity relationship generator
*/
function createEntityRelationshipGenerator(client) {
return new EntityRelationshipGenerator(client);
}
//# sourceMappingURL=entity-relationships.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"entity-relationships.js","sourceRoot":"","sources":["entity-relationships.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,286 @@
/**
* Entity relationship generator for domain-specific graphs
*/
import { OpenRouterClient } from '../openrouter-client.js';
import {
EntityRelationshipOptions,
GraphData,
GraphNode,
GraphEdge,
GraphGenerationResult
} from '../types.js';
interface EntityData {
id: string;
labels: string[];
properties: Record<string, unknown>;
}
interface RelationshipData {
source: string;
target: string;
type: string;
properties?: Record<string, unknown>;
}
export class EntityRelationshipGenerator {
constructor(private client: OpenRouterClient) {}
/**
* Generate entity-relationship graph
*/
async generate(options: EntityRelationshipOptions): Promise<GraphGenerationResult<GraphData>> {
const startTime = Date.now();
// Generate entities
const entities = await this.generateEntities(options);
// Generate relationships
const relationships = await this.generateRelationships(entities, options);
// Convert to graph structure
const nodes: GraphNode[] = entities.map(entity => ({
id: entity.id,
labels: entity.labels || ['Entity'],
properties: entity.properties
}));
const edges: GraphEdge[] = relationships.map((rel, idx) => ({
id: `rel_${idx}`,
type: rel.type,
source: rel.source,
target: rel.target,
properties: rel.properties || {}
}));
const data: GraphData = {
nodes,
edges,
metadata: {
domain: options.domain,
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate domain-specific entities
*/
private async generateEntities(options: EntityRelationshipOptions): Promise<EntityData[]> {
const systemPrompt = `You are an expert in ${options.domain} domain modeling. Generate realistic entities following best practices for ${options.domain} data models.`;
const schemaInfo = options.entitySchema
? `\n\nEntity schema to follow:\n${JSON.stringify(options.entitySchema, null, 2)}`
: '';
const userPrompt = `Generate ${options.entityCount} diverse entities for a ${options.domain} domain model.${schemaInfo}
Each entity should have:
- id: unique identifier (use snake_case)
- labels: array of entity type labels (e.g., ["Product", "Digital"])
- properties: object with entity properties (at least 3-5 meaningful properties)
Make entities realistic and relevant to ${options.domain}. Include variety in types and attributes.
Return a JSON array of entities.
Example format:
\`\`\`json
[
{
"id": "product_laptop_001",
"labels": ["Product", "Electronics", "Computer"],
"properties": {
"name": "UltraBook Pro 15",
"category": "Laptops",
"price": 1299.99,
"brand": "TechCorp",
"release_date": "2024-01-15",
"stock": 45,
"rating": 4.7
}
}
]
\`\`\``;
return this.client.generateStructured<EntityData[]>(systemPrompt, userPrompt, {
temperature: 0.8,
maxTokens: Math.min(8000, options.entityCount * 150)
});
}
/**
* Generate relationships between entities
*/
private async generateRelationships(
entities: EntityData[],
options: EntityRelationshipOptions
): Promise<RelationshipData[]> {
// Calculate target relationship count based on density
const maxPossibleRelationships = entities.length * (entities.length - 1);
const targetRelationships = Math.floor(maxPossibleRelationships * options.relationshipDensity);
const relationshipTypes = options.relationshipTypes || [
'RELATES_TO',
'PART_OF',
'DEPENDS_ON',
'SIMILAR_TO',
'CONTAINS'
];
const systemPrompt = `You are an expert in ${options.domain} domain modeling. Create meaningful, realistic relationships between entities.`;
const entityList = entities.slice(0, 100).map(e =>
`- ${e.id} (${e.labels.join(', ')}): ${JSON.stringify(e.properties).substring(0, 100)}`
).join('\n');
const userPrompt = `Given these entities from a ${options.domain} domain:
${entityList}
Generate ${targetRelationships} meaningful relationships between them.
Relationship types to use: ${relationshipTypes.join(', ')}
Each relationship should have:
- source: source entity id
- target: target entity id
- type: relationship type (use UPPER_SNAKE_CASE)
- properties: optional properties describing the relationship
Make relationships logical and realistic for ${options.domain}. Avoid creating too many relationships from/to the same entity.
Return a JSON array of relationships.
Example format:
\`\`\`json
[
{
"source": "product_laptop_001",
"target": "category_electronics",
"type": "BELONGS_TO",
"properties": {
"primary": true,
"added_date": "2024-01-15"
}
}
]
\`\`\``;
return this.client.generateStructured<RelationshipData[]>(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, targetRelationships * 80)
});
}
/**
* Generate schema-aware entities and relationships
*/
async generateWithSchema(
schema: {
entities: Record<string, {
properties: Record<string, string>;
relationships?: string[];
}>;
relationships: Record<string, {
from: string;
to: string;
properties?: Record<string, string>;
}>;
},
count: number
): Promise<GraphData> {
const systemPrompt = 'You are an expert at generating synthetic data that conforms to strict schemas.';
const userPrompt = `Generate ${count} instances of entities and relationships following this exact schema:
${JSON.stringify(schema, null, 2)}
Return a JSON object with:
- nodes: array of entities matching the entity types in the schema
- edges: array of relationships matching the relationship types in the schema
Ensure all properties match their specified types and all relationships connect valid entity types.
Example format:
\`\`\`json
{
"nodes": [...],
"edges": [...]
}
\`\`\``;
return this.client.generateStructured<GraphData>(
systemPrompt,
userPrompt,
{
temperature: 0.7,
maxTokens: Math.min(8000, count * 200)
}
);
}
/**
* Analyze entity-relationship patterns
*/
async analyzeERPatterns(data: GraphData): Promise<{
entityTypeDistribution: Record<string, number>;
relationshipTypeDistribution: Record<string, number>;
avgRelationshipsPerEntity: number;
densityScore: number;
}> {
const entityTypeDistribution: Record<string, number> = {};
const relationshipTypeDistribution: Record<string, number> = {};
const entityDegrees = new Map<string, number>();
// Count entity types
for (const node of data.nodes) {
for (const label of node.labels) {
entityTypeDistribution[label] = (entityTypeDistribution[label] || 0) + 1;
}
}
// Count relationship types and degrees
for (const edge of data.edges) {
relationshipTypeDistribution[edge.type] = (relationshipTypeDistribution[edge.type] || 0) + 1;
entityDegrees.set(edge.source, (entityDegrees.get(edge.source) || 0) + 1);
entityDegrees.set(edge.target, (entityDegrees.get(edge.target) || 0) + 1);
}
const degrees = Array.from(entityDegrees.values());
const avgRelationshipsPerEntity = degrees.length > 0
? degrees.reduce((a, b) => a + b, 0) / degrees.length
: 0;
const maxPossibleEdges = data.nodes.length * (data.nodes.length - 1);
const densityScore = maxPossibleEdges > 0
? data.edges.length / maxPossibleEdges
: 0;
return {
entityTypeDistribution,
relationshipTypeDistribution,
avgRelationshipsPerEntity,
densityScore
};
}
}
/**
* Create an entity relationship generator
*/
export function createEntityRelationshipGenerator(client: OpenRouterClient): EntityRelationshipGenerator {
return new EntityRelationshipGenerator(client);
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,uDAAqC;AACrC,sDAAoC;AACpC,uDAAqC;AACrC,4DAA0C"}

View File

@@ -0,0 +1,8 @@
/**
* Graph data generators exports
*/
export * from './knowledge-graph.js';
export * from './social-network.js';
export * from './temporal-events.js';
export * from './entity-relationships.js';

View File

@@ -0,0 +1,30 @@
/**
* Knowledge graph generator using OpenRouter/Kimi K2
*/
import { OpenRouterClient } from '../openrouter-client.js';
import { KnowledgeGraphOptions, GraphData, GraphGenerationResult, KnowledgeTriple } from '../types.js';
export declare class KnowledgeGraphGenerator {
private client;
constructor(client: OpenRouterClient);
/**
* Generate a knowledge graph
*/
generate(options: KnowledgeGraphOptions): Promise<GraphGenerationResult<GraphData>>;
/**
* Generate entities for the knowledge graph
*/
private generateEntities;
/**
* Generate relationships between entities
*/
private generateRelationships;
/**
* Generate knowledge triples (subject-predicate-object)
*/
generateTriples(domain: string, count: number): Promise<KnowledgeTriple[]>;
}
/**
* Create a knowledge graph generator
*/
export declare function createKnowledgeGraphGenerator(client: OpenRouterClient): KnowledgeGraphGenerator;
//# sourceMappingURL=knowledge-graph.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"knowledge-graph.d.ts","sourceRoot":"","sources":["knowledge-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,SAAS,EAGT,qBAAqB,EACrB,eAAe,EAChB,MAAM,aAAa,CAAC;AAoCrB,qBAAa,uBAAuB;IACtB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAgDzF;;OAEG;YACW,gBAAgB;IA8C9B;;OAEG;YACW,qBAAqB;IAiDnC;;OAEG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,EAAE,CAAC;CA+B9B;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,gBAAgB,GAAG,uBAAuB,CAE/F"}

View File

@@ -0,0 +1,192 @@
"use strict";
/**
* Knowledge graph generator using OpenRouter/Kimi K2
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.KnowledgeGraphGenerator = void 0;
exports.createKnowledgeGraphGenerator = createKnowledgeGraphGenerator;
const DEFAULT_ENTITY_TYPES = [
'Person',
'Organization',
'Location',
'Event',
'Concept',
'Technology',
'Product'
];
const DEFAULT_RELATIONSHIP_TYPES = [
'WORKS_FOR',
'LOCATED_IN',
'CREATED_BY',
'PART_OF',
'RELATED_TO',
'INFLUENCES',
'DEPENDS_ON'
];
class KnowledgeGraphGenerator {
constructor(client) {
this.client = client;
}
/**
* Generate a knowledge graph
*/
async generate(options) {
const startTime = Date.now();
// Generate entities first
const entities = await this.generateEntities(options);
// Generate relationships between entities
const relationships = await this.generateRelationships(entities, options);
// Convert to graph structure
const nodes = entities.map((entity, idx) => ({
id: entity.id || `entity_${idx}`,
labels: [entity.type || 'Entity'],
properties: {
name: entity.name,
...entity.properties
}
}));
const edges = relationships.map((rel, idx) => ({
id: `rel_${idx}`,
type: rel.type,
source: rel.source,
target: rel.target,
properties: rel.properties || {}
}));
const data = {
nodes,
edges,
metadata: {
domain: options.domain,
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate entities for the knowledge graph
*/
async generateEntities(options) {
const entityTypes = options.entityTypes || DEFAULT_ENTITY_TYPES;
const systemPrompt = `You are an expert knowledge graph architect. Generate realistic entities for a knowledge graph about ${options.domain}.`;
const userPrompt = `Generate ${options.entities} diverse entities for a knowledge graph about ${options.domain}.
Entity types to include: ${entityTypes.join(', ')}
For each entity, provide:
- id: unique identifier (use snake_case)
- name: entity name
- type: one of the specified entity types
- properties: relevant properties (at least 2-3 properties per entity)
Return a JSON array of entities. Make them realistic and relevant to ${options.domain}.
Example format:
\`\`\`json
[
{
"id": "john_doe",
"name": "John Doe",
"type": "Person",
"properties": {
"role": "Software Engineer",
"expertise": "AI/ML",
"years_experience": 5
}
}
]
\`\`\``;
const entities = await this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.8,
maxTokens: Math.min(8000, options.entities * 100)
});
return entities;
}
/**
* Generate relationships between entities
*/
async generateRelationships(entities, options) {
const relationshipTypes = options.relationshipTypes || DEFAULT_RELATIONSHIP_TYPES;
const systemPrompt = `You are an expert at creating meaningful relationships in knowledge graphs. Create realistic relationships that make sense for ${options.domain}.`;
const entityList = entities.slice(0, 50).map(e => `- ${e.id}: ${e.name} (${e.type})`).join('\n');
const userPrompt = `Given these entities from a ${options.domain} knowledge graph:
${entityList}
Generate ${options.relationships} meaningful relationships between them.
Relationship types to use: ${relationshipTypes.join(', ')}
For each relationship, provide:
- source: source entity id
- target: target entity id
- type: relationship type (use one of the specified types)
- properties: optional properties describing the relationship
Return a JSON array of relationships. Make them logical and realistic.
Example format:
\`\`\`json
[
{
"source": "john_doe",
"target": "acme_corp",
"type": "WORKS_FOR",
"properties": {
"since": "2020",
"position": "Senior Engineer"
}
}
]
\`\`\``;
const relationships = await this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, options.relationships * 80)
});
return relationships;
}
/**
* Generate knowledge triples (subject-predicate-object)
*/
async generateTriples(domain, count) {
const systemPrompt = `You are an expert at extracting knowledge triples from domains. Generate meaningful subject-predicate-object triples about ${domain}.`;
const userPrompt = `Generate ${count} knowledge triples about ${domain}.
Each triple should have:
- subject: the entity or concept
- predicate: the relationship or property
- object: the related entity, value, or concept
- confidence: confidence score (0-1)
Return a JSON array of triples.
Example format:
\`\`\`json
[
{
"subject": "Einstein",
"predicate": "developed",
"object": "Theory of Relativity",
"confidence": 1.0
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, { temperature: 0.7, maxTokens: count * 100 });
}
}
exports.KnowledgeGraphGenerator = KnowledgeGraphGenerator;
/**
* Create a knowledge graph generator
*/
function createKnowledgeGraphGenerator(client) {
return new KnowledgeGraphGenerator(client);
}
//# sourceMappingURL=knowledge-graph.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"knowledge-graph.js","sourceRoot":"","sources":["knowledge-graph.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,248 @@
/**
* Knowledge graph generator using OpenRouter/Kimi K2
*/
import { OpenRouterClient } from '../openrouter-client.js';
import {
KnowledgeGraphOptions,
GraphData,
GraphNode,
GraphEdge,
GraphGenerationResult,
KnowledgeTriple
} from '../types.js';
interface EntityData {
id: string;
name: string;
type: string;
properties: Record<string, unknown>;
}
interface RelationshipData {
source: string;
target: string;
type: string;
properties?: Record<string, unknown>;
}
const DEFAULT_ENTITY_TYPES = [
'Person',
'Organization',
'Location',
'Event',
'Concept',
'Technology',
'Product'
];
const DEFAULT_RELATIONSHIP_TYPES = [
'WORKS_FOR',
'LOCATED_IN',
'CREATED_BY',
'PART_OF',
'RELATED_TO',
'INFLUENCES',
'DEPENDS_ON'
];
export class KnowledgeGraphGenerator {
constructor(private client: OpenRouterClient) {}
/**
* Generate a knowledge graph
*/
async generate(options: KnowledgeGraphOptions): Promise<GraphGenerationResult<GraphData>> {
const startTime = Date.now();
// Generate entities first
const entities = await this.generateEntities(options);
// Generate relationships between entities
const relationships = await this.generateRelationships(entities, options);
// Convert to graph structure
const nodes: GraphNode[] = entities.map((entity, idx) => ({
id: entity.id || `entity_${idx}`,
labels: [entity.type || 'Entity'],
properties: {
name: entity.name,
...entity.properties
}
}));
const edges: GraphEdge[] = relationships.map((rel, idx) => ({
id: `rel_${idx}`,
type: rel.type,
source: rel.source,
target: rel.target,
properties: rel.properties || {}
}));
const data: GraphData = {
nodes,
edges,
metadata: {
domain: options.domain,
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate entities for the knowledge graph
*/
private async generateEntities(options: KnowledgeGraphOptions): Promise<Array<{
id: string;
name: string;
type: string;
properties: Record<string, unknown>;
}>> {
const entityTypes = options.entityTypes || DEFAULT_ENTITY_TYPES;
const systemPrompt = `You are an expert knowledge graph architect. Generate realistic entities for a knowledge graph about ${options.domain}.`;
const userPrompt = `Generate ${options.entities} diverse entities for a knowledge graph about ${options.domain}.
Entity types to include: ${entityTypes.join(', ')}
For each entity, provide:
- id: unique identifier (use snake_case)
- name: entity name
- type: one of the specified entity types
- properties: relevant properties (at least 2-3 properties per entity)
Return a JSON array of entities. Make them realistic and relevant to ${options.domain}.
Example format:
\`\`\`json
[
{
"id": "john_doe",
"name": "John Doe",
"type": "Person",
"properties": {
"role": "Software Engineer",
"expertise": "AI/ML",
"years_experience": 5
}
}
]
\`\`\``;
const entities = await this.client.generateStructured<EntityData[]>(systemPrompt, userPrompt, {
temperature: 0.8,
maxTokens: Math.min(8000, options.entities * 100)
});
return entities;
}
/**
* Generate relationships between entities
*/
private async generateRelationships(
entities: EntityData[],
options: KnowledgeGraphOptions
): Promise<RelationshipData[]> {
const relationshipTypes = options.relationshipTypes || DEFAULT_RELATIONSHIP_TYPES;
const systemPrompt = `You are an expert at creating meaningful relationships in knowledge graphs. Create realistic relationships that make sense for ${options.domain}.`;
const entityList = entities.slice(0, 50).map(e => `- ${e.id}: ${e.name} (${e.type})`).join('\n');
const userPrompt = `Given these entities from a ${options.domain} knowledge graph:
${entityList}
Generate ${options.relationships} meaningful relationships between them.
Relationship types to use: ${relationshipTypes.join(', ')}
For each relationship, provide:
- source: source entity id
- target: target entity id
- type: relationship type (use one of the specified types)
- properties: optional properties describing the relationship
Return a JSON array of relationships. Make them logical and realistic.
Example format:
\`\`\`json
[
{
"source": "john_doe",
"target": "acme_corp",
"type": "WORKS_FOR",
"properties": {
"since": "2020",
"position": "Senior Engineer"
}
}
]
\`\`\``;
const relationships = await this.client.generateStructured<RelationshipData[]>(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, options.relationships * 80)
});
return relationships;
}
/**
* Generate knowledge triples (subject-predicate-object)
*/
async generateTriples(
domain: string,
count: number
): Promise<KnowledgeTriple[]> {
const systemPrompt = `You are an expert at extracting knowledge triples from domains. Generate meaningful subject-predicate-object triples about ${domain}.`;
const userPrompt = `Generate ${count} knowledge triples about ${domain}.
Each triple should have:
- subject: the entity or concept
- predicate: the relationship or property
- object: the related entity, value, or concept
- confidence: confidence score (0-1)
Return a JSON array of triples.
Example format:
\`\`\`json
[
{
"subject": "Einstein",
"predicate": "developed",
"object": "Theory of Relativity",
"confidence": 1.0
}
]
\`\`\``;
return this.client.generateStructured<KnowledgeTriple[]>(
systemPrompt,
userPrompt,
{ temperature: 0.7, maxTokens: count * 100 }
);
}
}
/**
* Create a knowledge graph generator
*/
export function createKnowledgeGraphGenerator(client: OpenRouterClient): KnowledgeGraphGenerator {
return new KnowledgeGraphGenerator(client);
}

View File

@@ -0,0 +1,39 @@
/**
* Social network generator using OpenRouter/Kimi K2
*/
import { OpenRouterClient } from '../openrouter-client.js';
import { SocialNetworkOptions, GraphData, GraphGenerationResult } from '../types.js';
export declare class SocialNetworkGenerator {
private client;
constructor(client: OpenRouterClient);
/**
* Generate a social network graph
*/
generate(options: SocialNetworkOptions): Promise<GraphGenerationResult<GraphData>>;
/**
* Generate realistic social network users
*/
private generateUsers;
/**
* Generate connections between users
*/
private generateConnections;
/**
* Get guidance for network type
*/
private getNetworkTypeGuidance;
/**
* Analyze network properties
*/
analyzeNetwork(data: GraphData): Promise<{
avgDegree: number;
maxDegree: number;
communities?: number;
clustering?: number;
}>;
}
/**
* Create a social network generator
*/
export declare function createSocialNetworkGenerator(client: OpenRouterClient): SocialNetworkGenerator;
//# sourceMappingURL=social-network.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"social-network.d.ts","sourceRoot":"","sources":["social-network.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,oBAAoB,EAEpB,SAAS,EAGT,qBAAqB,EACtB,MAAM,aAAa,CAAC;AASrB,qBAAa,sBAAsB;IACrB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAiDxF;;OAEG;YACW,aAAa;IA6C3B;;OAEG;YACW,mBAAmB;IA+CjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7C,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CAiBH;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,gBAAgB,GAAG,sBAAsB,CAE7F"}

View File

@@ -0,0 +1,180 @@
"use strict";
/**
* Social network generator using OpenRouter/Kimi K2
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SocialNetworkGenerator = void 0;
exports.createSocialNetworkGenerator = createSocialNetworkGenerator;
class SocialNetworkGenerator {
constructor(client) {
this.client = client;
}
/**
* Generate a social network graph
*/
async generate(options) {
const startTime = Date.now();
// Generate users
const users = await this.generateUsers(options);
// Generate connections based on network type
const connections = await this.generateConnections(users, options);
// Convert to graph structure
const nodes = users.map(user => ({
id: user.id,
labels: ['User'],
properties: {
username: user.username,
...user.profile,
...(user.metadata || {})
}
}));
const edges = connections.map((conn, idx) => ({
id: `connection_${idx}`,
type: conn.type || 'FOLLOWS',
source: conn.source,
target: conn.target,
properties: conn.properties || {}
}));
const data = {
nodes,
edges,
metadata: {
domain: 'social-network',
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate realistic social network users
*/
async generateUsers(options) {
const systemPrompt = 'You are an expert at creating realistic social network user profiles. Generate diverse, believable users.';
const userPrompt = `Generate ${options.users} realistic social network user profiles.
Each user should have:
- id: unique user ID (format: user_XXXXX)
- username: unique username
- profile: object with name, bio, joined (ISO date), followers (number), following (number)
${options.includeMetadata ? '- metadata: additional information like interests, location, verified status' : ''}
Make the profiles diverse and realistic. Return a JSON array.
Example format:
\`\`\`json
[
{
"id": "user_12345",
"username": "tech_enthusiast_42",
"profile": {
"name": "Alex Johnson",
"bio": "Software developer passionate about AI and open source",
"joined": "2020-03-15T00:00:00Z",
"followers": 1250,
"following": 430
}${options.includeMetadata ? `,
"metadata": {
"interests": ["technology", "AI", "coding"],
"location": "San Francisco, CA",
"verified": false
}` : ''}
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.9,
maxTokens: Math.min(8000, options.users * 150)
});
}
/**
* Generate connections between users
*/
async generateConnections(users, options) {
const totalConnections = Math.floor(options.users * options.avgConnections / 2);
const systemPrompt = `You are an expert at modeling social network connections. Create realistic ${options.networkType || 'random'} network patterns.`;
const userList = users.slice(0, 100).map(u => `- ${u.id}: @${u.username}`).join('\n');
const userPrompt = `Given these social network users:
${userList}
Generate ${totalConnections} connections creating a ${options.networkType || 'random'} network structure.
${this.getNetworkTypeGuidance(options.networkType)}
Each connection should have:
- source: user id who initiates the connection
- target: user id being connected to
- type: connection type (FOLLOWS, FRIEND, BLOCKS, MUTES)
- properties: optional properties like since (ISO date), strength (0-1)
Return a JSON array of connections.
Example format:
\`\`\`json
[
{
"source": "user_12345",
"target": "user_67890",
"type": "FOLLOWS",
"properties": {
"since": "2021-06-15T00:00:00Z",
"strength": 0.8
}
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, totalConnections * 80)
});
}
/**
* Get guidance for network type
*/
getNetworkTypeGuidance(networkType) {
switch (networkType) {
case 'small-world':
return 'Create clusters of highly connected users with occasional bridges between clusters (small-world property).';
case 'scale-free':
return 'Create a power-law distribution where a few users have many connections (influencers) and most have few connections.';
case 'clustered':
return 'Create distinct communities/clusters with high internal connectivity and sparse connections between clusters.';
default:
return 'Create random connections with varying connection strengths.';
}
}
/**
* Analyze network properties
*/
async analyzeNetwork(data) {
const degrees = new Map();
for (const edge of data.edges) {
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
}
const degreeValues = Array.from(degrees.values());
const avgDegree = degreeValues.reduce((a, b) => a + b, 0) / degreeValues.length;
const maxDegree = Math.max(...degreeValues);
return {
avgDegree,
maxDegree
};
}
}
exports.SocialNetworkGenerator = SocialNetworkGenerator;
/**
* Create a social network generator
*/
function createSocialNetworkGenerator(client) {
return new SocialNetworkGenerator(client);
}
//# sourceMappingURL=social-network.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"social-network.js","sourceRoot":"","sources":["social-network.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,223 @@
/**
* Social network generator using OpenRouter/Kimi K2
*/
import { OpenRouterClient } from '../openrouter-client.js';
import {
SocialNetworkOptions,
SocialNode,
GraphData,
GraphNode,
GraphEdge,
GraphGenerationResult
} from '../types.js';
interface ConnectionData {
source: string;
target: string;
type: string;
properties?: Record<string, unknown>;
}
export class SocialNetworkGenerator {
constructor(private client: OpenRouterClient) {}
/**
* Generate a social network graph
*/
async generate(options: SocialNetworkOptions): Promise<GraphGenerationResult<GraphData>> {
const startTime = Date.now();
// Generate users
const users = await this.generateUsers(options);
// Generate connections based on network type
const connections = await this.generateConnections(users, options);
// Convert to graph structure
const nodes: GraphNode[] = users.map(user => ({
id: user.id,
labels: ['User'],
properties: {
username: user.username,
...user.profile,
...(user.metadata || {})
}
}));
const edges: GraphEdge[] = connections.map((conn, idx) => ({
id: `connection_${idx}`,
type: conn.type || 'FOLLOWS',
source: conn.source,
target: conn.target,
properties: conn.properties || {}
}));
const data: GraphData = {
nodes,
edges,
metadata: {
domain: 'social-network',
generated_at: new Date(),
total_nodes: nodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate realistic social network users
*/
private async generateUsers(options: SocialNetworkOptions): Promise<SocialNode[]> {
const systemPrompt = 'You are an expert at creating realistic social network user profiles. Generate diverse, believable users.';
const userPrompt = `Generate ${options.users} realistic social network user profiles.
Each user should have:
- id: unique user ID (format: user_XXXXX)
- username: unique username
- profile: object with name, bio, joined (ISO date), followers (number), following (number)
${options.includeMetadata ? '- metadata: additional information like interests, location, verified status' : ''}
Make the profiles diverse and realistic. Return a JSON array.
Example format:
\`\`\`json
[
{
"id": "user_12345",
"username": "tech_enthusiast_42",
"profile": {
"name": "Alex Johnson",
"bio": "Software developer passionate about AI and open source",
"joined": "2020-03-15T00:00:00Z",
"followers": 1250,
"following": 430
}${options.includeMetadata ? `,
"metadata": {
"interests": ["technology", "AI", "coding"],
"location": "San Francisco, CA",
"verified": false
}` : ''}
}
]
\`\`\``;
return this.client.generateStructured<SocialNode[]>(
systemPrompt,
userPrompt,
{
temperature: 0.9,
maxTokens: Math.min(8000, options.users * 150)
}
);
}
/**
* Generate connections between users
*/
private async generateConnections(
users: SocialNode[],
options: SocialNetworkOptions
): Promise<ConnectionData[]> {
const totalConnections = Math.floor(options.users * options.avgConnections / 2);
const systemPrompt = `You are an expert at modeling social network connections. Create realistic ${options.networkType || 'random'} network patterns.`;
const userList = users.slice(0, 100).map(u => `- ${u.id}: @${u.username}`).join('\n');
const userPrompt = `Given these social network users:
${userList}
Generate ${totalConnections} connections creating a ${options.networkType || 'random'} network structure.
${this.getNetworkTypeGuidance(options.networkType)}
Each connection should have:
- source: user id who initiates the connection
- target: user id being connected to
- type: connection type (FOLLOWS, FRIEND, BLOCKS, MUTES)
- properties: optional properties like since (ISO date), strength (0-1)
Return a JSON array of connections.
Example format:
\`\`\`json
[
{
"source": "user_12345",
"target": "user_67890",
"type": "FOLLOWS",
"properties": {
"since": "2021-06-15T00:00:00Z",
"strength": 0.8
}
}
]
\`\`\``;
return this.client.generateStructured<ConnectionData[]>(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, totalConnections * 80)
});
}
/**
* Get guidance for network type
*/
private getNetworkTypeGuidance(networkType?: string): string {
switch (networkType) {
case 'small-world':
return 'Create clusters of highly connected users with occasional bridges between clusters (small-world property).';
case 'scale-free':
return 'Create a power-law distribution where a few users have many connections (influencers) and most have few connections.';
case 'clustered':
return 'Create distinct communities/clusters with high internal connectivity and sparse connections between clusters.';
default:
return 'Create random connections with varying connection strengths.';
}
}
/**
* Analyze network properties
*/
async analyzeNetwork(data: GraphData): Promise<{
avgDegree: number;
maxDegree: number;
communities?: number;
clustering?: number;
}> {
const degrees = new Map<string, number>();
for (const edge of data.edges) {
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
}
const degreeValues = Array.from(degrees.values());
const avgDegree = degreeValues.reduce((a, b) => a + b, 0) / degreeValues.length;
const maxDegree = Math.max(...degreeValues);
return {
avgDegree,
maxDegree
};
}
}
/**
* Create a social network generator
*/
export function createSocialNetworkGenerator(client: OpenRouterClient): SocialNetworkGenerator {
return new SocialNetworkGenerator(client);
}

View File

@@ -0,0 +1,34 @@
/**
* Temporal events generator for time-series graph data
*/
import { OpenRouterClient } from '../openrouter-client.js';
import { TemporalEventOptions, TemporalEvent, GraphData, GraphGenerationResult } from '../types.js';
export declare class TemporalEventsGenerator {
private client;
constructor(client: OpenRouterClient);
/**
* Generate temporal event graph data
*/
generate(options: TemporalEventOptions): Promise<GraphGenerationResult<GraphData>>;
/**
* Generate temporal events
*/
private generateEvents;
/**
* Generate entities from events
*/
private generateEntities;
/**
* Analyze temporal patterns
*/
analyzeTemporalPatterns(events: TemporalEvent[]): Promise<{
eventsPerHour: Record<string, number>;
eventTypeDistribution: Record<string, number>;
avgTimeBetweenEvents: number;
}>;
}
/**
* Create a temporal events generator
*/
export declare function createTemporalEventsGenerator(client: OpenRouterClient): TemporalEventsGenerator;
//# sourceMappingURL=temporal-events.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"temporal-events.d.ts","sourceRoot":"","sources":["temporal-events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,SAAS,EAGT,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAQrB,qBAAa,uBAAuB;IACtB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAiGxF;;OAEG;YACW,cAAc;IA+D5B;;OAEG;YACW,gBAAgB;IAiD9B;;OAEG;IACG,uBAAuB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;QAC9D,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9C,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;CAgCH;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,gBAAgB,GAAG,uBAAuB,CAE/F"}

View File

@@ -0,0 +1,232 @@
"use strict";
/**
* Temporal events generator for time-series graph data
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemporalEventsGenerator = void 0;
exports.createTemporalEventsGenerator = createTemporalEventsGenerator;
class TemporalEventsGenerator {
constructor(client) {
this.client = client;
}
/**
* Generate temporal event graph data
*/
async generate(options) {
const startTime = Date.now();
// Generate events
const events = await this.generateEvents(options);
// Generate entities involved in events
const entities = await this.generateEntities(events, options);
// Convert to graph structure
const eventNodes = events.map(event => ({
id: event.id,
labels: ['Event', event.type],
properties: {
type: event.type,
timestamp: event.timestamp.toISOString(),
...event.properties
}
}));
const entityNodes = entities.map(entity => ({
id: entity.id,
labels: ['Entity', entity.type],
properties: entity.properties
}));
const edges = [];
let edgeId = 0;
// Create edges between events and entities
for (const event of events) {
for (const entityId of event.entities) {
edges.push({
id: `edge_${edgeId++}`,
type: 'INVOLVES',
source: event.id,
target: entityId,
properties: {
timestamp: event.timestamp.toISOString()
}
});
}
// Create edges for relationships
if (event.relationships) {
for (const rel of event.relationships) {
edges.push({
id: `edge_${edgeId++}`,
type: rel.type,
source: event.id,
target: rel.target,
properties: {
timestamp: event.timestamp.toISOString()
}
});
}
}
}
// Create temporal sequences (NEXT relationships)
const sortedEvents = [...events].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
for (let i = 0; i < sortedEvents.length - 1; i++) {
edges.push({
id: `edge_${edgeId++}`,
type: 'NEXT',
source: sortedEvents[i].id,
target: sortedEvents[i + 1].id,
properties: {
time_diff_ms: sortedEvents[i + 1].timestamp.getTime() - sortedEvents[i].timestamp.getTime()
}
});
}
const data = {
nodes: [...eventNodes, ...entityNodes],
edges,
metadata: {
domain: 'temporal-events',
generated_at: new Date(),
total_nodes: eventNodes.length + entityNodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate temporal events
*/
async generateEvents(options) {
const startDate = new Date(options.startDate);
const endDate = new Date(options.endDate);
const daysDiff = Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
const totalEvents = (options.eventsPerDay || 10) * daysDiff;
const systemPrompt = 'You are an expert at generating realistic temporal event sequences. Create events that follow logical patterns and causality.';
const userPrompt = `Generate ${totalEvents} temporal events between ${startDate.toISOString()} and ${endDate.toISOString()}.
Event types to include: ${options.eventTypes.join(', ')}
Each event should have:
- id: unique event ID (format: event_XXXXX)
- type: one of the specified event types
- timestamp: ISO 8601 timestamp within the date range
- entities: array of entity IDs involved (format: entity_XXXXX)
- properties: relevant properties for the event
- relationships: (optional) array of relationships to other events/entities
Create realistic temporal patterns (e.g., business hours for work events, clustering of related events).
Return a JSON array sorted by timestamp.
Example format:
\`\`\`json
[
{
"id": "event_00001",
"type": "login",
"timestamp": "2024-01-15T09:23:15Z",
"entities": ["entity_user_001"],
"properties": {
"ip_address": "192.168.1.100",
"device": "desktop",
"success": true
},
"relationships": [
{
"type": "TRIGGERED_BY",
"target": "entity_user_001"
}
]
}
]
\`\`\``;
const events = await this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.8,
maxTokens: Math.min(8000, totalEvents * 150)
});
// Convert timestamp strings to Date objects
return events.map(event => ({
...event,
timestamp: new Date(event.timestamp)
}));
}
/**
* Generate entities from events
*/
async generateEntities(events, options) {
const uniqueEntityIds = new Set();
events.forEach(event => {
event.entities.forEach(entityId => uniqueEntityIds.add(entityId));
});
const entityIds = Array.from(uniqueEntityIds);
const entityCount = options.entities || entityIds.length;
const systemPrompt = 'You are an expert at creating entity profiles for event-driven systems.';
const sampleIds = entityIds.slice(0, 50).join(', ');
const userPrompt = `Generate ${entityCount} entity profiles for entities involved in temporal events.
Sample entity IDs that must be included: ${sampleIds}
Each entity should have:
- id: the entity ID
- type: entity type (User, System, Device, Service, etc.)
- properties: relevant properties for the entity
Return a JSON array of entities.
Example format:
\`\`\`json
[
{
"id": "entity_user_001",
"type": "User",
"properties": {
"name": "Alice Smith",
"email": "alice@example.com",
"role": "developer",
"created_at": "2023-01-15T00:00:00Z"
}
}
]
\`\`\``;
return this.client.generateStructured(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, entityCount * 100)
});
}
/**
* Analyze temporal patterns
*/
async analyzeTemporalPatterns(events) {
const eventsPerHour = {};
const eventTypeDistribution = {};
const timeDiffs = [];
const sortedEvents = [...events].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
for (let i = 0; i < sortedEvents.length; i++) {
const event = sortedEvents[i];
const hour = event.timestamp.toISOString().substring(0, 13);
eventsPerHour[hour] = (eventsPerHour[hour] || 0) + 1;
eventTypeDistribution[event.type] = (eventTypeDistribution[event.type] || 0) + 1;
if (i > 0) {
timeDiffs.push(event.timestamp.getTime() - sortedEvents[i - 1].timestamp.getTime());
}
}
const avgTimeBetweenEvents = timeDiffs.length > 0
? timeDiffs.reduce((a, b) => a + b, 0) / timeDiffs.length
: 0;
return {
eventsPerHour,
eventTypeDistribution,
avgTimeBetweenEvents
};
}
}
exports.TemporalEventsGenerator = TemporalEventsGenerator;
/**
* Create a temporal events generator
*/
function createTemporalEventsGenerator(client) {
return new TemporalEventsGenerator(client);
}
//# sourceMappingURL=temporal-events.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,288 @@
/**
* Temporal events generator for time-series graph data
*/
import { OpenRouterClient } from '../openrouter-client.js';
import {
TemporalEventOptions,
TemporalEvent,
GraphData,
GraphNode,
GraphEdge,
GraphGenerationResult
} from '../types.js';
interface EntityData {
id: string;
type: string;
properties: Record<string, unknown>;
}
export class TemporalEventsGenerator {
constructor(private client: OpenRouterClient) {}
/**
* Generate temporal event graph data
*/
async generate(options: TemporalEventOptions): Promise<GraphGenerationResult<GraphData>> {
const startTime = Date.now();
// Generate events
const events = await this.generateEvents(options);
// Generate entities involved in events
const entities = await this.generateEntities(events, options);
// Convert to graph structure
const eventNodes: GraphNode[] = events.map(event => ({
id: event.id,
labels: ['Event', event.type],
properties: {
type: event.type,
timestamp: event.timestamp.toISOString(),
...event.properties
}
}));
const entityNodes: GraphNode[] = entities.map(entity => ({
id: entity.id,
labels: ['Entity', entity.type],
properties: entity.properties
}));
const edges: GraphEdge[] = [];
let edgeId = 0;
// Create edges between events and entities
for (const event of events) {
for (const entityId of event.entities) {
edges.push({
id: `edge_${edgeId++}`,
type: 'INVOLVES',
source: event.id,
target: entityId,
properties: {
timestamp: event.timestamp.toISOString()
}
});
}
// Create edges for relationships
if (event.relationships) {
for (const rel of event.relationships) {
edges.push({
id: `edge_${edgeId++}`,
type: rel.type,
source: event.id,
target: rel.target,
properties: {
timestamp: event.timestamp.toISOString()
}
});
}
}
}
// Create temporal sequences (NEXT relationships)
const sortedEvents = [...events].sort((a, b) =>
a.timestamp.getTime() - b.timestamp.getTime()
);
for (let i = 0; i < sortedEvents.length - 1; i++) {
edges.push({
id: `edge_${edgeId++}`,
type: 'NEXT',
source: sortedEvents[i].id,
target: sortedEvents[i + 1].id,
properties: {
time_diff_ms: sortedEvents[i + 1].timestamp.getTime() - sortedEvents[i].timestamp.getTime()
}
});
}
const data: GraphData = {
nodes: [...eventNodes, ...entityNodes],
edges,
metadata: {
domain: 'temporal-events',
generated_at: new Date(),
total_nodes: eventNodes.length + entityNodes.length,
total_edges: edges.length
}
};
return {
data,
metadata: {
generated_at: new Date(),
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
duration: Date.now() - startTime
}
};
}
/**
* Generate temporal events
*/
private async generateEvents(options: TemporalEventOptions): Promise<TemporalEvent[]> {
const startDate = new Date(options.startDate);
const endDate = new Date(options.endDate);
const daysDiff = Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
const totalEvents = (options.eventsPerDay || 10) * daysDiff;
const systemPrompt = 'You are an expert at generating realistic temporal event sequences. Create events that follow logical patterns and causality.';
const userPrompt = `Generate ${totalEvents} temporal events between ${startDate.toISOString()} and ${endDate.toISOString()}.
Event types to include: ${options.eventTypes.join(', ')}
Each event should have:
- id: unique event ID (format: event_XXXXX)
- type: one of the specified event types
- timestamp: ISO 8601 timestamp within the date range
- entities: array of entity IDs involved (format: entity_XXXXX)
- properties: relevant properties for the event
- relationships: (optional) array of relationships to other events/entities
Create realistic temporal patterns (e.g., business hours for work events, clustering of related events).
Return a JSON array sorted by timestamp.
Example format:
\`\`\`json
[
{
"id": "event_00001",
"type": "login",
"timestamp": "2024-01-15T09:23:15Z",
"entities": ["entity_user_001"],
"properties": {
"ip_address": "192.168.1.100",
"device": "desktop",
"success": true
},
"relationships": [
{
"type": "TRIGGERED_BY",
"target": "entity_user_001"
}
]
}
]
\`\`\``;
const events = await this.client.generateStructured<TemporalEvent[]>(
systemPrompt,
userPrompt,
{
temperature: 0.8,
maxTokens: Math.min(8000, totalEvents * 150)
}
);
// Convert timestamp strings to Date objects
return events.map(event => ({
...event,
timestamp: new Date(event.timestamp)
}));
}
/**
* Generate entities from events
*/
private async generateEntities(
events: TemporalEvent[],
options: TemporalEventOptions
): Promise<EntityData[]> {
const uniqueEntityIds = new Set<string>();
events.forEach(event => {
event.entities.forEach(entityId => uniqueEntityIds.add(entityId));
});
const entityIds = Array.from(uniqueEntityIds);
const entityCount = options.entities || entityIds.length;
const systemPrompt = 'You are an expert at creating entity profiles for event-driven systems.';
const sampleIds = entityIds.slice(0, 50).join(', ');
const userPrompt = `Generate ${entityCount} entity profiles for entities involved in temporal events.
Sample entity IDs that must be included: ${sampleIds}
Each entity should have:
- id: the entity ID
- type: entity type (User, System, Device, Service, etc.)
- properties: relevant properties for the entity
Return a JSON array of entities.
Example format:
\`\`\`json
[
{
"id": "entity_user_001",
"type": "User",
"properties": {
"name": "Alice Smith",
"email": "alice@example.com",
"role": "developer",
"created_at": "2023-01-15T00:00:00Z"
}
}
]
\`\`\``;
return this.client.generateStructured<EntityData[]>(systemPrompt, userPrompt, {
temperature: 0.7,
maxTokens: Math.min(8000, entityCount * 100)
});
}
/**
* Analyze temporal patterns
*/
async analyzeTemporalPatterns(events: TemporalEvent[]): Promise<{
eventsPerHour: Record<string, number>;
eventTypeDistribution: Record<string, number>;
avgTimeBetweenEvents: number;
}> {
const eventsPerHour: Record<string, number> = {};
const eventTypeDistribution: Record<string, number> = {};
const timeDiffs: number[] = [];
const sortedEvents = [...events].sort((a, b) =>
a.timestamp.getTime() - b.timestamp.getTime()
);
for (let i = 0; i < sortedEvents.length; i++) {
const event = sortedEvents[i];
const hour = event.timestamp.toISOString().substring(0, 13);
eventsPerHour[hour] = (eventsPerHour[hour] || 0) + 1;
eventTypeDistribution[event.type] = (eventTypeDistribution[event.type] || 0) + 1;
if (i > 0) {
timeDiffs.push(
event.timestamp.getTime() - sortedEvents[i - 1].timestamp.getTime()
);
}
}
const avgTimeBetweenEvents = timeDiffs.length > 0
? timeDiffs.reduce((a, b) => a + b, 0) / timeDiffs.length
: 0;
return {
eventsPerHour,
eventTypeDistribution,
avgTimeBetweenEvents
};
}
}
/**
* Create a temporal events generator
*/
export function createTemporalEventsGenerator(client: OpenRouterClient): TemporalEventsGenerator {
return new TemporalEventsGenerator(client);
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAA0B,MAAM,wBAAwB,CAAC;AAiBlF,OAAO,EAAE,eAAe,EAAyB,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAA6B,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,SAAS,EACT,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,qBAAqB,CAA8B;IAC3D,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,mBAAmB,CAAC,CAAsB;gBAEtC,MAAM,GAAE,OAAO,CAAC,gBAAgB,CAAM;IASlD;;OAEG;IACG,sBAAsB,CAC1B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAgB5C;;OAEG;IACG,qBAAqB,CACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAc5C;;OAEG;IACG,sBAAsB,CAC1B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAc5C;;OAEG;IACG,2BAA2B,CAC/B,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAc5C;;OAEG;IACG,oBAAoB,CACxB,IAAI,EAAE,SAAS,EACf,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,OAAO,CAAC,SAAS,CAAC;IAQrB;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE;QACxC,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GAAG,MAAM;IAIV;;OAEG;IACH,SAAS,IAAI,gBAAgB;IAI7B;;OAEG;IACH,kBAAkB,IAAI,eAAe;IAIrC;;OAEG;IACH,sBAAsB,IAAI,mBAAmB,GAAG,SAAS;CAG1D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GACjC,kBAAkB,CAEpB;AAGD,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,eAAe,kBAAkB,CAAC"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,202 @@
/**
* @ruvector/graph-data-generator - AI-powered synthetic graph data generation
*
* @packageDocumentation
*/
import 'dotenv/config';
import { OpenRouterClient, createOpenRouterClient } from './openrouter-client.js';
import {
KnowledgeGraphGenerator,
createKnowledgeGraphGenerator
} from './generators/knowledge-graph.js';
import {
SocialNetworkGenerator,
createSocialNetworkGenerator
} from './generators/social-network.js';
import {
TemporalEventsGenerator,
createTemporalEventsGenerator
} from './generators/temporal-events.js';
import {
EntityRelationshipGenerator,
createEntityRelationshipGenerator
} from './generators/entity-relationships.js';
import { CypherGenerator, createCypherGenerator } from './cypher-generator.js';
import { EmbeddingEnrichment, createEmbeddingEnrichment } from './embedding-enrichment.js';
import {
OpenRouterConfig,
KnowledgeGraphOptions,
SocialNetworkOptions,
TemporalEventOptions,
EntityRelationshipOptions,
GraphGenerationResult,
GraphData,
EmbeddingConfig
} from './types.js';
/**
* Main GraphDataGenerator class
*/
export class GraphDataGenerator {
private client: OpenRouterClient;
private knowledgeGraphGen: KnowledgeGraphGenerator;
private socialNetworkGen: SocialNetworkGenerator;
private temporalEventsGen: TemporalEventsGenerator;
private entityRelationshipGen: EntityRelationshipGenerator;
private cypherGen: CypherGenerator;
private embeddingEnrichment?: EmbeddingEnrichment;
constructor(config: Partial<OpenRouterConfig> = {}) {
this.client = createOpenRouterClient(config);
this.knowledgeGraphGen = createKnowledgeGraphGenerator(this.client);
this.socialNetworkGen = createSocialNetworkGenerator(this.client);
this.temporalEventsGen = createTemporalEventsGenerator(this.client);
this.entityRelationshipGen = createEntityRelationshipGenerator(this.client);
this.cypherGen = createCypherGenerator();
}
/**
* Generate a knowledge graph
*/
async generateKnowledgeGraph(
options: KnowledgeGraphOptions
): Promise<GraphGenerationResult<GraphData>> {
const result = await this.knowledgeGraphGen.generate(options);
// Add embeddings if requested
if (options.includeEmbeddings) {
result.data = await this.enrichWithEmbeddings(result.data, {
dimensions: options.embeddingDimension
});
}
// Generate Cypher statements
result.cypher = this.cypherGen.generate(result.data);
return result;
}
/**
* Generate a social network
*/
async generateSocialNetwork(
options: SocialNetworkOptions
): Promise<GraphGenerationResult<GraphData>> {
const result = await this.socialNetworkGen.generate(options);
// Add embeddings if requested
if (options.includeEmbeddings) {
result.data = await this.enrichWithEmbeddings(result.data);
}
// Generate Cypher statements
result.cypher = this.cypherGen.generate(result.data);
return result;
}
/**
* Generate temporal events
*/
async generateTemporalEvents(
options: TemporalEventOptions
): Promise<GraphGenerationResult<GraphData>> {
const result = await this.temporalEventsGen.generate(options);
// Add embeddings if requested
if (options.includeEmbeddings) {
result.data = await this.enrichWithEmbeddings(result.data);
}
// Generate Cypher statements
result.cypher = this.cypherGen.generate(result.data);
return result;
}
/**
* Generate entity relationships
*/
async generateEntityRelationships(
options: EntityRelationshipOptions
): Promise<GraphGenerationResult<GraphData>> {
const result = await this.entityRelationshipGen.generate(options);
// Add embeddings if requested
if (options.includeEmbeddings) {
result.data = await this.enrichWithEmbeddings(result.data);
}
// Generate Cypher statements
result.cypher = this.cypherGen.generate(result.data);
return result;
}
/**
* Enrich graph data with embeddings
*/
async enrichWithEmbeddings(
data: GraphData,
config?: Partial<EmbeddingConfig>
): Promise<GraphData> {
if (!this.embeddingEnrichment) {
this.embeddingEnrichment = createEmbeddingEnrichment(this.client, config);
}
return this.embeddingEnrichment.enrichGraphData(data);
}
/**
* Generate Cypher statements from graph data
*/
generateCypher(data: GraphData, options?: {
useConstraints?: boolean;
useIndexes?: boolean;
useMerge?: boolean;
}): string {
return this.cypherGen.generateSetupScript(data, options);
}
/**
* Get OpenRouter client
*/
getClient(): OpenRouterClient {
return this.client;
}
/**
* Get Cypher generator
*/
getCypherGenerator(): CypherGenerator {
return this.cypherGen;
}
/**
* Get embedding enrichment
*/
getEmbeddingEnrichment(): EmbeddingEnrichment | undefined {
return this.embeddingEnrichment;
}
}
/**
* Create a new GraphDataGenerator instance
*/
export function createGraphDataGenerator(
config?: Partial<OpenRouterConfig>
): GraphDataGenerator {
return new GraphDataGenerator(config);
}
// Export all types and utilities
export * from './types.js';
export * from './openrouter-client.js';
export * from './generators/index.js';
export * from './cypher-generator.js';
export * from './embedding-enrichment.js';
export * from './schemas/index.js';
// Default export
export default GraphDataGenerator;

View File

@@ -0,0 +1,41 @@
/**
* OpenRouter API client with Kimi K2 support
*/
import { OpenRouterConfig, OpenRouterRequest, OpenRouterResponse, OpenRouterMessage } from './types.js';
export declare class OpenRouterClient {
private config;
private throttledFetch;
constructor(config?: Partial<OpenRouterConfig>);
/**
* Create a chat completion
*/
createCompletion(messages: OpenRouterMessage[], options?: Partial<Omit<OpenRouterRequest, 'messages' | 'model'>>): Promise<OpenRouterResponse>;
/**
* Create a streaming chat completion
*/
createStreamingCompletion(messages: OpenRouterMessage[], options?: Partial<Omit<OpenRouterRequest, 'messages' | 'model'>>): AsyncGenerator<string, void, unknown>;
/**
* Generate structured data using prompt engineering
*/
generateStructured<T = unknown>(systemPrompt: string, userPrompt: string, options?: {
temperature?: number;
maxTokens?: number;
}): Promise<T>;
/**
* Generate embeddings (if the model supports it)
*/
generateEmbedding(_text: string): Promise<number[]>;
/**
* Update configuration
*/
configure(config: Partial<OpenRouterConfig>): void;
/**
* Get current configuration
*/
getConfig(): OpenRouterConfig;
}
/**
* Create a new OpenRouter client
*/
export declare function createOpenRouterClient(config?: Partial<OpenRouterConfig>): OpenRouterClient;
//# sourceMappingURL=openrouter-client.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"openrouter-client.d.ts","sourceRoot":"","sources":["openrouter-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,gBAAgB,EAEhB,iBAAiB,EACjB,kBAAkB,EAElB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,cAAc,CAA2D;gBAErE,MAAM,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAmBlD;;OAEG;IACG,gBAAgB,CACpB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,OAAO,CAAC,CAAM,GACnE,OAAO,CAAC,kBAAkB,CAAC;IAgD9B;;OAEG;IACI,yBAAyB,CAC9B,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,OAAO,CAAC,CAAM,GACnE,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;IA2ExC;;OAEG;IACG,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAClC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,CAAC,CAAC;IA+Bb;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAMzD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAIlD;;OAEG;IACH,SAAS,IAAI,gBAAgB;CAG9B;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAE3F"}

View File

@@ -0,0 +1,194 @@
"use strict";
/**
* OpenRouter API client with Kimi K2 support
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenRouterClient = void 0;
exports.createOpenRouterClient = createOpenRouterClient;
const p_retry_1 = __importDefault(require("p-retry"));
const p_throttle_1 = __importDefault(require("p-throttle"));
const types_js_1 = require("./types.js");
class OpenRouterClient {
constructor(config = {}) {
const apiKey = config.apiKey || process.env.OPENROUTER_API_KEY;
if (!apiKey) {
throw new Error('OpenRouter API key is required. Set OPENROUTER_API_KEY environment variable or pass apiKey in config.');
}
this.config = types_js_1.OpenRouterConfigSchema.parse({ ...config, apiKey });
// Setup rate limiting if configured
if (this.config.rateLimit) {
this.throttledFetch = (0, p_throttle_1.default)({
limit: this.config.rateLimit.requests,
interval: this.config.rateLimit.interval
})(fetch.bind(globalThis));
}
else {
this.throttledFetch = fetch.bind(globalThis);
}
}
/**
* Create a chat completion
*/
async createCompletion(messages, options = {}) {
const request = {
model: this.config.model || 'moonshot/kimi-k2-instruct',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.max_tokens ?? 4096,
top_p: options.top_p ?? 1,
stream: false,
...options
};
return (0, p_retry_1.default)(async () => {
const response = await this.throttledFetch(`${this.config.baseURL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'HTTP-Referer': 'https://github.com/ruvnet/ruvector',
'X-Title': 'RuVector Graph Data Generator'
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.config.timeout || 60000)
});
if (!response.ok) {
const error = await response.text();
throw new types_js_1.OpenRouterError(`OpenRouter API error: ${response.status} ${response.statusText}`, { status: response.status, error });
}
const data = await response.json();
return data;
}, {
retries: this.config.maxRetries || 3,
onFailedAttempt: (error) => {
console.warn(`Attempt ${error.attemptNumber} failed. ${error.retriesLeft} retries left.`);
}
});
}
/**
* Create a streaming chat completion
*/
async *createStreamingCompletion(messages, options = {}) {
const request = {
model: this.config.model || 'moonshot/kimi-k2-instruct',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.max_tokens ?? 4096,
top_p: options.top_p ?? 1,
stream: true,
...options
};
const response = await this.throttledFetch(`${this.config.baseURL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'HTTP-Referer': 'https://github.com/ruvnet/ruvector',
'X-Title': 'RuVector Graph Data Generator'
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.config.timeout || 60000)
});
if (!response.ok) {
const error = await response.text();
throw new types_js_1.OpenRouterError(`OpenRouter API error: ${response.status} ${response.statusText}`, { status: response.status, error });
}
if (!response.body) {
throw new types_js_1.OpenRouterError('No response body received');
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done)
break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6).trim();
if (data === '[DONE]') {
return;
}
try {
const parsed = JSON.parse(data);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
yield content;
}
}
catch (e) {
console.warn('Failed to parse SSE data:', data);
}
}
}
}
}
finally {
reader.releaseLock();
}
}
/**
* Generate structured data using prompt engineering
*/
async generateStructured(systemPrompt, userPrompt, options) {
const messages = [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
];
const response = await this.createCompletion(messages, {
temperature: options?.temperature ?? 0.7,
max_tokens: options?.maxTokens ?? 4096
});
const content = response.choices[0]?.message?.content;
if (!content) {
throw new types_js_1.OpenRouterError('No content in response');
}
// Try to extract JSON from response
try {
// Look for JSON in code blocks
const jsonMatch = content.match(/```(?:json)?\s*(\{[\s\S]*?\}|\[[\s\S]*?\])\s*```/);
if (jsonMatch) {
return JSON.parse(jsonMatch[1]);
}
// Try to parse the entire response as JSON
return JSON.parse(content);
}
catch (e) {
throw new types_js_1.OpenRouterError('Failed to parse JSON from response', { content, error: e });
}
}
/**
* Generate embeddings (if the model supports it)
*/
async generateEmbedding(_text) {
// Note: Kimi K2 may not support embeddings directly
// This is a placeholder for potential future support
throw new Error('Embedding generation not yet implemented for Kimi K2');
}
/**
* Update configuration
*/
configure(config) {
this.config = types_js_1.OpenRouterConfigSchema.parse({ ...this.config, ...config });
}
/**
* Get current configuration
*/
getConfig() {
return { ...this.config };
}
}
exports.OpenRouterClient = OpenRouterClient;
/**
* Create a new OpenRouter client
*/
function createOpenRouterClient(config) {
return new OpenRouterClient(config);
}
//# sourceMappingURL=openrouter-client.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,244 @@
/**
* OpenRouter API client with Kimi K2 support
*/
import pRetry from 'p-retry';
import pThrottle from 'p-throttle';
import {
OpenRouterConfig,
OpenRouterConfigSchema,
OpenRouterRequest,
OpenRouterResponse,
OpenRouterError,
OpenRouterMessage
} from './types.js';
export class OpenRouterClient {
private config: OpenRouterConfig;
private throttledFetch: (url: string, options: RequestInit) => Promise<Response>;
constructor(config: Partial<OpenRouterConfig> = {}) {
const apiKey = config.apiKey || process.env.OPENROUTER_API_KEY;
if (!apiKey) {
throw new Error('OpenRouter API key is required. Set OPENROUTER_API_KEY environment variable or pass apiKey in config.');
}
this.config = OpenRouterConfigSchema.parse({ ...config, apiKey });
// Setup rate limiting if configured
if (this.config.rateLimit) {
this.throttledFetch = pThrottle({
limit: this.config.rateLimit.requests,
interval: this.config.rateLimit.interval
})(fetch.bind(globalThis)) as (url: string, options: RequestInit) => Promise<Response>;
} else {
this.throttledFetch = fetch.bind(globalThis);
}
}
/**
* Create a chat completion
*/
async createCompletion(
messages: OpenRouterMessage[],
options: Partial<Omit<OpenRouterRequest, 'messages' | 'model'>> = {}
): Promise<OpenRouterResponse> {
const request: OpenRouterRequest = {
model: this.config.model || 'moonshot/kimi-k2-instruct',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.max_tokens ?? 4096,
top_p: options.top_p ?? 1,
stream: false,
...options
};
return pRetry(
async () => {
const response = await this.throttledFetch(
`${this.config.baseURL}/chat/completions`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'HTTP-Referer': 'https://github.com/ruvnet/ruvector',
'X-Title': 'RuVector Graph Data Generator'
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.config.timeout || 60000)
}
);
if (!response.ok) {
const error = await response.text();
throw new OpenRouterError(
`OpenRouter API error: ${response.status} ${response.statusText}`,
{ status: response.status, error }
);
}
const data = await response.json() as OpenRouterResponse;
return data;
},
{
retries: this.config.maxRetries || 3,
onFailedAttempt: (error) => {
console.warn(`Attempt ${error.attemptNumber} failed. ${error.retriesLeft} retries left.`);
}
}
);
}
/**
* Create a streaming chat completion
*/
async *createStreamingCompletion(
messages: OpenRouterMessage[],
options: Partial<Omit<OpenRouterRequest, 'messages' | 'model'>> = {}
): AsyncGenerator<string, void, unknown> {
const request: OpenRouterRequest = {
model: this.config.model || 'moonshot/kimi-k2-instruct',
messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.max_tokens ?? 4096,
top_p: options.top_p ?? 1,
stream: true,
...options
};
const response = await this.throttledFetch(
`${this.config.baseURL}/chat/completions`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'HTTP-Referer': 'https://github.com/ruvnet/ruvector',
'X-Title': 'RuVector Graph Data Generator'
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.config.timeout || 60000)
}
);
if (!response.ok) {
const error = await response.text();
throw new OpenRouterError(
`OpenRouter API error: ${response.status} ${response.statusText}`,
{ status: response.status, error }
);
}
if (!response.body) {
throw new OpenRouterError('No response body received');
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6).trim();
if (data === '[DONE]') {
return;
}
try {
const parsed = JSON.parse(data);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
yield content;
}
} catch (e) {
console.warn('Failed to parse SSE data:', data);
}
}
}
}
} finally {
reader.releaseLock();
}
}
/**
* Generate structured data using prompt engineering
*/
async generateStructured<T = unknown>(
systemPrompt: string,
userPrompt: string,
options?: {
temperature?: number;
maxTokens?: number;
}
): Promise<T> {
const messages: OpenRouterMessage[] = [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
];
const response = await this.createCompletion(messages, {
temperature: options?.temperature ?? 0.7,
max_tokens: options?.maxTokens ?? 4096
});
const content = response.choices[0]?.message?.content;
if (!content) {
throw new OpenRouterError('No content in response');
}
// Try to extract JSON from response
try {
// Look for JSON in code blocks
const jsonMatch = content.match(/```(?:json)?\s*(\{[\s\S]*?\}|\[[\s\S]*?\])\s*```/);
if (jsonMatch) {
return JSON.parse(jsonMatch[1]) as T;
}
// Try to parse the entire response as JSON
return JSON.parse(content) as T;
} catch (e) {
throw new OpenRouterError('Failed to parse JSON from response', { content, error: e });
}
}
/**
* Generate embeddings (if the model supports it)
*/
async generateEmbedding(_text: string): Promise<number[]> {
// Note: Kimi K2 may not support embeddings directly
// This is a placeholder for potential future support
throw new Error('Embedding generation not yet implemented for Kimi K2');
}
/**
* Update configuration
*/
configure(config: Partial<OpenRouterConfig>): void {
this.config = OpenRouterConfigSchema.parse({ ...this.config, ...config });
}
/**
* Get current configuration
*/
getConfig(): OpenRouterConfig {
return { ...this.config };
}
}
/**
* Create a new OpenRouter client
*/
export function createOpenRouterClient(config?: Partial<OpenRouterConfig>): OpenRouterClient {
return new OpenRouterClient(config);
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;EAK1B,CAAC;AAGH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;EAO1B,CAAC;AAGH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU1B,CAAC;AAGH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;EAQtC,CAAC;AAGH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;EAOrC,CAAC;AAGH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;EAOrC,CAAC;AAGH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;EAO1C,CAAC;AAGH,eAAO,MAAM,qBAAqB;;;;;;;;;EAGhC,CAAC;AAGH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ5B,CAAC;AAGH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAatC,CAAC;AAGH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;EAE9C;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO;;;;;;;;EAE7D;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO;;;;;;;EAE5D;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO;;;;;;;EAE5D;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,OAAO;;;;;;;EAEjE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO;;;;;;;;;;;EAEjD;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE5D"}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,139 @@
/**
* Zod schemas for graph data validation
*/
import { z } from 'zod';
// Graph node schema
export const GraphNodeSchema = z.object({
id: z.string(),
labels: z.array(z.string()),
properties: z.record(z.string(), z.unknown()),
embedding: z.array(z.number()).optional()
});
// Graph edge schema
export const GraphEdgeSchema = z.object({
id: z.string(),
type: z.string(),
source: z.string(),
target: z.string(),
properties: z.record(z.string(), z.unknown()),
embedding: z.array(z.number()).optional()
});
// Graph data schema
export const GraphDataSchema = z.object({
nodes: z.array(GraphNodeSchema),
edges: z.array(GraphEdgeSchema),
metadata: z.object({
domain: z.string().optional(),
generated_at: z.date().optional(),
model: z.string().optional(),
total_nodes: z.number().optional(),
total_edges: z.number().optional()
}).optional()
});
// Knowledge graph options schema
export const KnowledgeGraphOptionsSchema = z.object({
domain: z.string(),
entities: z.number().positive(),
relationships: z.number().positive(),
entityTypes: z.array(z.string()).optional(),
relationshipTypes: z.array(z.string()).optional(),
includeEmbeddings: z.boolean().optional(),
embeddingDimension: z.number().positive().optional()
});
// Social network options schema
export const SocialNetworkOptionsSchema = z.object({
users: z.number().positive(),
avgConnections: z.number().positive(),
networkType: z.enum(['random', 'small-world', 'scale-free', 'clustered']).optional(),
communities: z.number().positive().optional(),
includeMetadata: z.boolean().optional(),
includeEmbeddings: z.boolean().optional()
});
// Temporal event options schema
export const TemporalEventOptionsSchema = z.object({
startDate: z.union([z.date(), z.string()]),
endDate: z.union([z.date(), z.string()]),
eventTypes: z.array(z.string()),
eventsPerDay: z.number().positive().optional(),
entities: z.number().positive().optional(),
includeEmbeddings: z.boolean().optional()
});
// Entity relationship options schema
export const EntityRelationshipOptionsSchema = z.object({
domain: z.string(),
entityCount: z.number().positive(),
relationshipDensity: z.number().min(0).max(1),
entitySchema: z.record(z.string(), z.unknown()).optional(),
relationshipTypes: z.array(z.string()).optional(),
includeEmbeddings: z.boolean().optional()
});
// Cypher statement schema
export const CypherStatementSchema = z.object({
query: z.string(),
parameters: z.record(z.string(), z.unknown()).optional()
});
// Cypher batch schema
export const CypherBatchSchema = z.object({
statements: z.array(CypherStatementSchema),
metadata: z.object({
total_nodes: z.number().optional(),
total_relationships: z.number().optional(),
labels: z.array(z.string()).optional(),
relationship_types: z.array(z.string()).optional()
}).optional()
});
// Graph generation result schema
export const GraphGenerationResultSchema = z.object({
data: GraphDataSchema,
metadata: z.object({
generated_at: z.date(),
model: z.string(),
duration: z.number(),
token_usage: z.object({
prompt_tokens: z.number(),
completion_tokens: z.number(),
total_tokens: z.number()
}).optional()
}),
cypher: CypherBatchSchema.optional()
});
// Validation helpers
export function validateGraphData(data: unknown) {
return GraphDataSchema.parse(data);
}
export function validateKnowledgeGraphOptions(options: unknown) {
return KnowledgeGraphOptionsSchema.parse(options);
}
export function validateSocialNetworkOptions(options: unknown) {
return SocialNetworkOptionsSchema.parse(options);
}
export function validateTemporalEventOptions(options: unknown) {
return TemporalEventOptionsSchema.parse(options);
}
export function validateEntityRelationshipOptions(options: unknown) {
return EntityRelationshipOptionsSchema.parse(options);
}
export function validateCypherBatch(batch: unknown) {
return CypherBatchSchema.parse(batch);
}
export function validateGraphGenerationResult(result: unknown) {
return GraphGenerationResultSchema.parse(result);
}

View File

@@ -0,0 +1,218 @@
/**
* Core types and interfaces for graph-data-generator
*/
import { z } from 'zod';
export interface GraphNode {
id: string;
labels: string[];
properties: Record<string, unknown>;
embedding?: number[];
}
export interface GraphEdge {
id: string;
type: string;
source: string;
target: string;
properties: Record<string, unknown>;
embedding?: number[];
}
export interface GraphData {
nodes: GraphNode[];
edges: GraphEdge[];
metadata?: {
domain?: string;
generated_at?: Date;
model?: string;
total_nodes?: number;
total_edges?: number;
};
}
export interface KnowledgeTriple {
subject: string;
predicate: string;
object: string;
confidence?: number;
source?: string;
}
export interface KnowledgeGraphOptions {
domain: string;
entities: number;
relationships: number;
entityTypes?: string[];
relationshipTypes?: string[];
includeEmbeddings?: boolean;
embeddingDimension?: number;
}
export interface SocialNetworkOptions {
users: number;
avgConnections: number;
networkType?: 'random' | 'small-world' | 'scale-free' | 'clustered';
communities?: number;
includeMetadata?: boolean;
includeEmbeddings?: boolean;
}
export interface SocialNode {
id: string;
username: string;
profile: {
name?: string;
bio?: string;
joined?: Date;
followers?: number;
following?: number;
};
metadata?: Record<string, unknown>;
}
export interface TemporalEventOptions {
startDate: Date | string;
endDate: Date | string;
eventTypes: string[];
eventsPerDay?: number;
entities?: number;
includeEmbeddings?: boolean;
}
export interface TemporalEvent {
id: string;
type: string;
timestamp: Date;
entities: string[];
properties: Record<string, unknown>;
relationships?: Array<{
type: string;
target: string;
}>;
}
export interface EntityRelationshipOptions {
domain: string;
entityCount: number;
relationshipDensity: number;
entitySchema?: Record<string, unknown>;
relationshipTypes?: string[];
includeEmbeddings?: boolean;
}
export interface OpenRouterConfig {
apiKey: string;
model?: string;
baseURL?: string;
timeout?: number;
maxRetries?: number;
rateLimit?: {
requests: number;
interval: number;
};
}
export declare const OpenRouterConfigSchema: z.ZodObject<{
apiKey: z.ZodString;
model: z.ZodDefault<z.ZodOptional<z.ZodString>>;
baseURL: z.ZodDefault<z.ZodOptional<z.ZodString>>;
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
maxRetries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
rateLimit: z.ZodOptional<z.ZodObject<{
requests: z.ZodNumber;
interval: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
interval: number;
requests: number;
}, {
interval: number;
requests: number;
}>>;
}, "strip", z.ZodTypeAny, {
maxRetries: number;
apiKey: string;
model: string;
timeout: number;
baseURL: string;
rateLimit?: {
interval: number;
requests: number;
} | undefined;
}, {
apiKey: string;
maxRetries?: number | undefined;
model?: string | undefined;
timeout?: number | undefined;
baseURL?: string | undefined;
rateLimit?: {
interval: number;
requests: number;
} | undefined;
}>;
export interface OpenRouterMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}
export interface OpenRouterRequest {
model: string;
messages: OpenRouterMessage[];
temperature?: number;
max_tokens?: number;
top_p?: number;
stream?: boolean;
}
export interface OpenRouterResponse {
id: string;
model: string;
choices: Array<{
message: {
role: string;
content: string;
};
finish_reason: string;
}>;
usage: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
}
export interface CypherStatement {
query: string;
parameters?: Record<string, unknown>;
}
export interface CypherBatch {
statements: CypherStatement[];
metadata?: {
total_nodes?: number;
total_relationships?: number;
labels?: string[];
relationship_types?: string[];
};
}
export interface EmbeddingConfig {
provider: 'openrouter' | 'local';
model?: string;
dimensions?: number;
batchSize?: number;
}
export interface EmbeddingResult {
embedding: number[];
model: string;
dimensions: number;
}
export interface GraphGenerationResult<T = GraphData> {
data: T;
metadata: {
generated_at: Date;
model: string;
duration: number;
token_usage?: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
};
cypher?: CypherBatch;
}
export declare class GraphGenerationError extends Error {
code: string;
details?: unknown | undefined;
constructor(message: string, code: string, details?: unknown | undefined);
}
export declare class OpenRouterError extends GraphGenerationError {
constructor(message: string, details?: unknown);
}
export declare class ValidationError extends GraphGenerationError {
constructor(message: string, details?: unknown);
}
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,43 @@
"use strict";
/**
* Core types and interfaces for graph-data-generator
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidationError = exports.OpenRouterError = exports.GraphGenerationError = exports.OpenRouterConfigSchema = void 0;
const zod_1 = require("zod");
exports.OpenRouterConfigSchema = zod_1.z.object({
apiKey: zod_1.z.string(),
model: zod_1.z.string().optional().default('moonshot/kimi-k2-instruct'),
baseURL: zod_1.z.string().optional().default('https://openrouter.ai/api/v1'),
timeout: zod_1.z.number().optional().default(60000),
maxRetries: zod_1.z.number().optional().default(3),
rateLimit: zod_1.z.object({
requests: zod_1.z.number(),
interval: zod_1.z.number()
}).optional()
});
// Error types
class GraphGenerationError extends Error {
constructor(message, code, details) {
super(message);
this.code = code;
this.details = details;
this.name = 'GraphGenerationError';
}
}
exports.GraphGenerationError = GraphGenerationError;
class OpenRouterError extends GraphGenerationError {
constructor(message, details) {
super(message, 'OPENROUTER_ERROR', details);
this.name = 'OpenRouterError';
}
}
exports.OpenRouterError = OpenRouterError;
class ValidationError extends GraphGenerationError {
constructor(message, details) {
super(message, 'VALIDATION_ERROR', details);
this.name = 'ValidationError';
}
}
exports.ValidationError = ValidationError;
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,6BAAwB;AAsHX,QAAA,sBAAsB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE;IAClB,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC;IACjE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,8BAA8B,CAAC;IACtE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7C,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,SAAS,EAAE,OAAC,CAAC,MAAM,CAAC;QAClB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;QACpB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;KACrB,CAAC,CAAC,QAAQ,EAAE;CACd,CAAC,CAAC;AA+EH,cAAc;AACd,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YACE,OAAe,EACR,IAAY,EACZ,OAAiB;QAExB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAU;QAGxB,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AATD,oDASC;AAED,MAAa,eAAgB,SAAQ,oBAAoB;IACvD,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AAED,MAAa,eAAgB,SAAQ,oBAAoB;IACvD,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC"}

View File

@@ -0,0 +1,236 @@
/**
* Core types and interfaces for graph-data-generator
*/
import { z } from 'zod';
// Graph data types
export interface GraphNode {
id: string;
labels: string[];
properties: Record<string, unknown>;
embedding?: number[];
}
export interface GraphEdge {
id: string;
type: string;
source: string;
target: string;
properties: Record<string, unknown>;
embedding?: number[];
}
export interface GraphData {
nodes: GraphNode[];
edges: GraphEdge[];
metadata?: {
domain?: string;
generated_at?: Date;
model?: string;
total_nodes?: number;
total_edges?: number;
};
}
// Knowledge graph types
export interface KnowledgeTriple {
subject: string;
predicate: string;
object: string;
confidence?: number;
source?: string;
}
export interface KnowledgeGraphOptions {
domain: string;
entities: number;
relationships: number;
entityTypes?: string[];
relationshipTypes?: string[];
includeEmbeddings?: boolean;
embeddingDimension?: number;
}
// Social network types
export interface SocialNetworkOptions {
users: number;
avgConnections: number;
networkType?: 'random' | 'small-world' | 'scale-free' | 'clustered';
communities?: number;
includeMetadata?: boolean;
includeEmbeddings?: boolean;
}
export interface SocialNode {
id: string;
username: string;
profile: {
name?: string;
bio?: string;
joined?: Date;
followers?: number;
following?: number;
};
metadata?: Record<string, unknown>;
}
// Temporal event types
export interface TemporalEventOptions {
startDate: Date | string;
endDate: Date | string;
eventTypes: string[];
eventsPerDay?: number;
entities?: number;
includeEmbeddings?: boolean;
}
export interface TemporalEvent {
id: string;
type: string;
timestamp: Date;
entities: string[];
properties: Record<string, unknown>;
relationships?: Array<{
type: string;
target: string;
}>;
}
// Entity relationship types
export interface EntityRelationshipOptions {
domain: string;
entityCount: number;
relationshipDensity: number; // 0-1
entitySchema?: Record<string, unknown>;
relationshipTypes?: string[];
includeEmbeddings?: boolean;
}
// OpenRouter client types
export interface OpenRouterConfig {
apiKey: string;
model?: string;
baseURL?: string;
timeout?: number;
maxRetries?: number;
rateLimit?: {
requests: number;
interval: number; // milliseconds
};
}
export const OpenRouterConfigSchema = z.object({
apiKey: z.string(),
model: z.string().optional().default('moonshot/kimi-k2-instruct'),
baseURL: z.string().optional().default('https://openrouter.ai/api/v1'),
timeout: z.number().optional().default(60000),
maxRetries: z.number().optional().default(3),
rateLimit: z.object({
requests: z.number(),
interval: z.number()
}).optional()
});
export interface OpenRouterMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}
export interface OpenRouterRequest {
model: string;
messages: OpenRouterMessage[];
temperature?: number;
max_tokens?: number;
top_p?: number;
stream?: boolean;
}
export interface OpenRouterResponse {
id: string;
model: string;
choices: Array<{
message: {
role: string;
content: string;
};
finish_reason: string;
}>;
usage: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
}
// Cypher types
export interface CypherStatement {
query: string;
parameters?: Record<string, unknown>;
}
export interface CypherBatch {
statements: CypherStatement[];
metadata?: {
total_nodes?: number;
total_relationships?: number;
labels?: string[];
relationship_types?: string[];
};
}
// Embedding types
export interface EmbeddingConfig {
provider: 'openrouter' | 'local';
model?: string;
dimensions?: number;
batchSize?: number;
}
export interface EmbeddingResult {
embedding: number[];
model: string;
dimensions: number;
}
// Generation result types
export interface GraphGenerationResult<T = GraphData> {
data: T;
metadata: {
generated_at: Date;
model: string;
duration: number;
token_usage?: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
};
cypher?: CypherBatch;
}
// Error types
export class GraphGenerationError extends Error {
constructor(
message: string,
public code: string,
public details?: unknown
) {
super(message);
this.name = 'GraphGenerationError';
}
}
export class OpenRouterError extends GraphGenerationError {
constructor(message: string, details?: unknown) {
super(message, 'OPENROUTER_ERROR', details);
this.name = 'OpenRouterError';
}
}
export class ValidationError extends GraphGenerationError {
constructor(message: string, details?: unknown) {
super(message, 'VALIDATION_ERROR', details);
this.name = 'ValidationError';
}
}