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,404 @@
1
+ import { isAbsolute, normalize, resolve } from "node:path";
2
+
3
+ export type DiffLineRange = {
4
+ startLine: number;
5
+ endLine: number;
6
+ };
7
+
8
+ export type DiffTocEntry = {
9
+ filename: string;
10
+ startLine: number;
11
+ endLine: number;
12
+ };
13
+
14
+ export type DiffCoverageFileBreakdown = {
15
+ filename: string;
16
+ startLine: number;
17
+ endLine: number;
18
+ totalLines: number;
19
+ coveredLines: number;
20
+ coveredRanges: DiffLineRange[];
21
+ unreadRanges: DiffLineRange[];
22
+ };
23
+
24
+ export type DiffCoverageBreakdown = {
25
+ totalLines: number;
26
+ coveredLines: number;
27
+ unreadLines: number;
28
+ coveragePercent: number;
29
+ coveredRanges: DiffLineRange[];
30
+ unreadRanges: DiffLineRange[];
31
+ files: DiffCoverageFileBreakdown[];
32
+ };
33
+
34
+ export type DiffCoverageState = {
35
+ diffPath: string;
36
+ totalLines: number;
37
+ tocEntries: DiffTocEntry[];
38
+ coveredRanges: DiffLineRange[];
39
+ coveragePreflightRan: boolean;
40
+ lastBreakdown?: string | undefined;
41
+ };
42
+
43
+ type ReadTarget = {
44
+ path: string;
45
+ offset?: number | undefined;
46
+ limit?: number | undefined;
47
+ startLine?: number | undefined;
48
+ endLine?: number | undefined;
49
+ };
50
+
51
+ type OffsetBase = "zero" | "one";
52
+
53
+ export function countLines(params: { content: string }): number {
54
+ const content = params.content;
55
+ if (content.length === 0) return 0;
56
+ return content.split("\n").length;
57
+ }
58
+
59
+ export function parseDiffTocEntries(params: { toc: string }): DiffTocEntry[] {
60
+ const lines = params.toc.split("\n");
61
+ const entries: DiffTocEntry[] = [];
62
+ // production TOC lines (see formatFilesWithLineNumbers in checkout.ts) append
63
+ // ` · diff-<sha256>` so the agent has the GitHub "Files Changed" anchor
64
+ // precomputed. accept that suffix optionally so we also parse the shorter
65
+ // shape used in tests and in reviewComments.
66
+ for (const line of lines) {
67
+ const match = line.match(/^- (.+) (?:→|->) lines (\d+)-(\d+)(?: · diff-[0-9a-f]+)?$/);
68
+ if (!match) continue;
69
+ const startLine = Number.parseInt(match[2]!, 10);
70
+ const endLine = Number.parseInt(match[3]!, 10);
71
+ if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) continue;
72
+ entries.push({ filename: match[1]!, startLine, endLine });
73
+ }
74
+ return entries;
75
+ }
76
+
77
+ export function createDiffCoverageState(params: {
78
+ diffPath: string;
79
+ totalLines: number;
80
+ toc: string;
81
+ previous?: DiffCoverageState | undefined;
82
+ }): DiffCoverageState {
83
+ return {
84
+ diffPath: params.diffPath,
85
+ totalLines: params.totalLines,
86
+ tocEntries: parseDiffTocEntries({ toc: params.toc }),
87
+ coveredRanges: [],
88
+ // carry forward across checkout_pr refreshes so the nudge stays "once per
89
+ // review session". coveredRanges are intentionally not carried because
90
+ // line numbers are tied to the previous diff's content.
91
+ coveragePreflightRan: params.previous?.coveragePreflightRan ?? false,
92
+ };
93
+ }
94
+
95
+ export function recordDiffReadFromToolUse(params: {
96
+ state: DiffCoverageState | undefined;
97
+ toolName: string;
98
+ input: unknown;
99
+ cwd: string;
100
+ }): boolean {
101
+ const state = params.state;
102
+ if (!state) return false;
103
+ if (!isReadTool(params.toolName)) return false;
104
+ const readTarget = extractReadTarget({ input: params.input });
105
+ if (!readTarget) return false;
106
+
107
+ const normalizedReadPath = normalizePath({ path: readTarget.path, cwd: params.cwd });
108
+ const normalizedDiffPath = normalize(state.diffPath);
109
+ if (normalizedReadPath !== normalizedDiffPath) return false;
110
+
111
+ const range = resolveReadRange({
112
+ totalLines: state.totalLines,
113
+ offset: readTarget.offset,
114
+ limit: readTarget.limit,
115
+ startLine: readTarget.startLine,
116
+ endLine: readTarget.endLine,
117
+ offsetBase: resolveOffsetBase({ toolName: params.toolName }),
118
+ });
119
+ if (!range) return false;
120
+
121
+ state.coveredRanges = mergeRanges({ ranges: state.coveredRanges, nextRange: range });
122
+ return true;
123
+ }
124
+
125
+ export function getDiffCoverageBreakdown(params: {
126
+ state: DiffCoverageState;
127
+ }): DiffCoverageBreakdown {
128
+ const state = params.state;
129
+ const coveredRanges = mergeRangesList({ ranges: state.coveredRanges });
130
+ const unreadRanges = invertRanges({ totalLines: state.totalLines, coveredRanges });
131
+ const coveredLines = countLinesInRanges({ ranges: coveredRanges });
132
+ const unreadLines = Math.max(0, state.totalLines - coveredLines);
133
+ const coveragePercent = state.totalLines
134
+ ? Number(((coveredLines / state.totalLines) * 100).toFixed(2))
135
+ : 100;
136
+
137
+ const files: DiffCoverageFileBreakdown[] = [];
138
+ for (const entry of state.tocEntries) {
139
+ const fileRange: DiffLineRange = { startLine: entry.startLine, endLine: entry.endLine };
140
+ const coveredInFile = intersectRangesWithRange({ ranges: coveredRanges, target: fileRange });
141
+ const unreadInFile = intersectRangesWithRange({ ranges: unreadRanges, target: fileRange });
142
+ const totalFileLines = Math.max(0, entry.endLine - entry.startLine + 1);
143
+ const fileCoveredLines = countLinesInRanges({ ranges: coveredInFile });
144
+ files.push({
145
+ filename: entry.filename,
146
+ startLine: entry.startLine,
147
+ endLine: entry.endLine,
148
+ totalLines: totalFileLines,
149
+ coveredLines: fileCoveredLines,
150
+ coveredRanges: coveredInFile,
151
+ unreadRanges: unreadInFile,
152
+ });
153
+ }
154
+
155
+ return {
156
+ totalLines: state.totalLines,
157
+ coveredLines,
158
+ unreadLines,
159
+ coveragePercent,
160
+ coveredRanges,
161
+ unreadRanges,
162
+ files,
163
+ };
164
+ }
165
+
166
+ export function renderDiffCoverageBreakdown(params: {
167
+ diffPath: string;
168
+ breakdown: DiffCoverageBreakdown;
169
+ }): string {
170
+ const breakdown = params.breakdown;
171
+ const lines: string[] = [];
172
+ lines.push(`diff coverage report for \`${params.diffPath}\``);
173
+ lines.push(
174
+ `overall: ${breakdown.coveredLines}/${breakdown.totalLines} lines read (${breakdown.coveragePercent}%), unread: ${breakdown.unreadLines}`,
175
+ );
176
+ lines.push(`covered ranges: ${formatRanges({ ranges: breakdown.coveredRanges })}`);
177
+ lines.push(`unread ranges: ${formatRanges({ ranges: breakdown.unreadRanges })}`);
178
+ lines.push("");
179
+ lines.push("per-file TOC coverage:");
180
+ for (const file of breakdown.files) {
181
+ const filePercent = file.totalLines
182
+ ? Number(((file.coveredLines / file.totalLines) * 100).toFixed(2))
183
+ : 100;
184
+ lines.push(
185
+ `- ${file.filename} (toc lines ${file.startLine}-${file.endLine}): ${file.coveredLines}/${file.totalLines} lines read (${filePercent}%)`,
186
+ );
187
+ lines.push(` read: ${formatRanges({ ranges: file.coveredRanges })}`);
188
+ lines.push(` unread: ${formatRanges({ ranges: file.unreadRanges })}`);
189
+ }
190
+ return lines.join("\n");
191
+ }
192
+
193
+ function resolveOffsetBase(params: { toolName: string }): OffsetBase {
194
+ const lower = params.toolName.toLowerCase();
195
+ if (lower === "readfile" || lower.endsWith(".readfile")) {
196
+ return "one";
197
+ }
198
+ return "zero";
199
+ }
200
+
201
+ function isReadTool(toolName: string): boolean {
202
+ const lower = toolName.toLowerCase();
203
+ if (lower === "read" || lower === "readfile") return true;
204
+ if (lower.endsWith(".read") || lower.endsWith(".readfile")) return true;
205
+ return false;
206
+ }
207
+
208
+ function extractReadTarget(params: { input: unknown }): ReadTarget | null {
209
+ const inputRecord = asRecord(params.input);
210
+ if (!inputRecord) return null;
211
+
212
+ const direct = extractReadTargetFromRecord({ record: inputRecord });
213
+ if (direct) return direct;
214
+
215
+ const nestedCandidates = [inputRecord.args, inputRecord.params, inputRecord.input];
216
+ for (const candidate of nestedCandidates) {
217
+ const nestedRecord = asRecord(candidate);
218
+ if (!nestedRecord) continue;
219
+ const nested = extractReadTargetFromRecord({ record: nestedRecord });
220
+ if (nested) return nested;
221
+ }
222
+
223
+ return null;
224
+ }
225
+
226
+ function extractReadTargetFromRecord(params: {
227
+ record: Record<string, unknown>;
228
+ }): ReadTarget | null {
229
+ const record = params.record;
230
+ const pathValue =
231
+ readString({ value: record.path }) ??
232
+ readString({ value: record.file_path }) ??
233
+ readString({ value: record.filePath }) ??
234
+ readString({ value: record.filepath }) ??
235
+ readString({ value: record.file }) ??
236
+ readString({ value: record.target_file });
237
+
238
+ if (!pathValue) return null;
239
+
240
+ const offset = readNumber({ value: record.offset });
241
+ const limit = readNumber({ value: record.limit });
242
+ const startLine =
243
+ readNumber({ value: record.start_line }) ??
244
+ readNumber({ value: record.startLine }) ??
245
+ readNumber({ value: record.line_start });
246
+ const endLine =
247
+ readNumber({ value: record.end_line }) ??
248
+ readNumber({ value: record.endLine }) ??
249
+ readNumber({ value: record.line_end });
250
+
251
+ return { path: pathValue, offset, limit, startLine, endLine };
252
+ }
253
+
254
+ function resolveReadRange(params: {
255
+ totalLines: number;
256
+ offset?: number | undefined;
257
+ limit?: number | undefined;
258
+ startLine?: number | undefined;
259
+ endLine?: number | undefined;
260
+ offsetBase: OffsetBase;
261
+ }): DiffLineRange | null {
262
+ const totalLines = params.totalLines;
263
+ if (totalLines <= 0) return null;
264
+
265
+ if (params.startLine !== undefined || params.endLine !== undefined) {
266
+ const rawStart = params.startLine ?? 1;
267
+ const rawEnd = params.endLine ?? totalLines;
268
+ const startLine = clampLine({ value: rawStart, totalLines });
269
+ const endLine = clampLine({ value: rawEnd, totalLines });
270
+ if (endLine < startLine) return null;
271
+ return { startLine, endLine };
272
+ }
273
+
274
+ let startLine = 1;
275
+ if (params.offset !== undefined) {
276
+ if (params.offset >= 0) {
277
+ const normalizedOffset =
278
+ params.offsetBase === "zero" ? params.offset + 1 : params.offset === 0 ? 1 : params.offset;
279
+ startLine = clampLine({ value: normalizedOffset, totalLines });
280
+ } else {
281
+ startLine = clampLine({ value: totalLines + params.offset + 1, totalLines });
282
+ }
283
+ }
284
+
285
+ let endLine = totalLines;
286
+ if (params.limit !== undefined) {
287
+ if (params.limit <= 0) return null;
288
+ endLine = clampLine({ value: startLine + params.limit - 1, totalLines });
289
+ }
290
+
291
+ if (endLine < startLine) return null;
292
+ return { startLine, endLine };
293
+ }
294
+
295
+ function normalizePath(params: { path: string; cwd: string }): string {
296
+ if (isAbsolute(params.path)) return normalize(params.path);
297
+ return normalize(resolve(params.cwd, params.path));
298
+ }
299
+
300
+ function mergeRanges(params: {
301
+ ranges: DiffLineRange[];
302
+ nextRange: DiffLineRange;
303
+ }): DiffLineRange[] {
304
+ return mergeRangesList({ ranges: [...params.ranges, params.nextRange] });
305
+ }
306
+
307
+ function mergeRangesList(params: { ranges: DiffLineRange[] }): DiffLineRange[] {
308
+ if (params.ranges.length === 0) return [];
309
+ const sorted = [...params.ranges].sort((a, b) => a.startLine - b.startLine);
310
+ const merged: DiffLineRange[] = [];
311
+ for (const range of sorted) {
312
+ const last = merged[merged.length - 1];
313
+ if (!last) {
314
+ merged.push({ startLine: range.startLine, endLine: range.endLine });
315
+ continue;
316
+ }
317
+ if (range.startLine <= last.endLine + 1) {
318
+ if (range.endLine > last.endLine) {
319
+ last.endLine = range.endLine;
320
+ }
321
+ continue;
322
+ }
323
+ merged.push({ startLine: range.startLine, endLine: range.endLine });
324
+ }
325
+ return merged;
326
+ }
327
+
328
+ function invertRanges(params: {
329
+ totalLines: number;
330
+ coveredRanges: DiffLineRange[];
331
+ }): DiffLineRange[] {
332
+ if (params.totalLines <= 0) return [];
333
+ if (params.coveredRanges.length === 0) {
334
+ return [{ startLine: 1, endLine: params.totalLines }];
335
+ }
336
+
337
+ const unread: DiffLineRange[] = [];
338
+ let cursor = 1;
339
+ for (const range of params.coveredRanges) {
340
+ if (cursor < range.startLine) {
341
+ unread.push({ startLine: cursor, endLine: range.startLine - 1 });
342
+ }
343
+ cursor = Math.max(cursor, range.endLine + 1);
344
+ }
345
+ if (cursor <= params.totalLines) {
346
+ unread.push({ startLine: cursor, endLine: params.totalLines });
347
+ }
348
+ return unread;
349
+ }
350
+
351
+ function intersectRangesWithRange(params: {
352
+ ranges: DiffLineRange[];
353
+ target: DiffLineRange;
354
+ }): DiffLineRange[] {
355
+ const intersections: DiffLineRange[] = [];
356
+ for (const range of params.ranges) {
357
+ if (range.endLine < params.target.startLine) continue;
358
+ if (range.startLine > params.target.endLine) continue;
359
+ const startLine = Math.max(range.startLine, params.target.startLine);
360
+ const endLine = Math.min(range.endLine, params.target.endLine);
361
+ if (endLine >= startLine) {
362
+ intersections.push({ startLine, endLine });
363
+ }
364
+ }
365
+ return intersections;
366
+ }
367
+
368
+ export function countLinesInRanges(params: { ranges: DiffLineRange[] }): number {
369
+ let total = 0;
370
+ for (const range of params.ranges) {
371
+ total += range.endLine - range.startLine + 1;
372
+ }
373
+ return total;
374
+ }
375
+
376
+ function formatRanges(params: { ranges: DiffLineRange[] }): string {
377
+ if (params.ranges.length === 0) return "none";
378
+ return params.ranges.map((range) => `${range.startLine}-${range.endLine}`).join(", ");
379
+ }
380
+
381
+ function clampLine(params: { value: number; totalLines: number }): number {
382
+ if (params.value < 1) return 1;
383
+ if (params.value > params.totalLines) return params.totalLines;
384
+ return params.value;
385
+ }
386
+
387
+ function asRecord(value: unknown): Record<string, unknown> | null {
388
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
389
+ return Object.fromEntries(Object.entries(value));
390
+ }
391
+
392
+ function readString(params: { value: unknown }): string | undefined {
393
+ if (typeof params.value === "string") return params.value;
394
+ return undefined;
395
+ }
396
+
397
+ function readNumber(params: { value: unknown }): number | undefined {
398
+ if (typeof params.value === "number" && Number.isFinite(params.value)) return params.value;
399
+ if (typeof params.value === "string") {
400
+ const parsed = Number.parseInt(params.value, 10);
401
+ if (Number.isFinite(parsed)) return parsed;
402
+ }
403
+ return undefined;
404
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Small typed accessors for process env — read once, in one place, instead of
3
+ * re-implementing the same `process.env.X` guard at every call site. Provider
4
+ * API-key names live in `models.ts`; the Cloud host/allowlist in
5
+ * `cloudFetchCore.ts`; this module holds the generic presence/read helpers plus
6
+ * the shared-temp-dir accessor.
7
+ */
8
+
9
+ /** True when `name` is set to a non-empty string. Folds the copy that lived
10
+ * privately in agent.ts / apiKeys.ts / byokFallback.ts / vertex.ts. */
11
+ export function hasEnvVar(name: string): boolean {
12
+ const value = process.env[name];
13
+ return typeof value === "string" && value.length > 0;
14
+ }
15
+
16
+ /** The trimmed value of `name`, or undefined when unset/blank. */
17
+ export function readEnv(name: string): string | undefined {
18
+ const value = process.env[name]?.trim();
19
+ return value && value.length > 0 ? value : undefined;
20
+ }
21
+
22
+ /** The action's shared temp dir, or undefined outside a Infraweaver action run
23
+ * (created by `createTempDirectory()` in setup.ts, which sets INFRAWEAVER_TEMP_DIR). */
24
+ export function readTempDir(): string | undefined {
25
+ return process.env.INFRAWEAVER_TEMP_DIR || undefined;
26
+ }
27
+
28
+ /**
29
+ * The GitHub Actions run context (the `GITHUB_*` env the runner injects), read
30
+ * through one typed accessor instead of `process.env.GITHUB_*` at ~30 sites.
31
+ * Every field is optional — the vars are absent outside a GHA runner (local dev,
32
+ * the stdio server), and callers already treat them as best-effort metadata.
33
+ */
34
+ export type GitHubContext = {
35
+ /** `owner/repo`. */
36
+ repository: string | undefined;
37
+ /** the commit SHA under test. */
38
+ sha: string | undefined;
39
+ /** the short branch/tag name (`GITHUB_REF_NAME`). */
40
+ refName: string | undefined;
41
+ /** the full ref (`refs/heads/…`). */
42
+ ref: string | undefined;
43
+ runId: string | undefined;
44
+ runNumber: string | undefined;
45
+ eventName: string | undefined;
46
+ actor: string | undefined;
47
+ workflow: string | undefined;
48
+ serverUrl: string | undefined;
49
+ workspace: string | undefined;
50
+ };
51
+
52
+ export function githubContext(): GitHubContext {
53
+ return {
54
+ repository: readEnv("GITHUB_REPOSITORY"),
55
+ sha: readEnv("GITHUB_SHA"),
56
+ refName: readEnv("GITHUB_REF_NAME"),
57
+ ref: readEnv("GITHUB_REF"),
58
+ runId: readEnv("GITHUB_RUN_ID"),
59
+ runNumber: readEnv("GITHUB_RUN_NUMBER"),
60
+ eventName: readEnv("GITHUB_EVENT_NAME"),
61
+ actor: readEnv("GITHUB_ACTOR"),
62
+ workflow: readEnv("GITHUB_WORKFLOW"),
63
+ serverUrl: readEnv("GITHUB_SERVER_URL"),
64
+ workspace: readEnv("GITHUB_WORKSPACE"),
65
+ };
66
+ }
67
+
68
+ /**
69
+ * The action's shared temp dir, throwing when it isn't set — the single home for
70
+ * the guard that ~9 call sites previously re-implemented with drifting messages.
71
+ * Pass `context` (a tool name) to keep the "must run in infraweaver action context"
72
+ * hint the checkout/commit tools surfaced.
73
+ */
74
+ export function getTempDir(context?: string): string {
75
+ const tempDir = readTempDir();
76
+ if (!tempDir) {
77
+ throw new Error(
78
+ context
79
+ ? `INFRAWEAVER_TEMP_DIR not set - ${context} must run in infraweaver action context`
80
+ : "INFRAWEAVER_TEMP_DIR not set",
81
+ );
82
+ }
83
+ return tempDir;
84
+ }
@@ -0,0 +1,94 @@
1
+ import { chromeStrings } from "#app/i18n/scaffolding";
2
+ import type { ToolState } from "#app/toolState";
3
+ import { getApiUrl } from "#app/utils/apiUrl";
4
+ import { buildInfraweaverFooter } from "#app/utils/buildInfraweaverFooter";
5
+ import { log } from "#app/utils/cli";
6
+ import { createOctokit, parseRepoContext } from "#app/utils/github";
7
+ import { updateProgressComment } from "#app/utils/progressComment";
8
+ import {
9
+ getGitHubInstallationToken,
10
+ getMcpTokenRefresh,
11
+ } from "#app/utils/token";
12
+
13
+ interface ReportErrorParams {
14
+ toolState: ToolState;
15
+ error: string;
16
+ title?: string;
17
+ /**
18
+ * When the run has no pre-existing progress comment to update (silent
19
+ * IncrementalReview / pull_request_synchronize, mode-less polls), create
20
+ * a fresh issue comment on `toolState.issueNumber` instead of returning
21
+ * silently. Used for terminal errors (BillingError, TransientError) where
22
+ * the GH job summary is the only other surface and most users never open
23
+ * it. see #775.
24
+ */
25
+ createIfMissing?: boolean;
26
+ }
27
+
28
+ export async function reportErrorToComment(
29
+ ctx: ReportErrorParams,
30
+ ): Promise<void> {
31
+ const formattedError = ctx.title ? `${ctx.title}\n\n${ctx.error}` : ctx.error;
32
+
33
+ const repoContext = parseRepoContext();
34
+ const octokit = createOctokit(
35
+ getGitHubInstallationToken(),
36
+ getMcpTokenRefresh(),
37
+ );
38
+ const runId = process.env.GITHUB_RUN_ID
39
+ ? Number.parseInt(process.env.GITHUB_RUN_ID, 10)
40
+ : undefined;
41
+
42
+ const customParts: string[] = [];
43
+ if (runId) {
44
+ const apiUrl = getApiUrl();
45
+ const label = chromeStrings(ctx.toolState.language).rerunFailedJob;
46
+ customParts.push(
47
+ `[${label} ➔](${apiUrl}/trigger/${repoContext.owner}/${repoContext.name}/${runId}?action=rerun)`,
48
+ );
49
+ }
50
+
51
+ const footer = buildInfraweaverFooter({
52
+ triggeredBy: true,
53
+ customParts,
54
+ model: ctx.toolState.model,
55
+ fallbackFrom: ctx.toolState.modelFallback?.from,
56
+ language: ctx.toolState.language,
57
+ });
58
+
59
+ const body = `${formattedError}${footer}`;
60
+
61
+ const comment = ctx.toolState.progressComment;
62
+ if (comment) {
63
+ await updateProgressComment(
64
+ { octokit, owner: repoContext.owner, repo: repoContext.name },
65
+ comment,
66
+ body,
67
+ );
68
+ ctx.toolState.wasUpdated = true;
69
+ return;
70
+ }
71
+
72
+ // silent triggers (pull_request_synchronize IncrementalReview, etc.)
73
+ // intentionally have no progress comment. for terminal errors that need
74
+ // user action — billing exhaustion, transient billing-service outage —
75
+ // surface a fresh issue comment instead of leaving the GH job summary as
76
+ // the only signal. see #775.
77
+ if (!ctx.createIfMissing) return;
78
+ if (!ctx.toolState.issueNumber) return;
79
+
80
+ try {
81
+ const created = await octokit.rest.issues.createComment({
82
+ owner: repoContext.owner,
83
+ repo: repoContext.name,
84
+ issue_number: ctx.toolState.issueNumber,
85
+ body,
86
+ });
87
+ ctx.toolState.progressComment = { id: created.data.id, type: "issue" };
88
+ ctx.toolState.wasUpdated = true;
89
+ } catch (error) {
90
+ log.warning(
91
+ `[errorReport] fallback comment create failed: ${error instanceof Error ? error.message : String(error)}`,
92
+ );
93
+ }
94
+ }
@@ -0,0 +1,35 @@
1
+ import os from "node:os";
2
+
3
+ type ExitSignalHandler = (signal: "SIGINT" | "SIGTERM") => void | Promise<void>;
4
+
5
+ const handlers = new Set<ExitSignalHandler>();
6
+ let installed = false;
7
+
8
+ /**
9
+ * Register a handler to run when the process receives SIGINT or SIGTERM.
10
+ * Returns a dispose function that removes the handler.
11
+ */
12
+ export function onExitSignal(handler: ExitSignalHandler): () => void {
13
+ installSignalHandlers();
14
+ handlers.add(handler);
15
+ return () => {
16
+ handlers.delete(handler);
17
+ };
18
+ }
19
+
20
+ function installSignalHandlers(): void {
21
+ if (installed) return;
22
+ installed = true;
23
+
24
+ async function handleSignal(signal: "SIGINT" | "SIGTERM") {
25
+ await Promise.allSettled([...handlers].map((h) => Promise.try(h, signal)));
26
+ exitWithSignal(signal);
27
+ }
28
+
29
+ process.on("SIGINT", handleSignal);
30
+ process.on("SIGTERM", handleSignal);
31
+ }
32
+
33
+ export function exitWithSignal(signal: "SIGINT" | "SIGTERM") {
34
+ process.exit(128 + os.constants.signals[signal]);
35
+ }
@@ -0,0 +1,9 @@
1
+ // LLMs sometimes double-escape JSON strings, producing literal \n \t \"
2
+ // instead of actual newline/tab/quote characters.
3
+ // detected when the string contains literal \n but no actual newlines.
4
+ export function fixDoubleEscapedString(str: string): string {
5
+ if (!str.includes("\n") && str.includes("\\n")) {
6
+ return str.replace(/\\n/g, "\n").replace(/\\t/g, "\t").replace(/\\"/g, '"');
7
+ }
8
+ return str;
9
+ }
@@ -0,0 +1,13 @@
1
+ /** stdlib-only GitHub Actions helpers for entryPost.ts (no node_modules). */
2
+
3
+ export function getState(name: string): string {
4
+ return process.env[`STATE_${name}`] ?? "";
5
+ }
6
+
7
+ export function info(message: string): void {
8
+ console.log(message);
9
+ }
10
+
11
+ export function warning(message: string): void {
12
+ console.log(`::warning::${message}`);
13
+ }