@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,174 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Config, Option } from "effect";
|
|
2
|
+
import { Data } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* Error indicating query expansion is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
export class QueryExpansionUnavailableError extends Data.TaggedError("QueryExpansionUnavailableError") {
|
|
7
|
+
get message() {
|
|
8
|
+
return `Query expansion unavailable: ${this.reason}`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* QueryExpansionService uses an LLM to generate alternative phrasings of search queries.
|
|
13
|
+
* This improves recall by searching for semantically equivalent but differently worded queries.
|
|
14
|
+
*
|
|
15
|
+
* Design: Following DD-006 patterns for LLM integration.
|
|
16
|
+
* The service gracefully degrades when ANTHROPIC_API_KEY is not set.
|
|
17
|
+
*/
|
|
18
|
+
export class QueryExpansionService extends Context.Tag("QueryExpansionService")() {
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The prompt template for query expansion.
|
|
22
|
+
* Designed to generate concise, search-optimized alternative queries.
|
|
23
|
+
*/
|
|
24
|
+
const EXPANSION_PROMPT = `You are a search query expansion assistant. Given a search query, generate 2-3 alternative phrasings that capture the same intent but use different words or perspectives.
|
|
25
|
+
|
|
26
|
+
Rules:
|
|
27
|
+
1. Keep alternatives concise (similar length to original)
|
|
28
|
+
2. Use synonyms and related terminology
|
|
29
|
+
3. Consider different ways to express the same concept
|
|
30
|
+
4. Do NOT add information not implied by the original query
|
|
31
|
+
5. Output ONLY a JSON array of strings, nothing else
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
Input: "fix authentication bug"
|
|
35
|
+
Output: ["resolve auth issue", "debug login problem", "authentication error fix"]
|
|
36
|
+
|
|
37
|
+
Input: "add user profile page"
|
|
38
|
+
Output: ["create profile view", "implement user account page", "build profile screen"]
|
|
39
|
+
|
|
40
|
+
Now expand this query:
|
|
41
|
+
`;
|
|
42
|
+
/**
|
|
43
|
+
* Parse LLM JSON response, handling common formatting issues.
|
|
44
|
+
* Robust parser from DD-006.
|
|
45
|
+
*/
|
|
46
|
+
const parseLlmJson = (raw) => {
|
|
47
|
+
// Step 1: Try direct parse
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(raw);
|
|
50
|
+
}
|
|
51
|
+
catch { /* continue */ }
|
|
52
|
+
// Step 2: Strip markdown code fences
|
|
53
|
+
const fenceMatch = raw.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
|
|
54
|
+
if (fenceMatch && fenceMatch[1]) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(fenceMatch[1].trim());
|
|
57
|
+
}
|
|
58
|
+
catch { /* continue */ }
|
|
59
|
+
}
|
|
60
|
+
// Step 3: Find first [ or { and parse from there
|
|
61
|
+
const jsonStart = raw.search(/[[{]/);
|
|
62
|
+
if (jsonStart >= 0) {
|
|
63
|
+
const candidate = raw.slice(jsonStart);
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(candidate);
|
|
66
|
+
}
|
|
67
|
+
catch { /* continue */ }
|
|
68
|
+
// Step 4: Find matching bracket and extract
|
|
69
|
+
const openChar = candidate[0];
|
|
70
|
+
const closeChar = openChar === "[" ? "]" : "}";
|
|
71
|
+
const lastClose = candidate.lastIndexOf(closeChar);
|
|
72
|
+
if (lastClose > 0) {
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(candidate.slice(0, lastClose + 1));
|
|
75
|
+
}
|
|
76
|
+
catch { /* continue */ }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Noop implementation - returns original query only.
|
|
83
|
+
* Used when ANTHROPIC_API_KEY is not set or LLM features are disabled.
|
|
84
|
+
*/
|
|
85
|
+
export const QueryExpansionServiceNoop = Layer.succeed(QueryExpansionService, {
|
|
86
|
+
expand: (query) => Effect.succeed({
|
|
87
|
+
original: query,
|
|
88
|
+
expanded: [query],
|
|
89
|
+
wasExpanded: false
|
|
90
|
+
}),
|
|
91
|
+
isAvailable: () => Effect.succeed(false)
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Live implementation using Anthropic Claude API.
|
|
95
|
+
* Lazy-loads the SDK and caches the client.
|
|
96
|
+
*/
|
|
97
|
+
export const QueryExpansionServiceLive = Layer.effect(QueryExpansionService, Effect.gen(function* () {
|
|
98
|
+
// Read API key from environment
|
|
99
|
+
const apiKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.mapError(() => new QueryExpansionUnavailableError({
|
|
100
|
+
reason: "ANTHROPIC_API_KEY environment variable is not set"
|
|
101
|
+
})));
|
|
102
|
+
// Lazy-load client
|
|
103
|
+
let client = null;
|
|
104
|
+
const ensureClient = Effect.gen(function* () {
|
|
105
|
+
if (client)
|
|
106
|
+
return client;
|
|
107
|
+
// Dynamic import of Anthropic SDK (optional peer dependency)
|
|
108
|
+
const Anthropic = yield* Effect.tryPromise({
|
|
109
|
+
try: async () => {
|
|
110
|
+
// @ts-expect-error - @anthropic-ai/sdk is an optional peer dependency
|
|
111
|
+
const mod = await import("@anthropic-ai/sdk");
|
|
112
|
+
return mod.default;
|
|
113
|
+
},
|
|
114
|
+
catch: () => new QueryExpansionUnavailableError({
|
|
115
|
+
reason: "@anthropic-ai/sdk is not installed"
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
client = new Anthropic({ apiKey });
|
|
119
|
+
return client;
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
expand: (query) => Effect.gen(function* () {
|
|
123
|
+
const anthropic = yield* ensureClient;
|
|
124
|
+
const response = yield* Effect.tryPromise({
|
|
125
|
+
try: () => anthropic.messages.create({
|
|
126
|
+
model: "claude-haiku-4-20250514",
|
|
127
|
+
max_tokens: 256,
|
|
128
|
+
messages: [{
|
|
129
|
+
role: "user",
|
|
130
|
+
content: EXPANSION_PROMPT + JSON.stringify(query)
|
|
131
|
+
}]
|
|
132
|
+
}),
|
|
133
|
+
catch: (e) => new QueryExpansionUnavailableError({
|
|
134
|
+
reason: `API call failed: ${String(e)}`
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
// Extract text from response
|
|
138
|
+
const textContent = response.content.find(c => c.type === "text");
|
|
139
|
+
if (!textContent || !textContent.text) {
|
|
140
|
+
return { original: query, expanded: [query], wasExpanded: false };
|
|
141
|
+
}
|
|
142
|
+
// Parse the JSON array of expanded queries
|
|
143
|
+
const alternatives = parseLlmJson(textContent.text);
|
|
144
|
+
if (!alternatives || !Array.isArray(alternatives)) {
|
|
145
|
+
return { original: query, expanded: [query], wasExpanded: false };
|
|
146
|
+
}
|
|
147
|
+
// Filter out empty strings and duplicates
|
|
148
|
+
const uniqueAlternatives = [...new Set(alternatives
|
|
149
|
+
.filter((alt) => typeof alt === "string" && alt.trim().length > 0)
|
|
150
|
+
.map(alt => alt.trim()))];
|
|
151
|
+
// Always include original query first
|
|
152
|
+
const expanded = [query, ...uniqueAlternatives.filter(alt => alt.toLowerCase() !== query.toLowerCase())];
|
|
153
|
+
return {
|
|
154
|
+
original: query,
|
|
155
|
+
expanded,
|
|
156
|
+
wasExpanded: true
|
|
157
|
+
};
|
|
158
|
+
}),
|
|
159
|
+
isAvailable: () => Effect.succeed(true)
|
|
160
|
+
};
|
|
161
|
+
}));
|
|
162
|
+
/**
|
|
163
|
+
* Auto-detecting layer that uses Live if ANTHROPIC_API_KEY is set, Noop otherwise.
|
|
164
|
+
* This allows graceful degradation when the API key is not configured.
|
|
165
|
+
*/
|
|
166
|
+
export const QueryExpansionServiceAuto = Layer.unwrapEffect(Effect.gen(function* () {
|
|
167
|
+
// Check if API key is available
|
|
168
|
+
const apiKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.option);
|
|
169
|
+
if (Option.isSome(apiKey) && apiKey.value.trim().length > 0) {
|
|
170
|
+
return QueryExpansionServiceLive;
|
|
171
|
+
}
|
|
172
|
+
return QueryExpansionServiceNoop;
|
|
173
|
+
}));
|
|
174
|
+
//# sourceMappingURL=query-expansion-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-expansion-service.js","sourceRoot":"","sources":["../../src/services/query-expansion-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { TaskRepository } from "../repo/task-repo.js";
|
|
3
|
+
import { DependencyRepository } from "../repo/dep-repo.js";
|
|
4
|
+
import { DatabaseError } from "../errors.js";
|
|
5
|
+
import type { Task, TaskId, TaskWithDeps } from "@jamesaphoenix/tx-types";
|
|
6
|
+
declare const ReadyService_base: Context.TagClass<ReadyService, "ReadyService", {
|
|
7
|
+
readonly getReady: (limit?: number) => Effect.Effect<readonly TaskWithDeps[], DatabaseError>;
|
|
8
|
+
readonly isReady: (id: TaskId) => Effect.Effect<boolean, DatabaseError>;
|
|
9
|
+
readonly getBlockers: (id: TaskId) => Effect.Effect<readonly Task[], DatabaseError>;
|
|
10
|
+
readonly getBlocking: (id: TaskId) => Effect.Effect<readonly Task[], DatabaseError>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare class ReadyService extends ReadyService_base {
|
|
13
|
+
}
|
|
14
|
+
export declare const ReadyServiceLive: Layer.Layer<ReadyService, never, TaskRepository | DependencyRepository>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=ready-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready-service.d.ts","sourceRoot":"","sources":["../../src/services/ready-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,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;;uBAKlD,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,YAAY,EAAE,EAAE,aAAa,CAAC;sBAC1E,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;0BACjD,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC;0BAC7D,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC;;AANvF,qBAAa,YAAa,SAAQ,iBAQ/B;CAAG;AAEN,eAAO,MAAM,gBAAgB,yEA2E5B,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { TaskRepository } from "../repo/task-repo.js";
|
|
3
|
+
import { DependencyRepository } from "../repo/dep-repo.js";
|
|
4
|
+
export class ReadyService extends Context.Tag("ReadyService")() {
|
|
5
|
+
}
|
|
6
|
+
export const ReadyServiceLive = Layer.effect(ReadyService, Effect.gen(function* () {
|
|
7
|
+
const taskRepo = yield* TaskRepository;
|
|
8
|
+
const depRepo = yield* DependencyRepository;
|
|
9
|
+
return {
|
|
10
|
+
getReady: (limit = 100) => Effect.gen(function* () {
|
|
11
|
+
const candidates = yield* taskRepo.findAll({
|
|
12
|
+
status: ["backlog", "ready", "planning"]
|
|
13
|
+
});
|
|
14
|
+
const ready = [];
|
|
15
|
+
for (const task of candidates) {
|
|
16
|
+
const blockerIds = yield* depRepo.getBlockerIds(task.id);
|
|
17
|
+
const blockingIds = yield* depRepo.getBlockingIds(task.id);
|
|
18
|
+
const childIds = yield* taskRepo.getChildIds(task.id);
|
|
19
|
+
if (blockerIds.length === 0) {
|
|
20
|
+
ready.push({
|
|
21
|
+
...task,
|
|
22
|
+
blockedBy: [],
|
|
23
|
+
blocks: blockingIds,
|
|
24
|
+
children: childIds,
|
|
25
|
+
isReady: true
|
|
26
|
+
});
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const blockers = yield* taskRepo.findByIds(blockerIds);
|
|
30
|
+
const allDone = blockers.every(b => b.status === "done");
|
|
31
|
+
if (allDone) {
|
|
32
|
+
ready.push({
|
|
33
|
+
...task,
|
|
34
|
+
blockedBy: blockerIds,
|
|
35
|
+
blocks: blockingIds,
|
|
36
|
+
children: childIds,
|
|
37
|
+
isReady: true
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
ready.sort((a, b) => b.score - a.score);
|
|
42
|
+
return ready.slice(0, limit);
|
|
43
|
+
}),
|
|
44
|
+
isReady: (id) => Effect.gen(function* () {
|
|
45
|
+
const task = yield* taskRepo.findById(id);
|
|
46
|
+
if (!task)
|
|
47
|
+
return false;
|
|
48
|
+
if (!["backlog", "ready", "planning"].includes(task.status))
|
|
49
|
+
return false;
|
|
50
|
+
const blockerIds = yield* depRepo.getBlockerIds(id);
|
|
51
|
+
if (blockerIds.length === 0)
|
|
52
|
+
return true;
|
|
53
|
+
const blockers = yield* taskRepo.findByIds(blockerIds);
|
|
54
|
+
return blockers.every(b => b.status === "done");
|
|
55
|
+
}),
|
|
56
|
+
getBlockers: (id) => Effect.gen(function* () {
|
|
57
|
+
const blockerIds = yield* depRepo.getBlockerIds(id);
|
|
58
|
+
if (blockerIds.length === 0)
|
|
59
|
+
return [];
|
|
60
|
+
return yield* taskRepo.findByIds(blockerIds);
|
|
61
|
+
}),
|
|
62
|
+
getBlocking: (id) => Effect.gen(function* () {
|
|
63
|
+
const blockingIds = yield* depRepo.getBlockingIds(id);
|
|
64
|
+
if (blockingIds.length === 0)
|
|
65
|
+
return [];
|
|
66
|
+
return yield* taskRepo.findByIds(blockingIds);
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
}));
|
|
70
|
+
//# sourceMappingURL=ready-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready-service.js","sourceRoot":"","sources":["../../src/services/ready-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { RerankerUnavailableError } from "../errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Result of re-ranking documents against a query.
|
|
5
|
+
*/
|
|
6
|
+
export interface RerankerResult {
|
|
7
|
+
/** Original document content */
|
|
8
|
+
readonly document: string;
|
|
9
|
+
/** Relevance score (0-1, higher is more relevant) */
|
|
10
|
+
readonly score: number;
|
|
11
|
+
/** Original index before re-ranking */
|
|
12
|
+
readonly originalIndex: number;
|
|
13
|
+
}
|
|
14
|
+
declare const RerankerService_base: Context.TagClass<RerankerService, "RerankerService", {
|
|
15
|
+
/**
|
|
16
|
+
* Re-rank documents against a query.
|
|
17
|
+
* Returns documents sorted by relevance score (highest first).
|
|
18
|
+
*/
|
|
19
|
+
readonly rerank: (query: string, documents: readonly string[]) => Effect.Effect<readonly RerankerResult[], RerankerUnavailableError>;
|
|
20
|
+
/** Check if re-ranking functionality is available */
|
|
21
|
+
readonly isAvailable: () => Effect.Effect<boolean>;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* RerankerService uses LLM-based re-ranking to improve search result quality.
|
|
25
|
+
*
|
|
26
|
+
* Re-ranking takes initial search results and uses a specialized model to
|
|
27
|
+
* re-score them based on query relevance. This typically improves precision
|
|
28
|
+
* at the cost of some latency.
|
|
29
|
+
*
|
|
30
|
+
* Design: Following DD-010 patterns for local model integration.
|
|
31
|
+
* The service gracefully degrades when node-llama-cpp is not available.
|
|
32
|
+
*/
|
|
33
|
+
export declare class RerankerService extends RerankerService_base {
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Noop fallback - returns documents unchanged with default scores.
|
|
37
|
+
* Used when node-llama-cpp is not available or re-ranking is disabled.
|
|
38
|
+
*/
|
|
39
|
+
export declare const RerankerServiceNoop: Layer.Layer<RerankerService, never, never>;
|
|
40
|
+
/**
|
|
41
|
+
* Live implementation with node-llama-cpp and Qwen3-Reranker model.
|
|
42
|
+
* Lazy-loads the model on first use and caches the context.
|
|
43
|
+
*/
|
|
44
|
+
export declare const RerankerServiceLive: Layer.Layer<RerankerService, never, never>;
|
|
45
|
+
/**
|
|
46
|
+
* Auto-detecting layer that uses Live if node-llama-cpp is available, Noop otherwise.
|
|
47
|
+
* This allows graceful degradation when the re-ranking library is not installed.
|
|
48
|
+
*/
|
|
49
|
+
export declare const RerankerServiceAuto: Layer.Layer<RerankerService, boolean, never>;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=reranker-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reranker-service.d.ts","sourceRoot":"","sources":["../../src/services/reranker-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAO,MAAM,QAAQ,CAAA;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAqBvD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B;;IAeG;;;OAGG;qBACc,CACf,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,MAAM,EAAE,KACzB,MAAM,CAAC,MAAM,CAAC,SAAS,cAAc,EAAE,EAAE,wBAAwB,CAAC;IACvE,qDAAqD;0BAC/B,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;AAtBtD;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,oBAclC;CAAG;AAEN;;;GAGG;AACH,eAAO,MAAM,mBAAmB,4CAa/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,4CAmG/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,8CAgB/B,CAAA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Ref } from "effect";
|
|
2
|
+
import { RerankerUnavailableError } from "../errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* RerankerService uses LLM-based re-ranking to improve search result quality.
|
|
5
|
+
*
|
|
6
|
+
* Re-ranking takes initial search results and uses a specialized model to
|
|
7
|
+
* re-score them based on query relevance. This typically improves precision
|
|
8
|
+
* at the cost of some latency.
|
|
9
|
+
*
|
|
10
|
+
* Design: Following DD-010 patterns for local model integration.
|
|
11
|
+
* The service gracefully degrades when node-llama-cpp is not available.
|
|
12
|
+
*/
|
|
13
|
+
export class RerankerService extends Context.Tag("RerankerService")() {
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Noop fallback - returns documents unchanged with default scores.
|
|
17
|
+
* Used when node-llama-cpp is not available or re-ranking is disabled.
|
|
18
|
+
*/
|
|
19
|
+
export const RerankerServiceNoop = Layer.succeed(RerankerService, {
|
|
20
|
+
rerank: (_query, documents) => Effect.succeed(documents.map((document, index) => ({
|
|
21
|
+
document,
|
|
22
|
+
score: 1 - index * 0.01, // Preserve original order with decreasing scores
|
|
23
|
+
originalIndex: index
|
|
24
|
+
}))),
|
|
25
|
+
isAvailable: () => Effect.succeed(false)
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Live implementation with node-llama-cpp and Qwen3-Reranker model.
|
|
29
|
+
* Lazy-loads the model on first use and caches the context.
|
|
30
|
+
*/
|
|
31
|
+
export const RerankerServiceLive = Layer.scoped(RerankerService, Effect.gen(function* () {
|
|
32
|
+
// State for lazy-loaded context
|
|
33
|
+
const stateRef = yield* Ref.make({
|
|
34
|
+
context: null,
|
|
35
|
+
lastActivity: Date.now()
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Ensure the ranking context is loaded.
|
|
39
|
+
* Lazy-loads node-llama-cpp and the model on first call.
|
|
40
|
+
*/
|
|
41
|
+
const ensureContext = Effect.gen(function* () {
|
|
42
|
+
const state = yield* Ref.get(stateRef);
|
|
43
|
+
if (state.context) {
|
|
44
|
+
yield* Ref.update(stateRef, s => ({ ...s, lastActivity: Date.now() }));
|
|
45
|
+
return state.context;
|
|
46
|
+
}
|
|
47
|
+
// Lazy load node-llama-cpp
|
|
48
|
+
const nodeLlamaCpp = yield* Effect.tryPromise({
|
|
49
|
+
try: async () => {
|
|
50
|
+
const mod = await import("node-llama-cpp");
|
|
51
|
+
return mod;
|
|
52
|
+
},
|
|
53
|
+
catch: () => new RerankerUnavailableError({ reason: "node-llama-cpp not installed" })
|
|
54
|
+
});
|
|
55
|
+
// Get llama instance
|
|
56
|
+
const llama = yield* Effect.tryPromise({
|
|
57
|
+
try: () => nodeLlamaCpp.getLlama(),
|
|
58
|
+
catch: (e) => new RerankerUnavailableError({ reason: `Failed to initialize llama: ${String(e)}` })
|
|
59
|
+
});
|
|
60
|
+
// Load Qwen3-Reranker model - uses HuggingFace model spec format
|
|
61
|
+
// Using the 0.6B model for a good balance of quality and speed
|
|
62
|
+
const model = yield* Effect.tryPromise({
|
|
63
|
+
try: () => llama.loadModel({
|
|
64
|
+
modelPath: "hf:Mungert/Qwen3-Reranker-0.6B-GGUF/Qwen3-Reranker-0.6B-Q8_0.gguf"
|
|
65
|
+
}),
|
|
66
|
+
catch: (e) => new RerankerUnavailableError({ reason: `Failed to load model: ${String(e)}` })
|
|
67
|
+
});
|
|
68
|
+
// Create ranking context
|
|
69
|
+
const context = yield* Effect.tryPromise({
|
|
70
|
+
try: () => model.createRankingContext(),
|
|
71
|
+
catch: (e) => new RerankerUnavailableError({ reason: `Failed to create ranking context: ${String(e)}` })
|
|
72
|
+
});
|
|
73
|
+
yield* Ref.set(stateRef, { context, lastActivity: Date.now() });
|
|
74
|
+
return context;
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
rerank: (query, documents) => Effect.gen(function* () {
|
|
78
|
+
if (documents.length === 0) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
// For very small result sets, re-ranking may not be worth the cost
|
|
82
|
+
if (documents.length <= 2) {
|
|
83
|
+
return documents.map((document, index) => ({
|
|
84
|
+
document,
|
|
85
|
+
score: 1 - index * 0.1,
|
|
86
|
+
originalIndex: index
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
const ctx = yield* ensureContext;
|
|
90
|
+
// Create index map to track original positions
|
|
91
|
+
const docArray = [...documents];
|
|
92
|
+
const indexMap = new Map();
|
|
93
|
+
docArray.forEach((doc, idx) => {
|
|
94
|
+
indexMap.set(doc, idx);
|
|
95
|
+
});
|
|
96
|
+
const ranked = yield* Effect.tryPromise({
|
|
97
|
+
try: () => ctx.rankAndSort(query, docArray),
|
|
98
|
+
catch: (e) => new RerankerUnavailableError({ reason: `Re-ranking failed: ${String(e)}` })
|
|
99
|
+
});
|
|
100
|
+
yield* Ref.update(stateRef, s => ({ ...s, lastActivity: Date.now() }));
|
|
101
|
+
return ranked.map(result => ({
|
|
102
|
+
document: result.document,
|
|
103
|
+
score: result.score,
|
|
104
|
+
originalIndex: indexMap.get(result.document) ?? -1
|
|
105
|
+
}));
|
|
106
|
+
}),
|
|
107
|
+
isAvailable: () => Effect.succeed(true)
|
|
108
|
+
};
|
|
109
|
+
}));
|
|
110
|
+
/**
|
|
111
|
+
* Auto-detecting layer that uses Live if node-llama-cpp is available, Noop otherwise.
|
|
112
|
+
* This allows graceful degradation when the re-ranking library is not installed.
|
|
113
|
+
*/
|
|
114
|
+
export const RerankerServiceAuto = Layer.unwrapEffect(Effect.gen(function* () {
|
|
115
|
+
// Try to import node-llama-cpp to check availability
|
|
116
|
+
const available = yield* Effect.tryPromise({
|
|
117
|
+
try: async () => {
|
|
118
|
+
await import("node-llama-cpp");
|
|
119
|
+
return true;
|
|
120
|
+
},
|
|
121
|
+
catch: () => false
|
|
122
|
+
});
|
|
123
|
+
if (available) {
|
|
124
|
+
return RerankerServiceLive;
|
|
125
|
+
}
|
|
126
|
+
return RerankerServiceNoop;
|
|
127
|
+
}));
|
|
128
|
+
//# sourceMappingURL=reranker-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reranker-service.js","sourceRoot":"","sources":["../../src/services/reranker-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { LearningRepository } from "../repo/learning-repo.js";
|
|
3
|
+
import { EmbeddingService } from "./embedding-service.js";
|
|
4
|
+
import { QueryExpansionService } from "./query-expansion-service.js";
|
|
5
|
+
import { RerankerService } from "./reranker-service.js";
|
|
6
|
+
import { RetrievalError, DatabaseError } from "../errors.js";
|
|
7
|
+
import type { LearningWithScore, RetrievalOptions } from "@jamesaphoenix/tx-types";
|
|
8
|
+
declare const RetrieverService_base: Context.TagClass<RetrieverService, "RetrieverService", {
|
|
9
|
+
/**
|
|
10
|
+
* Search for learnings matching a query.
|
|
11
|
+
* Returns scored results sorted by relevance (highest first).
|
|
12
|
+
*/
|
|
13
|
+
readonly search: (query: string, options?: RetrievalOptions) => Effect.Effect<readonly LearningWithScore[], RetrievalError | DatabaseError>;
|
|
14
|
+
/** Check if retrieval functionality is available */
|
|
15
|
+
readonly isAvailable: () => Effect.Effect<boolean>;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* RetrieverService provides pluggable retrieval for learnings.
|
|
19
|
+
*
|
|
20
|
+
* Design: PRD-015 specifies retrieval should be pluggable with good defaults.
|
|
21
|
+
* Users can swap out the default BM25+vector+RRF pipeline for their own
|
|
22
|
+
* implementation (Pinecone, Weaviate, Chroma, etc.).
|
|
23
|
+
*/
|
|
24
|
+
export declare class RetrieverService extends RetrieverService_base {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Noop fallback - returns empty results.
|
|
28
|
+
* Used when retrieval is disabled or for testing without full pipeline.
|
|
29
|
+
*/
|
|
30
|
+
export declare const RetrieverServiceNoop: Layer.Layer<RetrieverService, never, never>;
|
|
31
|
+
/**
|
|
32
|
+
* Live implementation with BM25 + vector + RRF pipeline.
|
|
33
|
+
* Uses the default hybrid search with:
|
|
34
|
+
* - Query expansion via LLM
|
|
35
|
+
* - BM25 full-text search
|
|
36
|
+
* - Vector similarity (when embeddings available)
|
|
37
|
+
* - RRF fusion
|
|
38
|
+
* - Optional LLM re-ranking
|
|
39
|
+
* - Recency/outcome/frequency boosts
|
|
40
|
+
*/
|
|
41
|
+
export declare const RetrieverServiceLive: Layer.Layer<RetrieverService, DatabaseError, LearningRepository | EmbeddingService | QueryExpansionService | RerankerService>;
|
|
42
|
+
/**
|
|
43
|
+
* Auto-detecting layer that always uses Live since BM25 is always available.
|
|
44
|
+
* The Live implementation gracefully degrades vector search when embeddings
|
|
45
|
+
* are unavailable, so Auto just delegates to Live.
|
|
46
|
+
*/
|
|
47
|
+
export declare const RetrieverServiceAuto: Layer.Layer<RetrieverService, DatabaseError, LearningRepository | EmbeddingService | QueryExpansionService | RerankerService>;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=retriever-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retriever-service.d.ts","sourceRoot":"","sources":["../../src/services/retriever-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAmB,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAY,iBAAiB,EAAc,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;;IA+BpG;;;OAGG;qBACc,CACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,KACvB,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,EAAE,cAAc,GAAG,aAAa,CAAC;IAChF,oDAAoD;0BAC9B,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;AAnBtD;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,qBAcnC;CAAG;AAwNN;;;GAGG;AACH,eAAO,MAAM,oBAAoB,6CAMhC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,+HAmQhC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,+HAAuB,CAAA"}
|