@achieveai/hitl-mcp-server 1.2.0 → 2.1.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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +131 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/git-context.d.ts +7 -0
- package/dist/git-context.d.ts.map +1 -0
- package/dist/git-context.js +29 -0
- package/dist/git-context.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +237 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/ntfy-transport.d.ts +41 -0
- package/dist/ntfy-transport.d.ts.map +1 -0
- package/dist/ntfy-transport.js +150 -0
- package/dist/ntfy-transport.js.map +1 -0
- package/dist/setup.d.ts +43 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +184 -0
- package/dist/setup.js.map +1 -0
- package/package.json +61 -63
- package/scripts/postinstall.js +33 -0
- package/LICENSE +0 -20
- package/README.md +0 -422
- package/config/claude-desktop.json +0 -11
- package/config/cursor-mcp.json +0 -17
- package/config/vscode-mcp.json +0 -17
- package/dist/__tests__/dialog-manager.test.d.ts +0 -2
- package/dist/__tests__/dialog-manager.test.d.ts.map +0 -1
- package/dist/__tests__/dialog-manager.test.js +0 -140
- package/dist/__tests__/dialog-manager.test.js.map +0 -1
- package/dist/dialog-manager.d.ts +0 -37
- package/dist/dialog-manager.d.ts.map +0 -1
- package/dist/dialog-manager.js +0 -644
- package/dist/dialog-manager.js.map +0 -1
- package/dist/dialog-manager.test.d.ts +0 -2
- package/dist/dialog-manager.test.d.ts.map +0 -1
- package/dist/dialog-manager.test.js +0 -156
- package/dist/dialog-manager.test.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -222
- package/dist/index.js.map +0 -1
- package/dist/test-client.d.ts +0 -3
- package/dist/test-client.d.ts.map +0 -1
- package/dist/test-client.js +0 -125
- package/dist/test-client.js.map +0 -1
- package/dist/test-dialog-manager.d.ts +0 -2
- package/dist/test-dialog-manager.d.ts.map +0 -1
- package/dist/test-dialog-manager.js +0 -156
- package/dist/test-dialog-manager.js.map +0 -1
- package/example-usage.md +0 -223
- package/mcp.json +0 -152
- package/sounds/notification.wav +0 -0
package/README.md
DELETED
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
# Human In The Loop MCP Server
|
|
2
|
-
|
|
3
|
-
A Model Context Protocol (MCP) server that bridges the gap between AI autonomy and human oversight by enabling LLM agents to request human input at critical decision points.
|
|
4
|
-
|
|
5
|
-
## What This Tool Does
|
|
6
|
-
|
|
7
|
-
This MCP server allows AI agents like Claude to pause their execution and ask humans for guidance through interactive browser-based dialogs. Instead of making assumptions or failing when faced with ambiguity, AI agents can now gracefully request human input and continue with confidence.
|
|
8
|
-
|
|
9
|
-
## Real-World Use Cases
|
|
10
|
-
|
|
11
|
-
### 1. **Code Generation Decisions**
|
|
12
|
-
When generating code, the AI can ask:
|
|
13
|
-
- "Which framework should I use: React, Vue, or Angular?"
|
|
14
|
-
- "Should I implement this with TypeScript or JavaScript?"
|
|
15
|
-
- "Which testing framework do you prefer?"
|
|
16
|
-
|
|
17
|
-
### 2. **Deployment & Operations**
|
|
18
|
-
- "Ready to deploy to production? I've run all tests."
|
|
19
|
-
- "Should I rollback the deployment? Errors detected."
|
|
20
|
-
- "Which environment: staging or production?"
|
|
21
|
-
|
|
22
|
-
### 3. **Data Processing**
|
|
23
|
-
- "Found 1000 duplicate records. Delete all, keep first, or review manually?"
|
|
24
|
-
- "Which columns should I include in the export?"
|
|
25
|
-
- "Normalize the data using method A (faster) or B (more accurate)?"
|
|
26
|
-
|
|
27
|
-
### 4. **Content & Documentation**
|
|
28
|
-
- "Which tone for the documentation: formal, casual, or technical?"
|
|
29
|
-
- "Include code examples in the README?"
|
|
30
|
-
- "Which sections are most important for your users?"
|
|
31
|
-
|
|
32
|
-
### 5. **Git Operations**
|
|
33
|
-
- "Which files should I include in this commit?"
|
|
34
|
-
- "Merge conflict detected. Keep theirs, ours, or manual review?"
|
|
35
|
-
- "Create a new branch or commit to main?"
|
|
36
|
-
|
|
37
|
-
## What to Expect
|
|
38
|
-
|
|
39
|
-
### For Developers
|
|
40
|
-
- **Reduced Errors**: AI agents won't make incorrect assumptions about your preferences
|
|
41
|
-
- **Better Control**: Maintain oversight of critical decisions while letting AI handle the implementation
|
|
42
|
-
- **Improved Workflow**: AI can complete complex multi-step tasks with human guidance at key points
|
|
43
|
-
- **Time Savings**: Let AI do the work while you just make the important decisions
|
|
44
|
-
|
|
45
|
-
### For AI Agents
|
|
46
|
-
- **Clear Decision Points**: No more guessing what the user wants
|
|
47
|
-
- **Graceful Handling**: Ambiguous situations become opportunities for clarification
|
|
48
|
-
- **Better Results**: Human input ensures the output matches expectations
|
|
49
|
-
- **Continuous Workflow**: Complete tasks without stopping for every small decision
|
|
50
|
-
|
|
51
|
-
## Core Features
|
|
52
|
-
|
|
53
|
-
- **Browser-Based Dialogs**: Clean, accessible UI that opens automatically
|
|
54
|
-
- **Multiple Choice Support**: Single or multi-select options with descriptions
|
|
55
|
-
- **Custom Input**: "Other" field for responses not in the list
|
|
56
|
-
- **Timeout Support**: Auto-dismiss dialogs after specified time
|
|
57
|
-
- **Cross-Platform**: Works on Windows, macOS, and Linux
|
|
58
|
-
- **Zero Configuration**: Works out of the box with sensible defaults
|
|
59
|
-
|
|
60
|
-
## Installation
|
|
61
|
-
|
|
62
|
-
### Prerequisites
|
|
63
|
-
|
|
64
|
-
- Node.js 18+ and npm
|
|
65
|
-
- A browser (for displaying dialogs)
|
|
66
|
-
|
|
67
|
-
### Quick Install from NPM
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# Install globally from npm
|
|
71
|
-
npm install -g @achieveai/hitl-mcp-server
|
|
72
|
-
|
|
73
|
-
# Now you can run it from anywhere
|
|
74
|
-
hitl-mcp-server
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Using with npx (no installation required)
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
# Run directly without installing
|
|
81
|
-
npx @achieveai/hitl-mcp-server
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### From Source
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
# Clone the repository
|
|
88
|
-
git clone https://github.com/achieveai/HumanInTheLoop.git
|
|
89
|
-
cd HumanInTheLoop/hitl-mcp-server
|
|
90
|
-
|
|
91
|
-
# Install dependencies
|
|
92
|
-
npm install
|
|
93
|
-
|
|
94
|
-
# Build the TypeScript code
|
|
95
|
-
npm run build
|
|
96
|
-
|
|
97
|
-
# Test the installation
|
|
98
|
-
npm run dev
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Configuration
|
|
102
|
-
|
|
103
|
-
Pre-configured examples are available in the `config/` directory for different MCP clients.
|
|
104
|
-
|
|
105
|
-
### Claude Desktop Configuration
|
|
106
|
-
|
|
107
|
-
Add the server to your Claude Desktop config file:
|
|
108
|
-
|
|
109
|
-
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
110
|
-
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
111
|
-
**Linux**: `~/.config/claude/claude_desktop_config.json`
|
|
112
|
-
|
|
113
|
-
```json
|
|
114
|
-
{
|
|
115
|
-
"mcpServers": {
|
|
116
|
-
"human-in-the-loop": {
|
|
117
|
-
"command": "npx",
|
|
118
|
-
"args": ["-y", "@achieveai/hitl-mcp-server"],
|
|
119
|
-
"env": {
|
|
120
|
-
"NODE_ENV": "production"
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Or if you've installed it globally:
|
|
128
|
-
|
|
129
|
-
```json
|
|
130
|
-
{
|
|
131
|
-
"mcpServers": {
|
|
132
|
-
"human-in-the-loop": {
|
|
133
|
-
"command": "hitl-mcp-server",
|
|
134
|
-
"env": {
|
|
135
|
-
"NODE_ENV": "production"
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### VS Code Configuration
|
|
143
|
-
|
|
144
|
-
Create `.vscode/mcp.json` in your workspace:
|
|
145
|
-
|
|
146
|
-
```json
|
|
147
|
-
{
|
|
148
|
-
"mcpServers": {
|
|
149
|
-
"human-in-the-loop": {
|
|
150
|
-
"command": "npx",
|
|
151
|
-
"args": ["-y", "@achieveai/hitl-mcp-server"],
|
|
152
|
-
"env": {
|
|
153
|
-
"NODE_ENV": "production"
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Cursor IDE Configuration
|
|
161
|
-
|
|
162
|
-
Add to your Cursor settings:
|
|
163
|
-
|
|
164
|
-
```json
|
|
165
|
-
{
|
|
166
|
-
"mcpServers": {
|
|
167
|
-
"human-in-the-loop": {
|
|
168
|
-
"name": "Human In The Loop",
|
|
169
|
-
"command": "npx",
|
|
170
|
-
"args": ["-y", "@achieveai/hitl-mcp-server"],
|
|
171
|
-
"transport": "stdio",
|
|
172
|
-
"autoStart": false
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Or if you've installed it globally:
|
|
179
|
-
|
|
180
|
-
```json
|
|
181
|
-
{
|
|
182
|
-
"mcpServers": {
|
|
183
|
-
"human-in-the-loop": {
|
|
184
|
-
"name": "Human In The Loop",
|
|
185
|
-
"command": "hitl-mcp-server",
|
|
186
|
-
"transport": "stdio",
|
|
187
|
-
"autoStart": false
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Recommended Configuration
|
|
194
|
-
|
|
195
|
-
For all MCP clients, we recommend using npx for zero-installation setup:
|
|
196
|
-
|
|
197
|
-
```json
|
|
198
|
-
{
|
|
199
|
-
"mcpServers": {
|
|
200
|
-
"human-in-the-loop": {
|
|
201
|
-
"command": "npx",
|
|
202
|
-
"args": ["-y", "@achieveai/hitl-mcp-server"]
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
This approach:
|
|
209
|
-
- Requires no installation
|
|
210
|
-
- Always uses the latest version
|
|
211
|
-
- Works immediately on any system with Node.js
|
|
212
|
-
|
|
213
|
-
## Usage
|
|
214
|
-
|
|
215
|
-
Once configured, the AI agent can use the `ask_human` tool to request input:
|
|
216
|
-
|
|
217
|
-
### Example: Single Choice
|
|
218
|
-
|
|
219
|
-
```javascript
|
|
220
|
-
{
|
|
221
|
-
"question": "Which database should I use for this project?",
|
|
222
|
-
"options": [
|
|
223
|
-
{
|
|
224
|
-
"label": "PostgreSQL",
|
|
225
|
-
"value": "postgres",
|
|
226
|
-
"description": "Robust relational database with advanced features"
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
"label": "MongoDB",
|
|
230
|
-
"value": "mongo",
|
|
231
|
-
"description": "Flexible document database for unstructured data"
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"label": "SQLite",
|
|
235
|
-
"value": "sqlite",
|
|
236
|
-
"description": "Lightweight embedded database"
|
|
237
|
-
}
|
|
238
|
-
],
|
|
239
|
-
"allowMultiple": false,
|
|
240
|
-
"allowOther": true,
|
|
241
|
-
"context": "This is for a medium-scale web application with complex queries"
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Example: Multiple Choice
|
|
246
|
-
|
|
247
|
-
```javascript
|
|
248
|
-
{
|
|
249
|
-
"question": "Which files should I include in the commit?",
|
|
250
|
-
"options": [
|
|
251
|
-
{
|
|
252
|
-
"label": "src/index.ts",
|
|
253
|
-
"value": "index"
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
"label": "src/utils.ts",
|
|
257
|
-
"value": "utils"
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
"label": "README.md",
|
|
261
|
-
"value": "readme"
|
|
262
|
-
}
|
|
263
|
-
],
|
|
264
|
-
"allowMultiple": true,
|
|
265
|
-
"allowOther": false,
|
|
266
|
-
"context": "Several files have been modified"
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Example: With Timeout
|
|
271
|
-
|
|
272
|
-
```javascript
|
|
273
|
-
{
|
|
274
|
-
"question": "Should I proceed with the deployment?",
|
|
275
|
-
"options": [
|
|
276
|
-
{
|
|
277
|
-
"label": "Yes, deploy now",
|
|
278
|
-
"value": "yes"
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
"label": "No, cancel",
|
|
282
|
-
"value": "no"
|
|
283
|
-
}
|
|
284
|
-
],
|
|
285
|
-
"allowMultiple": false,
|
|
286
|
-
"allowOther": false,
|
|
287
|
-
"timeout": 30000 // 30 seconds
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
## Response Format
|
|
292
|
-
|
|
293
|
-
The tool returns a JSON response:
|
|
294
|
-
|
|
295
|
-
```javascript
|
|
296
|
-
{
|
|
297
|
-
"success": true,
|
|
298
|
-
"timestamp": 1703001234567,
|
|
299
|
-
"response": "selected_value", // or array for multiple selection
|
|
300
|
-
"responseType": "selection" // or "custom" for other text, "none" if skipped
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
## Testing
|
|
305
|
-
|
|
306
|
-
### Run Unit Tests
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
npm test
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### Test Dialog Manager
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
npm run build
|
|
316
|
-
node dist/test-client.js
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
This will open test dialogs to verify the UI is working correctly.
|
|
320
|
-
|
|
321
|
-
### Manual Testing with MCP Inspector
|
|
322
|
-
|
|
323
|
-
You can use the MCP Inspector tool to test the server:
|
|
324
|
-
|
|
325
|
-
```bash
|
|
326
|
-
npx @modelcontextprotocol/inspector node dist/index.js
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
## Development
|
|
330
|
-
|
|
331
|
-
### Project Structure
|
|
332
|
-
|
|
333
|
-
```
|
|
334
|
-
hitl-mcp-server/
|
|
335
|
-
├── src/
|
|
336
|
-
│ ├── index.ts # Main MCP server implementation
|
|
337
|
-
│ ├── dialog-manager.ts # Dialog UI and HTTP server
|
|
338
|
-
│ └── test-client.ts # Test client for dialog manager
|
|
339
|
-
├── dist/ # Compiled JavaScript (after build)
|
|
340
|
-
├── package.json
|
|
341
|
-
├── tsconfig.json
|
|
342
|
-
└── README.md
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### Available Scripts
|
|
346
|
-
|
|
347
|
-
- `npm run build` - Compile TypeScript to JavaScript
|
|
348
|
-
- `npm run dev` - Run in development mode with auto-reload
|
|
349
|
-
- `npm test` - Run unit tests
|
|
350
|
-
- `npm run typecheck` - Check TypeScript types without building
|
|
351
|
-
|
|
352
|
-
## Why This Tool Matters
|
|
353
|
-
|
|
354
|
-
### The Problem
|
|
355
|
-
AI agents are powerful but often encounter situations where they need human judgment:
|
|
356
|
-
- Ambiguous requirements that could be interpreted multiple ways
|
|
357
|
-
- Critical decisions that could have significant consequences
|
|
358
|
-
- Subjective choices about style, approach, or priorities
|
|
359
|
-
- Missing context that only the human user possesses
|
|
360
|
-
|
|
361
|
-
### The Solution
|
|
362
|
-
This tool creates a seamless communication channel between AI and humans:
|
|
363
|
-
- **AI Autonomy**: The agent continues working independently until it needs input
|
|
364
|
-
- **Human Control**: You maintain oversight of important decisions
|
|
365
|
-
- **Efficient Workflow**: No need to micromanage - only intervene when necessary
|
|
366
|
-
- **Better Outcomes**: Combine AI efficiency with human judgment
|
|
367
|
-
|
|
368
|
-
### Expected Benefits
|
|
369
|
-
|
|
370
|
-
1. **Increased Productivity**
|
|
371
|
-
- Let AI handle implementation while you focus on decisions
|
|
372
|
-
- Batch multiple tasks with decision points
|
|
373
|
-
- Reduce back-and-forth clarifications
|
|
374
|
-
|
|
375
|
-
2. **Improved Accuracy**
|
|
376
|
-
- No more AI guessing your preferences
|
|
377
|
-
- Catch potential issues before they happen
|
|
378
|
-
- Ensure outputs match your expectations
|
|
379
|
-
|
|
380
|
-
3. **Enhanced Trust**
|
|
381
|
-
- Know that AI will ask before making critical changes
|
|
382
|
-
- Review and approve important decisions
|
|
383
|
-
- Maintain control while leveraging AI capabilities
|
|
384
|
-
|
|
385
|
-
4. **Seamless Integration**
|
|
386
|
-
- Works with Claude Desktop, Cursor, VS Code, and other MCP clients
|
|
387
|
-
- No complex setup or configuration required
|
|
388
|
-
- Natural integration into existing AI workflows
|
|
389
|
-
|
|
390
|
-
## Troubleshooting
|
|
391
|
-
|
|
392
|
-
### Dialog doesn't open
|
|
393
|
-
|
|
394
|
-
- Check if port 3000-5000 range is available
|
|
395
|
-
- Ensure your default browser is properly configured
|
|
396
|
-
- Check the server logs for error messages
|
|
397
|
-
|
|
398
|
-
### Timeout errors
|
|
399
|
-
|
|
400
|
-
- Increase the timeout value in your request
|
|
401
|
-
- Ensure the dialog window has focus
|
|
402
|
-
|
|
403
|
-
### Server won't start
|
|
404
|
-
|
|
405
|
-
- Check if another instance is already running
|
|
406
|
-
- Verify Node.js version is 18 or higher
|
|
407
|
-
- Run `npm install` to ensure all dependencies are installed
|
|
408
|
-
|
|
409
|
-
## Security & Privacy
|
|
410
|
-
|
|
411
|
-
- All dialogs run locally on your machine
|
|
412
|
-
- No data is sent to external servers
|
|
413
|
-
- Dialog server only accepts connections from localhost
|
|
414
|
-
- Temporary server instances are created per request
|
|
415
|
-
|
|
416
|
-
## License
|
|
417
|
-
|
|
418
|
-
GPL-3.0
|
|
419
|
-
|
|
420
|
-
## Contributing
|
|
421
|
-
|
|
422
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/config/cursor-mcp.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mcpServers": {
|
|
3
|
-
"human-in-the-loop": {
|
|
4
|
-
"name": "Human In The Loop",
|
|
5
|
-
"description": "Interactive dialog system for getting human feedback",
|
|
6
|
-
"command": "npx",
|
|
7
|
-
"args": ["-y", "@achieveai/hitl-mcp-server"],
|
|
8
|
-
"env": {
|
|
9
|
-
"NODE_ENV": "production"
|
|
10
|
-
},
|
|
11
|
-
"transport": "stdio",
|
|
12
|
-
"autoStart": false,
|
|
13
|
-
"restartOnFailure": true,
|
|
14
|
-
"maxRestarts": 3
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
package/config/vscode-mcp.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dialog-manager.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { DialogManager } from '../dialog-manager.js';
|
|
2
|
-
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
3
|
-
describe('DialogManager', () => {
|
|
4
|
-
let manager;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
manager = new DialogManager();
|
|
7
|
-
});
|
|
8
|
-
afterEach(async () => {
|
|
9
|
-
await manager.close();
|
|
10
|
-
});
|
|
11
|
-
describe('initialization', () => {
|
|
12
|
-
it('should initialize the server on a random port', async () => {
|
|
13
|
-
const port = await manager.initialize();
|
|
14
|
-
expect(port).toBeGreaterThan(0);
|
|
15
|
-
expect(port).toBeLessThanOrEqual(65535);
|
|
16
|
-
});
|
|
17
|
-
it('should not reinitialize if already initialized', async () => {
|
|
18
|
-
const port1 = await manager.initialize();
|
|
19
|
-
const port2 = await manager.initialize();
|
|
20
|
-
expect(port1).toBe(port2);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
describe('HTML generation', () => {
|
|
24
|
-
it('should escape HTML in user input', () => {
|
|
25
|
-
const manager = new DialogManager();
|
|
26
|
-
const html = manager.generateDialogHTML({
|
|
27
|
-
id: 'test',
|
|
28
|
-
question: '<script>alert("XSS")</script>',
|
|
29
|
-
options: [
|
|
30
|
-
{
|
|
31
|
-
label: '<b>Bold</b>',
|
|
32
|
-
value: 'test',
|
|
33
|
-
description: '"Quotes" & \'apostrophes\''
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
allowMultiple: false,
|
|
37
|
-
allowOther: true
|
|
38
|
-
});
|
|
39
|
-
expect(html).not.toContain('<script>alert("XSS")</script>');
|
|
40
|
-
expect(html).toContain('<script>alert("XSS")</script>');
|
|
41
|
-
expect(html).not.toContain('<b>Bold</b>');
|
|
42
|
-
expect(html).toContain('<b>Bold</b>');
|
|
43
|
-
});
|
|
44
|
-
it('should include context when provided', () => {
|
|
45
|
-
const manager = new DialogManager();
|
|
46
|
-
const html = manager.generateDialogHTML({
|
|
47
|
-
id: 'test',
|
|
48
|
-
question: 'Test question',
|
|
49
|
-
options: [{ label: 'Option 1', value: 'opt1' }],
|
|
50
|
-
allowMultiple: false,
|
|
51
|
-
allowOther: false,
|
|
52
|
-
context: 'Important context information'
|
|
53
|
-
});
|
|
54
|
-
expect(html).toContain('Important context information');
|
|
55
|
-
expect(html).toContain('Context:');
|
|
56
|
-
});
|
|
57
|
-
it('should not include context section when not provided', () => {
|
|
58
|
-
const manager = new DialogManager();
|
|
59
|
-
const html = manager.generateDialogHTML({
|
|
60
|
-
id: 'test',
|
|
61
|
-
question: 'Test question',
|
|
62
|
-
options: [{ label: 'Option 1', value: 'opt1' }],
|
|
63
|
-
allowMultiple: false,
|
|
64
|
-
allowOther: false
|
|
65
|
-
});
|
|
66
|
-
expect(html).not.toContain('Context:');
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
describe('dialog options', () => {
|
|
70
|
-
it('should render radio buttons for single choice', () => {
|
|
71
|
-
const manager = new DialogManager();
|
|
72
|
-
const html = manager.generateDialogHTML({
|
|
73
|
-
id: 'test',
|
|
74
|
-
question: 'Choose one',
|
|
75
|
-
options: [
|
|
76
|
-
{ label: 'A', value: 'a' },
|
|
77
|
-
{ label: 'B', value: 'b' }
|
|
78
|
-
],
|
|
79
|
-
allowMultiple: false,
|
|
80
|
-
allowOther: false
|
|
81
|
-
});
|
|
82
|
-
expect(html).toContain('type="radio"');
|
|
83
|
-
expect(html).not.toContain('type="checkbox"');
|
|
84
|
-
});
|
|
85
|
-
it('should render checkboxes for multiple choice', () => {
|
|
86
|
-
const manager = new DialogManager();
|
|
87
|
-
const html = manager.generateDialogHTML({
|
|
88
|
-
id: 'test',
|
|
89
|
-
question: 'Choose many',
|
|
90
|
-
options: [
|
|
91
|
-
{ label: 'A', value: 'a' },
|
|
92
|
-
{ label: 'B', value: 'b' }
|
|
93
|
-
],
|
|
94
|
-
allowMultiple: true,
|
|
95
|
-
allowOther: false
|
|
96
|
-
});
|
|
97
|
-
expect(html).toContain('type="checkbox"');
|
|
98
|
-
expect(html).not.toContain('type="radio"');
|
|
99
|
-
});
|
|
100
|
-
it('should include other field when allowed', () => {
|
|
101
|
-
const manager = new DialogManager();
|
|
102
|
-
const html = manager.generateDialogHTML({
|
|
103
|
-
id: 'test',
|
|
104
|
-
question: 'Choose',
|
|
105
|
-
options: [{ label: 'A', value: 'a' }],
|
|
106
|
-
allowMultiple: false,
|
|
107
|
-
allowOther: true
|
|
108
|
-
});
|
|
109
|
-
expect(html).toContain('id="other-input"');
|
|
110
|
-
expect(html).toContain('Additional Context (optional)');
|
|
111
|
-
});
|
|
112
|
-
it('should not include other field when not allowed', () => {
|
|
113
|
-
const manager = new DialogManager();
|
|
114
|
-
const html = manager.generateDialogHTML({
|
|
115
|
-
id: 'test',
|
|
116
|
-
question: 'Choose',
|
|
117
|
-
options: [{ label: 'A', value: 'a' }],
|
|
118
|
-
allowMultiple: false,
|
|
119
|
-
allowOther: false
|
|
120
|
-
});
|
|
121
|
-
expect(html).not.toContain('id="other-input"');
|
|
122
|
-
expect(html).not.toContain('Additional Context (optional)');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
describe('timeout handling', () => {
|
|
126
|
-
it('should reject with timeout error after specified duration', async () => {
|
|
127
|
-
await manager.initialize();
|
|
128
|
-
const dialogPromise = manager.showDialog({
|
|
129
|
-
id: 'timeout-test',
|
|
130
|
-
question: 'This will timeout',
|
|
131
|
-
options: [{ label: 'Option', value: 'opt' }],
|
|
132
|
-
allowMultiple: false,
|
|
133
|
-
allowOther: false,
|
|
134
|
-
timeout: 100
|
|
135
|
-
});
|
|
136
|
-
await expect(dialogPromise).rejects.toThrow('Dialog timeout');
|
|
137
|
-
}, 10000);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
//# sourceMappingURL=dialog-manager.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/dialog-manager.test.ts"],"names":[],"mappings":"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"}
|
package/dist/dialog-manager.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
export interface DialogOption {
|
|
3
|
-
label: string;
|
|
4
|
-
value: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface DialogRequest {
|
|
8
|
-
id: string;
|
|
9
|
-
question: string;
|
|
10
|
-
options: DialogOption[];
|
|
11
|
-
allowMultiple: boolean;
|
|
12
|
-
allowOther: boolean;
|
|
13
|
-
context?: string;
|
|
14
|
-
timeout?: number;
|
|
15
|
-
}
|
|
16
|
-
export interface DialogResponse {
|
|
17
|
-
id: string;
|
|
18
|
-
selectedValues: string[];
|
|
19
|
-
otherText?: string;
|
|
20
|
-
timestamp: number;
|
|
21
|
-
}
|
|
22
|
-
export declare class DialogManager extends EventEmitter {
|
|
23
|
-
private app;
|
|
24
|
-
private port;
|
|
25
|
-
private pendingDialogs;
|
|
26
|
-
private server;
|
|
27
|
-
private isInitialized;
|
|
28
|
-
constructor(port?: number);
|
|
29
|
-
private setupRoutes;
|
|
30
|
-
private generateDialogHTML;
|
|
31
|
-
private escapeHtml;
|
|
32
|
-
initialize(): Promise<number>;
|
|
33
|
-
showDialog(request: DialogRequest): Promise<DialogResponse>;
|
|
34
|
-
private playNotificationSound;
|
|
35
|
-
close(): Promise<void>;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=dialog-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-manager.d.ts","sourceRoot":"","sources":["../src/dialog-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,cAAc,CAKnB;IACH,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,aAAa,CAAkB;gBAE3B,IAAI,GAAE,MAAU;IAQ5B,OAAO,CAAC,WAAW;IAgDnB,OAAO,CAAC,kBAAkB;IAqd1B,OAAO,CAAC,UAAU;IAWZ,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAoB7B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAqCjE,OAAO,CAAC,qBAAqB;IA+CvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU7B"}
|