@oneuptime/common 9.2.16 → 9.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/Models/DatabaseModels/CodeRepository.ts +664 -0
  2. package/Models/DatabaseModels/Index.ts +8 -0
  3. package/Models/DatabaseModels/LlmLog.ts +818 -0
  4. package/Models/DatabaseModels/LlmProvider.ts +21 -0
  5. package/Models/DatabaseModels/Project.ts +206 -0
  6. package/Models/DatabaseModels/ServiceCatalogCodeRepository.ts +549 -0
  7. package/Server/API/AIBillingAPI.ts +126 -0
  8. package/Server/API/AlertAPI.ts +139 -0
  9. package/Server/API/GitHubAPI.ts +360 -0
  10. package/Server/API/IncidentAPI.ts +258 -0
  11. package/Server/API/ScheduledMaintenanceAPI.ts +164 -0
  12. package/Server/EnvironmentConfig.ts +44 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1765580181582-MigrationName.ts +79 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1765633554715-MigrationName.ts +75 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1765801357168-MigrationName.ts +32 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1765810218488-MigrationName.ts +69 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1765830758857-MigrationName.ts +111 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1765834537501-MigrationName.ts +39 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  20. package/Server/Services/AIBillingService.ts +247 -0
  21. package/Server/Services/AIService.ts +238 -0
  22. package/Server/Services/CodeRepositoryService.ts +10 -0
  23. package/Server/Services/IncidentService.ts +88 -0
  24. package/Server/Services/Index.ts +2 -0
  25. package/Server/Services/LlmLogService.ts +14 -0
  26. package/Server/Services/LlmProviderService.ts +58 -0
  27. package/Server/Services/ServiceCatalogCodeRepositoryService.ts +55 -0
  28. package/Server/Utils/AI/AlertAIContextBuilder.ts +264 -0
  29. package/Server/Utils/AI/IncidentAIContextBuilder.ts +710 -0
  30. package/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.ts +345 -0
  31. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +226 -0
  32. package/Server/Utils/LLM/LLMService.ts +276 -0
  33. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +166 -0
  34. package/Server/Utils/Workspace/Slack/Slack.ts +134 -0
  35. package/Server/Utils/Workspace/Workspace.ts +126 -0
  36. package/Tests/Types/Domain.test.ts +24 -3
  37. package/Types/CodeRepository/CodeRepositoryType.ts +1 -1
  38. package/Types/Domain.ts +21 -24
  39. package/Types/LlmLogStatus.ts +7 -0
  40. package/Types/Permission.ts +87 -0
  41. package/Types/ServiceCatalog/CodeRepositoryImprovementAction.ts +9 -0
  42. package/UI/Components/AI/AILoader.tsx +95 -0
  43. package/UI/Components/AI/GenerateFromAIModal.tsx +432 -0
  44. package/UI/Components/Modal/Modal.tsx +6 -1
  45. package/build/dist/Models/DatabaseModels/CodeRepository.js +689 -0
  46. package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -0
  47. package/build/dist/Models/DatabaseModels/Index.js +7 -0
  48. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  49. package/build/dist/Models/DatabaseModels/LlmLog.js +856 -0
  50. package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -0
  51. package/build/dist/Models/DatabaseModels/LlmProvider.js +22 -0
  52. package/build/dist/Models/DatabaseModels/LlmProvider.js.map +1 -1
  53. package/build/dist/Models/DatabaseModels/Project.js +220 -0
  54. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/ServiceCatalogCodeRepository.js +565 -0
  56. package/build/dist/Models/DatabaseModels/ServiceCatalogCodeRepository.js.map +1 -0
  57. package/build/dist/Server/API/AIBillingAPI.js +58 -0
  58. package/build/dist/Server/API/AIBillingAPI.js.map +1 -0
  59. package/build/dist/Server/API/AlertAPI.js +94 -0
  60. package/build/dist/Server/API/AlertAPI.js.map +1 -0
  61. package/build/dist/Server/API/GitHubAPI.js +207 -0
  62. package/build/dist/Server/API/GitHubAPI.js.map +1 -0
  63. package/build/dist/Server/API/IncidentAPI.js +171 -1
  64. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  65. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +103 -0
  66. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -0
  67. package/build/dist/Server/EnvironmentConfig.js +31 -0
  68. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  69. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765580181582-MigrationName.js +34 -0
  70. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765580181582-MigrationName.js.map +1 -0
  71. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765633554715-MigrationName.js +32 -0
  72. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765633554715-MigrationName.js.map +1 -0
  73. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765801357168-MigrationName.js +38 -0
  74. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765801357168-MigrationName.js.map +1 -0
  75. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765810218488-MigrationName.js +30 -0
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765810218488-MigrationName.js.map +1 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765830758857-MigrationName.js +44 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765830758857-MigrationName.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765834537501-MigrationName.js +22 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765834537501-MigrationName.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  83. package/build/dist/Server/Services/AIBillingService.js +187 -0
  84. package/build/dist/Server/Services/AIBillingService.js.map +1 -0
  85. package/build/dist/Server/Services/AIService.js +184 -0
  86. package/build/dist/Server/Services/AIService.js.map +1 -0
  87. package/build/dist/Server/Services/CodeRepositoryService.js +9 -0
  88. package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -0
  89. package/build/dist/Server/Services/IncidentService.js +60 -0
  90. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  91. package/build/dist/Server/Services/Index.js +2 -0
  92. package/build/dist/Server/Services/Index.js.map +1 -1
  93. package/build/dist/Server/Services/LlmLogService.js +13 -0
  94. package/build/dist/Server/Services/LlmLogService.js.map +1 -0
  95. package/build/dist/Server/Services/LlmProviderService.js +65 -0
  96. package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
  97. package/build/dist/Server/Services/ServiceCatalogCodeRepositoryService.js +54 -0
  98. package/build/dist/Server/Services/ServiceCatalogCodeRepositoryService.js.map +1 -0
  99. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +238 -0
  100. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -0
  101. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +597 -0
  102. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -0
  103. package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js +311 -0
  104. package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js.map +1 -0
  105. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +163 -0
  106. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  107. package/build/dist/Server/Utils/LLM/LLMService.js +225 -0
  108. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -0
  109. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +110 -0
  110. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  111. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +89 -0
  112. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  113. package/build/dist/Server/Utils/Workspace/Workspace.js +80 -0
  114. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  115. package/build/dist/Tests/Types/Domain.test.js +19 -3
  116. package/build/dist/Tests/Types/Domain.test.js.map +1 -1
  117. package/build/dist/Types/CodeRepository/CodeRepositoryType.js +1 -1
  118. package/build/dist/Types/CodeRepository/CodeRepositoryType.js.map +1 -1
  119. package/build/dist/Types/Domain.js +18 -16
  120. package/build/dist/Types/Domain.js.map +1 -1
  121. package/build/dist/Types/LlmLogStatus.js +8 -0
  122. package/build/dist/Types/LlmLogStatus.js.map +1 -0
  123. package/build/dist/Types/Permission.js +74 -0
  124. package/build/dist/Types/Permission.js.map +1 -1
  125. package/build/dist/Types/ServiceCatalog/CodeRepositoryImprovementAction.js +10 -0
  126. package/build/dist/Types/ServiceCatalog/CodeRepositoryImprovementAction.js.map +1 -0
  127. package/build/dist/UI/Components/AI/AILoader.js +64 -0
  128. package/build/dist/UI/Components/AI/AILoader.js.map +1 -0
  129. package/build/dist/UI/Components/AI/GenerateFromAIModal.js +320 -0
  130. package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -0
  131. package/build/dist/UI/Components/Modal/Modal.js +6 -1
  132. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  133. package/package.json +1 -1
