@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,166 @@
1
+ /**
2
+ * PostgreSQL Database Service with pgvector
3
+ * Optimized for Cloudflare Workers with external database connection
4
+ */
5
+ import postgres from "postgres";
6
+ import { logger } from "../utils/logger.js";
7
+ export class DatabaseService {
8
+ sql;
9
+ constructor(config) {
10
+ // Direct PostgreSQL connection - no checks, no logs
11
+ this.sql = postgres({
12
+ host: config.RAG_DB_HOST,
13
+ port: config.RAG_DB_PORT,
14
+ database: config.RAG_DB_DATABASE,
15
+ username: config.RAG_DB_USER,
16
+ password: config.RAG_DB_PASSWORD,
17
+ ssl: config.RAG_DB_SSLMODE === "require",
18
+ max: 5,
19
+ idle_timeout: 60000,
20
+ connect_timeout: 10000,
21
+ prepare: true,
22
+ connection: {
23
+ application_name: "apple-rag-mcp",
24
+ },
25
+ transform: {
26
+ undefined: null,
27
+ },
28
+ });
29
+ }
30
+ /**
31
+ * Initialize database - no checks, trust ready state
32
+ */
33
+ async initialize() {
34
+ // Database assumed ready - no checks, no logs, instant return
35
+ }
36
+ /**
37
+ * Semantic search using vector similarity
38
+ */
39
+ async semanticSearch(queryEmbedding, options = {}) {
40
+ const { resultCount = 5 } = options;
41
+ try {
42
+ const results = await this.sql `
43
+ SELECT id, url, title, content, chunk_index, total_chunks
44
+ FROM chunks
45
+ WHERE embedding IS NOT NULL
46
+ ORDER BY embedding <=> ${JSON.stringify(queryEmbedding)}::halfvec
47
+ LIMIT ${resultCount}
48
+ `;
49
+ return results.map((row) => ({
50
+ id: row.id,
51
+ url: row.url,
52
+ title: row.title,
53
+ content: row.content,
54
+ contentLength: row.content.length,
55
+ chunk_index: row.chunk_index,
56
+ total_chunks: row.total_chunks,
57
+ }));
58
+ }
59
+ catch (error) {
60
+ logger.error(`Database semantic search failed (operation: semantic_search, embeddingDimensions: ${queryEmbedding.length}, resultCount: ${resultCount}): ${String(error)}`);
61
+ throw new Error(`Vector search failed: ${error}`);
62
+ }
63
+ }
64
+ /**
65
+ * Keyword search optimized for Apple Developer Documentation
66
+ * Uses PostgreSQL 'simple' configuration for precise matching of technical terms,
67
+ * API names, and special symbols (@State, SecItemAdd, etc.)
68
+ */
69
+ async keywordSearch(query, options = {}) {
70
+ const { resultCount = 5 } = options;
71
+ try {
72
+ const results = await this.sql `
73
+ SELECT id, url, title, content, chunk_index, total_chunks
74
+ FROM chunks
75
+ WHERE to_tsvector('simple', COALESCE(title, '') || ' ' || content)
76
+ @@ plainto_tsquery('simple', ${query})
77
+ LIMIT ${resultCount}
78
+ `;
79
+ return results.map((row) => ({
80
+ id: row.id,
81
+ url: row.url,
82
+ title: row.title,
83
+ content: row.content,
84
+ contentLength: row.content.length,
85
+ chunk_index: row.chunk_index,
86
+ total_chunks: row.total_chunks,
87
+ }));
88
+ }
89
+ catch (error) {
90
+ logger.error(`Database keyword search failed (operation: keyword_search, query: ${query.substring(0, 50)}, resultCount: ${resultCount}): ${String(error)}`);
91
+ throw new Error(`Keyword search failed: ${error}`);
92
+ }
93
+ }
94
+ /**
95
+ * Normalize URL for flexible matching
96
+ */
97
+ normalizeUrl(url) {
98
+ // Remove trailing slash
99
+ let normalized = url.replace(/\/$/, "");
100
+ // Ensure https:// prefix
101
+ if (!normalized.startsWith("http://") &&
102
+ !normalized.startsWith("https://")) {
103
+ normalized = `https://${normalized}`;
104
+ }
105
+ // Convert http:// to https://
106
+ if (normalized.startsWith("http://")) {
107
+ normalized = normalized.replace("http://", "https://");
108
+ }
109
+ return normalized;
110
+ }
111
+ /**
112
+ * Get page content by URL from pages table with flexible matching
113
+ */
114
+ async getPageByUrl(url) {
115
+ const normalizedUrl = this.normalizeUrl(url);
116
+ try {
117
+ // Try exact match first
118
+ let results = await this.sql `
119
+ SELECT id, url, title, content
120
+ FROM pages
121
+ WHERE url = ${normalizedUrl}
122
+ LIMIT 1
123
+ `;
124
+ // If no exact match, try flexible matching
125
+ if (results.length === 0) {
126
+ // Try with/without trailing slash
127
+ const alternativeUrl = normalizedUrl.endsWith("/")
128
+ ? normalizedUrl.slice(0, -1)
129
+ : `${normalizedUrl}/`;
130
+ results = await this.sql `
131
+ SELECT id, url, title, content
132
+ FROM pages
133
+ WHERE url = ${alternativeUrl}
134
+ LIMIT 1
135
+ `;
136
+ }
137
+ if (results.length === 0) {
138
+ return null;
139
+ }
140
+ const row = results[0];
141
+ return {
142
+ id: row.id,
143
+ url: row.url,
144
+ title: row.title,
145
+ content: row.content,
146
+ };
147
+ }
148
+ catch (error) {
149
+ logger.error(`Database page lookup failed (operation: page_lookup, url: ${url.substring(0, 100)}, normalizedUrl: ${this.normalizeUrl(url).substring(0, 100)}): ${String(error)}`);
150
+ throw new Error(`Page lookup failed: ${error}`);
151
+ }
152
+ }
153
+ /**
154
+ * Close database connection
155
+ */
156
+ async close() {
157
+ try {
158
+ await this.sql.end();
159
+ }
160
+ catch (error) {
161
+ logger.error(`Database close failed (operation: database_close): ${String(error)}`);
162
+ // Don't re-throw - closing errors are not critical
163
+ }
164
+ }
165
+ }
166
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/services/database.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * DeepInfra client utilities (config + base service)
3
+ * Minimal single-key client with retry support.
4
+ */
5
+ export declare const DEEPINFRA_CONFIG: {
6
+ readonly BASE_URL: "https://api.deepinfra.com";
7
+ readonly TIMEOUT_MS: 5000;
8
+ readonly USER_AGENT: "Apple-RAG-MCP/2.0.0";
9
+ readonly EMBEDDING_MODEL: "Qwen/Qwen3-Embedding-4B";
10
+ readonly RERANKER_MODEL_PRIMARY: "Qwen/Qwen3-Reranker-8B";
11
+ readonly RERANKER_MODEL_FALLBACK: "Qwen/Qwen3-Reranker-4B";
12
+ };
13
+ export declare abstract class DeepInfraService<TRequest, TResponse, TResult> {
14
+ protected abstract readonly endpoint: string;
15
+ private readonly apiKey;
16
+ constructor(apiKey: string);
17
+ protected call(input: TRequest, operationName: string): Promise<TResult>;
18
+ protected singleRequest(endpoint: string, payload: unknown): Promise<TResponse>;
19
+ protected abstract buildPayload(input: TRequest): unknown;
20
+ protected abstract processResponse(response: TResponse, input: TRequest): TResult;
21
+ }
22
+ //# sourceMappingURL=deepinfra-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepinfra-base.d.ts","sourceRoot":"","sources":["../../../src/services/deepinfra-base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,eAAO,MAAM,gBAAgB;;;;;;;CAOnB,CAAC;AAEX,8BAAsB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO;IACjE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,MAAM;cAKV,IAAI,CAClB,KAAK,EAAE,QAAQ,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC;cAuBH,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,SAAS,CAAC;IAqBrB,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IACzD,SAAS,CAAC,QAAQ,CAAC,eAAe,CAChC,QAAQ,EAAE,SAAS,EACnB,KAAK,EAAE,QAAQ,GACd,OAAO;CACX"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * DeepInfra client utilities (config + base service)
3
+ * Minimal single-key client with retry support.
4
+ */
5
+ import { logger } from "../utils/logger.js";
6
+ export const DEEPINFRA_CONFIG = {
7
+ BASE_URL: "https://api.deepinfra.com",
8
+ TIMEOUT_MS: 5_000,
9
+ USER_AGENT: "Apple-RAG-MCP/2.0.0",
10
+ EMBEDDING_MODEL: "Qwen/Qwen3-Embedding-4B",
11
+ RERANKER_MODEL_PRIMARY: "Qwen/Qwen3-Reranker-8B",
12
+ RERANKER_MODEL_FALLBACK: "Qwen/Qwen3-Reranker-4B",
13
+ };
14
+ export class DeepInfraService {
15
+ apiKey;
16
+ constructor(apiKey) {
17
+ if (!apiKey)
18
+ throw new Error("DEEPINFRA_API_KEY is required");
19
+ this.apiKey = apiKey;
20
+ }
21
+ async call(input, operationName) {
22
+ const startTime = Date.now();
23
+ const payload = this.buildPayload(input);
24
+ let lastError;
25
+ for (let i = 0; i < 3; i++) {
26
+ try {
27
+ const json = await this.singleRequest(this.endpoint, payload);
28
+ logger.info(`${operationName} completed (${((Date.now() - startTime) / 1000).toFixed(1)}s)`);
29
+ return this.processResponse(json, input);
30
+ }
31
+ catch (e) {
32
+ lastError = e instanceof Error ? e : new Error(String(e));
33
+ }
34
+ }
35
+ logger.error(`${operationName} failed after 3 attempts (${((Date.now() - startTime) / 1000).toFixed(1)}s): ${lastError.message}`);
36
+ throw lastError;
37
+ }
38
+ async singleRequest(endpoint, payload) {
39
+ const res = await fetch(`${DEEPINFRA_CONFIG.BASE_URL}${endpoint}`, {
40
+ method: "POST",
41
+ headers: {
42
+ Authorization: `Bearer ${this.apiKey}`,
43
+ "Content-Type": "application/json",
44
+ "User-Agent": DEEPINFRA_CONFIG.USER_AGENT,
45
+ },
46
+ body: JSON.stringify(payload),
47
+ signal: AbortSignal.timeout(DEEPINFRA_CONFIG.TIMEOUT_MS),
48
+ });
49
+ if (!res.ok) {
50
+ throw new Error(`API error ${res.status}: ${await res.text().catch(() => "")}`);
51
+ }
52
+ return (await res.json());
53
+ }
54
+ }
55
+ //# sourceMappingURL=deepinfra-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepinfra-base.js","sourceRoot":"","sources":["../../../src/services/deepinfra-base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,2BAA2B;IACrC,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,qBAAqB;IACjC,eAAe,EAAE,yBAAyB;IAC1C,sBAAsB,EAAE,wBAAwB;IAChD,uBAAuB,EAAE,wBAAwB;CACzC,CAAC;AAEX,MAAM,OAAgB,gBAAgB;IAEnB,MAAM,CAAS;IAEhC,YAAY,MAAc;QACxB,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAES,KAAK,CAAC,IAAI,CAClB,KAAe,EACf,aAAqB;QAErB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,SAAiB,CAAC;QAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC9D,MAAM,CAAC,IAAI,CACT,GAAG,aAAa,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAChF,CAAC;gBACF,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,SAAS,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,MAAM,CAAC,KAAK,CACV,GAAG,aAAa,6BAA6B,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,SAAS,CAAC,OAAO,EAAE,CACpH,CAAC;QACF,MAAM,SAAS,CAAC;IAClB,CAAC;IAES,KAAK,CAAC,aAAa,CAC3B,QAAgB,EAChB,OAAgB;QAEhB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,gBAAgB,CAAC,QAAQ,GAAG,QAAQ,EAAE,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,cAAc,EAAE,kBAAkB;gBAClC,YAAY,EAAE,gBAAgB,CAAC,UAAU;aAC1C;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC;SACzD,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,aAAa,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAC/D,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAc,CAAC;IACzC,CAAC;CAOF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Modern Embedding Service - MCP Optimized
3
+ * DeepInfra API integration (single provider, no fallback)
4
+ */
5
+ import type { EmbeddingService as IEmbeddingService } from "../types/index.js";
6
+ import { DeepInfraService } from "./deepinfra-base.js";
7
+ interface EmbeddingInput {
8
+ text: string;
9
+ }
10
+ interface EmbeddingPayload {
11
+ model: "Qwen/Qwen3-Embedding-4B";
12
+ input: string;
13
+ encoding_format: "float";
14
+ }
15
+ interface EmbeddingResponse {
16
+ data: Array<{
17
+ embedding: number[];
18
+ }>;
19
+ }
20
+ export declare class EmbeddingService extends DeepInfraService<EmbeddingInput, EmbeddingResponse, number[]> implements IEmbeddingService {
21
+ protected readonly endpoint = "/v1/openai/embeddings";
22
+ /**
23
+ * Create embedding (single provider)
24
+ */
25
+ createEmbedding(text: string): Promise<number[]>;
26
+ /**
27
+ * Build API payload from request
28
+ */
29
+ protected buildPayload(input: EmbeddingInput): EmbeddingPayload;
30
+ /**
31
+ * Process API response and return normalized embedding
32
+ */
33
+ protected processResponse(response: EmbeddingResponse, _input: EmbeddingInput): number[];
34
+ /**
35
+ * Extract embedding from API response
36
+ */
37
+ private extractEmbedding;
38
+ /**
39
+ * L2 normalization for optimal vector search performance
40
+ */
41
+ private normalizeL2;
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=embedding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../src/services/embedding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,OAAO,EAAoB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,gBAAgB;IACxB,KAAK,EAAE,yBAAyB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,KAAK,CAAC;QACV,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,qBAAa,gBACX,SAAQ,gBAAgB,CAAC,cAAc,EAAE,iBAAiB,EAAE,MAAM,EAAE,CACpE,YAAW,iBAAiB;IAE5B,SAAS,CAAC,QAAQ,CAAC,QAAQ,2BAA2B;IAEtD;;OAEG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAStD;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,gBAAgB;IAQ/D;;OAEG;IACH,SAAS,CAAC,eAAe,CACvB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,cAAc,GACrB,MAAM,EAAE;IAKX;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,WAAW;CAUpB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Modern Embedding Service - MCP Optimized
3
+ * DeepInfra API integration (single provider, no fallback)
4
+ */
5
+ import { logger } from "../utils/logger.js";
6
+ import { DEEPINFRA_CONFIG, DeepInfraService } from "./deepinfra-base.js";
7
+ export class EmbeddingService extends DeepInfraService {
8
+ endpoint = "/v1/openai/embeddings";
9
+ /**
10
+ * Create embedding (single provider)
11
+ */
12
+ async createEmbedding(text) {
13
+ if (!text?.trim()) {
14
+ throw new Error("Text cannot be empty for embedding generation");
15
+ }
16
+ const input = { text: text.trim() };
17
+ return this.call(input, "Embedding generation");
18
+ }
19
+ /**
20
+ * Build API payload from request
21
+ */
22
+ buildPayload(input) {
23
+ return {
24
+ model: DEEPINFRA_CONFIG.EMBEDDING_MODEL,
25
+ input: input.text,
26
+ encoding_format: "float",
27
+ };
28
+ }
29
+ /**
30
+ * Process API response and return normalized embedding
31
+ */
32
+ processResponse(response, _input) {
33
+ const embedding = this.extractEmbedding(response);
34
+ return this.normalizeL2(embedding);
35
+ }
36
+ /**
37
+ * Extract embedding from API response
38
+ */
39
+ extractEmbedding(response) {
40
+ const embedding = response.data?.[0]?.embedding;
41
+ if (!embedding || !Array.isArray(embedding)) {
42
+ throw new Error("No embedding data received from DeepInfra API");
43
+ }
44
+ if (embedding.length === 0) {
45
+ throw new Error("Empty embedding received from DeepInfra API");
46
+ }
47
+ return embedding;
48
+ }
49
+ /**
50
+ * L2 normalization for optimal vector search performance
51
+ */
52
+ normalizeL2(embedding) {
53
+ const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
54
+ if (norm === 0) {
55
+ logger.warn("Zero norm embedding detected, returning original");
56
+ return [...embedding];
57
+ }
58
+ return embedding.map((val) => val / norm);
59
+ }
60
+ }
61
+ //# sourceMappingURL=embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../../src/services/embedding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAkBzE,MAAM,OAAO,gBACX,SAAQ,gBAA6D;IAGlD,QAAQ,GAAG,uBAAuB,CAAC;IAEtD;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAmB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,KAAqB;QAC1C,OAAO;YACL,KAAK,EAAE,gBAAgB,CAAC,eAAe;YACvC,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,eAAe,EAAE,OAAO;SACzB,CAAC;IACJ,CAAC;IAED;;OAEG;IACO,eAAe,CACvB,QAA2B,EAC3B,MAAsB;QAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,QAA2B;QAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;QAEhD,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,SAAmB;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAE3E,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Modern Service Factory - Cloudflare Worker Native
3
+ * Creates and configures all services with optimal performance
4
+ */
5
+ import type { Services, WorkerEnv } from "../types/index.js";
6
+ /**
7
+ * Create all services from Worker environment with validation
8
+ */
9
+ export declare function createServices(env: WorkerEnv): Promise<Services>;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAa,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKxE;;GAEG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8BtE"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Modern Service Factory - Cloudflare Worker Native
3
+ * Creates and configures all services with optimal performance
4
+ */
5
+ import { AuthMiddleware } from "../auth/auth-middleware.js";
6
+ import { RAGService } from "./rag.js";
7
+ import { RateLimitService } from "./rate-limit.js";
8
+ import { ToolCallLogger } from "./tool-call-logger.js";
9
+ /**
10
+ * Create all services from Worker environment with validation
11
+ */
12
+ export async function createServices(env) {
13
+ try {
14
+ // Convert Worker env to app config
15
+ const config = createAppConfig(env);
16
+ // Initialize services
17
+ const auth = new AuthMiddleware(env.DB);
18
+ const rag = new RAGService(config, env);
19
+ const rateLimit = new RateLimitService(env.DB);
20
+ const logger = new ToolCallLogger(env.DB);
21
+ // Initialize async services
22
+ await rag.initialize();
23
+ return {
24
+ rag,
25
+ auth,
26
+ database: rag.database,
27
+ embedding: rag.embedding,
28
+ rateLimit,
29
+ logger,
30
+ };
31
+ }
32
+ catch (error) {
33
+ // Import logger here to avoid circular dependency
34
+ const { logger } = await import("../utils/logger.js");
35
+ logger.error(`Service initialization failed: ${error instanceof Error ? error.message : String(error)}`);
36
+ throw error;
37
+ }
38
+ }
39
+ /**
40
+ * Convert Worker environment to app configuration
41
+ */
42
+ function createAppConfig(env) {
43
+ return {
44
+ RAG_DB_HOST: env.RAG_DB_HOST,
45
+ RAG_DB_PORT: parseInt(env.RAG_DB_PORT, 10),
46
+ RAG_DB_DATABASE: env.RAG_DB_DATABASE,
47
+ RAG_DB_USER: env.RAG_DB_USER,
48
+ RAG_DB_PASSWORD: env.RAG_DB_PASSWORD,
49
+ RAG_DB_SSLMODE: env.RAG_DB_SSLMODE,
50
+ };
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAc;IACjD,IAAI,CAAC;QACH,mCAAmC;QACnC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QAEpC,sBAAsB;QACtB,MAAM,IAAI,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE1C,4BAA4B;QAC5B,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;QAEvB,OAAO;YACL,GAAG;YACH,IAAI;YACJ,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS;YACT,MAAM;SACP,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,kDAAkD;QAClD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CACV,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC3F,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,GAAc;IACrC,OAAO;QACL,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1C,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,cAAc,EAAE,GAAG,CAAC,cAAc;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * IP Authentication Service with D1 timeout protection
3
+ */
4
+ import type { UserTokenData } from "../auth/token-validator.js";
5
+ export declare class IPAuthenticationService {
6
+ private d1;
7
+ constructor(d1: D1Database);
8
+ checkIPAuthentication(clientIP: string): Promise<UserTokenData | null>;
9
+ private queryIP;
10
+ private updateLastUsed;
11
+ }
12
+ //# sourceMappingURL=ip-authentication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip-authentication.d.ts","sourceRoot":"","sources":["../../../src/services/ip-authentication.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUhE,qBAAa,uBAAuB;IACtB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU;IAE5B,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;YAsB9D,OAAO;YAcP,cAAc;CAQ7B"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * IP Authentication Service with D1 timeout protection
3
+ */
4
+ import { backgroundD1Write, withD1Timeout } from "../utils/d1-utils.js";
5
+ import { logger } from "../utils/logger.js";
6
+ export class IPAuthenticationService {
7
+ d1;
8
+ constructor(d1) {
9
+ this.d1 = d1;
10
+ }
11
+ async checkIPAuthentication(clientIP) {
12
+ const user = await withD1Timeout(() => this.queryIP(clientIP), null, "ip_auth");
13
+ if (!user)
14
+ return null;
15
+ backgroundD1Write(logger.getContext(), () => this.updateLastUsed(clientIP, user.user_id), "ip_last_used");
16
+ return {
17
+ userId: user.user_id,
18
+ email: user.email || "ip-authenticated",
19
+ name: user.name || "IP User",
20
+ };
21
+ }
22
+ async queryIP(clientIP) {
23
+ const result = await this.d1
24
+ .prepare(`SELECT uai.user_id, u.email, u.name
25
+ FROM user_authorized_ips uai
26
+ JOIN users u ON uai.user_id = u.id
27
+ WHERE uai.ip_address = ?`)
28
+ .bind(clientIP)
29
+ .all();
30
+ return result.results?.[0] ?? null;
31
+ }
32
+ async updateLastUsed(ipAddress, userId) {
33
+ await this.d1
34
+ .prepare("UPDATE user_authorized_ips SET last_used_at = ? WHERE ip_address = ? AND user_id = ?")
35
+ .bind(new Date().toISOString(), ipAddress, userId)
36
+ .run();
37
+ }
38
+ }
39
+ //# sourceMappingURL=ip-authentication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip-authentication.js","sourceRoot":"","sources":["../../../src/services/ip-authentication.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ5C,MAAM,OAAO,uBAAuB;IACd;IAApB,YAAoB,EAAc;QAAd,OAAE,GAAF,EAAE,CAAY;IAAG,CAAC;IAEtC,KAAK,CAAC,qBAAqB,CAAC,QAAgB;QAC1C,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC5B,IAAI,EACJ,SAAS,CACV,CAAC;QAEF,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,iBAAiB,CACf,MAAM,CAAC,UAAU,EAAE,EACnB,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,EACjD,cAAc,CACf,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,kBAAkB;YACvC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,SAAS;SAC7B,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,QAAgB;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE;aACzB,OAAO,CACN;;;kCAG0B,CAC3B;aACA,IAAI,CAAC,QAAQ,CAAC;aACd,GAAG,EAAE,CAAC;QAET,OAAQ,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAuC,IAAI,IAAI,CAAC;IAC5E,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,MAAc;QAC5D,MAAM,IAAI,CAAC,EAAE;aACV,OAAO,CACN,sFAAsF,CACvF;aACA,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC;aACjD,GAAG,EAAE,CAAC;IACX,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Modern RAG Service - Cloudflare Worker Native
3
+ * Optimized for edge computing with zero-dependency architecture
4
+ */
5
+ import type { AppConfig, RAGQuery, RAGResult, WorkerEnv } from "../types/index.js";
6
+ import { DatabaseService } from "./database.js";
7
+ import { EmbeddingService } from "./embedding.js";
8
+ export declare class RAGService {
9
+ readonly database: DatabaseService;
10
+ readonly embedding: EmbeddingService;
11
+ private readonly reranker;
12
+ private readonly searchEngine;
13
+ constructor(config: AppConfig, env: WorkerEnv);
14
+ /**
15
+ * Initialize - no-op since database initialization is removed
16
+ */
17
+ initialize(): Promise<void>;
18
+ /**
19
+ * Perform RAG query with intelligent processing and detailed timing
20
+ */
21
+ query(request: RAGQuery): Promise<RAGResult>;
22
+ /**
23
+ * Format search results for MCP response
24
+ */
25
+ private formatResults;
26
+ /**
27
+ * Create standardized error response
28
+ */
29
+ private createErrorResponse;
30
+ /**
31
+ * Clean up resources
32
+ */
33
+ close(): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=rag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag.d.ts","sourceRoot":"","sources":["../../../src/services/rag.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EAET,SAAS,EACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,qBAAa,UAAU;IACrB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS;IAW7C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAmElD;;OAEG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Modern RAG Service - Cloudflare Worker Native
3
+ * Optimized for edge computing with zero-dependency architecture
4
+ */
5
+ import { logger } from "../utils/logger.js";
6
+ import { DatabaseService } from "./database.js";
7
+ import { EmbeddingService } from "./embedding.js";
8
+ import { RerankerService } from "./reranker.js";
9
+ import { SearchEngine } from "./search-engine.js";
10
+ export class RAGService {
11
+ database;
12
+ embedding;
13
+ reranker;
14
+ searchEngine;
15
+ constructor(config, env) {
16
+ this.database = new DatabaseService(config);
17
+ this.embedding = new EmbeddingService(env.DEEPINFRA_API_KEY);
18
+ this.reranker = new RerankerService(env.DEEPINFRA_API_KEY);
19
+ this.searchEngine = new SearchEngine(this.database, this.embedding, this.reranker);
20
+ }
21
+ /**
22
+ * Initialize - no-op since database initialization is removed
23
+ */
24
+ async initialize() {
25
+ // No initialization needed - database trusted ready
26
+ }
27
+ /**
28
+ * Perform RAG query with intelligent processing and detailed timing
29
+ */
30
+ async query(request) {
31
+ const startTime = Date.now();
32
+ const { query, result_count = 4 } = request;
33
+ // No started log - only completion with timing
34
+ // Input validation
35
+ if (!query?.trim()) {
36
+ return this.createErrorResponse(query, "Query cannot be empty. Please provide a search query to find relevant Apple Developer Documentation.", "Try searching for topics like 'SwiftUI navigation', 'iOS app development', or 'API documentation'.", startTime);
37
+ }
38
+ const trimmedQuery = query.trim();
39
+ if (trimmedQuery.length > 10000) {
40
+ return this.createErrorResponse(query, "Query is too long. Please limit your query to 10000 characters or less.", "Try to make your query more concise and specific.", startTime);
41
+ }
42
+ try {
43
+ // Initialize services (if not already initialized)
44
+ await this.initialize();
45
+ // Execute search
46
+ const resultCount = Math.min(Math.max(result_count, 1), 20);
47
+ const searchResult = await this.searchEngine.search(trimmedQuery, {
48
+ resultCount,
49
+ });
50
+ // Format results
51
+ const formattedResults = this.formatResults(searchResult.results);
52
+ const totalTime = Date.now() - startTime;
53
+ // Log completion with timing
54
+ logger.info(`RAG query completed (${(totalTime / 1000).toFixed(1)}s) - results: ${formattedResults.length}, query: ${query.substring(0, 50)}`);
55
+ return {
56
+ success: true,
57
+ query: trimmedQuery,
58
+ results: formattedResults,
59
+ additionalUrls: searchResult.additionalUrls,
60
+ count: formattedResults.length,
61
+ processing_time_ms: totalTime,
62
+ };
63
+ }
64
+ catch (error) {
65
+ logger.error(`RAG query failed for query "${trimmedQuery.substring(0, 50)}": ${error instanceof Error ? error.message : "Unknown error"}`);
66
+ return this.createErrorResponse(trimmedQuery, `Search failed: ${error instanceof Error ? error.message : "Unknown error"}`, "Please try again with a different query or check your connection.", startTime);
67
+ }
68
+ }
69
+ /**
70
+ * Format search results for MCP response
71
+ */
72
+ formatResults(results) {
73
+ return results.map((result) => ({
74
+ id: result.id,
75
+ url: result.url,
76
+ title: result.title,
77
+ content: result.content,
78
+ contentLength: result.content.length,
79
+ chunk_index: result.chunk_index,
80
+ total_chunks: result.total_chunks,
81
+ mergedChunkIndices: result.mergedChunkIndices,
82
+ }));
83
+ }
84
+ /**
85
+ * Create standardized error response
86
+ */
87
+ createErrorResponse(query, _error, _suggestion, startTime) {
88
+ return {
89
+ success: false,
90
+ query,
91
+ results: [],
92
+ additionalUrls: [],
93
+ count: 0,
94
+ processing_time_ms: Date.now() - startTime,
95
+ };
96
+ }
97
+ /**
98
+ * Clean up resources
99
+ */
100
+ async close() {
101
+ if (this.database) {
102
+ await this.database.close();
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=rag.js.map