@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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory ChatProvider for tests: records every post/update, serves
|
|
3
|
+
* `channelInfo` from a settable map, and lets a test queue one error per
|
|
4
|
+
* method to be thrown on its next call.
|
|
5
|
+
*/
|
|
6
|
+
import type { ChatError, ChatMessage, ChatProvider } from "./types.js";
|
|
7
|
+
export declare class FakeChatProvider implements ChatProvider {
|
|
8
|
+
readonly name: "slack";
|
|
9
|
+
readonly posts: Array<{
|
|
10
|
+
channelId: string;
|
|
11
|
+
ts: string;
|
|
12
|
+
msg: ChatMessage;
|
|
13
|
+
threadTs?: string;
|
|
14
|
+
broadcast?: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
readonly updates: Array<{
|
|
17
|
+
channelId: string;
|
|
18
|
+
ts: string;
|
|
19
|
+
msg: ChatMessage;
|
|
20
|
+
}>;
|
|
21
|
+
readonly channels: Map<string, {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
isPrivate: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
private readonly queuedErrors;
|
|
27
|
+
private nextTs;
|
|
28
|
+
failNext(method: "postMessage" | "updateMessage" | "channelInfo" | "authTest", err: ChatError): void;
|
|
29
|
+
private consumeFailure;
|
|
30
|
+
postMessage(channelId: string, msg: ChatMessage, opts?: {
|
|
31
|
+
threadTs?: string;
|
|
32
|
+
broadcast?: boolean;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
ts: string;
|
|
35
|
+
}>;
|
|
36
|
+
updateMessage(channelId: string, ts: string, msg: ChatMessage): Promise<void>;
|
|
37
|
+
channelInfo(channel: string): Promise<{
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
isPrivate: boolean;
|
|
41
|
+
} | null>;
|
|
42
|
+
authTest(): Promise<{
|
|
43
|
+
team: string;
|
|
44
|
+
botUserId: string;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export class FakeChatProvider {
|
|
2
|
+
name = "slack";
|
|
3
|
+
posts = [];
|
|
4
|
+
updates = [];
|
|
5
|
+
channels = new Map();
|
|
6
|
+
queuedErrors = {
|
|
7
|
+
postMessage: [],
|
|
8
|
+
updateMessage: [],
|
|
9
|
+
channelInfo: [],
|
|
10
|
+
authTest: [],
|
|
11
|
+
};
|
|
12
|
+
nextTs = 1;
|
|
13
|
+
failNext(method, err) {
|
|
14
|
+
this.queuedErrors[method].push(err);
|
|
15
|
+
}
|
|
16
|
+
consumeFailure(method) {
|
|
17
|
+
const err = this.queuedErrors[method].shift();
|
|
18
|
+
if (err)
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
async postMessage(channelId, msg, opts = {}) {
|
|
22
|
+
this.consumeFailure("postMessage");
|
|
23
|
+
const ts = `${this.nextTs++}.000`;
|
|
24
|
+
this.posts.push({ channelId, ts, msg, threadTs: opts.threadTs, broadcast: opts.broadcast });
|
|
25
|
+
return { ts };
|
|
26
|
+
}
|
|
27
|
+
async updateMessage(channelId, ts, msg) {
|
|
28
|
+
this.consumeFailure("updateMessage");
|
|
29
|
+
this.updates.push({ channelId, ts, msg });
|
|
30
|
+
}
|
|
31
|
+
async channelInfo(channel) {
|
|
32
|
+
this.consumeFailure("channelInfo");
|
|
33
|
+
return this.channels.get(channel) ?? null;
|
|
34
|
+
}
|
|
35
|
+
async authTest() {
|
|
36
|
+
this.consumeFailure("authTest");
|
|
37
|
+
return { team: "fake", botUserId: "UFAKE" };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChatProviderRegistry } from "./types.js";
|
|
2
|
+
export * from "./types.js";
|
|
3
|
+
/** One provider per configured chat service; empty when Slack is not configured. */
|
|
4
|
+
export declare function buildChatProviders(env?: NodeJS.ProcessEnv, fetchImpl?: typeof fetch): ChatProviderRegistry;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { loadSlackConfig } from "../../config/providers.js";
|
|
2
|
+
import { SlackChatProvider } from "./slack.js";
|
|
3
|
+
export * from "./types.js";
|
|
4
|
+
/** One provider per configured chat service; empty when Slack is not configured. */
|
|
5
|
+
export function buildChatProviders(env = process.env, fetchImpl) {
|
|
6
|
+
const slack = loadSlackConfig(env);
|
|
7
|
+
return slack ? { slack: new SlackChatProvider(slack, fetchImpl) } : {};
|
|
8
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack Web API client for workflow notifications: chat.postMessage,
|
|
3
|
+
* chat.update, conversations.info, auth.test. Plain fetch (JSON bodies for
|
|
4
|
+
* writes, form-encoded for reads), bot token. Every failure becomes a ChatError with a normalized code the
|
|
5
|
+
* dispatcher acts on; Slack's own error string is kept for the operator.
|
|
6
|
+
*/
|
|
7
|
+
import type { SlackConfig } from "../../config/providers.js";
|
|
8
|
+
import { type ChatMessage, type ChatProvider } from "./types.js";
|
|
9
|
+
export declare class SlackChatProvider implements ChatProvider {
|
|
10
|
+
private readonly config;
|
|
11
|
+
private readonly fetchImpl;
|
|
12
|
+
readonly name: "slack";
|
|
13
|
+
constructor(config: SlackConfig, fetchImpl?: typeof fetch);
|
|
14
|
+
/**
|
|
15
|
+
* `form` for read methods (conversations.info, auth.test): Slack accepts JSON
|
|
16
|
+
* bodies only on write methods and answers a read method's JSON body with
|
|
17
|
+
* invalid_arguments.
|
|
18
|
+
*/
|
|
19
|
+
private call;
|
|
20
|
+
private messageBody;
|
|
21
|
+
postMessage(channelId: string, msg: ChatMessage, opts?: {
|
|
22
|
+
threadTs?: string;
|
|
23
|
+
broadcast?: boolean;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
ts: string;
|
|
26
|
+
}>;
|
|
27
|
+
updateMessage(channelId: string, ts: string, msg: ChatMessage): Promise<void>;
|
|
28
|
+
channelInfo(channel: string): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
isPrivate: boolean;
|
|
32
|
+
} | null>;
|
|
33
|
+
authTest(): Promise<{
|
|
34
|
+
team: string;
|
|
35
|
+
botUserId: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ChatError } from "./types.js";
|
|
2
|
+
const CHANNEL_UNREACHABLE = new Set(["channel_not_found", "not_in_channel", "is_archived"]);
|
|
3
|
+
const AUTH_FAILED = new Set([
|
|
4
|
+
"invalid_auth",
|
|
5
|
+
"not_authed",
|
|
6
|
+
"token_revoked",
|
|
7
|
+
"token_expired",
|
|
8
|
+
"account_inactive",
|
|
9
|
+
"missing_scope",
|
|
10
|
+
]);
|
|
11
|
+
const TIMEOUT_MS = 10_000;
|
|
12
|
+
function classify(slackError) {
|
|
13
|
+
if (CHANNEL_UNREACHABLE.has(slackError))
|
|
14
|
+
return "channel_unreachable";
|
|
15
|
+
if (AUTH_FAILED.has(slackError))
|
|
16
|
+
return "auth_failed";
|
|
17
|
+
if (slackError === "message_not_found")
|
|
18
|
+
return "message_not_found";
|
|
19
|
+
if (slackError === "ratelimited")
|
|
20
|
+
return "rate_limited";
|
|
21
|
+
return "transient";
|
|
22
|
+
}
|
|
23
|
+
export class SlackChatProvider {
|
|
24
|
+
config;
|
|
25
|
+
fetchImpl;
|
|
26
|
+
name = "slack";
|
|
27
|
+
constructor(config, fetchImpl = fetch) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.fetchImpl = fetchImpl;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `form` for read methods (conversations.info, auth.test): Slack accepts JSON
|
|
33
|
+
* bodies only on write methods and answers a read method's JSON body with
|
|
34
|
+
* invalid_arguments.
|
|
35
|
+
*/
|
|
36
|
+
async call(method, body, encoding = "json") {
|
|
37
|
+
let res;
|
|
38
|
+
try {
|
|
39
|
+
res = await this.fetchImpl(`${this.config.apiBaseUrl}/${method}`, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: {
|
|
42
|
+
authorization: `Bearer ${this.config.botToken}`,
|
|
43
|
+
"content-type": encoding === "json" ? "application/json; charset=utf-8" : "application/x-www-form-urlencoded",
|
|
44
|
+
},
|
|
45
|
+
body: encoding === "json"
|
|
46
|
+
? JSON.stringify(body)
|
|
47
|
+
: new URLSearchParams(Object.fromEntries(Object.entries(body).map(([k, v]) => [k, String(v)]))).toString(),
|
|
48
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
throw new ChatError("transient", err instanceof Error ? err.message : String(err));
|
|
53
|
+
}
|
|
54
|
+
if (res.status === 429) {
|
|
55
|
+
const seconds = Number(res.headers.get("retry-after") ?? "1");
|
|
56
|
+
throw new ChatError("rate_limited", "ratelimited", (Number.isFinite(seconds) && seconds > 0 ? seconds : 1) * 1000);
|
|
57
|
+
}
|
|
58
|
+
if (!res.ok)
|
|
59
|
+
throw new ChatError("transient", `http_${res.status}`);
|
|
60
|
+
const json = (await res.json().catch(() => ({ ok: false, error: "invalid_json" })));
|
|
61
|
+
if (json.ok !== true) {
|
|
62
|
+
const slackError = typeof json.error === "string" ? json.error : "unknown_error";
|
|
63
|
+
throw new ChatError(classify(slackError), slackError);
|
|
64
|
+
}
|
|
65
|
+
return json;
|
|
66
|
+
}
|
|
67
|
+
messageBody(msg) {
|
|
68
|
+
return {
|
|
69
|
+
text: msg.text,
|
|
70
|
+
...(msg.blocks ? { blocks: msg.blocks } : {}),
|
|
71
|
+
...(this.config.customize && msg.username ? { username: msg.username } : {}),
|
|
72
|
+
...(this.config.customize && msg.iconEmoji ? { icon_emoji: msg.iconEmoji } : {}),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async postMessage(channelId, msg, opts = {}) {
|
|
76
|
+
const json = await this.call("chat.postMessage", {
|
|
77
|
+
channel: channelId,
|
|
78
|
+
...this.messageBody(msg),
|
|
79
|
+
...(opts.threadTs ? { thread_ts: opts.threadTs } : {}),
|
|
80
|
+
...(opts.threadTs && opts.broadcast ? { reply_broadcast: true } : {}),
|
|
81
|
+
unfurl_links: false,
|
|
82
|
+
unfurl_media: false,
|
|
83
|
+
});
|
|
84
|
+
return { ts: String(json.ts) };
|
|
85
|
+
}
|
|
86
|
+
async updateMessage(channelId, ts, msg) {
|
|
87
|
+
await this.call("chat.update", { channel: channelId, ts, ...this.messageBody(msg) });
|
|
88
|
+
}
|
|
89
|
+
async channelInfo(channel) {
|
|
90
|
+
try {
|
|
91
|
+
const json = await this.call("conversations.info", { channel }, "form");
|
|
92
|
+
const c = json.channel;
|
|
93
|
+
return { id: c.id, name: c.name, isPrivate: c.is_private === true };
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err instanceof ChatError && err.code === "channel_unreachable")
|
|
97
|
+
return null;
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async authTest() {
|
|
102
|
+
const json = await this.call("auth.test", {}, "form");
|
|
103
|
+
return { team: String(json.team), botUserId: String(json.user_id) };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-neutral chat surface for outbound workflow notifications. Slack is
|
|
3
|
+
* the first (and only) implementation (./slack.ts). wardby only ever posts
|
|
4
|
+
* or updates messages here — it never reads channel history or listens for
|
|
5
|
+
* events.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHAT_PROVIDERS: readonly ["slack"];
|
|
8
|
+
export type ChatProviderName = (typeof CHAT_PROVIDERS)[number];
|
|
9
|
+
export type ChatErrorCode = "rate_limited" | "channel_unreachable" | "auth_failed" | "message_not_found" | "transient";
|
|
10
|
+
export declare class ChatError extends Error {
|
|
11
|
+
readonly code: ChatErrorCode;
|
|
12
|
+
readonly slackError: string;
|
|
13
|
+
readonly retryAfterMs?: number | undefined;
|
|
14
|
+
constructor(code: ChatErrorCode, slackError: string, retryAfterMs?: number | undefined);
|
|
15
|
+
}
|
|
16
|
+
export interface ChatMessage {
|
|
17
|
+
text: string;
|
|
18
|
+
blocks?: unknown[];
|
|
19
|
+
username?: string;
|
|
20
|
+
iconEmoji?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ChatProvider {
|
|
23
|
+
readonly name: ChatProviderName;
|
|
24
|
+
postMessage(channelId: string, msg: ChatMessage, opts?: {
|
|
25
|
+
threadTs?: string;
|
|
26
|
+
broadcast?: boolean;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
ts: string;
|
|
29
|
+
}>;
|
|
30
|
+
updateMessage(channelId: string, ts: string, msg: ChatMessage): Promise<void>;
|
|
31
|
+
/** null when the bot cannot see the channel; throws ChatError("auth_failed") on missing scope. */
|
|
32
|
+
channelInfo(channel: string): Promise<{
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
isPrivate: boolean;
|
|
36
|
+
} | null>;
|
|
37
|
+
authTest(): Promise<{
|
|
38
|
+
team: string;
|
|
39
|
+
botUserId: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
export type ChatProviderRegistry = Partial<Record<ChatProviderName, ChatProvider>>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-neutral chat surface for outbound workflow notifications. Slack is
|
|
3
|
+
* the first (and only) implementation (./slack.ts). wardby only ever posts
|
|
4
|
+
* or updates messages here — it never reads channel history or listens for
|
|
5
|
+
* events.
|
|
6
|
+
*/
|
|
7
|
+
export const CHAT_PROVIDERS = ["slack"];
|
|
8
|
+
export class ChatError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
slackError;
|
|
11
|
+
retryAfterMs;
|
|
12
|
+
constructor(code, slackError, retryAfterMs) {
|
|
13
|
+
super(`chat_error:${code}:${slackError}`);
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.slackError = slackError;
|
|
16
|
+
this.retryAfterMs = retryAfterMs;
|
|
17
|
+
this.name = "ChatError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { BlobStore } from "../../storage/types.js";
|
|
2
|
+
import type { DependencyCacheStore, EvictionRow } from "./store.js";
|
|
3
|
+
/** How often the proxy runs an eviction pass. */
|
|
4
|
+
export declare const DEFAULT_EVICTION_INTERVAL_MS: number;
|
|
5
|
+
export interface EvictionLimits {
|
|
6
|
+
maxAgeMs: number;
|
|
7
|
+
repoCapBytes: number;
|
|
8
|
+
totalCapBytes: number;
|
|
9
|
+
}
|
|
10
|
+
/** The snapshots to evict, in the order to evict them. */
|
|
11
|
+
export declare function selectEvictions(rows: readonly EvictionRow[], limits: EvictionLimits, now: Date): EvictionRow[];
|
|
12
|
+
export interface EvictionOptions {
|
|
13
|
+
store: DependencyCacheStore;
|
|
14
|
+
blobs: Pick<BlobStore, "delete">;
|
|
15
|
+
limits: EvictionLimits;
|
|
16
|
+
now?: () => Date;
|
|
17
|
+
}
|
|
18
|
+
/** One eviction pass; `ran` is false when another holder had the lock. */
|
|
19
|
+
export declare function runEviction(options: EvictionOptions): Promise<{
|
|
20
|
+
ran: boolean;
|
|
21
|
+
deleted: number;
|
|
22
|
+
failed: number;
|
|
23
|
+
}>;
|
|
24
|
+
/** Runs an eviction pass every `intervalMs` (the first one interval after start). */
|
|
25
|
+
export declare function startEviction(options: EvictionOptions & {
|
|
26
|
+
intervalMs?: number;
|
|
27
|
+
}): {
|
|
28
|
+
stop(): void;
|
|
29
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency cache eviction: a periodic pass inside the proxy, coordinated
|
|
3
|
+
* across replicas by a Postgres advisory lock (the store's
|
|
4
|
+
* withEvictionLock). It removes snapshots past the maximum age (by creation,
|
|
5
|
+
* so every snapshot is rebuilt at least that often), then the least recently
|
|
6
|
+
* used beyond each repository's cap, then beyond the total cap. A blob is
|
|
7
|
+
* deleted before its row, so a failed blob delete leaves the row for the next
|
|
8
|
+
* pass to retry rather than an orphaned blob.
|
|
9
|
+
*/
|
|
10
|
+
import { logger } from "../../../core/logger.js";
|
|
11
|
+
const evictionLog = logger.child({ module: "dependency-cache" });
|
|
12
|
+
/** How often the proxy runs an eviction pass. */
|
|
13
|
+
export const DEFAULT_EVICTION_INTERVAL_MS = 60 * 60_000;
|
|
14
|
+
const leastRecentlyUsed = (a, b) => a.lastUsedAt.getTime() - b.lastUsedAt.getTime() || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
15
|
+
/** The snapshots to evict, in the order to evict them. */
|
|
16
|
+
export function selectEvictions(rows, limits, now) {
|
|
17
|
+
const cutoff = now.getTime() - limits.maxAgeMs;
|
|
18
|
+
const evicted = rows
|
|
19
|
+
.filter((row) => row.createdAt.getTime() <= cutoff)
|
|
20
|
+
.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || leastRecentlyUsed(a, b));
|
|
21
|
+
let kept = rows.filter((row) => row.createdAt.getTime() > cutoff);
|
|
22
|
+
const byRepository = new Map();
|
|
23
|
+
for (const row of kept)
|
|
24
|
+
byRepository.set(row.repository, [...(byRepository.get(row.repository) ?? []), row]);
|
|
25
|
+
const overRepoCap = new Set();
|
|
26
|
+
for (const repoRows of byRepository.values()) {
|
|
27
|
+
let total = repoRows.reduce((sum, row) => sum + row.sizeBytes, 0);
|
|
28
|
+
for (const row of [...repoRows].sort(leastRecentlyUsed)) {
|
|
29
|
+
if (total <= limits.repoCapBytes)
|
|
30
|
+
break;
|
|
31
|
+
evicted.push(row);
|
|
32
|
+
overRepoCap.add(row.id);
|
|
33
|
+
total -= row.sizeBytes;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
kept = kept.filter((row) => !overRepoCap.has(row.id));
|
|
37
|
+
let total = kept.reduce((sum, row) => sum + row.sizeBytes, 0);
|
|
38
|
+
for (const row of [...kept].sort(leastRecentlyUsed)) {
|
|
39
|
+
if (total <= limits.totalCapBytes)
|
|
40
|
+
break;
|
|
41
|
+
evicted.push(row);
|
|
42
|
+
total -= row.sizeBytes;
|
|
43
|
+
}
|
|
44
|
+
return evicted;
|
|
45
|
+
}
|
|
46
|
+
/** One eviction pass; `ran` is false when another holder had the lock. */
|
|
47
|
+
export async function runEviction(options) {
|
|
48
|
+
const result = { ran: false, deleted: 0, failed: 0 };
|
|
49
|
+
result.ran = await options.store.withEvictionLock(async () => {
|
|
50
|
+
const rows = await options.store.listForEviction();
|
|
51
|
+
for (const row of selectEvictions(rows, options.limits, (options.now ?? (() => new Date()))())) {
|
|
52
|
+
try {
|
|
53
|
+
await options.blobs.delete(row.blobKey);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
result.failed += 1;
|
|
57
|
+
evictionLog.warn({ event: "dependency_cache.evict_blob_failed", snapshotId: row.id, err: error }, "dependency cache: a snapshot's blob could not be deleted; the next pass retries");
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
await options.store.delete(row.id);
|
|
61
|
+
result.deleted += 1;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
/** Runs an eviction pass every `intervalMs` (the first one interval after start). */
|
|
67
|
+
export function startEviction(options) {
|
|
68
|
+
let running = false;
|
|
69
|
+
const timer = setInterval(() => {
|
|
70
|
+
if (running)
|
|
71
|
+
return;
|
|
72
|
+
running = true;
|
|
73
|
+
runEviction(options)
|
|
74
|
+
.then((result) => {
|
|
75
|
+
if (result.deleted > 0 || result.failed > 0)
|
|
76
|
+
evictionLog.info({ event: "dependency_cache.evicted", deleted: result.deleted, failed: result.failed }, "dependency cache eviction pass");
|
|
77
|
+
})
|
|
78
|
+
.catch((error) => {
|
|
79
|
+
evictionLog.warn({ event: "dependency_cache.evict_failed", err: error }, "dependency cache eviction failed");
|
|
80
|
+
})
|
|
81
|
+
.finally(() => {
|
|
82
|
+
running = false;
|
|
83
|
+
});
|
|
84
|
+
}, options.intervalMs ?? DEFAULT_EVICTION_INTERVAL_MS);
|
|
85
|
+
timer.unref();
|
|
86
|
+
return { stop: () => clearInterval(timer) };
|
|
87
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** The only ecosystem the cache serves today. */
|
|
2
|
+
export declare const DEPENDENCY_CACHE_ECOSYSTEM = "npm";
|
|
3
|
+
/** Lockfile hashes one session may hold (plans beyond this are not recorded). */
|
|
4
|
+
export declare const MAX_DEPENDENCY_CACHE_LOCK_HASHES = 8;
|
|
5
|
+
export declare function sha256Hex(data: string | Uint8Array): string;
|
|
6
|
+
/** JSON with object keys sorted, so equal values always serialize alike. */
|
|
7
|
+
export declare function canonicalJson(value: unknown): string;
|
|
8
|
+
export declare function isLockHash(value: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The project folder relative to the repository root, or null when it is not
|
|
11
|
+
* acceptable: "." (or absent) is the root; otherwise 1-3 plain segments, none
|
|
12
|
+
* empty, none starting with a dot, none named node_modules.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseProjectPath(raw: string | null | undefined): string | null;
|
|
15
|
+
export interface SnapshotKeyParts {
|
|
16
|
+
repository: string;
|
|
17
|
+
projectPath: string;
|
|
18
|
+
lockHash: string;
|
|
19
|
+
workerImage: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SnapshotKey extends SnapshotKeyParts {
|
|
22
|
+
ecosystem: string;
|
|
23
|
+
/** The opaque id a worker downloads the derived key by: sha256 of the canonical identity tuple. */
|
|
24
|
+
keyId: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function deriveSnapshotKey(parts: SnapshotKeyParts): SnapshotKey;
|
|
27
|
+
/**
|
|
28
|
+
* A fresh blob key for one upload of `key`. Each upload writes its own object
|
|
29
|
+
* (the random suffix), so a concurrent or refused upload can never replace
|
|
30
|
+
* the bytes of a snapshot already committed; a row always names the exact
|
|
31
|
+
* object its sha256 and size describe.
|
|
32
|
+
*/
|
|
33
|
+
export declare function newBlobKey(key: SnapshotKey): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency cache keys, derived only on the proxy. A worker names nothing
|
|
3
|
+
* in a key except its project folder (validated here); the lock hash comes
|
|
4
|
+
* from a lockfile plan the proxy approved, and the repository and image come
|
|
5
|
+
* from the run's own records.
|
|
6
|
+
*
|
|
7
|
+
* The agent's package policy is not part of a key. A snapshot's contents
|
|
8
|
+
* depend only on the lockfile and the image (`npm ci --ignore-scripts`
|
|
9
|
+
* installs exactly the lockfile's integrity-checked packages), and every
|
|
10
|
+
* restore already requires the proxy to have approved this run's lockfile
|
|
11
|
+
* under the restoring agent's current policy (the plan gate,
|
|
12
|
+
* `dependencyCacheLockHashes`). So a snapshot built under another policy, or
|
|
13
|
+
* by another agent on the same repository, restores only when today's policy
|
|
14
|
+
* approves the same lockfile.
|
|
15
|
+
*/
|
|
16
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
17
|
+
/** The only ecosystem the cache serves today. */
|
|
18
|
+
export const DEPENDENCY_CACHE_ECOSYSTEM = "npm";
|
|
19
|
+
/** Lockfile hashes one session may hold (plans beyond this are not recorded). */
|
|
20
|
+
export const MAX_DEPENDENCY_CACHE_LOCK_HASHES = 8;
|
|
21
|
+
const LOCK_HASH = /^[0-9a-f]{64}$/;
|
|
22
|
+
/** A project-path segment: no leading dot (no `.`, `..` or dot-folder), no
|
|
23
|
+
* separators, whitespace or control characters. */
|
|
24
|
+
const PROJECT_SEGMENT = /^[A-Za-z0-9_@+-][A-Za-z0-9._@+-]{0,99}$/;
|
|
25
|
+
const MAX_PROJECT_SEGMENTS = 3;
|
|
26
|
+
export function sha256Hex(data) {
|
|
27
|
+
return createHash("sha256").update(data).digest("hex");
|
|
28
|
+
}
|
|
29
|
+
function canonical(value) {
|
|
30
|
+
if (Array.isArray(value))
|
|
31
|
+
return value.map((item) => (item === undefined ? null : canonical(item)));
|
|
32
|
+
if (value !== null && typeof value === "object") {
|
|
33
|
+
const record = value;
|
|
34
|
+
// Code-unit order (the default sort), never locale order: the hash must
|
|
35
|
+
// be the same on every host.
|
|
36
|
+
return Object.fromEntries(Object.keys(record)
|
|
37
|
+
.filter((key) => record[key] !== undefined)
|
|
38
|
+
.sort()
|
|
39
|
+
.map((key) => [key, canonical(record[key])]));
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/** JSON with object keys sorted, so equal values always serialize alike. */
|
|
44
|
+
export function canonicalJson(value) {
|
|
45
|
+
return JSON.stringify(canonical(value)) ?? "null";
|
|
46
|
+
}
|
|
47
|
+
export function isLockHash(value) {
|
|
48
|
+
return LOCK_HASH.test(value);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The project folder relative to the repository root, or null when it is not
|
|
52
|
+
* acceptable: "." (or absent) is the root; otherwise 1-3 plain segments, none
|
|
53
|
+
* empty, none starting with a dot, none named node_modules.
|
|
54
|
+
*/
|
|
55
|
+
export function parseProjectPath(raw) {
|
|
56
|
+
if (raw === undefined || raw === null || raw === ".")
|
|
57
|
+
return ".";
|
|
58
|
+
const segments = raw.split("/");
|
|
59
|
+
if (segments.length > MAX_PROJECT_SEGMENTS)
|
|
60
|
+
return null;
|
|
61
|
+
for (const segment of segments) {
|
|
62
|
+
if (!PROJECT_SEGMENT.test(segment) || segment === "node_modules")
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return raw;
|
|
66
|
+
}
|
|
67
|
+
export function deriveSnapshotKey(parts) {
|
|
68
|
+
const identity = {
|
|
69
|
+
ecosystem: DEPENDENCY_CACHE_ECOSYSTEM,
|
|
70
|
+
repository: parts.repository,
|
|
71
|
+
projectPath: parts.projectPath,
|
|
72
|
+
lockHash: parts.lockHash,
|
|
73
|
+
workerImage: parts.workerImage,
|
|
74
|
+
};
|
|
75
|
+
return { ...identity, keyId: sha256Hex(canonicalJson(identity)) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A fresh blob key for one upload of `key`. Each upload writes its own object
|
|
79
|
+
* (the random suffix), so a concurrent or refused upload can never replace
|
|
80
|
+
* the bytes of a snapshot already committed; a row always names the exact
|
|
81
|
+
* object its sha256 and size describe.
|
|
82
|
+
*/
|
|
83
|
+
export function newBlobKey(key) {
|
|
84
|
+
return (`dependency-cache/${key.ecosystem}/${sha256Hex(key.repository)}/${sha256Hex(key.projectPath).slice(0, 16)}/` +
|
|
85
|
+
`${key.lockHash}-${sha256Hex(key.workerImage).slice(0, 16)}-${randomUUID()}.tgz`);
|
|
86
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DependencyCacheStore } from "./store.js";
|
|
2
|
+
/**
|
|
3
|
+
* Seals a run's dependency-cache session on its first model request: the agent exists from that
|
|
4
|
+
* request on, so the cache's pre-agent phase is over whatever the worker did (or failed to do).
|
|
5
|
+
* The workers run the cache before they create the agent (Codex: driver.ts runs it before
|
|
6
|
+
* startThread; Claude Code: driver.ts calls the prepare tool before createQuery), so no model
|
|
7
|
+
* request precedes it. The seal is idempotent and conditional (only an unsealed session of a run
|
|
8
|
+
* with the cache on), remembered per run in this process so it costs one write per run per proxy
|
|
9
|
+
* replica, and never fails the model request: a database error is logged and retried on the
|
|
10
|
+
* run's next request.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ModelRequestSeal {
|
|
13
|
+
private readonly store;
|
|
14
|
+
private readonly now;
|
|
15
|
+
private readonly sealed;
|
|
16
|
+
constructor(store: Pick<DependencyCacheStore, "sealForModelRequest">, now?: () => Date);
|
|
17
|
+
onModelRequest(runId: string): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { logger } from "../../../core/logger.js";
|
|
2
|
+
const sealLog = logger.child({ module: "dependency-cache" });
|
|
3
|
+
/** Runs remembered as sealed per proxy process; the oldest are forgotten past this (a re-seal is a no-op write). */
|
|
4
|
+
const MAX_REMEMBERED_RUNS = 10_000;
|
|
5
|
+
/**
|
|
6
|
+
* Seals a run's dependency-cache session on its first model request: the agent exists from that
|
|
7
|
+
* request on, so the cache's pre-agent phase is over whatever the worker did (or failed to do).
|
|
8
|
+
* The workers run the cache before they create the agent (Codex: driver.ts runs it before
|
|
9
|
+
* startThread; Claude Code: driver.ts calls the prepare tool before createQuery), so no model
|
|
10
|
+
* request precedes it. The seal is idempotent and conditional (only an unsealed session of a run
|
|
11
|
+
* with the cache on), remembered per run in this process so it costs one write per run per proxy
|
|
12
|
+
* replica, and never fails the model request: a database error is logged and retried on the
|
|
13
|
+
* run's next request.
|
|
14
|
+
*/
|
|
15
|
+
export class ModelRequestSeal {
|
|
16
|
+
store;
|
|
17
|
+
now;
|
|
18
|
+
sealed = new Set();
|
|
19
|
+
constructor(store, now = () => new Date()) {
|
|
20
|
+
this.store = store;
|
|
21
|
+
this.now = now;
|
|
22
|
+
}
|
|
23
|
+
async onModelRequest(runId) {
|
|
24
|
+
if (this.sealed.has(runId))
|
|
25
|
+
return;
|
|
26
|
+
try {
|
|
27
|
+
await this.store.sealForModelRequest(runId, this.now());
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
sealLog.warn({ event: "dependency_cache.model_seal_failed", runId, err: error }, "dependency cache: seal on the run's model request failed");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.sealed.add(runId);
|
|
34
|
+
if (this.sealed.size > MAX_REMEMBERED_RUNS) {
|
|
35
|
+
const oldest = this.sealed.values().next().value;
|
|
36
|
+
if (oldest !== undefined)
|
|
37
|
+
this.sealed.delete(oldest);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type PrismaClient } from "#prisma";
|
|
2
|
+
import type { DependencyCacheSessionState } from "../registry/store.js";
|
|
3
|
+
import { type DependencyCacheStore, type EvictionRow, type NewSnapshot, type SnapshotIdentity, type SnapshotRow, type SnapshotScope } from "./store.js";
|
|
4
|
+
export declare class PrismaDependencyCacheStore implements DependencyCacheStore {
|
|
5
|
+
private readonly db;
|
|
6
|
+
constructor(db: PrismaClient);
|
|
7
|
+
session(runId: string): Promise<DependencyCacheSessionState | null>;
|
|
8
|
+
seal(runId: string, now: Date): Promise<void>;
|
|
9
|
+
sealForModelRequest(runId: string, now: Date): Promise<void>;
|
|
10
|
+
findByIdentity(identity: SnapshotIdentity): Promise<SnapshotRow | null>;
|
|
11
|
+
findNearest(scope: SnapshotScope, excludeLockHash: string): Promise<SnapshotRow | null>;
|
|
12
|
+
hasUploaded(runId: string, ecosystem: string, projectPath: string): Promise<boolean>;
|
|
13
|
+
insert(snapshot: NewSnapshot): Promise<"inserted" | "exists">;
|
|
14
|
+
touch(id: string, now: Date): Promise<void>;
|
|
15
|
+
delete(id: string): Promise<void>;
|
|
16
|
+
deleteIfBlob(id: string, blobKey: string): Promise<boolean>;
|
|
17
|
+
listForEviction(): Promise<EvictionRow[]>;
|
|
18
|
+
/**
|
|
19
|
+
* A transaction-scoped advisory lock: Postgres releases it when the
|
|
20
|
+
* transaction ends, so a crashed proxy never leaves it held. The work runs
|
|
21
|
+
* on the ordinary client (each delete commits at once); the transaction
|
|
22
|
+
* only holds the lock.
|
|
23
|
+
*/
|
|
24
|
+
withEvictionLock(work: () => Promise<void>): Promise<boolean>;
|
|
25
|
+
}
|