auq-mcp-server 0.1.10 → 1.2.5

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 (42) hide show
  1. package/README.md +24 -0
  2. package/dist/bin/auq.js +138 -7
  3. package/dist/package.json +17 -6
  4. package/dist/src/__tests__/schema-validation.test.js +34 -26
  5. package/dist/src/core/ask-user-questions.js +35 -0
  6. package/dist/src/server.js +11 -74
  7. package/dist/src/shared/schemas.js +64 -0
  8. package/dist/src/tui/components/Header.js +9 -1
  9. package/dist/src/tui/components/MultiLineTextInput.js +53 -14
  10. package/dist/src/tui/components/OptionsList.js +8 -0
  11. package/dist/src/tui/components/QuestionDisplay.js +10 -6
  12. package/dist/src/tui/components/ReviewScreen.js +6 -2
  13. package/dist/src/tui/components/StepperView.js +25 -3
  14. package/dist/src/tui/components/WaitingScreen.js +31 -4
  15. package/package.json +10 -4
  16. package/dist/__tests__/schema-validation.test.js +0 -137
  17. package/dist/__tests__/server.integration.test.js +0 -263
  18. package/dist/add.js +0 -1
  19. package/dist/add.test.js +0 -5
  20. package/dist/bin/test-session-menu.js +0 -28
  21. package/dist/bin/test-tabbar.js +0 -42
  22. package/dist/file-utils.js +0 -59
  23. package/dist/format/ResponseFormatter.js +0 -206
  24. package/dist/format/__tests__/ResponseFormatter.test.js +0 -380
  25. package/dist/server.js +0 -107
  26. package/dist/session/ResponseFormatter.js +0 -130
  27. package/dist/session/SessionManager.js +0 -474
  28. package/dist/session/__tests__/ResponseFormatter.test.js +0 -417
  29. package/dist/session/__tests__/SessionManager.test.js +0 -553
  30. package/dist/session/__tests__/atomic-operations.test.js +0 -345
  31. package/dist/session/__tests__/file-watcher.test.js +0 -311
  32. package/dist/session/__tests__/workflow.integration.test.js +0 -334
  33. package/dist/session/atomic-operations.js +0 -307
  34. package/dist/session/file-watcher.js +0 -218
  35. package/dist/session/index.js +0 -7
  36. package/dist/session/types.js +0 -20
  37. package/dist/session/utils.js +0 -125
  38. package/dist/session-manager.js +0 -171
  39. package/dist/session-watcher.js +0 -110
  40. package/dist/src/tui/components/SessionSelectionMenu.js +0 -151
  41. package/dist/tui/__tests__/session-watcher.test.js +0 -368
  42. package/dist/tui/session-watcher.js +0 -183
