@wardby/cli 0.2.1 → 0.4.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 +53 -4
- package/README.md +52 -13
- 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 +14 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +284 -36
- package/dist/coding/base-commit.d.ts +6 -0
- package/dist/coding/base-commit.js +12 -0
- 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 +91 -4
- package/dist/coding/protocol.js +123 -12
- package/dist/coding/provider.d.ts +6 -1
- package/dist/coding/provider.js +16 -9
- 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 +66 -0
- package/dist/config/providers.js +137 -0
- package/dist/core/attribution.d.ts +101 -0
- package/dist/core/attribution.js +208 -0
- package/dist/core/budget-groups.d.ts +120 -10
- package/dist/core/budget-groups.js +133 -24
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/coding-queue.d.ts +3 -0
- package/dist/core/coding-queue.js +6 -2
- package/dist/core/coding-service-status.d.ts +11 -0
- package/dist/core/coding-service-status.js +17 -0
- package/dist/core/cost-report.d.ts +88 -0
- package/dist/core/cost-report.js +248 -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 +74 -7
- package/dist/core/dispatch.js +382 -47
- package/dist/core/engine-native.js +44 -14
- package/dist/core/glob.d.ts +10 -0
- package/dist/core/glob.js +33 -0
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +72 -0
- package/dist/core/host-events.js +597 -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 +78 -0
- package/dist/core/host-status.js +228 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/issue-bridge.d.ts +60 -0
- package/dist/core/issue-bridge.js +189 -0
- package/dist/core/issue-dedupe.d.ts +70 -0
- package/dist/core/issue-dedupe.js +255 -0
- package/dist/core/issue-events.d.ts +42 -0
- package/dist/core/issue-events.js +155 -0
- package/dist/core/issue-status.d.ts +29 -0
- package/dist/core/issue-status.js +241 -0
- package/dist/core/issue-tracker-tools.d.ts +64 -0
- package/dist/core/issue-tracker-tools.js +850 -0
- package/dist/core/model-usage.d.ts +10 -0
- package/dist/core/model-usage.js +24 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +42 -2
- package/dist/core/reconciler.js +97 -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 +354 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/run-pricing.d.ts +61 -0
- package/dist/core/run-pricing.js +56 -0
- package/dist/core/runner.d.ts +33 -8
- package/dist/core/runner.js +410 -62
- package/dist/core/scheduler.d.ts +4 -1
- package/dist/core/scheduler.js +3 -2
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/self-defects.d.ts +80 -0
- package/dist/core/self-defects.js +180 -0
- 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 +67 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +17 -2
- package/dist/core/webhooks.js +42 -3
- package/dist/generated/prisma/browser.d.ts +166 -0
- package/dist/generated/prisma/client.d.ts +166 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +152 -52
- package/dist/generated/prisma/enums.d.ts +13 -0
- package/dist/generated/prisma/enums.js +12 -1
- package/dist/generated/prisma/internal/class.d.ts +242 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +2571 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +312 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +328 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +312 -6
- package/dist/generated/prisma/models/Agent.d.ts +682 -1
- package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
- package/dist/generated/prisma/models/AgentIssueProject.js +1 -0
- 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 +195 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1405 -95
- package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
- package/dist/generated/prisma/models/CodingRunServiceStatus.js +1 -0
- 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/IssueFingerprint.d.ts +1183 -0
- package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
- package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
- package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
- package/dist/generated/prisma/models/ModelCatalogEntry.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 +1402 -82
- package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
- package/dist/generated/prisma/models/RunAttribution.js +1 -0
- 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/RunIssueStatus.d.ts +1199 -0
- package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
- package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
- package/dist/generated/prisma/models/RunModelUsage.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
- package/dist/generated/prisma/models/WorkItem.js +1 -0
- package/dist/generated/prisma/models.d.ts +22 -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 +999 -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 +18 -18
- package/dist/knowledge/check.d.ts +13 -0
- package/dist/knowledge/check.js +69 -0
- package/dist/knowledge/cli.d.ts +14 -0
- package/dist/knowledge/cli.js +67 -0
- package/dist/knowledge/concept.d.ts +54 -0
- package/dist/knowledge/concept.js +78 -0
- package/dist/knowledge/note.d.ts +11 -0
- package/dist/knowledge/note.js +39 -0
- package/dist/knowledge/relevance.d.ts +11 -0
- package/dist/knowledge/relevance.js +14 -0
- package/dist/knowledge/span-hash.d.ts +3 -0
- package/dist/knowledge/span-hash.js +16 -0
- package/dist/mcp/auth/access.d.ts +72 -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 +25 -51
- 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 +33 -2
- package/dist/mcp/auth/resource-server.js +99 -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 +23 -5
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +7 -6
- package/dist/mcp/context.d.ts +30 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/deliveries.d.ts +9 -0
- package/dist/mcp/host-events/deliveries.js +17 -0
- package/dist/mcp/host-events/github-ingress.d.ts +38 -0
- package/dist/mcp/host-events/github-ingress.js +83 -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/host-events/jira-ingress.d.ts +29 -0
- package/dist/mcp/host-events/jira-ingress.js +92 -0
- package/dist/mcp/index.d.ts +10 -1
- package/dist/mcp/index.js +187 -19
- package/dist/mcp/server.js +32 -11
- package/dist/mcp/tools/agents.js +519 -50
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/cost-report.d.ts +8 -0
- package/dist/mcp/tools/cost-report.js +60 -0
- 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/issue-projects.d.ts +2 -0
- package/dist/mcp/tools/issue-projects.js +238 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/model-catalog.d.ts +22 -0
- package/dist/mcp/tools/model-catalog.js +423 -0
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +182 -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 +65 -7
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +15 -0
- package/dist/mcp/transport/streamable-http.js +55 -3
- package/dist/mcp/webhooks/ingress.d.ts +2 -1
- package/dist/mcp/webhooks/ingress.js +9 -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 +10 -2
- package/dist/providers/auth/self-hosted.js +55 -6
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +4 -1
- package/dist/providers/coding-proxy/memory-ledger.js +31 -3
- package/dist/providers/coding-proxy/metering.d.ts +6 -1
- package/dist/providers/coding-proxy/metering.js +41 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +106 -8
- package/dist/providers/coding-proxy/proxy.d.ts +25 -2
- package/dist/providers/coding-proxy/proxy.js +561 -38
- 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 +33 -1
- package/dist/providers/coding-proxy/types.js +12 -1
- package/dist/providers/engine/types.d.ts +29 -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 +28 -1
- package/dist/providers/executor/container.d.ts +134 -4
- package/dist/providers/executor/container.js +394 -37
- package/dist/providers/executor/dbos.d.ts +4 -3
- package/dist/providers/executor/dbos.js +7 -5
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +13 -0
- package/dist/providers/executor/routing.js +18 -0
- package/dist/providers/executor/types.d.ts +34 -0
- package/dist/providers/issue-tracker/adf.d.ts +31 -0
- package/dist/providers/issue-tracker/adf.js +181 -0
- package/dist/providers/issue-tracker/index.d.ts +5 -0
- package/dist/providers/issue-tracker/index.js +12 -0
- package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
- package/dist/providers/issue-tracker/jira-client.js +151 -0
- package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
- package/dist/providers/issue-tracker/jira-events.js +98 -0
- package/dist/providers/issue-tracker/jira.d.ts +116 -0
- package/dist/providers/issue-tracker/jira.js +502 -0
- package/dist/providers/issue-tracker/types.d.ts +269 -0
- package/dist/providers/issue-tracker/types.js +16 -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 +53 -2
- package/dist/providers/jobs/docker.js +307 -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 +24 -2
- package/dist/providers/jobs/kubernetes.js +153 -22
- package/dist/providers/jobs/service-state.d.ts +22 -0
- package/dist/providers/jobs/service-state.js +17 -0
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.d.ts +3 -3
- package/dist/providers/llm/anthropic.js +3 -5
- package/dist/providers/llm/bedrock.d.ts +3 -3
- package/dist/providers/llm/bedrock.js +3 -8
- package/dist/providers/llm/catalog-lookup.d.ts +10 -0
- package/dist/providers/llm/catalog-lookup.js +15 -0
- package/dist/providers/llm/catalog-shipped.d.ts +18 -0
- package/dist/providers/llm/catalog-shipped.js +197 -0
- package/dist/providers/llm/catalog-store.d.ts +58 -0
- package/dist/providers/llm/catalog-store.js +138 -0
- package/dist/providers/llm/catalog-types.d.ts +66 -0
- package/dist/providers/llm/catalog-types.js +64 -0
- package/dist/providers/llm/catalog.d.ts +61 -0
- package/dist/providers/llm/catalog.js +147 -0
- 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 +10 -12
- package/dist/providers/llm/claude-provider.js +15 -6
- package/dist/providers/llm/index.d.ts +9 -6
- package/dist/providers/llm/index.js +8 -5
- package/dist/providers/llm/openai.d.ts +14 -5
- package/dist/providers/llm/openai.js +24 -14
- package/dist/providers/llm/pricing-core.d.ts +5 -3
- package/dist/providers/llm/registration.js +8 -12
- package/dist/providers/llm/routing.d.ts +21 -11
- package/dist/providers/llm/routing.js +47 -13
- 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 +226 -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 +568 -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 +309 -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 +78 -34
- package/dist/providers/vcs/github.d.ts +94 -3
- package/dist/providers/vcs/github.js +223 -17
- package/dist/providers/vcs/types.d.ts +48 -4
- package/dist/quickstart/index.d.ts +2 -0
- package/dist/quickstart/index.js +36 -8
- 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 +8 -2
- package/dist/viewer/api-schema.d.ts +2757 -0
- package/dist/viewer/api-schema.js +165 -0
- package/dist/viewer/build-schemas.d.ts +2 -0
- package/dist/viewer/build-schemas.js +18 -0
- package/dist/viewer/event-bus.d.ts +38 -0
- package/dist/viewer/event-bus.js +232 -0
- package/dist/viewer/graph.d.ts +40 -0
- package/dist/viewer/graph.js +243 -0
- package/dist/viewer/http.d.ts +30 -0
- package/dist/viewer/http.js +133 -0
- package/dist/viewer/run-detail.d.ts +4 -0
- package/dist/viewer/run-detail.js +61 -0
- package/dist/wardby-bin.js +11 -0
- package/docs/README.md +40 -0
- package/docs/agent-recipes.md +383 -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 +508 -0
- package/docs/coding-agent-setup.md +175 -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 +1068 -0
- package/docs/getting-started-gke.md +632 -0
- package/docs/getting-started-identity-provider.md +319 -0
- package/docs/getting-started.md +147 -0
- package/docs/jira-agents.md +649 -0
- package/docs/knowledge.md +387 -0
- package/docs/models.md +221 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +667 -0
- package/docs/viewer-api.md +142 -0
- package/help/admin-viewer.md +39 -0
- package/help/agent-recipes.md +173 -0
- package/help/architecture-agent.md +189 -0
- package/help/builder-agent.md +80 -0
- package/help/code-review-agents.md +37 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/cost-attribution.md +67 -0
- package/help/creating-agents.md +90 -0
- package/help/deploy-gke.md +45 -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/model-unavailable.md +63 -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 +32 -0
- package/help/github.md +48 -0
- package/help/identity-and-access.md +44 -0
- package/help/jira.md +135 -0
- package/help/knowledge.md +47 -0
- package/help/mcp.md +30 -0
- package/help/models.md +90 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +36 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +32 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +14 -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/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
- package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
- package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
- package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
- package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
- package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
- package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
- package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
- package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
- package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
- package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
- package/prisma/schema.prisma +663 -21
- package/dist/mcp/tools/models.d.ts +0 -8
- package/dist/mcp/tools/models.js +0 -15
- package/dist/providers/llm/pricing-anthropic.d.ts +0 -4
- package/dist/providers/llm/pricing-anthropic.js +0 -30
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -12
- package/dist/providers/llm/pricing-bedrock-claude.js +0 -37
- package/dist/providers/llm/pricing.d.ts +0 -30
- package/dist/providers/llm/pricing.js +0 -74
|
@@ -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
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { PrismaClient } from "#prisma";
|
|
18
18
|
import type { Executor } from "../providers/executor/types.js";
|
|
19
|
+
import { type SelfDefectSink } from "./self-defects.js";
|
|
19
20
|
export declare const CODING_QUEUE_TIMEOUT_ERROR = "coding_queue_timeout";
|
|
20
21
|
export type CodingQueueDb = Pick<PrismaClient, "run" | "codingRun" | "$transaction">;
|
|
21
22
|
export interface DrainCodingQueueOptions {
|
|
@@ -24,6 +25,8 @@ export interface DrainCodingQueueOptions {
|
|
|
24
25
|
maxConcurrent: number;
|
|
25
26
|
queueTimeoutSec: number;
|
|
26
27
|
now?: () => Date;
|
|
28
|
+
/** Files a self-defect for each run this drain fails (queue timeout or start failure). Optional. */
|
|
29
|
+
selfDefects?: SelfDefectSink;
|
|
27
30
|
}
|
|
28
31
|
export interface DrainCodingQueueResult {
|
|
29
32
|
timedOut: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { markRunFailedFromExecutorError } from "./dispatch.js";
|
|
2
2
|
import { logger } from "./logger.js";
|
|
3
|
+
import { fileSelfDefectForRun } from "./self-defects.js";
|
|
3
4
|
const queueLog = logger.child({ module: "coding-queue" });
|
|
4
5
|
export const CODING_QUEUE_TIMEOUT_ERROR = "coding_queue_timeout";
|
|
5
6
|
export async function drainCodingQueue(options) {
|
|
@@ -25,8 +26,11 @@ export async function drainCodingQueue(options) {
|
|
|
25
26
|
await tx.codingRun.update({ where: { runId }, data: { failureCategory: CODING_QUEUE_TIMEOUT_ERROR } });
|
|
26
27
|
return true;
|
|
27
28
|
});
|
|
28
|
-
if (didTimeOut)
|
|
29
|
+
if (didTimeOut) {
|
|
29
30
|
timedOut += 1;
|
|
31
|
+
// Only this drain made the row failed (a concurrent drain matched zero rows); bounded, never throws.
|
|
32
|
+
await fileSelfDefectForRun(options.selfDefects, runId);
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
const active = await db.codingRun.count({
|
|
32
36
|
where: { jobBackend: { not: null }, run: { status: { in: ["pending", "running"] } } },
|
|
@@ -48,7 +52,7 @@ export async function drainCodingQueue(options) {
|
|
|
48
52
|
// drainCodingQueue's own call stack.
|
|
49
53
|
void Promise.resolve()
|
|
50
54
|
.then(() => executor.start(runId))
|
|
51
|
-
.catch((err) => markRunFailedFromExecutorError(db, runId, err).catch((err2) => queueLog.error({ err: err2, runId }, "failed to persist queued-run start failure")));
|
|
55
|
+
.catch((err) => markRunFailedFromExecutorError(db, runId, err, options.selfDefects).catch((err2) => queueLog.error({ err: err2, runId }, "failed to persist queued-run start failure")));
|
|
52
56
|
}
|
|
53
57
|
return { timedOut, started: next.map((row) => row.runId) };
|
|
54
58
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persists launcher-observed coding-run service states (CodingRunServiceStatus, one row per
|
|
3
|
+
* run x service) for the viewer. Composed into the job launchers by
|
|
4
|
+
* providers/executor/composition.ts; launchers call it through reportServiceState, which drops
|
|
5
|
+
* its errors.
|
|
6
|
+
*/
|
|
7
|
+
import type { PrismaClient } from "#prisma";
|
|
8
|
+
import type { ServiceStateReporter } from "../providers/jobs/service-state.js";
|
|
9
|
+
type ServiceStatusDb = Pick<PrismaClient, "codingRunServiceStatus">;
|
|
10
|
+
export declare function prismaServiceStateReporter(db: ServiceStatusDb, now?: () => Date): ServiceStateReporter;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function prismaServiceStateReporter(db, now = () => new Date()) {
|
|
2
|
+
return async ({ runId, name, state, attempts, reason }) => {
|
|
3
|
+
const at = now();
|
|
4
|
+
const data = {
|
|
5
|
+
state,
|
|
6
|
+
attempts: attempts ?? null,
|
|
7
|
+
reason: reason ?? null,
|
|
8
|
+
readyAt: state === "ready" ? at : null,
|
|
9
|
+
failedAt: state === "failed" ? at : null,
|
|
10
|
+
};
|
|
11
|
+
await db.codingRunServiceStatus.upsert({
|
|
12
|
+
where: { runId_name: { runId, name } },
|
|
13
|
+
create: { runId, name, ...data },
|
|
14
|
+
update: data,
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost by issue / parent / scope / agent / model / run over a time window
|
|
3
|
+
* (docs/private/2026-10-01-issue-cost-attribution-design.md §7). Rows count
|
|
4
|
+
* attributed runs only; unattributed spend is reported separately so the gap
|
|
5
|
+
* is visible. Money is summed as NUMERIC in SQL and returned as strings; tokens
|
|
6
|
+
* are always by priced kind, never one total.
|
|
7
|
+
*/
|
|
8
|
+
import { type PrismaClient } from "#prisma";
|
|
9
|
+
export type CostGroupBy = "issue" | "parent" | "scope" | "agent" | "model" | "run";
|
|
10
|
+
export declare class CostReportInputError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export interface CostReportQuery {
|
|
14
|
+
groupBy: CostGroupBy;
|
|
15
|
+
from: Date;
|
|
16
|
+
to: Date;
|
|
17
|
+
provider?: string;
|
|
18
|
+
scopeKey?: string;
|
|
19
|
+
parentKey?: string;
|
|
20
|
+
issueKey?: string;
|
|
21
|
+
agentId?: string;
|
|
22
|
+
limit: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function parseCostReportQuery(raw: unknown, now?: Date): CostReportQuery;
|
|
25
|
+
/** Which runs the caller may count: null = all (stdio operator). */
|
|
26
|
+
export interface CostVisibility {
|
|
27
|
+
ownedAgentIds: string[];
|
|
28
|
+
principalId: string;
|
|
29
|
+
}
|
|
30
|
+
export interface TokenKinds {
|
|
31
|
+
freshInput: number;
|
|
32
|
+
cachedInput: number;
|
|
33
|
+
cacheWrite: number;
|
|
34
|
+
output: number;
|
|
35
|
+
}
|
|
36
|
+
export interface CostRow {
|
|
37
|
+
key: string;
|
|
38
|
+
title: string | null;
|
|
39
|
+
kind: string | null;
|
|
40
|
+
provider: string | null;
|
|
41
|
+
runs: number;
|
|
42
|
+
inProgressRuns: number;
|
|
43
|
+
costUsd: string;
|
|
44
|
+
tokens: TokenKinds;
|
|
45
|
+
byModel: Array<{
|
|
46
|
+
model: string;
|
|
47
|
+
costUsd: string;
|
|
48
|
+
tokens: TokenKinds;
|
|
49
|
+
}>;
|
|
50
|
+
bySource: {
|
|
51
|
+
issue_event: string;
|
|
52
|
+
linked_pr: string;
|
|
53
|
+
explicit: string;
|
|
54
|
+
inherited: string;
|
|
55
|
+
};
|
|
56
|
+
firstRunAt: string;
|
|
57
|
+
lastRunAt: string;
|
|
58
|
+
}
|
|
59
|
+
export interface CostReport {
|
|
60
|
+
currency: "USD";
|
|
61
|
+
groupBy: CostGroupBy;
|
|
62
|
+
from: string;
|
|
63
|
+
to: string;
|
|
64
|
+
rows: CostRow[];
|
|
65
|
+
truncated: boolean;
|
|
66
|
+
totals: {
|
|
67
|
+
runs: number;
|
|
68
|
+
costUsd: string;
|
|
69
|
+
tokens: TokenKinds;
|
|
70
|
+
};
|
|
71
|
+
unattributed: {
|
|
72
|
+
runs: number;
|
|
73
|
+
costUsd: string;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* How long one report may take. Prisma's interactive-transaction default (5 s)
|
|
78
|
+
* is too short for a wide window over a large Run table; the same limit is set
|
|
79
|
+
* as the transaction's statement_timeout so Postgres stops the work too, not
|
|
80
|
+
* only the client.
|
|
81
|
+
*/
|
|
82
|
+
export declare const COST_REPORT_TIMEOUT_MS = 30000;
|
|
83
|
+
/**
|
|
84
|
+
* Every query runs in one read-only REPEATABLE READ transaction, so the rows,
|
|
85
|
+
* the totals and the unattributed figure all come from the same snapshot even
|
|
86
|
+
* while runs are finishing.
|
|
87
|
+
*/
|
|
88
|
+
export declare function costReport(db: Pick<PrismaClient, "$queryRaw" | "$transaction">, q: CostReportQuery, visibility: CostVisibility | null): Promise<CostReport>;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost by issue / parent / scope / agent / model / run over a time window
|
|
3
|
+
* (docs/private/2026-10-01-issue-cost-attribution-design.md §7). Rows count
|
|
4
|
+
* attributed runs only; unattributed spend is reported separately so the gap
|
|
5
|
+
* is visible. Money is summed as NUMERIC in SQL and returned as strings; tokens
|
|
6
|
+
* are always by priced kind, never one total.
|
|
7
|
+
*/
|
|
8
|
+
import { Prisma } from "#prisma";
|
|
9
|
+
const GROUP_BYS = ["issue", "parent", "scope", "agent", "model", "run"];
|
|
10
|
+
const DEFAULT_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;
|
|
11
|
+
const DEFAULT_LIMIT = 25;
|
|
12
|
+
const MAX_LIMIT = 200;
|
|
13
|
+
export class CostReportInputError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "CostReportInputError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function optionalString(args, name) {
|
|
20
|
+
const v = args[name];
|
|
21
|
+
if (v === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof v !== "string" || v.length === 0 || v.length > 256) {
|
|
24
|
+
throw new CostReportInputError(`${name} must be a non-empty string.`);
|
|
25
|
+
}
|
|
26
|
+
return v;
|
|
27
|
+
}
|
|
28
|
+
function optionalDate(args, name) {
|
|
29
|
+
const v = args[name];
|
|
30
|
+
if (v === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const d = typeof v === "string" ? new Date(v) : new Date(NaN);
|
|
33
|
+
if (Number.isNaN(d.getTime()))
|
|
34
|
+
throw new CostReportInputError(`${name} must be an ISO date.`);
|
|
35
|
+
return d;
|
|
36
|
+
}
|
|
37
|
+
export function parseCostReportQuery(raw, now = new Date()) {
|
|
38
|
+
const args = raw && typeof raw === "object" ? raw : {};
|
|
39
|
+
const groupBy = (args.groupBy ?? "issue");
|
|
40
|
+
if (!GROUP_BYS.includes(groupBy)) {
|
|
41
|
+
throw new CostReportInputError(`groupBy must be one of: ${GROUP_BYS.join(", ")}.`);
|
|
42
|
+
}
|
|
43
|
+
const to = optionalDate(args, "to") ?? now;
|
|
44
|
+
const from = optionalDate(args, "from") ?? new Date(to.getTime() - DEFAULT_WINDOW_MS);
|
|
45
|
+
if (from.getTime() >= to.getTime())
|
|
46
|
+
throw new CostReportInputError("from must be before to.");
|
|
47
|
+
let limit = DEFAULT_LIMIT;
|
|
48
|
+
if (args.limit !== undefined) {
|
|
49
|
+
if (typeof args.limit !== "number" || !Number.isInteger(args.limit) || args.limit < 1) {
|
|
50
|
+
throw new CostReportInputError("limit must be a positive integer.");
|
|
51
|
+
}
|
|
52
|
+
limit = Math.min(args.limit, MAX_LIMIT);
|
|
53
|
+
}
|
|
54
|
+
const q = { groupBy, from, to, limit };
|
|
55
|
+
for (const name of ["provider", "scopeKey", "parentKey", "issueKey", "agentId"]) {
|
|
56
|
+
const v = optionalString(args, name);
|
|
57
|
+
if (v !== undefined)
|
|
58
|
+
q[name] = v;
|
|
59
|
+
}
|
|
60
|
+
return q;
|
|
61
|
+
}
|
|
62
|
+
const NO_PARENT = "(no parent)";
|
|
63
|
+
/** NUMERIC text → canonical decimal string without trailing zeros ("3.100000" → "3.1", null → "0"). */
|
|
64
|
+
function usd(v) {
|
|
65
|
+
if (v == null)
|
|
66
|
+
return "0";
|
|
67
|
+
return v.includes(".") ? v.replace(/0+$/, "").replace(/\.$/, "") : v;
|
|
68
|
+
}
|
|
69
|
+
const kinds = (r) => ({
|
|
70
|
+
freshInput: Number(r?.fresh ?? 0),
|
|
71
|
+
cachedInput: Number(r?.cached ?? 0),
|
|
72
|
+
cacheWrite: Number(r?.write ?? 0),
|
|
73
|
+
output: Number(r?.out ?? 0),
|
|
74
|
+
});
|
|
75
|
+
/** The run filter every query shares: window, visibility, and the agent filter. Only `r` must be in scope. */
|
|
76
|
+
function runFilter(q, vis) {
|
|
77
|
+
const parts = [Prisma.sql `r."startedAt" >= ${q.from} AND r."startedAt" < ${q.to}`];
|
|
78
|
+
if (vis) {
|
|
79
|
+
parts.push(vis.ownedAgentIds.length > 0
|
|
80
|
+
? Prisma.sql `(r."agentId" IN (${Prisma.join(vis.ownedAgentIds)}) OR r."triggeredById" = ${vis.principalId})`
|
|
81
|
+
: Prisma.sql `r."triggeredById" = ${vis.principalId}`);
|
|
82
|
+
}
|
|
83
|
+
if (q.agentId)
|
|
84
|
+
parts.push(Prisma.sql `r."agentId" = ${q.agentId}`);
|
|
85
|
+
return Prisma.join(parts, " AND ");
|
|
86
|
+
}
|
|
87
|
+
/** The work-item filters; `a` (RunAttribution) and `w` (WorkItem) must be joined. */
|
|
88
|
+
function attributionFilter(q) {
|
|
89
|
+
const parts = [Prisma.sql `TRUE`];
|
|
90
|
+
if (q.provider)
|
|
91
|
+
parts.push(Prisma.sql `w."provider" = ${q.provider}`);
|
|
92
|
+
if (q.scopeKey)
|
|
93
|
+
parts.push(Prisma.sql `w."scopeKey" = ${q.scopeKey}`);
|
|
94
|
+
if (q.parentKey)
|
|
95
|
+
parts.push(Prisma.sql `a."parentKeyAtRun" = ${q.parentKey}`);
|
|
96
|
+
if (q.issueKey)
|
|
97
|
+
parts.push(Prisma.sql `w."key" = ${q.issueKey}`);
|
|
98
|
+
return Prisma.join(parts, " AND ");
|
|
99
|
+
}
|
|
100
|
+
/** The group key for each groupBy, over Run r / RunAttribution a / WorkItem w (and RunModelUsage u for "model"). */
|
|
101
|
+
const GROUP_KEY = {
|
|
102
|
+
issue: Prisma.sql `w."key"`,
|
|
103
|
+
parent: Prisma.sql `COALESCE(a."parentKeyAtRun", '(no parent)')`,
|
|
104
|
+
scope: Prisma.sql `w."scopeKey"`,
|
|
105
|
+
agent: Prisma.sql `r."agentId"`,
|
|
106
|
+
model: Prisma.sql `u."model"`,
|
|
107
|
+
run: Prisma.sql `r."id"`,
|
|
108
|
+
};
|
|
109
|
+
const ATTRIBUTED = Prisma.sql `"Run" r JOIN "RunAttribution" a ON a."runId" = r."id" JOIN "WorkItem" w ON w."id" = a."workItemId"`;
|
|
110
|
+
const USAGE_ATTRIBUTED = Prisma.sql `"RunModelUsage" u JOIN ${ATTRIBUTED} ON r."id" = u."runId"`;
|
|
111
|
+
/**
|
|
112
|
+
* How long one report may take. Prisma's interactive-transaction default (5 s)
|
|
113
|
+
* is too short for a wide window over a large Run table; the same limit is set
|
|
114
|
+
* as the transaction's statement_timeout so Postgres stops the work too, not
|
|
115
|
+
* only the client.
|
|
116
|
+
*/
|
|
117
|
+
export const COST_REPORT_TIMEOUT_MS = 30_000;
|
|
118
|
+
/**
|
|
119
|
+
* Every query runs in one read-only REPEATABLE READ transaction, so the rows,
|
|
120
|
+
* the totals and the unattributed figure all come from the same snapshot even
|
|
121
|
+
* while runs are finishing.
|
|
122
|
+
*/
|
|
123
|
+
export async function costReport(db, q, visibility) {
|
|
124
|
+
return db.$transaction(async (tx) => {
|
|
125
|
+
await tx.$executeRaw `SET TRANSACTION READ ONLY`;
|
|
126
|
+
// SET takes no bind parameters; the value is a constant.
|
|
127
|
+
await tx.$executeRawUnsafe(`SET LOCAL statement_timeout = '${COST_REPORT_TIMEOUT_MS}ms'`);
|
|
128
|
+
return reportIn(tx, q, visibility);
|
|
129
|
+
}, { isolationLevel: "RepeatableRead", timeout: COST_REPORT_TIMEOUT_MS });
|
|
130
|
+
}
|
|
131
|
+
async function reportIn(db, q, visibility) {
|
|
132
|
+
const where = Prisma.sql `${runFilter(q, visibility)} AND ${attributionFilter(q)}`;
|
|
133
|
+
const key = GROUP_KEY[q.groupBy];
|
|
134
|
+
// "model" groups usage rows, so its money comes from RunModelUsage; every other grouping sums Run.costUsd once per run.
|
|
135
|
+
const byModel = q.groupBy === "model";
|
|
136
|
+
const money = byModel ? Prisma.sql `u."costUsd"` : Prisma.sql `r."costUsd"`;
|
|
137
|
+
const source = byModel ? USAGE_ATTRIBUTED : ATTRIBUTED;
|
|
138
|
+
const groups = await db.$queryRaw `
|
|
139
|
+
SELECT ${key} AS key,
|
|
140
|
+
MIN(w."provider") AS provider,
|
|
141
|
+
MIN(w."parentKind") AS parent_kind,
|
|
142
|
+
COUNT(DISTINCT r."id") AS runs,
|
|
143
|
+
COUNT(DISTINCT r."id") FILTER (WHERE r."status" IN ('pending', 'running')) AS in_progress,
|
|
144
|
+
SUM(${money})::text AS usd,
|
|
145
|
+
SUM(${money}) FILTER (WHERE a."source" = 'issue_event')::text AS src_issue_event,
|
|
146
|
+
SUM(${money}) FILTER (WHERE a."source" = 'linked_pr')::text AS src_linked_pr,
|
|
147
|
+
SUM(${money}) FILTER (WHERE a."source" = 'explicit')::text AS src_explicit,
|
|
148
|
+
SUM(${money}) FILTER (WHERE a."source" = 'inherited')::text AS src_inherited,
|
|
149
|
+
MIN(r."startedAt") AS first_at,
|
|
150
|
+
MAX(r."startedAt") AS last_at
|
|
151
|
+
FROM ${source}
|
|
152
|
+
WHERE ${where}
|
|
153
|
+
GROUP BY ${key}
|
|
154
|
+
ORDER BY SUM(${money}) DESC NULLS LAST, ${key}
|
|
155
|
+
LIMIT ${q.limit + 1}`;
|
|
156
|
+
const truncated = groups.length > q.limit;
|
|
157
|
+
const page = groups.slice(0, q.limit);
|
|
158
|
+
// Per-group, per-model tokens and money for just this page's groups.
|
|
159
|
+
const usage = page.length
|
|
160
|
+
? await db.$queryRaw `
|
|
161
|
+
SELECT ${key} AS key, u."model" AS model, SUM(u."costUsd")::text AS usd,
|
|
162
|
+
SUM(u."freshInputTokens") AS fresh, SUM(u."cachedInputTokens") AS cached,
|
|
163
|
+
SUM(u."cacheWriteTokens") AS write, SUM(u."outputTokens") AS out
|
|
164
|
+
FROM ${USAGE_ATTRIBUTED}
|
|
165
|
+
WHERE ${where} AND ${key} IN (${Prisma.join(page.map((g) => g.key))})
|
|
166
|
+
GROUP BY ${key}, u."model"
|
|
167
|
+
ORDER BY SUM(u."costUsd") DESC, u."model"`
|
|
168
|
+
: [];
|
|
169
|
+
const titles = await groupTitles(db, q.groupBy, page);
|
|
170
|
+
const rows = page.map((g) => {
|
|
171
|
+
const models = usage
|
|
172
|
+
.filter((u) => u.key === g.key)
|
|
173
|
+
.map((m) => ({ model: m.model, costUsd: usd(m.usd), tokens: kinds(m) }));
|
|
174
|
+
const tokens = models.reduce((t, m) => ({
|
|
175
|
+
freshInput: t.freshInput + m.tokens.freshInput,
|
|
176
|
+
cachedInput: t.cachedInput + m.tokens.cachedInput,
|
|
177
|
+
cacheWrite: t.cacheWrite + m.tokens.cacheWrite,
|
|
178
|
+
output: t.output + m.tokens.output,
|
|
179
|
+
}), { freshInput: 0, cachedInput: 0, cacheWrite: 0, output: 0 });
|
|
180
|
+
return {
|
|
181
|
+
key: g.key,
|
|
182
|
+
...titles(g),
|
|
183
|
+
provider: g.provider,
|
|
184
|
+
runs: Number(g.runs),
|
|
185
|
+
inProgressRuns: Number(g.in_progress),
|
|
186
|
+
costUsd: usd(g.usd),
|
|
187
|
+
tokens,
|
|
188
|
+
byModel: models,
|
|
189
|
+
bySource: {
|
|
190
|
+
issue_event: usd(g.src_issue_event),
|
|
191
|
+
linked_pr: usd(g.src_linked_pr),
|
|
192
|
+
explicit: usd(g.src_explicit),
|
|
193
|
+
inherited: usd(g.src_inherited),
|
|
194
|
+
},
|
|
195
|
+
firstRunAt: g.first_at.toISOString(),
|
|
196
|
+
lastRunAt: g.last_at.toISOString(),
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
const [totals] = await db.$queryRaw `
|
|
200
|
+
SELECT COUNT(*) AS runs, SUM(r."costUsd")::text AS usd FROM ${ATTRIBUTED} WHERE ${where}`;
|
|
201
|
+
const [totalTokens] = await db.$queryRaw `
|
|
202
|
+
SELECT SUM(u."freshInputTokens") AS fresh, SUM(u."cachedInputTokens") AS cached,
|
|
203
|
+
SUM(u."cacheWriteTokens") AS write, SUM(u."outputTokens") AS out
|
|
204
|
+
FROM ${USAGE_ATTRIBUTED} WHERE ${where}`;
|
|
205
|
+
const [unattributed] = await db.$queryRaw `
|
|
206
|
+
SELECT COUNT(*) AS runs, SUM(r."costUsd")::text AS usd
|
|
207
|
+
FROM "Run" r
|
|
208
|
+
WHERE ${runFilter(q, visibility)}
|
|
209
|
+
AND NOT EXISTS (SELECT 1 FROM "RunAttribution" ra WHERE ra."runId" = r."id")`;
|
|
210
|
+
return {
|
|
211
|
+
currency: "USD",
|
|
212
|
+
groupBy: q.groupBy,
|
|
213
|
+
from: q.from.toISOString(),
|
|
214
|
+
to: q.to.toISOString(),
|
|
215
|
+
rows,
|
|
216
|
+
truncated,
|
|
217
|
+
totals: { runs: Number(totals?.runs ?? 0), costUsd: usd(totals?.usd), tokens: kinds(totalTokens) },
|
|
218
|
+
unattributed: { runs: Number(unattributed?.runs ?? 0), costUsd: usd(unattributed?.usd) },
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** Titles and kinds per group: current WorkItem names for issue/parent, agent names for agent; none otherwise. */
|
|
222
|
+
async function groupTitles(db, groupBy, page) {
|
|
223
|
+
const none = () => ({ title: null, kind: null });
|
|
224
|
+
if (page.length === 0)
|
|
225
|
+
return none;
|
|
226
|
+
if (groupBy === "issue" || groupBy === "parent") {
|
|
227
|
+
const keys = page.map((g) => g.key).filter((k) => k !== NO_PARENT);
|
|
228
|
+
if (keys.length === 0)
|
|
229
|
+
return none;
|
|
230
|
+
const items = await db.$queryRaw `
|
|
231
|
+
SELECT "provider", "key", "title", "type" FROM "WorkItem" WHERE "key" IN (${Prisma.join(keys)})`;
|
|
232
|
+
const byKey = new Map(items.map((i) => [`${i.provider}\u0000${i.key}`, i]));
|
|
233
|
+
return (g) => {
|
|
234
|
+
if (groupBy === "parent" && g.key === NO_PARENT)
|
|
235
|
+
return { title: null, kind: null };
|
|
236
|
+
const i = byKey.get(`${g.provider}\u0000${g.key}`);
|
|
237
|
+
// A parent's kind lives on its children (WorkItem.parentKind), selected in the group query.
|
|
238
|
+
return { title: i?.title ?? null, kind: groupBy === "parent" ? g.parent_kind : (i?.type ?? null) };
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
if (groupBy === "agent") {
|
|
242
|
+
const agents = await db.$queryRaw `
|
|
243
|
+
SELECT "id", "name" FROM "Agent" WHERE "id" IN (${Prisma.join(page.map((g) => g.key))})`;
|
|
244
|
+
const byId = new Map(agents.map((a) => [a.id, a.name]));
|
|
245
|
+
return (g) => ({ title: byId.get(g.key) ?? null, kind: "agent" });
|
|
246
|
+
}
|
|
247
|
+
return none;
|
|
248
|
+
}
|
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,10 @@
|
|
|
1
1
|
import type { Prisma, PrismaClient, Run, RunTrigger, Task } from "#prisma";
|
|
2
2
|
import type { Executor } from "../providers/executor/types.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { type AttributionIntent } from "./attribution.js";
|
|
4
|
+
import { type BudgetConstraint } from "./budget-groups.js";
|
|
5
|
+
import { type SelfDefectSink } from "./self-defects.js";
|
|
6
|
+
export type DispatchDb = Pick<PrismaClient, "agent" | "run" | "runHostCheck" | "codingRun" | "task" | "webhook" | "budgetGroup" | "$transaction" | "$queryRaw">;
|
|
7
|
+
export type DispatchTx = Pick<Prisma.TransactionClient, "agent" | "run" | "runHostCheck" | "runHostStatus" | "runIssueStatus" | "codingRun" | "codingService" | "task" | "webhook" | "budgetGroup" | "resourceGrant" | "workItem" | "runAttribution" | "$queryRaw" | "$executeRawUnsafe">;
|
|
5
8
|
type DispatchAgent = Prisma.AgentGetPayload<{
|
|
6
9
|
include: {
|
|
7
10
|
codingProfile: true;
|
|
@@ -32,8 +35,30 @@ export interface DispatchRunOptions {
|
|
|
32
35
|
ttlMs: number;
|
|
33
36
|
};
|
|
34
37
|
beforePersist?: (tx: DispatchTx, agent: DispatchAgent) => Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Runs inside the persist transaction right after the run row is created,
|
|
40
|
+
* before the executor is started — for rows that must exist before the run
|
|
41
|
+
* can observe them (e.g. RunHostCheck, see core/host-events.ts).
|
|
42
|
+
*/
|
|
43
|
+
afterPersist?: (tx: DispatchTx, run: Run) => Promise<void>;
|
|
44
|
+
/** Files a self-defect when the executor fails to start the run and this marks it failed. Optional. */
|
|
45
|
+
selfDefects?: SelfDefectSink;
|
|
46
|
+
/**
|
|
47
|
+
* Who the run is visible to besides the agent owner (Run.triggeredById,
|
|
48
|
+
* resource-sharing grants spec §3.5): the trigger_agent caller, a
|
|
49
|
+
* webhook's creator, a sub-agent's parent triggerer. Omit/null for
|
|
50
|
+
* scheduled and host-event runs, which only the owner sees.
|
|
51
|
+
*/
|
|
52
|
+
triggeredById?: string | null;
|
|
35
53
|
/** Sub-agent dispatch (see AgentSubAgent): links this run into a run tree. */
|
|
36
54
|
parentRunId?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Cost attribution for a run that starts a new attribution (issue event,
|
|
57
|
+
* linked PR, explicit key), resolved before the call (attribution.ts
|
|
58
|
+
* resolveWorkItem). Ignored when the parent run or the continued coding run
|
|
59
|
+
* is attributed: inheritance wins.
|
|
60
|
+
*/
|
|
61
|
+
attribution?: AttributionIntent;
|
|
37
62
|
grantedParentMemoryKeys?: string[];
|
|
38
63
|
/**
|
|
39
64
|
* Per-run task text for a NATIVE agent (appended to its systemPrompt at
|
|
@@ -42,10 +67,10 @@ export interface DispatchRunOptions {
|
|
|
42
67
|
*/
|
|
43
68
|
taskOverride?: string;
|
|
44
69
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* budget
|
|
48
|
-
*
|
|
70
|
+
* Replaces `agent.budgetUsd` as the requested ceiling for this run's coding
|
|
71
|
+
* budget reservation. The reservation is still tightened by the agent's
|
|
72
|
+
* budget group and, with `parentRunId`, the run tree (see
|
|
73
|
+
* src/core/budget-groups.ts), computed inside the persist transaction.
|
|
49
74
|
* Ignored for native agents, which compute their own effective budget
|
|
50
75
|
* inside executeRun's load step.
|
|
51
76
|
*/
|
|
@@ -74,6 +99,10 @@ export interface DispatchRunResult {
|
|
|
74
99
|
* (Prisma 7) -- Prisma 6's engine put 40001 at meta.code, still accepted;
|
|
75
100
|
* - at COMMIT (e.g. SSI write skew): an unwrapped DriverAdapterError, no
|
|
76
101
|
* code or meta, with the SQLSTATE at cause.originalCode.
|
|
102
|
+
* Also a unique violation (P2002) on WorkItem: concurrent first dispatches
|
|
103
|
+
* attributed to one new issue each insert its WorkItem, and Postgres reports
|
|
104
|
+
* the loser as 23505 rather than 40001. The retry finds the committed row.
|
|
105
|
+
* Unique violations on other models are real errors and are not retried.
|
|
77
106
|
*
|
|
78
107
|
* @internal Exported only for the real-PostgreSQL tests.
|
|
79
108
|
*/
|
|
@@ -86,7 +115,45 @@ export declare function isSerializationConflict(err: unknown): boolean;
|
|
|
86
115
|
* the conditional `updateMany` makes the second call match zero rows rather
|
|
87
116
|
* than overwrite whatever landed in between.
|
|
88
117
|
*/
|
|
89
|
-
export declare function markRunFailedFromExecutorError(db: Pick<DispatchDb, "run">, runId: string, err: unknown): Promise<void>;
|
|
118
|
+
export declare function markRunFailedFromExecutorError(db: Pick<DispatchDb, "run">, runId: string, err: unknown, selfDefects?: SelfDefectSink): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* The `Run.error` of a coding run refused at dispatch because a budget
|
|
121
|
+
* constraint has nothing left: `budget_group_exhausted:<period>` or
|
|
122
|
+
* `run_tree_exhausted`, then a sentence for people.
|
|
123
|
+
*/
|
|
124
|
+
export declare function budgetExhaustedError(constraint: BudgetConstraint): string;
|
|
125
|
+
/**
|
|
126
|
+
* Attempts for the persist transaction, and the jittered backoff between
|
|
127
|
+
* them, for serialization failures and deadlocks.
|
|
128
|
+
*
|
|
129
|
+
* @internal Exported only for the real-PostgreSQL tests.
|
|
130
|
+
*/
|
|
131
|
+
export declare const PERSIST_ATTEMPTS = 8;
|
|
132
|
+
export type ContinuationRefusal = "unknown_run" | "other_repository" | "no_pull_request";
|
|
133
|
+
/** A continuation refused because of the run it names. Its message is fixed text, safe to show the model. */
|
|
134
|
+
export declare class ContinuationRefusedError extends Error {
|
|
135
|
+
readonly reason: ContinuationRefusal;
|
|
136
|
+
constructor(reason: ContinuationRefusal);
|
|
137
|
+
}
|
|
138
|
+
export type ContinuationCheck = {
|
|
139
|
+
ok: true;
|
|
140
|
+
root: {
|
|
141
|
+
runId: string;
|
|
142
|
+
baseRef: string;
|
|
143
|
+
headRef: string;
|
|
144
|
+
pullRequestNumber: number;
|
|
145
|
+
};
|
|
146
|
+
} | {
|
|
147
|
+
ok: false;
|
|
148
|
+
reason: ContinuationRefusal;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Whether this deployment can continue coding run `runId` in `repository`: the
|
|
152
|
+
* run (or its root) is in this database, in that repository, and opened a pull
|
|
153
|
+
* request. A run id read from a pull request can name a run that another
|
|
154
|
+
* deployment sharing the same App made, so check before relying on one.
|
|
155
|
+
*/
|
|
156
|
+
export declare function checkContinuation(reader: Pick<DispatchTx, "codingRun">, runId: string, repository: string): Promise<ContinuationCheck>;
|
|
90
157
|
/**
|
|
91
158
|
* Persists every detached run input in one transaction, then invokes the
|
|
92
159
|
* executor only after commit. A null result means the caller's transactional
|