claudia-orchestrator 0.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/LICENSE +201 -0
- package/README.md +109 -0
- package/dist/cli-parser.d.ts +11 -0
- package/dist/cli-parser.d.ts.map +1 -0
- package/dist/cli-parser.js +57 -0
- package/dist/cli-parser.js.map +1 -0
- package/dist/cui-server.d.ts +69 -0
- package/dist/cui-server.d.ts.map +1 -0
- package/dist/cui-server.js +705 -0
- package/dist/cui-server.js.map +1 -0
- package/dist/mcp-server/claudia-tools.d.ts +15 -0
- package/dist/mcp-server/claudia-tools.d.ts.map +1 -0
- package/dist/mcp-server/claudia-tools.js +366 -0
- package/dist/mcp-server/claudia-tools.js.map +1 -0
- package/dist/mcp-server/index.d.ts +3 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +176 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +18 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +136 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors-setup.d.ts +7 -0
- package/dist/middleware/cors-setup.d.ts.map +1 -0
- package/dist/middleware/cors-setup.js +8 -0
- package/dist/middleware/cors-setup.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +4 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/query-parser.d.ts +11 -0
- package/dist/middleware/query-parser.d.ts.map +1 -0
- package/dist/middleware/query-parser.js +68 -0
- package/dist/middleware/query-parser.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +4 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +29 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/process-daemon/index.d.ts +14 -0
- package/dist/process-daemon/index.d.ts.map +1 -0
- package/dist/process-daemon/index.js +51 -0
- package/dist/process-daemon/index.js.map +1 -0
- package/dist/process-daemon/process-daemon.d.ts +78 -0
- package/dist/process-daemon/process-daemon.d.ts.map +1 -0
- package/dist/process-daemon/process-daemon.js +568 -0
- package/dist/process-daemon/process-daemon.js.map +1 -0
- package/dist/process-daemon/process-manager-client.d.ts +108 -0
- package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-client.js +314 -0
- package/dist/process-daemon/process-manager-client.js.map +1 -0
- package/dist/process-daemon/process-manager-interface.d.ts +47 -0
- package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-interface.js +8 -0
- package/dist/process-daemon/process-manager-interface.js.map +1 -0
- package/dist/process-daemon/test-daemon.d.ts +12 -0
- package/dist/process-daemon/test-daemon.d.ts.map +1 -0
- package/dist/process-daemon/test-daemon.js +81 -0
- package/dist/process-daemon/test-daemon.js.map +1 -0
- package/dist/process-daemon/types.d.ts +85 -0
- package/dist/process-daemon/types.d.ts.map +1 -0
- package/dist/process-daemon/types.js +8 -0
- package/dist/process-daemon/types.js.map +1 -0
- package/dist/routes/claudia.routes.d.ts +10 -0
- package/dist/routes/claudia.routes.d.ts.map +1 -0
- package/dist/routes/claudia.routes.js +123 -0
- package/dist/routes/claudia.routes.js.map +1 -0
- package/dist/routes/config.routes.d.ts +4 -0
- package/dist/routes/config.routes.d.ts.map +1 -0
- package/dist/routes/config.routes.js +27 -0
- package/dist/routes/config.routes.js.map +1 -0
- package/dist/routes/conversation.routes.d.ts +8 -0
- package/dist/routes/conversation.routes.d.ts.map +1 -0
- package/dist/routes/conversation.routes.js +870 -0
- package/dist/routes/conversation.routes.js.map +1 -0
- package/dist/routes/filesystem.routes.d.ts +4 -0
- package/dist/routes/filesystem.routes.d.ts.map +1 -0
- package/dist/routes/filesystem.routes.js +86 -0
- package/dist/routes/filesystem.routes.js.map +1 -0
- package/dist/routes/gemini.routes.d.ts +4 -0
- package/dist/routes/gemini.routes.d.ts.map +1 -0
- package/dist/routes/gemini.routes.js +93 -0
- package/dist/routes/gemini.routes.js.map +1 -0
- package/dist/routes/insights.routes.d.ts +17 -0
- package/dist/routes/insights.routes.d.ts.map +1 -0
- package/dist/routes/insights.routes.js +417 -0
- package/dist/routes/insights.routes.js.map +1 -0
- package/dist/routes/license.routes.d.ts +3 -0
- package/dist/routes/license.routes.d.ts.map +1 -0
- package/dist/routes/license.routes.js +111 -0
- package/dist/routes/license.routes.js.map +1 -0
- package/dist/routes/log.routes.d.ts +3 -0
- package/dist/routes/log.routes.d.ts.map +1 -0
- package/dist/routes/log.routes.js +65 -0
- package/dist/routes/log.routes.js.map +1 -0
- package/dist/routes/notifications.routes.d.ts +4 -0
- package/dist/routes/notifications.routes.d.ts.map +1 -0
- package/dist/routes/notifications.routes.js +71 -0
- package/dist/routes/notifications.routes.js.map +1 -0
- package/dist/routes/permission.routes.d.ts +4 -0
- package/dist/routes/permission.routes.d.ts.map +1 -0
- package/dist/routes/permission.routes.js +116 -0
- package/dist/routes/permission.routes.js.map +1 -0
- package/dist/routes/question.routes.d.ts +8 -0
- package/dist/routes/question.routes.d.ts.map +1 -0
- package/dist/routes/question.routes.js +82 -0
- package/dist/routes/question.routes.js.map +1 -0
- package/dist/routes/streaming.routes.d.ts +4 -0
- package/dist/routes/streaming.routes.d.ts.map +1 -0
- package/dist/routes/streaming.routes.js +28 -0
- package/dist/routes/streaming.routes.js.map +1 -0
- package/dist/routes/system.routes.d.ts +5 -0
- package/dist/routes/system.routes.d.ts.map +1 -0
- package/dist/routes/system.routes.js +103 -0
- package/dist/routes/system.routes.js.map +1 -0
- package/dist/routes/working-directories.routes.d.ts +4 -0
- package/dist/routes/working-directories.routes.d.ts.map +1 -0
- package/dist/routes/working-directories.routes.js +25 -0
- package/dist/routes/working-directories.routes.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +34 -0
- package/dist/server.js.map +1 -0
- package/dist/services/ToolMetricsService.d.ts +53 -0
- package/dist/services/ToolMetricsService.d.ts.map +1 -0
- package/dist/services/ToolMetricsService.js +230 -0
- package/dist/services/ToolMetricsService.js.map +1 -0
- package/dist/services/anthropic-service.d.ts +186 -0
- package/dist/services/anthropic-service.d.ts.map +1 -0
- package/dist/services/anthropic-service.js +1132 -0
- package/dist/services/anthropic-service.js.map +1 -0
- package/dist/services/claude-history-reader.d.ts +126 -0
- package/dist/services/claude-history-reader.d.ts.map +1 -0
- package/dist/services/claude-history-reader.js +717 -0
- package/dist/services/claude-history-reader.js.map +1 -0
- package/dist/services/claude-process-manager.d.ts +108 -0
- package/dist/services/claude-process-manager.d.ts.map +1 -0
- package/dist/services/claude-process-manager.js +909 -0
- package/dist/services/claude-process-manager.js.map +1 -0
- package/dist/services/claude-router-service.d.ts +19 -0
- package/dist/services/claude-router-service.d.ts.map +1 -0
- package/dist/services/claude-router-service.js +160 -0
- package/dist/services/claude-router-service.js.map +1 -0
- package/dist/services/claudia-service.d.ts +77 -0
- package/dist/services/claudia-service.d.ts.map +1 -0
- package/dist/services/claudia-service.js +194 -0
- package/dist/services/claudia-service.js.map +1 -0
- package/dist/services/commands-service.d.ts +18 -0
- package/dist/services/commands-service.d.ts.map +1 -0
- package/dist/services/commands-service.js +76 -0
- package/dist/services/commands-service.js.map +1 -0
- package/dist/services/config-service.d.ts +68 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +429 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/conversation-cache.d.ts +86 -0
- package/dist/services/conversation-cache.d.ts.map +1 -0
- package/dist/services/conversation-cache.js +235 -0
- package/dist/services/conversation-cache.js.map +1 -0
- package/dist/services/conversation-status-manager.d.ts +98 -0
- package/dist/services/conversation-status-manager.d.ts.map +1 -0
- package/dist/services/conversation-status-manager.js +295 -0
- package/dist/services/conversation-status-manager.js.map +1 -0
- package/dist/services/cost-tracker.d.ts +87 -0
- package/dist/services/cost-tracker.d.ts.map +1 -0
- package/dist/services/cost-tracker.js +335 -0
- package/dist/services/cost-tracker.js.map +1 -0
- package/dist/services/file-system-service.d.ts +61 -0
- package/dist/services/file-system-service.d.ts.map +1 -0
- package/dist/services/file-system-service.js +348 -0
- package/dist/services/file-system-service.js.map +1 -0
- package/dist/services/gemini-service.d.ts +72 -0
- package/dist/services/gemini-service.d.ts.map +1 -0
- package/dist/services/gemini-service.js +431 -0
- package/dist/services/gemini-service.js.map +1 -0
- package/dist/services/insight-queue.d.ts +99 -0
- package/dist/services/insight-queue.d.ts.map +1 -0
- package/dist/services/insight-queue.js +277 -0
- package/dist/services/insight-queue.js.map +1 -0
- package/dist/services/insights-service.d.ts +102 -0
- package/dist/services/insights-service.d.ts.map +1 -0
- package/dist/services/insights-service.js +1152 -0
- package/dist/services/insights-service.js.map +1 -0
- package/dist/services/json-lines-parser.d.ts +19 -0
- package/dist/services/json-lines-parser.d.ts.map +1 -0
- package/dist/services/json-lines-parser.js +56 -0
- package/dist/services/json-lines-parser.js.map +1 -0
- package/dist/services/license-service.d.ts +69 -0
- package/dist/services/license-service.d.ts.map +1 -0
- package/dist/services/license-service.js +330 -0
- package/dist/services/license-service.js.map +1 -0
- package/dist/services/log-formatter.d.ts +5 -0
- package/dist/services/log-formatter.d.ts.map +1 -0
- package/dist/services/log-formatter.js +77 -0
- package/dist/services/log-formatter.js.map +1 -0
- package/dist/services/log-stream-buffer.d.ts +11 -0
- package/dist/services/log-stream-buffer.d.ts.map +1 -0
- package/dist/services/log-stream-buffer.js +36 -0
- package/dist/services/log-stream-buffer.js.map +1 -0
- package/dist/services/logger.d.ts +71 -0
- package/dist/services/logger.d.ts.map +1 -0
- package/dist/services/logger.js +215 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/services/mcp-config-generator.d.ts +32 -0
- package/dist/services/mcp-config-generator.d.ts.map +1 -0
- package/dist/services/mcp-config-generator.js +126 -0
- package/dist/services/mcp-config-generator.js.map +1 -0
- package/dist/services/message-filter.d.ts +22 -0
- package/dist/services/message-filter.d.ts.map +1 -0
- package/dist/services/message-filter.js +57 -0
- package/dist/services/message-filter.js.map +1 -0
- package/dist/services/notification-service.d.ts +45 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +184 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/permission-tracker.d.ts +67 -0
- package/dist/services/permission-tracker.d.ts.map +1 -0
- package/dist/services/permission-tracker.js +161 -0
- package/dist/services/permission-tracker.js.map +1 -0
- package/dist/services/process-manager-factory.d.ts +81 -0
- package/dist/services/process-manager-factory.d.ts.map +1 -0
- package/dist/services/process-manager-factory.js +211 -0
- package/dist/services/process-manager-factory.js.map +1 -0
- package/dist/services/question-tracker.d.ts +47 -0
- package/dist/services/question-tracker.d.ts.map +1 -0
- package/dist/services/question-tracker.js +105 -0
- package/dist/services/question-tracker.js.map +1 -0
- package/dist/services/session-activity-watcher.d.ts +33 -0
- package/dist/services/session-activity-watcher.d.ts.map +1 -0
- package/dist/services/session-activity-watcher.js +194 -0
- package/dist/services/session-activity-watcher.js.map +1 -0
- package/dist/services/session-info-service.d.ts +228 -0
- package/dist/services/session-info-service.d.ts.map +1 -0
- package/dist/services/session-info-service.js +920 -0
- package/dist/services/session-info-service.js.map +1 -0
- package/dist/services/session-insights-service.d.ts +119 -0
- package/dist/services/session-insights-service.d.ts.map +1 -0
- package/dist/services/session-insights-service.js +889 -0
- package/dist/services/session-insights-service.js.map +1 -0
- package/dist/services/stream-manager.d.ts +62 -0
- package/dist/services/stream-manager.d.ts.map +1 -0
- package/dist/services/stream-manager.js +239 -0
- package/dist/services/stream-manager.js.map +1 -0
- package/dist/services/web-push-service.d.ts +48 -0
- package/dist/services/web-push-service.d.ts.map +1 -0
- package/dist/services/web-push-service.js +186 -0
- package/dist/services/web-push-service.js.map +1 -0
- package/dist/services/working-directories-service.d.ts +19 -0
- package/dist/services/working-directories-service.d.ts.map +1 -0
- package/dist/services/working-directories-service.js +103 -0
- package/dist/services/working-directories-service.js.map +1 -0
- package/dist/types/config.d.ts +111 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +14 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/express.d.ts +5 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/express.js +2 -0
- package/dist/types/express.js.map +1 -0
- package/dist/types/index.d.ts +325 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/insights.d.ts +99 -0
- package/dist/types/insights.d.ts.map +1 -0
- package/dist/types/insights.js +7 -0
- package/dist/types/insights.js.map +1 -0
- package/dist/types/license.d.ts +70 -0
- package/dist/types/license.d.ts.map +1 -0
- package/dist/types/license.js +5 -0
- package/dist/types/license.js.map +1 -0
- package/dist/types/router-config.d.ts +13 -0
- package/dist/types/router-config.d.ts.map +1 -0
- package/dist/types/router-config.js +2 -0
- package/dist/types/router-config.js.map +1 -0
- package/dist/utils/constants.d.ts +26 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +28 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/machine-id.d.ts +7 -0
- package/dist/utils/machine-id.d.ts.map +1 -0
- package/dist/utils/machine-id.js +76 -0
- package/dist/utils/machine-id.js.map +1 -0
- package/dist/utils/server-startup.d.ts +13 -0
- package/dist/utils/server-startup.d.ts.map +1 -0
- package/dist/utils/server-startup.js +20 -0
- package/dist/utils/server-startup.js.map +1 -0
- package/dist/web/assets/main-DAc2rjJ2.css +1 -0
- package/dist/web/assets/main-DvlZ02mT.js +137 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/favicon.svg +22 -0
- package/dist/web/icon-192x192.png +0 -0
- package/dist/web/icon-512x512.png +0 -0
- package/dist/web/index.html +36 -0
- package/dist/web/manifest.json +61 -0
- package/package.json +174 -0
- package/scripts/postinstall.js +30 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { existsSync, constants } from 'fs';
|
|
6
|
+
import ignore from 'ignore';
|
|
7
|
+
import { CUIError } from '../types/index.js';
|
|
8
|
+
import { createLogger } from './logger.js';
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
/**
|
|
11
|
+
* Service for secure file system operations
|
|
12
|
+
*/
|
|
13
|
+
export class FileSystemService {
|
|
14
|
+
logger;
|
|
15
|
+
maxFileSize = 10 * 1024 * 1024; // 10MB default
|
|
16
|
+
allowedBasePaths = []; // Empty means all paths allowed
|
|
17
|
+
constructor(maxFileSize, allowedBasePaths) {
|
|
18
|
+
this.logger = createLogger('FileSystemService');
|
|
19
|
+
if (maxFileSize !== undefined) {
|
|
20
|
+
this.maxFileSize = maxFileSize;
|
|
21
|
+
}
|
|
22
|
+
if (allowedBasePaths) {
|
|
23
|
+
this.allowedBasePaths = allowedBasePaths.map(p => path.normalize(p));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* List directory contents with security checks
|
|
28
|
+
*/
|
|
29
|
+
async listDirectory(requestedPath, recursive = false, respectGitignore = false) {
|
|
30
|
+
this.logger.debug('List directory requested', { requestedPath, recursive, respectGitignore });
|
|
31
|
+
try {
|
|
32
|
+
// Validate and normalize path
|
|
33
|
+
const safePath = await this.validatePath(requestedPath);
|
|
34
|
+
// Check if path exists and is a directory
|
|
35
|
+
const stats = await fs.stat(safePath);
|
|
36
|
+
if (!stats.isDirectory()) {
|
|
37
|
+
throw new CUIError('NOT_A_DIRECTORY', `Path is not a directory: ${requestedPath}`, 400);
|
|
38
|
+
}
|
|
39
|
+
// Initialize gitignore if requested
|
|
40
|
+
let ig = null;
|
|
41
|
+
if (respectGitignore) {
|
|
42
|
+
ig = await this.loadGitignore(safePath);
|
|
43
|
+
}
|
|
44
|
+
// Get entries
|
|
45
|
+
const entries = recursive
|
|
46
|
+
? await this.listDirectoryRecursive(safePath, safePath, ig)
|
|
47
|
+
: await this.listDirectoryFlat(safePath, ig);
|
|
48
|
+
// Sort entries: directories first, then by name
|
|
49
|
+
entries.sort((a, b) => {
|
|
50
|
+
if (a.type !== b.type) {
|
|
51
|
+
return a.type === 'directory' ? -1 : 1;
|
|
52
|
+
}
|
|
53
|
+
return a.name.localeCompare(b.name);
|
|
54
|
+
});
|
|
55
|
+
this.logger.debug('Directory listed successfully', {
|
|
56
|
+
path: safePath,
|
|
57
|
+
entryCount: entries.length,
|
|
58
|
+
recursive,
|
|
59
|
+
respectGitignore
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
path: safePath,
|
|
63
|
+
entries,
|
|
64
|
+
total: entries.length
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error instanceof CUIError) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
const errorCode = error.code;
|
|
72
|
+
if (errorCode === 'ENOENT') {
|
|
73
|
+
throw new CUIError('PATH_NOT_FOUND', `Path not found: ${requestedPath}`, 404);
|
|
74
|
+
}
|
|
75
|
+
else if (errorCode === 'EACCES') {
|
|
76
|
+
throw new CUIError('ACCESS_DENIED', `Access denied to path: ${requestedPath}`, 403);
|
|
77
|
+
}
|
|
78
|
+
this.logger.error('Error listing directory', error, { requestedPath });
|
|
79
|
+
throw new CUIError('LIST_DIRECTORY_FAILED', `Failed to list directory: ${error}`, 500);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read file contents with security checks
|
|
84
|
+
*/
|
|
85
|
+
async readFile(requestedPath) {
|
|
86
|
+
this.logger.debug('Read file requested', { requestedPath });
|
|
87
|
+
try {
|
|
88
|
+
// Validate and normalize path
|
|
89
|
+
const safePath = await this.validatePath(requestedPath);
|
|
90
|
+
// Check if path exists and is a file
|
|
91
|
+
const stats = await fs.stat(safePath);
|
|
92
|
+
if (!stats.isFile()) {
|
|
93
|
+
throw new CUIError('NOT_A_FILE', `Path is not a file: ${requestedPath}`, 400);
|
|
94
|
+
}
|
|
95
|
+
// Check file size
|
|
96
|
+
if (stats.size > this.maxFileSize) {
|
|
97
|
+
throw new CUIError('FILE_TOO_LARGE', `File size (${stats.size} bytes) exceeds maximum allowed size (${this.maxFileSize} bytes)`, 400);
|
|
98
|
+
}
|
|
99
|
+
// Read file content
|
|
100
|
+
const content = await fs.readFile(safePath, 'utf-8');
|
|
101
|
+
// Check if content is valid UTF-8 text
|
|
102
|
+
if (!this.isValidUtf8(content)) {
|
|
103
|
+
throw new CUIError('BINARY_FILE', 'File appears to be binary or not valid UTF-8', 400);
|
|
104
|
+
}
|
|
105
|
+
this.logger.debug('File read successfully', {
|
|
106
|
+
path: safePath,
|
|
107
|
+
size: stats.size
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
path: safePath,
|
|
111
|
+
content,
|
|
112
|
+
size: stats.size,
|
|
113
|
+
lastModified: stats.mtime.toISOString(),
|
|
114
|
+
encoding: 'utf-8'
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (error instanceof CUIError) {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
const errorCode = error.code;
|
|
122
|
+
if (errorCode === 'ENOENT') {
|
|
123
|
+
throw new CUIError('FILE_NOT_FOUND', `File not found: ${requestedPath}`, 404);
|
|
124
|
+
}
|
|
125
|
+
else if (errorCode === 'EACCES') {
|
|
126
|
+
throw new CUIError('ACCESS_DENIED', `Access denied to file: ${requestedPath}`, 403);
|
|
127
|
+
}
|
|
128
|
+
this.logger.error('Error reading file', error, { requestedPath });
|
|
129
|
+
throw new CUIError('READ_FILE_FAILED', `Failed to read file: ${error}`, 500);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validate and normalize a path to prevent path traversal attacks
|
|
134
|
+
*/
|
|
135
|
+
async validatePath(requestedPath) {
|
|
136
|
+
// Require absolute paths
|
|
137
|
+
if (!path.isAbsolute(requestedPath)) {
|
|
138
|
+
throw new CUIError('INVALID_PATH', 'Path must be absolute', 400);
|
|
139
|
+
}
|
|
140
|
+
// Check for path traversal attempts before normalization
|
|
141
|
+
if (requestedPath.includes('..')) {
|
|
142
|
+
this.logger.warn('Path traversal attempt detected', {
|
|
143
|
+
requestedPath
|
|
144
|
+
});
|
|
145
|
+
throw new CUIError('PATH_TRAVERSAL_DETECTED', 'Invalid path: path traversal detected', 400);
|
|
146
|
+
}
|
|
147
|
+
// Normalize the path to resolve . segments and clean up
|
|
148
|
+
const normalizedPath = path.normalize(requestedPath);
|
|
149
|
+
// Check against allowed base paths if configured
|
|
150
|
+
if (this.allowedBasePaths.length > 0) {
|
|
151
|
+
const isAllowed = this.allowedBasePaths.some(basePath => normalizedPath.startsWith(basePath));
|
|
152
|
+
if (!isAllowed) {
|
|
153
|
+
this.logger.warn('Path outside allowed directories', {
|
|
154
|
+
requestedPath,
|
|
155
|
+
normalizedPath,
|
|
156
|
+
allowedBasePaths: this.allowedBasePaths
|
|
157
|
+
});
|
|
158
|
+
throw new CUIError('PATH_NOT_ALLOWED', 'Path is outside allowed directories', 403);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Additional security checks
|
|
162
|
+
const segments = normalizedPath.split(path.sep);
|
|
163
|
+
for (const segment of segments) {
|
|
164
|
+
if (!segment)
|
|
165
|
+
continue;
|
|
166
|
+
// Check for hidden files/directories
|
|
167
|
+
if (segment.startsWith('.')) {
|
|
168
|
+
this.logger.warn('Hidden file/directory detected', {
|
|
169
|
+
requestedPath,
|
|
170
|
+
segment
|
|
171
|
+
});
|
|
172
|
+
throw new CUIError('INVALID_PATH', 'Path contains hidden files/directories', 400);
|
|
173
|
+
}
|
|
174
|
+
// Check for null bytes
|
|
175
|
+
if (segment.includes('\u0000')) {
|
|
176
|
+
this.logger.warn('Null byte detected in path', {
|
|
177
|
+
requestedPath,
|
|
178
|
+
segment
|
|
179
|
+
});
|
|
180
|
+
throw new CUIError('INVALID_PATH', 'Path contains null bytes', 400);
|
|
181
|
+
}
|
|
182
|
+
// Check for invalid characters
|
|
183
|
+
if (/[<>:|?*]/.test(segment)) {
|
|
184
|
+
this.logger.warn('Invalid characters detected in path', {
|
|
185
|
+
requestedPath,
|
|
186
|
+
segment
|
|
187
|
+
});
|
|
188
|
+
throw new CUIError('INVALID_PATH', 'Path contains invalid characters', 400);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
this.logger.debug('Path validated successfully', {
|
|
192
|
+
requestedPath,
|
|
193
|
+
normalizedPath
|
|
194
|
+
});
|
|
195
|
+
return normalizedPath;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if content appears to be valid UTF-8 text
|
|
199
|
+
*/
|
|
200
|
+
isValidUtf8(content) {
|
|
201
|
+
// Check for null bytes - common binary file indicator
|
|
202
|
+
if (content.includes('\u0000')) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
// Check for control characters (excluding tab, newline, and carriage return)
|
|
206
|
+
for (let i = 0; i < content.length; i++) {
|
|
207
|
+
const charCode = content.charCodeAt(i);
|
|
208
|
+
// Allow tab (9), newline (10), and carriage return (13)
|
|
209
|
+
// Reject other control characters (1-8, 11-12, 14-31)
|
|
210
|
+
if ((charCode >= 1 && charCode <= 8) ||
|
|
211
|
+
(charCode >= 11 && charCode <= 12) ||
|
|
212
|
+
(charCode >= 14 && charCode <= 31)) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* List directory contents without recursion
|
|
220
|
+
*/
|
|
221
|
+
async listDirectoryFlat(dirPath, ig) {
|
|
222
|
+
const dirents = await fs.readdir(dirPath, { withFileTypes: true });
|
|
223
|
+
const entries = [];
|
|
224
|
+
for (const dirent of dirents) {
|
|
225
|
+
// Check gitignore BEFORE any expensive operations
|
|
226
|
+
if (ig && ig.ignores(dirent.name)) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const fullPath = path.join(dirPath, dirent.name);
|
|
230
|
+
const stats = await fs.stat(fullPath);
|
|
231
|
+
entries.push({
|
|
232
|
+
name: dirent.name,
|
|
233
|
+
type: dirent.isDirectory() ? 'directory' : 'file',
|
|
234
|
+
size: dirent.isFile() ? stats.size : undefined,
|
|
235
|
+
lastModified: stats.mtime.toISOString()
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return entries;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* List directory contents recursively
|
|
242
|
+
*/
|
|
243
|
+
async listDirectoryRecursive(dirPath, basePath, ig) {
|
|
244
|
+
const entries = [];
|
|
245
|
+
async function traverse(currentPath) {
|
|
246
|
+
const dirents = await fs.readdir(currentPath, { withFileTypes: true });
|
|
247
|
+
for (const dirent of dirents) {
|
|
248
|
+
const fullPath = path.join(currentPath, dirent.name);
|
|
249
|
+
const relativePath = path.relative(basePath, fullPath);
|
|
250
|
+
// Check gitignore BEFORE any expensive operations
|
|
251
|
+
if (ig && ig.ignores(relativePath)) {
|
|
252
|
+
// Skip this entry entirely - don't stat, don't recurse into directories
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const stats = await fs.stat(fullPath);
|
|
256
|
+
entries.push({
|
|
257
|
+
name: relativePath,
|
|
258
|
+
type: dirent.isDirectory() ? 'directory' : 'file',
|
|
259
|
+
size: dirent.isFile() ? stats.size : undefined,
|
|
260
|
+
lastModified: stats.mtime.toISOString()
|
|
261
|
+
});
|
|
262
|
+
// Recurse into subdirectories (already checked it's not ignored)
|
|
263
|
+
if (dirent.isDirectory()) {
|
|
264
|
+
await traverse(fullPath);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
await traverse(dirPath);
|
|
269
|
+
return entries;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Load gitignore patterns from a directory and its parents
|
|
273
|
+
*/
|
|
274
|
+
async loadGitignore(dirPath) {
|
|
275
|
+
const ig = ignore();
|
|
276
|
+
// Load .gitignore from the directory
|
|
277
|
+
try {
|
|
278
|
+
const gitignorePath = path.join(dirPath, '.gitignore');
|
|
279
|
+
const content = await fs.readFile(gitignorePath, 'utf-8');
|
|
280
|
+
ig.add(content);
|
|
281
|
+
this.logger.debug('Loaded .gitignore', { path: gitignorePath });
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
// .gitignore doesn't exist or can't be read - that's fine
|
|
285
|
+
const errorCode = error.code;
|
|
286
|
+
if (errorCode !== 'ENOENT') {
|
|
287
|
+
this.logger.debug('Error reading .gitignore', { error, path: dirPath });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Always ignore .git directory
|
|
291
|
+
ig.add('.git');
|
|
292
|
+
return ig;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Check if a directory is a git repository
|
|
296
|
+
*/
|
|
297
|
+
async isGitRepository(dirPath) {
|
|
298
|
+
try {
|
|
299
|
+
await execAsync('git rev-parse --git-dir', { cwd: dirPath });
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
this.logger.debug('Directory is not a git repository', { dirPath, error });
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get current git HEAD commit hash
|
|
309
|
+
*/
|
|
310
|
+
async getCurrentGitHead(dirPath) {
|
|
311
|
+
try {
|
|
312
|
+
const { stdout } = await execAsync('git rev-parse HEAD', { cwd: dirPath });
|
|
313
|
+
return stdout.trim();
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
this.logger.debug('Failed to get git HEAD', { dirPath, error });
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Validate that an executable exists and has executable permissions
|
|
322
|
+
*/
|
|
323
|
+
async validateExecutable(executablePath) {
|
|
324
|
+
this.logger.debug('Validating executable', { executablePath });
|
|
325
|
+
try {
|
|
326
|
+
// Check if file exists
|
|
327
|
+
if (!existsSync(executablePath)) {
|
|
328
|
+
throw new CUIError('EXECUTABLE_NOT_FOUND', `Executable not found: ${executablePath}`, 404);
|
|
329
|
+
}
|
|
330
|
+
// Check if file is executable
|
|
331
|
+
try {
|
|
332
|
+
await fs.access(executablePath, constants.X_OK);
|
|
333
|
+
}
|
|
334
|
+
catch (_error) {
|
|
335
|
+
throw new CUIError('NOT_EXECUTABLE', `File exists but is not executable: ${executablePath}`, 403);
|
|
336
|
+
}
|
|
337
|
+
this.logger.debug('Executable validation successful', { executablePath });
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
if (error instanceof CUIError) {
|
|
341
|
+
throw error;
|
|
342
|
+
}
|
|
343
|
+
this.logger.error('Error validating executable', error, { executablePath });
|
|
344
|
+
throw new CUIError('EXECUTABLE_VALIDATION_FAILED', `Failed to validate executable: ${error}`, 500);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=file-system-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system-service.js","sourceRoot":"","sources":["../../src/services/file-system-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export interface GeminiHealthResponse {
|
|
2
|
+
status: 'healthy' | 'unhealthy';
|
|
3
|
+
message: string;
|
|
4
|
+
apiKeyValid: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface GeminiTranscribeRequest {
|
|
7
|
+
audio: string;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GeminiTranscribeResponse {
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
export interface GeminiSummarizeRequest {
|
|
14
|
+
text: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GeminiSummarizeResponse {
|
|
17
|
+
title: string;
|
|
18
|
+
keypoints: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface GeminiSessionNameResponse {
|
|
21
|
+
name: string;
|
|
22
|
+
}
|
|
23
|
+
export interface GeminiImageResponse {
|
|
24
|
+
imageData: string;
|
|
25
|
+
mimeType: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class GeminiService {
|
|
28
|
+
private logger;
|
|
29
|
+
private genAI;
|
|
30
|
+
private model;
|
|
31
|
+
constructor();
|
|
32
|
+
initialize(): Promise<void>;
|
|
33
|
+
checkHealth(): Promise<GeminiHealthResponse>;
|
|
34
|
+
transcribe(audio: string, mimeType: string): Promise<GeminiTranscribeResponse>;
|
|
35
|
+
summarize(text: string): Promise<GeminiSummarizeResponse>;
|
|
36
|
+
generateSessionName(conversationText: string): Promise<GeminiSessionNameResponse>;
|
|
37
|
+
/**
|
|
38
|
+
* Generate structured session insights for display
|
|
39
|
+
*/
|
|
40
|
+
generateSessionInsights(conversationText: string): Promise<{
|
|
41
|
+
purposes: string[];
|
|
42
|
+
milestones: Array<{
|
|
43
|
+
label: string;
|
|
44
|
+
status: 'done' | 'current' | 'pending';
|
|
45
|
+
}>;
|
|
46
|
+
recentActions: string[];
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Map session theme to a neon glow color for visual differentiation.
|
|
50
|
+
* This creates instant visual grouping - all debugging sessions are amber,
|
|
51
|
+
* all implementing sessions are green, etc.
|
|
52
|
+
*/
|
|
53
|
+
private getColorForTheme;
|
|
54
|
+
/**
|
|
55
|
+
* Create a black canvas PNG to use as base for image editing.
|
|
56
|
+
* Using inpainting on a black canvas ensures consistent black backgrounds.
|
|
57
|
+
*/
|
|
58
|
+
private createBlackCanvas;
|
|
59
|
+
/**
|
|
60
|
+
* Generate an abstract visual identity image for a session.
|
|
61
|
+
* Uses image editing on a black canvas to ensure consistent black backgrounds,
|
|
62
|
+
* with color-mood mapping for instant visual differentiation between session types.
|
|
63
|
+
*/
|
|
64
|
+
generateSessionImage(sessionContext: {
|
|
65
|
+
mission: string;
|
|
66
|
+
project?: string;
|
|
67
|
+
theme?: string;
|
|
68
|
+
workTypes?: string[];
|
|
69
|
+
}): Promise<GeminiImageResponse>;
|
|
70
|
+
}
|
|
71
|
+
export declare const geminiService: GeminiService;
|
|
72
|
+
//# sourceMappingURL=gemini-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-service.d.ts","sourceRoot":"","sources":["../../src/services/gemini-service.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,KAAK,CAAS;;IAOhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B,WAAW,IAAI,OAAO,CAAC,oBAAoB,CAAC;IA4C5C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAwC9E,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAgEzD,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA2DvF;;OAEG;IACG,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,UAAU,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;SAAE,CAAC,CAAC;QAC7E,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA+EF;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;;OAGG;YACW,iBAAiB;IAY/B;;;;OAIG;IACG,oBAAoB,CAAC,cAAc,EAAE;QACzC,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAsFjC;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|