auq-mcp-server 1.2.6 → 1.2.8

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/dist/bin/auq.js CHANGED
@@ -3,14 +3,7 @@
3
3
  import { readFileSync } from "fs";
4
4
  import { dirname, join } from "path";
5
5
  import { fileURLToPath } from "url";
6
- import { Box, render, Text } from "ink";
7
- import React, { useEffect, useState } from "react";
8
- import { ensureDirectoryExists, getSessionDirectory, } from "../src/session/utils.js";
9
- import { Header } from "../src/tui/components/Header.js";
10
- import { StepperView } from "../src/tui/components/StepperView.js";
11
- import { Toast } from "../src/tui/components/Toast.js";
12
- import { WaitingScreen } from "../src/tui/components/WaitingScreen.js";
13
- import { createTUIWatcher } from "../src/tui/session-watcher.js";
6
+ import { getSessionDirectory } from "../src/session/utils.js";
14
7
  // import { goodbyeText } from "../src/tui/utils/gradientText.js";
15
8
  // Handle command-line arguments
16
9
  const args = process.argv.slice(2);
@@ -180,164 +173,11 @@ if (command === "ask") {
180
173
  process.exit(1);
181
174
  }
182
175
  }
183
- const App = () => {
184
- const [state, setState] = useState({ mode: "WAITING" });
185
- const [sessionQueue, setSessionQueue] = useState([]);
186
- const [isInitialized, setIsInitialized] = useState(false);
187
- const [toast, setToast] = useState(null);
188
- const [showSessionLog, setShowSessionLog] = useState(true);
189
- // Get session directory for logging
190
- const sessionDir = getSessionDirectory();
191
- // Auto-hide session log after 3 seconds
192
- useEffect(() => {
193
- const timer = setTimeout(() => {
194
- setShowSessionLog(false);
195
- }, 3000);
196
- return () => clearTimeout(timer);
197
- }, []);
198
- // Initialize: Load existing sessions + start persistent watcher
199
- useEffect(() => {
200
- let watcherInstance = null;
201
- const initialize = async () => {
202
- try {
203
- // Step 0: Ensure session directory exists
204
- await ensureDirectoryExists(sessionDir);
205
- // Step 1: Load existing pending sessions
206
- const watcher = createTUIWatcher();
207
- const sessionIds = await watcher.getPendingSessions();
208
- const sessionData = await Promise.all(sessionIds.map(async (sessionId) => {
209
- const sessionRequest = await watcher.getSessionRequest(sessionId);
210
- if (!sessionRequest)
211
- return null;
212
- return {
213
- sessionId,
214
- sessionRequest,
215
- timestamp: new Date(sessionRequest.timestamp),
216
- };
217
- }));
218
- // Filter out null entries and sort by timestamp (FIFO - oldest first)
219
- const validSessions = sessionData
220
- .filter((s) => s !== null)
221
- .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
222
- setSessionQueue(validSessions);
223
- setIsInitialized(true);
224
- // Step 2: Start persistent watcher for new sessions
225
- watcherInstance = createTUIWatcher({ autoLoadData: true });
226
- watcherInstance.startEnhancedWatching((event) => {
227
- // Add new session to queue (FIFO - append to end)
228
- setSessionQueue((prev) => {
229
- // Check for duplicates
230
- if (prev.some((s) => s.sessionId === event.sessionId)) {
231
- return prev;
232
- }
233
- // Add to end of queue
234
- return [
235
- ...prev,
236
- {
237
- sessionId: event.sessionId,
238
- sessionRequest: event.sessionRequest,
239
- timestamp: new Date(event.timestamp),
240
- },
241
- ];
242
- });
243
- });
244
- }
245
- catch (error) {
246
- console.error("Failed to initialize:", error);
247
- setIsInitialized(true); // Continue even if initialization fails
248
- }
249
- };
250
- initialize();
251
- // Cleanup: stop watcher on unmount
252
- return () => {
253
- if (watcherInstance) {
254
- watcherInstance.stop();
255
- }
256
- };
257
- }, []);
258
- // Auto-transition: WAITING → PROCESSING when queue has items
259
- useEffect(() => {
260
- if (!isInitialized)
261
- return;
262
- if (state.mode === "WAITING" && sessionQueue.length > 0) {
263
- const [nextSession, ...rest] = sessionQueue;
264
- setSessionQueue(rest);
265
- setState({ mode: "PROCESSING", session: nextSession });
266
- }
267
- }, [state, sessionQueue, isInitialized]);
268
- // Show toast notification
269
- const showToast = (message, type = "success", title) => {
270
- setToast({ message, type, title });
271
- };
272
- // Handle session completion
273
- const handleSessionComplete = (wasRejected = false, rejectionReason) => {
274
- // Show appropriate toast
275
- if (wasRejected) {
276
- if (rejectionReason) {
277
- showToast(`Rejection reason: ${rejectionReason}`, "info", "Question set rejected");
278
- }
279
- else {
280
- showToast("", "info", "Question set rejected");
281
- }
282
- }
283
- else {
284
- showToast("✓ Answers submitted successfully!", "success");
285
- }
286
- if (sessionQueue.length > 0) {
287
- // Auto-load next session
288
- const [nextSession, ...rest] = sessionQueue;
289
- setSessionQueue(rest);
290
- setState({ mode: "PROCESSING", session: nextSession });
291
- }
292
- else {
293
- // Return to WAITING
294
- setState({ mode: "WAITING" });
295
- }
296
- };
297
- // Render based on state
298
- if (!isInitialized) {
299
- return React.createElement(Text, null, "Loading...");
300
- }
301
- let mainContent;
302
- if (state.mode === "WAITING") {
303
- mainContent = React.createElement(WaitingScreen, { queueCount: sessionQueue.length });
304
- }
305
- else {
306
- // PROCESSING mode
307
- const { session } = state;
308
- mainContent = (React.createElement(StepperView, { key: session.sessionId, onComplete: handleSessionComplete, sessionId: session.sessionId, sessionRequest: session.sessionRequest }));
309
- }
310
- // Render with header, toast overlay, and main content
311
- return (React.createElement(Box, { flexDirection: "column", paddingX: 1 },
312
- React.createElement(Header, { pendingCount: sessionQueue.length }),
313
- toast && (React.createElement(Box, { marginBottom: 1, marginTop: 1 },
314
- React.createElement(Toast, { message: toast.message, onDismiss: () => setToast(null), type: toast.type, title: toast.title }))),
315
- mainContent,
316
- showSessionLog && (React.createElement(Box, { marginTop: 1 },
317
- React.createElement(Text, { dimColor: true },
318
- "[AUQ] Session directory: ",
319
- sessionDir)))));
320
- };
321
- // Clear terminal before showing app
322
- console.clear();
323
- const { waitUntilExit } = render(React.createElement(App, null));
324
- // Periodically clear performance measures to prevent memory leak warnings
325
- // React development mode creates performance marks that can accumulate over time
326
- const clearPerformanceBuffer = () => {
327
- if (typeof performance !== 'undefined' && performance.clearMeasures) {
328
- performance.clearMeasures();
329
- }
330
- };
331
- // Clear performance buffer every 5 minutes to prevent accumulation
332
- const performanceCleanupInterval = setInterval(clearPerformanceBuffer, 5 * 60 * 1000);
333
- // Handle Ctrl+C gracefully
334
- process.on("SIGINT", () => {
335
- clearInterval(performanceCleanupInterval);
336
- process.exit(0);
337
- });
338
- // Show goodbye after Ink unmounts
339
- waitUntilExit().then(() => {
340
- clearInterval(performanceCleanupInterval);
341
- process.stdout.write("\n");
342
- console.log("👋 Goodbye! See you next time.");
343
- });
176
+ // Default: Start TUI
177
+ // Important: Lazy-load Ink/React so non-interactive commands (ask/server) don't pull them in.
178
+ // Also force production mode before importing React/Ink to avoid perf_hooks measure accumulation warnings.
179
+ if (!process.env.NODE_ENV) {
180
+ process.env.NODE_ENV = "production";
181
+ }
182
+ const { runTui } = await import("./tui-app.js");
183
+ runTui();
@@ -0,0 +1,160 @@
1
+ import { Box, render, Text } from "ink";
2
+ import React, { useEffect, useState } from "react";
3
+ import { ensureDirectoryExists, getSessionDirectory, } from "../src/session/utils.js";
4
+ import { Header } from "../src/tui/components/Header.js";
5
+ import { StepperView } from "../src/tui/components/StepperView.js";
6
+ import { Toast } from "../src/tui/components/Toast.js";
7
+ import { WaitingScreen } from "../src/tui/components/WaitingScreen.js";
8
+ import { createTUIWatcher } from "../src/tui/session-watcher.js";
9
+ const App = () => {
10
+ const [state, setState] = useState({ mode: "WAITING" });
11
+ const [sessionQueue, setSessionQueue] = useState([]);
12
+ const [isInitialized, setIsInitialized] = useState(false);
13
+ const [toast, setToast] = useState(null);
14
+ const [showSessionLog, setShowSessionLog] = useState(true);
15
+ // Get session directory for logging
16
+ const sessionDir = getSessionDirectory();
17
+ // Auto-hide session log after 3 seconds
18
+ useEffect(() => {
19
+ const timer = setTimeout(() => {
20
+ setShowSessionLog(false);
21
+ }, 3000);
22
+ return () => clearTimeout(timer);
23
+ }, []);
24
+ // Initialize: Load existing sessions + start persistent watcher
25
+ useEffect(() => {
26
+ let watcherInstance = null;
27
+ const initialize = async () => {
28
+ try {
29
+ // Step 0: Ensure session directory exists
30
+ await ensureDirectoryExists(sessionDir);
31
+ // Step 1: Load existing pending sessions
32
+ const watcher = createTUIWatcher();
33
+ const sessionIds = await watcher.getPendingSessions();
34
+ const sessionData = await Promise.all(sessionIds.map(async (sessionId) => {
35
+ const sessionRequest = await watcher.getSessionRequest(sessionId);
36
+ if (!sessionRequest)
37
+ return null;
38
+ return {
39
+ sessionId,
40
+ sessionRequest,
41
+ timestamp: new Date(sessionRequest.timestamp),
42
+ };
43
+ }));
44
+ // Filter out null entries and sort by timestamp (FIFO - oldest first)
45
+ const validSessions = sessionData
46
+ .filter((s) => s !== null)
47
+ .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
48
+ setSessionQueue(validSessions);
49
+ setIsInitialized(true);
50
+ // Step 2: Start persistent watcher for new sessions
51
+ watcherInstance = createTUIWatcher({ autoLoadData: true });
52
+ watcherInstance.startEnhancedWatching((event) => {
53
+ // Add new session to queue (FIFO - append to end)
54
+ setSessionQueue((prev) => {
55
+ // Check for duplicates
56
+ if (prev.some((s) => s.sessionId === event.sessionId)) {
57
+ return prev;
58
+ }
59
+ // Add to end of queue
60
+ return [
61
+ ...prev,
62
+ {
63
+ sessionId: event.sessionId,
64
+ sessionRequest: event.sessionRequest,
65
+ timestamp: new Date(event.timestamp),
66
+ },
67
+ ];
68
+ });
69
+ });
70
+ }
71
+ catch (error) {
72
+ console.error("Failed to initialize:", error);
73
+ setIsInitialized(true); // Continue even if initialization fails
74
+ }
75
+ };
76
+ initialize();
77
+ // Cleanup: stop watcher on unmount
78
+ return () => {
79
+ if (watcherInstance) {
80
+ watcherInstance.stop();
81
+ }
82
+ };
83
+ }, []);
84
+ // Auto-transition: WAITING → PROCESSING when queue has items
85
+ useEffect(() => {
86
+ if (!isInitialized)
87
+ return;
88
+ if (state.mode === "WAITING" && sessionQueue.length > 0) {
89
+ const [nextSession, ...rest] = sessionQueue;
90
+ setSessionQueue(rest);
91
+ setState({ mode: "PROCESSING", session: nextSession });
92
+ }
93
+ }, [state, sessionQueue, isInitialized]);
94
+ // Show toast notification
95
+ const showToast = (message, type = "success", title) => {
96
+ setToast({ message, type, title });
97
+ };
98
+ // Handle session completion
99
+ const handleSessionComplete = (wasRejected = false, rejectionReason) => {
100
+ // Show appropriate toast
101
+ if (wasRejected) {
102
+ if (rejectionReason) {
103
+ showToast(`Rejection reason: ${rejectionReason}`, "info", "Question set rejected");
104
+ }
105
+ else {
106
+ showToast("", "info", "Question set rejected");
107
+ }
108
+ }
109
+ else {
110
+ showToast("✓ Answers submitted successfully!", "success");
111
+ }
112
+ if (sessionQueue.length > 0) {
113
+ // Auto-load next session
114
+ const [nextSession, ...rest] = sessionQueue;
115
+ setSessionQueue(rest);
116
+ setState({ mode: "PROCESSING", session: nextSession });
117
+ }
118
+ else {
119
+ // Return to WAITING
120
+ setState({ mode: "WAITING" });
121
+ }
122
+ };
123
+ // Render based on state
124
+ if (!isInitialized) {
125
+ return React.createElement(Text, null, "Loading...");
126
+ }
127
+ let mainContent;
128
+ if (state.mode === "WAITING") {
129
+ mainContent = React.createElement(WaitingScreen, { queueCount: sessionQueue.length });
130
+ }
131
+ else {
132
+ // PROCESSING mode
133
+ const { session } = state;
134
+ mainContent = (React.createElement(StepperView, { key: session.sessionId, onComplete: handleSessionComplete, sessionId: session.sessionId, sessionRequest: session.sessionRequest }));
135
+ }
136
+ // Render with header, toast overlay, and main content
137
+ return (React.createElement(Box, { flexDirection: "column", paddingX: 1 },
138
+ React.createElement(Header, { pendingCount: sessionQueue.length }),
139
+ toast && (React.createElement(Box, { marginBottom: 1, marginTop: 1 },
140
+ React.createElement(Toast, { message: toast.message, onDismiss: () => setToast(null), type: toast.type, title: toast.title }))),
141
+ mainContent,
142
+ showSessionLog && (React.createElement(Box, { marginTop: 1 },
143
+ React.createElement(Text, { dimColor: true },
144
+ "[AUQ] Session directory: ",
145
+ sessionDir)))));
146
+ };
147
+ export const runTui = () => {
148
+ // Clear terminal before showing app
149
+ console.clear();
150
+ const { waitUntilExit } = render(React.createElement(App, null));
151
+ // Handle Ctrl+C gracefully
152
+ process.on("SIGINT", () => {
153
+ process.exit(0);
154
+ });
155
+ // Show goodbye after Ink unmounts
156
+ waitUntilExit().then(() => {
157
+ process.stdout.write("\n");
158
+ console.log("👋 Goodbye! See you next time.");
159
+ });
160
+ };
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auq-mcp-server",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "auq": "dist/bin/auq.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auq-mcp-server",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "auq": "dist/bin/auq.js"