@wardby/cli 0.2.1 → 0.3.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 +34 -4
- package/README.md +41 -4
- package/dist/claude-coding-worker/driver.d.ts +6 -1
- package/dist/claude-coding-worker/driver.js +27 -1
- package/dist/claude-coding-worker/main.js +2 -0
- package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
- package/dist/claude-coding-worker/tool-socket.js +26 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +13 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +219 -29
- package/dist/coding/collect-exclude.d.ts +25 -0
- package/dist/coding/collect-exclude.js +76 -0
- package/dist/coding/profile.d.ts +67 -22
- package/dist/coding/profile.js +58 -25
- package/dist/coding/protected-path-wording.d.ts +24 -0
- package/dist/coding/protected-path-wording.js +55 -0
- package/dist/coding/protected-paths.d.ts +31 -0
- package/dist/coding/protected-paths.js +48 -0
- package/dist/coding/protocol.d.ts +75 -4
- package/dist/coding/protocol.js +107 -7
- package/dist/coding/registry/adapters.d.ts +2 -0
- package/dist/coding/registry/adapters.js +9 -0
- package/dist/coding/registry/allowlist.d.ts +9 -0
- package/dist/coding/registry/allowlist.js +28 -0
- package/dist/coding/registry/json-scan.d.ts +55 -0
- package/dist/coding/registry/json-scan.js +191 -0
- package/dist/coding/registry/lockfiles.d.ts +6 -0
- package/dist/coding/registry/lockfiles.js +89 -0
- package/dist/coding/registry/npm-lockfile.d.ts +9 -0
- package/dist/coding/registry/npm-lockfile.js +73 -0
- package/dist/coding/registry/npm-plan.d.ts +29 -0
- package/dist/coding/registry/npm-plan.js +289 -0
- package/dist/coding/registry/npm.d.ts +7 -0
- package/dist/coding/registry/npm.js +252 -0
- package/dist/coding/registry/pypi.d.ts +4 -0
- package/dist/coding/registry/pypi.js +210 -0
- package/dist/coding/registry/report.d.ts +37 -0
- package/dist/coding/registry/report.js +31 -0
- package/dist/coding/registry/token.d.ts +4 -0
- package/dist/coding/registry/token.js +7 -0
- package/dist/coding/registry/types.d.ts +286 -0
- package/dist/coding/registry/types.js +19 -0
- package/dist/coding/registry/worker-config.d.ts +14 -0
- package/dist/coding/registry/worker-config.js +31 -0
- package/dist/coding/services/builtins.d.ts +22 -0
- package/dist/coding/services/builtins.js +85 -0
- package/dist/coding/services/catalog.d.ts +443 -0
- package/dist/coding/services/catalog.js +159 -0
- package/dist/coding/services/declaration.d.ts +11 -0
- package/dist/coding/services/declaration.js +114 -0
- package/dist/coding/services/note.d.ts +8 -0
- package/dist/coding/services/note.js +15 -0
- package/dist/coding/services/resolve.d.ts +25 -0
- package/dist/coding/services/resolve.js +50 -0
- package/dist/coding/services/wording.d.ts +25 -0
- package/dist/coding/services/wording.js +70 -0
- package/dist/coding-proxy/main.js +24 -4
- package/dist/coding-worker/artifact.d.ts +6 -0
- package/dist/coding-worker/debug-trace.d.ts +37 -0
- package/dist/coding-worker/debug-trace.js +117 -0
- package/dist/coding-worker/driver.d.ts +13 -1
- package/dist/coding-worker/driver.js +102 -13
- package/dist/coding-worker/errors.js +8 -0
- package/dist/coding-worker/main.js +10 -2
- package/dist/coding-worker/sdk.d.ts +2 -2
- package/dist/coding-worker/sdk.js +7 -2
- package/dist/coding-worker/types.d.ts +3 -0
- package/dist/config/providers.d.ts +41 -0
- package/dist/config/providers.js +66 -0
- package/dist/core/budget-groups.d.ts +108 -5
- package/dist/core/budget-groups.js +125 -19
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +5 -1
- package/dist/core/db.js +8 -2
- package/dist/core/dispatch.d.ts +33 -6
- package/dist/core/dispatch.js +260 -43
- package/dist/core/engine-native.js +27 -10
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +49 -0
- package/dist/core/host-events.js +257 -0
- package/dist/core/host-identity-links.d.ts +54 -0
- package/dist/core/host-identity-links.js +189 -0
- package/dist/core/host-status.d.ts +61 -0
- package/dist/core/host-status.js +211 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +38 -2
- package/dist/core/reconciler.js +86 -2
- package/dist/core/repo-access.d.ts +99 -0
- package/dist/core/repo-access.js +136 -0
- package/dist/core/review-host-checks.d.ts +11 -0
- package/dist/core/review-host-checks.js +41 -0
- package/dist/core/review-host-tools.d.ts +47 -0
- package/dist/core/review-host-tools.js +347 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/runner.d.ts +30 -8
- package/dist/core/runner.js +237 -40
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +1 -1
- package/dist/core/subagent-memory-tools.js +16 -3
- package/dist/core/tool-admin.d.ts +81 -0
- package/dist/core/tool-admin.js +129 -0
- package/dist/core/tool-names.d.ts +42 -0
- package/dist/core/tool-names.js +64 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +8 -1
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +100 -0
- package/dist/generated/prisma/client.d.ts +100 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
- package/dist/generated/prisma/enums.d.ts +6 -0
- package/dist/generated/prisma/enums.js +6 -1
- package/dist/generated/prisma/internal/class.d.ts +143 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
- package/dist/generated/prisma/models/Agent.d.ts +294 -1
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
- package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
- package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
- package/dist/generated/prisma/models/HostIdentity.js +1 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
- package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +455 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
- package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
- package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
- package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
- package/dist/generated/prisma/models/RegistryFetch.js +1 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
- package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
- package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
- package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
- package/dist/generated/prisma/models/ResourceGrant.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +389 -1
- package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
- package/dist/generated/prisma/models/RunHostCheck.js +1 -0
- package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
- package/dist/generated/prisma/models/RunHostStatus.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models.d.ts +13 -0
- package/dist/help/build.d.ts +1 -0
- package/dist/help/build.js +9 -0
- package/dist/help/catalog.d.ts +24 -0
- package/dist/help/catalog.js +160 -0
- package/dist/help/cli.d.ts +2 -0
- package/dist/help/cli.js +65 -0
- package/dist/help/runtime.d.ts +3 -0
- package/dist/help/runtime.js +44 -0
- package/dist/help/search.d.ts +9 -0
- package/dist/help/search.js +104 -0
- package/dist/help-index.json +660 -0
- package/dist/import/cli-args.js +3 -2
- package/dist/import/create.d.ts +5 -0
- package/dist/import/create.js +67 -13
- package/dist/import/index.js +19 -9
- package/dist/import/neutral-schema.d.ts +11 -11
- package/dist/mcp/auth/access.d.ts +70 -0
- package/dist/mcp/auth/access.js +58 -0
- package/dist/mcp/auth/grants-cli.d.ts +149 -0
- package/dist/mcp/auth/grants-cli.js +518 -0
- package/dist/mcp/auth/host-account-cli.d.ts +2 -0
- package/dist/mcp/auth/host-account-cli.js +47 -0
- package/dist/mcp/auth/ownership.d.ts +26 -52
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/repo-authorization.d.ts +22 -0
- package/dist/mcp/auth/repo-authorization.js +51 -0
- package/dist/mcp/auth/resource-server.d.ts +31 -2
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +2 -2
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
- package/dist/mcp/context.d.ts +27 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/github-ingress.d.ts +36 -0
- package/dist/mcp/host-events/github-ingress.js +92 -0
- package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
- package/dist/mcp/host-events/github-user-callback.js +50 -0
- package/dist/mcp/index.d.ts +8 -1
- package/dist/mcp/index.js +106 -16
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/tools/agents.js +446 -48
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +22 -15
- package/dist/mcp/tools/grants.d.ts +2 -0
- package/dist/mcp/tools/grants.js +239 -0
- package/dist/mcp/tools/help.d.ts +5 -0
- package/dist/mcp/tools/help.js +67 -0
- package/dist/mcp/tools/host-accounts.d.ts +2 -0
- package/dist/mcp/tools/host-accounts.js +114 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +181 -0
- package/dist/mcp/tools/runs.d.ts +6 -0
- package/dist/mcp/tools/runs.js +60 -6
- package/dist/mcp/tools/scheduling.js +3 -6
- package/dist/mcp/tools/secrets.js +18 -6
- package/dist/mcp/tools/services.d.ts +2 -0
- package/dist/mcp/tools/services.js +222 -0
- package/dist/mcp/tools/subagents.js +52 -16
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +201 -40
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +10 -0
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +2 -0
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +2 -1
- package/dist/providers/auth/self-hosted.js +16 -4
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
- package/dist/providers/coding-proxy/memory-ledger.js +21 -2
- package/dist/providers/coding-proxy/metering.d.ts +4 -0
- package/dist/providers/coding-proxy/metering.js +28 -2
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
- package/dist/providers/coding-proxy/proxy.d.ts +13 -0
- package/dist/providers/coding-proxy/proxy.js +479 -18
- package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
- package/dist/providers/coding-proxy/registry/audit.js +380 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
- package/dist/providers/coding-proxy/registry/plan.js +304 -0
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
- package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
- package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
- package/dist/providers/coding-proxy/registry/service.js +1137 -0
- package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
- package/dist/providers/coding-proxy/registry/store.js +70 -0
- package/dist/providers/coding-proxy/runtime.d.ts +17 -0
- package/dist/providers/coding-proxy/runtime.js +63 -0
- package/dist/providers/coding-proxy/secure-fetch.js +0 -1
- package/dist/providers/coding-proxy/server.d.ts +11 -0
- package/dist/providers/coding-proxy/server.js +163 -0
- package/dist/providers/coding-proxy/types.d.ts +15 -0
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +2 -2
- package/dist/providers/executor/composition.d.ts +3 -0
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +105 -3
- package/dist/providers/executor/container.js +296 -20
- package/dist/providers/executor/dbos.d.ts +2 -3
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +7 -0
- package/dist/providers/executor/routing.js +13 -0
- package/dist/providers/executor/types.d.ts +22 -0
- package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
- package/dist/providers/jobs/claude-tool-setup.js +50 -0
- package/dist/providers/jobs/collect-prune.d.ts +7 -0
- package/dist/providers/jobs/collect-prune.js +27 -0
- package/dist/providers/jobs/docker-isolation.d.ts +48 -3
- package/dist/providers/jobs/docker-isolation.js +213 -22
- package/dist/providers/jobs/docker-services.d.ts +35 -0
- package/dist/providers/jobs/docker-services.js +191 -0
- package/dist/providers/jobs/docker.d.ts +49 -2
- package/dist/providers/jobs/docker.js +279 -32
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
- package/dist/providers/jobs/kubernetes-isolation.js +238 -57
- package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
- package/dist/providers/jobs/kubernetes-platform.js +11 -5
- package/dist/providers/jobs/kubernetes-preflight.js +3 -0
- package/dist/providers/jobs/kubernetes.d.ts +21 -2
- package/dist/providers/jobs/kubernetes.js +112 -21
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.js +6 -2
- package/dist/providers/llm/bedrock.js +2 -1
- package/dist/providers/llm/claude-messages.d.ts +5 -1
- package/dist/providers/llm/claude-messages.js +1 -0
- package/dist/providers/llm/claude-provider.d.ts +3 -1
- package/dist/providers/llm/claude-provider.js +5 -1
- package/dist/providers/llm/index.d.ts +1 -1
- package/dist/providers/llm/index.js +1 -1
- package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
- package/dist/providers/llm/pricing-anthropic.js +32 -14
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
- package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
- package/dist/providers/llm/routing.d.ts +10 -1
- package/dist/providers/llm/routing.js +18 -0
- package/dist/providers/llm/types.d.ts +12 -0
- package/dist/providers/llm/types.js +8 -1
- package/dist/providers/review-host/diff-lines.d.ts +16 -0
- package/dist/providers/review-host/diff-lines.js +59 -0
- package/dist/providers/review-host/github-events.d.ts +6 -0
- package/dist/providers/review-host/github-events.js +180 -0
- package/dist/providers/review-host/github-user-auth.d.ts +38 -0
- package/dist/providers/review-host/github-user-auth.js +128 -0
- package/dist/providers/review-host/github.d.ts +57 -0
- package/dist/providers/review-host/github.js +567 -0
- package/dist/providers/review-host/index.d.ts +12 -0
- package/dist/providers/review-host/index.js +30 -0
- package/dist/providers/review-host/review-format.d.ts +19 -0
- package/dist/providers/review-host/review-format.js +59 -0
- package/dist/providers/review-host/types.d.ts +284 -0
- package/dist/providers/review-host/types.js +24 -0
- package/dist/providers/vcs/git.d.ts +16 -6
- package/dist/providers/vcs/git.js +77 -13
- package/dist/providers/vcs/github.d.ts +74 -3
- package/dist/providers/vcs/github.js +195 -15
- package/dist/providers/vcs/types.d.ts +42 -4
- package/dist/quickstart/index.js +13 -2
- package/dist/sandbox/fetch-policy.d.ts +20 -2
- package/dist/sandbox/fetch-policy.js +64 -3
- package/dist/sandbox/host-functions.d.ts +9 -1
- package/dist/sandbox/host-functions.js +12 -5
- package/dist/serve.js +1 -1
- package/dist/wardby-bin.js +6 -0
- package/docs/README.md +30 -0
- package/docs/architecture-runtime.md +90 -0
- package/docs/assets/brand/wardby-icon-512.png +0 -0
- package/docs/assets/brand/wardby-icon.svg +16 -0
- package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
- package/docs/assets/brand/wardby-mascot.png +0 -0
- package/docs/assets/brand/wardby-mascot.svg +5 -0
- package/docs/assets/wardby-workflow.svg +106 -0
- package/docs/code-review-agents.md +481 -0
- package/docs/coding-agent-setup.md +172 -0
- package/docs/coding-packages.md +455 -0
- package/docs/coding-services.md +300 -0
- package/docs/coding-worker-byo-images.md +98 -0
- package/docs/coding-worker-isolation.md +1061 -0
- package/docs/getting-started-gke.md +615 -0
- package/docs/getting-started-identity-provider.md +308 -0
- package/docs/getting-started.md +133 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +657 -0
- package/help/code-review-agents.md +31 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/creating-agents.md +68 -0
- package/help/deploy-gke.md +39 -0
- package/help/deployment-targets.md +39 -0
- package/help/errors/budget-group-exhausted.md +25 -0
- package/help/errors/docker-isolation-unsupported.md +26 -0
- package/help/errors/protected-path.md +45 -0
- package/help/errors/repo-access.md +27 -0
- package/help/errors/service-declaration-invalid.md +27 -0
- package/help/errors/service-declaration-unavailable.md +25 -0
- package/help/errors/service-launcher-unsupported.md +30 -0
- package/help/errors/service-not-allowed.md +27 -0
- package/help/errors/service-unknown.md +23 -0
- package/help/errors/service-unready.md +49 -0
- package/help/getting-started.md +31 -0
- package/help/github.md +30 -0
- package/help/identity-and-access.md +39 -0
- package/help/mcp.md +30 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +30 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +26 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +12 -3
- package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
- package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
- package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
- package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
- package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
- package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
- package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
- package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
- package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
- package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
- package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
- package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
- package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
- package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
- package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
- package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
- package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
- package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
- package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
- package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
- package/prisma/schema.prisma +407 -21
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-agent package allowlist and policy model: parsing raw allowlist
|
|
3
|
+
* strings (via each ecosystem's adapter) into `AllowlistEntry` values, and
|
|
4
|
+
* matching a normalized package name against them.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
export const DEFAULT_MIN_RELEASE_AGE_DAYS = 3;
|
|
8
|
+
const PolicySchema = z
|
|
9
|
+
.object({ minReleaseAgeDays: z.number().int().min(0).max(30).default(DEFAULT_MIN_RELEASE_AGE_DAYS) })
|
|
10
|
+
.strict();
|
|
11
|
+
export function resolvePolicy(value) {
|
|
12
|
+
return PolicySchema.parse(value ?? {});
|
|
13
|
+
}
|
|
14
|
+
export function parseAllowlist(allowlist, adapters) {
|
|
15
|
+
const parsed = new Map();
|
|
16
|
+
for (const [ecosystem, entries] of Object.entries(allowlist)) {
|
|
17
|
+
const adapter = adapters.get(ecosystem);
|
|
18
|
+
if (!adapter)
|
|
19
|
+
throw new Error(`unknown package ecosystem "${ecosystem}"`);
|
|
20
|
+
parsed.set(ecosystem, entries.map((entry) => adapter.parseAllowlistEntry(entry)));
|
|
21
|
+
}
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
export function matchRoot(entries, normalizedName) {
|
|
25
|
+
return entries.find((entry) => entry.wildcard
|
|
26
|
+
? normalizedName.startsWith(entry.name) && normalizedName.length > entry.name.length
|
|
27
|
+
: entry.name === normalizedName);
|
|
28
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A streaming scan for one top-level member of a JSON object document,
|
|
3
|
+
* without ever holding the document: only the wanted member's value text is
|
|
4
|
+
* kept (bounded), and every other value, however large, is skipped as it
|
|
5
|
+
* streams past. Used to read an npm packument's `time` (per-version publish
|
|
6
|
+
* times), which comes after `versions` and can follow tens of MB of it.
|
|
7
|
+
*
|
|
8
|
+
* It is a tokenizer, not a validator: it tracks strings, escapes and
|
|
9
|
+
* nesting depth, which is all that locating a top-level member needs. The
|
|
10
|
+
* captured value is then parsed with JSON.parse, so a malformed value
|
|
11
|
+
* throws there. A document that is not an object, or that ends before the
|
|
12
|
+
* member closes, yields null.
|
|
13
|
+
*/
|
|
14
|
+
export declare class JsonMemberTooLarge extends Error {
|
|
15
|
+
}
|
|
16
|
+
export declare class TopLevelMemberScanner {
|
|
17
|
+
private readonly wanted;
|
|
18
|
+
private readonly maxValueLength;
|
|
19
|
+
private depth;
|
|
20
|
+
private inString;
|
|
21
|
+
private escape;
|
|
22
|
+
/** At depth 1, the next string is a key. */
|
|
23
|
+
private expectKey;
|
|
24
|
+
private collectingKey;
|
|
25
|
+
private key;
|
|
26
|
+
private lastKey;
|
|
27
|
+
/** After `"<wanted>":`, waiting for the value's first character. */
|
|
28
|
+
private pending;
|
|
29
|
+
private capturing;
|
|
30
|
+
private captured;
|
|
31
|
+
private capturedLength;
|
|
32
|
+
private finished;
|
|
33
|
+
private result;
|
|
34
|
+
private started;
|
|
35
|
+
constructor(wanted: string, maxValueLength: number);
|
|
36
|
+
/** True once the member was captured (or proven absent or not an
|
|
37
|
+
* object), so the caller may stop reading. */
|
|
38
|
+
get done(): boolean;
|
|
39
|
+
/** The member's value, parsed; undefined while scanning or when absent. */
|
|
40
|
+
get value(): unknown;
|
|
41
|
+
/** Feeds the next decoded text. Throws JsonMemberTooLarge when the
|
|
42
|
+
* member's value exceeds its bound. */
|
|
43
|
+
push(text: string): void;
|
|
44
|
+
private appendKey;
|
|
45
|
+
private capture;
|
|
46
|
+
private finish;
|
|
47
|
+
}
|
|
48
|
+
/** Reads `stream` (UTF-8 JSON) until the top-level member `wanted` has
|
|
49
|
+
* been captured, then cancels the rest. Returns its parsed value, or
|
|
50
|
+
* undefined when the document has no such object-valued member. At most
|
|
51
|
+
* `maxBytes` of the stream are read; more throws JsonMemberTooLarge. */
|
|
52
|
+
export declare function scanTopLevelMember(stream: ReadableStream<Uint8Array>, wanted: string, limits: {
|
|
53
|
+
maxBytes: number;
|
|
54
|
+
maxValueLength: number;
|
|
55
|
+
}): Promise<unknown>;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A streaming scan for one top-level member of a JSON object document,
|
|
3
|
+
* without ever holding the document: only the wanted member's value text is
|
|
4
|
+
* kept (bounded), and every other value, however large, is skipped as it
|
|
5
|
+
* streams past. Used to read an npm packument's `time` (per-version publish
|
|
6
|
+
* times), which comes after `versions` and can follow tens of MB of it.
|
|
7
|
+
*
|
|
8
|
+
* It is a tokenizer, not a validator: it tracks strings, escapes and
|
|
9
|
+
* nesting depth, which is all that locating a top-level member needs. The
|
|
10
|
+
* captured value is then parsed with JSON.parse, so a malformed value
|
|
11
|
+
* throws there. A document that is not an object, or that ends before the
|
|
12
|
+
* member closes, yields null.
|
|
13
|
+
*/
|
|
14
|
+
/** Longest top-level key compared; a longer one cannot be the wanted key. */
|
|
15
|
+
const MAX_KEY_LENGTH = 256;
|
|
16
|
+
export class JsonMemberTooLarge extends Error {
|
|
17
|
+
}
|
|
18
|
+
export class TopLevelMemberScanner {
|
|
19
|
+
wanted;
|
|
20
|
+
maxValueLength;
|
|
21
|
+
depth = 0;
|
|
22
|
+
inString = false;
|
|
23
|
+
escape = false;
|
|
24
|
+
/** At depth 1, the next string is a key. */
|
|
25
|
+
expectKey = false;
|
|
26
|
+
collectingKey = false;
|
|
27
|
+
key = "";
|
|
28
|
+
lastKey;
|
|
29
|
+
/** After `"<wanted>":`, waiting for the value's first character. */
|
|
30
|
+
pending = false;
|
|
31
|
+
capturing = false;
|
|
32
|
+
captured = [];
|
|
33
|
+
capturedLength = 0;
|
|
34
|
+
finished = false;
|
|
35
|
+
result = undefined;
|
|
36
|
+
started = false;
|
|
37
|
+
constructor(wanted, maxValueLength) {
|
|
38
|
+
this.wanted = wanted;
|
|
39
|
+
this.maxValueLength = maxValueLength;
|
|
40
|
+
}
|
|
41
|
+
/** True once the member was captured (or proven absent or not an
|
|
42
|
+
* object), so the caller may stop reading. */
|
|
43
|
+
get done() {
|
|
44
|
+
return this.finished;
|
|
45
|
+
}
|
|
46
|
+
/** The member's value, parsed; undefined while scanning or when absent. */
|
|
47
|
+
get value() {
|
|
48
|
+
return this.result;
|
|
49
|
+
}
|
|
50
|
+
/** Feeds the next decoded text. Throws JsonMemberTooLarge when the
|
|
51
|
+
* member's value exceeds its bound. */
|
|
52
|
+
push(text) {
|
|
53
|
+
if (this.finished)
|
|
54
|
+
return;
|
|
55
|
+
let segmentStart = this.capturing ? 0 : -1;
|
|
56
|
+
const length = text.length;
|
|
57
|
+
let i = 0;
|
|
58
|
+
while (i < length) {
|
|
59
|
+
if (this.inString) {
|
|
60
|
+
if (this.escape) {
|
|
61
|
+
this.escape = false;
|
|
62
|
+
if (this.collectingKey)
|
|
63
|
+
this.appendKey(text[i]);
|
|
64
|
+
i += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Skip ahead to the next quote or backslash: the bulk of a
|
|
68
|
+
// packument is string content, never looked at char by char.
|
|
69
|
+
const quote = text.indexOf('"', i);
|
|
70
|
+
const backslash = text.indexOf("\\", i);
|
|
71
|
+
const stop = quote < 0 ? backslash : backslash < 0 ? quote : Math.min(quote, backslash);
|
|
72
|
+
if (stop < 0) {
|
|
73
|
+
if (this.collectingKey)
|
|
74
|
+
this.appendKey(text.slice(i));
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
if (this.collectingKey)
|
|
78
|
+
this.appendKey(text.slice(i, stop));
|
|
79
|
+
if (stop === backslash) {
|
|
80
|
+
this.escape = true;
|
|
81
|
+
if (this.collectingKey)
|
|
82
|
+
this.appendKey("\\");
|
|
83
|
+
i = stop + 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
this.inString = false;
|
|
87
|
+
if (this.collectingKey) {
|
|
88
|
+
this.collectingKey = false;
|
|
89
|
+
this.lastKey = this.key;
|
|
90
|
+
}
|
|
91
|
+
i = stop + 1;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const c = text[i];
|
|
95
|
+
if (c === " " || c === "\n" || c === "\r" || c === "\t") {
|
|
96
|
+
i += 1;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (!this.started) {
|
|
100
|
+
this.started = true;
|
|
101
|
+
if (c !== "{")
|
|
102
|
+
return this.finish(undefined);
|
|
103
|
+
}
|
|
104
|
+
if (this.pending) {
|
|
105
|
+
this.pending = false;
|
|
106
|
+
if (c !== "{")
|
|
107
|
+
return this.finish(undefined);
|
|
108
|
+
this.capturing = true;
|
|
109
|
+
segmentStart = i;
|
|
110
|
+
}
|
|
111
|
+
if (c === '"') {
|
|
112
|
+
this.inString = true;
|
|
113
|
+
if (this.depth === 1 && this.expectKey) {
|
|
114
|
+
this.collectingKey = true;
|
|
115
|
+
this.key = "";
|
|
116
|
+
this.expectKey = false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else if (c === "{" || c === "[") {
|
|
120
|
+
this.depth += 1;
|
|
121
|
+
if (this.depth === 1)
|
|
122
|
+
this.expectKey = true;
|
|
123
|
+
}
|
|
124
|
+
else if (c === "}" || c === "]") {
|
|
125
|
+
this.depth -= 1;
|
|
126
|
+
if (this.capturing && this.depth === 1) {
|
|
127
|
+
this.capture(text.slice(segmentStart, i + 1));
|
|
128
|
+
return this.finish(JSON.parse(this.captured.join("")));
|
|
129
|
+
}
|
|
130
|
+
if (this.depth === 0)
|
|
131
|
+
return this.finish(undefined);
|
|
132
|
+
}
|
|
133
|
+
else if (c === ":") {
|
|
134
|
+
if (this.depth === 1 && this.lastKey === this.wanted)
|
|
135
|
+
this.pending = true;
|
|
136
|
+
}
|
|
137
|
+
else if (c === ",") {
|
|
138
|
+
if (this.depth === 1) {
|
|
139
|
+
this.expectKey = true;
|
|
140
|
+
this.lastKey = undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
i += 1;
|
|
144
|
+
}
|
|
145
|
+
if (this.capturing && segmentStart >= 0)
|
|
146
|
+
this.capture(text.slice(segmentStart));
|
|
147
|
+
}
|
|
148
|
+
appendKey(part) {
|
|
149
|
+
if (this.key.length <= MAX_KEY_LENGTH)
|
|
150
|
+
this.key += part.slice(0, MAX_KEY_LENGTH + 1 - this.key.length);
|
|
151
|
+
}
|
|
152
|
+
capture(part) {
|
|
153
|
+
this.capturedLength += part.length;
|
|
154
|
+
if (this.capturedLength > this.maxValueLength)
|
|
155
|
+
throw new JsonMemberTooLarge(`"${this.wanted}" is too large`);
|
|
156
|
+
this.captured.push(part);
|
|
157
|
+
}
|
|
158
|
+
finish(value) {
|
|
159
|
+
this.finished = true;
|
|
160
|
+
this.result = value;
|
|
161
|
+
this.captured = [];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/** Reads `stream` (UTF-8 JSON) until the top-level member `wanted` has
|
|
165
|
+
* been captured, then cancels the rest. Returns its parsed value, or
|
|
166
|
+
* undefined when the document has no such object-valued member. At most
|
|
167
|
+
* `maxBytes` of the stream are read; more throws JsonMemberTooLarge. */
|
|
168
|
+
export async function scanTopLevelMember(stream, wanted, limits) {
|
|
169
|
+
const scanner = new TopLevelMemberScanner(wanted, limits.maxValueLength);
|
|
170
|
+
const decoder = new TextDecoder("utf-8");
|
|
171
|
+
const reader = stream.getReader();
|
|
172
|
+
let bytes = 0;
|
|
173
|
+
try {
|
|
174
|
+
for (;;) {
|
|
175
|
+
const { done, value } = await reader.read();
|
|
176
|
+
if (done) {
|
|
177
|
+
scanner.push(decoder.decode());
|
|
178
|
+
return scanner.value;
|
|
179
|
+
}
|
|
180
|
+
bytes += value.byteLength;
|
|
181
|
+
if (bytes > limits.maxBytes)
|
|
182
|
+
throw new JsonMemberTooLarge(`the document is larger than ${limits.maxBytes} bytes`);
|
|
183
|
+
scanner.push(decoder.decode(value, { stream: true }));
|
|
184
|
+
if (scanner.done)
|
|
185
|
+
return scanner.value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
await reader.cancel().catch(() => undefined);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rewrites the proxy download URLs a package manager records in lockfiles
|
|
3
|
+
* back to public ones, for every adapter with a `lockfiles` hook. The driver
|
|
4
|
+
* runs this on the workspace before it is collected, so a committed lockfile
|
|
5
|
+
* never points at the sandbox-only proxy host.
|
|
6
|
+
*
|
|
7
|
+
* Best effort by design: a file that cannot be read or written safely is
|
|
8
|
+
* skipped, never a reason to fail the run. The walk never follows symlinks
|
|
9
|
+
* and skips the folders collection excludes by name (dependency and cache
|
|
10
|
+
* folders), which are never sent back anyway.
|
|
11
|
+
*/
|
|
12
|
+
import { constants } from "node:fs";
|
|
13
|
+
import { open, readdir } from "node:fs/promises";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { BUILTIN_COLLECT_EXCLUDE_NAMES } from "../collect-exclude.js";
|
|
16
|
+
import { REGISTRY_ADAPTERS } from "./adapters.js";
|
|
17
|
+
import { registryUrlFor } from "./worker-config.js";
|
|
18
|
+
const MAX_LOCKFILE_BYTES = 64 * 1024 * 1024;
|
|
19
|
+
const MAX_DEPTH = 32;
|
|
20
|
+
const SKIPPED_DIRECTORIES = new Set([...BUILTIN_COLLECT_EXCLUDE_NAMES, ".git"]);
|
|
21
|
+
/** Rewrites one file in place through a single descriptor (no symlinks, no
|
|
22
|
+
* path re-resolution between the checks and the write). Returns whether it
|
|
23
|
+
* changed; any failure leaves the file as it was found or skips it. */
|
|
24
|
+
async function normalizeFile(path, normalize) {
|
|
25
|
+
let file;
|
|
26
|
+
try {
|
|
27
|
+
file = await open(path, constants.O_RDWR | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const metadata = await file.stat();
|
|
34
|
+
if (!metadata.isFile() || metadata.size > MAX_LOCKFILE_BYTES)
|
|
35
|
+
return false;
|
|
36
|
+
const before = (await file.readFile()).toString("utf8");
|
|
37
|
+
const after = normalize(before);
|
|
38
|
+
if (after === before)
|
|
39
|
+
return false;
|
|
40
|
+
await file.truncate(0);
|
|
41
|
+
await file.write(after, 0, "utf8");
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
await file.close();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Normalises every recognised lockfile under `workspace`; returns the
|
|
52
|
+
* workspace-relative paths it rewrote, sorted. */
|
|
53
|
+
export async function normalizeRegistryLockfiles(input) {
|
|
54
|
+
const byName = new Map();
|
|
55
|
+
for (const adapter of REGISTRY_ADAPTERS.values()) {
|
|
56
|
+
const lockfiles = adapter.lockfiles;
|
|
57
|
+
if (!lockfiles)
|
|
58
|
+
continue;
|
|
59
|
+
const registryUrl = registryUrlFor(input.proxyBaseUrl, adapter.id);
|
|
60
|
+
for (const name of lockfiles.names)
|
|
61
|
+
byName.set(name, (content) => lockfiles.normalize(content, registryUrl));
|
|
62
|
+
}
|
|
63
|
+
const rewritten = [];
|
|
64
|
+
const walk = async (relative, depth) => {
|
|
65
|
+
let entries;
|
|
66
|
+
try {
|
|
67
|
+
entries = await readdir(join(input.workspace, relative), { withFileTypes: true });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
const path = relative ? `${relative}/${entry.name}` : entry.name;
|
|
74
|
+
// Dirent types come from lstat semantics: a symlink is neither a directory nor a file here.
|
|
75
|
+
if (entry.isDirectory()) {
|
|
76
|
+
if (depth < MAX_DEPTH && !SKIPPED_DIRECTORIES.has(entry.name))
|
|
77
|
+
await walk(path, depth + 1);
|
|
78
|
+
}
|
|
79
|
+
else if (entry.isFile()) {
|
|
80
|
+
const normalize = byName.get(entry.name);
|
|
81
|
+
if (normalize && (await normalizeFile(join(input.workspace, path), normalize)))
|
|
82
|
+
rewritten.push(path);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
if (byName.size > 0)
|
|
87
|
+
await walk("", 0);
|
|
88
|
+
return rewritten.sort();
|
|
89
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Same shape as the adapter's allowlist name check (scoped names are lower case). */
|
|
2
|
+
export declare const PACKAGE_NAME: RegExp;
|
|
3
|
+
/** `https://registry.npmjs.org/@scope/pkg/-/pkg-1.0.0.tgz` */
|
|
4
|
+
export declare function publicNpmTarballUrl(name: string, version: string): string;
|
|
5
|
+
export declare function normalizeNpmLockfile(content: string, registryUrl: string): string;
|
|
6
|
+
export declare const npmLockfiles: {
|
|
7
|
+
readonly names: readonly ["package-lock.json", "npm-shrinkwrap.json"];
|
|
8
|
+
readonly normalize: typeof normalizeNpmLockfile;
|
|
9
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm lockfile normaliser. The npm adapter serves metadata whose tarball
|
|
3
|
+
* links point at the proxy, so `npm install` in the worker records those
|
|
4
|
+
* proxy URLs as `resolved` in package-lock.json / npm-shrinkwrap.json. They
|
|
5
|
+
* only resolve inside the sandbox, so before the workspace is collected every
|
|
6
|
+
* `resolved` value under the proxy's npm route is rewritten to the canonical
|
|
7
|
+
* public registry URL for the same package and version. `integrity` is left
|
|
8
|
+
* as is: it covers the same tarball bytes. Only the matched values change;
|
|
9
|
+
* the rest of the file stays byte-for-byte identical (no JSON round trip).
|
|
10
|
+
*
|
|
11
|
+
* Kept free of imports from npm.ts, which imports this module.
|
|
12
|
+
*/
|
|
13
|
+
import semver from "semver";
|
|
14
|
+
const PUBLIC_REGISTRY = "https://registry.npmjs.org/";
|
|
15
|
+
/** Same shape as the adapter's allowlist name check (scoped names are lower case). */
|
|
16
|
+
export const PACKAGE_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/[a-z0-9-~][a-z0-9-._~]*|[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/;
|
|
17
|
+
/** A `"resolved": "<value>"` pair whose value has no JSON escapes. */
|
|
18
|
+
const RESOLVED = /("resolved"\s*:\s*")([^"\\]*)(")/g;
|
|
19
|
+
function decode(value) {
|
|
20
|
+
try {
|
|
21
|
+
return decodeURIComponent(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function unscoped(name) {
|
|
28
|
+
return name.slice(name.indexOf("/") + 1);
|
|
29
|
+
}
|
|
30
|
+
/** The package and version a path under the proxy's npm base downloads:
|
|
31
|
+
* `-/tarball/<encoded name>/<version>` (the proxy's own route) or the
|
|
32
|
+
* standard `<name>/-/<unscoped>-<version>.tgz`, with the scope separator
|
|
33
|
+
* literal or percent-encoded. Null for anything else. */
|
|
34
|
+
function parseProxyPath(path) {
|
|
35
|
+
let name;
|
|
36
|
+
let version;
|
|
37
|
+
const own = path.match(/^-\/tarball\/([^/]+)\/([^/]+)$/);
|
|
38
|
+
if (own) {
|
|
39
|
+
name = decode(own[1]);
|
|
40
|
+
version = decode(own[2]);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const standard = path.match(/^(.+)\/-\/([^/]+)\.tgz$/);
|
|
44
|
+
if (!standard)
|
|
45
|
+
return null;
|
|
46
|
+
name = decode(standard[1]);
|
|
47
|
+
const file = decode(standard[2]);
|
|
48
|
+
if (!name || !file)
|
|
49
|
+
return null;
|
|
50
|
+
const prefix = `${unscoped(name)}-`;
|
|
51
|
+
version = file.startsWith(prefix) ? file.slice(prefix.length) : null;
|
|
52
|
+
}
|
|
53
|
+
if (!name || !version || !PACKAGE_NAME.test(name) || semver.valid(version) !== version)
|
|
54
|
+
return null;
|
|
55
|
+
return { name, version };
|
|
56
|
+
}
|
|
57
|
+
/** `https://registry.npmjs.org/@scope/pkg/-/pkg-1.0.0.tgz` */
|
|
58
|
+
export function publicNpmTarballUrl(name, version) {
|
|
59
|
+
return `${PUBLIC_REGISTRY}${name}/-/${unscoped(name)}-${version}.tgz`;
|
|
60
|
+
}
|
|
61
|
+
export function normalizeNpmLockfile(content, registryUrl) {
|
|
62
|
+
const base = registryUrl.endsWith("/") ? registryUrl : `${registryUrl}/`;
|
|
63
|
+
return content.replace(RESOLVED, (match, open, url, close) => {
|
|
64
|
+
if (!url.startsWith(base))
|
|
65
|
+
return match;
|
|
66
|
+
const target = parseProxyPath(url.slice(base.length));
|
|
67
|
+
return target ? `${open}${publicNpmTarballUrl(target.name, target.version)}${close}` : match;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export const npmLockfiles = {
|
|
71
|
+
names: ["package-lock.json", "npm-shrinkwrap.json"],
|
|
72
|
+
normalize: normalizeNpmLockfile,
|
|
73
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type DeclaredDependency, type LockfilePlanSupport, type ParsedLockfile, type UpstreamFetch, type VersionFact } from "./types.js";
|
|
2
|
+
/** The registry dependencies a manifest's dependency map declares: each
|
|
3
|
+
* one's install folder (`key`), the registry package it installs (an
|
|
4
|
+
* alias `"string-width-cjs": "npm:string-width@^4"` installs its target,
|
|
5
|
+
* under the alias's own range) and its range. A spec that isn't fetched
|
|
6
|
+
* from the registry at all (`file:`, `link:`, a path, `git`/`git+…`, an
|
|
7
|
+
* `http(s):` tarball, `github:`/`user/repo` shorthands, `workspace:`)
|
|
8
|
+
* contributes nothing: every such spec contains a `:` or a `/`, which no
|
|
9
|
+
* semver range or dist-tag does. */
|
|
10
|
+
export declare function registryDependencyEdges(deps: unknown): DeclaredDependency[];
|
|
11
|
+
/** Every registry dependency a manifest declares, in npm's install order
|
|
12
|
+
* (dependencies, optionalDependencies, peerDependencies), once per
|
|
13
|
+
* install folder: npm lists an optional dependency under `dependencies`
|
|
14
|
+
* too, and the first declaration of a folder is the one npm uses. */
|
|
15
|
+
export declare function declaredDependencies(manifest: Record<string, unknown>, fields: readonly string[]): DeclaredDependency[];
|
|
16
|
+
export declare function parseNpmLockfile(body: string, options: {
|
|
17
|
+
maxEntries: number;
|
|
18
|
+
proxyRegistryUrl: string;
|
|
19
|
+
}): ParsedLockfile;
|
|
20
|
+
export declare function fetchNpmVersionFact(name: string, version: string, upstream: UpstreamFetch, signal?: AbortSignal): Promise<VersionFact | null>;
|
|
21
|
+
export declare function fetchNpmPublishTimes(name: string, versions: readonly string[], upstream: UpstreamFetch, options: {
|
|
22
|
+
maxBytes: number;
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}): Promise<Map<string, Date>>;
|
|
25
|
+
/** Whether a locked version satisfies a declared range: `*` and dist-tags
|
|
26
|
+
* accept any version (as npm's own dep-valid does), otherwise strict semver,
|
|
27
|
+
* the same match the graph walk uses. */
|
|
28
|
+
export declare function npmEdgeSatisfies(version: string, range: string): boolean;
|
|
29
|
+
export declare const npmLockfilePlan: LockfilePlanSupport;
|