@oneuptime/common 11.5.8 → 11.5.9

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 (195) hide show
  1. package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +15 -6
  2. package/Models/DatabaseModels/AIRun.ts +37 -0
  3. package/Models/DatabaseModels/AIRunEvent.ts +34 -1
  4. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +215 -0
  5. package/Models/DatabaseModels/Project.ts +25 -0
  6. package/Models/DatabaseModels/StatusPage.ts +42 -0
  7. package/Server/API/AIAgentTaskAPI.ts +38 -12
  8. package/Server/API/AIAgentTaskLogAPI.ts +49 -0
  9. package/Server/API/AIChatAPI.ts +16 -0
  10. package/Server/API/AIReadinessAPI.ts +84 -0
  11. package/Server/API/CodeFixRunAPI.ts +182 -0
  12. package/Server/API/TelemetryExceptionAPI.ts +6 -1
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1784124919694-AddAITaskNumberAndRunTranscript.ts +95 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1784135099754-AllowNullAiAgentOnPullRequest.ts +52 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1784137457184-AddEnableMcpServerToStatusPage.ts +30 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1784200000000-AddSnmpV3ColumnsToNetworkDeviceDiscoveryScan.ts +49 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  18. package/Server/Services/AIRunEventService.ts +15 -1
  19. package/Server/Services/AIRunService.ts +38 -1
  20. package/Server/Services/LlmProviderService.ts +2 -0
  21. package/Server/Services/ProjectService.ts +42 -0
  22. package/Server/Services/StatusPageService.ts +87 -0
  23. package/Server/Services/TelemetryExceptionService.ts +19 -90
  24. package/Server/Types/Markdown.ts +9 -9
  25. package/Server/Types/MarkdownSlugify.ts +47 -0
  26. package/Server/Utils/AI/AIRunTranscript.ts +240 -0
  27. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +9 -0
  28. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +119 -5
  29. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +75 -0
  30. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +235 -0
  31. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +2 -3
  32. package/Server/Utils/AI/Toolbox/CodeTools.ts +883 -0
  33. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +519 -0
  34. package/Server/Utils/AI/Toolbox/Index.ts +27 -0
  35. package/Server/Utils/AI/Toolbox/ScheduledMaintenanceTools.ts +279 -0
  36. package/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.ts +19 -1
  37. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +600 -0
  38. package/Server/Utils/CodeRepository/StackTraceRepoResolver.ts +7 -2
  39. package/Server/Utils/LLM/LLMService.ts +397 -18
  40. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +4 -11
  41. package/Tests/Models/StatusPageEnableMcpServer.test.ts +125 -0
  42. package/Tests/Server/Services/StatusPageServiceMcp.test.ts +223 -0
  43. package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +26 -3
  44. package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +12 -0
  45. package/Tests/Server/Types/Markdown.test.ts +106 -0
  46. package/Tests/Server/Utils/AI/AIRunTranscript.test.ts +182 -0
  47. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +411 -0
  48. package/Tests/Server/Utils/AI/CodeTools.test.ts +596 -0
  49. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +475 -0
  50. package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +548 -0
  51. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +142 -0
  52. package/Tests/Server/Utils/AI/ScheduledMaintenanceTools.test.ts +176 -0
  53. package/Tests/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.test.ts +63 -0
  54. package/Tests/Server/Utils/GitHubGetFileContent.test.ts +197 -0
  55. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +502 -0
  56. package/Tests/Types/AI/AIAgentTaskStatus.test.ts +7 -6
  57. package/Tests/Types/AI/AIChatPageContext.test.ts +0 -0
  58. package/Tests/Types/AI/AIRunStatus.test.ts +42 -0
  59. package/Tests/Types/Log/LogSeverity.test.ts +78 -0
  60. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +167 -0
  61. package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +66 -0
  62. package/Tests/UI/Utils/AIChatExport/ChatWidgetData.test.ts +319 -0
  63. package/Tests/UI/Utils/AIChatExport/ChatWidgetMarkdown.test.ts +188 -0
  64. package/Types/AI/AIAgentTaskStatus.ts +13 -0
  65. package/Types/AI/AIChatPageContext.ts +137 -0
  66. package/Types/AI/AIChatTypes.ts +44 -0
  67. package/Types/AI/AIFixReadiness.ts +46 -0
  68. package/Types/AI/AIRunStatus.ts +11 -0
  69. package/Types/Log/LogSeverity.ts +61 -0
  70. package/Types/Monitor/SnmpMonitor/SnmpVersion.ts +40 -0
  71. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +8 -2
  72. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +3 -1
  73. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +8 -2
  74. package/UI/Components/Forms/BasicForm.tsx +26 -8
  75. package/UI/Styles/Theme.css +1314 -0
  76. package/UI/Utils/AIChatExport/ChatWidgetData.ts +316 -0
  77. package/UI/Utils/AIChatExport/ChatWidgetMarkdown.ts +349 -0
  78. package/UI/Utils/AIChatExport/ConversationMarkdown.ts +177 -0
  79. package/UI/Utils/AIChatExport/MarkdownBlocks.ts +327 -0
  80. package/UI/Utils/AIChatExport/MarkdownSafety.ts +215 -0
  81. package/UI/Utils/DownloadFile.ts +54 -0
  82. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +15 -7
  83. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
  84. package/build/dist/Models/DatabaseModels/AIRun.js +38 -0
  85. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  86. package/build/dist/Models/DatabaseModels/AIRunEvent.js +31 -0
  87. package/build/dist/Models/DatabaseModels/AIRunEvent.js.map +1 -1
  88. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +225 -0
  89. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  90. package/build/dist/Models/DatabaseModels/Project.js +27 -0
  91. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  92. package/build/dist/Models/DatabaseModels/StatusPage.js +43 -0
  93. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  94. package/build/dist/Server/API/AIAgentTaskAPI.js +37 -11
  95. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  96. package/build/dist/Server/API/AIAgentTaskLogAPI.js +32 -7
  97. package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
  98. package/build/dist/Server/API/AIChatAPI.js +9 -0
  99. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  100. package/build/dist/Server/API/AIReadinessAPI.js +57 -0
  101. package/build/dist/Server/API/AIReadinessAPI.js.map +1 -0
  102. package/build/dist/Server/API/CodeFixRunAPI.js +142 -0
  103. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
  104. package/build/dist/Server/API/TelemetryExceptionAPI.js +4 -0
  105. package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -1
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784124919694-AddAITaskNumberAndRunTranscript.js +80 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784124919694-AddAITaskNumberAndRunTranscript.js.map +1 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784135099754-AllowNullAiAgentOnPullRequest.js +37 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784135099754-AllowNullAiAgentOnPullRequest.js.map +1 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784137457184-AddEnableMcpServerToStatusPage.js +23 -0
  111. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784137457184-AddEnableMcpServerToStatusPage.js.map +1 -0
  112. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784200000000-AddSnmpV3ColumnsToNetworkDeviceDiscoveryScan.js +22 -0
  113. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784200000000-AddSnmpV3ColumnsToNetworkDeviceDiscoveryScan.js.map +1 -0
  114. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  115. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  116. package/build/dist/Server/Services/AIRunEventService.js +8 -0
  117. package/build/dist/Server/Services/AIRunEventService.js.map +1 -1
  118. package/build/dist/Server/Services/AIRunService.js +29 -0
  119. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  120. package/build/dist/Server/Services/LlmProviderService.js +2 -0
  121. package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
  122. package/build/dist/Server/Services/ProjectService.js +39 -0
  123. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  124. package/build/dist/Server/Services/StatusPageService.js +81 -0
  125. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  126. package/build/dist/Server/Services/TelemetryExceptionService.js +14 -61
  127. package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
  128. package/build/dist/Server/Types/Markdown.js +8 -8
  129. package/build/dist/Server/Types/Markdown.js.map +1 -1
  130. package/build/dist/Server/Types/MarkdownSlugify.js +47 -0
  131. package/build/dist/Server/Types/MarkdownSlugify.js.map +1 -0
  132. package/build/dist/Server/Utils/AI/AIRunTranscript.js +180 -0
  133. package/build/dist/Server/Utils/AI/AIRunTranscript.js.map +1 -0
  134. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +1 -0
  135. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  136. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +103 -5
  137. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  138. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +55 -0
  139. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
  140. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +211 -0
  141. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -0
  142. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
  143. package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js +654 -0
  144. package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js.map +1 -0
  145. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +389 -0
  146. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -0
  147. package/build/dist/Server/Utils/AI/Toolbox/Index.js +19 -0
  148. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  149. package/build/dist/Server/Utils/AI/Toolbox/ScheduledMaintenanceTools.js +239 -0
  150. package/build/dist/Server/Utils/AI/Toolbox/ScheduledMaintenanceTools.js.map +1 -0
  151. package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js +19 -1
  152. package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js.map +1 -1
  153. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +439 -0
  154. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  155. package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js +1 -1
  156. package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js.map +1 -1
  157. package/build/dist/Server/Utils/LLM/LLMService.js +275 -19
  158. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  159. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +2 -11
  160. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  161. package/build/dist/Types/AI/AIAgentTaskStatus.js +12 -0
  162. package/build/dist/Types/AI/AIAgentTaskStatus.js.map +1 -1
  163. package/build/dist/Types/AI/AIChatPageContext.js +101 -0
  164. package/build/dist/Types/AI/AIChatPageContext.js.map +1 -0
  165. package/build/dist/Types/AI/AIChatTypes.js +2 -0
  166. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  167. package/build/dist/Types/AI/AIFixReadiness.js +9 -0
  168. package/build/dist/Types/AI/AIFixReadiness.js.map +1 -0
  169. package/build/dist/Types/AI/AIRunStatus.js +11 -0
  170. package/build/dist/Types/AI/AIRunStatus.js.map +1 -1
  171. package/build/dist/Types/Log/LogSeverity.js +56 -0
  172. package/build/dist/Types/Log/LogSeverity.js.map +1 -1
  173. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVersion.js +38 -0
  174. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVersion.js.map +1 -1
  175. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +9 -2
  176. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  177. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +3 -1
  178. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  179. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +9 -2
  180. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  181. package/build/dist/UI/Components/Forms/BasicForm.js +24 -6
  182. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  183. package/build/dist/UI/Utils/AIChatExport/ChatWidgetData.js +217 -0
  184. package/build/dist/UI/Utils/AIChatExport/ChatWidgetData.js.map +1 -0
  185. package/build/dist/UI/Utils/AIChatExport/ChatWidgetMarkdown.js +234 -0
  186. package/build/dist/UI/Utils/AIChatExport/ChatWidgetMarkdown.js.map +1 -0
  187. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +111 -0
  188. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -0
  189. package/build/dist/UI/Utils/AIChatExport/MarkdownBlocks.js +233 -0
  190. package/build/dist/UI/Utils/AIChatExport/MarkdownBlocks.js.map +1 -0
  191. package/build/dist/UI/Utils/AIChatExport/MarkdownSafety.js +134 -0
  192. package/build/dist/UI/Utils/AIChatExport/MarkdownSafety.js.map +1 -0
  193. package/build/dist/UI/Utils/DownloadFile.js +41 -0
  194. package/build/dist/UI/Utils/DownloadFile.js.map +1 -0
  195. package/package.json +5 -1
