@mseep/ai-tech-app-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.
Files changed (67) hide show
  1. package/.env +24 -0
  2. package/.env.example +24 -0
  3. package/Jenkinsfile +210 -0
  4. package/MCP-SERVER-GUIDE.md +405 -0
  5. package/README.MD +450 -0
  6. package/dist/config/app.config.d.ts +65 -0
  7. package/dist/config/app.config.d.ts.map +1 -0
  8. package/dist/config/app.config.js +94 -0
  9. package/dist/config/app.config.js.map +1 -0
  10. package/dist/config/llm.config.d.ts +63 -0
  11. package/dist/config/llm.config.d.ts.map +1 -0
  12. package/dist/config/llm.config.js +158 -0
  13. package/dist/config/llm.config.js.map +1 -0
  14. package/dist/config/mcp.config.d.ts +175 -0
  15. package/dist/config/mcp.config.d.ts.map +1 -0
  16. package/dist/config/mcp.config.js +215 -0
  17. package/dist/config/mcp.config.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +175 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/llm/llamaClient.d.ts +14 -0
  23. package/dist/llm/llamaClient.d.ts.map +1 -0
  24. package/dist/llm/llamaClient.js +136 -0
  25. package/dist/llm/llamaClient.js.map +1 -0
  26. package/dist/mcp/mcpClient.d.ts +132 -0
  27. package/dist/mcp/mcpClient.d.ts.map +1 -0
  28. package/dist/mcp/mcpClient.js +784 -0
  29. package/dist/mcp/mcpClient.js.map +1 -0
  30. package/dist/models/testSpec.d.ts +78 -0
  31. package/dist/models/testSpec.d.ts.map +1 -0
  32. package/dist/models/testSpec.js +3 -0
  33. package/dist/models/testSpec.js.map +1 -0
  34. package/dist/orchestrator/aiTestRunner.d.ts +18 -0
  35. package/dist/orchestrator/aiTestRunner.d.ts.map +1 -0
  36. package/dist/orchestrator/aiTestRunner.js +247 -0
  37. package/dist/orchestrator/aiTestRunner.js.map +1 -0
  38. package/dist/utils/logger.d.ts +4 -0
  39. package/dist/utils/logger.d.ts.map +1 -0
  40. package/dist/utils/logger.js +49 -0
  41. package/dist/utils/logger.js.map +1 -0
  42. package/dist/utils/promptBuilder.d.ts +62 -0
  43. package/dist/utils/promptBuilder.d.ts.map +1 -0
  44. package/dist/utils/promptBuilder.js +333 -0
  45. package/dist/utils/promptBuilder.js.map +1 -0
  46. package/knowledge/app-knowledge.txt +100 -0
  47. package/logs/combined.log +486 -0
  48. package/logs/error.log +50 -0
  49. package/package.json +62 -0
  50. package/reports/screenshots/screenshot_1764535110518.png +0 -0
  51. package/reports/test-report.json +106 -0
  52. package/scripts/check-mcp-server.sh +100 -0
  53. package/scripts/extract-pom-knowledge.js +222 -0
  54. package/scripts/pre-test-setup.js +262 -0
  55. package/scripts/start-mcp-server.sh +76 -0
  56. package/src/config/app.config.ts +175 -0
  57. package/src/config/llm.config.ts +220 -0
  58. package/src/config/mcp.config.ts +291 -0
  59. package/src/index.ts +161 -0
  60. package/src/llm/llamaClient.ts +159 -0
  61. package/src/mcp/mcpClient.ts +878 -0
  62. package/src/models/testSpec.ts +85 -0
  63. package/src/orchestrator/aiTestRunner.ts +286 -0
  64. package/src/utils/logger.ts +59 -0
  65. package/src/utils/promptBuilder.ts +384 -0
  66. package/tests/nlp-specs/login-flow.yaml +31 -0
  67. package/tsconfig.json +31 -0
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PromptBuilder = void 0;
37
+ const llm_config_1 = __importStar(require("../config/llm.config"));
38
+ class PromptBuilder {
39
+ constructor() {
40
+ this.maxUIElements = llm_config_1.default.prompt.maxUIElements;
41
+ this.maxContextTokens = llm_config_1.default.prompt.maxContextTokens;
42
+ this.includeAppContext = llm_config_1.default.prompt.includeAppContext;
43
+ this.includeUIContext = llm_config_1.default.prompt.includeUIContext;
44
+ }
45
+ /**
46
+ * Build the main action planning prompt
47
+ */
48
+ buildActionPlanningPrompt(stepText, uiContext, appKnowledge, platform) {
49
+ const sections = [];
50
+ // System context
51
+ sections.push(llm_config_1.PromptTemplates.actionPlanning);
52
+ sections.push('');
53
+ // App-specific knowledge
54
+ if (this.includeAppContext && appKnowledge) {
55
+ sections.push('**App-Specific Knowledge:**');
56
+ sections.push(this.truncateText(appKnowledge, 1000));
57
+ sections.push('');
58
+ }
59
+ // Platform information
60
+ if (platform) {
61
+ sections.push(`**Platform:** ${platform.toUpperCase()}`);
62
+ sections.push('');
63
+ }
64
+ // Current UI state
65
+ if (this.includeUIContext) {
66
+ sections.push('**Current UI State:**');
67
+ sections.push(this.formatUIContext(uiContext));
68
+ sections.push('');
69
+ }
70
+ // Test step to execute
71
+ sections.push('**Test Step to Execute:**');
72
+ sections.push(`"${stepText}"`);
73
+ sections.push('');
74
+ // Output format instructions
75
+ sections.push(this.getOutputFormatInstructions());
76
+ return sections.join('\n');
77
+ }
78
+ /**
79
+ * Build prompt for context analysis
80
+ */
81
+ buildContextAnalysisPrompt(uiContext, focusArea) {
82
+ const sections = [];
83
+ sections.push(llm_config_1.PromptTemplates.contextAnalysis);
84
+ sections.push('');
85
+ if (focusArea) {
86
+ sections.push(`**Focus Area:** ${focusArea}`);
87
+ sections.push('');
88
+ }
89
+ sections.push('**Current UI State:**');
90
+ sections.push(this.formatUIContext(uiContext));
91
+ sections.push('');
92
+ sections.push('Identify and list the most relevant interactive elements with their best selectors.');
93
+ return sections.join('\n');
94
+ }
95
+ /**
96
+ * Build prompt for error recovery
97
+ */
98
+ buildErrorRecoveryPrompt(stepText, previousError, uiContext, attemptNumber) {
99
+ const sections = [];
100
+ sections.push(llm_config_1.PromptTemplates.errorRecovery);
101
+ sections.push('');
102
+ sections.push(`**Original Test Step:** "${stepText}"`);
103
+ sections.push(`**Attempt Number:** ${attemptNumber}`);
104
+ sections.push(`**Previous Error:** ${previousError}`);
105
+ sections.push('');
106
+ sections.push('**Current UI State:**');
107
+ sections.push(this.formatUIContext(uiContext));
108
+ sections.push('');
109
+ sections.push('**Instructions:**');
110
+ sections.push('1. Analyze why the previous attempt failed');
111
+ sections.push('2. Check if the UI state has changed');
112
+ sections.push('3. Suggest alternative actions or selectors');
113
+ sections.push('4. If the step is impossible, return an empty actions array with reasoning');
114
+ sections.push('');
115
+ sections.push(this.getOutputFormatInstructions());
116
+ return sections.join('\n');
117
+ }
118
+ /**
119
+ * Build prompt for assertion generation
120
+ */
121
+ buildAssertionPrompt(expectedOutcome, uiContext) {
122
+ const sections = [];
123
+ sections.push(llm_config_1.PromptTemplates.assertionGeneration);
124
+ sections.push('');
125
+ sections.push(`**Expected Outcome:** "${expectedOutcome}"`);
126
+ sections.push('');
127
+ sections.push('**Current UI State:**');
128
+ sections.push(this.formatUIContext(uiContext));
129
+ sections.push('');
130
+ sections.push('Generate assertion actions to verify the expected outcome.');
131
+ sections.push('');
132
+ sections.push(this.getOutputFormatInstructions());
133
+ return sections.join('\n');
134
+ }
135
+ /**
136
+ * Format UI context for inclusion in prompts
137
+ */
138
+ formatUIContext(uiContext) {
139
+ const lines = [];
140
+ // Current screen/activity
141
+ if (uiContext.currentActivity) {
142
+ lines.push(`Current Screen: ${uiContext.currentActivity}`);
143
+ lines.push('');
144
+ }
145
+ // Visible elements
146
+ const elements = uiContext.visibleElements || [];
147
+ if (elements.length === 0) {
148
+ lines.push('No visible elements detected.');
149
+ return lines.join('\n');
150
+ }
151
+ lines.push(`Visible Elements (showing ${Math.min(elements.length, this.maxUIElements)} of ${elements.length}):`);
152
+ lines.push('');
153
+ // Filter and sort elements by relevance
154
+ const relevantElements = this.filterRelevantElements(elements);
155
+ const topElements = relevantElements.slice(0, this.maxUIElements);
156
+ topElements.forEach((element, index) => {
157
+ lines.push(this.formatElement(element, index + 1));
158
+ });
159
+ return lines.join('\n');
160
+ }
161
+ /**
162
+ * Format a single UI element
163
+ */
164
+ formatElement(element, index) {
165
+ const parts = [`${index}.`];
166
+ // Element type
167
+ parts.push(`[${element.type}]`);
168
+ // Text content
169
+ if (element.text && element.text.trim().length > 0) {
170
+ parts.push(`text="${this.truncateText(element.text, 50)}"`);
171
+ }
172
+ // Resource ID (Android) or Name (iOS)
173
+ if (element.resourceId) {
174
+ const shortId = element.resourceId.split('/').pop() || element.resourceId;
175
+ parts.push(`id="${shortId}"`);
176
+ }
177
+ // Content description / accessibility label
178
+ if (element.contentDesc) {
179
+ parts.push(`desc="${this.truncateText(element.contentDesc, 30)}"`);
180
+ }
181
+ // Attributes
182
+ const attrs = [];
183
+ if (element.clickable)
184
+ attrs.push('clickable');
185
+ if (element.enabled)
186
+ attrs.push('enabled');
187
+ if (!element.enabled)
188
+ attrs.push('disabled');
189
+ if (attrs.length > 0) {
190
+ parts.push(`[${attrs.join(', ')}]`);
191
+ }
192
+ // Bounds (if useful)
193
+ if (element.bounds) {
194
+ parts.push(`bounds=${element.bounds}`);
195
+ }
196
+ return parts.join(' ');
197
+ }
198
+ /**
199
+ * Filter elements to show most relevant ones
200
+ */
201
+ filterRelevantElements(elements) {
202
+ // Prioritize elements that are:
203
+ // 1. Interactive (clickable, editable)
204
+ // 2. Have meaningful text or labels
205
+ // 3. Are common UI patterns (buttons, inputs, etc.)
206
+ const scored = elements.map(element => ({
207
+ element,
208
+ score: this.calculateElementRelevance(element),
209
+ }));
210
+ // Sort by score (descending)
211
+ scored.sort((a, b) => b.score - a.score);
212
+ return scored.map(s => s.element);
213
+ }
214
+ /**
215
+ * Calculate relevance score for an element
216
+ */
217
+ calculateElementRelevance(element) {
218
+ let score = 0;
219
+ // Interactive elements get high priority
220
+ if (element.clickable)
221
+ score += 10;
222
+ // Elements with text are usually important
223
+ if (element.text && element.text.trim().length > 0) {
224
+ score += 8;
225
+ }
226
+ // Elements with IDs are identifiable
227
+ if (element.resourceId)
228
+ score += 5;
229
+ // Elements with accessibility labels
230
+ if (element.contentDesc)
231
+ score += 5;
232
+ // Common interactive types
233
+ const interactiveTypes = [
234
+ 'Button', 'EditText', 'TextView', 'ImageButton',
235
+ 'CheckBox', 'RadioButton', 'Switch', 'Spinner',
236
+ 'UIButton', 'UITextField', 'UITextView', 'UILabel',
237
+ ];
238
+ if (interactiveTypes.some(type => element.type.includes(type))) {
239
+ score += 7;
240
+ }
241
+ // Enabled elements
242
+ if (element.enabled)
243
+ score += 3;
244
+ // Penalize common container types (unless they have text)
245
+ const containerTypes = ['ViewGroup', 'LinearLayout', 'FrameLayout', 'View', 'UIView'];
246
+ if (containerTypes.some(type => element.type.includes(type)) && !element.text) {
247
+ score -= 5;
248
+ }
249
+ return Math.max(0, score);
250
+ }
251
+ /**
252
+ * Get output format instructions
253
+ */
254
+ getOutputFormatInstructions() {
255
+ return `**Output Format (JSON only, no markdown):**
256
+ {
257
+ "actions": [
258
+ {
259
+ "type": "tap|type|scroll|swipe|wait|assert|screenshot",
260
+ "selector": {
261
+ "strategy": "text|id|accessibility-id|xpath|class",
262
+ "value": "selector_value",
263
+ "index": 0
264
+ },
265
+ "value": "text_to_type (only for type action)",
266
+ "direction": "up|down|left|right (only for scroll/swipe)",
267
+ "duration": 1000,
268
+ "assertionType": "exists|visible|text|enabled (only for assert)",
269
+ "expectedValue": "expected_value (only for assert)"
270
+ }
271
+ ],
272
+ "reasoning": "Brief explanation of the action sequence and why these selectors were chosen"
273
+ }
274
+
275
+ **Critical Rules:**
276
+ 1. Return ONLY valid JSON, no markdown code blocks
277
+ 2. Always prefer text-based selectors over XPath
278
+ 3. Use accessibility-id or resource-id when available
279
+ 4. Include reasoning for your selector choices
280
+ 5. If no action is possible, return empty actions array with explanation
281
+ 6. Keep action sequences minimal (1-3 actions preferred)
282
+ 7. Add wait actions if UI transitions are expected
283
+
284
+ Generate the JSON action plan now:`;
285
+ }
286
+ /**
287
+ * Truncate text to max length
288
+ */
289
+ truncateText(text, maxLength) {
290
+ if (text.length <= maxLength) {
291
+ return text;
292
+ }
293
+ return text.substring(0, maxLength - 3) + '...';
294
+ }
295
+ /**
296
+ * Estimate token count (rough approximation)
297
+ */
298
+ estimateTokens(text) {
299
+ // Rough estimate: 1 token ≈ 4 characters
300
+ return Math.ceil(text.length / 4);
301
+ }
302
+ /**
303
+ * Build a few-shot learning prompt with examples
304
+ */
305
+ buildFewShotPrompt(stepText, uiContext, examples) {
306
+ const sections = [];
307
+ sections.push(llm_config_1.PromptTemplates.actionPlanning);
308
+ sections.push('');
309
+ sections.push('**Example Scenarios:**');
310
+ sections.push('');
311
+ examples.forEach((example, index) => {
312
+ sections.push(`Example ${index + 1}:`);
313
+ sections.push(`Step: "${example.step}"`);
314
+ if (example.context) {
315
+ sections.push(`Context: ${example.context}`);
316
+ }
317
+ sections.push(`Actions: ${JSON.stringify(example.actions, null, 2)}`);
318
+ sections.push('');
319
+ });
320
+ sections.push('**Now, solve this:**');
321
+ sections.push('');
322
+ sections.push('**Current UI State:**');
323
+ sections.push(this.formatUIContext(uiContext));
324
+ sections.push('');
325
+ sections.push(`**Test Step:** "${stepText}"`);
326
+ sections.push('');
327
+ sections.push(this.getOutputFormatInstructions());
328
+ return sections.join('\n');
329
+ }
330
+ }
331
+ exports.PromptBuilder = PromptBuilder;
332
+ exports.default = PromptBuilder;
333
+ //# sourceMappingURL=promptBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptBuilder.js","sourceRoot":"","sources":["../../src/utils/promptBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ # Technician App Knowledge Base
2
+
3
+ ## App Overview
4
+ A mobile application for technicians to manage jobs, check-in/checkout, and capture photos for completed work.
5
+
6
+ ## Common Screens and Elements
7
+
8
+ ### Get Started Screen
9
+ - Get Started buton: text="Get Started"
10
+
11
+ ### Login Screen
12
+ - Mobile number input field: accessibility-id="mobile-number-input" or text contains "mobile number"
13
+ - Continue/Next button: text="Continue" or "Next"
14
+ - OTP input fields: Usually 4-6 digit fields
15
+
16
+ ### OTP Screen
17
+ - OTP input boxes: accessibility-id contains "otp" or "code"
18
+ - Verify/Submit button: text="Verify" or "Submit"
19
+ - Resend OTP link: text contains "Resend"
20
+
21
+ ### Permission Dialogs
22
+ - Notification permission:
23
+ - Android: text="Allow"
24
+ - iOS: text="Allow" or "OK"
25
+ - Location permission:
26
+ - Android: text="Allow" or "While using the app"
27
+ - iOS: text="Allow While Using App" or "Allow Once"
28
+ - Camera permission:
29
+ - Android: text="Allow" or "Only this time"
30
+ - iOS: text="OK" or "Allow"
31
+ - Photo library:
32
+ - text="Allow access to all photos" or "Select Photos"
33
+
34
+ ### Home Screen
35
+ - Bottom navigation tabs:
36
+ - Jobs: accessibility-id="tab-jobs" or text="My Jobs"
37
+ - Opportunities(optional): accessibility-id="tab-opportunities" or text="Opportunities"
38
+ - Estimates(optional): accessibility-id="tab-opportunities" or text="Estimates"
39
+ - Profile: accessibility-id="tab-profile" or text="Profile"
40
+
41
+ ### Jobs Screen
42
+ - Search bar: accessibility-id="job-search" or hint="Search jobs"
43
+ - Job list items: class="RecyclerView" (Android) or "UITableView" (iOS)
44
+ - Each job card contains:
45
+ - Job title: accessibility-id contains "job-title"
46
+ - Job location: accessibility-id contains "job-location"
47
+ - Job status badge
48
+
49
+ ### Job Details Screen
50
+ - Job title header
51
+ - Job description section
52
+ - Check-in button: text="Check In" or "Start Job"
53
+ - Check-out button: text="Check Out" or "Complete Job"
54
+ - Take photo button: text="Take Photo" or "Add Photo"
55
+ - Navigation back button: usually top-left
56
+
57
+ ### Check-in/Checkout Screens
58
+ - Location status indicator
59
+ - Photo capture area
60
+ - Notes/Comments field: hint contains "notes" or "comments"
61
+ - Submit button: text="Submit" or "Confirm"
62
+
63
+ ### Camera Screen
64
+ - Capture button: Large circular button at bottom center
65
+ - Gallery/Library button: Usually bottom-left
66
+ - Flash toggle: Usually top portion
67
+ - Confirm/Use photo button: text="Use Photo" or checkmark icon
68
+
69
+ ## Common Patterns
70
+
71
+ ### Navigation
72
+ - Bottom tab navigation for main sections
73
+ - Back button in top-left for sub-screens
74
+ - Hamburger menu (if present) in top-right for settings
75
+
76
+ ### Text Input
77
+ - Always look for hint text or placeholder text
78
+ - Input fields often have resource-id ending in "input" or "edit"
79
+
80
+ ### Buttons
81
+ - Primary actions: Usually prominent colors (blue, green)
82
+ - Text often includes: "Continue", "Submit", "Confirm", "Next", "Done"
83
+ - Cancel/Back: Usually gray or outline style
84
+
85
+ ### Lists and Scrolling
86
+ - Job lists and opportunity lists are scrollable
87
+ - Use scroll gesture with direction "down" to load more
88
+ - Pull to refresh at top of lists
89
+
90
+ ## Error Handling
91
+ - Toast messages appear at bottom (Android) or top (iOS)
92
+ - Error dialogs usually have "OK" or "Dismiss" button
93
+ - Network errors may show retry button
94
+
95
+ ## Important Notes
96
+ - Always wait after location permission grant (GPS initialization takes time)
97
+ - Photos may take 2-3 seconds to process after capture
98
+ - Job status updates may have slight delay (1-2 seconds)
99
+ - Prefer text-based selectors over XPath for reliability
100
+ - Use accessibility-id when available for best cross-platform support