@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
|
@@ -2,7 +2,9 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { shippedCatalog } from "../llm/catalog.js";
|
|
3
3
|
import { SHIPPED_CATALOG_VERSION } from "../llm/catalog-shipped.js";
|
|
4
4
|
import { deriveRegistryToken } from "../../coding/registry/token.js";
|
|
5
|
-
import { AnthropicSseUsageTracker, actualCostUsd,
|
|
5
|
+
import { AnthropicSseUsageTracker, actualCostUsd, fingerprintRequest, parseAnthropicAuthoritativeUsage, parseAuthoritativeUsage, pricingSnapshot, safeUpstreamErrorCode, terminalUsageFromSseFrame, } from "./metering.js";
|
|
6
|
+
import { conversationKey, estimateHold } from "./hold.js";
|
|
7
|
+
import { estimateInterrupted, previousInput } from "./interrupted.js";
|
|
6
8
|
import { createPinnedProxyFetch } from "./secure-fetch.js";
|
|
7
9
|
export const PROXY_MAX_BODY_BYTES = 8 * 1024 * 1024;
|
|
8
10
|
export const PROXY_MAX_OUTPUT_TOKENS = 1_000_000;
|
|
@@ -818,8 +820,10 @@ export class CodingProxy {
|
|
|
818
820
|
getPricing;
|
|
819
821
|
priceVersion;
|
|
820
822
|
activeRequests = new Map();
|
|
823
|
+
onModelRequest;
|
|
821
824
|
constructor(options) {
|
|
822
825
|
this.ledger = options.ledger;
|
|
826
|
+
this.onModelRequest = options.onModelRequest;
|
|
823
827
|
this.credentials = options.credentials;
|
|
824
828
|
this.upstreamUrls = {
|
|
825
829
|
"openai-responses": options.upstreamUrl ?? "https://api.openai.com/v1/responses",
|
|
@@ -905,12 +909,19 @@ export class CodingProxy {
|
|
|
905
909
|
budgetExhausted(sessionId) {
|
|
906
910
|
return this.ledger.budgetExhausted(sessionId);
|
|
907
911
|
}
|
|
912
|
+
/** The numbers behind this session's first budget refusal, if any. */
|
|
913
|
+
budgetRefusal(sessionId) {
|
|
914
|
+
return this.ledger.budgetRefusal(sessionId);
|
|
915
|
+
}
|
|
908
916
|
/** The code of the first upstream failure relayed for this session's run, if any. */
|
|
909
917
|
upstreamFailure(sessionId) {
|
|
910
918
|
return this.ledger.upstreamFailure(sessionId);
|
|
911
919
|
}
|
|
912
920
|
async execute(input, sink) {
|
|
913
921
|
const session = await this.authenticate(input.bearer);
|
|
922
|
+
// The run's agent exists from its first model request on (both protocols arrive here).
|
|
923
|
+
if (this.onModelRequest)
|
|
924
|
+
await this.onModelRequest(session.runId).catch(() => undefined);
|
|
914
925
|
if (session.protocol !== input.protocol) {
|
|
915
926
|
this.audit({ type: "request.rejected", runId: session.runId, reason: "protocol_mismatch" });
|
|
916
927
|
throw new CodingProxyError(403, "protocol_mismatch");
|
|
@@ -948,7 +959,32 @@ export class CodingProxy {
|
|
|
948
959
|
}
|
|
949
960
|
const requestKey = safeRequestKey(input.requestKey, parsed.fingerprint);
|
|
950
961
|
const snapshot = pricingSnapshot(terms.version, terms.pricing);
|
|
951
|
-
const
|
|
962
|
+
const bodyBytes = Buffer.byteLength(parsed.encoded);
|
|
963
|
+
const conversation = conversationKey(session.protocol, parsed.body);
|
|
964
|
+
// A failed lookup holds the ceiling: never a reason to fail the request.
|
|
965
|
+
const previous = conversation ? await this.ledger.previousReply(session.id, conversation).catch(() => null) : null;
|
|
966
|
+
const holdNow = this.now();
|
|
967
|
+
const hold = estimateHold({
|
|
968
|
+
protocol: session.protocol,
|
|
969
|
+
model: parsed.model,
|
|
970
|
+
bodyBytes,
|
|
971
|
+
maxOutputTokens: parsed.maxOutputTokens,
|
|
972
|
+
pricing: snapshot,
|
|
973
|
+
previous,
|
|
974
|
+
now: holdNow,
|
|
975
|
+
});
|
|
976
|
+
// An interrupted reply's input, from the same previous reply and clock as the hold.
|
|
977
|
+
const previousPrompt = previousInput({ model: parsed.model, bodyBytes, previous, pricing: snapshot, now: holdNow });
|
|
978
|
+
const reservationUsd = hold.holdUsd;
|
|
979
|
+
const holdAudit = {
|
|
980
|
+
reservationUsd,
|
|
981
|
+
ceilingUsd: hold.ceilingUsd,
|
|
982
|
+
reservationBasis: hold.basis,
|
|
983
|
+
...(hold.fallback ? { holdFallback: hold.fallback } : {}),
|
|
984
|
+
...(hold.cachedTokens !== undefined
|
|
985
|
+
? { holdCachedTokens: hold.cachedTokens, holdUncachedTokens: hold.uncachedTokens }
|
|
986
|
+
: {}),
|
|
987
|
+
};
|
|
952
988
|
const reservation = await this.ledger.reserve({
|
|
953
989
|
id: randomUUID(),
|
|
954
990
|
sessionId: session.id,
|
|
@@ -956,6 +992,10 @@ export class CodingProxy {
|
|
|
956
992
|
requestFingerprint: parsed.fingerprint,
|
|
957
993
|
model: parsed.model,
|
|
958
994
|
reservationUsd,
|
|
995
|
+
requestBytes: bodyBytes,
|
|
996
|
+
ceilingUsd: hold.ceilingUsd,
|
|
997
|
+
reservationBasis: hold.basis,
|
|
998
|
+
conversationKey: conversation,
|
|
959
999
|
pricing: snapshot,
|
|
960
1000
|
now: this.now(),
|
|
961
1001
|
});
|
|
@@ -969,7 +1009,12 @@ export class CodingProxy {
|
|
|
969
1009
|
runId: session.runId,
|
|
970
1010
|
model: parsed.model,
|
|
971
1011
|
reason: "budget_exhausted",
|
|
972
|
-
|
|
1012
|
+
...holdAudit,
|
|
1013
|
+
budgetUsd: reservation.details.budgetUsd,
|
|
1014
|
+
spentUsd: reservation.details.spentUsd,
|
|
1015
|
+
heldReservedUsd: reservation.details.heldReservedUsd,
|
|
1016
|
+
heldUncertainUsd: reservation.details.heldUncertainUsd,
|
|
1017
|
+
turn: reservation.details.turn,
|
|
973
1018
|
});
|
|
974
1019
|
throw new CodingProxyError(429, "wardby_budget_exhausted");
|
|
975
1020
|
}
|
|
@@ -982,7 +1027,7 @@ export class CodingProxy {
|
|
|
982
1027
|
runId: session.runId,
|
|
983
1028
|
requestId: request.id,
|
|
984
1029
|
model: request.model,
|
|
985
|
-
|
|
1030
|
+
...holdAudit,
|
|
986
1031
|
});
|
|
987
1032
|
let key;
|
|
988
1033
|
try {
|
|
@@ -1010,6 +1055,13 @@ export class CodingProxy {
|
|
|
1010
1055
|
const deadlineTimer = setTimeout(() => controller.abort(), remainingMs);
|
|
1011
1056
|
deadlineTimer.unref();
|
|
1012
1057
|
this.trackActive(session.id, controller);
|
|
1058
|
+
const progress = {
|
|
1059
|
+
maxOutputTokens: parsed.maxOutputTokens,
|
|
1060
|
+
stream: parsed.stream,
|
|
1061
|
+
bodyBytes,
|
|
1062
|
+
...(previousPrompt ? { previousInput: previousPrompt } : {}),
|
|
1063
|
+
relayedOutputBytes: 0,
|
|
1064
|
+
};
|
|
1013
1065
|
const cleanupActive = () => {
|
|
1014
1066
|
clearTimeout(deadlineTimer);
|
|
1015
1067
|
const active = this.activeRequests.get(session.id);
|
|
@@ -1042,10 +1094,11 @@ export class CodingProxy {
|
|
|
1042
1094
|
redirect: "error",
|
|
1043
1095
|
signal: controller.signal,
|
|
1044
1096
|
});
|
|
1097
|
+
progress.responseStarted = true;
|
|
1045
1098
|
}
|
|
1046
1099
|
catch {
|
|
1047
1100
|
cleanupActive();
|
|
1048
|
-
await this.markUncertain(session, request, undefined, controller.signal.aborted ? "upstream_aborted" : "upstream_transport");
|
|
1101
|
+
await this.markUncertain(session, request, undefined, controller.signal.aborted ? "upstream_aborted" : "upstream_transport", {}, progress);
|
|
1049
1102
|
throw new CodingProxyError(502, controller.signal.aborted ? "upstream_aborted" : "upstream_transport_error");
|
|
1050
1103
|
}
|
|
1051
1104
|
if (!upstream.ok) {
|
|
@@ -1068,12 +1121,12 @@ export class CodingProxy {
|
|
|
1068
1121
|
}
|
|
1069
1122
|
try {
|
|
1070
1123
|
if (parsed.stream)
|
|
1071
|
-
await this.forwardStream(session, request, upstream, sink);
|
|
1124
|
+
await this.forwardStream(session, request, upstream, sink, progress);
|
|
1072
1125
|
else
|
|
1073
1126
|
await this.forwardJson(session, request, upstream, sink);
|
|
1074
1127
|
}
|
|
1075
1128
|
catch (error) {
|
|
1076
|
-
await this.markUncertain(session, request, upstream.status, failureReason(error), responseHeadersOf(upstream));
|
|
1129
|
+
await this.markUncertain(session, request, upstream.status, failureReason(error), responseHeadersOf(upstream), progress);
|
|
1077
1130
|
sink.destroy();
|
|
1078
1131
|
throw error instanceof CodingProxyError ? error : new CodingProxyError(502, "invalid_upstream_response");
|
|
1079
1132
|
}
|
|
@@ -1117,6 +1170,7 @@ export class CodingProxy {
|
|
|
1117
1170
|
async complete(session, request, usage, upstreamStatus) {
|
|
1118
1171
|
const costUsd = actualCostUsd(usage, request.pricing);
|
|
1119
1172
|
await this.ledger.complete(request.id, usage, costUsd, upstreamStatus);
|
|
1173
|
+
const overshootUsd = costUsd - request.reservationUsd;
|
|
1120
1174
|
this.audit({
|
|
1121
1175
|
type: "response.completed",
|
|
1122
1176
|
runId: session.runId,
|
|
@@ -1124,13 +1178,17 @@ export class CodingProxy {
|
|
|
1124
1178
|
model: request.model,
|
|
1125
1179
|
status: upstreamStatus,
|
|
1126
1180
|
costUsd,
|
|
1181
|
+
reservationUsd: request.reservationUsd,
|
|
1182
|
+
...(overshootUsd > Number.EPSILON ? { reason: "reservation_exceeded", overshootUsd } : {}),
|
|
1127
1183
|
inputTokens: usage.inputTokens,
|
|
1128
1184
|
outputTokens: usage.outputTokens,
|
|
1129
1185
|
cachedInputTokens: usage.cachedInputTokens,
|
|
1130
1186
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
1131
1187
|
reasoningTokens: usage.reasoningTokens,
|
|
1132
1188
|
});
|
|
1133
|
-
|
|
1189
|
+
// A cached hold may be exceeded when the cache misses (settled, audited above); the ceiling may not.
|
|
1190
|
+
const ceilingUsd = request.ceilingUsd ?? request.reservationUsd;
|
|
1191
|
+
if (costUsd > ceilingUsd + Number.EPSILON) {
|
|
1134
1192
|
await this.ledger.cancelSession(session.id);
|
|
1135
1193
|
throw new CodingProxyError(502, "reservation_invariant_violated");
|
|
1136
1194
|
}
|
|
@@ -1156,7 +1214,7 @@ export class CodingProxy {
|
|
|
1156
1214
|
await safeWrite(sink, bytes, { value: true });
|
|
1157
1215
|
sink.end();
|
|
1158
1216
|
}
|
|
1159
|
-
async forwardStream(session, request, upstream, sink) {
|
|
1217
|
+
async forwardStream(session, request, upstream, sink, progress) {
|
|
1160
1218
|
if (!upstream.body)
|
|
1161
1219
|
throw new Error("missing_upstream_body");
|
|
1162
1220
|
sink.start(upstream.status, { "content-type": "text/event-stream", "cache-control": "no-store" });
|
|
@@ -1166,7 +1224,7 @@ export class CodingProxy {
|
|
|
1166
1224
|
let receivedBytes = 0;
|
|
1167
1225
|
let completed = false;
|
|
1168
1226
|
let failedWithoutUsage = false;
|
|
1169
|
-
const anthropicUsage = session.protocol === "anthropic-messages" ? new AnthropicSseUsageTracker() : undefined;
|
|
1227
|
+
const anthropicUsage = session.protocol === "anthropic-messages" ? (progress.anthropic = new AnthropicSseUsageTracker()) : undefined;
|
|
1170
1228
|
const body = upstream.body;
|
|
1171
1229
|
for await (const chunk of body) {
|
|
1172
1230
|
receivedBytes += chunk.byteLength;
|
|
@@ -1181,6 +1239,7 @@ export class CodingProxy {
|
|
|
1181
1239
|
buffer = buffer.slice(boundary + 2);
|
|
1182
1240
|
const terminal = anthropicUsage ? anthropicUsage.consume(frame) : terminalUsageFromSseFrame(frame);
|
|
1183
1241
|
if (!terminal.terminal) {
|
|
1242
|
+
progress.relayedOutputBytes += relayedTextBytes(frame, session.protocol);
|
|
1184
1243
|
await safeWrite(sink, Buffer.from(`${frame}\n\n`), connected);
|
|
1185
1244
|
continue;
|
|
1186
1245
|
}
|
|
@@ -1191,7 +1250,7 @@ export class CodingProxy {
|
|
|
1191
1250
|
// client sees the real error instead of a cut connection; the reservation stays held.
|
|
1192
1251
|
await this.recordUpstreamFailure(session, terminal.failure);
|
|
1193
1252
|
if (!completed) {
|
|
1194
|
-
await this.markUncertain(session, request, upstream.status, `upstream_failed:${terminal.failure}`, responseHeadersOf(upstream));
|
|
1253
|
+
await this.markUncertain(session, request, upstream.status, `upstream_failed:${terminal.failure}`, responseHeadersOf(upstream), progress);
|
|
1195
1254
|
}
|
|
1196
1255
|
failedWithoutUsage = true;
|
|
1197
1256
|
await safeWrite(sink, Buffer.from(`${frame}\n\n`), connected);
|
|
@@ -1214,9 +1273,102 @@ export class CodingProxy {
|
|
|
1214
1273
|
async recordUpstreamFailure(session, code) {
|
|
1215
1274
|
await this.ledger.recordUpstreamFailure(session.id, code).catch(() => undefined);
|
|
1216
1275
|
}
|
|
1217
|
-
async markUncertain(session, request, status, reason, headers
|
|
1218
|
-
|
|
1219
|
-
|
|
1276
|
+
async markUncertain(session, request, status, reason, headers, progress) {
|
|
1277
|
+
if (progress.marked)
|
|
1278
|
+
return;
|
|
1279
|
+
progress.marked = true;
|
|
1280
|
+
let estimate = await this.estimateInterrupted(session, request, progress);
|
|
1281
|
+
if (estimate) {
|
|
1282
|
+
try {
|
|
1283
|
+
await this.ledger.markUncertain(request.id, status, estimate);
|
|
1284
|
+
}
|
|
1285
|
+
catch {
|
|
1286
|
+
// Settling at the estimate failed: mark it uncertain without one, so it keeps its full hold.
|
|
1287
|
+
estimate = undefined;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
if (!estimate)
|
|
1291
|
+
await this.ledger.markUncertain(request.id, status);
|
|
1292
|
+
this.audit({
|
|
1293
|
+
type: "request.uncertain",
|
|
1294
|
+
runId: session.runId,
|
|
1295
|
+
requestId: request.id,
|
|
1296
|
+
status,
|
|
1297
|
+
reason,
|
|
1298
|
+
...(estimate ? { estimatedCostUsd: estimate.costUsd } : {}),
|
|
1299
|
+
...headers,
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* The best known cost of a request that broke before its final usage (interrupted.ts), or
|
|
1304
|
+
* undefined when none can be made: the request then keeps its full hold. Never throws.
|
|
1305
|
+
*/
|
|
1306
|
+
async estimateInterrupted(session, request, progress) {
|
|
1307
|
+
try {
|
|
1308
|
+
const hints = await this.ledger.settlementHints(session.id, request.model);
|
|
1309
|
+
const estimate = estimateInterrupted({
|
|
1310
|
+
...progress.anthropic?.partial(),
|
|
1311
|
+
beforeResponse: progress.stream && !progress.responseStarted,
|
|
1312
|
+
relayedOutputBytes: progress.relayedOutputBytes,
|
|
1313
|
+
...hints,
|
|
1314
|
+
...(progress.previousInput ? { previous: progress.previousInput } : {}),
|
|
1315
|
+
bodyBytes: progress.bodyBytes,
|
|
1316
|
+
reservationUsd: request.reservationUsd,
|
|
1317
|
+
maxOutputTokens: progress.maxOutputTokens,
|
|
1318
|
+
ceilingUsd: request.ceilingUsd ?? request.reservationUsd,
|
|
1319
|
+
}, request.pricing);
|
|
1320
|
+
return Number.isFinite(estimate.costUsd) ? estimate : undefined;
|
|
1321
|
+
}
|
|
1322
|
+
catch {
|
|
1323
|
+
return undefined;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/** OpenAI Responses events whose string `delta` is generated output: text, tool input, reasoning. */
|
|
1328
|
+
const OPENAI_OUTPUT_DELTAS = new Set([
|
|
1329
|
+
"response.output_text.delta",
|
|
1330
|
+
"response.refusal.delta",
|
|
1331
|
+
"response.function_call_arguments.delta",
|
|
1332
|
+
"response.custom_tool_call_input.delta",
|
|
1333
|
+
"response.reasoning_text.delta",
|
|
1334
|
+
"response.reasoning_summary_text.delta",
|
|
1335
|
+
]);
|
|
1336
|
+
/** The generated-output field of each Anthropic content_block_delta type (signatures are not output). */
|
|
1337
|
+
const ANTHROPIC_OUTPUT_DELTAS = {
|
|
1338
|
+
text_delta: "text",
|
|
1339
|
+
input_json_delta: "partial_json",
|
|
1340
|
+
thinking_delta: "thinking",
|
|
1341
|
+
};
|
|
1342
|
+
/**
|
|
1343
|
+
* UTF-8 bytes of generated output in a relayed SSE frame: text, tool-call input and thinking or
|
|
1344
|
+
* reasoning deltas, which are most of a coding agent's output.
|
|
1345
|
+
*/
|
|
1346
|
+
function relayedTextBytes(frame, protocol) {
|
|
1347
|
+
if (!frame.includes(protocol === "anthropic-messages" ? "content_block_delta" : ".delta"))
|
|
1348
|
+
return 0;
|
|
1349
|
+
try {
|
|
1350
|
+
const data = frame
|
|
1351
|
+
.split("\n")
|
|
1352
|
+
.filter((line) => line.startsWith("data:"))
|
|
1353
|
+
.map((line) => line.slice(5).trimStart())
|
|
1354
|
+
.join("\n");
|
|
1355
|
+
const value = JSON.parse(data);
|
|
1356
|
+
if (!value || typeof value.type !== "string")
|
|
1357
|
+
return 0;
|
|
1358
|
+
if (protocol === "openai-responses") {
|
|
1359
|
+
return OPENAI_OUTPUT_DELTAS.has(value.type) && typeof value.delta === "string"
|
|
1360
|
+
? Buffer.byteLength(value.delta)
|
|
1361
|
+
: 0;
|
|
1362
|
+
}
|
|
1363
|
+
if (value.type !== "content_block_delta")
|
|
1364
|
+
return 0;
|
|
1365
|
+
const delta = value.delta;
|
|
1366
|
+
const field = typeof delta?.type === "string" ? ANTHROPIC_OUTPUT_DELTAS[delta.type] : undefined;
|
|
1367
|
+
const text = field ? delta?.[field] : undefined;
|
|
1368
|
+
return typeof text === "string" ? Buffer.byteLength(text) : 0;
|
|
1369
|
+
}
|
|
1370
|
+
catch {
|
|
1371
|
+
return 0;
|
|
1220
1372
|
}
|
|
1221
1373
|
}
|
|
1222
1374
|
/** The safe error code in a rejected upstream's JSON body, or undefined when it names none or cannot be read. */
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* - a version or event the comparator cannot parse counts as affected
|
|
17
17
|
* (fail closed).
|
|
18
18
|
*/
|
|
19
|
+
import { type AuditAdvisory } from "../../../coding/registry/audit-mode.js";
|
|
19
20
|
import { type RegistryAdapter, type UpstreamFetch } from "../../../coding/registry/types.js";
|
|
20
21
|
export declare const DEFAULT_VULN_CACHE_ENTRIES = 10000;
|
|
21
22
|
/** Exact versions whose querybatch results are cached. */
|
|
@@ -39,6 +40,7 @@ interface OsvAffected {
|
|
|
39
40
|
}
|
|
40
41
|
interface OsvVuln {
|
|
41
42
|
id: string;
|
|
43
|
+
summary?: unknown;
|
|
42
44
|
aliases?: string[];
|
|
43
45
|
affected?: (OsvAffected & {
|
|
44
46
|
database_specific?: Record<string, unknown>;
|
|
@@ -58,11 +60,50 @@ export declare function isMalware(vuln: OsvVuln): boolean;
|
|
|
58
60
|
* names compare, and how versions order. */
|
|
59
61
|
export type AuditAdapter = Pick<RegistryAdapter, "osvEcosystem" | "normalizeName" | "compareVersions">;
|
|
60
62
|
export interface AdvisoryIndex {
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
+
/** Ids of the blocking advisories (HIGH, CRITICAL or malware) that affect
|
|
64
|
+
* `version`, minus those waived by `accepted` (see `isWaived`). Without
|
|
65
|
+
* `accepted`, or with an empty set, every blocking advisory. With
|
|
66
|
+
* `auditAll` (package audit mode `full`), only those that can never be
|
|
67
|
+
* served past: malware. */
|
|
68
|
+
withheld(version: string, accepted?: ReadonlySet<string>, auditAll?: boolean): readonly string[];
|
|
69
|
+
/** Ids of the blocking advisories affecting `version` that `accepted`
|
|
70
|
+
* waives: exactly those `withheld` subtracts. For reporting. */
|
|
71
|
+
waived(version: string, accepted: ReadonlySet<string>): readonly string[];
|
|
63
72
|
/** Advisory ids of any other severity that affect `version`. */
|
|
64
73
|
reported(version: string): readonly string[];
|
|
74
|
+
/** Blocking, non-malware, non-accepted advisories that `auditAll` lets
|
|
75
|
+
* through, with detail: what a full-mode run records when it serves `version`. */
|
|
76
|
+
audited?(version: string, accepted: ReadonlySet<string>): readonly AuditAdvisory[];
|
|
65
77
|
}
|
|
78
|
+
/** A blocking advisory, with what deciding a waiver needs. */
|
|
79
|
+
export interface WithheldAdvisory {
|
|
80
|
+
id: string;
|
|
81
|
+
/** Reports malicious code (`isMalware`): never waived. */
|
|
82
|
+
malware: boolean;
|
|
83
|
+
/** The advisory's OSV aliases (CVE ids, other GHSA ids, …). */
|
|
84
|
+
aliases: readonly string[];
|
|
85
|
+
/** OSV severity, upper-cased (HIGH, CRITICAL, …); absent when OSV gives none (malware). */
|
|
86
|
+
severity?: string;
|
|
87
|
+
/** OSV summary as plain bounded text; absent when OSV gives none. */
|
|
88
|
+
summary?: string;
|
|
89
|
+
}
|
|
90
|
+
/** Whether `accepted` waives a blocking advisory: it is not malware, and
|
|
91
|
+
* its id or one of its aliases is accepted. Malware is never waived,
|
|
92
|
+
* whatever the accepted set lists. */
|
|
93
|
+
export declare function isWaived(advisory: WithheldAdvisory, accepted?: ReadonlySet<string>): boolean;
|
|
94
|
+
/** Splits the blocking advisories affecting one version into those still
|
|
95
|
+
* withholding it, those `accepted` waives, and (package audit mode `full`,
|
|
96
|
+
* `auditAll`) those served past and recorded. Malware is always withheld.
|
|
97
|
+
* The version is withheld while `withheld` is non-empty. */
|
|
98
|
+
export declare function splitWaived<T extends WithheldAdvisory>(advisories: readonly T[], accepted?: ReadonlySet<string>, options?: {
|
|
99
|
+
auditAll?: boolean;
|
|
100
|
+
}): {
|
|
101
|
+
withheld: T[];
|
|
102
|
+
waived: T[];
|
|
103
|
+
audited: T[];
|
|
104
|
+
};
|
|
105
|
+
/** A blocking advisory as package audit mode records it. */
|
|
106
|
+
export declare function auditAdvisoryOf(advisory: WithheldAdvisory): AuditAdvisory;
|
|
66
107
|
type Compare = (a: string, b: string) => number;
|
|
67
108
|
/** OSV range evaluation: sort events by version, then sweep. A version or
|
|
68
109
|
* event the comparator cannot parse makes the version count as affected. */
|
|
@@ -73,9 +114,10 @@ export interface AuditedVersion {
|
|
|
73
114
|
name: string;
|
|
74
115
|
version: string;
|
|
75
116
|
}
|
|
76
|
-
/** `name@version` -> the HIGH/CRITICAL
|
|
77
|
-
* version with none is absent.
|
|
78
|
-
|
|
117
|
+
/** `name@version` -> the blocking (HIGH/CRITICAL or malware) advisories
|
|
118
|
+
* affecting it; a version with none is absent. Independent of any
|
|
119
|
+
* accepted set: callers subtract waivers with `splitWaived`. */
|
|
120
|
+
export type WithheldVersions = Map<string, WithheldAdvisory[]>;
|
|
79
121
|
export declare const versionKey: (name: string, version: string) => string;
|
|
80
122
|
export declare class OsvAudit {
|
|
81
123
|
private readonly options;
|
|
@@ -85,8 +127,8 @@ export declare class OsvAudit {
|
|
|
85
127
|
private readonly cache;
|
|
86
128
|
/** Single-flight: concurrent audits of one package share one OSV query. */
|
|
87
129
|
private readonly loads;
|
|
88
|
-
/** Advisory severities by id, with the
|
|
89
|
-
* read at, least recently used first. */
|
|
130
|
+
/** Advisory severities (and malware flag and aliases) by id, with the
|
|
131
|
+
* OSV `modified` time they were read at, least recently used first. */
|
|
90
132
|
private readonly vulns;
|
|
91
133
|
/** Advisory ids (and their `modified` time) per exact version from
|
|
92
134
|
* querybatch, for the audit TTL, least recently used first, so repeated
|
|
@@ -121,9 +163,10 @@ export declare class OsvAudit {
|
|
|
121
163
|
auditVersions(adapter: AuditAdapter, versions: readonly AuditedVersion[], signal?: AbortSignal): Promise<WithheldVersions>;
|
|
122
164
|
private loadVersions;
|
|
123
165
|
private rememberBatch;
|
|
124
|
-
/** Whether an advisory
|
|
125
|
-
* `modified` time for
|
|
126
|
-
|
|
166
|
+
/** Whether an advisory blocks (HIGH, CRITICAL or malware), whether it is
|
|
167
|
+
* malware, and its aliases, cached by id while OSV's `modified` time for
|
|
168
|
+
* it is unchanged. */
|
|
169
|
+
private detail;
|
|
127
170
|
private remember;
|
|
128
171
|
private load;
|
|
129
172
|
private query;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* - a version or event the comparator cannot parse counts as affected
|
|
17
17
|
* (fail closed).
|
|
18
18
|
*/
|
|
19
|
+
import { sanitizeAuditSummary } from "../../../coding/registry/audit-mode.js";
|
|
19
20
|
import { RegistryError } from "../../../coding/registry/types.js";
|
|
20
21
|
import { boundedMetadataFetch, DEFAULT_MAX_METADATA_BYTES, DEFAULT_METADATA_TIMEOUT_MS } from "./bounded-fetch.js";
|
|
21
22
|
const OSV_QUERY = "https://api.osv.dev/v1/query";
|
|
@@ -52,10 +53,59 @@ export function isMalware(vuln) {
|
|
|
52
53
|
(typeof detail.source === "string" && detail.source.includes("/malicious-packages/")));
|
|
53
54
|
});
|
|
54
55
|
}
|
|
56
|
+
/** An advisory's OSV severity (database_specific.severity), upper-cased; "" when it has none. */
|
|
57
|
+
function severityOf(vuln) {
|
|
58
|
+
const severity = vuln.database_specific?.severity;
|
|
59
|
+
return typeof severity === "string" ? severity.toUpperCase() : "";
|
|
60
|
+
}
|
|
55
61
|
/** Whether an advisory withholds the versions it affects. */
|
|
56
62
|
function blocks(vuln) {
|
|
57
|
-
return BLOCKING.has(vuln
|
|
63
|
+
return BLOCKING.has(severityOf(vuln)) || isMalware(vuln);
|
|
64
|
+
}
|
|
65
|
+
/** What package audit mode records of an advisory: its severity, and its summary bounded at the source. */
|
|
66
|
+
function auditDetail(vuln) {
|
|
67
|
+
const severity = severityOf(vuln);
|
|
68
|
+
const summary = sanitizeAuditSummary(vuln.summary);
|
|
69
|
+
return { ...(severity ? { severity } : {}), ...(summary ? { summary } : {}) };
|
|
70
|
+
}
|
|
71
|
+
/** Whether `accepted` waives a blocking advisory: it is not malware, and
|
|
72
|
+
* its id or one of its aliases is accepted. Malware is never waived,
|
|
73
|
+
* whatever the accepted set lists. */
|
|
74
|
+
export function isWaived(advisory, accepted) {
|
|
75
|
+
if (advisory.malware || !accepted || accepted.size === 0)
|
|
76
|
+
return false;
|
|
77
|
+
// Belt and braces for entries not built from an OSV record here.
|
|
78
|
+
if ([advisory.id, ...advisory.aliases].some((id) => id.startsWith("MAL-")))
|
|
79
|
+
return false;
|
|
80
|
+
return accepted.has(advisory.id) || advisory.aliases.some((alias) => accepted.has(alias));
|
|
81
|
+
}
|
|
82
|
+
/** Whether a blocking advisory reports, or may report, malicious code: never served in any mode. */
|
|
83
|
+
function isMalwareAdvisory(advisory) {
|
|
84
|
+
return advisory.malware || [advisory.id, ...advisory.aliases].some((id) => id.startsWith("MAL-"));
|
|
58
85
|
}
|
|
86
|
+
/** Splits the blocking advisories affecting one version into those still
|
|
87
|
+
* withholding it, those `accepted` waives, and (package audit mode `full`,
|
|
88
|
+
* `auditAll`) those served past and recorded. Malware is always withheld.
|
|
89
|
+
* The version is withheld while `withheld` is non-empty. */
|
|
90
|
+
export function splitWaived(advisories, accepted, options = {}) {
|
|
91
|
+
const withheld = [];
|
|
92
|
+
const waived = [];
|
|
93
|
+
const audited = [];
|
|
94
|
+
for (const advisory of advisories) {
|
|
95
|
+
if (isWaived(advisory, accepted))
|
|
96
|
+
waived.push(advisory);
|
|
97
|
+
else if (options.auditAll && !isMalwareAdvisory(advisory))
|
|
98
|
+
audited.push(advisory);
|
|
99
|
+
else
|
|
100
|
+
withheld.push(advisory);
|
|
101
|
+
}
|
|
102
|
+
return { withheld, waived, audited };
|
|
103
|
+
}
|
|
104
|
+
/** A blocking advisory as package audit mode records it. */
|
|
105
|
+
export function auditAdvisoryOf(advisory) {
|
|
106
|
+
return { id: advisory.id, severity: advisory.severity ?? "UNKNOWN", summary: advisory.summary ?? "" };
|
|
107
|
+
}
|
|
108
|
+
const aliasesOf = (vuln) => Array.isArray(vuln.aliases) ? vuln.aliases.filter((alias) => typeof alias === "string") : [];
|
|
59
109
|
function eventVersion(event) {
|
|
60
110
|
return event.introduced ?? event.fixed ?? event.last_affected ?? event.limit;
|
|
61
111
|
}
|
|
@@ -122,11 +172,16 @@ function indexOf(advisories, adapter) {
|
|
|
122
172
|
const compare = (a, b) => adapter.compareVersions(a, b);
|
|
123
173
|
const matching = (version, blocking) => advisories
|
|
124
174
|
.filter((advisory) => advisory.blocking === blocking)
|
|
125
|
-
.filter((advisory) => advisory.affected.some((affected) => affects(version, affected, compare)))
|
|
126
|
-
|
|
127
|
-
return {
|
|
175
|
+
.filter((advisory) => advisory.affected.some((affected) => affects(version, affected, compare)));
|
|
176
|
+
const ids = (list) => list.map((advisory) => advisory.id);
|
|
177
|
+
return {
|
|
178
|
+
withheld: (version, accepted, auditAll) => ids(splitWaived(matching(version, true), accepted, { auditAll }).withheld),
|
|
179
|
+
waived: (version, accepted) => ids(splitWaived(matching(version, true), accepted).waived),
|
|
180
|
+
reported: (version) => ids(matching(version, false)),
|
|
181
|
+
audited: (version, accepted) => splitWaived(matching(version, true), accepted, { auditAll: true }).audited.map(auditAdvisoryOf),
|
|
182
|
+
};
|
|
128
183
|
}
|
|
129
|
-
const EMPTY_INDEX = { withheld: () => [], reported: () => [] };
|
|
184
|
+
const EMPTY_INDEX = { withheld: () => [], waived: () => [], reported: () => [], audited: () => [] };
|
|
130
185
|
export const DEFAULT_AUDIT_CACHE_ENTRIES = 5000;
|
|
131
186
|
export const versionKey = (name, version) => `${name}@${version}`;
|
|
132
187
|
export class OsvAudit {
|
|
@@ -137,8 +192,8 @@ export class OsvAudit {
|
|
|
137
192
|
cache = new Map();
|
|
138
193
|
/** Single-flight: concurrent audits of one package share one OSV query. */
|
|
139
194
|
loads = new Map();
|
|
140
|
-
/** Advisory severities by id, with the
|
|
141
|
-
* read at, least recently used first. */
|
|
195
|
+
/** Advisory severities (and malware flag and aliases) by id, with the
|
|
196
|
+
* OSV `modified` time they were read at, least recently used first. */
|
|
142
197
|
vulns = new Map();
|
|
143
198
|
/** Advisory ids (and their `modified` time) per exact version from
|
|
144
199
|
* querybatch, for the audit TTL, least recently used first, so repeated
|
|
@@ -286,10 +341,18 @@ export class OsvAudit {
|
|
|
286
341
|
while (cursor < ids.length) {
|
|
287
342
|
const id = ids[cursor++];
|
|
288
343
|
const advisory = found.get(id);
|
|
289
|
-
|
|
344
|
+
const detail = await this.detail(id, advisory.modified, signal);
|
|
345
|
+
if (!detail.blocking)
|
|
290
346
|
continue;
|
|
347
|
+
const entry = {
|
|
348
|
+
id,
|
|
349
|
+
malware: detail.malware,
|
|
350
|
+
aliases: detail.aliases,
|
|
351
|
+
...(detail.severity ? { severity: detail.severity } : {}),
|
|
352
|
+
...(detail.summary ? { summary: detail.summary } : {}),
|
|
353
|
+
};
|
|
291
354
|
for (const key of advisory.versions)
|
|
292
|
-
withheld.set(key, [...(withheld.get(key) ?? []),
|
|
355
|
+
withheld.set(key, [...(withheld.get(key) ?? []), entry]);
|
|
293
356
|
}
|
|
294
357
|
};
|
|
295
358
|
await Promise.all(Array.from({ length: Math.min(OSV_VULN_CONCURRENCY, ids.length) }, worker));
|
|
@@ -307,14 +370,15 @@ export class OsvAudit {
|
|
|
307
370
|
}
|
|
308
371
|
this.batchCache.set(key, { expires: now + this.ttlMs, vulns });
|
|
309
372
|
}
|
|
310
|
-
/** Whether an advisory
|
|
311
|
-
* `modified` time for
|
|
312
|
-
|
|
373
|
+
/** Whether an advisory blocks (HIGH, CRITICAL or malware), whether it is
|
|
374
|
+
* malware, and its aliases, cached by id while OSV's `modified` time for
|
|
375
|
+
* it is unchanged. */
|
|
376
|
+
async detail(id, modified, signal) {
|
|
313
377
|
const cached = this.vulns.get(id);
|
|
314
378
|
if (cached && modified !== "" && cached.modified === modified) {
|
|
315
379
|
this.vulns.delete(id);
|
|
316
380
|
this.vulns.set(id, cached); // most recently used
|
|
317
|
-
return cached
|
|
381
|
+
return cached;
|
|
318
382
|
}
|
|
319
383
|
const response = await this.fetch(`${OSV_VULN}${encodeURIComponent(id)}`, { accept: "application/json", signal });
|
|
320
384
|
if (!response.ok)
|
|
@@ -322,7 +386,13 @@ export class OsvAudit {
|
|
|
322
386
|
const vuln = (await response.json());
|
|
323
387
|
if (typeof vuln.id !== "string")
|
|
324
388
|
throw new Error("osv_vuln_invalid");
|
|
325
|
-
const
|
|
389
|
+
const detail = {
|
|
390
|
+
modified: typeof vuln.modified === "string" ? vuln.modified : modified,
|
|
391
|
+
blocking: blocks(vuln),
|
|
392
|
+
malware: isMalware(vuln),
|
|
393
|
+
aliases: aliasesOf(vuln),
|
|
394
|
+
...auditDetail(vuln),
|
|
395
|
+
};
|
|
326
396
|
this.vulns.delete(id);
|
|
327
397
|
while (this.vulns.size >= (this.options.maxVulnEntries ?? DEFAULT_VULN_CACHE_ENTRIES)) {
|
|
328
398
|
const oldest = this.vulns.keys().next();
|
|
@@ -330,8 +400,8 @@ export class OsvAudit {
|
|
|
330
400
|
break;
|
|
331
401
|
this.vulns.delete(oldest.value);
|
|
332
402
|
}
|
|
333
|
-
this.vulns.set(id,
|
|
334
|
-
return
|
|
403
|
+
this.vulns.set(id, detail);
|
|
404
|
+
return detail;
|
|
335
405
|
}
|
|
336
406
|
remember(key, advisories) {
|
|
337
407
|
const now = this.now();
|
|
@@ -356,7 +426,14 @@ export class OsvAudit {
|
|
|
356
426
|
adapter.normalizeName(entry.package.name) === wanted);
|
|
357
427
|
if (affected.length === 0)
|
|
358
428
|
continue;
|
|
359
|
-
advisories.push({
|
|
429
|
+
advisories.push({
|
|
430
|
+
id: vuln.id,
|
|
431
|
+
blocking: blocks(vuln),
|
|
432
|
+
malware: isMalware(vuln),
|
|
433
|
+
aliases: aliasesOf(vuln),
|
|
434
|
+
...auditDetail(vuln),
|
|
435
|
+
affected,
|
|
436
|
+
});
|
|
360
437
|
}
|
|
361
438
|
return advisories;
|
|
362
439
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ParsedLockfile } from "../../../coding/registry/types.js";
|
|
2
|
+
export interface ParseRequest {
|
|
3
|
+
ecosystem: string;
|
|
4
|
+
body: string;
|
|
5
|
+
maxEntries: number;
|
|
6
|
+
proxyRegistryUrl: string;
|
|
7
|
+
}
|
|
8
|
+
/** A ParsedLockfile without its functions: `edges[i]` lists, for
|
|
9
|
+
* `entries[i]`, each dependency key the lockfile records that resolves to
|
|
10
|
+
* an entry, with that entry's index; `projectEdges[i]` the same for
|
|
11
|
+
* `projects[i]`. */
|
|
12
|
+
export interface ShippedLockfile {
|
|
13
|
+
entries: ParsedLockfile["entries"];
|
|
14
|
+
projects: ParsedLockfile["projects"];
|
|
15
|
+
integrity?: ParsedLockfile["integrity"];
|
|
16
|
+
edges: [key: string, target: number][][];
|
|
17
|
+
projectEdges: [key: string, target: number][][];
|
|
18
|
+
}
|
|
19
|
+
export type ParseResponse = {
|
|
20
|
+
ok: true;
|
|
21
|
+
lockfile: ShippedLockfile;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
status: number;
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
unexpected: true;
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function parseAndShip(request: ParseRequest): ShippedLockfile;
|
|
33
|
+
/** The answer for one parse: the lockfile, the parser's refusal, or (a bug,
|
|
34
|
+
* not a verdict about the lockfile) the unexpected error's message, which
|
|
35
|
+
* the main thread logs. */
|
|
36
|
+
export declare function responseFor(parse: () => ShippedLockfile): ParseResponse;
|