@kb-labs/rest-api-app 1.3.0 → 1.5.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 (257) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +8151 -0
  3. package/dist/index.js.map +1 -0
  4. package/package.json +23 -20
  5. package/.kb/agents/sessions/session-1771531145393-ws3uh6q/turns.json +0 -42
  6. package/.kb/agents/sessions/session-1771548930486-ui6rtvm/turns.json +0 -33
  7. package/.kb/agents/sessions/session-1771549691485-nibqroq/turns.json +0 -133
  8. package/.kb/agents/sessions/session-1771550943182-dkwqdjc/turns.json +0 -130
  9. package/.kb/agents/sessions/session-1771551564182-cr4bwzn/turns.json +0 -349
  10. package/.kb/agents/sessions/session-1771552401370-g4ztwd1/turns.json +0 -206
  11. package/.kb/commit/current/plan.json +0 -248
  12. package/.kb/commit/current/status.json +0 -472
  13. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.d.ts +0 -10
  14. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js +0 -215
  15. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js.map +0 -1
  16. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.d.ts +0 -10
  17. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js +0 -271
  18. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js.map +0 -1
  19. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.d.ts +0 -10
  20. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js +0 -230
  21. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js.map +0 -1
  22. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.d.ts +0 -10
  23. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js +0 -228
  24. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js.map +0 -1
  25. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.d.ts +0 -11
  26. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js +0 -281
  27. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js.map +0 -1
  28. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.d.ts +0 -10
  29. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js +0 -266
  30. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js.map +0 -1
  31. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.d.ts +0 -11
  32. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js +0 -284
  33. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js.map +0 -1
  34. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/flags-WLdpSZl4.d.ts +0 -77
  35. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.d.ts +0 -2
  36. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js +0 -441
  37. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js.map +0 -1
  38. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.d.ts +0 -196
  39. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js +0 -441
  40. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js.map +0 -1
  41. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.d.ts +0 -19
  42. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js +0 -48
  43. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js.map +0 -1
  44. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.d.ts +0 -6
  45. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js +0 -170
  46. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js.map +0 -1
  47. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.d.ts +0 -12
  48. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js +0 -52
  49. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js.map +0 -1
  50. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.d.ts +0 -22
  51. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js +0 -52
  52. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js.map +0 -1
  53. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.d.ts +0 -13
  54. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js +0 -52
  55. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js.map +0 -1
  56. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.d.ts +0 -9
  57. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js +0 -43
  58. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js.map +0 -1
  59. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.d.ts +0 -26
  60. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js +0 -63
  61. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js.map +0 -1
  62. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.d.ts +0 -9
  63. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js +0 -46
  64. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js.map +0 -1
  65. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.d.ts +0 -16
  66. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js +0 -58
  67. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js.map +0 -1
  68. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.d.ts +0 -9
  69. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js +0 -46
  70. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js.map +0 -1
  71. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.d.ts +0 -11
  72. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js +0 -50
  73. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js.map +0 -1
  74. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.d.ts +0 -7
  75. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js +0 -39
  76. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js.map +0 -1
  77. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.d.ts +0 -10
  78. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js +0 -46
  79. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js.map +0 -1
  80. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.d.ts +0 -13
  81. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js +0 -47
  82. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js.map +0 -1
  83. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.d.ts +0 -14
  84. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js +0 -53
  85. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js.map +0 -1
  86. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.d.ts +0 -13
  87. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js +0 -54
  88. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js.map +0 -1
  89. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.d.ts +0 -12
  90. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js +0 -51
  91. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js.map +0 -1
  92. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.d.ts +0 -17
  93. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js +0 -133
  94. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js.map +0 -1
  95. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.d.ts +0 -11
  96. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js +0 -46
  97. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js.map +0 -1
  98. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.d.ts +0 -10
  99. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js +0 -215
  100. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js.map +0 -1
  101. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.d.ts +0 -10
  102. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js +0 -271
  103. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js.map +0 -1
  104. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.d.ts +0 -10
  105. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js +0 -230
  106. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js.map +0 -1
  107. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.d.ts +0 -10
  108. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js +0 -228
  109. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js.map +0 -1
  110. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.d.ts +0 -11
  111. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js +0 -281
  112. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js.map +0 -1
  113. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.d.ts +0 -10
  114. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js +0 -266
  115. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js.map +0 -1
  116. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.d.ts +0 -11
  117. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js +0 -284
  118. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js.map +0 -1
  119. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/flags-WLdpSZl4.d.ts +0 -77
  120. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.d.ts +0 -2
  121. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js +0 -441
  122. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js.map +0 -1
  123. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.d.ts +0 -196
  124. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js +0 -441
  125. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js.map +0 -1
  126. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.d.ts +0 -19
  127. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js +0 -48
  128. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js.map +0 -1
  129. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.d.ts +0 -6
  130. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js +0 -170
  131. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js.map +0 -1
  132. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.d.ts +0 -12
  133. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js +0 -52
  134. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js.map +0 -1
  135. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.d.ts +0 -22
  136. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js +0 -52
  137. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js.map +0 -1
  138. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.d.ts +0 -13
  139. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js +0 -52
  140. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js.map +0 -1
  141. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.d.ts +0 -9
  142. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js +0 -43
  143. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js.map +0 -1
  144. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.d.ts +0 -26
  145. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js +0 -63
  146. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js.map +0 -1
  147. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.d.ts +0 -9
  148. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js +0 -46
  149. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js.map +0 -1
  150. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.d.ts +0 -16
  151. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js +0 -58
  152. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js.map +0 -1
  153. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.d.ts +0 -9
  154. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js +0 -46
  155. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js.map +0 -1
  156. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.d.ts +0 -11
  157. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js +0 -50
  158. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js.map +0 -1
  159. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.d.ts +0 -7
  160. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js +0 -39
  161. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js.map +0 -1
  162. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.d.ts +0 -10
  163. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js +0 -46
  164. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js.map +0 -1
  165. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.d.ts +0 -13
  166. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js +0 -47
  167. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js.map +0 -1
  168. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.d.ts +0 -14
  169. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js +0 -53
  170. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js.map +0 -1
  171. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.d.ts +0 -13
  172. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js +0 -54
  173. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js.map +0 -1
  174. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.d.ts +0 -12
  175. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js +0 -51
  176. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js.map +0 -1
  177. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.d.ts +0 -17
  178. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js +0 -133
  179. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js.map +0 -1
  180. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.d.ts +0 -11
  181. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js +0 -46
  182. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js.map +0 -1
  183. package/eslint.config.js +0 -23
  184. package/src/.kb/agents/sessions/session-1773470583796-ximqnfk/kpi-baseline.json +0 -17
  185. package/src/.kb/memory/sessions/session-1773470583796-ximqnfk/fact-sheet.json +0 -1
  186. package/src/bootstrap.ts +0 -233
  187. package/src/diagnostics/header-debug.ts +0 -37
  188. package/src/events/hub.ts +0 -60
  189. package/src/events/index.ts +0 -1
  190. package/src/index.ts +0 -13
  191. package/src/manifest.ts +0 -21
  192. package/src/middleware/__tests__/cache.spec.ts +0 -184
  193. package/src/middleware/__tests__/envelope.spec.ts +0 -268
  194. package/src/middleware/__tests__/metrics.redis.spec.ts +0 -64
  195. package/src/middleware/__tests__/rate-limit.spec.ts +0 -283
  196. package/src/middleware/__tests__/request-id.spec.ts +0 -160
  197. package/src/middleware/cache.ts +0 -67
  198. package/src/middleware/envelope.ts +0 -136
  199. package/src/middleware/error-guard.ts +0 -69
  200. package/src/middleware/index.ts +0 -37
  201. package/src/middleware/metrics.ts +0 -810
  202. package/src/middleware/mock-mode.ts +0 -44
  203. package/src/middleware/prom-metrics.ts +0 -284
  204. package/src/middleware/rate-limit-routes.ts +0 -73
  205. package/src/middleware/rate-limit.ts +0 -72
  206. package/src/middleware/request-id.ts +0 -41
  207. package/src/middleware/request-timeout.ts +0 -69
  208. package/src/middleware/security-headers.ts +0 -24
  209. package/src/middleware/startup-guard.ts +0 -107
  210. package/src/observability/service-contract.ts +0 -192
  211. package/src/plugins/index.ts +0 -118
  212. package/src/routes/__tests__/adapters-date-helpers.spec.ts +0 -332
  213. package/src/routes/__tests__/adapters.spec.ts +0 -680
  214. package/src/routes/__tests__/cache.spec.ts +0 -264
  215. package/src/routes/__tests__/events.spec.ts +0 -434
  216. package/src/routes/__tests__/health.spec.ts +0 -414
  217. package/src/routes/__tests__/logs.spec.ts +0 -494
  218. package/src/routes/__tests__/observability.spec.ts +0 -392
  219. package/src/routes/__tests__/plugins.spec.ts +0 -931
  220. package/src/routes/__tests__/workflow-management.spec.ts +0 -698
  221. package/src/routes/__tests__/workflows.spec.ts +0 -204
  222. package/src/routes/adapter-call.ts +0 -220
  223. package/src/routes/adapters.ts +0 -1206
  224. package/src/routes/analytics.ts +0 -328
  225. package/src/routes/cache.ts +0 -104
  226. package/src/routes/debug-routes.ts +0 -95
  227. package/src/routes/events.ts +0 -115
  228. package/src/routes/health.ts +0 -348
  229. package/src/routes/hello.ts +0 -47
  230. package/src/routes/index.ts +0 -395
  231. package/src/routes/jobs.ts +0 -253
  232. package/src/routes/logs.ts +0 -718
  233. package/src/routes/metrics.ts +0 -120
  234. package/src/routes/observability.ts +0 -1388
  235. package/src/routes/openapi.ts +0 -101
  236. package/src/routes/platform.ts +0 -143
  237. package/src/routes/plugins.ts +0 -998
  238. package/src/routes/readiness.ts +0 -83
  239. package/src/routes/workflow-management.ts +0 -469
  240. package/src/routes/workflows.ts +0 -256
  241. package/src/server.ts +0 -203
  242. package/src/services/historical-metrics.ts +0 -496
  243. package/src/services/incident-analyzer.ts +0 -289
  244. package/src/services/incident-detector.ts +0 -691
  245. package/src/services/incident-schema.sql +0 -76
  246. package/src/services/incident-storage.ts +0 -593
  247. package/src/services/system-metrics-collector.ts +0 -244
  248. package/src/types/fastify.d.ts +0 -58
  249. package/src/utils/__tests__/sse-auth.spec.ts +0 -113
  250. package/src/utils/path-helpers.ts +0 -15
  251. package/src/utils/repo.ts +0 -42
  252. package/src/utils/schema.ts +0 -20
  253. package/src/utils/sse-auth.ts +0 -81
  254. package/test-sandbox.sh +0 -105
  255. package/tsconfig.build.json +0 -15
  256. package/tsconfig.json +0 -9
  257. package/tsup.config.ts +0 -18
