ai-consultation-mcp 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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/api/index.d.ts +27 -0
  4. package/dist/api/index.js +213 -0
  5. package/dist/api/index.js.map +1 -0
  6. package/dist/api/middleware/security.d.ts +6 -0
  7. package/dist/api/middleware/security.js +28 -0
  8. package/dist/api/middleware/security.js.map +1 -0
  9. package/dist/api/routes/chat.d.ts +2 -0
  10. package/dist/api/routes/chat.js +78 -0
  11. package/dist/api/routes/chat.js.map +1 -0
  12. package/dist/api/routes/config.d.ts +2 -0
  13. package/dist/api/routes/config.js +81 -0
  14. package/dist/api/routes/config.js.map +1 -0
  15. package/dist/api/routes/providers.d.ts +2 -0
  16. package/dist/api/routes/providers.js +225 -0
  17. package/dist/api/routes/providers.js.map +1 -0
  18. package/dist/api/standalone-server.d.ts +12 -0
  19. package/dist/api/standalone-server.js +117 -0
  20. package/dist/api/standalone-server.js.map +1 -0
  21. package/dist/config/defaults.d.ts +17 -0
  22. package/dist/config/defaults.js +30 -0
  23. package/dist/config/defaults.js.map +1 -0
  24. package/dist/config/encryption.d.ts +12 -0
  25. package/dist/config/encryption.js +85 -0
  26. package/dist/config/encryption.js.map +1 -0
  27. package/dist/config/index.d.ts +5 -0
  28. package/dist/config/index.js +6 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/config/manager.d.ts +62 -0
  31. package/dist/config/manager.js +210 -0
  32. package/dist/config/manager.js.map +1 -0
  33. package/dist/config/prompts.d.ts +10 -0
  34. package/dist/config/prompts.js +168 -0
  35. package/dist/config/prompts.js.map +1 -0
  36. package/dist/config/schema.d.ts +141 -0
  37. package/dist/config/schema.js +54 -0
  38. package/dist/config/schema.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +260 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/installer/detector.d.ts +48 -0
  43. package/dist/installer/detector.js +164 -0
  44. package/dist/installer/detector.js.map +1 -0
  45. package/dist/installer/index.d.ts +7 -0
  46. package/dist/installer/index.js +10 -0
  47. package/dist/installer/index.js.map +1 -0
  48. package/dist/installer/installer.d.ts +16 -0
  49. package/dist/installer/installer.js +262 -0
  50. package/dist/installer/installer.js.map +1 -0
  51. package/dist/installer/tools.d.ts +16 -0
  52. package/dist/installer/tools.js +327 -0
  53. package/dist/installer/tools.js.map +1 -0
  54. package/dist/installer/types.d.ts +68 -0
  55. package/dist/installer/types.js +5 -0
  56. package/dist/installer/types.js.map +1 -0
  57. package/dist/providers/base.d.ts +44 -0
  58. package/dist/providers/base.js +84 -0
  59. package/dist/providers/base.js.map +1 -0
  60. package/dist/providers/deepseek.d.ts +30 -0
  61. package/dist/providers/deepseek.js +148 -0
  62. package/dist/providers/deepseek.js.map +1 -0
  63. package/dist/providers/index.d.ts +5 -0
  64. package/dist/providers/index.js +8 -0
  65. package/dist/providers/index.js.map +1 -0
  66. package/dist/providers/openai.d.ts +30 -0
  67. package/dist/providers/openai.js +123 -0
  68. package/dist/providers/openai.js.map +1 -0
  69. package/dist/providers/registry.d.ts +37 -0
  70. package/dist/providers/registry.js +65 -0
  71. package/dist/providers/registry.js.map +1 -0
  72. package/dist/providers/types.d.ts +71 -0
  73. package/dist/providers/types.js +2 -0
  74. package/dist/providers/types.js.map +1 -0
  75. package/dist/server/conversation.d.ts +105 -0
  76. package/dist/server/conversation.js +279 -0
  77. package/dist/server/conversation.js.map +1 -0
  78. package/dist/server/index.d.ts +2 -0
  79. package/dist/server/index.js +3 -0
  80. package/dist/server/index.js.map +1 -0
  81. package/dist/server/tools/consult.d.ts +15 -0
  82. package/dist/server/tools/consult.js +164 -0
  83. package/dist/server/tools/consult.js.map +1 -0
  84. package/dist/server/tools/index.d.ts +1 -0
  85. package/dist/server/tools/index.js +2 -0
  86. package/dist/server/tools/index.js.map +1 -0
  87. package/dist/types/config.d.ts +20 -0
  88. package/dist/types/config.js +2 -0
  89. package/dist/types/config.js.map +1 -0
  90. package/dist/types/index.d.ts +3 -0
  91. package/dist/types/index.js +4 -0
  92. package/dist/types/index.js.map +1 -0
  93. package/dist/types/messages.d.ts +48 -0
  94. package/dist/types/messages.js +2 -0
  95. package/dist/types/messages.js.map +1 -0
  96. package/dist/types/models.d.ts +39 -0
  97. package/dist/types/models.js +66 -0
  98. package/dist/types/models.js.map +1 -0
  99. package/dist/ui/index.html +1244 -0
  100. package/dist/utils/errors.d.ts +32 -0
  101. package/dist/utils/errors.js +53 -0
  102. package/dist/utils/errors.js.map +1 -0
  103. package/dist/utils/index.d.ts +2 -0
  104. package/dist/utils/index.js +3 -0
  105. package/dist/utils/index.js.map +1 -0
  106. package/dist/utils/logger.d.ts +13 -0
  107. package/dist/utils/logger.js +73 -0
  108. package/dist/utils/logger.js.map +1 -0
  109. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Menes Ekinci
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # Agent Consultation MCP
2
+
3
+ [![npm version](https://img.shields.io/npm/v/ai-consultation-mcp.svg)](https://www.npmjs.com/package/ai-consultation-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ An MCP (Model Context Protocol) server that enables AI agents to get a **second opinion** from other AI models, enriching their perspectives during work.
7
+
8
+ > **Purpose**: When AI agents work on complex tasks, having a single perspective can lead to blind spots or suboptimal solutions. This MCP server allows agents like Claude Code to consult with DeepSeek Reasoner or ChatGPT for alternative viewpoints, validation, or different problem-solving strategies.
9
+
10
+ ## Features
11
+
12
+ - **Multi-Tool Auto-Install**: Automatically detects and configures MCP for Claude Code, Cursor, Windsurf, Cline, Continue, Zed, and more
13
+ - **Multi-Provider Support**: DeepSeek (Reasoner, Chat) and OpenAI (GPT-5.2, GPT-5.2 Pro)
14
+ - **Specialized Consultation Modes**: Debug, Code Analysis, Architecture Review, Plan Validation, Concept Explanation
15
+ - **Conversation Management**: Continue multi-turn conversations with context
16
+ - **Web UI**: Configure providers and API keys through a browser interface
17
+ - **Encrypted Storage**: API keys are encrypted at rest
18
+
19
+ ## Quick Start (2 steps)
20
+
21
+ ```bash
22
+ # 1. Auto-install to all detected AI tools
23
+ npx ai-consultation-mcp --install
24
+
25
+ # 2. Configure your API key in the Web UI that opens automatically
26
+ # Done! Restart your AI tools and start using
27
+ ```
28
+
29
+ ## Installation
30
+
31
+ ### Option 1: npm (Recommended)
32
+
33
+ The easiest way to install and use the MCP server:
34
+
35
+ ```bash
36
+ # Auto-install to all detected AI tools
37
+ npx ai-consultation-mcp --install
38
+
39
+ # Or install globally
40
+ npm install -g ai-consultation-mcp
41
+ ai-consultation-mcp --install
42
+ ```
43
+
44
+ ### Option 2: From GitHub
45
+
46
+ Clone the repository and build from source:
47
+
48
+ ```bash
49
+ # Clone the repository
50
+ git clone https://github.com/menesekinci/ai-consultation-mcp.git
51
+ cd ai-consultation-mcp
52
+
53
+ # Install dependencies
54
+ npm install
55
+
56
+ # Build
57
+ npm run build
58
+
59
+ # Run the installer
60
+ npm start -- --install
61
+ ```
62
+
63
+ ### Auto-Install Features
64
+
65
+ The `--install` flag will:
66
+ - Scan for installed AI tools (Claude Code, Cursor, Windsurf, OpenCode, VSCode Copilot, Cline, Continue, Zed, Roo Code)
67
+ - Add MCP configuration to each detected tool
68
+ - Open the Web UI to configure your API key
69
+ - Show which tools need to be restarted
70
+
71
+ ### Supported AI Tools
72
+
73
+ | Tool | Config Location |
74
+ |------|-----------------|
75
+ | Claude Code | `~/.claude/mcp.json` |
76
+ | Cursor | `~/.cursor/mcp.json` |
77
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
78
+ | OpenCode | `~/.config/opencode/opencode.json` |
79
+ | VSCode Copilot | `~/Library/Application Support/Code/User/mcp.json` |
80
+ | Cline | VSCode globalStorage |
81
+ | Continue | `~/.continue/config.json` |
82
+ | Zed | `~/.config/zed/settings.json` |
83
+ | Roo Code | VSCode globalStorage |
84
+
85
+ ### Manual Installation (Claude Code)
86
+
87
+ Add to `~/.claude/mcp.json`:
88
+
89
+ ```json
90
+ {
91
+ "mcpServers": {
92
+ "agent-consultation": {
93
+ "command": "npx",
94
+ "args": ["-y", "ai-consultation-mcp"]
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ ### Setting Up API Keys
103
+
104
+ ```bash
105
+ npx ai-consultation-mcp --config
106
+ ```
107
+
108
+ This opens a web UI where you can:
109
+ - Add/update API keys for DeepSeek and OpenAI
110
+ - Test API key validity
111
+ - Change default model
112
+ - View conversation history
113
+
114
+ ### Supported Providers
115
+
116
+ | Provider | Models | API Key |
117
+ |----------|--------|---------|
118
+ | DeepSeek | `deepseek-reasoner` (default), `deepseek-chat` | [Get API Key](https://platform.deepseek.com/) |
119
+ | OpenAI | `gpt-5.2`, `gpt-5.2-pro` | [Get API Key](https://platform.openai.com/) |
120
+
121
+ ## Usage
122
+
123
+ Once configured, Claude Code can use the following tools:
124
+
125
+ ### consult_agent
126
+
127
+ Get a second opinion from another AI model.
128
+
129
+ ```
130
+ Parameters:
131
+ - question (required): The question or problem to get advice on
132
+ - mode (optional): Consultation mode - debug, analyzeCode, reviewArchitecture, validatePlan, explainConcept, general
133
+ - context (optional): Additional context like code snippets or error messages
134
+ ```
135
+
136
+ ### continue_conversation
137
+
138
+ Continue an existing consultation conversation.
139
+
140
+ ```
141
+ Parameters:
142
+ - conversationId (required): The conversation ID from a previous consultation
143
+ - message (required): Your follow-up message
144
+ ```
145
+
146
+ ### end_conversation
147
+
148
+ End an active consultation conversation.
149
+
150
+ ```
151
+ Parameters:
152
+ - conversationId (required): The conversation ID to end
153
+ ```
154
+
155
+ ## Example
156
+
157
+ In Claude Code, you might use it like:
158
+
159
+ > "Can you consult DeepSeek about this architecture decision? I'm not sure if using a monorepo is the right choice for this microservices setup."
160
+
161
+ Claude will then call the `consult_agent` tool with your question and provide the response.
162
+
163
+ ## Consultation Modes
164
+
165
+ | Mode | Description |
166
+ |------|-------------|
167
+ | `debug` | Focus on finding bugs, analyzing errors, and suggesting fixes |
168
+ | `analyzeCode` | Code review focusing on quality, patterns, and improvements |
169
+ | `reviewArchitecture` | Evaluate architectural decisions and suggest alternatives |
170
+ | `validatePlan` | Review implementation plans for completeness and risks |
171
+ | `explainConcept` | Explain technical concepts clearly |
172
+ | `general` | General-purpose consultation |
173
+
174
+ ## Development
175
+
176
+ ```bash
177
+ # Clone the repo
178
+ git clone https://github.com/menesekinci/ai-consultation-mcp.git
179
+ cd ai-consultation-mcp
180
+
181
+ # Install dependencies
182
+ npm install
183
+
184
+ # Run in development mode
185
+ npm run dev
186
+
187
+ # Build for production
188
+ npm run build
189
+ ```
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,27 @@
1
+ export interface ConfigUIOptions {
2
+ port?: number;
3
+ openBrowser?: boolean;
4
+ }
5
+ /**
6
+ * Start the configuration UI HTTP server
7
+ */
8
+ export declare function startConfigUI(options?: ConfigUIOptions): Promise<void>;
9
+ /**
10
+ * Start the UI server in background mode (for MCP mode)
11
+ * Does not block and does not open browser automatically
12
+ */
13
+ export declare function startBackgroundUIServer(port?: number): Promise<boolean>;
14
+ /**
15
+ * Open the Web UI in browser (only opens once per session)
16
+ * Spawns a completely separate standalone server process that handles
17
+ * both server startup and browser opening.
18
+ */
19
+ export declare function openWebUI(): Promise<void>;
20
+ /**
21
+ * Check if browser has been opened
22
+ */
23
+ export declare function isBrowserOpened(): boolean;
24
+ /**
25
+ * Check if background server is running
26
+ */
27
+ export declare function isBackgroundServerRunning(): boolean;
@@ -0,0 +1,213 @@
1
+ import express from 'express';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { spawn } from 'child_process';
5
+ import open from 'open';
6
+ import { getConfigManager } from '../config/index.js';
7
+ import { logger } from '../utils/index.js';
8
+ import { configRoutes } from './routes/config.js';
9
+ import { providerRoutes } from './routes/providers.js';
10
+ import chatRoutes from './routes/chat.js';
11
+ import { securityMiddleware } from './middleware/security.js';
12
+ // Get __dirname equivalent in ES modules
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+ const DEFAULT_PORT = 3456;
16
+ // Track background UI server state
17
+ let backgroundServerRunning = false;
18
+ let browserOpened = false;
19
+ let backgroundServerPort = DEFAULT_PORT;
20
+ /**
21
+ * Start the configuration UI HTTP server
22
+ */
23
+ export async function startConfigUI(options = {}) {
24
+ const port = options.port ?? DEFAULT_PORT;
25
+ const shouldOpenBrowser = options.openBrowser ?? true;
26
+ // Ensure config is loaded
27
+ const configManager = getConfigManager();
28
+ await configManager.init();
29
+ const app = express();
30
+ // Middleware
31
+ app.use(express.json());
32
+ app.use(securityMiddleware);
33
+ // API routes
34
+ app.use('/api/config', configRoutes);
35
+ app.use('/api/providers', providerRoutes);
36
+ app.use('/api/chat', chatRoutes);
37
+ // Serve static UI files
38
+ const uiPath = path.join(__dirname, '../ui');
39
+ app.use(express.static(uiPath));
40
+ // Fallback to index.html for SPA-like behavior (Express 5 compatible)
41
+ app.use((_req, res, next) => {
42
+ // Only serve index.html for non-API requests that don't have a file extension
43
+ if (!_req.path.startsWith('/api') && !path.extname(_req.path)) {
44
+ res.sendFile(path.join(uiPath, 'index.html'));
45
+ }
46
+ else {
47
+ next();
48
+ }
49
+ });
50
+ // Error handling middleware
51
+ app.use((err, _req, res, _next) => {
52
+ logger.error('HTTP server error', { error: err.message });
53
+ res.status(500).json({
54
+ error: 'Internal server error',
55
+ message: err.message,
56
+ });
57
+ });
58
+ // CRITICAL: Bind to localhost only for security
59
+ return new Promise((resolve, reject) => {
60
+ const server = app.listen(port, '127.0.0.1', () => {
61
+ const url = `http://127.0.0.1:${port}`;
62
+ logger.info(`Config UI running at ${url}`);
63
+ console.log(`
64
+ ┌─────────────────────────────────────────────────┐
65
+ │ │
66
+ │ Agent Consultation MCP - Configuration UI │
67
+ │ │
68
+ │ URL: ${url.padEnd(40)}│
69
+ │ │
70
+ │ Press Ctrl+C to stop │
71
+ │ │
72
+ └─────────────────────────────────────────────────┘
73
+ `);
74
+ // Open browser
75
+ if (shouldOpenBrowser) {
76
+ open(url).catch((err) => {
77
+ logger.warn('Failed to open browser', { error: err.message });
78
+ console.log(`Please open ${url} in your browser`);
79
+ });
80
+ }
81
+ resolve();
82
+ });
83
+ server.on('error', (err) => {
84
+ if (err.code === 'EADDRINUSE') {
85
+ logger.error(`Port ${port} is already in use`);
86
+ console.error(`\nError: Port ${port} is already in use.`);
87
+ console.error(`Try a different port: npx agent-consultation-mcp --config --port ${port + 1}\n`);
88
+ }
89
+ reject(err);
90
+ });
91
+ });
92
+ }
93
+ /**
94
+ * Start the UI server in background mode (for MCP mode)
95
+ * Does not block and does not open browser automatically
96
+ */
97
+ export async function startBackgroundUIServer(port = DEFAULT_PORT) {
98
+ if (backgroundServerRunning) {
99
+ return true;
100
+ }
101
+ // Ensure config is loaded
102
+ const configManager = getConfigManager();
103
+ await configManager.init();
104
+ const app = express();
105
+ // Middleware
106
+ app.use(express.json());
107
+ app.use(securityMiddleware);
108
+ // API routes
109
+ app.use('/api/config', configRoutes);
110
+ app.use('/api/providers', providerRoutes);
111
+ app.use('/api/chat', chatRoutes);
112
+ // Serve static UI files
113
+ const uiPath = path.join(__dirname, '../ui');
114
+ app.use(express.static(uiPath));
115
+ // Fallback to index.html for SPA-like behavior
116
+ app.use((_req, res, next) => {
117
+ if (!_req.path.startsWith('/api') && !path.extname(_req.path)) {
118
+ res.sendFile(path.join(uiPath, 'index.html'));
119
+ }
120
+ else {
121
+ next();
122
+ }
123
+ });
124
+ // Error handling middleware
125
+ app.use((err, _req, res, _next) => {
126
+ logger.error('Background HTTP server error', { error: err.message });
127
+ res.status(500).json({
128
+ error: 'Internal server error',
129
+ message: err.message,
130
+ });
131
+ });
132
+ return new Promise((resolve) => {
133
+ const server = app.listen(port, '127.0.0.1', () => {
134
+ backgroundServerRunning = true;
135
+ backgroundServerPort = port;
136
+ logger.info(`Background UI server started at http://127.0.0.1:${port}`);
137
+ resolve(true);
138
+ });
139
+ server.on('error', (err) => {
140
+ if (err.code === 'EADDRINUSE') {
141
+ // Port is in use, maybe server is already running from another process
142
+ logger.debug(`Port ${port} already in use, assuming UI server is running`);
143
+ backgroundServerRunning = true;
144
+ backgroundServerPort = port;
145
+ resolve(true);
146
+ }
147
+ else {
148
+ logger.error('Failed to start background UI server', { error: err.message });
149
+ resolve(false);
150
+ }
151
+ });
152
+ });
153
+ }
154
+ /**
155
+ * Open the Web UI in browser (only opens once per session)
156
+ * Spawns a completely separate standalone server process that handles
157
+ * both server startup and browser opening.
158
+ */
159
+ export async function openWebUI() {
160
+ logger.info('openWebUI called', { browserOpened });
161
+ if (browserOpened) {
162
+ logger.info('Browser already opened, skipping');
163
+ return;
164
+ }
165
+ // Path to the standalone server script
166
+ const standaloneServerPath = path.join(__dirname, 'standalone-server.js');
167
+ logger.info('Spawning standalone server process', { standaloneServerPath });
168
+ try {
169
+ // Spawn a completely detached process
170
+ // This process will start the server AND open the browser
171
+ const child = spawn(process.execPath, [standaloneServerPath, String(backgroundServerPort)], {
172
+ detached: true,
173
+ stdio: 'ignore',
174
+ windowsHide: true,
175
+ env: { ...process.env }
176
+ });
177
+ // Unref to allow parent (MCP) process to exit independently
178
+ child.unref();
179
+ browserOpened = true;
180
+ backgroundServerRunning = true;
181
+ logger.info('Standalone server process spawned successfully');
182
+ }
183
+ catch (err) {
184
+ logger.error('Failed to spawn standalone server process', {
185
+ error: err instanceof Error ? err.message : 'Unknown error'
186
+ });
187
+ // Fallback: try to open browser directly (server might already be running)
188
+ const url = `http://127.0.0.1:${backgroundServerPort}`;
189
+ try {
190
+ await open(url, { wait: false });
191
+ browserOpened = true;
192
+ logger.info('Browser opened via fallback');
193
+ }
194
+ catch (openErr) {
195
+ logger.error('Fallback browser open also failed', {
196
+ error: openErr instanceof Error ? openErr.message : 'Unknown error'
197
+ });
198
+ }
199
+ }
200
+ }
201
+ /**
202
+ * Check if browser has been opened
203
+ */
204
+ export function isBrowserOpened() {
205
+ return browserOpened;
206
+ }
207
+ /**
208
+ * Check if background server is running
209
+ */
210
+ export function isBackgroundServerRunning() {
211
+ return backgroundServerRunning;
212
+ }
213
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ /**
3
+ * Security middleware for the config UI HTTP server
4
+ * Adds security headers to all responses
5
+ */
6
+ export declare function securityMiddleware(_req: Request, res: Response, next: NextFunction): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Security middleware for the config UI HTTP server
3
+ * Adds security headers to all responses
4
+ */
5
+ export function securityMiddleware(_req, res, next) {
6
+ // Prevent MIME type sniffing
7
+ res.setHeader('X-Content-Type-Options', 'nosniff');
8
+ // Prevent clickjacking
9
+ res.setHeader('X-Frame-Options', 'DENY');
10
+ // Enable XSS filter in browsers
11
+ res.setHeader('X-XSS-Protection', '1; mode=block');
12
+ // Content Security Policy - allow CDN resources for Alpine.js and Tailwind
13
+ // Note: 'unsafe-eval' is required for Alpine.js to evaluate expressions
14
+ // This is acceptable since the UI runs on localhost only
15
+ res.setHeader('Content-Security-Policy', [
16
+ "default-src 'self'",
17
+ "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com https://unpkg.com",
18
+ "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
19
+ "img-src 'self' data:",
20
+ "font-src 'self' https://fonts.gstatic.com",
21
+ "connect-src 'self'",
22
+ ].join('; '));
23
+ // Prevent caching of sensitive data
24
+ res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
25
+ res.setHeader('Pragma', 'no-cache');
26
+ next();
27
+ }
28
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/api/middleware/security.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAa,EACb,GAAa,EACb,IAAkB;IAElB,6BAA6B;IAC7B,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IAEnD,uBAAuB;IACvB,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAEzC,gCAAgC;IAChC,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IAEnD,2EAA2E;IAC3E,wEAAwE;IACxE,yDAAyD;IACzD,GAAG,CAAC,SAAS,CACX,yBAAyB,EACzB;QACE,oBAAoB;QACpB,+FAA+F;QAC/F,+DAA+D;QAC/D,sBAAsB;QACtB,2CAA2C;QAC3C,oBAAoB;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,oCAAoC;IACpC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;IACtE,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEpC,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
@@ -0,0 +1,78 @@
1
+ import { Router } from 'express';
2
+ import { ConversationManager, conversationManager } from '../../server/conversation.js';
3
+ const router = Router();
4
+ /**
5
+ * GET /api/chat/history
6
+ * Returns all conversations (active + archived) from files
7
+ */
8
+ router.get('/history', (_req, res) => {
9
+ try {
10
+ // Load active conversations from both in-memory (runtime) and file
11
+ const inMemoryActive = conversationManager.listActive();
12
+ const fileActive = ConversationManager.loadFromFile();
13
+ // Merge and dedupe by ID (in-memory takes precedence)
14
+ const activeMap = new Map();
15
+ [...fileActive, ...inMemoryActive].forEach((conv) => {
16
+ activeMap.set(conv.id, conv);
17
+ });
18
+ const activeConversations = Array.from(activeMap.values());
19
+ // Load archived conversations and dedupe
20
+ const archivedRaw = ConversationManager.loadHistoryFromFile();
21
+ // Get active IDs to exclude from archived (active takes precedence)
22
+ const activeIds = new Set(activeConversations.map((c) => c.id));
23
+ // Dedupe archived: keep only first occurrence (newest) and exclude active ones
24
+ const archivedMap = new Map();
25
+ archivedRaw.forEach((conv) => {
26
+ if (!activeIds.has(conv.id) && !archivedMap.has(conv.id)) {
27
+ archivedMap.set(conv.id, conv);
28
+ }
29
+ });
30
+ const archivedConversations = Array.from(archivedMap.values());
31
+ // Format active conversations for UI display
32
+ const active = activeConversations.map((conv) => ({
33
+ id: conv.id,
34
+ model: conv.model,
35
+ messageCount: conv.messages.length,
36
+ messages: conv.messages.map((msg, idx) => ({
37
+ id: `${conv.id}-${idx}`,
38
+ role: msg.role,
39
+ content: msg.content,
40
+ })),
41
+ createdAt: conv.createdAt.toISOString(),
42
+ lastActivityAt: conv.lastActivityAt.toISOString(),
43
+ status: 'active',
44
+ }));
45
+ // Format archived conversations for UI display
46
+ const archived = archivedConversations.map((conv) => ({
47
+ id: conv.id,
48
+ model: conv.model,
49
+ messageCount: conv.messages.length,
50
+ messages: conv.messages.map((msg, idx) => ({
51
+ id: `${conv.id}-${idx}`,
52
+ role: msg.role,
53
+ content: msg.content,
54
+ })),
55
+ createdAt: conv.createdAt,
56
+ lastActivityAt: conv.lastActivityAt,
57
+ endedAt: conv.endedAt,
58
+ endReason: conv.endReason,
59
+ status: 'archived',
60
+ }));
61
+ // Combine: active first, then archived (already sorted by newest first)
62
+ const allConversations = [...active, ...archived];
63
+ res.json({
64
+ count: allConversations.length,
65
+ activeCount: active.length,
66
+ archivedCount: archived.length,
67
+ conversations: allConversations,
68
+ });
69
+ }
70
+ catch (error) {
71
+ res.status(500).json({
72
+ error: 'Failed to fetch conversation history',
73
+ message: error instanceof Error ? error.message : 'Unknown error',
74
+ });
75
+ }
76
+ });
77
+ export default router;
78
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/api/routes/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export { router as configRoutes };