@vdpeijl/kb-mcp 0.1.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 (106) hide show
  1. package/README.md +416 -0
  2. package/dist/scripts/postinstall.d.ts +3 -0
  3. package/dist/scripts/postinstall.d.ts.map +1 -0
  4. package/dist/scripts/postinstall.js +110 -0
  5. package/dist/scripts/postinstall.js.map +1 -0
  6. package/dist/src/cli.d.ts +3 -0
  7. package/dist/src/cli.d.ts.map +1 -0
  8. package/dist/src/cli.js +22 -0
  9. package/dist/src/cli.js.map +1 -0
  10. package/dist/src/commands/doctor.d.ts +3 -0
  11. package/dist/src/commands/doctor.d.ts.map +1 -0
  12. package/dist/src/commands/doctor.js +93 -0
  13. package/dist/src/commands/doctor.js.map +1 -0
  14. package/dist/src/commands/init.d.ts +3 -0
  15. package/dist/src/commands/init.d.ts.map +1 -0
  16. package/dist/src/commands/init.js +150 -0
  17. package/dist/src/commands/init.js.map +1 -0
  18. package/dist/src/commands/serve.d.ts +3 -0
  19. package/dist/src/commands/serve.d.ts.map +1 -0
  20. package/dist/src/commands/serve.js +22 -0
  21. package/dist/src/commands/serve.js.map +1 -0
  22. package/dist/src/commands/setup.d.ts +9 -0
  23. package/dist/src/commands/setup.d.ts.map +1 -0
  24. package/dist/src/commands/setup.js +115 -0
  25. package/dist/src/commands/setup.js.map +1 -0
  26. package/dist/src/commands/sources.d.ts +3 -0
  27. package/dist/src/commands/sources.d.ts.map +1 -0
  28. package/dist/src/commands/sources.js +258 -0
  29. package/dist/src/commands/sources.js.map +1 -0
  30. package/dist/src/commands/stats.d.ts +3 -0
  31. package/dist/src/commands/stats.d.ts.map +1 -0
  32. package/dist/src/commands/stats.js +48 -0
  33. package/dist/src/commands/stats.js.map +1 -0
  34. package/dist/src/commands/sync.d.ts +13 -0
  35. package/dist/src/commands/sync.d.ts.map +1 -0
  36. package/dist/src/commands/sync.js +106 -0
  37. package/dist/src/commands/sync.js.map +1 -0
  38. package/dist/src/config/index.d.ts +18 -0
  39. package/dist/src/config/index.d.ts.map +1 -0
  40. package/dist/src/config/index.js +67 -0
  41. package/dist/src/config/index.js.map +1 -0
  42. package/dist/src/config/paths.d.ts +21 -0
  43. package/dist/src/config/paths.d.ts.map +1 -0
  44. package/dist/src/config/paths.js +38 -0
  45. package/dist/src/config/paths.js.map +1 -0
  46. package/dist/src/config/schema.d.ts +133 -0
  47. package/dist/src/config/schema.d.ts.map +1 -0
  48. package/dist/src/config/schema.js +34 -0
  49. package/dist/src/config/schema.js.map +1 -0
  50. package/dist/src/db/articles.d.ts +39 -0
  51. package/dist/src/db/articles.d.ts.map +1 -0
  52. package/dist/src/db/articles.js +103 -0
  53. package/dist/src/db/articles.js.map +1 -0
  54. package/dist/src/db/chunks.d.ts +46 -0
  55. package/dist/src/db/chunks.d.ts.map +1 -0
  56. package/dist/src/db/chunks.js +129 -0
  57. package/dist/src/db/chunks.js.map +1 -0
  58. package/dist/src/db/index.d.ts +19 -0
  59. package/dist/src/db/index.d.ts.map +1 -0
  60. package/dist/src/db/index.js +86 -0
  61. package/dist/src/db/index.js.map +1 -0
  62. package/dist/src/db/schema.d.ts +10 -0
  63. package/dist/src/db/schema.d.ts.map +1 -0
  64. package/dist/src/db/schema.js +80 -0
  65. package/dist/src/db/schema.js.map +1 -0
  66. package/dist/src/db/sources.d.ts +48 -0
  67. package/dist/src/db/sources.d.ts.map +1 -0
  68. package/dist/src/db/sources.js +110 -0
  69. package/dist/src/db/sources.js.map +1 -0
  70. package/dist/src/index.d.ts +8 -0
  71. package/dist/src/index.d.ts.map +1 -0
  72. package/dist/src/index.js +87 -0
  73. package/dist/src/index.js.map +1 -0
  74. package/dist/src/search/embeddings.d.ts +22 -0
  75. package/dist/src/search/embeddings.d.ts.map +1 -0
  76. package/dist/src/search/embeddings.js +122 -0
  77. package/dist/src/search/embeddings.js.map +1 -0
  78. package/dist/src/search/index.d.ts +21 -0
  79. package/dist/src/search/index.d.ts.map +1 -0
  80. package/dist/src/search/index.js +50 -0
  81. package/dist/src/search/index.js.map +1 -0
  82. package/dist/src/sync/chunker.d.ts +15 -0
  83. package/dist/src/sync/chunker.d.ts.map +1 -0
  84. package/dist/src/sync/chunker.js +117 -0
  85. package/dist/src/sync/chunker.js.map +1 -0
  86. package/dist/src/sync/index.d.ts +24 -0
  87. package/dist/src/sync/index.d.ts.map +1 -0
  88. package/dist/src/sync/index.js +180 -0
  89. package/dist/src/sync/index.js.map +1 -0
  90. package/dist/src/sync/parser.d.ts +9 -0
  91. package/dist/src/sync/parser.d.ts.map +1 -0
  92. package/dist/src/sync/parser.js +91 -0
  93. package/dist/src/sync/parser.js.map +1 -0
  94. package/dist/src/sync/zendesk.d.ts +45 -0
  95. package/dist/src/sync/zendesk.d.ts.map +1 -0
  96. package/dist/src/sync/zendesk.js +161 -0
  97. package/dist/src/sync/zendesk.js.map +1 -0
  98. package/dist/src/utils/errors.d.ts +39 -0
  99. package/dist/src/utils/errors.d.ts.map +1 -0
  100. package/dist/src/utils/errors.js +62 -0
  101. package/dist/src/utils/errors.js.map +1 -0
  102. package/dist/src/utils/logger.d.ts +21 -0
  103. package/dist/src/utils/logger.d.ts.map +1 -0
  104. package/dist/src/utils/logger.js +25 -0
  105. package/dist/src/utils/logger.js.map +1 -0
  106. package/package.json +57 -0
