@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
|
@@ -13,12 +13,11 @@
|
|
|
13
13
|
* `recover()` (Task 6) before declaring a DBOS run lost.
|
|
14
14
|
*/
|
|
15
15
|
import type { PrismaClient } from "#prisma";
|
|
16
|
-
import type { ProviderRegistry } from "../index.js";
|
|
17
16
|
import type { DbosConfig } from "../../config/providers.js";
|
|
18
|
-
import { type RunnerDb } from "../../core/runner.js";
|
|
17
|
+
import { type NativeRunProviders, type RunnerDb } from "../../core/runner.js";
|
|
19
18
|
import type { Executor, ExecutionRecoveryResult, PersistedExecutionHandle } from "./types.js";
|
|
20
19
|
export declare const DBOS_BACKEND = "dbos";
|
|
21
|
-
type Providers =
|
|
20
|
+
type Providers = NativeRunProviders;
|
|
22
21
|
type Db = RunnerDb & Pick<PrismaClient, "run">;
|
|
23
22
|
export declare class DbosExecutor implements Executor {
|
|
24
23
|
private readonly providers;
|
|
@@ -39,6 +38,8 @@ export declare class DbosExecutor implements Executor {
|
|
|
39
38
|
get executorId(): string;
|
|
40
39
|
launch(): Promise<void>;
|
|
41
40
|
close(): Promise<void>;
|
|
41
|
+
/** Where a run this executor marks failed files its self-defect (no-op without a configured issue tracker). */
|
|
42
|
+
private get selfDefects();
|
|
42
43
|
start(runId: string): Promise<void>;
|
|
43
44
|
stop(runId: string, reason?: string): Promise<void>;
|
|
44
45
|
/**
|
|
@@ -133,6 +133,10 @@ export class DbosExecutor {
|
|
|
133
133
|
setActiveExecutor(undefined);
|
|
134
134
|
await DBOS.shutdown({ workflowCompletionTimeoutMS: 5_000 });
|
|
135
135
|
}
|
|
136
|
+
/** Where a run this executor marks failed files its self-defect (no-op without a configured issue tracker). */
|
|
137
|
+
get selfDefects() {
|
|
138
|
+
return { db: this.db, issueTrackers: this.providers.issueTrackers };
|
|
139
|
+
}
|
|
136
140
|
async start(runId) {
|
|
137
141
|
if (!this.launched)
|
|
138
142
|
await this.launch();
|
|
@@ -165,7 +169,7 @@ export class DbosExecutor {
|
|
|
165
169
|
// the same failure — dispatchRun's own `.catch` around `start()` calls
|
|
166
170
|
// it too — which is harmless precisely because it is conditional and
|
|
167
171
|
// idempotent: the second call matches zero rows.
|
|
168
|
-
await markRunFailedFromExecutorError(this.db, runId, err);
|
|
172
|
+
await markRunFailedFromExecutorError(this.db, runId, err, this.selfDefects);
|
|
169
173
|
throw err;
|
|
170
174
|
}
|
|
171
175
|
}
|
|
@@ -241,10 +245,8 @@ export class DbosExecutor {
|
|
|
241
245
|
return { state: "terminal" };
|
|
242
246
|
case "mark-failed":
|
|
243
247
|
this.resumeAttempts.delete(handle.runId);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
data: { status: "failed", error: decision.error, finishedAt: new Date() },
|
|
247
|
-
});
|
|
248
|
+
// Conditional (only a pending/running row), so a self-defect is filed only when this made the run failed.
|
|
249
|
+
await markRunFailedFromExecutorError(this.db, handle.runId, decision.error, this.selfDefects);
|
|
248
250
|
return { state: "terminal" };
|
|
249
251
|
case "lost":
|
|
250
252
|
this.resumeAttempts.delete(handle.runId);
|
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
* heartbeat and recovers the run to `lost` rather than leaving it stuck
|
|
6
6
|
* `running` forever.
|
|
7
7
|
*/
|
|
8
|
-
import type
|
|
9
|
-
import { type RunnerDb } from "../../core/runner.js";
|
|
8
|
+
import { type NativeRunProviders, type RunnerDb } from "../../core/runner.js";
|
|
10
9
|
import type { Executor } from "./types.js";
|
|
11
10
|
export declare class InProcessExecutor implements Executor {
|
|
12
11
|
private readonly providers;
|
|
13
12
|
private readonly db;
|
|
14
13
|
private readonly heartbeatIntervalMs;
|
|
15
|
-
constructor(providers:
|
|
14
|
+
constructor(providers: NativeRunProviders, db?: RunnerDb, heartbeatIntervalMs?: number);
|
|
16
15
|
start(runId: string): Promise<void>;
|
|
17
16
|
stop(_runId: string, _reason?: string): Promise<void>;
|
|
18
17
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CodingImageSelector, Executor, ExecutionRecoveryResult, PersistedExecutionHandle } from "./types.js";
|
|
2
|
+
import type { CodingProvider } from "../../coding/provider.js";
|
|
2
3
|
export interface ExecutionKindResolver {
|
|
3
4
|
kindForRun(runId: string): Promise<"native" | "coding" | null>;
|
|
4
5
|
}
|
|
@@ -21,6 +22,18 @@ export declare class RoutingExecutor implements Executor {
|
|
|
21
22
|
launch(): Promise<void>;
|
|
22
23
|
close(): Promise<void>;
|
|
23
24
|
resolveCodingWorkerImage(selector: CodingImageSelector): string;
|
|
25
|
+
resolveCodingToolImage(selector: CodingImageSelector): string | null;
|
|
26
|
+
readCodingServiceDeclaration(input: {
|
|
27
|
+
repository: string;
|
|
28
|
+
baseRef: string;
|
|
29
|
+
}): Promise<string | null>;
|
|
30
|
+
readCodingRepositoryFile(input: {
|
|
31
|
+
repository: string;
|
|
32
|
+
baseRef: string;
|
|
33
|
+
path: string;
|
|
34
|
+
maxBytes: number;
|
|
35
|
+
}): Promise<string | null>;
|
|
36
|
+
supportsCodingServices(provider: CodingProvider): boolean;
|
|
24
37
|
}
|
|
25
38
|
export declare class PrismaExecutionKindResolver implements ExecutionKindResolver {
|
|
26
39
|
private readonly db;
|
|
@@ -54,6 +54,24 @@ export class RoutingExecutor {
|
|
|
54
54
|
throw new Error("coding_execution_not_configured");
|
|
55
55
|
return this.coding.resolveCodingWorkerImage(selector);
|
|
56
56
|
}
|
|
57
|
+
resolveCodingToolImage(selector) {
|
|
58
|
+
if (!this.coding.resolveCodingToolImage)
|
|
59
|
+
throw new Error("coding_execution_not_configured");
|
|
60
|
+
return this.coding.resolveCodingToolImage(selector);
|
|
61
|
+
}
|
|
62
|
+
async readCodingServiceDeclaration(input) {
|
|
63
|
+
if (!this.coding.readCodingServiceDeclaration)
|
|
64
|
+
return null;
|
|
65
|
+
return this.coding.readCodingServiceDeclaration(input);
|
|
66
|
+
}
|
|
67
|
+
async readCodingRepositoryFile(input) {
|
|
68
|
+
if (!this.coding.readCodingRepositoryFile)
|
|
69
|
+
return null;
|
|
70
|
+
return this.coding.readCodingRepositoryFile(input);
|
|
71
|
+
}
|
|
72
|
+
supportsCodingServices(provider) {
|
|
73
|
+
return this.coding.supportsCodingServices?.(provider) === true;
|
|
74
|
+
}
|
|
57
75
|
}
|
|
58
76
|
export class PrismaExecutionKindResolver {
|
|
59
77
|
db;
|
|
@@ -51,5 +51,39 @@ export interface Executor {
|
|
|
51
51
|
* the LLM pricing tables' unknown-model throw.
|
|
52
52
|
*/
|
|
53
53
|
resolveCodingWorkerImage?(selector: CodingImageSelector): string;
|
|
54
|
+
/**
|
|
55
|
+
* Claude Code's tool-runner image (the container that runs its commands) for the agent's
|
|
56
|
+
* toolchain, resolved and persisted at dispatch alongside the worker image; null for Codex, whose
|
|
57
|
+
* one worker image carries the toolchain. Throws, like resolveCodingWorkerImage, on a toolchain
|
|
58
|
+
* with no image.
|
|
59
|
+
*/
|
|
60
|
+
resolveCodingToolImage?(selector: CodingImageSelector): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Coding-run services (docs/coding-services.md): the raw text of the
|
|
63
|
+
* repository's .wardby/services.yaml at `baseRef`, or null when it has none.
|
|
64
|
+
* Called by dispatch before its transaction (it is a network call). An
|
|
65
|
+
* executor without it gives coding runs no services.
|
|
66
|
+
*/
|
|
67
|
+
readCodingServiceDeclaration?(input: {
|
|
68
|
+
repository: string;
|
|
69
|
+
baseRef: string;
|
|
70
|
+
}): Promise<string | null>;
|
|
71
|
+
/**
|
|
72
|
+
* The raw text of one repository file at `baseRef`, or null when absent.
|
|
73
|
+
* Throws (github_file_too_large, github_file_not_a_file, github_file_not_utf8)
|
|
74
|
+
* when the file is oversized or not UTF-8 text. Called by dispatch before its transaction (network call).
|
|
75
|
+
* Used for the knowledge note (src/knowledge/note.ts).
|
|
76
|
+
*/
|
|
77
|
+
readCodingRepositoryFile?(input: {
|
|
78
|
+
repository: string;
|
|
79
|
+
baseRef: string;
|
|
80
|
+
path: string;
|
|
81
|
+
maxBytes: number;
|
|
82
|
+
}): Promise<string | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Whether this executor can start coding-run services for a run of `provider`: its job launcher
|
|
85
|
+
* says so (Kubernetes and Docker, for Codex and Claude Code).
|
|
86
|
+
*/
|
|
87
|
+
supportsCodingServices?(provider: CodingProvider): boolean;
|
|
54
88
|
}
|
|
55
89
|
import type { CodingProvider } from "../../coding/provider.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atlassian Document Format helpers. Jira Cloud's v3 API takes and returns
|
|
3
|
+
* rich text as ADF; webhook payloads use the v2 shape (wiki-markup strings),
|
|
4
|
+
* so the readers (adfToText, adfMentionIds) accept both. Agents write a
|
|
5
|
+
* small Markdown subset (markdownToAdf); the control plane reads issue text
|
|
6
|
+
* as plain text (adfToText). Nothing here
|
|
7
|
+
* produces HTML or mention nodes: a model can never ping a person.
|
|
8
|
+
*/
|
|
9
|
+
export interface AdfNode {
|
|
10
|
+
type: string;
|
|
11
|
+
version?: number;
|
|
12
|
+
attrs?: Record<string, unknown>;
|
|
13
|
+
content?: AdfNode[];
|
|
14
|
+
text?: string;
|
|
15
|
+
marks?: Array<{
|
|
16
|
+
type: string;
|
|
17
|
+
attrs?: Record<string, unknown>;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Smart links (ADF inlineCard, what Jira's editor makes from a pasted issue link) for this site's
|
|
22
|
+
* issues: a bare `<siteUrl>/browse/KEY-1` URL, and a bare `KEY-1` whose project is in `projectKeys`
|
|
23
|
+
* (only those, so look-alikes such as UTF-8 or SHA-256 stay text).
|
|
24
|
+
*/
|
|
25
|
+
export interface SmartLinkOptions {
|
|
26
|
+
siteUrl: string;
|
|
27
|
+
projectKeys?: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function markdownToAdf(markdown: string, smart?: SmartLinkOptions): AdfNode;
|
|
30
|
+
export declare function adfToText(node: unknown, maxChars?: number): string;
|
|
31
|
+
export declare function adfMentionIds(node: unknown): string[];
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// `_x_` is italic only when the underscores aren't inside a word, so
|
|
2
|
+
// snake_case identifiers (WARDBY_JIRA_API_TOKEN, my_var_name) stay literal.
|
|
3
|
+
// A bare https:// URL becomes a link too; it ends before whitespace or a
|
|
4
|
+
// bracket and drops trailing sentence punctuation (`see https://x/y.`).
|
|
5
|
+
const INLINE = /\*\*([^*]+)\*\*|`([^`]+)`|(?<![A-Za-z0-9_])_([^_\s][^_]*?)_(?![A-Za-z0-9_])|\[([^\]]+)\]\(([^)\s]+)\)|(https:\/\/[^\s<>()[\]"']*[^\s<>()[\]"'.,;:!?])/g;
|
|
6
|
+
const ISSUE_KEY = /^[A-Z][A-Z0-9_]+-[1-9][0-9]*$/;
|
|
7
|
+
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8
|
+
function inline(text, smart) {
|
|
9
|
+
const out = [];
|
|
10
|
+
const site = smart?.siteUrl.replace(/\/+$/, "");
|
|
11
|
+
const card = (key) => ({ type: "inlineCard", attrs: { url: `${site}/browse/${key}` } });
|
|
12
|
+
const keys = (smart?.projectKeys ?? []).filter((k) => /^[A-Z][A-Z0-9_]+$/.test(k));
|
|
13
|
+
const keyRe = keys.length
|
|
14
|
+
? new RegExp(`(?<![A-Za-z0-9_/.-])(?:${keys.map(escapeRe).join("|")})-[1-9][0-9]*(?![A-Za-z0-9_-])`, "g")
|
|
15
|
+
: null;
|
|
16
|
+
const plain = (t) => {
|
|
17
|
+
if (!t)
|
|
18
|
+
return;
|
|
19
|
+
if (!keyRe)
|
|
20
|
+
return void out.push({ type: "text", text: t });
|
|
21
|
+
let at = 0;
|
|
22
|
+
for (const k of t.matchAll(keyRe)) {
|
|
23
|
+
if (k.index > at)
|
|
24
|
+
out.push({ type: "text", text: t.slice(at, k.index) });
|
|
25
|
+
out.push(card(k[0]));
|
|
26
|
+
at = k.index + k[0].length;
|
|
27
|
+
}
|
|
28
|
+
if (at < t.length)
|
|
29
|
+
out.push({ type: "text", text: t.slice(at) });
|
|
30
|
+
};
|
|
31
|
+
const push = (t, marks) => {
|
|
32
|
+
if (!t)
|
|
33
|
+
return;
|
|
34
|
+
if (marks)
|
|
35
|
+
out.push({ type: "text", text: t, marks });
|
|
36
|
+
else
|
|
37
|
+
plain(t);
|
|
38
|
+
};
|
|
39
|
+
const siteIssueKey = (url) => {
|
|
40
|
+
if (!site || !url.startsWith(`${site}/browse/`))
|
|
41
|
+
return null;
|
|
42
|
+
const key = url.slice(site.length + "/browse/".length);
|
|
43
|
+
return ISSUE_KEY.test(key) ? key : null;
|
|
44
|
+
};
|
|
45
|
+
let last = 0;
|
|
46
|
+
for (const m of text.matchAll(INLINE)) {
|
|
47
|
+
push(text.slice(last, m.index));
|
|
48
|
+
if (m[1] !== undefined)
|
|
49
|
+
push(m[1], [{ type: "strong" }]);
|
|
50
|
+
else if (m[2] !== undefined)
|
|
51
|
+
push(m[2], [{ type: "code" }]);
|
|
52
|
+
else if (m[3] !== undefined)
|
|
53
|
+
push(m[3], [{ type: "em" }]);
|
|
54
|
+
else if (m[5]?.startsWith("https://"))
|
|
55
|
+
push(m[4], [{ type: "link", attrs: { href: m[5] } }]);
|
|
56
|
+
else if (m[6] !== undefined) {
|
|
57
|
+
const key = siteIssueKey(m[6]);
|
|
58
|
+
if (key)
|
|
59
|
+
out.push(card(key));
|
|
60
|
+
else
|
|
61
|
+
push(m[6], [{ type: "link", attrs: { href: m[6] } }]);
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
push(m[0]);
|
|
65
|
+
last = m.index + m[0].length;
|
|
66
|
+
}
|
|
67
|
+
push(text.slice(last));
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
export function markdownToAdf(markdown, smart) {
|
|
71
|
+
const paragraph = (text) => ({ type: "paragraph", content: inline(text, smart) });
|
|
72
|
+
const lines = markdown.replace(/\r\n/g, "\n").split("\n");
|
|
73
|
+
const content = [];
|
|
74
|
+
let i = 0;
|
|
75
|
+
while (i < lines.length) {
|
|
76
|
+
const line = lines[i];
|
|
77
|
+
if (line.trim() === "") {
|
|
78
|
+
i++;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const fence = /^```(\w*)\s*$/.exec(line);
|
|
82
|
+
if (fence) {
|
|
83
|
+
const body = [];
|
|
84
|
+
i++;
|
|
85
|
+
while (i < lines.length && !/^```\s*$/.test(lines[i]))
|
|
86
|
+
body.push(lines[i++]);
|
|
87
|
+
i++;
|
|
88
|
+
content.push({
|
|
89
|
+
type: "codeBlock",
|
|
90
|
+
...(fence[1] ? { attrs: { language: fence[1] } } : {}),
|
|
91
|
+
content: body.length ? [{ type: "text", text: body.join("\n") }] : [],
|
|
92
|
+
});
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const heading = /^(#{1,3})\s+(.*)$/.exec(line);
|
|
96
|
+
if (heading) {
|
|
97
|
+
content.push({ type: "heading", attrs: { level: heading[1].length }, content: inline(heading[2], smart) });
|
|
98
|
+
i++;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const listOf = (re, type) => {
|
|
102
|
+
const items = [];
|
|
103
|
+
while (i < lines.length && re.test(lines[i])) {
|
|
104
|
+
items.push({ type: "listItem", content: [paragraph(lines[i].replace(re, ""))] });
|
|
105
|
+
i++;
|
|
106
|
+
}
|
|
107
|
+
content.push({ type, content: items });
|
|
108
|
+
};
|
|
109
|
+
if (/^\s*[-*]\s+/.test(line)) {
|
|
110
|
+
listOf(/^\s*[-*]\s+/, "bulletList");
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (/^\s*\d+\.\s+/.test(line)) {
|
|
114
|
+
listOf(/^\s*\d+\.\s+/, "orderedList");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (/^>\s?/.test(line)) {
|
|
118
|
+
const quoted = [];
|
|
119
|
+
while (i < lines.length && /^>\s?/.test(lines[i]))
|
|
120
|
+
quoted.push(lines[i++].replace(/^>\s?/, ""));
|
|
121
|
+
content.push({ type: "blockquote", content: [paragraph(quoted.join(" "))] });
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const para = [];
|
|
125
|
+
while (i < lines.length && lines[i].trim() !== "" && !/^(```|#{1,3}\s|\s*[-*]\s|\s*\d+\.\s|>)/.test(lines[i])) {
|
|
126
|
+
para.push(lines[i++]);
|
|
127
|
+
}
|
|
128
|
+
content.push(paragraph(para.join(" ")));
|
|
129
|
+
}
|
|
130
|
+
return { type: "doc", version: 1, content };
|
|
131
|
+
}
|
|
132
|
+
const BLOCKS = new Set(["paragraph", "heading", "codeBlock", "blockquote", "listItem", "rule", "panel", "tableRow"]);
|
|
133
|
+
/**
|
|
134
|
+
* Webhook payloads carry rich text in the REST v2 shape: a wiki-markup
|
|
135
|
+
* string, where a mention is `[~accountid:<accountId>]`.
|
|
136
|
+
*/
|
|
137
|
+
const WIKI_MENTION = /\[~accountid:([^\]\s]+)\]/gi;
|
|
138
|
+
export function adfToText(node, maxChars = 20_000) {
|
|
139
|
+
if (typeof node === "string")
|
|
140
|
+
return cap(node.replace(WIKI_MENTION, "@user"), maxChars);
|
|
141
|
+
const parts = [];
|
|
142
|
+
const walk = (n) => {
|
|
143
|
+
if (!n || typeof n !== "object")
|
|
144
|
+
return;
|
|
145
|
+
const a = n;
|
|
146
|
+
if (a.type === "text" && typeof a.text === "string")
|
|
147
|
+
parts.push(a.text);
|
|
148
|
+
else if (a.type === "mention")
|
|
149
|
+
parts.push(typeof a.attrs?.text === "string" ? a.attrs.text : "@user");
|
|
150
|
+
else if (a.type === "hardBreak")
|
|
151
|
+
parts.push("\n");
|
|
152
|
+
for (const c of a.content ?? [])
|
|
153
|
+
walk(c);
|
|
154
|
+
if (BLOCKS.has(a.type))
|
|
155
|
+
parts.push("\n");
|
|
156
|
+
};
|
|
157
|
+
walk(node);
|
|
158
|
+
return cap(parts
|
|
159
|
+
.join("")
|
|
160
|
+
.replace(/\n{2,}/g, "\n")
|
|
161
|
+
.trim(), maxChars);
|
|
162
|
+
}
|
|
163
|
+
function cap(text, max) {
|
|
164
|
+
return text.length > max ? `${text.slice(0, max)}…` : text;
|
|
165
|
+
}
|
|
166
|
+
export function adfMentionIds(node) {
|
|
167
|
+
if (typeof node === "string")
|
|
168
|
+
return [...node.matchAll(WIKI_MENTION)].map((m) => m[1]);
|
|
169
|
+
const ids = [];
|
|
170
|
+
const walk = (n) => {
|
|
171
|
+
if (!n || typeof n !== "object")
|
|
172
|
+
return;
|
|
173
|
+
const a = n;
|
|
174
|
+
if (a.type === "mention" && typeof a.attrs?.id === "string")
|
|
175
|
+
ids.push(a.attrs.id);
|
|
176
|
+
for (const c of a.content ?? [])
|
|
177
|
+
walk(c);
|
|
178
|
+
};
|
|
179
|
+
walk(node);
|
|
180
|
+
return ids;
|
|
181
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IssueTrackerRegistry } from "./types.js";
|
|
2
|
+
export * from "./types.js";
|
|
3
|
+
export { JiraIssueTracker, agentFooter } from "./jira.js";
|
|
4
|
+
/** One tracker per configured provider; empty when Jira isn't configured (the jira_* tools are then never offered). */
|
|
5
|
+
export declare function buildIssueTrackers(env?: NodeJS.ProcessEnv): IssueTrackerRegistry;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { loadJiraConfig } from "../../config/providers.js";
|
|
2
|
+
import { JiraClient } from "./jira-client.js";
|
|
3
|
+
import { JiraIssueTracker } from "./jira.js";
|
|
4
|
+
export * from "./types.js";
|
|
5
|
+
export { JiraIssueTracker, agentFooter } from "./jira.js";
|
|
6
|
+
/** One tracker per configured provider; empty when Jira isn't configured (the jira_* tools are then never offered). */
|
|
7
|
+
export function buildIssueTrackers(env = process.env) {
|
|
8
|
+
const jira = loadJiraConfig(env);
|
|
9
|
+
return jira
|
|
10
|
+
? { jira: new JiraIssueTracker(new JiraClient(jira), jira.siteUrl, { epicLinkField: jira.epicLinkField }) }
|
|
11
|
+
: {};
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Jira Cloud REST client. Holds the credential; callers pass paths.
|
|
3
|
+
* One retry on 429 honouring Retry-After (capped), per Atlassian's
|
|
4
|
+
* rate-limiting guidance. Response bodies are never logged.
|
|
5
|
+
*/
|
|
6
|
+
import type { JiraConfig } from "../../config/providers.js";
|
|
7
|
+
export interface RequestOptions {
|
|
8
|
+
/** Accept an empty 2xx body as `undefined` (void writes). */
|
|
9
|
+
allowEmpty?: boolean;
|
|
10
|
+
/** Per-attempt timeout; default 30 s. */
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
/** Retry once on 429 honouring Retry-After; default true. */
|
|
13
|
+
retryOn429?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class JiraClient {
|
|
16
|
+
private readonly cfg;
|
|
17
|
+
private readonly authorization;
|
|
18
|
+
private readonly fetchImpl;
|
|
19
|
+
private readonly sleep;
|
|
20
|
+
/**
|
|
21
|
+
* Always sent explicitly: undici's default `Accept-Language: *` makes Jira answer in the site's default
|
|
22
|
+
* language rather than the account's own, which breaks matching of status and link type names.
|
|
23
|
+
*/
|
|
24
|
+
private language;
|
|
25
|
+
constructor(cfg: Pick<JiraConfig, "apiBaseUrl" | "auth">, opts?: {
|
|
26
|
+
fetch?: typeof fetch;
|
|
27
|
+
sleep?: (ms: number) => Promise<void>;
|
|
28
|
+
});
|
|
29
|
+
setLanguage(tag: string): void;
|
|
30
|
+
request<T>(method: "GET" | "POST" | "PUT", path: string, body?: unknown, opts?: RequestOptions): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* GET returning at most `maxBytes` of the raw body (attachment content). Sends `Range` (unless
|
|
33
|
+
* `range: false`) and caps client-side too, in case the server ignores it. Redirects are never followed with the credential:
|
|
34
|
+
* a 3xx is followed only to an https Atlassian host and without Authorization.
|
|
35
|
+
*/
|
|
36
|
+
requestBytes(path: string, opts: {
|
|
37
|
+
maxBytes: number;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
range?: boolean;
|
|
40
|
+
}): Promise<Uint8Array>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { IssueTrackerError } from "./types.js";
|
|
2
|
+
const MAX_RETRY_AFTER_MS = 10_000;
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
4
|
+
export class JiraClient {
|
|
5
|
+
cfg;
|
|
6
|
+
authorization;
|
|
7
|
+
fetchImpl;
|
|
8
|
+
sleep;
|
|
9
|
+
/**
|
|
10
|
+
* Always sent explicitly: undici's default `Accept-Language: *` makes Jira answer in the site's default
|
|
11
|
+
* language rather than the account's own, which breaks matching of status and link type names.
|
|
12
|
+
*/
|
|
13
|
+
language = "en-US";
|
|
14
|
+
constructor(cfg, opts = {}) {
|
|
15
|
+
this.cfg = cfg;
|
|
16
|
+
this.authorization = `Bearer ${cfg.auth.token}`;
|
|
17
|
+
this.fetchImpl = opts.fetch ?? fetch;
|
|
18
|
+
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
19
|
+
}
|
|
20
|
+
setLanguage(tag) {
|
|
21
|
+
this.language = tag;
|
|
22
|
+
}
|
|
23
|
+
async request(method, path, body, opts = {}) {
|
|
24
|
+
for (let attempt = 0;; attempt++) {
|
|
25
|
+
let res;
|
|
26
|
+
try {
|
|
27
|
+
res = await this.fetchImpl(`${this.cfg.apiBaseUrl}${path}`, {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
authorization: this.authorization,
|
|
31
|
+
accept: "application/json",
|
|
32
|
+
"accept-language": this.language,
|
|
33
|
+
...(body !== undefined ? { "content-type": "application/json" } : {}),
|
|
34
|
+
},
|
|
35
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
36
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
throw new IssueTrackerError("tracker_api_error", "Jira could not be reached.");
|
|
41
|
+
}
|
|
42
|
+
if (res.status === 429 && attempt === 0 && opts.retryOn429 !== false) {
|
|
43
|
+
const seconds = Number(res.headers.get("retry-after"));
|
|
44
|
+
await this.sleep(Math.min(Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : 2000, MAX_RETRY_AFTER_MS));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (res.status === 204)
|
|
48
|
+
return undefined;
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw statusError(res.status);
|
|
51
|
+
try {
|
|
52
|
+
// Void writes (issue links, property writes) may succeed with an empty body; JSON callers may not.
|
|
53
|
+
const text = await res.text();
|
|
54
|
+
if (text === "" && opts.allowEmpty)
|
|
55
|
+
return undefined;
|
|
56
|
+
return JSON.parse(text);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
throw new IssueTrackerError("tracker_invalid_response", "Jira returned a response that was not JSON.");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* GET returning at most `maxBytes` of the raw body (attachment content). Sends `Range` (unless
|
|
65
|
+
* `range: false`) and caps client-side too, in case the server ignores it. Redirects are never followed with the credential:
|
|
66
|
+
* a 3xx is followed only to an https Atlassian host and without Authorization.
|
|
67
|
+
*/
|
|
68
|
+
async requestBytes(path, opts) {
|
|
69
|
+
const headers = {
|
|
70
|
+
authorization: this.authorization,
|
|
71
|
+
accept: "*/*",
|
|
72
|
+
"accept-language": this.language,
|
|
73
|
+
...(opts.range === false ? {} : { range: `bytes=0-${Math.max(opts.maxBytes, 1) - 1}` }),
|
|
74
|
+
};
|
|
75
|
+
let url = `${this.cfg.apiBaseUrl}${path}`;
|
|
76
|
+
let res;
|
|
77
|
+
let retried = false;
|
|
78
|
+
try {
|
|
79
|
+
for (let hops = 0; hops <= 3;) {
|
|
80
|
+
res = await this.fetchImpl(url, {
|
|
81
|
+
method: "GET",
|
|
82
|
+
headers,
|
|
83
|
+
redirect: "manual",
|
|
84
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
85
|
+
});
|
|
86
|
+
if (res.status === 429 && !retried) {
|
|
87
|
+
retried = true;
|
|
88
|
+
const seconds = Number(res.headers.get("retry-after"));
|
|
89
|
+
await this.sleep(Math.min(Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : 2000, MAX_RETRY_AFTER_MS));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (res.status < 300 || res.status >= 400)
|
|
93
|
+
break;
|
|
94
|
+
hops++;
|
|
95
|
+
let next;
|
|
96
|
+
try {
|
|
97
|
+
next = new URL(res.headers.get("location") ?? "", url);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
throw new IssueTrackerError("tracker_invalid_response", "Jira returned an unusable download redirect.");
|
|
101
|
+
}
|
|
102
|
+
if (next.protocol !== "https:" || !isAtlassianHost(next.hostname))
|
|
103
|
+
throw new IssueTrackerError("tracker_invalid_response", "Jira redirected the download somewhere unexpected.");
|
|
104
|
+
url = next.toString();
|
|
105
|
+
// A pre-signed media URL: the Jira credential never goes to it.
|
|
106
|
+
delete headers.authorization;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (err instanceof IssueTrackerError)
|
|
111
|
+
throw err;
|
|
112
|
+
throw new IssueTrackerError("tracker_api_error", "Jira could not be reached.");
|
|
113
|
+
}
|
|
114
|
+
if (!res || (res.status >= 300 && res.status < 400))
|
|
115
|
+
throw new IssueTrackerError("tracker_api_error", "Jira's download redirected too many times.");
|
|
116
|
+
if (!res.ok)
|
|
117
|
+
throw statusError(res.status);
|
|
118
|
+
const chunks = [];
|
|
119
|
+
let total = 0;
|
|
120
|
+
try {
|
|
121
|
+
const reader = res.body?.getReader();
|
|
122
|
+
while (reader && total < opts.maxBytes) {
|
|
123
|
+
const { done, value } = await reader.read();
|
|
124
|
+
if (done)
|
|
125
|
+
break;
|
|
126
|
+
const piece = value.subarray(0, opts.maxBytes - total);
|
|
127
|
+
chunks.push(piece);
|
|
128
|
+
total += piece.length;
|
|
129
|
+
}
|
|
130
|
+
if (reader && total >= opts.maxBytes)
|
|
131
|
+
await reader.cancel().catch(() => undefined);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
throw new IssueTrackerError("tracker_api_error", "Jira's download was interrupted.");
|
|
135
|
+
}
|
|
136
|
+
return Buffer.concat(chunks);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Hosts a download redirect may point at (Atlassian media). */
|
|
140
|
+
const isAtlassianHost = (h) => /(^|\.)(atlassian\.com|atlassian\.net|atl-paas\.net)$/.test(h);
|
|
141
|
+
function statusError(status) {
|
|
142
|
+
if (status === 404)
|
|
143
|
+
return new IssueTrackerError("tracker_not_found", "Not found in Jira (or not visible to wardby's Jira account).");
|
|
144
|
+
if (status === 401 || status === 403)
|
|
145
|
+
return new IssueTrackerError("tracker_permission_denied", "wardby's Jira account is not allowed to do that.");
|
|
146
|
+
if (status === 429)
|
|
147
|
+
return new IssueTrackerError("tracker_rate_limited", "Jira is rate-limiting wardby; try again shortly.");
|
|
148
|
+
if (status === 400)
|
|
149
|
+
return new IssueTrackerError("tracker_invalid_request", "Jira rejected the request as invalid.");
|
|
150
|
+
return new IssueTrackerError("tracker_api_error", `Jira returned HTTP ${status}.`);
|
|
151
|
+
}
|