@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
package/src/cli.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Kaseki Agent CLI
|
|
5
|
+
*
|
|
6
|
+
* Main entry point for @cyanautomation/kaseki-agent npm package
|
|
7
|
+
* Provides subcommands for setup, running agents, health checks, configuration, and reporting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import process from 'process';
|
|
11
|
+
import fs from 'fs/promises';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { createLogger } from './logger';
|
|
15
|
+
import { ConfigManager } from './config/ConfigManager';
|
|
16
|
+
import { KasekiCLI } from './cli/KasekiCLI';
|
|
17
|
+
|
|
18
|
+
const logger = createLogger('kaseki-cli');
|
|
19
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Main CLI entry point
|
|
23
|
+
*/
|
|
24
|
+
async function main() {
|
|
25
|
+
try {
|
|
26
|
+
// Parse CLI arguments and dispatch to appropriate subcommand
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
|
|
29
|
+
// Handle --version first (quick check)
|
|
30
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
31
|
+
const version = await getVersion();
|
|
32
|
+
console.log(version);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Handle --help first (quick check)
|
|
37
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
38
|
+
printHelp();
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Initialize CLI
|
|
43
|
+
const configManager = new ConfigManager();
|
|
44
|
+
const cli = new KasekiCLI(configManager);
|
|
45
|
+
|
|
46
|
+
// Get subcommand (first non-flag argument)
|
|
47
|
+
const subcommand = args[0];
|
|
48
|
+
|
|
49
|
+
// Dispatch to appropriate command handler
|
|
50
|
+
const exitCode = await cli.dispatch(subcommand, args.slice(1));
|
|
51
|
+
process.exit(exitCode);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (error instanceof Error) {
|
|
54
|
+
logger.error(error.message);
|
|
55
|
+
if (process.env.DEBUG === '1') {
|
|
56
|
+
console.error(error);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
logger.error('Unknown error occurred');
|
|
60
|
+
console.error(error);
|
|
61
|
+
}
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get version from package.json
|
|
68
|
+
*/
|
|
69
|
+
async function getVersion(): Promise<string> {
|
|
70
|
+
try {
|
|
71
|
+
const packagePath = path.join(__dirname, '../package.json');
|
|
72
|
+
const content = await fs.readFile(packagePath, 'utf-8');
|
|
73
|
+
const pkg = JSON.parse(content);
|
|
74
|
+
return pkg.version || '0.0.0';
|
|
75
|
+
} catch {
|
|
76
|
+
return '0.0.0';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Print CLI help message
|
|
82
|
+
*/
|
|
83
|
+
function printHelp(): void {
|
|
84
|
+
console.log(`
|
|
85
|
+
kaseki-agent - Ephemeral coding-agent runner
|
|
86
|
+
|
|
87
|
+
USAGE
|
|
88
|
+
kaseki-agent <command> [options]
|
|
89
|
+
|
|
90
|
+
COMMANDS
|
|
91
|
+
setup Interactive setup wizard (first-time configuration)
|
|
92
|
+
run [REPO] [REF] Run kaseki agent on target repository
|
|
93
|
+
doctor [--json] [--fix] Health checks and dependency validation
|
|
94
|
+
serve [--port N] Start REST API service for async execution
|
|
95
|
+
config [--get|--set] Manage configuration
|
|
96
|
+
list [--status STATE] List all kaseki instances
|
|
97
|
+
report <INSTANCE_ID> Generate report for completed instance
|
|
98
|
+
secrets Manage stored secrets (keyring/file)
|
|
99
|
+
|
|
100
|
+
COMMON OPTIONS
|
|
101
|
+
--help, -h Show this help message
|
|
102
|
+
--version, -v Show version number
|
|
103
|
+
--config FILE Use alternative config file
|
|
104
|
+
--verbose Verbose output
|
|
105
|
+
--json JSON output format
|
|
106
|
+
|
|
107
|
+
EXAMPLES
|
|
108
|
+
# First-time setup
|
|
109
|
+
kaseki-agent setup
|
|
110
|
+
|
|
111
|
+
# Verify environment
|
|
112
|
+
kaseki-agent doctor --verbose
|
|
113
|
+
|
|
114
|
+
# Run agent on a repository
|
|
115
|
+
kaseki-agent run https://github.com/CyanAutomation/crudmapper main
|
|
116
|
+
|
|
117
|
+
# Start API service
|
|
118
|
+
kaseki-agent serve --port 8080
|
|
119
|
+
|
|
120
|
+
# List completed instances
|
|
121
|
+
kaseki-agent list --status completed
|
|
122
|
+
|
|
123
|
+
DOCUMENTATION
|
|
124
|
+
For more information, visit: https://github.com/CyanAutomation/kaseki-agent
|
|
125
|
+
Check README.md and docs/ for detailed guides
|
|
126
|
+
|
|
127
|
+
ENVIRONMENT
|
|
128
|
+
KASEKI_ROOT Base directory for runs/results (default: /agents)
|
|
129
|
+
OPENROUTER_API_KEY_FILE Path to API key file (default: ~/.kaseki/secrets/openrouter_api_key)
|
|
130
|
+
DEBUG Enable debug output (set to 1)
|
|
131
|
+
`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Run main
|
|
135
|
+
main().catch((error) => {
|
|
136
|
+
console.error('Fatal error:', error);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
});
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles 4-tier precedence:
|
|
5
|
+
* 1. CLI flags/arguments (highest)
|
|
6
|
+
* 2. Config file: ./kaseki-agent.json (project-local)
|
|
7
|
+
* 3. Config file: ~/.kaseki/config.json (user-global)
|
|
8
|
+
* 4. Environment variables
|
|
9
|
+
* 5. Built-in defaults (lowest)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import fs from 'fs/promises';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { createLogger } from '../logger';
|
|
17
|
+
|
|
18
|
+
const logger = createLogger('config');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Full configuration schema with validation
|
|
22
|
+
*/
|
|
23
|
+
export const ConfigSchema = z.object({
|
|
24
|
+
// Authentication
|
|
25
|
+
auth: z.object({
|
|
26
|
+
openrouter_api_key_file: z.string().optional(),
|
|
27
|
+
github_app_id_file: z.string().optional(),
|
|
28
|
+
github_app_client_id_file: z.string().optional(),
|
|
29
|
+
github_app_private_key_file: z.string().optional(),
|
|
30
|
+
}).partial(),
|
|
31
|
+
|
|
32
|
+
// Agent execution
|
|
33
|
+
agent: z.object({
|
|
34
|
+
model: z.string().optional(),
|
|
35
|
+
provider: z.string().optional(),
|
|
36
|
+
timeout_seconds: z.number().int().positive().optional(),
|
|
37
|
+
guardrails: z.boolean().optional(),
|
|
38
|
+
}).partial(),
|
|
39
|
+
|
|
40
|
+
// Repository targeting
|
|
41
|
+
repo: z.object({
|
|
42
|
+
url: z.string().optional(),
|
|
43
|
+
ref: z.string().optional(),
|
|
44
|
+
task_mode: z.enum(['patch', 'inspect']).optional(),
|
|
45
|
+
}).partial(),
|
|
46
|
+
|
|
47
|
+
// Validation & quality gates
|
|
48
|
+
validation: z.object({
|
|
49
|
+
commands: z.array(z.string()).optional(),
|
|
50
|
+
skip_missing_npm_scripts: z.boolean().optional(),
|
|
51
|
+
fail_fast: z.boolean().optional(),
|
|
52
|
+
validate_after_agent_failure: z.boolean().optional(),
|
|
53
|
+
allowlist: z.array(z.string()).optional(),
|
|
54
|
+
validation_allowlist: z.array(z.string()).optional(),
|
|
55
|
+
restore_disallowed_changes: z.boolean().optional(),
|
|
56
|
+
max_diff_bytes: z.number().int().positive().optional(),
|
|
57
|
+
allow_empty_diff: z.boolean().optional(),
|
|
58
|
+
}).partial(),
|
|
59
|
+
|
|
60
|
+
// Dependency caching
|
|
61
|
+
caching: z.object({
|
|
62
|
+
dependency_cache_dir: z.string().optional(),
|
|
63
|
+
dependency_restore_mode: z.enum(['copy', 'link']).optional(),
|
|
64
|
+
install_ignore_scripts: z.boolean().optional(),
|
|
65
|
+
npm_omit_dev: z.boolean().optional(),
|
|
66
|
+
image_dependency_cache_dir: z.string().optional(),
|
|
67
|
+
git_cache_mode: z.enum(['off', 'mirror']).optional(),
|
|
68
|
+
git_cache_root: z.string().optional(),
|
|
69
|
+
}).partial(),
|
|
70
|
+
|
|
71
|
+
// Repository memory
|
|
72
|
+
repo_memory: z.object({
|
|
73
|
+
mode: z.enum(['off', 'read', 'read-write']).optional(),
|
|
74
|
+
ttl_days: z.number().int().positive().optional(),
|
|
75
|
+
max_bytes: z.number().int().positive().optional(),
|
|
76
|
+
}).partial(),
|
|
77
|
+
|
|
78
|
+
// GitHub integration
|
|
79
|
+
github: z.object({
|
|
80
|
+
app_enabled: z.boolean().optional(),
|
|
81
|
+
publish_mode: z.enum(['auto', 'on', 'off']).optional(),
|
|
82
|
+
}).partial(),
|
|
83
|
+
|
|
84
|
+
// Docker configuration
|
|
85
|
+
docker: z.object({
|
|
86
|
+
image: z.string().optional(),
|
|
87
|
+
auto_pull: z.boolean().optional(),
|
|
88
|
+
container_user: z.string().optional(),
|
|
89
|
+
}).partial(),
|
|
90
|
+
|
|
91
|
+
// REST API service
|
|
92
|
+
api: z.object({
|
|
93
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
94
|
+
keys: z.array(z.string()).optional(),
|
|
95
|
+
log_level: z.enum(['debug', 'info', 'warn', 'error']).optional(),
|
|
96
|
+
max_concurrent_runs: z.number().int().positive().optional(),
|
|
97
|
+
}).partial(),
|
|
98
|
+
|
|
99
|
+
// Directory paths
|
|
100
|
+
directories: z.object({
|
|
101
|
+
root: z.string().optional(),
|
|
102
|
+
log_dir: z.string().optional(),
|
|
103
|
+
cache_dir: z.string().optional(),
|
|
104
|
+
}).partial(),
|
|
105
|
+
|
|
106
|
+
// Debug & behavior flags
|
|
107
|
+
debug: z.object({
|
|
108
|
+
stream_progress: z.boolean().optional(),
|
|
109
|
+
keep_workspace: z.boolean().optional(),
|
|
110
|
+
debug_raw_events: z.boolean().optional(),
|
|
111
|
+
dry_run: z.boolean().optional(),
|
|
112
|
+
strict_script_check: z.boolean().optional(),
|
|
113
|
+
strict_host_logging: z.boolean().optional(),
|
|
114
|
+
}).partial(),
|
|
115
|
+
}).partial();
|
|
116
|
+
|
|
117
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Default configuration values
|
|
121
|
+
*/
|
|
122
|
+
const DEFAULT_CONFIG: Config = {
|
|
123
|
+
auth: {
|
|
124
|
+
openrouter_api_key_file: path.join(os.homedir(), '.kaseki', 'secrets', 'openrouter_api_key'),
|
|
125
|
+
},
|
|
126
|
+
agent: {
|
|
127
|
+
model: 'openrouter/free',
|
|
128
|
+
provider: 'openrouter',
|
|
129
|
+
timeout_seconds: 1200,
|
|
130
|
+
guardrails: true,
|
|
131
|
+
},
|
|
132
|
+
repo: {
|
|
133
|
+
url: 'https://github.com/CyanAutomation/crudmapper',
|
|
134
|
+
ref: 'main',
|
|
135
|
+
task_mode: 'patch',
|
|
136
|
+
},
|
|
137
|
+
validation: {
|
|
138
|
+
commands: ['npm run check', 'npm run test', 'npm run build'],
|
|
139
|
+
skip_missing_npm_scripts: true,
|
|
140
|
+
fail_fast: true,
|
|
141
|
+
validate_after_agent_failure: false,
|
|
142
|
+
allowlist: ['src/lib/parser.ts', 'tests/parser.validation.ts'],
|
|
143
|
+
restore_disallowed_changes: true,
|
|
144
|
+
max_diff_bytes: 200000,
|
|
145
|
+
allow_empty_diff: false,
|
|
146
|
+
},
|
|
147
|
+
caching: {
|
|
148
|
+
dependency_cache_dir: '/workspace/.kaseki-cache',
|
|
149
|
+
dependency_restore_mode: 'copy',
|
|
150
|
+
install_ignore_scripts: true,
|
|
151
|
+
npm_omit_dev: false,
|
|
152
|
+
git_cache_mode: 'off',
|
|
153
|
+
},
|
|
154
|
+
repo_memory: {
|
|
155
|
+
mode: 'off',
|
|
156
|
+
ttl_days: 30,
|
|
157
|
+
max_bytes: 8000,
|
|
158
|
+
},
|
|
159
|
+
github: {
|
|
160
|
+
app_enabled: false,
|
|
161
|
+
publish_mode: 'auto',
|
|
162
|
+
},
|
|
163
|
+
docker: {
|
|
164
|
+
image: 'docker.io/cyanautomation/kaseki-agent:latest',
|
|
165
|
+
auto_pull: true,
|
|
166
|
+
container_user: '10001:10001',
|
|
167
|
+
},
|
|
168
|
+
api: {
|
|
169
|
+
port: 8080,
|
|
170
|
+
log_level: 'info',
|
|
171
|
+
max_concurrent_runs: 3,
|
|
172
|
+
},
|
|
173
|
+
directories: {
|
|
174
|
+
root: '/agents',
|
|
175
|
+
log_dir: '/var/log/kaseki',
|
|
176
|
+
},
|
|
177
|
+
debug: {
|
|
178
|
+
stream_progress: true,
|
|
179
|
+
keep_workspace: false,
|
|
180
|
+
debug_raw_events: false,
|
|
181
|
+
dry_run: false,
|
|
182
|
+
strict_script_check: false,
|
|
183
|
+
strict_host_logging: false,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export class ConfigManager {
|
|
188
|
+
private config: Config = { ...DEFAULT_CONFIG };
|
|
189
|
+
private configFilePath: string | null = null;
|
|
190
|
+
private loaded = false;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Initialize and load configuration
|
|
194
|
+
* Loads from: project-local config > user config > environment > defaults
|
|
195
|
+
*/
|
|
196
|
+
async load(overrideConfigPath?: string): Promise<void> {
|
|
197
|
+
if (this.loaded) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
// Start with defaults
|
|
203
|
+
this.config = this.deepMerge(DEFAULT_CONFIG, {});
|
|
204
|
+
|
|
205
|
+
// Load project-local config
|
|
206
|
+
const projectConfigPath = path.join(process.cwd(), 'kaseki-agent.json');
|
|
207
|
+
const projectConfig = await this.tryLoadConfigFile(projectConfigPath);
|
|
208
|
+
if (projectConfig) {
|
|
209
|
+
this.config = this.deepMerge(this.config, projectConfig);
|
|
210
|
+
this.configFilePath = projectConfigPath;
|
|
211
|
+
logger.debug(`Loaded project config: ${projectConfigPath}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Load user-global config
|
|
215
|
+
const userConfigPath = path.join(os.homedir(), '.kaseki', 'config.json');
|
|
216
|
+
const userConfig = await this.tryLoadConfigFile(userConfigPath);
|
|
217
|
+
if (userConfig) {
|
|
218
|
+
this.config = this.deepMerge(this.config, userConfig);
|
|
219
|
+
// Only set configFilePath to user config if project config wasn't found
|
|
220
|
+
if (!projectConfig) {
|
|
221
|
+
this.configFilePath = userConfigPath;
|
|
222
|
+
}
|
|
223
|
+
logger.debug(`Loaded user config: ${userConfigPath}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Load override config if provided
|
|
227
|
+
if (overrideConfigPath) {
|
|
228
|
+
const overrideConfig = await this.tryLoadConfigFile(overrideConfigPath);
|
|
229
|
+
if (overrideConfig) {
|
|
230
|
+
this.config = this.deepMerge(this.config, overrideConfig);
|
|
231
|
+
this.configFilePath = overrideConfigPath;
|
|
232
|
+
logger.debug(`Loaded override config: ${overrideConfigPath}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Apply environment variables (override config files)
|
|
237
|
+
this.applyEnvironmentVariables();
|
|
238
|
+
|
|
239
|
+
// Validate final configuration
|
|
240
|
+
this.config = ConfigSchema.parse(this.config);
|
|
241
|
+
|
|
242
|
+
this.loaded = true;
|
|
243
|
+
logger.debug('Configuration loaded successfully');
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (error instanceof z.ZodError) {
|
|
246
|
+
logger.error(`Configuration validation error: ${error.message}`);
|
|
247
|
+
throw new Error(`Invalid configuration: ${error.errors[0]?.message}`);
|
|
248
|
+
}
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Try to load config from file, return null if file doesn't exist
|
|
255
|
+
*/
|
|
256
|
+
private async tryLoadConfigFile(filePath: string): Promise<Config | null> {
|
|
257
|
+
try {
|
|
258
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
259
|
+
const parsed = JSON.parse(content);
|
|
260
|
+
return parsed;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
if (error instanceof SyntaxError) {
|
|
266
|
+
logger.warn(`Malformed config file: ${filePath}`);
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Apply environment variables to config (lowest priority after files)
|
|
275
|
+
* Maps KASEKI_* and OPENROUTER_* env vars to config keys
|
|
276
|
+
*/
|
|
277
|
+
private applyEnvironmentVariables(): void {
|
|
278
|
+
const envMap: Record<string, (value: string) => any> = {
|
|
279
|
+
// Auth
|
|
280
|
+
OPENROUTER_API_KEY_FILE: (v) => {
|
|
281
|
+
if (!this.config.auth) this.config.auth = {};
|
|
282
|
+
this.config.auth.openrouter_api_key_file = v;
|
|
283
|
+
},
|
|
284
|
+
GITHUB_APP_ID_FILE: (v) => {
|
|
285
|
+
if (!this.config.auth) this.config.auth = {};
|
|
286
|
+
this.config.auth.github_app_id_file = v;
|
|
287
|
+
},
|
|
288
|
+
GITHUB_APP_CLIENT_ID_FILE: (v) => {
|
|
289
|
+
if (!this.config.auth) this.config.auth = {};
|
|
290
|
+
this.config.auth.github_app_client_id_file = v;
|
|
291
|
+
},
|
|
292
|
+
GITHUB_APP_PRIVATE_KEY_FILE: (v) => {
|
|
293
|
+
if (!this.config.auth) this.config.auth = {};
|
|
294
|
+
this.config.auth.github_app_private_key_file = v;
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
// Agent
|
|
298
|
+
KASEKI_MODEL: (v) => {
|
|
299
|
+
if (!this.config.agent) this.config.agent = {};
|
|
300
|
+
this.config.agent.model = v;
|
|
301
|
+
},
|
|
302
|
+
KASEKI_PROVIDER: (v) => {
|
|
303
|
+
if (!this.config.agent) this.config.agent = {};
|
|
304
|
+
this.config.agent.provider = v;
|
|
305
|
+
},
|
|
306
|
+
KASEKI_AGENT_TIMEOUT_SECONDS: (v) => {
|
|
307
|
+
if (!this.config.agent) this.config.agent = {};
|
|
308
|
+
this.config.agent.timeout_seconds = parseInt(v, 10);
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
// Repo
|
|
312
|
+
REPO_URL: (v) => {
|
|
313
|
+
if (!this.config.repo) this.config.repo = {};
|
|
314
|
+
this.config.repo.url = v;
|
|
315
|
+
},
|
|
316
|
+
GIT_REF: (v) => {
|
|
317
|
+
if (!this.config.repo) this.config.repo = {};
|
|
318
|
+
this.config.repo.ref = v;
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
// Validation
|
|
322
|
+
KASEKI_VALIDATION_COMMANDS: (v) => {
|
|
323
|
+
if (!this.config.validation) this.config.validation = {};
|
|
324
|
+
this.config.validation.commands = v.split(';').map((c) => c.trim());
|
|
325
|
+
},
|
|
326
|
+
KASEKI_MAX_DIFF_BYTES: (v) => {
|
|
327
|
+
if (!this.config.validation) this.config.validation = {};
|
|
328
|
+
this.config.validation.max_diff_bytes = parseInt(v, 10);
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
// Docker
|
|
332
|
+
KASEKI_IMAGE: (v) => {
|
|
333
|
+
if (!this.config.docker) this.config.docker = {};
|
|
334
|
+
this.config.docker.image = v;
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
// API
|
|
338
|
+
KASEKI_API_PORT: (v) => {
|
|
339
|
+
if (!this.config.api) this.config.api = {};
|
|
340
|
+
this.config.api.port = parseInt(v, 10);
|
|
341
|
+
},
|
|
342
|
+
KASEKI_API_KEYS: (v) => {
|
|
343
|
+
if (!this.config.api) this.config.api = {};
|
|
344
|
+
this.config.api.keys = v.split(',').map((k) => k.trim());
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
// Directories
|
|
348
|
+
KASEKI_ROOT: (v) => {
|
|
349
|
+
if (!this.config.directories) this.config.directories = {};
|
|
350
|
+
this.config.directories.root = v;
|
|
351
|
+
},
|
|
352
|
+
KASEKI_LOG_DIR: (v) => {
|
|
353
|
+
if (!this.config.directories) this.config.directories = {};
|
|
354
|
+
this.config.directories.log_dir = v;
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
for (const [envKey, setter] of Object.entries(envMap)) {
|
|
359
|
+
const value = process.env[envKey];
|
|
360
|
+
if (value !== undefined) {
|
|
361
|
+
setter(value);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Deep merge objects (right overwrites left)
|
|
368
|
+
*/
|
|
369
|
+
private deepMerge(target: any, source: any): any {
|
|
370
|
+
if (!source) return target;
|
|
371
|
+
|
|
372
|
+
const result = { ...target };
|
|
373
|
+
|
|
374
|
+
for (const key in source) {
|
|
375
|
+
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
|
|
376
|
+
result[key] = this.deepMerge(result[key] || {}, source[key]);
|
|
377
|
+
} else {
|
|
378
|
+
result[key] = source[key];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Get entire configuration
|
|
387
|
+
*/
|
|
388
|
+
getConfig(): Readonly<Config> {
|
|
389
|
+
if (!this.loaded) {
|
|
390
|
+
throw new Error('Configuration not loaded. Call load() first.');
|
|
391
|
+
}
|
|
392
|
+
return this.config;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get specific config value by dot-notation path
|
|
397
|
+
*/
|
|
398
|
+
get<T = any>(path: string, defaultValue?: T): T {
|
|
399
|
+
if (!this.loaded) {
|
|
400
|
+
throw new Error('Configuration not loaded. Call load() first.');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const parts = path.split('.');
|
|
404
|
+
let current: any = this.config;
|
|
405
|
+
|
|
406
|
+
for (const part of parts) {
|
|
407
|
+
if (current?.[part] === undefined) {
|
|
408
|
+
if (defaultValue !== undefined) {
|
|
409
|
+
return defaultValue;
|
|
410
|
+
}
|
|
411
|
+
throw new Error(`Configuration key not found: ${path}`);
|
|
412
|
+
}
|
|
413
|
+
current = current[part];
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return current;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Set configuration value
|
|
421
|
+
*/
|
|
422
|
+
set(path: string, value: any): void {
|
|
423
|
+
const parts = path.split('.');
|
|
424
|
+
const lastPart = parts.pop();
|
|
425
|
+
|
|
426
|
+
if (!lastPart) {
|
|
427
|
+
throw new Error('Invalid configuration path');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
let current: any = this.config;
|
|
431
|
+
|
|
432
|
+
for (const part of parts) {
|
|
433
|
+
if (!current[part]) {
|
|
434
|
+
current[part] = {};
|
|
435
|
+
}
|
|
436
|
+
current = current[part];
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
current[lastPart] = value;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Save configuration to file
|
|
444
|
+
*/
|
|
445
|
+
async save(filePath?: string): Promise<void> {
|
|
446
|
+
const targetPath = filePath || this.configFilePath;
|
|
447
|
+
if (!targetPath) {
|
|
448
|
+
throw new Error('No config file path specified for saving');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
const dir = path.dirname(targetPath);
|
|
453
|
+
await fs.mkdir(dir, { recursive: true });
|
|
454
|
+
await fs.writeFile(targetPath, JSON.stringify(this.config, null, 2), 'utf-8');
|
|
455
|
+
logger.debug(`Configuration saved to: ${targetPath}`);
|
|
456
|
+
} catch (error) {
|
|
457
|
+
throw new Error(`Failed to save configuration: ${error}`);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Get config file path (for reference/logging)
|
|
463
|
+
*/
|
|
464
|
+
getConfigFilePath(): string | null {
|
|
465
|
+
return this.configFilePath;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Reset to defaults
|
|
470
|
+
*/
|
|
471
|
+
reset(): void {
|
|
472
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
473
|
+
this.configFilePath = null;
|
|
474
|
+
this.loaded = false;
|
|
475
|
+
}
|
|
476
|
+
}
|