@apart-tech/intelligence-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/config/index.d.ts +3 -0
  2. package/dist/config/index.d.ts.map +1 -0
  3. package/dist/config/index.js +97 -0
  4. package/dist/config/index.js.map +1 -0
  5. package/dist/db/connection.d.ts +7 -0
  6. package/dist/db/connection.d.ts.map +1 -0
  7. package/dist/db/connection.js +49 -0
  8. package/dist/db/connection.js.map +1 -0
  9. package/dist/db/schema.d.ts +507 -0
  10. package/dist/db/schema.d.ts.map +1 -0
  11. package/dist/db/schema.js +77 -0
  12. package/dist/db/schema.js.map +1 -0
  13. package/dist/db/tenant.d.ts +8 -0
  14. package/dist/db/tenant.d.ts.map +1 -0
  15. package/dist/db/tenant.js +92 -0
  16. package/dist/db/tenant.js.map +1 -0
  17. package/dist/index.d.ts +16 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +18 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/providers/index.d.ts +5 -0
  22. package/dist/providers/index.d.ts.map +1 -0
  23. package/dist/providers/index.js +16 -0
  24. package/dist/providers/index.js.map +1 -0
  25. package/dist/providers/openai.d.ts +9 -0
  26. package/dist/providers/openai.d.ts.map +1 -0
  27. package/dist/providers/openai.js +34 -0
  28. package/dist/providers/openai.js.map +1 -0
  29. package/dist/services/cleaning-service.d.ts +152 -0
  30. package/dist/services/cleaning-service.d.ts.map +1 -0
  31. package/dist/services/cleaning-service.js +632 -0
  32. package/dist/services/cleaning-service.js.map +1 -0
  33. package/dist/services/context-service.d.ts +13 -0
  34. package/dist/services/context-service.d.ts.map +1 -0
  35. package/dist/services/context-service.js +74 -0
  36. package/dist/services/context-service.js.map +1 -0
  37. package/dist/services/domain-seed-data.d.ts +8 -0
  38. package/dist/services/domain-seed-data.d.ts.map +1 -0
  39. package/dist/services/domain-seed-data.js +84 -0
  40. package/dist/services/domain-seed-data.js.map +1 -0
  41. package/dist/services/domain-service.d.ts +26 -0
  42. package/dist/services/domain-service.d.ts.map +1 -0
  43. package/dist/services/domain-service.js +101 -0
  44. package/dist/services/domain-service.js.map +1 -0
  45. package/dist/services/edge-service.d.ts +25 -0
  46. package/dist/services/edge-service.d.ts.map +1 -0
  47. package/dist/services/edge-service.js +90 -0
  48. package/dist/services/edge-service.js.map +1 -0
  49. package/dist/services/node-service.d.ts +34 -0
  50. package/dist/services/node-service.d.ts.map +1 -0
  51. package/dist/services/node-service.js +113 -0
  52. package/dist/services/node-service.js.map +1 -0
  53. package/dist/services/search-service.d.ts +15 -0
  54. package/dist/services/search-service.d.ts.map +1 -0
  55. package/dist/services/search-service.js +118 -0
  56. package/dist/services/search-service.js.map +1 -0
  57. package/dist/types/index.d.ts +74 -0
  58. package/dist/types/index.d.ts.map +1 -0
  59. package/dist/types/index.js +2 -0
  60. package/dist/types/index.js.map +1 -0
  61. package/package.json +42 -0
  62. package/prisma/schema.prisma +114 -0
