@wardby/cli 0.6.0 → 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/deploy/local/docker-compose.quickstart-coding.yml +13 -0
- package/dist/claude-coding-worker/driver.d.ts +21 -3
- package/dist/claude-coding-worker/driver.js +125 -17
- package/dist/claude-coding-worker/main.js +34 -6
- package/dist/claude-coding-worker/sdk.js +12 -1
- 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 +1 -0
- package/dist/cli.js +24 -10
- 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 +46 -126
- package/dist/coding/profile.js +45 -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 +264 -346
- package/dist/coding/protocol.js +235 -12
- 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 +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- 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 +116 -38
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -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 +11 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- 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/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 +42 -0
- package/dist/core/dispatch.js +131 -56
- package/dist/core/engine-native.js +1 -1
- 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 +18 -2
- package/dist/core/host-events.js +284 -24
- 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 +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +54 -26
- 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 +2 -1
- package/dist/core/merge-order-check.js +8 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +27 -14
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +2 -1
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +99 -13
- 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 +80 -34
- package/dist/core/runner.js +439 -144
- 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 +10 -74
- 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/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +43 -8
- 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 +34 -3
- package/dist/generated/prisma/client.d.ts +34 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +220 -60
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +44 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +428 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +92 -1
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +95 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +92 -1
- package/dist/generated/prisma/models/Agent.d.ts +106 -8
- package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +229 -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 +1637 -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 +39 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- 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 +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models.d.ts +4 -0
- package/dist/help-index.json +1320 -69
- package/dist/import/create.js +32 -3
- package/dist/import/neutral-schema.d.ts +50 -281
- package/dist/import/neutral-schema.js +5 -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 +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/ownership.d.ts +7 -7
- 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/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +58 -10
- 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 +198 -16
- 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.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -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.js +34 -12
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secrets.js +2 -2
- 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 +1 -1
- package/dist/mcp/tools/tools.js +25 -9
- 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/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +41 -3
- package/dist/native-worker/gateway-server.js +124 -27
- package/dist/native-worker/gateway.d.ts +27 -1
- package/dist/native-worker/gateway.js +70 -4
- package/dist/native-worker/http-server.d.ts +3 -1
- package/dist/native-worker/http-server.js +11 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +18 -2
- package/dist/native-worker/ledger.js +57 -4
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +129 -577
- package/dist/native-worker/protocol.js +47 -1
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- 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 +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- 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 +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +47 -7
- package/dist/providers/executor/container.d.ts +361 -8
- package/dist/providers/executor/container.js +1136 -91
- 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 +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- 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 +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -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 +27 -2
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +2 -0
- package/dist/providers/jobs/kubernetes-isolation.js +17 -1
- package/dist/providers/jobs/kubernetes.d.ts +6 -1
- package/dist/providers/jobs/kubernetes.js +105 -16
- package/dist/providers/jobs/types.d.ts +33 -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 +29 -2
- package/dist/providers/review-host/github.js +224 -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 +134 -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 +214 -6
- package/dist/providers/vcs/github.js +447 -45
- 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 +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- 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/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +1 -0
- package/dist/sandbox/host-functions.js +6 -11
- package/dist/sandbox/secret-broker.js +3 -4
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +10 -0
- package/docs/agent-recipes.md +58 -20
- package/docs/code-review-agents.md +551 -41
- package/docs/coding-agent-setup.md +489 -7
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +20 -0
- package/docs/coding-worker-isolation.md +105 -30
- package/docs/getting-started-gke.md +124 -137
- package/docs/getting-started-identity-provider.md +10 -1
- package/docs/getting-started.md +9 -0
- package/docs/jira-agents.md +17 -8
- 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 +119 -23
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +33 -2
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +42 -10
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +24 -2
- package/help/architecture-agent.md +11 -6
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/code-review-agents.md +177 -6
- 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 +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- 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/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 +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +3 -2
- 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-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/identity-and-access.md +2 -0
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +29 -1
- package/help/native-sandbox.md +15 -1
- package/help/operating-agents.md +5 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +10 -7
- package/help/resume-runs-locally.md +131 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- 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 +78 -7
- package/package.json +17 -10
- 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 +311 -97
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { lastPusher } from "./budget-stopped-head.js";
|
|
2
|
+
import { pullRequestOutcome } from "./host-status.js";
|
|
3
|
+
import { MERGE_ORDER_CHECK_NAME } from "./merge-order-check.js";
|
|
4
|
+
const CI_GREEN = new Set(["passing", "none"]);
|
|
5
|
+
/** How far up the run tree (Run.parentRunId) the opt-in may come from. */
|
|
6
|
+
const MAX_ANCESTOR_HOPS = 10;
|
|
7
|
+
const CODING_RUN_SELECT = {
|
|
8
|
+
runId: true,
|
|
9
|
+
repository: true,
|
|
10
|
+
rootCodingRunId: true,
|
|
11
|
+
markedReadyAt: true,
|
|
12
|
+
result: true,
|
|
13
|
+
run: { select: { agentId: true, parentRunId: true, status: true } },
|
|
14
|
+
};
|
|
15
|
+
const passed = (c) => c !== undefined && c.status === "completed" && c.conclusion === "success";
|
|
16
|
+
export async function maybeMarkReady(deps, repository, prNumber, provider = "github") {
|
|
17
|
+
try {
|
|
18
|
+
const host = deps.hosts?.[provider];
|
|
19
|
+
if (!host?.pullRequestOrigin || !host.readOwnChecks || !host.readCi || !host.markReadyForReview)
|
|
20
|
+
return "off";
|
|
21
|
+
const links = await deps.db.agentRepository.findMany({
|
|
22
|
+
where: { provider, repository },
|
|
23
|
+
select: {
|
|
24
|
+
agentId: true,
|
|
25
|
+
access: true,
|
|
26
|
+
triggers: true,
|
|
27
|
+
checkName: true,
|
|
28
|
+
markReadyWhenPassing: true,
|
|
29
|
+
authorizedVia: true,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const optedIn = new Set(links
|
|
33
|
+
.filter((l) => l.access === "write" && l.authorizedVia !== null && l.markReadyWhenPassing)
|
|
34
|
+
.map((l) => l.agentId));
|
|
35
|
+
if (optedIn.size === 0)
|
|
36
|
+
return "off";
|
|
37
|
+
const reviewChecks = links
|
|
38
|
+
.filter((l) => l.access === "write" && l.authorizedVia !== null && l.triggers.includes("pull_request") && l.checkName)
|
|
39
|
+
.map((l) => l.checkName);
|
|
40
|
+
if (reviewChecks.length === 0)
|
|
41
|
+
return "not_ready";
|
|
42
|
+
// readOwnChecks reads at most 10 names; MERGE_ORDER_CHECK_NAME plus the reviewer
|
|
43
|
+
// check names must fit, or the merge-order check would silently be read as absent.
|
|
44
|
+
if (reviewChecks.length > 9)
|
|
45
|
+
return "not_ready";
|
|
46
|
+
const origin = await host.pullRequestOrigin(repository, prNumber);
|
|
47
|
+
if (origin.state !== "open" || origin.draft !== true || origin.isFork || !origin.markerRunId)
|
|
48
|
+
return "not_ready";
|
|
49
|
+
const marked = await deps.db.codingRun.findUnique({
|
|
50
|
+
where: { runId: origin.markerRunId },
|
|
51
|
+
select: CODING_RUN_SELECT,
|
|
52
|
+
});
|
|
53
|
+
if (!marked)
|
|
54
|
+
return "not_ready";
|
|
55
|
+
const root = marked.rootCodingRunId
|
|
56
|
+
? await deps.db.codingRun.findUnique({ where: { runId: marked.rootCodingRunId }, select: CODING_RUN_SELECT })
|
|
57
|
+
: marked;
|
|
58
|
+
if (!root || root.repository.toLowerCase() !== repository.toLowerCase())
|
|
59
|
+
return "not_ready";
|
|
60
|
+
if (pullRequestOutcome(root.result)?.pullRequestNumber !== prNumber)
|
|
61
|
+
return "not_ready";
|
|
62
|
+
if (!(await optedInInRunTree(deps.db, root.run, optedIn)))
|
|
63
|
+
return "not_ready";
|
|
64
|
+
if (root.markedReadyAt)
|
|
65
|
+
return "skipped";
|
|
66
|
+
if (await lastPushStoppedAtBudget(deps.db, root, prNumber))
|
|
67
|
+
return "not_ready";
|
|
68
|
+
const checks = await host.readOwnChecks(repository, origin.headSha, [MERGE_ORDER_CHECK_NAME, ...reviewChecks]);
|
|
69
|
+
if (!reviewChecks.every((name) => passed(checks.get(name))))
|
|
70
|
+
return "not_ready";
|
|
71
|
+
const order = checks.get(MERGE_ORDER_CHECK_NAME);
|
|
72
|
+
if (order !== undefined && !passed(order))
|
|
73
|
+
return "not_ready";
|
|
74
|
+
const ci = await host.readCi(repository, origin.headSha);
|
|
75
|
+
if (!CI_GREEN.has(ci.state) || ci.truncated)
|
|
76
|
+
return "not_ready";
|
|
77
|
+
const claimedAt = new Date();
|
|
78
|
+
// CodingRun.updatedAt is @updatedAt, so this claim (and a release below) bumps it, which
|
|
79
|
+
// feeds the merge-order sweep's ordering. Harmless: the sweep re-derives state from the
|
|
80
|
+
// host each time, it doesn't rely on updatedAt being untouched by mark-ready.
|
|
81
|
+
const claim = await deps.db.codingRun.updateMany({
|
|
82
|
+
where: { runId: root.runId, markedReadyAt: null },
|
|
83
|
+
data: { markedReadyAt: claimedAt },
|
|
84
|
+
});
|
|
85
|
+
if (claim.count === 0)
|
|
86
|
+
return "skipped";
|
|
87
|
+
const release = () => deps.db.codingRun
|
|
88
|
+
.updateMany({ where: { runId: root.runId, markedReadyAt: claimedAt }, data: { markedReadyAt: null } })
|
|
89
|
+
.catch((err) => deps.log?.warn({ err, repository, prNumber }, "could not release the mark-ready claim"));
|
|
90
|
+
try {
|
|
91
|
+
const result = await host.markReadyForReview(repository, prNumber, origin.headSha, origin.markerRunId);
|
|
92
|
+
if (result === "marked") {
|
|
93
|
+
deps.log?.info({ repository, prNumber }, "marked the pull request ready for review");
|
|
94
|
+
return "marked";
|
|
95
|
+
}
|
|
96
|
+
await release();
|
|
97
|
+
return "skipped";
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
await release();
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
deps.log?.warn({ err, repository, prNumber }, "could not mark the pull request ready for review");
|
|
106
|
+
return "failed";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Whether the last run that pushed to the pull request (the root, or a later continuation of it)
|
|
111
|
+
* stopped at its budget: its pushed changes are unfinished work, so the draft stays a draft. A
|
|
112
|
+
* continuation that finished the work makes it eligible again.
|
|
113
|
+
*/
|
|
114
|
+
async function lastPushStoppedAtBudget(db, root, prNumber) {
|
|
115
|
+
return (await lastPusher(db, root, prNumber)).status === "budget_exhausted";
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* True when the opener's agent, or an agent up its run tree (bounded, cycle-safe), is opted in.
|
|
119
|
+
* A coding run's parentRunId is set when a lead delegated to it.
|
|
120
|
+
*/
|
|
121
|
+
async function optedInInRunTree(db, opener, optedIn) {
|
|
122
|
+
if (optedIn.has(opener.agentId))
|
|
123
|
+
return true;
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
let next = opener.parentRunId ?? null;
|
|
126
|
+
for (let hop = 0; next && hop < MAX_ANCESTOR_HOPS && !seen.has(next); hop++) {
|
|
127
|
+
seen.add(next);
|
|
128
|
+
const run = await db.run.findUnique({ where: { id: next }, select: { agentId: true, parentRunId: true } });
|
|
129
|
+
if (!run)
|
|
130
|
+
return false;
|
|
131
|
+
if (optedIn.has(run.agentId))
|
|
132
|
+
return true;
|
|
133
|
+
next = run.parentRunId;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/** After a reviewer run ends: evaluate the pull request it reviewed. Null when it reviewed none. */
|
|
138
|
+
export async function markReadyAfterRun(deps, runId) {
|
|
139
|
+
try {
|
|
140
|
+
const row = await deps.db.runHostCheck.findUnique({
|
|
141
|
+
where: { runId },
|
|
142
|
+
select: { provider: true, repository: true, prNumber: true, verdict: true },
|
|
143
|
+
});
|
|
144
|
+
if (!row || row.prNumber === null || !row.verdict)
|
|
145
|
+
return null;
|
|
146
|
+
return await maybeMarkReady(deps, row.repository, row.prNumber, row.provider);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
deps.log?.warn({ err, runId }, "could not evaluate mark-ready after the run");
|
|
150
|
+
return "failed";
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub-flavoured Markdown with its code removed, so a mention quoted in code
|
|
3
|
+
* (`` `@app` ``, a fenced or indented block) is documentation, not a request.
|
|
4
|
+
* Close to CommonMark, not a full parser: when in doubt it keeps text, so a
|
|
5
|
+
* real mention is never lost to an odd construct.
|
|
6
|
+
*/
|
|
7
|
+
/** `markdown` without its code blocks and inline code spans. */
|
|
8
|
+
export declare function withoutMarkdownCode(markdown: string): string;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub-flavoured Markdown with its code removed, so a mention quoted in code
|
|
3
|
+
* (`` `@app` ``, a fenced or indented block) is documentation, not a request.
|
|
4
|
+
* Close to CommonMark, not a full parser: when in doubt it keeps text, so a
|
|
5
|
+
* real mention is never lost to an odd construct.
|
|
6
|
+
*/
|
|
7
|
+
const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;
|
|
8
|
+
const INDENTED = /^(?: {4}|\t)/;
|
|
9
|
+
const LIST_ITEM = /^ {0,3}(?:[-*+]|\d{1,9}[.)])(?:\s|$)/;
|
|
10
|
+
const BLANK = /^\s*$/;
|
|
11
|
+
/** Up to three spaces, at least the opening run of the fence's character, then only whitespace. */
|
|
12
|
+
function closesFence(line, fence) {
|
|
13
|
+
let index = 0;
|
|
14
|
+
while (index < 3 && line[index] === " ")
|
|
15
|
+
index += 1;
|
|
16
|
+
const start = index;
|
|
17
|
+
while (line[index] === fence.char)
|
|
18
|
+
index += 1;
|
|
19
|
+
return index - start >= fence.length && line.slice(index).trim() === "";
|
|
20
|
+
}
|
|
21
|
+
/** Fenced and indented code blocks blanked out, line count kept. */
|
|
22
|
+
function withoutCodeBlocks(markdown) {
|
|
23
|
+
const out = [];
|
|
24
|
+
let fence = null;
|
|
25
|
+
// Indented code needs a blank line before it, and indented text under a
|
|
26
|
+
// list item is the item's paragraph, not code.
|
|
27
|
+
let previousBlank = true;
|
|
28
|
+
let inIndentedCode = false;
|
|
29
|
+
let inList = false;
|
|
30
|
+
for (const line of markdown.split(/\r?\n/)) {
|
|
31
|
+
if (fence) {
|
|
32
|
+
if (closesFence(line, fence))
|
|
33
|
+
fence = null;
|
|
34
|
+
out.push("");
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const open = FENCE_OPEN.exec(line);
|
|
38
|
+
// A backtick fence's info string cannot contain a backtick (CommonMark).
|
|
39
|
+
if (open && !(open[1][0] === "`" && line.slice(line.indexOf(open[1]) + open[1].length).includes("`"))) {
|
|
40
|
+
fence = { char: open[1][0], length: open[1].length };
|
|
41
|
+
inIndentedCode = false;
|
|
42
|
+
previousBlank = false;
|
|
43
|
+
out.push("");
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (BLANK.test(line)) {
|
|
47
|
+
previousBlank = true;
|
|
48
|
+
out.push(line);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (INDENTED.test(line) && !inList && (previousBlank || inIndentedCode)) {
|
|
52
|
+
inIndentedCode = true;
|
|
53
|
+
previousBlank = false;
|
|
54
|
+
out.push("");
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
inIndentedCode = false;
|
|
58
|
+
if (LIST_ITEM.test(line))
|
|
59
|
+
inList = true;
|
|
60
|
+
else if (!INDENTED.test(line) && previousBlank)
|
|
61
|
+
inList = false;
|
|
62
|
+
previousBlank = false;
|
|
63
|
+
out.push(line);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/** Inline code spans in one paragraph replaced by a space; an unmatched run of backticks is literal. */
|
|
68
|
+
function withoutCodeSpans(paragraph) {
|
|
69
|
+
const runs = [];
|
|
70
|
+
for (let index = 0; index < paragraph.length;) {
|
|
71
|
+
if (paragraph[index] !== "`") {
|
|
72
|
+
index += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const start = index;
|
|
76
|
+
while (paragraph[index] === "`")
|
|
77
|
+
index += 1;
|
|
78
|
+
runs.push({ start, end: index });
|
|
79
|
+
}
|
|
80
|
+
// A span closes at the next run of exactly the opening run's length.
|
|
81
|
+
const closer = new Array(runs.length).fill(-1);
|
|
82
|
+
const nextOfLength = new Map();
|
|
83
|
+
for (let i = runs.length - 1; i >= 0; i--) {
|
|
84
|
+
const length = runs[i].end - runs[i].start;
|
|
85
|
+
closer[i] = nextOfLength.get(length) ?? -1;
|
|
86
|
+
nextOfLength.set(length, i);
|
|
87
|
+
}
|
|
88
|
+
let result = "";
|
|
89
|
+
let copied = 0;
|
|
90
|
+
for (let i = 0; i < runs.length; i++) {
|
|
91
|
+
const close = closer[i];
|
|
92
|
+
if (close === -1)
|
|
93
|
+
continue;
|
|
94
|
+
result += `${paragraph.slice(copied, runs[i].start)} `;
|
|
95
|
+
copied = runs[close].end;
|
|
96
|
+
i = close;
|
|
97
|
+
}
|
|
98
|
+
return result + paragraph.slice(copied);
|
|
99
|
+
}
|
|
100
|
+
/** `markdown` without its code blocks and inline code spans. */
|
|
101
|
+
export function withoutMarkdownCode(markdown) {
|
|
102
|
+
return withoutCodeBlocks(markdown)
|
|
103
|
+
.join("\n")
|
|
104
|
+
.split(/(\n[ \t]*\n)/)
|
|
105
|
+
.map((part, i) => (i % 2 === 1 ? part : withoutCodeSpans(part)))
|
|
106
|
+
.join("");
|
|
107
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* agents' data.
|
|
11
11
|
*/
|
|
12
12
|
import { z } from "zod";
|
|
13
|
+
import { SecretInValueError, SecretCheckUnavailableError } from "./secret-guard.js";
|
|
13
14
|
import { MEMORY_CONTENT_MAX_BYTES, MEMORY_KEY_MAX_BYTES, MEMORY_MAX_KEYS_PER_AGENT, MEMORY_SEARCH_MAX_LIMIT, } from "../providers/memory/types.js";
|
|
14
15
|
export const MEMORY_TOOL_NAMES = new Set([
|
|
15
16
|
"memory_get",
|
|
@@ -116,6 +117,12 @@ export async function handleMemoryTool(name, argsJson, agentId, memory) {
|
|
|
116
117
|
message: err.issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`).join("; "),
|
|
117
118
|
});
|
|
118
119
|
}
|
|
120
|
+
if (err instanceof SecretInValueError) {
|
|
121
|
+
return JSON.stringify({ error: err.code, message: err.message, secretNames: err.secretNames });
|
|
122
|
+
}
|
|
123
|
+
if (err instanceof SecretCheckUnavailableError) {
|
|
124
|
+
return JSON.stringify({ error: err.code, message: err.message });
|
|
125
|
+
}
|
|
119
126
|
const code = err instanceof Error ? err.message : "memory_error";
|
|
120
127
|
return JSON.stringify({ error: code, message: MEMORY_ERROR_MESSAGES[code] ?? code });
|
|
121
128
|
}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import type { Run } from "#prisma";
|
|
22
22
|
import type { PullRequestOrigin, ReviewHostRegistry, UpsertNamedCheckInput } from "../providers/review-host/types.js";
|
|
23
23
|
import { type Logger } from "./logger.js";
|
|
24
|
+
import { type MarkReadyDb } from "./mark-ready.js";
|
|
24
25
|
import { type RelatedPullRequestsDb } from "./related-pull-requests.js";
|
|
25
26
|
export declare const MERGE_ORDER_CHECK_NAME = "wardby merge order";
|
|
26
27
|
export interface MergeOrderMember {
|
|
@@ -49,7 +50,7 @@ export type MergeOrderVerdict = {
|
|
|
49
50
|
* as its entry in `set`; only `mergeOrder` is read from it.
|
|
50
51
|
*/
|
|
51
52
|
export declare function mergeOrderVerdict(self: MergeOrderMember, set: readonly MergeOrderMember[]): MergeOrderVerdict;
|
|
52
|
-
export type MergeOrderDb = RelatedPullRequestsDb;
|
|
53
|
+
export type MergeOrderDb = RelatedPullRequestsDb & MarkReadyDb;
|
|
53
54
|
export interface MergeOrderSyncDeps {
|
|
54
55
|
db: MergeOrderDb;
|
|
55
56
|
hosts: ReviewHostRegistry | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CODING_CODE_PROVIDER, normalizeGitHubRepository } from "../coding/protocol.js";
|
|
2
2
|
import { logger } from "./logger.js";
|
|
3
|
+
import { maybeMarkReady } from "./mark-ready.js";
|
|
3
4
|
import { collectRelatedPullRequests, runTreeRoot } from "./related-pull-requests.js";
|
|
4
5
|
const moduleLog = logger.child({ module: "merge-order-check" });
|
|
5
6
|
export const MERGE_ORDER_CHECK_NAME = "wardby merge order";
|
|
@@ -185,12 +186,18 @@ export async function syncMergeOrderChecks(deps, seedRunId, opts = {}) {
|
|
|
185
186
|
const verdict = mergeOrderVerdict(self, set);
|
|
186
187
|
if (verdict.status === "skip")
|
|
187
188
|
continue;
|
|
189
|
+
const input = mergeOrderCheckInput(self, verdict, steps, target.headSha, leadRunning);
|
|
188
190
|
try {
|
|
189
|
-
await host.upsertNamedCheck(self.repository,
|
|
191
|
+
await host.upsertNamedCheck(self.repository, input);
|
|
190
192
|
log.info({ seedRunId, repository: self.repository, number: self.number, status: verdict.status }, "merge order check posted");
|
|
191
193
|
}
|
|
192
194
|
catch (err) {
|
|
193
195
|
log.warn({ err, seedRunId, repository: self.repository, number: self.number }, "could not post the merge order check");
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (input.status === "completed" && input.conclusion === "success") {
|
|
199
|
+
// The last earlier step merged: the pull request may now be ready for review (#287).
|
|
200
|
+
await maybeMarkReady({ db: deps.db, hosts: deps.hosts, log: deps.log }, self.repository, self.number);
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic Slack text for workflow notifications. Pure functions: no
|
|
3
|
-
* I/O, no model output. Every string that came from a person or a model
|
|
4
|
-
* (titles, agent names, reasons) is escaped so it cannot become a link or a
|
|
5
|
-
* mention; only canonical tracker/host URLs are formatted as links.
|
|
6
|
-
*/
|
|
7
1
|
import type { ThreadSubject, WorkflowPayload } from "./workflow-events.js";
|
|
8
|
-
export type ThreadStatus = "picked up" | "PR open" | "changes requested" | "fixing" | "fix rounds exhausted" | "approved" | "merged ✅" | "closed" | "failed ❌";
|
|
2
|
+
export type ThreadStatus = "picked up" | "PR open" | "changes requested" | "fixing" | "fix rounds exhausted" | "approved" | "merged ✅" | "closed" | "failed ❌" | "blocked ⛔";
|
|
9
3
|
export declare function escapeMrkdwn(s: string): string;
|
|
10
4
|
export declare function nextStatus(prev: ThreadStatus | null, p: WorkflowPayload): ThreadStatus;
|
|
11
5
|
export declare function renderParent(subject: ThreadSubject, status: ThreadStatus): {
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic Slack text for workflow notifications. Pure functions: no
|
|
3
|
+
* I/O, no model output. Every string that came from a person or a model
|
|
4
|
+
* (titles, agent names, reasons) is escaped so it cannot become a link or a
|
|
5
|
+
* mention; only canonical tracker/host URLs are formatted as links.
|
|
6
|
+
*/
|
|
7
|
+
import { packageAuditStatusText } from "../coding/registry/audit-mode.js";
|
|
8
|
+
import { packageRefusalWording } from "../coding/registry/refusal-wording.js";
|
|
1
9
|
const TERMINAL = new Set(["merged ✅", "closed"]);
|
|
2
10
|
/** Events that start a new attempt (a new pickup, a new PR) and so reopen a merged/closed thread. */
|
|
3
11
|
const REOPENS = new Set(["issue_picked_up", "pr_opened"]);
|
|
@@ -28,8 +36,13 @@ export function nextStatus(prev, p) {
|
|
|
28
36
|
return p.state === "started" ? "fixing" : "fix rounds exhausted";
|
|
29
37
|
case "pr_closed":
|
|
30
38
|
return p.merged ? "merged ✅" : "closed";
|
|
39
|
+
case "run_blocked":
|
|
40
|
+
return "blocked ⛔";
|
|
31
41
|
case "run_failed":
|
|
32
42
|
return "failed ❌";
|
|
43
|
+
case "packages_audited":
|
|
44
|
+
// A report about the run, not a step in its workflow.
|
|
45
|
+
return prev ?? "picked up";
|
|
33
46
|
}
|
|
34
47
|
}
|
|
35
48
|
const section = (text) => ({ type: "section", text: { type: "mrkdwn", text } });
|
|
@@ -38,6 +51,19 @@ export function renderParent(subject, status) {
|
|
|
38
51
|
const text = `${head} — *${status}*`;
|
|
39
52
|
return { text, blocks: [section(text)] };
|
|
40
53
|
}
|
|
54
|
+
/** Refusal lists can exceed Slack's 3,000-character section limit. Keep each line intact. */
|
|
55
|
+
function refusalSections(text) {
|
|
56
|
+
const parts = [""];
|
|
57
|
+
for (const line of text.split("\n")) {
|
|
58
|
+
const last = parts.length - 1;
|
|
59
|
+
const joined = parts[last] ? parts[last] + "\n" + line : line;
|
|
60
|
+
if (joined.length > 3000)
|
|
61
|
+
parts.push(line);
|
|
62
|
+
else
|
|
63
|
+
parts[last] = joined;
|
|
64
|
+
}
|
|
65
|
+
return parts.map(section);
|
|
66
|
+
}
|
|
41
67
|
export function renderEvent(p, spend) {
|
|
42
68
|
let line;
|
|
43
69
|
switch (p.kind) {
|
|
@@ -69,6 +95,12 @@ export function renderEvent(p, spend) {
|
|
|
69
95
|
? `🎉 ${link(p.prUrl, p.prLabel)} merged${p.movedTo ? ` — moved to ${escapeMrkdwn(p.movedTo)}` : ""}`
|
|
70
96
|
: `⚪ ${link(p.prUrl, p.prLabel)} closed without merging`;
|
|
71
97
|
break;
|
|
98
|
+
case "run_blocked":
|
|
99
|
+
line = packageRefusalWording(p.packageRefusals, { slack: true });
|
|
100
|
+
break;
|
|
101
|
+
case "packages_audited":
|
|
102
|
+
line = packageAuditStatusText(p.mode, p, true);
|
|
103
|
+
break;
|
|
72
104
|
case "run_failed": {
|
|
73
105
|
const who = `*${escapeMrkdwn(p.agentName)}*`;
|
|
74
106
|
line =
|
|
@@ -83,7 +115,7 @@ export function renderEvent(p, spend) {
|
|
|
83
115
|
}
|
|
84
116
|
}
|
|
85
117
|
const text = spend ? `${line}\n_${escapeMrkdwn(spend)}_` : line;
|
|
86
|
-
return { text, blocks: [section(text)] };
|
|
118
|
+
return { text, blocks: p.kind === "run_blocked" ? refusalSections(text) : [section(text)] };
|
|
87
119
|
}
|
|
88
120
|
/**
|
|
89
121
|
* The Slack display name for a message about this event: the agent's name
|
|
@@ -93,13 +125,15 @@ export function renderEvent(p, spend) {
|
|
|
93
125
|
export function senderName(p) {
|
|
94
126
|
switch (p.kind) {
|
|
95
127
|
case "issue_picked_up":
|
|
128
|
+
case "run_blocked":
|
|
96
129
|
case "run_failed":
|
|
97
130
|
case "review_posted":
|
|
131
|
+
case "packages_audited":
|
|
98
132
|
return p.agentName;
|
|
99
133
|
default:
|
|
100
134
|
return "wardby";
|
|
101
135
|
}
|
|
102
136
|
}
|
|
103
137
|
export function broadcasts(p) {
|
|
104
|
-
return (p.kind === "pr_closed" && p.merged) || p.kind === "run_failed";
|
|
138
|
+
return (p.kind === "pr_closed" && p.merged) || p.kind === "run_failed" || p.kind === "run_blocked";
|
|
105
139
|
}
|
|
@@ -6,8 +6,8 @@ export const PR_STATE_SYNC_BATCH = 10;
|
|
|
6
6
|
/** A row is re-checked at most this often. */
|
|
7
7
|
export const PR_STATE_SYNC_MIN_AGE_MS = 10 * 60_000;
|
|
8
8
|
export async function syncOpenPullRequestStates(db, hosts, trackers, now = new Date()) {
|
|
9
|
-
//
|
|
10
|
-
if (!hosts
|
|
9
|
+
// Without trackers the rows (a GitHub issue's, say) are still settled; only tracker actions are skipped.
|
|
10
|
+
if (!hosts)
|
|
11
11
|
return 0;
|
|
12
12
|
let settled = 0;
|
|
13
13
|
try {
|
|
@@ -45,8 +45,9 @@ import type { PrismaClient } from "#prisma";
|
|
|
45
45
|
import type { Executor } from "../providers/executor/types.js";
|
|
46
46
|
import type { ReviewHostRegistry } from "../providers/review-host/types.js";
|
|
47
47
|
import type { IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
|
|
48
|
+
import { type HostStatusDb } from "./host-status.js";
|
|
48
49
|
import { type ReviewStartDeps } from "./host-events.js";
|
|
49
|
-
export type ReconcilerDb = Pick<PrismaClient, "run" | "runHostCheck" | "runHostStatus" | "runIssueStatus" | "agentIssueProject" | "issuePullRequest" | "codingRun" | "agent" | "$transaction" | "$queryRaw">;
|
|
50
|
+
export type ReconcilerDb = Pick<PrismaClient, "run" | "runHostCheck" | "runBudgetEvent" | "runHostStatus" | "runIssueStatus" | "agentIssueProject" | "issuePullRequest" | "codingRun" | "registryFetch" | "registryAuditRecord" | "agent" | "agentRepository" | "$transaction" | "$queryRaw">;
|
|
50
51
|
/**
|
|
51
52
|
* How long after a run finishes before its still-open check counts as
|
|
52
53
|
* orphaned: long enough that the sweep never races `executeRun`'s own
|
|
@@ -66,14 +67,14 @@ export declare const ORPHANED_CHECK_MAX_AGE_MS: number;
|
|
|
66
67
|
* than retried forever; its Re-run button still works. Never queries when
|
|
67
68
|
* no host is configured. `closeOpenHostCheck` is best-effort and never throws.
|
|
68
69
|
*/
|
|
69
|
-
export declare function closeOrphanedHostChecks(db: Pick<PrismaClient, "runHostCheck" | "run">, hosts: ReviewHostRegistry | undefined, now?: Date): Promise<void>;
|
|
70
|
+
export declare function closeOrphanedHostChecks(db: Pick<PrismaClient, "runHostCheck" | "run" | "runBudgetEvent">, hosts: ReviewHostRegistry | undefined, now?: Date): Promise<void>;
|
|
70
71
|
/**
|
|
71
72
|
* Completes open mention status comments on the same terms as
|
|
72
73
|
* closeOrphanedHostChecks: the run ended between ORPHANED_CHECK_GRACE_MS and
|
|
73
74
|
* ORPHANED_CHECK_MAX_AGE_MS ago, newest first, at most ORPHANED_CHECK_BATCH per
|
|
74
75
|
* pass. `completeHostStatus` is best-effort and never throws.
|
|
75
76
|
*/
|
|
76
|
-
export declare function closeOrphanedHostStatuses(db:
|
|
77
|
+
export declare function closeOrphanedHostStatuses(db: HostStatusDb, hosts: ReviewHostRegistry | undefined, now?: Date): Promise<void>;
|
|
77
78
|
/** Runs one reconciliation pass. Returns the number of runs marked `lost`. */
|
|
78
79
|
export declare function reconcileOnce(db: ReconcilerDb, now?: Date, heartbeatTimeoutMs?: number, executor?: Executor, reviewHosts?: ReviewHostRegistry, issueTrackers?: IssueTrackerRegistry,
|
|
79
80
|
/** What starting a deferred review needs; absent = no deferred-review sweep. */
|
package/dist/core/reconciler.js
CHANGED
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
import { HEARTBEAT_TIMEOUT_MS, RECONCILE_INTERVAL_MS } from "./timing.js";
|
|
45
45
|
import { prisma as defaultDb } from "./db.js";
|
|
46
46
|
import { logger } from "./logger.js";
|
|
47
|
+
import { stopChildrenOfLostRun } from "./lost-run-children.js";
|
|
47
48
|
import { closeOpenHostCheck } from "./review-host-checks.js";
|
|
48
49
|
import { completeHostStatus } from "./host-status.js";
|
|
49
50
|
import { closeOrphanedIssueStatuses } from "./issue-status.js";
|
|
@@ -210,7 +211,11 @@ deferredReviews) {
|
|
|
210
211
|
continue;
|
|
211
212
|
let recovered;
|
|
212
213
|
try {
|
|
213
|
-
recovered = await executor.recover({
|
|
214
|
+
recovered = await executor.recover({
|
|
215
|
+
runId: run.id,
|
|
216
|
+
backend: run.executionBackend,
|
|
217
|
+
id: run.executionWorkflowId ?? run.id,
|
|
218
|
+
});
|
|
214
219
|
}
|
|
215
220
|
catch (err) {
|
|
216
221
|
reconcilerLog.error({ err, runId: run.id }, "durable run recovery failed");
|
|
@@ -225,6 +230,7 @@ deferredReviews) {
|
|
|
225
230
|
});
|
|
226
231
|
lost += result.count;
|
|
227
232
|
if (result.count > 0) {
|
|
233
|
+
await stopChildrenOfLostRun(db, executor, run.id);
|
|
228
234
|
await fileSelfDefect(db, issueTrackers, { ...run, status: "lost", error: reason, finishedAt: now }, SELF_DEFECT_WAIT);
|
|
229
235
|
await emitRunFinishedEvents(db, {
|
|
230
236
|
id: run.id,
|
|
@@ -243,6 +249,7 @@ deferredReviews) {
|
|
|
243
249
|
lost += result.count;
|
|
244
250
|
// Only after this pass made the row lost (not when another instance won the race); bounded, never throws.
|
|
245
251
|
if (result.count > 0) {
|
|
252
|
+
await stopChildrenOfLostRun(db, executor, run.id);
|
|
246
253
|
await fileSelfDefect(db, issueTrackers, { ...run, status: "lost", error: reason, finishedAt: now }, SELF_DEFECT_WAIT);
|
|
247
254
|
await emitRunFinishedEvents(db, {
|
|
248
255
|
id: run.id,
|
|
@@ -1,8 +1,8 @@
|
|
|
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.
|
|
4
|
+
* fanned out to several repositories), plus any recorded for the same Jira or
|
|
5
|
+
* GitHub issue (IssuePullRequest). Control-plane rows only.
|
|
6
6
|
* Ordered by the delegating agent's declared merge order when any entry has
|
|
7
7
|
* one (CodingRun.mergeOrder; nulls last), then by when each pull request's
|
|
8
8
|
* coding run was dispatched: the lead's delegation order (for a lead with
|
|
@@ -47,7 +47,7 @@ export interface RelatedPullRequest {
|
|
|
47
47
|
}
|
|
48
48
|
export interface RelatedPullRequestGroup {
|
|
49
49
|
pullRequests: RelatedPullRequest[];
|
|
50
|
-
/** 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. */
|
|
51
51
|
issue?: {
|
|
52
52
|
provider: string;
|
|
53
53
|
key: string;
|
|
@@ -111,6 +111,14 @@ export interface OpenSibling {
|
|
|
111
111
|
number: number;
|
|
112
112
|
openedByRunId: string;
|
|
113
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;
|
|
114
122
|
/**
|
|
115
123
|
* The group's pull requests a follow-up may continue: stored state "open", or
|
|
116
124
|
* no stored state yet (a same-tree sibling not recorded for an issue), minus
|
|
@@ -1,8 +1,8 @@
|
|
|
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.
|
|
4
|
+
* fanned out to several repositories), plus any recorded for the same Jira or
|
|
5
|
+
* GitHub issue (IssuePullRequest). Control-plane rows only.
|
|
6
6
|
* Ordered by the delegating agent's declared merge order when any entry has
|
|
7
7
|
* one (CodingRun.mergeOrder; nulls last), then by when each pull request's
|
|
8
8
|
* coding run was dispatched: the lead's delegation order (for a lead with
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { Prisma } from "#prisma";
|
|
26
26
|
import { CODING_CODE_PROVIDER, normalizeGitHubRepository } from "../coding/protocol.js";
|
|
27
|
-
import {
|
|
27
|
+
import { issueReference, } from "../providers/issue-tracker/types.js";
|
|
28
28
|
import { renderRelatedSection } from "../providers/vcs/github.js";
|
|
29
29
|
import { pullRequestOutcome } from "./host-status.js";
|
|
30
30
|
import { logger } from "./logger.js";
|
|
@@ -162,7 +162,8 @@ onlyIssueKey) {
|
|
|
162
162
|
let issue;
|
|
163
163
|
const issues = new Map();
|
|
164
164
|
for (const r of rows) {
|
|
165
|
-
|
|
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)) {
|
|
166
167
|
const found = { provider: r.issueProvider, key: r.issueKey };
|
|
167
168
|
issue ??= found;
|
|
168
169
|
issues.set(`${found.provider}\0${found.key}`, found);
|
|
@@ -271,16 +272,8 @@ onlyIssueKey) {
|
|
|
271
272
|
function issueFor(group, trackers) {
|
|
272
273
|
if (!group.issue)
|
|
273
274
|
return undefined;
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
try {
|
|
277
|
-
url = trackers?.[provider]?.issueUrl(group.issue.key);
|
|
278
|
-
}
|
|
279
|
-
catch {
|
|
280
|
-
url = undefined;
|
|
281
|
-
}
|
|
282
|
-
const trackerName = Object.hasOwn(ISSUE_TRACKER_NAMES, provider) ? ISSUE_TRACKER_NAMES[provider] : undefined;
|
|
283
|
-
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);
|
|
284
277
|
}
|
|
285
278
|
/**
|
|
286
279
|
* After a native run ends, rewrites the Related pull requests section on
|
|
@@ -388,6 +381,26 @@ const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
|
388
381
|
export const SIBLING_GUIDANCE = "Continue the pull request you were asked about, and a listed open one only when the change requires it. " +
|
|
389
382
|
"Never open a new pull request in a repository that already has an open pull request listed here. Merged or " +
|
|
390
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
|
+
}
|
|
391
404
|
/**
|
|
392
405
|
* The group's pull requests a follow-up may continue: stored state "open", or
|
|
393
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;
|