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