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.
Files changed (524) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +244 -0
  3. package/dist/agents/claude.d.ts +113 -0
  4. package/dist/agents/claudePretoolGate.d.ts +137 -0
  5. package/dist/agents/dispatchMetrics.d.ts +77 -0
  6. package/dist/agents/gateServer.d.ts +7 -0
  7. package/dist/agents/index.d.ts +6 -0
  8. package/dist/agents/nativeFsDenies.d.ts +46 -0
  9. package/dist/agents/opencode.d.ts +284 -0
  10. package/dist/agents/opencodePlugin.d.ts +96 -0
  11. package/dist/agents/opencodeShared.d.ts +40 -0
  12. package/dist/agents/postRun.d.ts +126 -0
  13. package/dist/agents/reviewer.d.ts +41 -0
  14. package/dist/agents/sessionLabeler.d.ts +97 -0
  15. package/dist/agents/shared.d.ts +246 -0
  16. package/dist/agents/subagentModels.d.ts +19 -0
  17. package/dist/agents/tokenQuota.d.ts +118 -0
  18. package/dist/agents/writeGateSource.d.ts +22 -0
  19. package/dist/agents/writePolicy.d.ts +79 -0
  20. package/dist/brand.d.ts +67 -0
  21. package/dist/cli.mjs +247846 -0
  22. package/dist/external.d.ts +227 -0
  23. package/dist/i18n/scaffolding.d.ts +59 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.js +247061 -0
  26. package/dist/internal/index.d.ts +18 -0
  27. package/dist/internal.js +2398 -0
  28. package/dist/lifecycle.d.ts +2 -0
  29. package/dist/main.d.ts +8 -0
  30. package/dist/mcp/arkConfig.d.ts +1 -0
  31. package/dist/mcp/assess.d.ts +157 -0
  32. package/dist/mcp/capabilityContext.d.ts +71 -0
  33. package/dist/mcp/changeSummary.d.ts +52 -0
  34. package/dist/mcp/checkSuite.d.ts +27 -0
  35. package/dist/mcp/checkout.d.ts +92 -0
  36. package/dist/mcp/comment.d.ts +127 -0
  37. package/dist/mcp/commitInfo.d.ts +11 -0
  38. package/dist/mcp/crosswalk.d.ts +178 -0
  39. package/dist/mcp/crosswalkDigest.d.ts +1 -0
  40. package/dist/mcp/cyberEssentials.d.ts +24 -0
  41. package/dist/mcp/dashboard.d.ts +125 -0
  42. package/dist/mcp/dependencies.d.ts +12 -0
  43. package/dist/mcp/frameworks.d.ts +74 -0
  44. package/dist/mcp/geminiSanitizer.d.ts +28 -0
  45. package/dist/mcp/git.d.ts +60 -0
  46. package/dist/mcp/guardrails.d.ts +222 -0
  47. package/dist/mcp/issue.d.ts +20 -0
  48. package/dist/mcp/issueComments.d.ts +11 -0
  49. package/dist/mcp/issueEvents.d.ts +11 -0
  50. package/dist/mcp/issueInfo.d.ts +11 -0
  51. package/dist/mcp/labels.d.ts +14 -0
  52. package/dist/mcp/localContext.d.ts +26 -0
  53. package/dist/mcp/moduleExtraction.d.ts +79 -0
  54. package/dist/mcp/moduleTests.d.ts +106 -0
  55. package/dist/mcp/modules.d.ts +198 -0
  56. package/dist/mcp/output.d.ts +16 -0
  57. package/dist/mcp/pathSafety.d.ts +14 -0
  58. package/dist/mcp/policy.d.ts +50 -0
  59. package/dist/mcp/pr.d.ts +64 -0
  60. package/dist/mcp/prInfo.d.ts +11 -0
  61. package/dist/mcp/providerSchema.d.ts +52 -0
  62. package/dist/mcp/review.d.ts +212 -0
  63. package/dist/mcp/reviewComments.d.ts +245 -0
  64. package/dist/mcp/roots.d.ts +60 -0
  65. package/dist/mcp/scope.d.ts +26 -0
  66. package/dist/mcp/selectMode.d.ts +20 -0
  67. package/dist/mcp/server.d.ts +61 -0
  68. package/dist/mcp/shared.d.ts +62 -0
  69. package/dist/mcp/shell.d.ts +58 -0
  70. package/dist/mcp/staleFix.d.ts +138 -0
  71. package/dist/mcp/terraform/azurePrices.d.ts +8 -0
  72. package/dist/mcp/terraform/baseline.d.ts +57 -0
  73. package/dist/mcp/terraform/concernResult.d.ts +38 -0
  74. package/dist/mcp/terraform/cost.d.ts +55 -0
  75. package/dist/mcp/terraform/cspm.d.ts +80 -0
  76. package/dist/mcp/terraform/currency.d.ts +110 -0
  77. package/dist/mcp/terraform/decisions.d.ts +178 -0
  78. package/dist/mcp/terraform/eidas.d.ts +100 -0
  79. package/dist/mcp/terraform/evidence.d.ts +343 -0
  80. package/dist/mcp/terraform/findings.d.ts +76 -0
  81. package/dist/mcp/terraform/fixMemory.d.ts +81 -0
  82. package/dist/mcp/terraform/governance.d.ts +56 -0
  83. package/dist/mcp/terraform/hcl.d.ts +115 -0
  84. package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
  85. package/dist/mcp/terraform/idleFloor.d.ts +78 -0
  86. package/dist/mcp/terraform/keyless.d.ts +68 -0
  87. package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
  88. package/dist/mcp/terraform/nativeRules.d.ts +38 -0
  89. package/dist/mcp/terraform/nativeScan.d.ts +11 -0
  90. package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
  91. package/dist/mcp/terraform/normalization.d.ts +52 -0
  92. package/dist/mcp/terraform/oscal.d.ts +103 -0
  93. package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
  94. package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
  95. package/dist/mcp/terraform/paths.d.ts +28 -0
  96. package/dist/mcp/terraform/plan.d.ts +157 -0
  97. package/dist/mcp/terraform/planDrift.d.ts +199 -0
  98. package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
  99. package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
  100. package/dist/mcp/terraform/refactor.d.ts +183 -0
  101. package/dist/mcp/terraform/registry.d.ts +108 -0
  102. package/dist/mcp/terraform/risk.d.ts +41 -0
  103. package/dist/mcp/terraform/scanSession.d.ts +116 -0
  104. package/dist/mcp/terraform/scannerCache.d.ts +15 -0
  105. package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
  106. package/dist/mcp/terraform/scannerJson.d.ts +13 -0
  107. package/dist/mcp/terraform/scanners.d.ts +205 -0
  108. package/dist/mcp/terraform/signing.d.ts +61 -0
  109. package/dist/mcp/terraform/stateLocking.d.ts +18 -0
  110. package/dist/mcp/terraform/subprocess.d.ts +43 -0
  111. package/dist/mcp/terraform/suppressions.d.ts +90 -0
  112. package/dist/mcp/terraform/taxonomy.d.ts +39 -0
  113. package/dist/mcp/terraform/tfquery.d.ts +47 -0
  114. package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
  115. package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
  116. package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
  117. package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
  118. package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
  119. package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
  120. package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
  121. package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
  122. package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
  123. package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
  124. package/dist/mcp/terraform/tools/plan.d.ts +59 -0
  125. package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
  126. package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
  127. package/dist/mcp/terraform/tools/scan.d.ts +114 -0
  128. package/dist/mcp/terraform/tools/validate.d.ts +31 -0
  129. package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
  130. package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
  131. package/dist/mcp/terraform/tools.d.ts +16 -0
  132. package/dist/mcp/terraform/transformPacks.d.ts +267 -0
  133. package/dist/mcp/terraform/types.d.ts +226 -0
  134. package/dist/mcp/terraform/verification.d.ts +81 -0
  135. package/dist/mcp/terraform/vex.d.ts +115 -0
  136. package/dist/mcp/terraform/writeOnly.d.ts +67 -0
  137. package/dist/mcp/terraform.d.ts +51 -0
  138. package/dist/mcp/terratest.d.ts +85 -0
  139. package/dist/mcp/untrustedContent.d.ts +76 -0
  140. package/dist/mcp/upload.d.ts +8 -0
  141. package/dist/models.d.ts +181 -0
  142. package/dist/modes/address-reviews.d.ts +2 -0
  143. package/dist/modes/assess.d.ts +2 -0
  144. package/dist/modes/build.d.ts +2 -0
  145. package/dist/modes/compliance-audit.d.ts +2 -0
  146. package/dist/modes/cost-optimization.d.ts +2 -0
  147. package/dist/modes/drift-detect.d.ts +2 -0
  148. package/dist/modes/fix.d.ts +2 -0
  149. package/dist/modes/incremental-review.d.ts +2 -0
  150. package/dist/modes/index.d.ts +24 -0
  151. package/dist/modes/modernize-deprecated.d.ts +2 -0
  152. package/dist/modes/plan.d.ts +2 -0
  153. package/dist/modes/policy-gate.d.ts +2 -0
  154. package/dist/modes/prFormats.d.ts +3 -0
  155. package/dist/modes/refactor.d.ts +2 -0
  156. package/dist/modes/refresh-remediation.d.ts +2 -0
  157. package/dist/modes/remediate-and-refactor.d.ts +2 -0
  158. package/dist/modes/remediate.d.ts +2 -0
  159. package/dist/modes/resolve-conflicts.d.ts +2 -0
  160. package/dist/modes/review.d.ts +2 -0
  161. package/dist/modes/summarize-pr.d.ts +2 -0
  162. package/dist/modes/task.d.ts +2 -0
  163. package/dist/modes/terraform-code-review.d.ts +2 -0
  164. package/dist/modes/types.d.ts +9 -0
  165. package/dist/modes/update-dependencies.d.ts +2 -0
  166. package/dist/prep/index.d.ts +7 -0
  167. package/dist/prep/installNodeDependencies.d.ts +2 -0
  168. package/dist/prep/installPythonDependencies.d.ts +2 -0
  169. package/dist/prep/types.d.ts +31 -0
  170. package/dist/reviewQuality.d.ts +107 -0
  171. package/dist/skills/terraform-best-practices/SKILL.md +379 -0
  172. package/dist/toolState.d.ts +123 -0
  173. package/dist/utils/activity.d.ts +40 -0
  174. package/dist/utils/agent.d.ts +47 -0
  175. package/dist/utils/agentHangReport.d.ts +38 -0
  176. package/dist/utils/annotations.d.ts +17 -0
  177. package/dist/utils/apiFetch.d.ts +11 -0
  178. package/dist/utils/apiKeys.d.ts +48 -0
  179. package/dist/utils/apiUrl.d.ts +28 -0
  180. package/dist/utils/assets.d.ts +8 -0
  181. package/dist/utils/baseRefConfig.d.ts +121 -0
  182. package/dist/utils/billingErrors.d.ts +85 -0
  183. package/dist/utils/body.d.ts +34 -0
  184. package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
  185. package/dist/utils/byokFallback.d.ts +85 -0
  186. package/dist/utils/changeImpact.d.ts +101 -0
  187. package/dist/utils/claudeSubscription.d.ts +30 -0
  188. package/dist/utils/cli.d.ts +10 -0
  189. package/dist/utils/cloudClient.d.ts +33 -0
  190. package/dist/utils/cloudFetchCore.d.ts +42 -0
  191. package/dist/utils/cloudReport.d.ts +114 -0
  192. package/dist/utils/codexHome.d.ts +29 -0
  193. package/dist/utils/codexOAuth.d.ts +60 -0
  194. package/dist/utils/diffCoverage.d.ts +63 -0
  195. package/dist/utils/env.d.ts +46 -0
  196. package/dist/utils/errorReport.d.ts +17 -0
  197. package/dist/utils/exitHandler.d.ts +8 -0
  198. package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
  199. package/dist/utils/gitAuth.d.ts +84 -0
  200. package/dist/utils/gitAuthServer.d.ts +24 -0
  201. package/dist/utils/github.d.ts +104 -0
  202. package/dist/utils/globals.d.ts +3 -0
  203. package/dist/utils/infraweaverConfig.d.ts +56 -0
  204. package/dist/utils/install.d.ts +37 -0
  205. package/dist/utils/instructions.d.ts +48 -0
  206. package/dist/utils/keylessOidc.d.ts +28 -0
  207. package/dist/utils/leapingComment.d.ts +11 -0
  208. package/dist/utils/learnings.d.ts +62 -0
  209. package/dist/utils/learningsTruncate.d.ts +25 -0
  210. package/dist/utils/lifecycle.d.ts +57 -0
  211. package/dist/utils/log.d.ts +111 -0
  212. package/dist/utils/modelResolver.d.ts +63 -0
  213. package/dist/utils/moduleFetch.d.ts +39 -0
  214. package/dist/utils/normalizeEnv.d.ts +30 -0
  215. package/dist/utils/openCodeModels.d.ts +11 -0
  216. package/dist/utils/openaiCompatible.d.ts +26 -0
  217. package/dist/utils/opentofuMcp.d.ts +50 -0
  218. package/dist/utils/overrides.d.ts +40 -0
  219. package/dist/utils/packageManager.d.ts +49 -0
  220. package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
  221. package/dist/utils/payload.d.ts +249 -0
  222. package/dist/utils/prSummary.d.ts +61 -0
  223. package/dist/utils/presets.d.ts +36 -0
  224. package/dist/utils/progressComment.d.ts +146 -0
  225. package/dist/utils/providerErrors.d.ts +31 -0
  226. package/dist/utils/proxyModel.d.ts +76 -0
  227. package/dist/utils/rangeDiff.d.ts +51 -0
  228. package/dist/utils/redact.d.ts +33 -0
  229. package/dist/utils/registryAuth.d.ts +52 -0
  230. package/dist/utils/remediationCommand.d.ts +58 -0
  231. package/dist/utils/retry.d.ts +38 -0
  232. package/dist/utils/reviewCleanup.d.ts +14 -0
  233. package/dist/utils/run.d.ts +9 -0
  234. package/dist/utils/runContext.d.ts +112 -0
  235. package/dist/utils/runContextData.d.ts +42 -0
  236. package/dist/utils/runErrorRenderer.d.ts +64 -0
  237. package/dist/utils/runLifecycle.d.ts +89 -0
  238. package/dist/utils/runStartupLog.d.ts +15 -0
  239. package/dist/utils/secrets.d.ts +34 -0
  240. package/dist/utils/setup.d.ts +90 -0
  241. package/dist/utils/shell.d.ts +44 -0
  242. package/dist/utils/skills.d.ts +10 -0
  243. package/dist/utils/subprocess.d.ts +81 -0
  244. package/dist/utils/terraformMcp.d.ts +46 -0
  245. package/dist/utils/time.d.ts +15 -0
  246. package/dist/utils/timer.d.ts +23 -0
  247. package/dist/utils/todoTracking.d.ts +16 -0
  248. package/dist/utils/token.d.ts +52 -0
  249. package/dist/utils/toolLicensing.d.ts +56 -0
  250. package/dist/utils/toolSelection.d.ts +73 -0
  251. package/dist/utils/toon.d.ts +16 -0
  252. package/dist/utils/version.d.ts +2 -0
  253. package/dist/utils/versioning.d.ts +7 -0
  254. package/dist/utils/vertex.d.ts +16 -0
  255. package/dist/utils/workflow.d.ts +13 -0
  256. package/package.json +132 -0
  257. package/src/agents/claude.ts +1588 -0
  258. package/src/agents/claudePretoolGate.ts +286 -0
  259. package/src/agents/dispatchMetrics.ts +162 -0
  260. package/src/agents/gateServer.ts +178 -0
  261. package/src/agents/index.ts +10 -0
  262. package/src/agents/nativeFsDenies.ts +164 -0
  263. package/src/agents/opencode.ts +1600 -0
  264. package/src/agents/opencodePlugin.ts +304 -0
  265. package/src/agents/opencodeShared.ts +134 -0
  266. package/src/agents/postRun.ts +615 -0
  267. package/src/agents/reviewer.ts +134 -0
  268. package/src/agents/sessionLabeler.ts +185 -0
  269. package/src/agents/shared.ts +377 -0
  270. package/src/agents/subagentModels.ts +40 -0
  271. package/src/agents/tokenQuota.ts +203 -0
  272. package/src/agents/writeGateSource.ts +148 -0
  273. package/src/agents/writePolicy.ts +132 -0
  274. package/src/brand.ts +84 -0
  275. package/src/cli.ts +117 -0
  276. package/src/commands/gha.ts +188 -0
  277. package/src/commands/mcp.ts +126 -0
  278. package/src/commands/verifyEvidence.ts +100 -0
  279. package/src/entry.ts +7 -0
  280. package/src/entryPost.ts +109 -0
  281. package/src/external.ts +308 -0
  282. package/src/i18n/scaffolding.ts +191 -0
  283. package/src/index.ts +7 -0
  284. package/src/internal/index.ts +74 -0
  285. package/src/lifecycle.ts +2 -0
  286. package/src/main.ts +815 -0
  287. package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
  288. package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
  289. package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
  290. package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
  291. package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
  292. package/src/mcp/arkConfig.ts +7 -0
  293. package/src/mcp/assess.ts +723 -0
  294. package/src/mcp/capabilityContext.ts +80 -0
  295. package/src/mcp/changeSummary.ts +145 -0
  296. package/src/mcp/checkSuite.ts +261 -0
  297. package/src/mcp/checkout.ts +1015 -0
  298. package/src/mcp/comment.ts +683 -0
  299. package/src/mcp/commitInfo.ts +57 -0
  300. package/src/mcp/crosswalk.ts +1253 -0
  301. package/src/mcp/crosswalkDigest.ts +5 -0
  302. package/src/mcp/cyberEssentials.ts +60 -0
  303. package/src/mcp/dashboard.ts +232 -0
  304. package/src/mcp/dependencies.ts +190 -0
  305. package/src/mcp/frameworks.ts +236 -0
  306. package/src/mcp/geminiSanitizer.ts +212 -0
  307. package/src/mcp/git.ts +1116 -0
  308. package/src/mcp/guardrails.ts +771 -0
  309. package/src/mcp/issue.ts +74 -0
  310. package/src/mcp/issueComments.ts +48 -0
  311. package/src/mcp/issueEvents.ts +100 -0
  312. package/src/mcp/issueInfo.ts +72 -0
  313. package/src/mcp/labels.ts +35 -0
  314. package/src/mcp/localContext.ts +65 -0
  315. package/src/mcp/localServer.ts +217 -0
  316. package/src/mcp/moduleExtraction.ts +368 -0
  317. package/src/mcp/moduleTests.ts +421 -0
  318. package/src/mcp/modules.ts +752 -0
  319. package/src/mcp/output.ts +71 -0
  320. package/src/mcp/pathSafety.ts +28 -0
  321. package/src/mcp/policy.ts +226 -0
  322. package/src/mcp/pr.ts +238 -0
  323. package/src/mcp/prInfo.ts +91 -0
  324. package/src/mcp/providerSchema.ts +175 -0
  325. package/src/mcp/review.ts +1081 -0
  326. package/src/mcp/reviewComments.ts +1137 -0
  327. package/src/mcp/roots.ts +217 -0
  328. package/src/mcp/scope.ts +82 -0
  329. package/src/mcp/selectMode.ts +207 -0
  330. package/src/mcp/server.ts +498 -0
  331. package/src/mcp/shared.ts +120 -0
  332. package/src/mcp/shell.ts +631 -0
  333. package/src/mcp/staleFix.ts +557 -0
  334. package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
  335. package/src/mcp/terraform/azurePrices.ts +38 -0
  336. package/src/mcp/terraform/baseline.ts +172 -0
  337. package/src/mcp/terraform/concernResult.ts +111 -0
  338. package/src/mcp/terraform/cost.ts +175 -0
  339. package/src/mcp/terraform/cspm.ts +326 -0
  340. package/src/mcp/terraform/currency.ts +354 -0
  341. package/src/mcp/terraform/decisions.ts +590 -0
  342. package/src/mcp/terraform/eidas.ts +134 -0
  343. package/src/mcp/terraform/evidence.ts +771 -0
  344. package/src/mcp/terraform/findings.ts +383 -0
  345. package/src/mcp/terraform/fixMemory.ts +253 -0
  346. package/src/mcp/terraform/governance.ts +231 -0
  347. package/src/mcp/terraform/hcl.ts +273 -0
  348. package/src/mcp/terraform/iacLanguages.ts +431 -0
  349. package/src/mcp/terraform/idleFloor.ts +304 -0
  350. package/src/mcp/terraform/keyless.ts +123 -0
  351. package/src/mcp/terraform/moduleDocs.ts +303 -0
  352. package/src/mcp/terraform/nativeRules.ts +152 -0
  353. package/src/mcp/terraform/nativeScan.ts +67 -0
  354. package/src/mcp/terraform/noiseProfile.ts +183 -0
  355. package/src/mcp/terraform/normalization.ts +265 -0
  356. package/src/mcp/terraform/oscal.ts +283 -0
  357. package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
  358. package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
  359. package/src/mcp/terraform/paths.ts +59 -0
  360. package/src/mcp/terraform/plan.ts +377 -0
  361. package/src/mcp/terraform/planDrift.ts +520 -0
  362. package/src/mcp/terraform/policyAuthor.ts +886 -0
  363. package/src/mcp/terraform/prowlerOcsf.ts +380 -0
  364. package/src/mcp/terraform/refactor.ts +879 -0
  365. package/src/mcp/terraform/registry.ts +317 -0
  366. package/src/mcp/terraform/risk.ts +99 -0
  367. package/src/mcp/terraform/scanSession.ts +242 -0
  368. package/src/mcp/terraform/scannerCache.ts +86 -0
  369. package/src/mcp/terraform/scannerEgress.ts +141 -0
  370. package/src/mcp/terraform/scannerJson.ts +22 -0
  371. package/src/mcp/terraform/scanners.ts +1134 -0
  372. package/src/mcp/terraform/signing.ts +151 -0
  373. package/src/mcp/terraform/stateLocking.ts +106 -0
  374. package/src/mcp/terraform/subprocess.ts +102 -0
  375. package/src/mcp/terraform/suppressions.ts +551 -0
  376. package/src/mcp/terraform/taxonomy.ts +0 -0
  377. package/src/mcp/terraform/tfquery.ts +159 -0
  378. package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
  379. package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
  380. package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
  381. package/src/mcp/terraform/tools/emitCost.ts +130 -0
  382. package/src/mcp/terraform/tools/emitSarif.ts +108 -0
  383. package/src/mcp/terraform/tools/fixMemory.ts +82 -0
  384. package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
  385. package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
  386. package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
  387. package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
  388. package/src/mcp/terraform/tools/plan.ts +384 -0
  389. package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
  390. package/src/mcp/terraform/tools/readFindings.ts +138 -0
  391. package/src/mcp/terraform/tools/scan.ts +303 -0
  392. package/src/mcp/terraform/tools/validate.ts +160 -0
  393. package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
  394. package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
  395. package/src/mcp/terraform/tools.ts +62 -0
  396. package/src/mcp/terraform/transformPacks.ts +594 -0
  397. package/src/mcp/terraform/types.ts +382 -0
  398. package/src/mcp/terraform/verification.ts +150 -0
  399. package/src/mcp/terraform/vex.ts +367 -0
  400. package/src/mcp/terraform/writeOnly.ts +252 -0
  401. package/src/mcp/terraform.ts +52 -0
  402. package/src/mcp/terratest.ts +215 -0
  403. package/src/mcp/untrustedContent.ts +126 -0
  404. package/src/mcp/upload.ts +123 -0
  405. package/src/models.ts +753 -0
  406. package/src/modes/address-reviews.ts +35 -0
  407. package/src/modes/assess.ts +27 -0
  408. package/src/modes/build.ts +86 -0
  409. package/src/modes/compliance-audit.ts +25 -0
  410. package/src/modes/cost-optimization.ts +36 -0
  411. package/src/modes/drift-detect.ts +31 -0
  412. package/src/modes/fix.ts +29 -0
  413. package/src/modes/incremental-review.ts +103 -0
  414. package/src/modes/index.ts +94 -0
  415. package/src/modes/modernize-deprecated.ts +36 -0
  416. package/src/modes/plan.ts +21 -0
  417. package/src/modes/policy-gate.ts +27 -0
  418. package/src/modes/prFormats.ts +325 -0
  419. package/src/modes/refactor.ts +74 -0
  420. package/src/modes/refresh-remediation.ts +40 -0
  421. package/src/modes/remediate-and-refactor.ts +42 -0
  422. package/src/modes/remediate.ts +78 -0
  423. package/src/modes/resolve-conflicts.ts +32 -0
  424. package/src/modes/review.ts +135 -0
  425. package/src/modes/summarize-pr.ts +42 -0
  426. package/src/modes/task.ts +26 -0
  427. package/src/modes/terraform-code-review.ts +68 -0
  428. package/src/modes/types.ts +17 -0
  429. package/src/modes/update-dependencies.ts +44 -0
  430. package/src/prep/index.ts +96 -0
  431. package/src/prep/installNodeDependencies.ts +251 -0
  432. package/src/prep/installPythonDependencies.ts +235 -0
  433. package/src/prep/types.ts +38 -0
  434. package/src/reviewQuality.ts +237 -0
  435. package/src/runCli.ts +335 -0
  436. package/src/skills/terraform-best-practices/SKILL.md +379 -0
  437. package/src/toolState.ts +241 -0
  438. package/src/utils/activity.ts +210 -0
  439. package/src/utils/agent.ts +245 -0
  440. package/src/utils/agentHangReport.ts +180 -0
  441. package/src/utils/annotations.ts +56 -0
  442. package/src/utils/apiFetch.ts +19 -0
  443. package/src/utils/apiKeys.ts +305 -0
  444. package/src/utils/apiUrl.ts +42 -0
  445. package/src/utils/assets.ts +123 -0
  446. package/src/utils/baseRefConfig.ts +254 -0
  447. package/src/utils/billingErrors.ts +210 -0
  448. package/src/utils/body.ts +168 -0
  449. package/src/utils/buildInfraweaverFooter.ts +104 -0
  450. package/src/utils/byokFallback.ts +137 -0
  451. package/src/utils/changeImpact.ts +330 -0
  452. package/src/utils/claudeSubscription.ts +93 -0
  453. package/src/utils/cli.ts +36 -0
  454. package/src/utils/cloudClient.ts +57 -0
  455. package/src/utils/cloudFetchCore.ts +139 -0
  456. package/src/utils/cloudReport.ts +316 -0
  457. package/src/utils/codexHome.ts +204 -0
  458. package/src/utils/codexOAuth.ts +154 -0
  459. package/src/utils/codexRefreshDetect.ts +36 -0
  460. package/src/utils/diffCoverage.ts +404 -0
  461. package/src/utils/env.ts +84 -0
  462. package/src/utils/errorReport.ts +94 -0
  463. package/src/utils/exitHandler.ts +35 -0
  464. package/src/utils/fixDoubleEscapedString.ts +9 -0
  465. package/src/utils/ghaCore.ts +13 -0
  466. package/src/utils/gitAuth.ts +268 -0
  467. package/src/utils/gitAuthServer.ts +186 -0
  468. package/src/utils/github.ts +676 -0
  469. package/src/utils/globals.ts +9 -0
  470. package/src/utils/humanEditCapture.ts +198 -0
  471. package/src/utils/infraweaverConfig.ts +202 -0
  472. package/src/utils/install.ts +279 -0
  473. package/src/utils/instructions.ts +640 -0
  474. package/src/utils/keylessOidc.ts +47 -0
  475. package/src/utils/leapingComment.ts +20 -0
  476. package/src/utils/learnings.ts +145 -0
  477. package/src/utils/learningsTruncate.ts +42 -0
  478. package/src/utils/lifecycle.ts +198 -0
  479. package/src/utils/log.ts +452 -0
  480. package/src/utils/modelResolver.ts +105 -0
  481. package/src/utils/moduleFetch.ts +138 -0
  482. package/src/utils/normalizeEnv.ts +106 -0
  483. package/src/utils/openCodeModels.ts +86 -0
  484. package/src/utils/openaiCompatible.ts +52 -0
  485. package/src/utils/opentofuMcp.ts +61 -0
  486. package/src/utils/overrides.ts +100 -0
  487. package/src/utils/packageManager.ts +257 -0
  488. package/src/utils/patchWorkflowRunFields.ts +173 -0
  489. package/src/utils/payload.ts +1206 -0
  490. package/src/utils/prSummary.ts +148 -0
  491. package/src/utils/presets.ts +105 -0
  492. package/src/utils/progressComment.ts +266 -0
  493. package/src/utils/providerErrors.ts +189 -0
  494. package/src/utils/proxyModel.ts +239 -0
  495. package/src/utils/rangeDiff.ts +182 -0
  496. package/src/utils/redact.ts +86 -0
  497. package/src/utils/registryAuth.ts +115 -0
  498. package/src/utils/remediationCommand.ts +144 -0
  499. package/src/utils/retry.ts +180 -0
  500. package/src/utils/reviewCleanup.ts +116 -0
  501. package/src/utils/run.ts +100 -0
  502. package/src/utils/runContext.ts +276 -0
  503. package/src/utils/runContextData.ts +121 -0
  504. package/src/utils/runErrorRenderer.ts +282 -0
  505. package/src/utils/runFixture.ts +91 -0
  506. package/src/utils/runLifecycle.ts +360 -0
  507. package/src/utils/runStartupLog.ts +67 -0
  508. package/src/utils/secrets.ts +208 -0
  509. package/src/utils/setup.ts +368 -0
  510. package/src/utils/shell.ts +132 -0
  511. package/src/utils/skills.ts +67 -0
  512. package/src/utils/subprocess.ts +474 -0
  513. package/src/utils/terraformMcp.ts +99 -0
  514. package/src/utils/time.ts +59 -0
  515. package/src/utils/timer.ts +72 -0
  516. package/src/utils/todoTracking.ts +168 -0
  517. package/src/utils/token.ts +294 -0
  518. package/src/utils/toolLicensing.ts +152 -0
  519. package/src/utils/toolSelection.ts +239 -0
  520. package/src/utils/toon.ts +76 -0
  521. package/src/utils/version.ts +10 -0
  522. package/src/utils/versioning.ts +44 -0
  523. package/src/utils/vertex.ts +94 -0
  524. package/src/utils/workflow.ts +25 -0
