infraweaver 0.1.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/LICENSE +661 -0
- package/README.md +244 -0
- package/dist/agents/claude.d.ts +113 -0
- package/dist/agents/claudePretoolGate.d.ts +137 -0
- package/dist/agents/dispatchMetrics.d.ts +77 -0
- package/dist/agents/gateServer.d.ts +7 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/nativeFsDenies.d.ts +46 -0
- package/dist/agents/opencode.d.ts +284 -0
- package/dist/agents/opencodePlugin.d.ts +96 -0
- package/dist/agents/opencodeShared.d.ts +40 -0
- package/dist/agents/postRun.d.ts +126 -0
- package/dist/agents/reviewer.d.ts +41 -0
- package/dist/agents/sessionLabeler.d.ts +97 -0
- package/dist/agents/shared.d.ts +246 -0
- package/dist/agents/subagentModels.d.ts +19 -0
- package/dist/agents/tokenQuota.d.ts +118 -0
- package/dist/agents/writeGateSource.d.ts +22 -0
- package/dist/agents/writePolicy.d.ts +79 -0
- package/dist/brand.d.ts +67 -0
- package/dist/cli.mjs +247846 -0
- package/dist/external.d.ts +227 -0
- package/dist/i18n/scaffolding.d.ts +59 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +247061 -0
- package/dist/internal/index.d.ts +18 -0
- package/dist/internal.js +2398 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/main.d.ts +8 -0
- package/dist/mcp/arkConfig.d.ts +1 -0
- package/dist/mcp/assess.d.ts +157 -0
- package/dist/mcp/capabilityContext.d.ts +71 -0
- package/dist/mcp/changeSummary.d.ts +52 -0
- package/dist/mcp/checkSuite.d.ts +27 -0
- package/dist/mcp/checkout.d.ts +92 -0
- package/dist/mcp/comment.d.ts +127 -0
- package/dist/mcp/commitInfo.d.ts +11 -0
- package/dist/mcp/crosswalk.d.ts +178 -0
- package/dist/mcp/crosswalkDigest.d.ts +1 -0
- package/dist/mcp/cyberEssentials.d.ts +24 -0
- package/dist/mcp/dashboard.d.ts +125 -0
- package/dist/mcp/dependencies.d.ts +12 -0
- package/dist/mcp/frameworks.d.ts +74 -0
- package/dist/mcp/geminiSanitizer.d.ts +28 -0
- package/dist/mcp/git.d.ts +60 -0
- package/dist/mcp/guardrails.d.ts +222 -0
- package/dist/mcp/issue.d.ts +20 -0
- package/dist/mcp/issueComments.d.ts +11 -0
- package/dist/mcp/issueEvents.d.ts +11 -0
- package/dist/mcp/issueInfo.d.ts +11 -0
- package/dist/mcp/labels.d.ts +14 -0
- package/dist/mcp/localContext.d.ts +26 -0
- package/dist/mcp/moduleExtraction.d.ts +79 -0
- package/dist/mcp/moduleTests.d.ts +106 -0
- package/dist/mcp/modules.d.ts +198 -0
- package/dist/mcp/output.d.ts +16 -0
- package/dist/mcp/pathSafety.d.ts +14 -0
- package/dist/mcp/policy.d.ts +50 -0
- package/dist/mcp/pr.d.ts +64 -0
- package/dist/mcp/prInfo.d.ts +11 -0
- package/dist/mcp/providerSchema.d.ts +52 -0
- package/dist/mcp/review.d.ts +212 -0
- package/dist/mcp/reviewComments.d.ts +245 -0
- package/dist/mcp/roots.d.ts +60 -0
- package/dist/mcp/scope.d.ts +26 -0
- package/dist/mcp/selectMode.d.ts +20 -0
- package/dist/mcp/server.d.ts +61 -0
- package/dist/mcp/shared.d.ts +62 -0
- package/dist/mcp/shell.d.ts +58 -0
- package/dist/mcp/staleFix.d.ts +138 -0
- package/dist/mcp/terraform/azurePrices.d.ts +8 -0
- package/dist/mcp/terraform/baseline.d.ts +57 -0
- package/dist/mcp/terraform/concernResult.d.ts +38 -0
- package/dist/mcp/terraform/cost.d.ts +55 -0
- package/dist/mcp/terraform/cspm.d.ts +80 -0
- package/dist/mcp/terraform/currency.d.ts +110 -0
- package/dist/mcp/terraform/decisions.d.ts +178 -0
- package/dist/mcp/terraform/eidas.d.ts +100 -0
- package/dist/mcp/terraform/evidence.d.ts +343 -0
- package/dist/mcp/terraform/findings.d.ts +76 -0
- package/dist/mcp/terraform/fixMemory.d.ts +81 -0
- package/dist/mcp/terraform/governance.d.ts +56 -0
- package/dist/mcp/terraform/hcl.d.ts +115 -0
- package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
- package/dist/mcp/terraform/idleFloor.d.ts +78 -0
- package/dist/mcp/terraform/keyless.d.ts +68 -0
- package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
- package/dist/mcp/terraform/nativeRules.d.ts +38 -0
- package/dist/mcp/terraform/nativeScan.d.ts +11 -0
- package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
- package/dist/mcp/terraform/normalization.d.ts +52 -0
- package/dist/mcp/terraform/oscal.d.ts +103 -0
- package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
- package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
- package/dist/mcp/terraform/paths.d.ts +28 -0
- package/dist/mcp/terraform/plan.d.ts +157 -0
- package/dist/mcp/terraform/planDrift.d.ts +199 -0
- package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
- package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
- package/dist/mcp/terraform/refactor.d.ts +183 -0
- package/dist/mcp/terraform/registry.d.ts +108 -0
- package/dist/mcp/terraform/risk.d.ts +41 -0
- package/dist/mcp/terraform/scanSession.d.ts +116 -0
- package/dist/mcp/terraform/scannerCache.d.ts +15 -0
- package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
- package/dist/mcp/terraform/scannerJson.d.ts +13 -0
- package/dist/mcp/terraform/scanners.d.ts +205 -0
- package/dist/mcp/terraform/signing.d.ts +61 -0
- package/dist/mcp/terraform/stateLocking.d.ts +18 -0
- package/dist/mcp/terraform/subprocess.d.ts +43 -0
- package/dist/mcp/terraform/suppressions.d.ts +90 -0
- package/dist/mcp/terraform/taxonomy.d.ts +39 -0
- package/dist/mcp/terraform/tfquery.d.ts +47 -0
- package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
- package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
- package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
- package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
- package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
- package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
- package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
- package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
- package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
- package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
- package/dist/mcp/terraform/tools/plan.d.ts +59 -0
- package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
- package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
- package/dist/mcp/terraform/tools/scan.d.ts +114 -0
- package/dist/mcp/terraform/tools/validate.d.ts +31 -0
- package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
- package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
- package/dist/mcp/terraform/tools.d.ts +16 -0
- package/dist/mcp/terraform/transformPacks.d.ts +267 -0
- package/dist/mcp/terraform/types.d.ts +226 -0
- package/dist/mcp/terraform/verification.d.ts +81 -0
- package/dist/mcp/terraform/vex.d.ts +115 -0
- package/dist/mcp/terraform/writeOnly.d.ts +67 -0
- package/dist/mcp/terraform.d.ts +51 -0
- package/dist/mcp/terratest.d.ts +85 -0
- package/dist/mcp/untrustedContent.d.ts +76 -0
- package/dist/mcp/upload.d.ts +8 -0
- package/dist/models.d.ts +181 -0
- package/dist/modes/address-reviews.d.ts +2 -0
- package/dist/modes/assess.d.ts +2 -0
- package/dist/modes/build.d.ts +2 -0
- package/dist/modes/compliance-audit.d.ts +2 -0
- package/dist/modes/cost-optimization.d.ts +2 -0
- package/dist/modes/drift-detect.d.ts +2 -0
- package/dist/modes/fix.d.ts +2 -0
- package/dist/modes/incremental-review.d.ts +2 -0
- package/dist/modes/index.d.ts +24 -0
- package/dist/modes/modernize-deprecated.d.ts +2 -0
- package/dist/modes/plan.d.ts +2 -0
- package/dist/modes/policy-gate.d.ts +2 -0
- package/dist/modes/prFormats.d.ts +3 -0
- package/dist/modes/refactor.d.ts +2 -0
- package/dist/modes/refresh-remediation.d.ts +2 -0
- package/dist/modes/remediate-and-refactor.d.ts +2 -0
- package/dist/modes/remediate.d.ts +2 -0
- package/dist/modes/resolve-conflicts.d.ts +2 -0
- package/dist/modes/review.d.ts +2 -0
- package/dist/modes/summarize-pr.d.ts +2 -0
- package/dist/modes/task.d.ts +2 -0
- package/dist/modes/terraform-code-review.d.ts +2 -0
- package/dist/modes/types.d.ts +9 -0
- package/dist/modes/update-dependencies.d.ts +2 -0
- package/dist/prep/index.d.ts +7 -0
- package/dist/prep/installNodeDependencies.d.ts +2 -0
- package/dist/prep/installPythonDependencies.d.ts +2 -0
- package/dist/prep/types.d.ts +31 -0
- package/dist/reviewQuality.d.ts +107 -0
- package/dist/skills/terraform-best-practices/SKILL.md +379 -0
- package/dist/toolState.d.ts +123 -0
- package/dist/utils/activity.d.ts +40 -0
- package/dist/utils/agent.d.ts +47 -0
- package/dist/utils/agentHangReport.d.ts +38 -0
- package/dist/utils/annotations.d.ts +17 -0
- package/dist/utils/apiFetch.d.ts +11 -0
- package/dist/utils/apiKeys.d.ts +48 -0
- package/dist/utils/apiUrl.d.ts +28 -0
- package/dist/utils/assets.d.ts +8 -0
- package/dist/utils/baseRefConfig.d.ts +121 -0
- package/dist/utils/billingErrors.d.ts +85 -0
- package/dist/utils/body.d.ts +34 -0
- package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
- package/dist/utils/byokFallback.d.ts +85 -0
- package/dist/utils/changeImpact.d.ts +101 -0
- package/dist/utils/claudeSubscription.d.ts +30 -0
- package/dist/utils/cli.d.ts +10 -0
- package/dist/utils/cloudClient.d.ts +33 -0
- package/dist/utils/cloudFetchCore.d.ts +42 -0
- package/dist/utils/cloudReport.d.ts +114 -0
- package/dist/utils/codexHome.d.ts +29 -0
- package/dist/utils/codexOAuth.d.ts +60 -0
- package/dist/utils/diffCoverage.d.ts +63 -0
- package/dist/utils/env.d.ts +46 -0
- package/dist/utils/errorReport.d.ts +17 -0
- package/dist/utils/exitHandler.d.ts +8 -0
- package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
- package/dist/utils/gitAuth.d.ts +84 -0
- package/dist/utils/gitAuthServer.d.ts +24 -0
- package/dist/utils/github.d.ts +104 -0
- package/dist/utils/globals.d.ts +3 -0
- package/dist/utils/infraweaverConfig.d.ts +56 -0
- package/dist/utils/install.d.ts +37 -0
- package/dist/utils/instructions.d.ts +48 -0
- package/dist/utils/keylessOidc.d.ts +28 -0
- package/dist/utils/leapingComment.d.ts +11 -0
- package/dist/utils/learnings.d.ts +62 -0
- package/dist/utils/learningsTruncate.d.ts +25 -0
- package/dist/utils/lifecycle.d.ts +57 -0
- package/dist/utils/log.d.ts +111 -0
- package/dist/utils/modelResolver.d.ts +63 -0
- package/dist/utils/moduleFetch.d.ts +39 -0
- package/dist/utils/normalizeEnv.d.ts +30 -0
- package/dist/utils/openCodeModels.d.ts +11 -0
- package/dist/utils/openaiCompatible.d.ts +26 -0
- package/dist/utils/opentofuMcp.d.ts +50 -0
- package/dist/utils/overrides.d.ts +40 -0
- package/dist/utils/packageManager.d.ts +49 -0
- package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
- package/dist/utils/payload.d.ts +249 -0
- package/dist/utils/prSummary.d.ts +61 -0
- package/dist/utils/presets.d.ts +36 -0
- package/dist/utils/progressComment.d.ts +146 -0
- package/dist/utils/providerErrors.d.ts +31 -0
- package/dist/utils/proxyModel.d.ts +76 -0
- package/dist/utils/rangeDiff.d.ts +51 -0
- package/dist/utils/redact.d.ts +33 -0
- package/dist/utils/registryAuth.d.ts +52 -0
- package/dist/utils/remediationCommand.d.ts +58 -0
- package/dist/utils/retry.d.ts +38 -0
- package/dist/utils/reviewCleanup.d.ts +14 -0
- package/dist/utils/run.d.ts +9 -0
- package/dist/utils/runContext.d.ts +112 -0
- package/dist/utils/runContextData.d.ts +42 -0
- package/dist/utils/runErrorRenderer.d.ts +64 -0
- package/dist/utils/runLifecycle.d.ts +89 -0
- package/dist/utils/runStartupLog.d.ts +15 -0
- package/dist/utils/secrets.d.ts +34 -0
- package/dist/utils/setup.d.ts +90 -0
- package/dist/utils/shell.d.ts +44 -0
- package/dist/utils/skills.d.ts +10 -0
- package/dist/utils/subprocess.d.ts +81 -0
- package/dist/utils/terraformMcp.d.ts +46 -0
- package/dist/utils/time.d.ts +15 -0
- package/dist/utils/timer.d.ts +23 -0
- package/dist/utils/todoTracking.d.ts +16 -0
- package/dist/utils/token.d.ts +52 -0
- package/dist/utils/toolLicensing.d.ts +56 -0
- package/dist/utils/toolSelection.d.ts +73 -0
- package/dist/utils/toon.d.ts +16 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/versioning.d.ts +7 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/dist/utils/workflow.d.ts +13 -0
- package/package.json +132 -0
- package/src/agents/claude.ts +1588 -0
- package/src/agents/claudePretoolGate.ts +286 -0
- package/src/agents/dispatchMetrics.ts +162 -0
- package/src/agents/gateServer.ts +178 -0
- package/src/agents/index.ts +10 -0
- package/src/agents/nativeFsDenies.ts +164 -0
- package/src/agents/opencode.ts +1600 -0
- package/src/agents/opencodePlugin.ts +304 -0
- package/src/agents/opencodeShared.ts +134 -0
- package/src/agents/postRun.ts +615 -0
- package/src/agents/reviewer.ts +134 -0
- package/src/agents/sessionLabeler.ts +185 -0
- package/src/agents/shared.ts +377 -0
- package/src/agents/subagentModels.ts +40 -0
- package/src/agents/tokenQuota.ts +203 -0
- package/src/agents/writeGateSource.ts +148 -0
- package/src/agents/writePolicy.ts +132 -0
- package/src/brand.ts +84 -0
- package/src/cli.ts +117 -0
- package/src/commands/gha.ts +188 -0
- package/src/commands/mcp.ts +126 -0
- package/src/commands/verifyEvidence.ts +100 -0
- package/src/entry.ts +7 -0
- package/src/entryPost.ts +109 -0
- package/src/external.ts +308 -0
- package/src/i18n/scaffolding.ts +191 -0
- package/src/index.ts +7 -0
- package/src/internal/index.ts +74 -0
- package/src/lifecycle.ts +2 -0
- package/src/main.ts +815 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
- package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
- package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
- package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
- package/src/mcp/arkConfig.ts +7 -0
- package/src/mcp/assess.ts +723 -0
- package/src/mcp/capabilityContext.ts +80 -0
- package/src/mcp/changeSummary.ts +145 -0
- package/src/mcp/checkSuite.ts +261 -0
- package/src/mcp/checkout.ts +1015 -0
- package/src/mcp/comment.ts +683 -0
- package/src/mcp/commitInfo.ts +57 -0
- package/src/mcp/crosswalk.ts +1253 -0
- package/src/mcp/crosswalkDigest.ts +5 -0
- package/src/mcp/cyberEssentials.ts +60 -0
- package/src/mcp/dashboard.ts +232 -0
- package/src/mcp/dependencies.ts +190 -0
- package/src/mcp/frameworks.ts +236 -0
- package/src/mcp/geminiSanitizer.ts +212 -0
- package/src/mcp/git.ts +1116 -0
- package/src/mcp/guardrails.ts +771 -0
- package/src/mcp/issue.ts +74 -0
- package/src/mcp/issueComments.ts +48 -0
- package/src/mcp/issueEvents.ts +100 -0
- package/src/mcp/issueInfo.ts +72 -0
- package/src/mcp/labels.ts +35 -0
- package/src/mcp/localContext.ts +65 -0
- package/src/mcp/localServer.ts +217 -0
- package/src/mcp/moduleExtraction.ts +368 -0
- package/src/mcp/moduleTests.ts +421 -0
- package/src/mcp/modules.ts +752 -0
- package/src/mcp/output.ts +71 -0
- package/src/mcp/pathSafety.ts +28 -0
- package/src/mcp/policy.ts +226 -0
- package/src/mcp/pr.ts +238 -0
- package/src/mcp/prInfo.ts +91 -0
- package/src/mcp/providerSchema.ts +175 -0
- package/src/mcp/review.ts +1081 -0
- package/src/mcp/reviewComments.ts +1137 -0
- package/src/mcp/roots.ts +217 -0
- package/src/mcp/scope.ts +82 -0
- package/src/mcp/selectMode.ts +207 -0
- package/src/mcp/server.ts +498 -0
- package/src/mcp/shared.ts +120 -0
- package/src/mcp/shell.ts +631 -0
- package/src/mcp/staleFix.ts +557 -0
- package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
- package/src/mcp/terraform/azurePrices.ts +38 -0
- package/src/mcp/terraform/baseline.ts +172 -0
- package/src/mcp/terraform/concernResult.ts +111 -0
- package/src/mcp/terraform/cost.ts +175 -0
- package/src/mcp/terraform/cspm.ts +326 -0
- package/src/mcp/terraform/currency.ts +354 -0
- package/src/mcp/terraform/decisions.ts +590 -0
- package/src/mcp/terraform/eidas.ts +134 -0
- package/src/mcp/terraform/evidence.ts +771 -0
- package/src/mcp/terraform/findings.ts +383 -0
- package/src/mcp/terraform/fixMemory.ts +253 -0
- package/src/mcp/terraform/governance.ts +231 -0
- package/src/mcp/terraform/hcl.ts +273 -0
- package/src/mcp/terraform/iacLanguages.ts +431 -0
- package/src/mcp/terraform/idleFloor.ts +304 -0
- package/src/mcp/terraform/keyless.ts +123 -0
- package/src/mcp/terraform/moduleDocs.ts +303 -0
- package/src/mcp/terraform/nativeRules.ts +152 -0
- package/src/mcp/terraform/nativeScan.ts +67 -0
- package/src/mcp/terraform/noiseProfile.ts +183 -0
- package/src/mcp/terraform/normalization.ts +265 -0
- package/src/mcp/terraform/oscal.ts +283 -0
- package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
- package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
- package/src/mcp/terraform/paths.ts +59 -0
- package/src/mcp/terraform/plan.ts +377 -0
- package/src/mcp/terraform/planDrift.ts +520 -0
- package/src/mcp/terraform/policyAuthor.ts +886 -0
- package/src/mcp/terraform/prowlerOcsf.ts +380 -0
- package/src/mcp/terraform/refactor.ts +879 -0
- package/src/mcp/terraform/registry.ts +317 -0
- package/src/mcp/terraform/risk.ts +99 -0
- package/src/mcp/terraform/scanSession.ts +242 -0
- package/src/mcp/terraform/scannerCache.ts +86 -0
- package/src/mcp/terraform/scannerEgress.ts +141 -0
- package/src/mcp/terraform/scannerJson.ts +22 -0
- package/src/mcp/terraform/scanners.ts +1134 -0
- package/src/mcp/terraform/signing.ts +151 -0
- package/src/mcp/terraform/stateLocking.ts +106 -0
- package/src/mcp/terraform/subprocess.ts +102 -0
- package/src/mcp/terraform/suppressions.ts +551 -0
- package/src/mcp/terraform/taxonomy.ts +0 -0
- package/src/mcp/terraform/tfquery.ts +159 -0
- package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
- package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
- package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
- package/src/mcp/terraform/tools/emitCost.ts +130 -0
- package/src/mcp/terraform/tools/emitSarif.ts +108 -0
- package/src/mcp/terraform/tools/fixMemory.ts +82 -0
- package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
- package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
- package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
- package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
- package/src/mcp/terraform/tools/plan.ts +384 -0
- package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
- package/src/mcp/terraform/tools/readFindings.ts +138 -0
- package/src/mcp/terraform/tools/scan.ts +303 -0
- package/src/mcp/terraform/tools/validate.ts +160 -0
- package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
- package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
- package/src/mcp/terraform/tools.ts +62 -0
- package/src/mcp/terraform/transformPacks.ts +594 -0
- package/src/mcp/terraform/types.ts +382 -0
- package/src/mcp/terraform/verification.ts +150 -0
- package/src/mcp/terraform/vex.ts +367 -0
- package/src/mcp/terraform/writeOnly.ts +252 -0
- package/src/mcp/terraform.ts +52 -0
- package/src/mcp/terratest.ts +215 -0
- package/src/mcp/untrustedContent.ts +126 -0
- package/src/mcp/upload.ts +123 -0
- package/src/models.ts +753 -0
- package/src/modes/address-reviews.ts +35 -0
- package/src/modes/assess.ts +27 -0
- package/src/modes/build.ts +86 -0
- package/src/modes/compliance-audit.ts +25 -0
- package/src/modes/cost-optimization.ts +36 -0
- package/src/modes/drift-detect.ts +31 -0
- package/src/modes/fix.ts +29 -0
- package/src/modes/incremental-review.ts +103 -0
- package/src/modes/index.ts +94 -0
- package/src/modes/modernize-deprecated.ts +36 -0
- package/src/modes/plan.ts +21 -0
- package/src/modes/policy-gate.ts +27 -0
- package/src/modes/prFormats.ts +325 -0
- package/src/modes/refactor.ts +74 -0
- package/src/modes/refresh-remediation.ts +40 -0
- package/src/modes/remediate-and-refactor.ts +42 -0
- package/src/modes/remediate.ts +78 -0
- package/src/modes/resolve-conflicts.ts +32 -0
- package/src/modes/review.ts +135 -0
- package/src/modes/summarize-pr.ts +42 -0
- package/src/modes/task.ts +26 -0
- package/src/modes/terraform-code-review.ts +68 -0
- package/src/modes/types.ts +17 -0
- package/src/modes/update-dependencies.ts +44 -0
- package/src/prep/index.ts +96 -0
- package/src/prep/installNodeDependencies.ts +251 -0
- package/src/prep/installPythonDependencies.ts +235 -0
- package/src/prep/types.ts +38 -0
- package/src/reviewQuality.ts +237 -0
- package/src/runCli.ts +335 -0
- package/src/skills/terraform-best-practices/SKILL.md +379 -0
- package/src/toolState.ts +241 -0
- package/src/utils/activity.ts +210 -0
- package/src/utils/agent.ts +245 -0
- package/src/utils/agentHangReport.ts +180 -0
- package/src/utils/annotations.ts +56 -0
- package/src/utils/apiFetch.ts +19 -0
- package/src/utils/apiKeys.ts +305 -0
- package/src/utils/apiUrl.ts +42 -0
- package/src/utils/assets.ts +123 -0
- package/src/utils/baseRefConfig.ts +254 -0
- package/src/utils/billingErrors.ts +210 -0
- package/src/utils/body.ts +168 -0
- package/src/utils/buildInfraweaverFooter.ts +104 -0
- package/src/utils/byokFallback.ts +137 -0
- package/src/utils/changeImpact.ts +330 -0
- package/src/utils/claudeSubscription.ts +93 -0
- package/src/utils/cli.ts +36 -0
- package/src/utils/cloudClient.ts +57 -0
- package/src/utils/cloudFetchCore.ts +139 -0
- package/src/utils/cloudReport.ts +316 -0
- package/src/utils/codexHome.ts +204 -0
- package/src/utils/codexOAuth.ts +154 -0
- package/src/utils/codexRefreshDetect.ts +36 -0
- package/src/utils/diffCoverage.ts +404 -0
- package/src/utils/env.ts +84 -0
- package/src/utils/errorReport.ts +94 -0
- package/src/utils/exitHandler.ts +35 -0
- package/src/utils/fixDoubleEscapedString.ts +9 -0
- package/src/utils/ghaCore.ts +13 -0
- package/src/utils/gitAuth.ts +268 -0
- package/src/utils/gitAuthServer.ts +186 -0
- package/src/utils/github.ts +676 -0
- package/src/utils/globals.ts +9 -0
- package/src/utils/humanEditCapture.ts +198 -0
- package/src/utils/infraweaverConfig.ts +202 -0
- package/src/utils/install.ts +279 -0
- package/src/utils/instructions.ts +640 -0
- package/src/utils/keylessOidc.ts +47 -0
- package/src/utils/leapingComment.ts +20 -0
- package/src/utils/learnings.ts +145 -0
- package/src/utils/learningsTruncate.ts +42 -0
- package/src/utils/lifecycle.ts +198 -0
- package/src/utils/log.ts +452 -0
- package/src/utils/modelResolver.ts +105 -0
- package/src/utils/moduleFetch.ts +138 -0
- package/src/utils/normalizeEnv.ts +106 -0
- package/src/utils/openCodeModels.ts +86 -0
- package/src/utils/openaiCompatible.ts +52 -0
- package/src/utils/opentofuMcp.ts +61 -0
- package/src/utils/overrides.ts +100 -0
- package/src/utils/packageManager.ts +257 -0
- package/src/utils/patchWorkflowRunFields.ts +173 -0
- package/src/utils/payload.ts +1206 -0
- package/src/utils/prSummary.ts +148 -0
- package/src/utils/presets.ts +105 -0
- package/src/utils/progressComment.ts +266 -0
- package/src/utils/providerErrors.ts +189 -0
- package/src/utils/proxyModel.ts +239 -0
- package/src/utils/rangeDiff.ts +182 -0
- package/src/utils/redact.ts +86 -0
- package/src/utils/registryAuth.ts +115 -0
- package/src/utils/remediationCommand.ts +144 -0
- package/src/utils/retry.ts +180 -0
- package/src/utils/reviewCleanup.ts +116 -0
- package/src/utils/run.ts +100 -0
- package/src/utils/runContext.ts +276 -0
- package/src/utils/runContextData.ts +121 -0
- package/src/utils/runErrorRenderer.ts +282 -0
- package/src/utils/runFixture.ts +91 -0
- package/src/utils/runLifecycle.ts +360 -0
- package/src/utils/runStartupLog.ts +67 -0
- package/src/utils/secrets.ts +208 -0
- package/src/utils/setup.ts +368 -0
- package/src/utils/shell.ts +132 -0
- package/src/utils/skills.ts +67 -0
- package/src/utils/subprocess.ts +474 -0
- package/src/utils/terraformMcp.ts +99 -0
- package/src/utils/time.ts +59 -0
- package/src/utils/timer.ts +72 -0
- package/src/utils/todoTracking.ts +168 -0
- package/src/utils/token.ts +294 -0
- package/src/utils/toolLicensing.ts +152 -0
- package/src/utils/toolSelection.ts +239 -0
- package/src/utils/toon.ts +76 -0
- package/src/utils/version.ts +10 -0
- package/src/utils/versioning.ts +44 -0
- package/src/utils/vertex.ts +94 -0
- package/src/utils/workflow.ts +25 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { log } from "#app/utils/cli";
|
|
2
|
+
import { type CloudFetchOptions, cloudFetch } from "#app/utils/cloudFetchCore";
|
|
3
|
+
|
|
4
|
+
export type ApiFetchOptions = CloudFetchOptions;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* fetch wrapper for hitting the Infraweaver API. the transport concerns —
|
|
8
|
+
* default host, host allowlist, Vercel bypass secret, default timeout —
|
|
9
|
+
* live in cloudFetchCore.ts, shared with the stdlib-only post hook.
|
|
10
|
+
*
|
|
11
|
+
* requests without an explicit `signal` get the core's default timeout, so a
|
|
12
|
+
* stalled backend can't hang the action.
|
|
13
|
+
*/
|
|
14
|
+
export async function apiFetch(options: ApiFetchOptions): Promise<Response> {
|
|
15
|
+
log.debug(
|
|
16
|
+
`api fetch: ${options.method ?? "GET"} ${new URL(options.path, "https://x").pathname}`,
|
|
17
|
+
);
|
|
18
|
+
return cloudFetch(options);
|
|
19
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { DOCS_URL, PRODUCT_NAME } from "#app/brand";
|
|
2
|
+
import {
|
|
3
|
+
BEDROCK_MODEL_ID_ENV,
|
|
4
|
+
OPENAI_COMPATIBLE_MODEL_ID_ENV,
|
|
5
|
+
resolveDisplayAlias,
|
|
6
|
+
VERTEX_MODEL_ID_ENV,
|
|
7
|
+
} from "#app/models";
|
|
8
|
+
import { getApiUrl } from "#app/utils/apiUrl";
|
|
9
|
+
import {
|
|
10
|
+
isOpenAiCompatibleRoute,
|
|
11
|
+
OPENAI_COMPATIBLE_API_KEY_ENV,
|
|
12
|
+
OPENAI_COMPATIBLE_BASE_URL_ENV,
|
|
13
|
+
} from "#app/utils/openaiCompatible";
|
|
14
|
+
import {
|
|
15
|
+
GOOGLE_CLOUD_PROJECT_ENV,
|
|
16
|
+
readProjectIdFromVertexServiceAccountJson,
|
|
17
|
+
VERTEX_LOCATION_ENV,
|
|
18
|
+
VERTEX_SERVICE_ACCOUNT_JSON_ENV,
|
|
19
|
+
} from "#app/utils/vertex";
|
|
20
|
+
|
|
21
|
+
/** marker prefix on the throw message for the catch-side reclassification path */
|
|
22
|
+
const MISSING_KEY_MARKER = "no API key found";
|
|
23
|
+
|
|
24
|
+
/** Markdown body used for both the thrown error and the formatted PR comment summary. */
|
|
25
|
+
function buildMissingApiKeyError(params: { owner: string; name: string }): string {
|
|
26
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
27
|
+
const settingsUrl = `${getApiUrl()}/console/${params.owner}/${params.name}`;
|
|
28
|
+
|
|
29
|
+
return [
|
|
30
|
+
`**${MISSING_KEY_MARKER}** — ${PRODUCT_NAME} needs at least one LLM provider API key (e.g. \`ANTHROPIC_API_KEY\`, \`OPENAI_API_KEY\`, \`GEMINI_API_KEY\`) configured as a GitHub Actions secret.`,
|
|
31
|
+
"",
|
|
32
|
+
`[Open repo secrets →](${githubSecretsUrl}) · [Configure model →](${settingsUrl}) · [Setup docs →](${DOCS_URL}/keys) · [Ask in Discord →](https://discord.gg/8y96raFg8e)`,
|
|
33
|
+
].join("\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildBedrockSetupError(params: {
|
|
37
|
+
owner: string;
|
|
38
|
+
name: string;
|
|
39
|
+
missing: string[];
|
|
40
|
+
}): string {
|
|
41
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
42
|
+
|
|
43
|
+
return `Bedrock model selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
44
|
+
|
|
45
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
46
|
+
|
|
47
|
+
AWS_BEARER_TOKEN_BEDROCK: \${{ secrets.AWS_BEARER_TOKEN_BEDROCK }}
|
|
48
|
+
AWS_REGION: \${{ secrets.AWS_REGION }}
|
|
49
|
+
${BEDROCK_MODEL_ID_ENV}: \${{ secrets.${BEDROCK_MODEL_ID_ENV} }}
|
|
50
|
+
|
|
51
|
+
\`AWS_BEARER_TOKEN_BEDROCK\` may be substituted with \`AWS_ACCESS_KEY_ID\` + \`AWS_SECRET_ACCESS_KEY\` (and optional \`AWS_SESSION_TOKEN\`) if you prefer access keys.
|
|
52
|
+
|
|
53
|
+
for full setup instructions, see ${DOCS_URL}/bedrock`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function buildVertexSetupError(params: { owner: string; name: string; missing: string[] }): string {
|
|
57
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
58
|
+
|
|
59
|
+
return `Google Vertex AI model selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
60
|
+
|
|
61
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
62
|
+
|
|
63
|
+
${VERTEX_SERVICE_ACCOUNT_JSON_ENV}: \${{ secrets.${VERTEX_SERVICE_ACCOUNT_JSON_ENV} }}
|
|
64
|
+
${GOOGLE_CLOUD_PROJECT_ENV}: my-project
|
|
65
|
+
${VERTEX_LOCATION_ENV}: global
|
|
66
|
+
${VERTEX_MODEL_ID_ENV}: <vertex-model-id>
|
|
67
|
+
|
|
68
|
+
for full setup instructions, see ${DOCS_URL}/vertex`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function buildOpenAiCompatibleSetupError(params: {
|
|
72
|
+
owner: string;
|
|
73
|
+
name: string;
|
|
74
|
+
missing: string[];
|
|
75
|
+
}): string {
|
|
76
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
77
|
+
|
|
78
|
+
return `OpenAI-compatible endpoint selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
79
|
+
|
|
80
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
81
|
+
|
|
82
|
+
${OPENAI_COMPATIBLE_BASE_URL_ENV}: \${{ secrets.${OPENAI_COMPATIBLE_BASE_URL_ENV} }}
|
|
83
|
+
${OPENAI_COMPATIBLE_MODEL_ID_ENV}: <model-id-your-endpoint-serves>
|
|
84
|
+
${OPENAI_COMPATIBLE_API_KEY_ENV}: \${{ secrets.${OPENAI_COMPATIBLE_API_KEY_ENV} }} # optional for keyless self-hosted servers
|
|
85
|
+
|
|
86
|
+
for full setup instructions, see ${DOCS_URL}/openai-compatible`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function hasEnvVar(name: string): boolean {
|
|
90
|
+
const value = process.env[name];
|
|
91
|
+
return typeof value === "string" && value.length > 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function validateOpenAiCompatibleSetup(params: { owner: string; name: string }): void {
|
|
95
|
+
// base URL + model id are required; the API key is optional (keyless self-hosted
|
|
96
|
+
// endpoints like a local Ollama don't need one).
|
|
97
|
+
const missing: string[] = [];
|
|
98
|
+
if (!hasEnvVar(OPENAI_COMPATIBLE_BASE_URL_ENV)) missing.push(OPENAI_COMPATIBLE_BASE_URL_ENV);
|
|
99
|
+
if (!hasEnvVar(OPENAI_COMPATIBLE_MODEL_ID_ENV)) missing.push(OPENAI_COMPATIBLE_MODEL_ID_ENV);
|
|
100
|
+
|
|
101
|
+
if (missing.length > 0) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
buildOpenAiCompatibleSetupError({ owner: params.owner, name: params.name, missing }),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function validateBedrockSetup(params: { owner: string; name: string }): void {
|
|
109
|
+
const hasAuth =
|
|
110
|
+
hasEnvVar("AWS_BEARER_TOKEN_BEDROCK") ||
|
|
111
|
+
(hasEnvVar("AWS_ACCESS_KEY_ID") && hasEnvVar("AWS_SECRET_ACCESS_KEY"));
|
|
112
|
+
|
|
113
|
+
const missing: string[] = [];
|
|
114
|
+
if (!hasAuth)
|
|
115
|
+
missing.push("AWS_BEARER_TOKEN_BEDROCK (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)");
|
|
116
|
+
if (!hasEnvVar("AWS_REGION")) missing.push("AWS_REGION");
|
|
117
|
+
if (!hasEnvVar(BEDROCK_MODEL_ID_ENV)) missing.push(BEDROCK_MODEL_ID_ENV);
|
|
118
|
+
|
|
119
|
+
if (missing.length > 0) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
buildBedrockSetupError({
|
|
122
|
+
owner: params.owner,
|
|
123
|
+
name: params.name,
|
|
124
|
+
missing,
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function validateVertexSetup(params: { owner: string; name: string }): void {
|
|
131
|
+
const hasAuth = hasEnvVar(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
132
|
+
const hasProject =
|
|
133
|
+
hasEnvVar(GOOGLE_CLOUD_PROJECT_ENV) ||
|
|
134
|
+
readProjectIdFromVertexServiceAccountJson() !== undefined;
|
|
135
|
+
|
|
136
|
+
const missing: string[] = [];
|
|
137
|
+
if (!hasAuth) missing.push(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
138
|
+
if (!hasProject) missing.push(GOOGLE_CLOUD_PROJECT_ENV);
|
|
139
|
+
if (!hasEnvVar(VERTEX_LOCATION_ENV)) missing.push(VERTEX_LOCATION_ENV);
|
|
140
|
+
if (!hasEnvVar(VERTEX_MODEL_ID_ENV)) missing.push(VERTEX_MODEL_ID_ENV);
|
|
141
|
+
|
|
142
|
+
if (missing.length > 0) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
buildVertexSetupError({
|
|
145
|
+
owner: params.owner,
|
|
146
|
+
name: params.name,
|
|
147
|
+
missing,
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Validate that the resolved model can actually be served by the chosen
|
|
155
|
+
* agent. For routing slugs (Bedrock / Vertex) the auth shape is multi-var
|
|
156
|
+
* (auth + region/location + model-id) and `opencode models` doesn't catch
|
|
157
|
+
* gaps in the latter two — keep dedicated setup validators. For the
|
|
158
|
+
* opencode path, the authoritative answer comes from OpenCode's own model
|
|
159
|
+
* introspection (`authorized` set captured in `openCodeModels.ts`). For
|
|
160
|
+
* the claude path, fall back to the static check (`ANTHROPIC_API_KEY` /
|
|
161
|
+
* `CLAUDE_CODE_OAUTH_TOKEN`).
|
|
162
|
+
*/
|
|
163
|
+
export function validateAgentApiKey(params: {
|
|
164
|
+
agent: { name: string };
|
|
165
|
+
model: string | undefined;
|
|
166
|
+
authorized: Set<string>;
|
|
167
|
+
owner: string;
|
|
168
|
+
name: string;
|
|
169
|
+
}): void {
|
|
170
|
+
if (params.model) {
|
|
171
|
+
const alias = resolveDisplayAlias(params.model);
|
|
172
|
+
// OpenAI-compatible BYOK route: detected by env sentinel because the resolved
|
|
173
|
+
// id is the raw model (not the slug), and a HuggingFace id can contain a `/` —
|
|
174
|
+
// so this must come before BOTH the no-slash routing block and the opencode
|
|
175
|
+
// `authorized` check (a custom endpoint never appears in `opencode models`).
|
|
176
|
+
if (isOpenAiCompatibleRoute(params.model)) {
|
|
177
|
+
validateOpenAiCompatibleSetup({ owner: params.owner, name: params.name });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (alias?.routing === "bedrock") {
|
|
181
|
+
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (alias?.routing === "vertex") {
|
|
185
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// raw backend model IDs (post-resolveModel for routing slugs) have no
|
|
190
|
+
// `/`. discriminate by the env-var sentinel, then run the matching
|
|
191
|
+
// setup validator — `opencode models` doesn't help here because the
|
|
192
|
+
// Bedrock/Vertex provider plugins need region/location/model-id wired
|
|
193
|
+
// through env regardless of CLI-side auth.
|
|
194
|
+
if (!params.model.includes("/")) {
|
|
195
|
+
if (process.env[VERTEX_MODEL_ID_ENV]?.trim() === params.model) {
|
|
196
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (params.agent.name === "opencode") {
|
|
204
|
+
if (params.authorized.has(params.model)) return;
|
|
205
|
+
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// claude: single-provider check on the Anthropic auth shapes.
|
|
209
|
+
if (hasEnvVar("ANTHROPIC_API_KEY") || hasEnvVar("CLAUDE_CODE_OAUTH_TOKEN")) return;
|
|
210
|
+
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// no model configured (auto-select path).
|
|
214
|
+
if (params.agent.name === "opencode") {
|
|
215
|
+
if (params.authorized.size > 0) return;
|
|
216
|
+
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
217
|
+
}
|
|
218
|
+
if (hasEnvVar("ANTHROPIC_API_KEY") || hasEnvVar("CLAUDE_CODE_OAUTH_TOKEN")) return;
|
|
219
|
+
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Detect agent-runtime auth failures that should be reformatted as an actionable
|
|
224
|
+
* key-fix CTA before being shown to the user. Covers the shapes we see:
|
|
225
|
+
* - missing key (validateAgentApiKey throw): contains MISSING_KEY_MARKER
|
|
226
|
+
* - revoked / invalid key (Claude CLI 401 surfaced via api_error_status):
|
|
227
|
+
* "Invalid API key · Fix external API key" + similar provider variants
|
|
228
|
+
* - direct-Anthropic 401 (`Failed to authenticate. API Error: 401 ...
|
|
229
|
+
* {"type":"error","error":{"type":"authentication_error", ...
|
|
230
|
+
* "Invalid bearer token"}}`) emitted by the Claude CLI for revoked /
|
|
231
|
+
* mistyped / rotated `ANTHROPIC_API_KEY`. see #782.
|
|
232
|
+
*/
|
|
233
|
+
export function isApiKeyAuthError(text: string): boolean {
|
|
234
|
+
if (!text) return false;
|
|
235
|
+
return (
|
|
236
|
+
text.includes(MISSING_KEY_MARKER) ||
|
|
237
|
+
/Invalid API key/i.test(text) ||
|
|
238
|
+
/\bUser not found\b/i.test(text) ||
|
|
239
|
+
/\bInvalid authentication\b/i.test(text) ||
|
|
240
|
+
/authentication_error/i.test(text) ||
|
|
241
|
+
/Invalid bearer token/i.test(text) ||
|
|
242
|
+
/api_error_status\s*=\s*401/i.test(text) ||
|
|
243
|
+
/API Error:\s*401/i.test(text) ||
|
|
244
|
+
// upstream #931: covers the direct-Anthropic AND managed-Bedrock 403 shape
|
|
245
|
+
// (`Failed to authenticate. API Error: 403 … has expired`) — a short-lived
|
|
246
|
+
// bearer/OAuth credential that lapsed mid-run, not just a 401-rejected key.
|
|
247
|
+
/Failed to authenticate\. API Error:/i.test(text) ||
|
|
248
|
+
// upstream #960: DeepSeek's invalid-key shape, anchored so it can't collide
|
|
249
|
+
// with its separate `Insufficient balance` billing message.
|
|
250
|
+
/Your api key:.*is invalid/i.test(text) ||
|
|
251
|
+
isOAuthCredentialExpiredError(text)
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* A subscription/OAuth credential (Claude `CLAUDE_CODE_OAUTH_TOKEN`, Codex OAuth, or a
|
|
257
|
+
* short-lived Bedrock bearer) that has EXPIRED — distinct from a rejected/mistyped key.
|
|
258
|
+
* The fix is to refresh/re-mint the credential, not rotate an API key, so it gets its
|
|
259
|
+
* own CTA in {@link formatApiKeyErrorSummary}.
|
|
260
|
+
*/
|
|
261
|
+
export function isOAuthCredentialExpiredError(text: string): boolean {
|
|
262
|
+
if (!text) return false;
|
|
263
|
+
return (
|
|
264
|
+
/authentication token has expired/i.test(text) ||
|
|
265
|
+
/Token refresh failed/i.test(text) ||
|
|
266
|
+
/API Error:\s*403[\s\S]*has expired/i.test(text)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Friendly Markdown summary for both the missing-key and invalid-key cases.
|
|
272
|
+
* Used in the catch / result-failure paths in `main.ts` to overwrite the raw
|
|
273
|
+
* agent error before it's posted to the PR progress comment.
|
|
274
|
+
*/
|
|
275
|
+
export function formatApiKeyErrorSummary(params: {
|
|
276
|
+
owner: string;
|
|
277
|
+
name: string;
|
|
278
|
+
raw: string;
|
|
279
|
+
}): string {
|
|
280
|
+
if (params.raw.includes(MISSING_KEY_MARKER)) {
|
|
281
|
+
return buildMissingApiKeyError({ owner: params.owner, name: params.name });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
285
|
+
const settingsUrl = `${getApiUrl()}/console/${params.owner}/${params.name}`;
|
|
286
|
+
|
|
287
|
+
// An EXPIRED subscription/OAuth/Bedrock-bearer credential needs RE-ISSUING, not key
|
|
288
|
+
// rotation — give it its own CTA (upstream #931).
|
|
289
|
+
if (isOAuthCredentialExpiredError(params.raw)) {
|
|
290
|
+
return [
|
|
291
|
+
`**Your credential expired.** A subscription/OAuth token or short-lived Bedrock bearer ${PRODUCT_NAME} used is no longer valid — refreshing it (not rotating an API key) is the fix. Re-issue it and update the matching GitHub Actions secret:`,
|
|
292
|
+
"",
|
|
293
|
+
`- \`CLAUDE_CODE_OAUTH_TOKEN\` — re-mint the Claude subscription token, then update the secret.`,
|
|
294
|
+
`- Bedrock \`AWS_BEARER_TOKEN_BEDROCK\` — re-issue the bearer, or switch to \`AWS_ACCESS_KEY_ID\`/\`AWS_SECRET_ACCESS_KEY\`.`,
|
|
295
|
+
"",
|
|
296
|
+
`[Update repo secret →](${githubSecretsUrl}) · [Setup docs →](${DOCS_URL}/keys) · [Ask in Discord →](https://discord.gg/8y96raFg8e)`,
|
|
297
|
+
].join("\n");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return [
|
|
301
|
+
`**Your LLM provider API key was rejected (401/403).** Rotate the key in your provider dashboard, then update the matching GitHub Actions secret.`,
|
|
302
|
+
"",
|
|
303
|
+
`[Update repo secret →](${githubSecretsUrl}) · [Model settings →](${settingsUrl}) · [Setup docs →](${DOCS_URL}/keys) · [Ask in Discord →](https://discord.gg/8y96raFg8e)`,
|
|
304
|
+
].join("\n");
|
|
305
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { OIDC_AUDIENCE } from "#app/brand";
|
|
2
|
+
import { log } from "#app/utils/cli";
|
|
3
|
+
import { resolveApiUrl } from "#app/utils/cloudFetchCore";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* resolve the Infraweaver API base URL. validation (https enforcement, the
|
|
7
|
+
* bearer-credential host allowlist, API_ALLOWED_HOSTS) lives in
|
|
8
|
+
* cloudFetchCore.ts so the stdlib-only post hook enforces the same policy.
|
|
9
|
+
*/
|
|
10
|
+
export function getApiUrl(): string {
|
|
11
|
+
const raw = resolveApiUrl();
|
|
12
|
+
log.debug(`resolved API_URL: ${raw}`);
|
|
13
|
+
return raw;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Whether a real Infraweaver backend is configured.
|
|
18
|
+
*
|
|
19
|
+
* Standalone BYOK runs (the OSS default) leave `API_URL` unset — `getApiUrl`
|
|
20
|
+
* then falls back to the marketing host, which serves no API. The dormant
|
|
21
|
+
* open-core persistence seams (repo learnings, run-field PATCHes) must no-op
|
|
22
|
+
* in that case rather than POST into the void and surface the host's 404 as a
|
|
23
|
+
* CI warning. A real backend — the hosted SaaS, or local dev with
|
|
24
|
+
* `API_URL=http://localhost:3000` — sets `API_URL` explicitly.
|
|
25
|
+
*/
|
|
26
|
+
export function isBackendConfigured(): boolean {
|
|
27
|
+
return Boolean(process.env.API_URL);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The OIDC audience the tokenless path requests via `core.getIDToken(...)`.
|
|
32
|
+
*
|
|
33
|
+
* The default `"infraweaver-api"` is NOT the security boundary (the GitHub App
|
|
34
|
+
* install-consent gate is — Cloud only mints for an owner that installed the App). It
|
|
35
|
+
* is defence-in-depth, and is operator-overridable per deployment: set
|
|
36
|
+
* `GITHUB_OIDC_AUDIENCE` on BOTH the Cloud (its `expectedOidcAudience()` reads the same
|
|
37
|
+
* var) AND the engine's Action job env. Both must agree or OIDC auth fails closed.
|
|
38
|
+
* Single-source so all three engine call sites can never drift from the Cloud default.
|
|
39
|
+
*/
|
|
40
|
+
export function cloudOidcAudience(): string {
|
|
41
|
+
return process.env.GITHUB_OIDC_AUDIENCE || OIDC_AUDIENCE;
|
|
42
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { log } from "#app/utils/cli";
|
|
5
|
+
|
|
6
|
+
// github image hosts that appear in issue/PR/review/comment markdown.
|
|
7
|
+
// - github.com/user-attachments/assets/... and github.com/<owner>/<repo>/assets/...
|
|
8
|
+
// are the raw urls present in *unrendered* bodies (the MCP tools return these);
|
|
9
|
+
// fetching them needs the installation token.
|
|
10
|
+
// - {private-user-images,user-images,camo}.githubusercontent.com/... are the signed
|
|
11
|
+
// urls produced by body_html→turndown (see resolveBody); they self-authenticate via
|
|
12
|
+
// a jwt/signature in the query string and must be fetched WITHOUT an Authorization
|
|
13
|
+
// header (sending the token to the CDN would leak it).
|
|
14
|
+
const ASSET_HOST = String.raw`(?:github\.com\/(?:user-attachments\/assets|[^/\s]+\/[^/\s]+\/assets)\/|(?:private-user-images|user-images|camo)\.githubusercontent\.com\/)`;
|
|
15
|
+
const MARKDOWN_IMAGE = new RegExp(String.raw`!\[[^\]]*\]\((https:\/\/${ASSET_HOST}[^\s"')]+)`, "g");
|
|
16
|
+
const HTML_IMAGE = new RegExp(String.raw`<img[^>]+src=["'](https:\/\/${ASSET_HOST}[^"'\s]+)`, "g");
|
|
17
|
+
|
|
18
|
+
// Bound the download of an attacker-controlled (PR/issue/comment-sourced) asset
|
|
19
|
+
// url: a hung or oversized response must not stall the run or exhaust memory.
|
|
20
|
+
const ASSET_FETCH_TIMEOUT_MS = 20_000;
|
|
21
|
+
const MAX_ASSET_BYTES = 50 * 1024 * 1024;
|
|
22
|
+
|
|
23
|
+
const ALLOWED_EXTENSIONS = new Set([
|
|
24
|
+
".png",
|
|
25
|
+
".jpg",
|
|
26
|
+
".gif",
|
|
27
|
+
".webp",
|
|
28
|
+
".svg",
|
|
29
|
+
".mp4",
|
|
30
|
+
".mov",
|
|
31
|
+
".webm",
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* downloads any github-hosted image/video assets referenced in `markdown` to
|
|
36
|
+
* `<tmpdir>/assets` and rewrites the urls to the local file paths, so the agent can
|
|
37
|
+
* read screenshots directly instead of relying on remote (often short-lived, signed)
|
|
38
|
+
* urls. unique urls are downloaded once and every occurrence is rewritten. assets that
|
|
39
|
+
* fail to download are left untouched.
|
|
40
|
+
*/
|
|
41
|
+
export async function downloadAssetsInMarkdown(
|
|
42
|
+
markdown: string,
|
|
43
|
+
tmpdir: string,
|
|
44
|
+
githubToken: string,
|
|
45
|
+
): Promise<string> {
|
|
46
|
+
const urls = new Set<string>();
|
|
47
|
+
for (const match of markdown.matchAll(MARKDOWN_IMAGE)) urls.add(match[1]!);
|
|
48
|
+
for (const match of markdown.matchAll(HTML_IMAGE)) urls.add(match[1]!);
|
|
49
|
+
|
|
50
|
+
if (urls.size === 0) return markdown;
|
|
51
|
+
|
|
52
|
+
const assetsDir = path.join(tmpdir, "assets");
|
|
53
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
54
|
+
|
|
55
|
+
log.debug(`[assets] found ${urls.size} asset(s) to download`);
|
|
56
|
+
|
|
57
|
+
let result = markdown;
|
|
58
|
+
for (const url of urls) {
|
|
59
|
+
const localPath = await downloadAsset(url, assetsDir, githubToken);
|
|
60
|
+
if (localPath) result = result.replaceAll(url, localPath);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function downloadAsset(
|
|
66
|
+
url: string,
|
|
67
|
+
assetsDir: string,
|
|
68
|
+
githubToken: string,
|
|
69
|
+
): Promise<string | null> {
|
|
70
|
+
// only github.com itself needs the installation token; the githubusercontent CDN
|
|
71
|
+
// urls carry their own signature. `redirect: "follow"` (undici default) strips the
|
|
72
|
+
// Authorization header on cross-origin hops, so the token never reaches S3/the CDN.
|
|
73
|
+
const needsAuth = new URL(url).hostname === "github.com";
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch(url, {
|
|
77
|
+
headers: needsAuth ? { Authorization: `Bearer ${githubToken}` } : {},
|
|
78
|
+
signal: AbortSignal.timeout(ASSET_FETCH_TIMEOUT_MS),
|
|
79
|
+
});
|
|
80
|
+
if (!res.ok) {
|
|
81
|
+
log.warning(`[assets] failed to download ${url}: ${res.status}`);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const declared = Number(res.headers.get("content-length"));
|
|
86
|
+
if (Number.isFinite(declared) && declared > MAX_ASSET_BYTES) {
|
|
87
|
+
log.warning(`[assets] skipping ${url}: ${declared} bytes exceeds ${MAX_ASSET_BYTES} cap`);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
92
|
+
if (buffer.length > MAX_ASSET_BYTES) {
|
|
93
|
+
log.warning(`[assets] skipping ${url}: body exceeds ${MAX_ASSET_BYTES} cap`);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const ext = resolveExtension(url, res.headers.get("content-type"));
|
|
97
|
+
const filename = `${crypto.createHash("sha256").update(url).digest("hex").slice(0, 16)}${ext}`;
|
|
98
|
+
const localPath = path.join(assetsDir, filename);
|
|
99
|
+
fs.writeFileSync(localPath, buffer);
|
|
100
|
+
log.debug(`[assets] downloaded ${url} to ${localPath}`);
|
|
101
|
+
return localPath;
|
|
102
|
+
} catch (e) {
|
|
103
|
+
log.warning(`[assets] error downloading ${url}: ${e}`);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** picks a safe, whitelisted file extension from the url path or response content-type. */
|
|
109
|
+
function resolveExtension(url: string, contentType: string | null): string {
|
|
110
|
+
const fromPath = path.extname(new URL(url).pathname).toLowerCase();
|
|
111
|
+
if (ALLOWED_EXTENSIONS.has(fromPath)) return fromPath;
|
|
112
|
+
if (fromPath === ".jpeg") return ".jpg";
|
|
113
|
+
|
|
114
|
+
const ct = contentType?.toLowerCase() ?? "";
|
|
115
|
+
if (ct.includes("jpeg") || ct.includes("jpg")) return ".jpg";
|
|
116
|
+
if (ct.includes("gif")) return ".gif";
|
|
117
|
+
if (ct.includes("webp")) return ".webp";
|
|
118
|
+
if (ct.includes("svg")) return ".svg";
|
|
119
|
+
if (ct.includes("mp4")) return ".mp4";
|
|
120
|
+
if (ct.includes("quicktime") || ct.includes("mov")) return ".mov";
|
|
121
|
+
if (ct.includes("webm")) return ".webm";
|
|
122
|
+
return ".png";
|
|
123
|
+
}
|