@@ -189,13 +189,21 @@ export default class AIAgentTaskPullRequest extends BaseModel {
189
189
  ],
190
190
  update: [],
191
191
  })
192
+ /*
193
+ * Nullable since 2026-07-15: a pull request can now originate from an AI
194
+ * chat turn, which has no AIAgent behind it (the agent record belongs to the
195
+ * autonomous fix worker). A null aiAgent therefore means "authored from
196
+ * chat", and every consumer must tolerate it — SyncPullRequestStates already
197
+ * guards on aiRunId for the same reason.
198
+ */
192
199
  @TableColumn({
193
200
  type: TableColumnType.Entity,
194
- required: true,
201
+ required: false,
195
202
  modelType: AIAgent,
196
203
  manyToOneRelationColumn: "aiAgentId",
197
204
  title: "AI Agent",
198
- description: "AI Agent that created this pull request.",
205
+ description:
206
+ "AI Agent that created this pull request. Null when it was proposed from an AI chat conversation.",
199
207
  })
200
208
  @ManyToOne(
201
209
  () => {
@@ -204,7 +212,7 @@ export default class AIAgentTaskPullRequest extends BaseModel {
204
212
  {
205
213
  cascade: false,
206
214
  eager: false,
207
- nullable: false,
215
+ nullable: true,
208
216
  onDelete: "CASCADE",
209
217
  orphanedRowAction: "nullify",
210
218
  },
@@ -231,14 +239,15 @@ export default class AIAgentTaskPullRequest extends BaseModel {
231
239
  @Index()
232
240
  @TableColumn({
233
241
  type: TableColumnType.ObjectID,
234
- required: true,
242
+ required: false,
235
243
  canReadOnRelationQuery: true,
236
244
  title: "AI Agent ID",
237
- description: "ID of the AI Agent that created this pull request.",
245
+ description:
246
+ "ID of the AI Agent that created this pull request. Null when it was proposed from an AI chat conversation.",
238
247
  })
239
248
  @Column({
240
249
  type: ColumnType.ObjectID,
241
- nullable: false,
250
+ nullable: true,
242
251
  transformer: ObjectID.getDatabaseTransformer(),
243
252
  })
244
253
  public aiAgentId?: ObjectID = undefined;
@@ -180,6 +180,43 @@ export default class AIRun extends BaseModel {
180
180
  })
181
181
  public codeFixTaskType?: CodeFixTaskType = undefined;
182
182
 
183
+ /*
184
+ * The per-project sequential task number shown as "#42" — the stable handle
185
+ * a human cites when reporting a bad run, the same role Incident.incidentNumber
186
+ * plays. Set only on CodeFix runs (the AI Tasks list): chat turns and
187
+ * investigations also live in this table but are not tasks, so numbering them
188
+ * would burn the counter on every Ask-AI message. Null therefore means "not a
189
+ * task", and also covers CodeFix rows created before this column existed —
190
+ * the backfill numbers those by age.
191
+ */
192
+ @ColumnAccessControl({
193
+ create: [],
194
+ read: [
195
+ Permission.ProjectOwner,
196
+ Permission.ProjectAdmin,
197
+ Permission.ProjectMember,
198
+ Permission.Viewer,
199
+ ],
200
+ update: [],
201
+ })
202
+ @Index()
203
+ @TableColumn({
204
+ isDefaultValueColumn: false,
205
+ required: false,
206
+ type: TableColumnType.Number,
207
+ title: "Task Number",
208
+ description:
209
+ "Per-project sequential number for this AI task (code-fix runs only).",
210
+ example: 42,
211
+ computed: true,
212
+ canReadOnRelationQuery: true,
213
+ })
214
+ @Column({
215
+ type: ColumnType.Number,
216
+ nullable: true,
217
+ })
218
+ public taskNumber?: number = undefined;
219
+
183
220
  @ColumnAccessControl({
184
221
  create: [],
185
222
  read: [
@@ -21,7 +21,10 @@ import { JSONObject } from "../../Types/JSON";
21
21
  import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
22
22
  import EnableDocumentation from "../../Types/Database/EnableDocumentation";
23
23
  import AIRunEventType from "../../Types/AI/AIRunEventType";
24
- import { AIRunEventResultSummary } from "../../Types/AI/AIChatTypes";
24
+ import {
25
+ AIRunEventContentPayload,
26
+ AIRunEventResultSummary,
27
+ } from "../../Types/AI/AIChatTypes";
25
28
 
26
29
  /*
27
30
  * One event in an AI run: an LLM call, a tool call with its validated
@@ -364,6 +367,36 @@ export default class AIRunEvent extends BaseModel {
364
367
  })
365
368
  public citationId?: string = undefined;
366
369
 
370
+ /*
371
+ * The verbatim LLM/tool content behind this event (see
372
+ * AIRunEventContentPayload). Server-only — the read ACL is empty, like
373
+ * AIRun.pausedState and AIRun.taskContext, and for the same reason: a
374
+ * code-fix run's prompts embed customer source code, whose reach is
375
+ * narrower than this table's project-member read. LlmLog redacts the same
376
+ * content for exactly this reason and continues to.
377
+ *
378
+ * Reachable only through GET /code-fix-run/logs, which gates on
379
+ * ProjectOwner/ProjectAdmin. Never widen this ACL — doing so would publish
380
+ * customer source code to every project member through the CRUD API.
381
+ */
382
+ @ColumnAccessControl({
383
+ create: [],
384
+ read: [],
385
+ update: [],
386
+ })
387
+ @TableColumn({
388
+ required: false,
389
+ type: TableColumnType.JSON,
390
+ title: "Content Payload",
391
+ description:
392
+ "Internal: the verbatim LLM prompt/response and tool output behind this event.",
393
+ })
394
+ @Column({
395
+ nullable: true,
396
+ type: ColumnType.JSON,
397
+ })
398
+ public contentPayload?: AIRunEventContentPayload = undefined;
399
+
367
400
  @ColumnAccessControl({
368
401
  create: [],
369
402
  read: [],
@@ -377,6 +377,221 @@ export default class NetworkDeviceDiscoveryScan extends BaseModel {
377
377
  })
378
378
  public snmpPort?: number = undefined;
379
379
 
380
+ /*
381
+ * SNMP v3 credentials tried against every host in the subnet. These mirror
382
+ * the flattened snmpV3* columns on NetworkDevice so a v3 scan can be imported
383
+ * into a v3 device without re-entering credentials. Like the other SNMP
384
+ * config columns above they are create+read only (update: []): a scan's
385
+ * config is fixed once it is dispatched to the probe.
386
+ */
387
+ @ColumnAccessControl({
388
+ create: [
389
+ Permission.ProjectOwner,
390
+ Permission.ProjectAdmin,
391
+ Permission.ProjectMember,
392
+ Permission.SettingsAdmin,
393
+ Permission.SettingsMember,
394
+ Permission.CreateNetworkDeviceDiscoveryScan,
395
+ ],
396
+ read: [
397
+ Permission.ProjectOwner,
398
+ Permission.ProjectAdmin,
399
+ Permission.ProjectMember,
400
+ Permission.Viewer,
401
+ Permission.SettingsAdmin,
402
+ Permission.SettingsMember,
403
+ Permission.SettingsViewer,
404
+ Permission.ReadNetworkDeviceDiscoveryScan,
405
+ ],
406
+ update: [],
407
+ })
408
+ @TableColumn({
409
+ required: false,
410
+ type: TableColumnType.ShortText,
411
+ title: "SNMP v3 Security Level",
412
+ description:
413
+ "SNMP v3 security level tried against every host: noAuthNoPriv, authNoPriv, or authPriv",
414
+ example: "authPriv",
415
+ })
416
+ @Column({
417
+ nullable: true,
418
+ type: ColumnType.ShortText,
419
+ length: ColumnLength.ShortText,
420
+ })
421
+ public snmpV3SecurityLevel?: string = undefined;
422
+
423
+ @ColumnAccessControl({
424
+ create: [
425
+ Permission.ProjectOwner,
426
+ Permission.ProjectAdmin,
427
+ Permission.ProjectMember,
428
+ Permission.SettingsAdmin,
429
+ Permission.SettingsMember,
430
+ Permission.CreateNetworkDeviceDiscoveryScan,
431
+ ],
432
+ read: [
433
+ Permission.ProjectOwner,
434
+ Permission.ProjectAdmin,
435
+ Permission.ProjectMember,
436
+ Permission.Viewer,
437
+ Permission.SettingsAdmin,
438
+ Permission.SettingsMember,
439
+ Permission.SettingsViewer,
440
+ Permission.ReadNetworkDeviceDiscoveryScan,
441
+ ],
442
+ update: [],
443
+ })
444
+ @TableColumn({
445
+ required: false,
446
+ type: TableColumnType.ShortText,
447
+ title: "SNMP v3 Username",
448
+ description: "SNMP v3 security name (username) tried against every host",
449
+ example: "monitoring",
450
+ })
451
+ @Column({
452
+ nullable: true,
453
+ type: ColumnType.ShortText,
454
+ length: ColumnLength.ShortText,
455
+ })
456
+ public snmpV3Username?: string = undefined;
457
+
458
+ @ColumnAccessControl({
459
+ create: [
460
+ Permission.ProjectOwner,
461
+ Permission.ProjectAdmin,
462
+ Permission.ProjectMember,
463
+ Permission.SettingsAdmin,
464
+ Permission.SettingsMember,
465
+ Permission.CreateNetworkDeviceDiscoveryScan,
466
+ ],
467
+ read: [
468
+ Permission.ProjectOwner,
469
+ Permission.ProjectAdmin,
470
+ Permission.ProjectMember,
471
+ Permission.Viewer,
472
+ Permission.SettingsAdmin,
473
+ Permission.SettingsMember,
474
+ Permission.SettingsViewer,
475
+ Permission.ReadNetworkDeviceDiscoveryScan,
476
+ ],
477
+ update: [],
478
+ })
479
+ @TableColumn({
480
+ required: false,
481
+ type: TableColumnType.ShortText,
482
+ title: "SNMP v3 Authentication Protocol",
483
+ description: "SNMP v3 authentication protocol: MD5, SHA, SHA256, or SHA512",
484
+ example: "SHA",
485
+ })
486
+ @Column({
487
+ nullable: true,
488
+ type: ColumnType.ShortText,
489
+ length: ColumnLength.ShortText,
490
+ })
491
+ public snmpV3AuthProtocol?: string = undefined;
492
+
493
+ @ColumnAccessControl({
494
+ create: [
495
+ Permission.ProjectOwner,
496
+ Permission.ProjectAdmin,
497
+ Permission.ProjectMember,
498
+ Permission.SettingsAdmin,
499
+ Permission.SettingsMember,
500
+ Permission.CreateNetworkDeviceDiscoveryScan,
501
+ ],
502
+ read: [
503
+ Permission.ProjectOwner,
504
+ Permission.ProjectAdmin,
505
+ Permission.ProjectMember,
506
+ Permission.Viewer,
507
+ Permission.SettingsAdmin,
508
+ Permission.SettingsMember,
509
+ Permission.SettingsViewer,
510
+ Permission.ReadNetworkDeviceDiscoveryScan,
511
+ ],
512
+ update: [],
513
+ })
514
+ @TableColumn({
515
+ required: false,
516
+ type: TableColumnType.LongText,
517
+ title: "SNMP v3 Authentication Key",
518
+ description: "SNMP v3 authentication passphrase tried against every host",
519
+ })
520
+ @Column({
521
+ nullable: true,
522
+ type: ColumnType.LongText,
523
+ })
524
+ public snmpV3AuthKey?: string = undefined;
525
+
526
+ @ColumnAccessControl({
527
+ create: [
528
+ Permission.ProjectOwner,
529
+ Permission.ProjectAdmin,
530
+ Permission.ProjectMember,
531
+ Permission.SettingsAdmin,
532
+ Permission.SettingsMember,
533
+ Permission.CreateNetworkDeviceDiscoveryScan,
534
+ ],
535
+ read: [
536
+ Permission.ProjectOwner,
537
+ Permission.ProjectAdmin,
538
+ Permission.ProjectMember,
539
+ Permission.Viewer,
540
+ Permission.SettingsAdmin,
541
+ Permission.SettingsMember,
542
+ Permission.SettingsViewer,
543
+ Permission.ReadNetworkDeviceDiscoveryScan,
544
+ ],
545
+ update: [],
546
+ })
547
+ @TableColumn({
548
+ required: false,
549
+ type: TableColumnType.ShortText,
550
+ title: "SNMP v3 Privacy Protocol",
551
+ description: "SNMP v3 privacy (encryption) protocol: DES, AES, or AES256",
552
+ example: "AES",
553
+ })
554
+ @Column({
555
+ nullable: true,
556
+ type: ColumnType.ShortText,
557
+ length: ColumnLength.ShortText,
558
+ })
559
+ public snmpV3PrivProtocol?: string = undefined;
560
+
561
+ @ColumnAccessControl({
562
+ create: [
563
+ Permission.ProjectOwner,
564
+ Permission.ProjectAdmin,
565
+ Permission.ProjectMember,
566
+ Permission.SettingsAdmin,
567
+ Permission.SettingsMember,
568
+ Permission.CreateNetworkDeviceDiscoveryScan,
569
+ ],
570
+ read: [
571
+ Permission.ProjectOwner,
572
+ Permission.ProjectAdmin,
573
+ Permission.ProjectMember,
574
+ Permission.Viewer,
575
+ Permission.SettingsAdmin,
576
+ Permission.SettingsMember,
577
+ Permission.SettingsViewer,
578
+ Permission.ReadNetworkDeviceDiscoveryScan,
579
+ ],
580
+ update: [],
581
+ })
582
+ @TableColumn({
583
+ required: false,
584
+ type: TableColumnType.LongText,
585
+ title: "SNMP v3 Privacy Key",
586
+ description:
587
+ "SNMP v3 privacy (encryption) passphrase tried against every host",
588
+ })
589
+ @Column({
590
+ nullable: true,
591
+ type: ColumnType.LongText,
592
+ })
593
+ public snmpV3PrivKey?: string = undefined;
594
+
380
595
  @ColumnAccessControl({
381
596
  create: [],
382
597
  read: [
@@ -832,6 +832,31 @@ export default class Project extends TenantModel {
832
832
  })
833
833
  public incidentEpisodeCounter?: number = undefined;
834
834
 
835
+ /*
836
+ * Numbers AI code-fix tasks only. Chat and investigation runs share the
837
+ * AIRun table but are not tasks, so they never draw from this counter —
838
+ * see AIRunService.onBeforeCreate.
839
+ */
840
+ @ColumnAccessControl({
841
+ create: [],
842
+ read: [],
843
+ update: [],
844
+ })
845
+ @TableColumn({
846
+ type: TableColumnType.Number,
847
+ isDefaultValueColumn: true,
848
+ required: true,
849
+ hideColumnInDocumentation: true,
850
+ computed: true,
851
+ })
852
+ @Column({
853
+ type: ColumnType.Number,
854
+ nullable: false,
855
+ unique: false,
856
+ default: 0,
857
+ })
858
+ public aiRunCounter?: number = undefined;
859
+
835
860
  @ColumnAccessControl({
836
861
  create: [],
837
862
  read: [],
@@ -1063,6 +1063,48 @@ export default class StatusPage extends BaseModel {
1063
1063
  })
1064
1064
  public isPublicStatusPage?: boolean = undefined;
1065
1065
 
1066
+ @ColumnAccessControl({
1067
+ create: [
1068
+ Permission.ProjectOwner,
1069
+ Permission.ProjectAdmin,
1070
+ Permission.ProjectMember,
1071
+ Permission.StatusPageAdmin,
1072
+ Permission.StatusPageMember,
1073
+ Permission.CreateProjectStatusPage,
1074
+ ],
1075
+ read: [
1076
+ Permission.ProjectOwner,
1077
+ Permission.ProjectAdmin,
1078
+ Permission.ProjectMember,
1079
+ Permission.Viewer,
1080
+ Permission.StatusPageAdmin,
1081
+ Permission.StatusPageMember,
1082
+ Permission.StatusPageViewer,
1083
+ Permission.ReadProjectStatusPage,
1084
+ ],
1085
+ update: [
1086
+ Permission.ProjectOwner,
1087
+ Permission.ProjectAdmin,
1088
+ Permission.ProjectMember,
1089
+ Permission.StatusPageAdmin,
1090
+ Permission.StatusPageMember,
1091
+ Permission.EditProjectStatusPage,
1092
+ ],
1093
+ })
1094
+ @TableColumn({
1095
+ isDefaultValueColumn: true,
1096
+ type: TableColumnType.Boolean,
1097
+ title: "Enable MCP Server",
1098
+ description:
1099
+ "Can AI agents read this status page over the public OneUptime MCP server? This does not affect the status page website, its RSS feed, or its public JSON API.",
1100
+ defaultValue: true,
1101
+ })
1102
+ @Column({
1103
+ type: ColumnType.Boolean,
1104
+ default: true,
1105
+ })
1106
+ public enableMcpServer?: boolean = undefined;
1107
+
1066
1108
  @ColumnAccessControl({
1067
1109
  create: [
1068
1110
  Permission.ProjectOwner,
@@ -196,6 +196,7 @@ export default class AIAgentTaskAPI {
196
196
  const validStatuses: Array<AIAgentTaskStatus> = [
197
197
  AIAgentTaskStatus.InProgress,
198
198
  AIAgentTaskStatus.Completed,
199
+ AIAgentTaskStatus.NoFixFound,
199
200
  AIAgentTaskStatus.Error,
200
201
  ];
201
202
 
@@ -249,16 +250,35 @@ export default class AIAgentTaskAPI {
249
250
  },
250
251
  });
251
252
  } else {
252
- const toStatus: AIRunStatus =
253
- status === AIAgentTaskStatus.Completed
254
- ? AIRunStatus.Completed
255
- : AIRunStatus.Error;
253
+ /*
254
+ * Agents that predate NoFixFound report a fruitless run as Error,
255
+ * so an Error report still maps straight through — those runs keep
256
+ * looking exactly as they do today until the agent is upgraded.
257
+ */
258
+ let toStatus: AIRunStatus = AIRunStatus.Error;
259
+
260
+ if (status === AIAgentTaskStatus.Completed) {
261
+ toStatus = AIRunStatus.Completed;
262
+ } else if (status === AIAgentTaskStatus.NoFixFound) {
263
+ toStatus = AIRunStatus.NoFixFound;
264
+ }
265
+
266
+ /*
267
+ * Both terminal outcomes that carry a reason store it in
268
+ * errorMessage — the column is the run's only message field, and
269
+ * every reader (the detail page, the exception page's
270
+ * statusMessage) already renders it.
271
+ */
272
+ const shouldStoreMessage: boolean =
273
+ Boolean(statusMessage) &&
274
+ (toStatus === AIRunStatus.Error ||
275
+ toStatus === AIRunStatus.NoFixFound);
256
276
 
257
277
  /*
258
- * CAS Running -> Completed/Error. Losing the race (0 rows) means
259
- * another actor already finalized the run — e.g. the sweeper
260
- * marked it Error after a heartbeat gap — and that outcome wins;
261
- * we do not clobber it or write a duplicate terminal event.
278
+ * CAS Running -> Completed/NoFixFound/Error. Losing the race (0
279
+ * rows) means another actor already finalized the run — e.g. the
280
+ * sweeper marked it Error after a heartbeat gap — and that outcome
281
+ * wins; we do not clobber it or write a duplicate terminal event.
262
282
  */
263
283
  const transitionedCount: number =
264
284
  await AIRunService.attemptStatusTransition({
@@ -268,7 +288,7 @@ export default class AIAgentTaskAPI {
268
288
  status: toStatus,
269
289
  completedAt: OneUptimeDate.getCurrentDate(),
270
290
  lastHeartbeatAt: OneUptimeDate.getCurrentDate(),
271
- ...(toStatus === AIRunStatus.Error && statusMessage
291
+ ...(shouldStoreMessage
272
292
  ? { errorMessage: statusMessage }
273
293
  : {}),
274
294
  },
@@ -278,10 +298,16 @@ export default class AIAgentTaskAPI {
278
298
  await AIRunEventService.appendEventToRun({
279
299
  projectId: existingRun.projectId,
280
300
  aiRunId: runId,
301
+ /*
302
+ * Only a genuine failure closes the event trail with
303
+ * RunFailed. A NoFixFound run ran to completion and reported
304
+ * a conclusion, so it closes with RunCompleted and carries
305
+ * the "no fix" reason in resultSummary.
306
+ */
281
307
  eventType:
282
- toStatus === AIRunStatus.Completed
283
- ? AIRunEventType.RunCompleted
284
- : AIRunEventType.RunFailed,
308
+ toStatus === AIRunStatus.Error
309
+ ? AIRunEventType.RunFailed
310
+ : AIRunEventType.RunCompleted,
285
311
  ...(statusMessage
286
312
  ? { resultSummary: { message: statusMessage } }
287
313
  : {}),
@@ -120,6 +120,31 @@ export default class AIAgentTaskLogAPI {
120
120
  );
121
121
  }
122
122
 
123
+ /*
124
+ * Optional verbatim tool detail (see TaskLogger.toolCall): the
125
+ * arguments as executed and the full output the model saw, recorded
126
+ * on the run's transcript for the Logs page. Absent it — an older
127
+ * agent — behaviour is exactly as before.
128
+ *
129
+ * The event type stays ProgressLog even when the detail is present.
130
+ * That is deliberate, not laziness: the Overview's ChatActivityFeed
131
+ * renders a ProgressLog by printing resultSummary.message, but
132
+ * renders a ToolCallCompleted by trying to COMPLETE a matching
133
+ * running step from an earlier ToolCallStarted — an event the
134
+ * code-fix path never emits. Typing these as ToolCallCompleted
135
+ * therefore matched nothing and silently erased every tool line from
136
+ * the Overview feed. The payload rides on the same event instead.
137
+ */
138
+ const toolName: string | undefined = data["toolName"] as
139
+ | string
140
+ | undefined;
141
+ const toolArguments: JSONObject | undefined = data[
142
+ "toolArguments"
143
+ ] as JSONObject | undefined;
144
+ const toolResult: string | undefined = data["toolResult"] as
145
+ | string
146
+ | undefined;
147
+
123
148
  await AIRunEventService.appendEventToRun({
124
149
  projectId: existingRun.projectId,
125
150
  aiRunId: runId,
@@ -128,6 +153,30 @@ export default class AIAgentTaskLogAPI {
128
153
  message: message,
129
154
  severity: severity,
130
155
  },
156
+ ...(toolName ? { toolName: toolName } : {}),
157
+ /*
158
+ * toolArguments (the column) is deliberately NOT written: its read
159
+ * ACL is project-member-wide, and a write_file call's arguments are
160
+ * the file's full new content. The same arguments go onto
161
+ * contentPayload below, whose read ACL is empty and which only the
162
+ * owner/admin-gated logs endpoint returns.
163
+ */
164
+ ...(toolName
165
+ ? {
166
+ contentPayload: {
167
+ ...(toolResult !== undefined
168
+ ? { toolResult: toolResult }
169
+ : {}),
170
+ ...(toolArguments
171
+ ? {
172
+ responseToolCalls: [
173
+ { name: toolName, arguments: toolArguments },
174
+ ],
175
+ }
176
+ : {}),
177
+ },
178
+ }
179
+ : {}),
131
180
  });
132
181
 
133
182
  /* A progress report proves the agent is alive — refresh the heartbeat. */
@@ -21,6 +21,10 @@ import SubscriptionPlan, {
21
21
  import { IsBillingEnabled, getAllEnvVars } from "../EnvironmentConfig";
22
22
  import AIChatMessageRole from "../../Types/AI/AIChatMessageRole";
23
23
  import AIChatMessageStatus from "../../Types/AI/AIChatMessageStatus";
24
+ import {
25
+ AIChatPageContext,
26
+ AIChatPageContextHelper,
27
+ } from "../../Types/AI/AIChatPageContext";
24
28
  import AIChatPermissionMode, {
25
29
  AIChatPermissionModeHelper,
26
30
  } from "../../Types/AI/AIChatPermissionMode";
@@ -143,6 +147,16 @@ router.post(
143
147
  ? (req.body["permissionMode"] as AIChatPermissionMode)
144
148
  : undefined;
145
149
 
150
+ /*
151
+ * Optional page context — what the user was looking at when they asked
152
+ * (an incident, a monitor, the logs explorer, …). It is a hint for the
153
+ * system prompt, so an invalid payload is dropped, never an error.
154
+ */
155
+ const pageContext: AIChatPageContext | undefined =
156
+ AIChatPageContextHelper.sanitize(
157
+ req.body["pageContext"] as JSONObject | undefined,
158
+ );
159
+
146
160
  // Plan gate: custom endpoints get no automatic billing check.
147
161
  if (
148
162
  IsBillingEnabled &&
@@ -435,6 +449,7 @@ router.post(
435
449
  aiRunId: createdRun.id!,
436
450
  llmProviderId: effectiveLlmProviderId,
437
451
  permissionMode: effectivePermissionMode,
452
+ pageContext: pageContext,
438
453
  props: props,
439
454
  }).catch((error: Error) => {
440
455
  logger.error(`AI chat turn crashed: ${error.message}`);
@@ -498,6 +513,7 @@ router.post(
498
513
  return {
499
514
  id: provider.id?.toString(),
500
515
  name: provider.name,
516
+ description: provider.description || null,
501
517
  llmType: provider.llmType?.toString() || null,
502
518
  modelName: provider.modelName || null,
503
519
  isDefault: provider.isDefault || false,