@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
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The pull requests that came from the same request as a run: every pull
|
|
3
3
|
* request opened by a coding run in the same top-level run tree (a lead that
|
|
4
|
-
* fanned out to several repositories), plus any recorded for the same
|
|
5
|
-
* issue (IssuePullRequest). Control-plane rows only.
|
|
6
|
-
* Ordered by
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* fanned out to several repositories), plus any recorded for the same Jira or
|
|
5
|
+
* GitHub issue (IssuePullRequest). Control-plane rows only.
|
|
6
|
+
* Ordered by the delegating agent's declared merge order when any entry has
|
|
7
|
+
* one (CodingRun.mergeOrder; nulls last), then by when each pull request's
|
|
8
|
+
* coding run was dispatched: the lead's delegation order (for a lead with
|
|
9
|
+
* parallelDelegations, the order its concurrent delegations were admitted,
|
|
10
|
+
* ties broken by repository#number). A pull request's mergeOrder is the
|
|
11
|
+
* newest non-null value set by its opener run or any later continuation
|
|
12
|
+
* that acted on it, so a lead that re-delegates with a different order
|
|
13
|
+
* after the fact is reflected here. When mergeOrder is set on any entry,
|
|
14
|
+
* every truncation cap below this collector (MAX_RELATED_GROUP here,
|
|
15
|
+
* MAX_SIBLING_HINTS on openSiblingsOf, MAX_RELATED_PULL_REQUESTS on
|
|
16
|
+
* renderRelatedSection) drops entries with no order first, since they sort
|
|
17
|
+
* last.
|
|
9
18
|
* A PR opened while siblings were still running lists only the PRs opened
|
|
10
19
|
* before it; updateRelatedPullRequests rewrites every open PR of the set
|
|
11
20
|
* with the full list when the lead run ends. Continuations join
|
|
@@ -13,7 +22,7 @@
|
|
|
13
22
|
* pull requests brings the original request's tree, and the original request
|
|
14
23
|
* brings every later follow-up tree that continued one of its pull requests.
|
|
15
24
|
*/
|
|
16
|
-
import { type PrismaClient, type Run } from "#prisma";
|
|
25
|
+
import { type PrismaClient, type Run, type RunStatus } from "#prisma";
|
|
17
26
|
import { type IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
|
|
18
27
|
import type { ReviewHostRegistry } from "../providers/review-host/types.js";
|
|
19
28
|
/** Most pull requests a group holds; the description shows fewer (MAX_RELATED_PULL_REQUESTS). */
|
|
@@ -28,15 +37,50 @@ export interface RelatedPullRequest {
|
|
|
28
37
|
openedByRunId: string;
|
|
29
38
|
/** Only when stored (IssuePullRequest.state, kept current by pr_closed); otherwise unknown. */
|
|
30
39
|
state?: StoredPullRequestState;
|
|
40
|
+
/**
|
|
41
|
+
* Step in the delegating agent's merge order (CodingRun.mergeOrder, 1-99):
|
|
42
|
+
* the newest non-null value among the coding run that opened it and its
|
|
43
|
+
* continuations. Absent when none of them set one, or when the entry only
|
|
44
|
+
* came from IssuePullRequest (no CodingRun to read it from).
|
|
45
|
+
*/
|
|
46
|
+
mergeOrder?: number;
|
|
31
47
|
}
|
|
32
48
|
export interface RelatedPullRequestGroup {
|
|
33
49
|
pullRequests: RelatedPullRequest[];
|
|
34
|
-
/** The first well-formed issue seen on the group's coding runs. */
|
|
50
|
+
/** The first well-formed issue (a Jira or GitHub issue) seen on the group's coding runs. */
|
|
35
51
|
issue?: {
|
|
36
52
|
provider: string;
|
|
37
53
|
key: string;
|
|
38
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* The top-level run of every run tree the walk visited (the original
|
|
57
|
+
* request and each follow-up tree that continued one of its pull
|
|
58
|
+
* requests), with its status; absent when none was read. `codingRun` is
|
|
59
|
+
* true when the root is itself a coding run (a top-level follow-up such
|
|
60
|
+
* as a review fix round or an @mention picked up by a coding link), not a
|
|
61
|
+
* native lead agent's run.
|
|
62
|
+
*/
|
|
63
|
+
roots?: Array<{
|
|
64
|
+
id: string;
|
|
65
|
+
status: RunStatus;
|
|
66
|
+
codingRun: boolean;
|
|
67
|
+
}>;
|
|
39
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* The top-level run of the tree a pull request's marker run belongs to,
|
|
71
|
+
* whatever its status: the marker's coding run (a continuation resolves to
|
|
72
|
+
* its root coding run first), then up its parents. Null when the marker
|
|
73
|
+
* names no coding run, or one recorded for a different repository than
|
|
74
|
+
* `repository` (compared case-insensitively; omit it to skip the check).
|
|
75
|
+
* `isOpener` is true when that root is the opening coding run itself (the
|
|
76
|
+
* pull request was not delegated). The single place this walk and its
|
|
77
|
+
* repository guard live (requestLeadRunId, the merge order check).
|
|
78
|
+
*/
|
|
79
|
+
export declare function runTreeRoot(db: Pick<PrismaClient, "$queryRaw">, markerRunId: string, repository?: string): Promise<{
|
|
80
|
+
id: string;
|
|
81
|
+
status: RunStatus;
|
|
82
|
+
isOpener: boolean;
|
|
83
|
+
} | null>;
|
|
40
84
|
export declare function collectRelatedPullRequests(db: RelatedPullRequestsDb, runId: string,
|
|
41
85
|
/**
|
|
42
86
|
* Scopes the issue join (and any tree row explicitly tagged for a
|
|
@@ -67,6 +111,14 @@ export interface OpenSibling {
|
|
|
67
111
|
number: number;
|
|
68
112
|
openedByRunId: string;
|
|
69
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* The continuation hint for a ticket (a GitHub or Jira issue) that already has
|
|
116
|
+
* open wardby pull requests: one sentence per pull request (up to
|
|
117
|
+
* MAX_SIBLING_HINTS), then SIBLING_GUIDANCE once, as paragraphs. Built from
|
|
118
|
+
* stored rows only, with the run id, repository and number re-validated and the
|
|
119
|
+
* link built here, never taken from issue text. Empty when nothing is hintable.
|
|
120
|
+
*/
|
|
121
|
+
export declare function openPullRequestHints(prs: readonly OpenSibling[]): string;
|
|
70
122
|
/**
|
|
71
123
|
* The group's pull requests a follow-up may continue: stored state "open", or
|
|
72
124
|
* no stored state yet (a same-tree sibling not recorded for an issue), minus
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The pull requests that came from the same request as a run: every pull
|
|
3
3
|
* request opened by a coding run in the same top-level run tree (a lead that
|
|
4
|
-
* fanned out to several repositories), plus any recorded for the same
|
|
5
|
-
* issue (IssuePullRequest). Control-plane rows only.
|
|
6
|
-
* Ordered by
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* fanned out to several repositories), plus any recorded for the same Jira or
|
|
5
|
+
* GitHub issue (IssuePullRequest). Control-plane rows only.
|
|
6
|
+
* Ordered by the delegating agent's declared merge order when any entry has
|
|
7
|
+
* one (CodingRun.mergeOrder; nulls last), then by when each pull request's
|
|
8
|
+
* coding run was dispatched: the lead's delegation order (for a lead with
|
|
9
|
+
* parallelDelegations, the order its concurrent delegations were admitted,
|
|
10
|
+
* ties broken by repository#number). A pull request's mergeOrder is the
|
|
11
|
+
* newest non-null value set by its opener run or any later continuation
|
|
12
|
+
* that acted on it, so a lead that re-delegates with a different order
|
|
13
|
+
* after the fact is reflected here. When mergeOrder is set on any entry,
|
|
14
|
+
* every truncation cap below this collector (MAX_RELATED_GROUP here,
|
|
15
|
+
* MAX_SIBLING_HINTS on openSiblingsOf, MAX_RELATED_PULL_REQUESTS on
|
|
16
|
+
* renderRelatedSection) drops entries with no order first, since they sort
|
|
17
|
+
* last.
|
|
9
18
|
* A PR opened while siblings were still running lists only the PRs opened
|
|
10
19
|
* before it; updateRelatedPullRequests rewrites every open PR of the set
|
|
11
20
|
* with the full list when the lead run ends. Continuations join
|
|
@@ -15,7 +24,7 @@
|
|
|
15
24
|
*/
|
|
16
25
|
import { Prisma } from "#prisma";
|
|
17
26
|
import { CODING_CODE_PROVIDER, normalizeGitHubRepository } from "../coding/protocol.js";
|
|
18
|
-
import {
|
|
27
|
+
import { issueReference, } from "../providers/issue-tracker/types.js";
|
|
19
28
|
import { renderRelatedSection } from "../providers/vcs/github.js";
|
|
20
29
|
import { pullRequestOutcome } from "./host-status.js";
|
|
21
30
|
import { logger } from "./logger.js";
|
|
@@ -36,17 +45,50 @@ async function treeCodingRuns(db, seeds) {
|
|
|
36
45
|
UNION
|
|
37
46
|
SELECT p."id", p."parentRunId" FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
|
|
38
47
|
), down AS (
|
|
39
|
-
SELECT u."id" FROM up u WHERE u."parentRunId" IS NULL
|
|
48
|
+
SELECT u."id", u."id" AS "rootId" FROM up u WHERE u."parentRunId" IS NULL
|
|
40
49
|
UNION
|
|
41
|
-
SELECT c."id" FROM "Run" c JOIN down d ON c."parentRunId" = d."id"
|
|
50
|
+
SELECT c."id", d."rootId" FROM "Run" c JOIN down d ON c."parentRunId" = d."id"
|
|
42
51
|
)
|
|
43
|
-
SELECT cr."runId", cr."result", cr."rootCodingRunId", cr."issueProvider", cr."issueKey", r."startedAt"
|
|
52
|
+
SELECT cr."runId", cr."result", cr."rootCodingRunId", cr."issueProvider", cr."issueKey", cr."mergeOrder", r."startedAt",
|
|
53
|
+
d."rootId" AS "treeRootId", root."status"::text AS "treeRootStatus",
|
|
54
|
+
EXISTS (SELECT 1 FROM "CodingRun" rc WHERE rc."runId" = d."rootId") AS "treeRootIsCodingRun"
|
|
44
55
|
FROM "CodingRun" cr
|
|
45
56
|
JOIN down d ON cr."runId" = d."id"
|
|
46
57
|
JOIN "Run" r ON r."id" = cr."runId"
|
|
58
|
+
JOIN "Run" root ON root."id" = d."rootId"
|
|
47
59
|
ORDER BY r."startedAt" ASC, cr."runId" ASC
|
|
48
60
|
LIMIT ${MAX_TREE_CODING_RUNS}`;
|
|
49
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* The top-level run of the tree a pull request's marker run belongs to,
|
|
64
|
+
* whatever its status: the marker's coding run (a continuation resolves to
|
|
65
|
+
* its root coding run first), then up its parents. Null when the marker
|
|
66
|
+
* names no coding run, or one recorded for a different repository than
|
|
67
|
+
* `repository` (compared case-insensitively; omit it to skip the check).
|
|
68
|
+
* `isOpener` is true when that root is the opening coding run itself (the
|
|
69
|
+
* pull request was not delegated). The single place this walk and its
|
|
70
|
+
* repository guard live (requestLeadRunId, the merge order check).
|
|
71
|
+
*/
|
|
72
|
+
export async function runTreeRoot(db, markerRunId, repository) {
|
|
73
|
+
const repo = repository ?? null;
|
|
74
|
+
// UNION, not UNION ALL: a parentRunId cycle (never written, but not a constraint) can't recurse forever.
|
|
75
|
+
const rows = await db.$queryRaw `
|
|
76
|
+
WITH RECURSIVE opener AS (
|
|
77
|
+
SELECT COALESCE(cr."rootCodingRunId", cr."runId") AS "id"
|
|
78
|
+
FROM "CodingRun" cr
|
|
79
|
+
WHERE cr."runId" = ${markerRunId}
|
|
80
|
+
AND (${repo}::text IS NULL OR lower(cr."repository") = lower(${repo}::text))
|
|
81
|
+
), up AS (
|
|
82
|
+
SELECT r."id", r."parentRunId", r."status"::text AS "status" FROM "Run" r JOIN opener o ON r."id" = o."id"
|
|
83
|
+
UNION
|
|
84
|
+
SELECT p."id", p."parentRunId", p."status"::text FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
|
|
85
|
+
)
|
|
86
|
+
SELECT u."id", u."status", u."id" IN (SELECT "id" FROM opener) AS "isOpener"
|
|
87
|
+
FROM up u
|
|
88
|
+
WHERE u."parentRunId" IS NULL
|
|
89
|
+
LIMIT 1`;
|
|
90
|
+
return rows[0] ?? null;
|
|
91
|
+
}
|
|
50
92
|
function safeRepository(value) {
|
|
51
93
|
try {
|
|
52
94
|
return normalizeGitHubRepository(value);
|
|
@@ -120,7 +162,8 @@ onlyIssueKey) {
|
|
|
120
162
|
let issue;
|
|
121
163
|
const issues = new Map();
|
|
122
164
|
for (const r of rows) {
|
|
123
|
-
|
|
165
|
+
// A Jira issue and a GitHub issue join the same way: by provider and key, each key re-validated.
|
|
166
|
+
if (r.issueProvider && r.issueKey && issueReference(r.issueProvider, r.issueKey)) {
|
|
124
167
|
const found = { provider: r.issueProvider, key: r.issueKey };
|
|
125
168
|
issue ??= found;
|
|
126
169
|
issues.set(`${found.provider}\0${found.key}`, found);
|
|
@@ -139,9 +182,40 @@ onlyIssueKey) {
|
|
|
139
182
|
number: pr.pullRequestNumber,
|
|
140
183
|
openedAt: new Date(r.startedAt),
|
|
141
184
|
openedByRunId: r.runId,
|
|
185
|
+
...(r.mergeOrder != null ? { mergeOrder: r.mergeOrder } : {}),
|
|
142
186
|
});
|
|
143
187
|
}
|
|
144
188
|
}
|
|
189
|
+
// A continuation dispatched with its own mergeOrder overrides the opener's
|
|
190
|
+
// (one that omits it stores the value it inherited), and it starts after
|
|
191
|
+
// the opener; the entry's mergeOrder is the newest non-null
|
|
192
|
+
// value among the opener row and every continuation row (same PR key,
|
|
193
|
+
// "pull_request_opened" or "pull_request_updated") found in the tree walk.
|
|
194
|
+
const newestMergeOrder = new Map();
|
|
195
|
+
for (const r of rows) {
|
|
196
|
+
if (r.mergeOrder == null)
|
|
197
|
+
continue;
|
|
198
|
+
const pr = pullRequestOutcome(r.result);
|
|
199
|
+
if (pr?.outcome !== "pull_request_opened" && pr?.outcome !== "pull_request_updated")
|
|
200
|
+
continue;
|
|
201
|
+
if (onlyIssueKey && r.issueKey && (r.issueProvider !== onlyIssueKey.provider || r.issueKey !== onlyIssueKey.key)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const repository = safeRepository(pr.repository);
|
|
205
|
+
if (!repository)
|
|
206
|
+
continue;
|
|
207
|
+
const key = keyOf(repository, pr.pullRequestNumber);
|
|
208
|
+
const startedAt = new Date(r.startedAt);
|
|
209
|
+
const current = newestMergeOrder.get(key);
|
|
210
|
+
if (!current || startedAt.getTime() >= current.startedAt.getTime()) {
|
|
211
|
+
newestMergeOrder.set(key, { startedAt, mergeOrder: r.mergeOrder });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
for (const [key, entry] of byKey) {
|
|
215
|
+
const newest = newestMergeOrder.get(key);
|
|
216
|
+
if (newest)
|
|
217
|
+
entry.mergeOrder = newest.mergeOrder;
|
|
218
|
+
}
|
|
145
219
|
const issueFilter = onlyIssueKey
|
|
146
220
|
? new Map([[`${onlyIssueKey.provider}\0${onlyIssueKey.key}`, onlyIssueKey]])
|
|
147
221
|
: issues;
|
|
@@ -177,25 +251,29 @@ onlyIssueKey) {
|
|
|
177
251
|
});
|
|
178
252
|
}
|
|
179
253
|
}
|
|
254
|
+
const order = (e) => e.mergeOrder ?? Number.POSITIVE_INFINITY;
|
|
180
255
|
const pullRequests = [...byKey.values()]
|
|
181
|
-
.sort((a, b) => a
|
|
256
|
+
.sort((a, b) => order(a) - order(b) ||
|
|
257
|
+
a.openedAt.getTime() - b.openedAt.getTime() ||
|
|
182
258
|
`${a.repository}#${a.number}`.localeCompare(`${b.repository}#${b.number}`))
|
|
183
259
|
.slice(0, MAX_RELATED_GROUP);
|
|
184
|
-
|
|
260
|
+
const roots = new Map();
|
|
261
|
+
for (const r of rows) {
|
|
262
|
+
if (r.treeRootId && r.treeRootStatus) {
|
|
263
|
+
roots.set(r.treeRootId, { status: r.treeRootStatus, codingRun: r.treeRootIsCodingRun === true });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
pullRequests,
|
|
268
|
+
...(issue ? { issue } : {}),
|
|
269
|
+
...(roots.size > 0 ? { roots: [...roots].map(([id, root]) => ({ id, ...root })) } : {}),
|
|
270
|
+
};
|
|
185
271
|
}
|
|
186
272
|
function issueFor(group, trackers) {
|
|
187
273
|
if (!group.issue)
|
|
188
274
|
return undefined;
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
url = trackers?.[provider]?.issueUrl(group.issue.key);
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
url = undefined;
|
|
196
|
-
}
|
|
197
|
-
const trackerName = Object.hasOwn(ISSUE_TRACKER_NAMES, provider) ? ISSUE_TRACKER_NAMES[provider] : undefined;
|
|
198
|
-
return { key: group.issue.key, ...(url ? { url } : {}), ...(trackerName ? { trackerName } : {}) };
|
|
275
|
+
const tracker = trackers?.[group.issue.provider];
|
|
276
|
+
return issueReference(group.issue.provider, group.issue.key, tracker ? (key) => tracker.issueUrl(key) : undefined);
|
|
199
277
|
}
|
|
200
278
|
/**
|
|
201
279
|
* After a native run ends, rewrites the Related pull requests section on
|
|
@@ -219,7 +297,12 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
|
|
|
219
297
|
for (const pr of group.pullRequests) {
|
|
220
298
|
// A stored merged/closed state is final and such a PR is never edited: no host read.
|
|
221
299
|
if (pr.state === "merged" || pr.state === "closed") {
|
|
222
|
-
live.push({
|
|
300
|
+
live.push({
|
|
301
|
+
repository: pr.repository,
|
|
302
|
+
number: pr.number,
|
|
303
|
+
state: pr.state,
|
|
304
|
+
...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
|
|
305
|
+
});
|
|
223
306
|
continue;
|
|
224
307
|
}
|
|
225
308
|
try {
|
|
@@ -240,12 +323,23 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
|
|
|
240
323
|
if (opener && opener.repository.toLowerCase() === pr.repository)
|
|
241
324
|
markerRunId = origin.markerRunId;
|
|
242
325
|
}
|
|
243
|
-
live.push({
|
|
326
|
+
live.push({
|
|
327
|
+
repository: pr.repository,
|
|
328
|
+
number: pr.number,
|
|
329
|
+
state,
|
|
330
|
+
...(markerRunId ? { markerRunId } : {}),
|
|
331
|
+
...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
|
|
332
|
+
});
|
|
244
333
|
}
|
|
245
334
|
catch (err) {
|
|
246
335
|
log.warn({ err, runId: run.id, repository: pr.repository, number: pr.number }, "could not read a related pull request");
|
|
247
336
|
// The stored state (issue-recorded PRs) is better than none; never edited without a live read.
|
|
248
|
-
live.push({
|
|
337
|
+
live.push({
|
|
338
|
+
repository: pr.repository,
|
|
339
|
+
number: pr.number,
|
|
340
|
+
...(pr.state ? { state: pr.state } : {}),
|
|
341
|
+
...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
|
|
342
|
+
});
|
|
249
343
|
}
|
|
250
344
|
}
|
|
251
345
|
const issue = issueFor(group, trackers);
|
|
@@ -258,6 +352,7 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
|
|
|
258
352
|
number: pr.number,
|
|
259
353
|
...(pr.state ? { state: pr.state } : {}),
|
|
260
354
|
...(pr === target ? { self: true } : {}),
|
|
355
|
+
...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
|
|
261
356
|
})),
|
|
262
357
|
...(issue ? { issue } : {}),
|
|
263
358
|
});
|
|
@@ -286,6 +381,26 @@ const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
|
286
381
|
export const SIBLING_GUIDANCE = "Continue the pull request you were asked about, and a listed open one only when the change requires it. " +
|
|
287
382
|
"Never open a new pull request in a repository that already has an open pull request listed here. Merged or " +
|
|
288
383
|
"closed pull requests are not listed: a change there needs a new pull request.";
|
|
384
|
+
const HINT_REPOSITORY = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
385
|
+
/**
|
|
386
|
+
* The continuation hint for a ticket (a GitHub or Jira issue) that already has
|
|
387
|
+
* open wardby pull requests: one sentence per pull request (up to
|
|
388
|
+
* MAX_SIBLING_HINTS), then SIBLING_GUIDANCE once, as paragraphs. Built from
|
|
389
|
+
* stored rows only, with the run id, repository and number re-validated and the
|
|
390
|
+
* link built here, never taken from issue text. Empty when nothing is hintable.
|
|
391
|
+
*/
|
|
392
|
+
export function openPullRequestHints(prs) {
|
|
393
|
+
const lines = prs
|
|
394
|
+
.filter((p) => SAFE_RUN_ID.test(p.openedByRunId) &&
|
|
395
|
+
HINT_REPOSITORY.test(p.repository) &&
|
|
396
|
+
Number.isSafeInteger(p.number) &&
|
|
397
|
+
p.number > 0)
|
|
398
|
+
.slice(0, MAX_SIBLING_HINTS)
|
|
399
|
+
.map((p) => `This issue already has an open pull request wardby opened: ${p.repository}#${p.number} ` +
|
|
400
|
+
`(https://github.com/${p.repository}/pull/${p.number}). ` +
|
|
401
|
+
`To revise it, delegate with continuePriorRun set to exactly "${p.openedByRunId}".`);
|
|
402
|
+
return lines.length > 0 ? [...lines, SIBLING_GUIDANCE].join("\n\n") : "";
|
|
403
|
+
}
|
|
289
404
|
/**
|
|
290
405
|
* The group's pull requests a follow-up may continue: stored state "open", or
|
|
291
406
|
* no stored state yet (a same-tree sibling not recorded for an issue), minus
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits an agent's reply into comment-sized parts, so a long reply (a plan
|
|
3
|
+
* posted to an issue, say) can go out in full as numbered follow-up comments
|
|
4
|
+
* instead of being cut. Pure: numbering, headers and the cut note are the
|
|
5
|
+
* caller's job; each part is a raw slice of the defused text.
|
|
6
|
+
*/
|
|
7
|
+
export interface ReplyParts {
|
|
8
|
+
parts: string[];
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** "@" + U+200B before a word character, so a quoted reply pings nobody. */
|
|
12
|
+
export declare function defuseMentions(text: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Splits `text` into at most `maxParts` parts of at most `maxChars` each, preferring Markdown heading
|
|
15
|
+
* boundaries, then blank lines (paragraphs), then single newlines, then a hard cut. Defuses @-mentions.
|
|
16
|
+
* Never splits inside a fenced code block unless one block alone exceeds maxChars (then hard-cut it).
|
|
17
|
+
*/
|
|
18
|
+
export declare function splitReply(text: string, opts: {
|
|
19
|
+
maxChars: number;
|
|
20
|
+
maxParts: number;
|
|
21
|
+
}): ReplyParts;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits an agent's reply into comment-sized parts, so a long reply (a plan
|
|
3
|
+
* posted to an issue, say) can go out in full as numbered follow-up comments
|
|
4
|
+
* instead of being cut. Pure: numbering, headers and the cut note are the
|
|
5
|
+
* caller's job; each part is a raw slice of the defused text.
|
|
6
|
+
*/
|
|
7
|
+
/** "@" + U+200B before a word character, so a quoted reply pings nobody. */
|
|
8
|
+
export function defuseMentions(text) {
|
|
9
|
+
return text.replace(/@(?=[\w-])/g, "@\u200b");
|
|
10
|
+
}
|
|
11
|
+
const FENCE_LINE = /^\s{0,3}(```|~~~)/;
|
|
12
|
+
const HEADING_LINE = /^#{1,6}\s/;
|
|
13
|
+
/** [open, close) offsets of each fenced code block; a cut strictly inside one would break it. */
|
|
14
|
+
function fenceSpans(text) {
|
|
15
|
+
const spans = [];
|
|
16
|
+
let open = -1;
|
|
17
|
+
let offset = 0;
|
|
18
|
+
for (const line of text.split("\n")) {
|
|
19
|
+
const end = offset + line.length + 1;
|
|
20
|
+
if (FENCE_LINE.test(line)) {
|
|
21
|
+
if (open < 0)
|
|
22
|
+
open = offset;
|
|
23
|
+
else {
|
|
24
|
+
spans.push([open, Math.min(end, text.length)]);
|
|
25
|
+
open = -1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
offset = end;
|
|
29
|
+
}
|
|
30
|
+
if (open >= 0)
|
|
31
|
+
spans.push([open, text.length]);
|
|
32
|
+
return spans;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Splits `text` into at most `maxParts` parts of at most `maxChars` each, preferring Markdown heading
|
|
36
|
+
* boundaries, then blank lines (paragraphs), then single newlines, then a hard cut. Defuses @-mentions.
|
|
37
|
+
* Never splits inside a fenced code block unless one block alone exceeds maxChars (then hard-cut it).
|
|
38
|
+
*/
|
|
39
|
+
export function splitReply(text, opts) {
|
|
40
|
+
const maxChars = Math.max(1, Math.floor(opts.maxChars));
|
|
41
|
+
const maxParts = Math.max(1, Math.floor(opts.maxParts));
|
|
42
|
+
const defused = defuseMentions(text);
|
|
43
|
+
if (defused.length <= maxChars)
|
|
44
|
+
return { parts: [defused], truncated: false };
|
|
45
|
+
const spans = fenceSpans(defused);
|
|
46
|
+
const inFence = (at) => spans.some(([open, close]) => at > open && at < close);
|
|
47
|
+
const lineStart = (at) => defused[at - 1] === "\n";
|
|
48
|
+
const tiers = [
|
|
49
|
+
(at) => lineStart(at) && HEADING_LINE.test(defused.slice(at, at + 7)),
|
|
50
|
+
(at) => lineStart(at) && defused[at - 2] === "\n",
|
|
51
|
+
lineStart,
|
|
52
|
+
];
|
|
53
|
+
/** The furthest cut in (start, start + maxChars]: the best tier wins, then a hard cut. */
|
|
54
|
+
const cutAfter = (start) => {
|
|
55
|
+
const limit = start + maxChars;
|
|
56
|
+
for (const tier of tiers) {
|
|
57
|
+
for (let at = limit; at > start; at--)
|
|
58
|
+
if (!inFence(at) && tier(at))
|
|
59
|
+
return at;
|
|
60
|
+
}
|
|
61
|
+
// A surrogate pair is one character to a reader; keep it whole when we can.
|
|
62
|
+
const code = defused.charCodeAt(limit - 1);
|
|
63
|
+
return code >= 0xd800 && code <= 0xdbff && limit - 1 > start ? limit - 1 : limit;
|
|
64
|
+
};
|
|
65
|
+
const parts = [];
|
|
66
|
+
let start = 0;
|
|
67
|
+
while (start < defused.length && parts.length < maxParts) {
|
|
68
|
+
const end = defused.length - start <= maxChars ? defused.length : cutAfter(start);
|
|
69
|
+
parts.push(defused.slice(start, end));
|
|
70
|
+
start = end;
|
|
71
|
+
}
|
|
72
|
+
return { parts, truncated: start < defused.length };
|
|
73
|
+
}
|
|
@@ -23,6 +23,8 @@ export declare const AUTHORIZED_VIA: readonly AuthorizedVia[];
|
|
|
23
23
|
export type RepoAccessDenial = "owner_required" | "not_authorized" | "identity_not_linked" | "insufficient_permission" | "check_failed"
|
|
24
24
|
/** A `local:` repository that is not inside the current trusted roots (LOCAL_REPO_ROOTS). */
|
|
25
25
|
| "local_repo_not_allowed"
|
|
26
|
+
/** A GitHub repository whose owner is neither the App's owner nor in WARDBY_GITHUB_ALLOWED_ACCOUNTS. */
|
|
27
|
+
| "github_account_not_allowed"
|
|
26
28
|
/** In-flight use only: the host was unreachable or rate-limited, even after one retry. */
|
|
27
29
|
| "check_unavailable";
|
|
28
30
|
export type RepoAccessDecision = {
|
|
@@ -78,6 +80,8 @@ export interface RepoAccessGate {
|
|
|
78
80
|
required: HostPermission;
|
|
79
81
|
fresh?: boolean;
|
|
80
82
|
}): Promise<RepoAccessDecision>;
|
|
83
|
+
/** Is this repository's account served by the GitHub App? undefined = yes (or not a GitHub repository). */
|
|
84
|
+
checkAccount?(provider: string, repository: string): Promise<RepoAccessDecision | undefined>;
|
|
81
85
|
}
|
|
82
86
|
export interface RepoAccessGateOptions {
|
|
83
87
|
db: Pick<PrismaClient, "hostIdentity">;
|
|
@@ -92,9 +96,20 @@ export interface RepoAccessGateOptions {
|
|
|
92
96
|
/** Delay before the one retry of a transient error (default 1s). */
|
|
93
97
|
retryDelayMs?: number;
|
|
94
98
|
sleep?: (ms: number) => Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* The served GitHub accounts (default: the App owner from hosts.github plus
|
|
101
|
+
* WARDBY_GITHUB_ALLOWED_ACCOUNTS). undefined = no GitHub App, nothing to guard.
|
|
102
|
+
* Throwing = fail closed.
|
|
103
|
+
*/
|
|
104
|
+
trustedAccounts?: () => Promise<ReadonlySet<string> | undefined>;
|
|
95
105
|
}
|
|
96
106
|
/** 5xx, rate limits (403/429), and transport failures: worth one retry for a run already under way. */
|
|
97
107
|
export declare function isTransientHostError(err: unknown): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Why the trusted GitHub accounts could not be read, as a fixed string: every
|
|
110
|
+
* branch returns a literal, so nothing from the error itself reaches a log.
|
|
111
|
+
*/
|
|
112
|
+
export declare function trustedAccountsFailure(err: unknown): string;
|
|
98
113
|
export declare const DEFAULT_REPO_ACCESS_TTL_MS: number;
|
|
99
114
|
export declare function createRepoAccessGate(options: RepoAccessGateOptions): RepoAccessGate;
|
|
100
115
|
/** Actionable, non-leaking text for a denial, for tool results and run errors. */
|
package/dist/core/repo-access.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HOST_PERMISSION_RANK, ReviewHostError, } from "../providers/review-host/types.js";
|
|
2
2
|
import { LocalRepoError, isLocalRepository, loadLocalRepoRoots, resolveLocalRepository } from "../coding/local-repo.js";
|
|
3
|
+
import { githubAccountOf, isGitHubAccountAllowed, loadGitHubAllowedAccounts, trustedAccounts as trustedAccountSet, } from "../config/github-allowed-accounts.js";
|
|
3
4
|
import { logger } from "./logger.js";
|
|
4
5
|
const log = logger.child({ module: "repo-access" });
|
|
5
6
|
export const AUTHORIZED_VIA = ["host_permission", "admin", "grandfathered", "local_root"];
|
|
@@ -20,6 +21,24 @@ export function isTransientHostError(err) {
|
|
|
20
21
|
return false;
|
|
21
22
|
return err.message === "github_api_unavailable" || /^github_api_error:(5\d\d|429|403)(:|$)/.test(err.message);
|
|
22
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Why the trusted GitHub accounts could not be read, as a fixed string: every
|
|
26
|
+
* branch returns a literal, so nothing from the error itself reaches a log.
|
|
27
|
+
*/
|
|
28
|
+
export function trustedAccountsFailure(err) {
|
|
29
|
+
const message = err instanceof Error ? err.message : "";
|
|
30
|
+
if (message === "github_allowed_accounts_invalid")
|
|
31
|
+
return "github_allowed_accounts_invalid";
|
|
32
|
+
if (message === "github_api_unavailable")
|
|
33
|
+
return "github_api_unavailable";
|
|
34
|
+
if (message === "github_api_invalid_response")
|
|
35
|
+
return "github_api_invalid_response";
|
|
36
|
+
if (message === "github_app_private_key_invalid")
|
|
37
|
+
return "github_app_private_key_invalid";
|
|
38
|
+
if (message.startsWith("github_api_error:"))
|
|
39
|
+
return "github_api_error";
|
|
40
|
+
return "unexpected_error";
|
|
41
|
+
}
|
|
23
42
|
const defaultLocalRoots = () => loadLocalRepoRoots(process.env).roots;
|
|
24
43
|
export const DEFAULT_REPO_ACCESS_TTL_MS = 5 * 60_000;
|
|
25
44
|
export function createRepoAccessGate(options) {
|
|
@@ -29,6 +48,41 @@ export function createRepoAccessGate(options) {
|
|
|
29
48
|
const retryDelayMs = options.retryDelayMs ?? 1000;
|
|
30
49
|
const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
31
50
|
const cache = new Map();
|
|
51
|
+
const readTrusted = options.trustedAccounts ??
|
|
52
|
+
(async () => {
|
|
53
|
+
const host = options.hosts.github;
|
|
54
|
+
if (!host?.appOwnerLogin)
|
|
55
|
+
return undefined;
|
|
56
|
+
let extra;
|
|
57
|
+
try {
|
|
58
|
+
extra = loadGitHubAllowedAccounts();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// A fixed code: the parse error quotes the raw value, which must not reach the log.
|
|
62
|
+
throw new Error("github_allowed_accounts_invalid");
|
|
63
|
+
}
|
|
64
|
+
return trustedAccountSet(await host.appOwnerLogin(), extra);
|
|
65
|
+
});
|
|
66
|
+
/** A server-wide boundary, checked before any stamp, owner, or host call. Local repositories are exempt. */
|
|
67
|
+
async function checkAccount(provider, repository) {
|
|
68
|
+
if (provider !== "github" || isLocalRepository(repository))
|
|
69
|
+
return undefined;
|
|
70
|
+
let trusted;
|
|
71
|
+
try {
|
|
72
|
+
trusted = await readTrusted();
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
// Only a fixed code is logged, never the error: its message may carry
|
|
76
|
+
// WARDBY_GITHUB_ALLOWED_ACCOUNTS's value (CodeQL js/clear-text-logging).
|
|
77
|
+
log.warn({ code: trustedAccountsFailure(err) }, "could not read the GitHub App's trusted accounts; denying");
|
|
78
|
+
return { ok: false, reason: "check_failed" };
|
|
79
|
+
}
|
|
80
|
+
if (trusted === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
return isGitHubAccountAllowed(trusted, githubAccountOf(repository))
|
|
83
|
+
? undefined
|
|
84
|
+
: { ok: false, reason: "github_account_not_allowed" };
|
|
85
|
+
}
|
|
32
86
|
/** The user's level, or why it could not be determined (host missing or failing). */
|
|
33
87
|
async function levelOf(provider, repository, user, fresh, retryTransient) {
|
|
34
88
|
const key = `${provider}\u0000${repository}\u0000${user.id}`;
|
|
@@ -69,6 +123,9 @@ export function createRepoAccessGate(options) {
|
|
|
69
123
|
return atLeast(level, required) ? { ok: true, level } : { ok: false, reason: "insufficient_permission", level };
|
|
70
124
|
}
|
|
71
125
|
async function authorizePrincipal(input) {
|
|
126
|
+
const denied = await checkAccount(input.provider, input.repository);
|
|
127
|
+
if (denied)
|
|
128
|
+
return denied;
|
|
72
129
|
let identity;
|
|
73
130
|
try {
|
|
74
131
|
identity = await options.db.hostIdentity.findUnique({
|
|
@@ -108,6 +165,9 @@ export function createRepoAccessGate(options) {
|
|
|
108
165
|
return { ok: false, reason: "local_repo_not_allowed" };
|
|
109
166
|
}
|
|
110
167
|
}
|
|
168
|
+
const denied = await checkAccount(input.provider, input.repository);
|
|
169
|
+
if (denied)
|
|
170
|
+
return denied;
|
|
111
171
|
if (!input.ownerId)
|
|
112
172
|
return { ok: false, reason: "owner_required" };
|
|
113
173
|
if (input.authorizedVia === "admin" || input.authorizedVia === "grandfathered")
|
|
@@ -124,11 +184,15 @@ export function createRepoAccessGate(options) {
|
|
|
124
184
|
},
|
|
125
185
|
authorizePrincipal,
|
|
126
186
|
async authorizeHostUser(input) {
|
|
187
|
+
const denied = await checkAccount(input.provider, input.repository);
|
|
188
|
+
if (denied)
|
|
189
|
+
return denied;
|
|
127
190
|
const answer = await levelOf(input.provider, input.repository, input.user, input.fresh === true, false);
|
|
128
191
|
if (!answer.ok)
|
|
129
192
|
return unavailable(answer);
|
|
130
193
|
return decide(answer.level, input.required);
|
|
131
194
|
},
|
|
195
|
+
checkAccount,
|
|
132
196
|
};
|
|
133
197
|
}
|
|
134
198
|
/** Actionable, non-leaking text for a denial, for tool results and run errors. */
|
|
@@ -144,6 +208,8 @@ export function describeDenial(decision, repository) {
|
|
|
144
208
|
return `The agent owner's GitHub account has ${decision.level ?? "no"} access to ${repository}, which is not enough.`;
|
|
145
209
|
case "local_repo_not_allowed":
|
|
146
210
|
return `local_repo_not_allowed: ${repository} is not a git repository inside the configured local roots (LOCAL_REPO_ROOTS).`;
|
|
211
|
+
case "github_account_not_allowed":
|
|
212
|
+
return `github_account_not_allowed: ${repository} belongs to a GitHub account this server does not serve (the App's owner and WARDBY_GITHUB_ALLOWED_ACCOUNTS).`;
|
|
147
213
|
case "check_failed":
|
|
148
214
|
return `Could not verify access to ${repository} right now; try again later.`;
|
|
149
215
|
case "check_unavailable":
|