@apart-tech/intelligence-core 1.21.0 → 1.21.2

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 (86) hide show
  1. package/dist/db/tenant.d.ts.map +1 -1
  2. package/dist/db/tenant.js +2 -0
  3. package/dist/db/tenant.js.map +1 -1
  4. package/dist/index.d.ts +11 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +5 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/services/__tests__/node-service.test.js +3 -3
  9. package/dist/services/__tests__/node-service.test.js.map +1 -1
  10. package/dist/services/__tests__/search-service.test.js +3 -0
  11. package/dist/services/__tests__/search-service.test.js.map +1 -1
  12. package/dist/services/agent-cli-reference.d.ts +1 -1
  13. package/dist/services/agent-cli-reference.d.ts.map +1 -1
  14. package/dist/services/agent-cli-reference.js +2 -2
  15. package/dist/services/chat-capture-service.d.ts +6 -2
  16. package/dist/services/chat-capture-service.d.ts.map +1 -1
  17. package/dist/services/chat-capture-service.js +56 -19
  18. package/dist/services/chat-capture-service.js.map +1 -1
  19. package/dist/services/chat-context-service.d.ts.map +1 -1
  20. package/dist/services/chat-context-service.js +5 -0
  21. package/dist/services/chat-context-service.js.map +1 -1
  22. package/dist/services/chat-tool-definitions.d.ts +178 -0
  23. package/dist/services/chat-tool-definitions.d.ts.map +1 -0
  24. package/dist/services/chat-tool-definitions.js +120 -0
  25. package/dist/services/chat-tool-definitions.js.map +1 -0
  26. package/dist/services/chat-tool-definitions.test.d.ts +2 -0
  27. package/dist/services/chat-tool-definitions.test.d.ts.map +1 -0
  28. package/dist/services/chat-tool-definitions.test.js +150 -0
  29. package/dist/services/chat-tool-definitions.test.js.map +1 -0
  30. package/dist/services/dedup-service.d.ts +132 -0
  31. package/dist/services/dedup-service.d.ts.map +1 -0
  32. package/dist/services/dedup-service.js +434 -0
  33. package/dist/services/dedup-service.js.map +1 -0
  34. package/dist/services/dedup-service.test.d.ts +2 -0
  35. package/dist/services/dedup-service.test.d.ts.map +1 -0
  36. package/dist/services/dedup-service.test.js +160 -0
  37. package/dist/services/dedup-service.test.js.map +1 -0
  38. package/dist/services/document-post-check-service.d.ts +47 -0
  39. package/dist/services/document-post-check-service.d.ts.map +1 -0
  40. package/dist/services/document-post-check-service.js +130 -0
  41. package/dist/services/document-post-check-service.js.map +1 -0
  42. package/dist/services/document-post-check-service.test.d.ts +2 -0
  43. package/dist/services/document-post-check-service.test.d.ts.map +1 -0
  44. package/dist/services/document-post-check-service.test.js +150 -0
  45. package/dist/services/document-post-check-service.test.js.map +1 -0
  46. package/dist/services/document-render-service.d.ts +27 -0
  47. package/dist/services/document-render-service.d.ts.map +1 -0
  48. package/dist/services/document-render-service.js +186 -0
  49. package/dist/services/document-render-service.js.map +1 -0
  50. package/dist/services/document-render-service.test.d.ts +2 -0
  51. package/dist/services/document-render-service.test.d.ts.map +1 -0
  52. package/dist/services/document-render-service.test.js +144 -0
  53. package/dist/services/document-render-service.test.js.map +1 -0
  54. package/dist/services/document-service.d.ts +4 -1
  55. package/dist/services/document-service.d.ts.map +1 -1
  56. package/dist/services/document-service.js +24 -1
  57. package/dist/services/document-service.js.map +1 -1
  58. package/dist/services/document-tool-handler.d.ts +44 -0
  59. package/dist/services/document-tool-handler.d.ts.map +1 -0
  60. package/dist/services/document-tool-handler.js +179 -0
  61. package/dist/services/document-tool-handler.js.map +1 -0
  62. package/dist/services/document-tool-handler.test.d.ts +2 -0
  63. package/dist/services/document-tool-handler.test.d.ts.map +1 -0
  64. package/dist/services/document-tool-handler.test.js +149 -0
  65. package/dist/services/document-tool-handler.test.js.map +1 -0
  66. package/dist/services/edge-service.d.ts +1 -0
  67. package/dist/services/edge-service.d.ts.map +1 -1
  68. package/dist/services/edge-service.js +9 -0
  69. package/dist/services/edge-service.js.map +1 -1
  70. package/dist/services/node-service.js +2 -2
  71. package/dist/services/node-service.js.map +1 -1
  72. package/dist/services/quota-service.d.ts +2 -0
  73. package/dist/services/quota-service.d.ts.map +1 -1
  74. package/dist/services/quota-service.js +17 -1
  75. package/dist/services/quota-service.js.map +1 -1
  76. package/dist/services/search-service.d.ts.map +1 -1
  77. package/dist/services/search-service.js +34 -2
  78. package/dist/services/search-service.js.map +1 -1
  79. package/dist/services/usage-service.d.ts +21 -1
  80. package/dist/services/usage-service.d.ts.map +1 -1
  81. package/dist/services/usage-service.js +37 -1
  82. package/dist/services/usage-service.js.map +1 -1
  83. package/dist/types/index.d.ts +5 -0
  84. package/dist/types/index.d.ts.map +1 -1
  85. package/package.json +11 -1
  86. package/prisma/schema.prisma +48 -18