@@ -0,0 +1,180 @@
1
+ import { fetchAllArticles, fetchSections, fetchCategories } from './zendesk.js';
2
+ import { parseHTMLStructured } from './parser.js';
3
+ import { chunkText } from './chunker.js';
4
+ import { generateEmbeddingsBatch } from '../search/embeddings.js';
5
+ import { upsertArticle, getStaleArticleIds, deleteArticle } from '../db/articles.js';
6
+ import { deleteChunksByArticle, insertChunksBatch } from '../db/chunks.js';
7
+ import { updateLastSynced } from '../db/sources.js';
8
+ /**
9
+ * Sync a single source
10
+ */
11
+ export async function syncSource(db, source, config, onProgress, fullResync = false) {
12
+ const startTime = Date.now();
13
+ // Phase 1: Fetch articles
14
+ onProgress?.({
15
+ phase: 'fetching',
16
+ current: 0,
17
+ total: 0,
18
+ message: `Fetching articles from ${source.name}...`,
19
+ });
20
+ const articles = await fetchAllArticles(source, (fetched) => {
21
+ onProgress?.({
22
+ phase: 'fetching',
23
+ current: fetched,
24
+ total: fetched,
25
+ message: `Fetched ${fetched} articles from ${source.name}...`,
26
+ });
27
+ });
28
+ // Fetch sections and categories for metadata
29
+ const [sections, categories] = await Promise.all([
30
+ fetchSections(source),
31
+ fetchCategories(source),
32
+ ]);
33
+ // Phase 2: Determine which articles need processing
34
+ const articleSummaries = articles.map(a => ({ id: a.id, updated_at: a.updated_at }));
35
+ const staleIds = fullResync
36
+ ? new Set(articles.map(a => a.id))
37
+ : getStaleArticleIds(db, source.id, articleSummaries);
38
+ const articlesToProcess = articles.filter(a => staleIds.has(a.id));
39
+ if (articlesToProcess.length === 0) {
40
+ onProgress?.({
41
+ phase: 'storing',
42
+ current: articles.length,
43
+ total: articles.length,
44
+ message: 'All articles are up to date.',
45
+ });
46
+ return {
47
+ source: source.name,
48
+ articlesProcessed: 0,
49
+ articlesFetched: articles.length,
50
+ chunksCreated: 0,
51
+ timeElapsed: Date.now() - startTime,
52
+ };
53
+ }
54
+ // Phase 3: Parse, chunk, and prepare for embedding
55
+ onProgress?.({
56
+ phase: 'parsing',
57
+ current: 0,
58
+ total: articlesToProcess.length,
59
+ message: `Processing ${articlesToProcess.length} articles...`,
60
+ });
61
+ const allArticleChunks = [];
62
+ for (let i = 0; i < articlesToProcess.length; i++) {
63
+ const article = articlesToProcess[i];
64
+ // Parse HTML
65
+ const cleanText = parseHTMLStructured(article.body);
66
+ // Chunk text
67
+ const chunks = chunkText(cleanText, article.title, config.sync.chunkSize, config.sync.chunkOverlap);
68
+ allArticleChunks.push({
69
+ articleId: article.id,
70
+ title: article.title,
71
+ url: article.html_url,
72
+ sectionName: sections.get(article.section_id),
73
+ categoryName: categories.get(article.section_id),
74
+ updatedAt: new Date(article.updated_at),
75
+ chunks,
76
+ });
77
+ onProgress?.({
78
+ phase: 'parsing',
79
+ current: i + 1,
80
+ total: articlesToProcess.length,
81
+ message: `Parsed ${i + 1}/${articlesToProcess.length} articles...`,
82
+ });
83
+ }
84
+ // Phase 4: Generate embeddings
85
+ const allChunkTexts = allArticleChunks.flatMap(ac => ac.chunks.map(c => c.text));
86
+ const totalChunks = allChunkTexts.length;
87
+ onProgress?.({
88
+ phase: 'embedding',
89
+ current: 0,
90
+ total: totalChunks,
91
+ message: `Generating embeddings for ${totalChunks} chunks...`,
92
+ });
93
+ const embeddings = await generateEmbeddingsBatch(allChunkTexts, config.ollama, 5, (completed, total) => {
94
+ onProgress?.({
95
+ phase: 'embedding',
96
+ current: completed,
97
+ total,
98
+ message: `Generated ${completed}/${total} embeddings...`,
99
+ });
100
+ });
101
+ // Phase 5: Store in database
102
+ onProgress?.({
103
+ phase: 'storing',
104
+ current: 0,
105
+ total: articlesToProcess.length,
106
+ message: 'Storing articles and chunks...',
107
+ });
108
+ // Use a transaction for all database operations
109
+ const storeTransaction = db.transaction(() => {
110
+ let embeddingIndex = 0;
111
+ for (let i = 0; i < allArticleChunks.length; i++) {
112
+ const articleChunks = allArticleChunks[i];
113
+ // Delete old chunks for this article
114
+ deleteChunksByArticle(db, articleChunks.articleId, source.id);
115
+ // Upsert article
116
+ upsertArticle(db, {
117
+ id: articleChunks.articleId,
118
+ sourceId: source.id,
119
+ title: articleChunks.title,
120
+ url: articleChunks.url,
121
+ sectionName: articleChunks.sectionName,
122
+ categoryName: articleChunks.categoryName,
123
+ updatedAt: articleChunks.updatedAt,
124
+ });
125
+ // Prepare chunks with embeddings
126
+ const chunksWithEmbeddings = articleChunks.chunks.map(chunk => ({
127
+ articleId: articleChunks.articleId,
128
+ sourceId: source.id,
129
+ chunkIndex: chunk.index,
130
+ text: chunk.text,
131
+ tokenCount: chunk.tokenCount,
132
+ embedding: embeddings[embeddingIndex++],
133
+ }));
134
+ // Insert chunks
135
+ insertChunksBatch(db, chunksWithEmbeddings);
136
+ onProgress?.({
137
+ phase: 'storing',
138
+ current: i + 1,
139
+ total: articlesToProcess.length,
140
+ message: `Stored ${i + 1}/${articlesToProcess.length} articles...`,
141
+ });
142
+ }
143
+ // Delete articles that no longer exist in Zendesk
144
+ const validArticleIds = articles.map(a => a.id);
145
+ const currentArticleIds = db
146
+ .prepare('SELECT id FROM articles WHERE source_id = ?')
147
+ .all(source.id);
148
+ for (const { id } of currentArticleIds) {
149
+ if (!validArticleIds.includes(id)) {
150
+ deleteArticle(db, id, source.id);
151
+ }
152
+ }
153
+ // Update last synced timestamp
154
+ updateLastSynced(db, source.id);
155
+ });
156
+ storeTransaction();
157
+ const timeElapsed = Date.now() - startTime;
158
+ return {
159
+ source: source.name,
160
+ articlesProcessed: articlesToProcess.length,
161
+ articlesFetched: articles.length,
162
+ chunksCreated: totalChunks,
163
+ timeElapsed,
164
+ };
165
+ }
166
+ /**
167
+ * Sync all enabled sources
168
+ */
169
+ export async function syncAllSources(db, sources, config, onProgress, fullResync = false) {
170
+ const results = [];
171
+ for (const source of sources) {
172
+ if (!source.enabled) {
173
+ continue;
174
+ }
175
+ const result = await syncSource(db, source, config, (progress) => onProgress?.(source.name, progress), fullResync);
176
+ results.push(result);
177
+ }
178
+ return results;
179
+ }
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Strip HTML and extract clean text from article body
3
+ */
4
+ export declare function parseHTML(html: string): string;
5
+ /**
6
+ * Parse HTML with better handling of lists and structure
7
+ */
8
+ export declare function parseHTMLStructured(html: string): string;
9
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/sync/parser.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB9C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA2ExD"}
@@ -0,0 +1,91 @@
1
+ import * as cheerio from 'cheerio';
2
+ /**
3
+ * Strip HTML and extract clean text from article body
4
+ */
5
+ export function parseHTML(html) {
6
+ // Handle cases where html is not a string (null, undefined, etc.)
7
+ if (!html || typeof html !== 'string') {
8
+ return '';
9
+ }
10
+ const $ = cheerio.load(html);
11
+ // Remove script and style tags
12
+ $('script, style').remove();
13
+ // Get text content
14
+ let text = $.text();
15
+ // Clean up whitespace
16
+ text = text
17
+ .replace(/\s+/g, ' ') // Replace multiple spaces with single space
18
+ .replace(/\n\s*\n/g, '\n\n') // Replace multiple newlines with double newline
19
+ .trim();
20
+ return text;
21
+ }
22
+ /**
23
+ * Parse HTML with better handling of lists and structure
24
+ */
25
+ export function parseHTMLStructured(html) {
26
+ // Handle cases where html is not a string (null, undefined, etc.)
27
+ if (!html || typeof html !== 'string') {
28
+ return '';
29
+ }
30
+ const $ = cheerio.load(html);
31
+ // Remove unwanted elements
32
+ $('script, style, noscript, iframe').remove();
33
+ // Process the DOM to extract structured text
34
+ function extractText(element) {
35
+ const $el = $(element);
36
+ const tagName = element.tagName?.toLowerCase();
37
+ // Handle different elements
38
+ if (tagName === 'ul' || tagName === 'ol') {
39
+ const items = $el.find('> li')
40
+ .map((_, li) => {
41
+ const text = extractText(li).trim();
42
+ return text ? `• ${text}` : '';
43
+ })
44
+ .get()
45
+ .filter(Boolean);
46
+ return items.length > 0 ? items.join('\n') + '\n' : '';
47
+ }
48
+ if (tagName === 'li') {
49
+ // Get direct text content and nested lists
50
+ let text = '';
51
+ $el.contents().each((_, node) => {
52
+ if (node.type === 'text') {
53
+ text += $(node).text();
54
+ }
55
+ else if (node.type === 'tag') {
56
+ text += extractText(node);
57
+ }
58
+ });
59
+ return text.trim();
60
+ }
61
+ if (tagName === 'p' || tagName === 'div' || tagName === 'section') {
62
+ let text = '';
63
+ $el.contents().each((_, node) => {
64
+ if (node.type === 'text') {
65
+ text += $(node).text();
66
+ }
67
+ else if (node.type === 'tag') {
68
+ text += extractText(node);
69
+ }
70
+ });
71
+ const trimmed = text.trim();
72
+ return trimmed ? trimmed + '\n\n' : '';
73
+ }
74
+ if (tagName === 'br') {
75
+ return '\n';
76
+ }
77
+ if (tagName === 'table') {
78
+ // Simple table handling - extract all text
79
+ return $el.text().trim() + '\n\n';
80
+ }
81
+ // Default: get all text content
82
+ return $el.text();
83
+ }
84
+ const text = extractText($('body')[0] || $.root()[0]);
85
+ // Clean up whitespace
86
+ return text
87
+ .replace(/\n{3,}/g, '\n\n') // Max 2 consecutive newlines
88
+ .replace(/ +/g, ' ') // Replace multiple spaces with single space
89
+ .trim();
90
+ }
91
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/sync/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { Source } from '../config/schema.js';
2
+ export interface ZendeskArticle {
3
+ id: number;
4
+ title: string;
5
+ body: string;
6
+ section_id: number;
7
+ updated_at: string;
8
+ html_url: string;
9
+ draft: boolean;
10
+ promoted: boolean;
11
+ }
12
+ export interface ZendeskArticlesResponse {
13
+ articles: ZendeskArticle[];
14
+ next_page: string | null;
15
+ count: number;
16
+ page: number;
17
+ per_page: number;
18
+ page_count: number;
19
+ }
20
+ export interface ZendeskSection {
21
+ id: number;
22
+ name: string;
23
+ category_id: number;
24
+ }
25
+ export interface ZendeskCategory {
26
+ id: number;
27
+ name: string;
28
+ }
29
+ /**
30
+ * Fetch all articles from a Zendesk Help Center
31
+ */
32
+ export declare function fetchAllArticles(source: Source, onProgress?: (fetched: number) => void): Promise<ZendeskArticle[]>;
33
+ /**
34
+ * Fetch sections from a Zendesk Help Center
35
+ */
36
+ export declare function fetchSections(source: Source): Promise<Map<number, string>>;
37
+ /**
38
+ * Fetch categories from a Zendesk Help Center
39
+ */
40
+ export declare function fetchCategories(source: Source): Promise<Map<number, string>>;
41
+ /**
42
+ * Test connection to a Zendesk Help Center
43
+ */
44
+ export declare function testConnection(source: Source): Promise<boolean>;
45
+ //# sourceMappingURL=zendesk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zendesk.d.ts","sourceRoot":"","sources":["../../../src/sync/zendesk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AA4ED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,cAAc,EAAE,CAAC,CA0C3B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA+BhF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA+BlF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQrE"}
@@ -0,0 +1,161 @@
1
+ const DEFAULT_RETRY_OPTIONS = {
2
+ maxRetries: 5,
3
+ initialDelay: 1000,
4
+ maxDelay: 60000,
5
+ };
6
+ /**
7
+ * Sleep for a specified number of milliseconds
8
+ */
9
+ function sleep(ms) {
10
+ return new Promise(resolve => setTimeout(resolve, ms));
11
+ }
12
+ /**
13
+ * Fetch with retry logic and exponential backoff
14
+ */
15
+ async function fetchWithRetry(url, options = DEFAULT_RETRY_OPTIONS) {
16
+ let lastError = null;
17
+ let delay = options.initialDelay;
18
+ for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
19
+ try {
20
+ const response = await fetch(url);
21
+ // Handle rate limiting (429)
22
+ if (response.status === 429) {
23
+ const retryAfter = response.headers.get('Retry-After');
24
+ const waitTime = retryAfter
25
+ ? parseInt(retryAfter, 10) * 1000
26
+ : Math.min(delay * Math.pow(2, attempt), options.maxDelay);
27
+ if (attempt < options.maxRetries) {
28
+ console.error(`⚠ Rate limited by Zendesk, waiting ${Math.round(waitTime / 1000)}s... (retry ${attempt + 1}/${options.maxRetries})`);
29
+ await sleep(waitTime);
30
+ continue;
31
+ }
32
+ throw new Error('Rate limit exceeded. Please try again later.');
33
+ }
34
+ // Success or non-retryable error
35
+ if (response.ok || response.status < 500) {
36
+ return response;
37
+ }
38
+ // Server error (5xx) - retry
39
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
40
+ }
41
+ catch (error) {
42
+ lastError = error;
43
+ // Don't retry on network errors if we've exhausted retries
44
+ if (attempt >= options.maxRetries) {
45
+ break;
46
+ }
47
+ // Wait before retrying
48
+ const waitTime = Math.min(delay * Math.pow(2, attempt), options.maxDelay);
49
+ console.error(`⚠ Request failed, retrying in ${Math.round(waitTime / 1000)}s... (attempt ${attempt + 1}/${options.maxRetries})`);
50
+ await sleep(waitTime);
51
+ }
52
+ }
53
+ throw lastError || new Error('Request failed after retries');
54
+ }
55
+ /**
56
+ * Fetch all articles from a Zendesk Help Center
57
+ */
58
+ export async function fetchAllArticles(source, onProgress) {
59
+ const articles = [];
60
+ let nextPage = `${source.baseUrl}/api/v2/help_center/${source.locale}/articles.json?per_page=100`;
61
+ while (nextPage) {
62
+ try {
63
+ const response = await fetchWithRetry(nextPage);
64
+ if (!response.ok) {
65
+ throw new Error(`Failed to fetch articles from ${source.baseUrl}: HTTP ${response.status}\n\n` +
66
+ `Make sure the URL is correct and the Help Center is publicly accessible.`);
67
+ }
68
+ const data = (await response.json());
69
+ // Filter out drafts
70
+ const publishedArticles = data.articles.filter(a => !a.draft);
71
+ articles.push(...publishedArticles);
72
+ if (onProgress) {
73
+ onProgress(articles.length);
74
+ }
75
+ nextPage = data.next_page;
76
+ // Small delay between pages to be nice to Zendesk
77
+ if (nextPage) {
78
+ await sleep(100);
79
+ }
80
+ }
81
+ catch (error) {
82
+ if (error instanceof Error) {
83
+ throw new Error(`Failed to fetch articles from ${source.name}:\n${error.message}`);
84
+ }
85
+ throw error;
86
+ }
87
+ }
88
+ return articles;
89
+ }
90
+ /**
91
+ * Fetch sections from a Zendesk Help Center
92
+ */
93
+ export async function fetchSections(source) {
94
+ const sectionMap = new Map();
95
+ let nextPage = `${source.baseUrl}/api/v2/help_center/${source.locale}/sections.json?per_page=100`;
96
+ while (nextPage) {
97
+ try {
98
+ const response = await fetchWithRetry(nextPage);
99
+ if (!response.ok) {
100
+ // Sections are optional, just return empty map
101
+ return sectionMap;
102
+ }
103
+ const data = (await response.json());
104
+ for (const section of data.sections) {
105
+ sectionMap.set(section.id, section.name);
106
+ }
107
+ nextPage = data.next_page;
108
+ if (nextPage) {
109
+ await sleep(100);
110
+ }
111
+ }
112
+ catch (error) {
113
+ // Sections are optional, just return what we have
114
+ return sectionMap;
115
+ }
116
+ }
117
+ return sectionMap;
118
+ }
119
+ /**
120
+ * Fetch categories from a Zendesk Help Center
121
+ */
122
+ export async function fetchCategories(source) {
123
+ const categoryMap = new Map();
124
+ let nextPage = `${source.baseUrl}/api/v2/help_center/${source.locale}/categories.json?per_page=100`;
125
+ while (nextPage) {
126
+ try {
127
+ const response = await fetchWithRetry(nextPage);
128
+ if (!response.ok) {
129
+ // Categories are optional, just return empty map
130
+ return categoryMap;
131
+ }
132
+ const data = (await response.json());
133
+ for (const category of data.categories) {
134
+ categoryMap.set(category.id, category.name);
135
+ }
136
+ nextPage = data.next_page;
137
+ if (nextPage) {
138
+ await sleep(100);
139
+ }
140
+ }
141
+ catch (error) {
142
+ // Categories are optional, just return what we have
143
+ return categoryMap;
144
+ }
145
+ }
146
+ return categoryMap;
147
+ }
148
+ /**
149
+ * Test connection to a Zendesk Help Center
150
+ */
151
+ export async function testConnection(source) {
152
+ try {
153
+ const url = `${source.baseUrl}/api/v2/help_center/${source.locale}/articles.json?per_page=1`;
154
+ const response = await fetch(url);
155
+ return response.ok;
156
+ }
157
+ catch (error) {
158
+ return false;
159
+ }
160
+ }
161
+ //# sourceMappingURL=zendesk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zendesk.js","sourceRoot":"","sources":["../../../src/sync/zendesk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Base error class for kb-mcp
3
+ */
4
+ export declare class KBMCPError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /**
8
+ * Configuration error
9
+ */
10
+ export declare class ConfigError extends KBMCPError {
11
+ constructor(message: string);
12
+ }
13
+ /**
14
+ * Database error
15
+ */
16
+ export declare class DatabaseError extends KBMCPError {
17
+ constructor(message: string);
18
+ }
19
+ /**
20
+ * Ollama error
21
+ */
22
+ export declare class OllamaError extends KBMCPError {
23
+ constructor(message: string);
24
+ }
25
+ /**
26
+ * Zendesk error
27
+ */
28
+ export declare class ZendeskError extends KBMCPError {
29
+ constructor(message: string);
30
+ }
31
+ /**
32
+ * Format an error for display to the user
33
+ */
34
+ export declare function formatError(error: unknown): string;
35
+ /**
36
+ * Exit with an error message
37
+ */
38
+ export declare function exitWithError(error: unknown): never;
39
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,UAAU;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,UAAU;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,UAAU;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAGnD"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Base error class for kb-mcp
3
+ */
4
+ export class KBMCPError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'KBMCPError';
8
+ }
9
+ }
10
+ /**
11
+ * Configuration error
12
+ */
13
+ export class ConfigError extends KBMCPError {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = 'ConfigError';
17
+ }
18
+ }
19
+ /**
20
+ * Database error
21
+ */
22
+ export class DatabaseError extends KBMCPError {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = 'DatabaseError';
26
+ }
27
+ }
28
+ /**
29
+ * Ollama error
30
+ */
31
+ export class OllamaError extends KBMCPError {
32
+ constructor(message) {
33
+ super(message);
34
+ this.name = 'OllamaError';
35
+ }
36
+ }
37
+ /**
38
+ * Zendesk error
39
+ */
40
+ export class ZendeskError extends KBMCPError {
41
+ constructor(message) {
42
+ super(message);
43
+ this.name = 'ZendeskError';
44
+ }
45
+ }
46
+ /**
47
+ * Format an error for display to the user
48
+ */
49
+ export function formatError(error) {
50
+ if (error instanceof Error) {
51
+ return error.message;
52
+ }
53
+ return String(error);
54
+ }
55
+ /**
56
+ * Exit with an error message
57
+ */
58
+ export function exitWithError(error) {
59
+ console.error(`\n✗ Error: ${formatError(error)}\n`);
60
+ process.exit(1);
61
+ }
62
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,UAAU;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,UAAU;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,CAAC,KAAK,CAAC,cAAc,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import debug from 'debug';
2
+ /**
3
+ * Create namespaced loggers using the debug package
4
+ */
5
+ export declare const loggers: {
6
+ sync: debug.Debugger;
7
+ embed: debug.Debugger;
8
+ search: debug.Debugger;
9
+ mcp: debug.Debugger;
10
+ db: debug.Debugger;
11
+ cli: debug.Debugger;
12
+ };
13
+ /**
14
+ * Enable all kb-mcp loggers
15
+ */
16
+ export declare function enableAllLoggers(): void;
17
+ /**
18
+ * Check if debug logging is enabled
19
+ */
20
+ export declare function isDebugEnabled(): boolean;
21
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;CAOnB,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,SAE/B;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC"}