auq-mcp-server 1.3.2 β 1.5.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/README.md +74 -42
- package/dist/bin/auq.js +2 -3
- package/dist/package.json +9 -5
- package/dist/src/server.js +2 -21
- package/dist/src/session/__tests__/utils.test.js +152 -0
- package/dist/src/session/utils.js +9 -42
- package/dist/src/shared/schemas.js +17 -11
- package/dist/src/tui/components/Header.js +1 -1
- package/dist/src/tui/session-watcher.js +1 -1
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -106,10 +106,7 @@ npm install auq-mcp-server
|
|
|
106
106
|
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
**
|
|
110
|
-
|
|
111
|
-
- **Global install**: `~/Library/Application Support/auq/sessions` (macOS), `~/.local/share/auq/sessions` (Linux)
|
|
112
|
-
- **Local install**: `.auq/sessions/` in your project root
|
|
109
|
+
**Note:** Sessions are stored globally regardless of installation method. See [Troubleshooting](#troubleshooting) for session locations.
|
|
113
110
|
|
|
114
111
|
---
|
|
115
112
|
|
|
@@ -208,7 +205,7 @@ Add to `opencode.json`:
|
|
|
208
205
|
|
|
209
206
|
```json
|
|
210
207
|
{
|
|
211
|
-
"plugin": ["@paulp-o/opencode-auq"]
|
|
208
|
+
"plugin": ["@paulp-o/opencode-auq@latest"]
|
|
212
209
|
}
|
|
213
210
|
```
|
|
214
211
|
|
|
@@ -219,8 +216,8 @@ Add to `opencode.json`:
|
|
|
219
216
|
### Starting the CLI tool
|
|
220
217
|
|
|
221
218
|
```bash
|
|
222
|
-
auq
|
|
223
|
-
npx auq #
|
|
219
|
+
auq # if installed globally (npm install -g)
|
|
220
|
+
npx auq # works from anywhere
|
|
224
221
|
```
|
|
225
222
|
|
|
226
223
|
Then just start working with your coding agent or AI assistant. You may prompt to ask questions with the tool the agent got; it will mostly just get what you mean.
|
|
@@ -234,66 +231,101 @@ auq --version # Show version
|
|
|
234
231
|
auq --help # Show help
|
|
235
232
|
```
|
|
236
233
|
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Manual session cleanup
|
|
237
|
+
|
|
238
|
+
Sessions auto-clean after completion or timeout. However, you can manually clean them up if you want to.
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
rm -rf ~/Library/Application\ Support/auq/sessions/* # macOS
|
|
242
|
+
rm -rf ~/.local/share/auq/sessions/* # Linux
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
237
247
|
<details>
|
|
238
|
-
<summary
|
|
248
|
+
<summary>Local Development & Testing</summary>
|
|
249
|
+
|
|
250
|
+
To test the MCP server and CLI locally during development:
|
|
239
251
|
|
|
240
|
-
|
|
252
|
+
### 1. Start the MCP Server (Terminal 1)
|
|
241
253
|
|
|
242
|
-
|
|
254
|
+
```bash
|
|
255
|
+
# Option A: Run with tsx (recommended for development)
|
|
256
|
+
npm run start
|
|
257
|
+
|
|
258
|
+
# Option B: Run with fastmcp dev mode (includes web inspector at http://localhost:6274)
|
|
259
|
+
npm run dev
|
|
260
|
+
|
|
261
|
+
# Option C: Run the built version
|
|
262
|
+
npm run build && npm run server
|
|
263
|
+
```
|
|
243
264
|
|
|
244
|
-
|
|
265
|
+
### 2. Create a Test Session (Terminal 2)
|
|
266
|
+
|
|
267
|
+
Use the `auq ask` command to create a session and wait for answers:
|
|
245
268
|
|
|
246
269
|
```bash
|
|
247
|
-
|
|
270
|
+
# Run directly with tsx during development
|
|
271
|
+
npx tsx bin/auq.tsx ask '{"questions": [{"prompt": "Which language?", "title": "Lang", "options": [{"label": "TypeScript"}, {"label": "Python"}], "multiSelect": false}]}'
|
|
272
|
+
|
|
273
|
+
# Or pipe JSON to stdin
|
|
274
|
+
echo '{"questions": [{"prompt": "Which database?", "title": "DB", "options": [{"label": "PostgreSQL"}, {"label": "MongoDB"}], "multiSelect": false}]}' | npx tsx bin/auq.tsx ask
|
|
248
275
|
```
|
|
249
276
|
|
|
250
|
-
|
|
277
|
+
This will create a session and wait for the TUI to provide answers.
|
|
251
278
|
|
|
252
|
-
|
|
279
|
+
### 3. Answer with the TUI (Terminal 3)
|
|
253
280
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
281
|
+
```bash
|
|
282
|
+
# Run the TUI to answer pending questions
|
|
283
|
+
npx tsx bin/auq.tsx
|
|
284
|
+
```
|
|
258
285
|
|
|
259
|
-
|
|
286
|
+
### Create Mock Sessions for TUI Testing
|
|
260
287
|
|
|
261
|
-
|
|
262
|
-
- **λ€μ€ μμ΄μ νΈ μ§μ**: μ¬λ¬ AI μμ΄μ νΈμ μ§λ¬Έμ λμμ μ²λ¦¬
|
|
263
|
-
- **μΈμ
κ΄λ¦¬**: κ° μ§λ¬Έ μΈνΈλ λ
립μ μΈ μΈμ
μΌλ‘ κ΄λ¦¬λ¨
|
|
264
|
-
- **νμμμ μ²λ¦¬**: μΌμ μκ° λμ μλ΅μ΄ μμΌλ©΄ μΈμ
μ΄ μλ μ’
λ£
|
|
288
|
+
To test the TUI with multiple pending sessions:
|
|
265
289
|
|
|
266
|
-
|
|
290
|
+
```bash
|
|
291
|
+
# Create 3 mock sessions (default)
|
|
292
|
+
npx tsx scripts/create-mock-session.ts
|
|
267
293
|
|
|
294
|
+
# Create a specific number of sessions
|
|
295
|
+
npx tsx scripts/create-mock-session.ts 5
|
|
268
296
|
```
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
297
|
+
|
|
298
|
+
Then run the TUI to see and answer them:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
npx tsx bin/auq.tsx
|
|
274
302
|
```
|
|
275
303
|
|
|
276
|
-
|
|
304
|
+
### Verify MCP and CLI Use Same Session Directory
|
|
305
|
+
|
|
306
|
+
Both components should report the same session directory path. Check the logs:
|
|
277
307
|
|
|
278
|
-
-
|
|
279
|
-
-
|
|
280
|
-
|
|
308
|
+
- MCP server logs session directory on startup
|
|
309
|
+
- `auq ask` prints `[AUQ] Session directory: <path>` to stderr
|
|
310
|
+
|
|
311
|
+
On macOS, both should use: `~/Library/Application Support/auq/sessions`
|
|
281
312
|
|
|
282
313
|
</details>
|
|
283
314
|
|
|
284
|
-
|
|
315
|
+
## Troubleshooting
|
|
285
316
|
|
|
286
|
-
###
|
|
317
|
+
### Session Storage
|
|
287
318
|
|
|
288
|
-
Sessions
|
|
319
|
+
Sessions are stored in platform-specific global locations:
|
|
289
320
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
rm -rf ~/.local/share/auq/sessions/* # Linux
|
|
321
|
+
- **macOS**: `~/Library/Application Support/auq/sessions`
|
|
322
|
+
- **Linux**: `~/.local/share/auq/sessions` (or `$XDG_DATA_HOME/auq/sessions`)
|
|
323
|
+
- **Windows**: `%APPDATA%\auq\sessions`
|
|
294
324
|
|
|
295
|
-
|
|
296
|
-
|
|
325
|
+
To override the default location, set the `AUQ_SESSION_DIR` environment variable:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
export AUQ_SESSION_DIR=/custom/path
|
|
297
329
|
```
|
|
298
330
|
|
|
299
331
|
---
|
package/dist/bin/auq.js
CHANGED
|
@@ -40,12 +40,11 @@ ASK COMMAND:
|
|
|
40
40
|
- Multi-select mode (multiSelect: true): User can select MULTIPLE options
|
|
41
41
|
|
|
42
42
|
USAGE NOTES:
|
|
43
|
-
-
|
|
43
|
+
- Provide a descriptive 'title' field (max 12 chars) for each question
|
|
44
44
|
- Use multiSelect: true when choices are not mutually exclusive
|
|
45
45
|
- Option labels should be concise (1-5 words)
|
|
46
|
-
-
|
|
46
|
+
- To mark a recommended option, append '(recommended)' to its label
|
|
47
47
|
- Don't include an 'Other' option - it's provided automatically
|
|
48
|
-
- Mark one option as recommended.
|
|
49
48
|
|
|
50
49
|
Returns a formatted summary of all questions and answers.
|
|
51
50
|
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auq-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"auq": "dist/bin/auq.js"
|
|
@@ -15,17 +15,16 @@
|
|
|
15
15
|
"packages/opencode-plugin"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "npm run sync-schemas && tsc",
|
|
18
|
+
"build": "npm run sync-plugin-schemas && tsc",
|
|
19
19
|
"prepare": "npm run build",
|
|
20
20
|
"postinstall": "node scripts/postinstall.cjs",
|
|
21
|
-
"deploy": "node scripts/deploy.mjs",
|
|
22
21
|
"release": "semantic-release",
|
|
23
22
|
"release:dry-run": "semantic-release --dry-run",
|
|
24
23
|
"server": "node dist/src/server.js",
|
|
25
24
|
"start": "tsx src/server.ts",
|
|
26
25
|
"dev": "fastmcp dev src/server.ts",
|
|
27
26
|
"lint": "prettier --check . && eslint . && tsc --noEmit",
|
|
28
|
-
"sync-schemas": "node scripts/sync-schemas.mjs",
|
|
27
|
+
"sync-plugin-schemas": "node scripts/sync-plugin-schemas.mjs",
|
|
29
28
|
"test": "vitest run",
|
|
30
29
|
"format": "prettier --write . && eslint --fix ."
|
|
31
30
|
},
|
|
@@ -72,7 +71,12 @@
|
|
|
72
71
|
"changelogFile": "CHANGELOG.md"
|
|
73
72
|
}
|
|
74
73
|
],
|
|
75
|
-
|
|
74
|
+
[
|
|
75
|
+
"@semantic-release/npm",
|
|
76
|
+
{
|
|
77
|
+
"workspaces": true
|
|
78
|
+
}
|
|
79
|
+
],
|
|
76
80
|
"@semantic-release/github"
|
|
77
81
|
]
|
|
78
82
|
},
|
package/dist/src/server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FastMCP } from "fastmcp";
|
|
2
2
|
import { randomUUID } from "crypto";
|
|
3
3
|
import { AskUserQuestionsParametersSchema, createAskUserQuestionsCore, } from "./core/ask-user-questions.js";
|
|
4
|
+
import { TOOL_DESCRIPTION } from "./shared/schemas.js";
|
|
4
5
|
const askUserQuestionsCore = createAskUserQuestionsCore();
|
|
5
6
|
const server = new FastMCP({
|
|
6
7
|
name: "AskUserQuestions",
|
|
@@ -17,27 +18,7 @@ server.addTool({
|
|
|
17
18
|
readOnlyHint: false, // This tool waits for user input
|
|
18
19
|
idempotentHint: true,
|
|
19
20
|
},
|
|
20
|
-
description:
|
|
21
|
-
"This allows you to:\n" +
|
|
22
|
-
"1. Gather user preferences or requirements\n" +
|
|
23
|
-
"2. Clarify ambiguous instructions\n" +
|
|
24
|
-
"3. Get decisions on implementation choices as you work\n" +
|
|
25
|
-
"4. Offer choices to the user about what direction to take\n\n" +
|
|
26
|
-
"FEATURES:\n" +
|
|
27
|
-
"- Ask 1-4 structured questions via an interactive terminal interface\n" +
|
|
28
|
-
"- Each question includes 2-4 multiple-choice options with explanatory descriptions\n" +
|
|
29
|
-
"- Users can always provide custom free-text input as an alternative to predefined options\n" +
|
|
30
|
-
"- Single-select mode (default): User picks ONE option or provides custom text\n" +
|
|
31
|
-
"- Multi-select mode (multiSelect: true): User can select MULTIPLE options\n\n" +
|
|
32
|
-
"USAGE NOTES:\n" +
|
|
33
|
-
"- Always provide a descriptive 'title' field (max 12 chars) for each question\n" +
|
|
34
|
-
"- Use multiSelect: true when choices are not mutually exclusive\n" +
|
|
35
|
-
"- Option labels should be concise (1-5 words)\n" +
|
|
36
|
-
"- Questions should end with a question mark\n" +
|
|
37
|
-
"- Don't include an 'Other' option - it's provided automatically\n" +
|
|
38
|
-
"- Mark one option as recommended.\n\n" +
|
|
39
|
-
"- If user seems not aware how to answer the question, inform them that they need to install the 'auq' cli tool.\n\n" +
|
|
40
|
-
"Returns a formatted summary of all questions and answers.",
|
|
21
|
+
description: TOOL_DESCRIPTION,
|
|
41
22
|
execute: async (args, ctx) => {
|
|
42
23
|
const { log } = ctx;
|
|
43
24
|
try {
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for session utility functions
|
|
3
|
+
*/
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { getSessionDirectory, resolveSessionDirectory } from "../utils.js";
|
|
7
|
+
describe("session utilities", () => {
|
|
8
|
+
const originalEnv = { ...process.env };
|
|
9
|
+
const originalPlatform = process.platform;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// Reset process.env to original state before each test
|
|
12
|
+
process.env = { ...originalEnv };
|
|
13
|
+
vi.restoreAllMocks();
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
// Clean up process.env after each test
|
|
17
|
+
process.env = { ...originalEnv };
|
|
18
|
+
});
|
|
19
|
+
describe("getSessionDirectory", () => {
|
|
20
|
+
it("should return macOS XDG path when no env var is set", () => {
|
|
21
|
+
// Mock platform to macOS
|
|
22
|
+
vi.stubGlobal("process", {
|
|
23
|
+
...process,
|
|
24
|
+
platform: "darwin",
|
|
25
|
+
});
|
|
26
|
+
// Ensure AUQ_SESSION_DIR is not set
|
|
27
|
+
delete process.env.AUQ_SESSION_DIR;
|
|
28
|
+
const result = getSessionDirectory();
|
|
29
|
+
expect(result).toBe(`${homedir()}/Library/Application Support/auq/sessions`);
|
|
30
|
+
});
|
|
31
|
+
it("should return Linux XDG path when no env var is set", () => {
|
|
32
|
+
// Mock platform to Linux
|
|
33
|
+
vi.stubGlobal("process", {
|
|
34
|
+
...process,
|
|
35
|
+
platform: "linux",
|
|
36
|
+
});
|
|
37
|
+
// Ensure AUQ_SESSION_DIR is not set
|
|
38
|
+
delete process.env.AUQ_SESSION_DIR;
|
|
39
|
+
const result = getSessionDirectory();
|
|
40
|
+
expect(result).toBe(`${homedir()}/.local/share/auq/sessions`);
|
|
41
|
+
});
|
|
42
|
+
it("should use AUQ_SESSION_DIR env var when set", () => {
|
|
43
|
+
const customDir = "/custom/session/dir";
|
|
44
|
+
process.env.AUQ_SESSION_DIR = customDir;
|
|
45
|
+
const result = getSessionDirectory();
|
|
46
|
+
expect(result).toBe(customDir);
|
|
47
|
+
});
|
|
48
|
+
it("should expand tilde in AUQ_SESSION_DIR env var", () => {
|
|
49
|
+
process.env.AUQ_SESSION_DIR = "~/custom/sessions";
|
|
50
|
+
const result = getSessionDirectory();
|
|
51
|
+
expect(result).toBe(`${homedir()}/custom/sessions`);
|
|
52
|
+
});
|
|
53
|
+
it("should not expand tilde when AUQ_SESSION_DIR does not start with ~", () => {
|
|
54
|
+
const customDir = "/absolute/path/to/sessions";
|
|
55
|
+
process.env.AUQ_SESSION_DIR = customDir;
|
|
56
|
+
const result = getSessionDirectory();
|
|
57
|
+
expect(result).toBe(customDir);
|
|
58
|
+
});
|
|
59
|
+
it("should prefer AUQ_SESSION_DIR over XDG path", () => {
|
|
60
|
+
const customDir = "/custom/sessions";
|
|
61
|
+
process.env.AUQ_SESSION_DIR = customDir;
|
|
62
|
+
// Mock platform to macOS
|
|
63
|
+
vi.stubGlobal("process", {
|
|
64
|
+
...process,
|
|
65
|
+
platform: "darwin",
|
|
66
|
+
});
|
|
67
|
+
const result = getSessionDirectory();
|
|
68
|
+
// Should use env var, not the macOS default
|
|
69
|
+
expect(result).toBe(customDir);
|
|
70
|
+
expect(result).not.toBe(`${homedir()}/Library/Application Support/auq/sessions`);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe("resolveSessionDirectory", () => {
|
|
74
|
+
it("should return macOS path when platform is darwin", () => {
|
|
75
|
+
vi.stubGlobal("process", {
|
|
76
|
+
...process,
|
|
77
|
+
platform: "darwin",
|
|
78
|
+
});
|
|
79
|
+
const result = resolveSessionDirectory();
|
|
80
|
+
expect(result).toBe(`${homedir()}/Library/Application Support/auq/sessions`);
|
|
81
|
+
});
|
|
82
|
+
it("should return Linux path when platform is linux", () => {
|
|
83
|
+
vi.stubGlobal("process", {
|
|
84
|
+
...process,
|
|
85
|
+
platform: "linux",
|
|
86
|
+
});
|
|
87
|
+
const result = resolveSessionDirectory();
|
|
88
|
+
expect(result).toBe(`${homedir()}/.local/share/auq/sessions`);
|
|
89
|
+
});
|
|
90
|
+
it("should return Windows path when platform is win32 with APPDATA", () => {
|
|
91
|
+
vi.stubGlobal("process", {
|
|
92
|
+
...process,
|
|
93
|
+
platform: "win32",
|
|
94
|
+
env: {
|
|
95
|
+
...process.env,
|
|
96
|
+
APPDATA: "C:/Users/Test/AppData/Roaming",
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
const result = resolveSessionDirectory();
|
|
100
|
+
// Note: join() uses forward slashes when running on Unix systems
|
|
101
|
+
expect(result).toBe("C:/Users/Test/AppData/Roaming/auq/sessions");
|
|
102
|
+
});
|
|
103
|
+
it("should return Windows path with USERPROFILE fallback when APPDATA not set", () => {
|
|
104
|
+
vi.stubGlobal("process", {
|
|
105
|
+
...process,
|
|
106
|
+
platform: "win32",
|
|
107
|
+
env: {
|
|
108
|
+
...process.env,
|
|
109
|
+
APPDATA: undefined,
|
|
110
|
+
USERPROFILE: "C:/Users/Test",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const result = resolveSessionDirectory();
|
|
114
|
+
// Note: join() uses forward slashes when running on Unix systems
|
|
115
|
+
expect(result).toBe("C:/Users/Test/auq/sessions");
|
|
116
|
+
});
|
|
117
|
+
it("should return Linux XDG_DATA_HOME path when env var is set", () => {
|
|
118
|
+
vi.stubGlobal("process", {
|
|
119
|
+
...process,
|
|
120
|
+
platform: "linux",
|
|
121
|
+
env: {
|
|
122
|
+
...process.env,
|
|
123
|
+
XDG_DATA_HOME: "/custom/xdg/data",
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const result = resolveSessionDirectory();
|
|
127
|
+
expect(result).toBe("/custom/xdg/data/auq/sessions");
|
|
128
|
+
});
|
|
129
|
+
it("should expand tilde in provided baseDir", () => {
|
|
130
|
+
const result = resolveSessionDirectory("~/custom/base");
|
|
131
|
+
expect(result).toBe(`${homedir()}/custom/base`);
|
|
132
|
+
});
|
|
133
|
+
it("should use provided baseDir when it does not start with tilde", () => {
|
|
134
|
+
const result = resolveSessionDirectory("/absolute/custom/path");
|
|
135
|
+
expect(result).toBe("/absolute/custom/path");
|
|
136
|
+
});
|
|
137
|
+
it("should handle other Unix platforms (e.g., freebsd)", () => {
|
|
138
|
+
vi.stubGlobal("process", {
|
|
139
|
+
...process,
|
|
140
|
+
platform: "freebsd",
|
|
141
|
+
});
|
|
142
|
+
const result = resolveSessionDirectory();
|
|
143
|
+
expect(result).toBe(`${homedir()}/.local/share/auq/sessions`);
|
|
144
|
+
});
|
|
145
|
+
it("should handle empty baseDir parameter", () => {
|
|
146
|
+
const result = resolveSessionDirectory("");
|
|
147
|
+
// Should treat empty string as falsy and use default XDG path
|
|
148
|
+
expect(result).toContain(homedir());
|
|
149
|
+
expect(result).toContain("auq/sessions");
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for session management
|
|
3
3
|
*/
|
|
4
|
-
import { constants
|
|
4
|
+
import { constants } from "fs";
|
|
5
5
|
import { promises as fs } from "fs";
|
|
6
6
|
import { homedir } from "os";
|
|
7
7
|
import { join } from "path";
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
9
8
|
/**
|
|
10
9
|
* Create a safe filename from a session ID (basic validation)
|
|
11
10
|
*/
|
|
@@ -125,39 +124,13 @@ export async function validateSessionDirectory(baseDir) {
|
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
126
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const parts = __filename.split(/[/\\]/); // Handle both Unix and Windows separators
|
|
136
|
-
// Find the last occurrence of 'node_modules' in the path
|
|
137
|
-
const nodeModulesIndex = parts.lastIndexOf("node_modules");
|
|
138
|
-
if (nodeModulesIndex === -1) {
|
|
139
|
-
// Not in node_modules (development or global install without node_modules in path)
|
|
140
|
-
return { mode: "global" };
|
|
141
|
-
}
|
|
142
|
-
// We're inside node_modules - check if there's a project package.json above
|
|
143
|
-
const potentialProjectRoot = parts.slice(0, nodeModulesIndex).join("/");
|
|
144
|
-
const packageJsonPath = join(potentialProjectRoot, "package.json");
|
|
145
|
-
if (existsSync(packageJsonPath)) {
|
|
146
|
-
// Found a package.json above node_modules β local install
|
|
147
|
-
return { mode: "local", projectRoot: potentialProjectRoot };
|
|
148
|
-
}
|
|
149
|
-
// In node_modules but no project context β global install
|
|
150
|
-
return { mode: "global" };
|
|
151
|
-
}
|
|
152
|
-
catch (error) {
|
|
153
|
-
// Fallback to global mode if detection fails
|
|
154
|
-
console.error("[AUQ] Failed to detect install mode:", error);
|
|
155
|
-
return { mode: "global" };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Get the appropriate session directory based on installation mode
|
|
160
|
-
* Supports environment variable override via AUQ_SESSION_DIR
|
|
127
|
+
* Get the session directory path.
|
|
128
|
+
* Always uses global XDG-compliant paths to ensure MCP server and CLI
|
|
129
|
+
* always find each other's sessions regardless of installation location.
|
|
130
|
+
*
|
|
131
|
+
* Priority:
|
|
132
|
+
* 1. AUQ_SESSION_DIR environment variable (if set)
|
|
133
|
+
* 2. Platform-specific XDG-compliant path
|
|
161
134
|
*/
|
|
162
135
|
export function getSessionDirectory() {
|
|
163
136
|
// Check for environment variable override first
|
|
@@ -169,12 +142,6 @@ export function getSessionDirectory() {
|
|
|
169
142
|
}
|
|
170
143
|
return envDir;
|
|
171
144
|
}
|
|
172
|
-
//
|
|
173
|
-
const { mode, projectRoot } = detectInstallMode();
|
|
174
|
-
if (mode === "local" && projectRoot) {
|
|
175
|
-
// Local install: use project-relative .auq/sessions directory
|
|
176
|
-
return join(projectRoot, ".auq", "sessions");
|
|
177
|
-
}
|
|
178
|
-
// Global install: use XDG-compliant system paths
|
|
145
|
+
// Always use global XDG-compliant paths
|
|
179
146
|
return resolveSessionDirectory();
|
|
180
147
|
}
|
|
@@ -2,8 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
export const OptionSchema = z.object({
|
|
3
3
|
label: z
|
|
4
4
|
.string()
|
|
5
|
-
.describe("The display text for this option
|
|
6
|
-
"
|
|
5
|
+
.describe("The display text for this option. Should be concise (1-5 words). " +
|
|
6
|
+
"To mark as recommended, append '(recommended)' to the label text."),
|
|
7
7
|
description: z
|
|
8
8
|
.string()
|
|
9
9
|
.optional()
|
|
@@ -38,13 +38,19 @@ export const QuestionsSchema = z.array(QuestionSchema).min(1).max(4);
|
|
|
38
38
|
export const AskUserQuestionsParametersSchema = z.object({
|
|
39
39
|
questions: QuestionsSchema.describe("Questions to ask the user (1-4 questions). " +
|
|
40
40
|
"Each question must include: prompt (full question text), title (short label, max 12 chars), " +
|
|
41
|
-
"options (2-4 choices with labels and descriptions), and multiSelect (boolean).
|
|
42
|
-
"Mark one choice as recommended if possible."),
|
|
41
|
+
"options (2-4 choices with labels and descriptions), and multiSelect (boolean)."),
|
|
43
42
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
43
|
+
/**
|
|
44
|
+
* Comprehensive tool description - single source of truth.
|
|
45
|
+
* Used by MCP server and should be synced to opencode-plugin.
|
|
46
|
+
*/
|
|
47
|
+
export const TOOL_DESCRIPTION = "Use this tool when you need to ask the user questions during execution. This allows you to:\n\n" +
|
|
48
|
+
"Gather user preferences or requirements\n" +
|
|
49
|
+
"Clarify ambiguous instructions\n" +
|
|
50
|
+
"Get decisions on implementation choices as you work\n" +
|
|
51
|
+
"Offer choices to the user about what direction to take.\n" +
|
|
52
|
+
"Usage notes:\n\n" +
|
|
53
|
+
"Users will always be able to select \"Other\" to provide custom text input\n" +
|
|
54
|
+
"Use multiSelect: true to allow multiple answers to be selected for a question\n" +
|
|
55
|
+
"Recommend an option unless absolutely necessary, make it the first option in the list and add \"(Recommended)\" at the end of the label\n" +
|
|
56
|
+
"Do NOT use this tool to ask \"Is my plan ready?\" or \"Should I proceed?\"";
|
|
@@ -24,7 +24,7 @@ export const Header = ({ pendingCount }) => {
|
|
|
24
24
|
return packageJson.version || "unknown";
|
|
25
25
|
}, []);
|
|
26
26
|
// Use the selected gradient theme from theme.ts
|
|
27
|
-
const headerText = gradient[theme.headerGradient](".π₯ AUQ β Ask User Questions
|
|
27
|
+
const headerText = gradient[theme.headerGradient](".π₯ AUQ β Ask User Questions β ");
|
|
28
28
|
return (React.createElement(Box, { borderColor: theme.components.header.border, borderStyle: "single", flexDirection: "row", justifyContent: "space-between", paddingX: 1 },
|
|
29
29
|
React.createElement(Text, { bold: true }, headerText),
|
|
30
30
|
React.createElement(Box, null,
|
|
@@ -164,7 +164,7 @@ export class EnhancedTUISessionWatcher extends TUISessionWatcher {
|
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
166
|
* Create a simple TUI session watcher instance
|
|
167
|
-
*
|
|
167
|
+
* Uses global XDG-compliant session directory path
|
|
168
168
|
*/
|
|
169
169
|
export function createTUIWatcher(config) {
|
|
170
170
|
// Auto-detect session directory if not provided in config
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auq-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"auq": "dist/bin/auq.js"
|
|
@@ -15,17 +15,16 @@
|
|
|
15
15
|
"packages/opencode-plugin"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "npm run sync-schemas && tsc",
|
|
18
|
+
"build": "npm run sync-plugin-schemas && tsc",
|
|
19
19
|
"prepare": "npm run build",
|
|
20
20
|
"postinstall": "node scripts/postinstall.cjs",
|
|
21
|
-
"deploy": "node scripts/deploy.mjs",
|
|
22
21
|
"release": "semantic-release",
|
|
23
22
|
"release:dry-run": "semantic-release --dry-run",
|
|
24
23
|
"server": "node dist/src/server.js",
|
|
25
24
|
"start": "tsx src/server.ts",
|
|
26
25
|
"dev": "fastmcp dev src/server.ts",
|
|
27
26
|
"lint": "prettier --check . && eslint . && tsc --noEmit",
|
|
28
|
-
"sync-schemas": "node scripts/sync-schemas.mjs",
|
|
27
|
+
"sync-plugin-schemas": "node scripts/sync-plugin-schemas.mjs",
|
|
29
28
|
"test": "vitest run",
|
|
30
29
|
"format": "prettier --write . && eslint --fix ."
|
|
31
30
|
},
|
|
@@ -72,7 +71,12 @@
|
|
|
72
71
|
"changelogFile": "CHANGELOG.md"
|
|
73
72
|
}
|
|
74
73
|
],
|
|
75
|
-
|
|
74
|
+
[
|
|
75
|
+
"@semantic-release/npm",
|
|
76
|
+
{
|
|
77
|
+
"workspaces": true
|
|
78
|
+
}
|
|
79
|
+
],
|
|
76
80
|
"@semantic-release/github"
|
|
77
81
|
]
|
|
78
82
|
},
|