@kindgi/cli 0.0.0-bootstrap.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +690 -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 +45 -0
- package/dist/build/bundle.d.ts.map +1 -0
- package/dist/build/bundle.js +121 -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 +196 -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 +586 -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 +48 -0
- package/dist/build/host-install.d.ts.map +1 -0
- package/dist/build/host-install.js +375 -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 +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +88 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/build.d.ts +39 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +872 -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 +44 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +1032 -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 +37 -0
- package/dist/commands/helpers.d.ts.map +1 -0
- package/dist/commands/helpers.js +93 -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 +455 -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 +202 -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 +221 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/secrets.d.ts +21 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +750 -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 +153 -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 +17 -0
- package/dist/commands/unwired.d.ts.map +1 -0
- package/dist/commands/unwired.js +41 -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 +153 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +44 -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 +8 -0
- package/dist/dev/bundler.d.ts.map +1 -0
- package/dist/dev/bundler.js +154 -0
- package/dist/dev/bundler.js.map +1 -0
- package/dist/dev/defaults.d.ts +138 -0
- package/dist/dev/defaults.d.ts.map +1 -0
- package/dist/dev/defaults.js +691 -0
- package/dist/dev/defaults.js.map +1 -0
- package/dist/dev/docker-compose.dev.yml +56 -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 +32 -0
- package/dist/dev/pack-service.d.ts.map +1 -0
- package/dist/dev/pack-service.js +188 -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/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 +287 -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 +62 -0
- package/dist/dev/runtime-container.d.ts.map +1 -0
- package/dist/dev/runtime-container.js +164 -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 +13 -0
- package/dist/dev/runtime-image.d.ts.map +1 -0
- package/dist/dev/runtime-image.js +15 -0
- package/dist/dev/runtime-image.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 +107 -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 +74 -0
- package/dist/init/augment-scaffolder.d.ts.map +1 -0
- package/dist/init/augment-scaffolder.js +459 -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/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 +16 -0
- package/dist/init/template-files.d.ts.map +1 -0
- package/dist/init/template-files.js +38 -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 +106 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +198 -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 +82 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +99 -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 +253 -0
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +299 -0
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +291 -0
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +289 -0
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +704 -0
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +288 -0
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +211 -0
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +181 -0
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +205 -0
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +322 -0
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +173 -0
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +299 -0
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +240 -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/.gitignore +8 -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/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 +6 -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/.gitignore +9 -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/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/.gitignore +8 -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/guardrails/response-not-empty/index.ts.tmpl +50 -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 +6 -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/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,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kindgi-python-authoring-guardrails
|
|
3
|
+
description: >
|
|
4
|
+
Covers writing guardrails (safety checks on an agent's turn) for a
|
|
5
|
+
Kindgi pack in Python (the `kindgi` package): the `@guardrail`
|
|
6
|
+
decorator over a `(config, trace)` check, `RunTrace` and
|
|
7
|
+
`CheckResult`, config models, actions (halt / retry / escalate /
|
|
8
|
+
log-only / compensate), severity and scope, unit tests, and wiring a
|
|
9
|
+
guardrail onto an agent. Load this whenever you are authoring or
|
|
10
|
+
editing code inside a Python pack's guardrails/ directory (a pack
|
|
11
|
+
whose config is `[tool.kindgi]` in pyproject.toml), defining a check,
|
|
12
|
+
or wiring a guardrail onto an agent. Python agents are covered by
|
|
13
|
+
kindgi-python-authoring-agents, Python tools by
|
|
14
|
+
kindgi-python-authoring-tools.
|
|
15
|
+
type: core
|
|
16
|
+
library: "kindgi (Python)"
|
|
17
|
+
version: "0.1.0"
|
|
18
|
+
sdk_version: "0.1.0"
|
|
19
|
+
pack_languages: [python]
|
|
20
|
+
sources:
|
|
21
|
+
- sdks/python/src/kindgi/pack/define.py
|
|
22
|
+
- sdks/python/src/kindgi/pack/trace.py
|
|
23
|
+
- sdks/python/src/kindgi/pack/service.py
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Authoring Kindgi guardrails in Python
|
|
27
|
+
|
|
28
|
+
> **Running `kindgi`:** a Python pack has no Node project, so the
|
|
29
|
+
> `kindgi` CLI is the one on `PATH`. Python commands run in the pack's
|
|
30
|
+
> environment: `uv run …` (or `.venv/bin/python …`).
|
|
31
|
+
|
|
32
|
+
A **guardrail** is a rule an agent's turn must satisfy: a **check** (a
|
|
33
|
+
function over the turn's trace) plus an **action** (what happens when it
|
|
34
|
+
fails). In a Python pack, `@guardrail(...)` on a function at module
|
|
35
|
+
level in a file under `guardrails/` declares both. For an agent turn,
|
|
36
|
+
the runtime evaluates every guardrail the agent lists once, on the final
|
|
37
|
+
answer, before it is stored.
|
|
38
|
+
|
|
39
|
+
Ask what the rule should catch before writing one; the sample
|
|
40
|
+
`response-not-empty` guardrail is a demonstration, not a template.
|
|
41
|
+
|
|
42
|
+
## A guardrail
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
# guardrails/citations.py
|
|
46
|
+
from pydantic import BaseModel, Field
|
|
47
|
+
|
|
48
|
+
from kindgi import CheckResult, RunTrace, guardrail
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Config(BaseModel):
|
|
52
|
+
min_lookups: int = Field(1, alias="minLookups", ge=0)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@guardrail(
|
|
56
|
+
id="acme.no-fabricated-quotes",
|
|
57
|
+
name="No fabricated quotations",
|
|
58
|
+
on_violation="halt",
|
|
59
|
+
severity="critical",
|
|
60
|
+
config={"minLookups": 2}, # what the check runs with — keyed as on the wire
|
|
61
|
+
)
|
|
62
|
+
def no_fabricated_quotes(config: Config, trace: RunTrace) -> CheckResult:
|
|
63
|
+
lookups = [c for c in trace.tool_calls if c.tool_name == "acme.verify-citation"]
|
|
64
|
+
if len(lookups) < config.min_lookups:
|
|
65
|
+
return CheckResult(
|
|
66
|
+
passed=False,
|
|
67
|
+
reason=f"Only {len(lookups)} citation lookups (need {config.min_lookups}+).",
|
|
68
|
+
)
|
|
69
|
+
return CheckResult(passed=True)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- **The check** is `(config, trace)`, `def` or `async def`, and returns a
|
|
73
|
+
`CheckResult`, a dict with a boolean `"passed"`, or a `bool`. A failed
|
|
74
|
+
result's `reason` is what the violation reports — make it say what was
|
|
75
|
+
wrong.
|
|
76
|
+
- **`trace`** is a `RunTrace` (snake_case here, camelCase on the wire):
|
|
77
|
+
`output` (the final answer text), `tool_calls` (`tool_id`,
|
|
78
|
+
`tool_name`, `arguments`), `tool_results` (`tool_call_id`, `output`),
|
|
79
|
+
`model_calls` (`provider_id`, `model`, tokens), `user_input`,
|
|
80
|
+
`agent_id`, `conversation_id`, `turn_number`, `total_cost_usd`,
|
|
81
|
+
`duration_ms`, `mode` (`"runtime"` or `"ci"`). Annotate it `dict` to get
|
|
82
|
+
the raw wire dict instead.
|
|
83
|
+
- **`config`** — its type comes from the first parameter's annotation
|
|
84
|
+
(or `config_type=`) and becomes the guardrail's config schema. The
|
|
85
|
+
values are `config=` on the decorator, keyed as on the wire (the
|
|
86
|
+
model's aliases): `@guardrail(..., config={"minLookups": 2})`. They are
|
|
87
|
+
checked against the type where declared, go into the index, and the
|
|
88
|
+
check runs with them. Without `config=` the check runs with `{}` — so
|
|
89
|
+
give every field a default; a required field without a value fails
|
|
90
|
+
every evaluation (`input-validation-failed`).
|
|
91
|
+
- An exception in the check fails the evaluation (`handler-throw`);
|
|
92
|
+
return a failed `CheckResult` for a rule that isn't met.
|
|
93
|
+
- A check gets no model and no provider: it can't call an LLM. Keep it a
|
|
94
|
+
pure function of the trace (fast, deterministic, free).
|
|
95
|
+
|
|
96
|
+
## `@guardrail(...)`
|
|
97
|
+
|
|
98
|
+
- **`id`** — `<pack-id>.<guardrail-name>`, kebab-case. Name the rule as
|
|
99
|
+
a positive assertion: `no-fabricated-quotes`, `response-not-empty`.
|
|
100
|
+
- **`on_violation`** — the action: `"halt"`, `"retry"`, `"escalate"`,
|
|
101
|
+
`"log-only"`, `"compensate"`. For one that needs settings pass the
|
|
102
|
+
whole object with `action=` instead (exactly one of the two):
|
|
103
|
+
`action={"on-violation": "retry", "retry": {"maxAttempts": 2}}`,
|
|
104
|
+
`{"on-violation": "escalate", "escalateTo": …}`,
|
|
105
|
+
`{"on-violation": "compensate", "compensateWith": "<tool id>"}`.
|
|
106
|
+
In an agent turn a failed `halt` guardrail fails the turn
|
|
107
|
+
(`guardrail-violation`) and the answer is not stored; any other action
|
|
108
|
+
reports the failure in the turn result's `violations` and the turn
|
|
109
|
+
completes.
|
|
110
|
+
- **`severity`** — `"info"`, `"warn"`, `"error"` (default), `"critical"`.
|
|
111
|
+
Independent of the action: dashboards group by severity, execution
|
|
112
|
+
follows the action.
|
|
113
|
+
- **`scope`** — when it applies: `{"when": "always" | "ci-only" |
|
|
114
|
+
"runtime-only"}`, narrowed by `agents`, `flows`, `tenants` lists.
|
|
115
|
+
- **`kind`** — `"zero-llm"` (default): a check over the trace — what a
|
|
116
|
+
pack writes.
|
|
117
|
+
- **`config`** — the values the check runs with (above); **`config_type`**
|
|
118
|
+
— the config's type when the check's first parameter isn't annotated
|
|
119
|
+
with it.
|
|
120
|
+
- **`name`** — a display name. **`check_id`** — defaults to the id.
|
|
121
|
+
- `sandbox=`, `limits=`, `network=` are recorded in the index.
|
|
122
|
+
|
|
123
|
+
## Testing
|
|
124
|
+
|
|
125
|
+
A `Guardrail` is still callable:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
# tests/test_guardrails.py
|
|
129
|
+
from kindgi import RunTrace
|
|
130
|
+
from guardrails.citations import Config, no_fabricated_quotes
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_no_lookups_fails():
|
|
134
|
+
trace = RunTrace(run_id="r", tenant_id="t", output="As held in Smith v. Jones…")
|
|
135
|
+
assert not no_fabricated_quotes(Config(), trace).passed
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`RunTrace(...)` takes snake_case fields; `tool_calls` entries are
|
|
139
|
+
`ToolCallRecord(tool_id=…, tool_name=…, arguments={…}, at="…")`.
|
|
140
|
+
|
|
141
|
+
## Wiring onto an agent
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from ..guardrails.citations import no_fabricated_quotes
|
|
145
|
+
|
|
146
|
+
brief_writer = Agent(..., guardrails=[no_fabricated_quotes])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The `Guardrail` object (or its id). `kindgi dev` registers the pack's
|
|
150
|
+
guardrails; an agent naming an id with no registered guardrail fails
|
|
151
|
+
its turn (`unresolved-guardrail`).
|
|
152
|
+
|
|
153
|
+
## Common mistakes
|
|
154
|
+
|
|
155
|
+
1. **A required config field with no `config=` value.** Without
|
|
156
|
+
`config=` the check runs with `{}`; give the field a default or the
|
|
157
|
+
guardrail its values.
|
|
158
|
+
2. **Snake_case keys in `config=`.** It is keyed like the wire — the
|
|
159
|
+
model's aliases (`{"minLookups": 2}`), not the field names.
|
|
160
|
+
3. **Both `on_violation=` and `action=`, or neither** — `DefinitionError`.
|
|
161
|
+
4. **Expecting retries from `halt`.** `halt` stops the turn; use
|
|
162
|
+
`action={"on-violation": "retry", …}` for another attempt.
|
|
163
|
+
5. **Calling a model from the check.** Not available; keep checks pure.
|
|
164
|
+
6. **Raising for a broken rule.** Return `CheckResult(passed=False,
|
|
165
|
+
reason=…)`; an exception is an evaluation error, not a violation.
|
|
166
|
+
7. **Defining the guardrail inside a function** — only module-level
|
|
167
|
+
primitives are indexed.
|
|
168
|
+
|
|
169
|
+
## When the framework itself is the problem
|
|
170
|
+
|
|
171
|
+
If the bug is in Kindgi or the `kindgi` package (a trace field missing,
|
|
172
|
+
a misleading error) and not in the check, load
|
|
173
|
+
`kindgi-framework-feedback` and file it with `kindgi feedback write`.
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kindgi-python-authoring-tools
|
|
3
|
+
description: >
|
|
4
|
+
Covers writing tools for a Kindgi pack in Python (the `kindgi`
|
|
5
|
+
package): the `@tool` decorator, input and output schemas from pydantic
|
|
6
|
+
models / TypedDicts / dataclasses (or JSON Schema), sync and async
|
|
7
|
+
handlers, `ToolContext` and cancellation, reading configuration and
|
|
8
|
+
secrets, errors, tool id and version conventions, unit tests, and
|
|
9
|
+
wiring a tool onto an agent. Load this whenever you are authoring or
|
|
10
|
+
editing code inside a Python pack's tools/ directory (a pack whose
|
|
11
|
+
config is `[tool.kindgi]` in pyproject.toml), defining a tool, or
|
|
12
|
+
wiring one onto an agent. Python agents are covered by
|
|
13
|
+
kindgi-python-authoring-agents, getting started by
|
|
14
|
+
kindgi-python-getting-started.
|
|
15
|
+
type: core
|
|
16
|
+
library: "kindgi (Python)"
|
|
17
|
+
version: "0.1.0"
|
|
18
|
+
sdk_version: "0.1.0"
|
|
19
|
+
pack_languages: [python]
|
|
20
|
+
sources:
|
|
21
|
+
- sdks/python/src/kindgi/pack/define.py
|
|
22
|
+
- sdks/python/src/kindgi/pack/context.py
|
|
23
|
+
- sdks/python/src/kindgi/pack/service.py
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Authoring Kindgi tools in Python
|
|
27
|
+
|
|
28
|
+
> **Running `kindgi`:** a Python pack has no Node project, so the
|
|
29
|
+
> `kindgi` CLI is the one on `PATH`. Python commands run in the pack's
|
|
30
|
+
> environment: `uv run …` (or `.venv/bin/python …`).
|
|
31
|
+
|
|
32
|
+
A **tool** is a unit of work an agent (or a flow step) calls: typed
|
|
33
|
+
input, typed output, your code in between. In a Python pack it is a
|
|
34
|
+
function decorated with `@tool` at module level in a file under
|
|
35
|
+
`tools/`. Kindgi runs it in the pack's own Python process (the pack
|
|
36
|
+
service) and calls it over HTTP; the model sees its id, description and
|
|
37
|
+
input schema.
|
|
38
|
+
|
|
39
|
+
Before writing one, establish what it should **do** — what it computes
|
|
40
|
+
or fetches, what the caller provides, what it returns. "Add a tool" is
|
|
41
|
+
a conversation opener. The pack's sample tools prove the runtime works;
|
|
42
|
+
they are not the shape to copy unless the user asks.
|
|
43
|
+
|
|
44
|
+
## A tool
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
# tools/citations.py
|
|
48
|
+
import os
|
|
49
|
+
|
|
50
|
+
from pydantic import BaseModel, Field
|
|
51
|
+
|
|
52
|
+
from kindgi import ToolContext, tool
|
|
53
|
+
|
|
54
|
+
from ._citator import lookup # a helper module: the leading `_` keeps it out of discovery
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Citation(BaseModel):
|
|
58
|
+
citation: str = Field(min_length=1)
|
|
59
|
+
jurisdiction: str = Field(pattern="^(US|UK|EU)$")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Verdict(BaseModel):
|
|
63
|
+
found: bool
|
|
64
|
+
canonical_cite: str | None = Field(None, alias="canonicalCite")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@tool(id="acme.verify-citation")
|
|
68
|
+
def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
|
|
69
|
+
"""Verify a legal citation against the citator; returns whether it resolves and its canonical form."""
|
|
70
|
+
hit = lookup(os.environ["CITATOR_URL"], citation.citation, citation.jurisdiction)
|
|
71
|
+
return Verdict(found=hit is not None, canonicalCite=hit)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- **Id** — `<pack-id>.<tool-name>`, kebab-case, dot-namespaced.
|
|
75
|
+
- **Description** — the docstring, or `description=`. The model reads
|
|
76
|
+
it to decide when to call the tool: say what it does and returns.
|
|
77
|
+
- **Version** — the pack's version, or `version=` (an exact semver).
|
|
78
|
+
- **Schemas** — from the annotations: the first parameter is the input,
|
|
79
|
+
the return annotation the output. A pydantic model, a `TypedDict`, a
|
|
80
|
+
dataclass — anything pydantic understands — or `input=` / `output=`
|
|
81
|
+
(a type, or a JSON Schema dict). **Field aliases are the names on the
|
|
82
|
+
wire** — use them for camelCase (`alias="canonicalCite"`), and
|
|
83
|
+
construct the model with the alias. The input must be an **object**:
|
|
84
|
+
a model calls a tool with an object of arguments.
|
|
85
|
+
- **Handler** — `(input)` or `(input, ctx)`; `def` or `async def`. A
|
|
86
|
+
`def` handler runs in a worker thread, so blocking I/O is fine; an
|
|
87
|
+
`async def` one runs on the event loop — don't block it (use an async
|
|
88
|
+
client, or `asyncio.to_thread`).
|
|
89
|
+
- **Validation** — before your handler runs, the input is checked
|
|
90
|
+
against the schema (JSON Schema defaults filled in) and your model's
|
|
91
|
+
own validators run; what you return is validated against the output
|
|
92
|
+
schema. A bad input comes back as `input-validation-failed` with the
|
|
93
|
+
field's path (a bad output as `output-validation-failed`); the agent's
|
|
94
|
+
`tool_errors` policy decides whether the model gets to fix the call.
|
|
95
|
+
- **Problems in the declaration** (a missing docstring, an
|
|
96
|
+
unannotated parameter, a non-object input) raise `DefinitionError`
|
|
97
|
+
where the tool is declared; the indexer reports it with the file.
|
|
98
|
+
|
|
99
|
+
## `ToolContext`
|
|
100
|
+
|
|
101
|
+
- `ctx.tenant_id` — the tenant the call is for. Key any per-tenant
|
|
102
|
+
state by it.
|
|
103
|
+
- `ctx.run_id` — the run (an agent turn or a flow step) the call belongs to.
|
|
104
|
+
- `ctx.request_id` — this call, e.g. the model's tool-call id; useful
|
|
105
|
+
for logs and idempotency keys.
|
|
106
|
+
- `ctx.cancellation` — fires when the call's deadline passes or the
|
|
107
|
+
caller disconnects. An `async def` handler is also cancelled at its
|
|
108
|
+
next `await`. A `def` handler keeps running in its thread: check
|
|
109
|
+
`ctx.cancellation.cancelled`, call `ctx.cancellation.raise_if_cancelled()`,
|
|
110
|
+
or wait with `ctx.cancellation.wait(timeout)` between slow steps.
|
|
111
|
+
- `ctx.secrets` — the secrets the tool declares in `needs_spec`,
|
|
112
|
+
resolved for the call's tenant (below).
|
|
113
|
+
- `ctx.env`, `ctx.config` — **reserved, empty today**.
|
|
114
|
+
|
|
115
|
+
## Configuration and secrets
|
|
116
|
+
|
|
117
|
+
A secret that belongs to the tenant — an API key a customer gives you —
|
|
118
|
+
is declared, and read from `ctx.secrets`:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
@tool(
|
|
122
|
+
id="acme.verify-citation",
|
|
123
|
+
needs_spec={"secrets": {"CITATOR_KEY": {"type": "string", "minLength": 20}}},
|
|
124
|
+
)
|
|
125
|
+
def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
|
|
126
|
+
"""…"""
|
|
127
|
+
key = ctx.secrets["CITATOR_KEY"]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The runtime resolves every declared secret on every call — for the
|
|
131
|
+
call's tenant, in its env (`KINDGI_ENV`; in `kindgi dev`, `local`: the
|
|
132
|
+
pack's `.env` and `.env.local`) — checks it against its schema, and
|
|
133
|
+
fails the call, naming the secret, when it is missing or doesn't match.
|
|
134
|
+
Every declared secret is required. In a test, pass them:
|
|
135
|
+
`ToolContext.for_test(secrets={"CITATOR_KEY": "…"})`.
|
|
136
|
+
|
|
137
|
+
Everything else comes from the process environment: `os.environ["CITATOR_URL"]`.
|
|
138
|
+
The pack service runs with the pack's environment — in `kindgi dev`
|
|
139
|
+
that is the pack's `.env` and `.env.local` (or `[tool.kindgi.dev]
|
|
140
|
+
envFiles`), restarted when they change; nothing else from your shell
|
|
141
|
+
reaches it except `PATH`, `HOME` and `TMPDIR`. Put a secret there by
|
|
142
|
+
hand or with `kindgi secrets set NAME --env=local --scope=tenant` (a
|
|
143
|
+
no-echo prompt), and keep the env files out of git. `KINDGI_*` names
|
|
144
|
+
are Kindgi's own settings and never reach pack code.
|
|
145
|
+
|
|
146
|
+
## Errors and output
|
|
147
|
+
|
|
148
|
+
- Raise an exception for a failure: the call fails with
|
|
149
|
+
`handler-throw` and the exception's message. In an agent turn the
|
|
150
|
+
failure goes to the model only when the agent's `tool_errors` policy
|
|
151
|
+
includes `tool-error` — retrying must be safe for that tool.
|
|
152
|
+
- `print()` and `logging` go to the pack service's stdout/stderr
|
|
153
|
+
(`kindgi dev` shows them as `[pack] …`), never into a result.
|
|
154
|
+
|
|
155
|
+
## Other declarations
|
|
156
|
+
|
|
157
|
+
**`mutating=False`** declares a tool read-only: it changes nothing
|
|
158
|
+
outside itself (a lookup, a search, a calculation). A read-only tool
|
|
159
|
+
runs in a dry run (`kindgi runs start --dry-run`). Leave it out — or
|
|
160
|
+
`mutating=True` — for anything that writes, sends or deletes: such a
|
|
161
|
+
tool stops a dry run.
|
|
162
|
+
|
|
163
|
+
It also sets the tool's approval default. An agent that turns tool
|
|
164
|
+
approval gates on (`conversation_policy={"hitl": {"tools": {...}}}`)
|
|
165
|
+
and has neither an override for the tool nor a `default` doesn't ask
|
|
166
|
+
before a read-only tool, and asks before any other on first use.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
@tool(id="acme.find-citations", mutating=False)
|
|
170
|
+
def find_citations(query: CitationQuery) -> Citations:
|
|
171
|
+
"""Searches the citator. Changes nothing."""
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`@tool(...)` also takes `effects=` (side effects, e.g.
|
|
175
|
+
`[{"kind": "writes", "resource": "db:ledger"}]`; a dry run also stops at
|
|
176
|
+
a tool with a `writes`, `deletes`, `spawns-run`, `emits-event` or
|
|
177
|
+
`external-side-effect` effect), `needs=` / `needs_spec=`, `sandbox=`,
|
|
178
|
+
`limits=` and `network=`. They are recorded in the pack's index for
|
|
179
|
+
policy and review; declare what the tool really does.
|
|
180
|
+
|
|
181
|
+
## HTTP tools — one request, no code
|
|
182
|
+
|
|
183
|
+
A tool that is a single HTTP request needs no handler. `http_tool(...)`
|
|
184
|
+
declares the request; the Kindgi runtime makes it (TypeScript's
|
|
185
|
+
`defineTool({ spec: { kind: 'http' } })`):
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
# tools/citator.py
|
|
189
|
+
from kindgi import http_tool
|
|
190
|
+
|
|
191
|
+
lookup_case = http_tool(
|
|
192
|
+
id="acme.lookup-case",
|
|
193
|
+
description="Looks a case up in the citator by court and number.",
|
|
194
|
+
input=CaseRef, # pydantic models, as for @tool
|
|
195
|
+
output=CaseRecord,
|
|
196
|
+
method="GET",
|
|
197
|
+
url_template="https://citator.example.com/{court}/{case_number}",
|
|
198
|
+
headers={"Accept": "application/json"},
|
|
199
|
+
authorization={"kind": "bearer", "secretRef": {"envName": "local", "name": "CITATOR_KEY"}},
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- `{name}` placeholders in `url_template` are filled from the input's
|
|
204
|
+
fields, URL-encoded; each must be a field of the input model, or the
|
|
205
|
+
indexer reports it.
|
|
206
|
+
- `authorization`: `{"kind": "bearer", "secretRef": …}` or
|
|
207
|
+
`{"kind": "header", "headerName": "X-Api-Key", "secretRef": …}`. The
|
|
208
|
+
runtime resolves the secret on every call — `envName` `local` is the
|
|
209
|
+
pack's `.env` under `kindgi dev` — and fails the call, naming it, when
|
|
210
|
+
it's missing.
|
|
211
|
+
- `request_body`: `{"kind": "json-input"}` (the input's fields the URL
|
|
212
|
+
didn't use, as JSON — the default for POST, PUT and PATCH),
|
|
213
|
+
`{"kind": "input-passthrough"}` (the whole input), or
|
|
214
|
+
`{"kind": "text", "template": "…{field}…"}` (sent as `text/plain`).
|
|
215
|
+
- Also `timeout_ms=` (default 30000), `parse_json=` (default `True`),
|
|
216
|
+
`success_status=(200, 299)`, `effects=`, `version=`, and
|
|
217
|
+
`mutating=False` for a request that changes nothing (a GET, usually).
|
|
218
|
+
|
|
219
|
+
The spec is checked where it's declared, against the same schema as
|
|
220
|
+
TypeScript's. Calling the tool in Python raises: it runs in Kindgi, so
|
|
221
|
+
test it through `kindgi dev` (`kindgi runs start --flow=…`). Anything
|
|
222
|
+
more than one request — paging, retries, shaping the answer — is a
|
|
223
|
+
`@tool` handler with `httpx`.
|
|
224
|
+
|
|
225
|
+
## Testing
|
|
226
|
+
|
|
227
|
+
A `Tool` is still callable — test the function directly:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
# tests/test_citations.py — the template's pytest config puts the pack root on sys.path
|
|
231
|
+
from kindgi import ToolContext
|
|
232
|
+
from tools.citations import Citation, verify_citation
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_unknown_citation(monkeypatch):
|
|
236
|
+
monkeypatch.setenv("CITATOR_URL", "http://citator.test")
|
|
237
|
+
out = verify_citation(Citation(citation="1 U.S. 1", jurisdiction="US"), ToolContext.for_test())
|
|
238
|
+
assert out.found is False
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`ToolContext.for_test(tenant_id=…, run_id=…)` builds a context.
|
|
242
|
+
`uv run pytest` runs the pack's tests (`test_*.py` files are never
|
|
243
|
+
indexed). `uv run python -m kindgi.pack index --pack-dir .` shows the
|
|
244
|
+
schemas Kindgi derives.
|
|
245
|
+
|
|
246
|
+
## Wiring the tool onto an agent
|
|
247
|
+
|
|
248
|
+
Pass the `Tool` object — it pins that tool's version:
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from ..tools.citations import verify_citation
|
|
252
|
+
|
|
253
|
+
brief_writer = Agent(..., tools=[verify_citation])
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
or a ref with a semver **range**, `{"id": "acme.verify-citation",
|
|
257
|
+
"version": "^0.1.0"}`: the highest active version matching it is picked
|
|
258
|
+
at turn start. A bare string is not a tool ref. In a flow, a node's
|
|
259
|
+
`ref` may be the `Tool` object too.
|
|
260
|
+
|
|
261
|
+
## Iterating
|
|
262
|
+
|
|
263
|
+
Save the file; `kindgi dev` rebuilds and the next call runs the new
|
|
264
|
+
code (a syntax error is reported `file:line:col` and the previous code
|
|
265
|
+
keeps serving). Bump `version` when callers' contract changes — a
|
|
266
|
+
removed field, a narrower type — not on every save.
|
|
267
|
+
|
|
268
|
+
## Common mistakes
|
|
269
|
+
|
|
270
|
+
1. **Copying the sample tool's shape without asking what the tool should do.**
|
|
271
|
+
2. **Reading `ctx.env` / `ctx.config`, or an undeclared `ctx.secrets` name.**
|
|
272
|
+
The first two are empty, and `ctx.secrets` holds only what `needs_spec`
|
|
273
|
+
declares; use `os.environ` for the rest.
|
|
274
|
+
3. **A non-object input** (`def f(n: int)`): the input must be a model,
|
|
275
|
+
TypedDict, dataclass or object schema.
|
|
276
|
+
4. **No docstring and no `description=`**, or an unannotated input or
|
|
277
|
+
return: `DefinitionError`.
|
|
278
|
+
5. **Snake_case on the wire.** Without an alias, the field name *is* the
|
|
279
|
+
wire name; add `alias="camelCase"` (and build models with the alias).
|
|
280
|
+
6. **Defining the tool inside a function, or a helper module without a
|
|
281
|
+
leading `_`** under `tools/` — the first is never found; the second is
|
|
282
|
+
indexed and must define a primitive.
|
|
283
|
+
7. **Absolute imports of sibling pack modules inside the pack**
|
|
284
|
+
(`from tools._db import …` in `tools/x.py`): Kindgi imports the pack's
|
|
285
|
+
files as one package, so use relative imports there (`from ._db import
|
|
286
|
+
…`); import your app's own packages by name. (Tests are not pack
|
|
287
|
+
modules — the template's import `tools.x` directly.)
|
|
288
|
+
8. **Blocking inside `async def`.** Use a `def` handler for blocking I/O.
|
|
289
|
+
9. **A read-only tool without `mutating=False`.** A dry run stops at it,
|
|
290
|
+
and an agent's tool approval gate asks before it on first use.
|
|
291
|
+
10. **`mutating=False` on a tool that writes.** A dry run then runs it
|
|
292
|
+
for real.
|
|
293
|
+
|
|
294
|
+
## When the framework itself is the problem
|
|
295
|
+
|
|
296
|
+
If the bug is in Kindgi or the `kindgi` package (a schema derived wrong,
|
|
297
|
+
a misleading error, the pack service misbehaving) and not in the
|
|
298
|
+
tool's code, load `kindgi-framework-feedback` and file it with
|
|
299
|
+
`kindgi feedback write`.
|