@iflow-mcp/apple-rag-mcp 4.6.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 (148) hide show
  1. package/.github/workflows/release.yml +62 -0
  2. package/.releaserc.json +38 -0
  3. package/CHANGELOG.md +161 -0
  4. package/README.md +114 -0
  5. package/README.zh-CN.md +119 -0
  6. package/apple-rag-mcp_process.log +8 -0
  7. package/biome.json +59 -0
  8. package/dist/src/auth/auth-middleware.d.ts +26 -0
  9. package/dist/src/auth/auth-middleware.d.ts.map +1 -0
  10. package/dist/src/auth/auth-middleware.js +77 -0
  11. package/dist/src/auth/auth-middleware.js.map +1 -0
  12. package/dist/src/auth/token-validator.d.ts +22 -0
  13. package/dist/src/auth/token-validator.d.ts.map +1 -0
  14. package/dist/src/auth/token-validator.js +64 -0
  15. package/dist/src/auth/token-validator.js.map +1 -0
  16. package/dist/src/mcp/formatters/response-formatter.d.ts +26 -0
  17. package/dist/src/mcp/formatters/response-formatter.d.ts.map +1 -0
  18. package/dist/src/mcp/formatters/response-formatter.js +119 -0
  19. package/dist/src/mcp/formatters/response-formatter.js.map +1 -0
  20. package/dist/src/mcp/manifest.d.ts +48 -0
  21. package/dist/src/mcp/manifest.d.ts.map +1 -0
  22. package/dist/src/mcp/manifest.js +46 -0
  23. package/dist/src/mcp/manifest.js.map +1 -0
  24. package/dist/src/mcp/middleware/request-validator.d.ts +48 -0
  25. package/dist/src/mcp/middleware/request-validator.d.ts.map +1 -0
  26. package/dist/src/mcp/middleware/request-validator.js +102 -0
  27. package/dist/src/mcp/middleware/request-validator.js.map +1 -0
  28. package/dist/src/mcp/protocol-handler.d.ts +70 -0
  29. package/dist/src/mcp/protocol-handler.d.ts.map +1 -0
  30. package/dist/src/mcp/protocol-handler.js +285 -0
  31. package/dist/src/mcp/protocol-handler.js.map +1 -0
  32. package/dist/src/mcp/tools/fetch-tool.d.ts +18 -0
  33. package/dist/src/mcp/tools/fetch-tool.d.ts.map +1 -0
  34. package/dist/src/mcp/tools/fetch-tool.js +76 -0
  35. package/dist/src/mcp/tools/fetch-tool.js.map +1 -0
  36. package/dist/src/mcp/tools/search-tool.d.ts +20 -0
  37. package/dist/src/mcp/tools/search-tool.d.ts.map +1 -0
  38. package/dist/src/mcp/tools/search-tool.js +86 -0
  39. package/dist/src/mcp/tools/search-tool.js.map +1 -0
  40. package/dist/src/services/database.d.ts +37 -0
  41. package/dist/src/services/database.d.ts.map +1 -0
  42. package/dist/src/services/database.js +166 -0
  43. package/dist/src/services/database.js.map +1 -0
  44. package/dist/src/services/deepinfra-base.d.ts +22 -0
  45. package/dist/src/services/deepinfra-base.d.ts.map +1 -0
  46. package/dist/src/services/deepinfra-base.js +55 -0
  47. package/dist/src/services/deepinfra-base.js.map +1 -0
  48. package/dist/src/services/embedding.d.ts +44 -0
  49. package/dist/src/services/embedding.d.ts.map +1 -0
  50. package/dist/src/services/embedding.js +61 -0
  51. package/dist/src/services/embedding.js.map +1 -0
  52. package/dist/src/services/index.d.ts +10 -0
  53. package/dist/src/services/index.d.ts.map +1 -0
  54. package/dist/src/services/index.js +52 -0
  55. package/dist/src/services/index.js.map +1 -0
  56. package/dist/src/services/ip-authentication.d.ts +12 -0
  57. package/dist/src/services/ip-authentication.d.ts.map +1 -0
  58. package/dist/src/services/ip-authentication.js +39 -0
  59. package/dist/src/services/ip-authentication.js.map +1 -0
  60. package/dist/src/services/rag.d.ts +35 -0
  61. package/dist/src/services/rag.d.ts.map +1 -0
  62. package/dist/src/services/rag.js +106 -0
  63. package/dist/src/services/rag.js.map +1 -0
  64. package/dist/src/services/rate-limit.d.ts +27 -0
  65. package/dist/src/services/rate-limit.d.ts.map +1 -0
  66. package/dist/src/services/rate-limit.js +91 -0
  67. package/dist/src/services/rate-limit.js.map +1 -0
  68. package/dist/src/services/reranker.d.ts +40 -0
  69. package/dist/src/services/reranker.d.ts.map +1 -0
  70. package/dist/src/services/reranker.js +97 -0
  71. package/dist/src/services/reranker.js.map +1 -0
  72. package/dist/src/services/search-engine.d.ts +89 -0
  73. package/dist/src/services/search-engine.d.ts.map +1 -0
  74. package/dist/src/services/search-engine.js +225 -0
  75. package/dist/src/services/search-engine.js.map +1 -0
  76. package/dist/src/services/tool-call-logger.d.ts +36 -0
  77. package/dist/src/services/tool-call-logger.d.ts.map +1 -0
  78. package/dist/src/services/tool-call-logger.js +34 -0
  79. package/dist/src/services/tool-call-logger.js.map +1 -0
  80. package/dist/src/types/env.d.ts +18 -0
  81. package/dist/src/types/env.d.ts.map +1 -0
  82. package/dist/src/types/env.js +2 -0
  83. package/dist/src/types/env.js.map +1 -0
  84. package/dist/src/types/index.d.ts +145 -0
  85. package/dist/src/types/index.d.ts.map +1 -0
  86. package/dist/src/types/index.js +6 -0
  87. package/dist/src/types/index.js.map +1 -0
  88. package/dist/src/utils/d1-utils.d.ts +6 -0
  89. package/dist/src/utils/d1-utils.d.ts.map +1 -0
  90. package/dist/src/utils/d1-utils.js +29 -0
  91. package/dist/src/utils/d1-utils.js.map +1 -0
  92. package/dist/src/utils/logger.d.ts +11 -0
  93. package/dist/src/utils/logger.d.ts.map +1 -0
  94. package/dist/src/utils/logger.js +26 -0
  95. package/dist/src/utils/logger.js.map +1 -0
  96. package/dist/src/utils/query-cleaner.d.ts +20 -0
  97. package/dist/src/utils/query-cleaner.d.ts.map +1 -0
  98. package/dist/src/utils/query-cleaner.js +117 -0
  99. package/dist/src/utils/query-cleaner.js.map +1 -0
  100. package/dist/src/utils/request-info.d.ts +18 -0
  101. package/dist/src/utils/request-info.d.ts.map +1 -0
  102. package/dist/src/utils/request-info.js +32 -0
  103. package/dist/src/utils/request-info.js.map +1 -0
  104. package/dist/src/utils/telegram-notifier.d.ts +4 -0
  105. package/dist/src/utils/telegram-notifier.d.ts.map +1 -0
  106. package/dist/src/utils/telegram-notifier.js +33 -0
  107. package/dist/src/utils/telegram-notifier.js.map +1 -0
  108. package/dist/src/utils/url-processor.d.ts +15 -0
  109. package/dist/src/utils/url-processor.d.ts.map +1 -0
  110. package/dist/src/utils/url-processor.js +54 -0
  111. package/dist/src/utils/url-processor.js.map +1 -0
  112. package/dist/src/worker.d.ts +15 -0
  113. package/dist/src/worker.d.ts.map +1 -0
  114. package/dist/src/worker.js +136 -0
  115. package/dist/src/worker.js.map +1 -0
  116. package/migrations/schema.sql +155 -0
  117. package/package.json +49 -0
  118. package/scripts/semantic-release-server-json.js +34 -0
  119. package/server.json +25 -0
  120. package/src/auth/auth-middleware.ts +104 -0
  121. package/src/auth/token-validator.ts +96 -0
  122. package/src/mcp/formatters/response-formatter.ts +157 -0
  123. package/src/mcp/manifest.ts +48 -0
  124. package/src/mcp/middleware/request-validator.ts +135 -0
  125. package/src/mcp/protocol-handler.ts +412 -0
  126. package/src/mcp/tools/fetch-tool.ts +146 -0
  127. package/src/mcp/tools/search-tool.ts +165 -0
  128. package/src/services/database.ts +202 -0
  129. package/src/services/deepinfra-base.ts +81 -0
  130. package/src/services/embedding.ts +96 -0
  131. package/src/services/index.ts +59 -0
  132. package/src/services/ip-authentication.ts +62 -0
  133. package/src/services/rag.ts +158 -0
  134. package/src/services/rate-limit.ts +141 -0
  135. package/src/services/reranker.ts +171 -0
  136. package/src/services/search-engine.ts +333 -0
  137. package/src/services/tool-call-logger.ts +98 -0
  138. package/src/types/env.ts +22 -0
  139. package/src/types/index.ts +189 -0
  140. package/src/utils/d1-utils.ts +45 -0
  141. package/src/utils/logger.ts +33 -0
  142. package/src/utils/query-cleaner.ts +151 -0
  143. package/src/utils/request-info.ts +47 -0
  144. package/src/utils/telegram-notifier.ts +47 -0
  145. package/src/utils/url-processor.ts +65 -0
  146. package/src/worker.ts +176 -0
  147. package/tsconfig.json +32 -0
  148. package/wrangler.toml.example +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag.js","sourceRoot":"","sources":["../../../src/services/rag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Rate Limiting Service with D1 timeout protection