@@ -0,0 +1,13 @@
1
+ import type { ContextOptions, ContextPackage, ApartConfig } from "../types/index.js";
2
+ import type { SearchService } from "./search-service.js";
3
+ import type { EdgeService } from "./edge-service.js";
4
+ import type { NodeService } from "./node-service.js";
5
+ export declare class ContextService {
6
+ private nodeService;
7
+ private edgeService;
8
+ private searchService;
9
+ private config;
10
+ constructor(nodeService: NodeService, edgeService: EdgeService, searchService: SearchService, config: ApartConfig);
11
+ assemble(options: ContextOptions): Promise<ContextPackage>;
12
+ }
13
+ //# sourceMappingURL=context-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-service.d.ts","sourceRoot":"","sources":["../../src/services/context-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,WAAW,EAGZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,qBAAa,cAAc;IAEvB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,MAAM;gBAHN,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,WAAW;IAGvB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;CAyEjE"}
@@ -0,0 +1,74 @@
1
+ export class ContextService {
2
+ nodeService;
3
+ edgeService;
4
+ searchService;
5
+ config;
6
+ constructor(nodeService, edgeService, searchService, config) {
7
+ this.nodeService = nodeService;
8
+ this.edgeService = edgeService;
9
+ this.searchService = searchService;
10
+ this.config = config;
11
+ }
12
+ async assemble(options) {
13
+ const maxDepth = options.maxDepth ?? this.config.context.maxDepth;
14
+ const maxNodes = options.maxNodes ?? this.config.context.maxNodes;
15
+ const minRelevance = options.minRelevance ?? this.config.context.minRelevance;
16
+ // 1. Find seed nodes via hybrid search
17
+ const searchResults = await this.searchService.search({
18
+ query: options.query,
19
+ limit: Math.min(maxNodes, 10),
20
+ includeDrafts: options.includeDrafts,
21
+ types: options.types,
22
+ domainIds: options.domainIds,
23
+ });
24
+ const seedNodes = searchResults
25
+ .filter((r) => r.score >= minRelevance)
26
+ .map((r) => r.node);
27
+ if (seedNodes.length === 0) {
28
+ return {
29
+ nodes: [],
30
+ edges: [],
31
+ query: options.query,
32
+ assembledAt: new Date().toISOString(),
33
+ };
34
+ }
35
+ // 2. Expand via graph traversal
36
+ const collectedNodeIds = new Set(seedNodes.map((n) => n.id));
37
+ const collectedEdges = [];
38
+ for (const seed of seedNodes) {
39
+ if (collectedNodeIds.size >= maxNodes)
40
+ break;
41
+ const neighborIds = await this.edgeService.getNeighborIds(seed.id, maxDepth);
42
+ const nodeEdges = await this.edgeService.getByNodeId(seed.id);
43
+ collectedEdges.push(...nodeEdges);
44
+ for (const nId of neighborIds) {
45
+ if (collectedNodeIds.size >= maxNodes)
46
+ break;
47
+ collectedNodeIds.add(nId);
48
+ }
49
+ }
50
+ // 3. Fetch all nodes
51
+ const allNodes = [...seedNodes];
52
+ const missingIds = [...collectedNodeIds].filter((id) => !seedNodes.some((n) => n.id === id));
53
+ for (const id of missingIds) {
54
+ const node = await this.nodeService.getById(id);
55
+ if (node)
56
+ allNodes.push(node);
57
+ }
58
+ // 4. Deduplicate edges
59
+ const edgeIds = new Set();
60
+ const uniqueEdges = collectedEdges.filter((e) => {
61
+ if (edgeIds.has(e.id))
62
+ return false;
63
+ edgeIds.add(e.id);
64
+ return true;
65
+ });
66
+ return {
67
+ nodes: allNodes,
68
+ edges: uniqueEdges,
69
+ query: options.query,
70
+ assembledAt: new Date().toISOString(),
71
+ };
72
+ }
73
+ }
74
+ //# sourceMappingURL=context-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-service.js","sourceRoot":"","sources":["../../src/services/context-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface DomainSeedEntry {
2
+ slug: string;
3
+ name: string;
4
+ description: string;
5
+ children?: Omit<DomainSeedEntry, "children">[];
6
+ }
7
+ export declare const DEFAULT_TAXONOMY: DomainSeedEntry[];
8
+ //# sourceMappingURL=domain-seed-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-seed-data.d.ts","sourceRoot":"","sources":["../../src/services/domain-seed-data.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,EAAE,CAAC;CAChD;AAED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAkF7C,CAAC"}
@@ -0,0 +1,84 @@
1
+ export const DEFAULT_TAXONOMY = [
2
+ {
3
+ slug: "strategy",
4
+ name: "Strategic Direction & Leadership",
5
+ description: "Vision, mission, strategic planning, governance, and high-level decision-making",
6
+ children: [
7
+ { slug: "vision-mission", name: "Vision, Mission & Values", description: "Core purpose, values, and long-term direction" },
8
+ { slug: "planning", name: "Strategic Planning & Goals", description: "Goals, OKRs, roadmaps, and strategic initiatives" },
9
+ { slug: "governance", name: "Governance & Decision-Making", description: "Decision frameworks, policies, authority structures" },
10
+ ],
11
+ },
12
+ {
13
+ slug: "people",
14
+ name: "People & Culture",
15
+ description: "Talent, collaboration, learning, and organizational culture",
16
+ children: [
17
+ { slug: "talent", name: "Talent & Skills", description: "Hiring, roles, skills, team composition" },
18
+ { slug: "collaboration", name: "Collaboration & Communication", description: "How teams work together, communication norms" },
19
+ { slug: "learning", name: "Learning & Development", description: "Training, onboarding, knowledge sharing, growth" },
20
+ ],
21
+ },
22
+ {
23
+ slug: "customers",
24
+ name: "Customers & Relationships",
25
+ description: "Customer engagement, support, market understanding, and relationship management",
26
+ children: [
27
+ { slug: "engagement", name: "Customer Engagement", description: "Sales, marketing, outreach, relationship building" },
28
+ { slug: "support", name: "Customer Support & Success", description: "Support processes, success programs, satisfaction" },
29
+ { slug: "insights", name: "Market & Customer Insights", description: "Market research, customer feedback, competitive analysis" },
30
+ ],
31
+ },
32
+ {
33
+ slug: "products",
34
+ name: "Products & Services",
35
+ description: "Product design, delivery, and quality for what the organization offers",
36
+ children: [
37
+ { slug: "design", name: "Product Design & Requirements", description: "Requirements, specifications, UX, product decisions" },
38
+ { slug: "delivery", name: "Delivery & Operations", description: "Shipping, releasing, deploying, operational delivery" },
39
+ { slug: "quality", name: "Quality & Assurance", description: "Testing, QA, standards, acceptance criteria" },
40
+ ],
41
+ },
42
+ {
43
+ slug: "technology",
44
+ name: "Technology & Systems",
45
+ description: "Architecture, development, data management, and security",
46
+ children: [
47
+ { slug: "architecture", name: "Architecture & Infrastructure", description: "System design, infrastructure, platforms, technical foundations" },
48
+ { slug: "development", name: "Development & Engineering", description: "Code, APIs, engineering practices, technical implementation" },
49
+ { slug: "data", name: "Data & Information Management", description: "Databases, data pipelines, analytics, information architecture" },
50
+ { slug: "security", name: "Security & Resilience", description: "Cybersecurity, access control, disaster recovery, compliance" },
51
+ ],
52
+ },
53
+ {
54
+ slug: "operations",
55
+ name: "Operations & Processes",
56
+ description: "Workflows, coordination, compliance, and day-to-day execution",
57
+ children: [
58
+ { slug: "workflows", name: "Workflows & Procedures", description: "Standard operating procedures, process documentation" },
59
+ { slug: "coordination", name: "Coordination & Execution", description: "Project management, resource allocation, scheduling" },
60
+ { slug: "compliance", name: "Compliance & Risk", description: "Regulatory compliance, risk management, legal requirements" },
61
+ ],
62
+ },
63
+ {
64
+ slug: "innovation",
65
+ name: "Innovation & Growth",
66
+ description: "Research, experimentation, partnerships, and growth initiatives",
67
+ children: [
68
+ { slug: "research", name: "Research & Exploration", description: "R&D, market exploration, feasibility studies" },
69
+ { slug: "experiments", name: "Experiments & Prototyping", description: "Prototypes, pilots, A/B tests, proof of concepts" },
70
+ { slug: "partnerships", name: "Partnerships & Ecosystem", description: "Partner relationships, integrations, ecosystem development" },
71
+ ],
72
+ },
73
+ {
74
+ slug: "finance",
75
+ name: "Finance & Resources",
76
+ description: "Budgets, financial planning, metrics, and resource management",
77
+ children: [
78
+ { slug: "budgets", name: "Budgets & Allocation", description: "Budget planning, cost management, resource allocation" },
79
+ { slug: "performance", name: "Performance & Metrics", description: "KPIs, dashboards, measurement, reporting" },
80
+ { slug: "procurement", name: "Procurement & Vendors", description: "Vendor management, purchasing, contracts, licensing" },
81
+ ],
82
+ },
83
+ ];
84
+ //# sourceMappingURL=domain-seed-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-seed-data.js","sourceRoot":"","sources":["../../src/services/domain-seed-data.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { Domain } from "../types/index.js";
3
+ import { type TenantContext } from "../db/tenant.js";
4
+ export declare class DomainService {
5
+ private db;
6
+ private tenantCtx;
7
+ constructor(db: PrismaClient, tenantCtx?: TenantContext);
8
+ getTree(): Promise<(Domain & {
9
+ children: Domain[];
10
+ })[]>;
11
+ getById(id: string): Promise<Domain | null>;
12
+ getBySlug(slug: string): Promise<Domain | null>;
13
+ resolveSlugs(slugs: string[]): Promise<string[]>;
14
+ create(input: {
15
+ name: string;
16
+ slug: string;
17
+ description?: string;
18
+ parentId?: string;
19
+ sortOrder?: number;
20
+ }): Promise<Domain>;
21
+ seed(): Promise<{
22
+ created: number;
23
+ existing: number;
24
+ }>;
25
+ }
26
+ //# sourceMappingURL=domain-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-service.d.ts","sourceRoot":"","sources":["../../src/services/domain-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3E,qBAAa,aAAa;IAGZ,OAAO,CAAC,EAAE;IAFtB,OAAO,CAAC,SAAS,CAAgB;gBAEb,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,aAAa;IAIzD,OAAO,IAAI,OAAO,CAAC,CAAC,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAAE,CAAC;IASvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI/C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQhD,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAab,IAAI,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAwD7D"}
@@ -0,0 +1,101 @@
1
+ import { DEFAULT_TAXONOMY } from "./domain-seed-data.js";
2
+ import { SINGLE_TENANT_ORG_ID } from "../db/tenant.js";
3
+ export class DomainService {
4
+ db;
5
+ tenantCtx;
6
+ constructor(db, tenantCtx) {
7
+ this.db = db;
8
+ this.tenantCtx = tenantCtx ?? { organizationId: SINGLE_TENANT_ORG_ID };
9
+ }
10
+ async getTree() {
11
+ const domains = await this.db.domain.findMany({
12
+ where: { parentId: null },
13
+ include: { children: { orderBy: { sortOrder: "asc" } } },
14
+ orderBy: { sortOrder: "asc" },
15
+ });
16
+ return domains;
17
+ }
18
+ async getById(id) {
19
+ return this.db.domain.findUnique({ where: { id } });
20
+ }
21
+ async getBySlug(slug) {
22
+ return this.db.domain.findFirst({ where: { slug } });
23
+ }
24
+ async resolveSlugs(slugs) {
25
+ const domains = await this.db.domain.findMany({
26
+ where: { slug: { in: slugs } },
27
+ select: { id: true },
28
+ });
29
+ return domains.map((d) => d.id);
30
+ }
31
+ async create(input) {
32
+ return this.db.domain.create({
33
+ data: {
34
+ name: input.name,
35
+ slug: input.slug,
36
+ description: input.description ?? "",
37
+ parentId: input.parentId ?? null,
38
+ sortOrder: input.sortOrder ?? 0,
39
+ organizationId: this.tenantCtx.organizationId,
40
+ },
41
+ });
42
+ }
43
+ async seed() {
44
+ let created = 0;
45
+ let existing = 0;
46
+ for (let i = 0; i < DEFAULT_TAXONOMY.length; i++) {
47
+ const entry = DEFAULT_TAXONOMY[i];
48
+ const parent = await this.db.domain.upsert({
49
+ where: {
50
+ slug_organizationId: {
51
+ slug: entry.slug,
52
+ organizationId: this.tenantCtx.organizationId,
53
+ },
54
+ },
55
+ create: {
56
+ name: entry.name,
57
+ slug: entry.slug,
58
+ description: entry.description,
59
+ sortOrder: i,
60
+ organizationId: this.tenantCtx.organizationId,
61
+ },
62
+ update: {},
63
+ });
64
+ // Check if it was newly created (compare timestamps)
65
+ const wasJustCreated = (Date.now() - parent.createdAt.getTime()) < 5000;
66
+ if (wasJustCreated)
67
+ created++;
68
+ else
69
+ existing++;
70
+ if (entry.children) {
71
+ for (let j = 0; j < entry.children.length; j++) {
72
+ const child = entry.children[j];
73
+ const childResult = await this.db.domain.upsert({
74
+ where: {
75
+ slug_organizationId: {
76
+ slug: child.slug,
77
+ organizationId: this.tenantCtx.organizationId,
78
+ },
79
+ },
80
+ create: {
81
+ name: child.name,
82
+ slug: child.slug,
83
+ description: child.description,
84
+ parentId: parent.id,
85
+ sortOrder: j,
86
+ organizationId: this.tenantCtx.organizationId,
87
+ },
88
+ update: {},
89
+ });
90
+ const childWasJustCreated = (Date.now() - childResult.createdAt.getTime()) < 5000;
91
+ if (childWasJustCreated)
92
+ created++;
93
+ else
94
+ existing++;
95
+ }
96
+ }
97
+ }
98
+ return { created, existing };
99
+ }
100
+ }
101
+ //# sourceMappingURL=domain-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-service.js","sourceRoot":"","sources":["../../src/services/domain-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAsB,MAAM,iBAAiB,CAAC;AAE3E,MAAM,OAAO,aAAa;IAGJ;IAFZ,SAAS,CAAgB;IAEjC,YAAoB,EAAgB,EAAE,SAAyB;QAA3C,OAAE,GAAF,EAAE,CAAc;QAClC,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC5C,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;YACzB,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;YACxD,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;SAC9B,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAe;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;YAC9B,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;SACrB,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAMZ;QACC,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE;gBACJ,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;gBACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;gBAChC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC;gBAC/B,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc;aAC9C;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAElC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;gBACzC,KAAK,EAAE;oBACL,mBAAmB,EAAE;wBACnB,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc;qBAC9C;iBACF;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,SAAS,EAAE,CAAC;oBACZ,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc;iBAC9C;gBACD,MAAM,EAAE,EAAE;aACX,CAAC,CAAC;YAEH,qDAAqD;YACrD,MAAM,cAAc,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;YACxE,IAAI,cAAc;gBAAE,OAAO,EAAE,CAAC;;gBAAM,QAAQ,EAAE,CAAC;YAE/C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAChC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;wBAC9C,KAAK,EAAE;4BACL,mBAAmB,EAAE;gCACnB,IAAI,EAAE,KAAK,CAAC,IAAI;gCAChB,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc;6BAC9C;yBACF;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,WAAW,EAAE,KAAK,CAAC,WAAW;4BAC9B,QAAQ,EAAE,MAAM,CAAC,EAAE;4BACnB,SAAS,EAAE,CAAC;4BACZ,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc;yBAC9C;wBACD,MAAM,EAAE,EAAE;qBACX,CAAC,CAAC;oBACH,MAAM,mBAAmB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;oBAClF,IAAI,mBAAmB;wBAAE,OAAO,EAAE,CAAC;;wBAAM,QAAQ,EAAE,CAAC;gBACtD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { Edge } from "../types/index.js";
3
+ import { type TenantContext } from "../db/tenant.js";
4
+ export declare class EdgeService {
5
+ private db;
6
+ private tenantCtx;
7
+ constructor(db: PrismaClient, tenantCtx?: TenantContext);
8
+ create(input: {
9
+ sourceNodeId: string;
10
+ targetNodeId: string;
11
+ relationshipType: string;
12
+ weight?: number;
13
+ metadata?: Record<string, unknown>;
14
+ createdBy: string;
15
+ }): Promise<Edge>;
16
+ getByNodeId(nodeId: string): Promise<Edge[]>;
17
+ getNeighborIds(nodeId: string, depth?: number): Promise<string[]>;
18
+ listRelationshipTypes(): Promise<{
19
+ relationshipType: string;
20
+ count: number;
21
+ }[]>;
22
+ retypeMany(fromType: string, toType: string): Promise<number>;
23
+ delete(id: string): Promise<boolean>;
24
+ }
25
+ //# sourceMappingURL=edge-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-service.d.ts","sourceRoot":"","sources":["../../src/services/edge-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAU,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3E,qBAAa,WAAW;IAGV,OAAO,CAAC,EAAE;IAFtB,OAAO,CAAC,SAAS,CAAgB;gBAEb,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,aAAa;IAIzD,MAAM,CAAC,KAAK,EAAE;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcX,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQ5C,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoC5D,qBAAqB,IAAI,OAAO,CACpC;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAC9C;IAWK,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC;IAQZ,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ3C"}
@@ -0,0 +1,90 @@
1
+ import { SINGLE_TENANT_ORG_ID } from "../db/tenant.js";
2
+ export class EdgeService {
3
+ db;
4
+ tenantCtx;
5
+ constructor(db, tenantCtx) {
6
+ this.db = db;
7
+ this.tenantCtx = tenantCtx ?? { organizationId: SINGLE_TENANT_ORG_ID };
8
+ }
9
+ async create(input) {
10
+ return this.db.edge.create({
11
+ data: {
12
+ sourceNodeId: input.sourceNodeId,
13
+ targetNodeId: input.targetNodeId,
14
+ relationshipType: input.relationshipType,
15
+ weight: input.weight ?? 1.0,
16
+ metadata: (input.metadata ?? {}),
17
+ createdBy: input.createdBy,
18
+ organizationId: this.tenantCtx.organizationId,
19
+ },
20
+ });
21
+ }
22
+ async getByNodeId(nodeId) {
23
+ return this.db.edge.findMany({
24
+ where: {
25
+ OR: [{ sourceNodeId: nodeId }, { targetNodeId: nodeId }],
26
+ },
27
+ });
28
+ }
29
+ async getNeighborIds(nodeId, depth = 1) {
30
+ // For depth 1, simple query
31
+ const nodeEdges = await this.getByNodeId(nodeId);
32
+ const neighborIds = new Set();
33
+ for (const edge of nodeEdges) {
34
+ if (edge.sourceNodeId !== nodeId)
35
+ neighborIds.add(edge.sourceNodeId);
36
+ if (edge.targetNodeId !== nodeId)
37
+ neighborIds.add(edge.targetNodeId);
38
+ }
39
+ if (depth <= 1)
40
+ return [...neighborIds];
41
+ // For deeper traversals, recursively expand
42
+ const visited = new Set([nodeId]);
43
+ let frontier = [...neighborIds];
44
+ for (let d = 1; d < depth; d++) {
45
+ const nextFrontier = [];
46
+ for (const nId of frontier) {
47
+ if (visited.has(nId))
48
+ continue;
49
+ visited.add(nId);
50
+ const nEdges = await this.getByNodeId(nId);
51
+ for (const edge of nEdges) {
52
+ if (!visited.has(edge.sourceNodeId))
53
+ nextFrontier.push(edge.sourceNodeId);
54
+ if (!visited.has(edge.targetNodeId))
55
+ nextFrontier.push(edge.targetNodeId);
56
+ }
57
+ }
58
+ frontier = nextFrontier;
59
+ }
60
+ visited.delete(nodeId);
61
+ return [...visited];
62
+ }
63
+ async listRelationshipTypes() {
64
+ const result = await this.db.edge.groupBy({
65
+ by: ["relationshipType"],
66
+ _count: { relationshipType: true },
67
+ });
68
+ return result.map((r) => ({
69
+ relationshipType: r.relationshipType,
70
+ count: r._count.relationshipType,
71
+ }));
72
+ }
73
+ async retypeMany(fromType, toType) {
74
+ const result = await this.db.edge.updateMany({
75
+ where: { relationshipType: fromType },
76
+ data: { relationshipType: toType },
77
+ });
78
+ return result.count;
79
+ }
80
+ async delete(id) {
81
+ try {
82
+ await this.db.edge.delete({ where: { id } });
83
+ return true;
84
+ }
85
+ catch {
86
+ return false;
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=edge-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-service.js","sourceRoot":"","sources":["../../src/services/edge-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { Node, NodeStatus, EmbeddingProvider } from "../types/index.js";
3
+ import { type TenantContext } from "../db/tenant.js";
4
+ export declare class NodeService {
5
+ private db;
6
+ private embeddings;
7
+ private tenantCtx;
8
+ constructor(db: PrismaClient, embeddings: EmbeddingProvider, tenantCtx?: TenantContext);
9
+ create(input: {
10
+ type: string;
11
+ title: string;
12
+ content: string;
13
+ metadata?: Record<string, unknown>;
14
+ createdBy: string;
15
+ domainId?: string;
16
+ status?: string;
17
+ }): Promise<Node>;
18
+ getById(id: string): Promise<Node | null>;
19
+ update(id: string, input: {
20
+ title?: string;
21
+ content?: string;
22
+ metadata?: Record<string, unknown>;
23
+ type?: string;
24
+ domainId?: string;
25
+ }): Promise<Node | null>;
26
+ setStatus(id: string, status: NodeStatus): Promise<Node | null>;
27
+ listDrafts(limit?: number): Promise<Node[]>;
28
+ delete(id: string): Promise<boolean>;
29
+ listTypes(): Promise<{
30
+ type: string;
31
+ count: number;
32
+ }[]>;
33
+ }
34
+ //# sourceMappingURL=node-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-service.d.ts","sourceRoot":"","sources":["../../src/services/node-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAU,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EACV,IAAI,EACJ,UAAU,EACV,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExF,qBAAa,WAAW;IAIpB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAJpB,OAAO,CAAC,SAAS,CAAgB;gBAGvB,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,iBAAiB,EACrC,SAAS,CAAC,EAAE,aAAa;IAKrB,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCX,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIzC,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GACA,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAsCjB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW/D,UAAU,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQvC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAapC,SAAS,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAQ9D"}
@@ -0,0 +1,113 @@
1
+ import { tenantWhere, SINGLE_TENANT_ORG_ID } from "../db/tenant.js";
2
+ export class NodeService {
3
+ db;
4
+ embeddings;
5
+ tenantCtx;
6
+ constructor(db, embeddings, tenantCtx) {
7
+ this.db = db;
8
+ this.embeddings = embeddings;
9
+ this.tenantCtx = tenantCtx ?? { organizationId: SINGLE_TENANT_ORG_ID };
10
+ }
11
+ async create(input) {
12
+ const embedding = await this.embeddings.embed(`${input.title}\n\n${input.content}`);
13
+ const embeddingStr = `[${embedding.join(",")}]`;
14
+ const node = await this.db.node.create({
15
+ data: {
16
+ type: input.type,
17
+ title: input.title,
18
+ content: input.content,
19
+ metadata: (input.metadata ?? {}),
20
+ status: input.status ?? "draft",
21
+ createdBy: input.createdBy,
22
+ domainId: input.domainId ?? null,
23
+ organizationId: this.tenantCtx.organizationId,
24
+ },
25
+ });
26
+ // Update embedding and tsvector via raw SQL (Prisma doesn't support Unsupported fields in create)
27
+ const orgFilter = tenantWhere(this.tenantCtx);
28
+ await this.db.$executeRaw `
29
+ UPDATE nodes
30
+ SET embedding = ${embeddingStr}::vector,
31
+ search_vector = to_tsvector('english', ${input.title} || ' ' || ${input.content})
32
+ WHERE id = ${node.id}::uuid
33
+ AND ${orgFilter}
34
+ `;
35
+ return node;
36
+ }
37
+ async getById(id) {
38
+ return this.db.node.findUnique({ where: { id } });
39
+ }
40
+ async update(id, input) {
41
+ const existing = await this.getById(id);
42
+ if (!existing)
43
+ return null;
44
+ const title = input.title ?? existing.title;
45
+ const content = input.content ?? existing.content;
46
+ const updated = await this.db.node.update({
47
+ where: { id },
48
+ data: {
49
+ ...(input.title !== undefined && { title: input.title }),
50
+ ...(input.content !== undefined && { content: input.content }),
51
+ ...(input.metadata !== undefined && { metadata: input.metadata }),
52
+ ...(input.type !== undefined && { type: input.type }),
53
+ ...(input.domainId !== undefined && { domainId: input.domainId }),
54
+ updatedAt: new Date(),
55
+ version: existing.version + 1,
56
+ },
57
+ });
58
+ // Re-embed and update tsvector if content changed
59
+ if (input.title || input.content) {
60
+ const embedding = await this.embeddings.embed(`${title}\n\n${content}`);
61
+ const embeddingStr = `[${embedding.join(",")}]`;
62
+ const orgFilter = tenantWhere(this.tenantCtx);
63
+ await this.db.$executeRaw `
64
+ UPDATE nodes
65
+ SET embedding = ${embeddingStr}::vector,
66
+ search_vector = to_tsvector('english', ${title} || ' ' || ${content})
67
+ WHERE id = ${id}::uuid
68
+ AND ${orgFilter}
69
+ `;
70
+ }
71
+ return updated;
72
+ }
73
+ async setStatus(id, status) {
74
+ try {
75
+ return await this.db.node.update({
76
+ where: { id },
77
+ data: { status, updatedAt: new Date() },
78
+ });
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ async listDrafts(limit = 50) {
85
+ return this.db.node.findMany({
86
+ where: { status: "draft" },
87
+ orderBy: { createdAt: "desc" },
88
+ take: limit,
89
+ });
90
+ }
91
+ async delete(id) {
92
+ try {
93
+ // Delete associated edges first
94
+ await this.db.edge.deleteMany({
95
+ where: { OR: [{ sourceNodeId: id }, { targetNodeId: id }] },
96
+ });
97
+ await this.db.node.delete({ where: { id } });
98
+ return true;
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ }
104
+ async listTypes() {
105
+ const result = await this.db.node.groupBy({
106
+ by: ["type"],
107
+ _count: { type: true },
108
+ orderBy: { _count: { type: "desc" } },
109
+ });
110
+ return result.map((r) => ({ type: r.type, count: r._count.type }));
111
+ }
112
+ }
113
+ //# sourceMappingURL=node-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-service.js","sourceRoot":"","sources":["../../src/services/node-service.ts"],"names":[],"mappings":"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"}