@oneuptime/common 9.2.27 → 9.3.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/Models/DatabaseModels/AIAgent.ts +589 -0
- package/Models/DatabaseModels/AIAgentOwnerTeam.ts +434 -0
- package/Models/DatabaseModels/AIAgentOwnerUser.ts +433 -0
- package/Models/DatabaseModels/AIAgentTask.ts +549 -0
- package/Models/DatabaseModels/AIAgentTaskLog.ts +417 -0
- package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +731 -0
- package/Models/DatabaseModels/AIAgentTaskTelemetryException.ts +388 -0
- package/Models/DatabaseModels/Index.ts +15 -0
- package/Models/DatabaseModels/Monitor.ts +33 -0
- package/Models/DatabaseModels/Project.ts +25 -0
- package/Models/DatabaseModels/TelemetryException.ts +1 -1
- package/Server/API/AIAgentAPI.ts +200 -0
- package/Server/API/AIAgentDataAPI.ts +692 -0
- package/Server/API/AIAgentTaskAPI.ts +286 -0
- package/Server/API/AIAgentTaskLogAPI.ts +165 -0
- package/Server/API/AIAgentTaskPullRequestAPI.ts +14 -0
- package/Server/API/GitHubAPI.ts +25 -7
- package/Server/API/TelemetryExceptionAPI.ts +169 -0
- package/Server/EnvironmentConfig.ts +3 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766590916627-MigrationName.ts +195 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766600860972-MigrationName.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766606720183-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766688107858-MigrationName.ts +63 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766754182870-MigrationName.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766774689743-MigrationName.ts +157 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766777986427-MigrationName.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766918848434-AddAIAgentIsDefault.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766923324521-MigrationName.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1766958924188-AddGitHubAppInstallationIdToProject.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1767009661768-MigrationName.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +22 -0
- package/Server/Services/AIAgentOwnerTeamService.ts +10 -0
- package/Server/Services/AIAgentOwnerUserService.ts +10 -0
- package/Server/Services/AIAgentService.ts +564 -0
- package/Server/Services/AIAgentTaskLogService.ts +10 -0
- package/Server/Services/AIAgentTaskPullRequestService.ts +10 -0
- package/Server/Services/AIAgentTaskService.ts +178 -0
- package/Server/Services/AIAgentTaskTelemetryExceptionService.ts +39 -0
- package/Server/Services/Index.ts +10 -0
- package/Server/Services/TelemetryExceptionService.ts +162 -0
- package/Server/Utils/Monitor/MonitorResource.ts +228 -0
- package/Server/Utils/PushNotificationUtil.ts +29 -0
- package/Server/Utils/WhatsAppTemplateUtil.ts +6 -0
- package/Tests/UI/Components/Badge.test.tsx +5 -5
- package/Tests/UI/Components/Card.test.tsx +4 -8
- package/Tests/UI/Components/HiddenText.test.tsx +2 -5
- package/Tests/UI/Components/SideMenuItem.test.tsx +4 -2
- package/Types/AI/AIAgentTaskMetadata.ts +25 -0
- package/Types/AI/AIAgentTaskStatus.ts +65 -0
- package/Types/AI/AIAgentTaskType.ts +40 -0
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +2 -1
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/Permission.ts +176 -0
- package/Types/WhatsApp/WhatsAppTemplates.ts +9 -0
- package/UI/Components/AIAgent/AIAgent.tsx +69 -0
- package/UI/Components/Badge/Badge.tsx +9 -5
- package/UI/Components/Banner/Banner.tsx +1 -1
- package/UI/Components/Card/Card.tsx +14 -12
- package/UI/Components/CodeBlock/CodeBlock.tsx +47 -4
- package/UI/Components/Detail/Detail.tsx +239 -49
- package/UI/Components/Detail/FieldLabel.tsx +35 -11
- package/UI/Components/Detail/PlaceholderText.tsx +18 -1
- package/UI/Components/Footer/Footer.tsx +9 -7
- package/UI/Components/Header/Header.tsx +4 -3
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +13 -11
- package/UI/Components/Header/IconDropdown/IconDropdownItem.tsx +3 -3
- package/UI/Components/Header/IconDropdown/IconDropdownMenu.tsx +1 -1
- package/UI/Components/Header/ProjectPicker/CreateNewProjectButton.tsx +4 -4
- package/UI/Components/Header/ProjectPicker/ProjectPicker.tsx +6 -6
- package/UI/Components/Header/ProjectPicker/ProjectPickerFilterBox.tsx +3 -3
- package/UI/Components/Header/ProjectPicker/ProjectPickerMenu.tsx +1 -1
- package/UI/Components/Header/ProjectPicker/ProjectPickerMenuItem.tsx +4 -4
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +32 -32
- package/UI/Components/HeaderAlert/HeaderAlertGroup.tsx +1 -7
- package/UI/Components/HiddenText/HiddenText.tsx +98 -27
- package/UI/Components/Icon/Icon.tsx +12 -9
- package/UI/Components/InfoCard/InfoCard.tsx +7 -3
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ObjectID/ObjectIDView.tsx +73 -0
- package/UI/Components/Page/Page.tsx +3 -5
- package/UI/Components/SideMenu/SideMenu.tsx +175 -40
- package/UI/Components/SideMenu/SideMenuDivider.tsx +17 -0
- package/UI/Components/SideMenu/SideMenuItem.tsx +111 -158
- package/UI/Components/SideMenu/SideMenuSection.tsx +53 -3
- package/UI/Components/Table/Table.tsx +1 -1
- package/UI/Components/Types/FieldType.ts +2 -0
- package/UI/Config.ts +5 -0
- package/build/dist/Models/DatabaseModels/AIAgent.js +614 -0
- package/build/dist/Models/DatabaseModels/AIAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js +452 -0
- package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js +451 -0
- package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTask.js +580 -0
- package/build/dist/Models/DatabaseModels/AIAgentTask.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js +438 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +771 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js +404 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +14 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +34 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +26 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Server/API/AIAgentAPI.js +141 -0
- package/build/dist/Server/API/AIAgentAPI.js.map +1 -0
- package/build/dist/Server/API/AIAgentDataAPI.js +415 -0
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -0
- package/build/dist/Server/API/AIAgentTaskAPI.js +199 -0
- package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -0
- package/build/dist/Server/API/AIAgentTaskLogAPI.js +106 -0
- package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -0
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js +9 -0
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js.map +1 -0
- package/build/dist/Server/API/GitHubAPI.js +23 -8
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryExceptionAPI.js +120 -0
- package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +2 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766590916627-MigrationName.js +74 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766590916627-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766600860972-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766600860972-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766606720183-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766606720183-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766688107858-MigrationName.js +28 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766688107858-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766754182870-MigrationName.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766754182870-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766774689743-MigrationName.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766774689743-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766777986427-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766777986427-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766918848434-AddAIAgentIsDefault.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766918848434-AddAIAgentIsDefault.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766923324521-MigrationName.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766923324521-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766958924188-AddGitHubAppInstallationIdToProject.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1766958924188-AddGitHubAppInstallationIdToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1767009661768-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1767009661768-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/AIAgentOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentOwnerUserService.js +9 -0
- package/build/dist/Server/Services/AIAgentOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentService.js +471 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentTaskLogService.js +9 -0
- package/build/dist/Server/Services/AIAgentTaskLogService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js +9 -0
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentTaskService.js +158 -0
- package/build/dist/Server/Services/AIAgentTaskService.js.map +1 -0
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js +36 -0
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js.map +1 -0
- package/build/dist/Server/Services/Index.js +10 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +137 -0
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +168 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/PushNotificationUtil.js +21 -0
- package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +4 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Tests/UI/Components/Badge.test.js +5 -5
- package/build/dist/Tests/UI/Components/Badge.test.js.map +1 -1
- package/build/dist/Tests/UI/Components/Card.test.js +4 -8
- package/build/dist/Tests/UI/Components/Card.test.js.map +1 -1
- package/build/dist/Tests/UI/Components/HiddenText.test.js +2 -3
- package/build/dist/Tests/UI/Components/HiddenText.test.js.map +1 -1
- package/build/dist/Tests/UI/Components/SideMenuItem.test.js +3 -2
- package/build/dist/Tests/UI/Components/SideMenuItem.test.js.map +1 -1
- package/build/dist/Types/AI/AIAgentTaskMetadata.js +6 -0
- package/build/dist/Types/AI/AIAgentTaskMetadata.js.map +1 -0
- package/build/dist/Types/AI/AIAgentTaskStatus.js +51 -0
- package/build/dist/Types/AI/AIAgentTaskStatus.js.map +1 -0
- package/build/dist/Types/AI/AIAgentTaskType.js +29 -0
- package/build/dist/Types/AI/AIAgentTaskType.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +2 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +160 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +6 -0
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -1
- package/build/dist/UI/Components/AIAgent/AIAgent.js +32 -0
- package/build/dist/UI/Components/AIAgent/AIAgent.js.map +1 -0
- package/build/dist/UI/Components/Badge/Badge.js +9 -5
- package/build/dist/UI/Components/Badge/Badge.js.map +1 -1
- package/build/dist/UI/Components/Banner/Banner.js +1 -1
- package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +12 -12
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +22 -2
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +117 -37
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Detail/FieldLabel.js +12 -7
- package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
- package/build/dist/UI/Components/Detail/PlaceholderText.js +4 -1
- package/build/dist/UI/Components/Detail/PlaceholderText.js.map +1 -1
- package/build/dist/UI/Components/Footer/Footer.js +6 -6
- package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
- package/build/dist/UI/Components/Header/Header.js +4 -3
- package/build/dist/UI/Components/Header/Header.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +7 -7
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js +3 -3
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/CreateNewProjectButton.js +4 -4
- package/build/dist/UI/Components/Header/ProjectPicker/CreateNewProjectButton.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js +6 -6
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerFilterBox.js +2 -2
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerFilterBox.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerMenu.js +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerMenu.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerMenuItem.js +4 -4
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPickerMenuItem.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +31 -29
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlertGroup.js +1 -3
- package/build/dist/UI/Components/HeaderAlert/HeaderAlertGroup.js.map +1 -1
- package/build/dist/UI/Components/HiddenText/HiddenText.js +33 -14
- package/build/dist/UI/Components/HiddenText/HiddenText.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +3 -4
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +3 -3
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ObjectID/ObjectIDView.js +30 -0
- package/build/dist/UI/Components/ObjectID/ObjectIDView.js.map +1 -0
- package/build/dist/UI/Components/Page/Page.js +3 -3
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +82 -17
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuDivider.js +7 -0
- package/build/dist/UI/Components/SideMenu/SideMenuDivider.js.map +1 -0
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +68 -97
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +18 -3
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Types/FieldType.js +2 -0
- package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
- package/build/dist/UI/Config.js +2 -0
- package/build/dist/UI/Config.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import Model from "../../Models/DatabaseModels/AIAgentTask";
|
|
3
|
+
import AIAgent from "../../Models/DatabaseModels/AIAgent";
|
|
4
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
5
|
+
import { OnCreate } from "../Types/Database/Hooks";
|
|
6
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
7
|
+
import AIAgentService from "./AIAgentService";
|
|
8
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
9
|
+
import ObjectID from "../../Types/ObjectID";
|
|
10
|
+
import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
|
|
11
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
12
|
+
import logger from "../Utils/Logger";
|
|
13
|
+
import OneUptimeDate from "../../Types/Date";
|
|
14
|
+
|
|
15
|
+
export class Service extends DatabaseService<Model> {
|
|
16
|
+
public constructor() {
|
|
17
|
+
super(Model);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@CaptureSpan()
|
|
21
|
+
protected override async onBeforeCreate(
|
|
22
|
+
createBy: CreateBy<Model>,
|
|
23
|
+
): Promise<OnCreate<Model>> {
|
|
24
|
+
// If no aiAgentId is provided, assign one automatically
|
|
25
|
+
if (!createBy.data.aiAgentId) {
|
|
26
|
+
createBy.data.aiAgentId = await this.getDefaultAgentId(createBy);
|
|
27
|
+
} else {
|
|
28
|
+
// Validate the provided aiAgentId
|
|
29
|
+
await this.validateAgentBelongsToProject(createBy);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Generate task number
|
|
33
|
+
if (!createBy.data.projectId) {
|
|
34
|
+
throw new BadDataException(
|
|
35
|
+
"Project ID is required to create an AI Agent Task",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const projectId: ObjectID = createBy.data.projectId;
|
|
40
|
+
|
|
41
|
+
let mutex: SemaphoreMutex | null = null;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
mutex = await Semaphore.lock({
|
|
45
|
+
key: projectId.toString(),
|
|
46
|
+
namespace: "AIAgentTaskService.task-create",
|
|
47
|
+
lockTimeout: 15000,
|
|
48
|
+
acquireTimeout: 20000,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
logger.debug(
|
|
52
|
+
"Mutex acquired - AIAgentTaskService.task-create " +
|
|
53
|
+
projectId.toString() +
|
|
54
|
+
" at " +
|
|
55
|
+
OneUptimeDate.getCurrentDateAsFormattedString(),
|
|
56
|
+
);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
logger.debug(
|
|
59
|
+
"Mutex acquire failed - AIAgentTaskService.task-create " +
|
|
60
|
+
projectId.toString() +
|
|
61
|
+
" at " +
|
|
62
|
+
OneUptimeDate.getCurrentDateAsFormattedString(),
|
|
63
|
+
);
|
|
64
|
+
logger.error(err);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const taskNumberForThisTask: number =
|
|
69
|
+
(await this.getExistingTaskNumberForProject({
|
|
70
|
+
projectId: projectId,
|
|
71
|
+
})) + 1;
|
|
72
|
+
|
|
73
|
+
createBy.data.taskNumber = taskNumberForThisTask;
|
|
74
|
+
} finally {
|
|
75
|
+
if (mutex) {
|
|
76
|
+
await Semaphore.release(mutex);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { createBy, carryForward: null };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@CaptureSpan()
|
|
84
|
+
public async getExistingTaskNumberForProject(data: {
|
|
85
|
+
projectId: ObjectID;
|
|
86
|
+
}): Promise<number> {
|
|
87
|
+
// get last task number.
|
|
88
|
+
const lastTask: Model | null = await this.findOneBy({
|
|
89
|
+
query: {
|
|
90
|
+
projectId: data.projectId,
|
|
91
|
+
},
|
|
92
|
+
select: {
|
|
93
|
+
taskNumber: true,
|
|
94
|
+
},
|
|
95
|
+
sort: {
|
|
96
|
+
createdAt: SortOrder.Descending,
|
|
97
|
+
},
|
|
98
|
+
props: {
|
|
99
|
+
isRoot: true,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!lastTask) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return lastTask.taskNumber ? Number(lastTask.taskNumber) : 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@CaptureSpan()
|
|
111
|
+
private async getDefaultAgentId(
|
|
112
|
+
createBy: CreateBy<Model>,
|
|
113
|
+
): Promise<ObjectID> {
|
|
114
|
+
if (!createBy.data.projectId) {
|
|
115
|
+
throw new BadDataException(
|
|
116
|
+
"Project ID is required to assign an AI Agent",
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Try to get the default agent for the project (or global fallback)
|
|
121
|
+
const agent: AIAgent | null = await AIAgentService.getAIAgentForProject(
|
|
122
|
+
createBy.data.projectId,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (!agent || !agent.id) {
|
|
126
|
+
throw new BadDataException(
|
|
127
|
+
"No AI Agent available. Please configure an AI Agent for this project or ensure a global AI Agent is available.",
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return agent.id!;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@CaptureSpan()
|
|
135
|
+
private async validateAgentBelongsToProject(
|
|
136
|
+
createBy: CreateBy<Model>,
|
|
137
|
+
): Promise<void> {
|
|
138
|
+
if (!createBy.data.aiAgentId || !createBy.data.projectId) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const agent: AIAgent | null = await AIAgentService.findOneById({
|
|
143
|
+
id: createBy.data.aiAgentId,
|
|
144
|
+
select: {
|
|
145
|
+
_id: true,
|
|
146
|
+
projectId: true,
|
|
147
|
+
isGlobalAIAgent: true,
|
|
148
|
+
},
|
|
149
|
+
props: {
|
|
150
|
+
isRoot: true,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!agent) {
|
|
155
|
+
throw new BadDataException("AI Agent not found");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Allow if it's a global agent
|
|
159
|
+
if (agent.isGlobalAIAgent) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Allow if the agent belongs to the same project
|
|
164
|
+
if (
|
|
165
|
+
agent.projectId &&
|
|
166
|
+
agent.projectId.toString() === createBy.data.projectId.toString()
|
|
167
|
+
) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Reject if the agent belongs to a different project
|
|
172
|
+
throw new BadDataException(
|
|
173
|
+
"The specified AI Agent does not belong to this project. Please use an AI Agent from your project or a global AI Agent.",
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export default new Service();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import Model from "../../Models/DatabaseModels/AIAgentTaskTelemetryException";
|
|
3
|
+
import ObjectID from "../../Types/ObjectID";
|
|
4
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
5
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
6
|
+
|
|
7
|
+
export interface LinkTaskToTelemetryExceptionParams {
|
|
8
|
+
projectId: ObjectID;
|
|
9
|
+
aiAgentTaskId: ObjectID;
|
|
10
|
+
telemetryExceptionId: ObjectID;
|
|
11
|
+
props: DatabaseCommonInteractionProps;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Service extends DatabaseService<Model> {
|
|
15
|
+
public constructor() {
|
|
16
|
+
super(Model);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@CaptureSpan()
|
|
20
|
+
public async linkTaskToTelemetryException(
|
|
21
|
+
params: LinkTaskToTelemetryExceptionParams,
|
|
22
|
+
): Promise<Model> {
|
|
23
|
+
const { projectId, aiAgentTaskId, telemetryExceptionId, props } = params;
|
|
24
|
+
|
|
25
|
+
const taskExceptionLink: Model = new Model();
|
|
26
|
+
taskExceptionLink.projectId = projectId;
|
|
27
|
+
taskExceptionLink.aiAgentTaskId = aiAgentTaskId;
|
|
28
|
+
taskExceptionLink.telemetryExceptionId = telemetryExceptionId;
|
|
29
|
+
|
|
30
|
+
return await this.create({
|
|
31
|
+
data: taskExceptionLink,
|
|
32
|
+
props: {
|
|
33
|
+
...props,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default new Service();
|
package/Server/Services/Index.ts
CHANGED
|
@@ -64,6 +64,11 @@ import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
|
|
|
64
64
|
// On-Call Duty
|
|
65
65
|
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
66
66
|
import ProbeService from "./ProbeService";
|
|
67
|
+
import AIAgentService from "./AIAgentService";
|
|
68
|
+
import AIAgentOwnerUserService from "./AIAgentOwnerUserService";
|
|
69
|
+
import AIAgentOwnerTeamService from "./AIAgentOwnerTeamService";
|
|
70
|
+
import AIAgentTaskLogService from "./AIAgentTaskLogService";
|
|
71
|
+
import AIAgentTaskPullRequestService from "./AIAgentTaskPullRequestService";
|
|
67
72
|
import ProjectCallSMSConfigService from "./ProjectCallSMSConfigService";
|
|
68
73
|
import ProjectService from "./ProjectService";
|
|
69
74
|
// Project SMTP Config.
|
|
@@ -241,6 +246,11 @@ const services: Array<BaseService> = [
|
|
|
241
246
|
ProjectService,
|
|
242
247
|
ProjectSmtpConfigService,
|
|
243
248
|
ProbeService,
|
|
249
|
+
AIAgentService,
|
|
250
|
+
AIAgentOwnerUserService,
|
|
251
|
+
AIAgentOwnerTeamService,
|
|
252
|
+
AIAgentTaskLogService,
|
|
253
|
+
AIAgentTaskPullRequestService,
|
|
244
254
|
ProjectSsoService,
|
|
245
255
|
|
|
246
256
|
ScheduledMaintenanceCustomFieldService,
|
|
@@ -1,10 +1,172 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import Model from "../../Models/DatabaseModels/TelemetryException";
|
|
3
|
+
import AIAgentTask from "../../Models/DatabaseModels/AIAgentTask";
|
|
4
|
+
import AIAgentTaskTelemetryException from "../../Models/DatabaseModels/AIAgentTaskTelemetryException";
|
|
5
|
+
import ObjectID from "../../Types/ObjectID";
|
|
6
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
7
|
+
import AIAgentTaskType from "../../Types/AI/AIAgentTaskType";
|
|
8
|
+
import AIAgentTaskStatus from "../../Types/AI/AIAgentTaskStatus";
|
|
9
|
+
import { FixExceptionTaskMetadata } from "../../Types/AI/AIAgentTaskMetadata";
|
|
10
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
11
|
+
import AIAgentTaskService from "./AIAgentTaskService";
|
|
12
|
+
import AIAgentTaskTelemetryExceptionService from "./AIAgentTaskTelemetryExceptionService";
|
|
13
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
14
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
15
|
+
|
|
16
|
+
export interface CreateAIAgentTaskForExceptionParams {
|
|
17
|
+
telemetryExceptionId: ObjectID;
|
|
18
|
+
props: DatabaseCommonInteractionProps;
|
|
19
|
+
}
|
|
3
20
|
|
|
4
21
|
export class Service extends DatabaseService<Model> {
|
|
5
22
|
public constructor() {
|
|
6
23
|
super(Model);
|
|
7
24
|
}
|
|
25
|
+
|
|
26
|
+
@CaptureSpan()
|
|
27
|
+
public async createAIAgentTaskForException(
|
|
28
|
+
params: CreateAIAgentTaskForExceptionParams,
|
|
29
|
+
): Promise<AIAgentTask> {
|
|
30
|
+
const { telemetryExceptionId, props } = params;
|
|
31
|
+
|
|
32
|
+
// Get the telemetry exception
|
|
33
|
+
const telemetryException: Model | null = await this.findOneById({
|
|
34
|
+
id: telemetryExceptionId,
|
|
35
|
+
select: {
|
|
36
|
+
_id: true,
|
|
37
|
+
projectId: true,
|
|
38
|
+
message: true,
|
|
39
|
+
stackTrace: true,
|
|
40
|
+
telemetryServiceId: true,
|
|
41
|
+
exceptionType: true,
|
|
42
|
+
},
|
|
43
|
+
props,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!telemetryException || !telemetryException.projectId) {
|
|
47
|
+
throw new BadDataException("Telemetry Exception not found");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check if an active AI agent task already exists for this exception
|
|
51
|
+
await this.validateNoActiveTaskExists(telemetryExceptionId);
|
|
52
|
+
|
|
53
|
+
// Create the AI Agent Task
|
|
54
|
+
const createdTask: AIAgentTask = await this.createFixExceptionTask({
|
|
55
|
+
telemetryException,
|
|
56
|
+
telemetryExceptionId,
|
|
57
|
+
props,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Link the task to the telemetry exception
|
|
61
|
+
await AIAgentTaskTelemetryExceptionService.linkTaskToTelemetryException({
|
|
62
|
+
projectId: telemetryException.projectId,
|
|
63
|
+
aiAgentTaskId: createdTask.id!,
|
|
64
|
+
telemetryExceptionId,
|
|
65
|
+
props,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return createdTask;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@CaptureSpan()
|
|
72
|
+
private async validateNoActiveTaskExists(
|
|
73
|
+
telemetryExceptionId: ObjectID,
|
|
74
|
+
): Promise<void> {
|
|
75
|
+
const existingTaskLink: AIAgentTaskTelemetryException | null =
|
|
76
|
+
await AIAgentTaskTelemetryExceptionService.findOneBy({
|
|
77
|
+
query: {
|
|
78
|
+
telemetryExceptionId: telemetryExceptionId,
|
|
79
|
+
aiAgentTask: {
|
|
80
|
+
status: QueryHelper.notIn([
|
|
81
|
+
AIAgentTaskStatus.Completed,
|
|
82
|
+
AIAgentTaskStatus.Error,
|
|
83
|
+
]),
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
select: {
|
|
87
|
+
_id: true,
|
|
88
|
+
aiAgentTaskId: true,
|
|
89
|
+
},
|
|
90
|
+
props: {
|
|
91
|
+
isRoot: true,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (existingTaskLink) {
|
|
96
|
+
throw new BadDataException(
|
|
97
|
+
"An AI agent task is already in progress for this exception. Please wait for it to complete before creating a new one.",
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@CaptureSpan()
|
|
103
|
+
private async createFixExceptionTask(params: {
|
|
104
|
+
telemetryException: Model;
|
|
105
|
+
telemetryExceptionId: ObjectID;
|
|
106
|
+
props: DatabaseCommonInteractionProps;
|
|
107
|
+
}): Promise<AIAgentTask> {
|
|
108
|
+
const { telemetryException, telemetryExceptionId, props } = params;
|
|
109
|
+
|
|
110
|
+
const aiAgentTask: AIAgentTask = new AIAgentTask();
|
|
111
|
+
aiAgentTask.projectId = telemetryException.projectId!;
|
|
112
|
+
aiAgentTask.taskType = AIAgentTaskType.FixException;
|
|
113
|
+
aiAgentTask.status = AIAgentTaskStatus.Scheduled;
|
|
114
|
+
|
|
115
|
+
// Set name and description based on exception details
|
|
116
|
+
const exceptionType: string =
|
|
117
|
+
telemetryException.exceptionType || "Exception";
|
|
118
|
+
const exceptionMessage: string =
|
|
119
|
+
telemetryException.message || "No message available";
|
|
120
|
+
|
|
121
|
+
aiAgentTask.name = `Fix ${exceptionType}: ${exceptionMessage}`;
|
|
122
|
+
aiAgentTask.description = `AI Agent task to fix the exception: ${exceptionMessage}`;
|
|
123
|
+
|
|
124
|
+
// Build metadata
|
|
125
|
+
aiAgentTask.metadata = this.buildFixExceptionMetadata({
|
|
126
|
+
telemetryException,
|
|
127
|
+
telemetryExceptionId,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const createdTask: AIAgentTask = await AIAgentTaskService.create({
|
|
131
|
+
data: aiAgentTask,
|
|
132
|
+
props: {
|
|
133
|
+
...props,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!createdTask.id) {
|
|
138
|
+
throw new BadDataException("Failed to create AI Agent Task");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return createdTask;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private buildFixExceptionMetadata(params: {
|
|
145
|
+
telemetryException: Model;
|
|
146
|
+
telemetryExceptionId: ObjectID;
|
|
147
|
+
}): FixExceptionTaskMetadata {
|
|
148
|
+
const { telemetryException, telemetryExceptionId } = params;
|
|
149
|
+
|
|
150
|
+
const metadata: FixExceptionTaskMetadata = {
|
|
151
|
+
taskType: AIAgentTaskType.FixException,
|
|
152
|
+
exceptionId: telemetryExceptionId.toString(),
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
if (telemetryException.stackTrace) {
|
|
156
|
+
metadata.stackTrace = telemetryException.stackTrace;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (telemetryException.message) {
|
|
160
|
+
metadata.errorMessage = telemetryException.message;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (telemetryException.telemetryServiceId) {
|
|
164
|
+
metadata.telemetryServiceId =
|
|
165
|
+
telemetryException.telemetryServiceId.toString();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return metadata;
|
|
169
|
+
}
|
|
8
170
|
}
|
|
9
171
|
|
|
10
172
|
export default new Service();
|
|
@@ -40,6 +40,17 @@ import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
|
40
40
|
import ExceptionMessages from "../../../Types/Exception/ExceptionMessages";
|
|
41
41
|
import MonitorEvaluationSummary from "../../../Types/Monitor/MonitorEvaluationSummary";
|
|
42
42
|
import MonitorStatusService from "../../Services/MonitorStatusService";
|
|
43
|
+
import { ProbeConnectionStatus } from "../../../Models/DatabaseModels/Probe";
|
|
44
|
+
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
|
|
45
|
+
|
|
46
|
+
interface ProbeAgreementResult {
|
|
47
|
+
hasAgreement: boolean;
|
|
48
|
+
agreementCount: number;
|
|
49
|
+
requiredCount: number;
|
|
50
|
+
totalActiveProbes: number;
|
|
51
|
+
agreedCriteriaId: string | null;
|
|
52
|
+
agreedRootCause: string | null;
|
|
53
|
+
}
|
|
43
54
|
|
|
44
55
|
export default class MonitorResourceUtil {
|
|
45
56
|
@CaptureSpan()
|
|
@@ -125,6 +136,7 @@ export default class MonitorResourceUtil {
|
|
|
125
136
|
currentMonitorStatusId: true,
|
|
126
137
|
_id: true,
|
|
127
138
|
name: true,
|
|
139
|
+
minimumProbeAgreement: true,
|
|
128
140
|
},
|
|
129
141
|
props: {
|
|
130
142
|
isRoot: true,
|
|
@@ -500,6 +512,62 @@ export default class MonitorResourceUtil {
|
|
|
500
512
|
evaluationSummary: evaluationSummary,
|
|
501
513
|
});
|
|
502
514
|
|
|
515
|
+
// Check probe agreement for probe-based monitors
|
|
516
|
+
if (
|
|
517
|
+
monitor.monitorType &&
|
|
518
|
+
MonitorTypeHelper.isProbableMonitor(monitor.monitorType)
|
|
519
|
+
) {
|
|
520
|
+
const probeAgreementResult: ProbeAgreementResult =
|
|
521
|
+
await MonitorResourceUtil.checkProbeAgreement({
|
|
522
|
+
monitor: monitor,
|
|
523
|
+
monitorStep: monitorStep,
|
|
524
|
+
currentCriteriaMetId: response.criteriaMetId || null,
|
|
525
|
+
currentRootCause: response.rootCause || null,
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Add probe agreement event to evaluation summary
|
|
529
|
+
evaluationSummary.events.push({
|
|
530
|
+
type: "probe-agreement",
|
|
531
|
+
title: "Probe Agreement Check",
|
|
532
|
+
message: probeAgreementResult.hasAgreement
|
|
533
|
+
? `Probe agreement reached: ${probeAgreementResult.agreementCount}/${probeAgreementResult.requiredCount} probes agree (${probeAgreementResult.totalActiveProbes} active probes total).`
|
|
534
|
+
: `Probe agreement not reached: ${probeAgreementResult.agreementCount}/${probeAgreementResult.requiredCount} probes agree (${probeAgreementResult.totalActiveProbes} active probes total). Skipping status change.`,
|
|
535
|
+
at: OneUptimeDate.getCurrentDate(),
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
if (!probeAgreementResult.hasAgreement) {
|
|
539
|
+
logger.debug(
|
|
540
|
+
`${dataToProcess.monitorId.toString()} - Probe agreement not met. ${probeAgreementResult.agreementCount}/${probeAgreementResult.requiredCount} probes agree. Skipping status change.`,
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
// Release lock and return early - no status change
|
|
544
|
+
if (mutex) {
|
|
545
|
+
try {
|
|
546
|
+
await Semaphore.release(mutex);
|
|
547
|
+
} catch (err) {
|
|
548
|
+
logger.error(err);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
await persistLatestMonitorPayload();
|
|
553
|
+
|
|
554
|
+
MonitorLogUtil.saveMonitorLog({
|
|
555
|
+
monitorId: monitor.id!,
|
|
556
|
+
projectId: monitor.projectId!,
|
|
557
|
+
dataToProcess: dataToProcess,
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
response.evaluationSummary = evaluationSummary;
|
|
561
|
+
return response;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Use the agreed criteria result
|
|
565
|
+
response.criteriaMetId = probeAgreementResult.agreedCriteriaId
|
|
566
|
+
? probeAgreementResult.agreedCriteriaId
|
|
567
|
+
: undefined;
|
|
568
|
+
response.rootCause = probeAgreementResult.agreedRootCause;
|
|
569
|
+
}
|
|
570
|
+
|
|
503
571
|
if (response.criteriaMetId && response.rootCause) {
|
|
504
572
|
logger.debug(
|
|
505
573
|
`${dataToProcess.monitorId.toString()} - Criteria met: ${
|
|
@@ -735,4 +803,164 @@ export default class MonitorResourceUtil {
|
|
|
735
803
|
|
|
736
804
|
return response;
|
|
737
805
|
}
|
|
806
|
+
|
|
807
|
+
@CaptureSpan()
|
|
808
|
+
private static async checkProbeAgreement(input: {
|
|
809
|
+
monitor: Monitor;
|
|
810
|
+
monitorStep: MonitorStep;
|
|
811
|
+
currentCriteriaMetId: string | null;
|
|
812
|
+
currentRootCause: string | null;
|
|
813
|
+
}): Promise<ProbeAgreementResult> {
|
|
814
|
+
const { monitor, monitorStep, currentCriteriaMetId, currentRootCause } =
|
|
815
|
+
input;
|
|
816
|
+
|
|
817
|
+
/*
|
|
818
|
+
* If minimumProbeAgreement is not set, all probes must agree
|
|
819
|
+
* Get all MonitorProbes for this monitor with their probe connection status
|
|
820
|
+
*/
|
|
821
|
+
const monitorProbes: Array<MonitorProbe> = await MonitorProbeService.findBy(
|
|
822
|
+
{
|
|
823
|
+
query: {
|
|
824
|
+
monitorId: monitor.id!,
|
|
825
|
+
},
|
|
826
|
+
select: {
|
|
827
|
+
probeId: true,
|
|
828
|
+
isEnabled: true,
|
|
829
|
+
lastMonitoringLog: true,
|
|
830
|
+
probe: {
|
|
831
|
+
connectionStatus: true,
|
|
832
|
+
},
|
|
833
|
+
},
|
|
834
|
+
limit: LIMIT_PER_PROJECT,
|
|
835
|
+
skip: 0,
|
|
836
|
+
props: {
|
|
837
|
+
isRoot: true,
|
|
838
|
+
},
|
|
839
|
+
},
|
|
840
|
+
);
|
|
841
|
+
|
|
842
|
+
// Filter to only active probes (enabled AND connected)
|
|
843
|
+
const activeProbes: Array<MonitorProbe> = monitorProbes.filter(
|
|
844
|
+
(mp: MonitorProbe) => {
|
|
845
|
+
return (
|
|
846
|
+
mp.isEnabled &&
|
|
847
|
+
mp.probe?.connectionStatus === ProbeConnectionStatus.Connected
|
|
848
|
+
);
|
|
849
|
+
},
|
|
850
|
+
);
|
|
851
|
+
|
|
852
|
+
// If no active probes, treat as agreement met (nothing to compare)
|
|
853
|
+
if (activeProbes.length === 0) {
|
|
854
|
+
logger.debug(
|
|
855
|
+
`${monitor.id?.toString()} - No active probes found. Treating as agreement met.`,
|
|
856
|
+
);
|
|
857
|
+
return {
|
|
858
|
+
hasAgreement: true,
|
|
859
|
+
agreementCount: 0,
|
|
860
|
+
requiredCount: 0,
|
|
861
|
+
totalActiveProbes: 0,
|
|
862
|
+
agreedCriteriaId: currentCriteriaMetId,
|
|
863
|
+
agreedRootCause: currentRootCause,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Determine required count for agreement
|
|
868
|
+
const requiredCount: number =
|
|
869
|
+
monitor.minimumProbeAgreement ?? activeProbes.length;
|
|
870
|
+
// Effective threshold cannot exceed number of active probes
|
|
871
|
+
const effectiveThreshold: number = Math.min(
|
|
872
|
+
requiredCount,
|
|
873
|
+
activeProbes.length,
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
/*
|
|
877
|
+
* Count how many probes agree on each criteria result
|
|
878
|
+
* Key: criteriaId or "none" for no criteria met
|
|
879
|
+
* Value: { count, rootCause }
|
|
880
|
+
*/
|
|
881
|
+
const criteriaAgreements: Map<
|
|
882
|
+
string,
|
|
883
|
+
{ count: number; rootCause: string | null }
|
|
884
|
+
> = new Map();
|
|
885
|
+
|
|
886
|
+
const stepId: string = monitorStep.id.toString();
|
|
887
|
+
|
|
888
|
+
for (const monitorProbe of activeProbes) {
|
|
889
|
+
const probeResponse: ProbeMonitorResponse | undefined =
|
|
890
|
+
monitorProbe.lastMonitoringLog?.[stepId];
|
|
891
|
+
|
|
892
|
+
if (!probeResponse) {
|
|
893
|
+
// No response yet for this step from this probe - skip
|
|
894
|
+
logger.debug(
|
|
895
|
+
`${monitor.id?.toString()} - Probe ${monitorProbe.probeId?.toString()} has no response for step ${stepId}. Skipping.`,
|
|
896
|
+
);
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// Evaluate this probe's response against criteria
|
|
901
|
+
const tempResponse: ProbeApiIngestResponse = {
|
|
902
|
+
monitorId: monitor.id!,
|
|
903
|
+
criteriaMetId: undefined,
|
|
904
|
+
rootCause: null,
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
const tempEvaluationSummary: MonitorEvaluationSummary = {
|
|
908
|
+
evaluatedAt: OneUptimeDate.getCurrentDate(),
|
|
909
|
+
criteriaResults: [],
|
|
910
|
+
events: [],
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
const evaluatedResponse: ProbeApiIngestResponse =
|
|
914
|
+
await MonitorCriteriaEvaluator.processMonitorStep({
|
|
915
|
+
dataToProcess: probeResponse as DataToProcess,
|
|
916
|
+
monitorStep: monitorStep,
|
|
917
|
+
monitor: monitor,
|
|
918
|
+
probeApiIngestResponse: tempResponse,
|
|
919
|
+
evaluationSummary: tempEvaluationSummary,
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
// Record the result
|
|
923
|
+
const criteriaKey: string = evaluatedResponse.criteriaMetId || "none";
|
|
924
|
+
const existing: { count: number; rootCause: string | null } | undefined =
|
|
925
|
+
criteriaAgreements.get(criteriaKey);
|
|
926
|
+
|
|
927
|
+
if (existing) {
|
|
928
|
+
existing.count += 1;
|
|
929
|
+
} else {
|
|
930
|
+
criteriaAgreements.set(criteriaKey, {
|
|
931
|
+
count: 1,
|
|
932
|
+
rootCause: evaluatedResponse.rootCause,
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Find the criteria with the most agreement
|
|
938
|
+
let maxCount: number = 0;
|
|
939
|
+
let winningCriteriaId: string | null = null;
|
|
940
|
+
let winningRootCause: string | null = null;
|
|
941
|
+
|
|
942
|
+
for (const [criteriaId, data] of criteriaAgreements) {
|
|
943
|
+
if (data.count > maxCount) {
|
|
944
|
+
maxCount = data.count;
|
|
945
|
+
winningCriteriaId = criteriaId === "none" ? null : criteriaId;
|
|
946
|
+
winningRootCause = data.rootCause;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Check if the winning criteria has reached the agreement threshold
|
|
951
|
+
const hasAgreement: boolean = maxCount >= effectiveThreshold;
|
|
952
|
+
|
|
953
|
+
logger.debug(
|
|
954
|
+
`${monitor.id?.toString()} - Probe agreement check: ${maxCount}/${effectiveThreshold} probes agree on criteria "${winningCriteriaId || "none"}". Agreement ${hasAgreement ? "reached" : "not reached"}.`,
|
|
955
|
+
);
|
|
956
|
+
|
|
957
|
+
return {
|
|
958
|
+
hasAgreement,
|
|
959
|
+
agreementCount: maxCount,
|
|
960
|
+
requiredCount: effectiveThreshold,
|
|
961
|
+
totalActiveProbes: activeProbes.length,
|
|
962
|
+
agreedCriteriaId: hasAgreement ? winningCriteriaId : null,
|
|
963
|
+
agreedRootCause: hasAgreement ? winningRootCause : null,
|
|
964
|
+
};
|
|
965
|
+
}
|
|
738
966
|
}
|
|
@@ -327,4 +327,33 @@ export default class PushNotificationUtil {
|
|
|
327
327
|
|
|
328
328
|
return PushNotificationUtil.applyDefaults(notification);
|
|
329
329
|
}
|
|
330
|
+
|
|
331
|
+
public static createAIAgentStatusChangedNotification(params: {
|
|
332
|
+
aiAgentName: string;
|
|
333
|
+
projectName: string;
|
|
334
|
+
connectionStatus: string;
|
|
335
|
+
clickAction?: string;
|
|
336
|
+
}): PushNotificationMessage {
|
|
337
|
+
const { aiAgentName, projectName, connectionStatus, clickAction } = params;
|
|
338
|
+
const notification: Partial<PushNotificationMessage> = {
|
|
339
|
+
title: `AI Agent ${connectionStatus}: ${aiAgentName}`,
|
|
340
|
+
body: `AI Agent ${aiAgentName} is ${connectionStatus} in ${projectName}. Click to view details.`,
|
|
341
|
+
tag: "ai-agent-status-changed",
|
|
342
|
+
requireInteraction: true,
|
|
343
|
+
data: {
|
|
344
|
+
type: "ai-agent-status-changed",
|
|
345
|
+
aiAgentName: aiAgentName,
|
|
346
|
+
projectName: projectName,
|
|
347
|
+
connectionStatus: connectionStatus,
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
if (clickAction) {
|
|
352
|
+
notification.clickAction = clickAction;
|
|
353
|
+
notification.url = clickAction;
|
|
354
|
+
notification.data!["url"] = clickAction;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return PushNotificationUtil.applyDefaults(notification);
|
|
358
|
+
}
|
|
330
359
|
}
|