@@ -0,0 +1,238 @@
1
+ import { IsBillingEnabled } from "../EnvironmentConfig";
2
+ import BaseService from "./BaseService";
3
+ import LlmProviderService from "./LlmProviderService";
4
+ import LlmLogService from "./LlmLogService";
5
+ import ProjectService from "./ProjectService";
6
+ import Project from "../../Models/DatabaseModels/Project";
7
+ import AIBillingService from "./AIBillingService";
8
+ import LLMService, {
9
+ LLMProviderConfig,
10
+ LLMCompletionResponse,
11
+ LLMMessage,
12
+ } from "../Utils/LLM/LLMService";
13
+ import LlmProvider from "../../Models/DatabaseModels/LlmProvider";
14
+ import LlmLog from "../../Models/DatabaseModels/LlmLog";
15
+ import LlmLogStatus from "../../Types/LlmLogStatus";
16
+ import ObjectID from "../../Types/ObjectID";
17
+ import BadDataException from "../../Types/Exception/BadDataException";
18
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
19
+ import logger from "../Utils/Logger";
20
+
21
+ export interface AILogRequest {
22
+ projectId: ObjectID;
23
+ userId?: ObjectID;
24
+ feature: string; // e.g., "IncidentPostmortem", "IncidentNote"
25
+ incidentId?: ObjectID;
26
+ alertId?: ObjectID;
27
+ scheduledMaintenanceId?: ObjectID;
28
+ messages: Array<LLMMessage>;
29
+ maxTokens?: number;
30
+ temperature?: number;
31
+ }
32
+
33
+ export interface AILogResponse {
34
+ content: string;
35
+ llmLog: LlmLog;
36
+ }
37
+
38
+ export class Service extends BaseService {
39
+ public constructor() {
40
+ super();
41
+ }
42
+
43
+ @CaptureSpan()
44
+ public async executeWithLogging(
45
+ request: AILogRequest,
46
+ ): Promise<AILogResponse> {
47
+ const startTime: Date = new Date();
48
+
49
+ // Get LLM provider for the project
50
+ const llmProvider: LlmProvider | null =
51
+ await LlmProviderService.getLLMProviderForProject(request.projectId);
52
+
53
+ if (!llmProvider) {
54
+ throw new BadDataException(
55
+ "No LLM provider configured for this project. Please configure an LLM provider in Settings > AI > LLM Providers.",
56
+ );
57
+ }
58
+
59
+ if (!llmProvider.llmType) {
60
+ throw new BadDataException(
61
+ "LLM provider type is not configured properly.",
62
+ );
63
+ }
64
+
65
+ // Create log entry (will be updated after completion)
66
+ const logEntry: LlmLog = new LlmLog();
67
+ logEntry.projectId = request.projectId;
68
+ logEntry.isGlobalProvider = llmProvider.isGlobalLlm || false;
69
+ logEntry.feature = request.feature;
70
+ logEntry.requestPrompt = request.messages
71
+ .map((m: LLMMessage) => {
72
+ return m.content;
73
+ })
74
+ .join("\n")
75
+ .substring(0, 5000); // Store first 5000 chars
76
+ logEntry.requestStartedAt = startTime;
77
+
78
+ // Set optional fields only if they have values
79
+ if (llmProvider.id) {
80
+ logEntry.llmProviderId = llmProvider.id;
81
+ }
82
+ if (llmProvider.name) {
83
+ logEntry.llmProviderName = llmProvider.name;
84
+ }
85
+ if (llmProvider.llmType) {
86
+ logEntry.llmType = llmProvider.llmType;
87
+ }
88
+ if (llmProvider.modelName) {
89
+ logEntry.modelName = llmProvider.modelName;
90
+ }
91
+ if (request.userId) {
92
+ logEntry.userId = request.userId;
93
+ }
94
+ if (request.incidentId) {
95
+ logEntry.incidentId = request.incidentId;
96
+ }
97
+ if (request.alertId) {
98
+ logEntry.alertId = request.alertId;
99
+ }
100
+ if (request.scheduledMaintenanceId) {
101
+ logEntry.scheduledMaintenanceId = request.scheduledMaintenanceId;
102
+ }
103
+
104
+ // Check if billing should apply
105
+ const shouldBill: boolean =
106
+ IsBillingEnabled && (llmProvider.isGlobalLlm || false);
107
+
108
+ // Check balance if billing enabled and using global provider
109
+ if (shouldBill) {
110
+ const project: Project | null = await ProjectService.findOneById({
111
+ id: request.projectId,
112
+ select: { aiCurrentBalanceInUSDCents: true },
113
+ props: { isRoot: true },
114
+ });
115
+
116
+ if (!project || (project.aiCurrentBalanceInUSDCents || 0) <= 0) {
117
+ logEntry.status = LlmLogStatus.InsufficientBalance;
118
+ logEntry.statusMessage = "Insufficient AI balance";
119
+ logEntry.requestCompletedAt = new Date();
120
+ logEntry.durationMs = new Date().getTime() - startTime.getTime();
121
+
122
+ await LlmLogService.create({
123
+ data: logEntry,
124
+ props: { isRoot: true },
125
+ });
126
+
127
+ throw new BadDataException(
128
+ "Insufficient AI balance. Please recharge your AI balance in Project Settings > Billing.",
129
+ );
130
+ }
131
+ }
132
+
133
+ try {
134
+ // Build LLM config
135
+ const llmConfig: LLMProviderConfig = {
136
+ llmType: llmProvider.llmType,
137
+ };
138
+
139
+ if (llmProvider.apiKey) {
140
+ llmConfig.apiKey = llmProvider.apiKey;
141
+ }
142
+
143
+ if (llmProvider.baseUrl) {
144
+ llmConfig.baseUrl = llmProvider.baseUrl.toString();
145
+ }
146
+
147
+ if (llmProvider.modelName) {
148
+ llmConfig.modelName = llmProvider.modelName;
149
+ }
150
+
151
+ // Execute LLM call
152
+ const response: LLMCompletionResponse = await LLMService.getCompletion({
153
+ llmProviderConfig: llmConfig,
154
+ messages: request.messages,
155
+ temperature: request.temperature ?? 0.7,
156
+ });
157
+
158
+ const endTime: Date = new Date();
159
+
160
+ // Update log with success info
161
+ logEntry.status = LlmLogStatus.Success;
162
+ logEntry.totalTokens = response.usage?.totalTokens || 0;
163
+ logEntry.responsePreview = response.content.substring(0, 2000); // Store first 2000 chars
164
+ logEntry.requestCompletedAt = endTime;
165
+ logEntry.durationMs = endTime.getTime() - startTime.getTime();
166
+
167
+ // Calculate and apply costs if using global provider with billing enabled
168
+ if (shouldBill && response.usage) {
169
+ const totalCost: number = Math.ceil(
170
+ (response.usage.totalTokens / 1_000_000) *
171
+ (llmProvider.costPerMillionTokensInUSDCents || 0),
172
+ );
173
+
174
+ logEntry.costInUSDCents = totalCost;
175
+ logEntry.wasBilled = true;
176
+
177
+ // Deduct from project balance
178
+ if (totalCost > 0) {
179
+ const project: Project | null = await ProjectService.findOneById({
180
+ id: request.projectId,
181
+ select: { aiCurrentBalanceInUSDCents: true },
182
+ props: { isRoot: true },
183
+ });
184
+
185
+ if (project) {
186
+ const newBalance: number = Math.max(
187
+ 0,
188
+ (project.aiCurrentBalanceInUSDCents || 0) - totalCost,
189
+ );
190
+
191
+ await ProjectService.updateOneById({
192
+ id: request.projectId,
193
+ data: {
194
+ aiCurrentBalanceInUSDCents: newBalance,
195
+ },
196
+ props: { isRoot: true },
197
+ });
198
+ }
199
+
200
+ // Check if auto-recharge is needed (do this async, don't wait)
201
+ AIBillingService.rechargeIfBalanceIsLow(request.projectId).catch(
202
+ (err: Error) => {
203
+ logger.error("Error during AI balance auto-recharge check:");
204
+ logger.error(err);
205
+ },
206
+ );
207
+ }
208
+ }
209
+
210
+ // Save log entry
211
+ const savedLog: LlmLog = await LlmLogService.create({
212
+ data: logEntry,
213
+ props: { isRoot: true },
214
+ });
215
+
216
+ return {
217
+ content: response.content,
218
+ llmLog: savedLog,
219
+ };
220
+ } catch (error) {
221
+ // Log the error
222
+ logEntry.status = LlmLogStatus.Error;
223
+ logEntry.statusMessage =
224
+ error instanceof Error ? error.message : String(error);
225
+ logEntry.requestCompletedAt = new Date();
226
+ logEntry.durationMs = new Date().getTime() - startTime.getTime();
227
+
228
+ await LlmLogService.create({
229
+ data: logEntry,
230
+ props: { isRoot: true },
231
+ });
232
+
233
+ throw error;
234
+ }
235
+ }
236
+ }
237
+
238
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/CodeRepository";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -65,6 +65,16 @@ import OnCallDutyPolicy from "../../Models/DatabaseModels/OnCallDutyPolicy";
65
65
  import Dictionary from "../../Types/Dictionary";
