@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.
- package/.kb/agents/sessions/session-1771531145393-ws3uh6q/turns.json +42 -0
- package/.kb/agents/sessions/session-1771548930486-ui6rtvm/turns.json +33 -0
- package/.kb/agents/sessions/session-1771549691485-nibqroq/turns.json +133 -0
- package/.kb/agents/sessions/session-1771550943182-dkwqdjc/turns.json +130 -0
- package/.kb/agents/sessions/session-1771551564182-cr4bwzn/turns.json +349 -0
- package/.kb/agents/sessions/session-1771552401370-g4ztwd1/turns.json +206 -0
- package/.kb/commit/current/plan.json +248 -0
- package/.kb/commit/current/status.json +472 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js +215 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js +271 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js +230 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js +228 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js +281 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js +266 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js +284 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/flags-WLdpSZl4.d.ts +77 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.d.ts +2 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js +441 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.d.ts +196 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js +441 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.d.ts +19 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js +48 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.d.ts +6 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js +170 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.d.ts +12 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.d.ts +22 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js +43 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.d.ts +26 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js +63 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.d.ts +16 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js +58 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js +50 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.d.ts +7 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js +39 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js +47 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.d.ts +14 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js +53 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js +54 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.d.ts +12 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js +51 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.d.ts +17 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js +133 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js.map +1 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js +46 -0
- package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js +215 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js +271 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js +230 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js +228 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js +281 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js +266 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js +284 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/flags-WLdpSZl4.d.ts +77 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.d.ts +2 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js +441 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.d.ts +196 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js +441 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.d.ts +19 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js +48 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.d.ts +6 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js +170 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.d.ts +12 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.d.ts +22 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js +52 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js +43 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.d.ts +26 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js +63 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.d.ts +16 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js +58 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.d.ts +9 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js +50 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.d.ts +7 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js +39 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.d.ts +10 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js +46 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js +47 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.d.ts +14 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js +53 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.d.ts +13 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js +54 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.d.ts +12 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js +51 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.d.ts +17 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js +133 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js.map +1 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.d.ts +11 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js +46 -0
- package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js.map +1 -0
- package/README.md +54 -0
- package/eslint.config.js +23 -0
- package/package.json +72 -0
- package/src/.kb/agents/sessions/session-1773470583796-ximqnfk/kpi-baseline.json +17 -0
- package/src/.kb/memory/sessions/session-1773470583796-ximqnfk/fact-sheet.json +1 -0
- package/src/bootstrap.ts +233 -0
- package/src/diagnostics/header-debug.ts +37 -0
- package/src/events/hub.ts +60 -0
- package/src/events/index.ts +1 -0
- package/src/index.ts +13 -0
- package/src/manifest.ts +21 -0
- package/src/middleware/__tests__/cache.spec.ts +184 -0
- package/src/middleware/__tests__/envelope.spec.ts +268 -0
- package/src/middleware/__tests__/metrics.redis.spec.ts +64 -0
- package/src/middleware/__tests__/rate-limit.spec.ts +283 -0
- package/src/middleware/__tests__/request-id.spec.ts +160 -0
- package/src/middleware/cache.ts +67 -0
- package/src/middleware/envelope.ts +136 -0
- package/src/middleware/error-guard.ts +69 -0
- package/src/middleware/index.ts +37 -0
- package/src/middleware/metrics.ts +810 -0
- package/src/middleware/mock-mode.ts +44 -0
- package/src/middleware/prom-metrics.ts +284 -0
- package/src/middleware/rate-limit-routes.ts +73 -0
- package/src/middleware/rate-limit.ts +72 -0
- package/src/middleware/request-id.ts +41 -0
- package/src/middleware/request-timeout.ts +69 -0
- package/src/middleware/security-headers.ts +24 -0
- package/src/middleware/startup-guard.ts +107 -0
- package/src/observability/service-contract.ts +192 -0
- package/src/plugins/index.ts +118 -0
- package/src/routes/__tests__/adapters-date-helpers.spec.ts +332 -0
- package/src/routes/__tests__/adapters.spec.ts +680 -0
- package/src/routes/__tests__/cache.spec.ts +264 -0
- package/src/routes/__tests__/events.spec.ts +434 -0
- package/src/routes/__tests__/health.spec.ts +414 -0
- package/src/routes/__tests__/logs.spec.ts +494 -0
- package/src/routes/__tests__/observability.spec.ts +392 -0
- package/src/routes/__tests__/plugins.spec.ts +931 -0
- package/src/routes/__tests__/workflow-management.spec.ts +698 -0
- package/src/routes/__tests__/workflows.spec.ts +204 -0
- package/src/routes/adapter-call.ts +220 -0
- package/src/routes/adapters.ts +1206 -0
- package/src/routes/analytics.ts +328 -0
- package/src/routes/cache.ts +104 -0
- package/src/routes/debug-routes.ts +95 -0
- package/src/routes/events.ts +115 -0
- package/src/routes/health.ts +348 -0
- package/src/routes/hello.ts +47 -0
- package/src/routes/index.ts +395 -0
- package/src/routes/jobs.ts +253 -0
- package/src/routes/logs.ts +718 -0
- package/src/routes/metrics.ts +120 -0
- package/src/routes/observability.ts +1388 -0
- package/src/routes/openapi.ts +101 -0
- package/src/routes/platform.ts +143 -0
- package/src/routes/plugins.ts +998 -0
- package/src/routes/readiness.ts +83 -0
- package/src/routes/workflow-management.ts +469 -0
- package/src/routes/workflows.ts +256 -0
- package/src/server.ts +203 -0
- package/src/services/historical-metrics.ts +496 -0
- package/src/services/incident-analyzer.ts +289 -0
- package/src/services/incident-detector.ts +691 -0
- package/src/services/incident-schema.sql +76 -0
- package/src/services/incident-storage.ts +593 -0
- package/src/services/system-metrics-collector.ts +244 -0
- package/src/types/fastify.d.ts +58 -0
- package/src/utils/__tests__/sse-auth.spec.ts +113 -0
- package/src/utils/path-helpers.ts +15 -0
- package/src/utils/repo.ts +42 -0
- package/src/utils/schema.ts +20 -0
- package/src/utils/sse-auth.ts +81 -0
- package/test-sandbox.sh +105 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +18 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/rest-api-app/routes
|
|
3
|
+
* Route registration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FastifyInstance } from 'fastify';
|
|
7
|
+
import type { RestApiConfig } from '@kb-labs/rest-api-core';
|
|
8
|
+
import type { IEntityRegistry } from '@kb-labs/core-registry';
|
|
9
|
+
|
|
10
|
+
type RedisStatus = {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
healthy: boolean;
|
|
13
|
+
roles: { publisher?: string | null; subscriber?: string | null; cache?: string | null };
|
|
14
|
+
};
|
|
15
|
+
import type { ISQLDatabase } from '@kb-labs/core-platform/adapters';
|
|
16
|
+
import { platform } from '@kb-labs/core-runtime';
|
|
17
|
+
import { EventHub } from '../events/hub';
|
|
18
|
+
import { registerEventRoutes } from './events';
|
|
19
|
+
import { registerHealthRoutes } from './health';
|
|
20
|
+
import { registerOpenAPIRoutes } from './openapi';
|
|
21
|
+
import { registerMetricsRoutes } from './metrics';
|
|
22
|
+
import { registerPluginRoutes, registerPluginSnapshotRoutes } from './plugins';
|
|
23
|
+
import { registerWorkflowRoutes } from './workflows';
|
|
24
|
+
import { registerJobsRoutes } from './jobs';
|
|
25
|
+
import { registerCacheRoutes } from './cache';
|
|
26
|
+
import { registerObservabilityRoutes } from './observability';
|
|
27
|
+
import { registerAnalyticsRoutes } from './analytics';
|
|
28
|
+
import { registerAdaptersRoutes } from './adapters';
|
|
29
|
+
import { registerLogRoutes } from './logs';
|
|
30
|
+
import { registerPlatformRoutes } from './platform';
|
|
31
|
+
import { registerAdapterCallRoutes } from './adapter-call';
|
|
32
|
+
import { registerDebugRoutes, registerRouteCollector } from './debug-routes';
|
|
33
|
+
import type { ReadinessState } from './readiness';
|
|
34
|
+
import { isReady, resolveReadinessReason } from './readiness';
|
|
35
|
+
import { metricsCollector } from '../middleware/metrics.js';
|
|
36
|
+
import { HistoricalMetricsCollector } from '../services/historical-metrics';
|
|
37
|
+
import { IncidentStorage } from '../services/incident-storage';
|
|
38
|
+
import { IncidentDetector } from '../services/incident-detector';
|
|
39
|
+
|
|
40
|
+
function normalizeBasePath(basePath?: string): string {
|
|
41
|
+
if (!basePath || basePath === '/') {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
return basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Register all routes
|
|
49
|
+
*/
|
|
50
|
+
export async function registerRoutes(
|
|
51
|
+
server: FastifyInstance,
|
|
52
|
+
config: RestApiConfig,
|
|
53
|
+
repoRoot: string,
|
|
54
|
+
registry: IEntityRegistry
|
|
55
|
+
): Promise<void> {
|
|
56
|
+
// Register route collector hook FIRST, before any routes are registered
|
|
57
|
+
// This allows us to collect all routes for the /routes endpoint
|
|
58
|
+
registerRouteCollector(server);
|
|
59
|
+
|
|
60
|
+
const initialSnapshot = registry.snapshot();
|
|
61
|
+
const initialRedisStatus = (registry as any).getRedisStatus?.();
|
|
62
|
+
const initialRedisStates = initialRedisStatus?.roles ?? {
|
|
63
|
+
publisher: null,
|
|
64
|
+
subscriber: null,
|
|
65
|
+
cache: null,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const registryLoaded =
|
|
69
|
+
initialSnapshot.plugins.length > 0 && !initialSnapshot.partial && !initialSnapshot.stale;
|
|
70
|
+
|
|
71
|
+
const readiness: ReadinessState = {
|
|
72
|
+
cliApiInitialized: true,
|
|
73
|
+
registryLoaded,
|
|
74
|
+
registryPartial: initialSnapshot.partial,
|
|
75
|
+
registryStale: initialSnapshot.stale,
|
|
76
|
+
pluginRoutesMounted: false,
|
|
77
|
+
pluginMountInProgress: true,
|
|
78
|
+
pluginRoutesCount: 0,
|
|
79
|
+
pluginRouteErrors: 0,
|
|
80
|
+
pluginRouteFailures: [],
|
|
81
|
+
lastPluginMountTs: null,
|
|
82
|
+
pluginRoutesLastDurationMs: null,
|
|
83
|
+
redisEnabled: initialRedisStatus?.enabled ?? false,
|
|
84
|
+
redisConnected: initialRedisStatus?.healthy ?? true,
|
|
85
|
+
redisStates: initialRedisStates,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleRedisUpdate = (status: RedisStatus) => {
|
|
89
|
+
metricsCollector.recordRedisStatus(status);
|
|
90
|
+
if (!readiness.redisEnabled && status.enabled) {
|
|
91
|
+
platform.logger.info('Redis support enabled', { redis: status });
|
|
92
|
+
}
|
|
93
|
+
if (readiness.redisConnected !== status.healthy) {
|
|
94
|
+
const message = 'Redis health status changed';
|
|
95
|
+
if (status.healthy) {
|
|
96
|
+
platform.logger.info(message, { redis: status });
|
|
97
|
+
} else {
|
|
98
|
+
platform.logger.warn(message, { redis: status });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const prevStates = readiness.redisStates;
|
|
102
|
+
if (
|
|
103
|
+
prevStates.publisher !== (status.roles.publisher ?? null) ||
|
|
104
|
+
prevStates.subscriber !== (status.roles.subscriber ?? null) ||
|
|
105
|
+
prevStates.cache !== (status.roles.cache ?? null)
|
|
106
|
+
) {
|
|
107
|
+
platform.logger.info('Redis role state changed', { redis: status.roles });
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (initialRedisStatus) {
|
|
112
|
+
handleRedisUpdate(initialRedisStatus);
|
|
113
|
+
}
|
|
114
|
+
server.kbReadiness = readiness;
|
|
115
|
+
|
|
116
|
+
const eventHub = server.kbEventHub ?? new EventHub();
|
|
117
|
+
server.kbEventHub = eventHub;
|
|
118
|
+
|
|
119
|
+
const broadcastState = async (): Promise<void> => {
|
|
120
|
+
const pluginsSnapshot = metricsCollector.getLastPluginMountSnapshot();
|
|
121
|
+
const redisStatus = (registry as any).getRedisStatus?.();
|
|
122
|
+
if (redisStatus) {
|
|
123
|
+
handleRedisUpdate(redisStatus);
|
|
124
|
+
readiness.redisEnabled = redisStatus.enabled;
|
|
125
|
+
readiness.redisConnected = redisStatus.healthy;
|
|
126
|
+
readiness.redisStates = {
|
|
127
|
+
publisher: redisStatus.roles.publisher ?? null,
|
|
128
|
+
subscriber: redisStatus.roles.subscriber ?? null,
|
|
129
|
+
cache: redisStatus.roles.cache ?? null,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const snapshot = registry.snapshot();
|
|
134
|
+
eventHub.publish({
|
|
135
|
+
type: 'registry',
|
|
136
|
+
rev: snapshot.rev,
|
|
137
|
+
generatedAt: snapshot.generatedAt,
|
|
138
|
+
partial: snapshot.partial,
|
|
139
|
+
stale: snapshot.stale,
|
|
140
|
+
expiresAt: snapshot.expiresAt ?? null,
|
|
141
|
+
ttlMs: snapshot.ttlMs ?? null,
|
|
142
|
+
checksum: snapshot.checksum ?? undefined,
|
|
143
|
+
checksumAlgorithm: snapshot.checksumAlgorithm,
|
|
144
|
+
previousChecksum: snapshot.previousChecksum ?? null,
|
|
145
|
+
});
|
|
146
|
+
} catch (error) {
|
|
147
|
+
platform.logger.warn('Failed to publish registry snapshot event', {
|
|
148
|
+
error: error instanceof Error ? error.message : String(error),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const health = await registry.getSystemHealth();
|
|
154
|
+
const ready = isReady(readiness);
|
|
155
|
+
const reason = resolveReadinessReason(readiness);
|
|
156
|
+
eventHub.publish({
|
|
157
|
+
type: 'health',
|
|
158
|
+
status: health.status,
|
|
159
|
+
ts: health.ts,
|
|
160
|
+
ready,
|
|
161
|
+
reason,
|
|
162
|
+
registryPartial: readiness.registryPartial,
|
|
163
|
+
registryStale: readiness.registryStale,
|
|
164
|
+
registryLoaded: readiness.registryLoaded,
|
|
165
|
+
pluginsMounted: pluginsSnapshot?.succeeded ?? 0,
|
|
166
|
+
pluginsFailed: pluginsSnapshot?.failed ?? 0,
|
|
167
|
+
pluginMountInProgress: readiness.pluginMountInProgress,
|
|
168
|
+
pluginRoutesMounted: readiness.pluginRoutesMounted,
|
|
169
|
+
lastPluginMountTs: readiness.lastPluginMountTs ?? null,
|
|
170
|
+
pluginRoutesLastDurationMs: readiness.pluginRoutesLastDurationMs ?? null,
|
|
171
|
+
redisEnabled: readiness.redisEnabled,
|
|
172
|
+
redisHealthy: readiness.redisConnected,
|
|
173
|
+
redisStates: readiness.redisStates,
|
|
174
|
+
});
|
|
175
|
+
} catch (error) {
|
|
176
|
+
platform.logger.warn('Failed to publish health event', {
|
|
177
|
+
error: error instanceof Error ? error.message : String(error),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
await broadcastState();
|
|
183
|
+
|
|
184
|
+
const runMount = async (): Promise<void> => {
|
|
185
|
+
try {
|
|
186
|
+
await registerPluginRoutes(server, config, repoRoot, registry, readiness);
|
|
187
|
+
} finally {
|
|
188
|
+
await broadcastState();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Initial mount - wait for completion before server starts listening
|
|
193
|
+
platform.logger.info('Starting initial plugin route mounting');
|
|
194
|
+
try {
|
|
195
|
+
await runMount();
|
|
196
|
+
platform.logger.info('Plugin route mounting completed');
|
|
197
|
+
} catch (error) {
|
|
198
|
+
platform.logger.error(
|
|
199
|
+
'Plugin route mounting failed',
|
|
200
|
+
error instanceof Error ? error : new Error(String(error))
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Create a resolved promise for initial mount (already completed)
|
|
205
|
+
let mountPromise = Promise.resolve();
|
|
206
|
+
|
|
207
|
+
const scheduleRemount = (): void => {
|
|
208
|
+
// Check if server is already listening - Fastify doesn't allow adding routes after listen()
|
|
209
|
+
// Check both Fastify's listening property and underlying Node.js server
|
|
210
|
+
const isListening = (server as any).listening ||
|
|
211
|
+
(server.server && (server.server as any).listening);
|
|
212
|
+
|
|
213
|
+
if (isListening) {
|
|
214
|
+
platform.logger.warn(
|
|
215
|
+
'Cannot remount plugin routes: server is already listening. Restart required.'
|
|
216
|
+
);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
readiness.pluginMountInProgress = true;
|
|
221
|
+
mountPromise = mountPromise
|
|
222
|
+
.catch(() => void 0)
|
|
223
|
+
.then(async () => {
|
|
224
|
+
// Double-check server is not listening before remount
|
|
225
|
+
const stillListening = (server as any).listening ||
|
|
226
|
+
(server.server && (server.server as any).listening);
|
|
227
|
+
|
|
228
|
+
if (stillListening) {
|
|
229
|
+
platform.logger.warn(
|
|
230
|
+
'Cannot remount plugin routes: server started listening during remount. Restart required.'
|
|
231
|
+
);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
platform.logger.info('Registry change detected, remounting plugin routes');
|
|
235
|
+
await runMount();
|
|
236
|
+
})
|
|
237
|
+
.then(() => {
|
|
238
|
+
platform.logger.info('Plugin route remount completed');
|
|
239
|
+
})
|
|
240
|
+
.catch(error => {
|
|
241
|
+
platform.logger.error(
|
|
242
|
+
'Plugin route remount failed',
|
|
243
|
+
error instanceof Error ? error : new Error(String(error))
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
(server as any).kbPluginMountPromise = mountPromise;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
registry.onChange(() => {
|
|
251
|
+
scheduleRemount();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const basePath = normalizeBasePath(config.basePath);
|
|
255
|
+
|
|
256
|
+
await registerHealthRoutes(server, config, repoRoot, registry, readiness);
|
|
257
|
+
|
|
258
|
+
await registerOpenAPIRoutes(server, config, repoRoot, registry);
|
|
259
|
+
|
|
260
|
+
registerMetricsRoutes(server, config);
|
|
261
|
+
|
|
262
|
+
await registerPluginSnapshotRoutes(server, config, registry);
|
|
263
|
+
|
|
264
|
+
// Workflow SSE streaming (long-lived connections that can't go through plugin execution)
|
|
265
|
+
// All CRUD operations are handled by the workflow plugin routes (/plugins/workflow/...)
|
|
266
|
+
await registerWorkflowRoutes(server, config);
|
|
267
|
+
|
|
268
|
+
// Register jobs management endpoints (scheduled jobs)
|
|
269
|
+
const cronManager = (platform as any).cron ?? null;
|
|
270
|
+
await registerJobsRoutes(server, config, cronManager);
|
|
271
|
+
|
|
272
|
+
const platformServices = platform;
|
|
273
|
+
|
|
274
|
+
await registerCacheRoutes(server, config, registry);
|
|
275
|
+
|
|
276
|
+
// Initialize historical metrics collector
|
|
277
|
+
const historicalCollector = new HistoricalMetricsCollector(
|
|
278
|
+
platformServices.cache,
|
|
279
|
+
{
|
|
280
|
+
intervalMs: 5000, // Collect every 5 seconds
|
|
281
|
+
debug: process.env.NODE_ENV !== 'production',
|
|
282
|
+
},
|
|
283
|
+
platformServices.logger as any
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
// Start background collection
|
|
287
|
+
historicalCollector.start();
|
|
288
|
+
platform.logger.info('Historical metrics collector started');
|
|
289
|
+
|
|
290
|
+
// Stop collector on server close
|
|
291
|
+
server.addHook('onClose', async () => {
|
|
292
|
+
historicalCollector.stop();
|
|
293
|
+
platform.logger.info('Historical metrics collector stopped');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Initialize incident storage (uses logs database, optional)
|
|
297
|
+
let incidentStorage: IncidentStorage | undefined;
|
|
298
|
+
const db = platform.getAdapter<ISQLDatabase>('db');
|
|
299
|
+
|
|
300
|
+
if (db) {
|
|
301
|
+
try {
|
|
302
|
+
// Initialize incidents schema
|
|
303
|
+
const { readFileSync } = await import('node:fs');
|
|
304
|
+
const { fileURLToPath } = await import('node:url');
|
|
305
|
+
const { dirname, join } = await import('node:path');
|
|
306
|
+
|
|
307
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
308
|
+
const __dirname = dirname(__filename);
|
|
309
|
+
const schemaPath = join(__dirname, '..', 'services', 'incident-schema.sql');
|
|
310
|
+
const schema = readFileSync(schemaPath, 'utf-8');
|
|
311
|
+
|
|
312
|
+
// Execute schema
|
|
313
|
+
if ('exec' in db && typeof (db as any).exec === 'function') {
|
|
314
|
+
await (db as any).exec(schema);
|
|
315
|
+
} else {
|
|
316
|
+
// Fallback: execute statements one by one
|
|
317
|
+
const statements = schema
|
|
318
|
+
.split(';')
|
|
319
|
+
.map(s => s.trim())
|
|
320
|
+
.filter(s => s.length > 0 && !s.startsWith('--'));
|
|
321
|
+
|
|
322
|
+
for (const statement of statements) {
|
|
323
|
+
if (statement) {
|
|
324
|
+
await db.query(statement);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
platform.logger.info('Incidents schema initialized');
|
|
330
|
+
|
|
331
|
+
// Create incident storage
|
|
332
|
+
incidentStorage = new IncidentStorage(
|
|
333
|
+
db,
|
|
334
|
+
{ debug: process.env.NODE_ENV !== 'production' },
|
|
335
|
+
platformServices.logger as any
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
platform.logger.info('Incident storage initialized');
|
|
339
|
+
} catch (err) {
|
|
340
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
341
|
+
platform.logger.warn('Failed to initialize incident storage, continuing without it', { error: error.message });
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
platform.logger.warn('Database adapter (db) not configured — incident storage disabled. Configure db adapter in kb.config.json to enable.');
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Initialize incident detector for auto-detection (only if storage available)
|
|
348
|
+
if (incidentStorage) {
|
|
349
|
+
const incidentDetector = new IncidentDetector(
|
|
350
|
+
incidentStorage,
|
|
351
|
+
{
|
|
352
|
+
intervalMs: 30000, // Check every 30 seconds
|
|
353
|
+
cooldownMs: 5 * 60 * 1000, // 5 minute cooldown between same incidents
|
|
354
|
+
debug: process.env.NODE_ENV !== 'production',
|
|
355
|
+
thresholds: {
|
|
356
|
+
errorRateWarning: 5,
|
|
357
|
+
errorRateCritical: 10,
|
|
358
|
+
latencyP99Warning: 2000,
|
|
359
|
+
latencyP99Critical: 5000,
|
|
360
|
+
latencyP95Warning: 1000,
|
|
361
|
+
minRequestsForDetection: 10,
|
|
362
|
+
pluginErrorRateWarning: 10,
|
|
363
|
+
pluginErrorRateCritical: 25,
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
platformServices.logger as any
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
// Start incident detector
|
|
370
|
+
incidentDetector.start();
|
|
371
|
+
platform.logger.info('Incident detector started');
|
|
372
|
+
|
|
373
|
+
// Stop detector on server close
|
|
374
|
+
server.addHook('onClose', async () => {
|
|
375
|
+
incidentDetector.stop();
|
|
376
|
+
platform.logger.info('Incident detector stopped');
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
await registerObservabilityRoutes(server, config, repoRoot, historicalCollector, incidentStorage, platformServices);
|
|
381
|
+
|
|
382
|
+
await registerAnalyticsRoutes(server, config);
|
|
383
|
+
|
|
384
|
+
await registerAdaptersRoutes(server, config);
|
|
385
|
+
|
|
386
|
+
await registerLogRoutes(server, config, eventHub);
|
|
387
|
+
|
|
388
|
+
await registerPlatformRoutes(server, config, repoRoot);
|
|
389
|
+
|
|
390
|
+
await registerAdapterCallRoutes(server);
|
|
391
|
+
|
|
392
|
+
await registerDebugRoutes(server, config);
|
|
393
|
+
|
|
394
|
+
await registerEventRoutes(server, basePath, registry, readiness, eventHub, config);
|
|
395
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/rest-api-app/routes/jobs
|
|
3
|
+
* Scheduled jobs management endpoints
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FastifyInstance } from 'fastify';
|
|
7
|
+
import type { ZodTypeProvider } from 'fastify-type-provider-zod';
|
|
8
|
+
import { serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';
|
|
9
|
+
import type { RestApiConfig } from '@kb-labs/rest-api-core';
|
|
10
|
+
import type { ICronManager } from '@kb-labs/core-platform';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import {
|
|
13
|
+
ListJobsQuerySchema,
|
|
14
|
+
JobsListResponseSchema,
|
|
15
|
+
JobResponseSchema,
|
|
16
|
+
JobStatsResponseSchema,
|
|
17
|
+
JobActionResponseSchema,
|
|
18
|
+
ErrorResponseSchema,
|
|
19
|
+
} from '@kb-labs/rest-api-contracts';
|
|
20
|
+
import { normalizeBasePath } from '../utils/path-helpers';
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Helper Functions
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
function createError(statusCode: number, code: string, message: string) {
|
|
27
|
+
const error = new Error(message);
|
|
28
|
+
(error as any).statusCode = statusCode;
|
|
29
|
+
(error as any).code = code;
|
|
30
|
+
return error;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getJobId(params: unknown): string {
|
|
34
|
+
const id = (params as { id?: unknown } | undefined)?.id;
|
|
35
|
+
if (!id || typeof id !== 'string') {
|
|
36
|
+
throw createError(400, 'JOB_ID_REQUIRED', 'Job id must be provided');
|
|
37
|
+
}
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Route Registration
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
export async function registerJobsRoutes(
|
|
46
|
+
server: FastifyInstance,
|
|
47
|
+
config: RestApiConfig,
|
|
48
|
+
cronManager: ICronManager | null,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
const basePath = normalizeBasePath(config.basePath);
|
|
51
|
+
|
|
52
|
+
// Encapsulate Zod compilers so they don't leak to other scopes (plugin routes use plain JSON schemas)
|
|
53
|
+
await server.register(async (scope) => {
|
|
54
|
+
scope.setValidatorCompiler(validatorCompiler);
|
|
55
|
+
scope.setSerializerCompiler(serializerCompiler);
|
|
56
|
+
const s = scope.withTypeProvider<ZodTypeProvider>();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* GET /api/v1/jobs
|
|
60
|
+
* List all scheduled jobs
|
|
61
|
+
*/
|
|
62
|
+
s.route({
|
|
63
|
+
method: 'GET',
|
|
64
|
+
url: `${basePath}/jobs`,
|
|
65
|
+
schema: {
|
|
66
|
+
tags: ['Jobs'],
|
|
67
|
+
summary: 'List scheduled jobs',
|
|
68
|
+
querystring: ListJobsQuerySchema,
|
|
69
|
+
response: {
|
|
70
|
+
200: JobsListResponseSchema,
|
|
71
|
+
503: ErrorResponseSchema,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
handler: async (request, reply) => {
|
|
75
|
+
if (!cronManager) {
|
|
76
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let jobs = cronManager.list();
|
|
80
|
+
|
|
81
|
+
if (request.query.status) {
|
|
82
|
+
jobs = jobs.filter((job) => job.status === request.query.status);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return reply.send({ jobs: jobs as any });
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* GET /api/v1/jobs/stats
|
|
91
|
+
* Get cron jobs statistics (must be before /:id to avoid route conflict)
|
|
92
|
+
*/
|
|
93
|
+
s.route({
|
|
94
|
+
method: 'GET',
|
|
95
|
+
url: `${basePath}/jobs/stats`,
|
|
96
|
+
schema: {
|
|
97
|
+
tags: ['Jobs'],
|
|
98
|
+
summary: 'Get cron jobs statistics',
|
|
99
|
+
response: {
|
|
100
|
+
200: JobStatsResponseSchema,
|
|
101
|
+
503: ErrorResponseSchema,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
handler: async (request, reply) => {
|
|
105
|
+
if (!cronManager) {
|
|
106
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const jobs = cronManager.list();
|
|
110
|
+
return reply.send({ stats: { total: jobs.length, jobs: jobs as any } });
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* GET /api/v1/jobs/:id
|
|
116
|
+
* Get job details
|
|
117
|
+
*/
|
|
118
|
+
s.route({
|
|
119
|
+
method: 'GET',
|
|
120
|
+
url: `${basePath}/jobs/:id`,
|
|
121
|
+
schema: {
|
|
122
|
+
tags: ['Jobs'],
|
|
123
|
+
summary: 'Get job details',
|
|
124
|
+
params: z.object({ id: z.string() }),
|
|
125
|
+
response: {
|
|
126
|
+
200: JobResponseSchema,
|
|
127
|
+
404: ErrorResponseSchema,
|
|
128
|
+
503: ErrorResponseSchema,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
handler: async (request, reply) => {
|
|
132
|
+
if (!cronManager) {
|
|
133
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const jobId = request.params.id;
|
|
137
|
+
const jobs = cronManager.list();
|
|
138
|
+
const job = jobs.find((j) => j.id === jobId);
|
|
139
|
+
|
|
140
|
+
if (!job) {
|
|
141
|
+
throw createError(404, 'JOB_NOT_FOUND', `Job ${jobId} not found`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return reply.send({ job: job as any });
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* POST /api/v1/jobs/:id/trigger
|
|
150
|
+
* Trigger job execution immediately
|
|
151
|
+
*/
|
|
152
|
+
s.route({
|
|
153
|
+
method: 'POST',
|
|
154
|
+
url: `${basePath}/jobs/:id/trigger`,
|
|
155
|
+
schema: {
|
|
156
|
+
tags: ['Jobs'],
|
|
157
|
+
summary: 'Trigger job execution immediately',
|
|
158
|
+
params: z.object({ id: z.string() }),
|
|
159
|
+
response: {
|
|
160
|
+
200: JobActionResponseSchema,
|
|
161
|
+
404: ErrorResponseSchema,
|
|
162
|
+
503: ErrorResponseSchema,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
handler: async (request, reply) => {
|
|
166
|
+
if (!cronManager) {
|
|
167
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const jobId = request.params.id;
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
await cronManager.trigger(jobId);
|
|
174
|
+
return reply.send({ success: true as const, message: `Job ${jobId} triggered successfully` });
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
177
|
+
throw createError(404, 'JOB_NOT_FOUND', `Job ${jobId} not found`);
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* POST /api/v1/jobs/:id/pause
|
|
186
|
+
* Pause job execution
|
|
187
|
+
*/
|
|
188
|
+
s.route({
|
|
189
|
+
method: 'POST',
|
|
190
|
+
url: `${basePath}/jobs/:id/pause`,
|
|
191
|
+
schema: {
|
|
192
|
+
tags: ['Jobs'],
|
|
193
|
+
summary: 'Pause job execution',
|
|
194
|
+
params: z.object({ id: z.string() }),
|
|
195
|
+
response: {
|
|
196
|
+
200: JobActionResponseSchema,
|
|
197
|
+
404: ErrorResponseSchema,
|
|
198
|
+
503: ErrorResponseSchema,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
handler: async (request, reply) => {
|
|
202
|
+
if (!cronManager) {
|
|
203
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const jobId = request.params.id;
|
|
207
|
+
const jobs = cronManager.list();
|
|
208
|
+
const job = jobs.find((j) => j.id === jobId);
|
|
209
|
+
if (!job) {
|
|
210
|
+
throw createError(404, 'JOB_NOT_FOUND', `Job ${jobId} not found`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
cronManager.pause(jobId);
|
|
214
|
+
return reply.send({ success: true as const, message: `Job ${jobId} paused successfully` });
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* POST /api/v1/jobs/:id/resume
|
|
220
|
+
* Resume paused job
|
|
221
|
+
*/
|
|
222
|
+
s.route({
|
|
223
|
+
method: 'POST',
|
|
224
|
+
url: `${basePath}/jobs/:id/resume`,
|
|
225
|
+
schema: {
|
|
226
|
+
tags: ['Jobs'],
|
|
227
|
+
summary: 'Resume paused job',
|
|
228
|
+
params: z.object({ id: z.string() }),
|
|
229
|
+
response: {
|
|
230
|
+
200: JobActionResponseSchema,
|
|
231
|
+
404: ErrorResponseSchema,
|
|
232
|
+
503: ErrorResponseSchema,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
handler: async (request, reply) => {
|
|
236
|
+
if (!cronManager) {
|
|
237
|
+
throw createError(503, 'CRON_UNAVAILABLE', 'Cron manager not available');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const jobId = request.params.id;
|
|
241
|
+
const jobs = cronManager.list();
|
|
242
|
+
const job = jobs.find((j) => j.id === jobId);
|
|
243
|
+
if (!job) {
|
|
244
|
+
throw createError(404, 'JOB_NOT_FOUND', `Job ${jobId} not found`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
cronManager.resume(jobId);
|
|
248
|
+
return reply.send({ success: true as const, message: `Job ${jobId} resumed successfully` });
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
}); // end encapsulated scope
|
|
253
|
+
}
|