@wardby/cli 0.2.0 → 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 +183 -71
- package/dist/claude-coding-worker/driver.d.ts +7 -1
- package/dist/claude-coding-worker/driver.js +31 -2
- package/dist/claude-coding-worker/main.js +5 -2
- 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 +99 -3
- package/dist/coding/protocol.js +155 -4
- 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 +18 -0
- package/dist/coding-worker/artifact.js +48 -6
- 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 +14 -1
- package/dist/coding-worker/driver.js +106 -14
- package/dist/coding-worker/errors.d.ts +7 -0
- package/dist/coding-worker/errors.js +26 -0
- package/dist/coding-worker/main.js +13 -4
- 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 +109 -6
- 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/coding-queue.d.ts +1 -1
- package/dist/core/datastores.d.ts +1 -1
- package/dist/core/datastores.js +18 -2
- package/dist/core/db.d.ts +40 -2
- package/dist/core/db.js +75 -2
- package/dist/core/dispatch.d.ts +49 -7
- package/dist/core/dispatch.js +290 -45
- 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/http-runtime.js +3 -4
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/lease.d.ts +1 -1
- package/dist/core/private-directory.d.ts +20 -0
- package/dist/core/private-directory.js +36 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +39 -3
- 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 +31 -9
- package/dist/core/runner.js +237 -40
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/secrets.d.ts +12 -3
- package/dist/core/secrets.js +25 -6
- package/dist/core/subagent-memory-tools.d.ts +2 -2
- 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 +9 -2
- package/dist/core/webhooks.js +23 -2
- package/dist/generated/prisma/browser.d.ts +328 -0
- package/dist/generated/prisma/browser.js +17 -0
- package/dist/generated/prisma/client.d.ts +347 -0
- package/dist/generated/prisma/client.js +34 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +839 -0
- package/dist/generated/prisma/commonInputTypes.js +10 -0
- package/dist/generated/prisma/enums.d.ts +59 -0
- package/dist/generated/prisma/enums.js +59 -0
- package/dist/generated/prisma/internal/class.d.ts +605 -0
- package/dist/generated/prisma/internal/class.js +49 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +4494 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +628 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +635 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +599 -0
- package/dist/generated/prisma/models/Agent.d.ts +3560 -0
- package/dist/generated/prisma/models/Agent.js +1 -0
- package/dist/generated/prisma/models/AgentDatastore.d.ts +1210 -0
- package/dist/generated/prisma/models/AgentDatastore.js +1 -0
- package/dist/generated/prisma/models/AgentMemory.d.ts +986 -0
- package/dist/generated/prisma/models/AgentMemory.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
- package/dist/generated/prisma/models/AgentRepository.js +1 -0
- package/dist/generated/prisma/models/AgentSecret.d.ts +1212 -0
- package/dist/generated/prisma/models/AgentSecret.js +1 -0
- package/dist/generated/prisma/models/AgentSubAgent.d.ts +1217 -0
- package/dist/generated/prisma/models/AgentSubAgent.js +1 -0
- package/dist/generated/prisma/models/AgentTool.d.ts +1403 -0
- package/dist/generated/prisma/models/AgentTool.js +1 -0
- package/dist/generated/prisma/models/AuthFormChallenge.d.ts +1298 -0
- package/dist/generated/prisma/models/AuthFormChallenge.js +1 -0
- package/dist/generated/prisma/models/AuthLoginKey.d.ts +1245 -0
- package/dist/generated/prisma/models/AuthLoginKey.js +1 -0
- package/dist/generated/prisma/models/AuthRateLimit.d.ts +979 -0
- package/dist/generated/prisma/models/AuthRateLimit.js +1 -0
- package/dist/generated/prisma/models/AuthSession.d.ts +1376 -0
- package/dist/generated/prisma/models/AuthSession.js +1 -0
- package/dist/generated/prisma/models/AuthUser.d.ts +1700 -0
- package/dist/generated/prisma/models/AuthUser.js +1 -0
- package/dist/generated/prisma/models/BudgetGroup.d.ts +1548 -0
- package/dist/generated/prisma/models/BudgetGroup.js +1 -0
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +1681 -0
- package/dist/generated/prisma/models/CodingAgentProfile.js +1 -0
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +1749 -0
- package/dist/generated/prisma/models/CodingProxyRequest.js +1 -0
- package/dist/generated/prisma/models/CodingProxySession.d.ts +1626 -0
- package/dist/generated/prisma/models/CodingProxySession.js +1 -0
- package/dist/generated/prisma/models/CodingRun.d.ts +3583 -0
- package/dist/generated/prisma/models/CodingRun.js +1 -0
- package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
- package/dist/generated/prisma/models/CodingService.js +1 -0
- package/dist/generated/prisma/models/Datastore.d.ts +1434 -0
- package/dist/generated/prisma/models/Datastore.js +1 -0
- package/dist/generated/prisma/models/DatastoreEntry.d.ts +1314 -0
- package/dist/generated/prisma/models/DatastoreEntry.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/OAuthAuthorizationCode.d.ts +1526 -0
- package/dist/generated/prisma/models/OAuthAuthorizationCode.js +1 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.d.ts +1350 -0
- package/dist/generated/prisma/models/OAuthAuthorizationRequest.js +1 -0
- package/dist/generated/prisma/models/OAuthClient.d.ts +1289 -0
- package/dist/generated/prisma/models/OAuthClient.js +1 -0
- package/dist/generated/prisma/models/OAuthFamily.d.ts +1540 -0
- package/dist/generated/prisma/models/OAuthFamily.js +1 -0
- package/dist/generated/prisma/models/OAuthGrant.d.ts +1280 -0
- package/dist/generated/prisma/models/OAuthGrant.js +1 -0
- package/dist/generated/prisma/models/Principal.d.ts +2245 -0
- package/dist/generated/prisma/models/Principal.js +1 -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 +2669 -0
- package/dist/generated/prisma/models/Run.js +1 -0
- 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/SchedulerLease.d.ts +970 -0
- package/dist/generated/prisma/models/SchedulerLease.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +1399 -0
- package/dist/generated/prisma/models/Secret.js +1 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.d.ts +973 -0
- package/dist/generated/prisma/models/SecretElicitationOutcome.js +1 -0
- package/dist/generated/prisma/models/Task.d.ts +1176 -0
- package/dist/generated/prisma/models/Task.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +1490 -0
- package/dist/generated/prisma/models/Tool.js +1 -0
- package/dist/generated/prisma/models/Webhook.d.ts +1386 -0
- package/dist/generated/prisma/models/Webhook.js +1 -0
- package/dist/generated/prisma/models.d.ts +45 -0
- package/dist/generated/prisma/models.js +1 -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 +6 -1
- package/dist/import/create.js +68 -14
- package/dist/import/index.d.ts +1 -1
- 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 +37 -63
- package/dist/mcp/auth/ownership.js +19 -14
- package/dist/mcp/auth/principal.d.ts +1 -1
- 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 +32 -3
- package/dist/mcp/auth/resource-server.js +84 -3
- package/dist/mcp/auth/self-hosted/browser.js +22 -8
- package/dist/mcp/auth/self-hosted/cli.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/cli.js +47 -13
- package/dist/mcp/auth/self-hosted/credentials.d.ts +21 -3
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/rate-limit.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/session.d.ts +3 -2
- package/dist/mcp/context.d.ts +28 -2
- 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.d.ts +1 -1
- package/dist/mcp/server.js +27 -9
- package/dist/mcp/shared/page-style.d.ts +16 -0
- package/dist/mcp/shared/page-style.js +129 -0
- package/dist/mcp/tasks/manager.d.ts +1 -1
- package/dist/mcp/tools/agents.js +447 -49
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/datastore.js +23 -16
- 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 +4 -7
- package/dist/mcp/tools/secret-elicitation-form.d.ts +1 -1
- package/dist/mcp/tools/secret-elicitation-form.js +10 -28
- package/dist/mcp/tools/secret-elicitation.d.ts +1 -1
- 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 +53 -17
- package/dist/mcp/tools/tools.d.ts +41 -0
- package/dist/mcp/tools/tools.js +202 -41
- package/dist/mcp/tools/trigger.js +36 -6
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +11 -1
- package/dist/mcp/transport/streamable-http.js +32 -2
- package/dist/mcp/unattended-schedules.d.ts +1 -1
- package/dist/mcp/webhooks/ingress.d.ts +1 -1
- package/dist/providers/auth/delegating.d.ts +19 -0
- package/dist/providers/auth/delegating.js +71 -0
- package/dist/providers/auth/index.d.ts +3 -1
- package/dist/providers/auth/index.js +11 -0
- package/dist/providers/auth/self-hosted.d.ts +4 -3
- 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 +18 -1
- 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 +18 -1
- 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/datastore/postgres.d.ts +1 -1
- package/dist/providers/engine/types.d.ts +10 -0
- package/dist/providers/executor/build.d.ts +3 -3
- package/dist/providers/executor/composition.d.ts +4 -1
- package/dist/providers/executor/composition.js +19 -0
- package/dist/providers/executor/container.d.ts +106 -4
- package/dist/providers/executor/container.js +305 -22
- package/dist/providers/executor/dbos.d.ts +3 -4
- 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 +60 -2
- package/dist/providers/jobs/docker.js +313 -50
- 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 +117 -31
- package/dist/providers/jobs/types.d.ts +20 -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/memory/postgres.d.ts +1 -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 +79 -14
- 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 +34 -32
- package/dist/quickstart/migrate.d.ts +23 -0
- package/dist/quickstart/migrate.js +125 -0
- 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 +30 -11
- package/prisma/migrate.config.mjs +20 -0
- 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 +417 -23
|
@@ -29,20 +29,26 @@ import { finished } from "node:stream/promises";
|
|
|
29
29
|
import { createHash } from "node:crypto";
|
|
30
30
|
import { isIP } from "node:net";
|
|
31
31
|
import { logger } from "../../core/logger.js";
|
|
32
|
-
import { MAX_CODING_ARTIFACT_BYTES, parseCodingAgentOutputJson } from "../../coding/protocol.js";
|
|
32
|
+
import { MAX_CODING_ARTIFACT_BYTES, MAX_DEBUG_TRACE_LINE_BYTES, parseCodingAgentOutputJson, } from "../../coding/protocol.js";
|
|
33
33
|
import { CODING_PROXY_DENY_PORT, CODING_PROXY_PORT } from "./docker-isolation.js";
|
|
34
|
-
import {
|
|
34
|
+
import { parseWorkerDiagnosticLine } from "./docker.js";
|
|
35
35
|
import { KubernetesAlreadyExistsError, KubernetesConflictError } from "./kubernetes-api.js";
|
|
36
|
-
import { ENFORCEMENT_PROBE_DENY_REACHABLE, ENFORCEMENT_PROBE_PROVEN, ENFORCEMENT_PROBE_DENY_REFUSED, ENFORCEMENT_PROBE_PROXY_UNREACHABLE, KEEPER_CONTAINER, KEEPER_SEEDED_MARKER, KUBERNETES_ISOLATION_ERROR, STORAGE_ROOT, WORKER_CONTAINER, assertRunNetworkPolicyMatches, assertRunPodMatches, buildCapabilitySecret, buildRunNetworkPolicy, buildRunPod, enforcementProbeScript, kubernetesRunNames, kubernetesRunNamesForToken, runLabels, validateKubernetesSpec, } from "./kubernetes-isolation.js";
|
|
36
|
+
import { ENFORCEMENT_PROBE_DENY_REACHABLE, ENFORCEMENT_PROBE_PROVEN, ENFORCEMENT_PROBE_DENY_REFUSED, ENFORCEMENT_PROBE_PROXY_UNREACHABLE, KEEPER_CONTAINER, KEEPER_SEEDED_MARKER, KUBERNETES_ISOLATION_ERROR, STORAGE_ROOT, TOOL_RUNNER_CONTAINER, WORKER_CONTAINER, assertRunNetworkPolicyMatches, assertRunPodMatches, buildCapabilitySecret, buildRunNetworkPolicy, buildRunPod, enforcementProbeScript, kubernetesRunNames, kubernetesRunNamesForToken, runLabels, serviceContainerName, validateKubernetesSpec, } from "./kubernetes-isolation.js";
|
|
37
|
+
import { claudeToolSetup } from "./claude-tool-setup.js";
|
|
37
38
|
import { readProxyWitness } from "./kubernetes-witness.js";
|
|
38
39
|
import { safeExtract } from "./safe-extract.js";
|
|
40
|
+
import { serviceUnreadyError } from "../../coding/services/wording.js";
|
|
39
41
|
import { replaceDirectoryFromStaging } from "./workspace-swap.js";
|
|
42
|
+
import { collectExclusions, normalizeCollectExclusions, tarExcludeArgs, } from "../../coding/collect-exclude.js";
|
|
40
43
|
const BACKEND = "kubernetes";
|
|
41
44
|
const RECORD_SCHEMA_VERSION = 1;
|
|
42
45
|
const RECORD_KEY = "record.json";
|
|
43
46
|
const STOP_GRACE_SECONDS = 10;
|
|
44
47
|
const DIAGNOSTIC_TAIL_LINES = 8;
|
|
45
|
-
|
|
48
|
+
// The API cuts the tail from its FRONT at limitBytes, so this must hold every
|
|
49
|
+
// tail line at full size: a debug-traced run writes lines of up to
|
|
50
|
+
// MAX_DEBUG_TRACE_LINE_BYTES just before its diagnostic line.
|
|
51
|
+
const DIAGNOSTIC_LIMIT_BYTES = DIAGNOSTIC_TAIL_LINES * MAX_DEBUG_TRACE_LINE_BYTES;
|
|
46
52
|
const MAX_WORKSPACE_ENTRIES = 100_000;
|
|
47
53
|
const MAX_RECORD_ATTEMPTS = 5;
|
|
48
54
|
const READY_POLL_MS = 250;
|
|
@@ -51,8 +57,17 @@ const DEFAULT_ENFORCEMENT_TIMEOUT_MS = 30_000;
|
|
|
51
57
|
const ENFORCEMENT_POLL_MS = 500;
|
|
52
58
|
/** Consecutive proven probes required (8787 reachable, 8788 blocked): one dropped SYN must not open the gate. */
|
|
53
59
|
const ENFORCEMENT_BLOCKED_STREAK = 3;
|
|
54
|
-
/**
|
|
55
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Default bound for one enforcement probe exec (the probe makes two sequential connects, so it
|
|
62
|
+
* gives up after at most 6 s of its own connect timeouts). Overridable per KubernetesJobConfig's
|
|
63
|
+
* `enforcementExecTimeoutMs` (KUBERNETES_ENFORCEMENT_EXEC_TIMEOUT_MS) — a resource-constrained
|
|
64
|
+
* keeper (e.g. a laptop `kind` cluster's default 250m CPU / 128Mi limit) can take noticeably
|
|
65
|
+
* longer than this to run even a healthy probe to completion. DEFAULT_ENFORCEMENT_TIMEOUT_MS
|
|
66
|
+
* above is exactly this default times ENFORCEMENT_BLOCKED_STREAK, which is not a coincidence: see
|
|
67
|
+
* the constructor, which derives the effective overall bound the same way from whichever exec
|
|
68
|
+
* timeout is actually configured, so the two never drift apart.
|
|
69
|
+
*/
|
|
70
|
+
const DEFAULT_ENFORCEMENT_EXEC_TIMEOUT_MS = 10_000;
|
|
56
71
|
/**
|
|
57
72
|
* What the gate reports at its bound, by the last probe's exit code. Each names a different place
|
|
58
73
|
* to look, and each carries the reason in its own message rather than in the documentation: an
|
|
@@ -224,6 +239,11 @@ function exitedCleanlyInTime(pod, finishedAt, deadlineAt) {
|
|
|
224
239
|
const finished = new Date(finishedAt).getTime();
|
|
225
240
|
return Number.isFinite(finished) && finished <= deadlineAt + FINISHED_AT_SKEW_MS;
|
|
226
241
|
}
|
|
242
|
+
/** A Claude run's tool runner that restarted or exited: its socket (and any in-flight command) is gone. */
|
|
243
|
+
function toolRunnerFailed(statuses) {
|
|
244
|
+
const tool = statuses?.find((status) => status.name === TOOL_RUNNER_CONTAINER);
|
|
245
|
+
return tool !== undefined && ((tool.restartCount ?? 0) > 0 || tool.state?.terminated !== undefined);
|
|
246
|
+
}
|
|
227
247
|
/** Maps a pod read-back onto the next record state; `undefined` means "no change". Never called for terminal records. */
|
|
228
248
|
function observePod(pod, record, now, readyTimeoutMs) {
|
|
229
249
|
if (!pod) {
|
|
@@ -242,6 +262,16 @@ function observePod(pod, record, now, readyTimeoutMs) {
|
|
|
242
262
|
if (now >= record.deadlineAt || pod.status?.reason === "DeadlineExceeded") {
|
|
243
263
|
return { phase: "failed", result: { exitCode: 124, reason: "timed_out" }, deleteGraceSeconds: STOP_GRACE_SECONDS };
|
|
244
264
|
}
|
|
265
|
+
// Docker's worker_tool_runner_failed, for the same reason: without its tool runner a Claude worker
|
|
266
|
+
// can only stall until the deadline. Checked only while the worker still runs, so a clean finish
|
|
267
|
+
// (checked above) or the pod's own teardown never reads as a tool-runner failure.
|
|
268
|
+
if (!terminated && toolRunnerFailed(pod.status?.initContainerStatuses)) {
|
|
269
|
+
return {
|
|
270
|
+
phase: "failed",
|
|
271
|
+
result: { exitCode: 1, reason: "failed", diagnostic: "worker_tool_runner_failed" },
|
|
272
|
+
deleteGraceSeconds: STOP_GRACE_SECONDS,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
245
275
|
if (terminated) {
|
|
246
276
|
// An exit 0 that failed the guard above (pod being deleted, no usable finish time) is not a success.
|
|
247
277
|
if (terminated.exitCode === 0)
|
|
@@ -328,6 +358,7 @@ export class KubernetesJobLauncher {
|
|
|
328
358
|
createArchive;
|
|
329
359
|
warn;
|
|
330
360
|
enforcementTimeoutMs;
|
|
361
|
+
enforcementExecTimeoutMs;
|
|
331
362
|
preflightResult;
|
|
332
363
|
constructor(options) {
|
|
333
364
|
this.options = options;
|
|
@@ -339,10 +370,24 @@ export class KubernetesJobLauncher {
|
|
|
339
370
|
this.now = options.now ?? Date.now;
|
|
340
371
|
this.sleep = options.sleep ?? ((ms) => new Promise((resolvePromise) => setTimeout(resolvePromise, ms)));
|
|
341
372
|
this.readyTimeoutMs = options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
342
|
-
this.
|
|
373
|
+
this.enforcementExecTimeoutMs = options.enforcementExecTimeoutMs ?? DEFAULT_ENFORCEMENT_EXEC_TIMEOUT_MS;
|
|
374
|
+
// Never less than a full blocked-streak's worth of worst-case probes: a longer configured exec
|
|
375
|
+
// timeout that left this unchanged could make the wall-clock bound expire before the loop ever
|
|
376
|
+
// has a chance to observe ENFORCEMENT_BLOCKED_STREAK consecutive probes, which would turn "the
|
|
377
|
+
// keeper is just slow" into an indistinguishable "the policy is not enforced" false negative.
|
|
378
|
+
// DEFAULT_ENFORCEMENT_TIMEOUT_MS (30_000) already equals the default exec timeout times the
|
|
379
|
+
// streak (10_000 * 3), so this is a no-op unless a longer exec timeout is actually configured.
|
|
380
|
+
this.enforcementTimeoutMs = Math.max(options.enforcementTimeoutMs ?? DEFAULT_ENFORCEMENT_TIMEOUT_MS, this.enforcementExecTimeoutMs * ENFORCEMENT_BLOCKED_STREAK);
|
|
343
381
|
this.createArchive = options.createArchive ?? hostTarArchive;
|
|
344
382
|
this.warn = options.onWarning ?? ((message) => kubernetesLog.warn(message));
|
|
345
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Services run as native sidecars in the run pod (kubernetes-isolation.ts), for either provider:
|
|
386
|
+
* Claude Code's tool runner is a sidecar in the same pod, so it reaches them on 127.0.0.1 too.
|
|
387
|
+
*/
|
|
388
|
+
supportsServicesFor(provider) {
|
|
389
|
+
return provider === "codex" || provider === "claude-code";
|
|
390
|
+
}
|
|
346
391
|
/**
|
|
347
392
|
* Every per-run object name derives from the run id, so the handle is known before any cluster call.
|
|
348
393
|
* The executor persists it first; a crash mid-launch then still has a handle to clean up with (the
|
|
@@ -359,7 +404,19 @@ export class KubernetesJobLauncher {
|
|
|
359
404
|
}
|
|
360
405
|
}
|
|
361
406
|
async launch(spec) {
|
|
362
|
-
|
|
407
|
+
try {
|
|
408
|
+
validateKubernetesSpec(spec);
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
// The thrown error already carries the real reason (e.g.
|
|
412
|
+
// "kubernetes_isolation_unsupported:image-not-registry-digest") and is rethrown unchanged;
|
|
413
|
+
// this only makes that reason visible to an operator watching logs before the caller (which
|
|
414
|
+
// may only surface the top-level error code) does anything with it. Nothing here is derived
|
|
415
|
+
// from spec content beyond that fixed reason tag — no image reference, no limit value.
|
|
416
|
+
if (error instanceof Error)
|
|
417
|
+
this.warn(`kubernetes_spec_rejected: ${error.message}`);
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
363
420
|
await this.runPreflight();
|
|
364
421
|
const names = kubernetesRunNames(spec.runId);
|
|
365
422
|
const handle = { backend: BACKEND, id: `${this.namespace}/${names.token}` };
|
|
@@ -376,6 +433,7 @@ export class KubernetesJobLauncher {
|
|
|
376
433
|
createdAt,
|
|
377
434
|
deadlineAt: createdAt + spec.timeoutSec * 1000,
|
|
378
435
|
phase: "provisioning",
|
|
436
|
+
collectExclude: spec.collectExclude ?? collectExclusions([]),
|
|
379
437
|
};
|
|
380
438
|
try {
|
|
381
439
|
// The record is the idempotency fence before any other cluster side effect.
|
|
@@ -428,7 +486,7 @@ export class KubernetesJobLauncher {
|
|
|
428
486
|
if (phase === "failed" && !result.diagnostic) {
|
|
429
487
|
const diagnostic = await this.readWorkerDiagnostic(names);
|
|
430
488
|
if (diagnostic)
|
|
431
|
-
result = { ...result, diagnostic };
|
|
489
|
+
result = { ...result, ...diagnostic };
|
|
432
490
|
}
|
|
433
491
|
if (phase === "succeeded" && !result.resultArtifact) {
|
|
434
492
|
result = { ...result, resultArtifact: await this.readResultArtifact(names, record.runId) };
|
|
@@ -454,7 +512,9 @@ export class KubernetesJobLauncher {
|
|
|
454
512
|
throw new Error("kubernetes_workspace_destination_invalid");
|
|
455
513
|
}
|
|
456
514
|
const maxBytes = record.diskMb * 1024 * 1024;
|
|
457
|
-
await replaceDirectoryFromStaging(expected, maxBytes, "kubernetes_workspace_destination_invalid", (staging) => this.extractWorkspace(names, staging, maxBytes, this.transferBudgetMs(record)
|
|
515
|
+
await replaceDirectoryFromStaging(expected, maxBytes, "kubernetes_workspace_destination_invalid", (staging) => this.extractWorkspace(names, staging, maxBytes, this.transferBudgetMs(record),
|
|
516
|
+
// Names are always the current built-in list; only the paths come from the record.
|
|
517
|
+
normalizeCollectExclusions(record.collectExclude?.paths)));
|
|
458
518
|
}
|
|
459
519
|
async stop(handle, _reason) {
|
|
460
520
|
const names = this.namesFor(handle);
|
|
@@ -532,7 +592,7 @@ export class KubernetesJobLauncher {
|
|
|
532
592
|
// `exitCode` is this iteration's probe, and the bound below is only ever reached from here —
|
|
533
593
|
// so the verdict is always the *last* probe's, never a remembered earlier one.
|
|
534
594
|
const exitCode = await this.api.exec(this.namespace, names.pod, KEEPER_CONTAINER, command, {
|
|
535
|
-
timeoutMs:
|
|
595
|
+
timeoutMs: this.enforcementExecTimeoutMs,
|
|
536
596
|
});
|
|
537
597
|
blocked = exitCode === 0 ? blocked + 1 : 0;
|
|
538
598
|
if (blocked >= ENFORCEMENT_BLOCKED_STREAK)
|
|
@@ -552,7 +612,7 @@ export class KubernetesJobLauncher {
|
|
|
552
612
|
return structuredClone(handle);
|
|
553
613
|
}
|
|
554
614
|
async provision(spec, names, record) {
|
|
555
|
-
const { runtimeClassName, proxyService, platform } = this.options.config;
|
|
615
|
+
const { runtimeClassName, priorityClassName, proxyService, platform } = this.options.config;
|
|
556
616
|
if (!runtimeClassName) {
|
|
557
617
|
this.warn("kubernetes_runtime_class_unset: no runtime class configured; coding pods run without gVisor (development clusters only)");
|
|
558
618
|
}
|
|
@@ -563,12 +623,19 @@ export class KubernetesJobLauncher {
|
|
|
563
623
|
// which is only meaningful against a Service that actually exposes it with a ready backend.
|
|
564
624
|
const witness = await readProxyWitness(this.api, this.namespace, proxyService);
|
|
565
625
|
const proxyIp = witness.clusterIp;
|
|
566
|
-
const pod = buildRunPod(spec, {
|
|
626
|
+
const pod = buildRunPod(spec, {
|
|
627
|
+
namespace: this.namespace,
|
|
628
|
+
proxyIp,
|
|
629
|
+
runtimeClassName,
|
|
630
|
+
priorityClassName,
|
|
631
|
+
platform,
|
|
632
|
+
});
|
|
567
633
|
const policy = buildRunNetworkPolicy(spec, this.namespace);
|
|
568
|
-
|
|
634
|
+
const toolSetup = spec.provider === "claude-code" ? claudeToolSetup(spec, capability) : undefined;
|
|
635
|
+
await this.createIfMissing(() => this.api.createSecret(this.namespace, buildCapabilitySecret(spec, this.namespace, capability, toolSetup)));
|
|
569
636
|
await this.createIfMissing(() => this.api.createNetworkPolicy(this.namespace, policy));
|
|
570
637
|
await this.createIfMissing(() => this.api.createPod(this.namespace, pod));
|
|
571
|
-
await this.waitForKeeper(names);
|
|
638
|
+
await this.waitForKeeper(names, (spec.services ?? []).map((service) => service.name), spec.provider === "claude-code");
|
|
572
639
|
const [actualPod, actualPolicy] = await Promise.all([
|
|
573
640
|
this.api.readPod(this.namespace, names.pod),
|
|
574
641
|
this.api.readNetworkPolicy(this.namespace, names.policy),
|
|
@@ -612,7 +679,7 @@ export class KubernetesJobLauncher {
|
|
|
612
679
|
throw error;
|
|
613
680
|
}
|
|
614
681
|
}
|
|
615
|
-
async waitForKeeper(names) {
|
|
682
|
+
async waitForKeeper(names, serviceNames, toolRunner = false) {
|
|
616
683
|
const started = this.now();
|
|
617
684
|
for (;;) {
|
|
618
685
|
const pod = await this.api.readPod(this.namespace, names.pod);
|
|
@@ -620,6 +687,23 @@ export class KubernetesJobLauncher {
|
|
|
620
687
|
throw new Error("kubernetes_pod_start_failed");
|
|
621
688
|
const statuses = pod.status?.containerStatuses ?? [];
|
|
622
689
|
const initStatuses = pod.status?.initContainerStatuses ?? [];
|
|
690
|
+
const sidecar = (name) => initStatuses.find((status) => status.name === serviceContainerName(name));
|
|
691
|
+
// A service sidecar that restarted (its startup probe gave up), can't be pulled or created, or
|
|
692
|
+
// exited will never let the keeper start. Name the service rather than a generic start failure.
|
|
693
|
+
const failedService = serviceNames.find((name) => {
|
|
694
|
+
const status = sidecar(name);
|
|
695
|
+
return (status !== undefined &&
|
|
696
|
+
((status.restartCount ?? 0) > 0 ||
|
|
697
|
+
FATAL_WAITING_REASONS.has(status.state?.waiting?.reason ?? "") ||
|
|
698
|
+
status.state?.terminated !== undefined));
|
|
699
|
+
});
|
|
700
|
+
if (failedService !== undefined)
|
|
701
|
+
throw serviceUnreadyError(failedService);
|
|
702
|
+
const toolStatus = initStatuses.find((status) => status.name === TOOL_RUNNER_CONTAINER);
|
|
703
|
+
if (toolRunner &&
|
|
704
|
+
(toolRunnerFailed(initStatuses) || FATAL_WAITING_REASONS.has(toolStatus?.state?.waiting?.reason ?? ""))) {
|
|
705
|
+
throw new Error("kubernetes_tool_runner_failed");
|
|
706
|
+
}
|
|
623
707
|
const keeper = statuses.find((status) => status.name === KEEPER_CONTAINER);
|
|
624
708
|
if ([...initStatuses, ...statuses].some((status) => FATAL_WAITING_REASONS.has(status.state?.waiting?.reason ?? "")) ||
|
|
625
709
|
// A failed init container (kubectl's Init:Error) or a keeper that already exited can never become ready.
|
|
@@ -629,8 +713,17 @@ export class KubernetesJobLauncher {
|
|
|
629
713
|
}
|
|
630
714
|
if (keeper?.ready === true)
|
|
631
715
|
return;
|
|
632
|
-
if (this.now() - started >= this.readyTimeoutMs)
|
|
716
|
+
if (this.now() - started >= this.readyTimeoutMs) {
|
|
717
|
+
if (toolRunner && toolStatus?.started !== true) {
|
|
718
|
+
throw new Error("kubernetes_tool_runner_unready");
|
|
719
|
+
}
|
|
720
|
+
// At the bound, a service that never passed its startup probe (still pulling, still starting)
|
|
721
|
+
// is why the keeper never started.
|
|
722
|
+
const waiting = serviceNames.find((name) => sidecar(name)?.started !== true);
|
|
723
|
+
if (waiting !== undefined)
|
|
724
|
+
throw serviceUnreadyError(waiting);
|
|
633
725
|
throw new Error("kubernetes_pod_start_timeout");
|
|
726
|
+
}
|
|
634
727
|
await this.sleep(READY_POLL_MS);
|
|
635
728
|
}
|
|
636
729
|
}
|
|
@@ -715,14 +808,9 @@ export class KubernetesJobLauncher {
|
|
|
715
808
|
return undefined;
|
|
716
809
|
}
|
|
717
810
|
for (const line of raw.split("\n").reverse()) {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return value.error;
|
|
722
|
-
}
|
|
723
|
-
catch {
|
|
724
|
-
// Worker output is untrusted; only one fixed JSON shape is recognized.
|
|
725
|
-
}
|
|
811
|
+
const diagnostic = parseWorkerDiagnosticLine(line);
|
|
812
|
+
if (diagnostic)
|
|
813
|
+
return diagnostic;
|
|
726
814
|
}
|
|
727
815
|
return undefined;
|
|
728
816
|
}
|
|
@@ -759,9 +847,10 @@ export class KubernetesJobLauncher {
|
|
|
759
847
|
* Streams the keeper's workspace through the strict extractor into `staging`.
|
|
760
848
|
* The transfer is bounded by `timeoutMs` (see transferBudgetMs): on expiry the
|
|
761
849
|
* extraction is aborted. On any failure the output stream this method created
|
|
762
|
-
* is destroyed, since the exec's own timeout does not end it.
|
|
850
|
+
* is destroyed, since the exec's own timeout does not end it. Excluded dependency
|
|
851
|
+
* and cache paths never leave the pod (see src/coding/collect-exclude.ts).
|
|
763
852
|
*/
|
|
764
|
-
async extractWorkspace(names, staging, maxBytes, timeoutMs) {
|
|
853
|
+
async extractWorkspace(names, staging, maxBytes, timeoutMs, exclusions) {
|
|
765
854
|
const output = new PassThrough();
|
|
766
855
|
// Errors are surfaced through the exec/extraction promises; never let a late destroy() crash the process.
|
|
767
856
|
output.on("error", () => undefined);
|
|
@@ -772,10 +861,7 @@ export class KubernetesJobLauncher {
|
|
|
772
861
|
signal: controller.signal,
|
|
773
862
|
});
|
|
774
863
|
const execution = this.api
|
|
775
|
-
.exec(this.namespace, names.pod, KEEPER_CONTAINER, ["tar", "-C", WORKSPACE_STORAGE, "-cf", "-", "."], {
|
|
776
|
-
stdout: output,
|
|
777
|
-
timeoutMs,
|
|
778
|
-
})
|
|
864
|
+
.exec(this.namespace, names.pod, KEEPER_CONTAINER, ["tar", "-C", WORKSPACE_STORAGE, ...tarExcludeArgs(exclusions), "-cf", "-", "."], { stdout: output, timeoutMs })
|
|
779
865
|
.then((exitCode) => {
|
|
780
866
|
if (exitCode !== 0)
|
|
781
867
|
throw new Error("kubernetes_workspace_archive_failed");
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
* values are carried in a versioned input artifact, never expanded into an
|
|
4
4
|
* arbitrary environment map or shell command.
|
|
5
5
|
*/
|
|
6
|
+
import type { CodingProvider } from "../../coding/provider.js";
|
|
6
7
|
export interface JobResourceLimits {
|
|
7
8
|
cpus: number;
|
|
8
9
|
memoryMb: number;
|
|
9
10
|
pids: number;
|
|
10
11
|
diskMb: number;
|
|
11
12
|
}
|
|
13
|
+
import type { CollectExclusions } from "../../coding/collect-exclude.js";
|
|
14
|
+
import type { ResolvedCodingService } from "../../coding/services/catalog.js";
|
|
12
15
|
export interface JobSpec {
|
|
13
16
|
kind: "coding-agent";
|
|
14
17
|
runId: string;
|
|
@@ -21,6 +24,16 @@ export interface JobSpec {
|
|
|
21
24
|
timeoutSec: number;
|
|
22
25
|
limits: JobResourceLimits;
|
|
23
26
|
labels: Record<string, string>;
|
|
27
|
+
/** Workspace paths never collected; absent on legacy specs, which get the built-in names. */
|
|
28
|
+
collectExclude?: CollectExclusions;
|
|
29
|
+
/**
|
|
30
|
+
* Coding-run services (docs/coding-services.md): catalog snapshots resolved
|
|
31
|
+
* at dispatch, started next to the worker. Their images and environments come
|
|
32
|
+
* from the admin-managed catalog, never from repository content. Absent for
|
|
33
|
+
* a run without services (never an empty list), so such a spec, and its hash,
|
|
34
|
+
* is unchanged.
|
|
35
|
+
*/
|
|
36
|
+
services?: ResolvedCodingService[];
|
|
24
37
|
}
|
|
25
38
|
/** Opaque provider reference. Callers persist both fields exactly as given. */
|
|
26
39
|
export interface JobHandle {
|
|
@@ -45,6 +58,8 @@ export interface JobResult {
|
|
|
45
58
|
resultArtifact?: string;
|
|
46
59
|
/** Fixed worker-owned failure code; never raw container output. */
|
|
47
60
|
diagnostic?: string;
|
|
61
|
+
/** Output-schema failure locations (`path:code`) that passed SAFE_CODING_OUTPUT_ISSUE; never values. */
|
|
62
|
+
diagnosticIssues?: string[];
|
|
48
63
|
}
|
|
49
64
|
/**
|
|
50
65
|
* Lifecycle invariants implemented by every launcher:
|
|
@@ -75,4 +90,9 @@ export interface JobLauncher {
|
|
|
75
90
|
/** A launcher that can safely copy a terminal worker workspace back to trusted storage. */
|
|
76
91
|
export interface WorkspaceJobLauncher extends JobLauncher {
|
|
77
92
|
materializeWorkspace: (handle: JobHandle, destination: string) => Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Whether this launcher starts JobSpec.services for a run of `provider`: Kubernetes and Docker, for
|
|
95
|
+
* Codex and Claude Code. Absent means no services at all.
|
|
96
|
+
*/
|
|
97
|
+
supportsServicesFor?(provider: CodingProvider): boolean;
|
|
78
98
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import Anthropic from "@anthropic-ai/sdk";
|
|
8
8
|
import { ClaudeLlmProvider } from "./claude-provider.js";
|
|
9
|
-
import { anthropicPriceUsd, getAnthropicPricing } from "./pricing-anthropic.js";
|
|
9
|
+
import { anthropicPriceUsd, anthropicSupportedEfforts, getAnthropicPricing } from "./pricing-anthropic.js";
|
|
10
10
|
export { anthropicSupportedModels } from "./pricing-anthropic.js";
|
|
11
11
|
export function anthropicCredentialsPresent(env = process.env) {
|
|
12
12
|
return Boolean(env.ANTHROPIC_API_KEY);
|
|
@@ -16,6 +16,10 @@ export class AnthropicLlmProvider extends ClaudeLlmProvider {
|
|
|
16
16
|
if (!client && !apiKey) {
|
|
17
17
|
throw new Error("ANTHROPIC_API_KEY is not set — required by the Anthropic LlmProvider adapter.");
|
|
18
18
|
}
|
|
19
|
-
super(client ?? new Anthropic({ apiKey }), {
|
|
19
|
+
super(client ?? new Anthropic({ apiKey }), {
|
|
20
|
+
getPricing: getAnthropicPricing,
|
|
21
|
+
priceUsd: anthropicPriceUsd,
|
|
22
|
+
supportedEfforts: anthropicSupportedEfforts,
|
|
23
|
+
});
|
|
20
24
|
}
|
|
21
25
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
|
|
14
14
|
import { ClaudeLlmProvider } from "./claude-provider.js";
|
|
15
|
-
import { bedrockClaudePriceUsd, getBedrockClaudePricing } from "./pricing-bedrock-claude.js";
|
|
15
|
+
import { bedrockClaudePriceUsd, bedrockClaudeSupportedEfforts, getBedrockClaudePricing, } from "./pricing-bedrock-claude.js";
|
|
16
16
|
export { bedrockClaudeSupportedModels } from "./pricing-bedrock-claude.js";
|
|
17
17
|
export function bedrockCredentialsPresent(env = process.env) {
|
|
18
18
|
// A region is the one thing Bedrock always needs; AWS resolves actual
|
|
@@ -28,6 +28,7 @@ export class BedrockClaudeLlmProvider extends ClaudeLlmProvider {
|
|
|
28
28
|
super(client ?? new AnthropicBedrock({ awsRegion: region }), {
|
|
29
29
|
getPricing: getBedrockClaudePricing,
|
|
30
30
|
priceUsd: bedrockClaudePriceUsd,
|
|
31
|
+
supportedEfforts: bedrockClaudeSupportedEfforts,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LlmMessage, LlmRequest, LlmToolDef, LlmStreamEvent, LlmUsage } from "./types.js";
|
|
1
|
+
import type { LlmEffort, LlmMessage, LlmRequest, LlmToolDef, LlmStreamEvent, LlmUsage } from "./types.js";
|
|
2
2
|
export interface CacheControl {
|
|
3
3
|
type: "ephemeral";
|
|
4
4
|
}
|
|
@@ -36,6 +36,10 @@ export interface ClaudeRequest {
|
|
|
36
36
|
messages: ClaudeMessage[];
|
|
37
37
|
tools?: ClaudeTool[];
|
|
38
38
|
max_tokens: number;
|
|
39
|
+
/** Present only when an effort is set; omitted means the API default. */
|
|
40
|
+
output_config?: {
|
|
41
|
+
effort: LlmEffort;
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
/**
|
|
41
45
|
* Same shape sent to the API in `toClaudeRequest` — kept as one function so
|
|
@@ -77,6 +77,7 @@ export function toClaudeRequest(req, defaultMaxTokens) {
|
|
|
77
77
|
messages,
|
|
78
78
|
...(tools && tools.length > 0 ? { tools } : {}),
|
|
79
79
|
max_tokens: req.maxTokens ?? defaultMaxTokens,
|
|
80
|
+
...(req.effort ? { output_config: { effort: req.effort } } : {}),
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
const EPHEMERAL = { type: "ephemeral" };
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* stays exactly what each concrete adapter (anthropic.ts, bedrock.ts) has in
|
|
6
6
|
* common, and nothing more.
|
|
7
7
|
*/
|
|
8
|
-
import type { LlmMessage, LlmProvider, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
|
|
8
|
+
import type { LlmEffort, LlmMessage, LlmProvider, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
|
|
9
9
|
import type { ModelPricing, UsageTokens } from "./pricing-core.js";
|
|
10
10
|
/**
|
|
11
11
|
* Structural shape every Claude-protocol SDK client satisfies. Loose on
|
|
@@ -24,6 +24,8 @@ export interface ClaudePricingModule {
|
|
|
24
24
|
/** Must throw on an unknown model — fail-closed, never price at zero. */
|
|
25
25
|
getPricing(model: string): ModelPricing;
|
|
26
26
|
priceUsd(model: string, usage: UsageTokens): number;
|
|
27
|
+
/** Effort levels the model accepts; empty = never send an effort. */
|
|
28
|
+
supportedEfforts(model: string): readonly LlmEffort[];
|
|
27
29
|
}
|
|
28
30
|
export declare class ClaudeLlmProvider implements LlmProvider {
|
|
29
31
|
private readonly client;
|
|
@@ -17,7 +17,11 @@ export class ClaudeLlmProvider {
|
|
|
17
17
|
this.pricing = pricing;
|
|
18
18
|
}
|
|
19
19
|
async *stream(req, signal) {
|
|
20
|
-
|
|
20
|
+
// Defence in depth behind config-time validation: a level the model
|
|
21
|
+
// doesn't accept would fail the whole call, so it is dropped here.
|
|
22
|
+
const { effort, ...rest } = req;
|
|
23
|
+
const accepted = effort && this.pricing.supportedEfforts(req.model).includes(effort);
|
|
24
|
+
const claudeReq = withCacheBreakpoints(toClaudeRequest(accepted ? { ...rest, effort } : rest, DEFAULT_MAX_TOKENS));
|
|
21
25
|
const raw = this.client.messages.stream({ model: req.model, ...claudeReq }, { signal });
|
|
22
26
|
yield* mapClaudeStream(raw, (usage) => this.priceUsd(req.model, usage));
|
|
23
27
|
}
|
|
@@ -6,5 +6,5 @@ export { BedrockClaudeLlmProvider, bedrockCredentialsPresent, bedrockClaudeSuppo
|
|
|
6
6
|
export { ClaudeLlmProvider, type ClaudeMessagesClient, type ClaudePricingModule } from "./claude-provider.js";
|
|
7
7
|
export { openaiCredentialsPresent } from "./openai.js";
|
|
8
8
|
export { supportedModels as openaiSupportedModels } from "./pricing.js";
|
|
9
|
-
export { RoutingLlmProvider, type LlmRegistration } from "./routing.js";
|
|
9
|
+
export { RoutingLlmProvider, modelAcceptsEffort, modelSupportedEfforts, type LlmRegistration } from "./routing.js";
|
|
10
10
|
export { resolveLlmRegistrations, type LlmRegistrationResult } from "./registration.js";
|
|
@@ -6,5 +6,5 @@ export { BedrockClaudeLlmProvider, bedrockCredentialsPresent, bedrockClaudeSuppo
|
|
|
6
6
|
export { ClaudeLlmProvider } from "./claude-provider.js";
|
|
7
7
|
export { openaiCredentialsPresent } from "./openai.js";
|
|
8
8
|
export { supportedModels as openaiSupportedModels } from "./pricing.js";
|
|
9
|
-
export { RoutingLlmProvider } from "./routing.js";
|
|
9
|
+
export { RoutingLlmProvider, modelAcceptsEffort, modelSupportedEfforts } from "./routing.js";
|
|
10
10
|
export { resolveLlmRegistrations } from "./registration.js";
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic direct-API pricing table. Every entry is a fully literal,
|
|
3
|
+
* hardcoded ModelPricing — every field, including cache read/write, is the
|
|
4
|
+
* provider's own published rate for that exact model, never derived from
|
|
5
|
+
* another field via a ratio (see CLAUDE.md "LLM pricing tables — STRICT": a
|
|
6
|
+
* multiplier that happens to be correct today silently goes stale the
|
|
7
|
+
* moment one model's real cache pricing diverges from the pattern).
|
|
8
|
+
*/
|
|
1
9
|
import { type ModelPricing, type UsageTokens } from "./pricing-core.js";
|
|
10
|
+
import type { LlmEffort } from "./types.js";
|
|
11
|
+
export declare function anthropicSupportedEfforts(model: string): readonly LlmEffort[];
|
|
2
12
|
export declare function getAnthropicPricing(model: string): ModelPricing;
|
|
3
13
|
export declare function anthropicSupportedModels(): string[];
|
|
4
14
|
export declare function anthropicPriceUsd(model: string, usage: UsageTokens): number;
|
|
@@ -1,21 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic direct-API pricing table. Every entry is a fully literal,
|
|
3
|
+
* hardcoded ModelPricing — every field, including cache read/write, is the
|
|
4
|
+
* provider's own published rate for that exact model, never derived from
|
|
5
|
+
* another field via a ratio (see CLAUDE.md "LLM pricing tables — STRICT": a
|
|
6
|
+
* multiplier that happens to be correct today silently goes stale the
|
|
7
|
+
* moment one model's real cache pricing diverges from the pattern).
|
|
8
|
+
*/
|
|
1
9
|
import { computeCost } from "./pricing-core.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
function claude(inputPerMTok, outputPerMTok) {
|
|
5
|
-
return {
|
|
6
|
-
encoding: "o200k_base",
|
|
7
|
-
inputPerMTok,
|
|
8
|
-
outputPerMTok,
|
|
9
|
-
cachedInputPerMTok: inputPerMTok * CACHE_READ_MULT,
|
|
10
|
-
cacheWritePerMTok: inputPerMTok * CACHE_WRITE_MULT,
|
|
11
|
-
};
|
|
10
|
+
function claude(inputPerMTok, outputPerMTok, cachedInputPerMTok, cacheWritePerMTok) {
|
|
11
|
+
return { encoding: "o200k_base", inputPerMTok, outputPerMTok, cachedInputPerMTok, cacheWritePerMTok };
|
|
12
12
|
}
|
|
13
|
+
// Rates are the exact published 5-minute cache-TTL numbers
|
|
14
|
+
// (platform.claude.com/docs/en/about-claude/pricing, "Model pricing" table)
|
|
15
|
+
// — wardby only ever emits the default 5-minute cache_control breakpoint,
|
|
16
|
+
// so the 1-hour-TTL rates are out of scope and not stored here.
|
|
13
17
|
const PRICING = {
|
|
14
|
-
"claude-opus-5": claude(5, 25),
|
|
15
|
-
"claude-sonnet-5": claude(2, 10),
|
|
16
|
-
"claude-fable-5": claude(10, 50),
|
|
17
|
-
"claude-haiku-4-5": claude(1, 5),
|
|
18
|
+
"claude-opus-5": claude(5, 25, 0.5, 6.25),
|
|
19
|
+
"claude-sonnet-5": claude(2, 10, 0.2, 2.5),
|
|
20
|
+
"claude-fable-5": claude(10, 50, 1, 12.5),
|
|
21
|
+
"claude-haiku-4-5": claude(1, 5, 0.1, 1.25),
|
|
18
22
|
};
|
|
23
|
+
// Reasoning effort levels each model accepts (`output_config.effort`). The
|
|
24
|
+
// single source of truth for direct-API Claude models; a model missing here
|
|
25
|
+
// accepts no effort, so a new roster entry never gets one by accident.
|
|
26
|
+
// Haiku 4.5 rejects the parameter outright.
|
|
27
|
+
const ALL_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
28
|
+
const EFFORTS = {
|
|
29
|
+
"claude-opus-5": ALL_EFFORTS,
|
|
30
|
+
"claude-sonnet-5": ALL_EFFORTS,
|
|
31
|
+
"claude-fable-5": ALL_EFFORTS,
|
|
32
|
+
"claude-haiku-4-5": [],
|
|
33
|
+
};
|
|
34
|
+
export function anthropicSupportedEfforts(model) {
|
|
35
|
+
return EFFORTS[model] ?? [];
|
|
36
|
+
}
|
|
19
37
|
export function getAnthropicPricing(model) {
|
|
20
38
|
const p = PRICING[model];
|
|
21
39
|
if (!p)
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
* moment one model's real cache pricing diverges from the pattern).
|
|
8
8
|
*/
|
|
9
9
|
import { type ModelPricing, type UsageTokens } from "./pricing-core.js";
|
|
10
|
+
import type { LlmEffort } from "./types.js";
|
|
10
11
|
export declare function getBedrockClaudePricing(model: string): ModelPricing;
|
|
11
12
|
export declare function bedrockClaudeSupportedModels(): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Reasoning effort is not sent through Bedrock: whether InvokeModel accepts
|
|
15
|
+
* the Messages `output_config.effort` field for these models is unconfirmed,
|
|
16
|
+
* and an unaccepted field fails the whole call. Every Bedrock model therefore
|
|
17
|
+
* accepts no effort until that is verified per model.
|
|
18
|
+
*/
|
|
19
|
+
export declare function bedrockClaudeSupportedEfforts(_model: string): readonly LlmEffort[];
|
|
12
20
|
export declare function bedrockClaudePriceUsd(model: string, usage: UsageTokens): number;
|
|
@@ -32,6 +32,15 @@ export function getBedrockClaudePricing(model) {
|
|
|
32
32
|
export function bedrockClaudeSupportedModels() {
|
|
33
33
|
return Object.keys(PRICING);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Reasoning effort is not sent through Bedrock: whether InvokeModel accepts
|
|
37
|
+
* the Messages `output_config.effort` field for these models is unconfirmed,
|
|
38
|
+
* and an unaccepted field fails the whole call. Every Bedrock model therefore
|
|
39
|
+
* accepts no effort until that is verified per model.
|
|
40
|
+
*/
|
|
41
|
+
export function bedrockClaudeSupportedEfforts(_model) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
35
44
|
export function bedrockClaudePriceUsd(model, usage) {
|
|
36
45
|
return computeCost(getBedrockClaudePricing(model), usage);
|
|
37
46
|
}
|
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
* selection (Agent.model) selects the provider too — GPT and Claude agents
|
|
5
5
|
* run in one deployment. Unknown model / duplicate registration fail closed.
|
|
6
6
|
*/
|
|
7
|
-
import type { LlmMessage, LlmProvider, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
|
|
7
|
+
import type { LlmEffort, LlmMessage, LlmProvider, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Effort levels `model` accepts, whichever provider owns it — for config-time
|
|
10
|
+
* validation, so it needs no credentials. Each provider's own table is the
|
|
11
|
+
* source of truth. OpenAI models accept none: the Chat Completions
|
|
12
|
+
* `reasoning_effort` parameter is documented for o-series models only, and
|
|
13
|
+
* none is on the roster.
|
|
14
|
+
*/
|
|
15
|
+
export declare function modelSupportedEfforts(model: string): readonly LlmEffort[];
|
|
16
|
+
export declare function modelAcceptsEffort(model: string, effort: LlmEffort): boolean;
|
|
8
17
|
export interface LlmRegistration {
|
|
9
18
|
provider: LlmProvider;
|
|
10
19
|
models: string[];
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import { anthropicSupportedEfforts } from "./pricing-anthropic.js";
|
|
2
|
+
import { bedrockClaudeSupportedEfforts } from "./pricing-bedrock-claude.js";
|
|
3
|
+
/**
|
|
4
|
+
* Effort levels `model` accepts, whichever provider owns it — for config-time
|
|
5
|
+
* validation, so it needs no credentials. Each provider's own table is the
|
|
6
|
+
* source of truth. OpenAI models accept none: the Chat Completions
|
|
7
|
+
* `reasoning_effort` parameter is documented for o-series models only, and
|
|
8
|
+
* none is on the roster.
|
|
9
|
+
*/
|
|
10
|
+
export function modelSupportedEfforts(model) {
|
|
11
|
+
const direct = anthropicSupportedEfforts(model);
|
|
12
|
+
if (direct.length > 0)
|
|
13
|
+
return direct;
|
|
14
|
+
return bedrockClaudeSupportedEfforts(model);
|
|
15
|
+
}
|
|
16
|
+
export function modelAcceptsEffort(model, effort) {
|
|
17
|
+
return modelSupportedEfforts(model).includes(effort);
|
|
18
|
+
}
|
|
1
19
|
export class RoutingLlmProvider {
|
|
2
20
|
byModel = new Map();
|
|
3
21
|
constructor(registrations) {
|
|
@@ -35,6 +35,13 @@ export interface LlmToolDef {
|
|
|
35
35
|
/** JSON Schema for the tool's parameters. */
|
|
36
36
|
parameters: Record<string, unknown>;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Reasoning effort levels, lowest to highest. Which levels a model accepts
|
|
40
|
+
* is per model and per provider — ask `modelSupportedEfforts` (routing.ts).
|
|
41
|
+
*/
|
|
42
|
+
export declare const LLM_EFFORT_LEVELS: readonly ["low", "medium", "high", "xhigh", "max"];
|
|
43
|
+
export type LlmEffort = (typeof LLM_EFFORT_LEVELS)[number];
|
|
44
|
+
export declare function isLlmEffort(value: unknown): value is LlmEffort;
|
|
38
45
|
export interface LlmRequest {
|
|
39
46
|
model: string;
|
|
40
47
|
messages: LlmMessage[];
|
|
@@ -42,6 +49,11 @@ export interface LlmRequest {
|
|
|
42
49
|
maxTokens?: number;
|
|
43
50
|
temperature?: number;
|
|
44
51
|
stopSequences?: string[];
|
|
52
|
+
/**
|
|
53
|
+
* Reasoning effort. Unset = the provider's own default. An adapter sends
|
|
54
|
+
* it only when the model accepts that level, and drops it otherwise.
|
|
55
|
+
*/
|
|
56
|
+
effort?: LlmEffort;
|
|
45
57
|
}
|
|
46
58
|
export interface LlmUsage {
|
|
47
59
|
/** Total input tokens, including any served from cache. */
|
|
@@ -9,4 +9,11 @@
|
|
|
9
9
|
* Selected per-agent by RoutingLlmProvider (Agent.model -> provider).
|
|
10
10
|
* Bedrock-hosted Claude is a reserved future adapter (shared claude-messages.ts core).
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Reasoning effort levels, lowest to highest. Which levels a model accepts
|
|
14
|
+
* is per model and per provider — ask `modelSupportedEfforts` (routing.ts).
|
|
15
|
+
*/
|
|
16
|
+
export const LLM_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
17
|
+
export function isLlmEffort(value) {
|
|
18
|
+
return typeof value === "string" && LLM_EFFORT_LEVELS.includes(value);
|
|
19
|
+
}
|