@wardby/cli 0.5.3 → 0.7.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 +33 -0
- package/README.md +25 -14
- package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/context.d.ts +22 -0
- package/dist/claude-coding-worker/context.js +92 -0
- package/dist/claude-coding-worker/driver.d.ts +27 -3
- package/dist/claude-coding-worker/driver.js +161 -20
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +25 -5
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +6 -2
- package/dist/cli-native-mode.d.ts +9 -0
- package/dist/cli-native-mode.js +20 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +161 -11
- package/dist/coding/claude-context.d.ts +45 -0
- package/dist/coding/claude-context.js +434 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +50 -118
- package/dist/coding/profile.js +51 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +292 -270
- package/dist/coding/protocol.js +322 -15
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +12 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +51 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +16 -3
- package/dist/coding-worker/artifact.js +5 -3
- package/dist/coding-worker/debug-trace.d.ts +6 -5
- package/dist/coding-worker/debug-trace.js +13 -18
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +118 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/sdk.d.ts +6 -0
- package/dist/coding-worker/sdk.js +1 -0
- package/dist/coding-worker/skills.d.ts +23 -0
- package/dist/coding-worker/skills.js +117 -0
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +13 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/github-allowed-accounts.d.ts +15 -0
- package/dist/config/github-allowed-accounts.js +36 -0
- package/dist/config/low-power.d.ts +12 -0
- package/dist/config/low-power.js +18 -0
- package/dist/config/mobile.d.ts +12 -0
- package/dist/config/mobile.js +18 -0
- package/dist/config/providers.d.ts +65 -3
- package/dist/config/providers.js +147 -11
- package/dist/config/test-simulators.d.ts +82 -0
- package/dist/config/test-simulators.js +305 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/db.d.ts +16 -6
- package/dist/core/db.js +12 -10
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/dispatch.d.ts +53 -0
- package/dist/core/dispatch.js +167 -57
- package/dist/core/engine-native.js +10 -6
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +168 -0
- package/dist/core/grants.d.ts +19 -6
- package/dist/core/grants.js +55 -6
- package/dist/core/host-events.d.ts +67 -5
- package/dist/core/host-events.js +571 -37
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +298 -20
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +151 -20
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +16 -11
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +68 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +130 -0
- package/dist/core/merge-order-check.js +343 -0
- package/dist/core/notification-dispatcher.d.ts +70 -0
- package/dist/core/notification-dispatcher.js +368 -0
- package/dist/core/notification-templates.d.ts +19 -0
- package/dist/core/notification-templates.js +139 -0
- package/dist/core/notifications.d.ts +10 -0
- package/dist/core/notifications.js +38 -0
- package/dist/core/pg-auth.d.ts +22 -0
- package/dist/core/pg-auth.js +152 -0
- package/dist/core/power-composition.d.ts +16 -0
- package/dist/core/power-composition.js +37 -0
- package/dist/core/power-idle.d.ts +14 -0
- package/dist/core/power-idle.js +30 -0
- package/dist/core/power.d.ts +71 -0
- package/dist/core/power.js +202 -0
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +8 -5
- package/dist/core/reconciler.js +37 -6
- package/dist/core/related-pull-requests.d.ts +59 -7
- package/dist/core/related-pull-requests.js +140 -25
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/repo-access.d.ts +15 -0
- package/dist/core/repo-access.js +66 -0
- package/dist/core/review-fix.d.ts +38 -1
- package/dist/core/review-fix.js +209 -7
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +23 -0
- package/dist/core/review-host-tools.js +156 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +384 -5
- package/dist/core/runner.js +1244 -372
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +39 -0
- package/dist/core/secret-broker-config.js +112 -0
- package/dist/core/secret-guard.d.ts +46 -0
- package/dist/core/secret-guard.js +104 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +39 -4
- package/dist/core/secrets.js +148 -40
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/workflow-event-recorder.d.ts +14 -0
- package/dist/core/workflow-event-recorder.js +120 -0
- package/dist/core/workflow-events.d.ts +94 -0
- package/dist/core/workflow-events.js +48 -0
- package/dist/core/workflow-run-events.d.ts +18 -0
- package/dist/core/workflow-run-events.js +75 -0
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +92 -3
- package/dist/generated/prisma/client.d.ts +92 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
- package/dist/generated/prisma/enums.d.ts +37 -0
- package/dist/generated/prisma/enums.js +31 -0
- package/dist/generated/prisma/internal/class.d.ts +132 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
- package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
- package/dist/generated/prisma/models/Agent.d.ts +464 -7
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -1
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
- package/dist/generated/prisma/models/CodingRun.d.ts +1841 -1
- package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1713 -0
- package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
- package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
- package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
- package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
- package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
- package/dist/generated/prisma/models/NotificationChannel.js +1 -0
- package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
- package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
- package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
- package/dist/generated/prisma/models/NotificationThread.js +1 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +1619 -58
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +37 -1
- package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
- package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
- package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
- package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
- package/dist/generated/prisma/models.d.ts +12 -0
- package/dist/help/build.js +4 -2
- package/dist/help/catalog.d.ts +1 -1
- package/dist/help/catalog.js +31 -6
- package/dist/help-index.json +2584 -146
- package/dist/import/create.js +49 -3
- package/dist/import/neutral-schema.d.ts +50 -277
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +11 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/repo-authorization.js +14 -0
- package/dist/mcp/auth/resource-server.d.ts +2 -1
- package/dist/mcp/auth/resource-server.js +7 -2
- package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/browser.js +19 -6
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +6 -0
- package/dist/mcp/host-events/github-ingress.d.ts +25 -1
- package/dist/mcp/host-events/github-ingress.js +70 -1
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.js +117 -20
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +277 -24
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +9 -3
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.d.ts +2 -0
- package/dist/mcp/tools/notification-channels.js +293 -0
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/power.d.ts +2 -0
- package/dist/mcp/tools/power.js +77 -0
- package/dist/mcp/tools/repositories.js +18 -5
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.d.ts +0 -6
- package/dist/mcp/tools/runs.js +41 -14
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
- package/dist/mcp/tools/secret-broker-compat.js +23 -0
- package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
- package/dist/mcp/tools/secret-elicitation-form.js +205 -10
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -54
- package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
- package/dist/mcp/tools/secret-elicitation.js +110 -12
- package/dist/mcp/tools/secrets.js +186 -9
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +2 -2
- package/dist/mcp/tools/tools.js +47 -11
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/native-worker/composition.d.ts +23 -0
- package/dist/native-worker/composition.js +77 -0
- package/dist/native-worker/docker-isolation.d.ts +65 -0
- package/dist/native-worker/docker-isolation.js +183 -0
- package/dist/native-worker/docker-launcher.d.ts +110 -0
- package/dist/native-worker/docker-launcher.js +297 -0
- package/dist/native-worker/gateway-server.d.ts +77 -0
- package/dist/native-worker/gateway-server.js +412 -0
- package/dist/native-worker/gateway.d.ts +70 -0
- package/dist/native-worker/gateway.js +263 -0
- package/dist/native-worker/http-server.d.ts +24 -0
- package/dist/native-worker/http-server.js +113 -0
- package/dist/native-worker/http-transport.d.ts +17 -0
- package/dist/native-worker/http-transport.js +88 -0
- package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
- package/dist/native-worker/kubernetes-isolation.js +218 -0
- package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
- package/dist/native-worker/kubernetes-launcher.js +375 -0
- package/dist/native-worker/launch.d.ts +62 -0
- package/dist/native-worker/launch.js +49 -0
- package/dist/native-worker/ledger.d.ts +125 -0
- package/dist/native-worker/ledger.js +245 -0
- package/dist/native-worker/loopback.d.ts +12 -0
- package/dist/native-worker/loopback.js +44 -0
- package/dist/native-worker/main.d.ts +8 -0
- package/dist/native-worker/main.js +85 -0
- package/dist/native-worker/protocol.d.ts +296 -0
- package/dist/native-worker/protocol.js +246 -0
- package/dist/native-worker/sandbox-executor.d.ts +83 -0
- package/dist/native-worker/sandbox-executor.js +284 -0
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +29 -0
- package/dist/native-worker/stdio.js +189 -0
- package/dist/native-worker/warm-delivery.d.ts +16 -0
- package/dist/native-worker/warm-delivery.js +33 -0
- package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
- package/dist/native-worker/warm-pool-ledger.js +73 -0
- package/dist/native-worker/warm-pool.d.ts +107 -0
- package/dist/native-worker/warm-pool.js +283 -0
- package/dist/native-worker/worker.d.ts +17 -0
- package/dist/native-worker/worker.js +141 -0
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/authorization-server.d.ts +3 -0
- package/dist/providers/auth/index.js +2 -0
- package/dist/providers/auth/self-hosted.d.ts +14 -2
- package/dist/providers/auth/self-hosted.js +54 -4
- package/dist/providers/chat/fake.d.ts +46 -0
- package/dist/providers/chat/fake.js +39 -0
- package/dist/providers/chat/index.d.ts +4 -0
- package/dist/providers/chat/index.js +8 -0
- package/dist/providers/chat/slack.d.ts +37 -0
- package/dist/providers/chat/slack.js +105 -0
- package/dist/providers/chat/types.d.ts +42 -0
- package/dist/providers/chat/types.js +19 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
- package/dist/providers/coding-proxy/memory-ledger.js +84 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
- package/dist/providers/coding-proxy/proxy.d.ts +14 -1
- package/dist/providers/coding-proxy/proxy.js +166 -14
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +4 -0
- package/dist/providers/coding-proxy/runtime.js +78 -16
- package/dist/providers/coding-proxy/server.d.ts +6 -1
- package/dist/providers/coding-proxy/server.js +45 -1
- package/dist/providers/coding-proxy/types.d.ts +65 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +36 -2
- package/dist/providers/engine/types.js +39 -0
- package/dist/providers/executor/composition.d.ts +31 -1
- package/dist/providers/executor/composition.js +81 -8
- package/dist/providers/executor/container.d.ts +385 -9
- package/dist/providers/executor/container.js +1234 -99
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +91 -0
- package/dist/providers/executor/dbos.js +319 -26
- package/dist/providers/executor/deferred.d.ts +44 -0
- package/dist/providers/executor/deferred.js +100 -0
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +39 -10
- package/dist/providers/executor/routing.js +77 -32
- package/dist/providers/executor/types.d.ts +25 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +8 -0
- package/dist/providers/jobs/docker-isolation.js +17 -0
- package/dist/providers/jobs/docker.d.ts +1 -0
- package/dist/providers/jobs/docker.js +29 -4
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
- package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
- package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
- package/dist/providers/jobs/kubernetes-api.js +17 -0
- package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
- package/dist/providers/jobs/kubernetes-client.js +61 -3
- package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
- package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +23 -1
- package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
- package/dist/providers/jobs/kubernetes-platform.js +38 -1
- package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
- package/dist/providers/jobs/kubernetes-preflight.js +4 -2
- package/dist/providers/jobs/kubernetes.d.ts +42 -2
- package/dist/providers/jobs/kubernetes.js +178 -19
- package/dist/providers/jobs/metadata-probes.d.ts +11 -0
- package/dist/providers/jobs/metadata-probes.js +13 -0
- package/dist/providers/jobs/types.d.ts +42 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +39 -2
- package/dist/providers/review-host/github.js +274 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +157 -2
- package/dist/providers/review-host/types.js +8 -0
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +33 -2
- package/dist/providers/vcs/git.js +324 -22
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +246 -12
- package/dist/providers/vcs/github.js +521 -61
- package/dist/providers/vcs/index.js +8 -1
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +33 -1
- package/dist/providers/vcs/routing.d.ts +4 -2
- package/dist/providers/vcs/routing.js +6 -0
- package/dist/providers/vcs/types.d.ts +80 -3
- package/dist/quickstart/coding-seed.d.ts +21 -3
- package/dist/quickstart/coding-seed.js +283 -3
- package/dist/quickstart/images.d.ts +2 -0
- package/dist/quickstart/images.js +7 -1
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/brokered-fetch.d.ts +23 -0
- package/dist/sandbox/brokered-fetch.js +37 -0
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +35 -0
- package/dist/sandbox/host-functions.js +150 -91
- package/dist/sandbox/prelude.js +7 -1
- package/dist/sandbox/run-in-sandbox.d.ts +19 -0
- package/dist/sandbox/run-in-sandbox.js +28 -10
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +3 -1
- package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
- package/dist/sandbox/secret-broker-sigv4.js +49 -0
- package/dist/sandbox/secret-broker.d.ts +34 -0
- package/dist/sandbox/secret-broker.js +161 -0
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/user-tool.d.ts +14 -0
- package/dist/sandbox/user-tool.js +32 -0
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +25 -0
- package/dist/viewer/api-schema.d.ts +372 -2454
- package/dist/viewer/api-schema.js +29 -0
- package/dist/viewer/build-schemas.js +10 -3
- package/dist/viewer/event-bus.d.ts +6 -0
- package/dist/viewer/event-bus.js +16 -7
- package/dist/viewer/graph.d.ts +5 -2
- package/dist/viewer/graph.js +7 -2
- package/dist/viewer/http.d.ts +0 -1
- package/dist/viewer/http.js +2 -2
- package/dist/viewer/infra.js +25 -2
- package/dist/viewer/limits.d.ts +4 -0
- package/dist/viewer/limits.js +4 -0
- package/dist/viewer/openapi.d.ts +15 -0
- package/dist/viewer/openapi.js +170 -0
- package/dist/wardby-bin.js +10 -0
- package/docs/README.md +7 -0
- package/docs/agent-recipes.md +114 -27
- package/docs/architecture-runtime.md +16 -1
- package/docs/code-review-agents.md +689 -45
- package/docs/coding-agent-setup.md +602 -12
- package/docs/coding-packages.md +1037 -92
- package/docs/coding-services.md +30 -13
- package/docs/coding-worker-byo-images.md +218 -6
- package/docs/coding-worker-isolation.md +173 -44
- package/docs/getting-started-gke.md +332 -129
- package/docs/getting-started-identity-provider.md +31 -11
- package/docs/getting-started.md +14 -4
- package/docs/jira-agents.md +22 -9
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/native-sandbox.md +731 -0
- package/docs/observability.md +4 -0
- package/docs/release-verification.md +9 -0
- package/docs/security-deployment.md +146 -14
- package/docs/slack-notifications.md +268 -0
- package/docs/tool-secrets.md +284 -0
- package/docs/viewer-api.md +46 -5
- package/docs/viewer-api.openapi.yml +1404 -0
- package/help/admin-viewer.md +29 -3
- package/help/agent-recipes.md +27 -0
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +79 -0
- package/help/build-claude-code-image.md +131 -0
- package/help/build-worker-image.md +6 -7
- package/help/builder-agent.md +19 -6
- package/help/code-review-agents.md +243 -10
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +23 -9
- package/help/deployment-targets.md +25 -14
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-provider-not-configured.md +2 -2
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +28 -0
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +29 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/low-power-disabled.md +29 -0
- package/help/errors/low-power-scale-forbidden.md +35 -0
- package/help/errors/low-power-wake-timeout.md +30 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/mobile-disabled.md +31 -0
- package/help/errors/native-sandbox-capacity.md +22 -0
- package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
- package/help/errors/native-sandbox-docker-failed.md +20 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
- package/help/errors/native-sandbox-image-not-pinned.md +19 -0
- package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +22 -0
- package/help/errors/native-sandbox-requires-catalog.md +31 -0
- package/help/errors/native-sandbox-unavailable.md +19 -0
- package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +21 -0
- package/help/errors/native-sandbox-worker-lost.md +20 -0
- package/help/errors/native-sandbox-worker-unready.md +22 -0
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-broker-body-invalid.md +26 -0
- package/help/errors/secret-broker-changed.md +20 -0
- package/help/errors/secret-broker-config-invalid.md +30 -0
- package/help/errors/secret-broker-conflict.md +27 -0
- package/help/errors/secret-broker-destination-denied.md +28 -0
- package/help/errors/secret-broker-value-invalid.md +28 -0
- package/help/errors/secret-brokered.md +24 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/secret-not-brokered.md +25 -0
- package/help/errors/slack-auth-failed.md +48 -0
- package/help/errors/slack-channel-unreachable.md +39 -0
- package/help/errors/slack-not-configured.md +33 -0
- package/help/errors/target-merge.md +40 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/getting-started.md +4 -5
- package/help/github-app-setup.md +132 -0
- package/help/github.md +40 -1
- package/help/identity-and-access.md +7 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +3 -4
- package/help/low-power-mode.md +131 -0
- package/help/merge-order-check.md +122 -0
- package/help/mobile-app.md +54 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +150 -0
- package/help/observability.md +8 -0
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +80 -16
- package/help/repo-instructions-and-skills.md +91 -0
- package/help/resume-runs-locally.md +131 -0
- package/help/review-fix-rounds.md +43 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +76 -0
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +99 -7
- package/package.json +27 -13
- package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
- package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
- package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
- package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
- package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
- package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
- package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
- package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
- package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
- package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
- package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
- package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
- package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
- package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/schema.prisma +631 -146
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
package/dist/mcp/tools/grants.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import { Prisma } from "#prisma";
|
|
15
|
-
import { EVERYONE_KEY, EVERYONE_MAX, LEVELS, SHAREABLE_TYPES, accessRank, atLeast, isLevel, isResourceType, principalGranteeKey, } from "../../core/grants.js";
|
|
15
|
+
import { EVERYONE_KEY, EVERYONE_MAX, LEVELS, agentOwnerBindings, SHAREABLE_TYPES, accessRank, atLeast, isLevel, isResourceType, principalGranteeKey, } from "../../core/grants.js";
|
|
16
16
|
import { agentNotFound, assertAgentAccess, agentAccess } from "../auth/access.js";
|
|
17
17
|
import { permissionsOf } from "../auth/resource-server.js";
|
|
18
18
|
import { McpError } from "../errors.js";
|
|
@@ -107,7 +107,7 @@ export function registerGrantTools(mcp) {
|
|
|
107
107
|
"Owner-only whatever the level: the coding profile (task, base ref, protected paths, task-override opt-in, image, packages, limits), kind, budget group, sub-agents, secret/datastore/repository bindings, tool capabilities, memory and datastore contents, grants, delete. " +
|
|
108
108
|
"Consequences: execute lets them run your agent with your tools, secrets, datastores and repository, and every run shares the agent's memory; they supply no task text unless it's a coding agent with allowWebhookTaskOverride. " +
|
|
109
109
|
"Write lets them rewrite what those runs do: the prompt can make a run use everything the agent can already reach (the capabilities you granted, its memory, its linked repositories), and on a coding agent the prompt is part of every coding task, so write directs work done with your GitHub access. " +
|
|
110
|
-
"Granting again replaces the level. Everyone
|
|
110
|
+
"Granting again replaces the level. Everyone may get write only on a native agent with no secrets, datastores, repositories, sub-agents or tool capabilities. The grantee must have signed in once.",
|
|
111
111
|
inputSchema: {
|
|
112
112
|
type: "object",
|
|
113
113
|
additionalProperties: false,
|
|
@@ -131,7 +131,13 @@ export function registerGrantTools(mcp) {
|
|
|
131
131
|
throw new McpError(400, "The owner already has full access; a grant to yourself or the owner changes nothing.");
|
|
132
132
|
}
|
|
133
133
|
if (!principal && accessRank(type, args.level) > accessRank(type, EVERYONE_MAX[type])) {
|
|
134
|
-
throw new McpError(400, `An everyone grant can be at most ${EVERYONE_MAX[type]}
|
|
134
|
+
throw new McpError(400, `An everyone grant can be at most ${EVERYONE_MAX[type]}.`);
|
|
135
|
+
}
|
|
136
|
+
if (!principal && atLeast(type, args.level, "write")) {
|
|
137
|
+
const bindings = await agentOwnerBindings(tx, resource.id);
|
|
138
|
+
if (bindings.length) {
|
|
139
|
+
throw new McpError(409, `Agent "${resource.id}" holds ${bindings.join(", ")}: write for everyone would let anyone rewrite an agent that uses them. Detach them first, or grant everyone execute.`);
|
|
140
|
+
}
|
|
135
141
|
}
|
|
136
142
|
const granteeKey = principal ? principalGranteeKey(principal.id) : EVERYONE_KEY;
|
|
137
143
|
const grant = await tx.resourceGrant.upsert({
|
package/dist/mcp/tools/memory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { requireAgentAccess } from "../auth/access.js";
|
|
2
2
|
import { textResult } from "./text-result.js";
|
|
3
|
+
import { SecretInValueError, SecretCheckUnavailableError } from "../../core/secret-guard.js";
|
|
4
|
+
import { McpError } from "../errors.js";
|
|
3
5
|
export function registerMemoryTools(mcp) {
|
|
4
6
|
mcp.registerTool({
|
|
5
7
|
name: "get_agent_memory",
|
|
@@ -39,7 +41,15 @@ export function registerMemoryTools(mcp) {
|
|
|
39
41
|
},
|
|
40
42
|
handler: async (args, ctx) => {
|
|
41
43
|
await requireAgentAccess(ctx, args.agentId, "owner");
|
|
42
|
-
|
|
44
|
+
try {
|
|
45
|
+
await ctx.providers.memory.set(args.agentId, args.key, args.content);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err instanceof SecretInValueError || err instanceof SecretCheckUnavailableError) {
|
|
49
|
+
throw new McpError(400, err.message);
|
|
50
|
+
}
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
43
53
|
return textResult({ ok: true });
|
|
44
54
|
},
|
|
45
55
|
});
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NotificationChannel CRUD — admin-approved links from a Slack channel to a
|
|
3
|
+
* Jira project or to an agent (native or coding), so wardby's workflow dispatcher
|
|
4
|
+
* (core/notification-dispatcher.ts) knows where to post a card's lifecycle:
|
|
5
|
+
* picked up, PR opened, review verdict, fix rounds, merge. Outbound only —
|
|
6
|
+
* wardby never reads a channel's history, and linking posts nothing.
|
|
7
|
+
*
|
|
8
|
+
* Same trust model as link_issue_project (src/mcp/tools/issue-projects.ts):
|
|
9
|
+
* wardby cannot verify a caller's own Slack workspace access (one bot token
|
|
10
|
+
* for the whole deployment, no per-user OAuth), so link/unlink/test need
|
|
11
|
+
* agents:admin with the admin role, and the approver is stamped on the
|
|
12
|
+
* link. Exactly one of projectKey/agentId is the link's subject (enforced
|
|
13
|
+
* again by a DB CHECK constraint); `events` narrows which of the
|
|
14
|
+
* workflow event kinds post to it (empty/omitted = all); private Slack
|
|
15
|
+
* channels always need /invite @<app> before the bot can see or post to
|
|
16
|
+
* them. See docs/private/2026-10-08-slack-workflow-notifications-design.md §8.
|
|
17
|
+
*/
|
|
18
|
+
import { Prisma } from "#prisma";
|
|
19
|
+
import { requireAgentAccess } from "../auth/access.js";
|
|
20
|
+
import { requireScope } from "../auth/resource-server.js";
|
|
21
|
+
import { McpError } from "../errors.js";
|
|
22
|
+
import { PROJECT_KEY } from "../../providers/issue-tracker/types.js";
|
|
23
|
+
import { ChatError } from "../../providers/chat/types.js";
|
|
24
|
+
import { WORKFLOW_EVENT_KINDS } from "../../core/workflow-events.js";
|
|
25
|
+
import { textResult } from "./text-result.js";
|
|
26
|
+
const CHAT_PROVIDERS = ["slack"];
|
|
27
|
+
/** Slack channel id: C… (public) or G… (private), case-insensitive, normalized upper-case. */
|
|
28
|
+
const CHANNEL_ID = /^[CG][A-Z0-9]{2,20}$/i;
|
|
29
|
+
function normalizeProjectKey(projectKey) {
|
|
30
|
+
const key = projectKey.trim().toUpperCase();
|
|
31
|
+
if (!PROJECT_KEY.test(key))
|
|
32
|
+
throw new McpError(400, `invalid projectKey "${projectKey}"`);
|
|
33
|
+
return key;
|
|
34
|
+
}
|
|
35
|
+
function normalizeChannelId(channel) {
|
|
36
|
+
const id = channel.trim().toUpperCase();
|
|
37
|
+
if (!CHANNEL_ID.test(id)) {
|
|
38
|
+
throw new McpError(400, "Pass the channel id (C…); find it in the channel's details in Slack.");
|
|
39
|
+
}
|
|
40
|
+
return id;
|
|
41
|
+
}
|
|
42
|
+
export function registerNotificationChannelTools(mcp) {
|
|
43
|
+
mcp.registerTool({
|
|
44
|
+
name: "link_notification_channel",
|
|
45
|
+
scope: "agents:write",
|
|
46
|
+
description: "Links a Slack channel to a Jira project or to an agent (native or coding), so wardby posts that project's or " +
|
|
47
|
+
"agent's workflow updates there: a card picked up, a PR opened, a review verdict, fix rounds, and the merge (one thread per card). " +
|
|
48
|
+
"Outbound only — wardby never reads the channel's history, and nothing in Slack starts work. Admin-approved " +
|
|
49
|
+
"(agents:admin with the admin role), the same trust model as link_issue_project: wardby cannot verify a caller's " +
|
|
50
|
+
"own Slack workspace access, so an admin approves every link and is stamped as its authorizer. " +
|
|
51
|
+
"Exactly one of projectKey or agentId is the link's subject: a project link (with issueProvider, default jira) " +
|
|
52
|
+
"matches events for issues in that project; an agent link matches events for that agent's runs. " +
|
|
53
|
+
"channel is the Slack channel id (C… for public, G… for private), never a #name — find it in the channel's " +
|
|
54
|
+
"details in Slack. Private channels always need /invite @<app> before the bot can see or post to them. " +
|
|
55
|
+
"events narrows which of the workflow event kinds post to this link; empty or omitted means all. " +
|
|
56
|
+
"includeCost appends the run's spend line to messages. Re-linking the same channel + subject replaces events and " +
|
|
57
|
+
"includeCost and clears any previously recorded delivery error — always send the full desired state.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
properties: {
|
|
62
|
+
provider: { type: "string", enum: [...CHAT_PROVIDERS] },
|
|
63
|
+
channel: { type: "string", minLength: 1, maxLength: 64 },
|
|
64
|
+
projectKey: { type: "string", minLength: 1, maxLength: 255 },
|
|
65
|
+
issueProvider: { type: "string", enum: ["jira"] },
|
|
66
|
+
agentId: { type: "string" },
|
|
67
|
+
events: { type: "array", items: { type: "string", enum: [...WORKFLOW_EVENT_KINDS] }, uniqueItems: true },
|
|
68
|
+
includeCost: { type: "boolean" },
|
|
69
|
+
},
|
|
70
|
+
required: ["channel"],
|
|
71
|
+
},
|
|
72
|
+
handler: async (args, ctx) => {
|
|
73
|
+
requireScope(ctx, ctx.canonicalUri, "agents:admin");
|
|
74
|
+
const provider = args.provider ?? "slack";
|
|
75
|
+
const chat = ctx.providers.chat?.[provider];
|
|
76
|
+
if (!chat) {
|
|
77
|
+
throw new McpError(400, "Slack is not configured (WARDBY_SLACK_BOT_TOKEN). See help article errors/slack-not-configured.");
|
|
78
|
+
}
|
|
79
|
+
const hasProject = args.projectKey !== undefined;
|
|
80
|
+
const hasAgent = args.agentId !== undefined;
|
|
81
|
+
if (hasProject === hasAgent) {
|
|
82
|
+
throw new McpError(400, "Give exactly one of projectKey or agentId.");
|
|
83
|
+
}
|
|
84
|
+
let issueProvider = null;
|
|
85
|
+
let projectKey = null;
|
|
86
|
+
let agentId = null;
|
|
87
|
+
if (hasProject) {
|
|
88
|
+
issueProvider = args.issueProvider ?? "jira";
|
|
89
|
+
projectKey = normalizeProjectKey(args.projectKey);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
agentId = args.agentId;
|
|
93
|
+
const agent = await ctx.db.agent.findUnique({ where: { id: agentId } });
|
|
94
|
+
if (!agent)
|
|
95
|
+
throw new McpError(404, `Agent "${agentId}" not found.`);
|
|
96
|
+
}
|
|
97
|
+
const channelId = normalizeChannelId(args.channel);
|
|
98
|
+
// `info` is undefined when channelInfo can't be validated at all
|
|
99
|
+
// (missing_scope: no channels:read/groups:read — accept the id
|
|
100
|
+
// unvalidated); any other auth failure (revoked or invalid token) is a
|
|
101
|
+
// real error the operator must fix before linking. `info` is
|
|
102
|
+
// null when the bot genuinely cannot see the channel (an error, not a
|
|
103
|
+
// validation gap) — kept out of the try/catch below so the 400 for
|
|
104
|
+
// "bot cannot see this channel" isn't routed through ChatError handling.
|
|
105
|
+
let info;
|
|
106
|
+
try {
|
|
107
|
+
info = await chat.channelInfo(channelId);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (!(err instanceof ChatError && err.code === "auth_failed"))
|
|
111
|
+
throw err;
|
|
112
|
+
if (err.slackError !== "missing_scope") {
|
|
113
|
+
throw new McpError(400, `Slack rejected the bot token (${err.slackError}). See help article errors/slack-auth-failed.`);
|
|
114
|
+
}
|
|
115
|
+
info = undefined;
|
|
116
|
+
}
|
|
117
|
+
if (info === null) {
|
|
118
|
+
throw new McpError(400, `The bot cannot see channel ${channelId}: invite it with /invite @<app> (private channels always need ` +
|
|
119
|
+
"this). See errors/slack-channel-unreachable.");
|
|
120
|
+
}
|
|
121
|
+
const channelName = info ? info.name : null;
|
|
122
|
+
const events = [...new Set(args.events ?? [])];
|
|
123
|
+
const includeCost = args.includeCost ?? false;
|
|
124
|
+
const fields = {
|
|
125
|
+
channelName,
|
|
126
|
+
events,
|
|
127
|
+
includeCost,
|
|
128
|
+
lastError: null,
|
|
129
|
+
lastErrorAt: null,
|
|
130
|
+
authorizedById: ctx.principal.id,
|
|
131
|
+
authorizedAt: new Date(),
|
|
132
|
+
};
|
|
133
|
+
// Can't use Prisma `upsert` here: Postgres treats NULLs as distinct
|
|
134
|
+
// within a unique index, and this link's unique keys
|
|
135
|
+
// (provider, channelId, issueProvider, projectKey) / (provider,
|
|
136
|
+
// channelId, agentId) each have two columns that are null for the
|
|
137
|
+
// other subject kind — so the where-unique input Prisma generates for
|
|
138
|
+
// this compound key never matches an existing row the way a fully
|
|
139
|
+
// non-null key would. Find the existing row explicitly instead, then
|
|
140
|
+
// update it by id or create.
|
|
141
|
+
const subjectWhere = hasProject
|
|
142
|
+
? { provider, channelId, issueProvider, projectKey }
|
|
143
|
+
: { provider, channelId, agentId };
|
|
144
|
+
const existing = await ctx.db.notificationChannel.findFirst({ where: subjectWhere });
|
|
145
|
+
let link;
|
|
146
|
+
if (existing) {
|
|
147
|
+
link = await ctx.db.notificationChannel.update({ where: { id: existing.id }, data: fields });
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
try {
|
|
151
|
+
link = await ctx.db.notificationChannel.create({
|
|
152
|
+
data: { provider, channelId, issueProvider, projectKey, agentId, ...fields },
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
if (!(err instanceof Prisma.PrismaClientKnownRequestError) || err.code !== "P2002")
|
|
157
|
+
throw err;
|
|
158
|
+
// Lost a create race: another concurrent link_notification_channel
|
|
159
|
+
// call for the same channel + subject committed first. Re-linking
|
|
160
|
+
// an existing link is normal, documented behavior (it replaces
|
|
161
|
+
// events/includeCost and clears lastError) — so re-query and
|
|
162
|
+
// update that row instead of surfacing the race as an error.
|
|
163
|
+
const raced = await ctx.db.notificationChannel.findFirst({ where: subjectWhere });
|
|
164
|
+
if (!raced)
|
|
165
|
+
throw err;
|
|
166
|
+
link = await ctx.db.notificationChannel.update({ where: { id: raced.id }, data: fields });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return textResult({ link });
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
mcp.registerTool({
|
|
173
|
+
name: "unlink_notification_channel",
|
|
174
|
+
scope: "agents:write",
|
|
175
|
+
description: "Removes a notification channel link. Admin only (agents:admin with the admin role).",
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: "object",
|
|
178
|
+
additionalProperties: false,
|
|
179
|
+
properties: { id: { type: "string" } },
|
|
180
|
+
required: ["id"],
|
|
181
|
+
},
|
|
182
|
+
handler: async (args, ctx) => {
|
|
183
|
+
requireScope(ctx, ctx.canonicalUri, "agents:admin");
|
|
184
|
+
const { count } = await ctx.db.notificationChannel.deleteMany({ where: { id: args.id } });
|
|
185
|
+
return textResult({ unlinked: count > 0 });
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
mcp.registerTool({
|
|
189
|
+
name: "list_notification_channels",
|
|
190
|
+
scope: "agents:read",
|
|
191
|
+
description: "Lists notification channel links, each with its pending and failed delivery counts. Filter by projectKey, " +
|
|
192
|
+
"agentId, or channel (the Slack channel id). Listing an agent's own links needs read access to that agent; " +
|
|
193
|
+
"listing without agentId (every link, including project links) needs agents:admin with the admin role.",
|
|
194
|
+
inputSchema: {
|
|
195
|
+
type: "object",
|
|
196
|
+
additionalProperties: false,
|
|
197
|
+
properties: {
|
|
198
|
+
projectKey: { type: "string", minLength: 1, maxLength: 255 },
|
|
199
|
+
agentId: { type: "string" },
|
|
200
|
+
channel: { type: "string", minLength: 1, maxLength: 64 },
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
handler: async (args, ctx) => {
|
|
204
|
+
if (args.agentId !== undefined) {
|
|
205
|
+
await requireAgentAccess(ctx, args.agentId, "read");
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
requireScope(ctx, ctx.canonicalUri, "agents:admin");
|
|
209
|
+
}
|
|
210
|
+
const where = {};
|
|
211
|
+
if (args.agentId !== undefined)
|
|
212
|
+
where.agentId = args.agentId;
|
|
213
|
+
if (args.projectKey !== undefined)
|
|
214
|
+
where.projectKey = normalizeProjectKey(args.projectKey);
|
|
215
|
+
if (args.channel !== undefined)
|
|
216
|
+
where.channelId = normalizeChannelId(args.channel);
|
|
217
|
+
const links = await ctx.db.notificationChannel.findMany({ where, orderBy: { createdAt: "asc" } });
|
|
218
|
+
// Counts only for the listed links' own (provider, channel) pairs, so a
|
|
219
|
+
// caller never learns about deliveries to channels it cannot list.
|
|
220
|
+
const pairKey = (r) => `${r.provider}\u0000${r.channelId}`;
|
|
221
|
+
const pairs = [
|
|
222
|
+
...new Map(links.map((l) => [pairKey(l), { provider: l.provider, channelId: l.channelId }])).values(),
|
|
223
|
+
];
|
|
224
|
+
const counts = pairs.length === 0
|
|
225
|
+
? []
|
|
226
|
+
: await ctx.db.notificationDelivery.groupBy({
|
|
227
|
+
by: ["provider", "channelId", "state"],
|
|
228
|
+
where: { state: { in: ["pending", "failed"] }, OR: pairs },
|
|
229
|
+
_count: true,
|
|
230
|
+
});
|
|
231
|
+
const byChannel = new Map();
|
|
232
|
+
for (const row of counts) {
|
|
233
|
+
const entry = byChannel.get(pairKey(row)) ?? { pending: 0, failed: 0 };
|
|
234
|
+
if (row.state === "pending")
|
|
235
|
+
entry.pending = row._count;
|
|
236
|
+
else if (row.state === "failed")
|
|
237
|
+
entry.failed = row._count;
|
|
238
|
+
byChannel.set(pairKey(row), entry);
|
|
239
|
+
}
|
|
240
|
+
const channels = links.map((l) => ({
|
|
241
|
+
...l,
|
|
242
|
+
pending: byChannel.get(pairKey(l))?.pending ?? 0,
|
|
243
|
+
failed: byChannel.get(pairKey(l))?.failed ?? 0,
|
|
244
|
+
}));
|
|
245
|
+
return textResult({ channels });
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
mcp.registerTool({
|
|
249
|
+
name: "test_notification_channel",
|
|
250
|
+
scope: "agents:write",
|
|
251
|
+
description: "Posts a one-off confirmation message to a linked channel, to prove the bot can write there before relying on it " +
|
|
252
|
+
"for workflow notifications (a private channel needs /invite @<app> first; a channel the bot can't reach " +
|
|
253
|
+
"surfaces its error immediately instead of silently queueing). Admin only (agents:admin with the admin role).",
|
|
254
|
+
inputSchema: {
|
|
255
|
+
type: "object",
|
|
256
|
+
additionalProperties: false,
|
|
257
|
+
properties: { id: { type: "string" } },
|
|
258
|
+
required: ["id"],
|
|
259
|
+
},
|
|
260
|
+
handler: async (args, ctx) => {
|
|
261
|
+
requireScope(ctx, ctx.canonicalUri, "agents:admin");
|
|
262
|
+
const link = await ctx.db.notificationChannel.findUnique({ where: { id: args.id } });
|
|
263
|
+
if (!link)
|
|
264
|
+
throw new McpError(404, `Notification channel link "${args.id}" not found.`);
|
|
265
|
+
const chat = ctx.providers.chat?.[link.provider];
|
|
266
|
+
if (!chat) {
|
|
267
|
+
throw new McpError(400, "Slack is not configured (WARDBY_SLACK_BOT_TOKEN). See help article errors/slack-not-configured.");
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
await chat.postMessage(link.channelId, { text: "✅ wardby is connected to this channel." });
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
if (!(err instanceof ChatError))
|
|
274
|
+
throw err;
|
|
275
|
+
if (err.code === "channel_unreachable") {
|
|
276
|
+
await ctx.db.notificationChannel.update({
|
|
277
|
+
where: { id: link.id },
|
|
278
|
+
data: { lastError: err.slackError, lastErrorAt: new Date() },
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
throw new McpError(400, `${err.code}: ${err.slackError}`);
|
|
282
|
+
}
|
|
283
|
+
// The bot can post here again: clear any recorded delivery error.
|
|
284
|
+
if (link.lastError !== null || link.lastErrorAt !== null) {
|
|
285
|
+
await ctx.db.notificationChannel.update({
|
|
286
|
+
where: { id: link.id },
|
|
287
|
+
data: { lastError: null, lastErrorAt: null },
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return textResult({ tested: true });
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* approve_audited_packages: promotes what package audit mode recorded on a
|
|
3
|
+
* run (docs/coding-packages.md#package-audit-mode) into the agent's package
|
|
4
|
+
* allowlist, as bare names. Only `top-level` records are promoted by
|
|
5
|
+
* default; an `unknown` one (a direct download, or after a plan fallback)
|
|
6
|
+
* may really be a dependency of an allowlisted package, so it is promoted
|
|
7
|
+
* only when `names` lists it. A `transitive` one follows its parent once that is allowlisted,
|
|
8
|
+
* and an `allowed` one is already on the allowlist graph (it was recorded
|
|
9
|
+
* only for the advisories full mode served past, which approving cannot
|
|
10
|
+
* waive). For a parent run, each coding sub-run's names go to that sub-run's
|
|
11
|
+
* own agent. Same gate as packageAllowlist: packages:approve or agents:admin,
|
|
12
|
+
* and only the agent's owner. Every agent is checked before any is written,
|
|
13
|
+
* and all are written in one transaction, so a refusal changes nothing.
|
|
14
|
+
* Package audit mode itself is left as it is.
|
|
15
|
+
*/
|
|
16
|
+
import { Prisma } from "#prisma";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { matchRoot, parseAllowlist } from "../../coding/registry/allowlist.js";
|
|
19
|
+
import { UNKNOWN_RELATION_LABEL } from "../../coding/registry/audit-mode.js";
|
|
20
|
+
import { REGISTRY_ADAPTERS } from "../../coding/registry/adapters.js";
|
|
21
|
+
import { logger } from "../../core/logger.js";
|
|
22
|
+
import { agentAccess } from "../auth/access.js";
|
|
23
|
+
import { requireAnyScope } from "../auth/resource-server.js";
|
|
24
|
+
import { McpError } from "../errors.js";
|
|
25
|
+
import { textResult } from "./text-result.js";
|
|
26
|
+
const packagesLog = logger.child({ module: "mcp-packages" });
|
|
27
|
+
/** codingProfile.packageAllowlist's own cap per ecosystem (coding/profile.ts). */
|
|
28
|
+
const MAX_ALLOWLIST_ENTRIES = 256;
|
|
29
|
+
const ApproveSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
runId: z.string().trim().min(1).max(128),
|
|
32
|
+
names: z.array(z.string().min(1).max(256)).min(1).max(MAX_ALLOWLIST_ENTRIES).optional(),
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
export function registerPackageTools(mcp) {
|
|
36
|
+
mcp.registerTool({
|
|
37
|
+
name: "approve_audited_packages",
|
|
38
|
+
scope: "agents:write",
|
|
39
|
+
description: "Add the packages a run installed under package audit mode to its agent's codingProfile.packageAllowlist, as " +
|
|
40
|
+
"bare names (the top-level records in get_run's packageAudit; their dependencies then follow through the " +
|
|
41
|
+
"allowlist graph). Records with relation unknown may be dependencies of allowlisted packages: they are added only " +
|
|
42
|
+
"when `names` lists them, and are returned as `unknown` otherwise. For a parent run, each coding sub-run's " +
|
|
43
|
+
"packages go to that sub-run's agent; nothing is changed unless every agent can be. `names` limits it to those " +
|
|
44
|
+
"names. Needs packages:approve or agents:admin, and only the agent's owner may use it. Does not turn package " +
|
|
45
|
+
"audit mode off.",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
properties: {
|
|
50
|
+
runId: { type: "string", description: "The run whose package audit to approve (get_run's packageAudit)." },
|
|
51
|
+
names: {
|
|
52
|
+
type: "array",
|
|
53
|
+
items: { type: "string" },
|
|
54
|
+
description: "Only these package names (as get_run lists them), including any with relation unknown to add; omitted means every top-level one.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
required: ["runId"],
|
|
58
|
+
},
|
|
59
|
+
handler: async (raw, ctx) => {
|
|
60
|
+
const parsed = ApproveSchema.safeParse(raw);
|
|
61
|
+
if (!parsed.success) {
|
|
62
|
+
const details = parsed.error.issues.map((i) => `${i.path.join(".") || "input"}: ${i.message}`).join("; ");
|
|
63
|
+
throw new McpError(400, `Invalid approve_audited_packages arguments: ${details}`);
|
|
64
|
+
}
|
|
65
|
+
const { runId, names } = parsed.data;
|
|
66
|
+
// The same gate as changing packageAllowlist through update_agent.
|
|
67
|
+
requireAnyScope(ctx, ctx.canonicalUri, "packages:approve", "agents:admin");
|
|
68
|
+
// Visible to the agent's owner and the run's triggerer only, exactly as get_run.
|
|
69
|
+
const notFound = new McpError(404, `Run "${runId}" not found.`);
|
|
70
|
+
const run = await ctx.db.run.findUnique({
|
|
71
|
+
where: { id: runId },
|
|
72
|
+
select: { id: true, agentId: true, triggeredById: true },
|
|
73
|
+
});
|
|
74
|
+
if (!run)
|
|
75
|
+
throw notFound;
|
|
76
|
+
if (run.triggeredById !== ctx.principal.id) {
|
|
77
|
+
const agent = await ctx.db.agent.findUnique({ where: { id: run.agentId } });
|
|
78
|
+
if (!agent || (await agentAccess(ctx, agent)) !== "owner")
|
|
79
|
+
throw notFound;
|
|
80
|
+
}
|
|
81
|
+
// The coding runs whose records count, with the agent each one belongs to.
|
|
82
|
+
const coding = await ctx.db.codingRun.findUnique({ where: { runId }, select: { runId: true } });
|
|
83
|
+
const targets = coding
|
|
84
|
+
? [{ runId, agentId: run.agentId }]
|
|
85
|
+
: (await ctx.db.run.findMany({
|
|
86
|
+
where: { parentRunId: runId },
|
|
87
|
+
select: { id: true, agentId: true, codingRun: { select: { runId: true } } },
|
|
88
|
+
}))
|
|
89
|
+
.filter((child) => child.codingRun)
|
|
90
|
+
.map((child) => ({ runId: child.id, agentId: child.agentId }));
|
|
91
|
+
const agentOf = new Map(targets.map((target) => [target.runId, target.agentId]));
|
|
92
|
+
const records = targets.length > 0
|
|
93
|
+
? await ctx.db.registryAuditRecord.findMany({
|
|
94
|
+
where: { runId: { in: targets.map((target) => target.runId) } },
|
|
95
|
+
select: { runId: true, ecosystem: true, name: true, relation: true },
|
|
96
|
+
orderBy: { createdAt: "asc" },
|
|
97
|
+
})
|
|
98
|
+
: [];
|
|
99
|
+
const wanted = names ? new Set(names) : null;
|
|
100
|
+
/** agentId -> ecosystem -> names to add, first-seen order. */
|
|
101
|
+
const byAgent = new Map();
|
|
102
|
+
/** Unknown-relation names left out (not named), per ecosystem + name. */
|
|
103
|
+
const skippedUnknown = new Map();
|
|
104
|
+
const topLevel = new Set(records.filter((r) => r.relation === "top-level").map((r) => `${r.runId}\0${r.ecosystem}\0${r.name}`));
|
|
105
|
+
for (const record of records) {
|
|
106
|
+
if (record.relation !== "top-level" && record.relation !== "unknown")
|
|
107
|
+
continue;
|
|
108
|
+
if (wanted ? !wanted.has(record.name) : record.relation !== "top-level") {
|
|
109
|
+
if (!wanted && !topLevel.has(`${record.runId}\0${record.ecosystem}\0${record.name}`))
|
|
110
|
+
skippedUnknown.set(`${record.ecosystem}\0${record.name}`, {
|
|
111
|
+
ecosystem: record.ecosystem,
|
|
112
|
+
name: record.name,
|
|
113
|
+
});
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const agentId = agentOf.get(record.runId);
|
|
117
|
+
const ecosystems = byAgent.get(agentId) ?? new Map();
|
|
118
|
+
byAgent.set(agentId, ecosystems);
|
|
119
|
+
ecosystems.set(record.ecosystem, (ecosystems.get(record.ecosystem) ?? new Set()).add(record.name));
|
|
120
|
+
}
|
|
121
|
+
// One transaction: every agent is checked (owner, coding, the cap) before any is written.
|
|
122
|
+
const results = await ctx.db.$transaction(async (tx) => {
|
|
123
|
+
const planned = [];
|
|
124
|
+
for (const [agentId, ecosystems] of byAgent) {
|
|
125
|
+
const agent = await tx.agent.findUnique({ where: { id: agentId }, include: { codingProfile: true } });
|
|
126
|
+
if (!agent?.codingProfile || agent.kind !== "coding") {
|
|
127
|
+
throw new McpError(400, `Agent "${agentId}" is not a coding agent.`);
|
|
128
|
+
}
|
|
129
|
+
// Strict, like update_agent's coding profile: the owner only.
|
|
130
|
+
if (agent.ownerId === null || agent.ownerId !== ctx.principal.id) {
|
|
131
|
+
throw new McpError(403, `Agent "${agentId}": only its owner can change its package allowlist.`);
|
|
132
|
+
}
|
|
133
|
+
const current = (agent.codingProfile.packageAllowlist ?? {});
|
|
134
|
+
const parsedCurrent = parseAllowlist(current, REGISTRY_ADAPTERS);
|
|
135
|
+
const next = Object.fromEntries(Object.entries(current).map(([ecosystem, entries]) => [ecosystem, [...entries]]));
|
|
136
|
+
const added = {};
|
|
137
|
+
for (const [ecosystem, candidates] of ecosystems) {
|
|
138
|
+
const adapter = REGISTRY_ADAPTERS.get(ecosystem);
|
|
139
|
+
if (!adapter)
|
|
140
|
+
continue;
|
|
141
|
+
const entries = parsedCurrent.get(ecosystem) ?? [];
|
|
142
|
+
const list = next[ecosystem] ?? [];
|
|
143
|
+
for (const name of candidates) {
|
|
144
|
+
// Already allowed (exactly, by a ranged entry, or a wildcard): an entry's range is the owner's.
|
|
145
|
+
if (list.includes(name) || matchRoot(entries, adapter.normalizeName(name)))
|
|
146
|
+
continue;
|
|
147
|
+
list.push(name);
|
|
148
|
+
(added[ecosystem] ??= []).push(name);
|
|
149
|
+
}
|
|
150
|
+
if (list.length > MAX_ALLOWLIST_ENTRIES) {
|
|
151
|
+
throw new McpError(400, `Agent "${agentId}": approving these would put ${list.length} ${ecosystem} entries on its allowlist; the limit is ${MAX_ALLOWLIST_ENTRIES}. Approve fewer with \`names\`, or replace some entries with a scope wildcard. Nothing was changed.`);
|
|
152
|
+
}
|
|
153
|
+
if (list.length > 0)
|
|
154
|
+
next[ecosystem] = list;
|
|
155
|
+
}
|
|
156
|
+
// Every added name is a registry name the proxy normalized: still parsed, so the stored allowlist stays valid.
|
|
157
|
+
parseAllowlist(next, REGISTRY_ADAPTERS);
|
|
158
|
+
planned.push({ agentId, added, packageAllowlist: next });
|
|
159
|
+
}
|
|
160
|
+
for (const result of planned) {
|
|
161
|
+
if (Object.keys(result.added).length === 0)
|
|
162
|
+
continue;
|
|
163
|
+
await tx.codingAgentProfile.update({
|
|
164
|
+
where: { agentId: result.agentId },
|
|
165
|
+
data: { packageAllowlist: result.packageAllowlist },
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return planned;
|
|
169
|
+
}, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable });
|
|
170
|
+
for (const result of results) {
|
|
171
|
+
const count = Object.values(result.added).reduce((sum, list) => sum + list.length, 0);
|
|
172
|
+
if (count > 0) {
|
|
173
|
+
packagesLog.info({
|
|
174
|
+
event: "coding.package_audit.promoted",
|
|
175
|
+
agentId: result.agentId,
|
|
176
|
+
runId,
|
|
177
|
+
added: count,
|
|
178
|
+
by: ctx.principal.id,
|
|
179
|
+
}, "audited packages added to the allowlist");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const unknown = [...skippedUnknown.values()];
|
|
183
|
+
return textResult({
|
|
184
|
+
runId,
|
|
185
|
+
agents: results,
|
|
186
|
+
...(unknown.length > 0
|
|
187
|
+
? {
|
|
188
|
+
unknown,
|
|
189
|
+
unknownNote: `${UNKNOWN_RELATION_LABEL.toLowerCase()}. List one in \`names\` to add it.`,
|
|
190
|
+
}
|
|
191
|
+
: {}),
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-power mode over MCP: power_status reads the coding proxy's and native
|
|
3
|
+
* gateway's state, power_sleep scales them to zero now instead of waiting out
|
|
4
|
+
* the idle window. Both need power:manage, a privileged scope honoured only
|
|
5
|
+
* for the admin role (resource-server.ts). power_sleep never stops a run: a
|
|
6
|
+
* target with active or queued runs (or, for the gateway, an active gateway
|
|
7
|
+
* session) is refused and its run ids returned. Each power_sleep is audited
|
|
8
|
+
* (event power.sleep, outcome ok or error, naming the principal), including a
|
|
9
|
+
* failed or refused call, since a failure can follow a target already slept.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { logger } from "../../core/logger.js";
|
|
13
|
+
import { DISABLED_POWER, LOW_POWER_DISABLED } from "../../core/power.js";
|
|
14
|
+
import { McpError } from "../errors.js";
|
|
15
|
+
import { textResult } from "./text-result.js";
|
|
16
|
+
const powerToolLog = logger.child({ module: "mcp-power" });
|
|
17
|
+
const TARGETS = ["proxy", "gateway"];
|
|
18
|
+
const SleepSchema = z.object({ target: z.enum(TARGETS).optional() }).strict();
|
|
19
|
+
const StatusSchema = z.object({}).strict();
|
|
20
|
+
function parse(schema, label, value) {
|
|
21
|
+
const result = schema.safeParse(value ?? {});
|
|
22
|
+
if (!result.success) {
|
|
23
|
+
const details = result.error.issues
|
|
24
|
+
.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`)
|
|
25
|
+
.join("; ");
|
|
26
|
+
throw new McpError(400, `Invalid ${label}: ${details}`);
|
|
27
|
+
}
|
|
28
|
+
return result.data;
|
|
29
|
+
}
|
|
30
|
+
export function registerPowerTools(mcp) {
|
|
31
|
+
mcp.registerTool({
|
|
32
|
+
name: "power_status",
|
|
33
|
+
scope: "power:manage",
|
|
34
|
+
description: "Admins (power:manage): low-power mode state. For the coding proxy and the native gateway: replicas, whether a ready endpoint exists, when it last woke (wokeAt), and blockers (run ids keeping it busy). Returns { enabled: false } when low-power mode is off.",
|
|
35
|
+
inputSchema: { type: "object", additionalProperties: false, properties: {} },
|
|
36
|
+
handler: async (rawArgs, ctx) => {
|
|
37
|
+
parse(StatusSchema, "power_status arguments", rawArgs);
|
|
38
|
+
return textResult(await (ctx.providers.power ?? DISABLED_POWER).status());
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
mcp.registerTool({
|
|
42
|
+
name: "power_sleep",
|
|
43
|
+
scope: "power:manage",
|
|
44
|
+
description: "Admins (power:manage): scale the coding proxy and/or native gateway to zero now, skipping low-power mode's idle window. It never stops a run: a target is refused while it has active or queued runs (for the gateway, also an active gateway session), and those run ids are returned under blocked. Recently finished runs do not block it. The next run wakes the target again. Fails (409 low_power_disabled) when low-power mode is off.",
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
properties: {
|
|
49
|
+
target: {
|
|
50
|
+
type: "string",
|
|
51
|
+
enum: [...TARGETS],
|
|
52
|
+
description: "Sleep only this target. Omit to sleep both.",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
handler: async (rawArgs, ctx) => {
|
|
57
|
+
const { target } = parse(SleepSchema, "power_sleep arguments", rawArgs);
|
|
58
|
+
const targets = target ? [target] : [...TARGETS];
|
|
59
|
+
const power = ctx.providers.power ?? DISABLED_POWER;
|
|
60
|
+
const audit = { event: "power.sleep", principal: ctx.principal.id, targets };
|
|
61
|
+
let result;
|
|
62
|
+
try {
|
|
63
|
+
result = await power.sleepNow(targets);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
// Audited before rethrowing: sleepNow may already have slept an earlier target.
|
|
67
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
68
|
+
powerToolLog.warn({ ...audit, outcome: "error", error }, "power_sleep");
|
|
69
|
+
if (err instanceof Error && err.message.startsWith(`${LOW_POWER_DISABLED}:`))
|
|
70
|
+
throw new McpError(409, err.message);
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
powerToolLog.info({ ...audit, outcome: "ok", slept: result.slept, blocked: result.blocked }, "power_sleep");
|
|
74
|
+
return textResult(result);
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|