@kindgi/api 0.1.4 → 0.1.5
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/dist/agent-binding.d.ts +13 -0
- package/dist/agent-binding.d.ts.map +1 -1
- package/dist/agent-pins.d.ts.map +1 -1
- package/dist/agent-pins.js +18 -2
- package/dist/agent-pins.js.map +1 -1
- package/dist/app.d.ts +110 -17
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +163 -35
- package/dist/app.js.map +1 -1
- package/dist/block-publish.d.ts +56 -0
- package/dist/block-publish.d.ts.map +1 -0
- package/dist/block-publish.js +132 -0
- package/dist/block-publish.js.map +1 -0
- package/dist/caller.d.ts +24 -0
- package/dist/caller.d.ts.map +1 -0
- package/dist/caller.js +47 -0
- package/dist/caller.js.map +1 -0
- package/dist/capability-binding.d.ts +11 -0
- package/dist/capability-binding.d.ts.map +1 -1
- package/dist/cost-binding.d.ts +19 -0
- package/dist/cost-binding.d.ts.map +1 -1
- package/dist/cost-binding.js.map +1 -1
- package/dist/derive-agent-version.d.ts +7 -0
- package/dist/derive-agent-version.d.ts.map +1 -1
- package/dist/derive-agent-version.js +4 -0
- package/dist/derive-agent-version.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +75 -7
- package/dist/errors.js.map +1 -1
- package/dist/eval-case-binding.d.ts +16 -4
- package/dist/eval-case-binding.d.ts.map +1 -1
- package/dist/eval-run-binding.d.ts +31 -0
- package/dist/eval-run-binding.d.ts.map +1 -1
- package/dist/eval-run-dispatcher.d.ts +7 -0
- package/dist/eval-run-dispatcher.d.ts.map +1 -1
- package/dist/eval-run-dispatcher.js.map +1 -1
- package/dist/eval-sample.d.ts +11 -0
- package/dist/eval-sample.d.ts.map +1 -0
- package/dist/eval-sample.js +34 -0
- package/dist/eval-sample.js.map +1 -0
- package/dist/eval-suite-binding.d.ts +13 -0
- package/dist/eval-suite-binding.d.ts.map +1 -1
- package/dist/eval-suite-binding.js.map +1 -1
- package/dist/flow-binding.d.ts +18 -0
- package/dist/flow-binding.d.ts.map +1 -1
- package/dist/flow-pins.d.ts.map +1 -1
- package/dist/flow-pins.js +18 -2
- package/dist/flow-pins.js.map +1 -1
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +25 -0
- package/dist/gate.js.map +1 -1
- package/dist/handler-binding.d.ts +32 -0
- package/dist/handler-binding.d.ts.map +1 -1
- package/dist/hitl-binding.d.ts +23 -0
- package/dist/hitl-binding.d.ts.map +1 -1
- package/dist/identity-directory-binding.d.ts +82 -4
- package/dist/identity-directory-binding.d.ts.map +1 -1
- package/dist/identity-provider-binding.d.ts +197 -17
- package/dist/identity-provider-binding.d.ts.map +1 -1
- package/dist/improvement-pass-binding.d.ts +196 -0
- package/dist/improvement-pass-binding.d.ts.map +1 -0
- package/dist/improvement-pass-binding.js +9 -0
- package/dist/improvement-pass-binding.js.map +1 -0
- package/dist/index.d.ts +35 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/judged-dispatcher.d.ts +25 -4
- package/dist/judged-dispatcher.d.ts.map +1 -1
- package/dist/judged-dispatcher.js +43 -6
- package/dist/judged-dispatcher.js.map +1 -1
- package/dist/judgment-binding.d.ts +25 -1
- package/dist/judgment-binding.d.ts.map +1 -1
- package/dist/mcp-endpoint-binding.d.ts +7 -0
- package/dist/mcp-endpoint-binding.d.ts.map +1 -1
- package/dist/memory-binding.d.ts +124 -17
- package/dist/memory-binding.d.ts.map +1 -1
- package/dist/memory-erasure-binding.d.ts +145 -0
- package/dist/memory-erasure-binding.d.ts.map +1 -0
- package/dist/memory-erasure-binding.js +4 -0
- package/dist/memory-erasure-binding.js.map +1 -0
- package/dist/middleware/auth.d.ts +66 -13
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +150 -50
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/authorize.d.ts +9 -0
- package/dist/middleware/authorize.d.ts.map +1 -1
- package/dist/middleware/authorize.js +122 -4
- package/dist/middleware/authorize.js.map +1 -1
- package/dist/middleware/error-mapper.d.ts +5 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -1
- package/dist/middleware/error-mapper.js +14 -1
- package/dist/middleware/error-mapper.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +70 -5
- package/dist/middleware/idempotency.d.ts.map +1 -1
- package/dist/middleware/idempotency.js +174 -41
- package/dist/middleware/idempotency.js.map +1 -1
- package/dist/middleware/key-project.d.ts +17 -0
- package/dist/middleware/key-project.d.ts.map +1 -0
- package/dist/middleware/key-project.js +75 -0
- package/dist/middleware/key-project.js.map +1 -0
- package/dist/middleware/principal.d.ts.map +1 -1
- package/dist/middleware/principal.js +9 -5
- package/dist/middleware/principal.js.map +1 -1
- package/dist/middleware/project-ref.d.ts.map +1 -1
- package/dist/middleware/project-ref.js +3 -0
- package/dist/middleware/project-ref.js.map +1 -1
- package/dist/openapi/generate.d.ts.map +1 -1
- package/dist/openapi/generate.js +5 -2
- package/dist/openapi/generate.js.map +1 -1
- package/dist/openapi/operations.d.ts.map +1 -1
- package/dist/openapi/operations.js +919 -140
- package/dist/openapi/operations.js.map +1 -1
- package/dist/openapi/schemas.d.ts +90 -13
- package/dist/openapi/schemas.d.ts.map +1 -1
- package/dist/openapi/schemas.js +2081 -359
- package/dist/openapi/schemas.js.map +1 -1
- package/dist/person-grants-binding.d.ts +77 -0
- package/dist/person-grants-binding.d.ts.map +1 -0
- package/dist/person-grants-binding.js +4 -0
- package/dist/person-grants-binding.js.map +1 -0
- package/dist/proposal-service.d.ts +121 -0
- package/dist/proposal-service.d.ts.map +1 -0
- package/dist/proposal-service.js +447 -0
- package/dist/proposal-service.js.map +1 -0
- package/dist/proposal-status.d.ts +60 -0
- package/dist/proposal-status.d.ts.map +1 -0
- package/dist/proposal-status.js +109 -0
- package/dist/proposal-status.js.map +1 -0
- package/dist/provider-binding.d.ts +10 -0
- package/dist/provider-binding.d.ts.map +1 -1
- package/dist/publish-refused.d.ts +28 -3
- package/dist/publish-refused.d.ts.map +1 -1
- package/dist/publish-refused.js +24 -3
- package/dist/publish-refused.js.map +1 -1
- package/dist/routes/adapters.d.ts +2 -1
- package/dist/routes/adapters.d.ts.map +1 -1
- package/dist/routes/adapters.js +3 -1
- package/dist/routes/adapters.js.map +1 -1
- package/dist/routes/agent-releases.d.ts +55 -3
- package/dist/routes/agent-releases.d.ts.map +1 -1
- package/dist/routes/agent-releases.js +85 -55
- package/dist/routes/agent-releases.js.map +1 -1
- package/dist/routes/agents.d.ts +12 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +100 -2
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/approvals.d.ts +15 -3
- package/dist/routes/approvals.d.ts.map +1 -1
- package/dist/routes/approvals.js +133 -122
- package/dist/routes/approvals.js.map +1 -1
- package/dist/routes/artifacts.d.ts +25 -3
- package/dist/routes/artifacts.d.ts.map +1 -1
- package/dist/routes/artifacts.js +116 -7
- package/dist/routes/artifacts.js.map +1 -1
- package/dist/routes/auth.d.ts +25 -1
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +655 -281
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/blocks.d.ts.map +1 -1
- package/dist/routes/blocks.js +2 -42
- package/dist/routes/blocks.js.map +1 -1
- package/dist/routes/capabilities.d.ts +2 -1
- package/dist/routes/capabilities.d.ts.map +1 -1
- package/dist/routes/capabilities.js +6 -1
- package/dist/routes/capabilities.js.map +1 -1
- package/dist/routes/compliance.d.ts +9 -10
- package/dist/routes/compliance.d.ts.map +1 -1
- package/dist/routes/compliance.js +42 -61
- package/dist/routes/compliance.js.map +1 -1
- package/dist/routes/conversations.d.ts +8 -1
- package/dist/routes/conversations.d.ts.map +1 -1
- package/dist/routes/conversations.js +87 -8
- package/dist/routes/conversations.js.map +1 -1
- package/dist/routes/cost.d.ts +12 -1
- package/dist/routes/cost.d.ts.map +1 -1
- package/dist/routes/cost.js +74 -3
- package/dist/routes/cost.js.map +1 -1
- package/dist/routes/denied.d.ts +11 -0
- package/dist/routes/denied.d.ts.map +1 -0
- package/dist/routes/denied.js +17 -0
- package/dist/routes/denied.js.map +1 -0
- package/dist/routes/deployments.d.ts +10 -1
- package/dist/routes/deployments.d.ts.map +1 -1
- package/dist/routes/deployments.js +171 -13
- package/dist/routes/deployments.js.map +1 -1
- package/dist/routes/eval-comparison.d.ts.map +1 -1
- package/dist/routes/eval-comparison.js +69 -1
- package/dist/routes/eval-comparison.js.map +1 -1
- package/dist/routes/eval-overrides.d.ts +18 -0
- package/dist/routes/eval-overrides.d.ts.map +1 -0
- package/dist/routes/eval-overrides.js +81 -0
- package/dist/routes/eval-overrides.js.map +1 -0
- package/dist/routes/eval-runs.d.ts +10 -1
- package/dist/routes/eval-runs.d.ts.map +1 -1
- package/dist/routes/eval-runs.js +66 -7
- package/dist/routes/eval-runs.js.map +1 -1
- package/dist/routes/eval-suites.d.ts.map +1 -1
- package/dist/routes/eval-suites.js +28 -2
- package/dist/routes/eval-suites.js.map +1 -1
- package/dist/routes/event-triggers.d.ts +5 -1
- package/dist/routes/event-triggers.d.ts.map +1 -1
- package/dist/routes/event-triggers.js +26 -3
- package/dist/routes/event-triggers.js.map +1 -1
- package/dist/routes/export-signing-keys.d.ts +12 -0
- package/dist/routes/export-signing-keys.d.ts.map +1 -0
- package/dist/routes/export-signing-keys.js +24 -0
- package/dist/routes/export-signing-keys.js.map +1 -0
- package/dist/routes/flows.d.ts.map +1 -1
- package/dist/routes/flows.js +9 -1
- package/dist/routes/flows.js.map +1 -1
- package/dist/routes/gate-policies.d.ts +4 -1
- package/dist/routes/gate-policies.d.ts.map +1 -1
- package/dist/routes/gate-policies.js +29 -5
- package/dist/routes/gate-policies.js.map +1 -1
- package/dist/routes/guardrails.d.ts +16 -14
- package/dist/routes/guardrails.d.ts.map +1 -1
- package/dist/routes/guardrails.js +39 -3
- package/dist/routes/guardrails.js.map +1 -1
- package/dist/routes/identity.d.ts +20 -4
- package/dist/routes/identity.d.ts.map +1 -1
- package/dist/routes/identity.js +246 -6
- package/dist/routes/identity.js.map +1 -1
- package/dist/routes/improvement-passes.d.ts +52 -0
- package/dist/routes/improvement-passes.d.ts.map +1 -0
- package/dist/routes/improvement-passes.js +449 -0
- package/dist/routes/improvement-passes.js.map +1 -0
- package/dist/routes/judged-suites.d.ts +50 -0
- package/dist/routes/judged-suites.d.ts.map +1 -1
- package/dist/routes/judged-suites.js +66 -27
- package/dist/routes/judged-suites.js.map +1 -1
- package/dist/routes/judgment-context.d.ts +18 -2
- package/dist/routes/judgment-context.d.ts.map +1 -1
- package/dist/routes/judgment-context.js +63 -5
- package/dist/routes/judgment-context.js.map +1 -1
- package/dist/routes/judgment-flow-context.d.ts.map +1 -1
- package/dist/routes/judgment-flow-context.js +14 -2
- package/dist/routes/judgment-flow-context.js.map +1 -1
- package/dist/routes/judgments.d.ts.map +1 -1
- package/dist/routes/judgments.js +8 -1
- package/dist/routes/judgments.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +26 -1
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/memory-access.d.ts +43 -0
- package/dist/routes/memory-access.d.ts.map +1 -0
- package/dist/routes/memory-access.js +114 -0
- package/dist/routes/memory-access.js.map +1 -0
- package/dist/routes/memory-erasures.d.ts +25 -0
- package/dist/routes/memory-erasures.d.ts.map +1 -0
- package/dist/routes/memory-erasures.js +214 -0
- package/dist/routes/memory-erasures.js.map +1 -0
- package/dist/routes/memory-parse.d.ts +38 -0
- package/dist/routes/memory-parse.d.ts.map +1 -0
- package/dist/routes/memory-parse.js +199 -0
- package/dist/routes/memory-parse.js.map +1 -0
- package/dist/routes/memory.d.ts +9 -4
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/memory.js +226 -234
- package/dist/routes/memory.js.map +1 -1
- package/dist/routes/observations.d.ts +4 -1
- package/dist/routes/observations.d.ts.map +1 -1
- package/dist/routes/observations.js +8 -2
- package/dist/routes/observations.js.map +1 -1
- package/dist/routes/pagination.d.ts +7 -0
- package/dist/routes/pagination.d.ts.map +1 -1
- package/dist/routes/pagination.js +10 -0
- package/dist/routes/pagination.js.map +1 -1
- package/dist/routes/policies.d.ts +2 -1
- package/dist/routes/policies.d.ts.map +1 -1
- package/dist/routes/policies.js +3 -1
- package/dist/routes/policies.js.map +1 -1
- package/dist/routes/project-mismatch.d.ts +22 -0
- package/dist/routes/project-mismatch.d.ts.map +1 -0
- package/dist/routes/project-mismatch.js +34 -0
- package/dist/routes/project-mismatch.js.map +1 -0
- package/dist/routes/projects.d.ts +15 -4
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +100 -9
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/proposals.d.ts +25 -17
- package/dist/routes/proposals.d.ts.map +1 -1
- package/dist/routes/proposals.js +340 -507
- package/dist/routes/proposals.js.map +1 -1
- package/dist/routes/provenance.d.ts +17 -3
- package/dist/routes/provenance.d.ts.map +1 -1
- package/dist/routes/provenance.js +79 -103
- package/dist/routes/provenance.js.map +1 -1
- package/dist/routes/providers.d.ts +17 -1
- package/dist/routes/providers.d.ts.map +1 -1
- package/dist/routes/providers.js +110 -3
- package/dist/routes/providers.js.map +1 -1
- package/dist/routes/public-run-tokens.d.ts.map +1 -1
- package/dist/routes/public-run-tokens.js +3 -0
- package/dist/routes/public-run-tokens.js.map +1 -1
- package/dist/routes/readable-projects.d.ts +26 -0
- package/dist/routes/readable-projects.d.ts.map +1 -0
- package/dist/routes/readable-projects.js +39 -0
- package/dist/routes/readable-projects.js.map +1 -0
- package/dist/routes/runs.d.ts +10 -0
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/runs.js +92 -42
- package/dist/routes/runs.js.map +1 -1
- package/dist/routes/schedules.d.ts +21 -13
- package/dist/routes/schedules.d.ts.map +1 -1
- package/dist/routes/schedules.js +416 -55
- package/dist/routes/schedules.js.map +1 -1
- package/dist/routes/segments.d.ts +2 -0
- package/dist/routes/segments.d.ts.map +1 -1
- package/dist/routes/segments.js +5 -0
- package/dist/routes/segments.js.map +1 -1
- package/dist/routes/service-accounts.d.ts +17 -0
- package/dist/routes/service-accounts.d.ts.map +1 -0
- package/dist/routes/service-accounts.js +212 -0
- package/dist/routes/service-accounts.js.map +1 -0
- package/dist/routes/sign-in-options.d.ts +50 -0
- package/dist/routes/sign-in-options.d.ts.map +1 -0
- package/dist/routes/sign-in-options.js +98 -0
- package/dist/routes/sign-in-options.js.map +1 -0
- package/dist/routes/signing-keys.d.ts +2 -1
- package/dist/routes/signing-keys.d.ts.map +1 -1
- package/dist/routes/signing-keys.js +3 -1
- package/dist/routes/signing-keys.js.map +1 -1
- package/dist/routes/tenant-access.d.ts +13 -0
- package/dist/routes/tenant-access.d.ts.map +1 -0
- package/dist/routes/tenant-access.js +26 -0
- package/dist/routes/tenant-access.js.map +1 -0
- package/dist/routes/tenant.d.ts.map +1 -1
- package/dist/routes/tenant.js +4 -0
- package/dist/routes/tenant.js.map +1 -1
- package/dist/routes/token-sign-in.d.ts +36 -0
- package/dist/routes/token-sign-in.d.ts.map +1 -0
- package/dist/routes/token-sign-in.js +101 -0
- package/dist/routes/token-sign-in.js.map +1 -0
- package/dist/routes/tokens.d.ts +15 -5
- package/dist/routes/tokens.d.ts.map +1 -1
- package/dist/routes/tokens.js +162 -43
- package/dist/routes/tokens.js.map +1 -1
- package/dist/routes/tools.d.ts.map +1 -1
- package/dist/routes/tools.js +9 -1
- package/dist/routes/tools.js.map +1 -1
- package/dist/routes/trigger-access.d.ts +29 -0
- package/dist/routes/trigger-access.d.ts.map +1 -0
- package/dist/routes/trigger-access.js +33 -0
- package/dist/routes/trigger-access.js.map +1 -0
- package/dist/routes/webhook-endpoints.d.ts +2 -1
- package/dist/routes/webhook-endpoints.d.ts.map +1 -1
- package/dist/routes/webhook-endpoints.js +11 -3
- package/dist/routes/webhook-endpoints.js.map +1 -1
- package/dist/routes/webhooks.d.ts +5 -1
- package/dist/routes/webhooks.d.ts.map +1 -1
- package/dist/routes/webhooks.js +25 -2
- package/dist/routes/webhooks.js.map +1 -1
- package/dist/run-failure.d.ts +21 -0
- package/dist/run-failure.d.ts.map +1 -0
- package/dist/run-failure.js +29 -0
- package/dist/run-failure.js.map +1 -0
- package/dist/service-account-binding.d.ts +108 -0
- package/dist/service-account-binding.d.ts.map +1 -0
- package/dist/service-account-binding.js +4 -0
- package/dist/service-account-binding.js.map +1 -0
- package/dist/session-store-binding.d.ts +61 -13
- package/dist/session-store-binding.d.ts.map +1 -1
- package/dist/signed-export.d.ts +89 -0
- package/dist/signed-export.d.ts.map +1 -0
- package/dist/signed-export.js +149 -0
- package/dist/signed-export.js.map +1 -0
- package/dist/supervisor-binding.d.ts +186 -413
- package/dist/supervisor-binding.d.ts.map +1 -1
- package/dist/testing/app-bindings.d.ts +33 -0
- package/dist/testing/app-bindings.d.ts.map +1 -0
- package/dist/testing/app-bindings.js +112 -0
- package/dist/testing/app-bindings.js.map +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +13 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/stub-binding.d.ts +34 -0
- package/dist/testing/stub-binding.d.ts.map +1 -0
- package/dist/testing/stub-binding.js +42 -0
- package/dist/testing/stub-binding.js.map +1 -0
- package/dist/testing/trigger-registry.d.ts +21 -0
- package/dist/testing/trigger-registry.d.ts.map +1 -0
- package/dist/testing/trigger-registry.js +206 -0
- package/dist/testing/trigger-registry.js.map +1 -0
- package/dist/token-admin.d.ts +46 -8
- package/dist/token-admin.d.ts.map +1 -1
- package/dist/token-admin.js.map +1 -1
- package/dist/tool-binding.d.ts +13 -0
- package/dist/tool-binding.d.ts.map +1 -1
- package/dist/trigger-binding.d.ts +2 -2
- package/dist/trigger-binding.d.ts.map +1 -1
- package/dist/trigger-binding.js +1 -1
- package/dist/trigger-binding.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.d.ts +19 -3
- package/dist/webhook-endpoint-binding.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.js +1 -1
- package/dist/webhook-endpoint-binding.js.map +1 -1
- package/openapi.json +15387 -8789
- package/package.json +26 -22
- package/src/agent-binding.ts +14 -0
- package/src/agent-pins.ts +18 -2
- package/src/app.ts +366 -80
- package/src/block-publish.ts +181 -0
- package/src/caller.ts +62 -0
- package/src/capability-binding.ts +12 -0
- package/src/cost-binding.ts +19 -0
- package/src/derive-agent-version.ts +9 -1
- package/src/errors.ts +75 -7
- package/src/eval-case-binding.ts +17 -1
- package/src/eval-run-binding.ts +31 -0
- package/src/eval-run-dispatcher.ts +7 -0
- package/src/eval-sample.ts +42 -0
- package/src/eval-suite-binding.ts +14 -0
- package/src/flow-binding.ts +19 -0
- package/src/flow-pins.ts +18 -2
- package/src/gate.ts +26 -0
- package/src/handler-binding.ts +36 -1
- package/src/hitl-binding.ts +24 -0
- package/src/identity-directory-binding.ts +85 -4
- package/src/identity-provider-binding.ts +216 -21
- package/src/improvement-pass-binding.ts +193 -0
- package/src/index.ts +153 -31
- package/src/judged-dispatcher.ts +78 -11
- package/src/judgment-binding.ts +25 -1
- package/src/mcp-endpoint-binding.ts +7 -0
- package/src/memory-binding.ts +121 -17
- package/src/memory-erasure-binding.ts +156 -0
- package/src/middleware/auth.ts +228 -62
- package/src/middleware/authorize.ts +155 -3
- package/src/middleware/error-mapper.ts +15 -1
- package/src/middleware/idempotency.ts +230 -43
- package/src/middleware/key-project.ts +86 -0
- package/src/middleware/principal.ts +9 -5
- package/src/middleware/project-ref.ts +3 -0
- package/src/openapi/generate.ts +11 -2
- package/src/openapi/operations.ts +1060 -143
- package/src/openapi/schemas.ts +2387 -469
- package/src/person-grants-binding.ts +76 -0
- package/src/proposal-service.ts +640 -0
- package/src/proposal-status.ts +176 -0
- package/src/provider-binding.ts +10 -0
- package/src/publish-refused.ts +56 -9
- package/src/routes/adapters.ts +4 -0
- package/src/routes/agent-releases.ts +121 -69
- package/src/routes/agents.ts +128 -1
- package/src/routes/approvals.ts +164 -154
- package/src/routes/artifacts.ts +181 -11
- package/src/routes/auth.ts +804 -336
- package/src/routes/blocks.ts +2 -53
- package/src/routes/capabilities.ts +10 -1
- package/src/routes/compliance.ts +60 -99
- package/src/routes/conversations.ts +101 -7
- package/src/routes/cost.ts +110 -4
- package/src/routes/denied.ts +28 -0
- package/src/routes/deployments.ts +210 -17
- package/src/routes/eval-comparison.ts +81 -2
- package/src/routes/eval-overrides.ts +108 -0
- package/src/routes/eval-runs.ts +89 -6
- package/src/routes/eval-suites.ts +32 -2
- package/src/routes/event-triggers.ts +27 -3
- package/src/routes/export-signing-keys.ts +31 -0
- package/src/routes/flows.ts +12 -1
- package/src/routes/gate-policies.ts +37 -6
- package/src/routes/guardrails.ts +61 -2
- package/src/routes/identity.ts +328 -10
- package/src/routes/improvement-passes.ts +541 -0
- package/src/routes/judged-suites.ts +113 -43
- package/src/routes/judgment-context.ts +76 -5
- package/src/routes/judgment-flow-context.ts +16 -2
- package/src/routes/judgments.ts +17 -3
- package/src/routes/mcp.ts +29 -1
- package/src/routes/memory-access.ts +160 -0
- package/src/routes/memory-erasures.ts +240 -0
- package/src/routes/memory-parse.ts +250 -0
- package/src/routes/memory.ts +244 -286
- package/src/routes/observations.ts +15 -2
- package/src/routes/pagination.ts +12 -0
- package/src/routes/policies.ts +7 -1
- package/src/routes/project-mismatch.ts +56 -0
- package/src/routes/projects.ts +107 -13
- package/src/routes/proposals.ts +370 -611
- package/src/routes/provenance.ts +99 -133
- package/src/routes/providers.ts +142 -3
- package/src/routes/public-run-tokens.ts +3 -0
- package/src/routes/readable-projects.ts +66 -0
- package/src/routes/runs.ts +119 -39
- package/src/routes/schedules.ts +472 -60
- package/src/routes/segments.ts +11 -0
- package/src/routes/service-accounts.ts +262 -0
- package/src/routes/sign-in-options.ts +168 -0
- package/src/routes/signing-keys.ts +7 -1
- package/src/routes/tenant-access.ts +37 -0
- package/src/routes/tenant.ts +6 -0
- package/src/routes/token-sign-in.ts +161 -0
- package/src/routes/tokens.ts +172 -46
- package/src/routes/tools.ts +12 -1
- package/src/routes/trigger-access.ts +72 -0
- package/src/routes/webhook-endpoints.ts +15 -3
- package/src/routes/webhooks.ts +26 -2
- package/src/run-failure.ts +42 -0
- package/src/service-account-binding.ts +113 -0
- package/src/session-store-binding.ts +65 -13
- package/src/signed-export.ts +250 -0
- package/src/supervisor-binding.ts +169 -409
- package/src/testing/app-bindings.ts +142 -0
- package/src/testing/index.ts +21 -0
- package/src/testing/stub-binding.ts +53 -0
- package/src/testing/trigger-registry.ts +259 -0
- package/src/token-admin.ts +40 -8
- package/src/tool-binding.ts +14 -0
- package/src/trigger-binding.ts +8 -1
- package/src/types.ts +16 -0
- package/src/webhook-endpoint-binding.ts +18 -3
package/src/routes/cost.ts
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (C) 2026 Kindgi Inc.
|
|
3
3
|
|
|
4
|
-
import { Hono } from 'hono';
|
|
4
|
+
import { type Context, Hono } from 'hono';
|
|
5
5
|
|
|
6
6
|
import type { Cursor, TenantId, Timestamp } from '@kindgi/types';
|
|
7
7
|
|
|
8
|
+
import { type ResourceRef, denyPayload, ref } from '@kindgi/authz';
|
|
9
|
+
import type { ProjectBinding } from '@kindgi/platform';
|
|
8
10
|
import {
|
|
9
11
|
COST_AGGREGATE_DEFAULT_LIMIT,
|
|
10
12
|
COST_AGGREGATE_MAX_LIMIT,
|
|
11
13
|
COST_GROUP_DIMENSIONS,
|
|
12
14
|
type CostAggregateGroup,
|
|
15
|
+
type CostAggregateInput,
|
|
13
16
|
type CostBinding,
|
|
14
17
|
type CostGroupDimension,
|
|
15
18
|
type CostRecord,
|
|
16
19
|
type CostRecordFilter,
|
|
17
20
|
type CostTokenTotals,
|
|
18
21
|
} from '../cost-binding.js';
|
|
22
|
+
|
|
19
23
|
import { statusFor, toWireError } from '../errors.js';
|
|
24
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
20
25
|
import type { AppEnv } from '../types.js';
|
|
26
|
+
import { deniedBy } from './denied.js';
|
|
21
27
|
import { clampLimit } from './pagination.js';
|
|
22
|
-
import {
|
|
28
|
+
import { projectIdsCallerMay } from './readable-projects.js';
|
|
29
|
+
import { parseScopeParams, scopeResourceRef } from './scope-params.js';
|
|
23
30
|
|
|
24
31
|
/**
|
|
25
32
|
* Cost readback routes — part of the admin control plane. Three
|
|
@@ -38,8 +45,23 @@ import { parseScopeParams } from './scope-params.js';
|
|
|
38
45
|
*
|
|
39
46
|
* Budgets are not part of this surface.
|
|
40
47
|
*/
|
|
41
|
-
export function costRouter(
|
|
48
|
+
export function costRouter(
|
|
49
|
+
binding: CostBinding,
|
|
50
|
+
/**
|
|
51
|
+
* With one: a record needs `read` on its project (the tenant, for one
|
|
52
|
+
* with no project); an aggregate, `read` on the scope it's asked for,
|
|
53
|
+
* and across projects (no scope, or an org) it counts only the projects
|
|
54
|
+
* the caller may read, unless the caller is a tenant admin.
|
|
55
|
+
*/
|
|
56
|
+
authorizer?: Authorizer,
|
|
57
|
+
/** The tenant's projects, to check one by one when the authorizer can't list them. */
|
|
58
|
+
projects?: Pick<ProjectBinding, 'list'>,
|
|
59
|
+
): Hono<AppEnv> {
|
|
42
60
|
const r = new Hono<AppEnv>();
|
|
61
|
+
const recordRef = (tenantId: TenantId, rec: { readonly projectId?: unknown }): ResourceRef =>
|
|
62
|
+
rec.projectId !== undefined && rec.projectId !== null
|
|
63
|
+
? ref('project', rec.projectId as string)
|
|
64
|
+
: ref('tenant', tenantId as unknown as string);
|
|
43
65
|
|
|
44
66
|
const DEFAULT_AGGREGATE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
45
67
|
|
|
@@ -81,8 +103,12 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
|
|
|
81
103
|
...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
|
|
82
104
|
...(include.rawUsage && { includeRawUsage: true }),
|
|
83
105
|
});
|
|
106
|
+
const visible =
|
|
107
|
+
authorizer === undefined
|
|
108
|
+
? page.data
|
|
109
|
+
: await authorizer.filterByCan(c, 'read', page.data, (rec) => recordRef(tenantId, rec));
|
|
84
110
|
return c.json({
|
|
85
|
-
data:
|
|
111
|
+
data: visible.map(serializeRecord),
|
|
86
112
|
hasMore: page.nextCursor !== undefined,
|
|
87
113
|
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
88
114
|
});
|
|
@@ -117,6 +143,8 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
|
|
|
117
143
|
),
|
|
118
144
|
);
|
|
119
145
|
}
|
|
146
|
+
const refused = await deniedBy(authorizer, c, 'read', recordRef(tenantId, record));
|
|
147
|
+
if (refused !== undefined) return refused;
|
|
120
148
|
return c.json(serializeRecord(record));
|
|
121
149
|
});
|
|
122
150
|
|
|
@@ -249,6 +277,24 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
|
|
|
249
277
|
);
|
|
250
278
|
}
|
|
251
279
|
|
|
280
|
+
const refused = await deniedBy(
|
|
281
|
+
authorizer,
|
|
282
|
+
c,
|
|
283
|
+
'read',
|
|
284
|
+
scopeResourceRef(scopeParsed.scope, tenantId),
|
|
285
|
+
);
|
|
286
|
+
if (refused !== undefined) return refused;
|
|
287
|
+
|
|
288
|
+
// Across projects, only what the caller may read counts (`aggregateReach`).
|
|
289
|
+
const reach = await aggregateReach(c, {
|
|
290
|
+
binding,
|
|
291
|
+
tenantId,
|
|
292
|
+
authorizer,
|
|
293
|
+
projects,
|
|
294
|
+
scope: scopeParsed.scope,
|
|
295
|
+
});
|
|
296
|
+
if (reach.kind === 'refused') return reach.response;
|
|
297
|
+
|
|
252
298
|
const result = await binding.aggregate({
|
|
253
299
|
tenantId,
|
|
254
300
|
groupBy,
|
|
@@ -257,6 +303,7 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
|
|
|
257
303
|
...(Object.keys(filter.value).length > 0 && { filter: filter.value }),
|
|
258
304
|
...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
|
|
259
305
|
...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
|
|
306
|
+
...(reach.kind === 'projects' && { readableProjectIds: reach.ids }),
|
|
260
307
|
limit,
|
|
261
308
|
});
|
|
262
309
|
|
|
@@ -285,6 +332,65 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
|
|
|
285
332
|
|
|
286
333
|
// -------- helpers --------
|
|
287
334
|
|
|
335
|
+
/**
|
|
336
|
+
* What an aggregate may count for this caller. Across projects (no scope,
|
|
337
|
+
* the tenant, or an org), `read` on the scope lets a member ask, not see
|
|
338
|
+
* every project's spend: only the projects they may read count, applied in
|
|
339
|
+
* the binding's query (`readableProjectIds`). A tenant admin's, a project
|
|
340
|
+
* scope's (already checked) and one without authorization count everything
|
|
341
|
+
* the scope holds. When the readable projects can't be worked out, or the
|
|
342
|
+
* binding can't apply them, the aggregate is refused rather than
|
|
343
|
+
* over-counted.
|
|
344
|
+
*/
|
|
345
|
+
async function aggregateReach(
|
|
346
|
+
c: Context<AppEnv>,
|
|
347
|
+
args: {
|
|
348
|
+
readonly binding: CostBinding;
|
|
349
|
+
readonly tenantId: TenantId;
|
|
350
|
+
readonly authorizer: Authorizer | undefined;
|
|
351
|
+
readonly projects: Pick<ProjectBinding, 'list'> | undefined;
|
|
352
|
+
readonly scope: CostAggregateInput['scope'] | undefined;
|
|
353
|
+
},
|
|
354
|
+
): Promise<
|
|
355
|
+
| { readonly kind: 'all' }
|
|
356
|
+
| { readonly kind: 'projects'; readonly ids: readonly string[] }
|
|
357
|
+
| { readonly kind: 'refused'; readonly response: Response }
|
|
358
|
+
> {
|
|
359
|
+
const { binding, tenantId, authorizer, projects, scope } = args;
|
|
360
|
+
if (authorizer === undefined || scope?.kind === 'project') return { kind: 'all' };
|
|
361
|
+
if (await authorizer.can(c, 'admin', ref('tenant', tenantId as unknown as string))) {
|
|
362
|
+
return { kind: 'all' };
|
|
363
|
+
}
|
|
364
|
+
const ids = await projectIdsCallerMay(c, authorizer, projects, 'read');
|
|
365
|
+
if (ids !== undefined && binding.aggregatesReadableProjects === true) {
|
|
366
|
+
return { kind: 'projects', ids };
|
|
367
|
+
}
|
|
368
|
+
const deny = denyPayload(
|
|
369
|
+
'read',
|
|
370
|
+
scope?.kind === 'org' ? 'org' : 'tenant',
|
|
371
|
+
scope?.kind === 'org' ? (scope.orgId as unknown as string) : (tenantId as unknown as string),
|
|
372
|
+
ids === undefined
|
|
373
|
+
? "the projects you may read can't be listed here, so an aggregate across projects can't be limited to them; ask per project (scopeKind=project)"
|
|
374
|
+
: "this deployment's cost store can't limit an aggregate to the projects you may read; ask per project (scopeKind=project)",
|
|
375
|
+
);
|
|
376
|
+
c.status(403);
|
|
377
|
+
return {
|
|
378
|
+
kind: 'refused',
|
|
379
|
+
response: c.json(
|
|
380
|
+
toWireError(
|
|
381
|
+
{
|
|
382
|
+
code: deny.code,
|
|
383
|
+
message: `Permission denied: ${deny.reason}`,
|
|
384
|
+
action: deny.action,
|
|
385
|
+
resource: deny.resource,
|
|
386
|
+
reason: deny.reason,
|
|
387
|
+
},
|
|
388
|
+
c.get('requestId'),
|
|
389
|
+
),
|
|
390
|
+
),
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
288
394
|
function parseRecordFilter(
|
|
289
395
|
query: Readonly<Record<string, string | undefined>>,
|
|
290
396
|
opts: { skipTime?: boolean } = {},
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type { Context } from 'hono';
|
|
5
|
+
|
|
6
|
+
import type { Action, ResourceRef } from '@kindgi/authz';
|
|
7
|
+
|
|
8
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
9
|
+
import type { AppEnv } from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* An in-handler check, for a resource known only once the request is
|
|
13
|
+
* read: nothing when the caller may take `action` on `resource` (or there
|
|
14
|
+
* is no authorizer), else the authorizer's own 403, to return as is.
|
|
15
|
+
*/
|
|
16
|
+
export async function deniedBy(
|
|
17
|
+
authorizer: Authorizer | undefined,
|
|
18
|
+
c: Context<AppEnv>,
|
|
19
|
+
action: Action,
|
|
20
|
+
resource: ResourceRef,
|
|
21
|
+
): Promise<Response | undefined> {
|
|
22
|
+
if (authorizer === undefined) return undefined;
|
|
23
|
+
let allowed = false;
|
|
24
|
+
const answer = await authorizer.authorize(action, () => resource)(c, async () => {
|
|
25
|
+
allowed = true;
|
|
26
|
+
});
|
|
27
|
+
return allowed ? undefined : (answer as Response);
|
|
28
|
+
}
|
|
@@ -9,7 +9,12 @@ import type { Agent, AgentId, AgentPins } from '@kindgi/agents';
|
|
|
9
9
|
import { tuplesForCreate } from '@kindgi/authz';
|
|
10
10
|
import { parsePublicKeyPem, verifyEd25519 } from '@kindgi/crypto';
|
|
11
11
|
import type { Flow, FlowPins } from '@kindgi/flow';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
GUARDRAIL_SPEC_KEYS,
|
|
14
|
+
type Guardrail,
|
|
15
|
+
createCheckRegistry,
|
|
16
|
+
validateGuardrailSpec,
|
|
17
|
+
} from '@kindgi/guardrails';
|
|
13
18
|
import type { ProjectBinding, Scope } from '@kindgi/platform';
|
|
14
19
|
import { validateToolManifest } from '@kindgi/tools';
|
|
15
20
|
import type {
|
|
@@ -42,6 +47,7 @@ import { type FlowPinsLive, publishDeployedFlow, resolveFlowPins } from '../flow
|
|
|
42
47
|
import type { GuardrailRegistryBinding } from '../guardrail-binding.js';
|
|
43
48
|
import type { ImageRegistryBinding } from '../image-registry-binding.js';
|
|
44
49
|
import type { LiveVersionBinding } from '../live-version-binding.js';
|
|
50
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
45
51
|
import { PublishRefused } from '../publish-refused.js';
|
|
46
52
|
import { type RegistryReadOnly, refuseReadOnly } from '../registry-read-only.js';
|
|
47
53
|
import type { SecretBinding } from '../secrets-binding.js';
|
|
@@ -51,6 +57,7 @@ import type { AppEnv } from '../types.js';
|
|
|
51
57
|
import { hasCapability, requireEnvName } from './env.js';
|
|
52
58
|
import type { GuardrailWriteHook } from './guardrails.js';
|
|
53
59
|
import { clampLimit } from './pagination.js';
|
|
60
|
+
import { tenantResourceAccess } from './tenant-access.js';
|
|
54
61
|
import type { ToolWriteHook } from './tools.js';
|
|
55
62
|
|
|
56
63
|
/**
|
|
@@ -167,8 +174,12 @@ export interface DeploymentsRouterBindings {
|
|
|
167
174
|
readonly onGuardrailWrite?: GuardrailWriteHook;
|
|
168
175
|
}
|
|
169
176
|
|
|
170
|
-
export function deploymentsRouter(
|
|
177
|
+
export function deploymentsRouter(
|
|
178
|
+
bindings: DeploymentsRouterBindings,
|
|
179
|
+
authorizer?: Authorizer,
|
|
180
|
+
): Hono<AppEnv> {
|
|
171
181
|
const r = new Hono<AppEnv>();
|
|
182
|
+
r.use('*', tenantResourceAccess(authorizer));
|
|
172
183
|
|
|
173
184
|
// ---------- GET / (list, cursor-paginated) ----------
|
|
174
185
|
r.get('/', async (c) => {
|
|
@@ -476,10 +487,11 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
|
|
|
476
487
|
}
|
|
477
488
|
|
|
478
489
|
// ---- Manifest validation ----
|
|
479
|
-
const validation = validatePrimitives(
|
|
480
|
-
|
|
481
|
-
artifactVersion: wire.artifactVersion,
|
|
482
|
-
|
|
490
|
+
const validation = validatePrimitives(
|
|
491
|
+
imageIndex,
|
|
492
|
+
{ imageRef: wire.imageRef, artifactVersion: wire.artifactVersion },
|
|
493
|
+
c.get('log'),
|
|
494
|
+
);
|
|
483
495
|
if (validation.kind === 'err') {
|
|
484
496
|
c.status(statusFor('deployment-validation-failed') as never);
|
|
485
497
|
return c.json(
|
|
@@ -580,7 +592,7 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
|
|
|
580
592
|
await bindings.toolRegistry?.unregister({ tenantId, toolId, version });
|
|
581
593
|
});
|
|
582
594
|
} else if (outcome.kind !== 'already-registered') {
|
|
583
|
-
throw new PublishRefused('tool', `${tool.id}@${tool.version}`, outcome
|
|
595
|
+
throw new PublishRefused('tool', `${tool.id}@${tool.version}`, outcome);
|
|
584
596
|
}
|
|
585
597
|
}
|
|
586
598
|
}
|
|
@@ -604,8 +616,22 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
|
|
|
604
616
|
rolled.push(async () => {
|
|
605
617
|
await bindings.guardrailRegistry?.unregister({ tenantId, guardrailId });
|
|
606
618
|
});
|
|
607
|
-
} else if (outcome.kind
|
|
608
|
-
|
|
619
|
+
} else if (outcome.kind === 'already-registered') {
|
|
620
|
+
const kept = await keepRegisteredGuardrail(
|
|
621
|
+
bindings.guardrailRegistry,
|
|
622
|
+
tenantId,
|
|
623
|
+
projectIdForGuardrail,
|
|
624
|
+
guardrail,
|
|
625
|
+
);
|
|
626
|
+
// Unregistered since the registry answered: registered afresh.
|
|
627
|
+
if (kept === 'registered') {
|
|
628
|
+
const guardrailId = guardrail.id;
|
|
629
|
+
rolled.push(async () => {
|
|
630
|
+
await bindings.guardrailRegistry?.unregister({ tenantId, guardrailId });
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
} else {
|
|
634
|
+
throw new PublishRefused('guardrail', guardrail.id, outcome);
|
|
609
635
|
}
|
|
610
636
|
}
|
|
611
637
|
}
|
|
@@ -645,6 +671,13 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
|
|
|
645
671
|
// A primitive refused with a typed outcome is the caller's to fix:
|
|
646
672
|
// that outcome's own status and code. Anything thrown is a 500.
|
|
647
673
|
if (cause instanceof PublishRefused) {
|
|
674
|
+
if (cause.projectId !== undefined) {
|
|
675
|
+
c.get('log').info(`${cause.message}: deploy refused`, {
|
|
676
|
+
primitive: cause.primitive,
|
|
677
|
+
id: cause.id,
|
|
678
|
+
ownerProjectId: cause.projectId as unknown as string,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
648
681
|
c.status(statusFor(cause.code) as never);
|
|
649
682
|
return c.json(
|
|
650
683
|
toWireError(
|
|
@@ -1215,6 +1248,139 @@ interface DeployedImage {
|
|
|
1215
1248
|
readonly artifactVersion: string;
|
|
1216
1249
|
}
|
|
1217
1250
|
|
|
1251
|
+
/**
|
|
1252
|
+
* A deploy keeps a guardrail id that's already live only when it's the
|
|
1253
|
+
* deploy's own: in the project the deploy registers into, with the same
|
|
1254
|
+
* definition (`sameGuardrailDefinition`, what its author declares). An id live in another project
|
|
1255
|
+
* is refused (`guardrail-project-mismatch`, its project never named): the
|
|
1256
|
+
* pack's agents would otherwise run that project's guardrail. One in this
|
|
1257
|
+
* project with another definition is refused too
|
|
1258
|
+
* (`guardrail-already-registered`): a deploy never changes a guardrail,
|
|
1259
|
+
* and keeping the old one would run what the pack no longer says.
|
|
1260
|
+
*
|
|
1261
|
+
* `get` answers a guardrail without its project, so whether the id is in
|
|
1262
|
+
* this project comes from the project's list. When the row is gone by the
|
|
1263
|
+
* time it's looked at (unregistered meanwhile), the guardrail is
|
|
1264
|
+
* registered again: `'registered'`, for the deploy to roll back.
|
|
1265
|
+
*/
|
|
1266
|
+
async function keepRegisteredGuardrail(
|
|
1267
|
+
registry: GuardrailRegistryBinding,
|
|
1268
|
+
tenantId: TenantId,
|
|
1269
|
+
projectId: ProjectId,
|
|
1270
|
+
guardrail: Guardrail,
|
|
1271
|
+
): Promise<'kept' | 'registered'> {
|
|
1272
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1273
|
+
const existing = await registry.get({ tenantId, guardrailId: guardrail.id });
|
|
1274
|
+
if (existing !== null) {
|
|
1275
|
+
if (!(await guardrailInProject(registry, tenantId, projectId, guardrail.id))) {
|
|
1276
|
+
throw new PublishRefused('guardrail', guardrail.id, {
|
|
1277
|
+
code: 'guardrail-project-mismatch',
|
|
1278
|
+
reason: 'it belongs to another project',
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
if (!sameGuardrailDefinition(existing, guardrail)) {
|
|
1282
|
+
throw new PublishRefused('guardrail', guardrail.id, {
|
|
1283
|
+
code: 'guardrail-already-registered',
|
|
1284
|
+
reason: `it is already registered with a different definition; unregister it (\`kindgi guardrails unregister ${guardrail.id}\`) and deploy again`,
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
return 'kept';
|
|
1288
|
+
}
|
|
1289
|
+
const again = await registry.register({
|
|
1290
|
+
tenantId,
|
|
1291
|
+
projectId,
|
|
1292
|
+
guardrail,
|
|
1293
|
+
enqueueTuples: (guardrailId) =>
|
|
1294
|
+
tuplesForCreate({
|
|
1295
|
+
kind: 'guardrail',
|
|
1296
|
+
id: guardrailId as GuardrailId,
|
|
1297
|
+
tenantId,
|
|
1298
|
+
projectId,
|
|
1299
|
+
}),
|
|
1300
|
+
});
|
|
1301
|
+
if (again.kind === 'ok') return 'registered';
|
|
1302
|
+
if (again.kind !== 'already-registered') {
|
|
1303
|
+
throw new PublishRefused('guardrail', guardrail.id, again);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
throw new Error(`guardrail ${guardrail.id}: registered and unregistered while deploying`);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/** Whether the live guardrail `id` is in `projectId`, by that project's list. */
|
|
1310
|
+
async function guardrailInProject(
|
|
1311
|
+
registry: GuardrailRegistryBinding,
|
|
1312
|
+
tenantId: TenantId,
|
|
1313
|
+
projectId: ProjectId,
|
|
1314
|
+
id: GuardrailId,
|
|
1315
|
+
): Promise<boolean> {
|
|
1316
|
+
let cursor: Cursor | undefined;
|
|
1317
|
+
do {
|
|
1318
|
+
const page = await registry.list({
|
|
1319
|
+
tenantId,
|
|
1320
|
+
limit: 100,
|
|
1321
|
+
nameFilter: id,
|
|
1322
|
+
scope: { kind: 'project', tenantId, projectId },
|
|
1323
|
+
...(cursor !== undefined && { cursor }),
|
|
1324
|
+
});
|
|
1325
|
+
if (page.data.some((g) => g.id === id)) return true;
|
|
1326
|
+
cursor = page.nextCursor;
|
|
1327
|
+
} while (cursor !== undefined);
|
|
1328
|
+
return false;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* The fields of a guardrail its author declares, which a deploy compares.
|
|
1333
|
+
* Never compared: what a deploy or a release derives. That includes
|
|
1334
|
+
* `configSchema`, which the deploy route dropped before 0.1.5, so a row a
|
|
1335
|
+
* 0.1.4 deploy stored has none; the image and artifact version a code
|
|
1336
|
+
* pointer names, which every new image changes; and any field a later
|
|
1337
|
+
* release adds. So an unchanged pack redeploys across releases.
|
|
1338
|
+
*/
|
|
1339
|
+
const DECLARED_GUARDRAIL_FIELDS = [
|
|
1340
|
+
'name',
|
|
1341
|
+
'description',
|
|
1342
|
+
'kind',
|
|
1343
|
+
'check',
|
|
1344
|
+
'config',
|
|
1345
|
+
'action',
|
|
1346
|
+
'severity',
|
|
1347
|
+
'scope',
|
|
1348
|
+
'budget',
|
|
1349
|
+
'judgeCapabilities',
|
|
1350
|
+
'sandbox',
|
|
1351
|
+
'limits',
|
|
1352
|
+
'network',
|
|
1353
|
+
'needsSpec',
|
|
1354
|
+
] as const;
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* The same guardrail definition: equal in what its author declares
|
|
1358
|
+
* (`DECLARED_GUARDRAIL_FIELDS`, and of where its code lives only the
|
|
1359
|
+
* module path), as JSON with keys in any order (a registry may store it as
|
|
1360
|
+
* JSONB) and an absent field the same as an `undefined` one.
|
|
1361
|
+
*/
|
|
1362
|
+
export function sameGuardrailDefinition(a: Guardrail, b: Guardrail): boolean {
|
|
1363
|
+
return canonicalJson(definitionOf(a)) === canonicalJson(definitionOf(b));
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
function definitionOf(guardrail: Guardrail): Record<string, unknown> {
|
|
1367
|
+
const declared: Record<string, unknown> = {};
|
|
1368
|
+
for (const field of DECLARED_GUARDRAIL_FIELDS) {
|
|
1369
|
+
declared[field] = (guardrail as unknown as Record<string, unknown>)[field];
|
|
1370
|
+
}
|
|
1371
|
+
declared.modulePath = guardrail.codeArtifactRef?.modulePath;
|
|
1372
|
+
return declared;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
/** JSON with every object's keys sorted, and absent and `undefined` alike. */
|
|
1376
|
+
function canonicalJson(value: unknown): string {
|
|
1377
|
+
return JSON.stringify(JSON.parse(JSON.stringify(value) ?? 'null'), (_key, v: unknown) =>
|
|
1378
|
+
v !== null && typeof v === 'object' && !Array.isArray(v)
|
|
1379
|
+
? Object.fromEntries(Object.entries(v).sort(([x], [y]) => (x < y ? -1 : x > y ? 1 : 0)))
|
|
1380
|
+
: v,
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1218
1384
|
/** The pointer to a tool's or guardrail's module inside the deployed image. */
|
|
1219
1385
|
function ociCodeArtifactRef(image: DeployedImage, modulePath: unknown) {
|
|
1220
1386
|
return typeof modulePath === 'string' && modulePath.length > 0
|
|
@@ -1236,9 +1402,13 @@ function ociCodeArtifactRef(image: DeployedImage, modulePath: unknown) {
|
|
|
1236
1402
|
* a guardrail's `checkId` becomes its `check`, as `kindgi dev`'s disk
|
|
1237
1403
|
* registry maps it.
|
|
1238
1404
|
*/
|
|
1405
|
+
/** The built-in checks, for the config of a guardrail naming one. */
|
|
1406
|
+
const builtInChecks = createCheckRegistry();
|
|
1407
|
+
|
|
1239
1408
|
function validatePrimitives(
|
|
1240
1409
|
index: Readonly<Record<string, unknown>>,
|
|
1241
1410
|
image: DeployedImage,
|
|
1411
|
+
log?: { debug(message: string): void },
|
|
1242
1412
|
): ValidateResult {
|
|
1243
1413
|
const details: ValidationDetail[] = [];
|
|
1244
1414
|
|
|
@@ -1286,12 +1456,20 @@ function validatePrimitives(
|
|
|
1286
1456
|
details.push({ primitive: 'guardrail', index: i, path: '', message: 'must be an object' });
|
|
1287
1457
|
return;
|
|
1288
1458
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1459
|
+
// The rest is the guardrail as registered, its `configSchema` included:
|
|
1460
|
+
// the runtime checks a guardrail naming this check against it. A field
|
|
1461
|
+
// the guardrail spec doesn't have (an index from a newer CLI) is dropped,
|
|
1462
|
+
// never refused, so a newer CLI never breaks a deployment.
|
|
1463
|
+
const { checkModulePath, checkId, ...indexed } = raw as Record<string, unknown>;
|
|
1464
|
+
const dropped = Object.keys(indexed).filter((k) => !GUARDRAIL_SPEC_KEYS.includes(k));
|
|
1465
|
+
const rest = Object.fromEntries(
|
|
1466
|
+
Object.entries(indexed).filter(([k]) => GUARDRAIL_SPEC_KEYS.includes(k)),
|
|
1467
|
+
);
|
|
1468
|
+
if (dropped.length > 0) {
|
|
1469
|
+
log?.debug(
|
|
1470
|
+
`deployment: guardrail ${String(indexed.id)}: ignored index field(s) this runtime doesn't know: ${dropped.join(', ')}`,
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1295
1473
|
const r = validateGuardrailSpec({
|
|
1296
1474
|
...rest,
|
|
1297
1475
|
check: checkId ?? rest.check ?? rest.id,
|
|
@@ -1325,6 +1503,21 @@ function validatePrimitives(
|
|
|
1325
1503
|
}
|
|
1326
1504
|
return;
|
|
1327
1505
|
}
|
|
1506
|
+
// A guardrail naming a built-in check: its config against the built-in's.
|
|
1507
|
+
const builtIn = builtInChecks.get(r.value.check);
|
|
1508
|
+
const configProblems = builtIn?.configProblems?.(r.value.config) ?? [];
|
|
1509
|
+
if (configProblems.length > 0) {
|
|
1510
|
+
for (const problem of configProblems) {
|
|
1511
|
+
details.push({
|
|
1512
|
+
primitive: 'guardrail',
|
|
1513
|
+
index: i,
|
|
1514
|
+
id: r.value.id as unknown as string,
|
|
1515
|
+
path: problem.path,
|
|
1516
|
+
message: problem.message,
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1328
1521
|
validatedGuardrails.push(r.value);
|
|
1329
1522
|
});
|
|
1330
1523
|
|
|
@@ -1524,7 +1717,7 @@ async function registerAgents(input: {
|
|
|
1524
1717
|
const outcome = await agents.publish({ tenantId, projectId, agent, enqueueTuples });
|
|
1525
1718
|
if (outcome.kind === 'ok') written(outcome.agentId, outcome.version);
|
|
1526
1719
|
else if (outcome.kind !== 'already-registered') {
|
|
1527
|
-
throw new PublishRefused('agent', `${agent.id}@${agent.version}`, outcome
|
|
1720
|
+
throw new PublishRefused('agent', `${agent.id}@${agent.version}`, outcome);
|
|
1528
1721
|
}
|
|
1529
1722
|
}
|
|
1530
1723
|
return input.defined.map(deployedPrimitive);
|
|
@@ -1588,7 +1781,7 @@ async function registerFlows(input: {
|
|
|
1588
1781
|
const outcome = await flows.publish({ tenantId, projectId, flow, enqueueTuples });
|
|
1589
1782
|
if (outcome.kind === 'ok') written(outcome.flowId, outcome.version as unknown as string);
|
|
1590
1783
|
else if (outcome.kind !== 'already-registered') {
|
|
1591
|
-
throw new PublishRefused('flow', `${flow.id}@${flow.version}`, outcome
|
|
1784
|
+
throw new PublishRefused('flow', `${flow.id}@${flow.version}`, outcome);
|
|
1592
1785
|
}
|
|
1593
1786
|
}
|
|
1594
1787
|
return input.defined.map(deployedPrimitive);
|
|
@@ -5,12 +5,18 @@ import type { AgentId } from '@kindgi/agents';
|
|
|
5
5
|
import type { FlowVersionOverrides } from '@kindgi/flow';
|
|
6
6
|
import type { ProjectId, Semver } from '@kindgi/types';
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
EvalBaseline,
|
|
10
|
+
EvalComparison,
|
|
11
|
+
EvalOverrides,
|
|
12
|
+
EvalSample,
|
|
13
|
+
} from '../eval-run-binding.js';
|
|
9
14
|
import { DEFAULT_COMPARISON } from '../judged-dispatcher.js';
|
|
10
15
|
import { parseSegmentsBody } from './segments.js';
|
|
11
16
|
|
|
12
17
|
const MAX_REPETITIONS = 10;
|
|
13
18
|
const MAX_K = 100;
|
|
19
|
+
const MAX_OVERRIDDEN_BLOCKS = 20;
|
|
14
20
|
|
|
15
21
|
function obj(value: unknown): Record<string, unknown> | undefined {
|
|
16
22
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
@@ -84,6 +90,71 @@ function integerIn(raw: unknown, name: string, max: number): number | string {
|
|
|
84
90
|
: `\`${name}\` must be an integer from 1 to ${max}`;
|
|
85
91
|
}
|
|
86
92
|
|
|
93
|
+
/** `overrides: { settings?, prompts? }`; `undefined` when it names nothing. */
|
|
94
|
+
function parseOverrides(raw: unknown): EvalOverrides | undefined | string {
|
|
95
|
+
const o = obj(raw);
|
|
96
|
+
if (o === undefined) return '`overrides` must be an object: { settings?, prompts? }';
|
|
97
|
+
const extra = Object.keys(o).filter((key) => key !== 'settings' && key !== 'prompts');
|
|
98
|
+
if (extra.length > 0) {
|
|
99
|
+
return `\`overrides\` takes \`settings\` and \`prompts\`, not \`${extra[0]}\``;
|
|
100
|
+
}
|
|
101
|
+
const settings = o.settings === undefined ? {} : obj(o.settings);
|
|
102
|
+
const prompts = o.prompts === undefined ? {} : obj(o.prompts);
|
|
103
|
+
const settingsBlocks = settings === undefined ? [] : Object.entries(settings);
|
|
104
|
+
const promptBlocks = prompts === undefined ? [] : Object.entries(prompts);
|
|
105
|
+
if (
|
|
106
|
+
settings === undefined ||
|
|
107
|
+
settingsBlocks.length > MAX_OVERRIDDEN_BLOCKS ||
|
|
108
|
+
settingsBlocks.some(([id, values]) => id === '' || obj(values) === undefined)
|
|
109
|
+
) {
|
|
110
|
+
return `\`overrides.settings\` must be an object of { blockId: { …values } } (at most ${MAX_OVERRIDDEN_BLOCKS} blocks)`;
|
|
111
|
+
}
|
|
112
|
+
if (
|
|
113
|
+
prompts === undefined ||
|
|
114
|
+
promptBlocks.length > 1 ||
|
|
115
|
+
promptBlocks.some(([id, content]) => {
|
|
116
|
+
const c = obj(content);
|
|
117
|
+
return (
|
|
118
|
+
id === '' ||
|
|
119
|
+
c === undefined ||
|
|
120
|
+
typeof c.template !== 'string' ||
|
|
121
|
+
Object.keys(c).length !== 1
|
|
122
|
+
);
|
|
123
|
+
})
|
|
124
|
+
) {
|
|
125
|
+
return '`overrides.prompts` must be { blockId: { template } } for the prompt block (one)';
|
|
126
|
+
}
|
|
127
|
+
if (settingsBlocks.length === 0 && promptBlocks.length === 0) return undefined;
|
|
128
|
+
return {
|
|
129
|
+
...(settingsBlocks.length > 0 && {
|
|
130
|
+
settings: settings as Readonly<Record<string, Readonly<Record<string, unknown>>>>,
|
|
131
|
+
}),
|
|
132
|
+
...(promptBlocks.length > 0 && {
|
|
133
|
+
prompts: prompts as Readonly<Record<string, { readonly template: string }>>,
|
|
134
|
+
}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** `sample: { part, seed, holdOutShare }`, or an error message. */
|
|
139
|
+
function parseSample(raw: unknown): EvalSample | string {
|
|
140
|
+
const o = obj(raw);
|
|
141
|
+
const share = o?.holdOutShare;
|
|
142
|
+
if (
|
|
143
|
+
o === undefined ||
|
|
144
|
+
(o.part !== 'search' && o.part !== 'hold-out') ||
|
|
145
|
+
typeof o.seed !== 'string' ||
|
|
146
|
+
o.seed === '' ||
|
|
147
|
+
o.seed.length > 200 ||
|
|
148
|
+
typeof share !== 'number' ||
|
|
149
|
+
share < 0.1 ||
|
|
150
|
+
share > 0.9 ||
|
|
151
|
+
Object.keys(o).some((key) => !['part', 'seed', 'holdOutShare'].includes(key))
|
|
152
|
+
) {
|
|
153
|
+
return "`sample` must be { part: 'search' | 'hold-out', seed, holdOutShare } with holdOutShare from 0.1 to 0.9";
|
|
154
|
+
}
|
|
155
|
+
return { part: o.part, seed: o.seed, holdOutShare: share };
|
|
156
|
+
}
|
|
157
|
+
|
|
87
158
|
/**
|
|
88
159
|
* A comparison eval run's settings from the start body: `baseline`,
|
|
89
160
|
* `reads`, `repetitions`, `k`, `classWeights` and a flow candidate's
|
|
@@ -99,13 +170,19 @@ export function parseComparison(
|
|
|
99
170
|
const { baseline, reads, repetitions, k, classWeights } = b;
|
|
100
171
|
const versions = b.versions === undefined ? undefined : parseVersions(b.versions);
|
|
101
172
|
if (typeof versions === 'string') return { kind: 'err', message: versions };
|
|
173
|
+
const overrides = b.overrides === undefined ? undefined : parseOverrides(b.overrides);
|
|
174
|
+
if (typeof overrides === 'string') return { kind: 'err', message: overrides };
|
|
175
|
+
const sample = b.sample === undefined ? undefined : parseSample(b.sample);
|
|
176
|
+
if (typeof sample === 'string') return { kind: 'err', message: sample };
|
|
102
177
|
if (
|
|
103
178
|
baseline === undefined &&
|
|
104
179
|
reads === undefined &&
|
|
105
180
|
repetitions === undefined &&
|
|
106
181
|
k === undefined &&
|
|
107
182
|
versions === undefined &&
|
|
108
|
-
classWeights === undefined
|
|
183
|
+
classWeights === undefined &&
|
|
184
|
+
overrides === undefined &&
|
|
185
|
+
sample === undefined
|
|
109
186
|
) {
|
|
110
187
|
return { kind: 'ok' };
|
|
111
188
|
}
|
|
@@ -144,6 +221,8 @@ export function parseComparison(
|
|
|
144
221
|
k: topK,
|
|
145
222
|
...(versions !== undefined && { versions }),
|
|
146
223
|
...(classWeights !== undefined && { classWeights }),
|
|
224
|
+
...(overrides !== undefined && { overrides }),
|
|
225
|
+
...(sample !== undefined && { sample }),
|
|
147
226
|
},
|
|
148
227
|
};
|
|
149
228
|
}
|