@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,133 @@
1
+ import { defineMessage, defineWebSocket, MessageRouter } from '@kb-labs/sdk';
2
+
3
+ // src/ws/logs-channel.ts
4
+ var SubscribeMsg = defineMessage("subscribe");
5
+ var UnsubscribeMsg = defineMessage("unsubscribe");
6
+ var LogMsg = defineMessage("log");
7
+ var ErrorMsg = defineMessage("error");
8
+ var subscriptions = /* @__PURE__ */ new Map();
9
+ function normalizeLevel(level) {
10
+ switch (level) {
11
+ case "trace":
12
+ case "debug":
13
+ return "debug";
14
+ case "info":
15
+ return "info";
16
+ case "warn":
17
+ return "warn";
18
+ case "error":
19
+ case "fatal":
20
+ return "error";
21
+ default:
22
+ return "info";
23
+ }
24
+ }
25
+ function levelMatches(logLevel, filterLevel) {
26
+ if (!filterLevel || filterLevel === "all") {
27
+ return true;
28
+ }
29
+ const levelOrder = {
30
+ debug: 0,
31
+ trace: 0,
32
+ info: 1,
33
+ warn: 2,
34
+ error: 3,
35
+ fatal: 3
36
+ };
37
+ const logPriority = levelOrder[logLevel] ?? 1;
38
+ const filterPriority = levelOrder[filterLevel] ?? 0;
39
+ return logPriority >= filterPriority;
40
+ }
41
+ var logs_channel_default = defineWebSocket({
42
+ path: "/logs/:jobId",
43
+ description: "Real-time job logs streaming",
44
+ handler: {
45
+ async onConnect(ctx, sender) {
46
+ const connectionId = sender.getConnectionId();
47
+ ctx.platform.logger.info("[logs-channel] Client connected", { connectionId });
48
+ const capabilities = ctx.platform.logs.getCapabilities();
49
+ if (!capabilities.hasStreaming) {
50
+ await sender.send(
51
+ ErrorMsg.create({
52
+ error: "Log streaming not available. Enable logRingBuffer adapter in config."
53
+ })
54
+ );
55
+ sender.close(1011, "Streaming not available");
56
+ }
57
+ },
58
+ async onMessage(ctx, message, sender) {
59
+ const connectionId = sender.getConnectionId();
60
+ const router = new MessageRouter().on(SubscribeMsg, async (ctx2, payload, _rawSender) => {
61
+ const { jobId, level } = payload;
62
+ ctx2.platform.logger.info("[logs-channel] Subscribing to logs", { connectionId, jobId, level });
63
+ const existingUnsubscribe = subscriptions.get(connectionId);
64
+ if (existingUnsubscribe) {
65
+ existingUnsubscribe();
66
+ }
67
+ const filter = {
68
+ source: jobId
69
+ // Logs are tagged with jobId as source
70
+ };
71
+ const unsubscribe = ctx2.platform.logs.subscribe((log) => {
72
+ if (!levelMatches(log.level, level)) {
73
+ return;
74
+ }
75
+ const logJobId = log.fields?.jobId ?? log.fields?.runId ?? log.source;
76
+ if (logJobId !== jobId) {
77
+ return;
78
+ }
79
+ sender.send(
80
+ LogMsg.create({
81
+ timestamp: new Date(log.timestamp).toISOString(),
82
+ level: normalizeLevel(log.level),
83
+ message: log.message,
84
+ context: log.fields
85
+ })
86
+ ).catch((err) => {
87
+ ctx2.platform.logger.error("[logs-channel] Failed to send log", err instanceof Error ? err : void 0);
88
+ });
89
+ }, filter);
90
+ subscriptions.set(connectionId, unsubscribe);
91
+ await sender.send(
92
+ LogMsg.create({
93
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
94
+ level: "info",
95
+ message: `Subscribed to logs for job ${jobId} (level: ${level || "all"})`
96
+ })
97
+ );
98
+ }).on(UnsubscribeMsg, async (ctx2, _payload, _rawSender) => {
99
+ ctx2.platform.logger.info("[logs-channel] Unsubscribing from logs", { connectionId });
100
+ const unsubscribe = subscriptions.get(connectionId);
101
+ if (unsubscribe) {
102
+ unsubscribe();
103
+ subscriptions.delete(connectionId);
104
+ }
105
+ await sender.send(
106
+ LogMsg.create({
107
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
108
+ level: "info",
109
+ message: "Unsubscribed from logs"
110
+ })
111
+ );
112
+ });
113
+ await router.handle(ctx, message, sender.raw);
114
+ },
115
+ async onDisconnect(ctx, code, reason) {
116
+ ctx.platform.logger.info("[logs-channel] Client disconnected", { code, reason });
117
+ },
118
+ async onError(ctx, error, sender) {
119
+ ctx.platform.logger.error("[logs-channel] Error", error);
120
+ try {
121
+ await sender.send(ErrorMsg.create({ error: error.message }));
122
+ } catch (sendError) {
123
+ ctx.platform.logger.error("[logs-channel] Failed to send error message", sendError instanceof Error ? sendError : void 0);
124
+ }
125
+ },
126
+ cleanup() {
127
+ }
128
+ }
129
+ });
130
+
131
+ export { logs_channel_default as default, levelMatches, normalizeLevel, subscriptions };
132
+ //# sourceMappingURL=logs-channel.js.map
133
+ //# sourceMappingURL=logs-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ws/logs-channel.ts"],"names":["ctx"],"mappings":"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","file":"logs-channel.js","sourcesContent":["/**\n * @module @kb-labs/workflow-cli/ws/logs-channel\n * WebSocket channel for real-time job logs streaming\n *\n * Uses platform.logs.subscribe() to stream logs filtered by jobId (runId).\n * Clients send Subscribe message with jobId to start receiving logs.\n */\n\nimport { defineWebSocket, defineMessage, MessageRouter } from '@kb-labs/sdk';\nimport type { LogRecord, LogQuery } from '@kb-labs/core-platform';\n\n// Define typed messages\nconst SubscribeMsg = defineMessage<{ jobId: string; level?: string }>('subscribe');\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nconst UnsubscribeMsg = defineMessage<{}>('unsubscribe');\n\nconst LogMsg = defineMessage<{\n timestamp: string;\n level: 'info' | 'warn' | 'error' | 'debug';\n message: string;\n context?: Record<string, unknown>;\n}>('log');\n\nconst ErrorMsg = defineMessage<{ error: string }>('error');\n\n// Incoming/Outgoing types (discriminated unions)\ntype Incoming = ReturnType<typeof SubscribeMsg.create> | ReturnType<typeof UnsubscribeMsg.create>;\n\ntype Outgoing =\n | ReturnType<typeof LogMsg.create>\n | ReturnType<ReturnType<typeof defineMessage<{ jobId: string; status: string }>>['create']>\n | ReturnType<typeof ErrorMsg.create>;\n\n// Store active subscriptions per connection\nconst subscriptions = new Map<string, () => void>();\n\n/**\n * Convert LogRecord level to channel level type\n */\nfunction normalizeLevel(level: LogRecord['level']): 'info' | 'warn' | 'error' | 'debug' {\n switch (level) {\n case 'trace':\n case 'debug':\n return 'debug';\n case 'info':\n return 'info';\n case 'warn':\n return 'warn';\n case 'error':\n case 'fatal':\n return 'error';\n default:\n return 'info';\n }\n}\n\n/**\n * Check if log level matches filter\n */\nfunction levelMatches(logLevel: LogRecord['level'], filterLevel?: string): boolean {\n if (!filterLevel || filterLevel === 'all') {\n return true;\n }\n\n const levelOrder: Record<string, number> = {\n debug: 0,\n trace: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 3,\n };\n\n const logPriority = levelOrder[logLevel] ?? 1;\n const filterPriority = levelOrder[filterLevel] ?? 0;\n\n return logPriority >= filterPriority;\n}\n\nexport default defineWebSocket<unknown, Incoming, Outgoing>({\n path: '/logs/:jobId',\n description: 'Real-time job logs streaming',\n\n handler: {\n async onConnect(ctx, sender) {\n const connectionId = sender.getConnectionId();\n ctx.platform.logger.info('[logs-channel] Client connected', { connectionId });\n\n // Check if streaming is available\n const capabilities = ctx.platform.logs.getCapabilities();\n if (!capabilities.hasStreaming) {\n await sender.send(\n ErrorMsg.create({\n error: 'Log streaming not available. Enable logRingBuffer adapter in config.',\n })\n );\n sender.close(1011, 'Streaming not available');\n }\n },\n\n async onMessage(ctx, message, sender) {\n const connectionId = sender.getConnectionId();\n\n const router = new MessageRouter()\n .on(SubscribeMsg, async (ctx, payload, _rawSender) => {\n const { jobId, level } = payload;\n\n ctx.platform.logger.info('[logs-channel] Subscribing to logs', { connectionId, jobId, level });\n\n // Unsubscribe from previous subscription if exists\n const existingUnsubscribe = subscriptions.get(connectionId);\n if (existingUnsubscribe) {\n existingUnsubscribe();\n }\n\n // Build filter for job logs\n const filter: LogQuery = {\n source: jobId, // Logs are tagged with jobId as source\n };\n\n // Subscribe to log stream\n const unsubscribe = ctx.platform.logs.subscribe((log: LogRecord) => {\n // Additional filtering by level\n if (!levelMatches(log.level, level)) {\n return;\n }\n\n // Also check if log belongs to this job via fields\n const logJobId = log.fields?.jobId ?? log.fields?.runId ?? log.source;\n if (logJobId !== jobId) {\n return;\n }\n\n // Send log to client\n sender.send(\n LogMsg.create({\n timestamp: new Date(log.timestamp).toISOString(),\n level: normalizeLevel(log.level),\n message: log.message,\n context: log.fields,\n })\n ).catch((err) => {\n ctx.platform.logger.error('[logs-channel] Failed to send log', err instanceof Error ? err : undefined);\n });\n }, filter);\n\n // Store unsubscribe function\n subscriptions.set(connectionId, unsubscribe);\n\n // Send confirmation\n await sender.send(\n LogMsg.create({\n timestamp: new Date().toISOString(),\n level: 'info',\n message: `Subscribed to logs for job ${jobId} (level: ${level || 'all'})`,\n })\n );\n })\n .on(UnsubscribeMsg, async (ctx, _payload, _rawSender) => {\n ctx.platform.logger.info('[logs-channel] Unsubscribing from logs', { connectionId });\n\n // Cleanup subscription\n const unsubscribe = subscriptions.get(connectionId);\n if (unsubscribe) {\n unsubscribe();\n subscriptions.delete(connectionId);\n }\n\n await sender.send(\n LogMsg.create({\n timestamp: new Date().toISOString(),\n level: 'info',\n message: 'Unsubscribed from logs',\n })\n );\n });\n\n await router.handle(ctx, message as any, sender.raw);\n },\n\n async onDisconnect(ctx, code, reason) {\n // Note: We don't have access to sender here, need to cleanup by other means\n // The connectionId would need to be stored during onConnect\n ctx.platform.logger.info('[logs-channel] Client disconnected', { code, reason });\n\n // Cleanup is handled automatically when connection is removed from registry\n // The subscription will be cleaned up when the socket closes\n },\n\n async onError(ctx, error, sender) {\n ctx.platform.logger.error('[logs-channel] Error', error);\n try {\n await sender.send(ErrorMsg.create({ error: error.message }));\n } catch (sendError) {\n ctx.platform.logger.error('[logs-channel] Failed to send error message', sendError instanceof Error ? sendError : undefined);\n }\n },\n\n cleanup() {\n // Note: This is called after each lifecycle event, not on final cleanup\n // For connection-specific cleanup, we handle it in onDisconnect and onMessage\n },\n },\n});\n\n// Export for testing\nexport { subscriptions, normalizeLevel, levelMatches };\n"]}
@@ -0,0 +1,11 @@
1
+ import * as _kb_labs_plugin_contracts from '@kb-labs/plugin-contracts';
2
+
3
+ /**
4
+ * @module @kb-labs/workflow-cli/ws/progress-channel
5
+ * WebSocket channel for real-time job progress updates
6
+ */
7
+ declare const _default: {
8
+ execute(context: _kb_labs_plugin_contracts.PluginContextV3<unknown>, input: _kb_labs_plugin_contracts.WSInput): Promise<_kb_labs_plugin_contracts.CommandResult | void>;
9
+ };
10
+
11
+ export { _default as default };
@@ -0,0 +1,46 @@
1
+ import { defineMessage, defineWebSocket, MessageRouter } from '@kb-labs/sdk';
2
+
3
+ // src/ws/progress-channel.ts
4
+ var SubscribeMsg = defineMessage("subscribe");
5
+ var UnsubscribeMsg = defineMessage("unsubscribe");
6
+ var StepStartMsg = defineMessage("step_start");
7
+ var ErrorMsg = defineMessage("error");
8
+ var progress_channel_default = defineWebSocket({
9
+ path: "/progress/:jobId",
10
+ description: "Real-time job progress updates",
11
+ handler: {
12
+ async onConnect(ctx, sender) {
13
+ ctx.platform.logger.info("[progress-channel] Client connected", { connectionId: sender.getConnectionId() });
14
+ },
15
+ async onMessage(ctx, message, sender) {
16
+ const router = new MessageRouter().on(SubscribeMsg, async (ctx2, payload, _rawSender) => {
17
+ const { jobId } = payload;
18
+ ctx2.platform.logger.info("[progress-channel] Subscribed to progress updates", { jobId });
19
+ await sender.send(
20
+ StepStartMsg.create({
21
+ stepName: "initialization",
22
+ stepIndex: 0
23
+ })
24
+ );
25
+ }).on(UnsubscribeMsg, async (ctx2, _payload, _rawSender) => {
26
+ ctx2.platform.logger.info("[progress-channel] Unsubscribed from progress updates");
27
+ });
28
+ await router.handle(ctx, message, sender.raw);
29
+ },
30
+ async onDisconnect(ctx, code, reason) {
31
+ ctx.platform.logger.info("[progress-channel] Client disconnected", { code, reason });
32
+ },
33
+ async onError(ctx, error, sender) {
34
+ ctx.platform.logger.error("[progress-channel] Error", error);
35
+ try {
36
+ await sender.send(ErrorMsg.create({ error: error.message }));
37
+ } catch (sendError) {
38
+ ctx.platform.logger.error("[progress-channel] Failed to send error message", sendError instanceof Error ? sendError : void 0);
39
+ }
40
+ }
41
+ }
42
+ });
43
+
44
+ export { progress_channel_default as default };
45
+ //# sourceMappingURL=progress-channel.js.map
46
+ //# sourceMappingURL=progress-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ws/progress-channel.ts"],"names":["ctx"],"mappings":";;;AAQA,IAAM,YAAA,GAAe,cAAiC,WAAW,CAAA;AAEjE,IAAM,cAAA,GAAiB,cAAkB,aAAa,CAAA;AAEtD,IAAM,YAAA,GAAe,cAAuD,YAAY,CAAA;AAYxF,IAAM,QAAA,GAAW,cAAiC,OAAO,CAAA;AAYzD,IAAO,2BAAQ,eAAA,CAA6C;AAAA,EAC1D,IAAA,EAAM,kBAAA;AAAA,EACN,WAAA,EAAa,gCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,SAAA,CAAU,GAAA,EAAK,MAAA,EAAQ;AAE3B,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,qCAAA,EAAuC,EAAE,YAAA,EAAc,MAAA,CAAO,eAAA,EAAgB,EAAG,CAAA;AAAA,IAI5G,CAAA;AAAA,IAEA,MAAM,SAAA,CAAU,GAAA,EAAK,OAAA,EAAS,MAAA,EAAQ;AACpC,MAAA,MAAM,MAAA,GAAS,IAAI,aAAA,EAAc,CAC9B,GAAG,YAAA,EAAc,OAAOA,IAAAA,EAAK,OAAA,EAAS,UAAA,KAAe;AACpD,QAAA,MAAM,EAAE,OAAM,GAAI,OAAA;AAElB,QAAAA,KAAI,QAAA,CAAS,MAAA,CAAO,KAAK,mDAAA,EAAqD,EAAE,OAAO,CAAA;AAIvF,QAAA,MAAM,MAAA,CAAO,IAAA;AAAA,UACX,aAAa,MAAA,CAAO;AAAA,YAClB,QAAA,EAAU,gBAAA;AAAA,YACV,SAAA,EAAW;AAAA,WACZ;AAAA,SACH;AAAA,MACF,CAAC,CAAA,CACA,EAAA,CAAG,gBAAgB,OAAOA,IAAAA,EAAK,UAAU,UAAA,KAAe;AACvD,QAAAA,IAAAA,CAAI,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,uDAAuD,CAAA;AAAA,MAElF,CAAC,CAAA;AAEH,MAAA,MAAM,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,OAAA,EAAgB,OAAO,GAAG,CAAA;AAAA,IACrD,CAAA;AAAA,IAEA,MAAM,YAAA,CAAa,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ;AACpC,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,0CAA0C,EAAE,IAAA,EAAM,QAAQ,CAAA;AAAA,IAErF,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAO,MAAA,EAAQ;AAChC,MAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,0BAAA,EAA4B,KAAK,CAAA;AAC3D,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,KAAK,QAAA,CAAS,MAAA,CAAO,EAAE,KAAA,EAAO,KAAA,CAAM,OAAA,EAAS,CAAC,CAAA;AAAA,MAC7D,SAAS,SAAA,EAAW;AAClB,QAAA,GAAA,CAAI,SAAS,MAAA,CAAO,KAAA,CAAM,mDAAmD,SAAA,YAAqB,KAAA,GAAQ,YAAY,MAAS,CAAA;AAAA,MACjI;AAAA,IACF;AAAA;AAEJ,CAAC","file":"progress-channel.js","sourcesContent":["/**\n * @module @kb-labs/workflow-cli/ws/progress-channel\n * WebSocket channel for real-time job progress updates\n */\n\nimport { defineWebSocket, defineMessage, MessageRouter } from '@kb-labs/sdk';\n\n// Define typed messages\nconst SubscribeMsg = defineMessage<{ jobId: string }>('subscribe');\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nconst UnsubscribeMsg = defineMessage<{}>('unsubscribe');\n\nconst StepStartMsg = defineMessage<{ stepName: string; stepIndex: number }>('step_start');\n\n// Type-only message definitions (used only in type unions)\ntype StepProgressMsg = ReturnType<typeof defineMessage<{ stepName: string; progress: number; message?: string }>>;\ntype StepCompleteMsg = ReturnType<typeof defineMessage<{\n stepName: string;\n status: 'completed' | 'failed';\n durationMs: number;\n error?: string;\n}>>;\ntype JobCompleteMsg = ReturnType<typeof defineMessage<{ jobId: string; status: string; durationMs: number }>>;\n\nconst ErrorMsg = defineMessage<{ error: string }>('error');\n\n// Incoming/Outgoing types\ntype Incoming = ReturnType<typeof SubscribeMsg.create> | ReturnType<typeof UnsubscribeMsg.create>;\n\ntype Outgoing =\n | ReturnType<typeof StepStartMsg.create>\n | StepProgressMsg\n | StepCompleteMsg\n | JobCompleteMsg\n | ReturnType<typeof ErrorMsg.create>;\n\nexport default defineWebSocket<unknown, Incoming, Outgoing>({\n path: '/progress/:jobId',\n description: 'Real-time job progress updates',\n\n handler: {\n async onConnect(ctx, sender) {\n // Note: jobId will come from path params via runtime, not ctx.params\n ctx.platform.logger.info('[progress-channel] Client connected', { connectionId: sender.getConnectionId() });\n\n // TODO: Subscribe to progress events from daemon/engine\n // Client needs to send Subscribe message with jobId\n },\n\n async onMessage(ctx, message, sender) {\n const router = new MessageRouter()\n .on(SubscribeMsg, async (ctx, payload, _rawSender) => {\n const { jobId } = payload;\n\n ctx.platform.logger.info('[progress-channel] Subscribed to progress updates', { jobId });\n\n // TODO: Start streaming progress updates from engine\n // For now, send confirmation via step start message\n await sender.send(\n StepStartMsg.create({\n stepName: 'initialization',\n stepIndex: 0,\n })\n );\n })\n .on(UnsubscribeMsg, async (ctx, _payload, _rawSender) => {\n ctx.platform.logger.info('[progress-channel] Unsubscribed from progress updates');\n // TODO: Stop streaming\n });\n\n await router.handle(ctx, message as any, sender.raw);\n },\n\n async onDisconnect(ctx, code, reason) {\n ctx.platform.logger.info('[progress-channel] Client disconnected', { code, reason });\n // TODO: Cleanup subscriptions\n },\n\n async onError(ctx, error, sender) {\n ctx.platform.logger.error('[progress-channel] Error', error);\n try {\n await sender.send(ErrorMsg.create({ error: error.message }));\n } catch (sendError) {\n ctx.platform.logger.error('[progress-channel] Failed to send error message', sendError instanceof Error ? sendError : undefined);\n }\n },\n },\n});\n"]}
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @kb-labs/rest-api-app
2
+
3
+ Deployable Fastify application for the KB Labs REST API.
4
+
5
+ ## Overview
6
+
7
+ Wires together `@kb-labs/rest-api-core`, plugin manifests, and runtime middleware into a production-ready HTTP service. All business capabilities come from discovered plugin manifests — the app itself only provides shared system endpoints and middleware.
8
+
9
+ ## Running Locally
10
+
11
+ ```bash
12
+ # From kb-labs-rest-api root
13
+ pnpm install
14
+ pnpm --filter @kb-labs/rest-api-app dev
15
+ # Server starts on http://localhost:5050
16
+ ```
17
+
18
+ Build and run compiled output:
19
+
20
+ ```bash
21
+ pnpm --filter @kb-labs/rest-api-app build
22
+ pnpm --filter @kb-labs/rest-api-app start
23
+ ```
24
+
25
+ ## Key Components
26
+
27
+ | Path | Responsibility |
28
+ |------|----------------|
29
+ | `src/bootstrap.ts` | Fastify server setup, middleware wiring, route registration |
30
+ | `src/index.ts` | Entry point — calls `bootstrap` with repo root |
31
+ | `src/routes/` | System routes: health, readiness, metrics, registry, OpenAPI, events |
32
+ | `src/middleware/` | Security headers, CORS, rate limiting, request envelopes, timeouts |
33
+ | `src/plugins/` | Plugin discovery and dynamic route mounting |
34
+ | `src/events/` | SSE hub and registry event bridge |
35
+
36
+ ## System Endpoints
37
+
38
+ - `GET /health` — versioned health snapshot (`kb.health/1`)
39
+ - `GET /ready` — readiness probe (`200` or `503`)
40
+ - `GET /openapi.json` — aggregated OpenAPI from all mounted plugins
41
+ - `GET /api/v1/plugins/registry` — mounted plugin manifest list
42
+ - `GET /api/v1/metrics` — Prometheus metrics
43
+ - `GET /api/v1/events/registry` — SSE stream for registry and health changes
44
+
45
+ ## Tests
46
+
47
+ ```bash
48
+ # From repo root
49
+ pnpm test
50
+ ```
51
+
52
+ ## License
53
+
54
+ KB Public License v1.1 © KB Labs
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Standard ESLint configuration template
3
+ *
4
+ * This is the canonical template for all @kb-labs packages.
5
+ * DO NOT modify this file locally - it is synced from @kb-labs/devkit
6
+ *
7
+ * Customization guidelines:
8
+ * - DevKit preset already includes all standard ignores
9
+ * - Only add project-specific ignores if absolutely necessary
10
+ * - Document why custom ignores are needed
11
+ *
12
+ * @see https://github.com/kb-labs/devkit#eslint-configuration
13
+ */
14
+ import nodePreset from '@kb-labs/devkit/eslint/node.js';
15
+
16
+ export default [
17
+ ...nodePreset,
18
+
19
+ // Ignore runtime-generated JS files (workspace sandboxes, etc.)
20
+ {
21
+ ignores: ['.kb/**']
22
+ }
23
+ ];
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@kb-labs/rest-api-app",
3
+ "version": "1.3.0",
4
+ "description": "REST API application for KB Labs, providing HTTP endpoints for plugin functionality",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "scripts": {
8
+ "clean": "rimraf dist",
9
+ "build": "tsup",
10
+ "dev": "tsx watch src/index.ts",
11
+ "start": "node dist/index.js",
12
+ "type-check": "tsc --noEmit",
13
+ "lint": "eslint .",
14
+ "lint:fix": "eslint . --fix",
15
+ "test": "vitest run --passWithNoTests -c ../../vitest.config.ts",
16
+ "test:watch": "vitest --passWithNoTests -c ../../vitest.config.ts"
17
+ },
18
+ "dependencies": {
19
+ "@fastify/cors": "^10.0.1",
20
+ "@fastify/rate-limit": "^10.1.1",
21
+ "@fastify/swagger": ">=9.5.1",
22
+ "@fastify/swagger-ui": "^5.2.0",
23
+ "@fastify/websocket": "^11.0.1",
24
+ "@kb-labs/shared-http": "^1.3.0",
25
+ "@kb-labs/core-contracts": "^1.5.0",
26
+ "fastify-type-provider-zod": "^6.0.0",
27
+ "@kb-labs/core-registry": "^1.5.0",
28
+ "@kb-labs/core-config": "^1.5.0",
29
+ "@kb-labs/core-platform": "^1.5.0",
30
+ "@kb-labs/core-runtime": "^1.5.0",
31
+ "@kb-labs/gateway-contracts": "^0.1.0",
32
+ "@kb-labs/core-tenant": "^1.5.0",
33
+ "@kb-labs/core-sys": "^1.5.0",
34
+ "@kb-labs/core-workspace": "^1.5.0",
35
+ "@kb-labs/plugin-contracts": "^1.3.0",
36
+ "@kb-labs/plugin-execution": "^1.3.0",
37
+ "@kb-labs/plugin-execution-factory": "^1.3.0",
38
+ "@kb-labs/plugin-runtime": "^1.3.0",
39
+ "@kb-labs/rest-api-contracts": "^1.3.0",
40
+ "@kb-labs/rest-api-core": "^1.3.0",
41
+ "@kb-labs/workflow-constants": "^1.4.0",
42
+ "@kb-labs/workflow-contracts": "^1.4.0",
43
+ "@kb-labs/workflow-engine": "^1.4.0",
44
+ "fastify": "^5.2.0",
45
+ "fastify-plugin": "^5.0.1",
46
+ "pino": "^8.16.2",
47
+ "pino-pretty": "^10.2.3",
48
+ "prom-client": "^15.1.3",
49
+ "ulid": "^2.3.0",
50
+ "ws": "^8.18.0",
51
+ "yaml": "^2.8.0",
52
+ "zod": "^4.0.0"
53
+ },
54
+ "devDependencies": {
55
+ "@kb-labs/devkit": "link:../../../../infra/kb-labs-devkit",
56
+ "@types/node": "^20.10.0",
57
+ "@types/ws": "^8.5.13",
58
+ "nodemon": "^3.1.11",
59
+ "tsup": "^8",
60
+ "tsx": "^4.20.5",
61
+ "typescript": "^5",
62
+ "vitest": "^3",
63
+ "rimraf": "^6.0.1"
64
+ },
65
+ "engines": {
66
+ "node": ">=20.0.0",
67
+ "pnpm": ">=9.0.0"
68
+ },
69
+ "kb": {
70
+ "manifest": "./dist/manifest.js"
71
+ }
72
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": 1,
3
+ "updatedAt": "2026-03-14T06:45:05.523Z",
4
+ "driftRateEma": 0.25,
5
+ "evidenceDensityEma": 0.6666666666666666,
6
+ "toolErrorRateEma": 0,
7
+ "samples": 1,
8
+ "tokenHistory": [
9
+ 18192
10
+ ],
11
+ "iterationUtilizationHistory": [
12
+ 0.3
13
+ ],
14
+ "qualityScoreHistory": [
15
+ 0.8611111111111112
16
+ ]
17
+ }
@@ -0,0 +1 @@
1
+ {"facts":[["fact_1",{"id":"fact_1","iteration":1,"category":"tool_result","fact":"grep 'emit' found ~23 matches","confidence":0.8,"source":"grep_search","updatedAt":"2026-03-14T06:44:42.851Z","confirmations":1}],["fact_2",{"id":"fact_2","iteration":2,"category":"file_content","fact":"Read kb-labs-rest-api/apps/rest-api/src/events/hub.ts (65 lines). Starts with: File: kb-labs-rest-api/apps/rest-api/src/events/hub.ts","confidence":0.9,"source":"fs_read","updatedAt":"2026-03-14T06:44:45.046Z","confirmations":1}],["fact_3",{"id":"fact_3","iteration":2,"category":"file_content","fact":"Read kb-labs-rest-api/apps/rest-api/src/routes/__tests__/workflows.spec.ts (205 lines). Starts with: File: kb-labs-rest-api/apps/rest-api/src/routes/__tests__/workflows.spec.ts","confidence":0.9,"source":"fs_read","updatedAt":"2026-03-14T06:44:45.048Z","confirmations":1}]],"nextId":4}
@@ -0,0 +1,233 @@
1
+ /**
2
+ * @module @kb-labs/rest-api-app/bootstrap
3
+ * Server bootstrap and startup
4
+ */
5
+
6
+ import { loadRestApiConfig } from '@kb-labs/rest-api-core';
7
+ import { createServer } from './server';
8
+ import { findRepoRoot } from '@kb-labs/core-sys';
9
+ import { createRegistry, type IEntityRegistry } from '@kb-labs/core-registry';
10
+ import { platform, createServiceBootstrap, loadEnvFromRoot } from '@kb-labs/core-runtime';
11
+ import { SystemMetricsCollector } from './services/system-metrics-collector';
12
+ import { metricsCollector as requestMetricsCollector, restDomainOperationMetrics } from './middleware/metrics.js';
13
+ import * as path from 'node:path';
14
+ import { promises as fs } from 'node:fs';
15
+ import { randomUUID } from 'node:crypto';
16
+ import { performance } from 'node:perf_hooks';
17
+
18
+ // Singleton CLI API instance for cleanup
19
+ let registryInstance: IEntityRegistry | null = null;
20
+
21
+ // System metrics collector instance for cleanup
22
+ let metricsCollector: SystemMetricsCollector | null = null;
23
+
24
+ /**
25
+ * Find monorepo root (prefer pnpm-workspace.yaml with kb-* patterns)
26
+ * Looks for the topmost directory with pnpm-workspace.yaml that includes kb-* patterns
27
+ */
28
+ async function findMonorepoRoot(startDir: string): Promise<string> {
29
+ let dir = path.resolve(startDir);
30
+ let monorepoRoot: string | null = null;
31
+
32
+ // First, try to find workspace with kb-* patterns (the actual monorepo root)
33
+ while (true) {
34
+ try {
35
+ const workspacePath = path.join(dir, 'pnpm-workspace.yaml');
36
+ await fs.access(workspacePath);
37
+ const content = await fs.readFile(workspacePath, 'utf-8');
38
+ if (content.includes('kb-*')) {
39
+ // Found the monorepo root with kb-* patterns
40
+ monorepoRoot = dir;
41
+ break;
42
+ }
43
+ } catch {
44
+ // Continue
45
+ }
46
+
47
+ const parent = path.dirname(dir);
48
+ if (parent === dir) {
49
+ break;
50
+ }
51
+ dir = parent;
52
+ }
53
+
54
+ if (monorepoRoot) {
55
+ return monorepoRoot;
56
+ }
57
+
58
+ // Fallback: try to find the topmost directory with both .git and pnpm-workspace.yaml
59
+ dir = path.resolve(startDir);
60
+ let foundRoot: string | null = null;
61
+ while (true) {
62
+ try {
63
+ const hasGit = await fs.access(path.join(dir, '.git')).then(() => true).catch(() => false);
64
+ const hasWorkspace = await fs.access(path.join(dir, 'pnpm-workspace.yaml')).then(() => true).catch(() => false);
65
+
66
+ if (hasGit && hasWorkspace) {
67
+ foundRoot = dir;
68
+ }
69
+ } catch {
70
+ // Continue
71
+ }
72
+
73
+ const parent = path.dirname(dir);
74
+ if (parent === dir) {
75
+ break;
76
+ }
77
+ dir = parent;
78
+ }
79
+
80
+ if (foundRoot) {
81
+ return foundRoot;
82
+ }
83
+
84
+ // Final fallback: try to find any pnpm-workspace.yaml
85
+ dir = path.resolve(startDir);
86
+ let topmostWorkspace: string | null = null;
87
+ while (true) {
88
+ try {
89
+ await fs.access(path.join(dir, 'pnpm-workspace.yaml'));
90
+ topmostWorkspace = dir;
91
+ } catch {
92
+ // Continue
93
+ }
94
+
95
+ const parent = path.dirname(dir);
96
+ if (parent === dir) {
97
+ break;
98
+ }
99
+ dir = parent;
100
+ }
101
+
102
+ if (topmostWorkspace) {
103
+ return topmostWorkspace;
104
+ }
105
+
106
+ // Final fallback to standard findRepoRoot
107
+ return findRepoRoot(startDir);
108
+ }
109
+
110
+ /**
111
+ * Bootstrap REST API server
112
+ */
113
+ export async function bootstrap(cwd: string = process.cwd()): Promise<void> {
114
+ // Detect repo root first so we can load .env before any config reads
115
+ const repoRoot = await findMonorepoRoot(cwd);
116
+
117
+ // Load .env early — must happen before loadRestApiConfig() so that
118
+ // KB_REST_* env overrides (port, redis, etc.) are available to the config mapper
119
+ loadEnvFromRoot(repoRoot);
120
+
121
+ // Load configuration (envMapper now sees fully-populated process.env)
122
+ const { config, diagnostics } = await loadRestApiConfig(cwd);
123
+
124
+ // Initialize platform (adapters from kb.config.json; .env already loaded above)
125
+ await createServiceBootstrap({ appId: 'rest-api', repoRoot });
126
+
127
+ // Now we can use platform.logger (configured from kb.config.json)
128
+ const startupRequestId = `rest-startup-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
129
+ const startupTraceId = randomUUID();
130
+ const startupSpanId = randomUUID();
131
+ const bootstrapLogger = platform.logger.child({
132
+ layer: 'rest',
133
+ service: 'bootstrap',
134
+ requestId: startupRequestId,
135
+ reqId: startupRequestId,
136
+ traceId: startupTraceId,
137
+ spanId: startupSpanId,
138
+ invocationId: startupSpanId,
139
+ executionId: startupSpanId,
140
+ });
141
+
142
+ if (diagnostics.length > 0) {
143
+ bootstrapLogger.warn('Configuration diagnostics', { diagnosticsCount: diagnostics.length });
144
+ for (const diagnostic of diagnostics) {
145
+ bootstrapLogger.warn('Configuration diagnostic', {
146
+ level: diagnostic.level,
147
+ message: diagnostic.message,
148
+ });
149
+ }
150
+ }
151
+
152
+ bootstrapLogger.info('Resolved repo root', { cwd, repoRoot });
153
+ bootstrapLogger.info('Platform adapters initialized');
154
+
155
+ // Initialize entity registry
156
+ bootstrapLogger.info('Initializing entity registry');
157
+
158
+ const isDevelopment = process.env.NODE_ENV !== 'production';
159
+ const snapshotTTL = isDevelopment
160
+ ? 10 * 60 * 1000 // 10 minutes for development
161
+ : 60 * 60 * 1000; // 1 hour for production
162
+
163
+ const registryInitStart = performance.now();
164
+ const registry = await createRegistry({
165
+ root: repoRoot,
166
+ cache: {
167
+ ttlMs: snapshotTTL,
168
+ adapter: platform.cache,
169
+ },
170
+ });
171
+ restDomainOperationMetrics.recordOperation('registry.init', performance.now() - registryInitStart, 'ok');
172
+
173
+ const plugins = registry.listPlugins();
174
+ bootstrapLogger.info('Entity registry initialized', {
175
+ pluginsFound: plugins.length,
176
+ pluginIds: plugins.map(p => `${p.id}@${p.version}`),
177
+ });
178
+
179
+ registryInstance = registry;
180
+
181
+ registry.onChange((diff) => {
182
+ restDomainOperationMetrics.recordOperation('registry.refresh', 0, 'ok');
183
+ bootstrapLogger.info('Registry changed', {
184
+ added: diff.added.length,
185
+ removed: diff.removed.length,
186
+ changed: diff.changed.length,
187
+ });
188
+ });
189
+
190
+ const server = await createServer(config, repoRoot, registry);
191
+
192
+ // Start system metrics collector
193
+ bootstrapLogger.info('Starting system metrics collector');
194
+ metricsCollector = new SystemMetricsCollector('rest', () => requestMetricsCollector.getActiveRequests());
195
+ await metricsCollector.start(10000, 60000); // Collect every 10s, TTL 60s
196
+
197
+ // Start server
198
+ const address = await server.listen({
199
+ port: config.port,
200
+ host: '0.0.0.0',
201
+ });
202
+
203
+ bootstrapLogger.info('REST API server listening', { address });
204
+
205
+ // Setup graceful shutdown
206
+ const shutdown = async (signal: string) => {
207
+ bootstrapLogger.warn('Received shutdown signal', { signal });
208
+
209
+ // Stop metrics collector
210
+ if (metricsCollector) {
211
+ metricsCollector.stop();
212
+ metricsCollector = null;
213
+ }
214
+
215
+ // Dispose CLI API
216
+ if (registryInstance) {
217
+ await registryInstance.dispose();
218
+ registryInstance = null;
219
+ }
220
+
221
+ // Shutdown platform (includes ExecutionBackend and all adapters)
222
+ await platform.shutdown();
223
+ bootstrapLogger.info('Platform shutdown complete');
224
+
225
+ // Close server
226
+ await server.close();
227
+ bootstrapLogger.info('Server closed');
228
+ process.exit(0);
229
+ };
230
+
231
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
232
+ process.on('SIGINT', () => shutdown('SIGINT'));
233
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @module @kb-labs/rest-api-app/diagnostics/header-debug
3
+ * In-memory buffer for recent header policy decisions (debug & dry-run).
4
+ */
5
+
6
+ export interface HeaderDebugEntry {
7
+ timestamp: number;
8
+ requestId: string;
9
+ pluginId?: string;
10
+ routeId?: string;
11
+ direction: 'inbound' | 'outbound';
12
+ header: string;
13
+ allowed?: boolean;
14
+ reason?: string;
15
+ action?: string;
16
+ dryRun: boolean;
17
+ }
18
+
19
+ const MAX_ENTRIES = 200;
20
+ const buffer: HeaderDebugEntry[] = [];
21
+
22
+ export function recordHeaderDebug(entry: HeaderDebugEntry): void {
23
+ buffer.push(entry);
24
+ if (buffer.length > MAX_ENTRIES) {
25
+ buffer.splice(0, buffer.length - MAX_ENTRIES);
26
+ }
27
+ }
28
+
29
+ export function getHeaderDebugEntries(limit = 50): HeaderDebugEntry[] {
30
+ if (buffer.length === 0) {
31
+ return [];
32
+ }
33
+ const clamped = Math.max(1, Math.min(limit, MAX_ENTRIES));
34
+ return buffer.slice(-clamped).reverse();
35
+ }
36
+
37
+