@@ -1,417 +0,0 @@
1
- /**
2
- * Unit tests for Response Formatter
3
- */
4
- import { describe, expect, it } from "vitest";
5
- import { ResponseFormatter } from "../ResponseFormatter.js";
6
- describe("ResponseFormatter", () => {
7
- describe("formatUserResponse", () => {
8
- it("should format a single question with selected option", () => {
9
- const questions = [
10
- {
11
- options: [
12
- {
13
- description: "Dynamic web language",
14
- label: "JavaScript",
15
- },
16
- {
17
- description: "Type-safe JavaScript",
18
- label: "TypeScript",
19
- },
20
- ],
21
- prompt: "What is your favorite programming language?",
22
- },
23
- ];
24
- const answers = {
25
- answers: [
26
- {
27
- questionIndex: 0,
28
- selectedOption: "TypeScript",
29
- timestamp: "2025-01-01T00:00:00Z",
30
- },
31
- ],
32
- sessionId: "test-123",
33
- timestamp: "2025-01-01T00:00:00Z",
34
- };
35
- const result = ResponseFormatter.formatUserResponse(answers, questions);
36
- expect(result).toBe("Here are the user's answers:\n\n" +
37
- "1. What is your favorite programming language?\n" +
38
- "→ TypeScript — Type-safe JavaScript");
39
- });
40
- it("should format multiple questions with selected options", () => {
41
- const questions = [
42
- {
43
- options: [
44
- {
45
- description: "Dynamic web language",
46
- label: "JavaScript",
47
- },
48
- {
49
- description: "Type-safe JavaScript",
50
- label: "TypeScript",
51
- },
52
- ],
53
- prompt: "What is your favorite programming language?",
54
- },
55
- {
56
- options: [
57
- {
58
- description: "Frontend or backend web application",
59
- label: "Web",
60
- },
61
- {
62
- description: "Command-line tool",
63
- label: "CLI",
64
- },
65
- ],
66
- prompt: "What type of application are you building?",
67
- },
68
- ];
69
- const answers = {
70
- answers: [
71
- {
72
- questionIndex: 0,
73
- selectedOption: "TypeScript",
74
- timestamp: "2025-01-01T00:00:00Z",
75
- },
76
- {
77
- questionIndex: 1,
78
- selectedOption: "Web",
79
- timestamp: "2025-01-01T00:00:00Z",
80
- },
81
- ],
82
- sessionId: "test-123",
83
- timestamp: "2025-01-01T00:00:00Z",
84
- };
85
- const result = ResponseFormatter.formatUserResponse(answers, questions);
86
- expect(result).toBe("Here are the user's answers:\n\n" +
87
- "1. What is your favorite programming language?\n" +
88
- "→ TypeScript — Type-safe JavaScript\n\n" +
89
- "2. What type of application are you building?\n" +
90
- "→ Web — Frontend or backend web application");
91
- });
92
- it("should format custom text answer", () => {
93
- const questions = [
94
- {
95
- options: [
96
- {
97
- description: "Frontend or backend web application",
98
- label: "Web",
99
- },
100
- {
101
- description: "Command-line tool",
102
- label: "CLI",
103
- },
104
- ],
105
- prompt: "What type of application are you building?",
106
- },
107
- ];
108
- const answers = {
109
- answers: [
110
- {
111
- customText: "Desktop app with Electron",
112
- questionIndex: 0,
113
- timestamp: "2025-01-01T00:00:00Z",
114
- },
115
- ],
116
- sessionId: "test-123",
117
- timestamp: "2025-01-01T00:00:00Z",
118
- };
119
- const result = ResponseFormatter.formatUserResponse(answers, questions);
120
- expect(result).toBe("Here are the user's answers:\n\n" +
121
- "1. What type of application are you building?\n" +
122
- "→ Other: 'Desktop app with Electron'");
123
- });
124
- it("should format mix of selected and custom answers", () => {
125
- const questions = [
126
- {
127
- options: [
128
- {
129
- description: "Dynamic web language",
130
- label: "JavaScript",
131
- },
132
- {
133
- description: "Type-safe JavaScript",
134
- label: "TypeScript",
135
- },
136
- ],
137
- prompt: "What is your favorite programming language?",
138
- },
139
- {
140
- options: [
141
- {
142
- description: "Frontend or backend web application",
143
- label: "Web",
144
- },
145
- {
146
- description: "Command-line tool",
147
- label: "CLI",
148
- },
149
- ],
150
- prompt: "What type of application are you building?",
151
- },
152
- ];
153
- const answers = {
154
- answers: [
155
- {
156
- questionIndex: 0,
157
- selectedOption: "TypeScript",
158
- timestamp: "2025-01-01T00:00:00Z",
159
- },
160
- {
161
- customText: "Desktop app with Electron",
162
- questionIndex: 1,
163
- timestamp: "2025-01-01T00:00:00Z",
164
- },
165
- ],
166
- sessionId: "test-123",
167
- timestamp: "2025-01-01T00:00:00Z",
168
- };
169
- const result = ResponseFormatter.formatUserResponse(answers, questions);
170
- expect(result).toBe("Here are the user's answers:\n\n" +
171
- "1. What is your favorite programming language?\n" +
172
- "→ TypeScript — Type-safe JavaScript\n\n" +
173
- "2. What type of application are you building?\n" +
174
- "→ Other: 'Desktop app with Electron'");
175
- });
176
- it("should handle option without description", () => {
177
- const questions = [
178
- {
179
- options: [
180
- {
181
- label: "Red",
182
- },
183
- {
184
- label: "Blue",
185
- },
186
- ],
187
- prompt: "Choose a color",
188
- },
189
- ];
190
- const answers = {
191
- answers: [
192
- {
193
- questionIndex: 0,
194
- selectedOption: "Red",
195
- timestamp: "2025-01-01T00:00:00Z",
196
- },
197
- ],
198
- sessionId: "test-123",
199
- timestamp: "2025-01-01T00:00:00Z",
200
- };
201
- const result = ResponseFormatter.formatUserResponse(answers, questions);
202
- expect(result).toBe("Here are the user's answers:\n\n" + "1. Choose a color\n" + "→ Red");
203
- });
204
- it("should escape single quotes in custom text", () => {
205
- const questions = [
206
- {
207
- options: [
208
- {
209
- label: "Good",
210
- },
211
- ],
212
- prompt: "What is your feedback?",
213
- },
214
- ];
215
- const answers = {
216
- answers: [
217
- {
218
- customText: "It's great! I'm loving it!",
219
- questionIndex: 0,
220
- timestamp: "2025-01-01T00:00:00Z",
221
- },
222
- ],
223
- sessionId: "test-123",
224
- timestamp: "2025-01-01T00:00:00Z",
225
- };
226
- const result = ResponseFormatter.formatUserResponse(answers, questions);
227
- expect(result).toContain("It\\'s great! I\\'m loving it!");
228
- });
229
- it("should throw error for empty answers", () => {
230
- const questions = [
231
- {
232
- options: [{ label: "Option 1" }],
233
- prompt: "Test question",
234
- },
235
- ];
236
- const answers = {
237
- answers: [],
238
- sessionId: "test-123",
239
- timestamp: "2025-01-01T00:00:00Z",
240
- };
241
- expect(() => ResponseFormatter.formatUserResponse(answers, questions)).toThrow("No answers provided in session");
242
- });
243
- it("should throw error for empty questions", () => {
244
- const questions = [];
245
- const answers = {
246
- answers: [
247
- {
248
- questionIndex: 0,
249
- selectedOption: "Option 1",
250
- timestamp: "2025-01-01T00:00:00Z",
251
- },
252
- ],
253
- sessionId: "test-123",
254
- timestamp: "2025-01-01T00:00:00Z",
255
- };
256
- expect(() => ResponseFormatter.formatUserResponse(answers, questions)).toThrow("No questions provided");
257
- });
258
- it("should handle missing answer for a question gracefully", () => {
259
- const questions = [
260
- {
261
- options: [{ label: "Option 1" }],
262
- prompt: "Question 1",
263
- },
264
- {
265
- options: [{ label: "Option 2" }],
266
- prompt: "Question 2",
267
- },
268
- ];
269
- const answers = {
270
- answers: [
271
- // Only answer for question 0, missing answer for question 1
272
- {
273
- questionIndex: 0,
274
- selectedOption: "Option 1",
275
- timestamp: "2025-01-01T00:00:00Z",
276
- },
277
- ],
278
- sessionId: "test-123",
279
- timestamp: "2025-01-01T00:00:00Z",
280
- };
281
- const result = ResponseFormatter.formatUserResponse(answers, questions);
282
- // Should only include the answered question
283
- expect(result).toBe("Here are the user's answers:\n\n" + "1. Question 1\n" + "→ Option 1");
284
- });
285
- });
286
- describe("validateAnswers", () => {
287
- it("should validate correct answers", () => {
288
- const questions = [
289
- {
290
- options: [{ label: "Option 1" }, { label: "Option 2" }],
291
- prompt: "Test question",
292
- },
293
- ];
294
- const answers = {
295
- answers: [
296
- {
297
- questionIndex: 0,
298
- selectedOption: "Option 1",
299
- timestamp: "2025-01-01T00:00:00Z",
300
- },
301
- ],
302
- sessionId: "test-123",
303
- timestamp: "2025-01-01T00:00:00Z",
304
- };
305
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).not.toThrow();
306
- });
307
- it("should throw error for invalid question index", () => {
308
- const questions = [
309
- {
310
- options: [{ label: "Option 1" }],
311
- prompt: "Test question",
312
- },
313
- ];
314
- const answers = {
315
- answers: [
316
- {
317
- questionIndex: 99, // Invalid index
318
- selectedOption: "Option 1",
319
- timestamp: "2025-01-01T00:00:00Z",
320
- },
321
- ],
322
- sessionId: "test-123",
323
- timestamp: "2025-01-01T00:00:00Z",
324
- };
325
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).toThrow("Answer references invalid question index: 99");
326
- });
327
- it("should throw error for answer with neither selectedOption nor customText", () => {
328
- const questions = [
329
- {
330
- options: [{ label: "Option 1" }],
331
- prompt: "Test question",
332
- },
333
- ];
334
- const answers = {
335
- answers: [
336
- {
337
- questionIndex: 0,
338
- // Neither selectedOption nor customText provided
339
- timestamp: "2025-01-01T00:00:00Z",
340
- },
341
- ],
342
- sessionId: "test-123",
343
- timestamp: "2025-01-01T00:00:00Z",
344
- };
345
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).toThrow("has neither selectedOption nor customText");
346
- });
347
- it("should throw error for non-existent option", () => {
348
- const questions = [
349
- {
350
- options: [{ label: "Option 1" }, { label: "Option 2" }],
351
- prompt: "Test question",
352
- },
353
- ];
354
- const answers = {
355
- answers: [
356
- {
357
- questionIndex: 0,
358
- selectedOption: "Option 3", // Non-existent option
359
- timestamp: "2025-01-01T00:00:00Z",
360
- },
361
- ],
362
- sessionId: "test-123",
363
- timestamp: "2025-01-01T00:00:00Z",
364
- };
365
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).toThrow("references non-existent option: Option 3");
366
- });
367
- it("should validate custom text answers", () => {
368
- const questions = [
369
- {
370
- options: [{ label: "Option 1" }],
371
- prompt: "Test question",
372
- },
373
- ];
374
- const answers = {
375
- answers: [
376
- {
377
- customText: "My custom answer",
378
- questionIndex: 0,
379
- timestamp: "2025-01-01T00:00:00Z",
380
- },
381
- ],
382
- sessionId: "test-123",
383
- timestamp: "2025-01-01T00:00:00Z",
384
- };
385
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).not.toThrow();
386
- });
387
- it("should throw error for empty answers array", () => {
388
- const questions = [
389
- {
390
- options: [{ label: "Option 1" }],
391
- prompt: "Test question",
392
- },
393
- ];
394
- const answers = {
395
- answers: [],
396
- sessionId: "test-123",
397
- timestamp: "2025-01-01T00:00:00Z",
398
- };
399
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).toThrow("No answers provided");
400
- });
401
- it("should throw error for empty questions array", () => {
402
- const questions = [];
403
- const answers = {
404
- answers: [
405
- {
406
- questionIndex: 0,
407
- selectedOption: "Option 1",
408
- timestamp: "2025-01-01T00:00:00Z",
409
- },
410
- ],
411
- sessionId: "test-123",
412
- timestamp: "2025-01-01T00:00:00Z",
413
- };
414
- expect(() => ResponseFormatter.validateAnswers(answers, questions)).toThrow("No questions provided");
415
- });
416
- });
417
- });