@chanaka_nakandala/integration-agent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/cache/file-cache.d.ts +10 -0
- package/dist/cache/file-cache.d.ts.map +1 -0
- package/dist/cache/file-cache.js +79 -0
- package/dist/cache/file-cache.js.map +1 -0
- package/dist/cli/init-command.d.ts +2 -0
- package/dist/cli/init-command.d.ts.map +1 -0
- package/dist/cli/init-command.js +115 -0
- package/dist/cli/init-command.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +493 -0
- package/dist/index.js.map +1 -0
- package/dist/scrapers/docs-scraper.d.ts +28 -0
- package/dist/scrapers/docs-scraper.d.ts.map +1 -0
- package/dist/scrapers/docs-scraper.js +200 -0
- package/dist/scrapers/docs-scraper.js.map +1 -0
- package/dist/search/keyword-search.d.ts +39 -0
- package/dist/search/keyword-search.d.ts.map +1 -0
- package/dist/search/keyword-search.js +127 -0
- package/dist/search/keyword-search.js.map +1 -0
- package/dist/tools/code-generation-tool.d.ts +33 -0
- package/dist/tools/code-generation-tool.d.ts.map +1 -0
- package/dist/tools/code-generation-tool.js +62 -0
- package/dist/tools/code-generation-tool.js.map +1 -0
- package/dist/tools/search-result-formatter.d.ts +27 -0
- package/dist/tools/search-result-formatter.d.ts.map +1 -0
- package/dist/tools/search-result-formatter.js +89 -0
- package/dist/tools/search-result-formatter.js.map +1 -0
- package/dist/tools/search-tool.d.ts +9 -0
- package/dist/tools/search-tool.d.ts.map +1 -0
- package/dist/tools/search-tool.js +32 -0
- package/dist/tools/search-tool.js.map +1 -0
- package/dist/tools/template-loader.d.ts +54 -0
- package/dist/tools/template-loader.d.ts.map +1 -0
- package/dist/tools/template-loader.js +148 -0
- package/dist/tools/template-loader.js.map +1 -0
- package/dist/types/search.d.ts +21 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/search.js +2 -0
- package/dist/types/search.js.map +1 -0
- package/package.json +63 -0
- package/templates/README.md +98 -0
- package/templates/authenticate/curl.template +97 -0
- package/templates/authenticate/java.template +155 -0
- package/templates/authenticate/python.template +111 -0
- package/templates/authenticate/typescript.template +98 -0
- package/templates/create_menu/curl.template +145 -0
- package/templates/create_menu/java.template +285 -0
- package/templates/create_menu/python.template +159 -0
- package/templates/create_menu/typescript.template +184 -0
- package/templates/receive_order/curl.template +138 -0
- package/templates/receive_order/java.template +263 -0
- package/templates/receive_order/python.template +157 -0
- package/templates/receive_order/typescript.template +194 -0
- package/templates/update_item_availability/curl.template +143 -0
- package/templates/update_item_availability/java.template +279 -0
- package/templates/update_item_availability/python.template +203 -0
- package/templates/update_item_availability/typescript.template +194 -0
- package/templates/update_order_status/curl.template +138 -0
- package/templates/update_order_status/java.template +202 -0
- package/templates/update_order_status/python.template +142 -0
- package/templates/update_order_status/typescript.template +139 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
import axios from 'axios';
|
2
|
+
import * as cheerio from 'cheerio';
|
3
|
+
import crypto from 'crypto';
|
4
|
+
export class DocsScraper {
|
5
|
+
axios;
|
6
|
+
cache;
|
7
|
+
visited = new Set();
|
8
|
+
lastRequestTime = 0;
|
9
|
+
RATE_LIMIT_MS = 500; // 0.5 seconds (faster scraping)
|
10
|
+
BASE_URL = 'https://docs.grubtech.io';
|
11
|
+
START_URL = 'https://docs.grubtech.io/docs/getting-started';
|
12
|
+
constructor(cache) {
|
13
|
+
this.cache = cache;
|
14
|
+
this.axios = axios.create({
|
15
|
+
baseURL: this.BASE_URL,
|
16
|
+
timeout: 10000,
|
17
|
+
headers: {
|
18
|
+
'User-Agent': 'GrubtechIntegrationAgent/1.0',
|
19
|
+
},
|
20
|
+
maxRedirects: 5,
|
21
|
+
});
|
22
|
+
}
|
23
|
+
async rateLimit() {
|
24
|
+
const now = Date.now();
|
25
|
+
const timeSinceLastRequest = now - this.lastRequestTime;
|
26
|
+
if (timeSinceLastRequest < this.RATE_LIMIT_MS) {
|
27
|
+
await new Promise(resolve => setTimeout(resolve, this.RATE_LIMIT_MS - timeSinceLastRequest));
|
28
|
+
}
|
29
|
+
this.lastRequestTime = Date.now();
|
30
|
+
}
|
31
|
+
urlToKey(url) {
|
32
|
+
// Create hash of URL for cache key
|
33
|
+
return crypto.createHash('md5').update(url).digest('hex');
|
34
|
+
}
|
35
|
+
shouldFollowLink(url) {
|
36
|
+
// Only follow documentation pages
|
37
|
+
if (!url.includes('/docs/'))
|
38
|
+
return false;
|
39
|
+
// Exclude anchor links (they're duplicates of main page)
|
40
|
+
if (url.includes('#'))
|
41
|
+
return false;
|
42
|
+
// Exclude non-documentation sections
|
43
|
+
if (url.includes('/reference'))
|
44
|
+
return false;
|
45
|
+
if (url.includes('/changelog'))
|
46
|
+
return false;
|
47
|
+
if (url.includes('/discuss'))
|
48
|
+
return false;
|
49
|
+
if (url.includes('/login'))
|
50
|
+
return false;
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
/**
|
54
|
+
* Extract all navigation links from the sidebar
|
55
|
+
*/
|
56
|
+
async getAllDocumentationLinks() {
|
57
|
+
console.error('Extracting all documentation links from navigation...');
|
58
|
+
try {
|
59
|
+
const response = await this.axios.get(this.START_URL);
|
60
|
+
const $ = cheerio.load(response.data);
|
61
|
+
// Extract all sidebar navigation links
|
62
|
+
const links = new Set();
|
63
|
+
$('nav a[href*="/docs/"]').each((_, element) => {
|
64
|
+
const href = $(element).attr('href');
|
65
|
+
if (!href)
|
66
|
+
return;
|
67
|
+
try {
|
68
|
+
const absoluteUrl = new URL(href, this.BASE_URL).toString();
|
69
|
+
if (this.shouldFollowLink(absoluteUrl)) {
|
70
|
+
links.add(absoluteUrl);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
catch {
|
74
|
+
// Invalid URL, skip
|
75
|
+
}
|
76
|
+
});
|
77
|
+
const linkArray = Array.from(links);
|
78
|
+
console.error(`Found ${linkArray.length} unique documentation pages`);
|
79
|
+
return linkArray;
|
80
|
+
}
|
81
|
+
catch (error) {
|
82
|
+
console.error('Failed to extract navigation links:', error);
|
83
|
+
// Fallback to starting URL
|
84
|
+
return [this.START_URL];
|
85
|
+
}
|
86
|
+
}
|
87
|
+
/**
|
88
|
+
* Scrape a single page and extract content chunks
|
89
|
+
*/
|
90
|
+
async scrapePage(url) {
|
91
|
+
// Check if already visited
|
92
|
+
if (this.visited.has(url)) {
|
93
|
+
return [];
|
94
|
+
}
|
95
|
+
this.visited.add(url);
|
96
|
+
// Check cache first
|
97
|
+
const cacheKey = this.urlToKey(url);
|
98
|
+
const cached = await this.cache.get(cacheKey);
|
99
|
+
if (cached) {
|
100
|
+
console.error(`Cache hit for: ${url}`);
|
101
|
+
return cached.chunks;
|
102
|
+
}
|
103
|
+
// Rate limit
|
104
|
+
await this.rateLimit();
|
105
|
+
try {
|
106
|
+
console.error(`Scraping: ${url}`);
|
107
|
+
// Fetch page
|
108
|
+
const response = await this.axios.get(url);
|
109
|
+
const $ = cheerio.load(response.data);
|
110
|
+
// Extract page title
|
111
|
+
const title = $('h1').first().text() || $('title').first().text() || 'Untitled';
|
112
|
+
// Extract content chunks
|
113
|
+
const chunks = [];
|
114
|
+
// Extract main content sections
|
115
|
+
$('article, main, .content, #content').find('h2, h3, h4, p, pre, ul, ol').each((index, element) => {
|
116
|
+
const $el = $(element);
|
117
|
+
const tagName = element.name;
|
118
|
+
if (tagName.startsWith('h')) {
|
119
|
+
// Heading
|
120
|
+
const heading = $el.text().trim();
|
121
|
+
if (heading) {
|
122
|
+
chunks.push({
|
123
|
+
chunkId: `${cacheKey}-${index}`,
|
124
|
+
sourceUrl: url,
|
125
|
+
title: heading,
|
126
|
+
content: heading,
|
127
|
+
metadata: {
|
128
|
+
tags: ['heading', tagName],
|
129
|
+
},
|
130
|
+
});
|
131
|
+
}
|
132
|
+
}
|
133
|
+
else if (tagName === 'pre') {
|
134
|
+
// Code block
|
135
|
+
const code = $el.find('code').text() || $el.text();
|
136
|
+
const language = $el.find('code').attr('class')?.replace('language-', '') || 'plaintext';
|
137
|
+
chunks.push({
|
138
|
+
chunkId: `${cacheKey}-${index}`,
|
139
|
+
sourceUrl: url,
|
140
|
+
title: 'Code Example',
|
141
|
+
content: `\`\`\`${language}\n${code}\n\`\`\``,
|
142
|
+
metadata: {
|
143
|
+
tags: ['code', language],
|
144
|
+
},
|
145
|
+
});
|
146
|
+
}
|
147
|
+
else {
|
148
|
+
// Paragraph or list
|
149
|
+
const text = $el.text().trim();
|
150
|
+
if (text.length > 20) { // Only meaningful content
|
151
|
+
chunks.push({
|
152
|
+
chunkId: `${cacheKey}-${index}`,
|
153
|
+
sourceUrl: url,
|
154
|
+
title,
|
155
|
+
content: text,
|
156
|
+
metadata: {
|
157
|
+
tags: [tagName],
|
158
|
+
},
|
159
|
+
});
|
160
|
+
}
|
161
|
+
}
|
162
|
+
});
|
163
|
+
// Cache the result
|
164
|
+
await this.cache.set(cacheKey, {
|
165
|
+
url,
|
166
|
+
html: response.data,
|
167
|
+
chunks,
|
168
|
+
});
|
169
|
+
console.error(`Scraped ${chunks.length} chunks from: ${url}`);
|
170
|
+
return chunks;
|
171
|
+
}
|
172
|
+
catch (error) {
|
173
|
+
console.error(`Failed to scrape ${url}:`, error);
|
174
|
+
return [];
|
175
|
+
}
|
176
|
+
}
|
177
|
+
/**
|
178
|
+
* Main scraping method - extracts all documentation links and scrapes each page
|
179
|
+
*/
|
180
|
+
async scrapeDocumentation() {
|
181
|
+
const startTime = Date.now();
|
182
|
+
console.error('Starting comprehensive documentation scrape...');
|
183
|
+
// Step 1: Get all documentation links from navigation
|
184
|
+
const allLinks = await this.getAllDocumentationLinks();
|
185
|
+
console.error(`Will scrape ${allLinks.length} documentation pages`);
|
186
|
+
// Step 2: Scrape each page
|
187
|
+
const allChunks = [];
|
188
|
+
for (const url of allLinks) {
|
189
|
+
const chunks = await this.scrapePage(url);
|
190
|
+
allChunks.push(...chunks);
|
191
|
+
}
|
192
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
|
193
|
+
console.error(`Scraping complete!`);
|
194
|
+
console.error(` Pages visited: ${this.visited.size}`);
|
195
|
+
console.error(` Total chunks: ${allChunks.length}`);
|
196
|
+
console.error(` Duration: ${duration}s`);
|
197
|
+
return allChunks;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
//# sourceMappingURL=docs-scraper.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"docs-scraper.js","sourceRoot":"","sources":["../../src/scrapers/docs-scraper.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { DocumentChunk } from '@grubtech/agent-core';
|
2
|
+
export interface SearchOptions {
|
3
|
+
partialMatch?: boolean;
|
4
|
+
maxResults?: number;
|
5
|
+
}
|
6
|
+
export interface ScoredChunk extends DocumentChunk {
|
7
|
+
relevanceScore: number;
|
8
|
+
matchedKeywords: string[];
|
9
|
+
}
|
10
|
+
export declare class KeywordSearch {
|
11
|
+
private options;
|
12
|
+
private defaultOptions;
|
13
|
+
constructor(options?: SearchOptions);
|
14
|
+
/**
|
15
|
+
* Search document chunks using keyword matching algorithm
|
16
|
+
*/
|
17
|
+
search(query: string, chunks: DocumentChunk[], limit?: number): ScoredChunk[];
|
18
|
+
/**
|
19
|
+
* Tokenize query into lowercase keywords
|
20
|
+
*/
|
21
|
+
private tokenize;
|
22
|
+
/**
|
23
|
+
* Score a single document chunk against keywords
|
24
|
+
*/
|
25
|
+
private scoreChunk;
|
26
|
+
/**
|
27
|
+
* Check if text matches keyword (exact or partial)
|
28
|
+
*/
|
29
|
+
private matchesKeyword;
|
30
|
+
/**
|
31
|
+
* Count keyword occurrences in text
|
32
|
+
*/
|
33
|
+
private countOccurrences;
|
34
|
+
/**
|
35
|
+
* Escape special regex characters
|
36
|
+
*/
|
37
|
+
private escapeRegex;
|
38
|
+
}
|
39
|
+
//# sourceMappingURL=keyword-search.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"keyword-search.d.ts","sourceRoot":"","sources":["../../src/search/keyword-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,qBAAa,aAAa;IAMZ,OAAO,CAAC,OAAO;IAL3B,OAAO,CAAC,cAAc,CAGpB;gBAEkB,OAAO,GAAE,aAAkB;IAI/C;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAwB7E;;OAEG;IACH,OAAO,CAAC,QAAQ;IAOhB;;OAEG;IACH,OAAO,CAAC,UAAU;IAoDlB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,WAAW;CAGpB"}
|
@@ -0,0 +1,127 @@
|
|
1
|
+
export class KeywordSearch {
|
2
|
+
options;
|
3
|
+
defaultOptions = {
|
4
|
+
partialMatch: false,
|
5
|
+
maxResults: 5,
|
6
|
+
};
|
7
|
+
constructor(options = {}) {
|
8
|
+
this.options = options;
|
9
|
+
this.options = { ...this.defaultOptions, ...options };
|
10
|
+
}
|
11
|
+
/**
|
12
|
+
* Search document chunks using keyword matching algorithm
|
13
|
+
*/
|
14
|
+
search(query, chunks, limit) {
|
15
|
+
const startTime = Date.now();
|
16
|
+
// Tokenize query
|
17
|
+
const keywords = this.tokenize(query);
|
18
|
+
// Score all chunks
|
19
|
+
const scoredChunks = chunks.map(chunk => ({
|
20
|
+
...chunk,
|
21
|
+
...this.scoreChunk(chunk, keywords),
|
22
|
+
}));
|
23
|
+
// Filter, sort, and limit results
|
24
|
+
const results = scoredChunks
|
25
|
+
.filter(chunk => chunk.relevanceScore > 0)
|
26
|
+
.sort((a, b) => b.relevanceScore - a.relevanceScore)
|
27
|
+
.slice(0, limit || this.options.maxResults);
|
28
|
+
const duration = Date.now() - startTime;
|
29
|
+
console.error(`Keyword search completed in ${duration}ms (${results.length} results)`);
|
30
|
+
return results;
|
31
|
+
}
|
32
|
+
/**
|
33
|
+
* Tokenize query into lowercase keywords
|
34
|
+
*/
|
35
|
+
tokenize(query) {
|
36
|
+
return query
|
37
|
+
.toLowerCase()
|
38
|
+
.split(/\s+/)
|
39
|
+
.filter(token => token.length > 0);
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* Score a single document chunk against keywords
|
43
|
+
*/
|
44
|
+
scoreChunk(chunk, keywords) {
|
45
|
+
let score = 0;
|
46
|
+
const matchedKeywords = new Set();
|
47
|
+
const content = chunk.content.toLowerCase();
|
48
|
+
const title = chunk.title?.toLowerCase() || '';
|
49
|
+
const headingTags = chunk.metadata?.tags?.filter(t => t.startsWith('h')) || [];
|
50
|
+
const headingContent = headingTags.length > 0 ? content : '';
|
51
|
+
for (const keyword of keywords) {
|
52
|
+
let keywordMatched = false;
|
53
|
+
// Title matching (+10 points)
|
54
|
+
if (this.matchesKeyword(title, keyword)) {
|
55
|
+
score += 10;
|
56
|
+
keywordMatched = true;
|
57
|
+
}
|
58
|
+
// Heading matching (+5 points)
|
59
|
+
if (headingTags.length > 0 && this.matchesKeyword(headingContent, keyword)) {
|
60
|
+
score += 5;
|
61
|
+
keywordMatched = true;
|
62
|
+
}
|
63
|
+
// Body text matching (+1 point per occurrence)
|
64
|
+
const occurrences = this.countOccurrences(content, keyword);
|
65
|
+
if (occurrences > 0) {
|
66
|
+
score += occurrences;
|
67
|
+
keywordMatched = true;
|
68
|
+
}
|
69
|
+
if (keywordMatched) {
|
70
|
+
matchedKeywords.add(keyword);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
// Bonus for all keywords present (+20 points)
|
74
|
+
if (matchedKeywords.size === keywords.length && keywords.length > 1) {
|
75
|
+
score += 20;
|
76
|
+
}
|
77
|
+
// Normalize score to 0-1 range
|
78
|
+
// Max theoretical score: 10*n + 5*n + 100*n + 20 = 135n + 20 (assuming max 100 body occurrences)
|
79
|
+
const maxScore = 135 * keywords.length + 20;
|
80
|
+
const relevanceScore = Math.min(score / maxScore, 1);
|
81
|
+
return {
|
82
|
+
relevanceScore,
|
83
|
+
matchedKeywords: Array.from(matchedKeywords),
|
84
|
+
};
|
85
|
+
}
|
86
|
+
/**
|
87
|
+
* Check if text matches keyword (exact or partial)
|
88
|
+
*/
|
89
|
+
matchesKeyword(text, keyword) {
|
90
|
+
if (this.options.partialMatch) {
|
91
|
+
return text.includes(keyword);
|
92
|
+
}
|
93
|
+
else {
|
94
|
+
// Exact word matching with word boundaries
|
95
|
+
const regex = new RegExp(`\\b${this.escapeRegex(keyword)}\\b`, 'i');
|
96
|
+
return regex.test(text);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
/**
|
100
|
+
* Count keyword occurrences in text
|
101
|
+
*/
|
102
|
+
countOccurrences(text, keyword) {
|
103
|
+
if (this.options.partialMatch) {
|
104
|
+
// Simple substring count
|
105
|
+
let count = 0;
|
106
|
+
let pos = 0;
|
107
|
+
while ((pos = text.indexOf(keyword, pos)) !== -1) {
|
108
|
+
count++;
|
109
|
+
pos += keyword.length;
|
110
|
+
}
|
111
|
+
return count;
|
112
|
+
}
|
113
|
+
else {
|
114
|
+
// Word boundary matching count
|
115
|
+
const regex = new RegExp(`\\b${this.escapeRegex(keyword)}\\b`, 'gi');
|
116
|
+
const matches = text.match(regex);
|
117
|
+
return matches ? matches.length : 0;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
/**
|
121
|
+
* Escape special regex characters
|
122
|
+
*/
|
123
|
+
escapeRegex(str) {
|
124
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
125
|
+
}
|
126
|
+
}
|
127
|
+
//# sourceMappingURL=keyword-search.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"keyword-search.js","sourceRoot":"","sources":["../../src/search/keyword-search.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
export type Operation = 'authenticate' | 'create_menu' | 'receive_order' | 'update_order_status' | 'update_item_availability';
|
2
|
+
export type Language = 'typescript' | 'python' | 'java' | 'curl';
|
3
|
+
export interface CodeGenerationResult {
|
4
|
+
code: string;
|
5
|
+
language: Language;
|
6
|
+
operation: Operation;
|
7
|
+
metadata: {
|
8
|
+
templatePath: string;
|
9
|
+
placeholders: string[];
|
10
|
+
generatedAt: string;
|
11
|
+
};
|
12
|
+
}
|
13
|
+
export interface CodeGenerationError {
|
14
|
+
error: string;
|
15
|
+
operation: Operation;
|
16
|
+
language: Language;
|
17
|
+
supportedCombinations: string[];
|
18
|
+
}
|
19
|
+
export declare class CodeGenerationTool {
|
20
|
+
private templateLoader;
|
21
|
+
constructor();
|
22
|
+
generate(operation: Operation, language: Language): Promise<CodeGenerationResult | CodeGenerationError>;
|
23
|
+
/**
|
24
|
+
* Extract placeholder variables from template
|
25
|
+
* Looks for {{PLACEHOLDER_NAME}} patterns
|
26
|
+
*/
|
27
|
+
private extractPlaceholders;
|
28
|
+
/**
|
29
|
+
* Get list of supported operation/language combinations
|
30
|
+
*/
|
31
|
+
private getSupportedCombinations;
|
32
|
+
}
|
33
|
+
//# sourceMappingURL=code-generation-tool.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"code-generation-tool.d.ts","sourceRoot":"","sources":["../../src/tools/code-generation-tool.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACjB,cAAc,GACd,aAAa,GACb,eAAe,GACf,qBAAqB,GACrB,0BAA0B,CAAC;AAE/B,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE;QACR,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,cAAc,CAAiB;;IAMjC,QAAQ,CACZ,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;IA2CtD;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;OAEG;YACW,wBAAwB;CAIvC"}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { TemplateLoader } from './template-loader.js';
|
2
|
+
export class CodeGenerationTool {
|
3
|
+
templateLoader;
|
4
|
+
constructor() {
|
5
|
+
this.templateLoader = new TemplateLoader();
|
6
|
+
}
|
7
|
+
async generate(operation, language) {
|
8
|
+
const startTime = Date.now();
|
9
|
+
try {
|
10
|
+
// Load template
|
11
|
+
const template = await this.templateLoader.loadTemplate(operation, language);
|
12
|
+
// Extract placeholders from template
|
13
|
+
const placeholders = this.extractPlaceholders(template);
|
14
|
+
const result = {
|
15
|
+
code: template,
|
16
|
+
language,
|
17
|
+
operation,
|
18
|
+
metadata: {
|
19
|
+
templatePath: `templates/${operation}/${language}.template`,
|
20
|
+
placeholders,
|
21
|
+
generatedAt: new Date().toISOString(),
|
22
|
+
},
|
23
|
+
};
|
24
|
+
const executionTime = Date.now() - startTime;
|
25
|
+
console.error(`Code generation: operation=${operation}, language=${language}, time=${executionTime}ms`);
|
26
|
+
return result;
|
27
|
+
}
|
28
|
+
catch (error) {
|
29
|
+
// Template not found or unsupported combination
|
30
|
+
const supportedCombinations = await this.getSupportedCombinations();
|
31
|
+
const errorResult = {
|
32
|
+
error: `Code generation not supported for ${operation} in ${language}. Supported: ${supportedCombinations.join(', ')}`,
|
33
|
+
operation,
|
34
|
+
language,
|
35
|
+
supportedCombinations,
|
36
|
+
};
|
37
|
+
console.error(`Code generation failed: ${errorResult.error}`);
|
38
|
+
return errorResult;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* Extract placeholder variables from template
|
43
|
+
* Looks for {{PLACEHOLDER_NAME}} patterns
|
44
|
+
*/
|
45
|
+
extractPlaceholders(template) {
|
46
|
+
const regex = /\{\{([A-Z_]+)\}\}/g;
|
47
|
+
const matches = template.matchAll(regex);
|
48
|
+
const placeholders = new Set();
|
49
|
+
for (const match of matches) {
|
50
|
+
placeholders.add(match[1]);
|
51
|
+
}
|
52
|
+
return Array.from(placeholders).sort();
|
53
|
+
}
|
54
|
+
/**
|
55
|
+
* Get list of supported operation/language combinations
|
56
|
+
*/
|
57
|
+
async getSupportedCombinations() {
|
58
|
+
const combinations = await this.templateLoader.listAvailableTemplates();
|
59
|
+
return combinations.map(c => `${c.operation}/${c.language}`);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
//# sourceMappingURL=code-generation-tool.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"code-generation-tool.js","sourceRoot":"","sources":["../../src/tools/code-generation-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA6BtD,MAAM,OAAO,kBAAkB;IACrB,cAAc,CAAiB;IAEvC;QACE,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,SAAoB,EACpB,QAAkB;QAElB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACH,gBAAgB;YAChB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAE7E,qCAAqC;YACrC,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAExD,MAAM,MAAM,GAAyB;gBACnC,IAAI,EAAE,QAAQ;gBACd,QAAQ;gBACR,SAAS;gBACT,QAAQ,EAAE;oBACR,YAAY,EAAE,aAAa,SAAS,IAAI,QAAQ,WAAW;oBAC3D,YAAY;oBACZ,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACtC;aACF,CAAC;YAEF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC7C,OAAO,CAAC,KAAK,CACX,8BAA8B,SAAS,cAAc,QAAQ,UAAU,aAAa,IAAI,CACzF,CAAC;YAEF,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gDAAgD;YAChD,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAEpE,MAAM,WAAW,GAAwB;gBACvC,KAAK,EAAE,qCAAqC,SAAS,OAAO,QAAQ,gBAAgB,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACtH,SAAS;gBACT,QAAQ;gBACR,qBAAqB;aACtB,CAAC;YAEF,OAAO,CAAC,KAAK,CAAC,2BAA2B,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9D,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,mBAAmB,CAAC,QAAgB;QAC1C,MAAM,KAAK,GAAG,oBAAoB,CAAC;QACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QAEvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,wBAAwB;QACpC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,sBAAsB,EAAE,CAAC;QACxE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/D,CAAC;CACF"}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { ScoredChunk } from '../search/keyword-search.js';
|
2
|
+
import { SearchResponse } from '../types/search.js';
|
3
|
+
export declare class SearchResultFormatter {
|
4
|
+
private readonly MAX_SNIPPET_WORDS;
|
5
|
+
/**
|
6
|
+
* Format search results for MCP response
|
7
|
+
*/
|
8
|
+
formatResults(chunks: ScoredChunk[], query: string, executionTime: number, integrationPhase?: string): SearchResponse;
|
9
|
+
/**
|
10
|
+
* Format a single chunk into a search result
|
11
|
+
*/
|
12
|
+
private formatChunk;
|
13
|
+
/**
|
14
|
+
* Create snippet with word limit and ellipsis
|
15
|
+
*/
|
16
|
+
private createSnippet;
|
17
|
+
/**
|
18
|
+
* Find the last sentence boundary (. ! ?) in text
|
19
|
+
*/
|
20
|
+
private findLastSentenceBoundary;
|
21
|
+
/**
|
22
|
+
* Highlight matched keywords in snippet (optional enhancement)
|
23
|
+
*/
|
24
|
+
highlightKeywords(snippet: string, keywords: string[]): string;
|
25
|
+
private escapeRegex;
|
26
|
+
}
|
27
|
+
//# sourceMappingURL=search-result-formatter.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"search-result-formatter.d.ts","sourceRoot":"","sources":["../../src/tools/search-result-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAgB,cAAc,EAAkB,MAAM,oBAAoB,CAAC;AAElF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAO;IAEzC;;OAEG;IACH,aAAa,CACX,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,gBAAgB,CAAC,EAAE,MAAM,GACxB,cAAc;IA+BjB;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAQhC;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM;IAY9D,OAAO,CAAC,WAAW;CAGpB"}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
export class SearchResultFormatter {
|
2
|
+
MAX_SNIPPET_WORDS = 500;
|
3
|
+
/**
|
4
|
+
* Format search results for MCP response
|
5
|
+
*/
|
6
|
+
formatResults(chunks, query, executionTime, integrationPhase) {
|
7
|
+
const results = chunks.map(chunk => this.formatChunk(chunk));
|
8
|
+
const metadata = {
|
9
|
+
queryTime: executionTime,
|
10
|
+
totalResults: chunks.length,
|
11
|
+
returned: results.length,
|
12
|
+
query,
|
13
|
+
integrationPhase,
|
14
|
+
};
|
15
|
+
// Handle empty results
|
16
|
+
if (results.length === 0) {
|
17
|
+
return {
|
18
|
+
results: [],
|
19
|
+
metadata,
|
20
|
+
message: `No results found for: ${query}. Try different keywords or check docs.grubtech.io directly.`,
|
21
|
+
suggestions: [
|
22
|
+
'Try different keywords',
|
23
|
+
'Use more specific terms',
|
24
|
+
'Check docs.grubtech.io directly',
|
25
|
+
],
|
26
|
+
};
|
27
|
+
}
|
28
|
+
return {
|
29
|
+
results,
|
30
|
+
metadata,
|
31
|
+
};
|
32
|
+
}
|
33
|
+
/**
|
34
|
+
* Format a single chunk into a search result
|
35
|
+
*/
|
36
|
+
formatChunk(chunk) {
|
37
|
+
return {
|
38
|
+
title: chunk.title || 'Untitled',
|
39
|
+
snippet: this.createSnippet(chunk.content),
|
40
|
+
sourceUrl: chunk.sourceUrl,
|
41
|
+
relevanceScore: parseFloat(chunk.relevanceScore.toFixed(2)),
|
42
|
+
highlights: chunk.matchedKeywords || [],
|
43
|
+
};
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* Create snippet with word limit and ellipsis
|
47
|
+
*/
|
48
|
+
createSnippet(content) {
|
49
|
+
const words = content.split(/\s+/);
|
50
|
+
if (words.length <= this.MAX_SNIPPET_WORDS) {
|
51
|
+
return content.trim();
|
52
|
+
}
|
53
|
+
// Truncate at word boundary
|
54
|
+
const truncated = words.slice(0, this.MAX_SNIPPET_WORDS).join(' ');
|
55
|
+
// Try to end at sentence boundary if possible
|
56
|
+
const lastSentenceEnd = this.findLastSentenceBoundary(truncated);
|
57
|
+
if (lastSentenceEnd > truncated.length * 0.8) {
|
58
|
+
// If we're within 80% of target, use sentence boundary
|
59
|
+
return truncated.substring(0, lastSentenceEnd + 1).trim() + '...';
|
60
|
+
}
|
61
|
+
return truncated.trim() + '...';
|
62
|
+
}
|
63
|
+
/**
|
64
|
+
* Find the last sentence boundary (. ! ?) in text
|
65
|
+
*/
|
66
|
+
findLastSentenceBoundary(text) {
|
67
|
+
const matches = Array.from(text.matchAll(/[.!?]/g));
|
68
|
+
if (matches.length === 0)
|
69
|
+
return -1;
|
70
|
+
const lastMatch = matches[matches.length - 1];
|
71
|
+
return lastMatch.index || -1;
|
72
|
+
}
|
73
|
+
/**
|
74
|
+
* Highlight matched keywords in snippet (optional enhancement)
|
75
|
+
*/
|
76
|
+
highlightKeywords(snippet, keywords) {
|
77
|
+
let highlighted = snippet;
|
78
|
+
for (const keyword of keywords) {
|
79
|
+
// Use case-insensitive replacement with markdown bold
|
80
|
+
const regex = new RegExp(`\\b(${this.escapeRegex(keyword)})\\b`, 'gi');
|
81
|
+
highlighted = highlighted.replace(regex, '**$1**');
|
82
|
+
}
|
83
|
+
return highlighted;
|
84
|
+
}
|
85
|
+
escapeRegex(str) {
|
86
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
87
|
+
}
|
88
|
+
}
|
89
|
+
//# sourceMappingURL=search-result-formatter.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"search-result-formatter.js","sourceRoot":"","sources":["../../src/tools/search-result-formatter.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { SearchResponse } from '../types/search.js';
|
2
|
+
export declare class SearchTool {
|
3
|
+
private cache;
|
4
|
+
private keywordSearch;
|
5
|
+
private formatter;
|
6
|
+
constructor();
|
7
|
+
search(query: string, integrationPhase?: string): Promise<SearchResponse>;
|
8
|
+
}
|
9
|
+
//# sourceMappingURL=search-tool.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"search-tool.d.ts","sourceRoot":"","sources":["../../src/tools/search-tool.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,SAAS,CAAwB;;IAQnC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAkChF"}
|