mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
- Replaced all instances of TelemetryService with Service in components, pages, and utilities. - Updated related imports and state management to reflect the new Service model. - Removed the TelemetryServices view and associated routes, as it is no longer needed. - Adjusted breadcrumb and route mappings to remove references to Telemetry Services. - Ensured that all relevant functionality, such as logs and metrics, now utilize the Service model.
395 lines
10 KiB
TypeScript
395 lines
10 KiB
TypeScript
import { ONEUPTIME_URL } from "../Config";
|
|
import AIAgentAPIRequest from "./AIAgentAPIRequest";
|
|
import URL from "Common/Types/API/URL";
|
|
import API from "Common/Utils/API";
|
|
import HTTPResponse from "Common/Types/API/HTTPResponse";
|
|
import { JSONObject } from "Common/Types/JSON";
|
|
import LlmType from "Common/Types/LLM/LlmType";
|
|
import AIAgentTaskStatus from "Common/Types/AI/AIAgentTaskStatus";
|
|
import logger from "Common/Server/Utils/Logger";
|
|
|
|
// API Response types
|
|
interface LLMConfigResponse {
|
|
llmType: LlmType;
|
|
apiKey?: string;
|
|
baseUrl?: string;
|
|
modelName?: string;
|
|
message?: string;
|
|
}
|
|
|
|
interface ExceptionResponse {
|
|
id: string;
|
|
message: string;
|
|
stackTrace: string;
|
|
exceptionType: string;
|
|
fingerprint: string;
|
|
}
|
|
|
|
interface ServiceResponse {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
}
|
|
|
|
interface ExceptionDetailsResponse {
|
|
exception: ExceptionResponse;
|
|
service: ServiceResponse | null;
|
|
message?: string;
|
|
}
|
|
|
|
interface CodeRepositoryResponse {
|
|
id: string;
|
|
name: string;
|
|
repositoryHostedAt: string;
|
|
organizationName: string;
|
|
repositoryName: string;
|
|
mainBranchName: string;
|
|
servicePathInRepository: string | null;
|
|
gitHubAppInstallationId: string | null;
|
|
}
|
|
|
|
interface CodeRepositoriesResponse {
|
|
repositories: Array<CodeRepositoryResponse>;
|
|
message?: string;
|
|
}
|
|
|
|
interface RepositoryTokenResponse {
|
|
token: string;
|
|
expiresAt: string;
|
|
repositoryUrl: string;
|
|
organizationName: string;
|
|
repositoryName: string;
|
|
message?: string;
|
|
}
|
|
|
|
interface RecordPullRequestResponse {
|
|
success: boolean;
|
|
pullRequestId: string;
|
|
message?: string;
|
|
}
|
|
|
|
interface UpdateTaskStatusResponse {
|
|
success?: boolean;
|
|
message?: string;
|
|
}
|
|
|
|
// Exported types
|
|
export interface LLMConfig {
|
|
llmType: LlmType;
|
|
apiKey?: string;
|
|
baseUrl?: string;
|
|
modelName?: string;
|
|
}
|
|
|
|
export interface ExceptionDetails {
|
|
exception: {
|
|
id: string;
|
|
message: string;
|
|
stackTrace: string;
|
|
exceptionType: string;
|
|
fingerprint: string;
|
|
};
|
|
service: {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
} | null;
|
|
}
|
|
|
|
export interface CodeRepositoryInfo {
|
|
id: string;
|
|
name: string;
|
|
repositoryHostedAt: string;
|
|
organizationName: string;
|
|
repositoryName: string;
|
|
mainBranchName: string;
|
|
servicePathInRepository: string | null;
|
|
gitHubAppInstallationId: string | null;
|
|
}
|
|
|
|
export interface RepositoryToken {
|
|
token: string;
|
|
expiresAt: Date;
|
|
repositoryUrl: string;
|
|
organizationName: string;
|
|
repositoryName: string;
|
|
}
|
|
|
|
export interface RecordPullRequestOptions {
|
|
taskId: string;
|
|
codeRepositoryId: string;
|
|
pullRequestUrl: string;
|
|
pullRequestNumber?: number;
|
|
pullRequestId?: number;
|
|
title: string;
|
|
description?: string;
|
|
headRefName?: string;
|
|
baseRefName?: string;
|
|
}
|
|
|
|
export interface RecordPullRequestResult {
|
|
success: boolean;
|
|
pullRequestId: string;
|
|
}
|
|
|
|
export default class BackendAPI {
|
|
private baseUrl: URL;
|
|
|
|
public constructor() {
|
|
this.baseUrl = URL.fromString(ONEUPTIME_URL.toString());
|
|
}
|
|
|
|
// Get LLM configuration for a project
|
|
public async getLLMConfig(projectId: string): Promise<LLMConfig> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-data/get-llm-config",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
projectId: projectId,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: LLMConfigResponse =
|
|
response.data as unknown as LLMConfigResponse;
|
|
const errorMessage: string = data?.message || "Failed to get LLM config";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: LLMConfigResponse =
|
|
response.data as unknown as LLMConfigResponse;
|
|
|
|
logger.debug(`Got LLM config for project ${projectId}: ${data.llmType}`);
|
|
|
|
const llmConfig: LLMConfig = {
|
|
llmType: data.llmType,
|
|
};
|
|
|
|
if (data.apiKey) {
|
|
llmConfig.apiKey = data.apiKey;
|
|
}
|
|
|
|
if (data.baseUrl) {
|
|
llmConfig.baseUrl = data.baseUrl;
|
|
}
|
|
|
|
if (data.modelName) {
|
|
llmConfig.modelName = data.modelName;
|
|
}
|
|
|
|
return llmConfig;
|
|
}
|
|
|
|
// Get exception details with telemetry service info
|
|
public async getExceptionDetails(
|
|
exceptionId: string,
|
|
): Promise<ExceptionDetails> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-data/get-exception-details",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
exceptionId: exceptionId,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: ExceptionDetailsResponse =
|
|
response.data as unknown as ExceptionDetailsResponse;
|
|
const errorMessage: string =
|
|
data?.message || "Failed to get exception details";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: ExceptionDetailsResponse =
|
|
response.data as unknown as ExceptionDetailsResponse;
|
|
|
|
logger.debug(
|
|
`Got exception details for ${exceptionId}: ${data.exception.message.substring(0, 100)}`,
|
|
);
|
|
|
|
return {
|
|
exception: {
|
|
id: data.exception.id,
|
|
message: data.exception.message,
|
|
stackTrace: data.exception.stackTrace,
|
|
exceptionType: data.exception.exceptionType,
|
|
fingerprint: data.exception.fingerprint,
|
|
},
|
|
service: data.service
|
|
? {
|
|
id: data.service.id,
|
|
name: data.service.name,
|
|
description: data.service.description,
|
|
}
|
|
: null,
|
|
};
|
|
}
|
|
|
|
// Get code repositories linked to a service
|
|
public async getCodeRepositories(
|
|
serviceId: string,
|
|
): Promise<Array<CodeRepositoryInfo>> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-data/get-code-repositories",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
serviceId: serviceId,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: CodeRepositoriesResponse =
|
|
response.data as unknown as CodeRepositoriesResponse;
|
|
const errorMessage: string =
|
|
data?.message || "Failed to get code repositories";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: CodeRepositoriesResponse =
|
|
response.data as unknown as CodeRepositoriesResponse;
|
|
|
|
logger.debug(
|
|
`Got ${data.repositories.length} code repositories for service ${serviceId}`,
|
|
);
|
|
|
|
return data.repositories.map((repo: CodeRepositoryResponse) => {
|
|
return {
|
|
id: repo.id,
|
|
name: repo.name,
|
|
repositoryHostedAt: repo.repositoryHostedAt,
|
|
organizationName: repo.organizationName,
|
|
repositoryName: repo.repositoryName,
|
|
mainBranchName: repo.mainBranchName,
|
|
servicePathInRepository: repo.servicePathInRepository,
|
|
gitHubAppInstallationId: repo.gitHubAppInstallationId,
|
|
};
|
|
});
|
|
}
|
|
|
|
// Get access token for a code repository
|
|
public async getRepositoryToken(
|
|
codeRepositoryId: string,
|
|
): Promise<RepositoryToken> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-data/get-repository-token",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
codeRepositoryId: codeRepositoryId,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: RepositoryTokenResponse =
|
|
response.data as unknown as RepositoryTokenResponse;
|
|
const errorMessage: string =
|
|
data?.message || "Failed to get repository token";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: RepositoryTokenResponse =
|
|
response.data as unknown as RepositoryTokenResponse;
|
|
|
|
logger.debug(
|
|
`Got access token for repository ${data.organizationName}/${data.repositoryName}`,
|
|
);
|
|
|
|
return {
|
|
token: data.token,
|
|
expiresAt: new Date(data.expiresAt),
|
|
repositoryUrl: data.repositoryUrl,
|
|
organizationName: data.organizationName,
|
|
repositoryName: data.repositoryName,
|
|
};
|
|
}
|
|
|
|
// Record a pull request created by the AI Agent
|
|
public async recordPullRequest(
|
|
options: RecordPullRequestOptions,
|
|
): Promise<RecordPullRequestResult> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-data/record-pull-request",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
taskId: options.taskId,
|
|
codeRepositoryId: options.codeRepositoryId,
|
|
pullRequestUrl: options.pullRequestUrl,
|
|
pullRequestNumber: options.pullRequestNumber,
|
|
pullRequestId: options.pullRequestId,
|
|
title: options.title,
|
|
description: options.description,
|
|
headRefName: options.headRefName,
|
|
baseRefName: options.baseRefName,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: RecordPullRequestResponse =
|
|
response.data as unknown as RecordPullRequestResponse;
|
|
const errorMessage: string =
|
|
data?.message || "Failed to record pull request";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data: RecordPullRequestResponse =
|
|
response.data as unknown as RecordPullRequestResponse;
|
|
|
|
logger.debug(`Recorded pull request: ${options.pullRequestUrl}`);
|
|
|
|
return {
|
|
success: data.success,
|
|
pullRequestId: data.pullRequestId,
|
|
};
|
|
}
|
|
|
|
// Update task status (wrapper around existing endpoint)
|
|
public async updateTaskStatus(
|
|
taskId: string,
|
|
status: AIAgentTaskStatus,
|
|
statusMessage?: string,
|
|
): Promise<void> {
|
|
const url: URL = URL.fromURL(this.baseUrl).addRoute(
|
|
"/api/ai-agent-task/update-task-status",
|
|
);
|
|
|
|
const response: HTTPResponse<JSONObject> = await API.post({
|
|
url,
|
|
data: {
|
|
...AIAgentAPIRequest.getDefaultRequestBody(),
|
|
taskId: taskId,
|
|
status: status,
|
|
statusMessage: statusMessage,
|
|
},
|
|
});
|
|
|
|
if (!response.isSuccess()) {
|
|
const data: UpdateTaskStatusResponse =
|
|
response.data as unknown as UpdateTaskStatusResponse;
|
|
const errorMessage: string =
|
|
data?.message || "Failed to update task status";
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
logger.debug(`Updated task ${taskId} status to ${status}`);
|
|
}
|
|
}
|