@kindgi/cli 0.0.0-bootstrap.0 → 0.1.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/LICENSE +201 -0
- package/README.md +738 -1
- package/dist/build/apt.d.ts +16 -0
- package/dist/build/apt.d.ts.map +1 -0
- package/dist/build/apt.js +50 -0
- package/dist/build/apt.js.map +1 -0
- package/dist/build/bundle.d.ts +48 -0
- package/dist/build/bundle.d.ts.map +1 -0
- package/dist/build/bundle.js +125 -0
- package/dist/build/bundle.js.map +1 -0
- package/dist/build/containerfile.d.ts +27 -0
- package/dist/build/containerfile.d.ts.map +1 -0
- package/dist/build/containerfile.js +197 -0
- package/dist/build/containerfile.js.map +1 -0
- package/dist/build/context-files.d.ts +24 -0
- package/dist/build/context-files.d.ts.map +1 -0
- package/dist/build/context-files.js +99 -0
- package/dist/build/context-files.js.map +1 -0
- package/dist/build/defaults.d.ts +66 -0
- package/dist/build/defaults.d.ts.map +1 -0
- package/dist/build/defaults.js +597 -0
- package/dist/build/defaults.js.map +1 -0
- package/dist/build/envelope.d.ts +72 -0
- package/dist/build/envelope.d.ts.map +1 -0
- package/dist/build/envelope.js +76 -0
- package/dist/build/envelope.js.map +1 -0
- package/dist/build/host-install.d.ts +100 -0
- package/dist/build/host-install.d.ts.map +1 -0
- package/dist/build/host-install.js +443 -0
- package/dist/build/host-install.js.map +1 -0
- package/dist/build/image-config.d.ts +32 -0
- package/dist/build/image-config.d.ts.map +1 -0
- package/dist/build/image-config.js +129 -0
- package/dist/build/image-config.js.map +1 -0
- package/dist/build/integrity.d.ts +51 -0
- package/dist/build/integrity.d.ts.map +1 -0
- package/dist/build/integrity.js +75 -0
- package/dist/build/integrity.js.map +1 -0
- package/dist/build/node-image.d.ts +18 -0
- package/dist/build/node-image.d.ts.map +1 -0
- package/dist/build/node-image.js +46 -0
- package/dist/build/node-image.js.map +1 -0
- package/dist/build/pack-root.d.ts +69 -0
- package/dist/build/pack-root.d.ts.map +1 -0
- package/dist/build/pack-root.js +102 -0
- package/dist/build/pack-root.js.map +1 -0
- package/dist/build/poetry-requirements.d.ts +5 -0
- package/dist/build/poetry-requirements.d.ts.map +1 -0
- package/dist/build/poetry-requirements.js +8 -0
- package/dist/build/poetry-requirements.js.map +1 -0
- package/dist/build/python-image.d.ts +40 -0
- package/dist/build/python-image.d.ts.map +1 -0
- package/dist/build/python-image.js +197 -0
- package/dist/build/python-image.js.map +1 -0
- package/dist/build/runners.d.ts +259 -0
- package/dist/build/runners.d.ts.map +1 -0
- package/dist/build/runners.js +4 -0
- package/dist/build/runners.js.map +1 -0
- package/dist/build/version-specifier.d.ts +2 -0
- package/dist/build/version-specifier.d.ts.map +1 -0
- package/dist/build/version-specifier.js +70 -0
- package/dist/build/version-specifier.js.map +1 -0
- package/dist/cli-package.d.ts +15 -0
- package/dist/cli-package.d.ts.map +1 -0
- package/dist/cli-package.js +37 -0
- package/dist/cli-package.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/adapters.d.ts +3 -0
- package/dist/commands/adapters.d.ts.map +1 -0
- package/dist/commands/adapters.js +148 -0
- package/dist/commands/adapters.js.map +1 -0
- package/dist/commands/agents.d.ts +3 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +82 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/approvals.d.ts +3 -0
- package/dist/commands/approvals.d.ts.map +1 -0
- package/dist/commands/approvals.js +92 -0
- package/dist/commands/approvals.js.map +1 -0
- package/dist/commands/artifacts.d.ts +3 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +87 -0
- package/dist/commands/artifacts.js.map +1 -0
- package/dist/commands/auth.d.ts +25 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +283 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/build.d.ts +46 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +902 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/capabilities.d.ts +3 -0
- package/dist/commands/capabilities.d.ts.map +1 -0
- package/dist/commands/capabilities.js +38 -0
- package/dist/commands/capabilities.js.map +1 -0
- package/dist/commands/conversations.d.ts +3 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +75 -0
- package/dist/commands/conversations.js.map +1 -0
- package/dist/commands/deploy.d.ts +7 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +697 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +43 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +1110 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/env.d.ts +27 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +816 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/feedback.d.ts +33 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +374 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/flows.d.ts +3 -0
- package/dist/commands/flows.d.ts.map +1 -0
- package/dist/commands/flows.js +60 -0
- package/dist/commands/flows.js.map +1 -0
- package/dist/commands/guardrails.d.ts +3 -0
- package/dist/commands/guardrails.d.ts.map +1 -0
- package/dist/commands/guardrails.js +89 -0
- package/dist/commands/guardrails.js.map +1 -0
- package/dist/commands/health.d.ts +8 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +40 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/helpers.d.ts +48 -0
- package/dist/commands/helpers.d.ts.map +1 -0
- package/dist/commands/helpers.js +110 -0
- package/dist/commands/helpers.js.map +1 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +90 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +46 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +454 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/key.d.ts +3 -0
- package/dist/commands/key.d.ts.map +1 -0
- package/dist/commands/key.js +322 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/mcp.d.ts +43 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +433 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/memory.d.ts +3 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +82 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/observations.d.ts +3 -0
- package/dist/commands/observations.d.ts.map +1 -0
- package/dist/commands/observations.js +27 -0
- package/dist/commands/observations.js.map +1 -0
- package/dist/commands/proposals.d.ts +3 -0
- package/dist/commands/proposals.d.ts.map +1 -0
- package/dist/commands/proposals.js +116 -0
- package/dist/commands/proposals.js.map +1 -0
- package/dist/commands/provenance.d.ts +3 -0
- package/dist/commands/provenance.d.ts.map +1 -0
- package/dist/commands/provenance.js +53 -0
- package/dist/commands/provenance.js.map +1 -0
- package/dist/commands/providers.d.ts +3 -0
- package/dist/commands/providers.d.ts.map +1 -0
- package/dist/commands/providers.js +212 -0
- package/dist/commands/providers.js.map +1 -0
- package/dist/commands/reviewers.d.ts +3 -0
- package/dist/commands/reviewers.d.ts.map +1 -0
- package/dist/commands/reviewers.js +78 -0
- package/dist/commands/reviewers.js.map +1 -0
- package/dist/commands/runs.d.ts +3 -0
- package/dist/commands/runs.d.ts.map +1 -0
- package/dist/commands/runs.js +223 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/secrets.d.ts +18 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +702 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/skills.d.ts +64 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +430 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/test.d.ts +5 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +181 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/tokens.d.ts +3 -0
- package/dist/commands/tokens.d.ts.map +1 -0
- package/dist/commands/tokens.js +33 -0
- package/dist/commands/tokens.js.map +1 -0
- package/dist/commands/tools.d.ts +3 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +162 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/types.d.ts +54 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +4 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/unwired.d.ts +22 -0
- package/dist/commands/unwired.d.ts.map +1 -0
- package/dist/commands/unwired.js +52 -0
- package/dist/commands/unwired.js.map +1 -0
- package/dist/commands/version.d.ts +8 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +41 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/config.d.ts +42 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +162 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +45 -0
- package/dist/context.js.map +1 -0
- package/dist/deploy/defaults.d.ts +14 -0
- package/dist/deploy/defaults.d.ts.map +1 -0
- package/dist/deploy/defaults.js +37 -0
- package/dist/deploy/defaults.js.map +1 -0
- package/dist/deploy/envelope-loader.d.ts +24 -0
- package/dist/deploy/envelope-loader.d.ts.map +1 -0
- package/dist/deploy/envelope-loader.js +141 -0
- package/dist/deploy/envelope-loader.js.map +1 -0
- package/dist/deploy/post.d.ts +48 -0
- package/dist/deploy/post.d.ts.map +1 -0
- package/dist/deploy/post.js +210 -0
- package/dist/deploy/post.js.map +1 -0
- package/dist/deploy/response.d.ts +42 -0
- package/dist/deploy/response.d.ts.map +1 -0
- package/dist/deploy/response.js +128 -0
- package/dist/deploy/response.js.map +1 -0
- package/dist/deploy/runners.d.ts +218 -0
- package/dist/deploy/runners.d.ts.map +1 -0
- package/dist/deploy/runners.js +4 -0
- package/dist/deploy/runners.js.map +1 -0
- package/dist/dev/bundler.d.ts +10 -0
- package/dist/dev/bundler.d.ts.map +1 -0
- package/dist/dev/bundler.js +235 -0
- package/dist/dev/bundler.js.map +1 -0
- package/dist/dev/defaults.d.ts +140 -0
- package/dist/dev/defaults.d.ts.map +1 -0
- package/dist/dev/defaults.js +709 -0
- package/dist/dev/defaults.js.map +1 -0
- package/dist/dev/dev-only-imports.d.ts +15 -0
- package/dist/dev/dev-only-imports.d.ts.map +1 -0
- package/dist/dev/dev-only-imports.js +57 -0
- package/dist/dev/dev-only-imports.js.map +1 -0
- package/dist/dev/docker-compose.dev.yml +68 -0
- package/dist/dev/index-child.d.ts +2 -0
- package/dist/dev/index-child.d.ts.map +1 -0
- package/dist/dev/index-child.js +53 -0
- package/dist/dev/index-child.js.map +1 -0
- package/dist/dev/pack-code.d.ts +36 -0
- package/dist/dev/pack-code.d.ts.map +1 -0
- package/dist/dev/pack-code.js +129 -0
- package/dist/dev/pack-code.js.map +1 -0
- package/dist/dev/pack-env.d.ts +13 -0
- package/dist/dev/pack-env.d.ts.map +1 -0
- package/dist/dev/pack-env.js +36 -0
- package/dist/dev/pack-env.js.map +1 -0
- package/dist/dev/pack-service.d.ts +40 -0
- package/dist/dev/pack-service.d.ts.map +1 -0
- package/dist/dev/pack-service.js +189 -0
- package/dist/dev/pack-service.js.map +1 -0
- package/dist/dev/paths.d.ts +22 -0
- package/dist/dev/paths.d.ts.map +1 -0
- package/dist/dev/paths.js +35 -0
- package/dist/dev/paths.js.map +1 -0
- package/dist/dev/postgres-container.d.ts +77 -0
- package/dist/dev/postgres-container.d.ts.map +1 -0
- package/dist/dev/postgres-container.js +346 -0
- package/dist/dev/postgres-container.js.map +1 -0
- package/dist/dev/python-builder.d.ts +16 -0
- package/dist/dev/python-builder.d.ts.map +1 -0
- package/dist/dev/python-builder.js +122 -0
- package/dist/dev/python-builder.js.map +1 -0
- package/dist/dev/register.d.ts +71 -0
- package/dist/dev/register.d.ts.map +1 -0
- package/dist/dev/register.js +54 -0
- package/dist/dev/register.js.map +1 -0
- package/dist/dev/runners.d.ts +312 -0
- package/dist/dev/runners.d.ts.map +1 -0
- package/dist/dev/runners.js +4 -0
- package/dist/dev/runners.js.map +1 -0
- package/dist/dev/runtime-container.d.ts +71 -0
- package/dist/dev/runtime-container.d.ts.map +1 -0
- package/dist/dev/runtime-container.js +173 -0
- package/dist/dev/runtime-container.js.map +1 -0
- package/dist/dev/runtime-env.d.ts +62 -0
- package/dist/dev/runtime-env.d.ts.map +1 -0
- package/dist/dev/runtime-env.js +100 -0
- package/dist/dev/runtime-env.js.map +1 -0
- package/dist/dev/runtime-image.d.ts +26 -0
- package/dist/dev/runtime-image.d.ts.map +1 -0
- package/dist/dev/runtime-image.js +44 -0
- package/dist/dev/runtime-image.js.map +1 -0
- package/dist/dev/runtime-registry.d.ts +73 -0
- package/dist/dev/runtime-registry.d.ts.map +1 -0
- package/dist/dev/runtime-registry.js +111 -0
- package/dist/dev/runtime-registry.js.map +1 -0
- package/dist/env/defaults.d.ts +3 -0
- package/dist/env/defaults.d.ts.map +1 -0
- package/dist/env/defaults.js +22 -0
- package/dist/env/defaults.js.map +1 -0
- package/dist/env/pack-env-plan.d.ts +70 -0
- package/dist/env/pack-env-plan.d.ts.map +1 -0
- package/dist/env/pack-env-plan.js +236 -0
- package/dist/env/pack-env-plan.js.map +1 -0
- package/dist/env/parser.d.ts +9 -0
- package/dist/env/parser.d.ts.map +1 -0
- package/dist/env/parser.js +11 -0
- package/dist/env/parser.js.map +1 -0
- package/dist/env/project-env.d.ts +34 -0
- package/dist/env/project-env.d.ts.map +1 -0
- package/dist/env/project-env.js +45 -0
- package/dist/env/project-env.js.map +1 -0
- package/dist/env/runners.d.ts +22 -0
- package/dist/env/runners.d.ts.map +1 -0
- package/dist/env/runners.js +4 -0
- package/dist/env/runners.js.map +1 -0
- package/dist/env/writer.d.ts +7 -0
- package/dist/env/writer.d.ts.map +1 -0
- package/dist/env/writer.js +9 -0
- package/dist/env/writer.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +111 -0
- package/dist/errors.js.map +1 -0
- package/dist/help.d.ts +5 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +61 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/init/augment-scaffolder.d.ts +86 -0
- package/dist/init/augment-scaffolder.d.ts.map +1 -0
- package/dist/init/augment-scaffolder.js +538 -0
- package/dist/init/augment-scaffolder.js.map +1 -0
- package/dist/init/dependency-specs.d.ts +58 -0
- package/dist/init/dependency-specs.d.ts.map +1 -0
- package/dist/init/dependency-specs.js +153 -0
- package/dist/init/dependency-specs.js.map +1 -0
- package/dist/init/gitignore-patcher.d.ts +23 -0
- package/dist/init/gitignore-patcher.d.ts.map +1 -0
- package/dist/init/gitignore-patcher.js +103 -0
- package/dist/init/gitignore-patcher.js.map +1 -0
- package/dist/init/mode-detect.d.ts +34 -0
- package/dist/init/mode-detect.d.ts.map +1 -0
- package/dist/init/mode-detect.js +115 -0
- package/dist/init/mode-detect.js.map +1 -0
- package/dist/init/package-json-patcher.d.ts +36 -0
- package/dist/init/package-json-patcher.d.ts.map +1 -0
- package/dist/init/package-json-patcher.js +128 -0
- package/dist/init/package-json-patcher.js.map +1 -0
- package/dist/init/pnpm-workspace-patcher.d.ts +55 -0
- package/dist/init/pnpm-workspace-patcher.d.ts.map +1 -0
- package/dist/init/pnpm-workspace-patcher.js +248 -0
- package/dist/init/pnpm-workspace-patcher.js.map +1 -0
- package/dist/init/pyproject-patcher.d.ts +56 -0
- package/dist/init/pyproject-patcher.d.ts.map +1 -0
- package/dist/init/pyproject-patcher.js +324 -0
- package/dist/init/pyproject-patcher.js.map +1 -0
- package/dist/init/python-augment.d.ts +22 -0
- package/dist/init/python-augment.d.ts.map +1 -0
- package/dist/init/python-augment.js +300 -0
- package/dist/init/python-augment.js.map +1 -0
- package/dist/init/template-files.d.ts +18 -0
- package/dist/init/template-files.d.ts.map +1 -0
- package/dist/init/template-files.js +53 -0
- package/dist/init/template-files.js.map +1 -0
- package/dist/key/defaults.d.ts +3 -0
- package/dist/key/defaults.d.ts.map +1 -0
- package/dist/key/defaults.js +60 -0
- package/dist/key/defaults.js.map +1 -0
- package/dist/key/fingerprint.d.ts +6 -0
- package/dist/key/fingerprint.d.ts.map +1 -0
- package/dist/key/fingerprint.js +25 -0
- package/dist/key/fingerprint.js.map +1 -0
- package/dist/key/paths.d.ts +30 -0
- package/dist/key/paths.d.ts.map +1 -0
- package/dist/key/paths.js +51 -0
- package/dist/key/paths.js.map +1 -0
- package/dist/key/runners.d.ts +60 -0
- package/dist/key/runners.d.ts.map +1 -0
- package/dist/key/runners.js +4 -0
- package/dist/key/runners.js.map +1 -0
- package/dist/main.d.ts +113 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +199 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/launcher.d.ts +143 -0
- package/dist/mcp/launcher.d.ts.map +1 -0
- package/dist/mcp/launcher.js +393 -0
- package/dist/mcp/launcher.js.map +1 -0
- package/dist/mcp/preset-loader.d.ts +29 -0
- package/dist/mcp/preset-loader.d.ts.map +1 -0
- package/dist/mcp/preset-loader.js +217 -0
- package/dist/mcp/preset-loader.js.map +1 -0
- package/dist/mcp/preset-types.d.ts +71 -0
- package/dist/mcp/preset-types.d.ts.map +1 -0
- package/dist/mcp/preset-types.js +4 -0
- package/dist/mcp/preset-types.js.map +1 -0
- package/dist/mcp/presets/README.md +68 -0
- package/dist/mcp/presets/postgres.json +15 -0
- package/dist/output.d.ts +26 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +46 -0
- package/dist/output.js.map +1 -0
- package/dist/pack-config.d.ts +37 -0
- package/dist/pack-config.d.ts.map +1 -0
- package/dist/pack-config.js +65 -0
- package/dist/pack-config.js.map +1 -0
- package/dist/package-manager.d.ts +33 -0
- package/dist/package-manager.d.ts.map +1 -0
- package/dist/package-manager.js +129 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/parse.d.ts +88 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +100 -0
- package/dist/parse.js.map +1 -0
- package/dist/providers/preset-loader.d.ts +47 -0
- package/dist/providers/preset-loader.d.ts.map +1 -0
- package/dist/providers/preset-loader.js +107 -0
- package/dist/providers/preset-loader.js.map +1 -0
- package/dist/providers/presets/anthropic.json +47 -0
- package/dist/providers/presets/gemini.json +40 -0
- package/dist/reference.d.ts +28 -0
- package/dist/reference.d.ts.map +1 -0
- package/dist/reference.js +52 -0
- package/dist/reference.js.map +1 -0
- package/dist/sdk-package.d.ts +9 -0
- package/dist/sdk-package.d.ts.map +1 -0
- package/dist/sdk-package.js +20 -0
- package/dist/sdk-package.js.map +1 -0
- package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +252 -0
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +302 -0
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +297 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +289 -0
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +705 -0
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +298 -0
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +211 -0
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +189 -0
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +205 -0
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +325 -0
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +176 -0
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +305 -0
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +242 -0
- package/dist/stop-signal.d.ts +15 -0
- package/dist/stop-signal.d.ts.map +1 -0
- package/dist/stop-signal.js +16 -0
- package/dist/stop-signal.js.map +1 -0
- package/dist/templates/minimal/.nvmrc +1 -0
- package/dist/templates/minimal/AGENTS.md +23 -0
- package/dist/templates/minimal/README.md.tmpl +69 -0
- package/dist/templates/minimal/agents/.gitkeep +0 -0
- package/dist/templates/minimal/flows/.gitkeep +0 -0
- package/dist/templates/minimal/gitignore +8 -0
- package/dist/templates/minimal/guardrails/.gitkeep +0 -0
- package/dist/templates/minimal/kindgi.config.ts.tmpl +44 -0
- package/dist/templates/minimal/package.json.tmpl +25 -0
- package/dist/templates/minimal/pnpm-workspace.yaml +8 -0
- package/dist/templates/minimal/tools/.gitkeep +0 -0
- package/dist/templates/minimal/tsconfig.json.tmpl +27 -0
- package/dist/templates/minimal/vitest.config.ts.tmpl +14 -0
- package/dist/templates/python/AGENTS.md +30 -0
- package/dist/templates/python/README.md.tmpl +56 -0
- package/dist/templates/python/agents/echo_agent.py.tmpl +23 -0
- package/dist/templates/python/flows/echo_flow.py.tmpl +17 -0
- package/dist/templates/python/gitignore +9 -0
- package/dist/templates/python/guardrails/response_not_empty.py.tmpl +27 -0
- package/dist/templates/python/pyproject.toml.tmpl +42 -0
- package/dist/templates/python/tests/test_tools.py.tmpl +22 -0
- package/dist/templates/python/tools/echo.py.tmpl +27 -0
- package/dist/templates/python/tools/greet.py.tmpl +20 -0
- package/dist/templates/sample/.nvmrc +1 -0
- package/dist/templates/sample/AGENTS.md +23 -0
- package/dist/templates/sample/README.md.tmpl +85 -0
- package/dist/templates/sample/agents/echo-agent/index.ts.tmpl +34 -0
- package/dist/templates/sample/flows/echo-flow/index.ts.tmpl +59 -0
- package/dist/templates/sample/gitignore +8 -0
- package/dist/templates/sample/guardrails/response-not-empty/index.ts.tmpl +58 -0
- package/dist/templates/sample/kindgi.config.ts.tmpl +41 -0
- package/dist/templates/sample/package.json.tmpl +25 -0
- package/dist/templates/sample/pnpm-workspace.yaml +8 -0
- package/dist/templates/sample/tools/echo/index.test.ts.tmpl +31 -0
- package/dist/templates/sample/tools/echo/index.ts.tmpl +37 -0
- package/dist/templates/sample/tools/fetch-httpbin/index.ts.tmpl +60 -0
- package/dist/templates/sample/tools/greet/index.ts.tmpl +35 -0
- package/dist/templates/sample/tsconfig.json.tmpl +27 -0
- package/dist/templates/sample/vitest.config.ts.tmpl +14 -0
- package/dist/terminal-input.d.ts +17 -0
- package/dist/terminal-input.d.ts.map +1 -0
- package/dist/terminal-input.js +88 -0
- package/dist/terminal-input.js.map +1 -0
- package/dist/test/defaults.d.ts +3 -0
- package/dist/test/defaults.d.ts.map +1 -0
- package/dist/test/defaults.js +104 -0
- package/dist/test/defaults.js.map +1 -0
- package/dist/test/runners.d.ts +60 -0
- package/dist/test/runners.d.ts.map +1 -0
- package/dist/test/runners.js +4 -0
- package/dist/test/runners.js.map +1 -0
- package/dist/version-info.d.ts +9 -0
- package/dist/version-info.d.ts.map +1 -0
- package/dist/version-info.js +27 -0
- package/dist/version-info.js.map +1 -0
- package/dist/write-fully.d.ts +13 -0
- package/dist/write-fully.d.ts.map +1 -0
- package/dist/write-fully.js +17 -0
- package/dist/write-fully.js.map +1 -0
- package/package.json +63 -4
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* `kindgi deploy` — client-side deploy orchestrator.
|
|
5
|
+
*
|
|
6
|
+
* The one deployment wire call: reads the `deploy-envelope.json`
|
|
7
|
+
* emitted by `kindgi build` — either from an explicit `--from-envelope <path>` OR by
|
|
8
|
+
* auto-detecting `<out>/deploy-envelope.json` from the pack config OR
|
|
9
|
+
* by running `kindgi build` inline as a fallback — then POSTs it to
|
|
10
|
+
* `POST /v1/deployments` and prints the resulting deployment record.
|
|
11
|
+
*
|
|
12
|
+
* Pipeline:
|
|
13
|
+
*
|
|
14
|
+
* 1. Resolve args (env block, endpoint, token, envelope source).
|
|
15
|
+
* 2. Ensure envelope exists — read from disk, or inline-build first.
|
|
16
|
+
* 3. Structurally validate the envelope.
|
|
17
|
+
* 4. Build the wire POST body (strip `tenantId` / `$schema` /
|
|
18
|
+
* `buildLogsUrl`).
|
|
19
|
+
* 5. Compute `Idempotency-Key: sha256(canonicalBody)` (or `--idempotency-key`).
|
|
20
|
+
* 6. If `--dry-run`: print the curl-equivalent + body + headers to
|
|
21
|
+
* stderr, exit 0.
|
|
22
|
+
* 7. Otherwise POST via `ctx.fetch`.
|
|
23
|
+
* 8. Handle response (201 / 200 / 4xx / 5xx / transport).
|
|
24
|
+
* 9. Warn on out-of-band secrets sync if `.env.<envName>` exists.
|
|
25
|
+
*/
|
|
26
|
+
import { stat } from 'node:fs/promises';
|
|
27
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
28
|
+
import { LOCAL_ENV_NAME, packValues, readPackEnv } from '@kindgi/secrets-dotenv';
|
|
29
|
+
import { isEnvelopeSigned } from '../deploy/envelope-loader.js';
|
|
30
|
+
import { buildPostBody, deriveIdempotencyKey, deriveSyncSecretsIdempotencyKey, } from '../deploy/post.js';
|
|
31
|
+
import { renderResponse } from '../deploy/response.js';
|
|
32
|
+
import { describePackEnvPlan, plainSecretReason, planPackEnv, } from '../env/pack-env-plan.js';
|
|
33
|
+
import { renderJson } from '../output.js';
|
|
34
|
+
import { loadPackConfig } from '../pack-config.js';
|
|
35
|
+
import { runBuild } from './build.js';
|
|
36
|
+
/** Default relative path to look for a pre-built envelope. */
|
|
37
|
+
export const DEFAULT_ENVELOPE_RELATIVE_PATH = '.kindgi/build/deploy-envelope.json';
|
|
38
|
+
export const deployCommand = {
|
|
39
|
+
kind: 'leaf',
|
|
40
|
+
name: 'deploy',
|
|
41
|
+
description: 'Deploy a signed pack image to Kindgi. Reads deploy-envelope.json (or runs `kindgi build` inline) + POSTs to /v1/deployments.',
|
|
42
|
+
usage: 'kindgi deploy [--env <name>] [--from-envelope <path>] [--endpoint <url>] [--token <bearer>] ' +
|
|
43
|
+
'[--tenant <id>] [--idempotency-key <str>] [--dry-run] [--sync-secrets] [--allow-missing-env] ' +
|
|
44
|
+
'[--target <t>] [--build-endpoint <url>] [--out <dir>] [--artifact-version <v>] [--published-at <iso>] ' +
|
|
45
|
+
'[--signing-key <path>] [--signer-key-id <id>] [--registry-push-creds <ref>] ' +
|
|
46
|
+
'[--skip-integrity-gate] [--skip-image-pull] [--skip-sign] [--path <dir>]',
|
|
47
|
+
optionSpec: {
|
|
48
|
+
env: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'The environment: its block in `kindgi.config.ts` and its `.env.<name>` file. Default: `staging`.',
|
|
51
|
+
},
|
|
52
|
+
'from-envelope': {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'The envelope to deploy. Default: `deploy-envelope.json` in `--out`; when there is none, `kindgi build` runs first.',
|
|
55
|
+
},
|
|
56
|
+
endpoint: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: "The API to deploy to. Default: the env block's `endpoint`, else the CLI's API URL (`--url`, `KINDGI_API_URL`, config files).",
|
|
59
|
+
},
|
|
60
|
+
tenant: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'Refuse unless the envelope was signed for this tenant (checked before sending). Also passed to an inline build.',
|
|
63
|
+
},
|
|
64
|
+
'idempotency-key': {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'The `Idempotency-Key` header. Default: a hash of the request body, so the same image deployed again returns the same deployment.',
|
|
67
|
+
},
|
|
68
|
+
'dry-run': {
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
description: 'Print the equivalent `curl` request instead of sending it. A missing envelope is still built first.',
|
|
71
|
+
},
|
|
72
|
+
// Opt-in post-deploy secret sync. Default OFF: regulated
|
|
73
|
+
// verticals rotate secrets on a separate cadence.
|
|
74
|
+
'sync-secrets': {
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
description: "After the deploy lands, also send the values in `.env.<env>` to the deployment's secrets. Off by default.",
|
|
77
|
+
},
|
|
78
|
+
// Deploy although a name the pack's env.required declares has no
|
|
79
|
+
// value for --env (the pack service won't be ready until it has).
|
|
80
|
+
'allow-missing-env': {
|
|
81
|
+
type: 'boolean',
|
|
82
|
+
description: "Deploy, with a warning, even when a name in the pack's `env.required` has no value for `--env`.",
|
|
83
|
+
},
|
|
84
|
+
// Pass-through build flags for inline-build fallback.
|
|
85
|
+
target: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description: "For an inline build: the build target. Default: the env block's `buildTarget`, else the env name.",
|
|
88
|
+
},
|
|
89
|
+
'build-endpoint': {
|
|
90
|
+
type: 'string',
|
|
91
|
+
description: "For an inline build: the build server (`kindgi build --endpoint`). Default: the env block's `build`.",
|
|
92
|
+
},
|
|
93
|
+
out: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
description: 'Where the envelope is looked for, and an inline build writes. Default: `.kindgi/build` under the pack root.',
|
|
96
|
+
},
|
|
97
|
+
'artifact-version': {
|
|
98
|
+
type: 'string',
|
|
99
|
+
description: "For an inline build: the artifact version. Default: today's date as `YYYYMMDD.1` (UTC).",
|
|
100
|
+
},
|
|
101
|
+
'published-at': {
|
|
102
|
+
type: 'string',
|
|
103
|
+
description: 'For an inline build: the publish time (ISO 8601). Default: the Unix epoch.',
|
|
104
|
+
},
|
|
105
|
+
'signing-key': {
|
|
106
|
+
type: 'string',
|
|
107
|
+
description: "For an inline build: the Ed25519 private key (PEM) to sign with. Default: the env block's `signingKey`.",
|
|
108
|
+
},
|
|
109
|
+
'signer-key-id': {
|
|
110
|
+
type: 'string',
|
|
111
|
+
description: "For an inline build: the key id the signature names. Default: the env block's `signerKeyId`, else the key file's name.",
|
|
112
|
+
},
|
|
113
|
+
'registry-push-creds': {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: 'For an inline build: a reference to the registry push credentials for the build server to use.',
|
|
116
|
+
},
|
|
117
|
+
'skip-integrity-gate': {
|
|
118
|
+
type: 'boolean',
|
|
119
|
+
description: "For an inline build: sign without checking the image's index against the local one.",
|
|
120
|
+
},
|
|
121
|
+
'skip-image-pull': {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
description: "For an inline build: check the image's index by hash only, without pulling the image.",
|
|
124
|
+
},
|
|
125
|
+
'skip-sign': {
|
|
126
|
+
type: 'boolean',
|
|
127
|
+
description: 'For an inline build: write an unsigned envelope, which the deploy then refuses unless `--dry-run`.',
|
|
128
|
+
},
|
|
129
|
+
path: { type: 'string', description: 'The pack root. Default: the current directory.' },
|
|
130
|
+
},
|
|
131
|
+
run: async (ctx) => runDeploy(ctx),
|
|
132
|
+
};
|
|
133
|
+
// ---------------------------------------------------------------------
|
|
134
|
+
// Main entrypoint
|
|
135
|
+
// ---------------------------------------------------------------------
|
|
136
|
+
export async function runDeploy(ctx) {
|
|
137
|
+
const runners = ctx.deployRunners;
|
|
138
|
+
if (runners === undefined) {
|
|
139
|
+
return failure('Internal error: kindgi deploy requires deploy runners to be wired. ' +
|
|
140
|
+
'Rebuild the CLI (`pnpm --filter @kindgi/cli build`).\n');
|
|
141
|
+
}
|
|
142
|
+
const parsed = await resolveDeployArgs(ctx);
|
|
143
|
+
if (parsed.kind === 'error')
|
|
144
|
+
return parsed;
|
|
145
|
+
const args = parsed.args;
|
|
146
|
+
const banner = [];
|
|
147
|
+
const line = (s) => {
|
|
148
|
+
banner.push(s);
|
|
149
|
+
};
|
|
150
|
+
line('');
|
|
151
|
+
line(` Environment: ${args.envName}`);
|
|
152
|
+
line(` API: ${args.endpoint}`);
|
|
153
|
+
line(` Envelope: ${args.envelopePath}${args.envelopeSource === 'auto-detect' ? ' (auto-detected)' : ''}`);
|
|
154
|
+
line(` Idempotency: ${args.idempotencyKeyOverride !== undefined ? '(caller-supplied)' : '(sha256 of canonical body — derived below)'}`);
|
|
155
|
+
line('');
|
|
156
|
+
// ---- 0. The pack service's env in this environment -------------------
|
|
157
|
+
//
|
|
158
|
+
// Every name the pack declares in env.required needs a value or a
|
|
159
|
+
// Secret Manager reference for this environment; a secret given in
|
|
160
|
+
// the clear is refused. Checked before anything is built or sent.
|
|
161
|
+
const envRefusal = checkPackEnv(args, line);
|
|
162
|
+
if (envRefusal !== undefined)
|
|
163
|
+
return envRefusal;
|
|
164
|
+
// ---- 1. Ensure envelope on disk -------------------------------------
|
|
165
|
+
const envelopeReady = await ensureEnvelopeExists(ctx, args, runners, line);
|
|
166
|
+
if (envelopeReady.kind === 'error')
|
|
167
|
+
return envelopeReady;
|
|
168
|
+
// ---- 2. Load + validate envelope ------------------------------------
|
|
169
|
+
const loaded = await runners.loadEnvelope({ path: args.envelopePath });
|
|
170
|
+
if (loaded.kind === 'err') {
|
|
171
|
+
return failure(`Failed to load deploy-envelope.json:\n [${loaded.code}] ${loaded.message}\n\n` +
|
|
172
|
+
`Path: ${loaded.path}\n\n` +
|
|
173
|
+
`Regenerate with \`kindgi build --env=${args.envName}\` or point --from-envelope at a valid file.\n`);
|
|
174
|
+
}
|
|
175
|
+
const envelope = loaded.envelope;
|
|
176
|
+
// ---- 3. Signed-envelope gate ----------------------------------------
|
|
177
|
+
if (!isEnvelopeSigned(envelope)) {
|
|
178
|
+
if (!args.dryRun) {
|
|
179
|
+
return failure('deploy-envelope.json is unsigned. The server will refuse the deployment.\n' +
|
|
180
|
+
'Re-run `kindgi build` without --skip-sign, or pass --dry-run to inspect ' +
|
|
181
|
+
'what would be POSTed.\n');
|
|
182
|
+
}
|
|
183
|
+
line(' ⚠ Envelope is unsigned — --dry-run is proceeding for inspection only.');
|
|
184
|
+
line('');
|
|
185
|
+
}
|
|
186
|
+
// ---- 4. Consistency check: envelope.tenantId vs --tenant override ---
|
|
187
|
+
if (args.explicitTenantId !== undefined && args.explicitTenantId !== envelope.tenantId) {
|
|
188
|
+
return failure(`--tenant mismatch: envelope was signed against tenantId="${envelope.tenantId}", but --tenant was passed as "${args.explicitTenantId}". The server re-canonicalises using the token's tenantId + verifies the signature — a mismatch would fail with signature-invalid. Either drop --tenant or re-run \`kindgi build --tenant=${args.explicitTenantId}\`.\n`);
|
|
189
|
+
}
|
|
190
|
+
// ---- 5. Build POST body + Idempotency-Key ---------------------------
|
|
191
|
+
let postBody;
|
|
192
|
+
try {
|
|
193
|
+
postBody = buildPostBody(envelope);
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
return failure(`Internal error building POST body: ${err.message}\n`);
|
|
197
|
+
}
|
|
198
|
+
const idempotencyKey = args.idempotencyKeyOverride !== undefined
|
|
199
|
+
? args.idempotencyKeyOverride
|
|
200
|
+
: deriveIdempotencyKey(postBody);
|
|
201
|
+
// ---- 6. Secrets sync detection + warning ---------------------------
|
|
202
|
+
//
|
|
203
|
+
// `POST /v1/deployments/:id/secrets` lands after a successful
|
|
204
|
+
// deploy iff `--sync-secrets` is passed. Default OFF (regulated
|
|
205
|
+
// verticals rotate on a separate cadence).
|
|
206
|
+
//
|
|
207
|
+
// Even with the flag OFF we still surface a hint when we detect
|
|
208
|
+
// `.env.<envName>` — otherwise the developer wonders why the sync
|
|
209
|
+
// didn't happen.
|
|
210
|
+
//
|
|
211
|
+
// When flag ON: any key whose name looks secret-shaped (`_KEY`,
|
|
212
|
+
// `_SECRET`, `_TOKEN`, `_PASSWORD`, `_PRIVATE`, `_APIKEY`) fires a
|
|
213
|
+
// LOUD warning pointing at `kindgi secrets set` — plaintext
|
|
214
|
+
// secrets in `.env.<envName>` are an anti-pattern the sync route
|
|
215
|
+
// permits but discourages.
|
|
216
|
+
const secretsFile = await detectSecretsFile(args, envelope.tenantId);
|
|
217
|
+
if (secretsFile !== null && !args.syncSecrets) {
|
|
218
|
+
line(` Note: detected .env.${args.envName} (${secretsFile.entries.length} keys) at ${secretsFile.path}.`);
|
|
219
|
+
line(' --sync-secrets is OFF (default). Pass --sync-secrets to POST them to');
|
|
220
|
+
line(` /v1/deployments/${'<deploymentId>'}/secrets after the deploy lands.`);
|
|
221
|
+
line('');
|
|
222
|
+
}
|
|
223
|
+
// ---- 7. Dry-run ------------------------------------------------------
|
|
224
|
+
if (args.dryRun) {
|
|
225
|
+
line(' Dry run — would POST the following:');
|
|
226
|
+
line('');
|
|
227
|
+
line(` curl -X POST ${args.endpoint.replace(/\/+$/, '')}/v1/deployments \\`);
|
|
228
|
+
line(' -H "Authorization: Bearer <redacted>" \\');
|
|
229
|
+
line(' -H "Content-Type: application/json" \\');
|
|
230
|
+
line(` -H "Idempotency-Key: ${idempotencyKey}" \\`);
|
|
231
|
+
line(" -d @- <<'JSON'");
|
|
232
|
+
for (const bodyLine of JSON.stringify(postBody, null, 2).split('\n')) {
|
|
233
|
+
line(` ${bodyLine}`);
|
|
234
|
+
}
|
|
235
|
+
line(' JSON');
|
|
236
|
+
line('');
|
|
237
|
+
line(' --dry-run set. No request sent. Exiting 0.');
|
|
238
|
+
line('');
|
|
239
|
+
const summary = {
|
|
240
|
+
envName: args.envName,
|
|
241
|
+
endpoint: args.endpoint,
|
|
242
|
+
envelopePath: args.envelopePath,
|
|
243
|
+
idempotencyKey,
|
|
244
|
+
dryRun: true,
|
|
245
|
+
wouldPost: postBody,
|
|
246
|
+
};
|
|
247
|
+
const rendered = renderJson(summary, ctx.globals.format);
|
|
248
|
+
return {
|
|
249
|
+
kind: 'ok',
|
|
250
|
+
rendered: { stdout: rendered.stdout, stderr: `${banner.join('\n')}\n` },
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
// ---- 8. POST ---------------------------------------------------------
|
|
254
|
+
const result = await runners.postDeployment({
|
|
255
|
+
endpoint: args.endpoint,
|
|
256
|
+
token: args.token,
|
|
257
|
+
body: postBody,
|
|
258
|
+
idempotencyKey,
|
|
259
|
+
fetchImpl: ctx.fetch,
|
|
260
|
+
...(ctx.stopSignal !== undefined && { signal: ctx.stopSignal }),
|
|
261
|
+
});
|
|
262
|
+
// ---- 9. Render response ---------------------------------------------
|
|
263
|
+
const rendered = renderResponse(result, {
|
|
264
|
+
envName: args.envName,
|
|
265
|
+
endpoint: args.endpoint,
|
|
266
|
+
imageRef: envelope.imageRef,
|
|
267
|
+
artifactVersion: envelope.artifactVersion,
|
|
268
|
+
indexHash: envelope.indexHash,
|
|
269
|
+
indexCounts: countIndexPrimitives(envelope.index),
|
|
270
|
+
signerKeyId: envelope.signerKeyId ?? '(unsigned)',
|
|
271
|
+
envelopePath: args.envelopePath,
|
|
272
|
+
idempotencyKey,
|
|
273
|
+
});
|
|
274
|
+
for (const l of rendered.banner)
|
|
275
|
+
line(l);
|
|
276
|
+
if (rendered.exitCode !== 0) {
|
|
277
|
+
return {
|
|
278
|
+
kind: 'error',
|
|
279
|
+
stderr: `${banner.join('\n')}\n`,
|
|
280
|
+
exitCode: rendered.exitCode,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
// ---- 10. Post-deploy secrets sync ----------------------------------
|
|
284
|
+
//
|
|
285
|
+
// Runs iff `--sync-secrets` is passed AND the deploy landed OK AND
|
|
286
|
+
// `.env.<envName>` has entries. Otherwise no-op (default path).
|
|
287
|
+
//
|
|
288
|
+
// Errors here do NOT change the exit code — the deployment already
|
|
289
|
+
// succeeded. We surface the failure in the banner so the operator can
|
|
290
|
+
// investigate + retry the sync manually via `kindgi secrets sync`
|
|
291
|
+
// (when that CLI command lands in secrets.h).
|
|
292
|
+
const syncSummary = { performed: false };
|
|
293
|
+
const deployedRecord = result.kind === 'created' || result.kind === 'replayed' ? result.record : null;
|
|
294
|
+
if (args.syncSecrets && deployedRecord !== null) {
|
|
295
|
+
const syncOutcome = await runSecretsSync(ctx, args, runners, deployedRecord.deploymentId, line);
|
|
296
|
+
Object.assign(syncSummary, syncOutcome);
|
|
297
|
+
}
|
|
298
|
+
const jsonOut = renderJson({ ...rendered.summary, ...(args.syncSecrets && { syncSecrets: syncSummary }) }, ctx.globals.format);
|
|
299
|
+
return {
|
|
300
|
+
kind: 'ok',
|
|
301
|
+
rendered: { stdout: jsonOut.stdout, stderr: `${banner.join('\n')}\n` },
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// ---------------------------------------------------------------------
|
|
305
|
+
// Post-deploy secrets sync
|
|
306
|
+
// ---------------------------------------------------------------------
|
|
307
|
+
/**
|
|
308
|
+
* Read `.env.<envName>` + POST entries to
|
|
309
|
+
* `/v1/deployments/:deploymentId/secrets`. Only invoked when the user
|
|
310
|
+
* opted in via `--sync-secrets`. Warns loudly when secret-shaped keys
|
|
311
|
+
* are present (they should live in `kindgi secrets set` instead).
|
|
312
|
+
*/
|
|
313
|
+
async function runSecretsSync(ctx, args, runners, deploymentId, line) {
|
|
314
|
+
const file = await detectSecretsFile(args, '');
|
|
315
|
+
if (file === null || file.entries.length === 0) {
|
|
316
|
+
line(' --sync-secrets set, but no `.env.<envName>` entries to sync. Skipping.');
|
|
317
|
+
line('');
|
|
318
|
+
return { performed: false, reason: 'no-entries' };
|
|
319
|
+
}
|
|
320
|
+
// Warn loudly if any key looks secret-shaped — `.env.<envName>` was
|
|
321
|
+
// designed for env vars, not secrets (regulated verticals should use
|
|
322
|
+
// `kindgi secrets set`). We still sync — but the warning must be
|
|
323
|
+
// impossible to miss.
|
|
324
|
+
const shaped = file.entries.filter((e) => plainSecretReason(e.name, e.value) !== undefined);
|
|
325
|
+
if (shaped.length > 0) {
|
|
326
|
+
line(` ! secret-shaped keys detected in .env.${args.envName}: ${shaped.map((e) => e.name).join(', ')}`);
|
|
327
|
+
line(' Keep secrets out of .env files: store them with `kindgi secrets`.');
|
|
328
|
+
line(` Consider: kindgi secrets set --env=${args.envName} <name> <value>`);
|
|
329
|
+
line('');
|
|
330
|
+
}
|
|
331
|
+
const syncBody = {
|
|
332
|
+
envName: args.envName,
|
|
333
|
+
secrets: file.entries.map((e) => ({ name: e.name, value: e.value })),
|
|
334
|
+
};
|
|
335
|
+
const idempotencyKey = deriveSyncSecretsIdempotencyKey(deploymentId, syncBody);
|
|
336
|
+
if (runners.syncSecrets === undefined) {
|
|
337
|
+
line(' ! --sync-secrets set but no syncSecrets runner wired. Skipping.');
|
|
338
|
+
line(' (Production wiring in packages/cli/src/deploy/defaults.ts).');
|
|
339
|
+
line('');
|
|
340
|
+
return { performed: false, reason: 'runner-not-wired' };
|
|
341
|
+
}
|
|
342
|
+
line(` Syncing ${file.entries.length} secret${file.entries.length === 1 ? '' : 's'} to`);
|
|
343
|
+
line(` POST /v1/deployments/${deploymentId}/secrets`);
|
|
344
|
+
const result = await runners.syncSecrets({
|
|
345
|
+
endpoint: args.endpoint,
|
|
346
|
+
token: args.token,
|
|
347
|
+
deploymentId,
|
|
348
|
+
body: syncBody,
|
|
349
|
+
idempotencyKey,
|
|
350
|
+
fetchImpl: ctx.fetch,
|
|
351
|
+
...(ctx.stopSignal !== undefined && { signal: ctx.stopSignal }),
|
|
352
|
+
});
|
|
353
|
+
if (result.kind === 'ok') {
|
|
354
|
+
line(` ✓ 200 OK → resolved=${result.response.resolved} added=${result.response.added}`);
|
|
355
|
+
line('');
|
|
356
|
+
return {
|
|
357
|
+
performed: true,
|
|
358
|
+
resolved: result.response.resolved,
|
|
359
|
+
added: result.response.added,
|
|
360
|
+
references: result.response.references,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
if (result.kind === 'wire-error') {
|
|
364
|
+
line(` ✗ ${result.status} ${result.error.code}: ${result.error.message}`);
|
|
365
|
+
line(' The deployment landed OK; only the secret sync failed. Retry with');
|
|
366
|
+
line(' `kindgi deploy --sync-secrets` (idempotent).');
|
|
367
|
+
line('');
|
|
368
|
+
return { performed: false, error: { code: result.error.code, message: result.error.message } };
|
|
369
|
+
}
|
|
370
|
+
line(` ✗ transport error: ${result.message}`);
|
|
371
|
+
line('');
|
|
372
|
+
return { performed: false, error: { code: 'transport-error', message: result.message } };
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* The deploy preflight for the pack service's env (R4): the plan's lines
|
|
376
|
+
* when the pack declares any, and the refusal when a required name has no
|
|
377
|
+
* value (unless `--allow-missing-env`) or a secret is given in the clear.
|
|
378
|
+
*/
|
|
379
|
+
function checkPackEnv(args, line) {
|
|
380
|
+
const plan = args.packEnv;
|
|
381
|
+
if (plan.entries.length === 0 && plan.problems.length === 0 && plan.warnings.length === 0) {
|
|
382
|
+
return undefined;
|
|
383
|
+
}
|
|
384
|
+
for (const l of describePackEnvPlan(plan))
|
|
385
|
+
line(l);
|
|
386
|
+
line('');
|
|
387
|
+
if (plan.problems.length > 0) {
|
|
388
|
+
return failure(`kindgi deploy: the pack service's env for ${args.envName} gives a secret in the clear or is malformed (above). Fix environments.${args.envName}.env in kindgi.config and deploy again.\n`);
|
|
389
|
+
}
|
|
390
|
+
if (plan.missing.length > 0 && !args.allowMissingEnv) {
|
|
391
|
+
return failure(`kindgi deploy: ${plan.missing.join(', ')} ${plan.missing.length === 1 ? 'is' : 'are'} required by the pack and ${plan.missing.length === 1 ? 'has' : 'have'} no value in environments.${args.envName}.env, so the pack service wouldn't be ready. Add ${plan.missing.length === 1 ? 'it' : 'them'}, or deploy anyway with --allow-missing-env.\n`);
|
|
392
|
+
}
|
|
393
|
+
if (plan.missing.length > 0) {
|
|
394
|
+
line(` ⚠ --allow-missing-env: deploying without ${plan.missing.join(', ')}`);
|
|
395
|
+
line('');
|
|
396
|
+
}
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
// ---------------------------------------------------------------------
|
|
400
|
+
// Envelope existence — either read from disk or inline-build
|
|
401
|
+
// ---------------------------------------------------------------------
|
|
402
|
+
async function ensureEnvelopeExists(ctx, args, runners, line) {
|
|
403
|
+
const exists = await pathExists(args.envelopePath);
|
|
404
|
+
if (exists)
|
|
405
|
+
return { kind: 'ok' };
|
|
406
|
+
if (args.explicitEnvelope) {
|
|
407
|
+
return failure(`deploy-envelope.json not found at ${args.envelopePath} (--from-envelope). Verify the path or drop --from-envelope to auto-build.\n`);
|
|
408
|
+
}
|
|
409
|
+
// Auto-detect path is missing → run build inline.
|
|
410
|
+
line(` Envelope missing — running \`kindgi build --env=${args.envName}\` inline...`);
|
|
411
|
+
line('');
|
|
412
|
+
if (runners.runBuild !== undefined) {
|
|
413
|
+
const buildArgv = buildInlineArgv(ctx, args);
|
|
414
|
+
const outcome = await runners.runBuild({
|
|
415
|
+
buildArgv,
|
|
416
|
+
packDir: args.packDir,
|
|
417
|
+
});
|
|
418
|
+
if (outcome.kind === 'err') {
|
|
419
|
+
return failure(`Inline \`kindgi build\` failed (exit ${outcome.exitCode}):\n\n${outcome.stderr}`);
|
|
420
|
+
}
|
|
421
|
+
if (outcome.banner.length > 0) {
|
|
422
|
+
line(outcome.banner);
|
|
423
|
+
line('');
|
|
424
|
+
}
|
|
425
|
+
// After the build the envelope should exist. If the build wrote it
|
|
426
|
+
// to a different location than we auto-detected, honour the build's
|
|
427
|
+
// reported path.
|
|
428
|
+
const producedExists = await pathExists(outcome.envelopePath);
|
|
429
|
+
if (!producedExists) {
|
|
430
|
+
return failure(`\`kindgi build\` completed but no deploy-envelope.json was written at ${outcome.envelopePath}. Aborting.\n`);
|
|
431
|
+
}
|
|
432
|
+
// Rebind path to the build's actual output. Mutating a readonly
|
|
433
|
+
// typed field is not allowed — the caller pattern is to inspect
|
|
434
|
+
// .envelopePath below.
|
|
435
|
+
args.envelopePath =
|
|
436
|
+
outcome.envelopePath;
|
|
437
|
+
return { kind: 'ok' };
|
|
438
|
+
}
|
|
439
|
+
// No inline runner available — invoke the same-package `runBuild`
|
|
440
|
+
// directly. This is the production path when
|
|
441
|
+
// `deployRunners.runBuild` is omitted (see `deploy/defaults.ts`).
|
|
442
|
+
const built = await runInlineBuild(ctx, args);
|
|
443
|
+
if (built.kind === 'error')
|
|
444
|
+
return built;
|
|
445
|
+
if (built.banner.length > 0) {
|
|
446
|
+
line(built.banner);
|
|
447
|
+
line('');
|
|
448
|
+
}
|
|
449
|
+
return { kind: 'ok' };
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Run `kindgi build` in-process, threading through the same
|
|
453
|
+
* `CommandContext` (buildRunners, buildConfigLoader, env, cwd, etc.)
|
|
454
|
+
* but with an argument set derived from the deploy invocation. We
|
|
455
|
+
* clone the context with `options` replaced so the build command sees
|
|
456
|
+
* only build-relevant flags.
|
|
457
|
+
*/
|
|
458
|
+
async function runInlineBuild(ctx, args) {
|
|
459
|
+
const buildOptions = buildInlineOptions(ctx, args);
|
|
460
|
+
const buildCtx = { ...ctx, options: buildOptions };
|
|
461
|
+
const result = await runBuild(buildCtx);
|
|
462
|
+
if (result.kind === 'error') {
|
|
463
|
+
return {
|
|
464
|
+
kind: 'error',
|
|
465
|
+
stderr: `Inline \`kindgi build\` failed (exit ${result.exitCode}):\n\n${result.stderr}`,
|
|
466
|
+
exitCode: 1,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
// Build success — envelope should now exist at args.envelopePath.
|
|
470
|
+
const exists = await pathExists(args.envelopePath);
|
|
471
|
+
if (!exists) {
|
|
472
|
+
return {
|
|
473
|
+
kind: 'error',
|
|
474
|
+
stderr: `\`kindgi build\` completed but no deploy-envelope.json was written at ${args.envelopePath}. Aborting.\n`,
|
|
475
|
+
exitCode: 1,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
kind: 'ok',
|
|
480
|
+
banner: result.rendered.stderr.trim(),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function buildInlineOptions(ctx, args) {
|
|
484
|
+
const opts = {};
|
|
485
|
+
opts.env = args.envName;
|
|
486
|
+
opts.path = args.packDir;
|
|
487
|
+
opts.out = args.outDir;
|
|
488
|
+
const pass = (key, alias) => {
|
|
489
|
+
const val = ctx.options[alias ?? key];
|
|
490
|
+
if (val !== undefined)
|
|
491
|
+
opts[key] = val;
|
|
492
|
+
};
|
|
493
|
+
pass('target');
|
|
494
|
+
// The deploy command has its OWN --endpoint (for the api-server). The
|
|
495
|
+
// build server URL is either `env.build` in kindgi.config.ts OR
|
|
496
|
+
// deploy's `--build-endpoint` alias. Thread the alias into build's
|
|
497
|
+
// `--endpoint`.
|
|
498
|
+
const buildEndpoint = ctx.options['build-endpoint'];
|
|
499
|
+
if (buildEndpoint !== undefined)
|
|
500
|
+
opts.endpoint = buildEndpoint;
|
|
501
|
+
pass('artifact-version');
|
|
502
|
+
pass('published-at');
|
|
503
|
+
if (args.explicitTenantId !== undefined)
|
|
504
|
+
opts.tenant = args.explicitTenantId;
|
|
505
|
+
pass('signing-key');
|
|
506
|
+
pass('signer-key-id');
|
|
507
|
+
pass('registry-push-creds');
|
|
508
|
+
pass('skip-integrity-gate');
|
|
509
|
+
pass('skip-image-pull');
|
|
510
|
+
pass('skip-sign');
|
|
511
|
+
return opts;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Same as `buildInlineOptions` but flattened into a `--flag=value`
|
|
515
|
+
* argv-style array. Used when a test-supplied `DeployRunners.runBuild`
|
|
516
|
+
* wants to see the exact CLI form the command would have invoked.
|
|
517
|
+
*/
|
|
518
|
+
function buildInlineArgv(ctx, args) {
|
|
519
|
+
const opts = buildInlineOptions(ctx, args);
|
|
520
|
+
const out = ['build'];
|
|
521
|
+
for (const [k, v] of Object.entries(opts)) {
|
|
522
|
+
if (v === undefined)
|
|
523
|
+
continue;
|
|
524
|
+
if (typeof v === 'boolean') {
|
|
525
|
+
if (v)
|
|
526
|
+
out.push(`--${k}`);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
out.push(`--${k}=${v}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return out;
|
|
533
|
+
}
|
|
534
|
+
async function resolveDeployArgs(ctx) {
|
|
535
|
+
// --path — pack root, default cwd.
|
|
536
|
+
const pathFlag = ctx.options.path;
|
|
537
|
+
const rawPath = typeof pathFlag === 'string' && pathFlag !== '' ? pathFlag : ctx.cwd;
|
|
538
|
+
const packDir = isAbsolute(rawPath) ? rawPath : resolve(ctx.cwd, rawPath);
|
|
539
|
+
// Load kindgi.config.ts — same seam kindgi build uses.
|
|
540
|
+
const config = await loadDeployConfig(ctx, packDir);
|
|
541
|
+
if (config.kind === 'error')
|
|
542
|
+
return config;
|
|
543
|
+
const cfg = config.config;
|
|
544
|
+
// --env — default staging (matches build's default).
|
|
545
|
+
const envFlag = ctx.options.env;
|
|
546
|
+
const envName = typeof envFlag === 'string' && envFlag !== '' ? envFlag : 'staging';
|
|
547
|
+
const envBlock = cfg.environments?.[envName] !== undefined
|
|
548
|
+
? cfg.environments[envName]
|
|
549
|
+
: undefined;
|
|
550
|
+
// --out — resolves the output dir the build command uses.
|
|
551
|
+
const outFlag = ctx.options.out;
|
|
552
|
+
const outDirRaw = typeof outFlag === 'string' && outFlag !== '' ? outFlag : '.kindgi/build';
|
|
553
|
+
const outDir = isAbsolute(outDirRaw) ? outDirRaw : resolve(packDir, outDirRaw);
|
|
554
|
+
// --endpoint — env.endpoint > --endpoint flag > config apiUrl > KINDGI_API_URL > error.
|
|
555
|
+
const endpointFlag = ctx.options.endpoint;
|
|
556
|
+
const endpoint = typeof endpointFlag === 'string' && endpointFlag !== ''
|
|
557
|
+
? endpointFlag
|
|
558
|
+
: (envBlock?.endpoint ??
|
|
559
|
+
ctx.config.apiUrl ??
|
|
560
|
+
(typeof ctx.env.KINDGI_API_URL === 'string'
|
|
561
|
+
? ctx.env.KINDGI_API_URL
|
|
562
|
+
: undefined));
|
|
563
|
+
if (endpoint === undefined || endpoint === '') {
|
|
564
|
+
return {
|
|
565
|
+
kind: 'error',
|
|
566
|
+
stderr: `kindgi deploy could not resolve an API endpoint. Set environments.${envName}.endpoint in kindgi.config.ts, pass --endpoint <url>, or export KINDGI_API_URL.\n`,
|
|
567
|
+
exitCode: 1,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
// --token — bearer token; standard config precedence.
|
|
571
|
+
const token = ctx.config.token;
|
|
572
|
+
if (token === undefined || token === '') {
|
|
573
|
+
return {
|
|
574
|
+
kind: 'error',
|
|
575
|
+
stderr: 'kindgi deploy could not resolve an API token. ' +
|
|
576
|
+
'Pass --token <bearer>, export KINDGI_API_TOKEN, or run `kindgi auth login`.\n',
|
|
577
|
+
exitCode: 1,
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
// --tenant — used only as a consistency check against the envelope.
|
|
581
|
+
const tenantFlag = ctx.options.tenant;
|
|
582
|
+
const explicitTenantId = typeof tenantFlag === 'string' && tenantFlag !== '' ? tenantFlag : undefined;
|
|
583
|
+
// --from-envelope — explicit path OR auto-detect.
|
|
584
|
+
const fromFlag = ctx.options['from-envelope'];
|
|
585
|
+
const explicitEnvelope = typeof fromFlag === 'string' && fromFlag !== '';
|
|
586
|
+
const envelopePath = explicitEnvelope
|
|
587
|
+
? isAbsolute(fromFlag)
|
|
588
|
+
? fromFlag
|
|
589
|
+
: resolve(ctx.cwd, fromFlag)
|
|
590
|
+
: join(outDir, 'deploy-envelope.json');
|
|
591
|
+
const idempotencyKeyFlag = ctx.options['idempotency-key'];
|
|
592
|
+
const idempotencyKeyOverride = typeof idempotencyKeyFlag === 'string' && idempotencyKeyFlag !== ''
|
|
593
|
+
? idempotencyKeyFlag
|
|
594
|
+
: undefined;
|
|
595
|
+
const dryRun = ctx.options['dry-run'] === true;
|
|
596
|
+
// Opt-in flag. Default OFF (see `syncSecrets` above).
|
|
597
|
+
const syncSecrets = ctx.options['sync-secrets'] === true;
|
|
598
|
+
// The pack service's env in this environment: the declaration in
|
|
599
|
+
// `env` against `environments.<envName>.env` (checked in runDeploy).
|
|
600
|
+
const packEnv = planPackEnv(cfg, envName);
|
|
601
|
+
if (packEnv.kind === 'err') {
|
|
602
|
+
return { kind: 'error', stderr: `kindgi deploy: ${packEnv.message}\n`, exitCode: 1 };
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
kind: 'ok',
|
|
606
|
+
args: {
|
|
607
|
+
packDir,
|
|
608
|
+
outDir,
|
|
609
|
+
envName,
|
|
610
|
+
endpoint,
|
|
611
|
+
token,
|
|
612
|
+
envelopePath,
|
|
613
|
+
envelopeSource: explicitEnvelope ? 'explicit' : 'auto-detect',
|
|
614
|
+
explicitEnvelope,
|
|
615
|
+
explicitTenantId,
|
|
616
|
+
idempotencyKeyOverride,
|
|
617
|
+
dryRun,
|
|
618
|
+
syncSecrets,
|
|
619
|
+
envBlock,
|
|
620
|
+
packEnv: packEnv.plan,
|
|
621
|
+
allowMissingEnv: ctx.options['allow-missing-env'] === true,
|
|
622
|
+
},
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
async function loadDeployConfig(ctx, packDir) {
|
|
626
|
+
const outcome = await loadPackConfig(ctx, packDir);
|
|
627
|
+
if (outcome.kind === 'ok')
|
|
628
|
+
return { kind: 'ok', config: outcome.config };
|
|
629
|
+
return {
|
|
630
|
+
kind: 'error',
|
|
631
|
+
stderr: outcome.kind === 'missing'
|
|
632
|
+
? `kindgi deploy could not load kindgi.config.ts at ${packDir}. Run \`kindgi init <pack-name>\` to scaffold a pack, or pass --path=<dir>.\n`
|
|
633
|
+
: `Failed to load kindgi.config.ts at ${packDir}: ${outcome.message}\n`,
|
|
634
|
+
exitCode: 1,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
// ---------------------------------------------------------------------
|
|
638
|
+
// Small helpers
|
|
639
|
+
// ---------------------------------------------------------------------
|
|
640
|
+
async function pathExists(path) {
|
|
641
|
+
try {
|
|
642
|
+
await stat(path);
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
catch {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
function failure(stderr) {
|
|
650
|
+
return { kind: 'error', stderr, exitCode: 1 };
|
|
651
|
+
}
|
|
652
|
+
function countIndexPrimitives(index) {
|
|
653
|
+
const asArrLen = (v) => (Array.isArray(v) ? v.length : 0);
|
|
654
|
+
return {
|
|
655
|
+
tools: asArrLen(index.tools),
|
|
656
|
+
guardrails: asArrLen(index.guardrails),
|
|
657
|
+
agents: asArrLen(index.agents),
|
|
658
|
+
flows: asArrLen(index.flows),
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Detect an out-of-band secrets file (`.env.<envName>`) next to the
|
|
663
|
+
* pack config + parse its `KEY=value` entries. Comments + blank lines
|
|
664
|
+
* are skipped. When the `--sync-secrets` flag is off, the
|
|
665
|
+
* detector still fires so the CLI can hint at the opt-in path. When
|
|
666
|
+
* the flag is on, the returned `entries` become the sync-request body.
|
|
667
|
+
*
|
|
668
|
+
* Parser is intentionally minimal (same subset as
|
|
669
|
+
* `packages/cli/src/env/parser.ts` — but re-inlined here to avoid
|
|
670
|
+
* pulling the whole `kindgi env` command flow into `deploy`).
|
|
671
|
+
*/
|
|
672
|
+
async function detectSecretsFile(args, _tenantId) {
|
|
673
|
+
// `local` is the project's own env files — in an existing app, the
|
|
674
|
+
// app's whole `.env`. `kindgi dev` reads them directly; they are never
|
|
675
|
+
// pushed anywhere.
|
|
676
|
+
if (args.envName === LOCAL_ENV_NAME)
|
|
677
|
+
return null;
|
|
678
|
+
let env;
|
|
679
|
+
try {
|
|
680
|
+
env = await readPackEnv({ packDir: args.packDir, envName: args.envName });
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
// If we can't read it, don't warn — a real file with a real
|
|
684
|
+
// problem will surface elsewhere.
|
|
685
|
+
return null;
|
|
686
|
+
}
|
|
687
|
+
if (env.present.length === 0)
|
|
688
|
+
return null;
|
|
689
|
+
// Same reader as `kindgi dev` / `kindgi env`: dotenv grammar, `${VAR}`
|
|
690
|
+
// expanded (no shell fallback — local machine values must not leak
|
|
691
|
+
// into a deployed environment), `KINDGI_*` runtime names excluded.
|
|
692
|
+
const entries = Object.entries(packValues(env.values))
|
|
693
|
+
.filter(([name]) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
|
|
694
|
+
.map(([name, value]) => ({ name, value }));
|
|
695
|
+
return { path: env.files.write, entries };
|
|
696
|
+
}
|
|
697
|
+
//# sourceMappingURL=deploy.js.map
|