@wardby/cli 0.2.0 → 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 +183 -71
- package/dist/claude-coding-worker/driver.d.ts +7 -1
- package/dist/claude-coding-worker/driver.js +31 -2
- package/dist/claude-coding-worker/main.js +5 -2
- 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 +99 -3
- package/dist/coding/protocol.js +155 -4
- 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 +18 -0
- package/dist/coding-worker/artifact.js +48 -6
- 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 +14 -1
- package/dist/coding-worker/driver.js +106 -14
- package/dist/coding-worker/errors.d.ts +7 -0
- package/dist/coding-worker/errors.js +26 -0
- package/dist/coding-worker/main.js +13 -4
- 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 +109 -6
- 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/coding-queue.d.ts +1 -1
- package/dist/core/datastores.d.ts +1 -1
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +40 -2
- package/dist/core/db.js +75 -2
- package/dist/core/dispatch.d.ts +49 -7
- package/dist/core/dispatch.js +290 -45
- 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/http-runtime.js +3 -4
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/lease.d.ts +1 -1
- package/dist/core/private-directory.d.ts +20 -0
- package/dist/core/private-directory.js +36 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +39 -3
- 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 +31 -9
- package/dist/core/runner.js +237 -40
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/secrets.d.ts +12 -3
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +2 -2
- 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 +9 -2
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +328 -0
- package/dist/generated/prisma/browser.js +17 -0
- package/dist/generated/prisma/client.d.ts +347 -0
- package/dist/generated/prisma/client.js +34 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +839 -0
- package/dist/generated/prisma/commonInputTypes.js +10 -0
- package/dist/generated/prisma/enums.d.ts +59 -0
- package/dist/generated/prisma/enums.js +59 -0
- package/dist/generated/prisma/internal/class.d.ts +605 -0
- package/dist/generated/prisma/internal/class.js +49 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +4494 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +628 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +635 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +599 -0
- package/dist/generated/prisma/models/Agent.d.ts +3560 -0
- package/dist/generated/prisma/models/Agent.js +1 -0
- package/dist/generated/prisma/models/AgentDatastore.d.ts +1210 -0
- package/dist/generated/prisma/models/AgentDatastore.js +1 -0
- package/dist/generated/prisma/models/AgentMemory.d.ts +986 -0
- package/dist/generated/prisma/models/AgentMemory.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/AgentSecret.d.ts +1212 -0
- package/dist/generated/prisma/models/AgentSecret.js +1 -0
- package/dist/generated/prisma/models/AgentSubAgent.d.ts +1217 -0
- package/dist/generated/prisma/models/AgentSubAgent.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +1403 -0
- package/dist/generated/prisma/models/AgentTool.js +1 -0
- package/dist/generated/prisma/models/AuthFormChallenge.d.ts +1298 -0
- package/dist/generated/prisma/models/AuthFormChallenge.js +1 -0
- package/dist/generated/prisma/models/AuthLoginKey.d.ts +1245 -0
- package/dist/generated/prisma/models/AuthLoginKey.js +1 -0
- package/dist/generated/prisma/models/AuthRateLimit.d.ts +979 -0
- package/dist/generated/prisma/models/AuthRateLimit.js +1 -0
- package/dist/generated/prisma/models/AuthSession.d.ts +1376 -0
- package/dist/generated/prisma/models/AuthSession.js +1 -0
- package/dist/generated/prisma/models/AuthUser.d.ts +1700 -0
- package/dist/generated/prisma/models/AuthUser.js +1 -0
- package/dist/generated/prisma/models/BudgetGroup.d.ts +1548 -0
- package/dist/generated/prisma/models/BudgetGroup.js +1 -0
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +1681 -0
- package/dist/generated/prisma/models/CodingAgentProfile.js +1 -0
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +1749 -0
- package/dist/generated/prisma/models/CodingProxyRequest.js +1 -0
- package/dist/generated/prisma/models/CodingProxySession.d.ts +1626 -0
- package/dist/generated/prisma/models/CodingProxySession.js +1 -0
- package/dist/generated/prisma/models/CodingRun.d.ts +3583 -0
- package/dist/generated/prisma/models/CodingRun.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/Datastore.d.ts +1434 -0
- package/dist/generated/prisma/models/Datastore.js +1 -0
- package/dist/generated/prisma/models/DatastoreEntry.d.ts +1314 -0
- package/dist/generated/prisma/models/DatastoreEntry.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/OAuthAuthorizationCode.d.ts +1526 -0
- package/dist/generated/prisma/models/OAuthAuthorizationCode.js +1 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.d.ts +1350 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.js +1 -0
- package/dist/generated/prisma/models/OAuthClient.d.ts +1289 -0
- package/dist/generated/prisma/models/OAuthClient.js +1 -0
- package/dist/generated/prisma/models/OAuthFamily.d.ts +1540 -0
- package/dist/generated/prisma/models/OAuthFamily.js +1 -0
- package/dist/generated/prisma/models/OAuthGrant.d.ts +1280 -0
- package/dist/generated/prisma/models/OAuthGrant.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +2245 -0
- package/dist/generated/prisma/models/Principal.js +1 -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 +2669 -0
- package/dist/generated/prisma/models/Run.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/SchedulerLease.d.ts +970 -0
- package/dist/generated/prisma/models/SchedulerLease.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +1399 -0
- package/dist/generated/prisma/models/Secret.js +1 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.d.ts +973 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.js +1 -0
- package/dist/generated/prisma/models/Task.d.ts +1176 -0
- package/dist/generated/prisma/models/Task.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +1490 -0
- package/dist/generated/prisma/models/Tool.js +1 -0
- package/dist/generated/prisma/models/Webhook.d.ts +1386 -0
- package/dist/generated/prisma/models/Webhook.js +1 -0
- package/dist/generated/prisma/models.d.ts +45 -0
- package/dist/generated/prisma/models.js +1 -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 +6 -1
- package/dist/import/create.js +68 -14
- package/dist/import/index.d.ts +1 -1
- 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 +37 -63
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/principal.d.ts +1 -1
- 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 +32 -3
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +22 -8
- package/dist/mcp/auth/self-hosted/cli.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +21 -3
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/rate-limit.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/session.d.ts +3 -2
- package/dist/mcp/context.d.ts +28 -2
- 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.d.ts +1 -1
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/shared/page-style.d.ts +16 -0
- package/dist/mcp/shared/page-style.js +129 -0
- package/dist/mcp/tasks/manager.d.ts +1 -1
- package/dist/mcp/tools/agents.js +447 -49
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +23 -16
- 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 +4 -7
- package/dist/mcp/tools/secret-elicitation-form.d.ts +1 -1
- package/dist/mcp/tools/secret-elicitation-form.js +10 -28
- package/dist/mcp/tools/secret-elicitation.d.ts +1 -1
- 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 +53 -17
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +202 -41
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +11 -1
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/mcp/unattended-schedules.d.ts +1 -1
- package/dist/mcp/webhooks/ingress.d.ts +1 -1
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +3 -1
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +4 -3
- 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 +18 -1
- 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 +18 -1
- 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/datastore/postgres.d.ts +1 -1
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +3 -3
- package/dist/providers/executor/composition.d.ts +4 -1
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +106 -4
- package/dist/providers/executor/container.js +305 -22
- package/dist/providers/executor/dbos.d.ts +3 -4
- 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 +60 -2
- package/dist/providers/jobs/docker.js +313 -50
- 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 +117 -31
- package/dist/providers/jobs/types.d.ts +20 -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/memory/postgres.d.ts +1 -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 +79 -14
- 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 +34 -32
- package/dist/quickstart/migrate.d.ts +23 -0
- package/dist/quickstart/migrate.js +125 -0
- 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 +30 -11
- package/prisma/migrate.config.mjs +20 -0
- 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 +417 -23
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentRepository CRUD — which repositories on which code-review host a
|
|
3
|
+
* native agent may act on, and which host events trigger it. Linking needs
|
|
4
|
+
* more than owning the agent: the owner's own linked GitHub account must have
|
|
5
|
+
* the link's access on the repository (write for a write link, read for a
|
|
6
|
+
* read link), or a wardby admin must approve it explicitly (adminOverride).
|
|
7
|
+
* The authorization is stamped on the link and re-checked whenever the link
|
|
8
|
+
* is used (core/repo-access.ts). A repository is an owner binding (resource-
|
|
9
|
+
* sharing grants spec §3.4.3): link/unlink are the agent owner's alone (or
|
|
10
|
+
* an admin's explicit approval), whatever grants others hold on the agent,
|
|
11
|
+
* and owner-less agents can't be linked.
|
|
12
|
+
* See docs/private/2026-09-26-repo-access-authorization-spec-and-plan.md.
|
|
13
|
+
*/
|
|
14
|
+
import { Prisma } from "#prisma";
|
|
15
|
+
import { normalizeGitHubRepository } from "../../coding/protocol.js";
|
|
16
|
+
import { requireAgentAccess, requireBindingOwner } from "../auth/access.js";
|
|
17
|
+
import { authorizeRepositoryForSet } from "../auth/repo-authorization.js";
|
|
18
|
+
import { requireScope } from "../auth/resource-server.js";
|
|
19
|
+
import { McpError } from "../errors.js";
|
|
20
|
+
import { textResult } from "./text-result.js";
|
|
21
|
+
const PROVIDERS = ["github"];
|
|
22
|
+
const TRIGGERS = ["pull_request", "mention"];
|
|
23
|
+
const CHECK_NAME = /^[A-Za-z0-9][A-Za-z0-9 ._/()-]{0,99}$/;
|
|
24
|
+
function normalizeRepository(provider, repository) {
|
|
25
|
+
try {
|
|
26
|
+
if (provider === "github")
|
|
27
|
+
return normalizeGitHubRepository(repository);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// fall through
|
|
31
|
+
}
|
|
32
|
+
throw new McpError(400, `invalid repository "${repository}" for provider ${provider}`);
|
|
33
|
+
}
|
|
34
|
+
async function assertNoConflicts(tx, args) {
|
|
35
|
+
if (args.triggers.length === 0 && args.checkName === null)
|
|
36
|
+
return;
|
|
37
|
+
const others = await tx.agentRepository.findMany({
|
|
38
|
+
where: { provider: args.provider, repository: args.repository, NOT: { agentId: args.agentId } },
|
|
39
|
+
});
|
|
40
|
+
if (args.triggers.includes("mention") && others.some((o) => o.triggers.includes("mention"))) {
|
|
41
|
+
throw new McpError(409, `Another agent already handles @-mentions on ${args.repository}.`);
|
|
42
|
+
}
|
|
43
|
+
// Against every other link, whatever its triggers: a check name identifies
|
|
44
|
+
// one agent's verdict on the repository (also a unique index).
|
|
45
|
+
if (args.checkName !== null && others.some((o) => o.checkName === args.checkName)) {
|
|
46
|
+
throw checkNameTaken(args.checkName, args.repository);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function checkNameTaken(checkName, repository) {
|
|
50
|
+
return new McpError(409, `Another agent already uses check name "${checkName}" on ${repository}.`);
|
|
51
|
+
}
|
|
52
|
+
export function registerRepositoryTools(mcp) {
|
|
53
|
+
mcp.registerTool({
|
|
54
|
+
name: "link_repository",
|
|
55
|
+
scope: "agents:write",
|
|
56
|
+
description: "Links a native agent you own to a repository on a code-review host, with its access, event triggers, and checkName. " +
|
|
57
|
+
"Your linked GitHub account (link_host_account) must have write access to the repository for a write link, or read for a " +
|
|
58
|
+
"read link; a wardby admin may instead approve it with adminOverride. checkName is only allowed (and required) with the " +
|
|
59
|
+
"pull_request trigger, and is unique per repository. Re-linking an already-linked repository replaces its access, " +
|
|
60
|
+
"triggers, and checkName (an omitted field is cleared, not kept) and re-checks access — always send the full desired state.",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
additionalProperties: false,
|
|
64
|
+
properties: {
|
|
65
|
+
agentId: { type: "string" },
|
|
66
|
+
provider: { type: "string", enum: [...PROVIDERS] },
|
|
67
|
+
repository: { type: "string", minLength: 1, maxLength: 300 },
|
|
68
|
+
access: { type: "string", enum: ["read", "write"] },
|
|
69
|
+
triggers: { type: "array", items: { type: "string", enum: [...TRIGGERS] }, uniqueItems: true },
|
|
70
|
+
checkName: { type: "string", minLength: 1, maxLength: 100 },
|
|
71
|
+
adminOverride: {
|
|
72
|
+
type: "boolean",
|
|
73
|
+
description: "Admins only (agents:admin with the admin role): approve this link without checking GitHub access, recorded as an admin approval. Allowed on any agent that has an owner, not only the admin's own.",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
required: ["agentId", "repository", "access"],
|
|
77
|
+
},
|
|
78
|
+
handler: async (args, ctx) => {
|
|
79
|
+
// An admin approving a repository explicitly may do it on any agent
|
|
80
|
+
// (the role already allows reassigning any agent with make_owner);
|
|
81
|
+
// everyone else, admins included, links only agents they own.
|
|
82
|
+
let agent;
|
|
83
|
+
if (args.adminOverride === true) {
|
|
84
|
+
requireScope(ctx, ctx.canonicalUri, "agents:admin");
|
|
85
|
+
agent = await ctx.db.agent.findUnique({ where: { id: args.agentId } });
|
|
86
|
+
if (!agent)
|
|
87
|
+
throw new McpError(404, `Agent "${args.agentId}" not found.`);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
agent = (await requireAgentAccess(ctx, args.agentId, "read")).agent;
|
|
91
|
+
requireBindingOwner(ctx, agent);
|
|
92
|
+
}
|
|
93
|
+
if (agent.kind !== "native") {
|
|
94
|
+
throw new McpError(400, "Repository links are for native agents only; coding agents use codingProfile.repository.");
|
|
95
|
+
}
|
|
96
|
+
const provider = args.provider ?? "github";
|
|
97
|
+
const repository = normalizeRepository(provider, args.repository);
|
|
98
|
+
const triggers = [...new Set(args.triggers ?? [])];
|
|
99
|
+
if (triggers.length > 0 && args.access !== "write")
|
|
100
|
+
throw new McpError(400, "Event triggers need write access.");
|
|
101
|
+
const checkName = args.checkName ?? null;
|
|
102
|
+
if (triggers.includes("pull_request") && !checkName) {
|
|
103
|
+
throw new McpError(400, "checkName is required with the pull_request trigger.");
|
|
104
|
+
}
|
|
105
|
+
if (checkName !== null && !triggers.includes("pull_request")) {
|
|
106
|
+
throw new McpError(400, "checkName needs the pull_request trigger (a check is only published for a dispatched PR).");
|
|
107
|
+
}
|
|
108
|
+
if (checkName !== null && !CHECK_NAME.test(checkName))
|
|
109
|
+
throw new McpError(400, "invalid checkName");
|
|
110
|
+
// The host call happens before, and outside, the serializable transaction.
|
|
111
|
+
const authorization = await authorizeRepositoryForSet(ctx, {
|
|
112
|
+
ownerId: agent.ownerId,
|
|
113
|
+
provider,
|
|
114
|
+
repository,
|
|
115
|
+
kind: args.access,
|
|
116
|
+
adminOverride: args.adminOverride === true,
|
|
117
|
+
});
|
|
118
|
+
let link;
|
|
119
|
+
try {
|
|
120
|
+
link = await ctx.db.$transaction(async (tx) => {
|
|
121
|
+
await assertNoConflicts(tx, { agentId: args.agentId, provider, repository, triggers, checkName });
|
|
122
|
+
const fields = { access: args.access, triggers, checkName, ...authorization };
|
|
123
|
+
return tx.agentRepository.upsert({
|
|
124
|
+
where: { agentId_provider_repository: { agentId: args.agentId, provider, repository } },
|
|
125
|
+
create: { agentId: args.agentId, provider, repository, ...fields },
|
|
126
|
+
update: fields,
|
|
127
|
+
});
|
|
128
|
+
}, { isolationLevel: "Serializable" });
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
if (checkName !== null && err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002") {
|
|
132
|
+
throw checkNameTaken(checkName, repository);
|
|
133
|
+
}
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
return textResult({ linked: true, link });
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
mcp.registerTool({
|
|
140
|
+
name: "unlink_repository",
|
|
141
|
+
scope: "agents:write",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
additionalProperties: false,
|
|
145
|
+
properties: {
|
|
146
|
+
agentId: { type: "string" },
|
|
147
|
+
provider: { type: "string", enum: [...PROVIDERS] },
|
|
148
|
+
repository: { type: "string", minLength: 1, maxLength: 300 },
|
|
149
|
+
},
|
|
150
|
+
required: ["agentId", "repository"],
|
|
151
|
+
},
|
|
152
|
+
handler: async (args, ctx) => {
|
|
153
|
+
const { agent } = await requireAgentAccess(ctx, args.agentId, "read");
|
|
154
|
+
requireBindingOwner(ctx, agent);
|
|
155
|
+
const provider = args.provider ?? "github";
|
|
156
|
+
const repository = normalizeRepository(provider, args.repository);
|
|
157
|
+
const { count } = await ctx.db.agentRepository.deleteMany({
|
|
158
|
+
where: { agentId: args.agentId, provider, repository },
|
|
159
|
+
});
|
|
160
|
+
return textResult({ unlinked: count > 0 });
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
mcp.registerTool({
|
|
164
|
+
name: "list_repositories",
|
|
165
|
+
scope: "agents:read",
|
|
166
|
+
inputSchema: {
|
|
167
|
+
type: "object",
|
|
168
|
+
additionalProperties: false,
|
|
169
|
+
properties: { agentId: { type: "string" } },
|
|
170
|
+
required: ["agentId"],
|
|
171
|
+
},
|
|
172
|
+
handler: async (args, ctx) => {
|
|
173
|
+
await requireAgentAccess(ctx, args.agentId, "read");
|
|
174
|
+
const links = await ctx.db.agentRepository.findMany({
|
|
175
|
+
where: { agentId: args.agentId },
|
|
176
|
+
orderBy: { createdAt: "asc" },
|
|
177
|
+
});
|
|
178
|
+
return textResult({ repositories: links });
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
package/dist/mcp/tools/runs.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { WardbyMcpServer } from "../server.js";
|
|
2
|
+
/**
|
|
3
|
+
* Run visibility (resource-sharing grants spec §3.5, A6): a run's output is
|
|
4
|
+
* the triggerer's and the agent owner's, never every reader's. The owner
|
|
5
|
+
* (and the stdio operator) sees every run; anyone else only runs with
|
|
6
|
+
* Run.triggeredById equal to themselves.
|
|
7
|
+
*/
|
|
2
8
|
export declare function registerRunTools(mcp: WardbyMcpServer): void;
|
package/dist/mcp/tools/runs.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { McpError } from "../errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { agentAccess, requireAgentAccess } from "../auth/access.js";
|
|
3
3
|
import { publicCodingRunResult } from "../../coding/protocol.js";
|
|
4
|
+
import { countPlanRefusals, summarizeRegistryFetches } from "../../coding/registry/report.js";
|
|
5
|
+
import { storedServiceLabels } from "../../coding/services/catalog.js";
|
|
4
6
|
import { textResult } from "./text-result.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run visibility (resource-sharing grants spec §3.5, A6): a run's output is
|
|
9
|
+
* the triggerer's and the agent owner's, never every reader's. The owner
|
|
10
|
+
* (and the stdio operator) sees every run; anyone else only runs with
|
|
11
|
+
* Run.triggeredById equal to themselves.
|
|
12
|
+
*/
|
|
5
13
|
export function registerRunTools(mcp) {
|
|
6
14
|
mcp.registerTool({
|
|
7
15
|
name: "list_runs",
|
|
@@ -12,9 +20,13 @@ export function registerRunTools(mcp) {
|
|
|
12
20
|
required: ["agentId"],
|
|
13
21
|
},
|
|
14
22
|
handler: async (args, ctx) => {
|
|
15
|
-
await
|
|
23
|
+
const { access } = await requireAgentAccess(ctx, args.agentId, "read");
|
|
16
24
|
const runs = await ctx.db.run.findMany({
|
|
17
|
-
where: {
|
|
25
|
+
where: {
|
|
26
|
+
agentId: args.agentId,
|
|
27
|
+
...(args.status ? { status: args.status } : {}),
|
|
28
|
+
...(access === "owner" ? {} : { triggeredById: ctx.principal.id }),
|
|
29
|
+
},
|
|
18
30
|
take: args.limit,
|
|
19
31
|
orderBy: { startedAt: "desc" },
|
|
20
32
|
});
|
|
@@ -40,21 +52,63 @@ export function registerRunTools(mcp) {
|
|
|
40
52
|
inputSchema: { type: "object", properties: { runId: { type: "string" } }, required: ["runId"] },
|
|
41
53
|
handler: async (args, ctx) => {
|
|
42
54
|
const run = await ctx.db.run.findUnique({ where: { id: args.runId } });
|
|
55
|
+
const notFound = new McpError(404, `Run "${args.runId}" not found.`);
|
|
43
56
|
if (!run)
|
|
44
|
-
throw
|
|
45
|
-
|
|
57
|
+
throw notFound;
|
|
58
|
+
// Its triggerer keeps seeing it even after losing access to the agent;
|
|
59
|
+
// otherwise only the agent's owner. read on the agent is not enough.
|
|
60
|
+
if (run.triggeredById !== ctx.principal.id) {
|
|
61
|
+
const agent = await ctx.db.agent.findUnique({ where: { id: run.agentId } });
|
|
62
|
+
if (!agent || (await agentAccess(ctx, agent)) !== "owner")
|
|
63
|
+
throw notFound;
|
|
64
|
+
}
|
|
46
65
|
const codingRun = await ctx.db.codingRun.findUnique({
|
|
47
66
|
where: { runId: run.id },
|
|
48
|
-
select: {
|
|
67
|
+
select: {
|
|
68
|
+
result: true,
|
|
69
|
+
queuedAt: true,
|
|
70
|
+
failureCategory: true,
|
|
71
|
+
diagnosticId: true,
|
|
72
|
+
debugTrace: true,
|
|
73
|
+
services: true,
|
|
74
|
+
},
|
|
49
75
|
});
|
|
50
76
|
const codingResult = publicCodingRunResult(codingRun?.result);
|
|
51
77
|
// A pending coding run with queuedAt is waiting for a concurrency slot
|
|
52
78
|
// (CODING_MAX_CONCURRENT), not stuck.
|
|
53
79
|
const codingQueuedAt = run.status === "pending" && codingRun?.queuedAt ? codingRun.queuedAt.toISOString() : undefined;
|
|
80
|
+
// Packages served/refused only exist for coding runs; a non-coding run
|
|
81
|
+
// has no RegistryFetch rows at all, so skip the query entirely.
|
|
82
|
+
const registryFetches = codingRun
|
|
83
|
+
? await ctx.db.registryFetch.findMany({ where: { runId: run.id }, orderBy: { createdAt: "asc" } })
|
|
84
|
+
: [];
|
|
85
|
+
const { packages, packageRefusals } = summarizeRegistryFetches(registryFetches);
|
|
86
|
+
// Lockfile verification (POST /registry/<ecosystem>/-/plan): exact
|
|
87
|
+
// versions approved for the run, and distinct entries it refused.
|
|
88
|
+
const packagePlan = codingRun
|
|
89
|
+
? {
|
|
90
|
+
approved: await ctx.db.registryApprovedVersion.count({ where: { runId: run.id } }),
|
|
91
|
+
refused: countPlanRefusals(registryFetches),
|
|
92
|
+
}
|
|
93
|
+
: undefined;
|
|
94
|
+
// A failed coding run's error is only an opaque id; these two say which
|
|
95
|
+
// stage failed and are the key an operator searches the control-plane
|
|
96
|
+
// log for (the real reason is logged there, never persisted). Both are
|
|
97
|
+
// designed to be safe to show the agent's owner (schema.prisma).
|
|
98
|
+
const failureCategory = codingRun?.failureCategory ?? undefined;
|
|
99
|
+
const diagnosticId = codingRun?.diagnosticId ?? undefined;
|
|
100
|
+
// Which services the run started with ("postgres 16"); never their images or environments.
|
|
101
|
+
const services = codingRun ? storedServiceLabels(codingRun.services) : [];
|
|
54
102
|
return textResult({
|
|
55
103
|
...run,
|
|
56
104
|
...(codingResult ? { codingResult } : {}),
|
|
105
|
+
...(failureCategory ? { failureCategory } : {}),
|
|
106
|
+
...(diagnosticId ? { diagnosticId } : {}),
|
|
57
107
|
...(codingQueuedAt ? { codingQueuedAt } : {}),
|
|
108
|
+
// An admin turned on the debug trace: the worker's full trace is in its pod log.
|
|
109
|
+
...(codingRun?.debugTrace ? { debugTrace: true } : {}),
|
|
110
|
+
...(services.length > 0 ? { services } : {}),
|
|
111
|
+
...(codingRun ? { packages, packageRefusals, packagePlan } : {}),
|
|
58
112
|
});
|
|
59
113
|
},
|
|
60
114
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Prisma } from "
|
|
1
|
+
import { Prisma } from "#prisma";
|
|
2
2
|
import { validateCronExpression } from "../../core/cron.js";
|
|
3
3
|
import { McpError } from "../errors.js";
|
|
4
|
-
import {
|
|
4
|
+
import { assertAgentAccess, requireAgentAccess } from "../auth/access.js";
|
|
5
5
|
import { textResult } from "./text-result.js";
|
|
6
6
|
export function registerSchedulingTools(mcp) {
|
|
7
7
|
mcp.registerTool({
|
|
@@ -20,10 +20,7 @@ export function registerSchedulingTools(mcp) {
|
|
|
20
20
|
throw new McpError(400, `Invalid schedule/timezone: ${err instanceof Error ? err.message : String(err)}`);
|
|
21
21
|
}
|
|
22
22
|
const agent = await ctx.db.$transaction(async (tx) => {
|
|
23
|
-
const existing = await tx.agent.findUnique({ where: { id: args.agentId }, include: { codingProfile: true } });
|
|
24
|
-
if (!existing)
|
|
25
|
-
throw new McpError(404, `Agent "${args.agentId}" not found.`);
|
|
26
|
-
assertCanMutate(existing.ownerId, ctx.principal.id, `Agent "${args.agentId}" is not owned by the caller.`);
|
|
23
|
+
const { agent: existing } = await assertAgentAccess(ctx, await tx.agent.findUnique({ where: { id: args.agentId }, include: { codingProfile: true } }), args.agentId, "write", tx);
|
|
27
24
|
if (existing.kind === "coding" && !existing.codingProfile?.defaultTask) {
|
|
28
25
|
throw new McpError(400, "A default task is required before enabling a coding-agent schedule.");
|
|
29
26
|
}
|
|
@@ -40,7 +37,7 @@ export function registerSchedulingTools(mcp) {
|
|
|
40
37
|
scope: "agents:write",
|
|
41
38
|
inputSchema: { type: "object", properties: { agentId: { type: "string" } }, required: ["agentId"] },
|
|
42
39
|
handler: async (args, ctx) => {
|
|
43
|
-
await
|
|
40
|
+
await requireAgentAccess(ctx, args.agentId, "write");
|
|
44
41
|
const agent = await ctx.db.agent.update({ where: { id: args.agentId }, data: { scheduleEnabled: false } });
|
|
45
42
|
return textResult(agent);
|
|
46
43
|
},
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* CSP can forbid scripts outright rather than needing a nonce.
|
|
7
7
|
*/
|
|
8
8
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
9
|
-
import type { PrismaClient } from "
|
|
9
|
+
import type { PrismaClient } from "#prisma";
|
|
10
10
|
import type { SecretCipher } from "../../providers/secrets/types.js";
|
|
11
11
|
import { type SecretElicitationPayload } from "./secret-elicitation.js";
|
|
12
12
|
/** The HTTP-transport route path this form is mounted at (see streamable-http.ts). */
|
|
@@ -1,43 +1,24 @@
|
|
|
1
1
|
import { fulfillSecretElicitation } from "./secret-elicitation.js";
|
|
2
|
+
import { PAGE_STYLE } from "../shared/page-style.js";
|
|
2
3
|
/** The HTTP-transport route path this form is mounted at (see streamable-http.ts). */
|
|
3
4
|
export const SECRET_ELICITATION_PATH = "/elicit/secret";
|
|
4
5
|
function escape(value) {
|
|
5
6
|
return value.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
6
7
|
}
|
|
7
|
-
const STYLE = `
|
|
8
|
-
:root { color-scheme: light dark; }
|
|
9
|
-
* { box-sizing: border-box; }
|
|
10
|
-
body { margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px;
|
|
11
|
-
background: #f5f5f7; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
|
12
|
-
.card { background: #fff; border-radius: 14px; box-shadow: 0 1px 3px rgba(0,0,0,.1), 0 8px 24px rgba(0,0,0,.08);
|
|
13
|
-
padding: 36px; max-width: 480px; width: 100%; }
|
|
14
|
-
h1 { margin: 0 0 10px; font-size: 21px; }
|
|
15
|
-
p { margin: 0 0 24px; color: #555; font-size: 14px; line-height: 1.5; }
|
|
16
|
-
p strong { color: #111; }
|
|
17
|
-
input[type=password] { display: block; width: 100%; padding: 16px 18px; font-size: 17px; letter-spacing: .02em;
|
|
18
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; border: 1px solid #d1d1d6; border-radius: 10px;
|
|
19
|
-
margin-bottom: 18px; }
|
|
20
|
-
input[type=password]:focus { outline: none; border-color: #0071e3; box-shadow: 0 0 0 3px rgba(0,113,227,.15); }
|
|
21
|
-
button { width: 100%; padding: 15px; font-size: 15px; font-weight: 600; color: #fff; background: #0071e3;
|
|
22
|
-
border: none; border-radius: 10px; cursor: pointer; }
|
|
23
|
-
button:hover { background: #0077ed; }
|
|
24
|
-
@media (prefers-color-scheme: dark) {
|
|
25
|
-
body { background: #1c1c1e; }
|
|
26
|
-
.card { background: #2c2c2e; box-shadow: none; }
|
|
27
|
-
h1 { color: #f5f5f7; }
|
|
28
|
-
p { color: #a1a1a6; }
|
|
29
|
-
p strong { color: #f5f5f7; }
|
|
30
|
-
input[type=password] { background: #1c1c1e; border-color: #48484a; color: #f5f5f7; }
|
|
31
|
-
}`;
|
|
32
8
|
function html(res, status, body) {
|
|
33
9
|
res.setHeader("content-security-policy", "default-src 'none'; script-src 'none'; style-src 'unsafe-inline'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'");
|
|
34
10
|
res.setHeader("cache-control", "no-store");
|
|
35
11
|
res.setHeader("x-content-type-options", "nosniff");
|
|
36
|
-
|
|
12
|
+
// Not no-referrer: under it a browser sends `Origin: null` on this page's native
|
|
13
|
+
// form POST, even to the same origin, and the HTTP transport rejects that as
|
|
14
|
+
// invalid_origin. same-origin keeps the Origin and still sends nothing,
|
|
15
|
+
// token-bearing URL included, to any other site. (The login page solves the
|
|
16
|
+
// same problem with a fetch() instead; this page runs no script at all.)
|
|
17
|
+
res.setHeader("referrer-policy", "same-origin");
|
|
37
18
|
res
|
|
38
19
|
.writeHead(status, { "content-type": "text/html; charset=utf-8" })
|
|
39
20
|
.end(`<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">` +
|
|
40
|
-
`<title>wardby secret entry</title><style>${
|
|
21
|
+
`<title>wardby secret entry</title><style>${PAGE_STYLE}</style><body><div class="card"><div class="kicker">wardby</div>${body}</div></body></html>`);
|
|
41
22
|
}
|
|
42
23
|
/** Handles one GET (render) or POST (submit) for the secret-entry form at the given token. */
|
|
43
24
|
export async function handleSecretElicitationForm(method, token, readFormBody, res, deps) {
|
|
@@ -53,7 +34,8 @@ export async function handleSecretElicitationForm(method, token, readFormBody, r
|
|
|
53
34
|
}
|
|
54
35
|
if (method === "GET") {
|
|
55
36
|
html(res, 200, `<h1>Enter secret value</h1><p>Name: <strong>${escape(payload.secretName)}</strong></p>` +
|
|
56
|
-
`<form method="post"><
|
|
37
|
+
`<form method="post"><label>Secret value` +
|
|
38
|
+
`<input type="password" name="value" autocomplete="off" required autofocus placeholder="Paste the value here"></label>` +
|
|
57
39
|
`<button type="submit">Save</button></form>`);
|
|
58
40
|
return;
|
|
59
41
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* Expiry is swept lazily on every read and write via a `deleteMany` rather
|
|
16
16
|
* than a timer, so an idle process holds no interval.
|
|
17
17
|
*/
|
|
18
|
-
import type { PrismaClient } from "
|
|
18
|
+
import type { PrismaClient } from "#prisma";
|
|
19
19
|
import { type SecretMetadata } from "../../core/secrets.js";
|
|
20
20
|
import type { SecretCipher } from "../../providers/secrets/types.js";
|
|
21
21
|
export interface SecretElicitationPayload {
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
import { inputRequired, inputResponse } from "@modelcontextprotocol/server";
|
|
7
7
|
import { createSecret, listSecrets, attachSecret, detachSecret, deleteSecret } from "../../core/secrets.js";
|
|
8
8
|
import { McpError } from "../errors.js";
|
|
9
|
-
import {
|
|
9
|
+
import { requireOwnedSecret } from "../auth/ownership.js";
|
|
10
|
+
import { requireAgentAccess, requireBindingOwner } from "../auth/access.js";
|
|
10
11
|
import { getSecretElicitationOutcome } from "./secret-elicitation.js";
|
|
11
12
|
import { textResult } from "./text-result.js";
|
|
12
13
|
export function registerSecretsTools(mcp, opts) {
|
|
@@ -87,9 +88,15 @@ export function registerSecretsTools(mcp, opts) {
|
|
|
87
88
|
required: ["agentId", "name"],
|
|
88
89
|
},
|
|
89
90
|
handler: async (args, ctx) => {
|
|
90
|
-
|
|
91
|
+
// Strictly the agent owner's own secret on the owner's own agent
|
|
92
|
+
// (A2/S2-2): a binding hands the value to every tool the owner lets
|
|
93
|
+
// read it. Not even the stdio operator crosses owners.
|
|
94
|
+
const { agent } = await requireAgentAccess(ctx, args.agentId, "read");
|
|
95
|
+
requireBindingOwner(ctx, agent);
|
|
96
|
+
const ownerId = agent.ownerId;
|
|
91
97
|
try {
|
|
92
|
-
|
|
98
|
+
// Resolved among the agent owner's secrets (== the caller here).
|
|
99
|
+
await attachSecret(args.agentId, args.name, ownerId, ctx.db, args.alias ?? args.name);
|
|
93
100
|
}
|
|
94
101
|
catch (err) {
|
|
95
102
|
throw new McpError(404, err instanceof Error ? err.message : String(err));
|
|
@@ -100,15 +107,20 @@ export function registerSecretsTools(mcp, opts) {
|
|
|
100
107
|
mcp.registerTool({
|
|
101
108
|
name: "detach_secret",
|
|
102
109
|
scope: "secrets:write",
|
|
110
|
+
description: "Detaches a secret from an agent. `name` is the alias it was attached under; the secret's own name also works when no attachment has that alias.",
|
|
103
111
|
inputSchema: {
|
|
104
112
|
type: "object",
|
|
105
113
|
properties: { agentId: { type: "string" }, name: { type: "string" } },
|
|
106
114
|
required: ["agentId", "name"],
|
|
107
115
|
},
|
|
108
116
|
handler: async (args, ctx) => {
|
|
109
|
-
await
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
const { agent } = await requireAgentAccess(ctx, args.agentId, "read");
|
|
118
|
+
requireBindingOwner(ctx, agent);
|
|
119
|
+
const count = await detachSecret(args.agentId, args.name, ctx.db);
|
|
120
|
+
if (count === 0) {
|
|
121
|
+
throw new McpError(404, `No secret is attached to agent "${args.agentId}" as "${args.name}".`);
|
|
122
|
+
}
|
|
123
|
+
return textResult({ detached: true, count });
|
|
112
124
|
},
|
|
113
125
|
});
|
|
114
126
|
mcp.registerTool({
|