@kb-labs/rest-api-app 1.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.
Files changed (255) hide show
  1. package/.kb/agents/sessions/session-1771531145393-ws3uh6q/turns.json +42 -0
  2. package/.kb/agents/sessions/session-1771548930486-ui6rtvm/turns.json +33 -0
  3. package/.kb/agents/sessions/session-1771549691485-nibqroq/turns.json +133 -0
  4. package/.kb/agents/sessions/session-1771550943182-dkwqdjc/turns.json +130 -0
  5. package/.kb/agents/sessions/session-1771551564182-cr4bwzn/turns.json +349 -0
  6. package/.kb/agents/sessions/session-1771552401370-g4ztwd1/turns.json +206 -0
  7. package/.kb/commit/current/plan.json +248 -0
  8. package/.kb/commit/current/status.json +472 -0
  9. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.d.ts +10 -0
  10. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js +215 -0
  11. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js.map +1 -0
  12. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.d.ts +10 -0
  13. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js +271 -0
  14. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js.map +1 -0
  15. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.d.ts +10 -0
  16. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js +230 -0
  17. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js.map +1 -0
  18. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.d.ts +10 -0
  19. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js +228 -0
  20. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js.map +1 -0
  21. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.d.ts +11 -0
  22. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js +281 -0
  23. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js.map +1 -0
  24. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.d.ts +10 -0
  25. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js +266 -0
  26. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js.map +1 -0
  27. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.d.ts +11 -0
  28. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js +284 -0
  29. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js.map +1 -0
  30. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/flags-WLdpSZl4.d.ts +77 -0
  31. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.d.ts +2 -0
  32. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js +441 -0
  33. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js.map +1 -0
  34. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.d.ts +196 -0
  35. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js +441 -0
  36. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js.map +1 -0
  37. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.d.ts +19 -0
  38. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js +48 -0
  39. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js.map +1 -0
  40. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.d.ts +6 -0
  41. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js +170 -0
  42. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js.map +1 -0
  43. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.d.ts +12 -0
  44. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js +52 -0
  45. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js.map +1 -0
  46. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.d.ts +22 -0
  47. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js +52 -0
  48. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js.map +1 -0
  49. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.d.ts +13 -0
  50. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js +52 -0
  51. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js.map +1 -0
  52. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.d.ts +9 -0
  53. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js +43 -0
  54. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js.map +1 -0
  55. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.d.ts +26 -0
  56. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js +63 -0
  57. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js.map +1 -0
  58. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.d.ts +9 -0
  59. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js +46 -0
  60. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js.map +1 -0
  61. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.d.ts +16 -0
  62. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js +58 -0
  63. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js.map +1 -0
  64. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.d.ts +9 -0
  65. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js +46 -0
  66. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js.map +1 -0
  67. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.d.ts +11 -0
  68. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js +50 -0
  69. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js.map +1 -0
  70. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.d.ts +7 -0
  71. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js +39 -0
  72. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js.map +1 -0
  73. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.d.ts +10 -0
  74. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js +46 -0
  75. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js.map +1 -0
  76. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.d.ts +13 -0
  77. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js +47 -0
  78. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js.map +1 -0
  79. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.d.ts +14 -0
  80. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js +53 -0
  81. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js.map +1 -0
  82. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.d.ts +13 -0
  83. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js +54 -0
  84. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js.map +1 -0
  85. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.d.ts +12 -0
  86. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js +51 -0
  87. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js.map +1 -0
  88. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.d.ts +17 -0
  89. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js +133 -0
  90. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js.map +1 -0
  91. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.d.ts +11 -0
  92. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js +46 -0
  93. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js.map +1 -0
  94. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.d.ts +10 -0
  95. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js +215 -0
  96. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js.map +1 -0
  97. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.d.ts +10 -0
  98. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js +271 -0
  99. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js.map +1 -0
  100. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.d.ts +10 -0
  101. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js +230 -0
  102. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js.map +1 -0
  103. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.d.ts +10 -0
  104. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js +228 -0
  105. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js.map +1 -0
  106. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.d.ts +11 -0
  107. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js +281 -0
  108. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js.map +1 -0
  109. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.d.ts +10 -0
  110. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js +266 -0
  111. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js.map +1 -0
  112. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.d.ts +11 -0
  113. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js +284 -0
  114. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js.map +1 -0
  115. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/flags-WLdpSZl4.d.ts +77 -0
  116. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.d.ts +2 -0
  117. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js +441 -0
  118. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js.map +1 -0
  119. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.d.ts +196 -0
  120. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js +441 -0
  121. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js.map +1 -0
  122. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.d.ts +19 -0
  123. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js +48 -0
  124. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js.map +1 -0
  125. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.d.ts +6 -0
  126. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js +170 -0
  127. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js.map +1 -0
  128. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.d.ts +12 -0
  129. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js +52 -0
  130. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js.map +1 -0
  131. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.d.ts +22 -0
  132. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js +52 -0
  133. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js.map +1 -0
  134. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.d.ts +13 -0
  135. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js +52 -0
  136. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js.map +1 -0
  137. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.d.ts +9 -0
  138. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js +43 -0
  139. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js.map +1 -0
  140. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.d.ts +26 -0
  141. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js +63 -0
  142. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js.map +1 -0
  143. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.d.ts +9 -0
  144. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js +46 -0
  145. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js.map +1 -0
  146. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.d.ts +16 -0
  147. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js +58 -0
  148. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js.map +1 -0
  149. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.d.ts +9 -0
  150. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js +46 -0
  151. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js.map +1 -0
  152. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.d.ts +11 -0
  153. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js +50 -0
  154. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js.map +1 -0
  155. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.d.ts +7 -0
  156. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js +39 -0
  157. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js.map +1 -0
  158. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.d.ts +10 -0
  159. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js +46 -0
  160. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js.map +1 -0
  161. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.d.ts +13 -0
  162. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js +47 -0
  163. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js.map +1 -0
  164. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.d.ts +14 -0
  165. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js +53 -0
  166. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js.map +1 -0
  167. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.d.ts +13 -0
  168. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js +54 -0
  169. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js.map +1 -0
  170. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.d.ts +12 -0
  171. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js +51 -0
  172. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js.map +1 -0
  173. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.d.ts +17 -0
  174. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js +133 -0
  175. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js.map +1 -0
  176. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.d.ts +11 -0
  177. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js +46 -0
  178. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js.map +1 -0
  179. package/README.md +54 -0
  180. package/eslint.config.js +23 -0
  181. package/package.json +72 -0
  182. package/src/.kb/agents/sessions/session-1773470583796-ximqnfk/kpi-baseline.json +17 -0
  183. package/src/.kb/memory/sessions/session-1773470583796-ximqnfk/fact-sheet.json +1 -0
  184. package/src/bootstrap.ts +233 -0
  185. package/src/diagnostics/header-debug.ts +37 -0
  186. package/src/events/hub.ts +60 -0
  187. package/src/events/index.ts +1 -0
  188. package/src/index.ts +13 -0
  189. package/src/manifest.ts +21 -0
  190. package/src/middleware/__tests__/cache.spec.ts +184 -0
  191. package/src/middleware/__tests__/envelope.spec.ts +268 -0
  192. package/src/middleware/__tests__/metrics.redis.spec.ts +64 -0
  193. package/src/middleware/__tests__/rate-limit.spec.ts +283 -0
  194. package/src/middleware/__tests__/request-id.spec.ts +160 -0
  195. package/src/middleware/cache.ts +67 -0
  196. package/src/middleware/envelope.ts +136 -0
  197. package/src/middleware/error-guard.ts +69 -0
  198. package/src/middleware/index.ts +37 -0
  199. package/src/middleware/metrics.ts +810 -0
  200. package/src/middleware/mock-mode.ts +44 -0
  201. package/src/middleware/prom-metrics.ts +284 -0
  202. package/src/middleware/rate-limit-routes.ts +73 -0
  203. package/src/middleware/rate-limit.ts +72 -0
  204. package/src/middleware/request-id.ts +41 -0
  205. package/src/middleware/request-timeout.ts +69 -0
  206. package/src/middleware/security-headers.ts +24 -0
  207. package/src/middleware/startup-guard.ts +107 -0
  208. package/src/observability/service-contract.ts +192 -0
  209. package/src/plugins/index.ts +118 -0
  210. package/src/routes/__tests__/adapters-date-helpers.spec.ts +332 -0
  211. package/src/routes/__tests__/adapters.spec.ts +680 -0
  212. package/src/routes/__tests__/cache.spec.ts +264 -0
  213. package/src/routes/__tests__/events.spec.ts +434 -0
  214. package/src/routes/__tests__/health.spec.ts +414 -0
  215. package/src/routes/__tests__/logs.spec.ts +494 -0
  216. package/src/routes/__tests__/observability.spec.ts +392 -0
  217. package/src/routes/__tests__/plugins.spec.ts +931 -0
  218. package/src/routes/__tests__/workflow-management.spec.ts +698 -0
  219. package/src/routes/__tests__/workflows.spec.ts +204 -0
  220. package/src/routes/adapter-call.ts +220 -0
  221. package/src/routes/adapters.ts +1206 -0
  222. package/src/routes/analytics.ts +328 -0
  223. package/src/routes/cache.ts +104 -0
  224. package/src/routes/debug-routes.ts +95 -0
  225. package/src/routes/events.ts +115 -0
  226. package/src/routes/health.ts +348 -0
  227. package/src/routes/hello.ts +47 -0
  228. package/src/routes/index.ts +395 -0
  229. package/src/routes/jobs.ts +253 -0
  230. package/src/routes/logs.ts +718 -0
  231. package/src/routes/metrics.ts +120 -0
  232. package/src/routes/observability.ts +1388 -0
  233. package/src/routes/openapi.ts +101 -0
  234. package/src/routes/platform.ts +143 -0
  235. package/src/routes/plugins.ts +998 -0
  236. package/src/routes/readiness.ts +83 -0
  237. package/src/routes/workflow-management.ts +469 -0
  238. package/src/routes/workflows.ts +256 -0
  239. package/src/server.ts +203 -0
  240. package/src/services/historical-metrics.ts +496 -0
  241. package/src/services/incident-analyzer.ts +289 -0
  242. package/src/services/incident-detector.ts +691 -0
  243. package/src/services/incident-schema.sql +76 -0
  244. package/src/services/incident-storage.ts +593 -0
  245. package/src/services/system-metrics-collector.ts +244 -0
  246. package/src/types/fastify.d.ts +58 -0
  247. package/src/utils/__tests__/sse-auth.spec.ts +113 -0
  248. package/src/utils/path-helpers.ts +15 -0
  249. package/src/utils/repo.ts +42 -0
  250. package/src/utils/schema.ts +20 -0
  251. package/src/utils/sse-auth.ts +81 -0
  252. package/test-sandbox.sh +105 -0
  253. package/tsconfig.build.json +15 -0
  254. package/tsconfig.json +9 -0
  255. package/tsup.config.ts +18 -0
