hawkeye-mcp-server 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.
- package/CHANGELOG.md +123 -0
- package/INSTALLATION.md +734 -0
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/SPECIFICATION.md +1073 -0
- package/USAGE.md +849 -0
- package/build/config/config.d.ts +58 -0
- package/build/config/config.js +100 -0
- package/build/config/config.js.map +1 -0
- package/build/index.d.ts +6 -0
- package/build/index.js +138 -0
- package/build/index.js.map +1 -0
- package/build/services/auth.service.d.ts +34 -0
- package/build/services/auth.service.js +96 -0
- package/build/services/auth.service.js.map +1 -0
- package/build/services/project.service.d.ts +50 -0
- package/build/services/project.service.js +136 -0
- package/build/services/project.service.js.map +1 -0
- package/build/services/session.service.d.ts +68 -0
- package/build/services/session.service.js +357 -0
- package/build/services/session.service.js.map +1 -0
- package/build/tools/continue-investigation.d.ts +10 -0
- package/build/tools/continue-investigation.js +84 -0
- package/build/tools/continue-investigation.js.map +1 -0
- package/build/tools/get-incident-report.d.ts +10 -0
- package/build/tools/get-incident-report.js +62 -0
- package/build/tools/get-incident-report.js.map +1 -0
- package/build/tools/get-session-report.d.ts +25 -0
- package/build/tools/get-session-report.js +46 -0
- package/build/tools/get-session-report.js.map +1 -0
- package/build/tools/get-session-summary.d.ts +22 -0
- package/build/tools/get-session-summary.js +41 -0
- package/build/tools/get-session-summary.js.map +1 -0
- package/build/tools/get-status.d.ts +10 -0
- package/build/tools/get-status.js +129 -0
- package/build/tools/get-status.js.map +1 -0
- package/build/tools/index.d.ts +29 -0
- package/build/tools/index.js +349 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/inspect-session.d.ts +28 -0
- package/build/tools/inspect-session.js +51 -0
- package/build/tools/inspect-session.js.map +1 -0
- package/build/tools/investigate-alert.d.ts +10 -0
- package/build/tools/investigate-alert.js +122 -0
- package/build/tools/investigate-alert.js.map +1 -0
- package/build/tools/list-sessions.d.ts +49 -0
- package/build/tools/list-sessions.js +79 -0
- package/build/tools/list-sessions.js.map +1 -0
- package/build/types/errors.d.ts +61 -0
- package/build/types/errors.js +76 -0
- package/build/types/errors.js.map +1 -0
- package/build/types/hawkeye.d.ts +238 -0
- package/build/types/hawkeye.js +8 -0
- package/build/types/hawkeye.js.map +1 -0
- package/build/types/mcp.d.ts +125 -0
- package/build/types/mcp.js +6 -0
- package/build/types/mcp.js.map +1 -0
- package/build/utils/errors.d.ts +20 -0
- package/build/utils/errors.js +125 -0
- package/build/utils/errors.js.map +1 -0
- package/build/utils/http-client.d.ts +51 -0
- package/build/utils/http-client.js +133 -0
- package/build/utils/http-client.js.map +1 -0
- package/build/utils/logger.d.ts +35 -0
- package/build/utils/logger.js +77 -0
- package/build/utils/logger.js.map +1 -0
- package/build/utils/validation.d.ts +134 -0
- package/build/utils/validation.js +68 -0
- package/build/utils/validation.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for Hawkeye MCP Server
|
|
3
|
+
* Loads and validates environment variables and provides application constants
|
|
4
|
+
*/
|
|
5
|
+
export interface HawkeyeConfig {
|
|
6
|
+
email: string;
|
|
7
|
+
password: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
defaultProjectUuid?: string;
|
|
10
|
+
defaultOrganizationUuid: string;
|
|
11
|
+
defaultTimeframe: string;
|
|
12
|
+
enableStreaming: boolean;
|
|
13
|
+
maxPollAttempts: number;
|
|
14
|
+
pollIntervalMs: number;
|
|
15
|
+
tokenRefreshBufferMs: number;
|
|
16
|
+
projectCacheTtlMs: number;
|
|
17
|
+
serverName: string;
|
|
18
|
+
serverVersion: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load and validate configuration from environment variables
|
|
22
|
+
*/
|
|
23
|
+
export declare function loadConfig(): HawkeyeConfig;
|
|
24
|
+
/**
|
|
25
|
+
* Get the global configuration instance
|
|
26
|
+
*/
|
|
27
|
+
export declare function getConfig(): HawkeyeConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Constants used throughout the application
|
|
30
|
+
*/
|
|
31
|
+
export declare const CONSTANTS: {
|
|
32
|
+
readonly ENDPOINTS: {
|
|
33
|
+
readonly LOGIN: "/v1/user/login";
|
|
34
|
+
readonly PROJECTS: "/v1/project";
|
|
35
|
+
readonly SESSION_LIST: "/v1/inference/session/list";
|
|
36
|
+
readonly SESSION_CREATE: "/v1/inference/new_session";
|
|
37
|
+
readonly SESSION_PROMPT: "/v1/inference/session";
|
|
38
|
+
readonly SESSION_INSPECT: "/v1/inference/session/inspect";
|
|
39
|
+
readonly SESSION_REPORT: "/v1/inference/session_report";
|
|
40
|
+
readonly SESSION_SUMMARY: "/v1/inference/session/summary";
|
|
41
|
+
readonly INCIDENT_REPORT: "/v1/inference/incident_report";
|
|
42
|
+
};
|
|
43
|
+
readonly HEADERS: {
|
|
44
|
+
readonly CONTENT_TYPE: "application/json";
|
|
45
|
+
readonly ACCEPT: "application/json";
|
|
46
|
+
readonly CLIENT_IDENTIFIER: "mcp-server";
|
|
47
|
+
};
|
|
48
|
+
readonly TIMEOUTS: {
|
|
49
|
+
readonly DEFAULT_REQUEST: 30000;
|
|
50
|
+
readonly LONG_REQUEST: 60000;
|
|
51
|
+
readonly AUTH_REQUEST: 10000;
|
|
52
|
+
};
|
|
53
|
+
readonly RETRY: {
|
|
54
|
+
readonly MAX_ATTEMPTS: 3;
|
|
55
|
+
readonly BACKOFF_MS: 1000;
|
|
56
|
+
readonly BACKOFF_MULTIPLIER: 2;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for Hawkeye MCP Server
|
|
3
|
+
* Loads and validates environment variables and provides application constants
|
|
4
|
+
*/
|
|
5
|
+
import dotenv from 'dotenv';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
// Get directory of current module
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
// Load environment variables from project root
|
|
12
|
+
const envPath = join(__dirname, '../../.env');
|
|
13
|
+
const result = dotenv.config({ path: envPath });
|
|
14
|
+
// Debug: Log if .env was loaded successfully
|
|
15
|
+
if (result.error) {
|
|
16
|
+
console.error('[CONFIG] Failed to load .env file:', result.error.message);
|
|
17
|
+
console.error('[CONFIG] Tried path:', envPath);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.error('[CONFIG] Successfully loaded .env from:', envPath);
|
|
21
|
+
console.error('[CONFIG] HAWKEYE_EMAIL:', process.env.HAWKEYE_EMAIL ? '✓ Set' : '✗ Not set');
|
|
22
|
+
console.error('[CONFIG] HAWKEYE_PASSWORD:', process.env.HAWKEYE_PASSWORD ? '✓ Set' : '✗ Not set');
|
|
23
|
+
console.error('[CONFIG] HAWKEYE_BASE_URL:', process.env.HAWKEYE_BASE_URL || 'Using default');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load and validate configuration from environment variables
|
|
27
|
+
*/
|
|
28
|
+
export function loadConfig() {
|
|
29
|
+
const email = process.env.HAWKEYE_EMAIL;
|
|
30
|
+
const password = process.env.HAWKEYE_PASSWORD;
|
|
31
|
+
if (!email || !password) {
|
|
32
|
+
throw new Error('Missing required environment variables: HAWKEYE_EMAIL and HAWKEYE_PASSWORD must be set');
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
// Required
|
|
36
|
+
email,
|
|
37
|
+
password,
|
|
38
|
+
baseUrl: process.env.HAWKEYE_BASE_URL || 'https://sandbox.app.neubird.ai/api',
|
|
39
|
+
// Optional with defaults
|
|
40
|
+
defaultProjectUuid: process.env.HAWKEYE_DEFAULT_PROJECT_UUID,
|
|
41
|
+
defaultOrganizationUuid: process.env.HAWKEYE_DEFAULT_ORGANIZATION_UUID || 'ORGANIZATION_NAME_ROOT',
|
|
42
|
+
defaultTimeframe: process.env.HAWKEYE_DEFAULT_TIMEFRAME || 'last 1 hour',
|
|
43
|
+
enableStreaming: process.env.HAWKEYE_ENABLE_STREAMING !== 'false', // Default true
|
|
44
|
+
// Performance
|
|
45
|
+
maxPollAttempts: parseInt(process.env.HAWKEYE_MAX_POLL_ATTEMPTS || '30', 10),
|
|
46
|
+
pollIntervalMs: parseInt(process.env.HAWKEYE_POLL_INTERVAL_MS || '2000', 10),
|
|
47
|
+
tokenRefreshBufferMs: 5 * 60 * 1000, // 5 minutes
|
|
48
|
+
projectCacheTtlMs: 5 * 60 * 1000, // 5 minutes
|
|
49
|
+
// Server metadata
|
|
50
|
+
serverName: 'hawkeye-mcp-server',
|
|
51
|
+
serverVersion: '2.0.0',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Global configuration instance
|
|
55
|
+
let config = null;
|
|
56
|
+
/**
|
|
57
|
+
* Get the global configuration instance
|
|
58
|
+
*/
|
|
59
|
+
export function getConfig() {
|
|
60
|
+
if (!config) {
|
|
61
|
+
config = loadConfig();
|
|
62
|
+
}
|
|
63
|
+
return config;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Constants used throughout the application
|
|
67
|
+
*/
|
|
68
|
+
export const CONSTANTS = {
|
|
69
|
+
// API endpoints
|
|
70
|
+
ENDPOINTS: {
|
|
71
|
+
LOGIN: '/v1/user/login',
|
|
72
|
+
PROJECTS: '/v1/project',
|
|
73
|
+
SESSION_LIST: '/v1/inference/session/list',
|
|
74
|
+
SESSION_CREATE: '/v1/inference/new_session',
|
|
75
|
+
SESSION_PROMPT: '/v1/inference/session',
|
|
76
|
+
SESSION_INSPECT: '/v1/inference/session/inspect',
|
|
77
|
+
SESSION_REPORT: '/v1/inference/session_report',
|
|
78
|
+
SESSION_SUMMARY: '/v1/inference/session/summary',
|
|
79
|
+
INCIDENT_REPORT: '/v1/inference/incident_report',
|
|
80
|
+
},
|
|
81
|
+
// Headers
|
|
82
|
+
HEADERS: {
|
|
83
|
+
CONTENT_TYPE: 'application/json',
|
|
84
|
+
ACCEPT: 'application/json',
|
|
85
|
+
CLIENT_IDENTIFIER: 'mcp-server',
|
|
86
|
+
},
|
|
87
|
+
// Timeouts
|
|
88
|
+
TIMEOUTS: {
|
|
89
|
+
DEFAULT_REQUEST: 30000, // 30 seconds
|
|
90
|
+
LONG_REQUEST: 60000, // 1 minute
|
|
91
|
+
AUTH_REQUEST: 10000, // 10 seconds
|
|
92
|
+
},
|
|
93
|
+
// Retry configuration
|
|
94
|
+
RETRY: {
|
|
95
|
+
MAX_ATTEMPTS: 3,
|
|
96
|
+
BACKOFF_MS: 1000,
|
|
97
|
+
BACKOFF_MULTIPLIER: 2,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hawkeye MCP Server v2.0
|
|
4
|
+
* A Model Context Protocol server for AI-powered incident investigation
|
|
5
|
+
*/
|
|
6
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
// Configuration and utilities
|
|
10
|
+
import { getConfig } from './config/config.js';
|
|
11
|
+
import { logger } from './utils/logger.js';
|
|
12
|
+
import { formatErrorForMCP } from './utils/errors.js';
|
|
13
|
+
import { HttpClient } from './utils/http-client.js';
|
|
14
|
+
// Services
|
|
15
|
+
import { AuthenticationService } from './services/auth.service.js';
|
|
16
|
+
import { ProjectService } from './services/project.service.js';
|
|
17
|
+
import { SessionService } from './services/session.service.js';
|
|
18
|
+
// Tools
|
|
19
|
+
import { getToolDefinitions } from './tools/index.js';
|
|
20
|
+
/**
|
|
21
|
+
* Initialize services
|
|
22
|
+
*/
|
|
23
|
+
function initializeServices() {
|
|
24
|
+
const config = getConfig();
|
|
25
|
+
const httpClient = new HttpClient(config.baseUrl);
|
|
26
|
+
const authService = new AuthenticationService(httpClient);
|
|
27
|
+
const projectService = new ProjectService(httpClient, authService);
|
|
28
|
+
const sessionService = new SessionService(httpClient, authService);
|
|
29
|
+
return {
|
|
30
|
+
authService,
|
|
31
|
+
projectService,
|
|
32
|
+
sessionService,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Main server setup
|
|
37
|
+
*/
|
|
38
|
+
async function main() {
|
|
39
|
+
try {
|
|
40
|
+
const config = getConfig();
|
|
41
|
+
const services = initializeServices();
|
|
42
|
+
// Create MCP server
|
|
43
|
+
const server = new Server({
|
|
44
|
+
name: config.serverName,
|
|
45
|
+
version: config.serverVersion,
|
|
46
|
+
}, {
|
|
47
|
+
capabilities: {
|
|
48
|
+
tools: {},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
// Get all tool definitions
|
|
52
|
+
const toolDefinitions = getToolDefinitions();
|
|
53
|
+
const toolHandlers = new Map(toolDefinitions.map((def) => [def.tool.name, def.handler]));
|
|
54
|
+
/**
|
|
55
|
+
* Handler for listing available tools
|
|
56
|
+
*/
|
|
57
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
58
|
+
const tools = toolDefinitions.map((def) => def.tool);
|
|
59
|
+
return { tools };
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Handler for tool execution
|
|
63
|
+
*/
|
|
64
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
65
|
+
const { name: toolName, arguments: toolArgs } = request.params;
|
|
66
|
+
try {
|
|
67
|
+
// Get the tool handler
|
|
68
|
+
const handler = toolHandlers.get(toolName);
|
|
69
|
+
if (!handler) {
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
error: {
|
|
76
|
+
type: 'validation',
|
|
77
|
+
message: `Unknown tool: ${toolName}`,
|
|
78
|
+
},
|
|
79
|
+
}, null, 2),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Execute the tool
|
|
85
|
+
const toolServices = {
|
|
86
|
+
projectService: services.projectService,
|
|
87
|
+
sessionService: services.sessionService,
|
|
88
|
+
};
|
|
89
|
+
const result = await handler(toolServices, toolArgs);
|
|
90
|
+
// Return the result
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: JSON.stringify(result, null, 2),
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
logger.error(`Error executing tool ${toolName}`, error);
|
|
102
|
+
return {
|
|
103
|
+
content: [
|
|
104
|
+
{
|
|
105
|
+
type: 'text',
|
|
106
|
+
text: JSON.stringify(formatErrorForMCP(error), null, 2),
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Connect to transport
|
|
113
|
+
const transport = new StdioServerTransport();
|
|
114
|
+
await server.connect(transport);
|
|
115
|
+
logger.info(`${config.serverName} v${config.serverVersion} started successfully`);
|
|
116
|
+
logger.info(`${toolDefinitions.length} tools registered`);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
logger.error('Fatal error during server startup', error);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Cleanup on shutdown
|
|
125
|
+
*/
|
|
126
|
+
async function cleanup() {
|
|
127
|
+
logger.info('Shutting down Hawkeye MCP server...');
|
|
128
|
+
process.exit(0);
|
|
129
|
+
}
|
|
130
|
+
// Signal handlers
|
|
131
|
+
process.on('SIGINT', cleanup);
|
|
132
|
+
process.on('SIGTERM', cleanup);
|
|
133
|
+
// Start the server
|
|
134
|
+
main().catch((error) => {
|
|
135
|
+
logger.error('Fatal error in main execution', error);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication service for Hawkeye API
|
|
3
|
+
* Handles login, token caching, and automatic token refresh
|
|
4
|
+
*/
|
|
5
|
+
import { HttpClient } from '../utils/http-client.js';
|
|
6
|
+
/**
|
|
7
|
+
* Authentication service
|
|
8
|
+
*/
|
|
9
|
+
export declare class AuthenticationService {
|
|
10
|
+
private httpClient;
|
|
11
|
+
private tokenCache;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(httpClient: HttpClient);
|
|
14
|
+
/**
|
|
15
|
+
* Get a valid access token, refreshing if necessary
|
|
16
|
+
*/
|
|
17
|
+
getAccessToken(): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if the cached token is still valid
|
|
20
|
+
*/
|
|
21
|
+
private isTokenValid;
|
|
22
|
+
/**
|
|
23
|
+
* Login and cache the access token
|
|
24
|
+
*/
|
|
25
|
+
private login;
|
|
26
|
+
/**
|
|
27
|
+
* Clear the cached token (useful for testing or forced re-authentication)
|
|
28
|
+
*/
|
|
29
|
+
clearTokenCache(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Check if user is authenticated (has valid cached token)
|
|
32
|
+
*/
|
|
33
|
+
isAuthenticated(): boolean;
|
|
34
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication service for Hawkeye API
|
|
3
|
+
* Handles login, token caching, and automatic token refresh
|
|
4
|
+
*/
|
|
5
|
+
import { AuthenticationError } from '../types/errors.js';
|
|
6
|
+
import { getConfig, CONSTANTS } from '../config/config.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
/**
|
|
9
|
+
* Authentication service
|
|
10
|
+
*/
|
|
11
|
+
export class AuthenticationService {
|
|
12
|
+
httpClient;
|
|
13
|
+
tokenCache = null;
|
|
14
|
+
config = getConfig();
|
|
15
|
+
constructor(httpClient) {
|
|
16
|
+
this.httpClient = httpClient;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get a valid access token, refreshing if necessary
|
|
20
|
+
*/
|
|
21
|
+
async getAccessToken() {
|
|
22
|
+
// Check if we have a valid cached token
|
|
23
|
+
if (this.tokenCache && this.isTokenValid()) {
|
|
24
|
+
logger.debug('Using cached authentication token');
|
|
25
|
+
return this.tokenCache.token;
|
|
26
|
+
}
|
|
27
|
+
// Token expired or doesn't exist, login again
|
|
28
|
+
logger.info('Authenticating with Hawkeye API...');
|
|
29
|
+
return this.login();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if the cached token is still valid
|
|
33
|
+
*/
|
|
34
|
+
isTokenValid() {
|
|
35
|
+
if (!this.tokenCache) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Check if token is expired (with buffer)
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
return now < this.tokenCache.expiresAt;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Login and cache the access token
|
|
44
|
+
*/
|
|
45
|
+
async login() {
|
|
46
|
+
try {
|
|
47
|
+
const loginRequest = {
|
|
48
|
+
email: this.config.email,
|
|
49
|
+
password: this.config.password,
|
|
50
|
+
};
|
|
51
|
+
const response = await this.httpClient.post(CONSTANTS.ENDPOINTS.LOGIN, loginRequest, {
|
|
52
|
+
timeout: CONSTANTS.TIMEOUTS.AUTH_REQUEST,
|
|
53
|
+
});
|
|
54
|
+
const token = response.data.access_token;
|
|
55
|
+
if (!token) {
|
|
56
|
+
throw new AuthenticationError('No access_token found in authentication response', { response: response.data }, [
|
|
57
|
+
'Check if the Hawkeye API is returning the expected response format',
|
|
58
|
+
'Verify API version compatibility',
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
// Cache the token with 55-minute expiry (5-minute buffer)
|
|
62
|
+
const expiresAt = Date.now() + (55 * 60 * 1000);
|
|
63
|
+
this.tokenCache = { token, expiresAt };
|
|
64
|
+
// Set token in HTTP client for future requests
|
|
65
|
+
this.httpClient.setAuthToken(token);
|
|
66
|
+
logger.info('Successfully authenticated with Hawkeye API');
|
|
67
|
+
return token;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger.error('Authentication failed', error);
|
|
71
|
+
if (error instanceof AuthenticationError) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
throw new AuthenticationError('Failed to authenticate with Hawkeye API', { originalError: error instanceof Error ? error.message : String(error) }, [
|
|
75
|
+
'Verify HAWKEYE_EMAIL and HAWKEYE_PASSWORD environment variables are correct',
|
|
76
|
+
'Check if HAWKEYE_BASE_URL is pointing to the correct Hawkeye instance',
|
|
77
|
+
'Ensure network connectivity to the Hawkeye API',
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clear the cached token (useful for testing or forced re-authentication)
|
|
83
|
+
*/
|
|
84
|
+
clearTokenCache() {
|
|
85
|
+
this.tokenCache = null;
|
|
86
|
+
this.httpClient.clearAuthToken();
|
|
87
|
+
logger.debug('Token cache cleared');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if user is authenticated (has valid cached token)
|
|
91
|
+
*/
|
|
92
|
+
isAuthenticated() {
|
|
93
|
+
return this.isTokenValid();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=auth.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project management service for Hawkeye API
|
|
3
|
+
* Handles listing projects, getting project details, and managing default project
|
|
4
|
+
*/
|
|
5
|
+
import { HttpClient } from '../utils/http-client.js';
|
|
6
|
+
import { AuthenticationService } from './auth.service.js';
|
|
7
|
+
import { Project } from '../types/hawkeye.js';
|
|
8
|
+
/**
|
|
9
|
+
* Project management service
|
|
10
|
+
*/
|
|
11
|
+
export declare class ProjectService {
|
|
12
|
+
private httpClient;
|
|
13
|
+
private authService;
|
|
14
|
+
private config;
|
|
15
|
+
private projectCache;
|
|
16
|
+
private defaultProjectUuid;
|
|
17
|
+
constructor(httpClient: HttpClient, authService: AuthenticationService);
|
|
18
|
+
/**
|
|
19
|
+
* List all projects, using cache if available
|
|
20
|
+
*/
|
|
21
|
+
listProjects(includeInactive?: boolean): Promise<Project[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Get a specific project by UUID
|
|
24
|
+
*/
|
|
25
|
+
getProject(projectUuid: string): Promise<Project>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the default project (from config or first active project)
|
|
28
|
+
*/
|
|
29
|
+
getDefaultProject(): Promise<Project>;
|
|
30
|
+
/**
|
|
31
|
+
* Set the default project UUID (for current session)
|
|
32
|
+
*/
|
|
33
|
+
setDefaultProject(projectUuid: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get the current default project UUID (if set)
|
|
36
|
+
*/
|
|
37
|
+
getDefaultProjectUuid(): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Check if project cache is still valid
|
|
40
|
+
*/
|
|
41
|
+
private isCacheValid;
|
|
42
|
+
/**
|
|
43
|
+
* Filter projects by state
|
|
44
|
+
*/
|
|
45
|
+
private filterProjects;
|
|
46
|
+
/**
|
|
47
|
+
* Clear project cache (useful for testing or forced refresh)
|
|
48
|
+
*/
|
|
49
|
+
clearCache(): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project management service for Hawkeye API
|
|
3
|
+
* Handles listing projects, getting project details, and managing default project
|
|
4
|
+
*/
|
|
5
|
+
import { ApiError } from '../types/errors.js';
|
|
6
|
+
import { getConfig, CONSTANTS } from '../config/config.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
/**
|
|
9
|
+
* Project management service
|
|
10
|
+
*/
|
|
11
|
+
export class ProjectService {
|
|
12
|
+
httpClient;
|
|
13
|
+
authService;
|
|
14
|
+
config = getConfig();
|
|
15
|
+
projectCache = null;
|
|
16
|
+
defaultProjectUuid = null;
|
|
17
|
+
constructor(httpClient, authService) {
|
|
18
|
+
this.httpClient = httpClient;
|
|
19
|
+
this.authService = authService;
|
|
20
|
+
this.defaultProjectUuid = this.config.defaultProjectUuid || null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* List all projects, using cache if available
|
|
24
|
+
*/
|
|
25
|
+
async listProjects(includeInactive = false) {
|
|
26
|
+
// Check cache
|
|
27
|
+
if (this.projectCache && this.isCacheValid()) {
|
|
28
|
+
logger.debug('Using cached project list');
|
|
29
|
+
return this.filterProjects(this.projectCache.projects, includeInactive);
|
|
30
|
+
}
|
|
31
|
+
// Fetch from API
|
|
32
|
+
await this.authService.getAccessToken(); // Ensure authenticated
|
|
33
|
+
try {
|
|
34
|
+
logger.info('Fetching project list from Hawkeye API');
|
|
35
|
+
const response = await this.httpClient.get(CONSTANTS.ENDPOINTS.PROJECTS);
|
|
36
|
+
const projects = response.data.specs || [];
|
|
37
|
+
// Cache the results
|
|
38
|
+
this.projectCache = {
|
|
39
|
+
projects,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
};
|
|
42
|
+
logger.info(`Found ${projects.length} projects`);
|
|
43
|
+
return this.filterProjects(projects, includeInactive);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.error('Failed to list projects', error);
|
|
47
|
+
// Re-throw the error as-is to preserve Axios error details
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get a specific project by UUID
|
|
53
|
+
*/
|
|
54
|
+
async getProject(projectUuid) {
|
|
55
|
+
const projects = await this.listProjects(true); // Include inactive
|
|
56
|
+
const project = projects.find(p => p.uuid === projectUuid);
|
|
57
|
+
if (!project) {
|
|
58
|
+
throw new ApiError(`Project not found: ${projectUuid}`, 404, { projectUuid }, [
|
|
59
|
+
'Verify the project UUID is correct',
|
|
60
|
+
'Check if you have access to this project',
|
|
61
|
+
'Use list_projects tool to see available projects',
|
|
62
|
+
]);
|
|
63
|
+
}
|
|
64
|
+
return project;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get the default project (from config or first active project)
|
|
68
|
+
*/
|
|
69
|
+
async getDefaultProject() {
|
|
70
|
+
// Use configured default if available
|
|
71
|
+
if (this.defaultProjectUuid) {
|
|
72
|
+
try {
|
|
73
|
+
return await this.getProject(this.defaultProjectUuid);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
logger.warn(`Configured default project ${this.defaultProjectUuid} not found, falling back to first project`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Fall back to first active project
|
|
80
|
+
const projects = await this.listProjects(false);
|
|
81
|
+
if (projects.length === 0) {
|
|
82
|
+
throw new ApiError('No active projects found', 404, undefined, [
|
|
83
|
+
'Create a project in Hawkeye first',
|
|
84
|
+
'Check if your projects are in active state',
|
|
85
|
+
'Verify you have access to at least one project',
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
logger.info(`Using first active project as default: ${projects[0].name}`);
|
|
89
|
+
return projects[0];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Set the default project UUID (for current session)
|
|
93
|
+
*/
|
|
94
|
+
setDefaultProject(projectUuid) {
|
|
95
|
+
this.defaultProjectUuid = projectUuid;
|
|
96
|
+
logger.info(`Default project set to: ${projectUuid}`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get the current default project UUID (if set)
|
|
100
|
+
*/
|
|
101
|
+
getDefaultProjectUuid() {
|
|
102
|
+
return this.defaultProjectUuid;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Check if project cache is still valid
|
|
106
|
+
*/
|
|
107
|
+
isCacheValid() {
|
|
108
|
+
if (!this.projectCache) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const age = now - this.projectCache.timestamp;
|
|
113
|
+
return age < this.config.projectCacheTtlMs;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Filter projects by state
|
|
117
|
+
*/
|
|
118
|
+
filterProjects(projects, includeInactive) {
|
|
119
|
+
if (includeInactive) {
|
|
120
|
+
return projects;
|
|
121
|
+
}
|
|
122
|
+
// Only return active projects
|
|
123
|
+
return projects.filter(p => p.state === 'ACTIVE' ||
|
|
124
|
+
p.state === 'active' ||
|
|
125
|
+
!p.state // If state is not defined, include it
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Clear project cache (useful for testing or forced refresh)
|
|
130
|
+
*/
|
|
131
|
+
clearCache() {
|
|
132
|
+
this.projectCache = null;
|
|
133
|
+
logger.debug('Project cache cleared');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=project.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.service.js","sourceRoot":"","sources":["../../src/services/project.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAO5C;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,UAAU,CAAa;IACvB,WAAW,CAAwB;IACnC,MAAM,GAAG,SAAS,EAAE,CAAC;IACrB,YAAY,GAAwB,IAAI,CAAC;IACzC,kBAAkB,GAAkB,IAAI,CAAC;IAEjD,YAAY,UAAsB,EAAE,WAAkC;QACpE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,IAAI,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,kBAA2B,KAAK;QACjD,cAAc;QACd,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC1E,CAAC;QAED,iBAAiB;QACjB,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC,CAAC,uBAAuB;QAEhE,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YAEtD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CACxC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAC7B,CAAC;YAEF,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAE3C,oBAAoB;YACpB,IAAI,CAAC,YAAY,GAAG;gBAClB,QAAQ;gBACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;YACjD,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAExD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC/C,2DAA2D;YAC3D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB;QACnE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,sBAAsB,WAAW,EAAE,EACnC,GAAG,EACH,EAAE,WAAW,EAAE,EACf;gBACE,oCAAoC;gBACpC,0CAA0C;gBAC1C,kDAAkD;aACnD,CACF,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB;QACrB,sCAAsC;QACtC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACxD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,kBAAkB,2CAA2C,CAAC,CAAC;YAChH,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,QAAQ,CAChB,0BAA0B,EAC1B,GAAG,EACH,SAAS,EACT;gBACE,mCAAmC;gBACnC,4CAA4C;gBAC5C,gDAAgD;aACjD,CACF,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,0CAA0C,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,WAAmB;QACnC,IAAI,CAAC,kBAAkB,GAAG,WAAW,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,2BAA2B,WAAW,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;QAC9C,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;IAC7C,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,QAAmB,EAAE,eAAwB;QAClE,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,8BAA8B;QAC9B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACzB,CAAC,CAAC,KAAK,KAAK,QAAQ;YACpB,CAAC,CAAC,KAAK,KAAK,QAAQ;YACpB,CAAC,CAAC,CAAC,KAAK,CAAC,sCAAsC;SAChD,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACxC,CAAC;CACF"}
|