66
66
  import IncidentTemplateService from "./IncidentTemplateService";
67
67
  import IncidentTemplate from "../../Models/DatabaseModels/IncidentTemplate";
68
+ import LLMService, {
69
+ LLMProviderConfig,
70
+ LLMCompletionResponse,
71
+ } from "../Utils/LLM/LLMService";
72
+ import LlmProviderService from "./LlmProviderService";
73
+ import LlmProvider from "../../Models/DatabaseModels/LlmProvider";
74
+ import IncidentAIContextBuilder, {
75
+ AIGenerationContext,
76
+ IncidentContextData,
77
+ } from "../Utils/AI/IncidentAIContextBuilder";
68
78
 
69
79
  // key is incidentId for this dictionary.
70
80
  type UpdateCarryForward = Dictionary<{
@@ -2388,6 +2398,84 @@ ${incidentSeverity.name}
2388
2398
  );
2389
2399
  }
2390
2400
  }
2401
+
2402
+ @CaptureSpan()
2403
+ public async generatePostmortemFromAI(data: {
2404
+ incidentId: ObjectID;
2405
+ template?: string;
2406
+ }): Promise<string> {
2407
+ // Get the incident to verify it exists and get the project ID
2408
+ const incident: Model | null = await this.findOneById({
2409
+ id: data.incidentId,
2410
+ select: {
2411
+ _id: true,
2412
+ projectId: true,
2413
+ },
2414
+ props: {
2415
+ isRoot: true,
2416
+ },
2417
+ });
2418
+
2419
+ if (!incident || !incident.projectId) {
2420
+ throw new BadDataException("Incident not found");
2421
+ }
2422
+
2423
+ // Get LLM provider for the project
2424
+ const llmProvider: LlmProvider | null =
2425
+ await LlmProviderService.getLLMProviderForProject(incident.projectId);
2426
+
2427
+ if (!llmProvider) {
2428
+ throw new BadDataException(
2429
+ "No LLM provider configured for this project. Please configure an LLM provider in Settings > AI > LLM Providers.",
2430
+ );
2431
+ }
2432
+
2433
+ if (!llmProvider.llmType) {
2434
+ throw new BadDataException(
2435
+ "LLM provider type is not configured properly.",
2436
+ );
2437
+ }
2438
+
2439
+ // Build incident context - always include workspace messages
2440
+ const contextData: IncidentContextData =
2441
+ await IncidentAIContextBuilder.buildIncidentContext({
2442
+ incidentId: data.incidentId,
2443
+ includeWorkspaceMessages: true,
2444
+ workspaceMessageLimit: 500,
2445
+ });
2446
+
2447
+ // Format context for postmortem generation
2448
+ const aiContext: AIGenerationContext =
2449
+ IncidentAIContextBuilder.formatIncidentContextForPostmortem(
2450
+ contextData,
2451
+ data.template,
2452
+ );
2453
+
2454
+ // Generate postmortem using LLM
2455
+ const llmConfig: LLMProviderConfig = {
2456
+ llmType: llmProvider.llmType,
2457
+ };
2458
+
2459
+ if (llmProvider.apiKey) {
2460
+ llmConfig.apiKey = llmProvider.apiKey;
2461
+ }
2462
+
2463
+ if (llmProvider.baseUrl) {
2464
+ llmConfig.baseUrl = llmProvider.baseUrl.toString();
2465
+ }
2466
+
2467
+ if (llmProvider.modelName) {
2468
+ llmConfig.modelName = llmProvider.modelName;
2469
+ }
2470
+
2471
+ const response: LLMCompletionResponse = await LLMService.getCompletion({
2472
+ llmProviderConfig: llmConfig,
2473
+ messages: aiContext.messages,
2474
+ temperature: 0.7,
2475
+ });
2476
+
2477
+ return response.content;
2478
+ }
2391
2479
  }