@@ -0,0 +1,691 @@
1
+ /**
2
+ * @module @kb-labs/rest-api-app/services/incident-detector
3
+ * Automatic incident detection based on metrics thresholds
4
+ */
5
+
6
+ import type { IncidentStorage, IncidentCreatePayload, IncidentSeverity, IncidentType, RelatedData } from './incident-storage';
7
+ import { metricsCollector } from '../middleware/metrics.js';
8
+ import { platform } from '@kb-labs/core-runtime';
9
+ import type { LogLevel } from '@kb-labs/core-platform';
10
+
11
+ /**
12
+ * Detection thresholds configuration
13
+ */
14
+ export interface DetectionThresholds {
15
+ /** Error rate threshold (percentage, default: 5%) */
16
+ errorRateWarning: number;
17
+ /** Error rate critical threshold (percentage, default: 10%) */
18
+ errorRateCritical: number;
19
+ /** P99 latency warning threshold (ms, default: 2000) */
20
+ latencyP99Warning: number;
21
+ /** P99 latency critical threshold (ms, default: 5000) */
22
+ latencyP99Critical: number;
23
+ /** P95 latency warning threshold (ms, default: 1000) */
24
+ latencyP95Warning: number;
25
+ /** Minimum requests before triggering (default: 10) */
26
+ minRequestsForDetection: number;
27
+ /** Plugin error rate threshold (percentage, default: 10%) */
28
+ pluginErrorRateWarning: number;
29
+ /** Plugin error rate critical threshold (percentage, default: 25%) */
30
+ pluginErrorRateCritical: number;
31
+ }
32
+
33
+ /**
34
+ * Detector configuration
35
+ */
36
+ export interface IncidentDetectorConfig {
37
+ /** Detection interval in milliseconds (default: 30000 - 30s) */
38
+ intervalMs: number;
39
+ /** Thresholds for detection */
40
+ thresholds: DetectionThresholds;
41
+ /** Cooldown period before creating same incident again (ms, default: 5 minutes) */
42
+ cooldownMs: number;
43
+ /** Enable debug logging */
44
+ debug: boolean;
45
+ }
46
+
47
+ const DEFAULT_THRESHOLDS: DetectionThresholds = {
48
+ errorRateWarning: 5,
49
+ errorRateCritical: 10,
50
+ latencyP99Warning: 2000,
51
+ latencyP99Critical: 5000,
52
+ latencyP95Warning: 1000,
53
+ minRequestsForDetection: 10,
54
+ pluginErrorRateWarning: 10,
55
+ pluginErrorRateCritical: 25,
56
+ };
57
+
58
+ const DEFAULT_CONFIG: IncidentDetectorConfig = {
59
+ intervalMs: 30000, // 30 seconds
60
+ thresholds: DEFAULT_THRESHOLDS,
61
+ cooldownMs: 5 * 60 * 1000, // 5 minutes
62
+ debug: false,
63
+ };
64
+
65
+ /**
66
+ * Track recently created incidents to avoid duplicates
67
+ */
68
+ interface RecentIncident {
69
+ type: IncidentType;
70
+ key: string; // unique key for deduplication (e.g., "error_rate" or "plugin:@kb-labs/foo")
71
+ timestamp: number;
72
+ }
73
+
74
+ /**
75
+ * Automatic incident detector service
76
+ *
77
+ * Periodically analyzes metrics and creates incidents when thresholds are exceeded.
78
+ * Includes deduplication to avoid spamming with repeated incidents.
79
+ */
80
+ export class IncidentDetector {
81
+ private incidentStorage: IncidentStorage;
82
+ private config: IncidentDetectorConfig;
83
+ private logger: Console | any;
84
+ private intervalHandle: NodeJS.Timeout | null = null;
85
+ private recentIncidents: RecentIncident[] = [];
86
+ private isRunning = false;
87
+
88
+ // Metrics history for "before" comparison (last 10 snapshots)
89
+ private metricsHistory: Array<{
90
+ timestamp: number;
91
+ errorRate: number;
92
+ avgLatency: number;
93
+ totalRequests: number;
94
+ }> = [];
95
+
96
+ constructor(
97
+ incidentStorage: IncidentStorage,
98
+ config: Partial<IncidentDetectorConfig> = {},
99
+ logger: Console | any = console
100
+ ) {
101
+ this.incidentStorage = incidentStorage;
102
+ this.config = {
103
+ ...DEFAULT_CONFIG,
104
+ ...config,
105
+ thresholds: { ...DEFAULT_THRESHOLDS, ...config.thresholds },
106
+ };
107
+ this.logger = logger;
108
+ }
109
+
110
+ /**
111
+ * Start automatic detection
112
+ */
113
+ start(): void {
114
+ if (this.isRunning) {
115
+ this.log('warn', 'Detector already running');
116
+ return;
117
+ }
118
+
119
+ this.isRunning = true;
120
+ this.log('info', 'Starting incident detector', {
121
+ intervalMs: this.config.intervalMs,
122
+ thresholds: this.config.thresholds,
123
+ });
124
+
125
+ // Run immediately once
126
+ this.runDetection().catch(err => {
127
+ this.log('error', 'Initial detection failed', { error: err.message });
128
+ });
129
+
130
+ // Schedule periodic detection
131
+ this.intervalHandle = setInterval(() => {
132
+ this.runDetection().catch(err => {
133
+ this.log('error', 'Detection cycle failed', { error: err.message });
134
+ });
135
+ }, this.config.intervalMs);
136
+ }
137
+
138
+ /**
139
+ * Stop automatic detection
140
+ */
141
+ stop(): void {
142
+ if (this.intervalHandle) {
143
+ clearInterval(this.intervalHandle);
144
+ this.intervalHandle = null;
145
+ }
146
+ this.isRunning = false;
147
+ this.log('info', 'Incident detector stopped');
148
+ }
149
+
150
+ /**
151
+ * Run a single detection cycle
152
+ */
153
+ async runDetection(): Promise<void> {
154
+ const metrics = metricsCollector.getMetrics();
155
+ const now = Date.now();
156
+
157
+ // Save current metrics to history (for "before" comparison)
158
+ const totalErrors = (metrics.requests.clientErrors ?? 0) + (metrics.requests.serverErrors ?? 0);
159
+ const errorRate = metrics.requests.total > 0
160
+ ? (totalErrors / metrics.requests.total) * 100
161
+ : 0;
162
+
163
+ this.metricsHistory.push({
164
+ timestamp: now,
165
+ errorRate,
166
+ avgLatency: metrics.latency.average ?? 0,
167
+ totalRequests: metrics.requests.total,
168
+ });
169
+
170
+ // Keep only last 10 snapshots (5 minutes history if running every 30s)
171
+ if (this.metricsHistory.length > 10) {
172
+ this.metricsHistory.shift();
173
+ }
174
+
175
+ // Clean up old recent incidents (outside cooldown period)
176
+ this.recentIncidents = this.recentIncidents.filter(
177
+ ri => now - ri.timestamp < this.config.cooldownMs
178
+ );
179
+
180
+ // Skip if not enough requests
181
+ if (metrics.requests.total < this.config.thresholds.minRequestsForDetection) {
182
+ this.log('debug', 'Not enough requests for detection', {
183
+ total: metrics.requests.total,
184
+ min: this.config.thresholds.minRequestsForDetection,
185
+ });
186
+ return;
187
+ }
188
+
189
+ // Detect error rate issues
190
+ await this.detectErrorRate(metrics, now);
191
+
192
+ // Detect latency issues
193
+ await this.detectLatencyIssues(metrics, now);
194
+
195
+ // Detect plugin failures
196
+ await this.detectPluginFailures(metrics, now);
197
+
198
+ this.log('debug', 'Detection cycle complete', {
199
+ recentIncidentsCount: this.recentIncidents.length,
200
+ });
201
+ }
202
+
203
+ /**
204
+ * Detect high error rate
205
+ */
206
+ private async detectErrorRate(metrics: any, now: number): Promise<void> {
207
+ const totalErrors = (metrics.requests.clientErrors ?? 0) + (metrics.requests.serverErrors ?? 0);
208
+ const errorRate = metrics.requests.total > 0
209
+ ? (totalErrors / metrics.requests.total) * 100
210
+ : 0;
211
+
212
+ const key = 'error_rate';
213
+
214
+ if (this.isInCooldown(key)) {
215
+ return;
216
+ }
217
+
218
+ let severity: IncidentSeverity | null = null;
219
+ let title = '';
220
+ let details = '';
221
+
222
+ if (errorRate >= this.config.thresholds.errorRateCritical) {
223
+ severity = 'critical';
224
+ title = `Critical Error Rate: ${errorRate.toFixed(1)}%`;
225
+ details = `Error rate has exceeded critical threshold of ${this.config.thresholds.errorRateCritical}%. ` +
226
+ `Current: ${errorRate.toFixed(2)}% (${totalErrors}/${metrics.requests.total} requests). ` +
227
+ `Client errors: ${metrics.requests.clientErrors ?? 0}, Server errors: ${metrics.requests.serverErrors ?? 0}.`;
228
+ } else if (errorRate >= this.config.thresholds.errorRateWarning) {
229
+ severity = 'warning';
230
+ title = `High Error Rate: ${errorRate.toFixed(1)}%`;
231
+ details = `Error rate has exceeded warning threshold of ${this.config.thresholds.errorRateWarning}%. ` +
232
+ `Current: ${errorRate.toFixed(2)}% (${totalErrors}/${metrics.requests.total} requests).`;
233
+ }
234
+
235
+ if (severity) {
236
+ await this.createIncident({
237
+ type: 'error_rate',
238
+ severity,
239
+ title,
240
+ details,
241
+ metadata: {
242
+ errorRate,
243
+ totalRequests: metrics.requests.total,
244
+ clientErrors: metrics.requests.clientErrors,
245
+ serverErrors: metrics.requests.serverErrors,
246
+ threshold: severity === 'critical'
247
+ ? this.config.thresholds.errorRateCritical
248
+ : this.config.thresholds.errorRateWarning,
249
+ },
250
+ }, key, now);
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Detect latency spikes
256
+ */
257
+ private async detectLatencyIssues(metrics: any, now: number): Promise<void> {
258
+ // We need to fetch p99 from histogram data
259
+ // For now, use average as approximation if p99 not available
260
+ const avgLatency = metrics.latency.average ?? 0;
261
+
262
+ // Try to calculate p99 from histogram if available
263
+ let p99 = avgLatency * 3; // rough approximation
264
+ let p95 = avgLatency * 2;
265
+
266
+ if (metrics.latency.histogram && metrics.latency.histogram.length > 0) {
267
+ // Sort by max latency and take top percentiles
268
+ const sorted = [...metrics.latency.histogram].sort((a: any, b: any) => b.max - a.max);
269
+ if (sorted.length > 0) {
270
+ p99 = sorted[0]?.max ?? p99;
271
+ p95 = sorted[Math.floor(sorted.length * 0.05)]?.max ?? p95;
272
+ }
273
+ }
274
+
275
+ const keyP99 = 'latency_p99';
276
+ const keyP95 = 'latency_p95';
277
+
278
+ // Check P99 latency
279
+ if (!this.isInCooldown(keyP99)) {
280
+ let severity: IncidentSeverity | null = null;
281
+ let title = '';
282
+ let details = '';
283
+
284
+ if (p99 >= this.config.thresholds.latencyP99Critical) {
285
+ severity = 'critical';
286
+ title = `Critical P99 Latency: ${p99.toFixed(0)}ms`;
287
+ details = `P99 latency has exceeded critical threshold of ${this.config.thresholds.latencyP99Critical}ms. ` +
288
+ `Current P99: ${p99.toFixed(0)}ms, Average: ${avgLatency.toFixed(0)}ms. ` +
289
+ `This indicates severe performance degradation affecting tail latencies.`;
290
+ } else if (p99 >= this.config.thresholds.latencyP99Warning) {
291
+ severity = 'warning';
292
+ title = `High P99 Latency: ${p99.toFixed(0)}ms`;
293
+ details = `P99 latency has exceeded warning threshold of ${this.config.thresholds.latencyP99Warning}ms. ` +
294
+ `Current P99: ${p99.toFixed(0)}ms, Average: ${avgLatency.toFixed(0)}ms.`;
295
+ }
296
+
297
+ if (severity) {
298
+ await this.createIncident({
299
+ type: 'latency_spike',
300
+ severity,
301
+ title,
302
+ details,
303
+ metadata: {
304
+ p99,
305
+ p95,
306
+ average: avgLatency,
307
+ threshold: severity === 'critical'
308
+ ? this.config.thresholds.latencyP99Critical
309
+ : this.config.thresholds.latencyP99Warning,
310
+ },
311
+ }, keyP99, now);
312
+ }
313
+ }
314
+
315
+ // Check P95 latency (separate incident)
316
+ if (!this.isInCooldown(keyP95) && p95 >= this.config.thresholds.latencyP95Warning) {
317
+ await this.createIncident({
318
+ type: 'latency_spike',
319
+ severity: 'warning',
320
+ title: `Elevated P95 Latency: ${p95.toFixed(0)}ms`,
321
+ details: `P95 latency has exceeded threshold of ${this.config.thresholds.latencyP95Warning}ms. ` +
322
+ `Current P95: ${p95.toFixed(0)}ms. Consider investigating slow endpoints.`,
323
+ metadata: {
324
+ p95,
325
+ average: avgLatency,
326
+ threshold: this.config.thresholds.latencyP95Warning,
327
+ },
328
+ }, keyP95, now);
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Detect plugin failures
334
+ */
335
+ private async detectPluginFailures(metrics: any, now: number): Promise<void> {
336
+ if (!metrics.perPlugin || !Array.isArray(metrics.perPlugin)) {
337
+ return;
338
+ }
339
+
340
+ for (const plugin of metrics.perPlugin) {
341
+ if (!plugin.pluginId || plugin.requests < 5) {
342
+ continue; // Skip plugins with too few requests
343
+ }
344
+
345
+ const errorRate = plugin.requests > 0
346
+ ? ((plugin.errors ?? 0) / plugin.requests) * 100
347
+ : 0;
348
+
349
+ const key = `plugin:${plugin.pluginId}`;
350
+
351
+ if (this.isInCooldown(key)) {
352
+ continue;
353
+ }
354
+
355
+ let severity: IncidentSeverity | null = null;
356
+ let title = '';
357
+ let details = '';
358
+
359
+ if (errorRate >= this.config.thresholds.pluginErrorRateCritical) {
360
+ severity = 'critical';
361
+ title = `Plugin Failure: ${plugin.pluginId}`;
362
+ details = `Plugin ${plugin.pluginId} has critical error rate of ${errorRate.toFixed(1)}% ` +
363
+ `(${plugin.errors ?? 0}/${plugin.requests} requests). ` +
364
+ `This exceeds the critical threshold of ${this.config.thresholds.pluginErrorRateCritical}%.`;
365
+ } else if (errorRate >= this.config.thresholds.pluginErrorRateWarning) {
366
+ severity = 'warning';
367
+ title = `Plugin Issues: ${plugin.pluginId}`;
368
+ details = `Plugin ${plugin.pluginId} has elevated error rate of ${errorRate.toFixed(1)}% ` +
369
+ `(${plugin.errors ?? 0}/${plugin.requests} requests).`;
370
+ }
371
+
372
+ if (severity) {
373
+ await this.createIncident({
374
+ type: 'plugin_failure',
375
+ severity,
376
+ title,
377
+ details,
378
+ affectedServices: [plugin.pluginId],
379
+ metadata: {
380
+ pluginId: plugin.pluginId,
381
+ errorRate,
382
+ requests: plugin.requests,
383
+ errors: plugin.errors,
384
+ avgLatency: plugin.latency?.average,
385
+ },
386
+ }, key, now);
387
+ }
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Check if incident key is in cooldown
393
+ */
394
+ private isInCooldown(key: string): boolean {
395
+ return this.recentIncidents.some(ri => ri.key === key);
396
+ }
397
+
398
+ /**
399
+ * Gather related data (logs, metrics, timeline) for incident
400
+ * @private
401
+ */
402
+ private async gatherRelatedData(
403
+ incidentType: IncidentType,
404
+ timeWindow: number = 5 * 60 * 1000 // 5 minutes default
405
+ ): Promise<RelatedData> {
406
+ const now = Date.now();
407
+ const from = now - timeWindow;
408
+
409
+ const relatedData: RelatedData = {
410
+ timeline: [],
411
+ };
412
+
413
+ try {
414
+ // Gather error and fatal logs from time window
415
+ const [errorLogsResult, fatalLogsResult] = await Promise.all([
416
+ platform.logs.query({ level: 'error' as LogLevel, from, to: now }, { limit: 50 }),
417
+ platform.logs.query({ level: 'fatal' as LogLevel, from, to: now }, { limit: 50 }),
418
+ ]);
419
+
420
+ const allErrorLogs = [...errorLogsResult.logs, ...fatalLogsResult.logs];
421
+
422
+ if (allErrorLogs.length > 0) {
423
+ // Sort by timestamp descending
424
+ allErrorLogs.sort((a, b) => b.timestamp - a.timestamp);
425
+
426
+ // Extract sample error messages with stack traces (top 5 unique)
427
+ const uniqueErrors = new Set<string>();
428
+ const endpointErrorCount = new Map<string, { count: number; sample: string }>();
429
+
430
+ for (const log of allErrorLogs) {
431
+ // Extract error message with stack trace if available
432
+ let errorMsg = typeof log.message === 'string' ? log.message : JSON.stringify(log.message);
433
+
434
+ // Add structured error info if available
435
+ if ((log as any).err) {
436
+ const err = (log as any).err;
437
+ const stack = err.stack ? `\n${err.stack.split('\n').slice(0, 3).join('\n')}` : '';
438
+ errorMsg = `${err.message || errorMsg}${stack}`;
439
+
440
+ // Add plugin/command context if available
441
+ if ((log as any).plugin) {
442
+ errorMsg = `[${(log as any).plugin}] ${errorMsg}`;
443
+ }
444
+ if ((log as any).command) {
445
+ errorMsg += `\nCommand: ${(log as any).command}`;
446
+ }
447
+ }
448
+
449
+ if (errorMsg && uniqueErrors.size < 5) {
450
+ uniqueErrors.add(errorMsg.substring(0, 500)); // Increased limit for stack traces
451
+ }
452
+
453
+ // Group errors by endpoint (if available in log metadata)
454
+ const endpoint = (log as any).endpoint || (log as any).url || 'unknown';
455
+ const existing = endpointErrorCount.get(endpoint);
456
+ if (existing) {
457
+ existing.count++;
458
+ } else {
459
+ endpointErrorCount.set(endpoint, {
460
+ count: 1,
461
+ sample: errorMsg.substring(0, 200)
462
+ });
463
+ }
464
+ }
465
+
466
+ // Get top 5 endpoints with most errors
467
+ const topEndpoints = Array.from(endpointErrorCount.entries())
468
+ .sort((a, b) => b[1].count - a[1].count)
469
+ .slice(0, 5)
470
+ .map(([endpoint, data]) => ({
471
+ endpoint,
472
+ count: data.count,
473
+ sample: data.sample,
474
+ }));
475
+
476
+ relatedData.logs = {
477
+ errorCount: allErrorLogs.filter(l => l.level === 'error').length,
478
+ warnCount: 0, // Could query warnings separately if needed
479
+ timeRange: [from, now],
480
+ sampleErrors: Array.from(uniqueErrors),
481
+ topEndpoints: topEndpoints.length > 0 ? topEndpoints : undefined,
482
+ };
483
+
484
+ // Add error logs to timeline (top 10 most recent)
485
+ for (const log of allErrorLogs.slice(0, 10)) {
486
+ const msg = typeof log.message === 'string' ? log.message : 'Error occurred';
487
+ const plugin = (log as any).plugin ? `[${(log as any).plugin}] ` : '';
488
+ relatedData.timeline!.push({
489
+ timestamp: log.timestamp,
490
+ event: `${plugin}${msg.substring(0, 100)}`,
491
+ source: 'logs',
492
+ });
493
+ }
494
+ }
495
+ } catch (error) {
496
+ this.log('warn', 'Failed to gather related logs', {
497
+ error: error instanceof Error ? error.message : String(error),
498
+ });
499
+ }
500
+
501
+ // Add current metrics snapshot (during)
502
+ const currentMetrics = metricsCollector.getMetrics();
503
+ const duringMetrics = {
504
+ errorRate: currentMetrics.requests.total > 0
505
+ ? ((currentMetrics.requests.clientErrors + currentMetrics.requests.serverErrors) / currentMetrics.requests.total) * 100
506
+ : 0,
507
+ avgLatency: currentMetrics.latency.average ?? 0,
508
+ totalRequests: currentMetrics.requests.total,
509
+ totalErrors: currentMetrics.requests.clientErrors + currentMetrics.requests.serverErrors,
510
+ };
511
+
512
+ // Calculate "before" metrics from history (average of last 5 snapshots before incident)
513
+ let beforeMetrics: Record<string, number> | undefined;
514
+ if (this.metricsHistory.length >= 2) {
515
+ // Use snapshots before the current one (exclude last snapshot which might be spike)
516
+ const beforeSnapshots = this.metricsHistory.slice(0, -1);
517
+
518
+ if (beforeSnapshots.length > 0) {
519
+ const avgErrorRate = beforeSnapshots.reduce((sum, s) => sum + s.errorRate, 0) / beforeSnapshots.length;
520
+ const avgLatency = beforeSnapshots.reduce((sum, s) => sum + s.avgLatency, 0) / beforeSnapshots.length;
521
+ const avgRequests = beforeSnapshots.reduce((sum, s) => sum + s.totalRequests, 0) / beforeSnapshots.length;
522
+
523
+ beforeMetrics = {
524
+ errorRate: avgErrorRate,
525
+ avgLatency,
526
+ totalRequests: avgRequests,
527
+ };
528
+
529
+ this.log('debug', 'Calculated before metrics', {
530
+ before: beforeMetrics,
531
+ during: duringMetrics,
532
+ snapshotsUsed: beforeSnapshots.length,
533
+ });
534
+ }
535
+ }
536
+
537
+ // Collect top slowest requests from metrics histogram (for latency incidents)
538
+ let topSlowest: Array<{ endpoint: string; method: string; durationMs: number; statusCode?: number }> | undefined;
539
+ let affectedEndpoints: string[] | undefined;
540
+
541
+ if (incidentType === 'latency_spike') {
542
+ const histogram = currentMetrics.latency.histogram;
543
+
544
+ if (histogram && histogram.length > 0) {
545
+ // Sort by max latency descending (slowest first)
546
+ const slowestRoutes = histogram
547
+ .filter(h => h.max > 100) // Only include requests >100ms
548
+ .sort((a, b) => b.max - a.max)
549
+ .slice(0, 10); // Top 10 slowest
550
+
551
+ topSlowest = slowestRoutes.map(h => {
552
+ const [method, ...pathParts] = h.route.split(' ');
553
+ const endpoint = pathParts.join(' ');
554
+ // Get most common status code
555
+ const statusCodes = Object.keys(h.byStatus);
556
+ const mostCommonStatus = statusCodes.length > 0 ? parseInt(statusCodes[0]!, 10) : undefined;
557
+
558
+ return {
559
+ endpoint,
560
+ method: method || 'GET',
561
+ durationMs: Math.round(h.max),
562
+ statusCode: mostCommonStatus,
563
+ };
564
+ });
565
+
566
+ affectedEndpoints = [...new Set(slowestRoutes.map(h => h.route))];
567
+
568
+ this.log('debug', 'Collected slow requests for latency incident', {
569
+ topSlowestCount: topSlowest.length,
570
+ affectedEndpointsCount: affectedEndpoints.length,
571
+ });
572
+ }
573
+ }
574
+
575
+ relatedData.metrics = {
576
+ before: beforeMetrics,
577
+ during: duringMetrics,
578
+ topSlowest,
579
+ affectedEndpoints,
580
+ };
581
+
582
+ // Add detection event to timeline
583
+ relatedData.timeline!.unshift({
584
+ timestamp: now,
585
+ event: `Incident detected: ${incidentType}`,
586
+ source: 'detector',
587
+ });
588
+
589
+ // Sort timeline by timestamp descending (newest first)
590
+ relatedData.timeline!.sort((a, b) => b.timestamp - a.timestamp);
591
+
592
+ return relatedData;
593
+ }
594
+
595
+ /**
596
+ * Create incident and track it
597
+ */
598
+ private async createIncident(
599
+ payload: IncidentCreatePayload,
600
+ key: string,
601
+ timestamp: number
602
+ ): Promise<void> {
603
+ try {
604
+ // Gather related data (logs, metrics, timeline)
605
+ const relatedData = await this.gatherRelatedData(payload.type);
606
+
607
+ // Merge with existing payload
608
+ const enrichedPayload: IncidentCreatePayload = {
609
+ ...payload,
610
+ relatedData,
611
+ };
612
+
613
+ const incident = await this.incidentStorage.createIncident(enrichedPayload);
614
+
615
+ // Track for deduplication
616
+ this.recentIncidents.push({
617
+ type: payload.type,
618
+ key,
619
+ timestamp,
620
+ });
621
+
622
+ this.log('info', 'Auto-created incident with context', {
623
+ id: incident.id,
624
+ type: incident.type,
625
+ severity: incident.severity,
626
+ title: incident.title,
627
+ errorLogsCount: relatedData.logs?.errorCount ?? 0,
628
+ timelineEventsCount: relatedData.timeline?.length ?? 0,
629
+ });
630
+
631
+ // Track analytics event
632
+ if (platform.analytics) {
633
+ platform.analytics.track('incident.created', {
634
+ incidentId: incident.id,
635
+ type: incident.type,
636
+ severity: incident.severity,
637
+ source: 'auto-detector',
638
+ errorLogsCount: relatedData.logs?.errorCount ?? 0,
639
+ timelineEventsCount: relatedData.timeline?.length ?? 0,
640
+ hasBeforeMetrics: !!relatedData.metrics?.before,
641
+ affectedServicesCount: payload.affectedServices?.length ?? 0,
642
+ }).catch(() => {
643
+ // Silently ignore analytics errors
644
+ });
645
+ }
646
+ } catch (error) {
647
+ this.log('error', 'Failed to create incident', {
648
+ key,
649
+ error: error instanceof Error ? error.message : String(error),
650
+ });
651
+ }
652
+ }
653
+
654
+ /**
655
+ * Get current detector status
656
+ */
657
+ getStatus(): {
658
+ running: boolean;
659
+ config: IncidentDetectorConfig;
660
+ recentIncidentsCount: number;
661
+ } {
662
+ return {
663
+ running: this.isRunning,
664
+ config: this.config,
665
+ recentIncidentsCount: this.recentIncidents.length,
666
+ };
667
+ }
668
+
669
+ /**
670
+ * Update thresholds at runtime
671
+ */
672
+ updateThresholds(thresholds: Partial<DetectionThresholds>): void {
673
+ this.config.thresholds = { ...this.config.thresholds, ...thresholds };
674
+ this.log('info', 'Thresholds updated', { thresholds: this.config.thresholds });
675
+ }
676
+
677
+ private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: any): void {
678
+ if (level === 'debug' && !this.config.debug) {return;}
679
+
680
+ const prefix = '[IncidentDetector]';
681
+ if (this.logger[level]) {
682
+ if (meta) {
683
+ this.logger[level]({ ...meta }, `${prefix} ${message}`);
684
+ } else {
685
+ this.logger[level](`${prefix} ${message}`);
686
+ }
687
+ } else {
688
+ console.log(`${prefix} [${level}] ${message}`, meta ?? '');
689
+ }
690
+ }
691
+ }