@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/core/secrets.js
CHANGED
|
@@ -1,31 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets: encrypted-at-rest values, attached to an agent by name, readable
|
|
3
|
+
* only inside the sandbox at point-of-use (never by any read/list tool).
|
|
4
|
+
* `Secret.name` is unique per owner (`@@unique([ownerId, name])`), so two
|
|
5
|
+
* owners can each have their own "API_KEY" without collision — attach/get
|
|
6
|
+
* always resolve a name within one owner's (or, at get-time, one agent's)
|
|
7
|
+
* scope, never globally.
|
|
8
|
+
*/
|
|
9
|
+
import { Prisma } from "#prisma";
|
|
1
10
|
import { boundedString } from "../sandbox/bounded-json.js";
|
|
11
|
+
import { assertBrokerableValue, brokerConfigHash, parseSecretBrokerConfig, SECRET_BROKER_CHANGED, } from "./secret-broker-config.js";
|
|
12
|
+
function brokerOf(secret) {
|
|
13
|
+
return secret.broker === null || secret.broker === undefined ? null : parseSecretBrokerConfig(secret.broker);
|
|
14
|
+
}
|
|
15
|
+
const BROKERED_GET_MESSAGE = 'secret_brokered: this secret is brokered; send it with fetch(url, { secrets: ["NAME"] }) instead of reading it';
|
|
2
16
|
/**
|
|
3
17
|
* Encrypts and stores a secret value. Upserts on (ownerId, name) — calling
|
|
4
18
|
* this again for a name the owner already has rotates its value in place
|
|
5
19
|
* (same id) rather than failing on the unique constraint. The plaintext is
|
|
6
|
-
* never logged or returned.
|
|
20
|
+
* never logged or returned. With `options.broker`, the config is validated
|
|
21
|
+
* against the value, saved, and audited in the same transaction.
|
|
7
22
|
*/
|
|
8
|
-
export async function createSecret(name, value, ownerId, cipher, db) {
|
|
23
|
+
export async function createSecret(name, value, ownerId, cipher, db, options = {}) {
|
|
9
24
|
boundedString(name, 1024);
|
|
10
25
|
boundedString(value, 65_536);
|
|
26
|
+
const broker = options.broker ? parseSecretBrokerConfig(options.broker) : undefined;
|
|
27
|
+
if (broker)
|
|
28
|
+
assertBrokerableValue(broker, value);
|
|
11
29
|
const ciphertext = await cipher.encrypt(value);
|
|
12
30
|
const keyId = cipher.keyId();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
31
|
+
if (!broker) {
|
|
32
|
+
// A rotation that omits `broker` keeps the stored config, so the new value must still be brokerable.
|
|
33
|
+
const existing = await db.secret.findUnique({
|
|
34
|
+
where: { ownerId_name: { ownerId, name } },
|
|
35
|
+
select: { broker: true },
|
|
36
|
+
});
|
|
37
|
+
if (existing?.broker)
|
|
38
|
+
assertBrokerableValue(brokerOf(existing), value);
|
|
39
|
+
return db.secret.upsert({
|
|
40
|
+
where: { ownerId_name: { ownerId, name } },
|
|
41
|
+
create: { name, ciphertext, keyId, ownerId },
|
|
42
|
+
update: { ciphertext, keyId },
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return db.$transaction(async (tx) => {
|
|
46
|
+
const existing = await tx.secret.findUnique({ where: { ownerId_name: { ownerId, name } } });
|
|
47
|
+
const before = existing ? brokerOf(existing) : null;
|
|
48
|
+
const secret = await tx.secret.upsert({
|
|
49
|
+
where: { ownerId_name: { ownerId, name } },
|
|
50
|
+
create: { name, ciphertext, keyId, ownerId, broker },
|
|
51
|
+
update: { ciphertext, keyId, broker },
|
|
52
|
+
});
|
|
53
|
+
if (JSON.stringify(before) !== JSON.stringify(broker)) {
|
|
54
|
+
await tx.secretBrokerChange.create({
|
|
55
|
+
data: {
|
|
56
|
+
secretId: secret.id,
|
|
57
|
+
ownerId,
|
|
58
|
+
secretName: name,
|
|
59
|
+
actorId: ownerId,
|
|
60
|
+
before: before ?? Prisma.JsonNull,
|
|
61
|
+
after: broker,
|
|
62
|
+
via: options.via ?? "mcp",
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return secret;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sets, changes, or (broker: null) removes a secret's broker config, with one audit
|
|
71
|
+
* row per actual change. `expectedBrokerHash` (brokerConfigHash of the config the
|
|
72
|
+
* caller confirmed) makes the change conditional, checked inside the transaction:
|
|
73
|
+
* if the secret is no longer brokered with exactly that config, it throws
|
|
74
|
+
* secret_broker_changed and changes nothing.
|
|
75
|
+
*/
|
|
76
|
+
export async function setSecretBroker(db, cipher, input) {
|
|
77
|
+
const after = input.broker === null ? null : parseSecretBrokerConfig(input.broker);
|
|
78
|
+
return db.$transaction(async (tx) => {
|
|
79
|
+
const secret = await tx.secret.findUnique({
|
|
80
|
+
where: { ownerId_name: { ownerId: input.ownerId, name: input.name } },
|
|
81
|
+
});
|
|
82
|
+
if (!secret)
|
|
83
|
+
throw new Error(`secret_not_found: no secret named "${input.name}"`);
|
|
84
|
+
const before = brokerOf(secret);
|
|
85
|
+
if (input.expectedBrokerHash !== undefined && (!before || brokerConfigHash(before) !== input.expectedBrokerHash)) {
|
|
86
|
+
throw new Error(SECRET_BROKER_CHANGED);
|
|
87
|
+
}
|
|
88
|
+
if (JSON.stringify(before) === JSON.stringify(after))
|
|
89
|
+
return { before, after };
|
|
90
|
+
if (after)
|
|
91
|
+
assertBrokerableValue(after, await cipher.decrypt(secret.ciphertext));
|
|
92
|
+
await tx.secret.update({ where: { id: secret.id }, data: { broker: after ?? Prisma.DbNull } });
|
|
93
|
+
await tx.secretBrokerChange.create({
|
|
94
|
+
data: {
|
|
95
|
+
secretId: secret.id,
|
|
96
|
+
ownerId: input.ownerId,
|
|
97
|
+
secretName: secret.name,
|
|
98
|
+
actorId: input.actorId,
|
|
99
|
+
before: before ?? Prisma.JsonNull,
|
|
100
|
+
after: after ?? Prisma.JsonNull,
|
|
101
|
+
via: input.via,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
return { before, after };
|
|
17
105
|
});
|
|
18
106
|
}
|
|
19
107
|
/** Names/metadata only — never a value or ciphertext. */
|
|
20
108
|
export async function listSecrets(ownerId, db) {
|
|
21
109
|
const secrets = await db.secret.findMany({ where: { ownerId } });
|
|
22
|
-
return secrets.map((
|
|
23
|
-
id,
|
|
24
|
-
name,
|
|
25
|
-
keyId,
|
|
26
|
-
ownerId:
|
|
27
|
-
createdAt,
|
|
28
|
-
updatedAt,
|
|
110
|
+
return secrets.map((s) => ({
|
|
111
|
+
id: s.id,
|
|
112
|
+
name: s.name,
|
|
113
|
+
keyId: s.keyId,
|
|
114
|
+
ownerId: s.ownerId,
|
|
115
|
+
createdAt: s.createdAt,
|
|
116
|
+
updatedAt: s.updatedAt,
|
|
117
|
+
broker: brokerOf(s),
|
|
29
118
|
}));
|
|
30
119
|
}
|
|
31
120
|
async function findOwnedSecretByName(db, ownerId, name) {
|
|
@@ -66,37 +155,53 @@ export async function deleteSecret(secretId, db) {
|
|
|
66
155
|
* binding written before that rule, left behind by make_owner, or on an
|
|
67
156
|
* owner-less agent behaves exactly like an unattached name, so one owner's
|
|
68
157
|
* secret never reaches another owner's agent (A2/S2-2, R2-1).
|
|
158
|
+
*
|
|
159
|
+
* A brokered secret's `get` throws `secret_brokered`; only the privileged host's `resolve` sees its value.
|
|
69
160
|
*/
|
|
70
161
|
export function buildSecretsAccessor(agentId, cipher, db) {
|
|
162
|
+
async function resolve(name) {
|
|
163
|
+
boundedString(name, 1024);
|
|
164
|
+
if (db.$queryRaw) {
|
|
165
|
+
// NULL-safe: "=" is never true when either owner is NULL.
|
|
166
|
+
const rows = await db.$queryRaw `
|
|
167
|
+
SELECT CASE WHEN octet_length(s."ciphertext") <= 262144 THEN s."ciphertext" ELSE NULL END AS "ciphertext",
|
|
168
|
+
s."broker" AS "broker"
|
|
169
|
+
FROM "Secret" s
|
|
170
|
+
JOIN "AgentSecret" a ON a."secretId" = s."id"
|
|
171
|
+
JOIN "Agent" g ON g."id" = a."agentId"
|
|
172
|
+
WHERE a."agentId" = ${agentId} AND a."boundName" = ${name} AND s."ownerId" = g."ownerId" LIMIT 1`;
|
|
173
|
+
if (!rows.length)
|
|
174
|
+
return undefined;
|
|
175
|
+
if (rows[0].ciphertext === null)
|
|
176
|
+
throw new Error("secret_value_limit");
|
|
177
|
+
return {
|
|
178
|
+
value: await cipher.decrypt(rows[0].ciphertext),
|
|
179
|
+
broker: brokerOf({ broker: rows[0].broker }),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// Lightweight provider doubles use the same post-read bound; production Prisma filters in SQL.
|
|
183
|
+
const attachment = await db.agentSecret.findFirst({
|
|
184
|
+
where: { agentId, boundName: name },
|
|
185
|
+
include: { secret: true, agent: { select: { ownerId: true } } },
|
|
186
|
+
});
|
|
187
|
+
if (!attachment)
|
|
188
|
+
return undefined;
|
|
189
|
+
const owner = attachment.agent.ownerId;
|
|
190
|
+
if (owner === null || attachment.secret.ownerId !== owner)
|
|
191
|
+
return undefined;
|
|
192
|
+
boundedString(attachment.secret.ciphertext, 256 * 1024);
|
|
193
|
+
return {
|
|
194
|
+
value: await cipher.decrypt(attachment.secret.ciphertext),
|
|
195
|
+
broker: brokerOf({ broker: attachment.secret.broker ?? null }),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
71
198
|
return {
|
|
199
|
+
resolve,
|
|
72
200
|
async get(name) {
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
SELECT CASE WHEN octet_length(s."ciphertext") <= 262144 THEN s."ciphertext" ELSE NULL END AS "ciphertext"
|
|
78
|
-
FROM "Secret" s
|
|
79
|
-
JOIN "AgentSecret" a ON a."secretId" = s."id"
|
|
80
|
-
JOIN "Agent" g ON g."id" = a."agentId"
|
|
81
|
-
WHERE a."agentId" = ${agentId} AND a."boundName" = ${name} AND s."ownerId" = g."ownerId" LIMIT 1`;
|
|
82
|
-
if (!rows.length)
|
|
83
|
-
return undefined;
|
|
84
|
-
if (rows[0].ciphertext === null)
|
|
85
|
-
throw new Error("secret_value_limit");
|
|
86
|
-
return cipher.decrypt(rows[0].ciphertext);
|
|
87
|
-
}
|
|
88
|
-
// Lightweight provider doubles use the same post-read bound; production Prisma filters in SQL.
|
|
89
|
-
const attachment = await db.agentSecret.findFirst({
|
|
90
|
-
where: { agentId, boundName: name },
|
|
91
|
-
include: { secret: true, agent: { select: { ownerId: true } } },
|
|
92
|
-
});
|
|
93
|
-
if (!attachment)
|
|
94
|
-
return undefined;
|
|
95
|
-
const owner = attachment.agent.ownerId;
|
|
96
|
-
if (owner === null || attachment.secret.ownerId !== owner)
|
|
97
|
-
return undefined;
|
|
98
|
-
boundedString(attachment.secret.ciphertext, 256 * 1024);
|
|
99
|
-
return cipher.decrypt(attachment.secret.ciphertext);
|
|
201
|
+
const entry = await resolve(name);
|
|
202
|
+
if (entry?.broker)
|
|
203
|
+
throw new Error(BROKERED_GET_MESSAGE);
|
|
204
|
+
return entry?.value;
|
|
100
205
|
},
|
|
101
206
|
};
|
|
102
207
|
}
|
|
@@ -115,5 +220,8 @@ export function scopeSecretsAccessor(accessor, allowedNames) {
|
|
|
115
220
|
return undefined;
|
|
116
221
|
return accessor.get(name);
|
|
117
222
|
},
|
|
223
|
+
...(accessor.resolve && {
|
|
224
|
+
resolve: async (name) => (allowed.has(name) ? accessor.resolve(name) : undefined),
|
|
225
|
+
}),
|
|
118
226
|
};
|
|
119
227
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stopping a run on request (the stop_run MCP tool). Every executor already owns the stop of the
|
|
3
|
+
* runs it executes (`Executor.stop`), and each makes the terminal write itself, conditional on the
|
|
4
|
+
* run still being pending or running, so the first terminal write wins and a finished run is never
|
|
5
|
+
* rewritten:
|
|
6
|
+
*
|
|
7
|
+
* - a native run in the control plane is recorded `cancelled` and stops at its next step boundary
|
|
8
|
+
* (InProcessExecutor/DbosExecutor; a run that has not started never does);
|
|
9
|
+
* - a native run in the sandbox is recorded `cancelled`, its gateway session ends so the worker's
|
|
10
|
+
* next call is refused, and after a short grace its worker is killed and removed
|
|
11
|
+
* (NativeSandboxExecutor);
|
|
12
|
+
* - a coding run, queued for a slot or running, is recorded `cancelled` first (the fence that keeps
|
|
13
|
+
* a finishing run from pushing or opening a pull request), then its proxy session is cancelled and
|
|
14
|
+
* its job stopped and removed (ContainerExecutor).
|
|
15
|
+
*
|
|
16
|
+
* This module adds what a caller asks for on top: the run's in-flight delegated child runs are
|
|
17
|
+
* stopped too (depth-first, so nothing keeps spending for a parent that stopped), who stopped it
|
|
18
|
+
* and why is kept on the row (Run.stopRequestReason) and logged, and a run already finished is
|
|
19
|
+
* returned unchanged.
|
|
20
|
+
*/
|
|
21
|
+
import type { PrismaClient, RunStatus } from "#prisma";
|
|
22
|
+
import type { Executor } from "../providers/executor/types.js";
|
|
23
|
+
export type StopRunDb = Pick<PrismaClient, "run">;
|
|
24
|
+
export interface StopRunOptions {
|
|
25
|
+
db: StopRunDb;
|
|
26
|
+
executor: Pick<Executor, "stop">;
|
|
27
|
+
runId: string;
|
|
28
|
+
/** Who asked (a principal id), recorded with the reason. */
|
|
29
|
+
stoppedBy: string;
|
|
30
|
+
/** The caller's own words, if any. */
|
|
31
|
+
reason?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface StopRunResult {
|
|
34
|
+
runId: string;
|
|
35
|
+
/** The run's status before this call. */
|
|
36
|
+
previousStatus: RunStatus;
|
|
37
|
+
/** The run's status after it: `cancelled` once stopped, or whatever it had already ended as. */
|
|
38
|
+
status: RunStatus;
|
|
39
|
+
/** False when the run had already finished: nothing was changed. */
|
|
40
|
+
stopRequested: boolean;
|
|
41
|
+
/** In-flight delegated child runs this call stopped as well. */
|
|
42
|
+
stoppedChildRunIds: string[];
|
|
43
|
+
}
|
|
44
|
+
/** The text recorded on a stopped run: who stopped it and why. */
|
|
45
|
+
export declare function stopRunReason(stoppedBy: string, reason?: string): string;
|
|
46
|
+
export declare function stopRun(options: StopRunOptions): Promise<StopRunResult>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
const stopLog = logger.child({ module: "stop-run" });
|
|
3
|
+
const DRIVABLE = ["pending", "running"];
|
|
4
|
+
/** Delegation trees are shallow; this only bounds a malformed one. */
|
|
5
|
+
const MAX_CHILD_DEPTH = 16;
|
|
6
|
+
/** The text recorded on a stopped run: who stopped it and why. */
|
|
7
|
+
export function stopRunReason(stoppedBy, reason) {
|
|
8
|
+
const why = reason?.trim();
|
|
9
|
+
return `Stopped by ${stoppedBy} with stop_run${why ? `: ${why}` : "."}`;
|
|
10
|
+
}
|
|
11
|
+
export async function stopRun(options) {
|
|
12
|
+
const { db, runId } = options;
|
|
13
|
+
const row = await db.run.findUnique({ where: { id: runId }, select: { status: true } });
|
|
14
|
+
if (!row)
|
|
15
|
+
throw new Error(`Unknown run "${runId}".`);
|
|
16
|
+
const previousStatus = row.status;
|
|
17
|
+
if (!DRIVABLE.includes(previousStatus)) {
|
|
18
|
+
return { runId, previousStatus, status: previousStatus, stopRequested: false, stoppedChildRunIds: [] };
|
|
19
|
+
}
|
|
20
|
+
const reason = stopRunReason(options.stoppedBy, options.reason);
|
|
21
|
+
stopLog.info({ runId, stoppedBy: options.stoppedBy, previousStatus, reason }, "stopping run");
|
|
22
|
+
const stoppedChildRunIds = [];
|
|
23
|
+
await stopOne(options, runId, reason, stoppedChildRunIds, 0, new Set());
|
|
24
|
+
const after = await db.run.findUniqueOrThrow({ where: { id: runId }, select: { status: true } });
|
|
25
|
+
return { runId, previousStatus, status: after.status, stopRequested: true, stoppedChildRunIds };
|
|
26
|
+
}
|
|
27
|
+
async function stopOne(options, runId, reason, stoppedChildRunIds, depth, visited) {
|
|
28
|
+
const { db, executor } = options;
|
|
29
|
+
visited.add(runId);
|
|
30
|
+
try {
|
|
31
|
+
await executor.stop(runId, reason);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
// Still stop the children and record the request: a failed stop is retried by calling again.
|
|
35
|
+
stopLog.warn({ err, runId }, "the executor failed to stop the run");
|
|
36
|
+
}
|
|
37
|
+
// A run that never started has nothing to interrupt: end it here if no executor did.
|
|
38
|
+
await db.run.updateMany({
|
|
39
|
+
where: { id: runId, status: "pending" },
|
|
40
|
+
data: { status: "cancelled", error: reason, finishedAt: new Date() },
|
|
41
|
+
});
|
|
42
|
+
// Kept for get_run; written only on a run this stop (or another) cancelled, never on one that
|
|
43
|
+
// finished some other way meanwhile. stopRequestedAt stays null: it is the native sandbox
|
|
44
|
+
// gateway's deferred-stop marker, which the scheduler leader drains.
|
|
45
|
+
await db.run.updateMany({
|
|
46
|
+
where: { id: runId, status: "cancelled", stopRequestReason: null },
|
|
47
|
+
data: { stopRequestReason: reason },
|
|
48
|
+
});
|
|
49
|
+
if (depth >= MAX_CHILD_DEPTH)
|
|
50
|
+
return;
|
|
51
|
+
const children = await db.run.findMany({
|
|
52
|
+
where: { parentRunId: runId, status: { in: [...DRIVABLE] } },
|
|
53
|
+
select: { id: true },
|
|
54
|
+
});
|
|
55
|
+
for (const child of children) {
|
|
56
|
+
if (visited.has(child.id))
|
|
57
|
+
continue;
|
|
58
|
+
stoppedChildRunIds.push(child.id);
|
|
59
|
+
await stopOne(options, child.id, `Parent run ${runId} was stopped. ${reason}`, stoppedChildRunIds, depth + 1, visited);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns an emitted workflow event into outbox rows: resolves the event's work
|
|
3
|
+
* item (given, else the run's attribution, else the PR's issue link), finds
|
|
4
|
+
* the channel links that match (project links by the item's project, agent
|
|
5
|
+
* links by the event's agent), filters each link's event kinds, de-duplicates
|
|
6
|
+
* by channel, and writes one WorkflowEvent plus one NotificationDelivery per
|
|
7
|
+
* channel in a transaction. A dedupeKey that already exists is a no-op, so
|
|
8
|
+
* redeliveries and repeated finalizers record a fact once. Writes nothing
|
|
9
|
+
* when no link matches.
|
|
10
|
+
*/
|
|
11
|
+
import { type PrismaClient } from "#prisma";
|
|
12
|
+
import { type WorkflowEventSink } from "./workflow-events.js";
|
|
13
|
+
export type RecorderDb = Pick<PrismaClient, "notificationChannel" | "workflowEvent" | "notificationDelivery" | "runAttribution" | "issuePullRequest" | "$transaction">;
|
|
14
|
+
export declare function createWorkflowEventRecorder(db: RecorderDb, enabledProviders: readonly string[]): WorkflowEventSink;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns an emitted workflow event into outbox rows: resolves the event's work
|
|
3
|
+
* item (given, else the run's attribution, else the PR's issue link), finds
|
|
4
|
+
* the channel links that match (project links by the item's project, agent
|
|
5
|
+
* links by the event's agent), filters each link's event kinds, de-duplicates
|
|
6
|
+
* by channel, and writes one WorkflowEvent plus one NotificationDelivery per
|
|
7
|
+
* channel in a transaction. A dedupeKey that already exists is a no-op, so
|
|
8
|
+
* redeliveries and repeated finalizers record a fact once. Writes nothing
|
|
9
|
+
* when no link matches.
|
|
10
|
+
*/
|
|
11
|
+
import { Prisma } from "#prisma";
|
|
12
|
+
import { projectOf } from "../providers/issue-tracker/types.js";
|
|
13
|
+
import { threadKeys } from "./workflow-events.js";
|
|
14
|
+
async function resolveWorkItem(db, input) {
|
|
15
|
+
if (input.workItem)
|
|
16
|
+
return input.workItem;
|
|
17
|
+
if (input.runId) {
|
|
18
|
+
const attribution = await db.runAttribution.findUnique({
|
|
19
|
+
where: { runId: input.runId },
|
|
20
|
+
select: { workItem: { select: { provider: true, key: true } } },
|
|
21
|
+
});
|
|
22
|
+
if (attribution)
|
|
23
|
+
return attribution.workItem;
|
|
24
|
+
}
|
|
25
|
+
if (input.pullRequest) {
|
|
26
|
+
const pr = await db.issuePullRequest.findFirst({
|
|
27
|
+
where: {
|
|
28
|
+
codeProvider: input.pullRequest.codeProvider,
|
|
29
|
+
repository: input.pullRequest.repository,
|
|
30
|
+
number: input.pullRequest.number,
|
|
31
|
+
},
|
|
32
|
+
orderBy: { createdAt: "asc" },
|
|
33
|
+
select: { issueProvider: true, issueKey: true },
|
|
34
|
+
});
|
|
35
|
+
if (pr)
|
|
36
|
+
return { provider: pr.issueProvider, key: pr.issueKey };
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
export function createWorkflowEventRecorder(db, enabledProviders) {
|
|
41
|
+
return async (input) => {
|
|
42
|
+
if (enabledProviders.length === 0)
|
|
43
|
+
return;
|
|
44
|
+
const existing = await db.workflowEvent.findUnique({
|
|
45
|
+
where: { dedupeKey: input.dedupeKey },
|
|
46
|
+
select: { id: true },
|
|
47
|
+
});
|
|
48
|
+
if (existing)
|
|
49
|
+
return;
|
|
50
|
+
const item = await resolveWorkItem(db, input);
|
|
51
|
+
const or = [];
|
|
52
|
+
if (item)
|
|
53
|
+
or.push({ issueProvider: item.provider, projectKey: projectOf(item.key) });
|
|
54
|
+
if (input.agentId)
|
|
55
|
+
or.push({ agentId: input.agentId });
|
|
56
|
+
if (or.length === 0)
|
|
57
|
+
return;
|
|
58
|
+
const links = await db.notificationChannel.findMany({
|
|
59
|
+
where: { provider: { in: [...enabledProviders] }, OR: or },
|
|
60
|
+
select: { provider: true, channelId: true, events: true, includeCost: true },
|
|
61
|
+
});
|
|
62
|
+
const kind = input.payload.kind;
|
|
63
|
+
const byChannel = new Map();
|
|
64
|
+
for (const link of links) {
|
|
65
|
+
if (link.events.length > 0 && !link.events.includes(kind))
|
|
66
|
+
continue;
|
|
67
|
+
const key = `${link.provider}\u0000${link.channelId}`;
|
|
68
|
+
const prev = byChannel.get(key);
|
|
69
|
+
byChannel.set(key, {
|
|
70
|
+
provider: link.provider,
|
|
71
|
+
channelId: link.channelId,
|
|
72
|
+
includeCost: (prev?.includeCost ?? false) || link.includeCost,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (byChannel.size === 0)
|
|
76
|
+
return;
|
|
77
|
+
const threadKey = item
|
|
78
|
+
? threadKeys.issue(item.provider, item.key)
|
|
79
|
+
: input.pullRequest
|
|
80
|
+
? threadKeys.pr(input.pullRequest.codeProvider, input.pullRequest.repository, input.pullRequest.number)
|
|
81
|
+
: input.runId
|
|
82
|
+
? threadKeys.run(input.runId)
|
|
83
|
+
: null;
|
|
84
|
+
if (!threadKey)
|
|
85
|
+
return;
|
|
86
|
+
try {
|
|
87
|
+
await db.$transaction(async (tx) => {
|
|
88
|
+
const event = await tx.workflowEvent.create({
|
|
89
|
+
data: {
|
|
90
|
+
kind,
|
|
91
|
+
dedupeKey: input.dedupeKey,
|
|
92
|
+
runId: input.runId ?? null,
|
|
93
|
+
agentId: input.agentId ?? null,
|
|
94
|
+
workItemProvider: item?.provider ?? null,
|
|
95
|
+
workItemKey: item?.key ?? null,
|
|
96
|
+
codeProvider: input.pullRequest?.codeProvider ?? null,
|
|
97
|
+
repository: input.pullRequest?.repository ?? null,
|
|
98
|
+
prNumber: input.pullRequest?.number ?? null,
|
|
99
|
+
payload: input.payload,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
await tx.notificationDelivery.createMany({
|
|
103
|
+
data: [...byChannel.values()].map((c) => ({
|
|
104
|
+
eventId: event.id,
|
|
105
|
+
provider: c.provider,
|
|
106
|
+
channelId: c.channelId,
|
|
107
|
+
threadKey,
|
|
108
|
+
includeCost: c.includeCost,
|
|
109
|
+
})),
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
// A concurrent recording of the same fact won the dedupeKey: nothing to do.
|
|
115
|
+
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002")
|
|
116
|
+
return;
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { PackageAuditDigest, PackageAuditMode } from "../coding/registry/audit-mode.js";
|
|
2
|
+
import type { RegistryRefusalSummary } from "../coding/registry/report.js";
|
|
3
|
+
export declare const WORKFLOW_EVENT_KINDS: readonly ["issue_picked_up", "run_failed", "run_blocked", "pr_opened", "review_posted", "review_fix", "pr_closed", "packages_audited"];
|
|
4
|
+
export type WorkflowEventKind = (typeof WORKFLOW_EVENT_KINDS)[number];
|
|
5
|
+
/** Template inputs per kind. Every string here may be shown in Slack (escaped). */
|
|
6
|
+
export type WorkflowPayload = {
|
|
7
|
+
kind: "run_blocked";
|
|
8
|
+
agentName: string;
|
|
9
|
+
packageRefusals: RegistryRefusalSummary[];
|
|
10
|
+
} | {
|
|
11
|
+
kind: "issue_picked_up";
|
|
12
|
+
agentName: string;
|
|
13
|
+
trigger: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "run_failed";
|
|
16
|
+
agentName: string;
|
|
17
|
+
status: "failed" | "budget_exhausted" | "cancelled" | "lost" | "refused";
|
|
18
|
+
reason: string | null;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "pr_opened";
|
|
21
|
+
prLabel: string;
|
|
22
|
+
prUrl: string;
|
|
23
|
+
movedTo: string | null;
|
|
24
|
+
} | {
|
|
25
|
+
kind: "review_posted";
|
|
26
|
+
agentName: string;
|
|
27
|
+
verdict: "APPROVE" | "CHANGES_REQUESTED" | "COMMENT";
|
|
28
|
+
prLabel: string;
|
|
29
|
+
prUrl: string | null;
|
|
30
|
+
ciPending: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
kind: "review_fix";
|
|
33
|
+
prLabel: string;
|
|
34
|
+
round: number;
|
|
35
|
+
maxRounds: number;
|
|
36
|
+
state: "started" | "capped";
|
|
37
|
+
} | {
|
|
38
|
+
kind: "pr_closed";
|
|
39
|
+
prLabel: string;
|
|
40
|
+
prUrl: string;
|
|
41
|
+
merged: boolean;
|
|
42
|
+
movedTo: string | null;
|
|
43
|
+
} | ({
|
|
44
|
+
kind: "packages_audited";
|
|
45
|
+
agentName: string;
|
|
46
|
+
mode: PackageAuditMode;
|
|
47
|
+
} & PackageAuditDigest);
|
|
48
|
+
/** What a thread's parent message shows about its subject. */
|
|
49
|
+
export interface ThreadSubject {
|
|
50
|
+
/** "PAY-241" or "org/repo#212" or "run abc123". */
|
|
51
|
+
label: string;
|
|
52
|
+
title: string | null;
|
|
53
|
+
url: string | null;
|
|
54
|
+
}
|
|
55
|
+
export declare const dedupeKeys: {
|
|
56
|
+
issuePickedUp: (runId: string) => string;
|
|
57
|
+
runBlocked: (runId: string) => string;
|
|
58
|
+
runFailed: (runId: string) => string;
|
|
59
|
+
prOpened: (codeProvider: string, repository: string, n: number) => string;
|
|
60
|
+
reviewPosted: (runId: string) => string;
|
|
61
|
+
reviewFix: (repository: string, n: number, round: number, state: "started" | "capped") => string;
|
|
62
|
+
prClosed: (codeProvider: string, repository: string, n: number) => string;
|
|
63
|
+
packagesAudited: (runId: string) => string;
|
|
64
|
+
};
|
|
65
|
+
export declare const threadKeys: {
|
|
66
|
+
issue: (provider: string, key: string) => string;
|
|
67
|
+
pr: (codeProvider: string, repository: string, n: number) => string;
|
|
68
|
+
run: (runId: string) => string;
|
|
69
|
+
};
|
|
70
|
+
/** First line of an error, at most 200 characters; null for empty. */
|
|
71
|
+
export declare function shortReason(error: string | null | undefined): string | null;
|
|
72
|
+
export interface WorkflowEventInput {
|
|
73
|
+
dedupeKey: string;
|
|
74
|
+
payload: WorkflowPayload;
|
|
75
|
+
/** The run the event is about (its attribution names the work item). */
|
|
76
|
+
runId?: string;
|
|
77
|
+
/** The agent the event is about (agent links match on it). */
|
|
78
|
+
agentId?: string;
|
|
79
|
+
/** Known work item; otherwise resolved from runId's RunAttribution, then the PR's IssuePullRequest. */
|
|
80
|
+
workItem?: {
|
|
81
|
+
provider: string;
|
|
82
|
+
key: string;
|
|
83
|
+
};
|
|
84
|
+
pullRequest?: {
|
|
85
|
+
codeProvider: string;
|
|
86
|
+
repository: string;
|
|
87
|
+
number: number;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export type WorkflowEventSink = (input: WorkflowEventInput) => Promise<void>;
|
|
91
|
+
/** Installed once per process by startNotifications; null uninstalls (tests). */
|
|
92
|
+
export declare function setWorkflowEventSink(next: WorkflowEventSink | null): void;
|
|
93
|
+
/** Never throws; a no-op until a sink is installed. */
|
|
94
|
+
export declare function emitWorkflowEvent(input: WorkflowEventInput): Promise<void>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
export const WORKFLOW_EVENT_KINDS = [
|
|
3
|
+
"issue_picked_up",
|
|
4
|
+
"run_failed",
|
|
5
|
+
"run_blocked",
|
|
6
|
+
"pr_opened",
|
|
7
|
+
"review_posted",
|
|
8
|
+
"review_fix",
|
|
9
|
+
"pr_closed",
|
|
10
|
+
"packages_audited",
|
|
11
|
+
];
|
|
12
|
+
export const dedupeKeys = {
|
|
13
|
+
issuePickedUp: (runId) => `issue_picked_up:${runId}`,
|
|
14
|
+
runBlocked: (runId) => `run_blocked:${runId}`,
|
|
15
|
+
runFailed: (runId) => `run_failed:${runId}`,
|
|
16
|
+
prOpened: (codeProvider, repository, n) => `pr_opened:${codeProvider}:${repository}#${n}`,
|
|
17
|
+
reviewPosted: (runId) => `review_posted:${runId}`,
|
|
18
|
+
reviewFix: (repository, n, round, state) => `review_fix:${repository}#${n}:${round}:${state}`,
|
|
19
|
+
prClosed: (codeProvider, repository, n) => `pr_closed:${codeProvider}:${repository}#${n}`,
|
|
20
|
+
packagesAudited: (runId) => `packages_audited:${runId}`,
|
|
21
|
+
};
|
|
22
|
+
export const threadKeys = {
|
|
23
|
+
issue: (provider, key) => `issue:${provider}:${key}`,
|
|
24
|
+
pr: (codeProvider, repository, n) => `pr:${codeProvider}:${repository}#${n}`,
|
|
25
|
+
run: (runId) => `run:${runId}`,
|
|
26
|
+
};
|
|
27
|
+
/** First line of an error, at most 200 characters; null for empty. */
|
|
28
|
+
export function shortReason(error) {
|
|
29
|
+
const first = (error ?? "").split("\n", 1)[0].trim();
|
|
30
|
+
return first ? first.slice(0, 200) : null;
|
|
31
|
+
}
|
|
32
|
+
const log = logger.child({ module: "workflow-events" });
|
|
33
|
+
let sink = null;
|
|
34
|
+
/** Installed once per process by startNotifications; null uninstalls (tests). */
|
|
35
|
+
export function setWorkflowEventSink(next) {
|
|
36
|
+
sink = next;
|
|
37
|
+
}
|
|
38
|
+
/** Never throws; a no-op until a sink is installed. */
|
|
39
|
+
export async function emitWorkflowEvent(input) {
|
|
40
|
+
if (!sink)
|
|
41
|
+
return;
|
|
42
|
+
try {
|
|
43
|
+
await sink(input);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
log.warn({ err, dedupeKey: input.dedupeKey }, "workflow event record failed");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow notifications a run's finalizer emits: run_failed for a top-level
|
|
3
|
+
* run that did not succeed, run_blocked for package refusals without changes
|
|
4
|
+
* (children are summarized by their parent), packages_audited when its coding
|
|
5
|
+
* children installed anything under package audit mode, and
|
|
6
|
+
* review_posted when the run published a verdict on its own check. Called
|
|
7
|
+
* only by the finalizer that made the run terminal. Never throws.
|
|
8
|
+
*/
|
|
9
|
+
import type { PrismaClient } from "#prisma";
|
|
10
|
+
export type RunEventsDb = Pick<PrismaClient, "agent" | "runHostCheck" | "run" | "runBudgetEvent" | "registryFetch" | "registryAuditRecord">;
|
|
11
|
+
/** Emits top-level run outcomes and published review verdicts. Never throws. */
|
|
12
|
+
export declare function emitRunFinishedEvents(db: RunEventsDb, run: {
|
|
13
|
+
id: string;
|
|
14
|
+
agentId: string;
|
|
15
|
+
status: string;
|
|
16
|
+
error: string | null;
|
|
17
|
+
parentRunId: string | null;
|
|
18
|
+
}): Promise<void>;
|