@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,680 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import Fastify from 'fastify';
3
+ import type { RestApiConfig } from '@kb-labs/rest-api-core';
4
+
5
+ // Mutable platform object that tests can configure
6
+ const mockPlatform: any = { analytics: {} };
7
+
8
+ vi.mock('@kb-labs/core-runtime', () => ({
9
+ platform: mockPlatform,
10
+ }));
11
+
12
+ const BASE_CONFIG: RestApiConfig = {
13
+ port: 3000,
14
+ basePath: '/api/v1',
15
+ apiVersion: 'test',
16
+ cors: {
17
+ origins: [],
18
+ allowCredentials: true,
19
+ profile: 'dev',
20
+ },
21
+ plugins: [],
22
+ mockMode: false,
23
+ };
24
+
25
+ /**
26
+ * Create mock analytics events with kb.v1 schema
27
+ */
28
+ function createMockEvent(
29
+ type: string,
30
+ timestamp: string,
31
+ payload: Record<string, unknown>
32
+ ): any {
33
+ return {
34
+ id: `evt-${Math.random()}`,
35
+ schema: 'kb.v1',
36
+ type,
37
+ ts: timestamp,
38
+ ingestTs: timestamp,
39
+ runId: 'run-test',
40
+ source: { product: 'test', version: '1.0.0' },
41
+ payload,
42
+ actor: { type: 'user', id: 'test-user' },
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Wrap events array as EventsResponse
48
+ */
49
+ function eventsResponse(events: any[]): any {
50
+ return { events, total: events.length, hasMore: false };
51
+ }
52
+
53
+ beforeEach(() => {
54
+ vi.resetAllMocks();
55
+ vi.resetModules();
56
+ });
57
+
58
+ describe('Adapter Analytics Routes - Date Range Support', () => {
59
+ describe('GET /api/v1/adapters/llm/usage', () => {
60
+ it('should return LLM usage stats without date range', async () => {
61
+ const completedEvents = [
62
+ createMockEvent('llm.completion.completed', '2026-01-15T10:00:00Z', {
63
+ model: 'gpt-4',
64
+ promptTokens: 100,
65
+ completionTokens: 50,
66
+ totalTokens: 150,
67
+ estimatedCost: 0.01,
68
+ durationMs: 1000,
69
+ }),
70
+ createMockEvent('llm.completion.completed', '2026-01-16T10:00:00Z', {
71
+ model: 'gpt-4',
72
+ promptTokens: 200,
73
+ completionTokens: 100,
74
+ totalTokens: 300,
75
+ estimatedCost: 0.02,
76
+ durationMs: 1500,
77
+ }),
78
+ ];
79
+
80
+ const errorEvents = [
81
+ createMockEvent('llm.completion.error', '2026-01-17T10:00:00Z', {
82
+ model: 'gpt-4',
83
+ error: 'Rate limit exceeded',
84
+ }),
85
+ ];
86
+
87
+ const mockAnalytics: any = {
88
+ getEvents: vi.fn((query: any) => {
89
+ if ([].concat(query.type).some(t => t === 'llm.completion.completed')) {
90
+ return Promise.resolve(eventsResponse(completedEvents));
91
+ }
92
+ if ([].concat(query.type).some(t => t === 'llm.completion.error')) {
93
+ return Promise.resolve(eventsResponse(errorEvents));
94
+ }
95
+ return Promise.resolve(eventsResponse([]));
96
+ }),
97
+ };
98
+
99
+ mockPlatform.analytics = mockAnalytics;
100
+
101
+ const { registerAdaptersRoutes } = await import('../adapters');
102
+ const app = Fastify({ logger: false });
103
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
104
+
105
+ const response = await app.inject({
106
+ method: 'GET',
107
+ url: '/api/v1/adapters/llm/usage',
108
+ });
109
+
110
+ expect(response.statusCode).toBe(200);
111
+ const payload = response.json();
112
+ expect(payload.ok).toBe(true);
113
+ expect(payload.data.totalRequests).toBe(2);
114
+ expect(payload.data.totalTokens).toBe(450);
115
+ expect(payload.data.totalCost).toBe(0.03);
116
+ expect(payload.data.errors).toBe(1);
117
+ expect(mockAnalytics.getEvents).toHaveBeenCalledWith(
118
+ expect.objectContaining({
119
+ type: expect.arrayContaining(['llm.completion.completed']),
120
+ from: undefined,
121
+ to: undefined,
122
+ limit: 10000,
123
+ })
124
+ );
125
+
126
+ await app.close();
127
+ });
128
+
129
+ it('should return LLM usage stats with date range', async () => {
130
+ const completedEvents = [
131
+ createMockEvent('llm.completion.completed', '2026-01-15T10:00:00Z', {
132
+ model: 'gpt-4',
133
+ promptTokens: 100,
134
+ completionTokens: 50,
135
+ totalTokens: 150,
136
+ estimatedCost: 0.01,
137
+ durationMs: 1000,
138
+ }),
139
+ ];
140
+
141
+ const errorEvents: any[] = [];
142
+
143
+ const mockAnalytics: any = {
144
+ getEvents: vi.fn((query: any) => {
145
+ expect(query.from).toBe('2026-01-01T00:00:00Z');
146
+ expect(query.to).toBe('2026-01-31T23:59:59Z');
147
+
148
+ if ([].concat(query.type).some(t => t === 'llm.completion.completed')) {
149
+ return Promise.resolve(eventsResponse(completedEvents));
150
+ }
151
+ if ([].concat(query.type).some(t => t === 'llm.completion.error')) {
152
+ return Promise.resolve(eventsResponse(errorEvents));
153
+ }
154
+ return Promise.resolve(eventsResponse([]));
155
+ }),
156
+ };
157
+
158
+ mockPlatform.analytics = mockAnalytics;
159
+
160
+ const { registerAdaptersRoutes } = await import('../adapters');
161
+ const app = Fastify({ logger: false });
162
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
163
+
164
+ const response = await app.inject({
165
+ method: 'GET',
166
+ url: '/api/v1/adapters/llm/usage?from=2026-01-01T00:00:00Z&to=2026-01-31T23:59:59Z',
167
+ });
168
+
169
+ expect(response.statusCode).toBe(200);
170
+ const payload = response.json();
171
+ expect(payload.ok).toBe(true);
172
+ expect(payload.data.totalRequests).toBe(1);
173
+ expect(payload.data.totalTokens).toBe(150);
174
+ expect(mockAnalytics.getEvents).toHaveBeenCalledWith(
175
+ expect.objectContaining({
176
+ type: expect.arrayContaining(['llm.completion.completed']),
177
+ from: '2026-01-01T00:00:00Z',
178
+ to: '2026-01-31T23:59:59Z',
179
+ limit: 10000,
180
+ })
181
+ );
182
+
183
+ await app.close();
184
+ });
185
+
186
+ it('should return 400 for invalid from date', async () => {
187
+ const mockAnalytics: any = {
188
+ getEvents: vi.fn(),
189
+ };
190
+
191
+ mockPlatform.analytics = mockAnalytics;
192
+
193
+ const { registerAdaptersRoutes } = await import('../adapters');
194
+ const app = Fastify({ logger: false });
195
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
196
+
197
+ const response = await app.inject({
198
+ method: 'GET',
199
+ url: '/api/v1/adapters/llm/usage?from=invalid-date',
200
+ });
201
+
202
+ expect(response.statusCode).toBe(400);
203
+ const payload = response.json();
204
+ expect(payload.ok).toBe(false);
205
+ expect(payload.error.code).toBe('INVALID_DATE_RANGE');
206
+ expect(payload.error.message).toContain('Invalid "from" date format');
207
+
208
+ await app.close();
209
+ });
210
+
211
+ it('should return 400 for invalid to date', async () => {
212
+ const mockAnalytics: any = {
213
+ getEvents: vi.fn(),
214
+ };
215
+
216
+ mockPlatform.analytics = mockAnalytics;
217
+
218
+ const { registerAdaptersRoutes } = await import('../adapters');
219
+ const app = Fastify({ logger: false });
220
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
221
+
222
+ const response = await app.inject({
223
+ method: 'GET',
224
+ url: '/api/v1/adapters/llm/usage?to=not-a-date',
225
+ });
226
+
227
+ expect(response.statusCode).toBe(400);
228
+ const payload = response.json();
229
+ expect(payload.ok).toBe(false);
230
+ expect(payload.error.code).toBe('INVALID_DATE_RANGE');
231
+ expect(payload.error.message).toContain('Invalid "to" date format');
232
+
233
+ await app.close();
234
+ });
235
+
236
+ it('should return 501 when analytics does not support getEvents', async () => {
237
+ const mockAnalytics: any = {
238
+ // getEvents not implemented
239
+ };
240
+
241
+ mockPlatform.analytics = mockAnalytics;
242
+
243
+ const { registerAdaptersRoutes } = await import('../adapters');
244
+ const app = Fastify({ logger: false });
245
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
246
+
247
+ const response = await app.inject({
248
+ method: 'GET',
249
+ url: '/api/v1/adapters/llm/usage',
250
+ });
251
+
252
+ expect(response.statusCode).toBe(501);
253
+ const payload = response.json();
254
+ expect(payload.ok).toBe(false);
255
+ expect(payload.error.code).toBe('ANALYTICS_NOT_IMPLEMENTED');
256
+
257
+ await app.close();
258
+ });
259
+ });
260
+
261
+ describe('GET /api/v1/adapters/embeddings/usage', () => {
262
+ it('should return embeddings usage stats with date range', async () => {
263
+ const embeddingEvents = [
264
+ createMockEvent('embeddings.embed.completed', '2026-01-15T10:00:00Z', {
265
+ model: 'text-embedding-ada-002',
266
+ textLength: 500,
267
+ estimatedCost: 0.001,
268
+ durationMs: 200,
269
+ }),
270
+ ];
271
+
272
+ const errorEvents: any[] = [];
273
+
274
+ const mockAnalytics: any = {
275
+ getEvents: vi.fn((query: any) => {
276
+ if ([].concat(query.type).some(t => t === 'embeddings.embed.completed')) {
277
+ return Promise.resolve(eventsResponse(embeddingEvents));
278
+ }
279
+ if ([].concat(query.type).some(t => t === 'embeddings.embed.error')) {
280
+ return Promise.resolve(eventsResponse(errorEvents));
281
+ }
282
+ return Promise.resolve(eventsResponse([]));
283
+ }),
284
+ };
285
+
286
+ mockPlatform.analytics = mockAnalytics;
287
+
288
+ const { registerAdaptersRoutes } = await import('../adapters');
289
+ const app = Fastify({ logger: false });
290
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
291
+
292
+ const response = await app.inject({
293
+ method: 'GET',
294
+ url: '/api/v1/adapters/embeddings/usage?from=2026-01-01T00:00:00Z&to=2026-01-31T23:59:59Z',
295
+ });
296
+
297
+ expect(response.statusCode).toBe(200);
298
+ const payload = response.json();
299
+ expect(payload.ok).toBe(true);
300
+ expect(payload.data.totalRequests).toBe(1);
301
+ expect(payload.data.totalTextLength).toBe(500);
302
+
303
+ await app.close();
304
+ });
305
+
306
+ it('should return 400 for invalid date range', async () => {
307
+ const mockAnalytics: any = {
308
+ getEvents: vi.fn(),
309
+ };
310
+
311
+ mockPlatform.analytics = mockAnalytics;
312
+
313
+ const { registerAdaptersRoutes } = await import('../adapters');
314
+ const app = Fastify({ logger: false });
315
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
316
+
317
+ const response = await app.inject({
318
+ method: 'GET',
319
+ url: '/api/v1/adapters/embeddings/usage?from=invalid&to=also-invalid',
320
+ });
321
+
322
+ expect(response.statusCode).toBe(400);
323
+ const payload = response.json();
324
+ expect(payload.ok).toBe(false);
325
+ expect(payload.error.code).toBe('INVALID_DATE_RANGE');
326
+
327
+ await app.close();
328
+ });
329
+ });
330
+
331
+ describe('GET /api/v1/adapters/vectorstore/usage', () => {
332
+ it('should return vectorstore usage stats with date range', async () => {
333
+ const searchEvents = [
334
+ createMockEvent('vectorstore.search.completed', '2026-01-15T10:00:00Z', {
335
+ durationMs: 50,
336
+ resultsCount: 5,
337
+ }),
338
+ ];
339
+
340
+ const upsertEvents = [
341
+ createMockEvent('vectorstore.upsert.completed', '2026-01-15T11:00:00Z', {
342
+ durationMs: 100,
343
+ vectorCount: 10,
344
+ }),
345
+ ];
346
+
347
+ const deleteEvents: any[] = [];
348
+
349
+ const mockAnalytics: any = {
350
+ getEvents: vi.fn((query: any) => {
351
+ expect(query.from).toBe('2026-01-01T00:00:00Z');
352
+ expect(query.to).toBe('2026-01-31T23:59:59Z');
353
+
354
+ if ([].concat(query.type).some(t => t === 'vectorstore.search.completed')) {
355
+ return Promise.resolve(eventsResponse(searchEvents));
356
+ }
357
+ if ([].concat(query.type).some(t => t === 'vectorstore.upsert.completed')) {
358
+ return Promise.resolve(eventsResponse(upsertEvents));
359
+ }
360
+ if ([].concat(query.type).some(t => t === 'vectorstore.delete.completed')) {
361
+ return Promise.resolve(eventsResponse(deleteEvents));
362
+ }
363
+ return Promise.resolve(eventsResponse([]));
364
+ }),
365
+ };
366
+
367
+ mockPlatform.analytics = mockAnalytics;
368
+
369
+ const { registerAdaptersRoutes } = await import('../adapters');
370
+ const app = Fastify({ logger: false });
371
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
372
+
373
+ const response = await app.inject({
374
+ method: 'GET',
375
+ url: '/api/v1/adapters/vectorstore/usage?from=2026-01-01T00:00:00Z&to=2026-01-31T23:59:59Z',
376
+ });
377
+
378
+ expect(response.statusCode).toBe(200);
379
+ const payload = response.json();
380
+ expect(payload.ok).toBe(true);
381
+ expect(payload.data.searchQueries).toBe(1);
382
+ expect(payload.data.upsertOperations).toBe(1);
383
+ expect(payload.data.deleteOperations).toBe(0);
384
+
385
+ await app.close();
386
+ });
387
+
388
+ it('should return 400 for invalid date', async () => {
389
+ const mockAnalytics: any = {
390
+ getEvents: vi.fn(),
391
+ };
392
+
393
+ mockPlatform.analytics = mockAnalytics;
394
+
395
+ const { registerAdaptersRoutes } = await import('../adapters');
396
+ const app = Fastify({ logger: false });
397
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
398
+
399
+ const response = await app.inject({
400
+ method: 'GET',
401
+ url: '/api/v1/adapters/vectorstore/usage?from=2026-13-45T99:99:99Z',
402
+ });
403
+
404
+ expect(response.statusCode).toBe(400);
405
+
406
+ await app.close();
407
+ });
408
+ });
409
+
410
+ describe('GET /api/v1/adapters/cache/usage', () => {
411
+ it('should return cache usage stats with date range', async () => {
412
+ const hitEvents = [
413
+ createMockEvent('cache.hit', '2026-01-15T10:00:00Z', { durationMs: 1 }),
414
+ createMockEvent('cache.hit', '2026-01-15T11:00:00Z', { durationMs: 2 }),
415
+ ];
416
+
417
+ const missEvents = [
418
+ createMockEvent('cache.miss', '2026-01-15T12:00:00Z', { durationMs: 1 }),
419
+ ];
420
+
421
+ const setEvents = [
422
+ createMockEvent('cache.set', '2026-01-15T13:00:00Z', { durationMs: 5 }),
423
+ ];
424
+
425
+ const mockAnalytics: any = {
426
+ getEvents: vi.fn((query: any) => {
427
+ expect(query.from).toBe('2026-01-01T00:00:00Z');
428
+ expect(query.to).toBe('2026-01-31T23:59:59Z');
429
+
430
+ if ([].concat(query.type).some(t => t === 'cache.get.hit')) {
431
+ return Promise.resolve(eventsResponse(hitEvents));
432
+ }
433
+ if ([].concat(query.type).some(t => t === 'cache.get.miss')) {
434
+ return Promise.resolve(eventsResponse(missEvents));
435
+ }
436
+ if ([].concat(query.type).some(t => t === 'cache.set.completed')) {
437
+ return Promise.resolve(eventsResponse(setEvents));
438
+ }
439
+ return Promise.resolve(eventsResponse([]));
440
+ }),
441
+ };
442
+
443
+ mockPlatform.analytics = mockAnalytics;
444
+
445
+ const { registerAdaptersRoutes } = await import('../adapters');
446
+ const app = Fastify({ logger: false });
447
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
448
+
449
+ const response = await app.inject({
450
+ method: 'GET',
451
+ url: '/api/v1/adapters/cache/usage?from=2026-01-01T00:00:00Z&to=2026-01-31T23:59:59Z',
452
+ });
453
+
454
+ expect(response.statusCode).toBe(200);
455
+ const payload = response.json();
456
+ expect(payload.ok).toBe(true);
457
+ expect(payload.data.hits).toBe(2);
458
+ expect(payload.data.misses).toBe(1);
459
+ expect(payload.data.sets).toBe(1);
460
+ expect(payload.data.totalGets).toBe(3);
461
+ expect(payload.data.hitRate).toBeCloseTo(66.67, 1);
462
+
463
+ await app.close();
464
+ });
465
+
466
+ it('should work without date parameters for backward compatibility', async () => {
467
+ const hitEvents = [
468
+ createMockEvent('cache.hit', '2026-01-15T10:00:00Z', { durationMs: 1 }),
469
+ ];
470
+
471
+ const mockAnalytics: any = {
472
+ getEvents: vi.fn((query: any) => {
473
+ expect(query.from).toBeUndefined();
474
+ expect(query.to).toBeUndefined();
475
+
476
+ if ([].concat(query.type).some(t => t === 'cache.get.hit')) {
477
+ return Promise.resolve(eventsResponse(hitEvents));
478
+ }
479
+ return Promise.resolve(eventsResponse([]));
480
+ }),
481
+ };
482
+
483
+ mockPlatform.analytics = mockAnalytics;
484
+
485
+ const { registerAdaptersRoutes } = await import('../adapters');
486
+ const app = Fastify({ logger: false });
487
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
488
+
489
+ const response = await app.inject({
490
+ method: 'GET',
491
+ url: '/api/v1/adapters/cache/usage',
492
+ });
493
+
494
+ expect(response.statusCode).toBe(200);
495
+
496
+ await app.close();
497
+ });
498
+ });
499
+
500
+ describe('GET /api/v1/adapters/storage/usage', () => {
501
+ it('should return storage usage stats with date range', async () => {
502
+ const readEvents = [
503
+ createMockEvent('storage.read.completed', '2026-01-15T10:00:00Z', {
504
+ durationMs: 10,
505
+ bytesRead: 1024,
506
+ }),
507
+ ];
508
+
509
+ const writeEvents = [
510
+ createMockEvent('storage.write.completed', '2026-01-15T11:00:00Z', {
511
+ durationMs: 20,
512
+ bytesWritten: 2048,
513
+ }),
514
+ ];
515
+
516
+ const deleteEvents: any[] = [];
517
+
518
+ const mockAnalytics: any = {
519
+ getEvents: vi.fn((query: any) => {
520
+ expect(query.from).toBe('2026-01-01T00:00:00Z');
521
+ expect(query.to).toBe('2026-01-31T23:59:59Z');
522
+
523
+ if ([].concat(query.type).some(t => t === 'storage.read.completed')) {
524
+ return Promise.resolve(eventsResponse(readEvents));
525
+ }
526
+ if ([].concat(query.type).some(t => t === 'storage.write.completed')) {
527
+ return Promise.resolve(eventsResponse(writeEvents));
528
+ }
529
+ if ([].concat(query.type).some(t => t === 'storage.delete.completed')) {
530
+ return Promise.resolve(eventsResponse(deleteEvents));
531
+ }
532
+ return Promise.resolve(eventsResponse([]));
533
+ }),
534
+ };
535
+
536
+ mockPlatform.analytics = mockAnalytics;
537
+
538
+ const { registerAdaptersRoutes } = await import('../adapters');
539
+ const app = Fastify({ logger: false });
540
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
541
+
542
+ const response = await app.inject({
543
+ method: 'GET',
544
+ url: '/api/v1/adapters/storage/usage?from=2026-01-01T00:00:00Z&to=2026-01-31T23:59:59Z',
545
+ });
546
+
547
+ expect(response.statusCode).toBe(200);
548
+ const payload = response.json();
549
+ expect(payload.ok).toBe(true);
550
+ expect(payload.data.readOperations).toBe(1);
551
+ expect(payload.data.writeOperations).toBe(1);
552
+ expect(payload.data.deleteOperations).toBe(0);
553
+ expect(payload.data.totalBytesRead).toBe(1024);
554
+ expect(payload.data.totalBytesWritten).toBe(2048);
555
+
556
+ await app.close();
557
+ });
558
+
559
+ it('should handle only from parameter', async () => {
560
+ const readEvents: any[] = [];
561
+
562
+ const mockAnalytics: any = {
563
+ getEvents: vi.fn((query: any) => {
564
+ expect(query.from).toBe('2026-01-01T00:00:00Z');
565
+ expect(query.to).toBeUndefined();
566
+
567
+ return Promise.resolve(eventsResponse(readEvents));
568
+ }),
569
+ };
570
+
571
+ mockPlatform.analytics = mockAnalytics;
572
+
573
+ const { registerAdaptersRoutes } = await import('../adapters');
574
+ const app = Fastify({ logger: false });
575
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
576
+
577
+ const response = await app.inject({
578
+ method: 'GET',
579
+ url: '/api/v1/adapters/storage/usage?from=2026-01-01T00:00:00Z',
580
+ });
581
+
582
+ expect(response.statusCode).toBe(200);
583
+
584
+ await app.close();
585
+ });
586
+
587
+ it('should handle only to parameter', async () => {
588
+ const readEvents: any[] = [];
589
+
590
+ const mockAnalytics: any = {
591
+ getEvents: vi.fn((query: any) => {
592
+ expect(query.from).toBeUndefined();
593
+ expect(query.to).toBe('2026-01-31T23:59:59Z');
594
+
595
+ return Promise.resolve(eventsResponse(readEvents));
596
+ }),
597
+ };
598
+
599
+ mockPlatform.analytics = mockAnalytics;
600
+
601
+ const { registerAdaptersRoutes } = await import('../adapters');
602
+ const app = Fastify({ logger: false });
603
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
604
+
605
+ const response = await app.inject({
606
+ method: 'GET',
607
+ url: '/api/v1/adapters/storage/usage?to=2026-01-31T23:59:59Z',
608
+ });
609
+
610
+ expect(response.statusCode).toBe(200);
611
+
612
+ await app.close();
613
+ });
614
+ });
615
+
616
+ describe('Date format support', () => {
617
+ it('should accept ISO 8601 with milliseconds', async () => {
618
+ const mockAnalytics: any = {
619
+ getEvents: vi.fn(() => Promise.resolve(eventsResponse([]))),
620
+ };
621
+
622
+ mockPlatform.analytics = mockAnalytics;
623
+
624
+ const { registerAdaptersRoutes } = await import('../adapters');
625
+ const app = Fastify({ logger: false });
626
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
627
+
628
+ const response = await app.inject({
629
+ method: 'GET',
630
+ url: '/api/v1/adapters/llm/usage?from=2026-01-01T00:00:00.000Z&to=2026-01-31T23:59:59.999Z',
631
+ });
632
+
633
+ expect(response.statusCode).toBe(200);
634
+
635
+ await app.close();
636
+ });
637
+
638
+ it('should accept ISO 8601 with timezone offset', async () => {
639
+ const mockAnalytics: any = {
640
+ getEvents: vi.fn(() => Promise.resolve(eventsResponse([]))),
641
+ };
642
+
643
+ mockPlatform.analytics = mockAnalytics;
644
+
645
+ const { registerAdaptersRoutes } = await import('../adapters');
646
+ const app = Fastify({ logger: false });
647
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
648
+
649
+ const response = await app.inject({
650
+ method: 'GET',
651
+ url: '/api/v1/adapters/llm/usage?from=2026-01-01T00:00:00%2B03:00&to=2026-01-31T23:59:59-05:00',
652
+ });
653
+
654
+ expect(response.statusCode).toBe(200);
655
+
656
+ await app.close();
657
+ });
658
+
659
+ it('should accept short ISO 8601 date format', async () => {
660
+ const mockAnalytics: any = {
661
+ getEvents: vi.fn(() => Promise.resolve(eventsResponse([]))),
662
+ };
663
+
664
+ mockPlatform.analytics = mockAnalytics;
665
+
666
+ const { registerAdaptersRoutes } = await import('../adapters');
667
+ const app = Fastify({ logger: false });
668
+ await registerAdaptersRoutes(app as any, BASE_CONFIG);
669
+
670
+ const response = await app.inject({
671
+ method: 'GET',
672
+ url: '/api/v1/adapters/llm/usage?from=2026-01-01&to=2026-01-31',
673
+ });
674
+
675
+ expect(response.statusCode).toBe(200);
676
+
677
+ await app.close();
678
+ });
679
+ });
680
+ });