2392
2480
 
2393
2481
  export default new Service();
@@ -87,6 +87,7 @@ import ServiceCatalogOwnerUserService from "./ServiceCatalogOwnerUserService";
87
87
  import ServiceCatalogService from "./ServiceCatalogService";
88
88
  import ServiceCatalogMonitorService from "./ServiceCatalogMonitorService";
89
89
  import ServiceCatalogTelemetryServiceService from "./ServiceCatalogTelemetryServiceService";
90
+ import ServiceCatalogCodeRepositoryService from "./ServiceCatalogCodeRepositoryService";
90
91
  import ShortLinkService from "./ShortLinkService";
91
92
  // SMS Log Service
92
93
  import SmsLogService from "./SmsLogService";
@@ -321,6 +322,7 @@ const services: Array<BaseService> = [
321
322
  ServiceCatalogDependencyService,
322
323
  ServiceCatalogMonitorService,
323
324
  ServiceCatalogTelemetryServiceService,
325
+ ServiceCatalogCodeRepositoryService,
324
326
 
325
327
  TelemetryExceptionService,
326
328
 
@@ -0,0 +1,14 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/LlmLog";
3
+ import { IsBillingEnabled } from "../EnvironmentConfig";
4
+
5
+ export class Service extends DatabaseService<Model> {
6
+ public constructor() {
7
+ super(Model);
8
+ if (IsBillingEnabled) {
9
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3);
10
+ }
11
+ }
12
+ }
13
+
14
+ export default new Service();
@@ -6,6 +6,7 @@ import ObjectID from "../../Types/ObjectID";
6
6
  import UpdateBy from "../Types/Database/UpdateBy";
