@jamesaphoenix/tx-core 0.4.1
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.
- package/dist/db.d.ts +42 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +46 -0
- package/dist/db.js.map +1 -0
- package/dist/errors.d.ts +231 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +139 -0
- package/dist/errors.js.map +1 -0
- package/dist/id.d.ts +6 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +21 -0
- package/dist/id.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/layer.d.ts +50 -0
- package/dist/layer.d.ts.map +1 -0
- package/dist/layer.js +155 -0
- package/dist/layer.js.map +1 -0
- package/dist/mappers/anchor.d.ts +14 -0
- package/dist/mappers/anchor.d.ts.map +1 -0
- package/dist/mappers/anchor.js +38 -0
- package/dist/mappers/anchor.js.map +1 -0
- package/dist/mappers/attempt.d.ts +15 -0
- package/dist/mappers/attempt.d.ts.map +1 -0
- package/dist/mappers/attempt.js +23 -0
- package/dist/mappers/attempt.js.map +1 -0
- package/dist/mappers/candidate.d.ts +23 -0
- package/dist/mappers/candidate.d.ts.map +1 -0
- package/dist/mappers/candidate.js +53 -0
- package/dist/mappers/candidate.js.map +1 -0
- package/dist/mappers/claim.d.ts +30 -0
- package/dist/mappers/claim.d.ts.map +1 -0
- package/dist/mappers/claim.js +32 -0
- package/dist/mappers/claim.js.map +1 -0
- package/dist/mappers/deduplication.d.ts +39 -0
- package/dist/mappers/deduplication.d.ts.map +1 -0
- package/dist/mappers/deduplication.js +53 -0
- package/dist/mappers/deduplication.js.map +1 -0
- package/dist/mappers/edge.d.ts +10 -0
- package/dist/mappers/edge.d.ts.map +1 -0
- package/dist/mappers/edge.js +19 -0
- package/dist/mappers/edge.js.map +1 -0
- package/dist/mappers/file-learning.d.ts +14 -0
- package/dist/mappers/file-learning.d.ts.map +1 -0
- package/dist/mappers/file-learning.js +75 -0
- package/dist/mappers/file-learning.js.map +1 -0
- package/dist/mappers/index.d.ts +17 -0
- package/dist/mappers/index.d.ts.map +1 -0
- package/dist/mappers/index.js +30 -0
- package/dist/mappers/index.js.map +1 -0
- package/dist/mappers/learning.d.ts +19 -0
- package/dist/mappers/learning.d.ts.map +1 -0
- package/dist/mappers/learning.js +41 -0
- package/dist/mappers/learning.js.map +1 -0
- package/dist/mappers/orchestrator-state.d.ts +33 -0
- package/dist/mappers/orchestrator-state.d.ts.map +1 -0
- package/dist/mappers/orchestrator-state.js +34 -0
- package/dist/mappers/orchestrator-state.js.map +1 -0
- package/dist/mappers/run.d.ts +32 -0
- package/dist/mappers/run.d.ts.map +1 -0
- package/dist/mappers/run.js +64 -0
- package/dist/mappers/run.js.map +1 -0
- package/dist/mappers/task.d.ts +23 -0
- package/dist/mappers/task.d.ts.map +1 -0
- package/dist/mappers/task.js +54 -0
- package/dist/mappers/task.js.map +1 -0
- package/dist/mappers/tracked-project.d.ts +15 -0
- package/dist/mappers/tracked-project.d.ts.map +1 -0
- package/dist/mappers/tracked-project.js +23 -0
- package/dist/mappers/tracked-project.js.map +1 -0
- package/dist/mappers/worker.d.ts +33 -0
- package/dist/mappers/worker.d.ts.map +1 -0
- package/dist/mappers/worker.js +35 -0
- package/dist/mappers/worker.js.map +1 -0
- package/dist/repo/anchor-repo.d.ts +52 -0
- package/dist/repo/anchor-repo.d.ts.map +1 -0
- package/dist/repo/anchor-repo.js +204 -0
- package/dist/repo/anchor-repo.js.map +1 -0
- package/dist/repo/attempt-repo.d.ts +25 -0
- package/dist/repo/attempt-repo.d.ts.map +1 -0
- package/dist/repo/attempt-repo.js +78 -0
- package/dist/repo/attempt-repo.js.map +1 -0
- package/dist/repo/candidate-repo.d.ts +16 -0
- package/dist/repo/candidate-repo.d.ts.map +1 -0
- package/dist/repo/candidate-repo.js +143 -0
- package/dist/repo/candidate-repo.js.map +1 -0
- package/dist/repo/claim-repo.d.ts +17 -0
- package/dist/repo/claim-repo.d.ts.map +1 -0
- package/dist/repo/claim-repo.js +62 -0
- package/dist/repo/claim-repo.js.map +1 -0
- package/dist/repo/deduplication-repo.d.ts +37 -0
- package/dist/repo/deduplication-repo.d.ts.map +1 -0
- package/dist/repo/deduplication-repo.js +133 -0
- package/dist/repo/deduplication-repo.js.map +1 -0
- package/dist/repo/dep-repo.d.ts +19 -0
- package/dist/repo/dep-repo.d.ts.map +1 -0
- package/dist/repo/dep-repo.js +104 -0
- package/dist/repo/dep-repo.js.map +1 -0
- package/dist/repo/edge-repo.d.ts +26 -0
- package/dist/repo/edge-repo.d.ts.map +1 -0
- package/dist/repo/edge-repo.js +227 -0
- package/dist/repo/edge-repo.js.map +1 -0
- package/dist/repo/file-learning-repo.d.ts +17 -0
- package/dist/repo/file-learning-repo.d.ts.map +1 -0
- package/dist/repo/file-learning-repo.js +60 -0
- package/dist/repo/file-learning-repo.js.map +1 -0
- package/dist/repo/index.d.ts +18 -0
- package/dist/repo/index.d.ts.map +1 -0
- package/dist/repo/index.js +18 -0
- package/dist/repo/index.js.map +1 -0
- package/dist/repo/learning-repo.d.ts +31 -0
- package/dist/repo/learning-repo.d.ts.map +1 -0
- package/dist/repo/learning-repo.js +165 -0
- package/dist/repo/learning-repo.js.map +1 -0
- package/dist/repo/orchestrator-state-repo.d.ts +27 -0
- package/dist/repo/orchestrator-state-repo.d.ts.map +1 -0
- package/dist/repo/orchestrator-state-repo.js +96 -0
- package/dist/repo/orchestrator-state-repo.js.map +1 -0
- package/dist/repo/run-repo.d.ts +31 -0
- package/dist/repo/run-repo.d.ts.map +1 -0
- package/dist/repo/run-repo.js +132 -0
- package/dist/repo/run-repo.js.map +1 -0
- package/dist/repo/task-repo.d.ts +21 -0
- package/dist/repo/task-repo.d.ts.map +1 -0
- package/dist/repo/task-repo.js +169 -0
- package/dist/repo/task-repo.js.map +1 -0
- package/dist/repo/tracked-project-repo.d.ts +16 -0
- package/dist/repo/tracked-project-repo.d.ts.map +1 -0
- package/dist/repo/tracked-project-repo.js +54 -0
- package/dist/repo/tracked-project-repo.js.map +1 -0
- package/dist/repo/worker-repo.d.ts +19 -0
- package/dist/repo/worker-repo.d.ts.map +1 -0
- package/dist/repo/worker-repo.js +72 -0
- package/dist/repo/worker-repo.js.map +1 -0
- package/dist/schemas/index.d.ts +8 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/sync.d.ts +296 -0
- package/dist/schemas/sync.d.ts.map +1 -0
- package/dist/schemas/sync.js +146 -0
- package/dist/schemas/sync.js.map +1 -0
- package/dist/schemas/worker.d.ts +77 -0
- package/dist/schemas/worker.d.ts.map +1 -0
- package/dist/schemas/worker.js +80 -0
- package/dist/schemas/worker.js.map +1 -0
- package/dist/services/anchor-service.d.ts +147 -0
- package/dist/services/anchor-service.d.ts.map +1 -0
- package/dist/services/anchor-service.js +540 -0
- package/dist/services/anchor-service.js.map +1 -0
- package/dist/services/anchor-verification.d.ts +94 -0
- package/dist/services/anchor-verification.d.ts.map +1 -0
- package/dist/services/anchor-verification.js +617 -0
- package/dist/services/anchor-verification.js.map +1 -0
- package/dist/services/ast-grep-service.d.ts +58 -0
- package/dist/services/ast-grep-service.d.ts.map +1 -0
- package/dist/services/ast-grep-service.js +356 -0
- package/dist/services/ast-grep-service.js.map +1 -0
- package/dist/services/attempt-service.d.ts +24 -0
- package/dist/services/attempt-service.d.ts.map +1 -0
- package/dist/services/attempt-service.js +55 -0
- package/dist/services/attempt-service.js.map +1 -0
- package/dist/services/auto-sync-service.d.ts +56 -0
- package/dist/services/auto-sync-service.d.ts.map +1 -0
- package/dist/services/auto-sync-service.js +66 -0
- package/dist/services/auto-sync-service.js.map +1 -0
- package/dist/services/candidate-extractor-service.d.ts +56 -0
- package/dist/services/candidate-extractor-service.d.ts.map +1 -0
- package/dist/services/candidate-extractor-service.js +365 -0
- package/dist/services/candidate-extractor-service.js.map +1 -0
- package/dist/services/claim-service.d.ts +52 -0
- package/dist/services/claim-service.d.ts.map +1 -0
- package/dist/services/claim-service.js +134 -0
- package/dist/services/claim-service.js.map +1 -0
- package/dist/services/daemon-service.d.ts +214 -0
- package/dist/services/daemon-service.d.ts.map +1 -0
- package/dist/services/daemon-service.js +522 -0
- package/dist/services/daemon-service.js.map +1 -0
- package/dist/services/deduplication-service.d.ts +67 -0
- package/dist/services/deduplication-service.d.ts.map +1 -0
- package/dist/services/deduplication-service.js +145 -0
- package/dist/services/deduplication-service.js.map +1 -0
- package/dist/services/dep-service.d.ts +14 -0
- package/dist/services/dep-service.d.ts.map +1 -0
- package/dist/services/dep-service.js +34 -0
- package/dist/services/dep-service.js.map +1 -0
- package/dist/services/diversifier-service.d.ts +46 -0
- package/dist/services/diversifier-service.d.ts.map +1 -0
- package/dist/services/diversifier-service.js +197 -0
- package/dist/services/diversifier-service.js.map +1 -0
- package/dist/services/edge-service.d.ts +78 -0
- package/dist/services/edge-service.d.ts.map +1 -0
- package/dist/services/edge-service.js +158 -0
- package/dist/services/edge-service.js.map +1 -0
- package/dist/services/embedding-service.d.ts +138 -0
- package/dist/services/embedding-service.d.ts.map +1 -0
- package/dist/services/embedding-service.js +318 -0
- package/dist/services/embedding-service.js.map +1 -0
- package/dist/services/feedback-tracker.d.ts +64 -0
- package/dist/services/feedback-tracker.d.ts.map +1 -0
- package/dist/services/feedback-tracker.js +110 -0
- package/dist/services/feedback-tracker.js.map +1 -0
- package/dist/services/file-learning-service.d.ts +17 -0
- package/dist/services/file-learning-service.d.ts.map +1 -0
- package/dist/services/file-learning-service.js +41 -0
- package/dist/services/file-learning-service.js.map +1 -0
- package/dist/services/file-watcher-service.d.ts +141 -0
- package/dist/services/file-watcher-service.d.ts.map +1 -0
- package/dist/services/file-watcher-service.js +278 -0
- package/dist/services/file-watcher-service.js.map +1 -0
- package/dist/services/graph-expansion.d.ts +155 -0
- package/dist/services/graph-expansion.d.ts.map +1 -0
- package/dist/services/graph-expansion.js +466 -0
- package/dist/services/graph-expansion.js.map +1 -0
- package/dist/services/hierarchy-service.d.ts +16 -0
- package/dist/services/hierarchy-service.d.ts.map +1 -0
- package/dist/services/hierarchy-service.js +66 -0
- package/dist/services/hierarchy-service.js.map +1 -0
- package/dist/services/index.d.ts +36 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +36 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/learning-service.d.ts +39 -0
- package/dist/services/learning-service.d.ts.map +1 -0
- package/dist/services/learning-service.js +151 -0
- package/dist/services/learning-service.js.map +1 -0
- package/dist/services/migration-service.d.ts +67 -0
- package/dist/services/migration-service.d.ts.map +1 -0
- package/dist/services/migration-service.js +144 -0
- package/dist/services/migration-service.js.map +1 -0
- package/dist/services/orchestrator-service.d.ts +52 -0
- package/dist/services/orchestrator-service.d.ts.map +1 -0
- package/dist/services/orchestrator-service.js +203 -0
- package/dist/services/orchestrator-service.js.map +1 -0
- package/dist/services/promotion-service.d.ts +67 -0
- package/dist/services/promotion-service.d.ts.map +1 -0
- package/dist/services/promotion-service.js +151 -0
- package/dist/services/promotion-service.js.map +1 -0
- package/dist/services/query-expansion-service.d.ts +55 -0
- package/dist/services/query-expansion-service.d.ts.map +1 -0
- package/dist/services/query-expansion-service.js +174 -0
- package/dist/services/query-expansion-service.js.map +1 -0
- package/dist/services/ready-service.d.ts +16 -0
- package/dist/services/ready-service.d.ts.map +1 -0
- package/dist/services/ready-service.js +70 -0
- package/dist/services/ready-service.js.map +1 -0
- package/dist/services/reranker-service.d.ts +51 -0
- package/dist/services/reranker-service.d.ts.map +1 -0
- package/dist/services/reranker-service.js +128 -0
- package/dist/services/reranker-service.js.map +1 -0
- package/dist/services/retriever-service.d.ts +49 -0
- package/dist/services/retriever-service.d.ts.map +1 -0
- package/dist/services/retriever-service.js +419 -0
- package/dist/services/retriever-service.js.map +1 -0
- package/dist/services/score-service.d.ts +43 -0
- package/dist/services/score-service.d.ts.map +1 -0
- package/dist/services/score-service.js +82 -0
- package/dist/services/score-service.js.map +1 -0
- package/dist/services/swarm-verification.d.ts +104 -0
- package/dist/services/swarm-verification.d.ts.map +1 -0
- package/dist/services/swarm-verification.js +400 -0
- package/dist/services/swarm-verification.js.map +1 -0
- package/dist/services/sync-service.d.ts +115 -0
- package/dist/services/sync-service.d.ts.map +1 -0
- package/dist/services/sync-service.js +350 -0
- package/dist/services/sync-service.js.map +1 -0
- package/dist/services/task-service.d.ts +22 -0
- package/dist/services/task-service.d.ts.map +1 -0
- package/dist/services/task-service.js +221 -0
- package/dist/services/task-service.js.map +1 -0
- package/dist/services/worker-process.d.ts +41 -0
- package/dist/services/worker-process.d.ts.map +1 -0
- package/dist/services/worker-process.js +280 -0
- package/dist/services/worker-process.js.map +1 -0
- package/dist/services/worker-service.d.ts +74 -0
- package/dist/services/worker-service.d.ts.map +1 -0
- package/dist/services/worker-service.js +148 -0
- package/dist/services/worker-service.js.map +1 -0
- package/dist/utils/glob.d.ts +15 -0
- package/dist/utils/glob.d.ts.map +1 -0
- package/dist/utils/glob.js +27 -0
- package/dist/utils/glob.js.map +1 -0
- package/dist/utils/math.d.ts +6 -0
- package/dist/utils/math.d.ts.map +1 -0
- package/dist/utils/math.js +21 -0
- package/dist/utils/math.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { DeduplicationRepository } from "../repo/deduplication-repo.js";
|
|
3
|
+
import { hashContent } from "../mappers/deduplication.js";
|
|
4
|
+
/**
|
|
5
|
+
* Default batch size for hash checking operations.
|
|
6
|
+
* Balances between query efficiency and memory usage.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_BATCH_SIZE = 100;
|
|
9
|
+
/**
|
|
10
|
+
* DeduplicationService handles JSONL line deduplication via SHA256 hashing.
|
|
11
|
+
* Tracks processed content hashes to skip already-seen lines.
|
|
12
|
+
* Supports incremental processing by tracking file progress.
|
|
13
|
+
*/
|
|
14
|
+
export class DeduplicationService extends Context.Tag("DeduplicationService")() {
|
|
15
|
+
}
|
|
16
|
+
export const DeduplicationServiceLive = Layer.effect(DeduplicationService, Effect.gen(function* () {
|
|
17
|
+
const repo = yield* DeduplicationRepository;
|
|
18
|
+
return {
|
|
19
|
+
processLine: (content, filePath, lineNumber) => Effect.gen(function* () {
|
|
20
|
+
const hash = hashContent(content);
|
|
21
|
+
const exists = yield* repo.hashExists(hash);
|
|
22
|
+
if (exists) {
|
|
23
|
+
return {
|
|
24
|
+
hash,
|
|
25
|
+
isNew: false,
|
|
26
|
+
lineNumber,
|
|
27
|
+
content
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// Record the new hash
|
|
31
|
+
yield* repo.insertHash({
|
|
32
|
+
contentHash: hash,
|
|
33
|
+
sourceFile: filePath,
|
|
34
|
+
sourceLine: lineNumber
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
hash,
|
|
38
|
+
isNew: true,
|
|
39
|
+
lineNumber,
|
|
40
|
+
content
|
|
41
|
+
};
|
|
42
|
+
}),
|
|
43
|
+
processLines: (lines, filePath, options = {}) => Effect.gen(function* () {
|
|
44
|
+
const startTime = Date.now();
|
|
45
|
+
const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
46
|
+
const startLine = options.startLine ?? 1;
|
|
47
|
+
const maxLines = options.maxLines;
|
|
48
|
+
// Filter to lines we should process
|
|
49
|
+
let linesToProcess = lines.filter(l => l.lineNumber >= startLine);
|
|
50
|
+
if (maxLines !== undefined) {
|
|
51
|
+
linesToProcess = linesToProcess.slice(0, maxLines);
|
|
52
|
+
}
|
|
53
|
+
if (linesToProcess.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
filePath,
|
|
56
|
+
totalLines: lines.length,
|
|
57
|
+
newLines: 0,
|
|
58
|
+
skippedLines: 0,
|
|
59
|
+
startLine,
|
|
60
|
+
endLine: startLine - 1,
|
|
61
|
+
duration: Date.now() - startTime
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Compute hashes for all lines
|
|
65
|
+
const lineHashes = linesToProcess.map(l => ({
|
|
66
|
+
...l,
|
|
67
|
+
hash: hashContent(l.content)
|
|
68
|
+
}));
|
|
69
|
+
// Check existing hashes in batches
|
|
70
|
+
let existingHashes = new Set();
|
|
71
|
+
for (let i = 0; i < lineHashes.length; i += batchSize) {
|
|
72
|
+
const batch = lineHashes.slice(i, i + batchSize);
|
|
73
|
+
const batchHashes = batch.map(l => l.hash);
|
|
74
|
+
const batchExisting = yield* repo.hashesExist(batchHashes);
|
|
75
|
+
existingHashes = new Set([...existingHashes, ...batchExisting]);
|
|
76
|
+
}
|
|
77
|
+
// Separate new and existing lines
|
|
78
|
+
const newLines = lineHashes.filter(l => !existingHashes.has(l.hash));
|
|
79
|
+
const skippedLines = lineHashes.filter(l => existingHashes.has(l.hash));
|
|
80
|
+
// Insert new hashes in batches
|
|
81
|
+
if (newLines.length > 0) {
|
|
82
|
+
const hashInputs = newLines.map(l => ({
|
|
83
|
+
contentHash: l.hash,
|
|
84
|
+
sourceFile: filePath,
|
|
85
|
+
sourceLine: l.lineNumber
|
|
86
|
+
}));
|
|
87
|
+
yield* repo.insertHashes(hashInputs);
|
|
88
|
+
}
|
|
89
|
+
// Calculate end line
|
|
90
|
+
const lastLine = linesToProcess[linesToProcess.length - 1];
|
|
91
|
+
const endLine = lastLine?.lineNumber ?? startLine - 1;
|
|
92
|
+
return {
|
|
93
|
+
filePath,
|
|
94
|
+
totalLines: lines.length,
|
|
95
|
+
newLines: newLines.length,
|
|
96
|
+
skippedLines: skippedLines.length,
|
|
97
|
+
startLine,
|
|
98
|
+
endLine,
|
|
99
|
+
duration: Date.now() - startTime
|
|
100
|
+
};
|
|
101
|
+
}),
|
|
102
|
+
isProcessed: (content) => Effect.gen(function* () {
|
|
103
|
+
const hash = hashContent(content);
|
|
104
|
+
return yield* repo.hashExists(hash);
|
|
105
|
+
}),
|
|
106
|
+
filterProcessed: (contents) => Effect.gen(function* () {
|
|
107
|
+
if (contents.length === 0)
|
|
108
|
+
return new Set();
|
|
109
|
+
// Compute hashes and check
|
|
110
|
+
const contentHashMap = new Map();
|
|
111
|
+
for (const content of contents) {
|
|
112
|
+
contentHashMap.set(hashContent(content), content);
|
|
113
|
+
}
|
|
114
|
+
const existingHashes = yield* repo.hashesExist([...contentHashMap.keys()]);
|
|
115
|
+
// Return the original content strings that have been processed
|
|
116
|
+
const processedContents = new Set();
|
|
117
|
+
for (const hash of existingHashes) {
|
|
118
|
+
const content = contentHashMap.get(hash);
|
|
119
|
+
if (content)
|
|
120
|
+
processedContents.add(content);
|
|
121
|
+
}
|
|
122
|
+
return processedContents;
|
|
123
|
+
}),
|
|
124
|
+
getProgress: (filePath) => repo.getFileProgress(filePath),
|
|
125
|
+
updateProgress: (filePath, lastLineProcessed, lastByteOffset, fileSize, fileChecksum) => repo.upsertFileProgress({
|
|
126
|
+
filePath,
|
|
127
|
+
lastLineProcessed,
|
|
128
|
+
lastByteOffset,
|
|
129
|
+
fileSize,
|
|
130
|
+
fileChecksum
|
|
131
|
+
}),
|
|
132
|
+
resetFile: (filePath) => Effect.gen(function* () {
|
|
133
|
+
const hashesDeleted = yield* repo.deleteHashesForFile(filePath);
|
|
134
|
+
yield* repo.deleteFileProgress(filePath);
|
|
135
|
+
return { hashesDeleted };
|
|
136
|
+
}),
|
|
137
|
+
getStats: () => Effect.gen(function* () {
|
|
138
|
+
const totalHashes = yield* repo.countHashes();
|
|
139
|
+
const trackedFiles = yield* repo.countFiles();
|
|
140
|
+
return { totalHashes, trackedFiles };
|
|
141
|
+
}),
|
|
142
|
+
computeHash: hashContent
|
|
143
|
+
};
|
|
144
|
+
}));
|
|
145
|
+
//# sourceMappingURL=deduplication-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deduplication-service.js","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AASzD;;;GAGG;AACH,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAE9B;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAwE1E;CAAG;AAEN,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC,MAAM,CAClD,oBAAoB,EACpB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,uBAAuB,CAAA;IAE3C,OAAO;QACL,WAAW,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,CAC7C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YAE3C,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO;oBACL,IAAI;oBACJ,KAAK,EAAE,KAAK;oBACZ,UAAU;oBACV,OAAO;iBACR,CAAA;YACH,CAAC;YAED,sBAAsB;YACtB,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;gBACrB,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,QAAQ;gBACpB,UAAU,EAAE,UAAU;aACvB,CAAC,CAAA;YAEF,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,IAAI;gBACX,UAAU;gBACV,OAAO;aACR,CAAA;QACH,CAAC,CAAC;QAEJ,YAAY,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CAC9C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;YACzD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;YAEjC,oCAAoC;YACpC,IAAI,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,CAAA;YACjE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;YACpD,CAAC;YAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,OAAO;oBACL,QAAQ;oBACR,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,QAAQ,EAAE,CAAC;oBACX,YAAY,EAAE,CAAC;oBACf,SAAS;oBACT,OAAO,EAAE,SAAS,GAAG,CAAC;oBACtB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBACjC,CAAA;YACH,CAAC;YAED,+BAA+B;YAC/B,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1C,GAAG,CAAC;gBACJ,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;aAC7B,CAAC,CAAC,CAAA;YAEH,mCAAmC;YACnC,IAAI,cAAc,GAAG,IAAI,GAAG,EAAU,CAAA;YACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;gBACtD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAA;gBAChD,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC1C,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;gBAC1D,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,aAAa,CAAC,CAAC,CAAA;YACjE,CAAC;YAED,kCAAkC;YAClC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;YACpE,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;YAEvE,+BAA+B;YAC/B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACpC,WAAW,EAAE,CAAC,CAAC,IAAI;oBACnB,UAAU,EAAE,QAAQ;oBACpB,UAAU,EAAE,CAAC,CAAC,UAAU;iBACzB,CAAC,CAAC,CAAA;gBACH,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;YACtC,CAAC;YAED,qBAAqB;YACrB,MAAM,QAAQ,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YAC1D,MAAM,OAAO,GAAG,QAAQ,EAAE,UAAU,IAAI,SAAS,GAAG,CAAC,CAAA;YAErD,OAAO;gBACL,QAAQ;gBACR,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,QAAQ,EAAE,QAAQ,CAAC,MAAM;gBACzB,YAAY,EAAE,YAAY,CAAC,MAAM;gBACjC,SAAS;gBACT,OAAO;gBACP,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aACjC,CAAA;QACH,CAAC,CAAC;QAEJ,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CACvB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;YACjC,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACrC,CAAC,CAAC;QAEJ,eAAe,EAAE,CAAC,QAAQ,EAAE,EAAE,CAC5B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,GAAG,EAAU,CAAA;YAEnD,2BAA2B;YAC3B,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAA;YAChD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;YACnD,CAAC;YAED,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YAE1E,+DAA+D;YAC/D,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAA;YAC3C,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;gBAClC,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACxC,IAAI,OAAO;oBAAE,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC7C,CAAC;YAED,OAAO,iBAAiB,CAAA;QAC1B,CAAC,CAAC;QAEJ,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAEzD,cAAc,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,CACtF,IAAI,CAAC,kBAAkB,CAAC;YACtB,QAAQ;YACR,iBAAiB;YACjB,cAAc;YACd,QAAQ;YACR,YAAY;SACb,CAAC;QAEJ,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CACtB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAA;YAC/D,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;YACxC,OAAO,EAAE,aAAa,EAAE,CAAA;QAC1B,CAAC,CAAC;QAEJ,QAAQ,EAAE,GAAG,EAAE,CACb,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;YAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAA;YAC7C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAA;QACtC,CAAC,CAAC;QAEJ,WAAW,EAAE,WAAW;KACzB,CAAA;AACH,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { DependencyRepository } from "../repo/dep-repo.js";
|
|
3
|
+
import { TaskRepository } from "../repo/task-repo.js";
|
|
4
|
+
import { ValidationError, CircularDependencyError, TaskNotFoundError, DatabaseError } from "../errors.js";
|
|
5
|
+
import type { TaskId } from "@jamesaphoenix/tx-types";
|
|
6
|
+
declare const DependencyService_base: Context.TagClass<DependencyService, "DependencyService", {
|
|
7
|
+
readonly addBlocker: (taskId: TaskId, blockerId: TaskId) => Effect.Effect<void, ValidationError | CircularDependencyError | TaskNotFoundError | DatabaseError>;
|
|
8
|
+
readonly removeBlocker: (taskId: TaskId, blockerId: TaskId) => Effect.Effect<void, DatabaseError>;
|
|
9
|
+
}>;
|
|
10
|
+
export declare class DependencyService extends DependencyService_base {
|
|
11
|
+
}
|
|
12
|
+
export declare const DependencyServiceLive: Layer.Layer<DependencyService, never, TaskRepository | DependencyRepository>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=dep-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dep-service.d.ts","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;;yBAK5B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,uBAAuB,GAAG,iBAAiB,GAAG,aAAa,CAAC;4BACtI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;;AAJrG,qBAAa,iBAAkB,SAAQ,sBAMpC;CAAG;AAEN,eAAO,MAAM,qBAAqB,8EAqCjC,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { DependencyRepository } from "../repo/dep-repo.js";
|
|
3
|
+
import { TaskRepository } from "../repo/task-repo.js";
|
|
4
|
+
import { ValidationError, CircularDependencyError, TaskNotFoundError } from "../errors.js";
|
|
5
|
+
export class DependencyService extends Context.Tag("DependencyService")() {
|
|
6
|
+
}
|
|
7
|
+
export const DependencyServiceLive = Layer.effect(DependencyService, Effect.gen(function* () {
|
|
8
|
+
const depRepo = yield* DependencyRepository;
|
|
9
|
+
const taskRepo = yield* TaskRepository;
|
|
10
|
+
return {
|
|
11
|
+
addBlocker: (taskId, blockerId) => Effect.gen(function* () {
|
|
12
|
+
if (taskId === blockerId) {
|
|
13
|
+
return yield* Effect.fail(new ValidationError({ reason: "A task cannot block itself" }));
|
|
14
|
+
}
|
|
15
|
+
const task = yield* taskRepo.findById(taskId);
|
|
16
|
+
if (!task) {
|
|
17
|
+
return yield* Effect.fail(new TaskNotFoundError({ id: taskId }));
|
|
18
|
+
}
|
|
19
|
+
const blocker = yield* taskRepo.findById(blockerId);
|
|
20
|
+
if (!blocker) {
|
|
21
|
+
return yield* Effect.fail(new TaskNotFoundError({ id: blockerId }));
|
|
22
|
+
}
|
|
23
|
+
// Cycle detection: check if there's already a path from taskId to blockerId
|
|
24
|
+
// (i.e., blockerId is transitively blocked by taskId)
|
|
25
|
+
const wouldCycle = yield* depRepo.hasPath(blockerId, taskId);
|
|
26
|
+
if (wouldCycle) {
|
|
27
|
+
return yield* Effect.fail(new CircularDependencyError({ taskId, blockerId }));
|
|
28
|
+
}
|
|
29
|
+
yield* depRepo.insert(blockerId, taskId);
|
|
30
|
+
}),
|
|
31
|
+
removeBlocker: (taskId, blockerId) => depRepo.remove(blockerId, taskId)
|
|
32
|
+
};
|
|
33
|
+
}));
|
|
34
|
+
//# sourceMappingURL=dep-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dep-service.js","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAAiB,MAAM,cAAc,CAAA;AAGzG,MAAM,OAAO,iBAAkB,SAAQ,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAMpE;CAAG;AAEN,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,CAC/C,iBAAiB,EACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;IAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,cAAc,CAAA;IAEtC,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAA;YAC1F,CAAC;YAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;YAClE,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YACrE,CAAC;YAED,4EAA4E;YAC5E,sDAAsD;YACtD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;YAC5D,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,uBAAuB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YAC/E,CAAC;YAED,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAC1C,CAAC,CAAC;QAEJ,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CACnC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;KACpC,CAAA;AACH,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import type { LearningWithScore } from "@jamesaphoenix/tx-types";
|
|
3
|
+
declare const DiversifierService_base: Context.TagClass<DiversifierService, "DiversifierService", {
|
|
4
|
+
/**
|
|
5
|
+
* Apply MMR diversification to scored candidates.
|
|
6
|
+
*
|
|
7
|
+
* @param candidates - Learnings with scores, sorted by relevance (highest first)
|
|
8
|
+
* @param limit - Maximum number of results to return
|
|
9
|
+
* @param lambda - Balance between relevance (1.0) and diversity (0.0), default 0.7
|
|
10
|
+
* @returns Diversified list of learnings, maintaining score order within diversity constraints
|
|
11
|
+
*/
|
|
12
|
+
readonly mmrDiversify: (candidates: readonly LearningWithScore[], limit: number, lambda?: number) => Effect.Effect<readonly LearningWithScore[]>;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* DiversifierService provides Maximal Marginal Relevance (MMR) diversification
|
|
16
|
+
* for search results to balance relevance and diversity.
|
|
17
|
+
*
|
|
18
|
+
* MMR iteratively selects items that are both relevant to the query AND
|
|
19
|
+
* dissimilar to already-selected items, preventing redundant results.
|
|
20
|
+
*
|
|
21
|
+
* Design: PRD-010 specifies diversity as a key quality metric for learning retrieval.
|
|
22
|
+
* The service also applies category-based limits to prevent over-representation.
|
|
23
|
+
*/
|
|
24
|
+
export declare class DiversifierService extends DiversifierService_base {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Noop implementation - returns candidates unchanged (just truncated to limit).
|
|
28
|
+
* Used when diversification is not needed or for testing.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DiversifierServiceNoop: Layer.Layer<DiversifierService, never, never>;
|
|
31
|
+
/**
|
|
32
|
+
* Live implementation with full MMR algorithm and category limits.
|
|
33
|
+
*
|
|
34
|
+
* Algorithm:
|
|
35
|
+
* 1. If no embeddings available, fallback to relevance-only ordering with category limits
|
|
36
|
+
* 2. Start with the highest-relevance item
|
|
37
|
+
* 3. Iteratively select the item with highest MMR score that doesn't violate category limits
|
|
38
|
+
* 4. Repeat until limit reached or no candidates remain
|
|
39
|
+
*/
|
|
40
|
+
export declare const DiversifierServiceLive: Layer.Layer<DiversifierService, never, never>;
|
|
41
|
+
/**
|
|
42
|
+
* Auto layer - uses Live implementation since MMR has no external dependencies.
|
|
43
|
+
*/
|
|
44
|
+
export declare const DiversifierServiceAuto: Layer.Layer<DiversifierService, never, never>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=diversifier-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diversifier-service.d.ts","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;;IAgB5D;;;;;;;OAOG;2BACoB,CACrB,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,CAAC;;AAzBpD;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,uBAiBrC;CAAG;AAmGN;;;GAGG;AACH,eAAO,MAAM,sBAAsB,+CAMlC,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,+CAyElC,CAAA;AA4CD;;GAEG;AACH,eAAO,MAAM,sBAAsB,+CAAyB,CAAA"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { cosineSimilarity } from "../utils/math.js";
|
|
3
|
+
/**
|
|
4
|
+
* DiversifierService provides Maximal Marginal Relevance (MMR) diversification
|
|
5
|
+
* for search results to balance relevance and diversity.
|
|
6
|
+
*
|
|
7
|
+
* MMR iteratively selects items that are both relevant to the query AND
|
|
8
|
+
* dissimilar to already-selected items, preventing redundant results.
|
|
9
|
+
*
|
|
10
|
+
* Design: PRD-010 specifies diversity as a key quality metric for learning retrieval.
|
|
11
|
+
* The service also applies category-based limits to prevent over-representation.
|
|
12
|
+
*/
|
|
13
|
+
export class DiversifierService extends Context.Tag("DiversifierService")() {
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Default lambda value for MMR.
|
|
17
|
+
* 0.7 weights relevance higher than diversity (70/30 split).
|
|
18
|
+
* Higher values = more relevant results, lower values = more diverse.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_LAMBDA = 0.7;
|
|
21
|
+
/**
|
|
22
|
+
* Maximum items from the same category allowed in top N results.
|
|
23
|
+
* Per task spec: max 2 results from same category in top 5.
|
|
24
|
+
*/
|
|
25
|
+
const CATEGORY_LIMIT_TOP_N = 5;
|
|
26
|
+
const CATEGORY_MAX_PER_TOP_N = 2;
|
|
27
|
+
/**
|
|
28
|
+
* Calculate maximum cosine similarity between a candidate and selected items.
|
|
29
|
+
* Returns 0 if candidate has no embedding or selected set is empty.
|
|
30
|
+
*/
|
|
31
|
+
const maxSimilarityToSelected = (candidate, selected) => {
|
|
32
|
+
// No embedding means we can't compute similarity
|
|
33
|
+
if (!candidate.embedding) {
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
// No selected items yet
|
|
37
|
+
if (selected.length === 0) {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
let maxSim = -Infinity;
|
|
41
|
+
for (const item of selected) {
|
|
42
|
+
// Skip items without embeddings
|
|
43
|
+
if (!item.embedding) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const sim = cosineSimilarity(candidate.embedding, item.embedding);
|
|
47
|
+
if (sim > maxSim) {
|
|
48
|
+
maxSim = sim;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// If no valid comparisons were made, return 0
|
|
52
|
+
return maxSim === -Infinity ? 0 : maxSim;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Calculate MMR score for a candidate.
|
|
56
|
+
*
|
|
57
|
+
* Formula: λ * relevance(item) - (1-λ) * max_similarity(item, selected_items)
|
|
58
|
+
*
|
|
59
|
+
* Higher lambda means more weight on relevance.
|
|
60
|
+
* Lower lambda means more weight on diversity (dissimilarity).
|
|
61
|
+
*/
|
|
62
|
+
const mmrScore = (candidate, selected, lambda) => {
|
|
63
|
+
const relevance = candidate.relevanceScore;
|
|
64
|
+
const maxSim = maxSimilarityToSelected(candidate, selected);
|
|
65
|
+
return lambda * relevance - (1 - lambda) * maxSim;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Check if adding a candidate would violate category limits in top N.
|
|
69
|
+
*
|
|
70
|
+
* Per spec: max 2 results from same category in top 5.
|
|
71
|
+
* This prevents over-representation of any single category.
|
|
72
|
+
*/
|
|
73
|
+
const wouldViolateCategoryLimit = (candidate, selected, topN = CATEGORY_LIMIT_TOP_N, maxPerTopN = CATEGORY_MAX_PER_TOP_N) => {
|
|
74
|
+
// No category = no limit
|
|
75
|
+
if (!candidate.category) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
// Only check if we're still in the top N range
|
|
79
|
+
if (selected.length >= topN) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
// Count items with the same category in current selection
|
|
83
|
+
const categoryCount = selected.filter(item => item.category === candidate.category).length;
|
|
84
|
+
return categoryCount >= maxPerTopN;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Noop implementation - returns candidates unchanged (just truncated to limit).
|
|
88
|
+
* Used when diversification is not needed or for testing.
|
|
89
|
+
*/
|
|
90
|
+
export const DiversifierServiceNoop = Layer.succeed(DiversifierService, {
|
|
91
|
+
mmrDiversify: (candidates, limit, _lambda) => Effect.succeed(candidates.slice(0, limit))
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Live implementation with full MMR algorithm and category limits.
|
|
95
|
+
*
|
|
96
|
+
* Algorithm:
|
|
97
|
+
* 1. If no embeddings available, fallback to relevance-only ordering with category limits
|
|
98
|
+
* 2. Start with the highest-relevance item
|
|
99
|
+
* 3. Iteratively select the item with highest MMR score that doesn't violate category limits
|
|
100
|
+
* 4. Repeat until limit reached or no candidates remain
|
|
101
|
+
*/
|
|
102
|
+
export const DiversifierServiceLive = Layer.succeed(DiversifierService, {
|
|
103
|
+
mmrDiversify: (candidates, limit, lambda = DEFAULT_LAMBDA) => Effect.sync(() => {
|
|
104
|
+
// Edge case: empty candidates
|
|
105
|
+
if (candidates.length === 0) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
// Edge case: limit <= 0
|
|
109
|
+
if (limit <= 0) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
// Edge case: only one candidate or limit is 1
|
|
113
|
+
if (candidates.length === 1 || limit === 1) {
|
|
114
|
+
return candidates.slice(0, 1);
|
|
115
|
+
}
|
|
116
|
+
// Check if any candidates have embeddings
|
|
117
|
+
const hasEmbeddings = candidates.some(c => c.embedding !== null);
|
|
118
|
+
// Fallback: if no embeddings, just apply category limits to relevance-sorted list
|
|
119
|
+
if (!hasEmbeddings) {
|
|
120
|
+
return applyFallbackWithCategoryLimits(candidates, limit);
|
|
121
|
+
}
|
|
122
|
+
// Full MMR algorithm
|
|
123
|
+
const selected = [];
|
|
124
|
+
const remaining = new Set(candidates);
|
|
125
|
+
while (selected.length < limit && remaining.size > 0) {
|
|
126
|
+
let bestCandidate = null;
|
|
127
|
+
let bestScore = -Infinity;
|
|
128
|
+
for (const candidate of remaining) {
|
|
129
|
+
// Skip if would violate category limit
|
|
130
|
+
if (wouldViolateCategoryLimit(candidate, selected)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const score = mmrScore(candidate, selected, lambda);
|
|
134
|
+
if (score > bestScore) {
|
|
135
|
+
bestScore = score;
|
|
136
|
+
bestCandidate = candidate;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// If no valid candidate found (all remaining violate category limits),
|
|
140
|
+
// try to find any candidate without category limit check
|
|
141
|
+
if (!bestCandidate) {
|
|
142
|
+
for (const candidate of remaining) {
|
|
143
|
+
const score = mmrScore(candidate, selected, lambda);
|
|
144
|
+
if (score > bestScore) {
|
|
145
|
+
bestScore = score;
|
|
146
|
+
bestCandidate = candidate;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Still no candidate? We're done
|
|
151
|
+
if (!bestCandidate) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
selected.push(bestCandidate);
|
|
155
|
+
remaining.delete(bestCandidate);
|
|
156
|
+
}
|
|
157
|
+
return selected;
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
/**
|
|
161
|
+
* Fallback diversification when no embeddings are available.
|
|
162
|
+
* Applies category limits to the relevance-sorted list.
|
|
163
|
+
*
|
|
164
|
+
* Returns candidates in original order, skipping items that would
|
|
165
|
+
* violate the category limit in top N.
|
|
166
|
+
*/
|
|
167
|
+
const applyFallbackWithCategoryLimits = (candidates, limit) => {
|
|
168
|
+
const selected = [];
|
|
169
|
+
for (const candidate of candidates) {
|
|
170
|
+
if (selected.length >= limit) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
// Skip if would violate category limit
|
|
174
|
+
if (wouldViolateCategoryLimit(candidate, selected)) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
selected.push(candidate);
|
|
178
|
+
}
|
|
179
|
+
// If we didn't get enough due to category limits, fill with remaining
|
|
180
|
+
if (selected.length < limit) {
|
|
181
|
+
const selectedSet = new Set(selected);
|
|
182
|
+
for (const candidate of candidates) {
|
|
183
|
+
if (selected.length >= limit) {
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
if (!selectedSet.has(candidate)) {
|
|
187
|
+
selected.push(candidate);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return selected;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Auto layer - uses Live implementation since MMR has no external dependencies.
|
|
195
|
+
*/
|
|
196
|
+
export const DiversifierServiceAuto = DiversifierServiceLive;
|
|
197
|
+
//# sourceMappingURL=diversifier-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diversifier-service.js","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { EdgeRepository } from "../repo/edge-repo.js";
|
|
3
|
+
import { DatabaseError, EdgeNotFoundError, ValidationError } from "../errors.js";
|
|
4
|
+
import type { Edge, EdgeType, NodeType, CreateEdgeInput, UpdateEdgeInput, NeighborNode } from "@jamesaphoenix/tx-types";
|
|
5
|
+
/** Extended neighbor with depth information */
|
|
6
|
+
export interface NeighborWithDepth extends NeighborNode {
|
|
7
|
+
readonly depth: number;
|
|
8
|
+
}
|
|
9
|
+
/** Options for multi-hop neighbor finding */
|
|
10
|
+
export interface FindNeighborsOptions {
|
|
11
|
+
/** Maximum depth to traverse (default: 1) */
|
|
12
|
+
readonly depth?: number;
|
|
13
|
+
/** Direction of traversal */
|
|
14
|
+
readonly direction?: "outgoing" | "incoming" | "both";
|
|
15
|
+
/** Filter by edge types */
|
|
16
|
+
readonly edgeTypes?: readonly EdgeType[];
|
|
17
|
+
/** Include the path of edges that led to this neighbor */
|
|
18
|
+
readonly includePath?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Neighbor with path information */
|
|
21
|
+
export interface NeighborWithPath extends NeighborWithDepth {
|
|
22
|
+
readonly path: readonly Edge[];
|
|
23
|
+
}
|
|
24
|
+
declare const EdgeService_base: Context.TagClass<EdgeService, "EdgeService", {
|
|
25
|
+
/**
|
|
26
|
+
* Create an edge between two nodes.
|
|
27
|
+
* Validates edge type, node types, and ensures weight is in [0, 1].
|
|
28
|
+
*/
|
|
29
|
+
readonly createEdge: (input: CreateEdgeInput) => Effect.Effect<Edge, ValidationError | DatabaseError>;
|
|
30
|
+
/**
|
|
31
|
+
* Find neighbors of a node with optional multi-hop traversal.
|
|
32
|
+
* Supports depth, direction, and edge type filtering.
|
|
33
|
+
*/
|
|
34
|
+
readonly findNeighbors: (nodeType: NodeType, nodeId: string, options?: FindNeighborsOptions) => Effect.Effect<readonly NeighborWithDepth[], DatabaseError>;
|
|
35
|
+
/**
|
|
36
|
+
* Find a path between two nodes.
|
|
37
|
+
* Returns the sequence of edges, or null if no path exists.
|
|
38
|
+
*/
|
|
39
|
+
readonly findPath: (fromType: NodeType, fromId: string, toType: NodeType, toId: string, maxDepth?: number) => Effect.Effect<readonly Edge[] | null, DatabaseError>;
|
|
40
|
+
/**
|
|
41
|
+
* Invalidate (soft delete) an edge.
|
|
42
|
+
*/
|
|
43
|
+
readonly invalidateEdge: (id: number) => Effect.Effect<boolean, EdgeNotFoundError | DatabaseError>;
|
|
44
|
+
/**
|
|
45
|
+
* Get an edge by ID.
|
|
46
|
+
*/
|
|
47
|
+
readonly get: (id: number) => Effect.Effect<Edge, EdgeNotFoundError | DatabaseError>;
|
|
48
|
+
/**
|
|
49
|
+
* Update an edge's weight or metadata.
|
|
50
|
+
*/
|
|
51
|
+
readonly update: (id: number, input: UpdateEdgeInput) => Effect.Effect<Edge, EdgeNotFoundError | ValidationError | DatabaseError>;
|
|
52
|
+
/**
|
|
53
|
+
* Find all edges of a specific type.
|
|
54
|
+
*/
|
|
55
|
+
readonly findByType: (edgeType: EdgeType) => Effect.Effect<readonly Edge[], ValidationError | DatabaseError>;
|
|
56
|
+
/**
|
|
57
|
+
* Find all edges from a source node.
|
|
58
|
+
*/
|
|
59
|
+
readonly findFromSource: (sourceType: NodeType, sourceId: string) => Effect.Effect<readonly Edge[], DatabaseError>;
|
|
60
|
+
/**
|
|
61
|
+
* Find all edges from multiple source nodes in a single batch query.
|
|
62
|
+
* Eliminates N+1 queries when fetching edges for multiple nodes.
|
|
63
|
+
*/
|
|
64
|
+
readonly findFromMultipleSources: (sourceType: NodeType, sourceIds: readonly string[]) => Effect.Effect<ReadonlyMap<string, readonly Edge[]>, DatabaseError>;
|
|
65
|
+
/**
|
|
66
|
+
* Find all edges to a target node.
|
|
67
|
+
*/
|
|
68
|
+
readonly findToTarget: (targetType: NodeType, targetId: string) => Effect.Effect<readonly Edge[], DatabaseError>;
|
|
69
|
+
/**
|
|
70
|
+
* Count edges by type.
|
|
71
|
+
*/
|
|
72
|
+
readonly countByType: () => Effect.Effect<Map<EdgeType, number>, DatabaseError>;
|
|
73
|
+
}>;
|
|
74
|
+
export declare class EdgeService extends EdgeService_base {
|
|
75
|
+
}
|
|
76
|
+
export declare const EdgeServiceLive: Layer.Layer<EdgeService, never, EdgeRepository>;
|
|
77
|
+
export {};
|
|
78
|
+
//# 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,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,KAAK,EACV,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,eAAe,EACf,YAAY,EACb,MAAM,yBAAyB,CAAA;AAiBhC,+CAA+C;AAC/C,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,6BAA6B;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;IACrD,2BAA2B;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;IACxC,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,QAAQ,CAAC,IAAI,EAAE,SAAS,IAAI,EAAE,CAAA;CAC/B;;IAKG;;;OAGG;yBACkB,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,CAAC;IAErG;;;OAGG;4BACqB,CACtB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,oBAAoB,KAC3B,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,EAAE,aAAa,CAAC;IAE/D;;;OAGG;uBACgB,CACjB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,GAAG,IAAI,EAAE,aAAa,CAAC;IAEzD;;OAEG;6BACsB,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAElG;;OAEG;kBACW,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAEpF;;OAEG;qBACc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,GAAG,aAAa,CAAC;IAEjI;;OAEG;yBACkB,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,eAAe,GAAG,aAAa,CAAC;IAE5G;;OAEG;6BACsB,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC;IAElH;;;OAGG;sCAC+B,CAChC,UAAU,EAAE,QAAQ,EACpB,SAAS,EAAE,SAAS,MAAM,EAAE,KACzB,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC;IAEvE;;OAEG;2BACoB,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC;IAEhH;;OAEG;0BACmB,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC;;AAzEnF,qBAAa,WAAY,SAAQ,gBA2E9B;CAAG;AAuDN,eAAO,MAAM,eAAe,iDAiI3B,CAAA"}
|