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,96 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { installNodeDependencies } from "#app/prep/installNodeDependencies";
|
|
3
|
+
import { installPythonDependencies } from "#app/prep/installPythonDependencies";
|
|
4
|
+
import type { PrepDefinition, PrepOptions, PrepResult } from "#app/prep/types";
|
|
5
|
+
import { log } from "#app/utils/cli";
|
|
6
|
+
import { spawn } from "#app/utils/subprocess";
|
|
7
|
+
|
|
8
|
+
export type { PrepOptions, PrepResult } from "#app/prep/types";
|
|
9
|
+
|
|
10
|
+
// register all prep steps here
|
|
11
|
+
const prepSteps: PrepDefinition[] = [installNodeDependencies, installPythonDependencies];
|
|
12
|
+
|
|
13
|
+
/** tracked paths with staged or unstaged modifications. */
|
|
14
|
+
async function dirtyTrackedPaths(): Promise<Set<string>> {
|
|
15
|
+
const result = await spawn({
|
|
16
|
+
cmd: "git",
|
|
17
|
+
args: ["diff", "--name-only", "HEAD"],
|
|
18
|
+
env: process.env,
|
|
19
|
+
activityTimeout: 0,
|
|
20
|
+
});
|
|
21
|
+
if (result.exitCode !== 0) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
`git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return new Set(result.stdout.split("\n").filter(Boolean));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* discard tracked-file mods left by prep steps so the customer checkout is
|
|
31
|
+
* clean before agent tools run (#906: frozen installs run package lifecycle
|
|
32
|
+
* scripts that rewrite tracked generated files like the msw worker, and the
|
|
33
|
+
* resulting dirt makes `checkout_pr` refuse). only paths that were clean
|
|
34
|
+
* before prep are restored — pre-existing dirt and files the agent touched
|
|
35
|
+
* elsewhere are never clobbered. untracked files (e.g. node_modules) are
|
|
36
|
+
* unaffected.
|
|
37
|
+
*/
|
|
38
|
+
async function restorePrepDirtiedFiles(preDirty: Set<string>): Promise<void> {
|
|
39
|
+
const dirtied = [...(await dirtyTrackedPaths())].filter((path) => !preDirty.has(path));
|
|
40
|
+
if (dirtied.length === 0) return;
|
|
41
|
+
const result = await spawn({
|
|
42
|
+
cmd: "git",
|
|
43
|
+
args: ["restore", "--staged", "--worktree", "--", ...dirtied],
|
|
44
|
+
env: process.env,
|
|
45
|
+
activityTimeout: 0,
|
|
46
|
+
});
|
|
47
|
+
if (result.exitCode !== 0) {
|
|
48
|
+
log.warning(
|
|
49
|
+
`» failed to restore ${dirtied.length} tracked file(s) modified by prep: ${result.stderr.trim() || "(no stderr)"}`,
|
|
50
|
+
);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
log.info(`» restored ${dirtied.length} tracked file(s) modified by prep: ${dirtied.join(", ")}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* run all prep steps sequentially.
|
|
58
|
+
* failures are logged as warnings but don't stop the run.
|
|
59
|
+
*/
|
|
60
|
+
export async function runPrepPhase(options: PrepOptions): Promise<PrepResult[]> {
|
|
61
|
+
log.debug("» starting prep phase...");
|
|
62
|
+
const startTime = performance.now();
|
|
63
|
+
const results: PrepResult[] = [];
|
|
64
|
+
|
|
65
|
+
// prep is non-mutating by contract; snapshot so any tracked drift from
|
|
66
|
+
// lifecycle scripts can be attributed to prep and restored, even when a
|
|
67
|
+
// step fails partway through.
|
|
68
|
+
const preDirty = await dirtyTrackedPaths();
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
for (const step of prepSteps) {
|
|
72
|
+
const shouldRun = await step.shouldRun();
|
|
73
|
+
if (!shouldRun) {
|
|
74
|
+
log.debug(`» skipping ${step.name} (not applicable)`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
log.debug(`» running ${step.name}...`);
|
|
79
|
+
const result = await step.run(options);
|
|
80
|
+
results.push(result);
|
|
81
|
+
|
|
82
|
+
if (result.dependenciesInstalled) {
|
|
83
|
+
log.debug(`» ${step.name}: dependencies installed`);
|
|
84
|
+
} else if (result.issues.length > 0) {
|
|
85
|
+
log.warning(`» ${step.name}: ${result.issues[0]}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} finally {
|
|
89
|
+
await restorePrepDirtiedFiles(preDirty);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const totalDurationMs = performance.now() - startTime;
|
|
93
|
+
log.debug(`» prep phase completed (${Math.round(totalDurationMs)}ms)`);
|
|
94
|
+
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { detect } from "package-manager-detector";
|
|
4
|
+
import { resolveCommand } from "package-manager-detector/commands";
|
|
5
|
+
import type {
|
|
6
|
+
NodePackageManager,
|
|
7
|
+
NodePrepResult,
|
|
8
|
+
PrepDefinition,
|
|
9
|
+
PrepOptions,
|
|
10
|
+
} from "#app/prep/types";
|
|
11
|
+
import { log } from "#app/utils/cli";
|
|
12
|
+
import {
|
|
13
|
+
ensurePackageManager,
|
|
14
|
+
resolvePackageManagerSpec,
|
|
15
|
+
} from "#app/utils/packageManager";
|
|
16
|
+
import { spawn } from "#app/utils/subprocess";
|
|
17
|
+
|
|
18
|
+
async function isCommandAvailable(command: string): Promise<boolean> {
|
|
19
|
+
const result = await spawn({
|
|
20
|
+
cmd: "which",
|
|
21
|
+
args: [command],
|
|
22
|
+
env: { PATH: process.env.PATH || "" },
|
|
23
|
+
});
|
|
24
|
+
return result.exitCode === 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Escape hatch for the one installer we cannot verify (see `installFallback`).
|
|
29
|
+
* Opt-in by name so enabling it is a deliberate, auditable choice.
|
|
30
|
+
*/
|
|
31
|
+
const ALLOW_REMOTE_INSTALL_SCRIPT = "INFRAWEAVER_ALLOW_REMOTE_INSTALL_SCRIPT";
|
|
32
|
+
|
|
33
|
+
// fallback installers for managers corepack doesn't ship shims for.
|
|
34
|
+
// pnpm and yarn are handled by `ensurePackageManager` (corepack); bun and
|
|
35
|
+
// deno fall through to here because corepack ignores them.
|
|
36
|
+
async function installFallback(
|
|
37
|
+
name: NodePackageManager,
|
|
38
|
+
installSpec: string,
|
|
39
|
+
): Promise<string | null> {
|
|
40
|
+
if (name === "npm") return null;
|
|
41
|
+
|
|
42
|
+
// Deno has no npm-installable shim, so upstream's documented path is
|
|
43
|
+
// `curl … | sh` — piping a remote script straight into a shell, with no
|
|
44
|
+
// pinned version and nothing to verify it against. That contradicts the
|
|
45
|
+
// supply-chain posture the rest of the engine holds (the agent CLIs are
|
|
46
|
+
// version-pinned AND digest-verified, see utils/install.ts), so it is
|
|
47
|
+
// fail-closed: we do not execute an unverifiable remote script by default.
|
|
48
|
+
//
|
|
49
|
+
// Pre-installing deno on the runner is the supported path — `isCommandAvailable`
|
|
50
|
+
// above short-circuits before we ever get here.
|
|
51
|
+
if (name === "deno" && process.env[ALLOW_REMOTE_INSTALL_SCRIPT] !== "true") {
|
|
52
|
+
return (
|
|
53
|
+
`refusing to install deno by piping a remote script into a shell ` +
|
|
54
|
+
`(curl https://deno.land/install.sh | sh) — it is neither version-pinned nor ` +
|
|
55
|
+
`integrity-verified. Install deno on the runner before this step (e.g. the ` +
|
|
56
|
+
`denoland/setup-deno action, which pins a version), or set ` +
|
|
57
|
+
`${ALLOW_REMOTE_INSTALL_SCRIPT}=true to accept the risk explicitly.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
log.info(
|
|
62
|
+
`» installing ${installSpec} via npm install -g (corepack does not manage ${name})`,
|
|
63
|
+
);
|
|
64
|
+
const args =
|
|
65
|
+
name === "deno"
|
|
66
|
+
? ["-c", "curl -fsSL https://deno.land/install.sh | sh"]
|
|
67
|
+
: ["install", "-g", installSpec];
|
|
68
|
+
const cmd = name === "deno" ? "sh" : "npm";
|
|
69
|
+
if (name === "deno") {
|
|
70
|
+
log.warning(
|
|
71
|
+
`» ${ALLOW_REMOTE_INSTALL_SCRIPT}=true — executing an unverified remote install script`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const result = await spawn({
|
|
75
|
+
cmd,
|
|
76
|
+
args,
|
|
77
|
+
env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
|
|
78
|
+
onStderr: (chunk) => process.stderr.write(chunk),
|
|
79
|
+
});
|
|
80
|
+
if (result.exitCode !== 0) {
|
|
81
|
+
return result.stderr || `failed to install ${name}`;
|
|
82
|
+
}
|
|
83
|
+
if (name === "deno") {
|
|
84
|
+
const denoPath = join(process.env.HOME || "", ".deno", "bin");
|
|
85
|
+
process.env.PATH = `${denoPath}:${process.env.PATH}`;
|
|
86
|
+
}
|
|
87
|
+
log.info(`» installed ${name}`);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const installNodeDependencies: PrepDefinition = {
|
|
92
|
+
name: "installNodeDependencies",
|
|
93
|
+
|
|
94
|
+
shouldRun: () => {
|
|
95
|
+
const packageJsonPath = join(process.cwd(), "package.json");
|
|
96
|
+
return existsSync(packageJsonPath);
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
run: async (options: PrepOptions): Promise<NodePrepResult> => {
|
|
100
|
+
// prefer the project's declared spec (devEngines.packageManager wins over
|
|
101
|
+
// packageManager). fall back to lockfile detection when nothing is declared.
|
|
102
|
+
// restrict detect() to the lockfile strategy: `detected` here doubles as
|
|
103
|
+
// the lockfile-presence gate below, and the default strategy set also
|
|
104
|
+
// returns positives off `packageManager`/`devEngines` fields (which would
|
|
105
|
+
// mask the very case we're trying to detect — declared manager but no
|
|
106
|
+
// lockfile committed).
|
|
107
|
+
const declared = await resolvePackageManagerSpec(process.cwd());
|
|
108
|
+
const detected = await detect({
|
|
109
|
+
cwd: process.cwd(),
|
|
110
|
+
strategies: ["lockfile"],
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const packageManager: NodePackageManager =
|
|
114
|
+
declared?.name ?? (detected?.name as NodePackageManager) ?? "npm";
|
|
115
|
+
const agent = detected?.agent ?? packageManager;
|
|
116
|
+
|
|
117
|
+
if (declared) {
|
|
118
|
+
log.info(
|
|
119
|
+
`» using ${packageManager}@${declared.version} from package.json (${declared.source})`,
|
|
120
|
+
);
|
|
121
|
+
} else if (detected) {
|
|
122
|
+
log.info(`» detected package manager: ${packageManager} (${agent})`);
|
|
123
|
+
} else {
|
|
124
|
+
log.info(`» no package manager declared, defaulting to npm`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// provisioning: corepack for pnpm/yarn, legacy npm-install-g for bun/deno.
|
|
128
|
+
// when shell is disabled we can't run installers (they execute code), so
|
|
129
|
+
// we require the binary to already be on PATH.
|
|
130
|
+
if (!(await isCommandAvailable(packageManager))) {
|
|
131
|
+
if (options.ignoreScripts) {
|
|
132
|
+
return {
|
|
133
|
+
language: "node",
|
|
134
|
+
packageManager,
|
|
135
|
+
dependenciesInstalled: false,
|
|
136
|
+
issues: [
|
|
137
|
+
`${packageManager} is not available and cannot be installed when shell is disabled (would execute code)`,
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let provisioned = false;
|
|
143
|
+
if (declared)
|
|
144
|
+
provisioned = await ensurePackageManager({
|
|
145
|
+
spec: declared,
|
|
146
|
+
binDir: options.binDir,
|
|
147
|
+
});
|
|
148
|
+
if (!provisioned) {
|
|
149
|
+
const fallbackSpec = declared
|
|
150
|
+
? `${declared.name}@${declared.version}`
|
|
151
|
+
: packageManager;
|
|
152
|
+
const installError = await installFallback(
|
|
153
|
+
packageManager,
|
|
154
|
+
fallbackSpec,
|
|
155
|
+
);
|
|
156
|
+
if (installError) {
|
|
157
|
+
return {
|
|
158
|
+
language: "node",
|
|
159
|
+
packageManager,
|
|
160
|
+
dependenciesInstalled: false,
|
|
161
|
+
issues: [installError],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} else if (declared) {
|
|
166
|
+
// PATH already has the binary — but it may be the wrong version.
|
|
167
|
+
// ensurePackageManager is idempotent (caches on `--version` match) so
|
|
168
|
+
// this is cheap when main.ts already activated it.
|
|
169
|
+
await ensurePackageManager({ spec: declared, binDir: options.binDir });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// frozen-lockfile install only. eager prep is non-mutating by contract:
|
|
173
|
+
// we run it before the agent starts and any artifact it leaves in the
|
|
174
|
+
// tree (e.g. a generated `package-lock.json`) trips the dirty-tree
|
|
175
|
+
// post-run gate and produces a spurious PR. `frozen` commands
|
|
176
|
+
// (`npm ci`, `pnpm install --frozen-lockfile`, etc.) were assumed to
|
|
177
|
+
// fail cleanly without a lockfile — that assumption is false for
|
|
178
|
+
// pnpm 11.1.1 against a no-deps `package.json` (it silently writes an
|
|
179
|
+
// empty `pnpm-lock.yaml` despite the flag). gate on `detect()` having
|
|
180
|
+
// found a lockfile; it walks up the tree (so monorepo subpackages
|
|
181
|
+
// resolve to the workspace-root lockfile) and recognizes every
|
|
182
|
+
// manager's accepted lockfile variants (`bun.lockb` + `bun.lock`,
|
|
183
|
+
// `npm-shrinkwrap.json` + `package-lock.json`, etc.). when none is
|
|
184
|
+
// present, the project either has no installable dependencies or
|
|
185
|
+
// opts into install via a `setup` lifecycle hook
|
|
186
|
+
// (`action/utils/lifecycle.ts`); either way, eager prep should skip.
|
|
187
|
+
if (!detected) {
|
|
188
|
+
log.info(
|
|
189
|
+
`» skipping ${packageManager} install: no lockfile found (would otherwise risk lockfile drift)`,
|
|
190
|
+
);
|
|
191
|
+
return {
|
|
192
|
+
language: "node",
|
|
193
|
+
packageManager,
|
|
194
|
+
dependenciesInstalled: false,
|
|
195
|
+
issues: [],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const resolved = resolveCommand(agent, "frozen", []);
|
|
200
|
+
if (!resolved) {
|
|
201
|
+
return {
|
|
202
|
+
language: "node",
|
|
203
|
+
packageManager,
|
|
204
|
+
dependenciesInstalled: false,
|
|
205
|
+
issues: [`no frozen-install command available for ${agent}`],
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// SECURITY: when shell is disabled, suppress lifecycle scripts to prevent
|
|
210
|
+
// agents from injecting arbitrary code execution via package.json scripts
|
|
211
|
+
if (options.ignoreScripts) {
|
|
212
|
+
resolved.args.push("--ignore-scripts");
|
|
213
|
+
log.info("» --ignore-scripts enabled (shell disabled)");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const fullCommand = `${resolved.command} ${resolved.args.join(" ")}`;
|
|
217
|
+
log.info(`» running: ${fullCommand}`);
|
|
218
|
+
const result = await spawn({
|
|
219
|
+
cmd: resolved.command,
|
|
220
|
+
args: resolved.args,
|
|
221
|
+
env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const output = [result.stdout, result.stderr]
|
|
225
|
+
.filter(Boolean)
|
|
226
|
+
.join("\n")
|
|
227
|
+
.trim();
|
|
228
|
+
if (output) {
|
|
229
|
+
log.startGroup(`${fullCommand} output`);
|
|
230
|
+
log.info(output);
|
|
231
|
+
log.endGroup();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (result.exitCode !== 0) {
|
|
235
|
+
const errorMessage = output || `exited with code ${result.exitCode}`;
|
|
236
|
+
return {
|
|
237
|
+
language: "node",
|
|
238
|
+
packageManager,
|
|
239
|
+
dependenciesInstalled: false,
|
|
240
|
+
issues: [`\`${fullCommand}\` failed:\n${errorMessage}`],
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
language: "node",
|
|
246
|
+
packageManager,
|
|
247
|
+
dependenciesInstalled: true,
|
|
248
|
+
issues: [],
|
|
249
|
+
};
|
|
250
|
+
},
|
|
251
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type {
|
|
4
|
+
PrepDefinition,
|
|
5
|
+
PrepOptions,
|
|
6
|
+
PythonPackageManager,
|
|
7
|
+
PythonPrepResult,
|
|
8
|
+
} from "#app/prep/types";
|
|
9
|
+
import { log } from "#app/utils/cli";
|
|
10
|
+
import { spawn } from "#app/utils/subprocess";
|
|
11
|
+
|
|
12
|
+
interface PythonConfig {
|
|
13
|
+
file: string;
|
|
14
|
+
tool: PythonPackageManager;
|
|
15
|
+
// non-empty: the first element is the executable, the rest are args
|
|
16
|
+
installCmd: [string, ...string[]];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// python dependency file patterns in priority order
|
|
20
|
+
const PYTHON_CONFIGS: PythonConfig[] = [
|
|
21
|
+
{
|
|
22
|
+
file: "requirements.txt",
|
|
23
|
+
tool: "pip",
|
|
24
|
+
installCmd: ["pip", "install", "-r", "requirements.txt"],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
file: "pyproject.toml",
|
|
28
|
+
tool: "pip",
|
|
29
|
+
installCmd: ["pip", "install", "."],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
file: "Pipfile",
|
|
33
|
+
tool: "pipenv",
|
|
34
|
+
installCmd: ["pipenv", "install"],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
file: "Pipfile.lock",
|
|
38
|
+
tool: "pipenv",
|
|
39
|
+
installCmd: ["pipenv", "sync"],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
file: "poetry.lock",
|
|
43
|
+
tool: "poetry",
|
|
44
|
+
installCmd: ["poetry", "install", "--no-interaction"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
file: "setup.py",
|
|
48
|
+
tool: "pip",
|
|
49
|
+
installCmd: ["pip", "install", "-e", "."],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A root `pyproject.toml` no longer implies a pip-installable package. When it
|
|
55
|
+
* lacks a `[build-system]` table (PEP 517/518) it is a tool-config / PEP 735
|
|
56
|
+
* dependency-groups file (e.g. ruff/mypy under uv), and `pip install .` falls
|
|
57
|
+
* back to legacy setuptools flat-layout discovery, which hard-fails on monorepos
|
|
58
|
+
* ("Multiple top-level packages discovered in a flat-layout"). The gate is a
|
|
59
|
+
* heuristic proxy for "scaffolded as a distributable package": pip treats a
|
|
60
|
+
* pyproject without `[build-system]` as the legacy setuptools backend and would
|
|
61
|
+
* proceed, so we trade a rare false-negative to kill the common tooling-only
|
|
62
|
+
* false positive. Unreadable → treat as not installable (skip, don't crash prep).
|
|
63
|
+
*/
|
|
64
|
+
function pyprojectDeclaresBuildSystem(cwd: string): boolean {
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(join(cwd, "pyproject.toml"), "utf8");
|
|
67
|
+
return /^\s*\[build-system\]/m.test(content);
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether a detected config file should actually drive an install. Everything
|
|
75
|
+
* applies except a `pyproject.toml` with no build system — that one is skipped
|
|
76
|
+
* so a tooling-only pyproject doesn't trigger a doomed `pip install .`.
|
|
77
|
+
*/
|
|
78
|
+
function configApplies(config: PythonConfig, cwd: string): boolean {
|
|
79
|
+
if (config.file === "pyproject.toml") return pyprojectDeclaresBuildSystem(cwd);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// tool install commands (via pip). Each command is non-empty (executable + args).
|
|
84
|
+
const TOOL_INSTALL_COMMANDS: Record<string, [string, ...string[]]> = {
|
|
85
|
+
pipenv: ["pip", "install", "pipenv"],
|
|
86
|
+
poetry: ["pip", "install", "poetry"],
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
async function isCommandAvailable(command: string): Promise<boolean> {
|
|
90
|
+
const result = await spawn({
|
|
91
|
+
cmd: "which",
|
|
92
|
+
args: [command],
|
|
93
|
+
env: { PATH: process.env.PATH || "" },
|
|
94
|
+
});
|
|
95
|
+
return result.exitCode === 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function installTool(name: string): Promise<string | null> {
|
|
99
|
+
const installCmd = TOOL_INSTALL_COMMANDS[name];
|
|
100
|
+
if (!installCmd) {
|
|
101
|
+
// tool doesn't need installation (e.g., pip)
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
log.info(`» installing ${name}...`);
|
|
106
|
+
const [cmd, ...args] = installCmd;
|
|
107
|
+
const result = await spawn({
|
|
108
|
+
cmd,
|
|
109
|
+
args,
|
|
110
|
+
env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
|
|
111
|
+
onStderr: (chunk) => process.stderr.write(chunk),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (result.exitCode !== 0) {
|
|
115
|
+
return result.stderr || `failed to install ${name}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
log.info(`» installed ${name}`);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const installPythonDependencies: PrepDefinition = {
|
|
123
|
+
name: "installPythonDependencies",
|
|
124
|
+
|
|
125
|
+
shouldRun: async () => {
|
|
126
|
+
// check if python is available
|
|
127
|
+
const hasPython = (await isCommandAvailable("python3")) || (await isCommandAvailable("python"));
|
|
128
|
+
if (!hasPython) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// check if any python config file exists AND actually drives an install
|
|
133
|
+
// (a tooling-only pyproject.toml without a [build-system] table does not).
|
|
134
|
+
const cwd = process.cwd();
|
|
135
|
+
return PYTHON_CONFIGS.some(
|
|
136
|
+
(config) => existsSync(join(cwd, config.file)) && configApplies(config, cwd),
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
run: async (options: PrepOptions): Promise<PythonPrepResult> => {
|
|
141
|
+
const cwd = process.cwd();
|
|
142
|
+
|
|
143
|
+
// find the first matching config that actually drives an install (skips a
|
|
144
|
+
// tooling-only pyproject.toml, letting a lower-priority config win instead).
|
|
145
|
+
const config = PYTHON_CONFIGS.find(
|
|
146
|
+
(c) => existsSync(join(cwd, c.file)) && configApplies(c, cwd),
|
|
147
|
+
);
|
|
148
|
+
if (!config) {
|
|
149
|
+
return {
|
|
150
|
+
language: "python",
|
|
151
|
+
packageManager: "pip",
|
|
152
|
+
configFile: "unknown",
|
|
153
|
+
dependenciesInstalled: false,
|
|
154
|
+
issues: ["no python config file found"],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
log.info(`» detected python config: ${config.file} (using ${config.tool})`);
|
|
159
|
+
|
|
160
|
+
// SECURITY: when shell is disabled, skip ALL python dependency installation.
|
|
161
|
+
// every python install path can potentially execute arbitrary code:
|
|
162
|
+
// - setup.py / pyproject.toml: directly execute build backends
|
|
163
|
+
// - requirements.txt: can contain "-e ." or local path references that
|
|
164
|
+
// trigger setup.py execution
|
|
165
|
+
// - Pipfile/poetry.lock: can contain path dependencies pointing to local
|
|
166
|
+
// directories with malicious setup.py
|
|
167
|
+
// - source distributions from PyPI also execute setup.py
|
|
168
|
+
// there is no equivalent of npm's --ignore-scripts for pip.
|
|
169
|
+
if (options.ignoreScripts) {
|
|
170
|
+
log.info(
|
|
171
|
+
`» skipping python install (shell disabled, python packages can execute arbitrary code)`,
|
|
172
|
+
);
|
|
173
|
+
return {
|
|
174
|
+
language: "python",
|
|
175
|
+
packageManager: config.tool,
|
|
176
|
+
configFile: config.file,
|
|
177
|
+
dependenciesInstalled: false,
|
|
178
|
+
issues: [
|
|
179
|
+
`skipped: python dependency installation can execute arbitrary code (setup.py, build backends, local path references), which is blocked when shell is disabled`,
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// check if the tool is available, install if needed
|
|
185
|
+
const isAvailable = await isCommandAvailable(config.tool);
|
|
186
|
+
if (!isAvailable) {
|
|
187
|
+
log.info(`» ${config.tool} not found, attempting to install...`);
|
|
188
|
+
const installError = await installTool(config.tool);
|
|
189
|
+
if (installError) {
|
|
190
|
+
return {
|
|
191
|
+
language: "python",
|
|
192
|
+
packageManager: config.tool,
|
|
193
|
+
configFile: config.file,
|
|
194
|
+
dependenciesInstalled: false,
|
|
195
|
+
issues: [installError],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// run the install command
|
|
201
|
+
const [cmd, ...args] = config.installCmd;
|
|
202
|
+
const fullCommand = `${cmd} ${args.join(" ")}`;
|
|
203
|
+
log.info(`» running: ${fullCommand}`);
|
|
204
|
+
const result = await spawn({
|
|
205
|
+
cmd,
|
|
206
|
+
args,
|
|
207
|
+
env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
211
|
+
if (output) {
|
|
212
|
+
log.startGroup(`${fullCommand} output`);
|
|
213
|
+
log.info(output);
|
|
214
|
+
log.endGroup();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (result.exitCode !== 0) {
|
|
218
|
+
return {
|
|
219
|
+
language: "python",
|
|
220
|
+
packageManager: config.tool,
|
|
221
|
+
configFile: config.file,
|
|
222
|
+
dependenciesInstalled: false,
|
|
223
|
+
issues: [output || `${cmd} exited with code ${result.exitCode}`],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
language: "python",
|
|
229
|
+
packageManager: config.tool,
|
|
230
|
+
configFile: config.file,
|
|
231
|
+
dependenciesInstalled: true,
|
|
232
|
+
issues: [],
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
interface PrepResultBase {
|
|
2
|
+
dependenciesInstalled: boolean;
|
|
3
|
+
issues: string[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type NodePackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno";
|
|
7
|
+
|
|
8
|
+
export interface NodePrepResult extends PrepResultBase {
|
|
9
|
+
language: "node";
|
|
10
|
+
packageManager: NodePackageManager;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type PythonPackageManager = "pip" | "pipenv" | "poetry";
|
|
14
|
+
|
|
15
|
+
export interface PythonPrepResult extends PrepResultBase {
|
|
16
|
+
language: "python";
|
|
17
|
+
packageManager: PythonPackageManager;
|
|
18
|
+
configFile: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface UnknownLanguagePrepResult extends PrepResultBase {
|
|
22
|
+
language: "unknown";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type PrepResult = NodePrepResult | PythonPrepResult | UnknownLanguagePrepResult;
|
|
26
|
+
|
|
27
|
+
export type PrepOptions = {
|
|
28
|
+
/** when true, lifecycle scripts (postinstall, etc.) are suppressed */
|
|
29
|
+
ignoreScripts: boolean;
|
|
30
|
+
/** directory the corepack shim is installed into (see `packageManagerBinDir`) */
|
|
31
|
+
binDir: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface PrepDefinition {
|
|
35
|
+
name: string;
|
|
36
|
+
shouldRun: () => Promise<boolean> | boolean;
|
|
37
|
+
run: (options: PrepOptions) => Promise<PrepResult>;
|
|
38
|
+
}
|