@@ -0,0 +1,189 @@
1
+ type ProviderErrorPattern = { regex: RegExp; label: string };
2
+
3
+ /** Stable label for the BYOK provider-billing-exhausted classification. */
4
+ export const PROVIDER_BILLING_EXHAUSTED_LABEL = "provider billing exhausted";
5
+
6
+ // status codes are only treated as provider errors when they are adjacent to
7
+ // a recognised status key. this rejects commit SHAs that happen to contain
8
+ // "429", version strings, file hashes, etc.
9
+ const statusKey = `\\b(?:status[_ ]?code|http[_ ]?status|status)["']?\\s*[:=]\\s*["']?`;
10
+
11
+ const PROVIDER_ERROR_PATTERNS: ProviderErrorPattern[] = [
12
+ // billing-payload patterns come BEFORE bare status-code patterns. providers
13
+ // commonly return 401 / 429 for billing/quota exhaustion (OpenCode Zen
14
+ // `CreditsError` / `FreeUsageLimitError`, Gemini `RESOURCE_EXHAUSTED` +
15
+ // "spending cap", Anthropic "Insufficient balance" / "credit balance is
16
+ // too low"). these are non-retryable and require user-billing action —
17
+ // distinct from a transient auth error or rate-limit. status-code patterns
18
+ // would otherwise win and surface "auth error (401)" / "rate limited (429)"
19
+ // with no billing hint. see #778, #835.
20
+ { regex: /\bCreditsError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
21
+ { regex: /\bFreeUsageLimitError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
22
+ { regex: /Insufficient balance/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
23
+ {
24
+ regex: /credit balance is too low/i,
25
+ label: PROVIDER_BILLING_EXHAUSTED_LABEL,
26
+ },
27
+ { regex: /spending cap/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
28
+ // auth patterns must come BEFORE rate-limit patterns. OpenRouter 401 error
29
+ // payloads carry `x-ratelimit-*` response headers in the dump, and the
30
+ // free-form rate-limit regex below would otherwise win on word-boundary
31
+ // matches inside header names. canonical 401 messages: OpenRouter returns
32
+ // `{"error":{"message":"User not found","code":401}}` for disabled or
33
+ // invalid keys (https://openai.luzhipeng.com/docs/api/reference/errors-and-debugging).
34
+ { regex: new RegExp(`${statusKey}401\\b`, "i"), label: "auth error (401)" },
35
+ { regex: new RegExp(`${statusKey}403\\b`, "i"), label: "auth error (403)" },
36
+ { regex: /\bUser not found\b/i, label: "auth error (invalid/disabled key)" },
37
+ {
38
+ regex: /\bInvalid authentication\b/i,
39
+ label: "auth error (invalid credentials)",
40
+ },
41
+ {
42
+ regex: /\bNo auth credentials found\b/i,
43
+ label: "auth error (missing credentials)",
44
+ },
45
+ { regex: new RegExp(`${statusKey}429\\b`, "i"), label: "rate limited (429)" },
46
+ { regex: new RegExp(`${statusKey}500\\b`, "i"), label: "provider 500 error" },
47
+ {
48
+ regex: new RegExp(`${statusKey}503\\b`, "i"),
49
+ label: "provider unavailable (503)",
50
+ },
51
+ // matches `rate limit`, `rate limited`, `rate limits exceeded`,
52
+ // `rate_limit_error`, `rate_limit_exceeded`. the leading `\b` + `[_ ]`
53
+ // separator rejects `x-ratelimit-*` / `anthropic-ratelimit-*` response
54
+ // headers (no separator between "rate" and "limit") which routinely
55
+ // appear in dumped 401 / 4xx error JSON.
56
+ { regex: /\brate[_ ]limit/i, label: "rate limited" },
57
+ { regex: /\bRESOURCE_EXHAUSTED\b/, label: "quota exhausted" },
58
+ // Google gRPC `INTERNAL` status. word-boundary anchors reject
59
+ // `INTERNAL_SERVER_ERROR` (HTTP 500 message that may appear in unrelated
60
+ // log lines) and identifiers like `INTERNALS`.
61
+ { regex: /\bINTERNAL\b/, label: "provider internal error" },
62
+ { regex: /\bUNAVAILABLE\b/, label: "provider unavailable" },
63
+ // matches `quota`, `insufficient_quota`, `quota_exceeded`, `quotaExceeded`.
64
+ // word-character lookarounds would reject `_quota` / `quotaX`; `quota` is
65
+ // specific enough that a plain substring match is safe.
66
+ { regex: /quota/i, label: "quota error" },
67
+ // explicit zero-quota response, e.g. `{"limit": 0}`. the `\b` anchor
68
+ // around `limit` rejects keys like `time_limit` or `field_limit`.
69
+ { regex: /["']?\blimit\b["']?\s*:\s*0\b/, label: "zero quota" },
70
+ ];
71
+
72
+ /**
73
+ * Result of a provider-error scan: the classification label plus a
74
+ * human-readable excerpt centered on the matched line. The excerpt is what
75
+ * gets surfaced in `» provider error detected (...)` log lines — see
76
+ * `extractExcerpt` for the windowing/byte-cap policy.
77
+ */
78
+ export type ProviderErrorMatch = {
79
+ label: string;
80
+ excerpt: string;
81
+ };
82
+
83
+ // roughly half a wide terminal line by 4–5 lines of context; large enough
84
+ // to capture a structured error payload (request id, retry-after, model)
85
+ // plus its immediate stack/headers, small enough to not flood the log.
86
+ const EXCERPT_MAX_BYTES = 600;
87
+ const LINES_BEFORE = 1;
88
+ const LINES_AFTER = 2;
89
+
90
+ export function findProviderErrorMatch(
91
+ text: string,
92
+ ): ProviderErrorMatch | null {
93
+ for (const entry of PROVIDER_ERROR_PATTERNS) {
94
+ const m = entry.regex.exec(text);
95
+ if (!m) continue;
96
+ return { label: entry.label, excerpt: extractExcerpt(text, m.index) };
97
+ }
98
+ return null;
99
+ }
100
+
101
+ export function detectProviderError(text: string): string | null {
102
+ return findProviderErrorMatch(text)?.label ?? null;
103
+ }
104
+
105
+ /**
106
+ * Slice a context window around `matchIndex`: the matched line plus
107
+ * `LINES_BEFORE`/`LINES_AFTER` neighbours. If the windowed slice exceeds
108
+ * `EXCERPT_MAX_BYTES` (giant adjacent lines, e.g. JSON tool-schema dumps),
109
+ * fall back to the matched line alone, head-truncated if still too long.
110
+ * Replaces the old `chunk.substring(0, 500)` head-anchored excerpt which
111
+ * surfaced whatever happened to be at the front of the stderr buffer
112
+ * instead of the error itself. See issue #703.
113
+ */
114
+ function extractExcerpt(text: string, matchIndex: number): string {
115
+ const lineStart = text.lastIndexOf("\n", matchIndex - 1) + 1;
116
+ const lineEndRaw = text.indexOf("\n", matchIndex);
117
+ const lineEnd = lineEndRaw === -1 ? text.length : lineEndRaw;
118
+
119
+ let start = lineStart;
120
+ for (let i = 0; i < LINES_BEFORE && start > 0; i++) {
121
+ const prev = text.lastIndexOf("\n", start - 2);
122
+ start = prev < 0 ? 0 : prev + 1;
123
+ }
124
+
125
+ let end = lineEnd;
126
+ for (let i = 0; i < LINES_AFTER && end < text.length; i++) {
127
+ const next = text.indexOf("\n", end + 1);
128
+ end = next < 0 ? text.length : next;
129
+ }
130
+
131
+ let excerpt = text.slice(start, end);
132
+ if (excerpt.length > EXCERPT_MAX_BYTES) {
133
+ excerpt = text.slice(lineStart, lineEnd);
134
+ if (excerpt.length > EXCERPT_MAX_BYTES)
135
+ excerpt = excerpt.slice(0, EXCERPT_MAX_BYTES);
136
+ }
137
+ return excerpt.trim();
138
+ }
139
+
140
+ /**
141
+ * OpenRouter's response when the per-run key's remaining budget can't cover
142
+ * the agent's `max_tokens` reservation. Distinct from a generic provider error
143
+ * because it's a Infraweaver billing concern, not an upstream outage — the user's
144
+ * Router wallet ran out (or the key budget was undersized at mint time and the
145
+ * agent ran out of headroom partway through).
146
+ *
147
+ * Match must be specific to this exact OpenRouter error class. Generic "credits"
148
+ * or "limit" text shows up in unrelated errors and would mis-classify them.
149
+ *
150
+ * Sample:
151
+ * `APIError: This request requires more credits, or fewer max_tokens.
152
+ * You requested up to 32000 tokens, but can only afford 22800.`
153
+ */
154
+ // `/s` (dotAll) lets `.*?` cross newlines so we still detect the error if any
155
+ // upstream layer reformats the message onto multiple lines. Without it, a
156
+ // single inserted `\n` would silently bypass the BillingError reclassification
157
+ // and the user would see the generic `❌ Infraweaver failed` dump instead of the
158
+ // actionable top-up CTA.
159
+ const ROUTER_KEYLIMIT_EXHAUSTED_PATTERN =
160
+ /requires more credits.*?fewer max_tokens|requested up to \d+ tokens.*?can only afford/is;
161
+
162
+ export function isRouterKeylimitExhaustedError(text: string): boolean {
163
+ return ROUTER_KEYLIMIT_EXHAUSTED_PATTERN.test(text);
164
+ }
165
+
166
+ /**
167
+ * BYOK billing-exhausted: provider rejected the request because the user's
168
+ * provider wallet is empty (DeepSeek "Insufficient Balance", Anthropic
169
+ * "credit balance is too low", OpenCode Zen `CreditsError` /
170
+ * `FreeUsageLimitError`, Gemini "spending cap"). Distinct from
171
+ * `isRouterKeylimitExhaustedError` — that's Infraweaver's Router wallet, this
172
+ * is the user's own provider account.
173
+ */
174
+ export function isProviderBillingExhausted(text: string): boolean {
175
+ return (
176
+ findProviderErrorMatch(text)?.label === PROVIDER_BILLING_EXHAUSTED_LABEL
177
+ );
178
+ }
179
+
180
+ /**
181
+ * Extract `providerID=foo` from agent error logs (OpenCode emits this on
182
+ * `provider error detected (...)` lines). Returns the lowercase provider
183
+ * slug, or null when absent. Used to render a provider-specific dashboard
184
+ * link in the BYOK billing-exhausted summary.
185
+ */
186
+ export function extractProviderId(text: string): string | null {
187
+ const match = text.match(/\bproviderID=([a-z0-9_-]+)/i);
188
+ return match ? match[1]!.toLowerCase() : null;
189
+ }
@@ -0,0 +1,239 @@
1
+ import * as core from "@actions/core";
2
+
3
+ import type { Agent } from "#app/agents/index";
4
+ import type { ModelGateResult } from "#app/utils/agent";
5
+ import { apiFetch } from "#app/utils/apiFetch";
6
+ import { BillingError } from "#app/utils/billingErrors";
7
+ import { resolveModelSlug } from "#app/models";
8
+ import { registerSecret } from "#app/utils/redact";
9
+ import type { AccountPlan } from "#app/utils/runContext";
10
+
11
+ /**
12
+ * Managed-model routing (the engine half of Phase D). On a PAYG plan with no BYO
13
+ * provider key, instead of the free fallback the engine mints a short-lived proxy
14
+ * token from the Cloud (`POST /api/proxy-token`) and points the Anthropic-compatible
15
+ * harness at the returned EU Bedrock proxy endpoint. The proxy meters usage out of
16
+ * band (`/api/proxy-usage`) — the engine never bills.
17
+ *
18
+ * `applyManagedProxy` overlays this decision onto a BYOK model gate and returns a
19
+ * complete `RoutedModel` — including the env patch the caller must apply
20
+ * (`envToApply`) rather than mutating `process.env` from inside, so the routing
21
+ * decision is fully described by its return value. The composition with the gate
22
+ * and validation lives in modelResolver.ts (`resolveRunModel`).
23
+ */
24
+
25
+ // The Anthropic CLI / Claude Code harness reads these to route through a gateway:
26
+ // a base URL + a bearer token. NOT CLAUDE_CODE_USE_BEDROCK — the proxy speaks the
27
+ // Anthropic Messages API, not the Bedrock wire format.
28
+ const PROXY_BASE_URL_ENV = "ANTHROPIC_BASE_URL";
29
+ const PROXY_AUTH_TOKEN_ENV = "ANTHROPIC_AUTH_TOKEN";
30
+
31
+ /** A resolved model decision plus the env patch (if any) the caller must apply to
32
+ * route the run. `envToApply` is set only when the managed proxy engaged. */
33
+ export type RoutedModel = ModelGateResult & {
34
+ envToApply?: Record<string, string>;
35
+ };
36
+
37
+ export type ProxyMintResult =
38
+ | { ok: true; token: string; endpoint: string }
39
+ | {
40
+ ok: false;
41
+ reason:
42
+ | "requires_card"
43
+ | "requires_upgrade"
44
+ | "unconfigured"
45
+ | "transient";
46
+ };
47
+
48
+ /**
49
+ * The proxy `endpoint` becomes `ANTHROPIC_BASE_URL` and receives the bearer on every
50
+ * model call, so it must be a well-formed **https** URL — never cleartext. It comes
51
+ * from the authenticated Cloud (not directly attacker-controlled), but a
52
+ * compromised/misconfigured Cloud response could otherwise redirect the proxy token.
53
+ * Operators can additionally pin exact hosts via `INFRAWEAVER_MODEL_PROXY_ALLOWED_HOSTS`
54
+ * (comma-separated); unset = trust any https host the Cloud returns.
55
+ */
56
+ export function isSafeProxyEndpoint(endpoint: string): boolean {
57
+ let url: URL;
58
+ try {
59
+ url = new URL(endpoint);
60
+ } catch {
61
+ return false;
62
+ }
63
+ if (url.protocol !== "https:") return false;
64
+ const pinned = (process.env.INFRAWEAVER_MODEL_PROXY_ALLOWED_HOSTS ?? "")
65
+ .split(",")
66
+ .map((h) => h.trim().toLowerCase())
67
+ .filter(Boolean);
68
+ return pinned.length === 0 || pinned.includes(url.hostname.toLowerCase());
69
+ }
70
+
71
+ /** Classify a `/api/proxy-token` response. Pure given the status + parsed body
72
+ * (aside from the optional `INFRAWEAVER_MODEL_PROXY_ALLOWED_HOSTS` host pin). */
73
+ export function classifyProxyMint(
74
+ status: number,
75
+ body: { token?: unknown; endpoint?: unknown } | null,
76
+ ): ProxyMintResult {
77
+ if (
78
+ status === 200 &&
79
+ body &&
80
+ typeof body.token === "string" &&
81
+ typeof body.endpoint === "string" &&
82
+ // refuse to route the bearer to a cleartext / malformed / non-allowlisted host.
83
+ isSafeProxyEndpoint(body.endpoint)
84
+ ) {
85
+ return { ok: true, token: body.token, endpoint: body.endpoint };
86
+ }
87
+ // 402 = router_requires_card (no payment method); 403 = the requested managed
88
+ // model needs a higher plan (Opus / Sonnet run on OSS + Team, Claude Fable is
89
+ // Enterprise); 501 = proxy not deployed yet.
90
+ if (status === 402) return { ok: false, reason: "requires_card" };
91
+ if (status === 403) return { ok: false, reason: "requires_upgrade" };
92
+ if (status === 501) return { ok: false, reason: "unconfigured" };
93
+ return { ok: false, reason: "transient" };
94
+ }
95
+
96
+ /** The env that points the Anthropic-compatible harness at the managed proxy. Pure. */
97
+ export function managedProxyEnv(
98
+ token: string,
99
+ endpoint: string,
100
+ ): Record<string, string> {
101
+ return { [PROXY_BASE_URL_ENV]: endpoint, [PROXY_AUTH_TOKEN_ENV]: token };
102
+ }
103
+
104
+ /** Apply a model-routing env patch to the process. The one place env is mutated, and
105
+ * the caller does it explicitly with a value it can see (no hidden side effect). */
106
+ export function applyModelEnv(env: Record<string, string>): void {
107
+ for (const [key, value] of Object.entries(env)) process.env[key] = value;
108
+ }
109
+
110
+ /** Mint a managed-model proxy token from the Cloud. Never throws — network/parse
111
+ * failures classify as `transient` so the caller can fall back to the free model. */
112
+ export async function mintProxyToken(opts: {
113
+ credential: string;
114
+ model?: string | undefined;
115
+ fetchImpl?: typeof apiFetch;
116
+ }): Promise<ProxyMintResult> {
117
+ const doFetch = opts.fetchImpl ?? apiFetch;
118
+ try {
119
+ const res = await doFetch({
120
+ path: "/api/proxy-token",
121
+ method: "POST",
122
+ headers: {
123
+ Authorization: `Bearer ${opts.credential}`,
124
+ "content-type": "application/json",
125
+ },
126
+ body: JSON.stringify(opts.model ? { model: opts.model } : {}),
127
+ });
128
+ let body: { token?: unknown; endpoint?: unknown } | null = null;
129
+ try {
130
+ body = (await res.json()) as { token?: unknown; endpoint?: unknown };
131
+ } catch {
132
+ body = null;
133
+ }
134
+ const result = classifyProxyMint(res.status, body);
135
+ // register the minted `tmpx_` proxy token for log masking the moment we
136
+ // receive it — exactly like every other bearer the engine handles (gitAuth,
137
+ // token.ts, payload.ts). It is about to be placed in `ANTHROPIC_AUTH_TOKEN`
138
+ // (managedProxyEnv → applyModelEnv); GitHub only masks REGISTERED secrets, so
139
+ // without this any later env dump / error line would print it in cleartext.
140
+ // also register it with the sink-independent redactor so it's masked on the
141
+ // stderr / local sinks `core.setSecret` doesn't cover.
142
+ if (result.ok) {
143
+ core.setSecret(result.token);
144
+ registerSecret(result.token);
145
+ }
146
+ return result;
147
+ } catch {
148
+ return { ok: false, reason: "transient" };
149
+ }
150
+ }
151
+
152
+ /** The mint seam `applyManagedProxy` / `resolveRunModel` accept for tests. */
153
+ export type ProxyMint = typeof mintProxyToken;
154
+
155
+ /**
156
+ * The model the managed EU Bedrock proxy should serve for this run. The managed
157
+ * gateway is Anthropic-on-Bedrock, and unlike a BYOK key it can serve the whole
158
+ * Claude family — including Claude Fable, which the BYOK catalog deprecates to Opus
159
+ * (many BYOK Anthropic keys can't invoke Fable). So for an `anthropic/*` selection
160
+ * we mint for the slug's *undeprecated* resolve (e.g. `anthropic/claude-fable`
161
+ * stays Fable) rather than the fallback-collapsed model the BYOK gate produced.
162
+ * Non-Anthropic selections keep the gate's resolved model (the proxy maps anything
163
+ * else to its default Claude model anyway). Returns undefined when there is no
164
+ * usable Anthropic override, so the caller keeps `gate.fallback.from`.
165
+ */
166
+ export function managedProxyModel(
167
+ slug: string | undefined,
168
+ ): string | undefined {
169
+ if (!slug?.startsWith("anthropic/")) return undefined;
170
+ return resolveModelSlug(slug);
171
+ }
172
+
173
+ /**
174
+ * Overlay the managed proxy onto a model gate. A no-op (returns the gate unchanged)
175
+ * unless the free fallback engaged (no BYO key) AND the org is on PAYG. On a
176
+ * successful mint it routes the originally-requested model through the proxy and sets
177
+ * `envToApply`; a `requires_card` mint surfaces a `BillingError`;
178
+ * `unconfigured`/`transient` keep the free fallback the gate already chose.
179
+ */
180
+ export async function applyManagedProxy(input: {
181
+ gate: ModelGateResult;
182
+ plan: AccountPlan;
183
+ credential: string;
184
+ resolveAgent: (ctx: { model?: string | undefined }) => Agent;
185
+ /** the originally-requested model slug (before BYOK fallback), when known */
186
+ slug?: string | undefined;
187
+ mint?: ProxyMint;
188
+ }): Promise<RoutedModel> {
189
+ const { gate } = input;
190
+ if (!gate.fallback || input.plan !== "payg" || !input.credential) return gate;
191
+
192
+ // Prefer the user's chosen managed Claude model (Fable survives here) over the
193
+ // BYOK fallback-collapsed model — see {@link managedProxyModel}.
194
+ const requested = managedProxyModel(input.slug) ?? gate.fallback.from;
195
+ const mintFn = input.mint ?? mintProxyToken;
196
+ const result = await mintFn({
197
+ credential: input.credential,
198
+ model: requested,
199
+ });
200
+
201
+ if (result.ok) {
202
+ const model = requested;
203
+ return {
204
+ model,
205
+ effectiveSlug: model,
206
+ agent: input.resolveAgent({ model }),
207
+ warnings: [
208
+ `» routing ${model} through the managed EU Bedrock proxy (no BYO key on a PAYG plan)`,
209
+ ],
210
+ validate: false,
211
+ envToApply: managedProxyEnv(result.token, result.endpoint),
212
+ };
213
+ }
214
+
215
+ if (result.reason === "requires_card") {
216
+ throw new BillingError(
217
+ "Managed models require a payment method on this organisation.",
218
+ {
219
+ code: "router_requires_card",
220
+ },
221
+ );
222
+ }
223
+
224
+ if (result.reason === "requires_upgrade") {
225
+ throw new BillingError(
226
+ `The managed model ${requested} needs a higher plan — Claude Opus and Sonnet run on OSS + Team, ` +
227
+ `Claude Fable is on Enterprise. Upgrade, or pick a managed model your plan includes.`,
228
+ { code: "router_requires_upgrade" },
229
+ );
230
+ }
231
+
232
+ return {
233
+ ...gate,
234
+ warnings: [
235
+ ...gate.warnings,
236
+ `» managed-model proxy ${result.reason}; using the free fallback model`,
237
+ ],
238
+ };
239
+ }
@@ -0,0 +1,182 @@
1
+ import { log } from "#app/utils/cli";
2
+ import { $ } from "#app/utils/shell";
3
+
4
+ type ComputeIncrementalDiffParams = {
5
+ baseBranch: string;
6
+ beforeSha: string;
7
+ headSha: string;
8
+ };
9
+
10
+ /**
11
+ * computes the incremental diff between two versions of a PR using range-diff
12
+ * on virtual squash commits created via `git commit-tree`.
13
+ *
14
+ * each PR version is squashed into a single synthetic commit (merge-base → tip tree),
15
+ * then range-diff compares those two single-commit ranges. this:
16
+ * - isolates each version's net effect (base branch noise eliminated via per-version merge bases)
17
+ * - avoids commit-matching issues that raw range-diff has with rebases/squashes/reordering
18
+ * - creates only loose git objects, no branches or refs (unlike temp-branch squash approaches)
19
+ *
20
+ * unlike fetchAndFormatPrDiff/formatFilesWithLineNumbers, this output has no line numbers.
21
+ * range-diff compares *patches* (diffs-of-diffs), not file trees — its hunk headers are
22
+ * `@@ file.ts` breadcrumbs, not positional `@@ -X,Y +A,B @@` markers. reconstructing
23
+ * line numbers would require cross-referencing with the v2 diff or content-matching against
24
+ * file trees, both of which are fragile (duplicate lines, hunk boundary shifts after rebase).
25
+ * a structured interdiff approach (diff two parsed patches, compare only +/- keys via Myers)
26
+ * could approximate line numbers but loses semantic precision: range-diff understands patch
27
+ * structure natively (rename detection, hunk-aware matching, dual-prefix inner/outer changes),
28
+ * while flat key-sequence comparison can misalign duplicate lines and can't distinguish
29
+ * "new addition to the PR" from "existing code newly modified by the PR". range-diff is the
30
+ * right abstraction here — the incremental diff answers "how did the changeset evolve?",
31
+ * not "where in the file is this?", and forcing positional line numbers onto it would be
32
+ * semantically misleading.
33
+ *
34
+ * alternatives considered:
35
+ * - plain git diff (two-tree or three-dot): includes base branch changes, no PR isolation
36
+ * - patch-text diffing (interdiff / diff-of-diffs): fragile, hunk offset noise on rebase
37
+ * - range-diff on raw commit ranges: confused by commit reorganization across force-pushes
38
+ */
39
+ export function computeIncrementalDiff(params: ComputeIncrementalDiffParams): string | null {
40
+ try {
41
+ // $1=beforeSha, $2=baseBranch, $3=headSha
42
+ const raw = $(
43
+ "sh",
44
+ [
45
+ "-c",
46
+ 'old_base=$(git merge-base "$1" "origin/$2") && ' +
47
+ 'new_base=$(git merge-base "$3" "origin/$2") && ' +
48
+ "git range-diff --no-color " +
49
+ '"$old_base..$(git commit-tree "$1^{tree}" -p "$old_base" -m x)" ' +
50
+ '"$new_base..$(git commit-tree "$3^{tree}" -p "$new_base" -m x)"',
51
+ "--",
52
+ params.beforeSha,
53
+ params.baseBranch,
54
+ params.headSha,
55
+ ],
56
+ { log: false },
57
+ );
58
+
59
+ return postProcessRangeDiff(raw);
60
+ } catch (e) {
61
+ log.debug(`» range-diff failed: ${e instanceof Error ? e.message : String(e)}`);
62
+ return null;
63
+ }
64
+ }
65
+
66
+ function isDiffPrefix(ch: string): boolean {
67
+ return ch === " " || ch === "+" || ch === "-";
68
+ }
69
+
70
+ /**
71
+ * transforms git range-diff output into a clean incremental diff.
72
+ *
73
+ * range-diff content lines have two prefix characters:
74
+ * 1st (outer): range-diff level — space (same in both), + (new only), - (old only)
75
+ * 2nd (inner): original diff level — space (context), + (added), - (removed)
76
+ *
77
+ * stripping the inner prefix produces a standard unified-diff-like output where
78
+ * +/- means "changed between PR versions" rather than "changed vs base branch".
79
+ *
80
+ * uses a streaming approach: a ring buffer of before-context lines is flushed when
81
+ * a change is hit, then afterCount lines of after-context are emitted directly.
82
+ * nearest preceding ## / @@ headers are force-included when outside the context window.
83
+ */
84
+ export function postProcessRangeDiff(raw: string, contextLines = 3): string | null {
85
+ if (!raw.trim()) return null;
86
+ if (/^\d+:\s+\w+\s+=\s+\d+:/m.test(raw)) return null;
87
+
88
+ type Line = { prefix: string; from: number; to: number; seq: number };
89
+
90
+ const beforeBuf: Line[] = [];
91
+ let lastFileHdr: Line | null = null;
92
+ let lastHunkHdr: Line | null = null;
93
+ let fileHdrEmitted = true;
94
+ let hunkHdrEmitted = true;
95
+
96
+ let out = "";
97
+ let afterRemaining = 0;
98
+ let lastEmittedSeq = -2;
99
+ let seq = 0;
100
+ let hasChanges = false;
101
+
102
+ function emit(line: Line) {
103
+ if (lastEmittedSeq >= 0 && line.seq > lastEmittedSeq + 1) out += `${out ? "\n" : ""}...`;
104
+ out += (out ? "\n" : "") + line.prefix + raw.slice(line.from, line.to);
105
+ lastEmittedSeq = line.seq;
106
+ if (lastFileHdr?.seq === line.seq) fileHdrEmitted = true;
107
+ if (lastHunkHdr?.seq === line.seq) hunkHdrEmitted = true;
108
+ }
109
+
110
+ function flushBefore() {
111
+ if (lastFileHdr && !fileHdrEmitted) emit(lastFileHdr);
112
+ if (lastHunkHdr && !hunkHdrEmitted) emit(lastHunkHdr);
113
+ for (const line of beforeBuf) {
114
+ if (line.seq > lastEmittedSeq) emit(line);
115
+ }
116
+ beforeBuf.length = 0;
117
+ }
118
+
119
+ let cursor = 0;
120
+ while (cursor < raw.length) {
121
+ const eol = raw.indexOf("\n", cursor);
122
+ const lineEnd = eol === -1 ? raw.length : eol;
123
+
124
+ if (raw.charCodeAt(cursor) >= 48 && raw.charCodeAt(cursor) <= 57) {
125
+ cursor = lineEnd + 1;
126
+ continue;
127
+ }
128
+
129
+ if (lineEnd - cursor >= 5 && raw.startsWith(" ", cursor)) {
130
+ const prefix = raw[cursor + 4]!;
131
+ if (isDiffPrefix(prefix)) {
132
+ const contentPos = cursor + 5;
133
+ const isOuterChange = prefix !== " ";
134
+ let line: Line;
135
+ let isChange = false;
136
+
137
+ if (contentPos >= lineEnd) {
138
+ line = { prefix, from: lineEnd, to: lineEnd, seq };
139
+ } else if (isDiffPrefix(raw[contentPos]!)) {
140
+ isChange = isOuterChange;
141
+ line = { prefix, from: contentPos + 1, to: lineEnd, seq };
142
+ } else {
143
+ line = { prefix, from: contentPos, to: lineEnd, seq };
144
+ if (
145
+ raw.startsWith("## ", contentPos) &&
146
+ !raw.startsWith("## Commit message", contentPos)
147
+ ) {
148
+ lastFileHdr = line;
149
+ fileHdrEmitted = false;
150
+ lastHunkHdr = null;
151
+ hunkHdrEmitted = true;
152
+ } else if (
153
+ raw.startsWith("@@", contentPos) &&
154
+ !raw.startsWith("@@ Metadata", contentPos)
155
+ ) {
156
+ lastHunkHdr = line;
157
+ hunkHdrEmitted = false;
158
+ }
159
+ }
160
+
161
+ if (isChange) {
162
+ hasChanges = true;
163
+ flushBefore();
164
+ emit(line);
165
+ afterRemaining = contextLines;
166
+ } else if (afterRemaining > 0) {
167
+ emit(line);
168
+ afterRemaining--;
169
+ } else {
170
+ if (beforeBuf.length >= contextLines) beforeBuf.shift();
171
+ beforeBuf.push(line);
172
+ }
173
+
174
+ seq++;
175
+ }
176
+ }
177
+
178
+ cursor = lineEnd + 1;
179
+ }
180
+
181
+ return hasChanges ? out : null;
182
+ }