@cyanautomation/kaseki-agent 1.4.1
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/.dockerignore +54 -0
- package/.eslintignore +11 -0
- package/.eslintrc.json +95 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +53 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +53 -0
- package/.github/ISSUE_TEMPLATE/security.md +51 -0
- package/.github/PULL_REQUEST_TEMPLATE/default.md +71 -0
- package/.github/dependabot.yml +38 -0
- package/.github/skills/dependency-cache-optimization/SKILL.md +526 -0
- package/.github/skills/docker-image-management/SKILL.md +532 -0
- package/.github/skills/frontend-design/SKILL.md +782 -0
- package/.github/skills/prompt-engineering/SKILL.md +360 -0
- package/.github/skills/quality-gate-config/SKILL.md +591 -0
- package/.github/skills/result-report-analysis/SKILL.md +576 -0
- package/.github/skills/test-automation/SKILL.md +593 -0
- package/.github/skills/workflow-diagnosis/SKILL.md +468 -0
- package/.github/workflows/build-docker-image.yml +453 -0
- package/.github/workflows/release.yml +68 -0
- package/.releaserc.json +135 -0
- package/CHANGELOG.md +117 -0
- package/CLAUDE.md +336 -0
- package/CONTRIBUTING.md +339 -0
- package/Dockerfile +217 -0
- package/README.md +1527 -0
- package/STYLE.md +521 -0
- package/add-js-extensions.d.ts +9 -0
- package/add-js-extensions.d.ts.map +1 -0
- package/add-js-extensions.js.map +1 -0
- package/dist/add-js-extensions.d.ts +9 -0
- package/dist/add-js-extensions.d.ts.map +1 -0
- package/dist/add-js-extensions.js +52 -0
- package/dist/add-js-extensions.js.map +1 -0
- package/dist/ansi-colors.d.ts +26 -0
- package/dist/ansi-colors.d.ts.map +1 -0
- package/dist/ansi-colors.js +51 -0
- package/dist/ansi-colors.js.map +1 -0
- package/dist/cli/BaseCommand.d.ts +18 -0
- package/dist/cli/BaseCommand.d.ts.map +1 -0
- package/dist/cli/BaseCommand.js +31 -0
- package/dist/cli/BaseCommand.js.map +1 -0
- package/dist/cli/KasekiCLI.d.ts +30 -0
- package/dist/cli/KasekiCLI.d.ts.map +1 -0
- package/dist/cli/KasekiCLI.js +134 -0
- package/dist/cli/KasekiCLI.js.map +1 -0
- package/dist/cli/commands/ConfigCommand.d.ts +13 -0
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -0
- package/dist/cli/commands/ConfigCommand.js +131 -0
- package/dist/cli/commands/ConfigCommand.js.map +1 -0
- package/dist/cli/commands/DoctorCommand.d.ts +45 -0
- package/dist/cli/commands/DoctorCommand.d.ts.map +1 -0
- package/dist/cli/commands/DoctorCommand.js +309 -0
- package/dist/cli/commands/DoctorCommand.js.map +1 -0
- package/dist/cli/commands/ListCommand.d.ts +9 -0
- package/dist/cli/commands/ListCommand.d.ts.map +1 -0
- package/dist/cli/commands/ListCommand.js +81 -0
- package/dist/cli/commands/ListCommand.js.map +1 -0
- package/dist/cli/commands/ReportCommand.d.ts +9 -0
- package/dist/cli/commands/ReportCommand.d.ts.map +1 -0
- package/dist/cli/commands/ReportCommand.js +98 -0
- package/dist/cli/commands/ReportCommand.js.map +1 -0
- package/dist/cli/commands/RunCommand.d.ts +13 -0
- package/dist/cli/commands/RunCommand.d.ts.map +1 -0
- package/dist/cli/commands/RunCommand.js +191 -0
- package/dist/cli/commands/RunCommand.js.map +1 -0
- package/dist/cli/commands/SecretsCommand.d.ts +9 -0
- package/dist/cli/commands/SecretsCommand.d.ts.map +1 -0
- package/dist/cli/commands/SecretsCommand.js +109 -0
- package/dist/cli/commands/SecretsCommand.js.map +1 -0
- package/dist/cli/commands/ServeCommand.d.ts +9 -0
- package/dist/cli/commands/ServeCommand.d.ts.map +1 -0
- package/dist/cli/commands/ServeCommand.js +50 -0
- package/dist/cli/commands/ServeCommand.js.map +1 -0
- package/dist/cli/commands/SetupCommand.d.ts +42 -0
- package/dist/cli/commands/SetupCommand.d.ts.map +1 -0
- package/dist/cli/commands/SetupCommand.js +249 -0
- package/dist/cli/commands/SetupCommand.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +395 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +446 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/docker/DockerManager.d.ts +69 -0
- package/dist/docker/DockerManager.d.ts.map +1 -0
- package/dist/docker/DockerManager.js +266 -0
- package/dist/docker/DockerManager.js.map +1 -0
- package/dist/event-aggregator.d.ts +71 -0
- package/dist/event-aggregator.d.ts.map +1 -0
- package/dist/event-aggregator.js +95 -0
- package/dist/event-aggregator.js.map +1 -0
- package/dist/github-app-token.d.ts +16 -0
- package/dist/github-app-token.d.ts.map +1 -0
- package/dist/github-app-token.js +148 -0
- package/dist/github-app-token.js.map +1 -0
- package/dist/idempotency-store.d.ts +61 -0
- package/dist/idempotency-store.d.ts.map +1 -0
- package/dist/idempotency-store.js +321 -0
- package/dist/idempotency-store.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/InstanceManager.d.ts +81 -0
- package/dist/instance/InstanceManager.d.ts.map +1 -0
- package/dist/instance/InstanceManager.js +220 -0
- package/dist/instance/InstanceManager.js.map +1 -0
- package/dist/instance-metadata-reader.d.ts +48 -0
- package/dist/instance-metadata-reader.d.ts.map +1 -0
- package/dist/instance-metadata-reader.js +94 -0
- package/dist/instance-metadata-reader.js.map +1 -0
- package/dist/instance-state-derivation.d.ts +42 -0
- package/dist/instance-state-derivation.d.ts.map +1 -0
- package/dist/instance-state-derivation.js +133 -0
- package/dist/instance-state-derivation.js.map +1 -0
- package/dist/job-scheduler.d.ts +124 -0
- package/dist/job-scheduler.d.ts.map +1 -0
- package/dist/job-scheduler.js +992 -0
- package/dist/job-scheduler.js.map +1 -0
- package/dist/kaseki-api-client.d.ts +89 -0
- package/dist/kaseki-api-client.d.ts.map +1 -0
- package/dist/kaseki-api-client.js +405 -0
- package/dist/kaseki-api-client.js.map +1 -0
- package/dist/kaseki-api-config.d.ts +34 -0
- package/dist/kaseki-api-config.d.ts.map +1 -0
- package/dist/kaseki-api-config.js +113 -0
- package/dist/kaseki-api-config.js.map +1 -0
- package/dist/kaseki-api-routes.d.ts +13 -0
- package/dist/kaseki-api-routes.d.ts.map +1 -0
- package/dist/kaseki-api-routes.js +559 -0
- package/dist/kaseki-api-routes.js.map +1 -0
- package/dist/kaseki-api-service-wrapper.d.ts +43 -0
- package/dist/kaseki-api-service-wrapper.d.ts.map +1 -0
- package/dist/kaseki-api-service-wrapper.js +150 -0
- package/dist/kaseki-api-service-wrapper.js.map +1 -0
- package/dist/kaseki-api-service.d.ts +16 -0
- package/dist/kaseki-api-service.d.ts.map +1 -0
- package/dist/kaseki-api-service.js +143 -0
- package/dist/kaseki-api-service.js.map +1 -0
- package/dist/kaseki-api-types.d.ts +440 -0
- package/dist/kaseki-api-types.d.ts.map +1 -0
- package/dist/kaseki-api-types.js +64 -0
- package/dist/kaseki-api-types.js.map +1 -0
- package/dist/kaseki-cli-lib.d.ts +219 -0
- package/dist/kaseki-cli-lib.d.ts.map +1 -0
- package/dist/kaseki-cli-lib.js +523 -0
- package/dist/kaseki-cli-lib.js.map +1 -0
- package/dist/kaseki-cli.d.ts +38 -0
- package/dist/kaseki-cli.d.ts.map +1 -0
- package/dist/kaseki-cli.js +559 -0
- package/dist/kaseki-cli.js.map +1 -0
- package/dist/kaseki-report.d.ts +3 -0
- package/dist/kaseki-report.d.ts.map +1 -0
- package/dist/kaseki-report.js +140 -0
- package/dist/kaseki-report.js.map +1 -0
- package/dist/lib/subprocess-helpers.d.ts +98 -0
- package/dist/lib/subprocess-helpers.d.ts.map +1 -0
- package/dist/lib/subprocess-helpers.js +136 -0
- package/dist/lib/subprocess-helpers.js.map +1 -0
- package/dist/logger.d.ts +39 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +79 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +19 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +59 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware/job-lookup.d.ts +27 -0
- package/dist/middleware/job-lookup.d.ts.map +1 -0
- package/dist/middleware/job-lookup.js +28 -0
- package/dist/middleware/job-lookup.js.map +1 -0
- package/dist/pi-event-filter.d.ts +3 -0
- package/dist/pi-event-filter.d.ts.map +1 -0
- package/dist/pi-event-filter.js +126 -0
- package/dist/pi-event-filter.js.map +1 -0
- package/dist/pi-progress-stream.d.ts +3 -0
- package/dist/pi-progress-stream.d.ts.map +1 -0
- package/dist/pi-progress-stream.js +205 -0
- package/dist/pi-progress-stream.js.map +1 -0
- package/dist/pi-progress-summarizer.d.ts +61 -0
- package/dist/pi-progress-summarizer.d.ts.map +1 -0
- package/dist/pi-progress-summarizer.js +246 -0
- package/dist/pi-progress-summarizer.js.map +1 -0
- package/dist/pre-flight-validator.d.ts +72 -0
- package/dist/pre-flight-validator.d.ts.map +1 -0
- package/dist/pre-flight-validator.js +513 -0
- package/dist/pre-flight-validator.js.map +1 -0
- package/dist/progress-stream-utils.d.ts +3 -0
- package/dist/progress-stream-utils.d.ts.map +1 -0
- package/dist/progress-stream-utils.js +15 -0
- package/dist/progress-stream-utils.js.map +1 -0
- package/dist/result-cache.d.ts +52 -0
- package/dist/result-cache.d.ts.map +1 -0
- package/dist/result-cache.js +134 -0
- package/dist/result-cache.js.map +1 -0
- package/dist/routes/artifact-routes.d.ts +10 -0
- package/dist/routes/artifact-routes.d.ts.map +1 -0
- package/dist/routes/artifact-routes.js +126 -0
- package/dist/routes/artifact-routes.js.map +1 -0
- package/dist/routes/log-routes.d.ts +8 -0
- package/dist/routes/log-routes.d.ts.map +1 -0
- package/dist/routes/log-routes.js +345 -0
- package/dist/routes/log-routes.js.map +1 -0
- package/dist/routes/status-routes.d.ts +8 -0
- package/dist/routes/status-routes.d.ts.map +1 -0
- package/dist/routes/status-routes.js +82 -0
- package/dist/routes/status-routes.js.map +1 -0
- package/dist/routes/webhook-routes.d.ts +6 -0
- package/dist/routes/webhook-routes.d.ts.map +1 -0
- package/dist/routes/webhook-routes.js +86 -0
- package/dist/routes/webhook-routes.js.map +1 -0
- package/dist/run-artifact-metadata-cache.d.ts +42 -0
- package/dist/run-artifact-metadata-cache.d.ts.map +1 -0
- package/dist/run-artifact-metadata-cache.js +139 -0
- package/dist/run-artifact-metadata-cache.js.map +1 -0
- package/dist/secret-value-cache.d.ts +13 -0
- package/dist/secret-value-cache.d.ts.map +1 -0
- package/dist/secret-value-cache.js +44 -0
- package/dist/secret-value-cache.js.map +1 -0
- package/dist/secrets/SecretsManager.d.ts +80 -0
- package/dist/secrets/SecretsManager.d.ts.map +1 -0
- package/dist/secrets/SecretsManager.js +306 -0
- package/dist/secrets/SecretsManager.js.map +1 -0
- package/dist/test-utils.d.ts +55 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +48 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/timestamp-tracker.d.ts +75 -0
- package/dist/timestamp-tracker.d.ts.map +1 -0
- package/dist/timestamp-tracker.js +121 -0
- package/dist/timestamp-tracker.js.map +1 -0
- package/dist/utils/failure-artifact-writer.d.ts +29 -0
- package/dist/utils/failure-artifact-writer.d.ts.map +1 -0
- package/dist/utils/failure-artifact-writer.js +157 -0
- package/dist/utils/failure-artifact-writer.js.map +1 -0
- package/dist/utils/file-helpers.d.ts +41 -0
- package/dist/utils/file-helpers.d.ts.map +1 -0
- package/dist/utils/file-helpers.js +143 -0
- package/dist/utils/file-helpers.js.map +1 -0
- package/dist/utils/http-client-factory.d.ts +46 -0
- package/dist/utils/http-client-factory.d.ts.map +1 -0
- package/dist/utils/http-client-factory.js +114 -0
- package/dist/utils/http-client-factory.js.map +1 -0
- package/dist/utils/progress-normalizer.d.ts +13 -0
- package/dist/utils/progress-normalizer.d.ts.map +1 -0
- package/dist/utils/progress-normalizer.js +57 -0
- package/dist/utils/progress-normalizer.js.map +1 -0
- package/dist/utils/response-helpers.d.ts +34 -0
- package/dist/utils/response-helpers.d.ts.map +1 -0
- package/dist/utils/response-helpers.js +78 -0
- package/dist/utils/response-helpers.js.map +1 -0
- package/dist/utils/route-helpers.d.ts +17 -0
- package/dist/utils/route-helpers.d.ts.map +1 -0
- package/dist/utils/route-helpers.js +22 -0
- package/dist/utils/route-helpers.js.map +1 -0
- package/dist/utils/status-response-builder.d.ts +23 -0
- package/dist/utils/status-response-builder.d.ts.map +1 -0
- package/dist/utils/status-response-builder.js +144 -0
- package/dist/utils/status-response-builder.js.map +1 -0
- package/dist/utils/type-guards.d.ts +37 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +45 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/dist/utils/utf8-helpers.d.ts +32 -0
- package/dist/utils/utf8-helpers.d.ts.map +1 -0
- package/dist/utils/utf8-helpers.js +97 -0
- package/dist/utils/utf8-helpers.js.map +1 -0
- package/dist/utils/webhook-event-builder.d.ts +26 -0
- package/dist/utils/webhook-event-builder.d.ts.map +1 -0
- package/dist/utils/webhook-event-builder.js +77 -0
- package/dist/utils/webhook-event-builder.js.map +1 -0
- package/dist/webhook-manager.d.ts +56 -0
- package/dist/webhook-manager.d.ts.map +1 -0
- package/dist/webhook-manager.js +359 -0
- package/dist/webhook-manager.js.map +1 -0
- package/docker/workspace-cache/package-lock.json +13 -0
- package/docker/workspace-cache/package.json +7 -0
- package/docker-compose.yml +53 -0
- package/docs/API.md +708 -0
- package/docs/BACKLOG.md +19 -0
- package/docs/BUILD_STRATEGY.md +404 -0
- package/docs/CLI.md +569 -0
- package/docs/DEPLOYMENT.md +521 -0
- package/docs/DEVELOPMENT.md +459 -0
- package/docs/DOCKER_SETUP.md +522 -0
- package/docs/ENHANCED_PROGRESS_LOGS.md +264 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +549 -0
- package/docs/INTEGRATION_EXAMPLE.md +217 -0
- package/docs/NPM_SETUP.md +468 -0
- package/docs/PHASE1-4_IMPLEMENTATION.md +302 -0
- package/docs/PHASE1_COMPLETION.md +192 -0
- package/docs/PHASE2_COMPLETION.md +134 -0
- package/docs/PHASE6_MIGRATION.md +392 -0
- package/docs/PRINTF_SAFETY_FIX.md +282 -0
- package/docs/QUALITY_GATES.md +369 -0
- package/docs/SETUP_GUIDE.md +482 -0
- package/docs/TASK_PROMPT_TEMPLATES.md +533 -0
- package/docs/VALIDATION_FIX.md +139 -0
- package/docs/VERIFICATION_CHECKLIST.md +335 -0
- package/docs/repo-maturity.md +760 -0
- package/fix-tests.d.ts +9 -0
- package/fix-tests.d.ts.map +1 -0
- package/fix-tests.js.map +1 -0
- package/fix-tests.ts +53 -0
- package/jest.config.ts +31 -0
- package/kaseki +183 -0
- package/kaseki-agent.sh +1961 -0
- package/ops/logrotate/kaseki +10 -0
- package/package.json +83 -0
- package/perf/README.md +54 -0
- package/perf/pi-event-filter.benchmark.test.ts +98 -0
- package/run-kaseki-json.test.sh +106 -0
- package/run-kaseki.sh +990 -0
- package/scripts/allowlist-helper.sh +56 -0
- package/scripts/cleanup-kaseki.sh +168 -0
- package/scripts/deploy-pi-template.sh +293 -0
- package/scripts/docker-entrypoint.sh +71 -0
- package/scripts/dry-run-allowlist.sh +161 -0
- package/scripts/kaseki-activate.sh +396 -0
- package/scripts/kaseki-api.service +62 -0
- package/scripts/kaseki-container-entrypoint-wrapper.sh +119 -0
- package/scripts/kaseki-container-setup-remote.sh +172 -0
- package/scripts/kaseki-container-setup.sh +193 -0
- package/scripts/kaseki-healthcheck.sh +95 -0
- package/scripts/kaseki-install.sh +50 -0
- package/scripts/kaseki-maturity-score.sh +291 -0
- package/scripts/kaseki-performance-metrics.sh +122 -0
- package/scripts/kaseki-preflight.sh +270 -0
- package/scripts/kaseki-setup.sh +265 -0
- package/scripts/pi-setup-remote.sh +213 -0
- package/scripts/setup-github-labels.sh +42 -0
- package/scripts/suggest-allowlist.sh +68 -0
- package/scripts/templates/MULTI_HOST_DISTRIBUTED.md +337 -0
- package/scripts/templates/REST_API_SERVICE.md +490 -0
- package/scripts/templates/SINGLE_HOST_CLI.md +194 -0
- package/scripts/test-github-app.sh +248 -0
- package/src/add-js-extensions.ts +61 -0
- package/src/ansi-colors.test.ts +62 -0
- package/src/ansi-colors.ts +67 -0
- package/src/cli/BaseCommand.ts +40 -0
- package/src/cli/KasekiCLI.ts +154 -0
- package/src/cli/commands/ConfigCommand.ts +145 -0
- package/src/cli/commands/DoctorCommand.ts +329 -0
- package/src/cli/commands/ListCommand.ts +105 -0
- package/src/cli/commands/ReportCommand.ts +110 -0
- package/src/cli/commands/RunCommand.ts +218 -0
- package/src/cli/commands/SecretsCommand.ts +120 -0
- package/src/cli/commands/ServeCommand.ts +62 -0
- package/src/cli/commands/SetupCommand.ts +301 -0
- package/src/cli.ts +138 -0
- package/src/config/ConfigManager.ts +476 -0
- package/src/docker/DockerManager.ts +319 -0
- package/src/docker-entrypoint-packaging.test.ts +33 -0
- package/src/event-aggregator.test.ts +117 -0
- package/src/event-aggregator.ts +126 -0
- package/src/github-app-token.ts +215 -0
- package/src/idempotency-store.test.ts +117 -0
- package/src/idempotency-store.ts +385 -0
- package/src/index.ts +89 -0
- package/src/instance/InstanceManager.ts +285 -0
- package/src/instance-metadata-reader.test.ts +190 -0
- package/src/instance-metadata-reader.ts +129 -0
- package/src/instance-state-derivation.test.ts +263 -0
- package/src/instance-state-derivation.ts +148 -0
- package/src/job-scheduler.test.ts +1236 -0
- package/src/job-scheduler.ts +1117 -0
- package/src/kaseki-api-client.ts +488 -0
- package/src/kaseki-api-config.test.ts +315 -0
- package/src/kaseki-api-config.ts +175 -0
- package/src/kaseki-api-routes.test.ts +1615 -0
- package/src/kaseki-api-routes.ts +643 -0
- package/src/kaseki-api-service-wrapper.ts +188 -0
- package/src/kaseki-api-service.test.ts +418 -0
- package/src/kaseki-api-service.ts +192 -0
- package/src/kaseki-api-types.ts +320 -0
- package/src/kaseki-cli-lib.test.ts +552 -0
- package/src/kaseki-cli-lib.ts +760 -0
- package/src/kaseki-cli.ts +682 -0
- package/src/kaseki-report.test.ts +118 -0
- package/src/kaseki-report.ts +192 -0
- package/src/lib/subprocess-helpers.ts +177 -0
- package/src/logger.ts +114 -0
- package/src/metrics.ts +66 -0
- package/src/middleware/job-lookup.test.ts +113 -0
- package/src/middleware/job-lookup.ts +45 -0
- package/src/pi-event-filter.test.ts +183 -0
- package/src/pi-event-filter.ts +183 -0
- package/src/pi-progress-stream.ts +287 -0
- package/src/pi-progress-summarizer.test.ts +302 -0
- package/src/pi-progress-summarizer.ts +287 -0
- package/src/pre-flight-validator.test.ts +512 -0
- package/src/pre-flight-validator.ts +618 -0
- package/src/progress-stream-utils.test.ts +35 -0
- package/src/progress-stream-utils.ts +14 -0
- package/src/result-cache.test.ts +195 -0
- package/src/result-cache.ts +181 -0
- package/src/routes/artifact-routes.ts +169 -0
- package/src/routes/log-routes.ts +391 -0
- package/src/routes/status-routes.ts +92 -0
- package/src/routes/webhook-routes.ts +97 -0
- package/src/run-artifact-metadata-cache.test.ts +80 -0
- package/src/run-artifact-metadata-cache.ts +184 -0
- package/src/secret-value-cache.test.ts +66 -0
- package/src/secret-value-cache.ts +55 -0
- package/src/secrets/SecretsManager.ts +343 -0
- package/src/test-utils.ts +81 -0
- package/src/timestamp-tracker.test.ts +134 -0
- package/src/timestamp-tracker.ts +132 -0
- package/src/utils/failure-artifact-writer.ts +187 -0
- package/src/utils/file-helpers.test.ts +235 -0
- package/src/utils/file-helpers.ts +150 -0
- package/src/utils/http-client-factory.test.ts +245 -0
- package/src/utils/http-client-factory.ts +157 -0
- package/src/utils/progress-normalizer.test.ts +442 -0
- package/src/utils/progress-normalizer.ts +68 -0
- package/src/utils/response-helpers.test.ts +122 -0
- package/src/utils/response-helpers.ts +101 -0
- package/src/utils/route-helpers.ts +30 -0
- package/src/utils/status-response-builder.ts +159 -0
- package/src/utils/type-guards.ts +52 -0
- package/src/utils/utf8-helpers.ts +102 -0
- package/src/utils/webhook-event-builder.test.ts +143 -0
- package/src/utils/webhook-event-builder.ts +87 -0
- package/src/webhook-manager.test.ts +152 -0
- package/src/webhook-manager.ts +445 -0
- package/templates/allowlist-api-route.txt +7 -0
- package/templates/allowlist-comprehensive.txt +8 -0
- package/templates/allowlist-parser-fix.txt +6 -0
- package/templates/allowlist-ui-component.txt +9 -0
- package/templates/allowlist-utility.txt +9 -0
- package/test/actual-model-metadata.test.sh +102 -0
- package/test/dry-run.test.sh +131 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-0.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-1.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-invalid.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-0.json +1 -0
- package/test/fixtures/kaseki-report-exit-codes/metadata-exit-str-1.json +1 -0
- package/test/kaseki-api.integration.test.sh +165 -0
- package/test/pi-event-filter-failure.test.sh +83 -0
- package/test/printf-safety-focused.test.sh +99 -0
- package/test/printf-safety-results/results/restoration.jsonl +10 -0
- package/test/printf-safety-results/results/test.jsonl +0 -0
- package/test/printf-safety.test.sh +297 -0
- package/test/validation-fix.test.sh +79 -0
- package/test/validation-integration.test.sh +109 -0
- package/tests/allowlist-glob.test.sh +61 -0
- package/tests/dependency-cache-key.test.sh +48 -0
- package/tests/dependency-restore-mode.test.sh +48 -0
- package/tests/doctor-template-parity.test.sh +95 -0
- package/tests/github-operations.test.sh +142 -0
- package/tests/npm-install-flags.test.sh +58 -0
- package/tests/quality-gates.test.sh +178 -0
- package/tests/repo-memory.test.sh +103 -0
- package/tests/restore-disallowed-changes.test.sh +80 -0
- package/tests/validation-missing-npm-scripts.test.sh +93 -0
- package/tests/validation-strict-mode.test.sh +118 -0
- package/tsconfig.changed.json +7 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { RunRequest, RunResponse, StatusResponse, AnalysisResponse, RunsListResponse, ValidationResponse } from './kaseki-api-types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Zod schemas for response validation.
|
|
7
|
+
* Replaces manual type-checking with declarative schema validation.
|
|
8
|
+
*/
|
|
9
|
+
const HealthResponseSchema = z.object({
|
|
10
|
+
status: z.string(),
|
|
11
|
+
errors: z.array(z.string()).optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const ValidationResponseSchema = z.object({
|
|
15
|
+
isValid: z.boolean(),
|
|
16
|
+
checks: z.array(z.any()),
|
|
17
|
+
warnings: z.array(z.any()),
|
|
18
|
+
errors: z.array(z.any()),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const StructuredProgressSchema = z.object({
|
|
22
|
+
stage: z.string(),
|
|
23
|
+
percentComplete: z.number().optional(),
|
|
24
|
+
message: z.string().optional(),
|
|
25
|
+
updatedAt: z.string().optional(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const StatusResponseSchema = z.object({
|
|
29
|
+
id: z.string(),
|
|
30
|
+
status: z.enum(['queued', 'running', 'completed', 'failed']),
|
|
31
|
+
failureClass: z.string().optional(),
|
|
32
|
+
error: z.string().optional(),
|
|
33
|
+
exitCode: z.number().optional(),
|
|
34
|
+
elapsedSeconds: z.number().optional(),
|
|
35
|
+
timeoutRiskPercent: z.number().optional(),
|
|
36
|
+
correlationId: z.string().optional(),
|
|
37
|
+
requestId: z.string().optional(),
|
|
38
|
+
resultDir: z.string().optional(),
|
|
39
|
+
progress: StructuredProgressSchema.optional(),
|
|
40
|
+
artifacts: z.object({
|
|
41
|
+
metadataJson: z.boolean(),
|
|
42
|
+
analysisMd: z.boolean(),
|
|
43
|
+
resultSummaryMd: z.boolean(),
|
|
44
|
+
failureJson: z.boolean(),
|
|
45
|
+
stderrLog: z.boolean(),
|
|
46
|
+
availableFiles: z.array(z.string()),
|
|
47
|
+
}).optional(),
|
|
48
|
+
diagnosticEntryPoint: z.enum(['failure.json', 'analysis.md', 'result-summary.md']).optional(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const RunResponseSchema = z.object({
|
|
52
|
+
id: z.string(),
|
|
53
|
+
createdAt: z.string(),
|
|
54
|
+
status: z.enum(['queued', 'running', 'completed', 'failed']),
|
|
55
|
+
error: z.string().optional(),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const ProgressResponseSchema = z.object({
|
|
59
|
+
events: z.array(z.record(z.unknown())),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const AnalysisResponseSchema = z.object({
|
|
63
|
+
id: z.string(),
|
|
64
|
+
createdAt: z.string(),
|
|
65
|
+
status: z.enum(['queued', 'running', 'completed', 'failed']),
|
|
66
|
+
completedAt: z.string().optional(),
|
|
67
|
+
elapsedSeconds: z.number().optional(),
|
|
68
|
+
exitCode: z.number().optional(),
|
|
69
|
+
failureClass: z.string().optional(),
|
|
70
|
+
metadata: z.object({
|
|
71
|
+
model: z.string().optional(),
|
|
72
|
+
instance: z.string().optional(),
|
|
73
|
+
repo: z.string().optional(),
|
|
74
|
+
ref: z.string().optional(),
|
|
75
|
+
}).optional(),
|
|
76
|
+
changes: z.object({
|
|
77
|
+
changedFiles: z.array(z.string()),
|
|
78
|
+
diffSize: z.number(),
|
|
79
|
+
}).optional(),
|
|
80
|
+
validation: z.object({
|
|
81
|
+
passed: z.boolean(),
|
|
82
|
+
commandResults: z.array(z.object({
|
|
83
|
+
command: z.string(),
|
|
84
|
+
exitCode: z.number(),
|
|
85
|
+
elapsed: z.number(),
|
|
86
|
+
})),
|
|
87
|
+
}).optional(),
|
|
88
|
+
errors: z.array(z.string()).optional(),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const LogResponseSchema = z.object({
|
|
92
|
+
content: z.string(),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const ArtifactResponseSchema = z.object({
|
|
96
|
+
content: z.string(),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const RunsListResponseSchema = z.object({
|
|
100
|
+
runs: z.array(z.object({
|
|
101
|
+
id: z.string(),
|
|
102
|
+
status: z.enum(['queued', 'running', 'completed', 'failed']),
|
|
103
|
+
createdAt: z.string(),
|
|
104
|
+
completedAt: z.string().optional(),
|
|
105
|
+
resultDir: z.string().optional(),
|
|
106
|
+
exitCode: z.number().optional(),
|
|
107
|
+
failureClass: z.string().optional(),
|
|
108
|
+
error: z.string().optional(),
|
|
109
|
+
})),
|
|
110
|
+
total: z.number(),
|
|
111
|
+
retention: z.object({
|
|
112
|
+
terminalJobIndexMaxEntries: z.number(),
|
|
113
|
+
note: z.string(),
|
|
114
|
+
}).optional(),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Kaseki API client for TypeScript/Node.js applications.
|
|
119
|
+
* Simplifies integration with the Kaseki API service.
|
|
120
|
+
*
|
|
121
|
+
* Example:
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const client = new KasekiApiClient('http://localhost:8080', 'sk-api-key');
|
|
124
|
+
*
|
|
125
|
+
* const run = await client.submit({
|
|
126
|
+
* repoUrl: 'https://github.com/org/repo',
|
|
127
|
+
* taskPrompt: 'Fix the bug'
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* console.log(`Run started: ${run.id}`);
|
|
131
|
+
*
|
|
132
|
+
* // Monitor
|
|
133
|
+
* const status = await client.getStatus(run.id);
|
|
134
|
+
* console.log(`Status: ${status.status}, elapsed: ${status.elapsedSeconds}s`);
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export class KasekiApiClient {
|
|
138
|
+
private baseUrl: string;
|
|
139
|
+
private baseHeaders: Record<string, string>;
|
|
140
|
+
private retryConfig = {
|
|
141
|
+
maxAttempts: 3,
|
|
142
|
+
initialDelayMs: 1000,
|
|
143
|
+
maxDelayMs: 8000,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
constructor(baseUrl: string, apiKey: string, retryConfig?: Partial<typeof KasekiApiClient.prototype.retryConfig>) {
|
|
147
|
+
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
148
|
+
this.baseHeaders = {
|
|
149
|
+
'Content-Type': 'application/json',
|
|
150
|
+
Authorization: `Bearer ${apiKey}`,
|
|
151
|
+
};
|
|
152
|
+
if (retryConfig) {
|
|
153
|
+
this.retryConfig = { ...this.retryConfig, ...retryConfig };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private parseErrorDetail(value: unknown): string | undefined {
|
|
158
|
+
try {
|
|
159
|
+
const parsed = z.object({ detail: z.string() }).safeParse(value);
|
|
160
|
+
return parsed.success ? parsed.data.detail : undefined;
|
|
161
|
+
} catch {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Check API health.
|
|
168
|
+
*/
|
|
169
|
+
async getHealth(): Promise<{ status: string; errors?: string[] }> {
|
|
170
|
+
const res = await fetch(`${this.baseUrl}/api/health`, {
|
|
171
|
+
method: 'GET',
|
|
172
|
+
headers: {},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
if (!res.ok) {
|
|
176
|
+
throw new Error(`Health check failed: ${res.status}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const data = await res.json();
|
|
180
|
+
return HealthResponseSchema.parse(data);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Retry helper with exponential backoff.
|
|
185
|
+
*/
|
|
186
|
+
private async retryWithBackoff<T>(
|
|
187
|
+
fn: () => Promise<T>,
|
|
188
|
+
description: string = 'Operation'
|
|
189
|
+
): Promise<T> {
|
|
190
|
+
let lastError: Error | undefined;
|
|
191
|
+
|
|
192
|
+
for (let attempt = 0; attempt < this.retryConfig.maxAttempts; attempt++) {
|
|
193
|
+
try {
|
|
194
|
+
return await fn();
|
|
195
|
+
} catch (error) {
|
|
196
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
197
|
+
|
|
198
|
+
// Don't retry on 4xx errors (except 429 Too Many Requests)
|
|
199
|
+
if (
|
|
200
|
+
lastError.message.includes('400') ||
|
|
201
|
+
lastError.message.includes('401') ||
|
|
202
|
+
lastError.message.includes('403') ||
|
|
203
|
+
lastError.message.includes('404')
|
|
204
|
+
) {
|
|
205
|
+
throw lastError;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// If this is the last attempt, throw
|
|
209
|
+
if (attempt === this.retryConfig.maxAttempts - 1) {
|
|
210
|
+
throw lastError;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Calculate backoff
|
|
214
|
+
const delayMs = Math.min(
|
|
215
|
+
this.retryConfig.initialDelayMs * Math.pow(2, attempt),
|
|
216
|
+
this.retryConfig.maxDelayMs
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// Wait before retrying
|
|
220
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
throw lastError || new Error(`${description} failed after ${this.retryConfig.maxAttempts} attempts`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Validate a job request before submission.
|
|
229
|
+
*/
|
|
230
|
+
async validate(request: RunRequest): Promise<ValidationResponse> {
|
|
231
|
+
const res = await fetch(`${this.baseUrl}/api/validate`, {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
headers: this.baseHeaders,
|
|
234
|
+
body: JSON.stringify(request),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
if (!res.ok) {
|
|
238
|
+
let errorDetail: string | undefined;
|
|
239
|
+
try {
|
|
240
|
+
const errorData = await res.json();
|
|
241
|
+
errorDetail = this.parseErrorDetail(errorData);
|
|
242
|
+
} catch {
|
|
243
|
+
// Ignore
|
|
244
|
+
}
|
|
245
|
+
throw new Error(`Validation failed: ${errorDetail ?? res.statusText}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const data = await res.json();
|
|
249
|
+
return ValidationResponseSchema.parse(data);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Submit a new kaseki run with automatic retry and idempotency support.
|
|
254
|
+
*/
|
|
255
|
+
async submit(request: RunRequest): Promise<RunResponse> {
|
|
256
|
+
// Auto-generate idempotency key if not provided
|
|
257
|
+
const idempotencyKey = request.idempotencyKey || randomUUID();
|
|
258
|
+
const requestWithIdempotency = { ...request, idempotencyKey };
|
|
259
|
+
|
|
260
|
+
// Perform submission with retry logic
|
|
261
|
+
return this.retryWithBackoff(async () => {
|
|
262
|
+
const res = await fetch(`${this.baseUrl}/api/runs`, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
headers: this.baseHeaders,
|
|
265
|
+
body: JSON.stringify(requestWithIdempotency),
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
if (!res.ok) {
|
|
269
|
+
let errorDetail: string | undefined;
|
|
270
|
+
try {
|
|
271
|
+
const errorData = await res.json();
|
|
272
|
+
errorDetail = this.parseErrorDetail(errorData);
|
|
273
|
+
} catch {
|
|
274
|
+
// Ignore non-JSON error payloads and fall back to statusText.
|
|
275
|
+
}
|
|
276
|
+
throw new Error(`Failed to submit run: ${errorDetail ?? res.statusText}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const data = await res.json();
|
|
280
|
+
return RunResponseSchema.parse(data);
|
|
281
|
+
}, 'Run submission');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Get the status of a run.
|
|
286
|
+
*/
|
|
287
|
+
async getStatus(runId: string): Promise<StatusResponse> {
|
|
288
|
+
const res = await fetch(`${this.baseUrl}/api/runs/${runId}/status`, {
|
|
289
|
+
method: 'GET',
|
|
290
|
+
headers: this.baseHeaders,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (res.status === 404) {
|
|
294
|
+
throw new Error(`Run not found: ${runId}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (!res.ok) {
|
|
298
|
+
throw new Error(`Failed to get status: ${res.status}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const data = await res.json();
|
|
302
|
+
return StatusResponseSchema.parse(data);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Cancel a queued or running run.
|
|
307
|
+
*/
|
|
308
|
+
async cancel(runId: string): Promise<StatusResponse> {
|
|
309
|
+
const res = await fetch(`${this.baseUrl}/api/runs/${runId}/cancel`, {
|
|
310
|
+
method: 'POST',
|
|
311
|
+
headers: this.baseHeaders,
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
if (res.status === 404) {
|
|
315
|
+
throw new Error(`Run not found: ${runId}`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!res.ok) {
|
|
319
|
+
throw new Error(`Failed to cancel run: ${res.status}`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const data = await res.json();
|
|
323
|
+
return StatusResponseSchema.parse(data);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get sanitized progress events for a run.
|
|
328
|
+
*/
|
|
329
|
+
async getProgress(runId: string, tail?: number): Promise<Array<Record<string, unknown>>> {
|
|
330
|
+
const suffix = typeof tail === 'number' ? `?tail=${encodeURIComponent(String(tail))}` : '';
|
|
331
|
+
const res = await fetch(`${this.baseUrl}/api/runs/${runId}/progress${suffix}`, {
|
|
332
|
+
method: 'GET',
|
|
333
|
+
headers: this.baseHeaders,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
if (res.status === 404) {
|
|
337
|
+
throw new Error(`Progress not found: ${runId}`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (!res.ok) {
|
|
341
|
+
throw new Error(`Failed to get progress: ${res.status}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const data = await res.json();
|
|
345
|
+
const parsed = ProgressResponseSchema.parse(data);
|
|
346
|
+
return parsed.events;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Get comprehensive analysis of a run.
|
|
351
|
+
*/
|
|
352
|
+
async getAnalysis(runId: string): Promise<AnalysisResponse> {
|
|
353
|
+
const res = await fetch(`${this.baseUrl}/api/runs/${runId}/analysis`, {
|
|
354
|
+
method: 'GET',
|
|
355
|
+
headers: this.baseHeaders,
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
if (res.status === 404) {
|
|
359
|
+
throw new Error(`Run not found: ${runId}`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (!res.ok) {
|
|
363
|
+
throw new Error(`Failed to get analysis: ${res.status}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const data = await res.json();
|
|
367
|
+
return AnalysisResponseSchema.parse(data);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Get a log from a run.
|
|
372
|
+
*/
|
|
373
|
+
async getLog(
|
|
374
|
+
runId: string,
|
|
375
|
+
logType: 'stdout' | 'stderr' | 'validation' | 'progress' | 'quality' | 'secret-scan'
|
|
376
|
+
): Promise<string> {
|
|
377
|
+
const res = await fetch(`${this.baseUrl}/api/runs/${runId}/logs/${logType}`, {
|
|
378
|
+
method: 'GET',
|
|
379
|
+
headers: this.baseHeaders,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
if (res.status === 404) {
|
|
383
|
+
throw new Error(`Log not found: ${runId}/${logType}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (!res.ok) {
|
|
387
|
+
throw new Error(`Failed to get log: ${res.status}`);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const data = await res.json();
|
|
391
|
+
const parsed = LogResponseSchema.parse(data);
|
|
392
|
+
return parsed.content;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get an artifact (diff, metadata, etc.).
|
|
397
|
+
*/
|
|
398
|
+
async getArtifact(
|
|
399
|
+
runId: string,
|
|
400
|
+
file: 'git.diff' | 'metadata.json' | 'result-summary.md' | 'pi-events.jsonl' | 'pi-summary.json'
|
|
401
|
+
): Promise<string> {
|
|
402
|
+
const res = await fetch(`${this.baseUrl}/api/results/${runId}/${file}`, {
|
|
403
|
+
method: 'GET',
|
|
404
|
+
headers: this.baseHeaders,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
if (res.status === 404) {
|
|
408
|
+
throw new Error(`Artifact not found: ${runId}/${file}`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!res.ok) {
|
|
412
|
+
throw new Error(`Failed to get artifact: ${res.status}`);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const data = await res.json();
|
|
416
|
+
const parsed = ArtifactResponseSchema.parse(data);
|
|
417
|
+
return parsed.content;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* List all recent runs.
|
|
422
|
+
*/
|
|
423
|
+
async listRuns(): Promise<RunsListResponse> {
|
|
424
|
+
const res = await fetch(`${this.baseUrl}/api/runs`, {
|
|
425
|
+
method: 'GET',
|
|
426
|
+
headers: this.baseHeaders,
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
if (!res.ok) {
|
|
430
|
+
throw new Error(`Failed to list runs: ${res.status}`);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const data = await res.json();
|
|
434
|
+
return RunsListResponseSchema.parse(data);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Poll a run until completion.
|
|
439
|
+
* Useful for automated workflows.
|
|
440
|
+
*/
|
|
441
|
+
async waitForCompletion(
|
|
442
|
+
runId: string,
|
|
443
|
+
options?: {
|
|
444
|
+
timeout?: number; // Max time to wait (ms)
|
|
445
|
+
interval?: number; // Poll interval (ms)
|
|
446
|
+
onProgress?: (status: StatusResponse) => void; // Progress callback
|
|
447
|
+
}
|
|
448
|
+
): Promise<StatusResponse> {
|
|
449
|
+
const timeoutMs = options?.timeout || 95 * 60 * 1000; // 95 min default
|
|
450
|
+
const intervalMs = options?.interval || 5000; // 5 sec default
|
|
451
|
+
const startTime = Date.now();
|
|
452
|
+
|
|
453
|
+
// eslint-disable-next-line no-constant-condition
|
|
454
|
+
while (true) {
|
|
455
|
+
const status = await this.getStatus(runId);
|
|
456
|
+
|
|
457
|
+
if (options?.onProgress) {
|
|
458
|
+
options.onProgress(status);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (status.status !== 'running' && status.status !== 'queued') {
|
|
462
|
+
return status;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const elapsed = Date.now() - startTime;
|
|
466
|
+
if (elapsed > timeoutMs) {
|
|
467
|
+
throw new Error(`Timeout waiting for run: ${runId}`);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Sleep before next poll
|
|
471
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Helper to create a client with sensible defaults.
|
|
478
|
+
*/
|
|
479
|
+
export function createKasekiClient(baseUrl?: string, apiKey?: string): KasekiApiClient {
|
|
480
|
+
const url = baseUrl || process.env.KASEKI_API_URL || 'http://localhost:8080';
|
|
481
|
+
const key = apiKey || process.env.KASEKI_API_KEY;
|
|
482
|
+
|
|
483
|
+
if (!key) {
|
|
484
|
+
throw new Error('KASEKI_API_KEY environment variable is required');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return new KasekiApiClient(url, key);
|
|
488
|
+
}
|