@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
package/dist/core/dispatch.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import { CODING_PROTOCOL_VERSION, CodingTaskInputSchema, normalizeGitHubRepository, publicCodingRunResult, composeCodingTask, } from "../coding/protocol.js";
|
|
2
|
-
import { assertCodingProviderModel } from "../coding/provider.js";
|
|
1
|
+
import { CODING_PROTOCOL_VERSION, CodingTaskInputSchema, normalizeGitHubRepository, normalizeGitRef, publicCodingRunResult, composeCodingTask, } from "../coding/protocol.js";
|
|
2
|
+
import { assertCodingProvider, assertCodingProviderModel } from "../coding/provider.js";
|
|
3
|
+
import { ModelUnavailableError, entryOf } from "../providers/llm/catalog-types.js";
|
|
4
|
+
import { parseAllowedServiceNames, workerServices } from "../coding/services/catalog.js";
|
|
5
|
+
import { MAX_SERVICE_DECLARATION_BYTES, ServiceDeclarationError, parseServiceDeclaration, } from "../coding/services/declaration.js";
|
|
6
|
+
import { servicesInstructionNote } from "../coding/services/note.js";
|
|
7
|
+
import { resolveRunServices } from "../coding/services/resolve.js";
|
|
8
|
+
import { DECLARATION_UNAVAILABLE_SENTENCE, LAUNCHER_UNSUPPORTED_SENTENCE, invalidDeclarationSentence, serviceRefusal, } from "../coding/services/wording.js";
|
|
9
|
+
import { attributeRun } from "./attribution.js";
|
|
10
|
+
import { effectiveBudgetForRun, MIN_RESERVATION_USD } from "./budget-groups.js";
|
|
11
|
+
import { DEFAULT_KNOWLEDGE_BUNDLE_PATH } from "../knowledge/concept.js";
|
|
12
|
+
import { KNOWLEDGE_INDEX_READ_MAX_BYTES, knowledgeSection } from "../knowledge/note.js";
|
|
3
13
|
import { logger } from "./logger.js";
|
|
14
|
+
import { CodingModelProviderMismatchError, resolveCodingEntry } from "./run-pricing.js";
|
|
15
|
+
import { fileSelfDefectForRun } from "./self-defects.js";
|
|
4
16
|
const dispatchLog = logger.child({ module: "dispatch" });
|
|
5
17
|
/** SQLSTATEs worth retrying the persist transaction for: serialization failure, deadlock. */
|
|
6
18
|
const RETRYABLE_SQLSTATES = new Set(["40001", "40P01"]);
|
|
@@ -15,6 +27,10 @@ const RETRYABLE_SQLSTATES = new Set(["40001", "40P01"]);
|
|
|
15
27
|
* (Prisma 7) -- Prisma 6's engine put 40001 at meta.code, still accepted;
|
|
16
28
|
* - at COMMIT (e.g. SSI write skew): an unwrapped DriverAdapterError, no
|
|
17
29
|
* code or meta, with the SQLSTATE at cause.originalCode.
|
|
30
|
+
* Also a unique violation (P2002) on WorkItem: concurrent first dispatches
|
|
31
|
+
* attributed to one new issue each insert its WorkItem, and Postgres reports
|
|
32
|
+
* the loser as 23505 rather than 40001. The retry finds the committed row.
|
|
33
|
+
* Unique violations on other models are real errors and are not retried.
|
|
18
34
|
*
|
|
19
35
|
* @internal Exported only for the real-PostgreSQL tests.
|
|
20
36
|
*/
|
|
@@ -24,6 +40,8 @@ export function isSerializationConflict(err) {
|
|
|
24
40
|
const candidate = err;
|
|
25
41
|
if (candidate.code === "P2034")
|
|
26
42
|
return true;
|
|
43
|
+
if (candidate.code === "P2002")
|
|
44
|
+
return candidate.meta?.modelName === "WorkItem";
|
|
27
45
|
if (candidate.code === "P2010") {
|
|
28
46
|
const sqlState = candidate.meta?.driverAdapterError?.cause?.originalCode;
|
|
29
47
|
return (typeof sqlState === "string" && RETRYABLE_SQLSTATES.has(sqlState)) || candidate.meta?.code === "40001";
|
|
@@ -42,8 +60,8 @@ export function isSerializationConflict(err) {
|
|
|
42
60
|
* the conditional `updateMany` makes the second call match zero rows rather
|
|
43
61
|
* than overwrite whatever landed in between.
|
|
44
62
|
*/
|
|
45
|
-
export async function markRunFailedFromExecutorError(db, runId, err) {
|
|
46
|
-
await db.run.updateMany({
|
|
63
|
+
export async function markRunFailedFromExecutorError(db, runId, err, selfDefects) {
|
|
64
|
+
const updated = await db.run.updateMany({
|
|
47
65
|
where: { id: runId, status: { in: ["pending", "running"] } },
|
|
48
66
|
data: {
|
|
49
67
|
status: "failed",
|
|
@@ -51,6 +69,232 @@ export async function markRunFailedFromExecutorError(db, runId, err) {
|
|
|
51
69
|
finishedAt: new Date(),
|
|
52
70
|
},
|
|
53
71
|
});
|
|
72
|
+
// Only the call that made the row failed files (the duplicate call matches zero rows); bounded, never throws.
|
|
73
|
+
if (updated.count > 0)
|
|
74
|
+
await fileSelfDefectForRun(selfDefects, runId);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The `Run.error` of a coding run refused at dispatch because a budget
|
|
78
|
+
* constraint has nothing left: `budget_group_exhausted:<period>` or
|
|
79
|
+
* `run_tree_exhausted`, then a sentence for people.
|
|
80
|
+
*/
|
|
81
|
+
export function budgetExhaustedError(constraint) {
|
|
82
|
+
if (constraint === "run-tree") {
|
|
83
|
+
return "run_tree_exhausted: the run tree's shared budget is spent; the run was not started.";
|
|
84
|
+
}
|
|
85
|
+
return (`budget_group_exhausted:${constraint}: the agent's budget group has no ${constraint} budget left ` +
|
|
86
|
+
"(recorded spend plus live in-flight runs' holds have reached its cap); the run was not started.");
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Serializes grouped coding dispatches (security review I1). Under
|
|
90
|
+
* Serializable, a row lock taken after the transaction's first read cannot
|
|
91
|
+
* queue anything: the snapshot is already fixed, so each waiter wakes up
|
|
92
|
+
* with a stale view and aborts. LOCK TABLE is the one statement that takes
|
|
93
|
+
* no snapshot, so as the transaction's first statement it makes a waiter's
|
|
94
|
+
* snapshot start only after the previous holder committed. SHARE ROW
|
|
95
|
+
* EXCLUSIVE conflicts with itself and with writes to BudgetGroup rows, but not
|
|
96
|
+
* with the ROW SHARE that foreign-key checks from Agent take, so attaching
|
|
97
|
+
* agents to groups is not blocked. It serializes grouped coding dispatches
|
|
98
|
+
* across all groups; each holds it only for one short transaction.
|
|
99
|
+
*/
|
|
100
|
+
const GROUP_DISPATCH_LOCK_SQL = 'LOCK TABLE "BudgetGroup" IN SHARE ROW EXCLUSIVE MODE';
|
|
101
|
+
/**
|
|
102
|
+
* A coding run's budget reservation: the requested ceiling (override or the
|
|
103
|
+
* agent's budgetUsd) tightened by its budget group and run tree, where every
|
|
104
|
+
* live in-flight run's unspent hold already counts as spent. Rounded down to
|
|
105
|
+
* CodingRun.budgetReservedUsd's 6 decimal places; less than that is refused.
|
|
106
|
+
*/
|
|
107
|
+
async function reserveCodingBudget(tx, agent, now, options) {
|
|
108
|
+
const effective = await effectiveBudgetForRun(tx, agent, now, options.parentRunId);
|
|
109
|
+
const requested = options.budgetUsdOverride ?? Number(agent.budgetUsd);
|
|
110
|
+
const budgetUsd = Math.floor(Math.min(requested, effective.effectiveBudgetUsd) / MIN_RESERVATION_USD) * MIN_RESERVATION_USD;
|
|
111
|
+
if (budgetUsd < MIN_RESERVATION_USD && effective.exhaustedBy) {
|
|
112
|
+
return { budgetUsd: 0, refusal: budgetExhaustedError(effective.exhaustedBy) };
|
|
113
|
+
}
|
|
114
|
+
return { budgetUsd };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Attempts for the persist transaction, and the jittered backoff between
|
|
118
|
+
* them, for serialization failures and deadlocks.
|
|
119
|
+
*
|
|
120
|
+
* @internal Exported only for the real-PostgreSQL tests.
|
|
121
|
+
*/
|
|
122
|
+
export const PERSIST_ATTEMPTS = 8;
|
|
123
|
+
const RETRY_BASE_MS = 20;
|
|
124
|
+
const RETRY_MAX_MS = 250;
|
|
125
|
+
function retryDelayMs(attempt) {
|
|
126
|
+
const ceiling = Math.min(RETRY_MAX_MS, RETRY_BASE_MS * 2 ** attempt);
|
|
127
|
+
return Math.floor(ceiling / 2 + Math.random() * (ceiling / 2));
|
|
128
|
+
}
|
|
129
|
+
const CONTINUATION_REFUSALS = {
|
|
130
|
+
unknown_run: "Cannot continue an unknown coding run.",
|
|
131
|
+
other_repository: "Cannot continue a coding run from a different repository.",
|
|
132
|
+
no_pull_request: "Cannot continue a coding run that never opened a pull request.",
|
|
133
|
+
};
|
|
134
|
+
/** A continuation refused because of the run it names. Its message is fixed text, safe to show the model. */
|
|
135
|
+
export class ContinuationRefusedError extends Error {
|
|
136
|
+
reason;
|
|
137
|
+
constructor(reason) {
|
|
138
|
+
super(CONTINUATION_REFUSALS[reason]);
|
|
139
|
+
this.reason = reason;
|
|
140
|
+
this.name = "ContinuationRefusedError";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Whether this deployment can continue coding run `runId` in `repository`: the
|
|
145
|
+
* run (or its root) is in this database, in that repository, and opened a pull
|
|
146
|
+
* request. A run id read from a pull request can name a run that another
|
|
147
|
+
* deployment sharing the same App made, so check before relying on one.
|
|
148
|
+
*/
|
|
149
|
+
export async function checkContinuation(reader, runId, repository) {
|
|
150
|
+
const candidate = await reader.codingRun.findUnique({ where: { runId } });
|
|
151
|
+
if (!candidate)
|
|
152
|
+
return { ok: false, reason: "unknown_run" };
|
|
153
|
+
const root = candidate.rootCodingRunId
|
|
154
|
+
? await reader.codingRun.findUnique({ where: { runId: candidate.rootCodingRunId } })
|
|
155
|
+
: candidate;
|
|
156
|
+
if (!root)
|
|
157
|
+
return { ok: false, reason: "unknown_run" };
|
|
158
|
+
if (normalizeGitHubRepository(root.repository) !== normalizeGitHubRepository(repository)) {
|
|
159
|
+
return { ok: false, reason: "other_repository" };
|
|
160
|
+
}
|
|
161
|
+
const rootResult = publicCodingRunResult(root.result);
|
|
162
|
+
if ((rootResult?.outcome !== "pull_request_opened" && rootResult?.outcome !== "pull_request_updated") ||
|
|
163
|
+
rootResult.pullRequestNumber === undefined) {
|
|
164
|
+
return { ok: false, reason: "no_pull_request" };
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
ok: true,
|
|
168
|
+
root: {
|
|
169
|
+
runId: root.runId,
|
|
170
|
+
baseRef: root.baseRef,
|
|
171
|
+
headRef: root.headRef,
|
|
172
|
+
pullRequestNumber: rootResult.pullRequestNumber,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Resolves a coding run's branch: an override, else a continuation root's
|
|
178
|
+
* (see checkContinuation), else the profile's base.
|
|
179
|
+
*/
|
|
180
|
+
async function resolveCodingBranch(reader, options, profile) {
|
|
181
|
+
if (options.continuesCodingRunId === undefined)
|
|
182
|
+
return { baseRef: options.codingBaseRef ?? profile.baseRef };
|
|
183
|
+
if (options.codingBaseRef !== undefined) {
|
|
184
|
+
throw new Error("continuesCodingRunId cannot be combined with codingBaseRef.");
|
|
185
|
+
}
|
|
186
|
+
const check = await checkContinuation(reader, options.continuesCodingRunId, profile.repository);
|
|
187
|
+
if (!check.ok)
|
|
188
|
+
throw new ContinuationRefusedError(check.reason);
|
|
189
|
+
const { root } = check;
|
|
190
|
+
return {
|
|
191
|
+
baseRef: root.baseRef,
|
|
192
|
+
headRef: root.headRef,
|
|
193
|
+
continuationOf: { runId: root.runId },
|
|
194
|
+
rootCodingRunId: root.runId,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/** Read failures that are the file's fault rather than the host's: reported as an invalid declaration. */
|
|
198
|
+
const UNREADABLE_DECLARATION = {
|
|
199
|
+
github_file_too_large: `it is larger than ${MAX_SERVICE_DECLARATION_BYTES} bytes`,
|
|
200
|
+
github_file_not_a_file: "it is not a file",
|
|
201
|
+
github_file_not_utf8: "it is not UTF-8 text",
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* The knowledge note's input (docs/knowledge.md): the repository's bundle
|
|
205
|
+
* index at the run's base, read before the transaction like the services
|
|
206
|
+
* declaration. Any failure means no note, never a failed dispatch.
|
|
207
|
+
*/
|
|
208
|
+
async function readKnowledgeIndex(options, profile, resolvedBranch) {
|
|
209
|
+
const executor = options.executor;
|
|
210
|
+
if (!executor.readCodingRepositoryFile)
|
|
211
|
+
return undefined;
|
|
212
|
+
try {
|
|
213
|
+
// Resolved here, inside the try: a branch problem is the transaction's to report, not the note's.
|
|
214
|
+
const branch = resolvedBranch ?? (await resolveCodingBranch(options.db, options, profile));
|
|
215
|
+
const indexText = await executor.readCodingRepositoryFile({
|
|
216
|
+
repository: profile.repository,
|
|
217
|
+
baseRef: normalizeGitRef(branch.baseRef),
|
|
218
|
+
path: `${DEFAULT_KNOWLEDGE_BUNDLE_PATH}/index.md`,
|
|
219
|
+
maxBytes: KNOWLEDGE_INDEX_READ_MAX_BYTES,
|
|
220
|
+
});
|
|
221
|
+
return indexText ? { bundlePath: DEFAULT_KNOWLEDGE_BUNDLE_PATH, indexText } : undefined;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
if (err instanceof Error && err.message in UNREADABLE_DECLARATION) {
|
|
225
|
+
dispatchLog.info({ repository: profile.repository, reason: err.message }, "knowledge index unreadable; dispatching without it");
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
dispatchLog.warn({ err, repository: profile.repository }, "knowledge index read failed; dispatching without it");
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Coding-run services (docs/coding-services.md): resolves the run's branch and
|
|
234
|
+
* reads the repository's declaration from its base, then parses it. A network
|
|
235
|
+
* call, so it runs before the Serializable transaction, which reuses the
|
|
236
|
+
* branch and resolves the services against the catalog and the agent.
|
|
237
|
+
*/
|
|
238
|
+
async function readServiceDeclaration(options, profile) {
|
|
239
|
+
const branch = await resolveCodingBranch(options.db, options, profile);
|
|
240
|
+
const read = { repository: profile.repository, profileBaseRef: profile.baseRef, branch };
|
|
241
|
+
const executor = options.executor;
|
|
242
|
+
if (!executor.readCodingServiceDeclaration)
|
|
243
|
+
return { ...read, outcome: { kind: "none" } };
|
|
244
|
+
let text;
|
|
245
|
+
try {
|
|
246
|
+
text = await executor.readCodingServiceDeclaration({
|
|
247
|
+
repository: profile.repository,
|
|
248
|
+
baseRef: normalizeGitRef(branch.baseRef),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
const reason = UNREADABLE_DECLARATION[err instanceof Error ? err.message : ""];
|
|
253
|
+
if (reason) {
|
|
254
|
+
return {
|
|
255
|
+
...read,
|
|
256
|
+
outcome: {
|
|
257
|
+
kind: "refused",
|
|
258
|
+
refusal: serviceRefusal("service_declaration_invalid", invalidDeclarationSentence(reason)),
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
dispatchLog.warn({ err, agentId: options.agentId }, "could not read the repository's service declaration");
|
|
263
|
+
return {
|
|
264
|
+
...read,
|
|
265
|
+
outcome: {
|
|
266
|
+
kind: "refused",
|
|
267
|
+
refusal: serviceRefusal("service_declaration_unavailable", DECLARATION_UNAVAILABLE_SENTENCE),
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
if (text === null)
|
|
272
|
+
return { ...read, outcome: { kind: "none" } };
|
|
273
|
+
try {
|
|
274
|
+
return { ...read, outcome: { kind: "declared", services: parseServiceDeclaration(text) } };
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
if (!(err instanceof ServiceDeclarationError))
|
|
278
|
+
throw err;
|
|
279
|
+
return {
|
|
280
|
+
...read,
|
|
281
|
+
outcome: {
|
|
282
|
+
kind: "refused",
|
|
283
|
+
refusal: serviceRefusal("service_declaration_invalid", invalidDeclarationSentence(err.reason)),
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** Inside the transaction: the run's services, or the refusal that stops it. */
|
|
289
|
+
async function resolveDispatchServices(tx, outcome, allowed, executor, provider, request, instructions) {
|
|
290
|
+
if (outcome.kind === "refused")
|
|
291
|
+
return { refusal: outcome.refusal };
|
|
292
|
+
if (outcome.kind === "none" || outcome.services.length === 0)
|
|
293
|
+
return { services: [] };
|
|
294
|
+
if (executor.supportsCodingServices?.(provider) !== true) {
|
|
295
|
+
return { refusal: serviceRefusal("service_launcher_unsupported", LAUNCHER_UNSUPPORTED_SENTENCE) };
|
|
296
|
+
}
|
|
297
|
+
return resolveRunServices({ findMany: (args) => tx.codingService.findMany(args) }, outcome.services, parseAllowedServiceNames(allowed), request, instructions);
|
|
54
298
|
}
|
|
55
299
|
/**
|
|
56
300
|
* Persists every detached run input in one transaction, then invokes the
|
|
@@ -59,7 +303,34 @@ export async function markRunFailedFromExecutorError(db, runId, err) {
|
|
|
59
303
|
*/
|
|
60
304
|
export async function dispatchRun(options) {
|
|
61
305
|
const now = options.now ?? new Date();
|
|
306
|
+
// Read outside the transaction only to decide whether to take the group
|
|
307
|
+
// dispatch lock before the transaction's first read, and whether to read the
|
|
308
|
+
// repository's service declaration (a network call); everything the run is
|
|
309
|
+
// built from is re-read inside. If the agent changes in between, the
|
|
310
|
+
// Serializable transaction still refuses a conflicting commit.
|
|
311
|
+
const preview = await options.db.agent.findUnique({
|
|
312
|
+
where: { id: options.agentId },
|
|
313
|
+
select: {
|
|
314
|
+
kind: true,
|
|
315
|
+
budgetGroupId: true,
|
|
316
|
+
codingProfile: { select: { repository: true, baseRef: true, services: true } },
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
const lockGroups = preview?.kind === "coding" && preview.budgetGroupId != null;
|
|
320
|
+
// Only an agent allowed some service reads the repository's declaration; any
|
|
321
|
+
// other coding agent never calls the host for it and gets no services.
|
|
322
|
+
const declarationRead = preview?.kind === "coding" &&
|
|
323
|
+
preview.codingProfile &&
|
|
324
|
+
parseAllowedServiceNames(preview.codingProfile.services).length > 0
|
|
325
|
+
? await readServiceDeclaration(options, preview.codingProfile)
|
|
326
|
+
: undefined;
|
|
327
|
+
// The knowledge note's input: the repository's bundle index at the run's base (a network call).
|
|
328
|
+
const knowledgeIndex = preview?.kind === "coding" && preview.codingProfile && options.executor.readCodingRepositoryFile
|
|
329
|
+
? await readKnowledgeIndex(options, preview.codingProfile, declarationRead?.branch)
|
|
330
|
+
: undefined;
|
|
62
331
|
const persistOnce = () => options.db.$transaction(async (tx) => {
|
|
332
|
+
if (lockGroups)
|
|
333
|
+
await tx.$executeRawUnsafe(GROUP_DISPATCH_LOCK_SQL);
|
|
63
334
|
if (options.lockAgent) {
|
|
64
335
|
const locked = await tx.$queryRaw `
|
|
65
336
|
SELECT "id" FROM "Agent" WHERE "id" = ${options.agentId} FOR UPDATE SKIP LOCKED
|
|
@@ -78,6 +349,52 @@ export async function dispatchRun(options) {
|
|
|
78
349
|
if (options.taskOverride !== undefined && agent.kind !== "native") {
|
|
79
350
|
throw new Error("taskOverride can only be supplied for a native agent.");
|
|
80
351
|
}
|
|
352
|
+
// A coding run's services are resolved, and its budget reserved, here,
|
|
353
|
+
// at dispatch (E-01): the container only ever checks the run's own
|
|
354
|
+
// reservation. A native run computes its effective budget in
|
|
355
|
+
// executeRun's load step instead.
|
|
356
|
+
let codingBudget;
|
|
357
|
+
let codingEntry;
|
|
358
|
+
let modelFailure;
|
|
359
|
+
let services = [];
|
|
360
|
+
let servicesRefusal;
|
|
361
|
+
if (agent.kind === "coding") {
|
|
362
|
+
if (!agent.codingProfile)
|
|
363
|
+
throw new Error(`Coding agent "${agent.id}" has no coding profile.`);
|
|
364
|
+
// An unknown coding provider is a broken profile, not a catalog state: still thrown.
|
|
365
|
+
assertCodingProvider(agent.codingProfile.provider);
|
|
366
|
+
// Recorded on the run row below: the run is billed at this entry for its whole life.
|
|
367
|
+
// A model the catalog cannot run (missing, disabled, or another provider's) fails
|
|
368
|
+
// the run here instead of throwing: the run row commits with the reason, so the
|
|
369
|
+
// caller's own writes stand (a scheduler's lastScheduledAt, a mention's status
|
|
370
|
+
// row) and the owner sees why in list_runs, rather than a rolled-back
|
|
371
|
+
// transaction that a scheduler would retry on every tick.
|
|
372
|
+
try {
|
|
373
|
+
codingEntry = resolveCodingEntry(agent.codingProfile.provider, agent.model);
|
|
374
|
+
}
|
|
375
|
+
catch (err) {
|
|
376
|
+
if (!(err instanceof ModelUnavailableError || err instanceof CodingModelProviderMismatchError))
|
|
377
|
+
throw err;
|
|
378
|
+
modelFailure = err.message;
|
|
379
|
+
}
|
|
380
|
+
if (!modelFailure && declarationRead) {
|
|
381
|
+
if (declarationRead.repository !== agent.codingProfile.repository ||
|
|
382
|
+
declarationRead.profileBaseRef !== agent.codingProfile.baseRef) {
|
|
383
|
+
// The declaration was read for a profile that changed before this transaction.
|
|
384
|
+
throw new Error("The coding agent's repository or base branch changed during dispatch; try again.");
|
|
385
|
+
}
|
|
386
|
+
// A missing request fails below, with its own error.
|
|
387
|
+
const request = options.codingTask ?? agent.codingProfile.defaultTask ?? "";
|
|
388
|
+
const resolved = await resolveDispatchServices(tx, declarationRead.outcome, agent.codingProfile.services, options.executor, agent.codingProfile.provider, request, agent.systemPrompt);
|
|
389
|
+
if ("refusal" in resolved)
|
|
390
|
+
servicesRefusal = resolved.refusal;
|
|
391
|
+
else
|
|
392
|
+
services = resolved.services;
|
|
393
|
+
}
|
|
394
|
+
if (!modelFailure && !servicesRefusal)
|
|
395
|
+
codingBudget = await reserveCodingBudget(tx, agent, now, options);
|
|
396
|
+
}
|
|
397
|
+
const refusal = servicesRefusal ?? codingBudget?.refusal;
|
|
81
398
|
const run = await tx.run.create({
|
|
82
399
|
data: {
|
|
83
400
|
agentId: agent.id,
|
|
@@ -86,46 +403,44 @@ export async function dispatchRun(options) {
|
|
|
86
403
|
parentRunId: options.parentRunId,
|
|
87
404
|
grantedParentMemoryKeys: options.grantedParentMemoryKeys ?? [],
|
|
88
405
|
taskOverride: options.taskOverride,
|
|
406
|
+
triggeredById: options.triggeredById ?? null,
|
|
407
|
+
// Failed before it starts, like a native run whose model the
|
|
408
|
+
// runner's load step finds unavailable: zero spend, never started.
|
|
409
|
+
...(modelFailure ? { status: "failed", error: modelFailure, finishedAt: now } : {}),
|
|
410
|
+
// Refused before it starts, the same terminal status (and zero
|
|
411
|
+
// spend) as a native run whose budget is gone at turn 1.
|
|
412
|
+
...(refusal ? { status: "refused", error: refusal, finishedAt: now } : {}),
|
|
413
|
+
...(codingEntry
|
|
414
|
+
? {
|
|
415
|
+
pricingVersion: codingEntry.priceVersion,
|
|
416
|
+
// entryOf returns plain JSON data (fresh array, no Dates); the interface's readonly
|
|
417
|
+
// efforts array is all that keeps it from matching Prisma's Json input type.
|
|
418
|
+
pricingSnapshot: entryOf(codingEntry),
|
|
419
|
+
}
|
|
420
|
+
: {}),
|
|
89
421
|
},
|
|
90
422
|
});
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
423
|
+
if (options.afterPersist)
|
|
424
|
+
await options.afterPersist(tx, run);
|
|
425
|
+
const attributed = await attributeRun(tx, run.id, {
|
|
426
|
+
parentRunId: options.parentRunId,
|
|
427
|
+
continuesCodingRunId: options.continuesCodingRunId,
|
|
428
|
+
intent: options.attribution,
|
|
429
|
+
}, now);
|
|
430
|
+
if (agent.kind === "coding" && agent.codingProfile && codingBudget && !refusal) {
|
|
431
|
+
// Checked above too; repeated so the provider type narrows here.
|
|
94
432
|
assertCodingProviderModel(agent.codingProfile.provider, agent.model);
|
|
95
433
|
const request = options.codingTask ?? agent.codingProfile.defaultTask;
|
|
96
434
|
if (!request)
|
|
97
435
|
throw new Error(`Coding agent "${agent.id}" requires a task.`);
|
|
98
|
-
// The worker sees only the task text, so the agent's own instructions
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (options.codingBaseRef !== undefined) {
|
|
107
|
-
throw new Error("continuesCodingRunId cannot be combined with codingBaseRef.");
|
|
108
|
-
}
|
|
109
|
-
const candidate = await tx.codingRun.findUnique({ where: { runId: options.continuesCodingRunId } });
|
|
110
|
-
if (!candidate)
|
|
111
|
-
throw new Error("Cannot continue an unknown coding run.");
|
|
112
|
-
const root = candidate.rootCodingRunId
|
|
113
|
-
? await tx.codingRun.findUnique({ where: { runId: candidate.rootCodingRunId } })
|
|
114
|
-
: candidate;
|
|
115
|
-
if (!root)
|
|
116
|
-
throw new Error("Cannot continue an unknown coding run.");
|
|
117
|
-
if (normalizeGitHubRepository(root.repository) !== normalizeGitHubRepository(agent.codingProfile.repository)) {
|
|
118
|
-
throw new Error("Cannot continue a coding run from a different repository.");
|
|
119
|
-
}
|
|
120
|
-
const rootResult = publicCodingRunResult(root.result);
|
|
121
|
-
if (rootResult?.outcome !== "pull_request_opened" && rootResult?.outcome !== "pull_request_updated") {
|
|
122
|
-
throw new Error("Cannot continue a coding run that never opened a pull request.");
|
|
123
|
-
}
|
|
124
|
-
baseRef = root.baseRef;
|
|
125
|
-
headRef = root.headRef;
|
|
126
|
-
continuationOf = { runId: root.runId };
|
|
127
|
-
rootCodingRunId = root.runId;
|
|
128
|
-
}
|
|
436
|
+
// The worker sees only the task text, so the agent's own instructions, and the
|
|
437
|
+
// services note, ride in it.
|
|
438
|
+
const task = composeCodingTask(agent.systemPrompt, request, servicesInstructionNote(services), knowledgeIndex ? knowledgeSection(knowledgeIndex) : undefined);
|
|
439
|
+
const budgetUsd = codingBudget.budgetUsd;
|
|
440
|
+
// Resolved once: before the transaction when the declaration was read from it.
|
|
441
|
+
const branch = declarationRead?.branch ?? (await resolveCodingBranch(tx, options, agent.codingProfile));
|
|
442
|
+
const { baseRef, continuationOf, rootCodingRunId } = branch;
|
|
443
|
+
const headRef = branch.headRef ?? `wardby/run-${run.id}`;
|
|
129
444
|
const input = CodingTaskInputSchema.parse({
|
|
130
445
|
schemaVersion: CODING_PROTOCOL_VERSION,
|
|
131
446
|
runId: run.id,
|
|
@@ -137,16 +452,23 @@ export async function dispatchRun(options) {
|
|
|
137
452
|
budgetUsd,
|
|
138
453
|
deadlineAt: new Date(now.getTime() + agent.codingProfile.timeoutSec * 1000).toISOString(),
|
|
139
454
|
continuationOf,
|
|
455
|
+
...(services.length > 0 ? { services: workerServices(services) } : {}),
|
|
140
456
|
});
|
|
141
|
-
const
|
|
457
|
+
const imageSelector = {
|
|
142
458
|
provider: agent.codingProfile.provider,
|
|
143
459
|
toolchain: agent.codingProfile.toolchain,
|
|
144
460
|
toolchainVersion: agent.codingProfile.toolchainVersion,
|
|
145
461
|
workerImageRef: agent.codingProfile.workerImageRef,
|
|
146
|
-
}
|
|
462
|
+
};
|
|
463
|
+
const workerImage = options.executor.resolveCodingWorkerImage?.(imageSelector);
|
|
464
|
+
// Claude Code's commands run in its tool runner, so the toolchain picks that image too; fixed
|
|
465
|
+
// here with the worker image so the run keeps both however the deployment changes later.
|
|
466
|
+
const toolImage = options.executor.resolveCodingToolImage?.(imageSelector) ?? null;
|
|
147
467
|
await tx.codingRun.create({
|
|
148
468
|
data: {
|
|
149
469
|
runId: run.id,
|
|
470
|
+
issueProvider: attributed?.provider ?? null,
|
|
471
|
+
issueKey: attributed?.key ?? null,
|
|
150
472
|
task: input.task,
|
|
151
473
|
repository: input.repository,
|
|
152
474
|
baseRef: input.baseRef,
|
|
@@ -154,18 +476,26 @@ export async function dispatchRun(options) {
|
|
|
154
476
|
provider: agent.codingProfile.provider,
|
|
155
477
|
model: input.model,
|
|
156
478
|
timeoutSec: agent.codingProfile.timeoutSec,
|
|
157
|
-
allowedEgress: agent.codingProfile.allowedEgress,
|
|
158
479
|
protectedPaths: agent.codingProfile.protectedPaths,
|
|
480
|
+
collectExclude: agent.codingProfile.collectExclude,
|
|
481
|
+
packageAllowlist: agent.codingProfile.packageAllowlist,
|
|
482
|
+
packagePolicy: agent.codingProfile.packagePolicy,
|
|
159
483
|
workerImage,
|
|
484
|
+
toolImage,
|
|
160
485
|
budgetReservedUsd: budgetUsd,
|
|
161
486
|
rootCodingRunId,
|
|
162
487
|
workspaceDiskMb: agent.codingProfile.workspaceDiskMb,
|
|
488
|
+
// Fixed here so a run's tracing never changes mid-run.
|
|
489
|
+
debugTrace: agent.codingProfile.debugTraceUntil != null &&
|
|
490
|
+
now.getTime() < agent.codingProfile.debugTraceUntil.getTime(),
|
|
491
|
+
services,
|
|
163
492
|
},
|
|
164
493
|
});
|
|
165
494
|
}
|
|
166
|
-
else if (
|
|
167
|
-
options.
|
|
168
|
-
|
|
495
|
+
else if (agent.kind !== "coding" &&
|
|
496
|
+
(options.codingTask !== undefined ||
|
|
497
|
+
options.codingBaseRef !== undefined ||
|
|
498
|
+
options.continuesCodingRunId !== undefined)) {
|
|
169
499
|
throw new Error("Coding overrides cannot be supplied for a native agent.");
|
|
170
500
|
}
|
|
171
501
|
const task = options.task
|
|
@@ -182,24 +512,29 @@ export async function dispatchRun(options) {
|
|
|
182
512
|
return { run, task };
|
|
183
513
|
}, { isolationLevel: "Serializable" });
|
|
184
514
|
let persisted = null;
|
|
185
|
-
for (let attempt = 0; attempt <
|
|
515
|
+
for (let attempt = 0; attempt < PERSIST_ATTEMPTS; attempt += 1) {
|
|
186
516
|
try {
|
|
187
517
|
persisted = await persistOnce();
|
|
188
518
|
break;
|
|
189
519
|
}
|
|
190
520
|
catch (err) {
|
|
191
|
-
if (!isSerializationConflict(err) || attempt ===
|
|
521
|
+
if (!isSerializationConflict(err) || attempt === PERSIST_ATTEMPTS - 1)
|
|
192
522
|
throw err;
|
|
523
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs(attempt)));
|
|
193
524
|
}
|
|
194
525
|
}
|
|
195
526
|
if (!persisted)
|
|
196
527
|
return null;
|
|
528
|
+
if (persisted.run.status === "refused" || persisted.run.status === "failed") {
|
|
529
|
+
dispatchLog.warn({ runId: persisted.run.id, agentId: options.agentId, reason: persisted.run.error }, `coding run ${persisted.run.status} at dispatch`);
|
|
530
|
+
return persisted;
|
|
531
|
+
}
|
|
197
532
|
const runStart = async () => {
|
|
198
533
|
try {
|
|
199
534
|
await options.executor.start(persisted.run.id);
|
|
200
535
|
}
|
|
201
536
|
catch (err) {
|
|
202
|
-
await markRunFailedFromExecutorError(options.db, persisted.run.id, err).catch((err2) => dispatchLog.error({ err: err2, runId: persisted.run.id }, "failed to persist executor start failure"));
|
|
537
|
+
await markRunFailedFromExecutorError(options.db, persisted.run.id, err, options.selfDefects).catch((err2) => dispatchLog.error({ err: err2, runId: persisted.run.id }, "failed to persist executor start failure"));
|
|
203
538
|
}
|
|
204
539
|
};
|
|
205
540
|
if (options.awaitExecution) {
|