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
package/src/utils/log.ts
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging utilities that work well in both local and GitHub Actions environments
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
|
+
import * as core from "@actions/core";
|
|
7
|
+
import { table } from "table";
|
|
8
|
+
import { type AgentUsage, formatCostUsd } from "#app/agents/shared";
|
|
9
|
+
import { isGitHubActions, isInsideDocker } from "#app/utils/globals";
|
|
10
|
+
import { redactSecrets } from "#app/utils/redact";
|
|
11
|
+
|
|
12
|
+
// --- log prefix via AsyncLocalStorage ---
|
|
13
|
+
|
|
14
|
+
type LogContext = { prefix: string };
|
|
15
|
+
|
|
16
|
+
const logContext = new AsyncLocalStorage<LogContext>();
|
|
17
|
+
|
|
18
|
+
const MAGENTA = "\x1b[35m";
|
|
19
|
+
const RESET = "\x1b[0m";
|
|
20
|
+
|
|
21
|
+
/** run `fn` with every log line prefixed by `prefix` (e.g. "[task-label]") in magenta */
|
|
22
|
+
export function withLogPrefix<T>(prefix: string, fn: () => Promise<T>): Promise<T> {
|
|
23
|
+
return logContext.run({ prefix }, fn);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function prefixLines(message: string): string {
|
|
27
|
+
const ctx = logContext.getStore();
|
|
28
|
+
if (!ctx) return message;
|
|
29
|
+
const colored = `${MAGENTA}${ctx.prefix}${RESET} `;
|
|
30
|
+
return message
|
|
31
|
+
.split("\n")
|
|
32
|
+
.map((line) => `${colored}${line}`)
|
|
33
|
+
.join("\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** plain-text prefix (no ANSI) for GitHub Actions group names */
|
|
37
|
+
function prefixPlain(name: string): string {
|
|
38
|
+
const ctx = logContext.getStore();
|
|
39
|
+
if (!ctx) return name;
|
|
40
|
+
return `${ctx.prefix} ${name}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// --- log sink ----------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
type LogSink = "actions" | "stderr";
|
|
46
|
+
|
|
47
|
+
let sink: LogSink = "actions";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Route ALL log output to stderr instead of `@actions/core` (which writes to
|
|
51
|
+
* stdout). Required before starting a stdio MCP server: stdout is the JSON-RPC
|
|
52
|
+
* channel there, and a single stray diagnostic line corrupts the framing.
|
|
53
|
+
* The GitHub Action path never calls this — its sink stays `@actions/core`.
|
|
54
|
+
*/
|
|
55
|
+
export function setLogSink(next: LogSink): void {
|
|
56
|
+
sink = next;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* info-level line via the active sink.
|
|
61
|
+
*
|
|
62
|
+
* Scrub secret-shaped substrings here, at the single sink primitive, so redaction
|
|
63
|
+
* is truly sink-independent. `formatArgs` already redacts the `info`/`success`/`debug`
|
|
64
|
+
* lines, but `box`/`table`/`separator`/`group` build their content directly and reach
|
|
65
|
+
* the sink through this function without passing through `formatArgs` — without this
|
|
66
|
+
* pass a secret printed via `log.box(...)` would leak in cleartext on stderr/local.
|
|
67
|
+
* `redactSecrets` is idempotent and allocation-light on the no-secret path, so the
|
|
68
|
+
* double-pass on the already-redacted lines is cheap.
|
|
69
|
+
*/
|
|
70
|
+
function emitInfo(line: string): void {
|
|
71
|
+
const safe = redactSecrets(line);
|
|
72
|
+
if (sink === "stderr") {
|
|
73
|
+
process.stderr.write(`${safe}\n`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
core.info(safe);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const isRunnerDebugEnabled = () => core.isDebug();
|
|
80
|
+
|
|
81
|
+
const isLocalDebugEnabled = () =>
|
|
82
|
+
process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true";
|
|
83
|
+
|
|
84
|
+
const isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled();
|
|
85
|
+
|
|
86
|
+
/** timestamp prefix for debug mode — empty string when debug is off */
|
|
87
|
+
function ts(): string {
|
|
88
|
+
return isDebugEnabled() ? `[${new Date().toISOString()}] ` : "";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Format arguments into a single string for logging.
|
|
93
|
+
*
|
|
94
|
+
* The joined line is passed through {@link redactSecrets} so secret-shaped
|
|
95
|
+
* substrings are scrubbed regardless of the active sink — `core.setSecret` only masks
|
|
96
|
+
* on the GitHub `actions` sink, leaving stderr (every stdio MCP server) and local dev
|
|
97
|
+
* unmasked.
|
|
98
|
+
*/
|
|
99
|
+
function formatArgs(args: unknown[]): string {
|
|
100
|
+
const joined = args
|
|
101
|
+
.map((arg) => {
|
|
102
|
+
if (typeof arg === "string") return arg;
|
|
103
|
+
if (arg instanceof Error) return `${arg.message}\n${arg.stack}`;
|
|
104
|
+
return JSON.stringify(arg);
|
|
105
|
+
})
|
|
106
|
+
.join(" ");
|
|
107
|
+
return redactSecrets(joined);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Start a collapsed group (GitHub Actions) or regular group (local)
|
|
112
|
+
*/
|
|
113
|
+
function startGroup(name: string): void {
|
|
114
|
+
const prefixed = prefixPlain(name);
|
|
115
|
+
if (sink === "stderr") {
|
|
116
|
+
emitInfo(`▼ ${prefixed}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (isGitHubActions) {
|
|
120
|
+
core.startGroup(prefixed);
|
|
121
|
+
} else {
|
|
122
|
+
console.group(prefixed);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* End a collapsed group
|
|
128
|
+
*/
|
|
129
|
+
function endGroup(): void {
|
|
130
|
+
if (sink === "stderr") return;
|
|
131
|
+
if (isGitHubActions) {
|
|
132
|
+
core.endGroup();
|
|
133
|
+
} else {
|
|
134
|
+
console.groupEnd();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Run a callback within a collapsed group
|
|
140
|
+
*/
|
|
141
|
+
function group(name: string, fn: () => void): void {
|
|
142
|
+
startGroup(name);
|
|
143
|
+
fn();
|
|
144
|
+
endGroup();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Print a formatted box with text (for console output)
|
|
149
|
+
*/
|
|
150
|
+
function boxString(
|
|
151
|
+
text: string,
|
|
152
|
+
options?: {
|
|
153
|
+
title?: string;
|
|
154
|
+
maxWidth?: number;
|
|
155
|
+
indent?: string;
|
|
156
|
+
padding?: number;
|
|
157
|
+
},
|
|
158
|
+
): string {
|
|
159
|
+
const { title, maxWidth = 80, indent = "", padding = 1 } = options || {};
|
|
160
|
+
|
|
161
|
+
const lines = text.trim().split("\n");
|
|
162
|
+
const wrappedLines: string[] = [];
|
|
163
|
+
|
|
164
|
+
for (const line of lines) {
|
|
165
|
+
if (line.length <= maxWidth - padding * 2) {
|
|
166
|
+
wrappedLines.push(line);
|
|
167
|
+
} else {
|
|
168
|
+
const words = line.split(" ");
|
|
169
|
+
let currentLine = "";
|
|
170
|
+
|
|
171
|
+
for (const word of words) {
|
|
172
|
+
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
173
|
+
if (testLine.length <= maxWidth - padding * 2) {
|
|
174
|
+
currentLine = testLine;
|
|
175
|
+
} else {
|
|
176
|
+
if (currentLine) {
|
|
177
|
+
wrappedLines.push(currentLine);
|
|
178
|
+
currentLine = "";
|
|
179
|
+
}
|
|
180
|
+
// wrap long words by breaking them into chunks
|
|
181
|
+
const maxLineLength = maxWidth - padding * 2;
|
|
182
|
+
let remainingWord = word;
|
|
183
|
+
while (remainingWord.length > maxLineLength) {
|
|
184
|
+
wrappedLines.push(remainingWord.substring(0, maxLineLength));
|
|
185
|
+
remainingWord = remainingWord.substring(maxLineLength);
|
|
186
|
+
}
|
|
187
|
+
currentLine = remainingWord;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (currentLine) {
|
|
192
|
+
wrappedLines.push(currentLine);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const maxLineLength = Math.max(...wrappedLines.map((line) => line.length));
|
|
198
|
+
const contentBoxWidth = maxLineLength + padding * 2;
|
|
199
|
+
|
|
200
|
+
// ensure box width is at least as wide as the title line when title exists
|
|
201
|
+
const titleLineLength = title ? ` ${title} `.length : 0;
|
|
202
|
+
const boxWidth = Math.max(contentBoxWidth, titleLineLength);
|
|
203
|
+
|
|
204
|
+
let result = "";
|
|
205
|
+
|
|
206
|
+
if (title) {
|
|
207
|
+
const titleLine = ` ${title} `;
|
|
208
|
+
const titlePadding = Math.max(0, boxWidth - titleLine.length);
|
|
209
|
+
result += `${indent}┌${titleLine}${"─".repeat(titlePadding)}┐\n`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!title) {
|
|
213
|
+
result += `${indent}┌${"─".repeat(boxWidth)}┐\n`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
for (const line of wrappedLines) {
|
|
217
|
+
const paddedLine = line.padEnd(maxLineLength);
|
|
218
|
+
result += `${indent}│${" ".repeat(padding)}${paddedLine}${" ".repeat(padding)}│\n`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
result += `${indent}└${"─".repeat(boxWidth)}┘`;
|
|
222
|
+
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Print a formatted box with text
|
|
228
|
+
*/
|
|
229
|
+
function box(
|
|
230
|
+
text: string,
|
|
231
|
+
options?: {
|
|
232
|
+
title?: string;
|
|
233
|
+
maxWidth?: number;
|
|
234
|
+
},
|
|
235
|
+
): void {
|
|
236
|
+
const boxContent = boxString(text, options);
|
|
237
|
+
emitInfo(prefixLines(boxContent));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Overwrite the job summary with the given text.
|
|
242
|
+
* Skips if:
|
|
243
|
+
* - Not in GitHub Actions
|
|
244
|
+
* - Running inside Docker (CI tests inherit host env vars but can't access host paths)
|
|
245
|
+
* - GITHUB_STEP_SUMMARY not set
|
|
246
|
+
*/
|
|
247
|
+
export async function writeSummary(text: string): Promise<void> {
|
|
248
|
+
if (!isGitHubActions) return;
|
|
249
|
+
|
|
250
|
+
// CI tests run in Docker with GITHUB_ACTIONS=true inherited from host,
|
|
251
|
+
// but the GITHUB_STEP_SUMMARY path points to a host filesystem location
|
|
252
|
+
// that doesn't exist inside the container
|
|
253
|
+
if (isInsideDocker) return;
|
|
254
|
+
|
|
255
|
+
if (!process.env.GITHUB_STEP_SUMMARY) return;
|
|
256
|
+
|
|
257
|
+
// LLM02: the job summary includes raw agent output — scrub secrets before it
|
|
258
|
+
// lands in the durable GitHub Actions step summary. Idempotent + no-op on clean text.
|
|
259
|
+
await core.summary.addRaw(redactSecrets(text)).write({ overwrite: true });
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Print a formatted table using the table package
|
|
264
|
+
*/
|
|
265
|
+
function printTable(
|
|
266
|
+
rows: Array<Array<{ data: string; header?: boolean } | string>>,
|
|
267
|
+
options?: {
|
|
268
|
+
title?: string;
|
|
269
|
+
},
|
|
270
|
+
): void {
|
|
271
|
+
const { title } = options || {};
|
|
272
|
+
|
|
273
|
+
// Convert rows to string arrays for the table package
|
|
274
|
+
const tableData = rows.map((row) =>
|
|
275
|
+
row.map((cell) => {
|
|
276
|
+
if (typeof cell === "string") {
|
|
277
|
+
return cell;
|
|
278
|
+
}
|
|
279
|
+
return cell.data;
|
|
280
|
+
}),
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
const formatted = table(tableData);
|
|
284
|
+
|
|
285
|
+
if (title) {
|
|
286
|
+
emitInfo(prefixLines(`\n${title}`));
|
|
287
|
+
}
|
|
288
|
+
emitInfo(prefixLines(`\n${formatted}\n`));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Print a separator line
|
|
293
|
+
*/
|
|
294
|
+
function separator(length: number = 50): void {
|
|
295
|
+
const separatorText = "─".repeat(length);
|
|
296
|
+
emitInfo(prefixLines(separatorText));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Main logging utility object - import this once and access all utilities
|
|
301
|
+
*/
|
|
302
|
+
export const log = {
|
|
303
|
+
/** Print info message */
|
|
304
|
+
info: (...args: unknown[]): void => {
|
|
305
|
+
emitInfo(prefixLines(`${ts()}${formatArgs(args)}`));
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
/** Print a warning message. Use only for warnings that should be displayed in the job summary. */
|
|
309
|
+
warning: (...args: unknown[]): void => {
|
|
310
|
+
if (sink === "stderr") {
|
|
311
|
+
emitInfo(prefixLines(`${ts()}warning: ${formatArgs(args)}`));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
core.warning(prefixLines(`${ts()}${formatArgs(args)}`));
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
/** Print an error message. Use only for errors that should be displayed in the job summary. */
|
|
318
|
+
error: (...args: unknown[]): void => {
|
|
319
|
+
if (sink === "stderr") {
|
|
320
|
+
emitInfo(prefixLines(`${ts()}error: ${formatArgs(args)}`));
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
core.error(prefixLines(`${ts()}${formatArgs(args)}`));
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
/** Print success message */
|
|
327
|
+
success: (...args: unknown[]): void => {
|
|
328
|
+
emitInfo(prefixLines(`${ts()}» ${formatArgs(args)}`));
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
/** Print debug message (only when debug mode is enabled) */
|
|
332
|
+
debug: (...args: unknown[]): void => {
|
|
333
|
+
if (sink === "actions" && isRunnerDebugEnabled()) {
|
|
334
|
+
core.debug(prefixLines(formatArgs(args)));
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (isLocalDebugEnabled()) {
|
|
338
|
+
emitInfo(prefixLines(`${ts()}[DEBUG] ${formatArgs(args)}`));
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
/** Print a formatted box with text */
|
|
343
|
+
box,
|
|
344
|
+
|
|
345
|
+
/** Print a formatted table using the table package */
|
|
346
|
+
table: printTable,
|
|
347
|
+
|
|
348
|
+
/** Print a separator line */
|
|
349
|
+
separator,
|
|
350
|
+
|
|
351
|
+
/** Start a collapsed group (GitHub Actions) or regular group (local) */
|
|
352
|
+
startGroup,
|
|
353
|
+
|
|
354
|
+
/** End a collapsed group */
|
|
355
|
+
endGroup,
|
|
356
|
+
|
|
357
|
+
/** Run a callback within a collapsed group */
|
|
358
|
+
group,
|
|
359
|
+
|
|
360
|
+
/** Log tool call information to console with formatted output */
|
|
361
|
+
toolCall: ({ toolName, input }: { toolName: string; input: unknown }): void => {
|
|
362
|
+
const inputFormatted = formatJsonValue(input);
|
|
363
|
+
const output = inputFormatted !== "{}" ? `» ${toolName}(${inputFormatted})` : `» ${toolName}()`;
|
|
364
|
+
|
|
365
|
+
log.info(output.trimEnd());
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Format a value as JSON, using compact format for simple values and pretty-printed for complex ones
|
|
371
|
+
*/
|
|
372
|
+
export function formatJsonValue(value: unknown): string {
|
|
373
|
+
const compact = JSON.stringify(value);
|
|
374
|
+
return compact.length > 80 || compact.includes("\n") ? JSON.stringify(value, null, 2) : compact;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Format a multi-line string with proper indentation for tool call output
|
|
379
|
+
* First line has the label, subsequent lines are indented 4 spaces
|
|
380
|
+
*/
|
|
381
|
+
export function formatIndentedField(label: string, content: string): string {
|
|
382
|
+
if (!content.includes("\n")) {
|
|
383
|
+
return ` ${label}: ${content}\n`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const lines = content.split("\n");
|
|
387
|
+
let formatted = ` ${label}: ${lines[0]}\n`;
|
|
388
|
+
for (let i = 1; i < lines.length; i++) {
|
|
389
|
+
formatted += ` ${lines[i]}\n`;
|
|
390
|
+
}
|
|
391
|
+
return formatted;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* format aggregated usage data as a markdown table for the GitHub step summary.
|
|
396
|
+
*
|
|
397
|
+
* columns mirror the per-run stdout token table emitted by `logTokenTable`
|
|
398
|
+
* (Input / Cache Read / Cache Write / Output / Total / Cost ($)) so the job
|
|
399
|
+
* summary and the in-run logs can be compared row-for-row.
|
|
400
|
+
*
|
|
401
|
+
* notes:
|
|
402
|
+
* - `AgentUsage.inputTokens` is the sum of non-cached input + cache read
|
|
403
|
+
* + cache write (set that way by both agent harnesses' `buildUsage`),
|
|
404
|
+
* so the non-cached Input column is recovered by subtracting cache fields.
|
|
405
|
+
* - `costUsd` is sourced from models.dev (OpenCode) or `total_cost_usd`
|
|
406
|
+
* (Claude CLI). absent rows show `—` so per-agent coverage is obvious.
|
|
407
|
+
*/
|
|
408
|
+
export function formatUsageSummary(entries: AgentUsage[]): string {
|
|
409
|
+
if (entries.length === 0) return "";
|
|
410
|
+
|
|
411
|
+
const header = "| Agent | Input | Cache Read | Cache Write | Output | Total | Cost ($) |";
|
|
412
|
+
const separatorRow = "| --- | ---: | ---: | ---: | ---: | ---: | ---: |";
|
|
413
|
+
const fmt = (n: number) => n.toLocaleString("en-US");
|
|
414
|
+
|
|
415
|
+
const nonCachedInput = (e: AgentUsage): number =>
|
|
416
|
+
Math.max(0, e.inputTokens - (e.cacheReadTokens ?? 0) - (e.cacheWriteTokens ?? 0));
|
|
417
|
+
const totalFor = (e: AgentUsage): number =>
|
|
418
|
+
nonCachedInput(e) + (e.cacheReadTokens ?? 0) + (e.cacheWriteTokens ?? 0) + e.outputTokens;
|
|
419
|
+
const costCell = (e: AgentUsage): string =>
|
|
420
|
+
typeof e.costUsd === "number" && e.costUsd > 0 ? formatCostUsd(e.costUsd) : "—";
|
|
421
|
+
|
|
422
|
+
const rows = entries.map(
|
|
423
|
+
(e) =>
|
|
424
|
+
`| ${e.agent} | ${fmt(nonCachedInput(e))} | ${fmt(e.cacheReadTokens ?? 0)} | ${fmt(e.cacheWriteTokens ?? 0)} | ${fmt(e.outputTokens)} | ${fmt(totalFor(e))} | ${costCell(e)} |`,
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const totalsRows: string[] = [];
|
|
428
|
+
if (entries.length > 1) {
|
|
429
|
+
const totalInput = entries.reduce((sum, e) => sum + nonCachedInput(e), 0);
|
|
430
|
+
const totalOutput = entries.reduce((sum, e) => sum + e.outputTokens, 0);
|
|
431
|
+
const totalCacheRead = entries.reduce((sum, e) => sum + (e.cacheReadTokens ?? 0), 0);
|
|
432
|
+
const totalCacheWrite = entries.reduce((sum, e) => sum + (e.cacheWriteTokens ?? 0), 0);
|
|
433
|
+
const grandTotal = totalInput + totalCacheRead + totalCacheWrite + totalOutput;
|
|
434
|
+
const totalCostUsd = entries.reduce((sum, e) => sum + (e.costUsd ?? 0), 0);
|
|
435
|
+
const totalCostCell = totalCostUsd > 0 ? `**${formatCostUsd(totalCostUsd)}**` : "—";
|
|
436
|
+
totalsRows.push(
|
|
437
|
+
`| **Total** | **${fmt(totalInput)}** | **${fmt(totalCacheRead)}** | **${fmt(totalCacheWrite)}** | **${fmt(totalOutput)}** | **${fmt(grandTotal)}** | ${totalCostCell} |`,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return [
|
|
442
|
+
"<details>",
|
|
443
|
+
"<summary>Usage</summary>",
|
|
444
|
+
"",
|
|
445
|
+
header,
|
|
446
|
+
separatorRow,
|
|
447
|
+
...rows,
|
|
448
|
+
...totalsRows,
|
|
449
|
+
"",
|
|
450
|
+
"</details>",
|
|
451
|
+
].join("\n");
|
|
452
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { Agent } from "#app/agents/index";
|
|
2
|
+
import { resolveAgent, resolveModelWithGating } from "#app/utils/agent";
|
|
3
|
+
import { validateAgentApiKey } from "#app/utils/apiKeys";
|
|
4
|
+
import { installCodexAuth } from "#app/utils/codexHome";
|
|
5
|
+
import {
|
|
6
|
+
captureAuthorizedModels,
|
|
7
|
+
captureBaselineModels,
|
|
8
|
+
getAuthorizedModels,
|
|
9
|
+
} from "#app/utils/openCodeModels";
|
|
10
|
+
import { applyManagedProxy, applyModelEnv, type ProxyMint } from "#app/utils/proxyModel";
|
|
11
|
+
import type { AccountPlan } from "#app/utils/runContext";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The single owner of the model decision. "Which model runs, on which harness,
|
|
15
|
+
* with what auth" used to be smeared across main.ts and four utils; the two
|
|
16
|
+
* entry points here are the whole story:
|
|
17
|
+
*
|
|
18
|
+
* 1. {@link captureModelAuthority} — the ordered BYOK-authority capture
|
|
19
|
+
* (baseline → Codex auth.json → authorized set), returned as an explicit
|
|
20
|
+
* value instead of hidden module state the caller must remember to
|
|
21
|
+
* sequence correctly.
|
|
22
|
+
* 2. {@link resolveRunModel} — BYOK gate → managed-proxy overlay → env
|
|
23
|
+
* patch → api-key validation, returning the routed model + harness.
|
|
24
|
+
*
|
|
25
|
+
* The building blocks stay where they are (catalog in models.ts, gate in
|
|
26
|
+
* agent.ts, proxy overlay in proxyModel.ts); this module owns their
|
|
27
|
+
* composition and ordering.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Capture the BYOK model authority in the one order that is correct:
|
|
32
|
+
* the BASELINE set (what OpenCode can route from the runner's pre-existing
|
|
33
|
+
* env alone) must be snapshotted BEFORE Codex auth.json is materialized, and
|
|
34
|
+
* the AUTHORIZED set after — their diff is the Codex credential's
|
|
35
|
+
* contribution, logged by the capture. Returns the authorized set, the
|
|
36
|
+
* authoritative input for {@link resolveRunModel}.
|
|
37
|
+
*/
|
|
38
|
+
export function captureModelAuthority(opencodeCliPath: string): Set<string> {
|
|
39
|
+
captureBaselineModels(opencodeCliPath);
|
|
40
|
+
installCodexAuth();
|
|
41
|
+
captureAuthorizedModels(opencodeCliPath);
|
|
42
|
+
return getAuthorizedModels();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface RoutedRunModel {
|
|
46
|
+
/** the effective model that will run (post-fallback); undefined → auto-select */
|
|
47
|
+
model: string | undefined;
|
|
48
|
+
/** the slug to surface in footers/logs */
|
|
49
|
+
effectiveSlug: string | undefined;
|
|
50
|
+
/** the harness resolved for the effective model */
|
|
51
|
+
agent: Agent;
|
|
52
|
+
/** set only when the free safety-net fallback engaged */
|
|
53
|
+
fallback?: { from: string; to: string };
|
|
54
|
+
/** operator warnings for the caller to log */
|
|
55
|
+
warnings: string[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the model + auth for this run in one call: the BYOK gate (resolve
|
|
60
|
+
* slug → pick harness → free-fallback decision), the managed EU Bedrock proxy
|
|
61
|
+
* overlay (a no-op unless PAYG with no BYO key), the env patch the routing
|
|
62
|
+
* needs, and the api-key validation the gate asks for. Throws the actionable
|
|
63
|
+
* authorized-model list on an unavailable model, a `BillingError` when the
|
|
64
|
+
* managed path needs a payment method, and the missing-key error when
|
|
65
|
+
* validation fails — all before any agent runs.
|
|
66
|
+
*/
|
|
67
|
+
export async function resolveRunModel(input: {
|
|
68
|
+
slug: string | undefined;
|
|
69
|
+
plan: AccountPlan;
|
|
70
|
+
credential: string;
|
|
71
|
+
authorized: Set<string>;
|
|
72
|
+
repo: { owner: string; name: string };
|
|
73
|
+
mint?: ProxyMint;
|
|
74
|
+
}): Promise<RoutedRunModel> {
|
|
75
|
+
const routed = await applyManagedProxy({
|
|
76
|
+
gate: resolveModelWithGating({ slug: input.slug, authorized: input.authorized }),
|
|
77
|
+
plan: input.plan,
|
|
78
|
+
credential: input.credential,
|
|
79
|
+
resolveAgent,
|
|
80
|
+
...(input.slug ? { slug: input.slug } : {}),
|
|
81
|
+
...(input.mint ? { mint: input.mint } : {}),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (routed.envToApply) {
|
|
85
|
+
applyModelEnv(routed.envToApply);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (routed.validate) {
|
|
89
|
+
validateAgentApiKey({
|
|
90
|
+
agent: routed.agent,
|
|
91
|
+
model: routed.model ?? routed.effectiveSlug,
|
|
92
|
+
authorized: input.authorized,
|
|
93
|
+
owner: input.repo.owner,
|
|
94
|
+
name: input.repo.name,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
model: routed.model,
|
|
100
|
+
effectiveSlug: routed.effectiveSlug,
|
|
101
|
+
agent: routed.agent,
|
|
102
|
+
warnings: routed.warnings,
|
|
103
|
+
...(routed.fallback ? { fallback: routed.fallback } : {}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Org-private cross-repo module fetch (the HepCare shape).
|
|
3
|
+
*
|
|
4
|
+
* Referencing a private module from another repo in your org works today
|
|
5
|
+
* (`git::https://github.com/acme/tf-modules.git//aws/s3?ref=…`), but FETCHING it
|
|
6
|
+
* at `terraform init` does not: the action's own git is locked down (ASKPASS,
|
|
7
|
+
* `credential.helper=`) and the job token is single-repo, so terraform's child
|
|
8
|
+
* `git clone` of the module repo has no credential. This module supplies a
|
|
9
|
+
* scoped one — a PAT / GitHub App token / fine-grained token the operator passes
|
|
10
|
+
* as `module_fetch_token`.
|
|
11
|
+
*
|
|
12
|
+
* Mechanism: Git's `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_n` / `GIT_CONFIG_VALUE_n`
|
|
13
|
+
* env injection (Git ≥ 2.31). We add an `http.https://<host>/.extraheader`
|
|
14
|
+
* carrying a Basic auth header (the same pattern actions/checkout uses), scoped
|
|
15
|
+
* to the terraform subprocess only — no global/file config is mutated and the
|
|
16
|
+
* token never lands on disk.
|
|
17
|
+
*
|
|
18
|
+
* SSH / deploy-key sources (`git::ssh://…` / `git::git@host:…`) are a separate
|
|
19
|
+
* transport: `module_fetch_ssh_key` supplies a private key, which — unlike the
|
|
20
|
+
* token — MUST exist as a file for `ssh -i`. We write it 0600 into the run's
|
|
21
|
+
* tmpdir (wiped at run end), never the home dir or a committed path, and point a
|
|
22
|
+
* scoped `GIT_SSH_COMMAND` at it. Both credentials can apply in one run (HTTPS
|
|
23
|
+
* token for `git::https`, SSH key for `git::ssh`); they're independent env.
|
|
24
|
+
*/
|
|
25
|
+
import { chmodSync, writeFileSync } from "node:fs";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
|
|
28
|
+
/** the `x-access-token:<token>` Basic header value Git sends per request. */
|
|
29
|
+
function basicAuthHeader(token: string): string {
|
|
30
|
+
const encoded = Buffer.from(`x-access-token:${token}`).toString("base64");
|
|
31
|
+
return `Authorization: Basic ${encoded}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build the `GIT_CONFIG_*` env that authorises `git clone` of a private module
|
|
36
|
+
* over HTTPS for each host. Pure (token + hosts in, env out) so it is unit-
|
|
37
|
+
* testable without a real git. Empty/whitespace hosts are dropped; hosts are
|
|
38
|
+
* de-duplicated case-insensitively. Returns an empty object only when no usable
|
|
39
|
+
* host remains (the caller treats that as "no module-fetch credential").
|
|
40
|
+
*/
|
|
41
|
+
export function buildModuleFetchGitEnv(token: string, hosts: string[]): Record<string, string> {
|
|
42
|
+
const seen = new Set<string>();
|
|
43
|
+
const uniqueHosts: string[] = [];
|
|
44
|
+
for (const h of hosts) {
|
|
45
|
+
const host = h.trim().toLowerCase();
|
|
46
|
+
if (!host || seen.has(host)) continue;
|
|
47
|
+
seen.add(host);
|
|
48
|
+
uniqueHosts.push(host);
|
|
49
|
+
}
|
|
50
|
+
if (uniqueHosts.length === 0) return {};
|
|
51
|
+
|
|
52
|
+
const header = basicAuthHeader(token);
|
|
53
|
+
const env: Record<string, string> = { GIT_CONFIG_COUNT: String(uniqueHosts.length) };
|
|
54
|
+
uniqueHosts.forEach((host, i) => {
|
|
55
|
+
env[`GIT_CONFIG_KEY_${i}`] = `http.https://${host}/.extraheader`;
|
|
56
|
+
env[`GIT_CONFIG_VALUE_${i}`] = header;
|
|
57
|
+
});
|
|
58
|
+
return env;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The hosts a module-fetch credential should authorise: always github.com, plus
|
|
63
|
+
* the GitHub host the run executes against (a GitHub Enterprise Server instance
|
|
64
|
+
* via `GITHUB_SERVER_URL`) when it differs. Reads the env; pure given it.
|
|
65
|
+
*/
|
|
66
|
+
export function moduleFetchHosts(serverUrl = process.env.GITHUB_SERVER_URL): string[] {
|
|
67
|
+
const hosts = ["github.com"];
|
|
68
|
+
if (serverUrl) {
|
|
69
|
+
try {
|
|
70
|
+
const host = new URL(serverUrl).hostname;
|
|
71
|
+
// de-dupe case-insensitively: on github.com-hosted runs GITHUB_SERVER_URL
|
|
72
|
+
// is https://github.com, so the seeded host would otherwise repeat.
|
|
73
|
+
if (host && !hosts.some((h) => h.toLowerCase() === host.toLowerCase())) hosts.push(host);
|
|
74
|
+
} catch {
|
|
75
|
+
/* malformed GITHUB_SERVER_URL — fall back to github.com only */
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return hosts;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function defaultWriteKey(path: string, contents: string): void {
|
|
82
|
+
// mode on writeFileSync is honoured on POSIX (the GitHub Actions runner); the
|
|
83
|
+
// explicit chmod is belt-and-suspenders for an existing-file overwrite + Windows
|
|
84
|
+
// local dev (where ssh applies its own perms model).
|
|
85
|
+
writeFileSync(path, contents, { mode: 0o600 });
|
|
86
|
+
try {
|
|
87
|
+
chmodSync(path, 0o600);
|
|
88
|
+
} catch {
|
|
89
|
+
/* best-effort — ssh still refuses a world-readable key on POSIX */
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Build the SSH env for fetching a private `git::ssh://…` module. The key MUST be
|
|
95
|
+
* a file for `ssh -i`, so it is written 0600 into `keyDir` (the run's tmpdir,
|
|
96
|
+
* wiped at run end) — never the home dir, never committed. `IdentitiesOnly=yes`
|
|
97
|
+
* stops ssh falling back to an agent or other keys; `StrictHostKeyChecking=accept-new`
|
|
98
|
+
* trusts the host on first use rather than the interactive prompt that would hang a
|
|
99
|
+
* headless run. Pure given an injected writer (so it is unit-testable without fs).
|
|
100
|
+
* Returns `{}` for a blank key.
|
|
101
|
+
*/
|
|
102
|
+
export function buildModuleFetchSshEnv(
|
|
103
|
+
sshKey: string,
|
|
104
|
+
keyDir: string,
|
|
105
|
+
writeKey: (path: string, contents: string) => void = defaultWriteKey,
|
|
106
|
+
): Record<string, string> {
|
|
107
|
+
const key = sshKey.trim();
|
|
108
|
+
if (!key) return {};
|
|
109
|
+
const keyPath = join(keyDir, "module_fetch_key");
|
|
110
|
+
// ssh rejects a key without a trailing newline.
|
|
111
|
+
writeKey(keyPath, key.endsWith("\n") ? key : `${key}\n`);
|
|
112
|
+
const sshPath = keyPath.replace(/\\/g, "/"); // GIT_SSH_COMMAND is shell-parsed
|
|
113
|
+
return {
|
|
114
|
+
GIT_SSH_COMMAND: `ssh -i "${sshPath}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Resolve the module-fetch git env for a run, or undefined when neither a
|
|
120
|
+
* `module_fetch_token` (HTTPS) nor a `module_fetch_ssh_key` (SSH) was supplied
|
|
121
|
+
* (the common case — public/registry/local modules need no credential). The result
|
|
122
|
+
* is merged into the env of the `terraform init`/`plan` invocations so private
|
|
123
|
+
* cross-repo modules resolve. SSH activates only when `opts.sshKeyDir` is given (a
|
|
124
|
+
* writable scratch dir for the ephemeral key — the run's tmpdir at the real sites).
|
|
125
|
+
*/
|
|
126
|
+
export function resolveModuleFetchEnv(
|
|
127
|
+
payload: { moduleFetchToken?: string | undefined; moduleFetchSshKey?: string | undefined },
|
|
128
|
+
opts: { sshKeyDir?: string; writeKey?: (path: string, contents: string) => void } = {},
|
|
129
|
+
): Record<string, string> | undefined {
|
|
130
|
+
const env: Record<string, string> = {};
|
|
131
|
+
const token = payload.moduleFetchToken?.trim();
|
|
132
|
+
if (token) Object.assign(env, buildModuleFetchGitEnv(token, moduleFetchHosts()));
|
|
133
|
+
const sshKey = payload.moduleFetchSshKey?.trim();
|
|
134
|
+
if (sshKey && opts.sshKeyDir) {
|
|
135
|
+
Object.assign(env, buildModuleFetchSshEnv(sshKey, opts.sshKeyDir, opts.writeKey));
|
|
136
|
+
}
|
|
137
|
+
return Object.keys(env).length > 0 ? env : undefined;
|
|
138
|
+
}
|