3
+ */
4
+ import type { AuthContext } from "../types/index.js";
5
+ interface RateLimitResult {
6
+ allowed: boolean;
7
+ limit: number;
8
+ remaining: number;
9
+ resetAt: string;
10
+ planType: string;
11
+ limitType: "weekly" | "minute";
12
+ minuteLimit?: number;
13
+ minuteRemaining?: number;
14
+ minuteResetAt?: string;
15
+ }
16
+ export declare class RateLimitService {
17
+ private d1;
18
+ constructor(d1: D1Database);
19
+ checkLimits(clientIP: string, authContext: AuthContext): Promise<RateLimitResult>;
20
+ private getPlanType;
21
+ private getUsageCount;
22
+ private getWeekStartTime;
23
+ private getWeeklyResetTime;
24
+ private getMinuteResetTime;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/services/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAcD,qBAAa,gBAAgB;IACf,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU;IAE5B,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,eAAe,CAAC;YAoCb,WAAW;YAiBX,aAAa;IA2B3B,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;CAM3B"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Rate Limiting Service with D1 timeout protection
3
+ */
4
+ import { withD1Timeout } from "../utils/d1-utils.js";
5
+ import { logger } from "../utils/logger.js";
6
+ const PLAN_LIMITS = {
7
+ anonymous: { weeklyQueries: 30, requestsPerMinute: 3 },
8
+ hobby: { weeklyQueries: 50, requestsPerMinute: 5 },
9
+ pro: { weeklyQueries: 50000, requestsPerMinute: 50 },
10
+ enterprise: { weeklyQueries: -1, requestsPerMinute: -1 },
11
+ };
12
+ export class RateLimitService {
13
+ d1;
14
+ constructor(d1) {
15
+ this.d1 = d1;
16
+ }
17
+ async checkLimits(clientIP, authContext) {
18
+ const identifier = authContext.userId || `anon_${clientIP}`;
19
+ const planType = authContext.isAuthenticated && authContext.userId
20
+ ? await this.getPlanType(authContext.userId)
21
+ : "anonymous";
22
+ const limits = PLAN_LIMITS[planType] || PLAN_LIMITS.hobby;
23
+ const [weeklyUsage, minuteUsage] = await Promise.all([
24
+ this.getUsageCount(identifier, "weekly"),
25
+ this.getUsageCount(identifier, "minute"),
26
+ ]);
27
+ const weeklyAllowed = limits.weeklyQueries === -1 || weeklyUsage < limits.weeklyQueries;
28
+ const minuteAllowed = limits.requestsPerMinute === -1 || minuteUsage < limits.requestsPerMinute;
29
+ const allowed = weeklyAllowed && minuteAllowed;
30
+ if (!allowed) {
31
+ logger.info(`Rate limit: ${identifier} (${planType}) weekly=${weeklyUsage}/${limits.weeklyQueries} minute=${minuteUsage}/${limits.requestsPerMinute}`);
32
+ }
33
+ return {
34
+ allowed,
35
+ limit: limits.weeklyQueries,
36
+ remaining: limits.weeklyQueries === -1 ? -1 : Math.max(0, limits.weeklyQueries - weeklyUsage),
37
+ resetAt: this.getWeeklyResetTime(),
38
+ planType,
39
+ limitType: !minuteAllowed ? "minute" : "weekly",
40
+ minuteLimit: limits.requestsPerMinute,
41
+ minuteRemaining: limits.requestsPerMinute === -1 ? -1 : Math.max(0, limits.requestsPerMinute - minuteUsage),
42
+ minuteResetAt: this.getMinuteResetTime(),
43
+ };
44
+ }
45
+ async getPlanType(userId) {
46
+ return withD1Timeout(async () => {
47
+ const result = await this.d1
48
+ .prepare(`SELECT plan_type FROM user_subscriptions
49
+ WHERE user_id = ? AND status = 'active' LIMIT 1`)
50
+ .bind(userId)
51
+ .first();
52
+ return result?.plan_type || "hobby";
53
+ }, "hobby", "get_plan_type");
54
+ }
55
+ async getUsageCount(identifier, period) {
56
+ const since = period === "weekly"
57
+ ? this.getWeekStartTime().toISOString()
58
+ : new Date(Date.now() - 60_000).toISOString();
59
+ const operator = period === "weekly" ? ">=" : ">";
60
+ return withD1Timeout(async () => {
61
+ const result = await this.d1
62
+ .prepare(`SELECT
63
+ (SELECT COUNT(*) FROM search_logs WHERE user_id = ? AND created_at ${operator} ? AND status_code = 200) +
64
+ (SELECT COUNT(*) FROM fetch_logs WHERE user_id = ? AND created_at ${operator} ? AND status_code = 200) as total`)
65
+ .bind(identifier, since, identifier, since)
66
+ .first();
67
+ return result?.total || 0;
68
+ }, 0, `get_${period}_usage`);
69
+ }
70
+ getWeekStartTime() {
71
+ const now = new Date();
72
+ const start = new Date(now);
73
+ start.setDate(now.getDate() - now.getDay());
74
+ start.setHours(0, 0, 0, 0);
75
+ return start;
76
+ }
77
+ getWeeklyResetTime() {
78
+ const now = new Date();
79
+ const next = new Date(now);
80
+ next.setDate(now.getDate() + (7 - now.getDay()));
81
+ next.setHours(0, 0, 0, 0);
82
+ return next.toISOString();
83
+ }
84
+ getMinuteResetTime() {
85
+ const next = new Date();
86
+ next.setSeconds(0, 0);
87
+ next.setMinutes(next.getMinutes() + 1);
88
+ return next.toISOString();
89
+ }
90
+ }
91
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../../src/services/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * DeepInfra Reranker Service - MCP Optimized
3
+ * Dual-model fallback: 8B → 4B, 2 attempts each
4
+ */
5
+ import { DeepInfraService } from "./deepinfra-base.js";
6
+ interface RerankerInput {
7
+ query: string;
8
+ documents: string[];
9
+ topN: number;
10
+ }
11
+ interface RerankerPayload {
12
+ queries: [string];
13
+ documents: string[];
14
+ top_n: number;
15
+ }
16
+ export interface RerankerResponse {
17
+ scores: number[];
18
+ }
19
+ export interface RankedDocument {
20
+ content: string;
21
+ originalIndex: number;
22
+ relevanceScore: number;
23
+ }
24
+ export declare class RerankerService extends DeepInfraService<RerankerInput, RerankerResponse, RankedDocument[]> {
25
+ protected readonly endpoint: string;
26
+ private static readonly MODELS;
27
+ private static readonly MAX_ATTEMPTS;
28
+ rerank(query: string, documents: string[], topN: number): Promise<RankedDocument[]>;
29
+ /**
30
+ * Dual-model fallback: 8B (2 attempts) → 4B (2 attempts) → fail
31
+ */
32
+ protected call(input: RerankerInput, operationName: string): Promise<RankedDocument[]>;
33
+ private tryModel;
34
+ private elapsed;
35
+ protected buildPayload(input: RerankerInput): RerankerPayload;
36
+ protected processResponse(response: RerankerResponse, input: RerankerInput): RankedDocument[];
37
+ healthCheck(): Promise<boolean>;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=reranker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../../src/services/reranker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAoB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAID,qBAAa,eAAgB,SAAQ,gBAAgB,CACnD,aAAa,EACb,gBAAgB,EAChB,cAAc,EAAE,CACjB;IACC,SAAS,CAAC,QAAQ,CAAC,QAAQ,SACkC;IAE7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAS5B;IAEF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAK;IAEnC,MAAM,CACV,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,EAAE,CAAC;IAc5B;;OAEG;cACsB,IAAI,CAC3B,KAAK,EAAE,aAAa,EACpB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,EAAE,CAAC;YAyBd,QAAQ;IAsBtB,OAAO,CAAC,OAAO;IAIf,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe;IAQ7D,SAAS,CAAC,eAAe,CACvB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,aAAa,GACnB,cAAc,EAAE;IAqBb,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAUtC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * DeepInfra Reranker Service - MCP Optimized
3
+ * Dual-model fallback: 8B → 4B, 2 attempts each
4
+ */
5
+ import { logger } from "../utils/logger.js";
6
+ import { DEEPINFRA_CONFIG, DeepInfraService } from "./deepinfra-base.js";
7
+ export class RerankerService extends DeepInfraService {
8
+ endpoint = `/v1/inference/${DEEPINFRA_CONFIG.RERANKER_MODEL_PRIMARY}`;
9
+ static MODELS = [
10
+ {
11
+ endpoint: `/v1/inference/${DEEPINFRA_CONFIG.RERANKER_MODEL_PRIMARY}`,
12
+ name: "8B",
13
+ },
14
+ {
15
+ endpoint: `/v1/inference/${DEEPINFRA_CONFIG.RERANKER_MODEL_FALLBACK}`,
16
+ name: "4B",
17
+ },
18
+ ];
19
+ static MAX_ATTEMPTS = 2;
20
+ async rerank(query, documents, topN) {
21
+ if (!query?.trim())
22
+ throw new Error("Query cannot be empty for reranking");
23
+ if (!documents?.length)
24
+ throw new Error("Documents cannot be empty for reranking");
25
+ const validTopN = Math.min(topN, documents.length);
26
+ if (validTopN <= 0)
27
+ throw new Error("top_n must be greater than 0");
28
+ return this.call({ query: query.trim(), documents, topN: validTopN }, "Document reranking");
29
+ }
30
+ /**
31
+ * Dual-model fallback: 8B (2 attempts) → 4B (2 attempts) → fail
32
+ */
33
+ async call(input, operationName) {
34
+ const startTime = Date.now();
35
+ const payload = this.buildPayload(input);
36
+ const errors = [];
37
+ for (const model of RerankerService.MODELS) {
38
+ const result = await this.tryModel(model, payload, input);
39
+ if (result.success) {
40
+ logger.info(`${operationName} completed with ${model.name} (${this.elapsed(startTime)})`);
41
+ return result.data;
42
+ }
43
+ errors.push(`${model.name}: ${result.error}`);
44
+ logger.warn(`${model.name} model failed, ${model === RerankerService.MODELS[0] ? "switching to 4B" : "no more fallbacks"}`);
45
+ }
46
+ logger.error(`${operationName} failed after all attempts (${this.elapsed(startTime)}): ${errors.join(" | ")}`);
47
+ throw new Error(`Reranking failed: ${errors.join(" | ")}`);
48
+ }
49
+ async tryModel(model, payload, input) {
50
+ let lastError = "";
51
+ for (let attempt = 1; attempt <= RerankerService.MAX_ATTEMPTS; attempt++) {
52
+ try {
53
+ const response = await this.singleRequest(model.endpoint, payload);
54
+ return { success: true, data: this.processResponse(response, input) };
55
+ }
56
+ catch (e) {
57
+ lastError = e instanceof Error ? e.message : String(e);
58
+ logger.warn(`${model.name} attempt ${attempt}/${RerankerService.MAX_ATTEMPTS} failed: ${lastError}`);
59
+ }
60
+ }
61
+ return { success: false, error: lastError };
62
+ }
63
+ elapsed(startTime) {
64
+ return `${((Date.now() - startTime) / 1000).toFixed(1)}s`;
65
+ }
66
+ buildPayload(input) {
67
+ return {
68
+ queries: [input.query],
69
+ documents: input.documents,
70
+ top_n: input.topN,
71
+ };
72
+ }
73
+ processResponse(response, input) {
74
+ if (!response.scores?.length) {
75
+ throw new Error("No reranking results received from DeepInfra API");
76
+ }
77
+ const count = Math.min(input.topN, response.scores.length, input.documents.length);
78
+ return input.documents
79
+ .map((content, index) => ({
80
+ content,
81
+ originalIndex: index,
82
+ relevanceScore: response.scores[index] ?? 0,
83
+ }))
84
+ .sort((a, b) => b.relevanceScore - a.relevanceScore)
85
+ .slice(0, count);
86
+ }
87
+ async healthCheck() {
88
+ try {
89
+ return (await this.rerank("test query", ["test document"], 1)).length > 0;
90
+ }
91
+ catch (error) {
92
+ logger.error(`Reranker health check failed: ${error instanceof Error ? error.message : String(error)}`);
93
+ return false;
94
+ }
95
+ }
96
+ }
97
+ //# sourceMappingURL=reranker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../../src/services/reranker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AA0BzE,MAAM,OAAO,eAAgB,SAAQ,gBAIpC;IACoB,QAAQ,GACzB,iBAAiB,gBAAgB,CAAC,sBAAsB,EAAE,CAAC;IAErD,MAAM,CAAU,MAAM,GAA2B;QACvD;YACE,QAAQ,EAAE,iBAAiB,gBAAgB,CAAC,sBAAsB,EAAE;YACpE,IAAI,EAAE,IAAI;SACX;QACD;YACE,QAAQ,EAAE,iBAAiB,gBAAgB,CAAC,uBAAuB,EAAE;YACrE,IAAI,EAAE,IAAI;SACX;KACF,CAAC;IAEM,MAAM,CAAU,YAAY,GAAG,CAAC,CAAC;IAEzC,KAAK,CAAC,MAAM,CACV,KAAa,EACb,SAAmB,EACnB,IAAY;QAEZ,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3E,IAAI,CAAC,SAAS,EAAE,MAAM;YACpB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAE7D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAEpE,OAAO,IAAI,CAAC,IAAI,CACd,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,EACnD,oBAAoB,CACrB,CAAC;IACJ,CAAC;IAED;;OAEG;IACgB,KAAK,CAAC,IAAI,CAC3B,KAAoB,EACpB,aAAqB;QAErB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CACT,GAAG,aAAa,mBAAmB,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7E,CAAC;gBACF,OAAO,MAAM,CAAC,IAAK,CAAC;YACtB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,KAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CACT,GAAG,KAAK,CAAC,IAAI,kBAAkB,KAAK,KAAK,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAC/G,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,KAAK,CACV,GAAG,aAAa,+BAA+B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACjG,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,QAAQ,CACpB,KAAkB,EAClB,OAAwB,EACxB,KAAoB;QAEpB,IAAI,SAAS,GAAG,EAAE,CAAC;QAEnB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,eAAe,CAAC,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;YACzE,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YACxE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,SAAS,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACvD,MAAM,CAAC,IAAI,CACT,GAAG,KAAK,CAAC,IAAI,YAAY,OAAO,IAAI,eAAe,CAAC,YAAY,YAAY,SAAS,EAAE,CACxF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9C,CAAC;IAEO,OAAO,CAAC,SAAiB;QAC/B,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5D,CAAC;IAES,YAAY,CAAC,KAAoB;QACzC,OAAO;YACL,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,KAAK,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IAES,eAAe,CACvB,QAA0B,EAC1B,KAAoB;QAEpB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,KAAK,CAAC,IAAI,EACV,QAAQ,CAAC,MAAM,CAAC,MAAM,EACtB,KAAK,CAAC,SAAS,CAAC,MAAM,CACvB,CAAC;QAEF,OAAO,KAAK,CAAC,SAAS;aACnB,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACxB,OAAO;YACP,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;SAC5C,CAAC,CAAC;aACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,CAAC;aACnD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CACV,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC1F,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Hybrid Search Engine for Apple Developer Documentation
3
+ *
4
+ * Advanced implementation combining Semantic Search for RAG with precise
5
+ * Keyword Search and Hybrid Search, optimized for developer documentation retrieval.
6
+ *
7
+ * Pipeline: Query → [Vector (4N) + Technical Term (4N)] → Merge → Title Merge → AI Rerank → Results
8
+ *
9
+ * Features:
10
+ * - 4N+4N hybrid candidate strategy
11
+ * - Semantic vector search with pgvector HNSW
12
+ * - Technical term search with PostgreSQL 'simple' configuration
13
+ * - Title-based content merging
14
+ * - AI reranking with Qwen3-Reranker-8B
15
+ */
16
+ import type { AdditionalUrl, SearchOptions } from "../types/index.js";
17
+ import type { DatabaseService } from "./database.js";
18
+ import type { EmbeddingService } from "./embedding.js";
19
+ import type { RerankerService } from "./reranker.js";
20
+ export interface ParsedChunk {
21
+ content: string;
22
+ title: string | null;
23
+ }
24
+ export interface ProcessedResult {
25
+ id: string;
26
+ url: string;
27
+ title: string | null;
28
+ content: string;
29
+ contentLength: number;
30
+ chunk_index: number;
31
+ total_chunks: number;
32
+ mergedChunkIndices?: number[];
33
+ }
34
+ export interface RankedSearchResult {
35
+ id: string;
36
+ url: string;
37
+ title: string | null;
38
+ content: string;
39
+ chunk_index: number;
40
+ total_chunks: number;
41
+ mergedChunkIndices?: number[];
42
+ original_index: number;
43
+ }
44
+ export interface SearchEngineResult {
45
+ results: RankedSearchResult[];
46
+ additionalUrls: AdditionalUrl[];
47
+ }
48
+ export declare class SearchEngine {
49
+ private database;
50
+ private embedding;
51
+ private reranker;
52
+ constructor(database: DatabaseService, embedding: EmbeddingService, reranker: RerankerService);
53
+ /**
54
+ * Execute hybrid search optimized for Apple Developer Documentation
55
+ */
56
+ search(query: string, options?: SearchOptions): Promise<SearchEngineResult>;
57
+ /**
58
+ * Hybrid search with 4N+4N candidate strategy
59
+ *
60
+ * 1. Parallel: Vector search (4N) + Technical term search (4N)
61
+ * 2. Merge and deduplicate by ID
62
+ * 3. Title-based content merging
63
+ * 4. AI reranking for optimal results
64
+ */
65
+ private hybridSearchWithReranker;
66
+ /**
67
+ * Retrieve semantic search candidates with error handling
68
+ */
69
+ private getSemanticCandidates;
70
+ /**
71
+ * Retrieve keyword search candidates with error handling
72
+ */
73
+ private getKeywordCandidates;
74
+ /**
75
+ * Merge and deduplicate candidates from semantic and keyword search
76
+ */
77
+ private mergeCandidates;
78
+ /**
79
+ * Collect additional URLs from processed results
80
+ */
81
+ private collectAdditionalUrls;
82
+ /**
83
+ * Process RAG candidates through title-based merging
84
+ */
85
+ private processResults;
86
+ private parseChunk;
87
+ private mergeByTitle;
88
+ }
89
+ //# sourceMappingURL=search-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-engine.d.ts","sourceRoot":"","sources":["../../../src/services/search-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EAEd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ;gBAFR,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,eAAe;IAGnC;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,kBAAkB,CAAC;IAK9B;;;;;;;OAOG;YACW,wBAAwB;IA8EtC;;OAEG;YACW,qBAAqB;IAyBnC;;OAEG;YACW,oBAAoB;IAwBlC;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqB7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,YAAY;CAkDrB"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Hybrid Search Engine for Apple Developer Documentation
3
+ *
4
+ * Advanced implementation combining Semantic Search for RAG with precise
5
+ * Keyword Search and Hybrid Search, optimized for developer documentation retrieval.
6
+ *
7
+ * Pipeline: Query → [Vector (4N) + Technical Term (4N)] → Merge → Title Merge → AI Rerank → Results
8
+ *
9
+ * Features:
10
+ * - 4N+4N hybrid candidate strategy
11
+ * - Semantic vector search with pgvector HNSW
12
+ * - Technical term search with PostgreSQL 'simple' configuration
13
+ * - Title-based content merging
14
+ * - AI reranking with Qwen3-Reranker-8B
15
+ */
16
+ import { logger } from "../utils/logger.js";
17
+ export class SearchEngine {
18
+ database;
19
+ embedding;
20
+ reranker;
21
+ constructor(database, embedding, reranker) {
22
+ this.database = database;
23
+ this.embedding = embedding;
24
+ this.reranker = reranker;
25
+ }
26
+ /**
27
+ * Execute hybrid search optimized for Apple Developer Documentation
28
+ */
29
+ async search(query, options = {}) {
30
+ const { resultCount = 4 } = options;
31
+ return this.hybridSearchWithReranker(query, resultCount);
32
+ }
33
+ /**
34
+ * Hybrid search with 4N+4N candidate strategy
35
+ *
36
+ * 1. Parallel: Vector search (4N) + Technical term search (4N)
37
+ * 2. Merge and deduplicate by ID
38
+ * 3. Title-based content merging
39
+ * 4. AI reranking for optimal results
40
+ */
41
+ async hybridSearchWithReranker(query, resultCount) {
42
+ // Step 1: Parallel candidate retrieval (4N each, no minimum limit)
43
+ const candidateCount = resultCount * 4;
44
+ const [semanticResults, keywordResults] = await Promise.all([
45
+ this.getSemanticCandidates(query, candidateCount),
46
+ this.getKeywordCandidates(query, candidateCount),
47
+ ]);
48
+ // Step 2: Merge and deduplicate candidates
49
+ const mergedCandidates = this.mergeCandidates(semanticResults, keywordResults);
50
+ // Step 3: Process results (title-based merging)
51
+ const processedResults = this.processResults(mergedCandidates);
52
+ // Step 4: AI reranking with fallback mechanism
53
+ let finalResults;
54
+ try {
55
+ const rankedDocuments = await this.reranker.rerank(query, processedResults.map((r) => r.content), Math.min(resultCount, processedResults.length));
56
+ // Step 5: Map back to final results
57
+ finalResults = rankedDocuments.map((doc) => {
58
+ const processed = processedResults[doc.originalIndex];
59
+ return {
60
+ id: processed.id,
61
+ url: processed.url,
62
+ title: processed.title,
63
+ content: processed.content,
64
+ chunk_index: processed.chunk_index,
65
+ total_chunks: processed.total_chunks,
66
+ mergedChunkIndices: processed.mergedChunkIndices,
67
+ original_index: doc.originalIndex,
68
+ };
69
+ });
70
+ }
71
+ catch (error) {
72
+ logger.error(`Reranking failed, falling back to original order (query_length: ${query.length}, candidates: ${processedResults.length}): ${error instanceof Error ? error.message : String(error)}`);
73
+ // Fallback: use original order, truncate to requested count
74
+ finalResults = processedResults
75
+ .slice(0, resultCount)
76
+ .map((processed, index) => ({
77
+ id: processed.id,
78
+ url: processed.url,
79
+ title: processed.title,
80
+ content: processed.content,
81
+ chunk_index: processed.chunk_index,
82
+ total_chunks: processed.total_chunks,
83
+ mergedChunkIndices: processed.mergedChunkIndices,
84
+ original_index: index,
85
+ }));
86
+ logger.warn(`Reranking failed, using original order with ${finalResults.length} results`);
87
+ }
88
+ // Collect additional URLs
89
+ const additionalUrls = this.collectAdditionalUrls(processedResults, finalResults);
90
+ return { results: finalResults, additionalUrls };
91
+ }
92
+ /**
93
+ * Retrieve semantic search candidates with error handling
94
+ */
95
+ async getSemanticCandidates(query, resultCount) {
96
+ const startTime = Date.now();
97
+ try {
98
+ const queryEmbedding = await this.embedding.createEmbedding(query);
99
+ const results = await this.database.semanticSearch(queryEmbedding, {
100
+ resultCount,
101
+ });
102
+ logger.info(`Semantic search completed (${((Date.now() - startTime) / 1000).toFixed(1)}s): ${results.length} results`);
103
+ return results;
104
+ }
105
+ catch (error) {
106
+ logger.error(`Semantic search failed, falling back to keyword-only: ${error instanceof Error ? error.message : String(error)}`);
107
+ return [];
108
+ }
109
+ }
110
+ /**
111
+ * Retrieve keyword search candidates with error handling
112
+ */
113
+ async getKeywordCandidates(query, resultCount) {
114
+ const startTime = Date.now();
115
+ try {
116
+ const results = await this.database.keywordSearch(query, {
117
+ resultCount,
118
+ });
119
+ logger.info(`Keyword search completed (${((Date.now() - startTime) / 1000).toFixed(1)}s): ${results.length} results`);
120
+ return results;
121
+ }
122
+ catch (error) {
123
+ logger.error(`Keyword search failed: ${error instanceof Error ? error.message : String(error)}`);
124
+ return [];
125
+ }
126
+ }
127
+ /**
128
+ * Merge and deduplicate candidates from semantic and keyword search
129
+ */
130
+ mergeCandidates(semanticResults, keywordResults) {
131
+ const seen = new Set();
132
+ // Prioritize semantic results, then add unique keyword results
133
+ return [
134
+ ...semanticResults.filter((result) => {
135
+ if (seen.has(result.id))
136
+ return false;
137
+ seen.add(result.id);
138
+ return true;
139
+ }),
140
+ ...keywordResults.filter((result) => {
141
+ if (seen.has(result.id))
142
+ return false;
143
+ seen.add(result.id);
144
+ return true;
145
+ }),
146
+ ];
147
+ }
148
+ /**
149
+ * Collect additional URLs from processed results
150
+ */
151
+ collectAdditionalUrls(processedResults, finalResults) {
152
+ const finalUrls = new Set(finalResults.map((r) => r.url));
153
+ return processedResults
154
+ .filter((r) => !finalUrls.has(r.url))
155
+ .reduce((urls, r) => {
156
+ if (!urls.some((u) => u.url === r.url)) {
157
+ urls.push({
158
+ url: r.url,
159
+ title: r.title,
160
+ characterCount: r.contentLength,
161
+ });
162
+ }
163
+ return urls;
164
+ }, [])
165
+ .slice(0, 10);
166
+ }
167
+ /**
168
+ * Process RAG candidates through title-based merging
169
+ */
170
+ processResults(candidates) {
171
+ // Step 1: Merge by title
172
+ return this.mergeByTitle(candidates);
173
+ }
174
+ parseChunk(content, title) {
175
+ // Since data migration is complete, content is now plain text
176
+ // and title comes from the dedicated title field
177
+ return {
178
+ title: title || "",
179
+ content: content,
180
+ };
181
+ }
182
+ mergeByTitle(results) {
183
+ const titleGroups = new Map();
184
+ // Group by title
185
+ for (const result of results) {
186
+ const { title } = this.parseChunk(result.content, result.title);
187
+ const titleKey = title || "untitled";
188
+ if (!titleGroups.has(titleKey)) {
189
+ titleGroups.set(titleKey, []);
190
+ }
191
+ titleGroups.get(titleKey).push(result);
192
+ }
193
+ return Array.from(titleGroups.entries()).map(([title, group]) => {
194
+ const primary = group[0];
195
+ // Sort and merge chunks by original index to maintain proper content order
196
+ const chunkIndices = group
197
+ .map((r) => r.chunk_index)
198
+ .sort((a, b) => a - b);
199
+ const mergedContent = group
200
+ .sort((a, b) => a.chunk_index - b.chunk_index)
201
+ .map((r) => this.parseChunk(r.content, r.title).content)
202
+ .join("\n\n---\n\n");
203
+ // Detect complete document merging
204
+ const isCompleteDocument = chunkIndices.length === primary.total_chunks &&
205
+ chunkIndices.every((idx, i) => idx === i);
206
+ // Determine final chunk representation
207
+ const [chunk_index, total_chunks] = chunkIndices.length === 1
208
+ ? [chunkIndices[0], primary.total_chunks]
209
+ : isCompleteDocument
210
+ ? [0, 1]
211
+ : [Math.min(...chunkIndices), primary.total_chunks];
212
+ return {
213
+ id: primary.id,
214
+ url: primary.url,
215
+ title,
216
+ content: mergedContent,
217
+ mergedChunkIndices: chunkIndices.length > 1 ? chunkIndices : undefined,
218
+ contentLength: mergedContent.length,
219
+ chunk_index,
220
+ total_chunks,
221
+ };
222
+ });
223
+ }
224
+ }
225
+ //# sourceMappingURL=search-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-engine.js","sourceRoot":"","sources":["../../../src/services/search-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Tool Call Logger with background D1 writes
3
+ */
4
+ export interface SearchLogEntry {
5
+ userId: string;
6
+ mcpToken?: string | null;
7
+ requestedQuery: string;
8
+ actualQuery: string;
9
+ resultCount: number;
10
+ responseTimeMs: number;
11
+ statusCode?: number;
12
+ errorCode?: string | null;
13
+ ipAddress?: string;
14
+ countryCode?: string | null;
15
+ }
16
+ export interface FetchLogEntry {
17
+ userId: string;
18
+ mcpToken?: string | null;
19
+ requestedUrl: string;
20
+ actualUrl: string;
21
+ pageId?: string | null;
22
+ responseTimeMs: number;
23
+ statusCode?: number;
24
+ errorCode?: string | null;
25
+ ipAddress?: string;
26
+ countryCode?: string | null;
27
+ }
28
+ export declare class ToolCallLogger {
29
+ private d1;
30
+ constructor(d1: D1Database);
31
+ logSearch(entry: SearchLogEntry): void;
32
+ logFetch(entry: FetchLogEntry): void;
33
+ private insertSearchLog;
34
+ private insertFetchLog;
35
+ }
36
+ //# sourceMappingURL=tool-call-logger.d.ts.map