@kindgi/api 0.1.4-rc.5 → 0.1.5-rc.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/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/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 +73 -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 +6 -0
- package/dist/middleware/authorize.d.ts.map +1 -1
- package/dist/middleware/authorize.js +113 -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 +918 -139
- package/dist/openapi/operations.js.map +1 -1
- package/dist/openapi/schemas.d.ts +92 -13
- package/dist/openapi/schemas.d.ts.map +1 -1
- package/dist/openapi/schemas.js +2122 -370
- 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 +18 -3
- package/dist/publish-refused.d.ts.map +1 -1
- package/dist/publish-refused.js +18 -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 +7 -1
- package/dist/routes/cost.d.ts.map +1 -1
- package/dist/routes/cost.js +22 -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 +2 -1
- package/dist/routes/deployments.d.ts.map +1 -1
- package/dist/routes/deployments.js +44 -12
- 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 +63 -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 +20 -1
- 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 +129 -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 +188 -8
- 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/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 +15286 -8653
- 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/derive-agent-version.ts +9 -1
- package/src/errors.ts +73 -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 +139 -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 +1059 -142
- package/src/openapi/schemas.ts +2438 -485
- 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 +38 -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 +32 -3
- package/src/routes/denied.ts +28 -0
- package/src/routes/deployments.ts +62 -16
- package/src/routes/eval-comparison.ts +81 -2
- package/src/routes/eval-overrides.ts +108 -0
- package/src/routes/eval-runs.ts +86 -6
- package/src/routes/eval-suites.ts +25 -1
- 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 +179 -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 +223 -8
- package/src/routes/public-run-tokens.ts +3 -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/schedules.ts
CHANGED
|
@@ -4,36 +4,88 @@
|
|
|
4
4
|
import { Hono } from 'hono';
|
|
5
5
|
import type { Context } from 'hono';
|
|
6
6
|
|
|
7
|
-
import type
|
|
7
|
+
import { type Action, type ResourceRef, ref } from '@kindgi/authz';
|
|
8
|
+
import type { ProjectBinding } from '@kindgi/platform';
|
|
9
|
+
import type { Cursor, ProjectId, TenantId, TriggerId } from '@kindgi/types';
|
|
8
10
|
|
|
9
11
|
import { statusFor, toWireError } from '../errors.js';
|
|
10
|
-
import type {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
13
|
+
import {
|
|
14
|
+
type CronTriggerRecord,
|
|
15
|
+
type RegisterCronTriggerInput,
|
|
16
|
+
SCHEDULE_DEFAULTS,
|
|
17
|
+
type ScheduleCatchUp,
|
|
18
|
+
type ScheduleOverlap,
|
|
19
|
+
type TriggerFire,
|
|
20
|
+
type TriggerOwner,
|
|
21
|
+
type TriggerRegistryBinding,
|
|
22
|
+
type TriggerTarget,
|
|
23
|
+
type UpdateCronTriggerInput,
|
|
15
24
|
} from '../trigger-binding.js';
|
|
16
25
|
import type { AppEnv } from '../types.js';
|
|
26
|
+
import { parseImproveScheduleInput } from './improvement-passes.js';
|
|
27
|
+
import { liveScopeToWire, parseLiveScopeBody } from './live-scope-wire.js';
|
|
17
28
|
import { clampLimit } from './pagination.js';
|
|
29
|
+
import { UUID_RE } from './uuid-param.js';
|
|
18
30
|
|
|
19
31
|
/**
|
|
20
|
-
* Schedules
|
|
32
|
+
* Schedules: cron-kind triggers that start a run of an agent or a flow.
|
|
21
33
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
34
|
+
* POST /v1/schedules register
|
|
35
|
+
* GET /v1/schedules list (cursor-paginated)
|
|
36
|
+
* GET /v1/schedules/:triggerId[?upcoming=N] get, with its next N occurrences
|
|
37
|
+
* PATCH /v1/schedules/:triggerId update
|
|
38
|
+
* POST /v1/schedules/:triggerId/pause | resume | unregister
|
|
39
|
+
* GET /v1/schedules/:triggerId/fires its fire history, newest first
|
|
40
|
+
* POST /v1/schedules/:triggerId/run-now fire it now, outside the schedule
|
|
41
|
+
* POST /v1/schedules/:triggerId/owner the caller becomes the owner
|
|
30
42
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
43
|
+
* A schedule's runs act as its owner (whoever registered it, until an
|
|
44
|
+
* admin takes it over), checked again at every fire. With an authorizer:
|
|
45
|
+
* reads need `read` on the schedule's project, changes `write`, taking
|
|
46
|
+
* ownership `admin`, and registering or retargeting also needs `execute`
|
|
47
|
+
* on what it runs, as starting that run does. The `triggerId` is aliased
|
|
48
|
+
* as `scheduleId` in bodies.
|
|
33
49
|
*/
|
|
34
|
-
export function schedulesRouter(
|
|
50
|
+
export function schedulesRouter(
|
|
51
|
+
binding: TriggerRegistryBinding,
|
|
52
|
+
authorizer?: Authorizer,
|
|
53
|
+
/** The tenant's Default project: where a schedule that names no project goes. */
|
|
54
|
+
projects?: Pick<ProjectBinding, 'getDefault'>,
|
|
55
|
+
): Hono<AppEnv> {
|
|
35
56
|
const r = new Hono<AppEnv>();
|
|
36
57
|
|
|
58
|
+
/** Nothing, when allowed; else the authorizer's own 403. */
|
|
59
|
+
async function denied(
|
|
60
|
+
c: Context<AppEnv>,
|
|
61
|
+
action: Action,
|
|
62
|
+
resource: ResourceRef,
|
|
63
|
+
): Promise<Response | undefined> {
|
|
64
|
+
if (authorizer === undefined) return undefined;
|
|
65
|
+
let allowed = false;
|
|
66
|
+
const answer = await authorizer.authorize(action, async () => resource)(c, async () => {
|
|
67
|
+
allowed = true;
|
|
68
|
+
});
|
|
69
|
+
return allowed ? undefined : (answer as Response);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** The schedule, if it is one (another kind's id is not found here), and the caller may `action` it. */
|
|
73
|
+
async function scheduleFor(
|
|
74
|
+
c: Context<AppEnv>,
|
|
75
|
+
action: Action,
|
|
76
|
+
): Promise<{ kind: 'ok'; value: CronTriggerRecord } | { kind: 'err'; response: Response }> {
|
|
77
|
+
const requestId = c.get('requestId');
|
|
78
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
79
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
80
|
+
const rec = UUID_RE.test(triggerId) ? await binding.get({ tenantId, triggerId }) : null;
|
|
81
|
+
if (rec === null || rec.kind !== 'cron') {
|
|
82
|
+
return { kind: 'err', response: notFound(c, requestId, triggerId) };
|
|
83
|
+
}
|
|
84
|
+
const refused = await denied(c, action, ref('project', rec.projectId as unknown as string));
|
|
85
|
+
if (refused !== undefined) return { kind: 'err', response: refused };
|
|
86
|
+
return { kind: 'ok', value: rec };
|
|
87
|
+
}
|
|
88
|
+
|
|
37
89
|
// ---------- POST / (register) ----------
|
|
38
90
|
r.post('/', async (c) => {
|
|
39
91
|
const requestId = c.get('requestId');
|
|
@@ -43,24 +95,49 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
43
95
|
if (parsed.kind === 'err') return parsed.response;
|
|
44
96
|
const body = parsed.value;
|
|
45
97
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
const cronExpression = requireString(body
|
|
49
|
-
if (flowId.kind === 'err') return bad(c, requestId, flowId.message);
|
|
50
|
-
if (flowVersion.kind === 'err') return bad(c, requestId, flowVersion.message);
|
|
98
|
+
const target = parseTarget(body);
|
|
99
|
+
if (target.kind === 'err') return bad(c, requestId, target.message);
|
|
100
|
+
const cronExpression = requireString(body, 'config.cronExpression');
|
|
51
101
|
if (cronExpression.kind === 'err') return bad(c, requestId, cronExpression.message);
|
|
52
|
-
|
|
102
|
+
const policy = parsePolicy(body);
|
|
103
|
+
if (policy.kind === 'err') return bad(c, requestId, policy.message);
|
|
104
|
+
const projectId = body.projectId;
|
|
105
|
+
if (projectId !== undefined && (typeof projectId !== 'string' || !UUID_RE.test(projectId))) {
|
|
106
|
+
return bad(c, requestId, '`projectId` must be a project id (a UUID)');
|
|
107
|
+
}
|
|
53
108
|
const rawConfig = (body.config ?? {}) as Record<string, unknown>;
|
|
109
|
+
const input = targetInput(target.value, rawConfig.input);
|
|
110
|
+
if (input.kind === 'err') return bad(c, requestId, input.message);
|
|
111
|
+
|
|
112
|
+
// A schedule that names no project goes in its improve scope's
|
|
113
|
+
// project, else the tenant's Default project: checked and stored as
|
|
114
|
+
// that project. With no Default to find, the registry picks it, and
|
|
115
|
+
// only a tenant admin may.
|
|
116
|
+
const project =
|
|
117
|
+
(projectId as string | undefined) ??
|
|
118
|
+
scopeProjectOf(target.value) ??
|
|
119
|
+
((await projects?.getDefault(tenantId))?.id as string | undefined);
|
|
120
|
+
const scopeProblem = improveScopeProblem(target.value, project);
|
|
121
|
+
if (scopeProblem !== undefined) return bad(c, requestId, scopeProblem);
|
|
122
|
+
const refused =
|
|
123
|
+
(project === undefined
|
|
124
|
+
? await denied(c, 'admin', ref('tenant', tenantId as unknown as string))
|
|
125
|
+
: await denied(c, 'write', ref('project', project))) ??
|
|
126
|
+
(await denied(c, ...targetAccess(target.value)));
|
|
127
|
+
if (refused !== undefined) return refused;
|
|
128
|
+
|
|
54
129
|
const registerInput: RegisterCronTriggerInput = {
|
|
55
130
|
kind: 'cron',
|
|
56
131
|
tenantId,
|
|
57
|
-
|
|
58
|
-
|
|
132
|
+
target: target.value,
|
|
133
|
+
...(project !== undefined && { projectId: project as ProjectId }),
|
|
134
|
+
owner: ownerOf(c),
|
|
59
135
|
config: {
|
|
60
136
|
cronExpression: cronExpression.value,
|
|
61
137
|
...(typeof rawConfig.timezone === 'string' && { timezone: rawConfig.timezone }),
|
|
62
|
-
...(
|
|
138
|
+
...(input.input !== undefined && { input: input.input }),
|
|
63
139
|
},
|
|
140
|
+
...policy.value,
|
|
64
141
|
...(typeof body.label === 'string' && body.label.length > 0 && { label: body.label }),
|
|
65
142
|
};
|
|
66
143
|
|
|
@@ -76,6 +153,10 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
76
153
|
});
|
|
77
154
|
|
|
78
155
|
// ---------- GET / (list) ----------
|
|
156
|
+
// The tenant's schedules, then only those whose project the caller may
|
|
157
|
+
// read (`read` on it, as reading one schedule needs): a schedule's input
|
|
158
|
+
// and target are its project's. The page and its cursor are the
|
|
159
|
+
// tenant's, so a page can hold fewer than `limit` rows and still have more.
|
|
79
160
|
r.get('/', async (c) => {
|
|
80
161
|
const tenantId = c.get('tenantId') as TenantId;
|
|
81
162
|
const limit = clampLimit(c.req.query('limit'));
|
|
@@ -92,8 +173,15 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
92
173
|
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
93
174
|
...(statusFilter !== undefined && { status: statusFilter }),
|
|
94
175
|
});
|
|
176
|
+
const rows = page.data as CronTriggerRecord[];
|
|
177
|
+
const visible =
|
|
178
|
+
authorizer === undefined
|
|
179
|
+
? rows
|
|
180
|
+
: await authorizer.filterByCan(c, 'read', rows, (rec) =>
|
|
181
|
+
ref('project', rec.projectId as unknown as string),
|
|
182
|
+
);
|
|
95
183
|
return c.json({
|
|
96
|
-
data:
|
|
184
|
+
data: visible.map((row) => serializeSchedule(row)),
|
|
97
185
|
hasMore: page.nextCursor !== undefined,
|
|
98
186
|
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
99
187
|
});
|
|
@@ -102,24 +190,54 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
102
190
|
// ---------- GET /:triggerId (get) ----------
|
|
103
191
|
r.get('/:triggerId', async (c) => {
|
|
104
192
|
const requestId = c.get('requestId');
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
193
|
+
const upcomingRaw = c.req.query('upcoming');
|
|
194
|
+
const upcoming = upcomingRaw === undefined ? undefined : Number(upcomingRaw);
|
|
195
|
+
if (upcoming !== undefined && (!Number.isInteger(upcoming) || upcoming < 1 || upcoming > 20)) {
|
|
196
|
+
return bad(c, requestId, '`upcoming` must be a whole number from 1 to 20');
|
|
197
|
+
}
|
|
198
|
+
const found = await scheduleFor(c, 'read');
|
|
199
|
+
if (found.kind === 'err') return found.response;
|
|
200
|
+
if (upcoming === undefined) return c.json(serializeSchedule(found.value));
|
|
201
|
+
const rec = await binding.get({
|
|
202
|
+
tenantId: c.get('tenantId') as TenantId,
|
|
203
|
+
triggerId: found.value.triggerId,
|
|
204
|
+
upcoming,
|
|
205
|
+
});
|
|
206
|
+
return c.json(serializeSchedule((rec ?? found.value) as CronTriggerRecord));
|
|
111
207
|
});
|
|
112
208
|
|
|
113
209
|
// ---------- PATCH /:triggerId (update) ----------
|
|
114
210
|
r.patch('/:triggerId', async (c) => {
|
|
115
211
|
const requestId = c.get('requestId');
|
|
116
212
|
const tenantId = c.get('tenantId') as TenantId;
|
|
117
|
-
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
118
213
|
|
|
119
214
|
const parsed = await parseJsonObject(c, requestId);
|
|
120
215
|
if (parsed.kind === 'err') return parsed.response;
|
|
121
216
|
const body = parsed.value;
|
|
122
217
|
|
|
218
|
+
const retarget =
|
|
219
|
+
'flowId' in body ||
|
|
220
|
+
'agentId' in body ||
|
|
221
|
+
'flowVersion' in body ||
|
|
222
|
+
'agentVersion' in body ||
|
|
223
|
+
'improve' in body;
|
|
224
|
+
const target = retarget ? parseTarget(body) : undefined;
|
|
225
|
+
if (target?.kind === 'err') return bad(c, requestId, target.message);
|
|
226
|
+
const policy = parsePolicy(body);
|
|
227
|
+
if (policy.kind === 'err') return bad(c, requestId, policy.message);
|
|
228
|
+
|
|
229
|
+
const found = await scheduleFor(c, 'write');
|
|
230
|
+
if (found.kind === 'err') return found.response;
|
|
231
|
+
if (target !== undefined) {
|
|
232
|
+
const scopeProblem = improveScopeProblem(
|
|
233
|
+
target.value,
|
|
234
|
+
found.value.projectId as unknown as string,
|
|
235
|
+
);
|
|
236
|
+
if (scopeProblem !== undefined) return bad(c, requestId, scopeProblem);
|
|
237
|
+
const refused = await denied(c, ...targetAccess(target.value));
|
|
238
|
+
if (refused !== undefined) return refused;
|
|
239
|
+
}
|
|
240
|
+
|
|
123
241
|
const patchConfig = body.config as Record<string, unknown> | undefined;
|
|
124
242
|
const cfg: Partial<{ cronExpression: string; timezone: string; input: unknown }> = {};
|
|
125
243
|
if (patchConfig !== undefined) {
|
|
@@ -128,14 +246,24 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
128
246
|
if (typeof patchConfig.timezone === 'string') cfg.timezone = patchConfig.timezone;
|
|
129
247
|
if ('input' in patchConfig) cfg.input = patchConfig.input;
|
|
130
248
|
}
|
|
249
|
+
if (target !== undefined || 'input' in cfg) {
|
|
250
|
+
const input = targetInput(
|
|
251
|
+
target?.value ?? found.value.target,
|
|
252
|
+
'input' in cfg ? cfg.input : found.value.config.input,
|
|
253
|
+
);
|
|
254
|
+
if (input.kind === 'err') return bad(c, requestId, input.message);
|
|
255
|
+
if (input.input !== undefined) cfg.input = input.input;
|
|
256
|
+
}
|
|
131
257
|
|
|
258
|
+
const triggerId = found.value.triggerId;
|
|
132
259
|
const updateInput: UpdateCronTriggerInput = {
|
|
133
260
|
kind: 'cron',
|
|
134
261
|
tenantId,
|
|
135
262
|
triggerId,
|
|
136
263
|
...(Object.keys(cfg).length > 0 && { config: cfg }),
|
|
264
|
+
...(target !== undefined && { target: target.value }),
|
|
265
|
+
...policy.value,
|
|
137
266
|
...('label' in body && { label: body.label === null ? null : (body.label as string) }),
|
|
138
|
-
...(typeof body.flowVersion === 'string' && { flowVersion: body.flowVersion }),
|
|
139
267
|
};
|
|
140
268
|
|
|
141
269
|
const result = await binding.update(updateInput);
|
|
@@ -155,30 +283,24 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
155
283
|
return c.json(serializeSchedule(result.value as CronTriggerRecord));
|
|
156
284
|
});
|
|
157
285
|
|
|
158
|
-
// ---------- POST /:triggerId/pause ----------
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const requestId = c.get('requestId');
|
|
171
|
-
const tenantId = c.get('tenantId') as TenantId;
|
|
172
|
-
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
173
|
-
const result = await binding.resume({ tenantId, triggerId });
|
|
174
|
-
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
175
|
-
return c.json(serializeSchedule(result.value as CronTriggerRecord));
|
|
176
|
-
});
|
|
286
|
+
// ---------- POST /:triggerId/pause | resume ----------
|
|
287
|
+
for (const verb of ['pause', 'resume'] as const) {
|
|
288
|
+
r.post(`/:triggerId/${verb}`, async (c) => {
|
|
289
|
+
const requestId = c.get('requestId');
|
|
290
|
+
const found = await scheduleFor(c, 'write');
|
|
291
|
+
if (found.kind === 'err') return found.response;
|
|
292
|
+
const { tenantId, triggerId } = found.value;
|
|
293
|
+
const result = await binding[verb]({ tenantId, triggerId });
|
|
294
|
+
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
295
|
+
return c.json(serializeSchedule(result.value as CronTriggerRecord));
|
|
296
|
+
});
|
|
297
|
+
}
|
|
177
298
|
|
|
178
299
|
// ---------- POST /:triggerId/unregister (soft delete) ----------
|
|
179
300
|
r.post('/:triggerId/unregister', async (c) => {
|
|
180
|
-
const
|
|
181
|
-
|
|
301
|
+
const found = await scheduleFor(c, 'write');
|
|
302
|
+
if (found.kind === 'err') return found.response;
|
|
303
|
+
const { tenantId, triggerId } = found.value;
|
|
182
304
|
const outcome = await binding.unregister({ tenantId, triggerId });
|
|
183
305
|
return c.json({
|
|
184
306
|
scheduleId: triggerId as unknown as string,
|
|
@@ -186,6 +308,53 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
186
308
|
});
|
|
187
309
|
});
|
|
188
310
|
|
|
311
|
+
// ---------- GET /:triggerId/fires (history) ----------
|
|
312
|
+
r.get('/:triggerId/fires', async (c) => {
|
|
313
|
+
const requestId = c.get('requestId');
|
|
314
|
+
const found = await scheduleFor(c, 'read');
|
|
315
|
+
if (found.kind === 'err') return found.response;
|
|
316
|
+
if (binding.listFires === undefined) return unsupported(c, requestId, 'fire history');
|
|
317
|
+
const cursorRaw = c.req.query('cursor');
|
|
318
|
+
const page = await binding.listFires({
|
|
319
|
+
tenantId: found.value.tenantId,
|
|
320
|
+
triggerId: found.value.triggerId,
|
|
321
|
+
limit: clampLimit(c.req.query('limit')),
|
|
322
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
323
|
+
});
|
|
324
|
+
return c.json({
|
|
325
|
+
data: page.data.map(serializeFire),
|
|
326
|
+
hasMore: page.nextCursor !== undefined,
|
|
327
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// ---------- POST /:triggerId/run-now ----------
|
|
332
|
+
r.post('/:triggerId/run-now', async (c) => {
|
|
333
|
+
const requestId = c.get('requestId');
|
|
334
|
+
const found = await scheduleFor(c, 'write');
|
|
335
|
+
if (found.kind === 'err') return found.response;
|
|
336
|
+
if (binding.fireNow === undefined) return unsupported(c, requestId, 'run-now');
|
|
337
|
+
const { tenantId, triggerId } = found.value;
|
|
338
|
+
const result = await binding.fireNow({ tenantId, triggerId });
|
|
339
|
+
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
340
|
+
c.status(202);
|
|
341
|
+
return c.json(serializeFire(result.value));
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// ---------- POST /:triggerId/owner (take ownership) ----------
|
|
345
|
+
r.post('/:triggerId/owner', async (c) => {
|
|
346
|
+
const requestId = c.get('requestId');
|
|
347
|
+
const found = await scheduleFor(c, 'admin');
|
|
348
|
+
if (found.kind === 'err') return found.response;
|
|
349
|
+
if (binding.setOwner === undefined) return unsupported(c, requestId, 'changing the owner');
|
|
350
|
+
const refused = await denied(c, ...targetAccess(found.value.target));
|
|
351
|
+
if (refused !== undefined) return refused;
|
|
352
|
+
const { tenantId, triggerId } = found.value;
|
|
353
|
+
const result = await binding.setOwner({ tenantId, triggerId, owner: ownerOf(c) });
|
|
354
|
+
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
355
|
+
return c.json(serializeSchedule(result.value as CronTriggerRecord));
|
|
356
|
+
});
|
|
357
|
+
|
|
189
358
|
return r;
|
|
190
359
|
}
|
|
191
360
|
|
|
@@ -193,24 +362,254 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
|
193
362
|
// Shared helpers (co-located to keep each router self-contained).
|
|
194
363
|
// -----------------------------------------------------------------------
|
|
195
364
|
|
|
365
|
+
/** A target on the wire: `flowId` + `flowVersion`, `agentId` (+ `agentVersion`), or `improve`. */
|
|
366
|
+
function targetFields(target: TriggerTarget): Record<string, unknown> {
|
|
367
|
+
switch (target.kind) {
|
|
368
|
+
case 'flow':
|
|
369
|
+
return { flowId: target.flowId, flowVersion: target.flowVersion };
|
|
370
|
+
case 'agent':
|
|
371
|
+
return {
|
|
372
|
+
agentId: target.agentId,
|
|
373
|
+
...(target.agentVersion !== undefined && { agentVersion: target.agentVersion }),
|
|
374
|
+
};
|
|
375
|
+
case 'improve':
|
|
376
|
+
return { improve: { agentId: target.agentId, scope: liveScopeToWire(target.scope) } };
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
196
380
|
function serializeSchedule(r: CronTriggerRecord): Record<string, unknown> {
|
|
197
381
|
return {
|
|
198
382
|
scheduleId: r.triggerId as unknown as string,
|
|
199
383
|
triggerId: r.triggerId as unknown as string,
|
|
200
|
-
|
|
201
|
-
|
|
384
|
+
...targetFields(r.target),
|
|
385
|
+
projectId: r.projectId as unknown as string,
|
|
386
|
+
owner: { kind: r.owner.kind, id: r.owner.id },
|
|
202
387
|
cronExpression: r.config.cronExpression,
|
|
203
388
|
...(r.config.timezone !== undefined && { timezone: r.config.timezone }),
|
|
204
389
|
...(r.config.input !== undefined && { input: r.config.input }),
|
|
390
|
+
catchUp: r.catchUp,
|
|
391
|
+
overlap: r.overlap,
|
|
392
|
+
startingDeadlineSeconds: r.startingDeadlineSeconds,
|
|
205
393
|
label: r.label,
|
|
206
394
|
status: r.status,
|
|
395
|
+
...(r.statusReason !== undefined && { statusReason: r.statusReason }),
|
|
207
396
|
nextFireAt: r.nextFireAt,
|
|
397
|
+
...(r.upcoming !== undefined && { upcoming: r.upcoming }),
|
|
208
398
|
lastFiredAt: r.lastFiredAt,
|
|
209
399
|
createdAt: r.createdAt,
|
|
210
400
|
updatedAt: r.updatedAt,
|
|
211
401
|
};
|
|
212
402
|
}
|
|
213
403
|
|
|
404
|
+
function serializeFire(f: TriggerFire): Record<string, unknown> {
|
|
405
|
+
return {
|
|
406
|
+
fireId: f.fireId,
|
|
407
|
+
scheduleId: f.triggerId as unknown as string,
|
|
408
|
+
triggerId: f.triggerId as unknown as string,
|
|
409
|
+
...(f.scheduledFor !== undefined && { scheduledFor: f.scheduledFor }),
|
|
410
|
+
firedAt: f.firedAt,
|
|
411
|
+
outcome: f.outcome,
|
|
412
|
+
...(f.runId !== undefined && { runId: f.runId }),
|
|
413
|
+
...(f.passId !== undefined && { passId: f.passId }),
|
|
414
|
+
...(f.detail !== undefined && { detail: f.detail }),
|
|
415
|
+
...(f.missedCount !== undefined && { missedCount: f.missedCount }),
|
|
416
|
+
...(f.manual === true && { manual: true }),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* What firing the target needs, as starting it by hand does: `execute` on
|
|
422
|
+
* the agent or flow a run starts; `publish` on the agent an improvement
|
|
423
|
+
* pass works on (as `POST /v1/proposals/improve`).
|
|
424
|
+
*/
|
|
425
|
+
function targetAccess(target: TriggerTarget): [Action, ResourceRef] {
|
|
426
|
+
switch (target.kind) {
|
|
427
|
+
case 'flow':
|
|
428
|
+
return ['execute', ref('flow', target.flowId)];
|
|
429
|
+
case 'agent':
|
|
430
|
+
return ['execute', ref('agent', target.agentId)];
|
|
431
|
+
case 'improve':
|
|
432
|
+
return ['publish', ref('agent', target.agentId)];
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** Who a schedule's runs act as: the request's principal. */
|
|
437
|
+
function ownerOf(c: Context<AppEnv>): TriggerOwner {
|
|
438
|
+
const actor = c.get('principal')?.actor;
|
|
439
|
+
if (actor === undefined) return { kind: 'service', id: 'unknown' };
|
|
440
|
+
return { kind: actor.kind === 'user' ? 'user' : 'service', id: actor.id };
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/** `flowId` + `flowVersion`, `agentId` (+ `agentVersion`), or `improve`: exactly one target. */
|
|
444
|
+
function parseTarget(
|
|
445
|
+
body: Record<string, unknown>,
|
|
446
|
+
): { kind: 'ok'; value: TriggerTarget } | { kind: 'err'; message: string } {
|
|
447
|
+
const { flowId, flowVersion, agentId, agentVersion, improve } = body;
|
|
448
|
+
const named = (v: unknown) => typeof v === 'string' && v.length > 0;
|
|
449
|
+
if ([named(flowId), named(agentId), improve !== undefined].filter(Boolean).length !== 1) {
|
|
450
|
+
return {
|
|
451
|
+
kind: 'err',
|
|
452
|
+
message:
|
|
453
|
+
'Name what the schedule runs: `flowId` (with `flowVersion`), `agentId`, or `improve` ({ agentId, scope }), one of them',
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
if (improve !== undefined) return parseImproveTarget(improve, flowVersion, agentVersion);
|
|
457
|
+
if (named(flowId)) {
|
|
458
|
+
if (!named(flowVersion))
|
|
459
|
+
return { kind: 'err', message: '`flowVersion` is required with `flowId`' };
|
|
460
|
+
if (agentVersion !== undefined) {
|
|
461
|
+
return { kind: 'err', message: '`agentVersion` goes with `agentId`, not `flowId`' };
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
kind: 'ok',
|
|
465
|
+
value: { kind: 'flow', flowId: flowId as string, flowVersion: flowVersion as string },
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
if (flowVersion !== undefined) {
|
|
469
|
+
return { kind: 'err', message: '`flowVersion` goes with `flowId`, not `agentId`' };
|
|
470
|
+
}
|
|
471
|
+
if (agentVersion !== undefined && !named(agentVersion)) {
|
|
472
|
+
return { kind: 'err', message: '`agentVersion` must be a version (semver)' };
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
kind: 'ok',
|
|
476
|
+
value: {
|
|
477
|
+
kind: 'agent',
|
|
478
|
+
agentId: agentId as string,
|
|
479
|
+
...(agentVersion !== undefined && { agentVersion: agentVersion as string }),
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/** An improve scope's project, when it names one. */
|
|
485
|
+
function scopeProjectOf(target: TriggerTarget): string | undefined {
|
|
486
|
+
if (target.kind !== 'improve') return undefined;
|
|
487
|
+
const { scope } = target;
|
|
488
|
+
return scope.kind === 'project' || scope.kind === 'segment'
|
|
489
|
+
? (scope.projectId as unknown as string)
|
|
490
|
+
: undefined;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* A pass's evidence must cover the scope it changes: an improve schedule
|
|
495
|
+
* learns from its project's runs (for a segment scope, that segment's),
|
|
496
|
+
* so its scope is the schedule's own project or a segment of it. The
|
|
497
|
+
* tenant and an org span projects: going wider stays a promotion by hand,
|
|
498
|
+
* through that scope's gate.
|
|
499
|
+
*/
|
|
500
|
+
function improveScopeProblem(
|
|
501
|
+
target: TriggerTarget,
|
|
502
|
+
project: string | undefined,
|
|
503
|
+
): string | undefined {
|
|
504
|
+
if (target.kind !== 'improve') return undefined;
|
|
505
|
+
if (target.scope.kind === 'tenant' || target.scope.kind === 'org') {
|
|
506
|
+
return `An improve schedule's scope is a project or a segment of it, not the ${target.scope.kind === 'org' ? 'org' : 'tenant'}: a pass's evidence must cover the scope it changes, and it learns from one project's runs. Use the project (or a segment) scope; promote to the ${target.scope.kind === 'org' ? 'org' : 'tenant'} by hand after review.`;
|
|
507
|
+
}
|
|
508
|
+
const own = scopeProjectOf(target);
|
|
509
|
+
if (own !== undefined && project !== undefined && own !== project) {
|
|
510
|
+
return "An improve schedule's scope must be in the schedule's project (`projectId`): it learns from that project's runs";
|
|
511
|
+
}
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function parseImproveTarget(
|
|
516
|
+
improve: unknown,
|
|
517
|
+
flowVersion: unknown,
|
|
518
|
+
agentVersion: unknown,
|
|
519
|
+
): { kind: 'ok'; value: TriggerTarget } | { kind: 'err'; message: string } {
|
|
520
|
+
const shape =
|
|
521
|
+
'An improve schedule names `improve: { agentId, scope }`: the agent its passes work on, and the live scope they propose for';
|
|
522
|
+
if (flowVersion !== undefined || agentVersion !== undefined) {
|
|
523
|
+
return {
|
|
524
|
+
kind: 'err',
|
|
525
|
+
message: `${shape}; \`flowVersion\` and \`agentVersion\` don't go with it`,
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
const o =
|
|
529
|
+
typeof improve === 'object' && improve !== null && !Array.isArray(improve)
|
|
530
|
+
? (improve as Record<string, unknown>)
|
|
531
|
+
: undefined;
|
|
532
|
+
if (
|
|
533
|
+
o === undefined ||
|
|
534
|
+
Object.keys(o).some((k) => k !== 'agentId' && k !== 'scope') ||
|
|
535
|
+
typeof o.agentId !== 'string' ||
|
|
536
|
+
o.agentId.length === 0
|
|
537
|
+
) {
|
|
538
|
+
return { kind: 'err', message: shape };
|
|
539
|
+
}
|
|
540
|
+
const scope = parseLiveScopeBody(o.scope);
|
|
541
|
+
if (scope.kind === 'err') return { kind: 'err', message: `\`improve.scope\`: ${scope.message}` };
|
|
542
|
+
return { kind: 'ok', value: { kind: 'improve', agentId: o.agentId, scope: scope.scope } };
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* The input a target's fires get, or why it can't be: an agent's run takes
|
|
547
|
+
* the agent payload, so an agent schedule's input must carry the message
|
|
548
|
+
* each run sends (without it every fire would be refused); an improve
|
|
549
|
+
* schedule's input is its pass options, kept with the defaults applied; a
|
|
550
|
+
* flow's input is the flow's own.
|
|
551
|
+
*/
|
|
552
|
+
function targetInput(
|
|
553
|
+
target: TriggerTarget,
|
|
554
|
+
input: unknown,
|
|
555
|
+
): { kind: 'ok'; input?: unknown } | { kind: 'err'; message: string } {
|
|
556
|
+
if (target.kind === 'improve') {
|
|
557
|
+
const parsed = parseImproveScheduleInput(input);
|
|
558
|
+
return parsed.kind === 'ok' ? { kind: 'ok', input: parsed.input } : parsed;
|
|
559
|
+
}
|
|
560
|
+
if (target.kind === 'flow') return { kind: 'ok', ...(input !== undefined && { input }) };
|
|
561
|
+
const message =
|
|
562
|
+
typeof input === 'object' && input !== null
|
|
563
|
+
? (input as Record<string, unknown>).userMessage
|
|
564
|
+
: undefined;
|
|
565
|
+
if (typeof message === 'string' && message.length > 0) return { kind: 'ok', input };
|
|
566
|
+
return {
|
|
567
|
+
kind: 'err',
|
|
568
|
+
message:
|
|
569
|
+
'An agent schedule needs `config.input.userMessage`: the message each run sends the agent (`{ userMessage, parameters? }`)',
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/** `catchUp`, `overlap` and `startingDeadlineSeconds`, each optional. */
|
|
574
|
+
function parsePolicy(body: Record<string, unknown>):
|
|
575
|
+
| {
|
|
576
|
+
kind: 'ok';
|
|
577
|
+
value: {
|
|
578
|
+
catchUp?: ScheduleCatchUp;
|
|
579
|
+
overlap?: ScheduleOverlap;
|
|
580
|
+
startingDeadlineSeconds?: number;
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
| { kind: 'err'; message: string } {
|
|
584
|
+
const { catchUp, overlap, startingDeadlineSeconds } = body;
|
|
585
|
+
if (catchUp !== undefined && catchUp !== 'latest' && catchUp !== 'skip') {
|
|
586
|
+
return { kind: 'err', message: '`catchUp` must be `latest` or `skip`' };
|
|
587
|
+
}
|
|
588
|
+
if (overlap !== undefined && overlap !== 'skip' && overlap !== 'allow') {
|
|
589
|
+
return { kind: 'err', message: '`overlap` must be `skip` or `allow`' };
|
|
590
|
+
}
|
|
591
|
+
if (
|
|
592
|
+
startingDeadlineSeconds !== undefined &&
|
|
593
|
+
(typeof startingDeadlineSeconds !== 'number' ||
|
|
594
|
+
!Number.isInteger(startingDeadlineSeconds) ||
|
|
595
|
+
startingDeadlineSeconds < 1 ||
|
|
596
|
+
startingDeadlineSeconds > 86_400)
|
|
597
|
+
) {
|
|
598
|
+
return {
|
|
599
|
+
kind: 'err',
|
|
600
|
+
message: `\`startingDeadlineSeconds\` must be a whole number of seconds from 1 to 86400 (default ${SCHEDULE_DEFAULTS.startingDeadlineSeconds})`,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
return {
|
|
604
|
+
kind: 'ok',
|
|
605
|
+
value: {
|
|
606
|
+
...(catchUp !== undefined && { catchUp }),
|
|
607
|
+
...(overlap !== undefined && { overlap }),
|
|
608
|
+
...(startingDeadlineSeconds !== undefined && { startingDeadlineSeconds }),
|
|
609
|
+
},
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
|
|
214
613
|
type ParseOk<T> = { readonly kind: 'ok'; readonly value: T };
|
|
215
614
|
type ParseErr = { readonly kind: 'err'; readonly response: Response };
|
|
216
615
|
|
|
@@ -270,13 +669,26 @@ function bad(c: Context<AppEnv>, requestId: string, message: string): Response {
|
|
|
270
669
|
return c.json(toWireError({ code: 'bad-input', message }, requestId));
|
|
271
670
|
}
|
|
272
671
|
|
|
672
|
+
function unsupported(c: Context<AppEnv>, requestId: string, what: string): Response {
|
|
673
|
+
c.status(statusFor('trigger-operation-unsupported') as never);
|
|
674
|
+
return c.json(
|
|
675
|
+
toWireError(
|
|
676
|
+
{
|
|
677
|
+
code: 'trigger-operation-unsupported',
|
|
678
|
+
message: `This deployment's schedules don't support ${what} yet.`,
|
|
679
|
+
},
|
|
680
|
+
requestId,
|
|
681
|
+
),
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
|
|
273
685
|
function notFound(c: Context<AppEnv>, requestId: string, triggerId: TriggerId): Response {
|
|
274
686
|
c.status(statusFor('trigger-not-found') as never);
|
|
275
687
|
return c.json(
|
|
276
688
|
toWireError(
|
|
277
689
|
{
|
|
278
690
|
code: 'trigger-not-found',
|
|
279
|
-
message: `No
|
|
691
|
+
message: `No schedule with id "${triggerId as unknown as string}"`,
|
|
280
692
|
triggerId: triggerId as unknown as string,
|
|
281
693
|
},
|
|
282
694
|
requestId,
|