@wardby/cli 0.2.1 → 0.4.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 +53 -4
- package/README.md +52 -13
- 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 +14 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +284 -36
- package/dist/coding/base-commit.d.ts +6 -0
- package/dist/coding/base-commit.js +12 -0
- 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 +91 -4
- package/dist/coding/protocol.js +123 -12
- package/dist/coding/provider.d.ts +6 -1
- package/dist/coding/provider.js +16 -9
- 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 +66 -0
- package/dist/config/providers.js +137 -0
- package/dist/core/attribution.d.ts +101 -0
- package/dist/core/attribution.js +208 -0
- package/dist/core/budget-groups.d.ts +120 -10
- package/dist/core/budget-groups.js +133 -24
- package/dist/core/budget-wording.d.ts +22 -0
- package/dist/core/budget-wording.js +55 -0
- package/dist/core/coding-queue.d.ts +3 -0
- package/dist/core/coding-queue.js +6 -2
- package/dist/core/coding-service-status.d.ts +11 -0
- package/dist/core/coding-service-status.js +17 -0
- package/dist/core/cost-report.d.ts +88 -0
- package/dist/core/cost-report.js +248 -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 +74 -7
- package/dist/core/dispatch.js +382 -47
- package/dist/core/engine-native.js +44 -14
- package/dist/core/glob.d.ts +10 -0
- package/dist/core/glob.js +33 -0
- package/dist/core/grants.d.ts +86 -0
- package/dist/core/grants.js +126 -0
- package/dist/core/host-events.d.ts +72 -0
- package/dist/core/host-events.js +597 -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 +78 -0
- package/dist/core/host-status.js +228 -0
- package/dist/core/in-flight-runs.d.ts +8 -0
- package/dist/core/in-flight-runs.js +56 -0
- package/dist/core/issue-bridge.d.ts +60 -0
- package/dist/core/issue-bridge.js +189 -0
- package/dist/core/issue-dedupe.d.ts +70 -0
- package/dist/core/issue-dedupe.js +255 -0
- package/dist/core/issue-events.d.ts +42 -0
- package/dist/core/issue-events.js +155 -0
- package/dist/core/issue-status.d.ts +29 -0
- package/dist/core/issue-status.js +241 -0
- package/dist/core/issue-tracker-tools.d.ts +64 -0
- package/dist/core/issue-tracker-tools.js +850 -0
- package/dist/core/model-usage.d.ts +10 -0
- package/dist/core/model-usage.js +24 -0
- package/dist/core/provider-wording.d.ts +12 -0
- package/dist/core/provider-wording.js +44 -0
- package/dist/core/reconciler.d.ts +42 -2
- package/dist/core/reconciler.js +97 -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 +354 -0
- package/dist/core/run-heartbeat.d.ts +27 -0
- package/dist/core/run-heartbeat.js +54 -0
- package/dist/core/run-pricing.d.ts +61 -0
- package/dist/core/run-pricing.js +56 -0
- package/dist/core/runner.d.ts +33 -8
- package/dist/core/runner.js +410 -62
- package/dist/core/scheduler.d.ts +4 -1
- package/dist/core/scheduler.js +3 -2
- package/dist/core/secrets.d.ts +11 -2
- package/dist/core/secrets.js +25 -6
- package/dist/core/self-defects.d.ts +80 -0
- package/dist/core/self-defects.js +180 -0
- 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 +67 -0
- package/dist/core/untrusted-content.d.ts +32 -0
- package/dist/core/untrusted-content.js +72 -0
- package/dist/core/webhooks.d.ts +17 -2
- package/dist/core/webhooks.js +42 -3
- package/dist/generated/prisma/browser.d.ts +166 -0
- package/dist/generated/prisma/client.d.ts +166 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +152 -52
- package/dist/generated/prisma/enums.d.ts +13 -0
- package/dist/generated/prisma/enums.js +12 -1
- package/dist/generated/prisma/internal/class.d.ts +242 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +2571 -577
- package/dist/generated/prisma/internal/prismaNamespace.js +312 -6
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +328 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +312 -6
- package/dist/generated/prisma/models/Agent.d.ts +682 -1
- package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
- package/dist/generated/prisma/models/AgentIssueProject.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/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 +195 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1405 -95
- package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
- package/dist/generated/prisma/models/CodingRunServiceStatus.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/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/IssueFingerprint.d.ts +1183 -0
- package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
- package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
- package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
- package/dist/generated/prisma/models/ModelCatalogEntry.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 +1402 -82
- package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
- package/dist/generated/prisma/models/RunAttribution.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/RunIssueStatus.d.ts +1199 -0
- package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
- package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
- package/dist/generated/prisma/models/RunModelUsage.js +1 -0
- package/dist/generated/prisma/models/Tool.d.ts +15 -3
- package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
- package/dist/generated/prisma/models/WorkItem.js +1 -0
- package/dist/generated/prisma/models.d.ts +22 -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 +999 -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 +18 -18
- package/dist/knowledge/check.d.ts +13 -0
- package/dist/knowledge/check.js +69 -0
- package/dist/knowledge/cli.d.ts +14 -0
- package/dist/knowledge/cli.js +67 -0
- package/dist/knowledge/concept.d.ts +54 -0
- package/dist/knowledge/concept.js +78 -0
- package/dist/knowledge/note.d.ts +11 -0
- package/dist/knowledge/note.js +39 -0
- package/dist/knowledge/relevance.d.ts +11 -0
- package/dist/knowledge/relevance.js +14 -0
- package/dist/knowledge/span-hash.d.ts +3 -0
- package/dist/knowledge/span-hash.js +16 -0
- package/dist/mcp/auth/access.d.ts +72 -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 +25 -51
- 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 +33 -2
- package/dist/mcp/auth/resource-server.js +99 -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 +23 -5
- package/dist/mcp/auth/self-hosted/credentials.js +62 -4
- package/dist/mcp/auth/self-hosted/session.d.ts +7 -6
- package/dist/mcp/context.d.ts +30 -1
- package/dist/mcp/errors.d.ts +25 -6
- package/dist/mcp/errors.js +98 -0
- package/dist/mcp/host-events/deliveries.d.ts +9 -0
- package/dist/mcp/host-events/deliveries.js +17 -0
- package/dist/mcp/host-events/github-ingress.d.ts +38 -0
- package/dist/mcp/host-events/github-ingress.js +83 -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/host-events/jira-ingress.d.ts +29 -0
- package/dist/mcp/host-events/jira-ingress.js +92 -0
- package/dist/mcp/index.d.ts +10 -1
- package/dist/mcp/index.js +187 -19
- package/dist/mcp/server.js +32 -11
- package/dist/mcp/tools/agents.js +519 -50
- package/dist/mcp/tools/budget-groups.js +3 -3
- package/dist/mcp/tools/cost-report.d.ts +8 -0
- package/dist/mcp/tools/cost-report.js +60 -0
- 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/issue-projects.d.ts +2 -0
- package/dist/mcp/tools/issue-projects.js +238 -0
- package/dist/mcp/tools/memory.d.ts +7 -1
- package/dist/mcp/tools/memory.js +5 -5
- package/dist/mcp/tools/model-catalog.d.ts +22 -0
- package/dist/mcp/tools/model-catalog.js +423 -0
- package/dist/mcp/tools/repositories.d.ts +2 -0
- package/dist/mcp/tools/repositories.js +182 -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 +65 -7
- package/dist/mcp/tools/webhooks.js +15 -4
- package/dist/mcp/transport/streamable-http.d.ts +15 -0
- package/dist/mcp/transport/streamable-http.js +55 -3
- package/dist/mcp/webhooks/ingress.d.ts +2 -1
- package/dist/mcp/webhooks/ingress.js +9 -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 +10 -2
- package/dist/providers/auth/self-hosted.js +55 -6
- package/dist/providers/auth/types.d.ts +6 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +4 -1
- package/dist/providers/coding-proxy/memory-ledger.js +31 -3
- package/dist/providers/coding-proxy/metering.d.ts +6 -1
- package/dist/providers/coding-proxy/metering.js +41 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +106 -8
- package/dist/providers/coding-proxy/proxy.d.ts +25 -2
- package/dist/providers/coding-proxy/proxy.js +561 -38
- 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 +33 -1
- package/dist/providers/coding-proxy/types.js +12 -1
- package/dist/providers/engine/types.d.ts +29 -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 +28 -1
- package/dist/providers/executor/container.d.ts +134 -4
- package/dist/providers/executor/container.js +394 -37
- package/dist/providers/executor/dbos.d.ts +4 -3
- package/dist/providers/executor/dbos.js +7 -5
- package/dist/providers/executor/in-process.d.ts +2 -3
- package/dist/providers/executor/routing.d.ts +13 -0
- package/dist/providers/executor/routing.js +18 -0
- package/dist/providers/executor/types.d.ts +34 -0
- package/dist/providers/issue-tracker/adf.d.ts +31 -0
- package/dist/providers/issue-tracker/adf.js +181 -0
- package/dist/providers/issue-tracker/index.d.ts +5 -0
- package/dist/providers/issue-tracker/index.js +12 -0
- package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
- package/dist/providers/issue-tracker/jira-client.js +151 -0
- package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
- package/dist/providers/issue-tracker/jira-events.js +98 -0
- package/dist/providers/issue-tracker/jira.d.ts +116 -0
- package/dist/providers/issue-tracker/jira.js +502 -0
- package/dist/providers/issue-tracker/types.d.ts +269 -0
- package/dist/providers/issue-tracker/types.js +16 -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 +53 -2
- package/dist/providers/jobs/docker.js +307 -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 +24 -2
- package/dist/providers/jobs/kubernetes.js +153 -22
- package/dist/providers/jobs/service-state.d.ts +22 -0
- package/dist/providers/jobs/service-state.js +17 -0
- package/dist/providers/jobs/types.d.ts +18 -0
- package/dist/providers/llm/anthropic.d.ts +3 -3
- package/dist/providers/llm/anthropic.js +3 -5
- package/dist/providers/llm/bedrock.d.ts +3 -3
- package/dist/providers/llm/bedrock.js +3 -8
- package/dist/providers/llm/catalog-lookup.d.ts +10 -0
- package/dist/providers/llm/catalog-lookup.js +15 -0
- package/dist/providers/llm/catalog-shipped.d.ts +18 -0
- package/dist/providers/llm/catalog-shipped.js +197 -0
- package/dist/providers/llm/catalog-store.d.ts +58 -0
- package/dist/providers/llm/catalog-store.js +138 -0
- package/dist/providers/llm/catalog-types.d.ts +66 -0
- package/dist/providers/llm/catalog-types.js +64 -0
- package/dist/providers/llm/catalog.d.ts +61 -0
- package/dist/providers/llm/catalog.js +147 -0
- 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 +10 -12
- package/dist/providers/llm/claude-provider.js +15 -6
- package/dist/providers/llm/index.d.ts +9 -6
- package/dist/providers/llm/index.js +8 -5
- package/dist/providers/llm/openai.d.ts +14 -5
- package/dist/providers/llm/openai.js +24 -14
- package/dist/providers/llm/pricing-core.d.ts +5 -3
- package/dist/providers/llm/registration.js +8 -12
- package/dist/providers/llm/routing.d.ts +21 -11
- package/dist/providers/llm/routing.js +47 -13
- 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 +226 -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 +568 -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 +309 -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 +78 -34
- package/dist/providers/vcs/github.d.ts +94 -3
- package/dist/providers/vcs/github.js +223 -17
- package/dist/providers/vcs/types.d.ts +48 -4
- package/dist/quickstart/index.d.ts +2 -0
- package/dist/quickstart/index.js +36 -8
- 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 +8 -2
- package/dist/viewer/api-schema.d.ts +2757 -0
- package/dist/viewer/api-schema.js +165 -0
- package/dist/viewer/build-schemas.d.ts +2 -0
- package/dist/viewer/build-schemas.js +18 -0
- package/dist/viewer/event-bus.d.ts +38 -0
- package/dist/viewer/event-bus.js +232 -0
- package/dist/viewer/graph.d.ts +40 -0
- package/dist/viewer/graph.js +243 -0
- package/dist/viewer/http.d.ts +30 -0
- package/dist/viewer/http.js +133 -0
- package/dist/viewer/run-detail.d.ts +4 -0
- package/dist/viewer/run-detail.js +61 -0
- package/dist/wardby-bin.js +11 -0
- package/docs/README.md +40 -0
- package/docs/agent-recipes.md +383 -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 +508 -0
- package/docs/coding-agent-setup.md +175 -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 +1068 -0
- package/docs/getting-started-gke.md +632 -0
- package/docs/getting-started-identity-provider.md +319 -0
- package/docs/getting-started.md +147 -0
- package/docs/jira-agents.md +649 -0
- package/docs/knowledge.md +387 -0
- package/docs/models.md +221 -0
- package/docs/observability.md +53 -0
- package/docs/release-verification.md +66 -0
- package/docs/security-deployment.md +667 -0
- package/docs/viewer-api.md +142 -0
- package/help/admin-viewer.md +39 -0
- package/help/agent-recipes.md +173 -0
- package/help/architecture-agent.md +189 -0
- package/help/builder-agent.md +80 -0
- package/help/code-review-agents.md +37 -0
- package/help/coding-packages.md +31 -0
- package/help/coding-services.md +71 -0
- package/help/cost-attribution.md +67 -0
- package/help/creating-agents.md +90 -0
- package/help/deploy-gke.md +45 -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/model-unavailable.md +63 -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 +32 -0
- package/help/github.md +48 -0
- package/help/identity-and-access.md +44 -0
- package/help/jira.md +135 -0
- package/help/knowledge.md +47 -0
- package/help/mcp.md +30 -0
- package/help/models.md +90 -0
- package/help/native-capabilities.md +30 -0
- package/help/observability.md +41 -0
- package/help/operating-agents.md +36 -0
- package/help/security.md +27 -0
- package/help/troubleshooting/budgets.md +32 -0
- package/help/troubleshooting/coding-workers.md +47 -0
- package/help/troubleshooting/repository-access.md +27 -0
- package/package.json +14 -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/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
- package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
- package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
- package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
- package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
- package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
- package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
- package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
- package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
- package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
- package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
- package/prisma/schema.prisma +663 -21
- package/dist/mcp/tools/models.d.ts +0 -8
- package/dist/mcp/tools/models.js +0 -15
- package/dist/providers/llm/pricing-anthropic.d.ts +0 -4
- package/dist/providers/llm/pricing-anthropic.js +0 -30
- package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -12
- package/dist/providers/llm/pricing-bedrock-claude.js +0 -37
- package/dist/providers/llm/pricing.d.ts +0 -30
- package/dist/providers/llm/pricing.js +0 -74
|
@@ -8,6 +8,18 @@ export interface PullRequestTestResult {
|
|
|
8
8
|
command: string;
|
|
9
9
|
outcome: "passed" | "failed" | "skipped";
|
|
10
10
|
}
|
|
11
|
+
/** One package the registry proxy served during the run (RegistryFetch outcome "served"). */
|
|
12
|
+
export interface PackageReport {
|
|
13
|
+
ecosystem: string;
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
}
|
|
17
|
+
/** One package the registry proxy refused during the run (RegistryFetch outcome "refused"). */
|
|
18
|
+
export interface PackageRefusal {
|
|
19
|
+
ecosystem: string;
|
|
20
|
+
name: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
}
|
|
11
23
|
export interface PullRequestInput {
|
|
12
24
|
runId: string;
|
|
13
25
|
repository: string;
|
|
@@ -17,6 +29,30 @@ export interface PullRequestInput {
|
|
|
17
29
|
summary?: string;
|
|
18
30
|
tests?: readonly PullRequestTestResult[];
|
|
19
31
|
tag?: string;
|
|
32
|
+
/** Deduplicated by the caller isn't required — pullRequestBody dedupes itself (ecosystem+name+version / +reason). */
|
|
33
|
+
packages?: readonly PackageReport[];
|
|
34
|
+
packageRefusals?: readonly PackageRefusal[];
|
|
35
|
+
/**
|
|
36
|
+
* A continuation re-finds the PR its root run opened, and a person may
|
|
37
|
+
* have marked that PR ready for review since. The push has already updated
|
|
38
|
+
* it, so it is accepted as found instead of failing the run as
|
|
39
|
+
* `github_pull_request_not_draft`. A PR this client creates is always a
|
|
40
|
+
* draft either way; unset (a fresh run), only a draft PR is accepted.
|
|
41
|
+
*/
|
|
42
|
+
acceptReadyForReview?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The originating issue-tracker issue (control-plane data, never model
|
|
45
|
+
* output). Provider-neutral: the title gets a `[KEY] ` prefix and the body a
|
|
46
|
+
* first line linking it ("Resolves <trackerName> issue …"). The key is
|
|
47
|
+
* re-validated here, a non-https `url` is dropped, and so is a `trackerName`
|
|
48
|
+
* that isn't a short plain name. The PR lookup keys on the hidden run
|
|
49
|
+
* marker, never the title.
|
|
50
|
+
*/
|
|
51
|
+
issue?: {
|
|
52
|
+
key: string;
|
|
53
|
+
url?: string;
|
|
54
|
+
trackerName?: string;
|
|
55
|
+
};
|
|
20
56
|
}
|
|
21
57
|
export interface PullRequestResult {
|
|
22
58
|
number: number;
|
|
@@ -42,6 +78,15 @@ export interface ContinuationCheckRunInput {
|
|
|
42
78
|
export interface ContinuationCheckRunCompleteInput extends ContinuationCheckRunInput {
|
|
43
79
|
outcome: "succeeded" | "failed";
|
|
44
80
|
}
|
|
81
|
+
/** One file at one ref, read through the API without a clone. */
|
|
82
|
+
export interface RepositoryFileInput {
|
|
83
|
+
repository: string;
|
|
84
|
+
ref: string;
|
|
85
|
+
/** Repository-relative POSIX path. */
|
|
86
|
+
path: string;
|
|
87
|
+
/** Refused above this many bytes. */
|
|
88
|
+
maxBytes: number;
|
|
89
|
+
}
|
|
45
90
|
export interface GitHubRepositoryAccess {
|
|
46
91
|
withRepositoryToken<T>(repository: string, action: (token: string) => Promise<T>): Promise<T>;
|
|
47
92
|
createOrFindDraftPullRequest(input: PullRequestInput): Promise<PullRequestResult>;
|
|
@@ -53,10 +98,29 @@ export interface GitHubRepositoryAccess {
|
|
|
53
98
|
createContinuationCheckRun(input: ContinuationCheckRunInput): Promise<void>;
|
|
54
99
|
/** Completes the check run if one exists for this run+commit; a no-op otherwise (never creates). */
|
|
55
100
|
completeContinuationCheckRun(input: ContinuationCheckRunCompleteInput): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* The raw text of one file at a ref, or null when it does not exist (a
|
|
103
|
+
* Contents: read token). Optional so test doubles and non-GitHub providers
|
|
104
|
+
* can omit it: coding-run services then read no declaration.
|
|
105
|
+
*/
|
|
106
|
+
readFileAtRef?(input: RepositoryFileInput): Promise<string | null>;
|
|
56
107
|
}
|
|
57
108
|
type Fetch = typeof globalThis.fetch;
|
|
58
109
|
/** Accepts bounded opaque installation tokens without allowing control characters. */
|
|
59
110
|
export declare function isSafeGitHubInstallationToken(value: unknown): value is string;
|
|
111
|
+
/**
|
|
112
|
+
* Same shape as ISSUE_KEY (issue-tracker/types.ts); duplicated so the VCS layer
|
|
113
|
+
* stays free of issue-tracker imports (a test keeps the two in step). The
|
|
114
|
+
* executor validates with the shared one.
|
|
115
|
+
*/
|
|
116
|
+
export declare const PR_ISSUE_KEY: RegExp;
|
|
117
|
+
export declare function pullRequestTitle(input: PullRequestInput): string;
|
|
118
|
+
/** At most this many packages, and separately this many refusals, are listed
|
|
119
|
+
* in a PR body; the rest are counted in a "…and N more" line pointing at
|
|
120
|
+
* get_run, which returns the full list. */
|
|
121
|
+
export declare const MAX_PR_PACKAGE_LINES = 100;
|
|
122
|
+
/** The hidden run marker stays first and unconditional: createOrFindDraftPullRequest's idempotent lookup depends on it. */
|
|
123
|
+
export declare function pullRequestBody(input: PullRequestInput): string;
|
|
60
124
|
export declare class GitHubAppClient implements GitHubRepositoryAccess {
|
|
61
125
|
private readonly config;
|
|
62
126
|
private readonly fetchImpl;
|
|
@@ -78,6 +142,28 @@ export declare class GitHubAppClient implements GitHubRepositoryAccess {
|
|
|
78
142
|
* apparently isn't gated the same way a genuine issue comment might be.)
|
|
79
143
|
*/
|
|
80
144
|
private withChecksToken;
|
|
145
|
+
/**
|
|
146
|
+
* Mints an installation token for exactly `permissions` on one repository,
|
|
147
|
+
* runs `action`, and always revokes. The building block for the
|
|
148
|
+
* code-review host (providers/review-host/github.ts), whose calls each
|
|
149
|
+
* request only what they need.
|
|
150
|
+
*/
|
|
151
|
+
withScopedToken<T>(repository: string, permissions: Record<string, "read" | "write">, action: (token: string) => Promise<T>): Promise<T>;
|
|
152
|
+
/**
|
|
153
|
+
* One file's raw text at a ref, without a clone (a Contents: read token).
|
|
154
|
+
* Requests the raw media type; GitHub honors it for an ordinary file but
|
|
155
|
+
* falls back to a JSON metadata response for anything else the raw type
|
|
156
|
+
* doesn't apply to -- a directory listing (a JSON array) or a symlink /
|
|
157
|
+
* submodule (a JSON object whose `type` isn't "file"). Either of those, or
|
|
158
|
+
* a 404, means there's no file text to return.
|
|
159
|
+
*/
|
|
160
|
+
readFileAtRef(input: RepositoryFileInput): Promise<string | null>;
|
|
161
|
+
private identity?;
|
|
162
|
+
/** The App's id and slug (its @-mention handle), read once with the App JWT. */
|
|
163
|
+
appIdentity(): Promise<{
|
|
164
|
+
id: number;
|
|
165
|
+
slug: string;
|
|
166
|
+
}>;
|
|
81
167
|
upsertContinuationStatusComment(input: ContinuationStatusCommentInput): Promise<void>;
|
|
82
168
|
updateContinuationStatusComment(input: ContinuationStatusCommentInput): Promise<void>;
|
|
83
169
|
createContinuationCheckRun(input: ContinuationCheckRunInput): Promise<void>;
|
|
@@ -85,13 +171,12 @@ export declare class GitHubAppClient implements GitHubRepositoryAccess {
|
|
|
85
171
|
createOrFindDraftPullRequest(input: PullRequestInput): Promise<PullRequestResult>;
|
|
86
172
|
private appJwt;
|
|
87
173
|
private mintRepositoryToken;
|
|
88
|
-
private mintChecksToken;
|
|
89
174
|
/**
|
|
90
175
|
* Shared installation-token mint: requests exactly `permissions`, then
|
|
91
176
|
* verifies the response granted exactly that (no more, no less, modulo
|
|
92
177
|
* the always-implicit `metadata: read`) before trusting the token. Each
|
|
93
178
|
* caller requests the narrowest permission set it needs — see
|
|
94
|
-
*
|
|
179
|
+
* withScopedToken/withChecksToken for why these are minted separately
|
|
95
180
|
* from withRepositoryToken rather than requesting a union of everything.
|
|
96
181
|
*/
|
|
97
182
|
private mintScopedToken;
|
|
@@ -100,6 +185,12 @@ export declare class GitHubAppClient implements GitHubRepositoryAccess {
|
|
|
100
185
|
private parsePullRequest;
|
|
101
186
|
private findStatusComment;
|
|
102
187
|
private findCheckRun;
|
|
103
|
-
|
|
188
|
+
/** Public for the code-review host, which issues its own REST calls with tokens minted here. */
|
|
189
|
+
requestJson(path: string, bearer: string, init?: RequestInit, expectedStatuses?: number[]): Promise<Response>;
|
|
190
|
+
/**
|
|
191
|
+
* Public for the code-review host: one GraphQL request, for what REST lacks
|
|
192
|
+
* (review threads). A response carrying `errors` fails like a REST error.
|
|
193
|
+
*/
|
|
194
|
+
graphql(bearer: string, query: string, variables: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
104
195
|
}
|
|
105
196
|
export {};
|
|
@@ -11,6 +11,7 @@ const SAFE_PULL_REQUEST_TAG = /^[A-Za-z0-9][A-Za-z0-9._/-]{0,31}$/;
|
|
|
11
11
|
/** Mirrors the runId shape validated elsewhere (coding/protocol.ts, git.ts) — validated independently here too. */
|
|
12
12
|
const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
13
13
|
const SAFE_COMMIT_SHA = /^[0-9a-f]{40}$/;
|
|
14
|
+
const SAFE_FILE_PATH = /^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/;
|
|
14
15
|
function record(value) {
|
|
15
16
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16
17
|
throw new Error("github_api_invalid_response");
|
|
@@ -32,17 +33,117 @@ export function isSafeGitHubInstallationToken(value) {
|
|
|
32
33
|
Buffer.byteLength(value, "utf8") <= 512 &&
|
|
33
34
|
/^[A-Za-z0-9._-]+$/.test(value));
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Same shape as ISSUE_KEY (issue-tracker/types.ts); duplicated so the VCS layer
|
|
38
|
+
* stays free of issue-tracker imports (a test keeps the two in step). The
|
|
39
|
+
* executor validates with the shared one.
|
|
40
|
+
*/
|
|
41
|
+
export const PR_ISSUE_KEY = /^[A-Z][A-Z0-9_]{0,254}-[1-9]\d{0,9}$/;
|
|
42
|
+
/** The issue key when it is well-formed; a malformed one is dropped everywhere it would be rendered. */
|
|
43
|
+
function validIssueKey(input) {
|
|
44
|
+
const key = input.issue?.key;
|
|
45
|
+
return typeof key === "string" && PR_ISSUE_KEY.test(key) ? key : undefined;
|
|
46
|
+
}
|
|
47
|
+
export function pullRequestTitle(input) {
|
|
48
|
+
const base = input.tag ? `[${input.tag}] Wardby run ${input.runId}` : `Wardby run ${input.runId}`;
|
|
49
|
+
const key = validIssueKey(input);
|
|
50
|
+
return key ? `[${key}] ${base}` : base;
|
|
51
|
+
}
|
|
52
|
+
function issueLine(input) {
|
|
53
|
+
const key = validIssueKey(input);
|
|
54
|
+
const url = input.issue?.url;
|
|
55
|
+
if (!key || typeof url !== "string" || !url.startsWith("https://") || /[\s<>()]/.test(url))
|
|
56
|
+
return undefined;
|
|
57
|
+
const name = input.issue?.trackerName;
|
|
58
|
+
const tracker = typeof name === "string" && /^[A-Za-z][A-Za-z0-9 .-]{0,39}$/.test(name) ? `${name.trim()} ` : "";
|
|
59
|
+
return `Resolves ${tracker}issue [${key}](${url})`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Package names/versions/reasons come from registry metadata, not from
|
|
63
|
+
* anything Wardby validated, and land inside inline code spans in the PR
|
|
64
|
+
* body. A backtick or newline in one of those fields could break out of the
|
|
65
|
+
* span or the line structure, so any entry containing either is dropped
|
|
66
|
+
* rather than escaped (npm/PyPI names can't contain backticks in practice,
|
|
67
|
+
* so this should never trigger — it's a cheap belt-and-suspenders guard).
|
|
68
|
+
*/
|
|
69
|
+
function isSafeMarkdownFragment(value) {
|
|
70
|
+
return !value.includes("`") && !value.includes("\n") && !value.includes("\r");
|
|
71
|
+
}
|
|
72
|
+
/** At most this many packages, and separately this many refusals, are listed
|
|
73
|
+
* in a PR body; the rest are counted in a "…and N more" line pointing at
|
|
74
|
+
* get_run, which returns the full list. */
|
|
75
|
+
export const MAX_PR_PACKAGE_LINES = 100;
|
|
76
|
+
/** A hard ceiling on each list's rendered size, whatever the entries
|
|
77
|
+
* contain, so the section can never push the body past GitHub's limit. */
|
|
78
|
+
const MAX_PR_PACKAGE_LIST_CHARS = 16 * 1024;
|
|
79
|
+
/** Renders at most MAX_PR_PACKAGE_LINES lines (and at most
|
|
80
|
+
* MAX_PR_PACKAGE_LIST_CHARS characters) of `lines`, then a count of the rest. */
|
|
81
|
+
function cappedList(lines) {
|
|
82
|
+
const shown = [];
|
|
83
|
+
let chars = 0;
|
|
84
|
+
for (const line of lines.slice(0, MAX_PR_PACKAGE_LINES)) {
|
|
85
|
+
if (chars + line.length + 1 > MAX_PR_PACKAGE_LIST_CHARS)
|
|
86
|
+
break;
|
|
87
|
+
shown.push(line);
|
|
88
|
+
chars += line.length + 1;
|
|
89
|
+
}
|
|
90
|
+
const more = lines.length - shown.length;
|
|
91
|
+
return more > 0 ? [...shown, `- …and ${more} more — see get_run for the full list`] : shown;
|
|
92
|
+
}
|
|
93
|
+
function packagesSection(input) {
|
|
94
|
+
const packages = [
|
|
95
|
+
...new Map((input.packages ?? [])
|
|
96
|
+
.filter((pkg) => isSafeMarkdownFragment(pkg.ecosystem) &&
|
|
97
|
+
isSafeMarkdownFragment(pkg.name) &&
|
|
98
|
+
isSafeMarkdownFragment(pkg.version))
|
|
99
|
+
.map((pkg) => [`${pkg.ecosystem}\0${pkg.name}\0${pkg.version}`, pkg])).values(),
|
|
100
|
+
];
|
|
101
|
+
const refusals = [
|
|
102
|
+
...new Map((input.packageRefusals ?? [])
|
|
103
|
+
.filter((refusal) => isSafeMarkdownFragment(refusal.ecosystem) &&
|
|
104
|
+
isSafeMarkdownFragment(refusal.name) &&
|
|
105
|
+
isSafeMarkdownFragment(refusal.reason))
|
|
106
|
+
.map((refusal) => [`${refusal.ecosystem}\0${refusal.name}\0${refusal.reason}`, refusal])).values(),
|
|
107
|
+
];
|
|
108
|
+
if (packages.length === 0 && refusals.length === 0)
|
|
109
|
+
return undefined;
|
|
110
|
+
return [
|
|
111
|
+
"<details>",
|
|
112
|
+
`<summary>Packages installed during this run (${packages.length})</summary>`,
|
|
113
|
+
"",
|
|
114
|
+
...cappedList(packages.map((pkg) => `- ${pkg.ecosystem} \`${pkg.name}@${pkg.version}\``)),
|
|
115
|
+
...(refusals.length > 0
|
|
116
|
+
? [
|
|
117
|
+
"",
|
|
118
|
+
"**Refused:**",
|
|
119
|
+
...cappedList(refusals.map((refusal) => `- ${refusal.ecosystem} \`${refusal.name}\`: ${refusal.reason}`)),
|
|
120
|
+
]
|
|
121
|
+
: []),
|
|
122
|
+
"</details>",
|
|
123
|
+
].join("\n");
|
|
37
124
|
}
|
|
38
125
|
/** The hidden run marker stays first and unconditional: createOrFindDraftPullRequest's idempotent lookup depends on it. */
|
|
39
|
-
function pullRequestBody(input) {
|
|
126
|
+
export function pullRequestBody(input) {
|
|
40
127
|
const sections = [`${RUN_MARKER_PREFIX}${input.runId} -->`];
|
|
128
|
+
// Hidden marker stays first; the issue link is the first visible line.
|
|
129
|
+
const issue = issueLine(input);
|
|
130
|
+
if (issue)
|
|
131
|
+
sections.push(issue);
|
|
41
132
|
if (input.summary)
|
|
42
133
|
sections.push(input.summary);
|
|
43
134
|
if (input.tests?.length) {
|
|
44
135
|
sections.push(["**Tests:**", ...input.tests.map((test) => `- \`${test.command}\`: ${test.outcome}`)].join("\n"));
|
|
45
136
|
}
|
|
137
|
+
// The packages section is informational: a failure rendering it (e.g. a
|
|
138
|
+
// malformed report) omits the section and never fails finalization.
|
|
139
|
+
try {
|
|
140
|
+
const packages = packagesSection(input);
|
|
141
|
+
if (packages)
|
|
142
|
+
sections.push(packages);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// omitted
|
|
146
|
+
}
|
|
46
147
|
return sections.join("\n\n");
|
|
47
148
|
}
|
|
48
149
|
/** The hidden marker stays first and unconditional: findStatusComment's lookup depends on it. */
|
|
@@ -108,8 +209,17 @@ export class GitHubAppClient {
|
|
|
108
209
|
* apparently isn't gated the same way a genuine issue comment might be.)
|
|
109
210
|
*/
|
|
110
211
|
async withChecksToken(repository, action) {
|
|
212
|
+
return this.withScopedToken(repository, { checks: "write" }, action);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Mints an installation token for exactly `permissions` on one repository,
|
|
216
|
+
* runs `action`, and always revokes. The building block for the
|
|
217
|
+
* code-review host (providers/review-host/github.ts), whose calls each
|
|
218
|
+
* request only what they need.
|
|
219
|
+
*/
|
|
220
|
+
async withScopedToken(repository, permissions, action) {
|
|
111
221
|
const normalized = normalizeGitHubRepository(repository);
|
|
112
|
-
const token = await this.
|
|
222
|
+
const token = await this.mintScopedToken(normalized, permissions, (name, level) => (name === "metadata" && level === "read") || permissions[name] === level);
|
|
113
223
|
try {
|
|
114
224
|
return await action(token);
|
|
115
225
|
}
|
|
@@ -117,6 +227,74 @@ export class GitHubAppClient {
|
|
|
117
227
|
await this.revokeToken(token).catch(() => undefined);
|
|
118
228
|
}
|
|
119
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* One file's raw text at a ref, without a clone (a Contents: read token).
|
|
232
|
+
* Requests the raw media type; GitHub honors it for an ordinary file but
|
|
233
|
+
* falls back to a JSON metadata response for anything else the raw type
|
|
234
|
+
* doesn't apply to -- a directory listing (a JSON array) or a symlink /
|
|
235
|
+
* submodule (a JSON object whose `type` isn't "file"). Either of those, or
|
|
236
|
+
* a 404, means there's no file text to return.
|
|
237
|
+
*/
|
|
238
|
+
async readFileAtRef(input) {
|
|
239
|
+
if (!SAFE_FILE_PATH.test(input.path) || input.path.split("/").some((part) => part === "." || part === "..")) {
|
|
240
|
+
throw new Error("github_file_path_invalid");
|
|
241
|
+
}
|
|
242
|
+
const repository = normalizeGitHubRepository(input.repository);
|
|
243
|
+
const ref = normalizeGitRef(input.ref);
|
|
244
|
+
const [owner, name] = repository.split("/");
|
|
245
|
+
const path = input.path.split("/").map(encodeURIComponent).join("/");
|
|
246
|
+
return this.withScopedToken(repository, { contents: "read" }, async (token) => {
|
|
247
|
+
const response = await this.requestJson(`/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/contents/${path}?ref=${encodeURIComponent(ref)}`, token, { headers: { accept: "application/vnd.github.raw+json" } }, [200, 404]);
|
|
248
|
+
if (response.status === 404)
|
|
249
|
+
return null;
|
|
250
|
+
const declared = Number(response.headers.get("content-length") ?? Number.NaN);
|
|
251
|
+
if (Number.isFinite(declared) && declared > input.maxBytes)
|
|
252
|
+
throw new Error("github_file_too_large");
|
|
253
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
254
|
+
if (bytes.byteLength > input.maxBytes)
|
|
255
|
+
throw new Error("github_file_too_large");
|
|
256
|
+
let text;
|
|
257
|
+
try {
|
|
258
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
throw new Error("github_file_not_utf8");
|
|
262
|
+
}
|
|
263
|
+
// Not raw content check: try to read the body as GitHub's own
|
|
264
|
+
// metadata shape rather than trusting the content-type header, since
|
|
265
|
+
// the raw media type itself is "application/vnd.github.raw+json" --
|
|
266
|
+
// a substring check for "json" would misfire on every real file.
|
|
267
|
+
let metadata;
|
|
268
|
+
try {
|
|
269
|
+
metadata = JSON.parse(text);
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return text;
|
|
273
|
+
}
|
|
274
|
+
if (Array.isArray(metadata))
|
|
275
|
+
throw new Error("github_file_not_a_file");
|
|
276
|
+
if (metadata && typeof metadata === "object" && "type" in metadata && metadata.type !== "file") {
|
|
277
|
+
throw new Error("github_file_not_a_file");
|
|
278
|
+
}
|
|
279
|
+
return text;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
identity;
|
|
283
|
+
/** The App's id and slug (its @-mention handle), read once with the App JWT. */
|
|
284
|
+
appIdentity() {
|
|
285
|
+
this.identity ??= (async () => {
|
|
286
|
+
const response = await this.requestJson("/app", await this.appJwt());
|
|
287
|
+
const payload = record(await response.json());
|
|
288
|
+
if (typeof payload.slug !== "string" || !/^[a-z0-9-]{1,64}$/.test(payload.slug)) {
|
|
289
|
+
throw new Error("github_api_invalid_response");
|
|
290
|
+
}
|
|
291
|
+
return { id: positiveInteger(payload.id), slug: payload.slug };
|
|
292
|
+
})().catch((err) => {
|
|
293
|
+
this.identity = undefined;
|
|
294
|
+
throw err;
|
|
295
|
+
});
|
|
296
|
+
return this.identity;
|
|
297
|
+
}
|
|
120
298
|
async upsertContinuationStatusComment(input) {
|
|
121
299
|
const repository = normalizeGitHubRepository(input.repository);
|
|
122
300
|
const baseRef = normalizeGitRef(input.baseRef);
|
|
@@ -125,7 +303,13 @@ export class GitHubAppClient {
|
|
|
125
303
|
throw new Error("github_status_comment_input_invalid");
|
|
126
304
|
}
|
|
127
305
|
await this.withRepositoryToken(repository, async (token) => {
|
|
128
|
-
const pr = await this.findPullRequest(token, {
|
|
306
|
+
const pr = await this.findPullRequest(token, {
|
|
307
|
+
runId: input.rootRunId,
|
|
308
|
+
repository,
|
|
309
|
+
baseRef,
|
|
310
|
+
headRef,
|
|
311
|
+
acceptReadyForReview: true,
|
|
312
|
+
});
|
|
129
313
|
if (!pr)
|
|
130
314
|
return;
|
|
131
315
|
const existing = await this.findStatusComment(token, repository, pr.number, input.runId);
|
|
@@ -147,7 +331,13 @@ export class GitHubAppClient {
|
|
|
147
331
|
throw new Error("github_status_comment_input_invalid");
|
|
148
332
|
}
|
|
149
333
|
await this.withRepositoryToken(repository, async (token) => {
|
|
150
|
-
const pr = await this.findPullRequest(token, {
|
|
334
|
+
const pr = await this.findPullRequest(token, {
|
|
335
|
+
runId: input.rootRunId,
|
|
336
|
+
repository,
|
|
337
|
+
baseRef,
|
|
338
|
+
headRef,
|
|
339
|
+
acceptReadyForReview: true,
|
|
340
|
+
});
|
|
151
341
|
if (!pr)
|
|
152
342
|
return;
|
|
153
343
|
const existing = await this.findStatusComment(token, repository, pr.number, input.runId);
|
|
@@ -253,24 +443,27 @@ export class GitHubAppClient {
|
|
|
253
443
|
(name === "pull_requests" && level === "write") ||
|
|
254
444
|
(name === "metadata" && level === "read"));
|
|
255
445
|
}
|
|
256
|
-
async mintChecksToken(repository) {
|
|
257
|
-
return this.mintScopedToken(repository, { checks: "write" }, (name, level) => (name === "checks" && level === "write") || (name === "metadata" && level === "read"));
|
|
258
|
-
}
|
|
259
446
|
/**
|
|
260
447
|
* Shared installation-token mint: requests exactly `permissions`, then
|
|
261
448
|
* verifies the response granted exactly that (no more, no less, modulo
|
|
262
449
|
* the always-implicit `metadata: read`) before trusting the token. Each
|
|
263
450
|
* caller requests the narrowest permission set it needs — see
|
|
264
|
-
*
|
|
451
|
+
* withScopedToken/withChecksToken for why these are minted separately
|
|
265
452
|
* from withRepositoryToken rather than requesting a union of everything.
|
|
266
453
|
*/
|
|
267
454
|
async mintScopedToken(repository, permissions, isAllowedPermission) {
|
|
268
455
|
const [owner, name] = repository.split("/");
|
|
269
456
|
const appJwt = await this.appJwt();
|
|
270
|
-
const installationResponse = await this.requestJson(`/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/installation`, appJwt);
|
|
457
|
+
const installationResponse = await this.requestJson(`/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/installation`, appJwt, {}, [200, 404]);
|
|
458
|
+
if (installationResponse.status === 404)
|
|
459
|
+
throw new Error("github_app_not_installed");
|
|
271
460
|
const installation = record(await installationResponse.json());
|
|
272
461
|
const installationId = positiveInteger(installation.id);
|
|
273
|
-
const tokenResponse = await this.requestJson(`/app/installations/${installationId}/access_tokens`, appJwt, { method: "POST", body: JSON.stringify({ repositories: [name], permissions }) }, [201]);
|
|
462
|
+
const tokenResponse = await this.requestJson(`/app/installations/${installationId}/access_tokens`, appJwt, { method: "POST", body: JSON.stringify({ repositories: [name], permissions }) }, [201, 422]);
|
|
463
|
+
// 422: the installation has not granted a requested permission (e.g. a
|
|
464
|
+
// new permission the owner has not accepted yet).
|
|
465
|
+
if (tokenResponse.status === 422)
|
|
466
|
+
throw new Error("github_installation_token_scope_invalid");
|
|
274
467
|
const payload = record(await tokenResponse.json());
|
|
275
468
|
const grantedPermissions = record(payload.permissions);
|
|
276
469
|
const repositories = Array.isArray(payload.repositories) ? payload.repositories.map(record) : [];
|
|
@@ -307,17 +500,15 @@ export class GitHubAppClient {
|
|
|
307
500
|
for (const item of payload) {
|
|
308
501
|
const candidate = record(item);
|
|
309
502
|
if (typeof candidate.body === "string" && candidate.body.includes(marker)) {
|
|
310
|
-
|
|
311
|
-
throw new Error("github_pull_request_not_draft");
|
|
312
|
-
return this.parsePullRequest(candidate, input.repository);
|
|
503
|
+
return this.parsePullRequest(candidate, input.repository, input.acceptReadyForReview === true);
|
|
313
504
|
}
|
|
314
505
|
}
|
|
315
506
|
return null;
|
|
316
507
|
}
|
|
317
|
-
parsePullRequest(value, repository) {
|
|
508
|
+
parsePullRequest(value, repository, acceptReadyForReview = false) {
|
|
318
509
|
const payload = record(value);
|
|
319
510
|
const number = positiveInteger(payload.number);
|
|
320
|
-
if (payload.draft !== true)
|
|
511
|
+
if (payload.draft !== true && !acceptReadyForReview)
|
|
321
512
|
throw new Error("github_pull_request_not_draft");
|
|
322
513
|
const expectedUrl = `https://github.com/${repository}/pull/${number}`;
|
|
323
514
|
if (typeof payload.html_url !== "string")
|
|
@@ -367,6 +558,7 @@ export class GitHubAppClient {
|
|
|
367
558
|
}
|
|
368
559
|
return null;
|
|
369
560
|
}
|
|
561
|
+
/** Public for the code-review host, which issues its own REST calls with tokens minted here. */
|
|
370
562
|
async requestJson(path, bearer, init = {}, expectedStatuses = [200]) {
|
|
371
563
|
let response;
|
|
372
564
|
try {
|
|
@@ -391,4 +583,18 @@ export class GitHubAppClient {
|
|
|
391
583
|
throw safeApiError(response);
|
|
392
584
|
return response;
|
|
393
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* Public for the code-review host: one GraphQL request, for what REST lacks
|
|
588
|
+
* (review threads). A response carrying `errors` fails like a REST error.
|
|
589
|
+
*/
|
|
590
|
+
async graphql(bearer, query, variables) {
|
|
591
|
+
const response = await this.requestJson("/graphql", bearer, {
|
|
592
|
+
method: "POST",
|
|
593
|
+
body: JSON.stringify({ query, variables }),
|
|
594
|
+
});
|
|
595
|
+
const payload = record(await response.json());
|
|
596
|
+
if (Array.isArray(payload.errors) && payload.errors.length > 0)
|
|
597
|
+
throw new Error("github_graphql_error");
|
|
598
|
+
return record(payload.data);
|
|
599
|
+
}
|
|
394
600
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import type { RepositoryFileInput } from "./github.js";
|
|
1
2
|
export interface VcsPrepareInput {
|
|
2
3
|
runId: string;
|
|
3
4
|
repository: string;
|
|
4
5
|
baseRef: string;
|
|
5
6
|
headRef: string;
|
|
6
7
|
protectedPaths: string[];
|
|
8
|
+
/** Repository-relative paths never collected, in addition to the built-in names. */
|
|
9
|
+
collectExclude?: string[];
|
|
7
10
|
/**
|
|
8
11
|
* Revision-in-place: set when headRef is an EXISTING branch to continue
|
|
9
12
|
* rather than a fresh one
|
|
@@ -38,6 +41,7 @@ export interface PreparedWorkspace {
|
|
|
38
41
|
workspacePath: string;
|
|
39
42
|
gitMetadataPath: string;
|
|
40
43
|
protectedPaths: string[];
|
|
44
|
+
collectExclude: string[];
|
|
41
45
|
continuation?: {
|
|
42
46
|
rootRunId: string;
|
|
43
47
|
};
|
|
@@ -50,6 +54,23 @@ export interface FinalizeChangesDetails {
|
|
|
50
54
|
outcome: "passed" | "failed" | "skipped";
|
|
51
55
|
}[];
|
|
52
56
|
tag?: string;
|
|
57
|
+
/** Packages the registry proxy served/refused during this run (RegistryFetch), for the PR body. */
|
|
58
|
+
packages?: readonly {
|
|
59
|
+
ecosystem: string;
|
|
60
|
+
name: string;
|
|
61
|
+
version: string;
|
|
62
|
+
}[];
|
|
63
|
+
packageRefusals?: readonly {
|
|
64
|
+
ecosystem: string;
|
|
65
|
+
name: string;
|
|
66
|
+
reason: string;
|
|
67
|
+
}[];
|
|
68
|
+
/** Originating issue (control-plane data): named in the PR title and body. Provider-neutral. */
|
|
69
|
+
issue?: {
|
|
70
|
+
key: string;
|
|
71
|
+
url?: string;
|
|
72
|
+
trackerName?: string;
|
|
73
|
+
};
|
|
53
74
|
}
|
|
54
75
|
export type FinalizeChangesResult = {
|
|
55
76
|
outcome: "no_changes";
|
|
@@ -110,9 +131,32 @@ export interface VcsProvider {
|
|
|
110
131
|
* (the same text that goes in the PR body -- see
|
|
111
132
|
* `FinalizeChangesDetails.summary`) so the "done" status reflects what
|
|
112
133
|
* actually happened instead of a caller having to go find out.
|
|
134
|
+
* `budget_exhausted` is a failure that ran out of budget;
|
|
135
|
+
* `details.budgetSentence` then says how (see core/budget-wording.ts).
|
|
136
|
+
* A `failed` run the model provider refused carries `details.providerSentence`.
|
|
137
|
+
* A `failed` run whose changes touched a protected path carries
|
|
138
|
+
* `details.protectedPathSentence` (see coding/protected-path-wording.ts).
|
|
113
139
|
*/
|
|
114
|
-
notifyContinuationFinished?(workspace: PreparedWorkspace, outcome:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
140
|
+
notifyContinuationFinished?(workspace: PreparedWorkspace, outcome: ContinuationOutcome, details?: ContinuationFinishedDetails): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* The raw text of one repository file at a ref, read through the host's API
|
|
143
|
+
* without a clone, or null when it does not exist. Dispatch reads a coding
|
|
144
|
+
* run's .wardby/services.yaml from its base branch with it
|
|
145
|
+
* (docs/coding-services.md). Optional, mirroring notifyContinuationStarted: a
|
|
146
|
+
* provider (or test double) without it gives runs no services.
|
|
147
|
+
*/
|
|
148
|
+
readRepositoryFile?(input: RepositoryFileInput): Promise<string | null>;
|
|
149
|
+
}
|
|
150
|
+
export type ContinuationOutcome = "succeeded" | "failed" | "budget_exhausted";
|
|
151
|
+
export interface ContinuationFinishedDetails {
|
|
152
|
+
summary?: string;
|
|
153
|
+
agentName?: string;
|
|
154
|
+
/** Host-safe sentence naming the run's budget; used with `budget_exhausted`. */
|
|
155
|
+
budgetSentence?: string;
|
|
156
|
+
/** Host-safe sentence naming a model-provider refusal (see core/provider-wording.ts); used with `failed`. */
|
|
157
|
+
providerSentence?: string;
|
|
158
|
+
/** Host-safe sentence naming a coding-run service that never became ready (coding/services/wording.ts); used with `failed`. */
|
|
159
|
+
serviceSentence?: string;
|
|
160
|
+
/** Host-safe sentence naming a protected path the run's changes touched (coding/protected-path-wording.ts); used with `failed`. */
|
|
161
|
+
protectedPathSentence?: string;
|
|
118
162
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare function quickstartCommand(args: string[]): Promise<void>;
|
|
2
|
+
/** The closing "build your first agent" hint; the assistant prompts only make sense once an MCP client is configured. */
|
|
3
|
+
export declare function nextStepLines(mcpConfigured: boolean): string[];
|
|
2
4
|
export declare function doctorCommand(args: string[]): Promise<void>;
|
|
3
5
|
export declare function statusCommand(args: string[]): Promise<void>;
|
|
4
6
|
export declare function logsCommand(args: string[]): Promise<void>;
|
package/dist/quickstart/index.js
CHANGED
|
@@ -212,8 +212,13 @@ function applyMigrations(paths) {
|
|
|
212
212
|
}
|
|
213
213
|
async function seedDemo(paths, state, budget) {
|
|
214
214
|
const { createPrismaClient } = await import("../core/db.js");
|
|
215
|
-
const
|
|
215
|
+
const { resolvePrincipal } = await import("../mcp/auth/principal.js");
|
|
216
|
+
const env = readQuickstartEnv(paths);
|
|
217
|
+
const db = createPrismaClient(env.DATABASE_URL);
|
|
216
218
|
try {
|
|
219
|
+
// The demo agent belongs to the local operator (LOCAL_PRINCIPAL) and is
|
|
220
|
+
// private: agents are never owner-less (resource-sharing grants).
|
|
221
|
+
const owner = await resolvePrincipal(env.LOCAL_PRINCIPAL || "local", db);
|
|
217
222
|
const existing = await db.agent.findUnique({ where: { name: DEMO_AGENT } });
|
|
218
223
|
if (existing && existing.systemPrompt !== DEMO_PROMPT) {
|
|
219
224
|
throw new Error(`An agent named "${DEMO_AGENT}" already exists and was not created by quickstart; rename it or use --skip-demo.`);
|
|
@@ -221,7 +226,12 @@ async function seedDemo(paths, state, budget) {
|
|
|
221
226
|
if (existing) {
|
|
222
227
|
await db.agent.update({
|
|
223
228
|
where: { name: DEMO_AGENT },
|
|
224
|
-
data: {
|
|
229
|
+
data: {
|
|
230
|
+
model: state.model,
|
|
231
|
+
budgetUsd: budget,
|
|
232
|
+
maxTurns: 2,
|
|
233
|
+
...(existing.ownerId ? {} : { ownerId: owner.id }),
|
|
234
|
+
},
|
|
225
235
|
});
|
|
226
236
|
}
|
|
227
237
|
else {
|
|
@@ -232,6 +242,7 @@ async function seedDemo(paths, state, budget) {
|
|
|
232
242
|
budgetUsd: budget,
|
|
233
243
|
maxTurns: 2,
|
|
234
244
|
systemPrompt: DEMO_PROMPT,
|
|
245
|
+
ownerId: owner.id,
|
|
235
246
|
},
|
|
236
247
|
});
|
|
237
248
|
}
|
|
@@ -255,12 +266,12 @@ function clientInstalled(command) {
|
|
|
255
266
|
function configureOneMcpClient(client, paths) {
|
|
256
267
|
if (!clientInstalled(client)) {
|
|
257
268
|
console.warn(`! ${client} is not installed; skipped its MCP configuration.`);
|
|
258
|
-
return;
|
|
269
|
+
return false;
|
|
259
270
|
}
|
|
260
271
|
const existing = runCommand(client, ["mcp", "get", "wardby"], { cwd: paths.projectDir });
|
|
261
272
|
if (existing.status === 0) {
|
|
262
273
|
console.log(`✓ ${client} already has an MCP server named wardby.`);
|
|
263
|
-
return;
|
|
274
|
+
return true;
|
|
264
275
|
}
|
|
265
276
|
const packageSpec = `@wardby/cli@${packageJson.version}`;
|
|
266
277
|
const args = client === "codex"
|
|
@@ -294,12 +305,16 @@ function configureOneMcpClient(client, paths) {
|
|
|
294
305
|
if (result.status !== 0)
|
|
295
306
|
commandFailure(`${client} MCP configuration`, result);
|
|
296
307
|
console.log(`✓ Configured Wardby MCP for ${client}.`);
|
|
308
|
+
return true;
|
|
297
309
|
}
|
|
310
|
+
/** True when at least one requested client ended up with the wardby MCP server. */
|
|
298
311
|
function configureMcpClients(client, paths) {
|
|
312
|
+
const results = [];
|
|
299
313
|
if (client === "codex" || client === "both")
|
|
300
|
-
configureOneMcpClient("codex", paths);
|
|
314
|
+
results.push(configureOneMcpClient("codex", paths));
|
|
301
315
|
if (client === "claude" || client === "both")
|
|
302
|
-
configureOneMcpClient("claude", paths);
|
|
316
|
+
results.push(configureOneMcpClient("claude", paths));
|
|
317
|
+
return results.some(Boolean);
|
|
303
318
|
}
|
|
304
319
|
async function chooseClient(nonInteractive) {
|
|
305
320
|
if (nonInteractive)
|
|
@@ -401,12 +416,25 @@ export async function quickstartCommand(args) {
|
|
|
401
416
|
console.log(`Skipped the billed run. Start it later with: npx @wardby/cli@latest run ${DEMO_AGENT}`);
|
|
402
417
|
}
|
|
403
418
|
const client = parseClient(values.client) ?? (await chooseClient(nonInteractive));
|
|
404
|
-
|
|
405
|
-
configureMcpClients(client, paths);
|
|
419
|
+
const mcpConfigured = client !== "none" && configureMcpClients(client, paths);
|
|
406
420
|
console.log("\nWardby is ready.");
|
|
407
421
|
console.log(" npx @wardby/cli@latest status");
|
|
408
422
|
console.log(" npx @wardby/cli@latest doctor");
|
|
409
423
|
console.log(" npx @wardby/cli@latest down");
|
|
424
|
+
for (const line of nextStepLines(mcpConfigured))
|
|
425
|
+
console.log(line);
|
|
426
|
+
}
|
|
427
|
+
/** The closing "build your first agent" hint; the assistant prompts only make sense once an MCP client is configured. */
|
|
428
|
+
export function nextStepLines(mcpConfigured) {
|
|
429
|
+
const guide = "the guide: npx @wardby/cli@latest help open agent-recipes";
|
|
430
|
+
const lines = ["", "Next: build your first agent."];
|
|
431
|
+
if (mcpConfigured) {
|
|
432
|
+
lines.push("Ask your assistant one of:", ' "Set up the Wardby architecture keeper for this repository"', ' "Set up a Wardby builder for this repository"', `Or read ${guide}`);
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
lines.push(`Read ${guide}`);
|
|
436
|
+
}
|
|
437
|
+
return lines;
|
|
410
438
|
}
|
|
411
439
|
async function databaseHealthy(paths) {
|
|
412
440
|
const env = readQuickstartEnv(paths);
|