7
7
  import QueryHelper from "../Types/Database/QueryHelper";
8
8
  import LIMIT_MAX from "../../Types/Database/LimitMax";
9
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
9
10
 
10
11
  export class Service extends DatabaseService<Model> {
11
12
  public constructor() {
@@ -95,6 +96,63 @@ export class Service extends DatabaseService<Model> {
95
96
 
96
97
  return { updateBy, carryForward: null };
97
98
  }
99
+
100
+ @CaptureSpan()
101
+ public async getLLMProviderForProject(
102
+ projectId: ObjectID,
103
+ ): Promise<Model | null> {
104
+ // First try to get the default provider for the project
105
+ let provider: Model | null = await this.findOneBy({
106
+ query: {
107
+ projectId: projectId,
108
+ isDefault: true,
109
+ },
110
+ select: {
111
+ _id: true,
112
+ name: true,
113
+ llmType: true,
114
+ apiKey: true,
115
+ baseUrl: true,
116
+ modelName: true,
117
+ isGlobalLlm: true,
118
+ costPerMillionTokensInUSDCents: true,
119
+ },
120
+ props: {
121
+ isRoot: true,
122
+ },
123
+ });
124
+
125
+ if (provider) {
126
+ return provider;
127
+ }
128
+
129
+ // If no default provider, get any global provider for the project.
130
+ provider = await this.findOneBy({
131
+ query: {
132
+ projectId: QueryHelper.isNull(),
133
+ isGlobalLlm: true,
134
+ },
135
+ select: {
136
+ _id: true,
137
+ name: true,
138
+ llmType: true,
139
+ apiKey: true,
140
+ baseUrl: true,
141
+ modelName: true,
142
+ isGlobalLlm: true,
143
+ costPerMillionTokensInUSDCents: true,
144
+ },
145
+ props: {
146
+ isRoot: true,
147
+ },
148
+ });
149
+
150
+ if (provider) {
151
+ return provider;
152
+ }
153
+
154
+ return null;
155
+ }
98
156
  }
99
157
 
100
158
  export default new Service();
@@ -0,0 +1,55 @@
1
+ import BadDataException from "../../Types/Exception/BadDataException";
2
+ import CreateBy from "../Types/Database/CreateBy";
3
+ import { OnCreate } from "../Types/Database/Hooks";
4
+ import DatabaseService from "./DatabaseService";
5
+ import Model from "../../Models/DatabaseModels/ServiceCatalogCodeRepository";
6
+ import ObjectID from "../../Types/ObjectID";
7
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
8
+
9
+ export class Service extends DatabaseService<Model> {
10
+ public constructor() {
11
+ super(Model);
12
+ }
13
+
14
+ @CaptureSpan()
15
+ protected override async onBeforeCreate(
16
+ createBy: CreateBy<Model>,
17
+ ): Promise<OnCreate<Model>> {
18
+ if (!createBy.data.serviceCatalogId && !createBy.data.serviceCatalog) {
19
+ throw new BadDataException("serviceCatalog is required");
20
+ }
21
+
22
+ if (!createBy.data.codeRepository && !createBy.data.codeRepositoryId) {
23
+ throw new BadDataException("codeRepository is required");
24
+ }
25
+
26
+ const serviceCatalogId: string | ObjectID | undefined =
27
+ createBy.data.serviceCatalogId || createBy.data.serviceCatalog?._id;
28
+ const codeRepositoryId: string | ObjectID | undefined =
29
+ createBy.data.codeRepositoryId || createBy.data.codeRepository?._id;
30
+
31
+ // check if this code repository is already added to the service catalog for this service.
32
+ const existingCodeRepository: Model | null = await this.findOneBy({
33
+ query: {
34
+ serviceCatalogId: serviceCatalogId as ObjectID,
35
+ codeRepositoryId: codeRepositoryId as ObjectID,
36
+ },
37
+ props: {
38
+ isRoot: true,
39
+ },
40
+ });
41
+
42
+ if (existingCodeRepository) {
43
+ throw new BadDataException(
44
+ "Code Repository already exists for this service",
45
+ );
46
+ }
47
+
48
+ return {
49
+ carryForward: null,
50
+ createBy: createBy,
51
+ };
52
+ }
53
+ }
54
+
55
+ export default new Service();