@@ -0,0 +1,434 @@
1
+ import { SINGLE_TENANT_ORG_ID } from "../db/tenant.js";
2
+ // ── Service ─────────────────────────────────────────────────────────────────
3
+ export class DedupService {
4
+ db;
5
+ tenantCtx;
6
+ constructor(db, tenantCtx) {
7
+ this.db = db;
8
+ this.tenantCtx = tenantCtx ?? { organizationId: SINGLE_TENANT_ORG_ID };
9
+ }
10
+ /**
11
+ * Scan chat nodes for similarity clusters and create merge proposals.
12
+ */
13
+ async scanChatNodes(opts) {
14
+ const threshold = opts.threshold ?? 0.82;
15
+ const limit = opts.limit ?? 500;
16
+ // Find similarity pairs among chat nodes
17
+ const pairs = await this.findChatSimilarityPairs(threshold, limit);
18
+ if (pairs.length === 0) {
19
+ return { proposalIds: [], clustersFound: 0, nodesScanned: 0 };
20
+ }
21
+ // Cluster via union-find
22
+ const clusters = this.computeClusters(pairs);
23
+ // Fetch node titles for labeling
24
+ const allNodeIds = new Set();
25
+ for (const c of clusters) {
26
+ for (const id of c.nodeIds)
27
+ allNodeIds.add(id);
28
+ }
29
+ const nodes = await this.db.node.findMany({
30
+ where: { id: { in: [...allNodeIds] } },
31
+ select: { id: true, title: true },
32
+ });
33
+ const titleMap = new Map(nodes.map((n) => [n.id, n.title]));
34
+ // Filter out clusters already covered by pending proposals
35
+ const pendingProposals = await this.db.mergeProposal.findMany({
36
+ where: { status: { in: ["pending", "approved"] } },
37
+ select: { sourceNodeIds: true },
38
+ });
39
+ const coveredNodeIds = new Set();
40
+ for (const p of pendingProposals) {
41
+ for (const id of p.sourceNodeIds)
42
+ coveredNodeIds.add(id);
43
+ }
44
+ const newClusters = clusters.filter((c) => !c.nodeIds.every((id) => coveredNodeIds.has(id)));
45
+ // Create proposals
46
+ const proposalIds = [];
47
+ for (const cluster of newClusters) {
48
+ const titles = cluster.nodeIds
49
+ .map((id) => titleMap.get(id) ?? "Untitled")
50
+ .filter(Boolean);
51
+ let topicLabel;
52
+ if (opts.llmLabeler) {
53
+ try {
54
+ topicLabel = await opts.llmLabeler(titles);
55
+ }
56
+ catch {
57
+ topicLabel = titles[0] ?? "Cluster";
58
+ }
59
+ }
60
+ else {
61
+ topicLabel = titles[0] ?? "Cluster";
62
+ }
63
+ const proposal = await this.db.mergeProposal.create({
64
+ data: {
65
+ status: "pending",
66
+ topicLabel: topicLabel.slice(0, 200),
67
+ sourceNodeIds: cluster.nodeIds,
68
+ similarity: cluster.avgSimilarity,
69
+ metadata: {
70
+ minSimilarity: cluster.minSimilarity,
71
+ avgSimilarity: cluster.avgSimilarity,
72
+ },
73
+ createdBy: opts.createdBy,
74
+ organizationId: this.tenantCtx.organizationId,
75
+ },
76
+ });
77
+ proposalIds.push(proposal.id);
78
+ }
79
+ return {
80
+ proposalIds,
81
+ clustersFound: newClusters.length,
82
+ nodesScanned: allNodeIds.size,
83
+ };
84
+ }
85
+ /**
86
+ * Union-find clustering of similarity pairs.
87
+ * Returns clusters with min/avg similarity.
88
+ */
89
+ computeClusters(pairs) {
90
+ if (pairs.length === 0)
91
+ return [];
92
+ const parent = new Map();
93
+ function find(x) {
94
+ if (!parent.has(x))
95
+ parent.set(x, x);
96
+ let root = x;
97
+ while (parent.get(root) !== root)
98
+ root = parent.get(root);
99
+ let cur = x;
100
+ while (cur !== root) {
101
+ const next = parent.get(cur);
102
+ parent.set(cur, root);
103
+ cur = next;
104
+ }
105
+ return root;
106
+ }
107
+ function union(a, b) {
108
+ const ra = find(a);
109
+ const rb = find(b);
110
+ if (ra !== rb)
111
+ parent.set(ra, rb);
112
+ }
113
+ for (const pair of pairs) {
114
+ union(pair.nodeAId, pair.nodeBId);
115
+ }
116
+ // Normalize all roots
117
+ for (const nodeId of parent.keys()) {
118
+ find(nodeId);
119
+ }
120
+ // Group by root
121
+ const groups = new Map();
122
+ for (const [nodeId, root] of parent.entries()) {
123
+ if (!groups.has(root))
124
+ groups.set(root, []);
125
+ groups.get(root).push(nodeId);
126
+ }
127
+ // Compute per-cluster similarity stats
128
+ const pairsByCluster = new Map();
129
+ for (const pair of pairs) {
130
+ const root = find(pair.nodeAId);
131
+ if (!pairsByCluster.has(root))
132
+ pairsByCluster.set(root, []);
133
+ pairsByCluster.get(root).push(pair);
134
+ }
135
+ const clusters = [];
136
+ for (const [root, nodeIds] of groups.entries()) {
137
+ // Skip single-node "clusters"
138
+ if (nodeIds.length < 2)
139
+ continue;
140
+ const clusterPairs = pairsByCluster.get(root) ?? [];
141
+ const similarities = clusterPairs.map((p) => p.similarity);
142
+ const minSimilarity = similarities.length > 0 ? Math.min(...similarities) : 0;
143
+ const avgSimilarity = similarities.length > 0
144
+ ? similarities.reduce((a, b) => a + b, 0) / similarities.length
145
+ : 0;
146
+ clusters.push({
147
+ nodeIds,
148
+ minSimilarity: Math.round(minSimilarity * 1000) / 1000,
149
+ avgSimilarity: Math.round(avgSimilarity * 1000) / 1000,
150
+ topicLabel: "", // filled by caller
151
+ });
152
+ }
153
+ return clusters;
154
+ }
155
+ /**
156
+ * List merge proposals with optional status filter and pagination.
157
+ */
158
+ async listProposals(opts) {
159
+ const where = {};
160
+ if (opts?.status)
161
+ where.status = opts.status;
162
+ const [proposals, total] = await Promise.all([
163
+ this.db.mergeProposal.findMany({
164
+ where,
165
+ orderBy: { createdAt: "desc" },
166
+ take: opts?.limit ?? 50,
167
+ skip: opts?.offset ?? 0,
168
+ }),
169
+ this.db.mergeProposal.count({ where }),
170
+ ]);
171
+ // Fetch source node titles
172
+ const allNodeIds = new Set();
173
+ for (const p of proposals) {
174
+ for (const id of p.sourceNodeIds)
175
+ allNodeIds.add(id);
176
+ }
177
+ const nodes = allNodeIds.size > 0
178
+ ? await this.db.node.findMany({
179
+ where: { id: { in: [...allNodeIds] } },
180
+ select: { id: true, title: true, status: true },
181
+ })
182
+ : [];
183
+ const nodeMap = new Map(nodes.map((n) => [n.id, n]));
184
+ const enriched = proposals.map((p) => ({
185
+ ...p,
186
+ sourceNodes: p.sourceNodeIds.map((id) => nodeMap.get(id) ?? { id, title: "Unknown", status: "unknown" }),
187
+ }));
188
+ return { proposals: enriched, total };
189
+ }
190
+ /**
191
+ * Get a single proposal with full source node data.
192
+ */
193
+ async getProposal(id) {
194
+ const proposal = await this.db.mergeProposal.findUnique({ where: { id } });
195
+ if (!proposal)
196
+ return null;
197
+ const nodes = await this.db.node.findMany({
198
+ where: { id: { in: proposal.sourceNodeIds } },
199
+ });
200
+ return { ...proposal, sourceNodes: nodes };
201
+ }
202
+ /**
203
+ * Update proposal status with transition validation.
204
+ * Allowed: pending→approved, pending→rejected, approved→merged.
205
+ */
206
+ async updateProposalStatus(id, status, resolvedBy) {
207
+ const proposal = await this.db.mergeProposal.findUnique({ where: { id } });
208
+ if (!proposal)
209
+ throw new Error("Proposal not found");
210
+ const TRANSITIONS = {
211
+ pending: ["approved", "rejected"],
212
+ approved: ["merged"],
213
+ };
214
+ const allowed = TRANSITIONS[proposal.status];
215
+ if (!allowed || !allowed.includes(status)) {
216
+ throw new Error(`Invalid transition: ${proposal.status} → ${status}. Allowed: ${allowed?.join(", ") ?? "none"}`);
217
+ }
218
+ return this.db.mergeProposal.update({
219
+ where: { id },
220
+ data: {
221
+ status,
222
+ resolvedBy,
223
+ resolvedAt: new Date(),
224
+ },
225
+ });
226
+ }
227
+ /**
228
+ * Execute a merge: create merged node, transfer edges, archive sources.
229
+ */
230
+ async executeMerge(proposalId, opts) {
231
+ const proposal = await this.db.mergeProposal.findUnique({
232
+ where: { id: proposalId },
233
+ });
234
+ if (!proposal)
235
+ throw new Error("Proposal not found");
236
+ if (proposal.status !== "approved") {
237
+ throw new Error("Proposal must be approved before merging");
238
+ }
239
+ // Fetch source nodes
240
+ const sourceNodes = await this.db.node.findMany({
241
+ where: { id: { in: proposal.sourceNodeIds } },
242
+ });
243
+ // Generate merged content
244
+ let mergedTitle = opts.title ?? proposal.topicLabel;
245
+ let mergedContent;
246
+ if (opts.content) {
247
+ mergedContent = opts.content;
248
+ }
249
+ else if (opts.llmSummarizer) {
250
+ const contents = sourceNodes.map((n) => `## ${n.title}\n\n${n.content}`);
251
+ mergedContent = await opts.llmSummarizer(contents);
252
+ }
253
+ else {
254
+ // Fallback: concatenate
255
+ mergedContent = sourceNodes
256
+ .map((n) => `## ${n.title}\n\n${n.content}`)
257
+ .join("\n\n---\n\n");
258
+ }
259
+ // Create merged node
260
+ const mergedNode = await opts.nodeService.create({
261
+ type: "note",
262
+ title: mergedTitle,
263
+ content: mergedContent,
264
+ status: "approved",
265
+ metadata: {
266
+ mergedFrom: proposal.sourceNodeIds,
267
+ mergedAt: new Date().toISOString(),
268
+ capturedFromSession: "merged",
269
+ },
270
+ createdBy: opts.mergedBy,
271
+ });
272
+ // Transfer edges: collect all edges from/to source nodes
273
+ const sourceNodeIdSet = new Set(proposal.sourceNodeIds);
274
+ let edgesTransferred = 0;
275
+ for (const sourceNode of sourceNodes) {
276
+ // Edges where source node is the source
277
+ const outEdges = await this.db.edge.findMany({
278
+ where: { sourceNodeId: sourceNode.id },
279
+ });
280
+ // Edges where source node is the target
281
+ const inEdges = await this.db.edge.findMany({
282
+ where: { targetNodeId: sourceNode.id },
283
+ });
284
+ // Track created edges to avoid duplicates
285
+ const createdEdgeKeys = new Set();
286
+ for (const edge of outEdges) {
287
+ // Skip edges between source nodes (they'll be archived)
288
+ if (sourceNodeIdSet.has(edge.targetNodeId))
289
+ continue;
290
+ const key = `${mergedNode.id}→${edge.targetNodeId}:${edge.relationshipType}`;
291
+ if (createdEdgeKeys.has(key))
292
+ continue;
293
+ createdEdgeKeys.add(key);
294
+ try {
295
+ await opts.edgeService.create({
296
+ sourceNodeId: mergedNode.id,
297
+ targetNodeId: edge.targetNodeId,
298
+ relationshipType: edge.relationshipType,
299
+ weight: edge.weight,
300
+ metadata: edge.metadata,
301
+ createdBy: opts.mergedBy,
302
+ });
303
+ edgesTransferred++;
304
+ }
305
+ catch {
306
+ // Skip if edge creation fails (e.g. target deleted)
307
+ }
308
+ }
309
+ for (const edge of inEdges) {
310
+ if (sourceNodeIdSet.has(edge.sourceNodeId))
311
+ continue;
312
+ const key = `${edge.sourceNodeId}→${mergedNode.id}:${edge.relationshipType}`;
313
+ if (createdEdgeKeys.has(key))
314
+ continue;
315
+ createdEdgeKeys.add(key);
316
+ try {
317
+ await opts.edgeService.create({
318
+ sourceNodeId: edge.sourceNodeId,
319
+ targetNodeId: mergedNode.id,
320
+ relationshipType: edge.relationshipType,
321
+ weight: edge.weight,
322
+ metadata: edge.metadata,
323
+ createdBy: opts.mergedBy,
324
+ });
325
+ edgesTransferred++;
326
+ }
327
+ catch {
328
+ // Skip failures
329
+ }
330
+ }
331
+ }
332
+ // Archive source nodes
333
+ const archivedNodeIds = [];
334
+ for (const sourceNode of sourceNodes) {
335
+ const existingMetadata = sourceNode.metadata ?? {};
336
+ await this.db.node.update({
337
+ where: { id: sourceNode.id },
338
+ data: {
339
+ status: "archived",
340
+ metadata: {
341
+ ...existingMetadata,
342
+ mergedInto: mergedNode.id,
343
+ },
344
+ },
345
+ });
346
+ archivedNodeIds.push(sourceNode.id);
347
+ }
348
+ // Update proposal
349
+ await this.db.mergeProposal.update({
350
+ where: { id: proposalId },
351
+ data: {
352
+ status: "merged",
353
+ mergedNodeId: mergedNode.id,
354
+ resolvedBy: opts.mergedBy,
355
+ resolvedAt: new Date(),
356
+ },
357
+ });
358
+ return {
359
+ mergedNodeId: mergedNode.id,
360
+ archivedNodeIds,
361
+ edgesTransferred,
362
+ };
363
+ }
364
+ /**
365
+ * Mark a node as canonical by applying the `canonical` tag.
366
+ */
367
+ async markCanonical(nodeId, tagService, taggedBy) {
368
+ // Ensure the canonical tag definition exists
369
+ let def = await this.db.tagDefinition.findFirst({
370
+ where: { tagName: "canonical" },
371
+ });
372
+ if (!def) {
373
+ def = await tagService.createDefinition({
374
+ tagName: "canonical",
375
+ tagType: "text",
376
+ cardinality: "singleton",
377
+ source: "declared",
378
+ description: "Marks a node as the canonical/authoritative answer for a topic",
379
+ createdBy: taggedBy,
380
+ });
381
+ }
382
+ // Apply tag (idempotent — check if already tagged)
383
+ const existing = await this.db.nodeTag.findFirst({
384
+ where: { nodeId, tagName: "canonical" },
385
+ });
386
+ if (!existing) {
387
+ await tagService.applyTags(nodeId, [{ tagName: "canonical" }], taggedBy);
388
+ }
389
+ }
390
+ /**
391
+ * Remove canonical tag from a node.
392
+ */
393
+ async removeCanonical(nodeId) {
394
+ const tag = await this.db.nodeTag.findFirst({
395
+ where: { nodeId, tagName: "canonical" },
396
+ });
397
+ if (tag) {
398
+ await this.db.nodeTag.delete({ where: { id: tag.id } });
399
+ }
400
+ }
401
+ // ── Private helpers ─────────────────────────────────────────────────────
402
+ /**
403
+ * Find similarity pairs among chat nodes using the embedding self-join.
404
+ * Scoped to nodes with capturedFromSession metadata.
405
+ */
406
+ async findChatSimilarityPairs(threshold, limit) {
407
+ const orgId = this.tenantCtx.organizationId;
408
+ const pairs = await this.db.$queryRaw `
409
+ SELECT
410
+ a.id AS a_id,
411
+ b.id AS b_id,
412
+ 1 - (a.embedding <=> b.embedding) AS similarity
413
+ FROM nodes a
414
+ JOIN nodes b ON a.id < b.id
415
+ AND b.organization_id = ${orgId}::uuid
416
+ WHERE a.embedding IS NOT NULL
417
+ AND b.embedding IS NOT NULL
418
+ AND a.metadata->>'capturedFromSession' IS NOT NULL
419
+ AND b.metadata->>'capturedFromSession' IS NOT NULL
420
+ AND a.status != 'archived'
421
+ AND b.status != 'archived'
422
+ AND 1 - (a.embedding <=> b.embedding) >= ${threshold}
423
+ AND a.organization_id = ${orgId}::uuid
424
+ ORDER BY similarity DESC
425
+ LIMIT ${limit}
426
+ `;
427
+ return pairs.map((p) => ({
428
+ nodeAId: p.a_id,
429
+ nodeBId: p.b_id,
430
+ similarity: Number(p.similarity),
431
+ }));
432
+ }
433
+ }
434
+ //# sourceMappingURL=dedup-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup-service.js","sourceRoot":"","sources":["../../src/services/dedup-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dedup-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup-service.test.d.ts","sourceRoot":"","sources":["../../src/services/dedup-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,160 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { DedupService } from "./dedup-service.js";
3
+ describe("DedupService.computeClusters", () => {
4
+ // Use a minimal mock — computeClusters is a pure function that doesn't touch the DB
5
+ const svc = new DedupService({}, { organizationId: "org-1" });
6
+ it("returns empty array for empty input", () => {
7
+ const clusters = svc.computeClusters([]);
8
+ expect(clusters).toEqual([]);
9
+ });
10
+ it("clusters a single pair into one cluster of size 2", () => {
11
+ const pairs = [
12
+ { nodeAId: "a", nodeBId: "b", similarity: 0.9 },
13
+ ];
14
+ const clusters = svc.computeClusters(pairs);
15
+ expect(clusters).toHaveLength(1);
16
+ expect(clusters[0].nodeIds).toHaveLength(2);
17
+ expect(clusters[0].nodeIds).toContain("a");
18
+ expect(clusters[0].nodeIds).toContain("b");
19
+ expect(clusters[0].minSimilarity).toBe(0.9);
20
+ expect(clusters[0].avgSimilarity).toBe(0.9);
21
+ });
22
+ it("merges connected chain into a single cluster", () => {
23
+ // a-b, b-c → one cluster {a, b, c}
24
+ const pairs = [
25
+ { nodeAId: "a", nodeBId: "b", similarity: 0.85 },
26
+ { nodeAId: "b", nodeBId: "c", similarity: 0.9 },
27
+ ];
28
+ const clusters = svc.computeClusters(pairs);
29
+ expect(clusters).toHaveLength(1);
30
+ expect(clusters[0].nodeIds).toHaveLength(3);
31
+ expect(clusters[0].nodeIds).toContain("a");
32
+ expect(clusters[0].nodeIds).toContain("b");
33
+ expect(clusters[0].nodeIds).toContain("c");
34
+ expect(clusters[0].minSimilarity).toBe(0.85);
35
+ expect(clusters[0].avgSimilarity).toBe(0.875);
36
+ });
37
+ it("keeps disjoint pairs as separate clusters", () => {
38
+ const pairs = [
39
+ { nodeAId: "a", nodeBId: "b", similarity: 0.9 },
40
+ { nodeAId: "c", nodeBId: "d", similarity: 0.85 },
41
+ ];
42
+ const clusters = svc.computeClusters(pairs);
43
+ expect(clusters).toHaveLength(2);
44
+ const sizes = clusters.map((c) => c.nodeIds.length).sort();
45
+ expect(sizes).toEqual([2, 2]);
46
+ });
47
+ it("merges all nodes into one cluster when fully connected", () => {
48
+ const pairs = [
49
+ { nodeAId: "a", nodeBId: "b", similarity: 0.9 },
50
+ { nodeAId: "b", nodeBId: "c", similarity: 0.85 },
51
+ { nodeAId: "a", nodeBId: "c", similarity: 0.88 },
52
+ ];
53
+ const clusters = svc.computeClusters(pairs);
54
+ expect(clusters).toHaveLength(1);
55
+ expect(clusters[0].nodeIds).toHaveLength(3);
56
+ });
57
+ it("handles larger chains correctly", () => {
58
+ // a-b, b-c, c-d, e-f → two clusters: {a,b,c,d} and {e,f}
59
+ const pairs = [
60
+ { nodeAId: "a", nodeBId: "b", similarity: 0.9 },
61
+ { nodeAId: "b", nodeBId: "c", similarity: 0.88 },
62
+ { nodeAId: "c", nodeBId: "d", similarity: 0.85 },
63
+ { nodeAId: "e", nodeBId: "f", similarity: 0.92 },
64
+ ];
65
+ const clusters = svc.computeClusters(pairs);
66
+ expect(clusters).toHaveLength(2);
67
+ const sizes = clusters.map((c) => c.nodeIds.length).sort((a, b) => a - b);
68
+ expect(sizes).toEqual([2, 4]);
69
+ });
70
+ it("computes min and avg similarity correctly", () => {
71
+ const pairs = [
72
+ { nodeAId: "a", nodeBId: "b", similarity: 0.9 },
73
+ { nodeAId: "b", nodeBId: "c", similarity: 0.8 },
74
+ { nodeAId: "a", nodeBId: "c", similarity: 0.85 },
75
+ ];
76
+ const clusters = svc.computeClusters(pairs);
77
+ expect(clusters).toHaveLength(1);
78
+ expect(clusters[0].minSimilarity).toBe(0.8);
79
+ // avg = (0.9 + 0.8 + 0.85) / 3 = 0.85
80
+ expect(clusters[0].avgSimilarity).toBe(0.85);
81
+ });
82
+ });
83
+ describe("DedupService.updateProposalStatus transitions", () => {
84
+ it("rejects invalid transitions", async () => {
85
+ const mockDb = {
86
+ mergeProposal: {
87
+ findUnique: async () => ({ id: "p1", status: "pending" }),
88
+ update: async () => ({}),
89
+ },
90
+ };
91
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
92
+ // pending → merged is not allowed (must go through approved first)
93
+ await expect(svc.updateProposalStatus("p1", "merged", "user-1")).rejects.toThrow("Invalid transition");
94
+ });
95
+ it("allows pending → approved", async () => {
96
+ const updatedData = {};
97
+ const mockDb = {
98
+ mergeProposal: {
99
+ findUnique: async () => ({ id: "p1", status: "pending" }),
100
+ update: async (args) => {
101
+ Object.assign(updatedData, args.data);
102
+ return { id: "p1", ...args.data };
103
+ },
104
+ },
105
+ };
106
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
107
+ await svc.updateProposalStatus("p1", "approved", "user-1");
108
+ expect(updatedData.status).toBe("approved");
109
+ expect(updatedData.resolvedBy).toBe("user-1");
110
+ });
111
+ it("allows pending → rejected", async () => {
112
+ const updatedData = {};
113
+ const mockDb = {
114
+ mergeProposal: {
115
+ findUnique: async () => ({ id: "p1", status: "pending" }),
116
+ update: async (args) => {
117
+ Object.assign(updatedData, args.data);
118
+ return { id: "p1", ...args.data };
119
+ },
120
+ },
121
+ };
122
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
123
+ await svc.updateProposalStatus("p1", "rejected", "user-1");
124
+ expect(updatedData.status).toBe("rejected");
125
+ });
126
+ it("allows approved → merged", async () => {
127
+ const updatedData = {};
128
+ const mockDb = {
129
+ mergeProposal: {
130
+ findUnique: async () => ({ id: "p1", status: "approved" }),
131
+ update: async (args) => {
132
+ Object.assign(updatedData, args.data);
133
+ return { id: "p1", ...args.data };
134
+ },
135
+ },
136
+ };
137
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
138
+ await svc.updateProposalStatus("p1", "merged", "user-1");
139
+ expect(updatedData.status).toBe("merged");
140
+ });
141
+ it("rejects transition from rejected status", async () => {
142
+ const mockDb = {
143
+ mergeProposal: {
144
+ findUnique: async () => ({ id: "p1", status: "rejected" }),
145
+ },
146
+ };
147
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
148
+ await expect(svc.updateProposalStatus("p1", "approved", "user-1")).rejects.toThrow("Invalid transition");
149
+ });
150
+ it("throws on proposal not found", async () => {
151
+ const mockDb = {
152
+ mergeProposal: {
153
+ findUnique: async () => null,
154
+ },
155
+ };
156
+ const svc = new DedupService(mockDb, { organizationId: "org-1" });
157
+ await expect(svc.updateProposalStatus("missing", "approved", "user-1")).rejects.toThrow("Proposal not found");
158
+ });
159
+ });
160
+ //# sourceMappingURL=dedup-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup-service.test.js","sourceRoot":"","sources":["../../src/services/dedup-service.test.ts"],"names":[],"mappings":"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"}