@wardby/cli 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +34 -4
- package/README.md +41 -4
- package/dist/claude-coding-worker/driver.d.ts +6 -1
- package/dist/claude-coding-worker/driver.js +27 -1
- package/dist/claude-coding-worker/main.js +2 -0
- package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
- package/dist/claude-coding-worker/tool-socket.js +26 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +13 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +219 -29
- package/dist/coding/collect-exclude.d.ts +25 -0
- package/dist/coding/collect-exclude.js +76 -0
- package/dist/coding/profile.d.ts +67 -22
- package/dist/coding/profile.js +58 -25
- package/dist/coding/protected-path-wording.d.ts +24 -0
- package/dist/coding/protected-path-wording.js +55 -0
- package/dist/coding/protected-paths.d.ts +31 -0
- package/dist/coding/protected-paths.js +48 -0
- package/dist/coding/protocol.d.ts +75 -4
- package/dist/coding/protocol.js +107 -7
- package/dist/coding/registry/adapters.d.ts +2 -0
- package/dist/coding/registry/adapters.js +9 -0
- package/dist/coding/registry/allowlist.d.ts +9 -0
- package/dist/coding/registry/allowlist.js +28 -0
- package/dist/coding/registry/json-scan.d.ts +55 -0
- package/dist/coding/registry/json-scan.js +191 -0
- package/dist/coding/registry/lockfiles.d.ts +6 -0
- package/dist/coding/registry/lockfiles.js +89 -0
- package/dist/coding/registry/npm-lockfile.d.ts +9 -0
- package/dist/coding/registry/npm-lockfile.js +73 -0
- package/dist/coding/registry/npm-plan.d.ts +29 -0
- package/dist/coding/registry/npm-plan.js +289 -0
- package/dist/coding/registry/npm.d.ts +7 -0
- package/dist/coding/registry/npm.js +252 -0
- package/dist/coding/registry/pypi.d.ts +4 -0
- package/dist/coding/registry/pypi.js +210 -0
- package/dist/coding/registry/report.d.ts +37 -0
- package/dist/coding/registry/report.js +31 -0
- package/dist/coding/registry/token.d.ts +4 -0
- package/dist/coding/registry/token.js +7 -0
- package/dist/coding/registry/types.d.ts +286 -0
- package/dist/coding/registry/types.js +19 -0
- package/dist/coding/registry/worker-config.d.ts +14 -0
- package/dist/coding/registry/worker-config.js +31 -0
- package/dist/coding/services/builtins.d.ts +22 -0
- package/dist/coding/services/builtins.js +85 -0
- package/dist/coding/services/catalog.d.ts +443 -0
- package/dist/coding/services/catalog.js +159 -0
- package/dist/coding/services/declaration.d.ts +11 -0
- package/dist/coding/services/declaration.js +114 -0
- package/dist/coding/services/note.d.ts +8 -0
- package/dist/coding/services/note.js +15 -0
- package/dist/coding/services/resolve.d.ts +25 -0
- package/dist/coding/services/resolve.js +50 -0
- package/dist/coding/services/wording.d.ts +25 -0
- package/dist/coding/services/wording.js +70 -0
- package/dist/coding-proxy/main.js +24 -4
- package/dist/coding-worker/artifact.d.ts +6 -0
- package/dist/coding-worker/debug-trace.d.ts +37 -0
- package/dist/coding-worker/debug-trace.js +117 -0
- package/dist/coding-worker/driver.d.ts +13 -1
- package/dist/coding-worker/driver.js +102 -13
- package/dist/coding-worker/errors.js +8 -0
- package/dist/coding-worker/main.js +10 -2
- package/dist/coding-worker/sdk.d.ts +2 -2
- package/dist/coding-worker/sdk.js +7 -2
- package/dist/coding-worker/types.d.ts +3 -0
- package/dist/config/providers.d.ts +41 -0
- package/dist/config/providers.js +66 -0
- package/dist/core/budget-groups.d.ts +108 -5
- package/dist/core/budget-groups.js +125 -19
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +5 -1
- package/dist/core/db.js +8 -2
- package/dist/core/dispatch.d.ts +33 -6
- package/dist/core/dispatch.js +260 -43
- package/dist/core/engine-native.js +27 -10
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +49 -0
- package/dist/core/host-events.js +257 -0
- package/dist/core/host-identity-links.d.ts +54 -0
- package/dist/core/host-identity-links.js +189 -0
- package/dist/core/host-status.d.ts +61 -0
- package/dist/core/host-status.js +211 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +38 -2
- package/dist/core/reconciler.js +86 -2
- package/dist/core/repo-access.d.ts +99 -0
- package/dist/core/repo-access.js +136 -0
- package/dist/core/review-host-checks.d.ts +11 -0
- package/dist/core/review-host-checks.js +41 -0
- package/dist/core/review-host-tools.d.ts +47 -0
- package/dist/core/review-host-tools.js +347 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/runner.d.ts +30 -8
- package/dist/core/runner.js +237 -40
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +1 -1
- package/dist/core/subagent-memory-tools.js +16 -3
- package/dist/core/tool-admin.d.ts +81 -0
- package/dist/core/tool-admin.js +129 -0
- package/dist/core/tool-names.d.ts +42 -0
- package/dist/core/tool-names.js +64 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +8 -1
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +100 -0
- package/dist/generated/prisma/client.d.ts +100 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
- package/dist/generated/prisma/enums.d.ts +6 -0
- package/dist/generated/prisma/enums.js +6 -1
- package/dist/generated/prisma/internal/class.d.ts +143 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
- package/dist/generated/prisma/models/Agent.d.ts +294 -1
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
- package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
- package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
- package/dist/generated/prisma/models/HostIdentity.js +1 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +455 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
- package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
- package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
- package/dist/generated/prisma/models/RegistryFetch.js +1 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
- package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
- package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
- package/dist/generated/prisma/models/ResourceGrant.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +389 -1
- package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
- package/dist/generated/prisma/models/RunHostCheck.js +1 -0
- package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
- package/dist/generated/prisma/models/RunHostStatus.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models.d.ts +13 -0
- package/dist/help/build.d.ts +1 -0
- package/dist/help/build.js +9 -0
- package/dist/help/catalog.d.ts +24 -0
- package/dist/help/catalog.js +160 -0
- package/dist/help/cli.d.ts +2 -0
- package/dist/help/cli.js +65 -0
- package/dist/help/runtime.d.ts +3 -0
- package/dist/help/runtime.js +44 -0
- package/dist/help/search.d.ts +9 -0
- package/dist/help/search.js +104 -0
- package/dist/help-index.json +660 -0
- package/dist/import/cli-args.js +3 -2
- package/dist/import/create.d.ts +5 -0
- package/dist/import/create.js +67 -13
- package/dist/import/index.js +19 -9
- package/dist/import/neutral-schema.d.ts +11 -11
- package/dist/mcp/auth/access.d.ts +70 -0
- package/dist/mcp/auth/access.js +58 -0
- package/dist/mcp/auth/grants-cli.d.ts +149 -0
- package/dist/mcp/auth/grants-cli.js +518 -0
- package/dist/mcp/auth/host-account-cli.d.ts +2 -0
- package/dist/mcp/auth/host-account-cli.js +47 -0
- package/dist/mcp/auth/ownership.d.ts +26 -52
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/repo-authorization.d.ts +22 -0
- package/dist/mcp/auth/repo-authorization.js +51 -0
- package/dist/mcp/auth/resource-server.d.ts +31 -2
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +2 -2
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
- package/dist/mcp/context.d.ts +27 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/github-ingress.d.ts +36 -0
- package/dist/mcp/host-events/github-ingress.js +92 -0
- package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
- package/dist/mcp/host-events/github-user-callback.js +50 -0
- package/dist/mcp/index.d.ts +8 -1
- package/dist/mcp/index.js +106 -16
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/tools/agents.js +446 -48
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +22 -15
- package/dist/mcp/tools/grants.d.ts +2 -0
- package/dist/mcp/tools/grants.js +239 -0
- package/dist/mcp/tools/help.d.ts +5 -0
- package/dist/mcp/tools/help.js +67 -0
- package/dist/mcp/tools/host-accounts.d.ts +2 -0
- package/dist/mcp/tools/host-accounts.js +114 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +181 -0
- package/dist/mcp/tools/runs.d.ts +6 -0
- package/dist/mcp/tools/runs.js +60 -6
- package/dist/mcp/tools/scheduling.js +3 -6
- package/dist/mcp/tools/secrets.js +18 -6
- package/dist/mcp/tools/services.d.ts +2 -0
- package/dist/mcp/tools/services.js +222 -0
- package/dist/mcp/tools/subagents.js +52 -16
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +201 -40
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +10 -0
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +2 -0
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +2 -1
- package/dist/providers/auth/self-hosted.js +16 -4
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
- package/dist/providers/coding-proxy/memory-ledger.js +21 -2
- package/dist/providers/coding-proxy/metering.d.ts +4 -0
- package/dist/providers/coding-proxy/metering.js +28 -2
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
- package/dist/providers/coding-proxy/proxy.d.ts +13 -0
- package/dist/providers/coding-proxy/proxy.js +479 -18
- package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
- package/dist/providers/coding-proxy/registry/audit.js +380 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
- package/dist/providers/coding-proxy/registry/plan.js +304 -0
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
- package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
- package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
- package/dist/providers/coding-proxy/registry/service.js +1137 -0
- package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
- package/dist/providers/coding-proxy/registry/store.js +70 -0
- package/dist/providers/coding-proxy/runtime.d.ts +17 -0
- package/dist/providers/coding-proxy/runtime.js +63 -0
- package/dist/providers/coding-proxy/secure-fetch.js +0 -1
- package/dist/providers/coding-proxy/server.d.ts +11 -0
- package/dist/providers/coding-proxy/server.js +163 -0
- package/dist/providers/coding-proxy/types.d.ts +15 -0
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +2 -2
- package/dist/providers/executor/composition.d.ts +3 -0
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +105 -3
- package/dist/providers/executor/container.js +296 -20
- package/dist/providers/executor/dbos.d.ts +2 -3
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +7 -0
- package/dist/providers/executor/routing.js +13 -0
- package/dist/providers/executor/types.d.ts +22 -0
- package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
- package/dist/providers/jobs/claude-tool-setup.js +50 -0
- package/dist/providers/jobs/collect-prune.d.ts +7 -0
- package/dist/providers/jobs/collect-prune.js +27 -0
- package/dist/providers/jobs/docker-isolation.d.ts +48 -3
- package/dist/providers/jobs/docker-isolation.js +213 -22
- package/dist/providers/jobs/docker-services.d.ts +35 -0
- package/dist/providers/jobs/docker-services.js +191 -0
- package/dist/providers/jobs/docker.d.ts +49 -2
- package/dist/providers/jobs/docker.js +279 -32
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
- package/dist/providers/jobs/kubernetes-isolation.js +238 -57
- package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
- package/dist/providers/jobs/kubernetes-platform.js +11 -5
- package/dist/providers/jobs/kubernetes-preflight.js +3 -0
- package/dist/providers/jobs/kubernetes.d.ts +21 -2
- package/dist/providers/jobs/kubernetes.js +112 -21
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.js +6 -2
- package/dist/providers/llm/bedrock.js +2 -1
- package/dist/providers/llm/claude-messages.d.ts +5 -1
- package/dist/providers/llm/claude-messages.js +1 -0
- package/dist/providers/llm/claude-provider.d.ts +3 -1
- package/dist/providers/llm/claude-provider.js +5 -1
- package/dist/providers/llm/index.d.ts +1 -1
- package/dist/providers/llm/index.js +1 -1
- package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
- package/dist/providers/llm/pricing-anthropic.js +32 -14
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
- package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
- package/dist/providers/llm/routing.d.ts +10 -1
- package/dist/providers/llm/routing.js +18 -0
- package/dist/providers/llm/types.d.ts +12 -0
- package/dist/providers/llm/types.js +8 -1
- package/dist/providers/review-host/diff-lines.d.ts +16 -0
- package/dist/providers/review-host/diff-lines.js +59 -0
- package/dist/providers/review-host/github-events.d.ts +6 -0
- package/dist/providers/review-host/github-events.js +180 -0
- package/dist/providers/review-host/github-user-auth.d.ts +38 -0
- package/dist/providers/review-host/github-user-auth.js +128 -0
- package/dist/providers/review-host/github.d.ts +57 -0
- package/dist/providers/review-host/github.js +567 -0
- package/dist/providers/review-host/index.d.ts +12 -0
- package/dist/providers/review-host/index.js +30 -0
- package/dist/providers/review-host/review-format.d.ts +19 -0
- package/dist/providers/review-host/review-format.js +59 -0
- package/dist/providers/review-host/types.d.ts +284 -0
- package/dist/providers/review-host/types.js +24 -0
- package/dist/providers/vcs/git.d.ts +16 -6
- package/dist/providers/vcs/git.js +77 -13
- package/dist/providers/vcs/github.d.ts +74 -3
- package/dist/providers/vcs/github.js +195 -15
- package/dist/providers/vcs/types.d.ts +42 -4
- package/dist/quickstart/index.js +13 -2
- package/dist/sandbox/fetch-policy.d.ts +20 -2
- package/dist/sandbox/fetch-policy.js +64 -3
- package/dist/sandbox/host-functions.d.ts +9 -1
- package/dist/sandbox/host-functions.js +12 -5
- package/dist/serve.js +1 -1
- package/dist/wardby-bin.js +6 -0
- package/docs/README.md +30 -0
- package/docs/architecture-runtime.md +90 -0
- package/docs/assets/brand/wardby-icon-512.png +0 -0
- package/docs/assets/brand/wardby-icon.svg +16 -0
- package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
- package/docs/assets/brand/wardby-mascot.png +0 -0
- package/docs/assets/brand/wardby-mascot.svg +5 -0
- package/docs/assets/wardby-workflow.svg +106 -0
- package/docs/code-review-agents.md +481 -0
- package/docs/coding-agent-setup.md +172 -0
- package/docs/coding-packages.md +455 -0
- package/docs/coding-services.md +300 -0
- package/docs/coding-worker-byo-images.md +98 -0
- package/docs/coding-worker-isolation.md +1061 -0
- package/docs/getting-started-gke.md +615 -0
- package/docs/getting-started-identity-provider.md +308 -0
- package/docs/getting-started.md +133 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +657 -0
- package/help/code-review-agents.md +31 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/creating-agents.md +68 -0
- package/help/deploy-gke.md +39 -0
- package/help/deployment-targets.md +39 -0
- package/help/errors/budget-group-exhausted.md +25 -0
- package/help/errors/docker-isolation-unsupported.md +26 -0
- package/help/errors/protected-path.md +45 -0
- package/help/errors/repo-access.md +27 -0
- package/help/errors/service-declaration-invalid.md +27 -0
- package/help/errors/service-declaration-unavailable.md +25 -0
- package/help/errors/service-launcher-unsupported.md +30 -0
- package/help/errors/service-not-allowed.md +27 -0
- package/help/errors/service-unknown.md +23 -0
- package/help/errors/service-unready.md +49 -0
- package/help/getting-started.md +31 -0
- package/help/github.md +30 -0
- package/help/identity-and-access.md +39 -0
- package/help/mcp.md +30 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +30 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +26 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +12 -3
- package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
- package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
- package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
- package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
- package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
- package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
- package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
- package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
- package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
- package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
- package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
- package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
- package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
- package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
- package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
- package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
- package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
- package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
- package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
- package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
- package/prisma/schema.prisma +407 -21
package/dist/coding/profile.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import { isIP } from "node:net";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
import { isImmutableDockerImage } from "../providers/jobs/docker-isolation.js";
|
|
4
3
|
import { MAX_CODING_TASK_BYTES, normalizeGitHubRepository, normalizeGitRef } from "./protocol.js";
|
|
4
|
+
import { MAX_COLLECT_EXCLUDE_PATHS, validateCollectExcludePath } from "./collect-exclude.js";
|
|
5
5
|
import { CODING_PROVIDERS } from "./provider.js";
|
|
6
|
+
import { WARDBY_PROTECTED_PATHS, isWellFormedProtectedPath, protectsSomePath } from "./protected-paths.js";
|
|
7
|
+
import { parseAllowlist, resolvePolicy } from "./registry/allowlist.js";
|
|
8
|
+
import { REGISTRY_ADAPTERS } from "./registry/adapters.js";
|
|
9
|
+
import { AllowedServiceNamesSchema } from "./services/catalog.js";
|
|
6
10
|
export const MIN_CODING_TIMEOUT_SEC = 60;
|
|
7
11
|
export const MAX_CODING_TIMEOUT_SEC = 7200;
|
|
8
|
-
export const MAX_ALLOWED_EGRESS_HOSTS = 64;
|
|
9
12
|
export const MAX_PROTECTED_PATHS = 128;
|
|
10
13
|
export const DEFAULT_PROTECTED_PATHS = [
|
|
11
14
|
".github/workflows/**",
|
|
12
15
|
".github/CODEOWNERS",
|
|
13
16
|
"CODEOWNERS",
|
|
14
17
|
"docs/CODEOWNERS",
|
|
18
|
+
// Enforced for every run anyway (providers/vcs/git.ts protectedPathMatcher); listed so new agents show it.
|
|
19
|
+
...WARDBY_PROTECTED_PATHS,
|
|
15
20
|
];
|
|
16
|
-
const MAX_HOST_BYTES = 253;
|
|
17
21
|
const MAX_PROTECTED_PATH_BYTES = 512;
|
|
18
22
|
const INVALID_MULTILINE_CONTROL = /[\u0000\u000B\u000C\u000E-\u001F\u007F]/;
|
|
19
23
|
const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
|
|
@@ -50,27 +54,21 @@ const defaultTaskSchema = z
|
|
|
50
54
|
.refine((value) => !INVALID_MULTILINE_CONTROL.test(value), "must not contain control characters")
|
|
51
55
|
.refine((value) => value.trim().length > 0, "must not be blank")
|
|
52
56
|
.nullable();
|
|
53
|
-
const egressHostSchema = z
|
|
54
|
-
.string()
|
|
55
|
-
.transform((value) => value.trim().toLowerCase())
|
|
56
|
-
.refine((value) => value.length > 0 && byteLength(value) <= MAX_HOST_BYTES, "must be a bounded hostname")
|
|
57
|
-
.refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters")
|
|
58
|
-
.refine((value) => isIP(value) === 0, "IP addresses and CIDRs are not allowed")
|
|
59
|
-
.refine((value) => !/^\d+(?:\.\d+){3}$/.test(value), "IP-like hostnames are not allowed")
|
|
60
|
-
.refine((value) => !value.includes("://") &&
|
|
61
|
-
!value.includes("/") &&
|
|
62
|
-
!value.includes("@") &&
|
|
63
|
-
!value.includes(":") &&
|
|
64
|
-
!value.includes("*"), "must be an exact hostname")
|
|
65
|
-
.refine((value) => value !== "localhost" && value.includes("."), "must be a fully qualified hostname")
|
|
66
|
-
.refine((value) => value.split(".").every((label) => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label)), "must be a valid ASCII hostname");
|
|
67
57
|
const protectedPathSchema = z
|
|
68
58
|
.string()
|
|
69
59
|
.transform((value) => value.trim())
|
|
70
60
|
.refine((value) => value.length > 0 && byteLength(value) <= MAX_PROTECTED_PATH_BYTES, "must be a bounded path")
|
|
71
61
|
.refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters")
|
|
72
|
-
.refine(
|
|
73
|
-
|
|
62
|
+
.refine(isWellFormedProtectedPath, "must be a repository-relative POSIX path without empty or traversal components, or ! and a literal file path (no wildcards) for an exception");
|
|
63
|
+
const collectExcludePathSchema = z.string().transform((value, ctx) => {
|
|
64
|
+
try {
|
|
65
|
+
return validateCollectExcludePath(value);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must be a repository-relative path without wildcards" });
|
|
69
|
+
return z.NEVER;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
74
72
|
const KNOWN_TOOLCHAINS = ["node", "node-python"];
|
|
75
73
|
const toolchainSchema = z.enum(KNOWN_TOOLCHAINS);
|
|
76
74
|
const toolchainVersionSchema = z.string().trim().min(1).max(32).nullable();
|
|
@@ -82,6 +80,30 @@ const workerImageRefSchema = z
|
|
|
82
80
|
.refine(isImmutableDockerImage, "must be an immutable repository digest")
|
|
83
81
|
.nullable();
|
|
84
82
|
const workspaceDiskMbSchema = z.number().int().min(64).max(32_768).nullable();
|
|
83
|
+
const packageAllowlistSchema = z
|
|
84
|
+
.record(z.string(), z.array(z.string().min(1).max(256)).max(256))
|
|
85
|
+
.superRefine((value, ctx) => {
|
|
86
|
+
try {
|
|
87
|
+
parseAllowlist(value, REGISTRY_ADAPTERS);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
ctx.addIssue({
|
|
91
|
+
code: z.ZodIssueCode.custom,
|
|
92
|
+
message: error instanceof Error ? error.message : "invalid allowlist",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
const packagePolicySchema = z
|
|
97
|
+
.object({ minReleaseAgeDays: z.number().int().min(0).max(30).optional() })
|
|
98
|
+
.strict()
|
|
99
|
+
.superRefine((value, ctx) => {
|
|
100
|
+
try {
|
|
101
|
+
resolvePolicy(value);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "invalid package policy" });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
85
107
|
const codingProfileFields = {
|
|
86
108
|
provider: z.enum(CODING_PROVIDERS),
|
|
87
109
|
repository: repositorySchema,
|
|
@@ -93,15 +115,20 @@ const codingProfileFields = {
|
|
|
93
115
|
toolchainVersion: toolchainVersionSchema,
|
|
94
116
|
workerImageRef: workerImageRefSchema,
|
|
95
117
|
workspaceDiskMb: workspaceDiskMbSchema,
|
|
96
|
-
allowedEgress: z
|
|
97
|
-
.array(egressHostSchema)
|
|
98
|
-
.max(MAX_ALLOWED_EGRESS_HOSTS)
|
|
99
|
-
.transform((hosts) => [...new Set(hosts)]),
|
|
100
118
|
protectedPaths: z
|
|
101
119
|
.array(protectedPathSchema)
|
|
102
120
|
.min(1)
|
|
103
121
|
.max(MAX_PROTECTED_PATHS)
|
|
122
|
+
.refine(protectsSomePath, "must protect at least one path; entries starting with ! are only exceptions")
|
|
123
|
+
.transform((paths) => [...new Set(paths)]),
|
|
124
|
+
collectExclude: z
|
|
125
|
+
.array(collectExcludePathSchema)
|
|
126
|
+
.max(MAX_COLLECT_EXCLUDE_PATHS)
|
|
104
127
|
.transform((paths) => [...new Set(paths)]),
|
|
128
|
+
packageAllowlist: packageAllowlistSchema,
|
|
129
|
+
packagePolicy: packagePolicySchema,
|
|
130
|
+
/** Coding-run services this agent's runs may start: catalog names, any version (docs/coding-services.md). */
|
|
131
|
+
services: AllowedServiceNamesSchema,
|
|
105
132
|
};
|
|
106
133
|
export const CodingProfileSchema = z
|
|
107
134
|
.object({
|
|
@@ -111,12 +138,15 @@ export const CodingProfileSchema = z
|
|
|
111
138
|
defaultTask: codingProfileFields.defaultTask.default(null),
|
|
112
139
|
allowWebhookTaskOverride: codingProfileFields.allowWebhookTaskOverride.default(false),
|
|
113
140
|
timeoutSec: codingProfileFields.timeoutSec.default(1800),
|
|
114
|
-
allowedEgress: codingProfileFields.allowedEgress.default([]),
|
|
115
141
|
protectedPaths: codingProfileFields.protectedPaths.default([...DEFAULT_PROTECTED_PATHS]),
|
|
142
|
+
collectExclude: codingProfileFields.collectExclude.default([]),
|
|
116
143
|
toolchain: codingProfileFields.toolchain.default("node"),
|
|
117
144
|
toolchainVersion: codingProfileFields.toolchainVersion.default(null),
|
|
118
145
|
workerImageRef: codingProfileFields.workerImageRef.default(null),
|
|
119
146
|
workspaceDiskMb: codingProfileFields.workspaceDiskMb.default(null),
|
|
147
|
+
packageAllowlist: codingProfileFields.packageAllowlist.default({}),
|
|
148
|
+
packagePolicy: codingProfileFields.packagePolicy.default({}),
|
|
149
|
+
services: codingProfileFields.services.default([]),
|
|
120
150
|
})
|
|
121
151
|
.strict();
|
|
122
152
|
export const CodingProfilePatchSchema = z
|
|
@@ -127,11 +157,14 @@ export const CodingProfilePatchSchema = z
|
|
|
127
157
|
defaultTask: codingProfileFields.defaultTask.optional(),
|
|
128
158
|
allowWebhookTaskOverride: codingProfileFields.allowWebhookTaskOverride.optional(),
|
|
129
159
|
timeoutSec: codingProfileFields.timeoutSec.optional(),
|
|
130
|
-
allowedEgress: codingProfileFields.allowedEgress.optional(),
|
|
131
160
|
protectedPaths: codingProfileFields.protectedPaths.optional(),
|
|
161
|
+
collectExclude: codingProfileFields.collectExclude.optional(),
|
|
132
162
|
toolchain: codingProfileFields.toolchain.optional(),
|
|
133
163
|
toolchainVersion: codingProfileFields.toolchainVersion.optional(),
|
|
134
164
|
workerImageRef: codingProfileFields.workerImageRef.optional(),
|
|
135
165
|
workspaceDiskMb: codingProfileFields.workspaceDiskMb.optional(),
|
|
166
|
+
packageAllowlist: codingProfileFields.packageAllowlist.optional(),
|
|
167
|
+
packagePolicy: codingProfileFields.packagePolicy.optional(),
|
|
168
|
+
services: codingProfileFields.services.optional(),
|
|
136
169
|
})
|
|
137
170
|
.strict();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host (a builder continuation comment, a mention status comment) is
|
|
3
|
+
* told when a coding run's changes touched a path this agent may not edit
|
|
4
|
+
* (protectedPathMatcher in src/providers/vcs/git.ts). Public repositories
|
|
5
|
+
* read these, so the path -- taken from the run's own diff -- is treated as
|
|
6
|
+
* untrusted text: it never carries a backtick, a control character, or more
|
|
7
|
+
* than MAX_PATH_CHARS.
|
|
8
|
+
*/
|
|
9
|
+
/** CodingRun.failureCategory for a run whose collected changes touched a protected path. */
|
|
10
|
+
export declare const PROTECTED_PATH_CATEGORY = "protected_path";
|
|
11
|
+
/** The path a `vcs_protected_path:<path>` error names, or null for any other error. */
|
|
12
|
+
export declare function protectedPathFromError(error: unknown): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* The host sentence for a run stopped because its changes touched a
|
|
15
|
+
* protected path. Named the file when `path` sanitises to something usable;
|
|
16
|
+
* otherwise falls back to a sentence that doesn't try to name it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function protectedPathSentence(path: string | null | undefined): string;
|
|
19
|
+
/**
|
|
20
|
+
* The fixed line for a mention status comment naming a failed protected_path
|
|
21
|
+
* sub-run (host-status.ts). That comment reads children from the database,
|
|
22
|
+
* which has no path -- only the category -- so this line never names a file.
|
|
23
|
+
*/
|
|
24
|
+
export declare const PROTECTED_PATH_HOST_LINE = "A sub-run could not open its changes: it changed a file its agent may not edit, so none of its changes were kept.";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host (a builder continuation comment, a mention status comment) is
|
|
3
|
+
* told when a coding run's changes touched a path this agent may not edit
|
|
4
|
+
* (protectedPathMatcher in src/providers/vcs/git.ts). Public repositories
|
|
5
|
+
* read these, so the path -- taken from the run's own diff -- is treated as
|
|
6
|
+
* untrusted text: it never carries a backtick, a control character, or more
|
|
7
|
+
* than MAX_PATH_CHARS.
|
|
8
|
+
*/
|
|
9
|
+
/** CodingRun.failureCategory for a run whose collected changes touched a protected path. */
|
|
10
|
+
export const PROTECTED_PATH_CATEGORY = "protected_path";
|
|
11
|
+
/** git.ts's finalizeChanges throws this when the collected diff touches a protected path. */
|
|
12
|
+
const PROTECTED_PATH_ERROR_PREFIX = "vcs_protected_path:";
|
|
13
|
+
/** The path a `vcs_protected_path:<path>` error names, or null for any other error. */
|
|
14
|
+
export function protectedPathFromError(error) {
|
|
15
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
16
|
+
if (!message.startsWith(PROTECTED_PATH_ERROR_PREFIX))
|
|
17
|
+
return null;
|
|
18
|
+
const path = message.slice(PROTECTED_PATH_ERROR_PREFIX.length);
|
|
19
|
+
return path.length > 0 ? path : null;
|
|
20
|
+
}
|
|
21
|
+
const MAX_PATH_CHARS = 200;
|
|
22
|
+
/**
|
|
23
|
+
* A single-line, backtick-free rendering of a repository path safe to drop
|
|
24
|
+
* into one Markdown code span: control characters and backticks (which would
|
|
25
|
+
* otherwise close the span early) are neutralised, runs of whitespace
|
|
26
|
+
* collapse to one line, and the result is capped with an ellipsis. Null when
|
|
27
|
+
* nothing usable is left.
|
|
28
|
+
*/
|
|
29
|
+
function sanitizePath(path) {
|
|
30
|
+
// eslint-disable-next-line no-control-regex -- deliberately stripping C0/DEL control characters.
|
|
31
|
+
const withoutControls = path.replace(/[\u0000-\u001f\u007f]+/g, " ");
|
|
32
|
+
const oneLine = withoutControls.replace(/\s+/g, " ").trim();
|
|
33
|
+
const withoutBackticks = oneLine.replace(/`/g, "'");
|
|
34
|
+
if (withoutBackticks.length === 0)
|
|
35
|
+
return null;
|
|
36
|
+
return withoutBackticks.length > MAX_PATH_CHARS ? `${withoutBackticks.slice(0, MAX_PATH_CHARS)}…` : withoutBackticks;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The host sentence for a run stopped because its changes touched a
|
|
40
|
+
* protected path. Named the file when `path` sanitises to something usable;
|
|
41
|
+
* otherwise falls back to a sentence that doesn't try to name it.
|
|
42
|
+
*/
|
|
43
|
+
export function protectedPathSentence(path) {
|
|
44
|
+
const safe = path ? sanitizePath(path) : null;
|
|
45
|
+
const named = safe
|
|
46
|
+
? `its changes include \`${safe}\`, which this agent may not edit`
|
|
47
|
+
: "its changes include a file this agent may not edit";
|
|
48
|
+
return `${named}, so none of its changes were kept. Ask again without changing that file, or have the repository owner make that change.`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The fixed line for a mention status comment naming a failed protected_path
|
|
52
|
+
* sub-run (host-status.ts). That comment reads children from the database,
|
|
53
|
+
* which has no path -- only the category -- so this line never names a file.
|
|
54
|
+
*/
|
|
55
|
+
export const PROTECTED_PATH_HOST_LINE = "A sub-run could not open its changes: it changed a file its agent may not edit, so none of its changes were kept.";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protected for every coding run, whatever an agent's own protectedPaths say
|
|
3
|
+
* (docs/coding-services.md): wardby's own configuration under .wardby/, except
|
|
4
|
+
* the service declaration, which any builder may propose in its pull request
|
|
5
|
+
* (it takes effect only after a person merges it, since dispatch reads it from
|
|
6
|
+
* the base branch). Part of DEFAULT_PROTECTED_PATHS so new agents show it, and
|
|
7
|
+
* always added by protectedPathMatcher (providers/vcs/git.ts) so agents created
|
|
8
|
+
* before it existed get it too. The matcher applies it ahead of the agent's own
|
|
9
|
+
* list: the declaration is never protected, and nothing else under .wardby/ can
|
|
10
|
+
* be unprotected by an agent's exceptions.
|
|
11
|
+
*/
|
|
12
|
+
export declare const WARDBY_PROTECTED_PATHS: readonly [".wardby/**", "!.wardby/services.yaml"];
|
|
13
|
+
/**
|
|
14
|
+
* A leading "!" makes a protectedPaths entry an exception (providers/vcs/git.ts
|
|
15
|
+
* protectedPathMatcher): one literal file path carved out of the agent's own
|
|
16
|
+
* patterns. Exceptions take no wildcards, so "!**" or "!.github/**" cannot
|
|
17
|
+
* switch a whole protected tree off.
|
|
18
|
+
*/
|
|
19
|
+
export declare const PROTECTED_PATH_EXCEPTION = "!";
|
|
20
|
+
export declare function isProtectedPathException(path: string): boolean;
|
|
21
|
+
/** The glob of a protectedPaths entry: the entry itself, or what follows an exception's leading "!". */
|
|
22
|
+
export declare function protectedPathBody(path: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether a trimmed protectedPaths entry has a valid shape: a repository-relative
|
|
25
|
+
* POSIX glob with no empty or traversal components, or, behind one leading "!",
|
|
26
|
+
* such a path with no glob metacharacters. Length and control-character bounds
|
|
27
|
+
* are the caller's.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isWellFormedProtectedPath(path: string): boolean;
|
|
30
|
+
/** Exceptions only carve paths out; a list of nothing but exceptions protects nothing. */
|
|
31
|
+
export declare function protectsSomePath(paths: readonly string[]): boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protected for every coding run, whatever an agent's own protectedPaths say
|
|
3
|
+
* (docs/coding-services.md): wardby's own configuration under .wardby/, except
|
|
4
|
+
* the service declaration, which any builder may propose in its pull request
|
|
5
|
+
* (it takes effect only after a person merges it, since dispatch reads it from
|
|
6
|
+
* the base branch). Part of DEFAULT_PROTECTED_PATHS so new agents show it, and
|
|
7
|
+
* always added by protectedPathMatcher (providers/vcs/git.ts) so agents created
|
|
8
|
+
* before it existed get it too. The matcher applies it ahead of the agent's own
|
|
9
|
+
* list: the declaration is never protected, and nothing else under .wardby/ can
|
|
10
|
+
* be unprotected by an agent's exceptions.
|
|
11
|
+
*/
|
|
12
|
+
export const WARDBY_PROTECTED_PATHS = [".wardby/**", "!.wardby/services.yaml"];
|
|
13
|
+
/**
|
|
14
|
+
* A leading "!" makes a protectedPaths entry an exception (providers/vcs/git.ts
|
|
15
|
+
* protectedPathMatcher): one literal file path carved out of the agent's own
|
|
16
|
+
* patterns. Exceptions take no wildcards, so "!**" or "!.github/**" cannot
|
|
17
|
+
* switch a whole protected tree off.
|
|
18
|
+
*/
|
|
19
|
+
export const PROTECTED_PATH_EXCEPTION = "!";
|
|
20
|
+
export function isProtectedPathException(path) {
|
|
21
|
+
return path.startsWith(PROTECTED_PATH_EXCEPTION);
|
|
22
|
+
}
|
|
23
|
+
/** The glob of a protectedPaths entry: the entry itself, or what follows an exception's leading "!". */
|
|
24
|
+
export function protectedPathBody(path) {
|
|
25
|
+
return isProtectedPathException(path) ? path.slice(PROTECTED_PATH_EXCEPTION.length) : path;
|
|
26
|
+
}
|
|
27
|
+
/** Glob metacharacters an exception may not contain: it names one literal file. */
|
|
28
|
+
const EXCEPTION_GLOB_CHARACTERS = /[*?[\]{}]/;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a trimmed protectedPaths entry has a valid shape: a repository-relative
|
|
31
|
+
* POSIX glob with no empty or traversal components, or, behind one leading "!",
|
|
32
|
+
* such a path with no glob metacharacters. Length and control-character bounds
|
|
33
|
+
* are the caller's.
|
|
34
|
+
*/
|
|
35
|
+
export function isWellFormedProtectedPath(path) {
|
|
36
|
+
const body = protectedPathBody(path);
|
|
37
|
+
return (body.length > 0 &&
|
|
38
|
+
!isProtectedPathException(body) &&
|
|
39
|
+
!(isProtectedPathException(path) && EXCEPTION_GLOB_CHARACTERS.test(body)) &&
|
|
40
|
+
!body.startsWith("/") &&
|
|
41
|
+
!body.startsWith("./") &&
|
|
42
|
+
!body.includes("\\") &&
|
|
43
|
+
!body.split("/").some((part) => part === "" || part === "." || part === ".."));
|
|
44
|
+
}
|
|
45
|
+
/** Exceptions only carve paths out; a list of nothing but exceptions protects nothing. */
|
|
46
|
+
export function protectsSomePath(paths) {
|
|
47
|
+
return paths.some((path) => !isProtectedPathException(path));
|
|
48
|
+
}
|
|
@@ -6,6 +6,18 @@ export declare const MAX_CODING_SUMMARY_BYTES: number;
|
|
|
6
6
|
export declare const MAX_CODING_TESTS = 64;
|
|
7
7
|
export declare const MAX_CODING_TEST_COMMAND_BYTES: number;
|
|
8
8
|
export declare const MAX_TAG_BYTES = 32;
|
|
9
|
+
/**
|
|
10
|
+
* Coding-run services (docs/coding-services.md): the catalog name and version
|
|
11
|
+
* grammar, shared by the repository's .wardby/services.yaml, the catalog, and
|
|
12
|
+
* the worker input.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CODING_SERVICE_NAME: RegExp;
|
|
15
|
+
export declare const CODING_SERVICE_VERSION: RegExp;
|
|
16
|
+
export declare const MAX_CODING_SERVICES = 5;
|
|
17
|
+
/** A variable a service hands the agent's shells (DATABASE_URL, PGHOST, REDIS_URL, ...). */
|
|
18
|
+
export declare const CODING_SERVICE_ENV_NAME: RegExp;
|
|
19
|
+
export declare const MAX_CODING_SERVICE_ENV = 16;
|
|
20
|
+
export declare const MAX_CODING_SERVICE_ENV_VALUE_BYTES = 1024;
|
|
9
21
|
/**
|
|
10
22
|
* A worker's output-schema failure, reduced to where and how it failed, never
|
|
11
23
|
* what the model wrote: `<path>:<zod issue code>`, where the path is dot-joined
|
|
@@ -14,6 +26,11 @@ export declare const MAX_TAG_BYTES = 32;
|
|
|
14
26
|
*/
|
|
15
27
|
export declare const MAX_CODING_OUTPUT_ISSUES = 8;
|
|
16
28
|
export declare const SAFE_CODING_OUTPUT_ISSUE: RegExp;
|
|
29
|
+
export declare const INVALID_SINGLE_LINE_CONTROL: RegExp;
|
|
30
|
+
export declare function byteLength(value: string): number;
|
|
31
|
+
export declare function isReservedServiceEnvName(name: string): boolean;
|
|
32
|
+
/** The variables one service hands the agent's shells: upper-case names wardby does not reserve. */
|
|
33
|
+
export declare const CodingServiceTestEnvSchema: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>, Record<string, string>, Record<string, string>>;
|
|
17
34
|
export declare function normalizeGitHubRepository(value: string): string;
|
|
18
35
|
export declare function normalizeGitRef(value: string): string;
|
|
19
36
|
export declare const CodingBaseRefSchema: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
@@ -21,11 +38,12 @@ export declare const CodingTaskOverrideSchema: z.ZodEffects<z.ZodEffects<z.ZodEf
|
|
|
21
38
|
/**
|
|
22
39
|
* A coding worker receives only its task text, so a coding agent's own
|
|
23
40
|
* instructions (its systemPrompt) travel inside that text, ahead of the
|
|
24
|
-
* request
|
|
25
|
-
*
|
|
26
|
-
*
|
|
41
|
+
* request, followed by any note wardby generates for the run (the services it
|
|
42
|
+
* started: src/coding/services/note.ts). Blank instructions and no note leave
|
|
43
|
+
* the task unchanged. The combination must still fit MAX_CODING_TASK_BYTES;
|
|
44
|
+
* exceeding it is an error naming both parts rather than a silent truncation.
|
|
27
45
|
*/
|
|
28
|
-
export declare function composeCodingTask(instructions: string | null | undefined, task: string): string;
|
|
46
|
+
export declare function composeCodingTask(instructions: string | null | undefined, task: string, note?: string): string;
|
|
29
47
|
/**
|
|
30
48
|
* The tag only labels a pull request title, so a model's malformed tag must not
|
|
31
49
|
* sink an otherwise finished run. A tag that already passes is kept as-is; any
|
|
@@ -35,6 +53,8 @@ export declare function composeCodingTask(instructions: string | null | undefine
|
|
|
35
53
|
* re-validates whatever survives.
|
|
36
54
|
*/
|
|
37
55
|
export declare function normalizeCodingTag(value: unknown): string | null | undefined;
|
|
56
|
+
/** Longest line a debug-traced worker writes to its log (src/coding-worker/debug-trace.ts). */
|
|
57
|
+
export declare const MAX_DEBUG_TRACE_LINE_BYTES: number;
|
|
38
58
|
export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
39
59
|
schemaVersion: z.ZodLiteral<1>;
|
|
40
60
|
runId: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>;
|
|
@@ -60,6 +80,33 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
60
80
|
}, {
|
|
61
81
|
runId: string;
|
|
62
82
|
}>>;
|
|
83
|
+
/**
|
|
84
|
+
* Admin-requested debug trace (CodingAgentProfile.debugTraceUntil): the
|
|
85
|
+
* worker writes its full stream trace to its own log. Absent means off;
|
|
86
|
+
* the control plane writes the key only when true, so an input for an
|
|
87
|
+
* untraced run is unchanged for workers that predate it.
|
|
88
|
+
*/
|
|
89
|
+
debugTrace: z.ZodOptional<z.ZodBoolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Coding-run services started next to this run (docs/coding-services.md):
|
|
92
|
+
* each one's catalog name and version, and the variables the agent's shells
|
|
93
|
+
* receive. Absent means none; the control plane writes the key only when a
|
|
94
|
+
* run has services, so every other input is unchanged for workers that
|
|
95
|
+
* predate it.
|
|
96
|
+
*/
|
|
97
|
+
services: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
98
|
+
name: z.ZodString;
|
|
99
|
+
version: z.ZodString;
|
|
100
|
+
testEnv: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>, Record<string, string>, Record<string, string>>;
|
|
101
|
+
}, "strict", z.ZodTypeAny, {
|
|
102
|
+
name: string;
|
|
103
|
+
version: string;
|
|
104
|
+
testEnv: Record<string, string>;
|
|
105
|
+
}, {
|
|
106
|
+
name: string;
|
|
107
|
+
version: string;
|
|
108
|
+
testEnv: Record<string, string>;
|
|
109
|
+
}>, "many">>;
|
|
63
110
|
}, "strict", z.ZodTypeAny, {
|
|
64
111
|
repository: string;
|
|
65
112
|
schemaVersion: 1;
|
|
@@ -73,6 +120,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
73
120
|
continuationOf?: {
|
|
74
121
|
runId: string;
|
|
75
122
|
} | undefined;
|
|
123
|
+
debugTrace?: boolean | undefined;
|
|
124
|
+
services?: {
|
|
125
|
+
name: string;
|
|
126
|
+
version: string;
|
|
127
|
+
testEnv: Record<string, string>;
|
|
128
|
+
}[] | undefined;
|
|
76
129
|
}, {
|
|
77
130
|
repository: string;
|
|
78
131
|
schemaVersion: 1;
|
|
@@ -86,6 +139,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
86
139
|
continuationOf?: {
|
|
87
140
|
runId: string;
|
|
88
141
|
} | undefined;
|
|
142
|
+
debugTrace?: boolean | undefined;
|
|
143
|
+
services?: {
|
|
144
|
+
name: string;
|
|
145
|
+
version: string;
|
|
146
|
+
testEnv: Record<string, string>;
|
|
147
|
+
}[] | undefined;
|
|
89
148
|
}>, {
|
|
90
149
|
repository: string;
|
|
91
150
|
schemaVersion: 1;
|
|
@@ -99,6 +158,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
99
158
|
continuationOf?: {
|
|
100
159
|
runId: string;
|
|
101
160
|
} | undefined;
|
|
161
|
+
debugTrace?: boolean | undefined;
|
|
162
|
+
services?: {
|
|
163
|
+
name: string;
|
|
164
|
+
version: string;
|
|
165
|
+
testEnv: Record<string, string>;
|
|
166
|
+
}[] | undefined;
|
|
102
167
|
}, {
|
|
103
168
|
repository: string;
|
|
104
169
|
schemaVersion: 1;
|
|
@@ -112,6 +177,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
|
|
|
112
177
|
continuationOf?: {
|
|
113
178
|
runId: string;
|
|
114
179
|
} | undefined;
|
|
180
|
+
debugTrace?: boolean | undefined;
|
|
181
|
+
services?: {
|
|
182
|
+
name: string;
|
|
183
|
+
version: string;
|
|
184
|
+
testEnv: Record<string, string>;
|
|
185
|
+
}[] | undefined;
|
|
115
186
|
}>;
|
|
116
187
|
export declare const CodingAgentOutputSchema: z.ZodEffects<z.ZodObject<{
|
|
117
188
|
schemaVersion: z.ZodLiteral<1>;
|
package/dist/coding/protocol.js
CHANGED
|
@@ -6,6 +6,18 @@ export const MAX_CODING_SUMMARY_BYTES = 8 * 1024;
|
|
|
6
6
|
export const MAX_CODING_TESTS = 64;
|
|
7
7
|
export const MAX_CODING_TEST_COMMAND_BYTES = 2 * 1024;
|
|
8
8
|
export const MAX_TAG_BYTES = 32;
|
|
9
|
+
/**
|
|
10
|
+
* Coding-run services (docs/coding-services.md): the catalog name and version
|
|
11
|
+
* grammar, shared by the repository's .wardby/services.yaml, the catalog, and
|
|
12
|
+
* the worker input.
|
|
13
|
+
*/
|
|
14
|
+
export const CODING_SERVICE_NAME = /^[a-z][a-z0-9-]{0,39}$/;
|
|
15
|
+
export const CODING_SERVICE_VERSION = /^[0-9A-Za-z][0-9A-Za-z._-]{0,19}$/;
|
|
16
|
+
export const MAX_CODING_SERVICES = 5;
|
|
17
|
+
/** A variable a service hands the agent's shells (DATABASE_URL, PGHOST, REDIS_URL, ...). */
|
|
18
|
+
export const CODING_SERVICE_ENV_NAME = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
19
|
+
export const MAX_CODING_SERVICE_ENV = 16;
|
|
20
|
+
export const MAX_CODING_SERVICE_ENV_VALUE_BYTES = 1024;
|
|
9
21
|
/**
|
|
10
22
|
* A worker's output-schema failure, reduced to where and how it failed, never
|
|
11
23
|
* what the model wrote: `<path>:<zod issue code>`, where the path is dot-joined
|
|
@@ -21,8 +33,8 @@ const MAX_RUN_ID_BYTES = 128;
|
|
|
21
33
|
const MAX_COST_USD = 1_000_000;
|
|
22
34
|
const MAX_JSON_NESTING_DEPTH = 64;
|
|
23
35
|
const INVALID_MULTILINE_CONTROL = /[\u0000\u000B\u000C\u000E-\u001F\u007F]/;
|
|
24
|
-
const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
|
|
25
|
-
function byteLength(value) {
|
|
36
|
+
export const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
|
|
37
|
+
export function byteLength(value) {
|
|
26
38
|
return Buffer.byteLength(value, "utf8");
|
|
27
39
|
}
|
|
28
40
|
function boundedText(maxBytes, singleLine = false) {
|
|
@@ -33,6 +45,72 @@ function boundedText(maxBytes, singleLine = false) {
|
|
|
33
45
|
.refine((value) => !invalidControl.test(value), "must not contain control characters")
|
|
34
46
|
.refine((value) => value.trim().length > 0, "must not be blank");
|
|
35
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Names the worker owns: its shell basics, anything that would redirect a
|
|
50
|
+
* process's loader or network proxy, and the registry proxy's and Wardby's own
|
|
51
|
+
* settings. No service may set one, whatever its catalog entry says.
|
|
52
|
+
*/
|
|
53
|
+
const RESERVED_SERVICE_ENV_NAMES = new Set([
|
|
54
|
+
"HOME",
|
|
55
|
+
"LANG",
|
|
56
|
+
"LC_ALL",
|
|
57
|
+
"PATH",
|
|
58
|
+
"SHELL",
|
|
59
|
+
"TMPDIR",
|
|
60
|
+
"USER",
|
|
61
|
+
"LD_PRELOAD",
|
|
62
|
+
"LD_LIBRARY_PATH",
|
|
63
|
+
"NODE_OPTIONS",
|
|
64
|
+
"NODE_PATH",
|
|
65
|
+
"PYTHONPATH",
|
|
66
|
+
"PYTHONHOME",
|
|
67
|
+
"HTTP_PROXY",
|
|
68
|
+
"HTTPS_PROXY",
|
|
69
|
+
"NO_PROXY",
|
|
70
|
+
"ALL_PROXY",
|
|
71
|
+
"SSL_CERT_FILE",
|
|
72
|
+
"SSL_CERT_DIR",
|
|
73
|
+
]);
|
|
74
|
+
const RESERVED_SERVICE_ENV_PREFIXES = [
|
|
75
|
+
"WARDBY_",
|
|
76
|
+
"CODEX_",
|
|
77
|
+
"OPENAI_",
|
|
78
|
+
"ANTHROPIC_",
|
|
79
|
+
"PIP_",
|
|
80
|
+
"NPM_CONFIG_",
|
|
81
|
+
"UV_",
|
|
82
|
+
"GIT_",
|
|
83
|
+
];
|
|
84
|
+
export function isReservedServiceEnvName(name) {
|
|
85
|
+
return (RESERVED_SERVICE_ENV_NAMES.has(name) || RESERVED_SERVICE_ENV_PREFIXES.some((prefix) => name.startsWith(prefix)));
|
|
86
|
+
}
|
|
87
|
+
const serviceEnvValueSchema = z
|
|
88
|
+
.string()
|
|
89
|
+
.refine((value) => byteLength(value) <= MAX_CODING_SERVICE_ENV_VALUE_BYTES, `must be at most ${MAX_CODING_SERVICE_ENV_VALUE_BYTES} UTF-8 bytes`)
|
|
90
|
+
.refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters");
|
|
91
|
+
/** The variables one service hands the agent's shells: upper-case names wardby does not reserve. */
|
|
92
|
+
export const CodingServiceTestEnvSchema = z.record(z.string(), serviceEnvValueSchema).superRefine((env, ctx) => {
|
|
93
|
+
const names = Object.keys(env);
|
|
94
|
+
if (names.length > MAX_CODING_SERVICE_ENV) {
|
|
95
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: `must have at most ${MAX_CODING_SERVICE_ENV} variables` });
|
|
96
|
+
}
|
|
97
|
+
for (const name of names) {
|
|
98
|
+
if (!CODING_SERVICE_ENV_NAME.test(name) || isReservedServiceEnvName(name)) {
|
|
99
|
+
ctx.addIssue({
|
|
100
|
+
code: z.ZodIssueCode.custom,
|
|
101
|
+
path: [name],
|
|
102
|
+
message: "must be an upper-case variable name wardby does not reserve",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const workerServiceSchema = z
|
|
108
|
+
.object({
|
|
109
|
+
name: z.string().regex(CODING_SERVICE_NAME),
|
|
110
|
+
version: z.string().regex(CODING_SERVICE_VERSION),
|
|
111
|
+
testEnv: CodingServiceTestEnvSchema,
|
|
112
|
+
})
|
|
113
|
+
.strict();
|
|
36
114
|
function repositoryParts(value) {
|
|
37
115
|
if (byteLength(value) > MAX_REPOSITORY_INPUT_BYTES || INVALID_SINGLE_LINE_CONTROL.test(value)) {
|
|
38
116
|
throw new Error("invalid GitHub repository");
|
|
@@ -119,12 +197,13 @@ export const CodingTaskOverrideSchema = boundedText(MAX_CODING_TASK_BYTES);
|
|
|
119
197
|
/**
|
|
120
198
|
* A coding worker receives only its task text, so a coding agent's own
|
|
121
199
|
* instructions (its systemPrompt) travel inside that text, ahead of the
|
|
122
|
-
* request
|
|
123
|
-
*
|
|
124
|
-
*
|
|
200
|
+
* request, followed by any note wardby generates for the run (the services it
|
|
201
|
+
* started: src/coding/services/note.ts). Blank instructions and no note leave
|
|
202
|
+
* the task unchanged. The combination must still fit MAX_CODING_TASK_BYTES;
|
|
203
|
+
* exceeding it is an error naming both parts rather than a silent truncation.
|
|
125
204
|
*/
|
|
126
|
-
export function composeCodingTask(instructions, task) {
|
|
127
|
-
const standing = instructions?.trim();
|
|
205
|
+
export function composeCodingTask(instructions, task, note) {
|
|
206
|
+
const standing = [instructions?.trim(), note?.trim()].filter((part) => Boolean(part)).join("\n\n");
|
|
128
207
|
if (!standing)
|
|
129
208
|
return task;
|
|
130
209
|
const composed = `Standing instructions for this coding agent:\n${standing}\n\nRequest:\n${task}`;
|
|
@@ -186,6 +265,8 @@ const testResultSchema = z
|
|
|
186
265
|
outcome: z.enum(["passed", "failed", "skipped"]),
|
|
187
266
|
})
|
|
188
267
|
.strict();
|
|
268
|
+
/** Longest line a debug-traced worker writes to its log (src/coding-worker/debug-trace.ts). */
|
|
269
|
+
export const MAX_DEBUG_TRACE_LINE_BYTES = 16 * 1024;
|
|
189
270
|
export const CodingTaskInputSchema = z
|
|
190
271
|
.object({
|
|
191
272
|
schemaVersion: z.literal(CODING_PROTOCOL_VERSION),
|
|
@@ -206,6 +287,21 @@ export const CodingTaskInputSchema = z
|
|
|
206
287
|
* only enforces that headRef is internally consistent with it.
|
|
207
288
|
*/
|
|
208
289
|
continuationOf: z.object({ runId: runIdSchema }).strict().optional(),
|
|
290
|
+
/**
|
|
291
|
+
* Admin-requested debug trace (CodingAgentProfile.debugTraceUntil): the
|
|
292
|
+
* worker writes its full stream trace to its own log. Absent means off;
|
|
293
|
+
* the control plane writes the key only when true, so an input for an
|
|
294
|
+
* untraced run is unchanged for workers that predate it.
|
|
295
|
+
*/
|
|
296
|
+
debugTrace: z.boolean().optional(),
|
|
297
|
+
/**
|
|
298
|
+
* Coding-run services started next to this run (docs/coding-services.md):
|
|
299
|
+
* each one's catalog name and version, and the variables the agent's shells
|
|
300
|
+
* receive. Absent means none; the control plane writes the key only when a
|
|
301
|
+
* run has services, so every other input is unchanged for workers that
|
|
302
|
+
* predate it.
|
|
303
|
+
*/
|
|
304
|
+
services: z.array(workerServiceSchema).min(1).max(MAX_CODING_SERVICES).optional(),
|
|
209
305
|
})
|
|
210
306
|
.strict()
|
|
211
307
|
.superRefine((value, ctx) => {
|
|
@@ -217,6 +313,10 @@ export const CodingTaskInputSchema = z
|
|
|
217
313
|
message: "must match wardby/run-<runId> (or wardby/run-<continuationOf.runId>)",
|
|
218
314
|
});
|
|
219
315
|
}
|
|
316
|
+
const names = (value.services ?? []).map((service) => service.name);
|
|
317
|
+
if (new Set(names).size !== names.length) {
|
|
318
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["services"], message: "must name each service once" });
|
|
319
|
+
}
|
|
220
320
|
});
|
|
221
321
|
export const CodingAgentOutputSchema = z
|
|
222
322
|
.object({
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registry adapter map: every ecosystem the coding package registry
|
|
3
|
+
* proxies, keyed by its EcosystemId. Adding a new ecosystem means adding it
|
|
4
|
+
* here (and to the allowlist/profile validation that reads this map) --
|
|
5
|
+
* nothing else in the registry core hardcodes "npm" or "pypi".
|
|
6
|
+
*/
|
|
7
|
+
import { npmAdapter } from "./npm.js";
|
|
8
|
+
import { pypiAdapter } from "./pypi.js";
|
|
9
|
+
export const REGISTRY_ADAPTERS = new Map([npmAdapter, pypiAdapter].map((adapter) => [adapter.id, adapter]));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AllowlistEntry, RegistryAdapter } from "./types.js";
|
|
2
|
+
export type PackageAllowlist = Readonly<Record<string, readonly string[]>>;
|
|
3
|
+
export interface PackagePolicy {
|
|
4
|
+
minReleaseAgeDays: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const DEFAULT_MIN_RELEASE_AGE_DAYS = 3;
|
|
7
|
+
export declare function resolvePolicy(value: unknown): PackagePolicy;
|
|
8
|
+
export declare function parseAllowlist(allowlist: PackageAllowlist, adapters: ReadonlyMap<string, RegistryAdapter>): Map<string, AllowlistEntry[]>;
|
|
9
|
+
export declare function matchRoot(entries: readonly AllowlistEntry[], normalizedName: string): AllowlistEntry | undefined;
|