@@ -1,998 +0,0 @@
1
- /**
2
- * @module @kb-labs/rest-api-app/routes/plugins
3
- * Plugin routes registration
4
- *
5
- * Uses @kb-labs/plugin-execution for unified execution layer.
6
- */
7
-
8
- import type { FastifyInstance } from 'fastify';
9
- import type { RestApiConfig } from '@kb-labs/rest-api-core';
10
- import type { IEntityRegistry, RegistrySnapshot } from '@kb-labs/core-registry';
11
- import type { ManifestV3 } from '@kb-labs/plugin-contracts';
12
- import { validateManifest } from '@kb-labs/plugin-contracts';
13
- import { mountRoutes } from '@kb-labs/plugin-execution/http';
14
- import { mountWebSocketChannels } from '@kb-labs/plugin-execution';
15
- import { combineManifestsToRegistry } from '@kb-labs/rest-api-core';
16
- import { platform } from '@kb-labs/core-runtime';
17
- import {
18
- logDiagnosticEvent,
19
- type DiagnosticLogLevel,
20
- } from '@kb-labs/core-platform';
21
- import type { DiagnosticReasonCode } from '@kb-labs/core-contracts';
22
- import * as path from 'node:path';
23
- import * as fs from 'node:fs/promises';
24
- import type { ReadinessState } from './readiness';
25
- import { resolveWorkspaceRoot } from '@kb-labs/core-workspace';
26
- import { metricsCollector, restDomainOperationMetrics } from '../middleware/metrics.js';
27
- import { performance } from 'node:perf_hooks';
28
-
29
- interface SnapshotManifestEntry {
30
- pluginId: string;
31
- manifest: ManifestV3;
32
- pluginRoot: string;
33
- }
34
-
35
- function extractSnapshotManifests(snapshot: RegistrySnapshot): SnapshotManifestEntry[] {
36
- return (snapshot.manifests || []).map(entry => ({
37
- pluginId: entry.pluginId,
38
- manifest: entry.manifest,
39
- pluginRoot: entry.pluginRoot,
40
- }));
41
- }
42
-
43
- /**
44
- * Register plugin routes
45
- */
46
- export async function registerPluginRoutes(
47
- server: FastifyInstance,
48
- config: RestApiConfig,
49
- repoRoot: string,
50
- registry: IEntityRegistry,
51
- readiness?: ReadinessState
52
- ): Promise<void> {
53
- const gatewayTimeoutMs = config.timeouts?.requestTimeout ?? 30_000;
54
- // Stats aggregated from sequential mount results
55
- const stats = {
56
- mountedRoutes: 0,
57
- mountedChannels: 0,
58
- errors: 0,
59
- };
60
-
61
- if (readiness) {
62
- readiness.pluginRoutesMounted = false;
63
- readiness.pluginMountInProgress = true;
64
- readiness.pluginRoutesCount = 0;
65
- readiness.pluginRouteErrors = 0;
66
- readiness.pluginRouteFailures = [];
67
- readiness.pluginRoutesLastDurationMs = null;
68
- }
69
-
70
- metricsCollector.resetPluginRouteBudgets();
71
-
72
- const mountMetrics = metricsCollector.beginPluginMount();
73
- const mountStart = performance.now();
74
-
75
- try {
76
- const workspaceResolution = await resolveWorkspaceRoot({
77
- startDir: repoRoot,
78
- env: {
79
- KB_LABS_WORKSPACE_ROOT: process.env.KB_LABS_WORKSPACE_ROOT,
80
- KB_LABS_REPO_ROOT: process.env.KB_LABS_REPO_ROOT,
81
- },
82
- });
83
- const workspaceRoot = workspaceResolution.rootDir;
84
- platform.logger.info('Resolved workspace root', {
85
- repoRoot,
86
- workspaceRoot,
87
- source: workspaceResolution.source,
88
- });
89
-
90
- const snapshot = registry.snapshot();
91
- const manifests = extractSnapshotManifests(snapshot);
92
-
93
- // Log discovery summary
94
- platform.logger.info('Plugin discovery summary', {
95
- totalManifests: manifests.length,
96
- rev: snapshot.rev,
97
- partial: snapshot.partial,
98
- stale: snapshot.stale,
99
- plugins: manifests.map(e => ({
100
- id: e.manifest.id,
101
- restRoutes: e.manifest.rest?.routes?.length ?? 0,
102
- wsChannels: e.manifest.ws?.channels?.length ?? 0,
103
- })),
104
- });
105
-
106
- if (snapshot.partial || snapshot.stale) {
107
- if (snapshot.partial) {
108
- logDiagnosticEvent(platform.logger, {
109
- domain: 'registry',
110
- event: 'plugin.registry.snapshot',
111
- level: 'warn',
112
- reasonCode: 'snapshot_partial',
113
- message: 'Registry snapshot is partial',
114
- outcome: 'failed',
115
- serviceId: 'rest',
116
- evidence: {
117
- rev: snapshot.rev,
118
- generatedAt: snapshot.generatedAt,
119
- },
120
- });
121
- }
122
-
123
- if (snapshot.stale) {
124
- logDiagnosticEvent(platform.logger, {
125
- domain: 'registry',
126
- event: 'plugin.registry.snapshot',
127
- level: 'warn',
128
- reasonCode: 'snapshot_stale',
129
- message: 'Registry snapshot is stale',
130
- outcome: 'failed',
131
- serviceId: 'rest',
132
- evidence: {
133
- rev: snapshot.rev,
134
- generatedAt: snapshot.generatedAt,
135
- expiresAt: snapshot.expiresAt,
136
- },
137
- });
138
- }
139
- }
140
-
141
- emitRegistrySnapshotDiagnostics(snapshot);
142
-
143
- // Use platform's unified ExecutionBackend (initialized in bootstrap.ts)
144
- const backend = platform.executionBackend;
145
-
146
- // Filter plugins that have routes or channels to mount
147
- const mountableManifests = manifests
148
- .filter(entry =>
149
- (entry.manifest.rest?.routes && entry.manifest.rest.routes.length > 0) ||
150
- (entry.manifest.ws?.channels && entry.manifest.ws.channels.length > 0)
151
- );
152
-
153
- platform.logger.info('Plugins selected for route mounting', {
154
- mountable: mountableManifests.length,
155
- skipped: manifests.length - mountableManifests.length,
156
- mountablePlugins: mountableManifests.map(e => e.manifest.id),
157
- });
158
-
159
- // ── Phase 1: Batch-validate all handler files in one I/O pass ──
160
- // Collect all handler file paths across all plugins, then validate in a single Promise.all()
161
- // This avoids interleaved fs.access() calls that caused race conditions with parallel mounting.
162
- //
163
- // Handler paths in manifests are relative to the plugin's dist/ directory, because manifests
164
- // are loaded from dist/manifest.js. pluginRoot points to the package root, so we resolve
165
- // handlers relative to pluginRoot/dist/ to match where the compiled files actually live.
166
- const handlerChecks: Array<{ key: string; filePath: string }> = [];
167
- for (const entry of mountableManifests) {
168
- if (entry.manifest.rest?.routes) {
169
- for (const route of entry.manifest.rest.routes) {
170
- const handlerFile = route.handler.split('#')[0];
171
- if (handlerFile) {
172
- const pluginDistRoot = path.join(entry.pluginRoot, 'dist');
173
- const handlerPath = path.resolve(pluginDistRoot, handlerFile);
174
- handlerChecks.push({
175
- key: `${entry.manifest.id}::${route.method} ${route.path}`,
176
- filePath: handlerPath,
177
- });
178
- }
179
- }
180
- }
181
- }
182
-
183
- const handlerAccessResults = await Promise.all(
184
- handlerChecks.map(async (check) => {
185
- try {
186
- await fs.access(check.filePath);
187
- return { key: check.key, filePath: check.filePath, exists: true };
188
- } catch {
189
- return { key: check.key, filePath: check.filePath, exists: false };
190
- }
191
- })
192
- );
193
-
194
- // Build lookup: "pluginId::METHOD /path" → { exists, filePath }
195
- const handlerExistsMap = new Map<string, { exists: boolean; filePath: string }>();
196
- for (const result of handlerAccessResults) {
197
- handlerExistsMap.set(result.key, { exists: result.exists, filePath: result.filePath });
198
- }
199
-
200
- platform.logger.debug('Batch handler file validation completed', {
201
- totalHandlers: handlerChecks.length,
202
- validHandlers: handlerAccessResults.filter(r => r.exists).length,
203
- invalidHandlers: handlerAccessResults.filter(r => !r.exists).length,
204
- });
205
-
206
- // ── Phase 2: Sequential plugin mounting ──
207
- // Routes are registered in-memory on Fastify (~0.1ms per route).
208
- // Sequential mounting eliminates race conditions with zero performance cost.
209
- let mountedRoutes = 0;
210
- let mountedChannels = 0;
211
- let errors = 0;
212
- const succeeded: string[] = [];
213
- const failed: string[] = [];
214
- const routeFailures: Array<{ id: string; error: string }> = [];
215
-
216
- for (const entry of mountableManifests) {
217
- const { manifest, pluginRoot } = entry;
218
- const pluginDistRoot = path.join(pluginRoot, 'dist');
219
-
220
- // Validate routes using pre-built handler map (no I/O here)
221
- const restValidationErrors: string[] = [];
222
- if (manifest.rest?.routes) {
223
- for (const route of manifest.rest.routes) {
224
- const handlerFile = route.handler.split('#')[0];
225
- if (!handlerFile) {
226
- restValidationErrors.push(
227
- `Route ${route.method} ${route.path}: Invalid handler reference "${route.handler}"`
228
- );
229
- continue;
230
- }
231
- const lookupKey = `${manifest.id}::${route.method} ${route.path}`;
232
- const check = handlerExistsMap.get(lookupKey);
233
- if (check && !check.exists) {
234
- restValidationErrors.push(
235
- `Route ${route.method} ${route.path}: Handler file not found: ${check.filePath}`
236
- );
237
- }
238
- }
239
- }
240
-
241
- if (restValidationErrors.length > 0) {
242
- const reasonCode = inferRouteValidationReasonCode(restValidationErrors);
243
- logDiagnosticEvent(platform.logger, {
244
- event: 'plugin.routes.validation',
245
- level: resolveRouteValidationLogLevel(restValidationErrors, manifest.rest?.routes?.length ?? 0),
246
- reasonCode,
247
- message: 'Plugin route validation failed',
248
- outcome: 'failed',
249
- pluginId: manifest.id,
250
- pluginVersion: manifest.version,
251
- serviceId: 'rest',
252
- issues: restValidationErrors,
253
- remediation: 'Verify handler file paths, exports, and route schema.',
254
- evidence: {
255
- pluginRoot,
256
- totalRoutes: manifest.rest?.routes?.length ?? 0,
257
- },
258
- });
259
-
260
- platform.logger.warn('REST validation errors found, will skip problematic routes but continue mounting others', {
261
- plugin: `${manifest.id}@${manifest.version}`,
262
- pluginRoot,
263
- remediation: 'Verify REST handler file and export exist',
264
- errors: restValidationErrors,
265
- });
266
-
267
- const errorPaths = new Set(restValidationErrors.map((error) => {
268
- const match = error.match(/Route\s+(\w+)\s+([^\s:]+)/);
269
- return match ? `${match[1]} ${match[2]}` : null;
270
- }).filter(Boolean));
271
-
272
- const validRoutes = manifest.rest!.routes!.filter((route) => {
273
- const routeKey = `${route.method} ${route.path}`;
274
- return !errorPaths.has(routeKey);
275
- });
276
-
277
- if (validRoutes.length === 0) {
278
- restDomainOperationMetrics.recordOperation('plugin.routes.mount', 0, 'error');
279
- logDiagnosticEvent(platform.logger, {
280
- event: 'plugin.routes.validation',
281
- level: 'error',
282
- reasonCode,
283
- message: 'All plugin routes failed validation; skipping plugin',
284
- outcome: 'failed',
285
- pluginId: manifest.id,
286
- pluginVersion: manifest.version,
287
- serviceId: 'rest',
288
- issues: restValidationErrors,
289
- evidence: {
290
- pluginRoot,
291
- },
292
- });
293
- errors += 1;
294
- failed.push(manifest.id);
295
- routeFailures.push({
296
- id: manifest.id,
297
- error: summarizeValidationErrors(restValidationErrors),
298
- });
299
- continue;
300
- }
301
-
302
- manifest.rest!.routes = validRoutes;
303
- platform.logger.info('Filtered routes, mounting valid ones', {
304
- plugin: `${manifest.id}@${manifest.version}`,
305
- totalRoutes: manifest.rest!.routes.length + restValidationErrors.length,
306
- validRoutes: validRoutes.length,
307
- skippedRoutes: restValidationErrors.length,
308
- });
309
- }
310
-
311
- try {
312
- const start = performance.now();
313
-
314
- let pluginBasePath: string;
315
- if (manifest.rest?.basePath) {
316
- if (manifest.rest.basePath.startsWith('/api/')) {
317
- pluginBasePath = manifest.rest.basePath;
318
- } else if (manifest.rest.basePath.startsWith('/v1/')) {
319
- pluginBasePath = manifest.rest.basePath.replace(/^\/v1/, config.basePath);
320
- } else {
321
- pluginBasePath = `${config.basePath}${manifest.rest.basePath}`;
322
- }
323
- } else {
324
- pluginBasePath = `${config.basePath}/plugins/${manifest.id}`;
325
- }
326
-
327
- platform.logger.info('Mounting plugin routes', {
328
- plugin: `${manifest.id}@${manifest.version}`,
329
- configBasePath: config.basePath,
330
- manifestBasePath: manifest.rest?.basePath,
331
- pluginBasePath,
332
- pluginRoot,
333
- routes: manifest.rest?.routes?.length ?? 0,
334
- });
335
-
336
- await mountRoutes(server, manifest, {
337
- backend,
338
- pluginRoot: pluginDistRoot,
339
- workspaceRoot,
340
- basePath: pluginBasePath,
341
- defaultTimeoutMs: gatewayTimeoutMs,
342
- });
343
-
344
- const duration = performance.now() - start;
345
- const routesCount = manifest.rest?.routes?.length ?? 0;
346
-
347
- for (const route of manifest.rest?.routes ?? []) {
348
- metricsCollector.registerRouteBudget(
349
- route.method,
350
- `${pluginBasePath}${route.path}`,
351
- route.timeoutMs ?? gatewayTimeoutMs,
352
- manifest.id
353
- );
354
- }
355
-
356
- mountMetrics.recordSuccess(manifest.id, routesCount, duration);
357
- restDomainOperationMetrics.recordOperation('plugin.routes.mount', duration, 'ok');
358
-
359
- for (const route of manifest.rest?.routes ?? []) {
360
- platform.logger.info('Mounted route', {
361
- plugin: manifest.id,
362
- method: route.method,
363
- path: `${pluginBasePath}${route.path}`,
364
- handler: route.handler,
365
- });
366
- }
367
-
368
- platform.logger.info('Successfully mounted plugin routes', {
369
- plugin: `${manifest.id}@${manifest.version}`,
370
- pluginBasePath,
371
- routesCount,
372
- durationMs: Number(duration.toFixed(2)),
373
- });
374
-
375
- // Mount WebSocket channels if present
376
- let channelsCount = 0;
377
- if (manifest.ws?.channels && manifest.ws.channels.length > 0) {
378
- try {
379
- const wsStart = performance.now();
380
- let wsBasePath: string = manifest.ws.basePath || `/v1/ws/plugins/${manifest.id}`;
381
- // Normalize: /v1/ → config.basePath (same as REST routes) so gateway
382
- // can proxy both HTTP and WS under the same /api/v1 prefix.
383
- if (wsBasePath.startsWith('/v1/')) {
384
- wsBasePath = wsBasePath.replace(/^\/v1/, config.basePath);
385
- }
386
-
387
- platform.logger.info('Mounting WebSocket channels', {
388
- plugin: `${manifest.id}@${manifest.version}`,
389
- wsBasePath,
390
- channels: manifest.ws.channels.length,
391
- });
392
-
393
- const wsResult = await mountWebSocketChannels(server, manifest, {
394
- backend,
395
- pluginRoot: pluginDistRoot,
396
- workspaceRoot,
397
- basePath: wsBasePath,
398
- defaultTimeoutMs: manifest.ws.defaults?.timeoutMs ?? gatewayTimeoutMs,
399
- defaultMaxMessageSize: manifest.ws.defaults?.maxMessageSize,
400
- });
401
-
402
- const wsDuration = performance.now() - wsStart;
403
- channelsCount = wsResult.mounted;
404
-
405
- if (wsResult.mounted > 0) {
406
- platform.logger.info('Successfully mounted WebSocket channels', {
407
- plugin: `${manifest.id}@${manifest.version}`,
408
- channels: wsResult.mounted,
409
- durationMs: Number(wsDuration.toFixed(2)),
410
- });
411
- }
412
-
413
- if (wsResult.errors.length > 0) {
414
- platform.logger.warn('WebSocket channel mounting had errors', {
415
- plugin: `${manifest.id}@${manifest.version}`,
416
- errors: wsResult.errors,
417
- });
418
- }
419
- } catch (wsError) {
420
- logDiagnosticEvent(platform.logger, {
421
- event: 'plugin.ws.mount',
422
- level: 'error',
423
- reasonCode: 'ws_mount_failed',
424
- message: 'Failed to mount plugin WebSocket channels',
425
- outcome: 'failed',
426
- error: wsError instanceof Error ? wsError : new Error(String(wsError)),
427
- pluginId: manifest.id,
428
- pluginVersion: manifest.version,
429
- serviceId: 'rest',
430
- });
431
- platform.logger.error(
432
- 'Failed to mount WebSocket channels',
433
- wsError instanceof Error ? wsError : new Error(String(wsError)),
434
- { plugin: manifest.id }
435
- );
436
- }
437
- }
438
-
439
- mountedRoutes += routesCount;
440
- mountedChannels += channelsCount;
441
- succeeded.push(manifest.id);
442
- } catch (error) {
443
- mountMetrics.recordFailure(manifest.id, shortErrorMessage(error));
444
- restDomainOperationMetrics.recordOperation('plugin.routes.mount', 0, 'error');
445
- logDiagnosticEvent(platform.logger, {
446
- event: 'plugin.routes.mount',
447
- level: 'error',
448
- reasonCode: 'route_mount_failed',
449
- message: 'Failed to mount plugin routes',
450
- outcome: 'failed',
451
- error: error instanceof Error ? error : new Error(String(error)),
452
- pluginId: manifest.id,
453
- pluginVersion: manifest.version,
454
- serviceId: 'rest',
455
- });
456
- platform.logger.error(
457
- 'Failed to mount plugin routes',
458
- error instanceof Error ? error : new Error(String(error)),
459
- { plugin: manifest.id }
460
- );
461
- errors += 1;
462
- failed.push(manifest.id);
463
- routeFailures.push({
464
- id: manifest.id,
465
- error: `rest_mount_failed ${shortErrorMessage(error)}`,
466
- });
467
- }
468
- }
469
-
470
- // Update stats and readiness
471
- stats.mountedRoutes = mountedRoutes;
472
- stats.mountedChannels = mountedChannels;
473
- stats.errors = errors;
474
- if (readiness) {
475
- readiness.pluginRouteFailures = routeFailures;
476
- }
477
-
478
- // Log summary
479
- platform.logger.info('Sequential plugin route and WebSocket channel mounting completed', {
480
- total: mountableManifests.length,
481
- succeeded: succeeded.length,
482
- failed: failed.length,
483
- mountedRoutes,
484
- mountedChannels,
485
- errors,
486
- });
487
- } catch (error) {
488
- logDiagnosticEvent(platform.logger, {
489
- domain: 'registry',
490
- event: 'plugin.discovery',
491
- level: 'error',
492
- reasonCode: 'plugin_discovery_failed',
493
- message: 'Plugin discovery failed during route registration',
494
- outcome: 'failed',
495
- error: error instanceof Error ? error : new Error(String(error)),
496
- serviceId: 'rest',
497
- });
498
- platform.logger.error(
499
- 'Plugin discovery failed',
500
- error instanceof Error ? error : new Error(String(error))
501
- );
502
- stats.errors += 1;
503
- if (readiness) {
504
- readiness.pluginRoutesCount = stats.mountedRoutes;
505
- readiness.pluginRouteErrors = stats.errors;
506
- readiness.pluginRoutesMounted = false;
507
- readiness.pluginMountInProgress = false;
508
- readiness.pluginRoutesLastDurationMs = null;
509
- readiness.pluginRouteFailures.push({
510
- id: 'discovery',
511
- error: `rest_discovery_failed ${shortErrorMessage(error)}`,
512
- });
513
- }
514
- metricsCollector.completePluginMount(platform.logger as any);
515
- return;
516
- }
517
-
518
- if (readiness) {
519
- readiness.pluginRoutesCount = stats.mountedRoutes;
520
- readiness.pluginRouteErrors = stats.errors;
521
- readiness.pluginRoutesMounted = stats.errors === 0;
522
- readiness.pluginMountInProgress = false;
523
- readiness.lastPluginMountTs = new Date().toISOString();
524
- readiness.pluginRoutesLastDurationMs = Number(
525
- (performance.now() - mountStart).toFixed(2)
526
- );
527
- }
528
-
529
- metricsCollector.completePluginMount(platform.logger as any);
530
- }
531
-
532
- /**
533
- * Register plugin snapshot endpoints for Studio
534
- */
535
- export async function registerPluginSnapshotRoutes(
536
- server: FastifyInstance,
537
- config: RestApiConfig,
538
- registry: IEntityRegistry
539
- ): Promise<void> {
540
- const basePath = config.basePath;
541
-
542
- server.post(`${basePath}/plugins/refresh`, async (_request, reply) => {
543
- try {
544
- await restDomainOperationMetrics.observeOperation('plugin.registry.refresh', async () => {
545
- await registry.refresh();
546
- });
547
- const snapshot = await restDomainOperationMetrics.observeOperation('plugin.registry.snapshot', async () =>
548
- registry.snapshot(),
549
- );
550
- emitRegistrySnapshotDiagnostics(snapshot);
551
-
552
- reply.type('application/json');
553
- return {
554
- ok: true,
555
- data: {
556
- rev: snapshot.rev,
557
- total: snapshot.plugins.length,
558
- generatedAt: snapshot.generatedAt,
559
- partial: snapshot.partial,
560
- stale: snapshot.stale,
561
- },
562
- };
563
- } catch (error) {
564
- logDiagnosticEvent(platform.logger, {
565
- domain: 'registry',
566
- event: 'plugin.registry.refresh',
567
- level: 'error',
568
- reasonCode: 'registry_refresh_failed',
569
- message: 'Failed to refresh plugin registry',
570
- outcome: 'failed',
571
- error: error instanceof Error ? error : new Error(String(error)),
572
- serviceId: 'rest',
573
- });
574
- platform.logger.error(
575
- 'Failed to refresh plugin registry',
576
- error instanceof Error ? error : new Error(String(error))
577
- );
578
- reply.code(500).send({
579
- ok: false,
580
- error: 'Failed to refresh plugin registry',
581
- message: error instanceof Error ? error.message : String(error),
582
- });
583
- }
584
- });
585
-
586
- // Raw manifests endpoint for Studio/debug consumers
587
- server.get(`${basePath}/plugins/registry`, async (_request, reply) => {
588
- try {
589
- const snapshot = await restDomainOperationMetrics.observeOperation('plugin.registry.snapshot', async () =>
590
- registry.snapshot(),
591
- );
592
-
593
- // Get build timestamps and validate manifests
594
- const manifestsWithTimestamps = await Promise.all(
595
- snapshot.manifests.map(async (entry) => {
596
- let buildTimestamp: string | undefined;
597
- try {
598
- const distPath = path.join(entry.pluginRoot, 'dist');
599
- const stats = await fs.stat(distPath);
600
- buildTimestamp = stats.mtime.toISOString();
601
- } catch {
602
- // dist/ doesn't exist or not accessible, skip
603
- }
604
-
605
- // Validate manifest structure
606
- const validation = validateManifest(entry.manifest);
607
-
608
- return {
609
- pluginId: entry.pluginId,
610
- manifest: entry.manifest,
611
- pluginRoot: entry.pluginRoot,
612
- source: entry.source,
613
- discoveredAt: snapshot.generatedAt,
614
- buildTimestamp,
615
- validation: {
616
- valid: validation.valid,
617
- errors: validation.errors,
618
- },
619
- };
620
- })
621
- );
622
-
623
- reply.type('application/json');
624
- return {
625
- manifests: manifestsWithTimestamps,
626
- apiBasePath: basePath,
627
- diagnostics: {
628
- total: snapshot.diagnostics?.length ?? 0,
629
- items: (snapshot.diagnostics ?? []).map((diagnostic) => ({
630
- severity: diagnostic.severity,
631
- code: diagnostic.code,
632
- reasonCode: mapRegistryDiagnosticReasonCode(diagnostic.code),
633
- message: diagnostic.message,
634
- pluginId: diagnostic.context?.pluginId,
635
- filePath: diagnostic.context?.filePath,
636
- remediation: diagnostic.remediation,
637
- ts: diagnostic.ts,
638
- })),
639
- },
640
- };
641
- } catch (error) {
642
- platform.logger.error(
643
- 'Failed to get plugin registry',
644
- error instanceof Error ? error : new Error(String(error))
645
- );
646
- reply.code(500).send({
647
- error: 'Failed to load plugin registry',
648
- message: error instanceof Error ? error.message : String(error),
649
- });
650
- }
651
- });
652
-
653
- // Studio Registry V2 — returns plugin pages and menus for Module Federation
654
- server.get(`${basePath}/studio/registry`, {
655
- schema: { tags: ['Studio'], summary: 'Get Studio Registry V2 (plugin pages for Module Federation)' },
656
- }, async (_request, reply) => {
657
- try {
658
- const snapshot = await restDomainOperationMetrics.observeOperation('plugin.studio.registry', async () =>
659
- registry.snapshot(),
660
- );
661
- const manifests = extractSnapshotManifests(snapshot);
662
-
663
- // Only plugins with studio V2 config
664
- const studioManifests = manifests
665
- .filter(entry => entry.manifest.studio?.version === 2)
666
- .map(entry => ({ manifest: entry.manifest, pluginRoot: entry.pluginRoot }));
667
-
668
- const studioRegistry = combineManifestsToRegistry(studioManifests);
669
-
670
- reply.type('application/json');
671
- return studioRegistry;
672
- } catch (error) {
673
- platform.logger.error('Failed to generate studio registry', error instanceof Error ? error : new Error(String(error)));
674
- reply.code(500).send({
675
- error: 'Failed to generate studio registry',
676
- message: error instanceof Error ? error.message : String(error),
677
- });
678
- }
679
- });
680
-
681
- // Widget bundle static files — serves dist/widgets/ from plugin packages
682
- server.get<{
683
- Params: { scope: string; name: string; '*': string };
684
- }>('/plugins/@:scope/:name/widgets/*', {
685
- schema: { hide: true },
686
- }, async (request, reply) => {
687
- const { scope, name } = request.params;
688
- const filePath = request.params['*'];
689
-
690
- if (!scope || !name || !filePath || filePath.includes('..')) {
691
- return reply.code(400).send({ error: 'Invalid path' });
692
- }
693
-
694
- const pluginId = `@${scope}/${name}`;
695
-
696
- // Find the plugin's widgetBundleDir from registry
697
- const snapshot = registry.snapshot();
698
- const manifests = extractSnapshotManifests(snapshot);
699
- const entry = manifests.find(e => e.manifest.id === pluginId && e.manifest.studio?.version === 2);
700
-
701
- if (!entry) {
702
- return reply.code(404).send({ error: `No widget bundle for ${pluginId}` });
703
- }
704
-
705
- const { join, extname } = await import('node:path');
706
- const { createReadStream, existsSync, statSync } = await import('node:fs');
707
-
708
- const bundleDir = join(entry.pluginRoot, 'dist', 'widgets');
709
- const fullPath = join(bundleDir, filePath);
710
-
711
- if (!fullPath.startsWith(bundleDir)) {
712
- return reply.code(400).send({ error: 'Invalid path' });
713
- }
714
-
715
- if (!existsSync(fullPath) || !statSync(fullPath).isFile()) {
716
- return reply.code(404).send({ error: `Widget file not found: ${pluginId}/widgets/${filePath}` });
717
- }
718
-
719
- const MIME: Record<string, string> = {
720
- '.js': 'application/javascript', '.mjs': 'application/javascript',
721
- '.css': 'text/css', '.json': 'application/json', '.map': 'application/json',
722
- };
723
-
724
- const ext = extname(filePath);
725
- const isEntry = filePath === 'remoteEntry.js';
726
-
727
- return reply
728
- .code(200)
729
- .header('Content-Type', MIME[ext] ?? 'application/octet-stream')
730
- .header('Content-Length', statSync(fullPath).size)
731
- .header('Cache-Control', isEntry ? 'public, max-age=10, must-revalidate' : 'public, max-age=31536000, immutable')
732
- .send(createReadStream(fullPath));
733
- });
734
-
735
- // Plugin registry health endpoint
736
- server.get(`${basePath}/plugins/health`, async (_request, reply) => {
737
- try {
738
- const snapshot = await restDomainOperationMetrics.observeOperation('plugin.registry.health', async () =>
739
- registry.snapshot(),
740
- );
741
-
742
- // Collect validation errors from all manifests
743
- const validationIssues: Array<{ pluginId: string; errors: string[] }> = [];
744
- for (const entry of snapshot.manifests) {
745
- const validation = validateManifest(entry.manifest);
746
- if (!validation.valid) {
747
- validationIssues.push({
748
- pluginId: entry.pluginId,
749
- errors: validation.errors,
750
- });
751
- }
752
- }
753
-
754
- // Registry resolution errors (plugins that failed to load)
755
- const registryErrors = (snapshot as any).errors ?? [];
756
- const discoveryDiagnostics = snapshot.diagnostics ?? [];
757
- const discoveryErrorCount = discoveryDiagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
758
-
759
- // Determine why registry is partial
760
- const partialReasons: string[] = [];
761
- if (snapshot.corrupted) {
762
- partialReasons.push('snapshot_corrupted');
763
- }
764
- if (registryErrors.length > 0) {
765
- partialReasons.push('registry_errors');
766
- }
767
- if (discoveryErrorCount > 0) {
768
- partialReasons.push('discovery_diagnostics');
769
- }
770
- // If partial but no clear reason, it's likely initialization
771
- if (snapshot.partial && partialReasons.length === 0) {
772
- partialReasons.push('initialization_incomplete');
773
- }
774
-
775
- reply.type('application/json');
776
- return {
777
- healthy: !snapshot.partial && !snapshot.stale && validationIssues.length === 0 && registryErrors.length === 0 && discoveryErrorCount === 0,
778
- snapshot: {
779
- partial: snapshot.partial,
780
- stale: snapshot.stale,
781
- corrupted: snapshot.corrupted,
782
- rev: snapshot.rev,
783
- generatedAt: snapshot.generatedAt,
784
- totalManifests: snapshot.manifests.length,
785
- partialReasons,
786
- },
787
- registryErrors: {
788
- total: registryErrors.length,
789
- items: registryErrors.map((err: any) => ({
790
- pluginPath: err.pluginPath,
791
- pluginId: err.pluginId,
792
- error: err.error,
793
- code: err.code,
794
- })),
795
- },
796
- diagnostics: {
797
- total: discoveryDiagnostics.length,
798
- errors: discoveryErrorCount,
799
- warnings: discoveryDiagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length,
800
- items: discoveryDiagnostics.map((diagnostic) => ({
801
- severity: diagnostic.severity,
802
- code: diagnostic.code,
803
- reasonCode: mapRegistryDiagnosticReasonCode(diagnostic.code),
804
- message: diagnostic.message,
805
- pluginId: diagnostic.context?.pluginId,
806
- filePath: diagnostic.context?.filePath,
807
- remediation: diagnostic.remediation,
808
- ts: diagnostic.ts,
809
- })),
810
- },
811
- validation: {
812
- totalIssues: validationIssues.length,
813
- issues: validationIssues,
814
- },
815
- message:
816
- registryErrors.length > 0
817
- ? `Registry is partial - ${registryErrors.length} plugin(s) failed to load. Check registryErrors.items for details.`
818
- : discoveryErrorCount > 0
819
- ? `Registry has discovery diagnostics - ${discoveryErrorCount} blocking issue(s). Check diagnostics.items for details.`
820
- : snapshot.partial && partialReasons.includes('initialization_incomplete')
821
- ? 'Registry is partial - initialization incomplete. Try refreshing or wait for the snapshot rebuild to complete.'
822
- : snapshot.partial
823
- ? `Registry is partial - reasons: ${partialReasons.join(', ')}`
824
- : snapshot.stale
825
- ? 'Registry is stale - plugin snapshot may be outdated.'
826
- : validationIssues.length > 0
827
- ? `${validationIssues.length} plugin(s) have validation errors.`
828
- : 'All plugins are healthy.',
829
- };
830
- } catch (error) {
831
- platform.logger.error('Failed to get plugin health', error instanceof Error ? error : new Error(String(error)));
832
- reply.code(500).send({
833
- error: 'Failed to get plugin health',
834
- message: error instanceof Error ? error.message : String(error),
835
- });
836
- }
837
- });
838
-
839
- // AI Assistant endpoint: ask questions about a plugin
840
- server.post(`${basePath}/plugins/:pluginId/ask`, async (request, reply) => {
841
- try {
842
- const { pluginId } = request.params as { pluginId: string };
843
- const { question } = request.body as { question: string };
844
-
845
- if (!question || typeof question !== 'string') {
846
- reply.code(400).send({
847
- error: 'Bad request',
848
- message: 'Question is required and must be a string',
849
- });
850
- return;
851
- }
852
-
853
- // Get plugin manifest
854
- const snapshot = await restDomainOperationMetrics.observeOperation('plugin.registry.snapshot', async () =>
855
- registry.snapshot(),
856
- );
857
- const pluginEntry = snapshot.manifests.find((entry) => entry.pluginId === pluginId);
858
-
859
- if (!pluginEntry) {
860
- reply.code(404).send({
861
- error: 'Plugin not found',
862
- message: `Plugin ${pluginId} not found in registry`,
863
- });
864
- return;
865
- }
866
-
867
- // Build prompt for LLM
868
- const systemPrompt = `You are a helpful assistant that explains KB Labs plugins based on their manifest.
869
- Provide clear, concise answers about the plugin's capabilities, API endpoints, permissions, and usage.
870
- Be specific and reference the actual values from the manifest.`;
871
-
872
- const userPrompt = `Plugin Manifest:
873
- ${JSON.stringify(pluginEntry.manifest, null, 2)}
874
-
875
- User Question: ${question}
876
-
877
- Please answer the question based on the plugin manifest above.`;
878
-
879
- // Call LLM
880
- const response = await restDomainOperationMetrics.observeOperation('plugin.assistant.ask', () =>
881
- platform.llm.complete(userPrompt, {
882
- systemPrompt,
883
- temperature: 0.3,
884
- maxTokens: 1000,
885
- }),
886
- );
887
-
888
- reply.type('application/json');
889
- return {
890
- answer: response.content,
891
- usage: response.usage,
892
- };
893
- } catch (error) {
894
- platform.logger.error('Failed to get AI answer about plugin', error instanceof Error ? error : new Error(String(error)));
895
- reply.code(500).send({
896
- error: 'Failed to get AI answer',
897
- message: error instanceof Error ? error.message : String(error),
898
- });
899
- }
900
- });
901
- }
902
-
903
- /**
904
- * Shutdown execution backend gracefully.
905
- * NOTE: ExecutionBackend is now owned by platform, shutdown via platform.shutdown()
906
- */
907
- export async function shutdownExecutionBackend(): Promise<void> {
908
- // ExecutionBackend lifecycle is now managed by platform
909
- // Call platform.shutdown() instead to shutdown all services including executionBackend
910
- await platform.shutdown();
911
- }
912
-
913
- function summarizeValidationErrors(errors: string[]): string {
914
- if (errors.length === 0) {
915
- return 'rest_validation_failed';
916
- }
917
- const first = errors[0] || 'rest_validation_failed';
918
- const prefix = first.split(':')[0]?.trim() ?? 'rest_validation_failed';
919
- return `rest_validation_failed ${prefix}`.trim();
920
- }
921
-
922
- function shortErrorMessage(error: unknown): string {
923
- if (!error) {
924
- return 'unknown_error';
925
- }
926
- const message = error instanceof Error ? error.message : String(error);
927
- const firstLine = message.trim().split('\n')[0] ?? message.trim();
928
- return firstLine.length > 120 ? `${firstLine.slice(0, 117)}...` : firstLine;
929
- }
930
-
931
- function mapDiagnosticSeverityToLogLevel(
932
- severity: 'error' | 'warning' | 'info' | 'debug',
933
- ): DiagnosticLogLevel {
934
- switch (severity) {
935
- case 'error':
936
- return 'error';
937
- case 'warning':
938
- return 'warn';
939
- case 'debug':
940
- return 'debug';
941
- default:
942
- return 'info';
943
- }
944
- }
945
-
946
- function mapRegistryDiagnosticReasonCode(code: string): DiagnosticReasonCode {
947
- switch (code) {
948
- case 'MANIFEST_NOT_FOUND':
949
- return 'manifest_missing';
950
- case 'MANIFEST_VALIDATION_ERROR':
951
- case 'MANIFEST_PARSE_ERROR':
952
- return 'manifest_invalid';
953
- case 'MANIFEST_LOAD_TIMEOUT':
954
- return 'manifest_load_timeout';
955
- case 'INTEGRITY_MISMATCH':
956
- return 'integrity_mismatch';
957
- default:
958
- return 'plugin_discovery_failed';
959
- }
960
- }
961
-
962
- function emitRegistrySnapshotDiagnostics(snapshot: RegistrySnapshot): void {
963
- for (const diagnostic of snapshot.diagnostics ?? []) {
964
- logDiagnosticEvent(platform.logger, {
965
- domain: 'registry',
966
- event: 'plugin.discovery.diagnostic',
967
- level: mapDiagnosticSeverityToLogLevel(diagnostic.severity),
968
- reasonCode: mapRegistryDiagnosticReasonCode(diagnostic.code),
969
- message: diagnostic.message,
970
- outcome: diagnostic.severity === 'error' ? 'failed' : 'skipped',
971
- pluginId: diagnostic.context?.pluginId,
972
- serviceId: 'rest',
973
- manifestPath: diagnostic.context?.filePath,
974
- discoveryCode: diagnostic.code,
975
- remediation: diagnostic.remediation,
976
- evidence: {
977
- severity: diagnostic.severity,
978
- entityKind: diagnostic.context?.entityKind,
979
- entityId: diagnostic.context?.entityId,
980
- ts: diagnostic.ts,
981
- },
982
- });
983
- }
984
- }
985
-
986
- function inferRouteValidationReasonCode(errors: string[]): DiagnosticReasonCode {
987
- if (errors.some((error) => error.includes('Handler file not found'))) {
988
- return 'handler_not_found';
989
- }
990
- return 'route_validation_failed';
991
- }
992
-
993
- function resolveRouteValidationLogLevel(
994
- errors: string[],
995
- totalRoutes: number,
996
- ): DiagnosticLogLevel {
997
- return errors.length >= totalRoutes ? 'error' : 'warn';
998
- }