@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,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Updating and deleting a Tool, shared by MCP update_tool/delete_tool (the
|
|
3
|
+
* owner, over MCP) and `wardby tool update|delete` (the operator, over the
|
|
4
|
+
* CLI). Each caller brings its own authorization -- MCP is strictly
|
|
5
|
+
* owner-only and never touches public tools; the operator may change any
|
|
6
|
+
* tool -- but the attachment rules are the same for both, and are always
|
|
7
|
+
* judged against the *tool's* owner:
|
|
8
|
+
*
|
|
9
|
+
* - An update is refused while the tool is attached to any agent owned by
|
|
10
|
+
* someone other than the tool's owner (a public agent counts, unless the
|
|
11
|
+
* tool is public too). An attachment's grants hand whatever code the row
|
|
12
|
+
* holds to that agent owner's secrets and hosts, and the description
|
|
13
|
+
* reaches their model context.
|
|
14
|
+
* - A delete is refused while any attachment remains; `detach` first removes
|
|
15
|
+
* the attachments to the tool owner's own agents (for a public tool, the
|
|
16
|
+
* public agents), never anyone else's. The check runs before any detach,
|
|
17
|
+
* so a refusal changes nothing.
|
|
18
|
+
*
|
|
19
|
+
* Both run in one Serializable transaction, the same isolation as MCP
|
|
20
|
+
* attach_tool, so an attach that commits between the check and the write
|
|
21
|
+
* aborts one side instead of letting new code reach a newly attached agent
|
|
22
|
+
* (pinned in core/prisma-adapter.database.test.ts). That guarantee covers
|
|
23
|
+
* MCP attach_tool only: `wardby tool attach` and the importer attach with a
|
|
24
|
+
* plain check-then-upsert, acceptable because both are operator-only.
|
|
25
|
+
*/
|
|
26
|
+
import { Prisma, type PrismaClient, type Tool } from "#prisma";
|
|
27
|
+
export type AttachedAgent = {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
ownerId: string | null;
|
|
31
|
+
};
|
|
32
|
+
export interface ToolChanges {
|
|
33
|
+
description?: string;
|
|
34
|
+
paramsZod?: string;
|
|
35
|
+
code?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Why a tool change was refused because of its attachments:
|
|
39
|
+
* - `other_owners`: attached to agents owned by someone other than the
|
|
40
|
+
* tool's owner (`agents` lists them; callers decide how much to reveal).
|
|
41
|
+
* - `needs_detach`: a delete without `detach`, still attached to the tool
|
|
42
|
+
* owner's own agents.
|
|
43
|
+
* - `race`: an attachment committed after the check, and the RESTRICT
|
|
44
|
+
* foreign key stopped the delete (`agents` is empty).
|
|
45
|
+
*/
|
|
46
|
+
export declare class ToolAttachedError extends Error {
|
|
47
|
+
readonly reason: "other_owners" | "needs_detach" | "race";
|
|
48
|
+
readonly agents: AttachedAgent[];
|
|
49
|
+
constructor(reason: "other_owners" | "needs_detach" | "race", agents: AttachedAgent[]);
|
|
50
|
+
}
|
|
51
|
+
/** Whether `changes` names at least one field to change. */
|
|
52
|
+
export declare function hasToolChanges(changes: ToolChanges): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The row update for `changes`, with jsonSchema re-derived exactly as tool
|
|
55
|
+
* creation does whenever paramsZod changes, so the cached schema never goes
|
|
56
|
+
* stale. An invalid paramsZod is returned, not thrown -- the caller reports
|
|
57
|
+
* it like create_tool does and writes nothing. Run it before the transaction
|
|
58
|
+
* so a QuickJS compile never holds one open.
|
|
59
|
+
*/
|
|
60
|
+
export declare function prepareToolUpdate(changes: ToolChanges): Promise<{
|
|
61
|
+
ok: true;
|
|
62
|
+
data: Prisma.ToolUpdateInput;
|
|
63
|
+
} | {
|
|
64
|
+
ok: false;
|
|
65
|
+
errorKind: string;
|
|
66
|
+
errorMessage: string;
|
|
67
|
+
}>;
|
|
68
|
+
/** The agents `toolId` is attached to, read inside the caller's transaction. */
|
|
69
|
+
export declare function attachedAgents(tx: Pick<Prisma.TransactionClient, "agentTool">, toolId: string): Promise<AttachedAgent[]>;
|
|
70
|
+
/** Refuses (by throwing) unless the caller may change this tool; receives the row read inside the transaction. */
|
|
71
|
+
export type AuthorizeTool = (tool: Tool | null) => void;
|
|
72
|
+
export declare function updateToolGuarded(db: Pick<PrismaClient, "$transaction">, toolId: string, data: Prisma.ToolUpdateInput, authorize: AuthorizeTool): Promise<Tool>;
|
|
73
|
+
/** Deletes the tool and returns the ids of the agents it was detached from. */
|
|
74
|
+
export declare function deleteToolGuarded(db: Pick<PrismaClient, "$transaction">, toolId: string, options: {
|
|
75
|
+
detach: boolean;
|
|
76
|
+
authorize: AuthorizeTool;
|
|
77
|
+
}): Promise<string[]>;
|
|
78
|
+
/** One `wardby tool list` line: names are only unique per owner, so the id and owner disambiguate. */
|
|
79
|
+
export declare function formatToolLine(tool: Pick<Tool, "id" | "name" | "description" | "ownerId">): string;
|
|
80
|
+
/** Attached agents for an operator-facing refusal: unlike MCP's, nothing is redacted. */
|
|
81
|
+
export declare function formatAttachedAgents(agents: AttachedAgent[]): string;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Updating and deleting a Tool, shared by MCP update_tool/delete_tool (the
|
|
3
|
+
* owner, over MCP) and `wardby tool update|delete` (the operator, over the
|
|
4
|
+
* CLI). Each caller brings its own authorization -- MCP is strictly
|
|
5
|
+
* owner-only and never touches public tools; the operator may change any
|
|
6
|
+
* tool -- but the attachment rules are the same for both, and are always
|
|
7
|
+
* judged against the *tool's* owner:
|
|
8
|
+
*
|
|
9
|
+
* - An update is refused while the tool is attached to any agent owned by
|
|
10
|
+
* someone other than the tool's owner (a public agent counts, unless the
|
|
11
|
+
* tool is public too). An attachment's grants hand whatever code the row
|
|
12
|
+
* holds to that agent owner's secrets and hosts, and the description
|
|
13
|
+
* reaches their model context.
|
|
14
|
+
* - A delete is refused while any attachment remains; `detach` first removes
|
|
15
|
+
* the attachments to the tool owner's own agents (for a public tool, the
|
|
16
|
+
* public agents), never anyone else's. The check runs before any detach,
|
|
17
|
+
* so a refusal changes nothing.
|
|
18
|
+
*
|
|
19
|
+
* Both run in one Serializable transaction, the same isolation as MCP
|
|
20
|
+
* attach_tool, so an attach that commits between the check and the write
|
|
21
|
+
* aborts one side instead of letting new code reach a newly attached agent
|
|
22
|
+
* (pinned in core/prisma-adapter.database.test.ts). That guarantee covers
|
|
23
|
+
* MCP attach_tool only: `wardby tool attach` and the importer attach with a
|
|
24
|
+
* plain check-then-upsert, acceptable because both are operator-only.
|
|
25
|
+
*/
|
|
26
|
+
import { Prisma } from "#prisma";
|
|
27
|
+
import { deriveJsonSchema } from "../sandbox/zod-params.js";
|
|
28
|
+
/**
|
|
29
|
+
* Why a tool change was refused because of its attachments:
|
|
30
|
+
* - `other_owners`: attached to agents owned by someone other than the
|
|
31
|
+
* tool's owner (`agents` lists them; callers decide how much to reveal).
|
|
32
|
+
* - `needs_detach`: a delete without `detach`, still attached to the tool
|
|
33
|
+
* owner's own agents.
|
|
34
|
+
* - `race`: an attachment committed after the check, and the RESTRICT
|
|
35
|
+
* foreign key stopped the delete (`agents` is empty).
|
|
36
|
+
*/
|
|
37
|
+
export class ToolAttachedError extends Error {
|
|
38
|
+
reason;
|
|
39
|
+
agents;
|
|
40
|
+
constructor(reason, agents) {
|
|
41
|
+
super(`tool_attached_${reason}`);
|
|
42
|
+
this.reason = reason;
|
|
43
|
+
this.agents = agents;
|
|
44
|
+
this.name = "ToolAttachedError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Whether `changes` names at least one field to change. */
|
|
48
|
+
export function hasToolChanges(changes) {
|
|
49
|
+
return changes.description !== undefined || changes.paramsZod !== undefined || changes.code !== undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The row update for `changes`, with jsonSchema re-derived exactly as tool
|
|
53
|
+
* creation does whenever paramsZod changes, so the cached schema never goes
|
|
54
|
+
* stale. An invalid paramsZod is returned, not thrown -- the caller reports
|
|
55
|
+
* it like create_tool does and writes nothing. Run it before the transaction
|
|
56
|
+
* so a QuickJS compile never holds one open.
|
|
57
|
+
*/
|
|
58
|
+
export async function prepareToolUpdate(changes) {
|
|
59
|
+
const data = {
|
|
60
|
+
...(changes.description !== undefined ? { description: changes.description } : {}),
|
|
61
|
+
...(changes.code !== undefined ? { code: changes.code } : {}),
|
|
62
|
+
};
|
|
63
|
+
if (changes.paramsZod !== undefined) {
|
|
64
|
+
const schemaResult = await deriveJsonSchema(changes.paramsZod);
|
|
65
|
+
if (!schemaResult.ok) {
|
|
66
|
+
return { ok: false, errorKind: schemaResult.errorKind, errorMessage: schemaResult.errorMessage };
|
|
67
|
+
}
|
|
68
|
+
data.paramsZod = changes.paramsZod;
|
|
69
|
+
data.jsonSchema = schemaResult.value;
|
|
70
|
+
}
|
|
71
|
+
return { ok: true, data };
|
|
72
|
+
}
|
|
73
|
+
/** The agents `toolId` is attached to, read inside the caller's transaction. */
|
|
74
|
+
export async function attachedAgents(tx, toolId) {
|
|
75
|
+
const rows = await tx.agentTool.findMany({
|
|
76
|
+
where: { toolId },
|
|
77
|
+
select: { agent: { select: { id: true, name: true, ownerId: true } } },
|
|
78
|
+
});
|
|
79
|
+
return rows.map((row) => row.agent);
|
|
80
|
+
}
|
|
81
|
+
export async function updateToolGuarded(db, toolId, data, authorize) {
|
|
82
|
+
return db.$transaction(async (tx) => {
|
|
83
|
+
const tool = await tx.tool.findUnique({ where: { id: toolId } });
|
|
84
|
+
authorize(tool);
|
|
85
|
+
const others = (await attachedAgents(tx, toolId)).filter((agent) => agent.ownerId !== tool.ownerId);
|
|
86
|
+
if (others.length > 0)
|
|
87
|
+
throw new ToolAttachedError("other_owners", others);
|
|
88
|
+
return tx.tool.update({ where: { id: toolId }, data });
|
|
89
|
+
}, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable });
|
|
90
|
+
}
|
|
91
|
+
/** Deletes the tool and returns the ids of the agents it was detached from. */
|
|
92
|
+
export async function deleteToolGuarded(db, toolId, options) {
|
|
93
|
+
try {
|
|
94
|
+
return await db.$transaction(async (tx) => {
|
|
95
|
+
const tool = await tx.tool.findUnique({ where: { id: toolId } });
|
|
96
|
+
options.authorize(tool);
|
|
97
|
+
const agents = await attachedAgents(tx, toolId);
|
|
98
|
+
const own = agents.filter((agent) => agent.ownerId === tool.ownerId);
|
|
99
|
+
const others = agents.filter((agent) => agent.ownerId !== tool.ownerId);
|
|
100
|
+
if (others.length > 0)
|
|
101
|
+
throw new ToolAttachedError("other_owners", others);
|
|
102
|
+
if (own.length > 0 && !options.detach)
|
|
103
|
+
throw new ToolAttachedError("needs_detach", own);
|
|
104
|
+
if (own.length > 0) {
|
|
105
|
+
await tx.agentTool.deleteMany({ where: { toolId, agentId: { in: own.map((agent) => agent.id) } } });
|
|
106
|
+
}
|
|
107
|
+
await tx.tool.delete({ where: { id: toolId } });
|
|
108
|
+
return own.map((agent) => agent.id);
|
|
109
|
+
}, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable });
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
// AgentTool.toolId is ON DELETE RESTRICT: an attachment that raced in
|
|
113
|
+
// past the check above still stops the delete, as P2003.
|
|
114
|
+
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2003") {
|
|
115
|
+
throw new ToolAttachedError("race", []);
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** One `wardby tool list` line: names are only unique per owner, so the id and owner disambiguate. */
|
|
121
|
+
export function formatToolLine(tool) {
|
|
122
|
+
return `${tool.id} ${tool.name} owner:${tool.ownerId ?? "public"} ${tool.description}`;
|
|
123
|
+
}
|
|
124
|
+
/** Attached agents for an operator-facing refusal: unlike MCP's, nothing is redacted. */
|
|
125
|
+
export function formatAttachedAgents(agents) {
|
|
126
|
+
return agents
|
|
127
|
+
.map((agent) => `"${agent.name}" (${agent.id}, ${agent.ownerId === null ? "public" : `owner ${agent.ownerId}`})`)
|
|
128
|
+
.join(", ");
|
|
129
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-name rules shared by every path that creates or attaches a Tool
|
|
3
|
+
* (MCP create_tool/attach_tool, `wardby tool create|attach`, the importer)
|
|
4
|
+
* and by the runner that dispatches them.
|
|
5
|
+
*
|
|
6
|
+
* Tool names are unique per owner, not globally (schema.prisma), so one
|
|
7
|
+
* agent could otherwise end up holding two same-named tools -- say its own
|
|
8
|
+
* `foo` plus a public `foo`. The runtime dispatches by name (runner.ts), so
|
|
9
|
+
* the model would see a duplicate tool name and one tool would silently
|
|
10
|
+
* shadow the other; every attach path refuses that instead
|
|
11
|
+
* (findSameNamedAttachedTool), and the runner asserts it at load time.
|
|
12
|
+
*/
|
|
13
|
+
import type { Prisma, PrismaClient, Tool } from "#prisma";
|
|
14
|
+
/** The runner's synthesized sub-agent tools are `delegate_to_<boundName>`. */
|
|
15
|
+
export declare const DELEGATE_TOOL_PREFIX = "delegate_to_";
|
|
16
|
+
/**
|
|
17
|
+
* Why `name` can't be a user tool's name, or undefined if it can. Each
|
|
18
|
+
* reserved name is checked by the runner before user tools, so a user tool
|
|
19
|
+
* with one of these names could be created but never reached.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reservedToolNameReason(name: string): string | undefined;
|
|
22
|
+
/** Names appearing more than once, each reported once, in first-seen order. */
|
|
23
|
+
export declare function duplicateToolNames(names: readonly string[]): string[];
|
|
24
|
+
export type ToolLookupDb = Pick<PrismaClient | Prisma.TransactionClient, "tool" | "agentTool">;
|
|
25
|
+
/**
|
|
26
|
+
* A tool other than `tool` that is already attached to `agentId` under the
|
|
27
|
+
* same name, or null. Run it inside the attaching transaction (attach_tool's
|
|
28
|
+
* is Serializable) so a concurrent attach can't slip in between.
|
|
29
|
+
*/
|
|
30
|
+
export declare function findSameNamedAttachedTool(db: Pick<ToolLookupDb, "agentTool">, agentId: string, tool: Pick<Tool, "id" | "name">): Promise<Pick<Tool, "id" | "name" | "ownerId"> | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Resolves a CLI tool reference: an id, else a name. A name is no longer
|
|
33
|
+
* unique across owners, so more than one match is refused -- with the
|
|
34
|
+
* candidate ids, so the operator can pass one -- rather than guessed at.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveToolRef(db: Pick<ToolLookupDb, "tool">, ref: string): Promise<{
|
|
37
|
+
ok: true;
|
|
38
|
+
tool: Tool;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
error: string;
|
|
42
|
+
}>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { MEMORY_TOOL_NAMES } from "./memory-tools.js";
|
|
2
|
+
import { SUBAGENT_MEMORY_TOOL_NAMES } from "./subagent-memory-tools.js";
|
|
3
|
+
/** The runner's synthesized sub-agent tools are `delegate_to_<boundName>`. */
|
|
4
|
+
export const DELEGATE_TOOL_PREFIX = "delegate_to_";
|
|
5
|
+
/**
|
|
6
|
+
* Why `name` can't be a user tool's name, or undefined if it can. Each
|
|
7
|
+
* reserved name is checked by the runner before user tools, so a user tool
|
|
8
|
+
* with one of these names could be created but never reached.
|
|
9
|
+
*/
|
|
10
|
+
export function reservedToolNameReason(name) {
|
|
11
|
+
if (MEMORY_TOOL_NAMES.has(name))
|
|
12
|
+
return `Tool name "${name}" is reserved for the built-in agent-memory tools.`;
|
|
13
|
+
if (SUBAGENT_MEMORY_TOOL_NAMES.has(name)) {
|
|
14
|
+
return `Tool name "${name}" is reserved for the built-in sub-agent memory tools.`;
|
|
15
|
+
}
|
|
16
|
+
if (name.startsWith(DELEGATE_TOOL_PREFIX)) {
|
|
17
|
+
return `Tool names starting with "${DELEGATE_TOOL_PREFIX}" are reserved for sub-agent delegation tools.`;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
/** Names appearing more than once, each reported once, in first-seen order. */
|
|
22
|
+
export function duplicateToolNames(names) {
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
const duplicates = new Set();
|
|
25
|
+
for (const name of names) {
|
|
26
|
+
if (seen.has(name))
|
|
27
|
+
duplicates.add(name);
|
|
28
|
+
seen.add(name);
|
|
29
|
+
}
|
|
30
|
+
return [...duplicates];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A tool other than `tool` that is already attached to `agentId` under the
|
|
34
|
+
* same name, or null. Run it inside the attaching transaction (attach_tool's
|
|
35
|
+
* is Serializable) so a concurrent attach can't slip in between.
|
|
36
|
+
*/
|
|
37
|
+
export async function findSameNamedAttachedTool(db, agentId, tool) {
|
|
38
|
+
const clash = await db.agentTool.findFirst({
|
|
39
|
+
where: { agentId, toolId: { not: tool.id }, tool: { name: tool.name } },
|
|
40
|
+
select: { tool: { select: { id: true, name: true, ownerId: true } } },
|
|
41
|
+
});
|
|
42
|
+
return clash?.tool ?? null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a CLI tool reference: an id, else a name. A name is no longer
|
|
46
|
+
* unique across owners, so more than one match is refused -- with the
|
|
47
|
+
* candidate ids, so the operator can pass one -- rather than guessed at.
|
|
48
|
+
*/
|
|
49
|
+
export async function resolveToolRef(db, ref) {
|
|
50
|
+
const byId = await db.tool.findUnique({ where: { id: ref } });
|
|
51
|
+
if (byId)
|
|
52
|
+
return { ok: true, tool: byId };
|
|
53
|
+
const byName = await db.tool.findMany({ where: { name: ref } });
|
|
54
|
+
if (byName.length === 0)
|
|
55
|
+
return { ok: false, error: `unknown tool "${ref}".` };
|
|
56
|
+
if (byName.length > 1) {
|
|
57
|
+
const candidates = byName.map((t) => `${t.id} (owner: ${t.ownerId ?? "public"})`).join(", ");
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: `ambiguous: ${byName.length} tools named "${ref}"; pass the tool id instead (${candidates}).`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return { ok: true, tool: byName[0] };
|
|
64
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place untrusted text is fenced for the model. Tool results
|
|
3
|
+
* (engine-native.ts) and a run's untrusted context (the parts of a trigger
|
|
4
|
+
* nobody vetted, e.g. a GitHub issue's title and description) are delivered
|
|
5
|
+
* inside wrapper tags; a run's task is fenced in the system prompt by
|
|
6
|
+
* run_task tags (runner.ts). Every one of those tags is only a boundary if
|
|
7
|
+
* the content inside cannot write it, so all wrapped text passes through
|
|
8
|
+
* neutraliseWrapperTags first (H5-6 / E-09).
|
|
9
|
+
*/
|
|
10
|
+
export declare const UNTRUSTED_TOOL_OUTPUT_TAG = "untrusted_tool_output";
|
|
11
|
+
export declare const UNTRUSTED_CONTEXT_TAG = "untrusted_context";
|
|
12
|
+
export declare const RUN_TASK_TAG = "run_task";
|
|
13
|
+
/** Makes every fence-like tag in `content` inert. Idempotent. */
|
|
14
|
+
export declare function neutraliseWrapperTags(content: string): string;
|
|
15
|
+
/** `content` between `<tag>` and `</tag>`, unable to close or reopen either fence itself. */
|
|
16
|
+
export declare function wrapUntrusted(tag: string, content: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Stores a run's task and its untrusted context in the one Run.taskOverride
|
|
19
|
+
* column: the task, then a wrapped context block. Both parts are
|
|
20
|
+
* neutralised, so the stored text holds exactly one real context opener.
|
|
21
|
+
*/
|
|
22
|
+
export declare function composeTaskOverride(task: string, untrustedContext?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* The inverse of composeTaskOverride, read by the runner. Everything from the
|
|
25
|
+
* first context opener on is context. A producer that wrote the opener
|
|
26
|
+
* without composeTaskOverride (a webhook caller, a delegating model) can only
|
|
27
|
+
* demote its own text into the untrusted context, never promote any.
|
|
28
|
+
*/
|
|
29
|
+
export declare function splitTaskOverride(taskOverride: string): {
|
|
30
|
+
task: string;
|
|
31
|
+
untrustedContext?: string;
|
|
32
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place untrusted text is fenced for the model. Tool results
|
|
3
|
+
* (engine-native.ts) and a run's untrusted context (the parts of a trigger
|
|
4
|
+
* nobody vetted, e.g. a GitHub issue's title and description) are delivered
|
|
5
|
+
* inside wrapper tags; a run's task is fenced in the system prompt by
|
|
6
|
+
* run_task tags (runner.ts). Every one of those tags is only a boundary if
|
|
7
|
+
* the content inside cannot write it, so all wrapped text passes through
|
|
8
|
+
* neutraliseWrapperTags first (H5-6 / E-09).
|
|
9
|
+
*/
|
|
10
|
+
export const UNTRUSTED_TOOL_OUTPUT_TAG = "untrusted_tool_output";
|
|
11
|
+
export const UNTRUSTED_CONTEXT_TAG = "untrusted_context";
|
|
12
|
+
export const RUN_TASK_TAG = "run_task";
|
|
13
|
+
/** Invisible characters (zero-width, bidi controls, soft hyphen, variation selectors, tag characters, ...). */
|
|
14
|
+
const IGNORABLE = "\\p{Default_Ignorable_Code_Point}";
|
|
15
|
+
/** "<" and its common lookalikes: fullwidth, small, angle brackets, single guillemet. */
|
|
16
|
+
const BRACKET = "[<\\uFF1C\\uFE64\\u2329\\u3008\\u27E8\\u2039]";
|
|
17
|
+
/** Between the bracket and the name: whitespace, invisibles, and any number of slashes, backslashes or slash lookalikes. */
|
|
18
|
+
const LEAD = `[\\s${IGNORABLE}/\\\\\\uFF0F\\u2215\\u2044\\u29F8]*`;
|
|
19
|
+
/** Between "run" and "task": whitespace, invisibles, "_", "-" and their dash/fullwidth lookalikes. */
|
|
20
|
+
const JOIN = `[\\s${IGNORABLE}_\\-\\u2010-\\u2015\\uFF3F\\uFF0D]*`;
|
|
21
|
+
/** One ASCII letter or its fullwidth form (the `i` flag covers either case). */
|
|
22
|
+
const letter = (ch) => `[${ch}${String.fromCharCode(0xff41 + ch.charCodeAt(0) - 0x61)}]`;
|
|
23
|
+
/** A word whose letters may be separated by invisible characters. */
|
|
24
|
+
const word = (w) => [...w].map(letter).join(`[${IGNORABLE}]*`);
|
|
25
|
+
/**
|
|
26
|
+
* A bracket that could be read as opening or closing one of the fences: a
|
|
27
|
+
* "<" or lookalike, then LEAD, then the start of a fence name ("untrusted…"
|
|
28
|
+
* or "run_task" / "run-task" / "run task"), in any case, with invisible
|
|
29
|
+
* characters or fullwidth letters allowed inside the name. Only the bracket
|
|
30
|
+
* is replaced, with "<", so the rest of the text is unchanged.
|
|
31
|
+
*
|
|
32
|
+
* Linear time (I-1): every starred class is followed by a letter it cannot
|
|
33
|
+
* contain, so it has exactly one way to match, and a failed attempt at one
|
|
34
|
+
* bracket gives back each character at most once. Homoglyphs from other
|
|
35
|
+
* scripts inside the name (a Cyrillic "е") are not caught.
|
|
36
|
+
*/
|
|
37
|
+
const FENCE_TAG_LIKE = new RegExp(`${BRACKET}(?=${LEAD}(?:${word("untrusted")}|${word("run")}${JOIN}${word("task")}))`, "giu");
|
|
38
|
+
/** Makes every fence-like tag in `content` inert. Idempotent. */
|
|
39
|
+
export function neutraliseWrapperTags(content) {
|
|
40
|
+
return content.replace(FENCE_TAG_LIKE, "<");
|
|
41
|
+
}
|
|
42
|
+
/** `content` between `<tag>` and `</tag>`, unable to close or reopen either fence itself. */
|
|
43
|
+
export function wrapUntrusted(tag, content) {
|
|
44
|
+
return `<${tag}>\n${neutraliseWrapperTags(content)}\n</${tag}>`;
|
|
45
|
+
}
|
|
46
|
+
const CONTEXT_OPEN = `<${UNTRUSTED_CONTEXT_TAG}>\n`;
|
|
47
|
+
const CONTEXT_CLOSE = `\n</${UNTRUSTED_CONTEXT_TAG}>`;
|
|
48
|
+
/**
|
|
49
|
+
* Stores a run's task and its untrusted context in the one Run.taskOverride
|
|
50
|
+
* column: the task, then a wrapped context block. Both parts are
|
|
51
|
+
* neutralised, so the stored text holds exactly one real context opener.
|
|
52
|
+
*/
|
|
53
|
+
export function composeTaskOverride(task, untrustedContext) {
|
|
54
|
+
const safeTask = neutraliseWrapperTags(task);
|
|
55
|
+
return untrustedContext ? `${safeTask}\n\n${wrapUntrusted(UNTRUSTED_CONTEXT_TAG, untrustedContext)}` : safeTask;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The inverse of composeTaskOverride, read by the runner. Everything from the
|
|
59
|
+
* first context opener on is context. A producer that wrote the opener
|
|
60
|
+
* without composeTaskOverride (a webhook caller, a delegating model) can only
|
|
61
|
+
* demote its own text into the untrusted context, never promote any.
|
|
62
|
+
*/
|
|
63
|
+
export function splitTaskOverride(taskOverride) {
|
|
64
|
+
const at = taskOverride.startsWith(CONTEXT_OPEN) ? 0 : taskOverride.indexOf(`\n${CONTEXT_OPEN}`);
|
|
65
|
+
if (at < 0)
|
|
66
|
+
return { task: taskOverride };
|
|
67
|
+
const task = taskOverride.slice(0, at).trimEnd();
|
|
68
|
+
let rest = taskOverride.slice(at === 0 ? CONTEXT_OPEN.length : at + 1 + CONTEXT_OPEN.length);
|
|
69
|
+
if (rest.endsWith(CONTEXT_CLOSE))
|
|
70
|
+
rest = rest.slice(0, -CONTEXT_CLOSE.length);
|
|
71
|
+
return { task, untrustedContext: rest };
|
|
72
|
+
}
|
package/dist/core/webhooks.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PrismaClient, Webhook } from "
|
|
1
|
+
import type { PrismaClient, Webhook } from "#prisma";
|
|
2
2
|
import type { Executor } from "../providers/executor/types.js";
|
|
3
3
|
export type WebhookMetadata = Pick<Webhook, "id" | "agentId" | "status" | "ownerId" | "createdAt" | "lastFiredAt">;
|
|
4
4
|
/** Creates a webhook and returns the raw secret ONCE — only its hash is ever stored. */
|
|
@@ -6,7 +6,14 @@ export declare function createWebhook(agentId: string, ownerId: string, db: Pris
|
|
|
6
6
|
id: string;
|
|
7
7
|
secret: string;
|
|
8
8
|
}>;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Webhooks the principal created, plus every webhook on an agent it owns
|
|
11
|
+
* (the agent owner must be able to see standing triggers others hold on
|
|
12
|
+
* its agent). `all` (the stdio operator) lists every webhook.
|
|
13
|
+
*/
|
|
14
|
+
export declare function listWebhooks(principalId: string, db: PrismaClient, opts?: {
|
|
15
|
+
all?: boolean;
|
|
16
|
+
}): Promise<WebhookMetadata[]>;
|
|
10
17
|
export declare function deleteWebhook(id: string, db: PrismaClient): Promise<void>;
|
|
11
18
|
export type ResolveWebhookRunResult = {
|
|
12
19
|
ok: true;
|
package/dist/core/webhooks.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
12
12
|
import { dispatchRun } from "./dispatch.js";
|
|
13
|
+
import { atLeast, effectiveAccess } from "./grants.js";
|
|
13
14
|
function hashSecret(secret) {
|
|
14
15
|
return createHash("sha256").update(secret).digest("hex");
|
|
15
16
|
}
|
|
@@ -39,8 +40,15 @@ export async function createWebhook(agentId, ownerId, db) {
|
|
|
39
40
|
const webhook = await db.webhook.create({ data: { agentId, ownerId, secretHash: hashSecret(secret) } });
|
|
40
41
|
return { id: webhook.id, secret };
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Webhooks the principal created, plus every webhook on an agent it owns
|
|
45
|
+
* (the agent owner must be able to see standing triggers others hold on
|
|
46
|
+
* its agent). `all` (the stdio operator) lists every webhook.
|
|
47
|
+
*/
|
|
48
|
+
export async function listWebhooks(principalId, db, opts = {}) {
|
|
49
|
+
const webhooks = await db.webhook.findMany({
|
|
50
|
+
where: opts.all ? {} : { OR: [{ ownerId: principalId }, { agent: { ownerId: principalId } }] },
|
|
51
|
+
});
|
|
44
52
|
return webhooks.map(({ id, agentId, status, ownerId: owner, createdAt, lastFiredAt }) => ({
|
|
45
53
|
id,
|
|
46
54
|
agentId,
|
|
@@ -85,6 +93,9 @@ export async function resolveWebhookRun(id, presentedSecret, db, executor, codin
|
|
|
85
93
|
// to modify a real repository.
|
|
86
94
|
codingTask: agent.kind === "coding" ? codingTask : undefined,
|
|
87
95
|
taskOverride: agent.kind === "native" ? codingTask : undefined,
|
|
96
|
+
// The webhook is its creator's standing trigger: its runs are visible to
|
|
97
|
+
// the creator (and the agent owner), like a trigger_agent call.
|
|
98
|
+
triggeredById: webhook.ownerId,
|
|
88
99
|
beforePersist: async (tx, currentAgent) => {
|
|
89
100
|
const current = await tx.webhook.findUnique({ where: { id } });
|
|
90
101
|
if (!current) {
|
|
@@ -103,6 +114,16 @@ export async function resolveWebhookRun(id, presentedSecret, db, executor, codin
|
|
|
103
114
|
rejected = "disabled";
|
|
104
115
|
return false;
|
|
105
116
|
}
|
|
117
|
+
// The creator must still be allowed to trigger the agent (resource-
|
|
118
|
+
// sharing grants spec §3.10): its owner, or a holder of execute. Read
|
|
119
|
+
// through tx, so a revoke or make_owner takes effect on the next fire.
|
|
120
|
+
// A webhook on a formerly public agent keeps firing through the
|
|
121
|
+
// migration's everyone-execute grant.
|
|
122
|
+
const creatorAccess = await effectiveAccess(tx, "agent", currentAgent, current.ownerId);
|
|
123
|
+
if (!atLeast("agent", creatorAccess, "execute")) {
|
|
124
|
+
rejected = "disabled";
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
106
127
|
await tx.webhook.update({ where: { id }, data: { lastFiredAt: new Date() } });
|
|
107
128
|
return true;
|
|
108
129
|
},
|