@wardby/cli 0.2.1 → 0.3.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/.env.example +34 -4
- package/README.md +41 -4
- package/dist/claude-coding-worker/driver.d.ts +6 -1
- package/dist/claude-coding-worker/driver.js +27 -1
- package/dist/claude-coding-worker/main.js +2 -0
- package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
- package/dist/claude-coding-worker/tool-socket.js +26 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +13 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +219 -29
- package/dist/coding/collect-exclude.d.ts +25 -0
- package/dist/coding/collect-exclude.js +76 -0
- package/dist/coding/profile.d.ts +67 -22
- package/dist/coding/profile.js +58 -25
- package/dist/coding/protected-path-wording.d.ts +24 -0
- package/dist/coding/protected-path-wording.js +55 -0
- package/dist/coding/protected-paths.d.ts +31 -0
- package/dist/coding/protected-paths.js +48 -0
- package/dist/coding/protocol.d.ts +75 -4
- package/dist/coding/protocol.js +107 -7
- package/dist/coding/registry/adapters.d.ts +2 -0
- package/dist/coding/registry/adapters.js +9 -0
- package/dist/coding/registry/allowlist.d.ts +9 -0
- package/dist/coding/registry/allowlist.js +28 -0
- package/dist/coding/registry/json-scan.d.ts +55 -0
- package/dist/coding/registry/json-scan.js +191 -0
- package/dist/coding/registry/lockfiles.d.ts +6 -0
- package/dist/coding/registry/lockfiles.js +89 -0
- package/dist/coding/registry/npm-lockfile.d.ts +9 -0
- package/dist/coding/registry/npm-lockfile.js +73 -0
- package/dist/coding/registry/npm-plan.d.ts +29 -0
- package/dist/coding/registry/npm-plan.js +289 -0
- package/dist/coding/registry/npm.d.ts +7 -0
- package/dist/coding/registry/npm.js +252 -0
- package/dist/coding/registry/pypi.d.ts +4 -0
- package/dist/coding/registry/pypi.js +210 -0
- package/dist/coding/registry/report.d.ts +37 -0
- package/dist/coding/registry/report.js +31 -0
- package/dist/coding/registry/token.d.ts +4 -0
- package/dist/coding/registry/token.js +7 -0
- package/dist/coding/registry/types.d.ts +286 -0
- package/dist/coding/registry/types.js +19 -0
- package/dist/coding/registry/worker-config.d.ts +14 -0
- package/dist/coding/registry/worker-config.js +31 -0
- package/dist/coding/services/builtins.d.ts +22 -0
- package/dist/coding/services/builtins.js +85 -0
- package/dist/coding/services/catalog.d.ts +443 -0
- package/dist/coding/services/catalog.js +159 -0
- package/dist/coding/services/declaration.d.ts +11 -0
- package/dist/coding/services/declaration.js +114 -0
- package/dist/coding/services/note.d.ts +8 -0
- package/dist/coding/services/note.js +15 -0
- package/dist/coding/services/resolve.d.ts +25 -0
- package/dist/coding/services/resolve.js +50 -0
- package/dist/coding/services/wording.d.ts +25 -0
- package/dist/coding/services/wording.js +70 -0
- package/dist/coding-proxy/main.js +24 -4
- package/dist/coding-worker/artifact.d.ts +6 -0
- package/dist/coding-worker/debug-trace.d.ts +37 -0
- package/dist/coding-worker/debug-trace.js +117 -0
- package/dist/coding-worker/driver.d.ts +13 -1
- package/dist/coding-worker/driver.js +102 -13
- package/dist/coding-worker/errors.js +8 -0
- package/dist/coding-worker/main.js +10 -2
- package/dist/coding-worker/sdk.d.ts +2 -2
- package/dist/coding-worker/sdk.js +7 -2
- package/dist/coding-worker/types.d.ts +3 -0
- package/dist/config/providers.d.ts +41 -0
- package/dist/config/providers.js +66 -0
- package/dist/core/budget-groups.d.ts +108 -5
- package/dist/core/budget-groups.js +125 -19
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +5 -1
- package/dist/core/db.js +8 -2
- package/dist/core/dispatch.d.ts +33 -6
- package/dist/core/dispatch.js +260 -43
- package/dist/core/engine-native.js +27 -10
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +49 -0
- package/dist/core/host-events.js +257 -0
- package/dist/core/host-identity-links.d.ts +54 -0
- package/dist/core/host-identity-links.js +189 -0
- package/dist/core/host-status.d.ts +61 -0
- package/dist/core/host-status.js +211 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +38 -2
- package/dist/core/reconciler.js +86 -2
- package/dist/core/repo-access.d.ts +99 -0
- package/dist/core/repo-access.js +136 -0
- package/dist/core/review-host-checks.d.ts +11 -0
- package/dist/core/review-host-checks.js +41 -0
- package/dist/core/review-host-tools.d.ts +47 -0
- package/dist/core/review-host-tools.js +347 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/runner.d.ts +30 -8
- package/dist/core/runner.js +237 -40
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +1 -1
- package/dist/core/subagent-memory-tools.js +16 -3
- package/dist/core/tool-admin.d.ts +81 -0
- package/dist/core/tool-admin.js +129 -0
- package/dist/core/tool-names.d.ts +42 -0
- package/dist/core/tool-names.js +64 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +8 -1
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +100 -0
- package/dist/generated/prisma/client.d.ts +100 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
- package/dist/generated/prisma/enums.d.ts +6 -0
- package/dist/generated/prisma/enums.js +6 -1
- package/dist/generated/prisma/internal/class.d.ts +143 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
- package/dist/generated/prisma/models/Agent.d.ts +294 -1
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
- package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
- package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
- package/dist/generated/prisma/models/HostIdentity.js +1 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +455 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
- package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
- package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
- package/dist/generated/prisma/models/RegistryFetch.js +1 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
- package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
- package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
- package/dist/generated/prisma/models/ResourceGrant.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +389 -1
- package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
- package/dist/generated/prisma/models/RunHostCheck.js +1 -0
- package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
- package/dist/generated/prisma/models/RunHostStatus.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models.d.ts +13 -0
- package/dist/help/build.d.ts +1 -0
- package/dist/help/build.js +9 -0
- package/dist/help/catalog.d.ts +24 -0
- package/dist/help/catalog.js +160 -0
- package/dist/help/cli.d.ts +2 -0
- package/dist/help/cli.js +65 -0
- package/dist/help/runtime.d.ts +3 -0
- package/dist/help/runtime.js +44 -0
- package/dist/help/search.d.ts +9 -0
- package/dist/help/search.js +104 -0
- package/dist/help-index.json +660 -0
- package/dist/import/cli-args.js +3 -2
- package/dist/import/create.d.ts +5 -0
- package/dist/import/create.js +67 -13
- package/dist/import/index.js +19 -9
- package/dist/import/neutral-schema.d.ts +11 -11
- package/dist/mcp/auth/access.d.ts +70 -0
- package/dist/mcp/auth/access.js +58 -0
- package/dist/mcp/auth/grants-cli.d.ts +149 -0
- package/dist/mcp/auth/grants-cli.js +518 -0
- package/dist/mcp/auth/host-account-cli.d.ts +2 -0
- package/dist/mcp/auth/host-account-cli.js +47 -0
- package/dist/mcp/auth/ownership.d.ts +26 -52
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/repo-authorization.d.ts +22 -0
- package/dist/mcp/auth/repo-authorization.js +51 -0
- package/dist/mcp/auth/resource-server.d.ts +31 -2
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +2 -2
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
- package/dist/mcp/context.d.ts +27 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/github-ingress.d.ts +36 -0
- package/dist/mcp/host-events/github-ingress.js +92 -0
- package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
- package/dist/mcp/host-events/github-user-callback.js +50 -0
- package/dist/mcp/index.d.ts +8 -1
- package/dist/mcp/index.js +106 -16
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/tools/agents.js +446 -48
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +22 -15
- package/dist/mcp/tools/grants.d.ts +2 -0
- package/dist/mcp/tools/grants.js +239 -0
- package/dist/mcp/tools/help.d.ts +5 -0
- package/dist/mcp/tools/help.js +67 -0
- package/dist/mcp/tools/host-accounts.d.ts +2 -0
- package/dist/mcp/tools/host-accounts.js +114 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +181 -0
- package/dist/mcp/tools/runs.d.ts +6 -0
- package/dist/mcp/tools/runs.js +60 -6
- package/dist/mcp/tools/scheduling.js +3 -6
- package/dist/mcp/tools/secrets.js +18 -6
- package/dist/mcp/tools/services.d.ts +2 -0
- package/dist/mcp/tools/services.js +222 -0
- package/dist/mcp/tools/subagents.js +52 -16
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +201 -40
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +10 -0
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +2 -0
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +2 -1
- package/dist/providers/auth/self-hosted.js +16 -4
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
- package/dist/providers/coding-proxy/memory-ledger.js +21 -2
- package/dist/providers/coding-proxy/metering.d.ts +4 -0
- package/dist/providers/coding-proxy/metering.js +28 -2
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
- package/dist/providers/coding-proxy/proxy.d.ts +13 -0
- package/dist/providers/coding-proxy/proxy.js +479 -18
- package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
- package/dist/providers/coding-proxy/registry/audit.js +380 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
- package/dist/providers/coding-proxy/registry/plan.js +304 -0
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
- package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
- package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
- package/dist/providers/coding-proxy/registry/service.js +1137 -0
- package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
- package/dist/providers/coding-proxy/registry/store.js +70 -0
- package/dist/providers/coding-proxy/runtime.d.ts +17 -0
- package/dist/providers/coding-proxy/runtime.js +63 -0
- package/dist/providers/coding-proxy/secure-fetch.js +0 -1
- package/dist/providers/coding-proxy/server.d.ts +11 -0
- package/dist/providers/coding-proxy/server.js +163 -0
- package/dist/providers/coding-proxy/types.d.ts +15 -0
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +2 -2
- package/dist/providers/executor/composition.d.ts +3 -0
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +105 -3
- package/dist/providers/executor/container.js +296 -20
- package/dist/providers/executor/dbos.d.ts +2 -3
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +7 -0
- package/dist/providers/executor/routing.js +13 -0
- package/dist/providers/executor/types.d.ts +22 -0
- package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
- package/dist/providers/jobs/claude-tool-setup.js +50 -0
- package/dist/providers/jobs/collect-prune.d.ts +7 -0
- package/dist/providers/jobs/collect-prune.js +27 -0
- package/dist/providers/jobs/docker-isolation.d.ts +48 -3
- package/dist/providers/jobs/docker-isolation.js +213 -22
- package/dist/providers/jobs/docker-services.d.ts +35 -0
- package/dist/providers/jobs/docker-services.js +191 -0
- package/dist/providers/jobs/docker.d.ts +49 -2
- package/dist/providers/jobs/docker.js +279 -32
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
- package/dist/providers/jobs/kubernetes-isolation.js +238 -57
- package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
- package/dist/providers/jobs/kubernetes-platform.js +11 -5
- package/dist/providers/jobs/kubernetes-preflight.js +3 -0
- package/dist/providers/jobs/kubernetes.d.ts +21 -2
- package/dist/providers/jobs/kubernetes.js +112 -21
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.js +6 -2
- package/dist/providers/llm/bedrock.js +2 -1
- package/dist/providers/llm/claude-messages.d.ts +5 -1
- package/dist/providers/llm/claude-messages.js +1 -0
- package/dist/providers/llm/claude-provider.d.ts +3 -1
- package/dist/providers/llm/claude-provider.js +5 -1
- package/dist/providers/llm/index.d.ts +1 -1
- package/dist/providers/llm/index.js +1 -1
- package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
- package/dist/providers/llm/pricing-anthropic.js +32 -14
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
- package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
- package/dist/providers/llm/routing.d.ts +10 -1
- package/dist/providers/llm/routing.js +18 -0
- package/dist/providers/llm/types.d.ts +12 -0
- package/dist/providers/llm/types.js +8 -1
- package/dist/providers/review-host/diff-lines.d.ts +16 -0
- package/dist/providers/review-host/diff-lines.js +59 -0
- package/dist/providers/review-host/github-events.d.ts +6 -0
- package/dist/providers/review-host/github-events.js +180 -0
- package/dist/providers/review-host/github-user-auth.d.ts +38 -0
- package/dist/providers/review-host/github-user-auth.js +128 -0
- package/dist/providers/review-host/github.d.ts +57 -0
- package/dist/providers/review-host/github.js +567 -0
- package/dist/providers/review-host/index.d.ts +12 -0
- package/dist/providers/review-host/index.js +30 -0
- package/dist/providers/review-host/review-format.d.ts +19 -0
- package/dist/providers/review-host/review-format.js +59 -0
- package/dist/providers/review-host/types.d.ts +284 -0
- package/dist/providers/review-host/types.js +24 -0
- package/dist/providers/vcs/git.d.ts +16 -6
- package/dist/providers/vcs/git.js +77 -13
- package/dist/providers/vcs/github.d.ts +74 -3
- package/dist/providers/vcs/github.js +195 -15
- package/dist/providers/vcs/types.d.ts +42 -4
- package/dist/quickstart/index.js +13 -2
- package/dist/sandbox/fetch-policy.d.ts +20 -2
- package/dist/sandbox/fetch-policy.js +64 -3
- package/dist/sandbox/host-functions.d.ts +9 -1
- package/dist/sandbox/host-functions.js +12 -5
- package/dist/serve.js +1 -1
- package/dist/wardby-bin.js +6 -0
- package/docs/README.md +30 -0
- package/docs/architecture-runtime.md +90 -0
- package/docs/assets/brand/wardby-icon-512.png +0 -0
- package/docs/assets/brand/wardby-icon.svg +16 -0
- package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
- package/docs/assets/brand/wardby-mascot.png +0 -0
- package/docs/assets/brand/wardby-mascot.svg +5 -0
- package/docs/assets/wardby-workflow.svg +106 -0
- package/docs/code-review-agents.md +481 -0
- package/docs/coding-agent-setup.md +172 -0
- package/docs/coding-packages.md +455 -0
- package/docs/coding-services.md +300 -0
- package/docs/coding-worker-byo-images.md +98 -0
- package/docs/coding-worker-isolation.md +1061 -0
- package/docs/getting-started-gke.md +615 -0
- package/docs/getting-started-identity-provider.md +308 -0
- package/docs/getting-started.md +133 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +657 -0
- package/help/code-review-agents.md +31 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/creating-agents.md +68 -0
- package/help/deploy-gke.md +39 -0
- package/help/deployment-targets.md +39 -0
- package/help/errors/budget-group-exhausted.md +25 -0
- package/help/errors/docker-isolation-unsupported.md +26 -0
- package/help/errors/protected-path.md +45 -0
- package/help/errors/repo-access.md +27 -0
- package/help/errors/service-declaration-invalid.md +27 -0
- package/help/errors/service-declaration-unavailable.md +25 -0
- package/help/errors/service-launcher-unsupported.md +30 -0
- package/help/errors/service-not-allowed.md +27 -0
- package/help/errors/service-unknown.md +23 -0
- package/help/errors/service-unready.md +49 -0
- package/help/getting-started.md +31 -0
- package/help/github.md +30 -0
- package/help/identity-and-access.md +39 -0
- package/help/mcp.md +30 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +30 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +26 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +12 -3
- package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
- package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
- package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
- package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
- package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
- package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
- package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
- package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
- package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
- package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
- package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
- package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
- package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
- package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
- package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
- package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
- package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
- package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
- package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
- package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
- package/prisma/schema.prisma +407 -21
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { loadCodingConcurrencyConfig } from "../config/providers.js";
|
|
1
2
|
import { logger } from "./logger.js";
|
|
3
|
+
import { HEARTBEAT_TIMEOUT_MS, RECONCILE_INTERVAL_MS } from "./timing.js";
|
|
2
4
|
const budgetGroupLog = logger.child({ module: "budget-groups" });
|
|
3
5
|
/**
|
|
4
6
|
* Calendar-aligned UTC period start. "week" is the ISO week: Monday 00:00
|
|
@@ -20,6 +22,44 @@ export function periodStart(period, now) {
|
|
|
20
22
|
function toNullableNumber(value) {
|
|
21
23
|
return value === null || value === undefined ? null : Number(value);
|
|
22
24
|
}
|
|
25
|
+
const IN_FLIGHT = new Set(["pending", "running"]);
|
|
26
|
+
/**
|
|
27
|
+
* How long a run's last heartbeat keeps its hold alive: the reconciler's
|
|
28
|
+
* heartbeat timeout plus one reconcile interval, so a managed run is reaped
|
|
29
|
+
* (or re-claimed, which refreshes heartbeatAt) before its hold lapses.
|
|
30
|
+
* Managed native runs beat every HEARTBEAT_INTERVAL_MS (InProcessExecutor,
|
|
31
|
+
* DbosExecutor), as do `wardby run` and native sub-agent children
|
|
32
|
+
* (withRunHeartbeat); a coding run beats while its job is polled.
|
|
33
|
+
*/
|
|
34
|
+
export const HOLD_HEARTBEAT_TTL_MS = HEARTBEAT_TIMEOUT_MS + RECONCILE_INTERVAL_MS;
|
|
35
|
+
/** Slack past a coding run's queue + run timeout before its hold lapses (matches the sub-agent wait grace). */
|
|
36
|
+
export const CODING_HOLD_GRACE_SEC = 60;
|
|
37
|
+
/** Smallest amount worth holding or reserving: CodingRun.budgetReservedUsd has 6 decimal places. */
|
|
38
|
+
export const MIN_RESERVATION_USD = 0.000001;
|
|
39
|
+
/**
|
|
40
|
+
* Whether an in-flight row still holds budget. A run holds while its last
|
|
41
|
+
* sign of life (heartbeatAt, or startedAt before its first beat) is within
|
|
42
|
+
* HOLD_HEARTBEAT_TTL_MS. A coding run also holds, beat or not, until its
|
|
43
|
+
* queue timeout + run timeout + grace have passed since dispatch: a queued
|
|
44
|
+
* coding run does not beat, and nothing can legitimately spend past that.
|
|
45
|
+
*/
|
|
46
|
+
export function isHoldLive(run, now, codingQueueTimeoutSec) {
|
|
47
|
+
if (!IN_FLIGHT.has(run.status))
|
|
48
|
+
return false;
|
|
49
|
+
const lastSign = (run.heartbeatAt ?? run.startedAt).getTime();
|
|
50
|
+
if (now.getTime() - lastSign <= HOLD_HEARTBEAT_TTL_MS)
|
|
51
|
+
return true;
|
|
52
|
+
if (run.codingRun) {
|
|
53
|
+
const deadlineMs = run.startedAt.getTime() + (codingQueueTimeoutSec + run.codingRun.timeoutSec + CODING_HOLD_GRACE_SEC) * 1000;
|
|
54
|
+
return now.getTime() <= deadlineMs;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
function isOrderedBefore(run, other) {
|
|
59
|
+
const a = run.startedAt.getTime();
|
|
60
|
+
const b = other.startedAt.getTime();
|
|
61
|
+
return a < b || (a === b && run.id < other.id);
|
|
62
|
+
}
|
|
23
63
|
/**
|
|
24
64
|
* Live per-period spend for whichever of a group's daily/weekly/monthly
|
|
25
65
|
* caps are actually set -- unset periods are omitted from the result, not
|
|
@@ -27,7 +67,7 @@ function toNullableNumber(value) {
|
|
|
27
67
|
* (month contains week contains day), bucketed in JS, rather than a
|
|
28
68
|
* separate DB round trip per period.
|
|
29
69
|
*/
|
|
30
|
-
export async function computeGroupSpend(db, group,
|
|
70
|
+
export async function computeGroupSpend(db, group, members, now = new Date(), options = {}) {
|
|
31
71
|
const caps = [
|
|
32
72
|
{ period: "day", capUsd: toNullableNumber(group.dailyBudgetUsd) },
|
|
33
73
|
{ period: "week", capUsd: toNullableNumber(group.weeklyBudgetUsd) },
|
|
@@ -42,28 +82,56 @@ export async function computeGroupSpend(db, group, memberAgentIds, now = new Dat
|
|
|
42
82
|
// query itself as a cheap no-op; an empty `agentId: { in: [] }` would
|
|
43
83
|
// match nothing anyway.
|
|
44
84
|
const widestStart = periodStart("month", now);
|
|
45
|
-
const
|
|
85
|
+
const memberBudgets = new Map(members.map((m) => [m.id, Number(m.budgetUsd)]));
|
|
86
|
+
const excluded = new Set(options.excludeReservationRunIds ?? []);
|
|
87
|
+
const queueTimeoutSec = options.codingQueueTimeoutSec ?? loadCodingConcurrencyConfig().queueTimeoutSec;
|
|
88
|
+
const runs = members.length === 0
|
|
46
89
|
? []
|
|
47
90
|
: await db.run.findMany({
|
|
48
|
-
where: { agentId: { in:
|
|
49
|
-
select: {
|
|
91
|
+
where: { agentId: { in: [...memberBudgets.keys()] }, startedAt: { gte: widestStart } },
|
|
92
|
+
select: {
|
|
93
|
+
id: true,
|
|
94
|
+
agentId: true,
|
|
95
|
+
status: true,
|
|
96
|
+
costUsd: true,
|
|
97
|
+
startedAt: true,
|
|
98
|
+
heartbeatAt: true,
|
|
99
|
+
codingRun: { select: { budgetReservedUsd: true, timeoutSec: true } },
|
|
100
|
+
},
|
|
50
101
|
});
|
|
102
|
+
const accounted = runs.map((r) => {
|
|
103
|
+
const costUsd = Number(r.costUsd);
|
|
104
|
+
let reservedUsd = 0;
|
|
105
|
+
const holds = !excluded.has(r.id) &&
|
|
106
|
+
(options.holdsBefore === undefined || isOrderedBefore(r, options.holdsBefore)) &&
|
|
107
|
+
isHoldLive(r, now, queueTimeoutSec);
|
|
108
|
+
if (holds) {
|
|
109
|
+
// A coding run holds exactly what dispatch reserved. A native run (or
|
|
110
|
+
// a coding run whose CodingRun row is missing) holds its agent's
|
|
111
|
+
// per-run budget: never less than what it can actually spend.
|
|
112
|
+
const reservation = r.codingRun != null ? Number(r.codingRun.budgetReservedUsd) : (memberBudgets.get(r.agentId) ?? 0);
|
|
113
|
+
reservedUsd = Math.max(0, reservation - costUsd);
|
|
114
|
+
}
|
|
115
|
+
return { startedAt: r.startedAt, costUsd, reservedUsd };
|
|
116
|
+
});
|
|
51
117
|
return configured.map(({ period, capUsd }) => {
|
|
52
118
|
const start = periodStart(period, now);
|
|
53
|
-
const
|
|
54
|
-
|
|
119
|
+
const inPeriod = accounted.filter((r) => r.startedAt >= start);
|
|
120
|
+
const spentUsd = inPeriod.reduce((sum, r) => sum + r.costUsd, 0);
|
|
121
|
+
const reservedUsd = inPeriod.reduce((sum, r) => sum + r.reservedUsd, 0);
|
|
122
|
+
return { period, capUsd, spentUsd, reservedUsd, remainingUsd: Math.max(0, capUsd - spentUsd - reservedUsd) };
|
|
55
123
|
});
|
|
56
124
|
}
|
|
57
125
|
/** Walks parentRunId upward from `runId` to the tree's root (parentRunId null). */
|
|
58
126
|
async function findRootRun(db, runId) {
|
|
59
127
|
let current = await db.run.findUniqueOrThrow({
|
|
60
128
|
where: { id: runId },
|
|
61
|
-
select: { id: true, agentId: true, parentRunId: true },
|
|
129
|
+
select: { id: true, agentId: true, parentRunId: true, startedAt: true },
|
|
62
130
|
});
|
|
63
131
|
while (current.parentRunId) {
|
|
64
132
|
current = await db.run.findUniqueOrThrow({
|
|
65
133
|
where: { id: current.parentRunId },
|
|
66
|
-
select: { id: true, agentId: true, parentRunId: true },
|
|
134
|
+
select: { id: true, agentId: true, parentRunId: true, startedAt: true },
|
|
67
135
|
});
|
|
68
136
|
}
|
|
69
137
|
return current;
|
|
@@ -88,9 +156,17 @@ async function collectTreeRunIds(db, rootRunId) {
|
|
|
88
156
|
* spent so far. The root's ceiling is recomputed fresh here, not pinned
|
|
89
157
|
* from whatever it was when the root run started — consistent with
|
|
90
158
|
* BudgetGroup periods already always being live-recomputed rather than
|
|
91
|
-
* snapshotted.
|
|
159
|
+
* snapshotted. That group check sees the group as the root did when it
|
|
160
|
+
* loaded: the tree's own holds are left out (the tree spends inside the
|
|
161
|
+
* root's hold, so counting it again would leave the tree nothing), and so
|
|
162
|
+
* are holds of runs that started after the root (they already counted the
|
|
163
|
+
* root's hold).
|
|
92
164
|
*/
|
|
93
165
|
export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
|
|
166
|
+
const { rootRunId, capUsd, spentUsd, remainingUsd } = await runTreeSpend(db, parentRunId, now);
|
|
167
|
+
return { rootRunId, capUsd, spentUsd, remainingUsd };
|
|
168
|
+
}
|
|
169
|
+
async function runTreeSpend(db, parentRunId, now) {
|
|
94
170
|
const root = await findRootRun(db, parentRunId);
|
|
95
171
|
const treeRunIds = await collectTreeRunIds(db, root.id);
|
|
96
172
|
const rows = await db.run.findMany({ where: { id: { in: treeRunIds } }, select: { costUsd: true } });
|
|
@@ -99,11 +175,23 @@ export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
|
|
|
99
175
|
where: { id: root.agentId },
|
|
100
176
|
select: { id: true, budgetGroupId: true, budgetUsd: true },
|
|
101
177
|
});
|
|
178
|
+
const rootOrder = { id: root.id, startedAt: root.startedAt };
|
|
102
179
|
// Root has no parentRunId of its own, so this terminates in one level —
|
|
103
180
|
// no unbounded recursion regardless of how deep `parentRunId` itself was.
|
|
104
|
-
const rootCeiling = await
|
|
181
|
+
const rootCeiling = await groupCappedBudget(db, rootAgent, now, {
|
|
182
|
+
excludeReservationRunIds: treeRunIds,
|
|
183
|
+
holdsBefore: rootOrder,
|
|
184
|
+
});
|
|
105
185
|
const capUsd = rootCeiling.effectiveBudgetUsd;
|
|
106
|
-
return {
|
|
186
|
+
return {
|
|
187
|
+
rootRunId: root.id,
|
|
188
|
+
capUsd,
|
|
189
|
+
spentUsd,
|
|
190
|
+
remainingUsd: Math.max(0, capUsd - spentUsd),
|
|
191
|
+
treeRunIds,
|
|
192
|
+
root: rootOrder,
|
|
193
|
+
rootBudgetGroupId: rootAgent.budgetGroupId,
|
|
194
|
+
};
|
|
107
195
|
}
|
|
108
196
|
/**
|
|
109
197
|
* The per-run budget ceiling to actually use for `agent`: its own
|
|
@@ -116,17 +204,35 @@ export async function computeRunTreeSpend(db, parentRunId, now = new Date()) {
|
|
|
116
204
|
* with no caps configured is returned unchanged. Also logs a warning
|
|
117
205
|
* (never blocks, never throws) once a period's spend crosses the group's
|
|
118
206
|
* own warnThresholdRatio.
|
|
207
|
+
*
|
|
208
|
+
* A sub-agent in the root's own budget group spends inside the root's hold,
|
|
209
|
+
* so its group check is the root's: the tree's holds and the holds of runs
|
|
210
|
+
* after the root are left out. A sub-agent in any other group is an
|
|
211
|
+
* ordinary member of that group and counts every earlier live hold there,
|
|
212
|
+
* the tree's included.
|
|
119
213
|
*/
|
|
120
|
-
export async function effectiveBudgetForRun(db, agent, now = new Date(), parentRunId) {
|
|
214
|
+
export async function effectiveBudgetForRun(db, agent, now = new Date(), parentRunId, options = {}) {
|
|
215
|
+
const self = options.self;
|
|
216
|
+
const ownSpend = { excludeReservationRunIds: self ? [self.id] : [], holdsBefore: self };
|
|
217
|
+
if (!parentRunId)
|
|
218
|
+
return groupCappedBudget(db, agent, now, ownSpend);
|
|
219
|
+
const tree = await runTreeSpend(db, parentRunId, now);
|
|
220
|
+
const sharesRootGroup = agent.budgetGroupId !== null && agent.budgetGroupId === tree.rootBudgetGroupId;
|
|
221
|
+
const spend = sharesRootGroup
|
|
222
|
+
? { excludeReservationRunIds: [...tree.treeRunIds, ...(self ? [self.id] : [])], holdsBefore: tree.root }
|
|
223
|
+
: ownSpend;
|
|
224
|
+
return groupCappedBudget(db, agent, now, spend, { value: tree.remainingUsd, reason: "run-tree" });
|
|
225
|
+
}
|
|
226
|
+
async function groupCappedBudget(db, agent, now, spendOptions, extra) {
|
|
121
227
|
const ownBudgetUsd = Number(agent.budgetUsd);
|
|
122
228
|
const candidates = [];
|
|
123
229
|
if (agent.budgetGroupId) {
|
|
124
230
|
const group = await db.budgetGroup.findUnique({
|
|
125
231
|
where: { id: agent.budgetGroupId },
|
|
126
|
-
include: { agents: { select: { id: true } } },
|
|
232
|
+
include: { agents: { select: { id: true, budgetUsd: true } } },
|
|
127
233
|
});
|
|
128
234
|
if (group) {
|
|
129
|
-
const spend = await computeGroupSpend(db, group, group.agents
|
|
235
|
+
const spend = await computeGroupSpend(db, group, group.agents, now, spendOptions);
|
|
130
236
|
const warnThresholdRatio = Number(group.warnThresholdRatio);
|
|
131
237
|
for (const s of spend) {
|
|
132
238
|
candidates.push({ value: s.remainingUsd, reason: s.period });
|
|
@@ -137,13 +243,13 @@ export async function effectiveBudgetForRun(db, agent, now = new Date(), parentR
|
|
|
137
243
|
}
|
|
138
244
|
}
|
|
139
245
|
}
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
candidates.push({ value: tree.remainingUsd, reason: "run-tree" });
|
|
143
|
-
}
|
|
246
|
+
if (extra)
|
|
247
|
+
candidates.push(extra);
|
|
144
248
|
if (candidates.length === 0)
|
|
145
249
|
return { effectiveBudgetUsd: ownBudgetUsd, constrainedBy: [] };
|
|
146
250
|
const constrainedBy = candidates.filter((c) => c.value < ownBudgetUsd).map((c) => c.reason);
|
|
147
251
|
const effectiveBudgetUsd = Math.min(ownBudgetUsd, ...candidates.map((c) => c.value));
|
|
148
|
-
|
|
252
|
+
// Less than the smallest reservable amount is nothing left.
|
|
253
|
+
const exhausted = candidates.find((c) => c.value < MIN_RESERVATION_USD);
|
|
254
|
+
return { effectiveBudgetUsd, constrainedBy, ...(exhausted ? { exhaustedBy: exhausted.reason } : {}) };
|
|
149
255
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one sentence a host (a PR comment, a check summary) is told when a run
|
|
3
|
+
* ran out of budget, or could not start for lack of it. Public repositories
|
|
4
|
+
* read these, so it names amounts and the budget group only: never error
|
|
5
|
+
* text, token counts, or ids.
|
|
6
|
+
*/
|
|
7
|
+
import type { PrismaClient } from "#prisma";
|
|
8
|
+
export interface BudgetFacts {
|
|
9
|
+
/** The run's own budget (a coding run's reservation); falls back to the agent's. */
|
|
10
|
+
runBudgetUsd?: number | null;
|
|
11
|
+
agentBudgetUsd: number;
|
|
12
|
+
budgetGroupName?: string | null;
|
|
13
|
+
/** The run was refused before it started. */
|
|
14
|
+
refused?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function budgetSentence(facts: BudgetFacts): string;
|
|
17
|
+
/**
|
|
18
|
+
* The sentence for a finished run, read from the database: a coding run's
|
|
19
|
+
* reserved budget, otherwise the agent's. Falls back to a sentence without
|
|
20
|
+
* amounts when they cannot be read. Never throws.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadBudgetSentence(db: Pick<PrismaClient, "run">, runId: string, status: string): Promise<string>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const MAX_GROUP_NAME_CHARS = 64;
|
|
2
|
+
const usd = (amount) => `$${amount.toFixed(2)}`;
|
|
3
|
+
/** A group name is operator-chosen text; keep it to one short, quote-free line. */
|
|
4
|
+
function groupName(name) {
|
|
5
|
+
const cleaned = (name ?? "").replace(/["`]/g, "").replace(/\s+/g, " ").trim().slice(0, MAX_GROUP_NAME_CHARS);
|
|
6
|
+
return cleaned || null;
|
|
7
|
+
}
|
|
8
|
+
export function budgetSentence(facts) {
|
|
9
|
+
const group = groupName(facts.budgetGroupName);
|
|
10
|
+
if (facts.refused) {
|
|
11
|
+
const within = `this run could not start within its ${usd(facts.runBudgetUsd ?? facts.agentBudgetUsd)} budget`;
|
|
12
|
+
return group
|
|
13
|
+
? `Out of budget: ${within} or what the "${group}" budget group had left of its limit.`
|
|
14
|
+
: `Out of budget: ${within}.`;
|
|
15
|
+
}
|
|
16
|
+
const runBudget = facts.runBudgetUsd ?? facts.agentBudgetUsd;
|
|
17
|
+
const used = `Out of budget: this run's ${usd(runBudget)} budget was used up`;
|
|
18
|
+
// A run reserved less than the agent's own budget: its group had only that much left.
|
|
19
|
+
if (group && runBudget < facts.agentBudgetUsd) {
|
|
20
|
+
return `${used} (the "${group}" budget group had only that much left of its limit).`;
|
|
21
|
+
}
|
|
22
|
+
return `${used}.`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The sentence for a finished run, read from the database: a coding run's
|
|
26
|
+
* reserved budget, otherwise the agent's. Falls back to a sentence without
|
|
27
|
+
* amounts when they cannot be read. Never throws.
|
|
28
|
+
*/
|
|
29
|
+
export async function loadBudgetSentence(db, runId, status) {
|
|
30
|
+
const refused = status === "refused";
|
|
31
|
+
try {
|
|
32
|
+
const row = await db.run.findUnique({
|
|
33
|
+
where: { id: runId },
|
|
34
|
+
select: {
|
|
35
|
+
agent: { select: { budgetUsd: true, budgetGroup: { select: { name: true } } } },
|
|
36
|
+
codingRun: { select: { budgetReservedUsd: true } },
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
const agentBudgetUsd = Number(row?.agent?.budgetUsd);
|
|
40
|
+
if (!row?.agent || !Number.isFinite(agentBudgetUsd))
|
|
41
|
+
throw new Error("budget_facts_unavailable");
|
|
42
|
+
const reserved = row.codingRun ? Number(row.codingRun.budgetReservedUsd) : NaN;
|
|
43
|
+
return budgetSentence({
|
|
44
|
+
runBudgetUsd: Number.isFinite(reserved) ? reserved : null,
|
|
45
|
+
agentBudgetUsd,
|
|
46
|
+
budgetGroupName: row.agent.budgetGroup?.name ?? null,
|
|
47
|
+
refused,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return refused
|
|
52
|
+
? "Out of budget: this run could not start within its budget."
|
|
53
|
+
: "Out of budget: this run's budget was used up.";
|
|
54
|
+
}
|
|
55
|
+
}
|
package/dist/core/datastores.js
CHANGED
|
@@ -25,9 +25,25 @@ export async function attachDatastore(agentId, datastoreId, db, boundName) {
|
|
|
25
25
|
export async function detachDatastore(agentId, boundName, db) {
|
|
26
26
|
await db.agentDatastore.deleteMany({ where: { agentId, boundName } });
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Owner rule (resource-sharing grants spec §3.4.1): a binding resolves only
|
|
30
|
+
* while the datastore's owner is the agent's CURRENT owner, both non-null.
|
|
31
|
+
* A cross-owner binding (written before that rule, or left behind by
|
|
32
|
+
* make_owner) and every binding on an owner-less agent resolve like an
|
|
33
|
+
* unattached boundName, so one owner's store never reaches another owner's
|
|
34
|
+
* agent (A2/S2-2, R2-1).
|
|
35
|
+
*/
|
|
28
36
|
async function resolveDatastoreId(agentId, boundName, db) {
|
|
29
|
-
const attachment = await db.agentDatastore.findFirst({
|
|
30
|
-
|
|
37
|
+
const attachment = await db.agentDatastore.findFirst({
|
|
38
|
+
where: { agentId, boundName },
|
|
39
|
+
include: { datastore: { select: { ownerId: true } }, agent: { select: { ownerId: true } } },
|
|
40
|
+
});
|
|
41
|
+
if (!attachment)
|
|
42
|
+
return undefined;
|
|
43
|
+
const owner = attachment.agent.ownerId;
|
|
44
|
+
if (owner === null || attachment.datastore.ownerId !== owner)
|
|
45
|
+
return undefined;
|
|
46
|
+
return attachment.datastoreId;
|
|
31
47
|
}
|
|
32
48
|
/**
|
|
33
49
|
* Resolves `boundName` to the Datastore attached to this agent under that
|
package/dist/core/db.d.ts
CHANGED
|
@@ -32,5 +32,9 @@ export declare function poolSettings(connectionString: string): PoolSettings;
|
|
|
32
32
|
* The one way wardby builds a Prisma client. `url` defaults to DATABASE_URL
|
|
33
33
|
* as read at call time.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
/** `poolMax` overrides the pool size for a caller that sizes its own pools
|
|
36
|
+
* (the coding proxy keeps its ledger and its package registry apart). */
|
|
37
|
+
export declare function createPrismaClient(url?: string | undefined, options?: {
|
|
38
|
+
poolMax?: number;
|
|
39
|
+
}): PrismaClient;
|
|
36
40
|
export declare const prisma: PrismaClient;
|
package/dist/core/db.js
CHANGED
|
@@ -60,9 +60,15 @@ class MissingUrlAdapter extends PrismaPg {
|
|
|
60
60
|
* The one way wardby builds a Prisma client. `url` defaults to DATABASE_URL
|
|
61
61
|
* as read at call time.
|
|
62
62
|
*/
|
|
63
|
-
|
|
63
|
+
/** `poolMax` overrides the pool size for a caller that sizes its own pools
|
|
64
|
+
* (the coding proxy keeps its ledger and its package registry apart). */
|
|
65
|
+
export function createPrismaClient(url = process.env.DATABASE_URL, options = {}) {
|
|
64
66
|
const adapter = url
|
|
65
|
-
? new PrismaPg({
|
|
67
|
+
? new PrismaPg({
|
|
68
|
+
connectionString: url,
|
|
69
|
+
...poolSettings(url),
|
|
70
|
+
...(options.poolMax !== undefined ? { max: options.poolMax } : {}),
|
|
71
|
+
})
|
|
66
72
|
: new MissingUrlAdapter({ connectionString: "" });
|
|
67
73
|
return new PrismaClient({ adapter });
|
|
68
74
|
}
|
package/dist/core/dispatch.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Prisma, PrismaClient, Run, RunTrigger, Task } from "#prisma";
|
|
2
2
|
import type { Executor } from "../providers/executor/types.js";
|
|
3
|
-
|
|
4
|
-
type
|
|
3
|
+
import { type BudgetConstraint } from "./budget-groups.js";
|
|
4
|
+
export type DispatchDb = Pick<PrismaClient, "agent" | "run" | "runHostCheck" | "codingRun" | "task" | "webhook" | "budgetGroup" | "$transaction" | "$queryRaw">;
|
|
5
|
+
export type DispatchTx = Pick<Prisma.TransactionClient, "agent" | "run" | "runHostCheck" | "runHostStatus" | "codingRun" | "codingService" | "task" | "webhook" | "budgetGroup" | "resourceGrant" | "$queryRaw" | "$executeRawUnsafe">;
|
|
5
6
|
type DispatchAgent = Prisma.AgentGetPayload<{
|
|
6
7
|
include: {
|
|
7
8
|
codingProfile: true;
|
|
@@ -32,6 +33,19 @@ export interface DispatchRunOptions {
|
|
|
32
33
|
ttlMs: number;
|
|
33
34
|
};
|
|
34
35
|
beforePersist?: (tx: DispatchTx, agent: DispatchAgent) => Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Runs inside the persist transaction right after the run row is created,
|
|
38
|
+
* before the executor is started — for rows that must exist before the run
|
|
39
|
+
* can observe them (e.g. RunHostCheck, see core/host-events.ts).
|
|
40
|
+
*/
|
|
41
|
+
afterPersist?: (tx: DispatchTx, run: Run) => Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Who the run is visible to besides the agent owner (Run.triggeredById,
|
|
44
|
+
* resource-sharing grants spec §3.5): the trigger_agent caller, a
|
|
45
|
+
* webhook's creator, a sub-agent's parent triggerer. Omit/null for
|
|
46
|
+
* scheduled and host-event runs, which only the owner sees.
|
|
47
|
+
*/
|
|
48
|
+
triggeredById?: string | null;
|
|
35
49
|
/** Sub-agent dispatch (see AgentSubAgent): links this run into a run tree. */
|
|
36
50
|
parentRunId?: string;
|
|
37
51
|
grantedParentMemoryKeys?: string[];
|
|
@@ -42,10 +56,10 @@ export interface DispatchRunOptions {
|
|
|
42
56
|
*/
|
|
43
57
|
taskOverride?: string;
|
|
44
58
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* budget
|
|
48
|
-
*
|
|
59
|
+
* Replaces `agent.budgetUsd` as the requested ceiling for this run's coding
|
|
60
|
+
* budget reservation. The reservation is still tightened by the agent's
|
|
61
|
+
* budget group and, with `parentRunId`, the run tree (see
|
|
62
|
+
* src/core/budget-groups.ts), computed inside the persist transaction.
|
|
49
63
|
* Ignored for native agents, which compute their own effective budget
|
|
50
64
|
* inside executeRun's load step.
|
|
51
65
|
*/
|
|
@@ -87,6 +101,19 @@ export declare function isSerializationConflict(err: unknown): boolean;
|
|
|
87
101
|
* than overwrite whatever landed in between.
|
|
88
102
|
*/
|
|
89
103
|
export declare function markRunFailedFromExecutorError(db: Pick<DispatchDb, "run">, runId: string, err: unknown): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* The `Run.error` of a coding run refused at dispatch because a budget
|
|
106
|
+
* constraint has nothing left: `budget_group_exhausted:<period>` or
|
|
107
|
+
* `run_tree_exhausted`, then a sentence for people.
|
|
108
|
+
*/
|
|
109
|
+
export declare function budgetExhaustedError(constraint: BudgetConstraint): string;
|
|
110
|
+
/**
|
|
111
|
+
* Attempts for the persist transaction, and the jittered backoff between
|
|
112
|
+
* them, for serialization failures and deadlocks.
|
|
113
|
+
*
|
|
114
|
+
* @internal Exported only for the real-PostgreSQL tests.
|
|
115
|
+
*/
|
|
116
|
+
export declare const PERSIST_ATTEMPTS = 8;
|
|
90
117
|
/**
|
|
91
118
|
* Persists every detached run input in one transaction, then invokes the
|
|
92
119
|
* executor only after commit. A null result means the caller's transactional
|