terramend 0.2.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 (406) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +145 -0
  3. package/dist/agents/claude.d.ts +73 -0
  4. package/dist/agents/claudePretoolGate.d.ts +99 -0
  5. package/dist/agents/gateServer.d.ts +7 -0
  6. package/dist/agents/index.d.ts +6 -0
  7. package/dist/agents/nativeFsDenies.d.ts +28 -0
  8. package/dist/agents/opencode.d.ts +231 -0
  9. package/dist/agents/opencodePlugin.d.ts +85 -0
  10. package/dist/agents/opencodeShared.d.ts +40 -0
  11. package/dist/agents/postRun.d.ts +132 -0
  12. package/dist/agents/reviewer.d.ts +38 -0
  13. package/dist/agents/sessionLabeler.d.ts +97 -0
  14. package/dist/agents/shared.d.ts +189 -0
  15. package/dist/agents/subagentModels.d.ts +19 -0
  16. package/dist/agents/subagentToolGates.d.ts +55 -0
  17. package/dist/cli.mjs +197426 -0
  18. package/dist/external.d.ts +227 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.js +196783 -0
  21. package/dist/internal/index.d.ts +18 -0
  22. package/dist/internal.js +1714 -0
  23. package/dist/lifecycle.d.ts +2 -0
  24. package/dist/main.d.ts +8 -0
  25. package/dist/mcp/arkConfig.d.ts +1 -0
  26. package/dist/mcp/checkSuite.d.ts +25 -0
  27. package/dist/mcp/checkout.d.ts +77 -0
  28. package/dist/mcp/comment.d.ts +119 -0
  29. package/dist/mcp/commitInfo.d.ts +9 -0
  30. package/dist/mcp/crosswalk.d.ts +105 -0
  31. package/dist/mcp/dependencies.d.ts +8 -0
  32. package/dist/mcp/geminiSanitizer.d.ts +28 -0
  33. package/dist/mcp/git.d.ts +46 -0
  34. package/dist/mcp/guardrails.d.ts +104 -0
  35. package/dist/mcp/issue.d.ts +18 -0
  36. package/dist/mcp/issueComments.d.ts +9 -0
  37. package/dist/mcp/issueEvents.d.ts +9 -0
  38. package/dist/mcp/issueInfo.d.ts +9 -0
  39. package/dist/mcp/labels.d.ts +12 -0
  40. package/dist/mcp/localContext.d.ts +19 -0
  41. package/dist/mcp/moduleExtraction.d.ts +71 -0
  42. package/dist/mcp/moduleTests.d.ts +104 -0
  43. package/dist/mcp/modules.d.ts +179 -0
  44. package/dist/mcp/output.d.ts +12 -0
  45. package/dist/mcp/pathSafety.d.ts +14 -0
  46. package/dist/mcp/policy.d.ts +48 -0
  47. package/dist/mcp/pr.d.ts +49 -0
  48. package/dist/mcp/prInfo.d.ts +9 -0
  49. package/dist/mcp/providerSchema.d.ts +50 -0
  50. package/dist/mcp/review.d.ts +199 -0
  51. package/dist/mcp/reviewComments.d.ts +178 -0
  52. package/dist/mcp/roots.d.ts +58 -0
  53. package/dist/mcp/scope.d.ts +15 -0
  54. package/dist/mcp/selectMode.d.ts +18 -0
  55. package/dist/mcp/server.d.ts +48 -0
  56. package/dist/mcp/shared.d.ts +47 -0
  57. package/dist/mcp/shell.d.ts +37 -0
  58. package/dist/mcp/staleFix.d.ts +51 -0
  59. package/dist/mcp/terraform/cost.d.ts +55 -0
  60. package/dist/mcp/terraform/currency.d.ts +94 -0
  61. package/dist/mcp/terraform/decisions.d.ts +178 -0
  62. package/dist/mcp/terraform/findings.d.ts +75 -0
  63. package/dist/mcp/terraform/plan.d.ts +157 -0
  64. package/dist/mcp/terraform/scanners.d.ts +131 -0
  65. package/dist/mcp/terraform/tools.d.ts +63 -0
  66. package/dist/mcp/terraform/types.d.ts +172 -0
  67. package/dist/mcp/terraform.d.ts +22 -0
  68. package/dist/mcp/terratest.d.ts +83 -0
  69. package/dist/mcp/upload.d.ts +6 -0
  70. package/dist/models.d.ts +171 -0
  71. package/dist/modes.d.ts +26 -0
  72. package/dist/prep/index.d.ts +7 -0
  73. package/dist/prep/installNodeDependencies.d.ts +2 -0
  74. package/dist/prep/installPythonDependencies.d.ts +2 -0
  75. package/dist/prep/types.d.ts +31 -0
  76. package/dist/reviewQuality.d.ts +64 -0
  77. package/dist/skills/terraform-best-practices/SKILL.md +369 -0
  78. package/dist/toolState.d.ts +135 -0
  79. package/dist/utils/activity.d.ts +40 -0
  80. package/dist/utils/agent.d.ts +20 -0
  81. package/dist/utils/agentHangReport.d.ts +38 -0
  82. package/dist/utils/apiFetch.d.ts +19 -0
  83. package/dist/utils/apiKeys.d.ts +41 -0
  84. package/dist/utils/apiUrl.d.ts +20 -0
  85. package/dist/utils/assets.d.ts +8 -0
  86. package/dist/utils/billingErrors.d.ts +85 -0
  87. package/dist/utils/body.d.ts +34 -0
  88. package/dist/utils/buildTerramendFooter.d.ts +25 -0
  89. package/dist/utils/byokFallback.d.ts +85 -0
  90. package/dist/utils/claudeSubscription.d.ts +30 -0
  91. package/dist/utils/cli.d.ts +10 -0
  92. package/dist/utils/codexHome.d.ts +29 -0
  93. package/dist/utils/codexOAuth.d.ts +60 -0
  94. package/dist/utils/diffCoverage.d.ts +63 -0
  95. package/dist/utils/errorReport.d.ts +17 -0
  96. package/dist/utils/exitHandler.d.ts +8 -0
  97. package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
  98. package/dist/utils/gitAuth.d.ts +84 -0
  99. package/dist/utils/gitAuthServer.d.ts +24 -0
  100. package/dist/utils/github.d.ts +78 -0
  101. package/dist/utils/globals.d.ts +3 -0
  102. package/dist/utils/install.d.ts +60 -0
  103. package/dist/utils/instructions.d.ts +48 -0
  104. package/dist/utils/leapingComment.d.ts +11 -0
  105. package/dist/utils/learnings.d.ts +62 -0
  106. package/dist/utils/learningsTruncate.d.ts +25 -0
  107. package/dist/utils/lifecycle.d.ts +57 -0
  108. package/dist/utils/log.d.ts +111 -0
  109. package/dist/utils/normalizeEnv.d.ts +30 -0
  110. package/dist/utils/openCodeModels.d.ts +11 -0
  111. package/dist/utils/overrides.d.ts +40 -0
  112. package/dist/utils/packageManager.d.ts +49 -0
  113. package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
  114. package/dist/utils/payload.d.ts +105 -0
  115. package/dist/utils/prSummary.d.ts +61 -0
  116. package/dist/utils/progressComment.d.ts +146 -0
  117. package/dist/utils/providerErrors.d.ts +31 -0
  118. package/dist/utils/rangeDiff.d.ts +51 -0
  119. package/dist/utils/remediationCommand.d.ts +55 -0
  120. package/dist/utils/retry.d.ts +13 -0
  121. package/dist/utils/reviewCleanup.d.ts +14 -0
  122. package/dist/utils/run.d.ts +9 -0
  123. package/dist/utils/runContext.d.ts +60 -0
  124. package/dist/utils/runContextData.d.ts +23 -0
  125. package/dist/utils/runErrorRenderer.d.ts +64 -0
  126. package/dist/utils/runLifecycle.d.ts +86 -0
  127. package/dist/utils/runStartupLog.d.ts +15 -0
  128. package/dist/utils/secrets.d.ts +22 -0
  129. package/dist/utils/setup.d.ts +90 -0
  130. package/dist/utils/shell.d.ts +32 -0
  131. package/dist/utils/skills.d.ts +10 -0
  132. package/dist/utils/subprocess.d.ts +80 -0
  133. package/dist/utils/terraformMcp.d.ts +42 -0
  134. package/dist/utils/time.d.ts +15 -0
  135. package/dist/utils/timer.d.ts +23 -0
  136. package/dist/utils/todoTracking.d.ts +16 -0
  137. package/dist/utils/token.d.ts +39 -0
  138. package/dist/utils/version.d.ts +2 -0
  139. package/dist/utils/versioning.d.ts +7 -0
  140. package/dist/utils/vertex.d.ts +16 -0
  141. package/dist/utils/workflow.d.ts +13 -0
  142. package/package.json +119 -0
  143. package/src/agents/claude.test.ts +1016 -0
  144. package/src/agents/claude.ts +1246 -0
  145. package/src/agents/claudePretoolGate.test.ts +28 -0
  146. package/src/agents/claudePretoolGate.ts +173 -0
  147. package/src/agents/gateServer.test.ts +204 -0
  148. package/src/agents/gateServer.ts +124 -0
  149. package/src/agents/index.ts +10 -0
  150. package/src/agents/nativeFsDenies.ts +82 -0
  151. package/src/agents/opencode.test.ts +1440 -0
  152. package/src/agents/opencode.ts +1312 -0
  153. package/src/agents/opencodePlugin.ts +222 -0
  154. package/src/agents/opencodeShared.test.ts +34 -0
  155. package/src/agents/opencodeShared.ts +121 -0
  156. package/src/agents/postRun.test.ts +549 -0
  157. package/src/agents/postRun.ts +535 -0
  158. package/src/agents/reviewer.ts +104 -0
  159. package/src/agents/sessionLabeler.test.ts +247 -0
  160. package/src/agents/sessionLabeler.ts +178 -0
  161. package/src/agents/shared.test.ts +76 -0
  162. package/src/agents/shared.ts +292 -0
  163. package/src/agents/subagentModels.test.ts +113 -0
  164. package/src/agents/subagentModels.ts +40 -0
  165. package/src/agents/subagentRegistration.test.ts +41 -0
  166. package/src/agents/subagentToolGates.ts +114 -0
  167. package/src/cli.test.ts +129 -0
  168. package/src/cli.ts +105 -0
  169. package/src/commands/gha.test.ts +192 -0
  170. package/src/commands/gha.ts +188 -0
  171. package/src/commands/mcp.ts +122 -0
  172. package/src/config.ts +1 -0
  173. package/src/entry.ts +7 -0
  174. package/src/entryPost.stdlibOnly.test.ts +109 -0
  175. package/src/entryPost.ts +99 -0
  176. package/src/external.test.ts +16 -0
  177. package/src/external.ts +302 -0
  178. package/src/index.ts +11 -0
  179. package/src/internal/index.ts +71 -0
  180. package/src/lifecycle.ts +2 -0
  181. package/src/main.test.ts +873 -0
  182. package/src/main.ts +712 -0
  183. package/src/mcp/__fixtures__/terramend-scratch-pr-49-review-3485940013.json +110 -0
  184. package/src/mcp/__fixtures__/terramend-scratch-pr-64-review-3531000326.json +14 -0
  185. package/src/mcp/__fixtures__/terramend-test-repo-pr-1.diff.json +67 -0
  186. package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
  187. package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
  188. package/src/mcp/arkConfig.ts +7 -0
  189. package/src/mcp/checkSuite.test.ts +245 -0
  190. package/src/mcp/checkSuite.ts +255 -0
  191. package/src/mcp/checkout.test.ts +752 -0
  192. package/src/mcp/checkout.ts +886 -0
  193. package/src/mcp/comment.test.ts +772 -0
  194. package/src/mcp/comment.ts +582 -0
  195. package/src/mcp/commitInfo.test.ts +127 -0
  196. package/src/mcp/commitInfo.ts +61 -0
  197. package/src/mcp/crosswalk.test.ts +106 -0
  198. package/src/mcp/crosswalk.ts +339 -0
  199. package/src/mcp/dependencies.test.ts +309 -0
  200. package/src/mcp/dependencies.ts +189 -0
  201. package/src/mcp/geminiSanitizer.test.ts +287 -0
  202. package/src/mcp/geminiSanitizer.ts +207 -0
  203. package/src/mcp/git.test.ts +1083 -0
  204. package/src/mcp/git.ts +890 -0
  205. package/src/mcp/guardrails.test.ts +705 -0
  206. package/src/mcp/guardrails.ts +465 -0
  207. package/src/mcp/issue.test.ts +113 -0
  208. package/src/mcp/issue.ts +73 -0
  209. package/src/mcp/issueComments.test.ts +69 -0
  210. package/src/mcp/issueComments.ts +48 -0
  211. package/src/mcp/issueEvents.test.ts +134 -0
  212. package/src/mcp/issueEvents.ts +100 -0
  213. package/src/mcp/issueInfo.test.ts +104 -0
  214. package/src/mcp/issueInfo.ts +72 -0
  215. package/src/mcp/labels.test.ts +52 -0
  216. package/src/mcp/labels.ts +34 -0
  217. package/src/mcp/localContext.ts +28 -0
  218. package/src/mcp/localServer.test.ts +75 -0
  219. package/src/mcp/localServer.ts +131 -0
  220. package/src/mcp/moduleExtraction.test.ts +261 -0
  221. package/src/mcp/moduleExtraction.ts +313 -0
  222. package/src/mcp/moduleTests.test.ts +269 -0
  223. package/src/mcp/moduleTests.ts +421 -0
  224. package/src/mcp/modules.test.ts +640 -0
  225. package/src/mcp/modules.ts +696 -0
  226. package/src/mcp/output.test.ts +96 -0
  227. package/src/mcp/output.ts +70 -0
  228. package/src/mcp/pathSafety.test.ts +44 -0
  229. package/src/mcp/pathSafety.ts +28 -0
  230. package/src/mcp/policy.test.ts +282 -0
  231. package/src/mcp/policy.ts +199 -0
  232. package/src/mcp/pr.test.ts +387 -0
  233. package/src/mcp/pr.ts +194 -0
  234. package/src/mcp/prInfo.test.ts +96 -0
  235. package/src/mcp/prInfo.ts +91 -0
  236. package/src/mcp/providerSchema.test.ts +85 -0
  237. package/src/mcp/providerSchema.ts +175 -0
  238. package/src/mcp/review.test.ts +936 -0
  239. package/src/mcp/review.ts +923 -0
  240. package/src/mcp/reviewComments.test.ts +549 -0
  241. package/src/mcp/reviewComments.ts +896 -0
  242. package/src/mcp/roots.test.ts +175 -0
  243. package/src/mcp/roots.ts +217 -0
  244. package/src/mcp/scope.test.ts +59 -0
  245. package/src/mcp/scope.ts +65 -0
  246. package/src/mcp/security.test.ts +720 -0
  247. package/src/mcp/selectMode.test.ts +210 -0
  248. package/src/mcp/selectMode.ts +181 -0
  249. package/src/mcp/server.test.ts +292 -0
  250. package/src/mcp/server.ts +403 -0
  251. package/src/mcp/shared.ts +100 -0
  252. package/src/mcp/shell.test.ts +520 -0
  253. package/src/mcp/shell.ts +505 -0
  254. package/src/mcp/staleFix.test.ts +237 -0
  255. package/src/mcp/staleFix.ts +277 -0
  256. package/src/mcp/terraform/cost.ts +163 -0
  257. package/src/mcp/terraform/currency.test.ts +338 -0
  258. package/src/mcp/terraform/currency.ts +336 -0
  259. package/src/mcp/terraform/decisions.ts +527 -0
  260. package/src/mcp/terraform/findings.ts +333 -0
  261. package/src/mcp/terraform/plan.ts +348 -0
  262. package/src/mcp/terraform/scanners.ts +809 -0
  263. package/src/mcp/terraform/tools.test.ts +1071 -0
  264. package/src/mcp/terraform/tools.ts +908 -0
  265. package/src/mcp/terraform/types.ts +305 -0
  266. package/src/mcp/terraform.test.ts +1957 -0
  267. package/src/mcp/terraform.ts +23 -0
  268. package/src/mcp/terratest.test.ts +105 -0
  269. package/src/mcp/terratest.ts +196 -0
  270. package/src/mcp/toolFiltering.test.ts +85 -0
  271. package/src/mcp/upload.test.ts +180 -0
  272. package/src/mcp/upload.ts +112 -0
  273. package/src/models.test.ts +300 -0
  274. package/src/models.ts +708 -0
  275. package/src/modes.test.ts +107 -0
  276. package/src/modes.ts +880 -0
  277. package/src/prep/index.ts +43 -0
  278. package/src/prep/installNodeDependencies.test.ts +298 -0
  279. package/src/prep/installNodeDependencies.ts +196 -0
  280. package/src/prep/installPythonDependencies.test.ts +268 -0
  281. package/src/prep/installPythonDependencies.ts +199 -0
  282. package/src/prep/types.ts +38 -0
  283. package/src/reviewQuality.test.ts +63 -0
  284. package/src/reviewQuality.ts +134 -0
  285. package/src/runCli.test.ts +214 -0
  286. package/src/runCli.ts +282 -0
  287. package/src/skills/terraform-best-practices/SKILL.md +369 -0
  288. package/src/toolState.test.ts +45 -0
  289. package/src/toolState.ts +252 -0
  290. package/src/utils/activity.test.ts +188 -0
  291. package/src/utils/activity.ts +210 -0
  292. package/src/utils/agent.test.ts +251 -0
  293. package/src/utils/agent.ts +139 -0
  294. package/src/utils/agentHangReport.test.ts +203 -0
  295. package/src/utils/agentHangReport.ts +170 -0
  296. package/src/utils/apiFetch.test.ts +115 -0
  297. package/src/utils/apiFetch.ts +62 -0
  298. package/src/utils/apiKeys.test.ts +344 -0
  299. package/src/utils/apiKeys.ts +206 -0
  300. package/src/utils/apiUrl.test.ts +30 -0
  301. package/src/utils/apiUrl.ts +59 -0
  302. package/src/utils/assets.test.ts +153 -0
  303. package/src/utils/assets.ts +107 -0
  304. package/src/utils/billingErrors.test.ts +121 -0
  305. package/src/utils/billingErrors.ts +189 -0
  306. package/src/utils/body.test.ts +217 -0
  307. package/src/utils/body.ts +168 -0
  308. package/src/utils/buildTerramendFooter.test.ts +38 -0
  309. package/src/utils/buildTerramendFooter.ts +82 -0
  310. package/src/utils/byokFallback.test.ts +205 -0
  311. package/src/utils/byokFallback.ts +128 -0
  312. package/src/utils/claudeSubscription.test.ts +179 -0
  313. package/src/utils/claudeSubscription.ts +93 -0
  314. package/src/utils/cli.ts +31 -0
  315. package/src/utils/codexHome.test.ts +190 -0
  316. package/src/utils/codexHome.ts +191 -0
  317. package/src/utils/codexOAuth.ts +147 -0
  318. package/src/utils/codexRefreshDetect.test.ts +85 -0
  319. package/src/utils/codexRefreshDetect.ts +35 -0
  320. package/src/utils/diffCoverage.test.ts +468 -0
  321. package/src/utils/diffCoverage.ts +404 -0
  322. package/src/utils/errorReport.test.ts +135 -0
  323. package/src/utils/errorReport.ts +83 -0
  324. package/src/utils/exitHandler.ts +35 -0
  325. package/src/utils/fixDoubleEscapedString.ts +9 -0
  326. package/src/utils/ghaCore.ts +13 -0
  327. package/src/utils/gitAuth.test.ts +322 -0
  328. package/src/utils/gitAuth.ts +263 -0
  329. package/src/utils/gitAuthServer.test.ts +260 -0
  330. package/src/utils/gitAuthServer.ts +182 -0
  331. package/src/utils/github.test.ts +615 -0
  332. package/src/utils/github.ts +538 -0
  333. package/src/utils/globals.ts +9 -0
  334. package/src/utils/humanEditCapture.test.ts +100 -0
  335. package/src/utils/humanEditCapture.ts +193 -0
  336. package/src/utils/install.test.ts +768 -0
  337. package/src/utils/install.ts +492 -0
  338. package/src/utils/instructions.test.ts +240 -0
  339. package/src/utils/instructions.ts +543 -0
  340. package/src/utils/leapingComment.test.ts +51 -0
  341. package/src/utils/leapingComment.ts +18 -0
  342. package/src/utils/learnings.test.ts +87 -0
  343. package/src/utils/learnings.ts +138 -0
  344. package/src/utils/learningsTocRender.test.ts +116 -0
  345. package/src/utils/learningsTruncate.test.ts +39 -0
  346. package/src/utils/learningsTruncate.ts +42 -0
  347. package/src/utils/lifecycle.test.ts +195 -0
  348. package/src/utils/lifecycle.ts +198 -0
  349. package/src/utils/log.test.ts +402 -0
  350. package/src/utils/log.ts +432 -0
  351. package/src/utils/normalizeEnv.test.ts +91 -0
  352. package/src/utils/normalizeEnv.ts +106 -0
  353. package/src/utils/openCodeModels.ts +82 -0
  354. package/src/utils/overrides.test.ts +89 -0
  355. package/src/utils/overrides.ts +98 -0
  356. package/src/utils/packageManager.test.ts +321 -0
  357. package/src/utils/packageManager.ts +257 -0
  358. package/src/utils/patchWorkflowRunFields.test.ts +92 -0
  359. package/src/utils/patchWorkflowRunFields.ts +150 -0
  360. package/src/utils/payload.test.ts +497 -0
  361. package/src/utils/payload.ts +371 -0
  362. package/src/utils/postApiFetch.ts +51 -0
  363. package/src/utils/prSummary.test.ts +224 -0
  364. package/src/utils/prSummary.ts +147 -0
  365. package/src/utils/progressComment.ts +261 -0
  366. package/src/utils/providerErrors.test.ts +315 -0
  367. package/src/utils/providerErrors.ts +172 -0
  368. package/src/utils/rangeDiff.test.ts +236 -0
  369. package/src/utils/rangeDiff.ts +182 -0
  370. package/src/utils/remediationCommand.test.ts +163 -0
  371. package/src/utils/remediationCommand.ts +119 -0
  372. package/src/utils/retry.test.ts +153 -0
  373. package/src/utils/retry.ts +58 -0
  374. package/src/utils/reviewCleanup.ts +106 -0
  375. package/src/utils/run.ts +99 -0
  376. package/src/utils/runContext.ts +145 -0
  377. package/src/utils/runContextData.ts +58 -0
  378. package/src/utils/runErrorRenderer.test.ts +95 -0
  379. package/src/utils/runErrorRenderer.ts +259 -0
  380. package/src/utils/runFixture.ts +76 -0
  381. package/src/utils/runLifecycle.ts +237 -0
  382. package/src/utils/runStartupLog.ts +60 -0
  383. package/src/utils/secrets.test.ts +103 -0
  384. package/src/utils/secrets.ts +177 -0
  385. package/src/utils/setup.test.ts +509 -0
  386. package/src/utils/setup.ts +352 -0
  387. package/src/utils/shell.ts +103 -0
  388. package/src/utils/skills.test.ts +46 -0
  389. package/src/utils/skills.ts +67 -0
  390. package/src/utils/subprocess.test.ts +170 -0
  391. package/src/utils/subprocess.ts +438 -0
  392. package/src/utils/terraformMcp.test.ts +63 -0
  393. package/src/utils/terraformMcp.ts +83 -0
  394. package/src/utils/time.test.ts +105 -0
  395. package/src/utils/time.ts +59 -0
  396. package/src/utils/timer.test.ts +91 -0
  397. package/src/utils/timer.ts +72 -0
  398. package/src/utils/todoTracking.test.ts +223 -0
  399. package/src/utils/todoTracking.ts +167 -0
  400. package/src/utils/token.test.ts +239 -0
  401. package/src/utils/token.ts +186 -0
  402. package/src/utils/version.ts +10 -0
  403. package/src/utils/versioning.test.ts +34 -0
  404. package/src/utils/versioning.ts +44 -0
  405. package/src/utils/vertex.ts +85 -0
  406. package/src/utils/workflow.ts +25 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Pure-stdlib (fetch + Buffer) Codex OAuth refresh + JWT exp decoding.
3
+ *
4
+ * Lives here (not in codexAuth.ts) so the Next.js server side can import it
5
+ * via terramend/internal without dragging in node:child_process / spawn /
6
+ * mkdtemp from the rest of codexAuth.ts. Used by:
7
+ * - action/utils/codexAuth.ts (re-exports refreshCodexAuthBody)
8
+ * - utils/codexSecretRotation.ts (server-side maybeRotate at run-context)
9
+ *
10
+ * See wiki/codex-auth.md for the end-to-end refresh lifecycle.
11
+ */
12
+ export interface CodexAuthBody {
13
+ auth_mode: "chatgpt";
14
+ tokens: {
15
+ access_token: string;
16
+ refresh_token: string;
17
+ id_token?: string;
18
+ account_id?: string;
19
+ };
20
+ last_refresh?: string;
21
+ }
22
+ /** OAuth client id Codex CLI and OpenCode both use against `auth.openai.com`.
23
+ * Same chain — a refresh token minted via `codex login --device-auth` can be
24
+ * refreshed against this client_id. */
25
+ export declare const CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
26
+ export declare const CODEX_OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token";
27
+ /** thrown when the OAuth provider rejects the refresh token (4xx). callers
28
+ * can distinguish "race-lost / token revoked" from network errors via
29
+ * `instanceof OAuthInvalidGrantError`. */
30
+ export declare class OAuthInvalidGrantError extends Error {
31
+ readonly status: number;
32
+ constructor(status: number, body: string);
33
+ }
34
+ /** force one refresh round-trip against the OAuth provider. returns the
35
+ * rotated Codex-shaped blob (the auth.json body verbatim). does NOT persist
36
+ * — caller is responsible for writing back to wherever the token lives.
37
+ *
38
+ * server-side callers (maybeRotateCodexSecret) hold a DB row lock around
39
+ * this call so concurrent runs serialize: first one rotates, subsequent
40
+ * ones see the fresh value and skip. The 10s timeout is critical for that
41
+ * use: it caps how long a stalled auth.openai.com holds the row lock,
42
+ * keeping us well under the enclosing 30s transaction budget so the lock
43
+ * always releases and queued callers get a turn instead of timing out on
44
+ * the tx wrapper. Real OAuth latency is sub-second; 10s is generous. */
45
+ export declare function refreshCodexAuthBody(body: CodexAuthBody): Promise<CodexAuthBody>;
46
+ /** decode the access_token's JWT payload and return its `exp` claim in ms
47
+ * since epoch. returns null if the token isn't a parseable JWT or has no
48
+ * `exp` claim — caller falls back to "treat as expired".
49
+ *
50
+ * We don't verify the JWT signature (we'd need OpenAI's JWKS); we're only
51
+ * using the claim as a freshness hint. The actual auth check happens
52
+ * server-side at OpenAI when the token is used — trusting a fake JWT here
53
+ * would just delay the inevitable 401 from OpenAI. No security boundary
54
+ * at this decode step. */
55
+ export declare function decodeJwtExpMs(token: string): number | null;
56
+ /** parse + validate a Codex auth.json body from its JSON-string form.
57
+ * returns null on any shape mismatch — caller treats as "no codex auth". */
58
+ export declare function parseCodexAuthBody(raw: string): CodexAuthBody | null;
59
+ /** serialize a CodexAuthBody to its canonical on-disk form. */
60
+ export declare function stringifyCodexAuthBody(body: CodexAuthBody): string;
@@ -0,0 +1,63 @@
1
+ export type DiffLineRange = {
2
+ startLine: number;
3
+ endLine: number;
4
+ };
5
+ export type DiffTocEntry = {
6
+ filename: string;
7
+ startLine: number;
8
+ endLine: number;
9
+ };
10
+ export type DiffCoverageFileBreakdown = {
11
+ filename: string;
12
+ startLine: number;
13
+ endLine: number;
14
+ totalLines: number;
15
+ coveredLines: number;
16
+ coveredRanges: DiffLineRange[];
17
+ unreadRanges: DiffLineRange[];
18
+ };
19
+ export type DiffCoverageBreakdown = {
20
+ totalLines: number;
21
+ coveredLines: number;
22
+ unreadLines: number;
23
+ coveragePercent: number;
24
+ coveredRanges: DiffLineRange[];
25
+ unreadRanges: DiffLineRange[];
26
+ files: DiffCoverageFileBreakdown[];
27
+ };
28
+ export type DiffCoverageState = {
29
+ diffPath: string;
30
+ totalLines: number;
31
+ tocEntries: DiffTocEntry[];
32
+ coveredRanges: DiffLineRange[];
33
+ coveragePreflightRan: boolean;
34
+ lastBreakdown?: string | undefined;
35
+ };
36
+ export declare function countLines(params: {
37
+ content: string;
38
+ }): number;
39
+ export declare function parseDiffTocEntries(params: {
40
+ toc: string;
41
+ }): DiffTocEntry[];
42
+ export declare function createDiffCoverageState(params: {
43
+ diffPath: string;
44
+ totalLines: number;
45
+ toc: string;
46
+ previous?: DiffCoverageState | undefined;
47
+ }): DiffCoverageState;
48
+ export declare function recordDiffReadFromToolUse(params: {
49
+ state: DiffCoverageState | undefined;
50
+ toolName: string;
51
+ input: unknown;
52
+ cwd: string;
53
+ }): boolean;
54
+ export declare function getDiffCoverageBreakdown(params: {
55
+ state: DiffCoverageState;
56
+ }): DiffCoverageBreakdown;
57
+ export declare function renderDiffCoverageBreakdown(params: {
58
+ diffPath: string;
59
+ breakdown: DiffCoverageBreakdown;
60
+ }): string;
61
+ export declare function countLinesInRanges(params: {
62
+ ranges: DiffLineRange[];
63
+ }): number;
@@ -0,0 +1,17 @@
1
+ import type { ToolState } from "#app/toolState";
2
+ interface ReportErrorParams {
3
+ toolState: ToolState;
4
+ error: string;
5
+ title?: string;
6
+ /**
7
+ * When the run has no pre-existing progress comment to update (silent
8
+ * IncrementalReview / pull_request_synchronize, mode-less polls), create
9
+ * a fresh issue comment on `toolState.issueNumber` instead of returning
10
+ * silently. Used for terminal errors (BillingError, TransientError) where
11
+ * the GH job summary is the only other surface and most users never open
12
+ * it. see #775.
13
+ */
14
+ createIfMissing?: boolean;
15
+ }
16
+ export declare function reportErrorToComment(ctx: ReportErrorParams): Promise<void>;
17
+ export {};
@@ -0,0 +1,8 @@
1
+ type ExitSignalHandler = (signal: "SIGINT" | "SIGTERM") => void | Promise<void>;
2
+ /**
3
+ * Register a handler to run when the process receives SIGINT or SIGTERM.
4
+ * Returns a dispose function that removes the handler.
5
+ */
6
+ export declare function onExitSignal(handler: ExitSignalHandler): () => void;
7
+ export declare function exitWithSignal(signal: "SIGINT" | "SIGTERM"): void;
8
+ export {};
@@ -0,0 +1 @@
1
+ export declare function fixDoubleEscapedString(str: string): string;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * git authentication via GIT_ASKPASS.
3
+ *
4
+ * a localhost HTTP server serves tokens via UUID codes whose lifetime is
5
+ * bounded by the parent $git() invocation: register() makes the code active,
6
+ * the script (and any sibling subprocess — e.g. git-lfs pre-push) can fetch
7
+ * the token any number of times, and $git()'s finally calls revoke() to
8
+ * close the window. each $git() call writes a unique askpass script with
9
+ * the server port+code baked into the file body — no secrets in subprocess
10
+ * env. a replay of a revoked code trips a 409 and revokes the underlying
11
+ * github installation token.
12
+ *
13
+ * see wiki/askpass.md for full security documentation.
14
+ */
15
+ import type { GitAuthServer } from "#app/utils/gitAuthServer";
16
+ type SafeGitSubcommand = "fetch" | "push";
17
+ type GitAuthOptions = {
18
+ token: string;
19
+ cwd?: string;
20
+ disableHooks?: boolean;
21
+ };
22
+ type GitResult = {
23
+ stdout: string;
24
+ stderr: string;
25
+ };
26
+ /**
27
+ * resolve and fingerprint the git binary. must be called once at startup
28
+ * (in main()) before any agent code runs, so the path and hash reflect
29
+ * the untampered binary.
30
+ *
31
+ * resolves symlinks via realpath so the hash is of the actual binary.
32
+ * a malicious agent with sudo could replace the binary later, which is
33
+ * caught by verifyGitBinary() before each authenticated call.
34
+ */
35
+ export declare function resolveGit(): void;
36
+ export declare function setGitAuthServer(server: GitAuthServer): void;
37
+ /**
38
+ * execute authenticated git command via ASKPASS.
39
+ *
40
+ * subcommand is restricted to "fetch" | "push" — operations that talk to
41
+ * a remote and need credentials. working-tree operations (checkout, merge)
42
+ * use $() from shell.ts which has no token.
43
+ *
44
+ * per call: registers a code with the auth server (valid for the lifetime
45
+ * of this invocation), writes a unique askpass script with port+code baked
46
+ * in, spawns git with GIT_ASKPASS pointing to the script. on completion,
47
+ * revokes the code and deletes the script in finally. multiple sibling
48
+ * askpass calls within one invocation (e.g. git itself + git-lfs pre-push)
49
+ * all see a valid code; replay attempts after finally trip a 409 and the
50
+ * server revokes the underlying github token as a tamper signal.
51
+ *
52
+ * @example
53
+ * await $git("fetch", ["origin", "main"], { token });
54
+ * await $git("push", ["-u", "origin", "feature"], { token });
55
+ */
56
+ export declare function $git(subcommand: SafeGitSubcommand, args: string[], options: GitAuthOptions): Promise<GitResult>;
57
+ /**
58
+ * shallow-clone unreachable: when an existing local depth is too shallow for
59
+ * git to traverse to the requested ref's ancestry, the remote walk fails with
60
+ * one of these wordings (git emits the full OID via oid_to_hex, so the bound
61
+ * is 40 for SHA-1 or 64 for SHA-256). detecting both lets a single deepen
62
+ * retry recover before the error reaches the agent — see issue #564 for the
63
+ * original `git_fetch` precedent and #656 for the `checkout_pr` follow-up.
64
+ */
65
+ export declare const SHALLOW_UNREACHABLE_PATTERNS: RegExp[];
66
+ /**
67
+ * large enough to clear the merge base on most real-world PRs without
68
+ * downloading the full history; matches the fallback used by
69
+ * `checkoutPrBranch` when the GitHub compare API is unavailable.
70
+ */
71
+ export declare const DEEPEN_RETRY_DEPTH = 1000;
72
+ /**
73
+ * authenticated `git fetch` that recovers from shallow-unreachable errors
74
+ * by retrying once with `--deepen=1000`. callers pass the same args they
75
+ * would to `$git("fetch", ...)`; on shallow-unreachable failures in a
76
+ * shallow repo, the second attempt prepends `--deepen=N` and strips any
77
+ * caller-supplied `--depth=` (the two flags are mutually exclusive, and
78
+ * the caller's depth is what got us into this mess).
79
+ *
80
+ * non-shallow-unreachable errors and non-shallow repos rethrow unchanged,
81
+ * so this is safe to wrap any fetch without changing fast-path behavior.
82
+ */
83
+ export declare function $gitFetchWithDeepen(args: string[], options: GitAuthOptions, label?: string): Promise<GitResult>;
84
+ export {};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ASKPASS-based git authentication server.
3
+ *
4
+ * serves tokens via a localhost HTTP server with per-$git()-call UUID codes.
5
+ * each $git() call gets a unique askpass script with the port+code baked in.
6
+ * the token never appears in subprocess env — only the script file path.
7
+ *
8
+ * lifetime: the code is valid for as long as the $git() invocation is
9
+ * running. multiple askpass calls within one invocation (e.g. git's own
10
+ * fetch/push + a git-lfs pre-push hook that also authenticates) all
11
+ * succeed. $git() calls revoke(code) in finally; subsequent requests for
12
+ * a revoked code trigger immediate token revocation via the GitHub API
13
+ * as a tamper-evidence precaution (an agent replaying the code after the
14
+ * legitimate window has closed is the realistic attack we still catch).
15
+ */
16
+ export type GitAuthServer = {
17
+ port: number;
18
+ register: (token: string) => string;
19
+ revoke: (code: string) => void;
20
+ writeAskpassScript: (code: string) => string;
21
+ close: () => Promise<void>;
22
+ [Symbol.asyncDispose]: () => Promise<void>;
23
+ };
24
+ export declare function startGitAuthServer(tmpdir: string): Promise<GitAuthServer>;
@@ -0,0 +1,78 @@
1
+ import { throttling } from "@octokit/plugin-throttling";
2
+ import { Octokit } from "@octokit/rest";
3
+ export interface InstallationToken {
4
+ token: string;
5
+ expires_at: string;
6
+ installation_id: number;
7
+ repository: string;
8
+ ref: string;
9
+ runner_environment: string;
10
+ owner?: string;
11
+ }
12
+ type ReadWrite = "read" | "write";
13
+ type WriteOnly = "write";
14
+ /**
15
+ * GitHub App installation access token permissions.
16
+ * passed to `POST /app/installations/{id}/access_tokens` to scope the token.
17
+ * fields and allowed values come from the `app-permissions` OpenAPI schema.
18
+ * @see https://docs.github.com/en/rest/apps/installations#create-an-installation-access-token-for-an-app
19
+ * @see https://github.com/github/rest-api-description — components.schemas.app-permissions
20
+ */
21
+ type GitHubAppPermissions = {
22
+ actions?: ReadWrite;
23
+ artifact_metadata?: ReadWrite;
24
+ attestations?: ReadWrite;
25
+ checks?: ReadWrite;
26
+ contents?: ReadWrite;
27
+ deployments?: ReadWrite;
28
+ discussions?: ReadWrite;
29
+ issues?: ReadWrite;
30
+ packages?: ReadWrite;
31
+ pages?: ReadWrite;
32
+ pull_requests?: ReadWrite;
33
+ security_events?: ReadWrite;
34
+ statuses?: ReadWrite;
35
+ workflows?: WriteOnly;
36
+ };
37
+ type AcquireTokenOptions = {
38
+ repos?: string[];
39
+ permissions?: GitHubAppPermissions;
40
+ };
41
+ /**
42
+ * ensure a GitHub token is available in the environment.
43
+ *
44
+ * when OIDC is available (CI), always mints a fresh token scoped to
45
+ * GITHUB_REPOSITORY — overriding any inherited GITHUB_TOKEN that may
46
+ * be scoped to the wrong repo.
47
+ *
48
+ * otherwise falls back to GitHub App credentials for local development.
49
+ *
50
+ * only called from dev-run.ts (test/dev path) — the live action calls
51
+ * main() directly and never calls this.
52
+ */
53
+ export declare function ensureGitHubToken(): Promise<void>;
54
+ export declare function acquireNewToken(opts?: AcquireTokenOptions): Promise<string>;
55
+ export interface RepoContext {
56
+ owner: string;
57
+ name: string;
58
+ }
59
+ /**
60
+ * Parse repository context from GITHUB_REPOSITORY environment variable.
61
+ */
62
+ export declare function parseRepoContext(): RepoContext;
63
+ export type OctokitWithPlugins = InstanceType<ReturnType<typeof Octokit.plugin<typeof Octokit, [typeof throttling]>>>;
64
+ export interface ResourceUsage {
65
+ requestCount: number;
66
+ rateLimitRemaining: number | null;
67
+ rateLimitResetMs: number | null;
68
+ }
69
+ export interface UsageSummary {
70
+ version: 1;
71
+ github: {
72
+ core: ResourceUsage;
73
+ graphql: ResourceUsage;
74
+ };
75
+ }
76
+ export declare function writeGitHubUsageSummaryToFile(path: string): Promise<void>;
77
+ export declare function createOctokit(token: string): OctokitWithPlugins;
78
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare const isCloudflareSandbox: boolean;
2
+ export declare const isGitHubActions: boolean;
3
+ export declare const isInsideDocker: boolean;
@@ -0,0 +1,60 @@
1
+ export interface InstallFromNpmTarballParams {
2
+ packageName: string;
3
+ version: string;
4
+ executablePath: string;
5
+ installDependencies?: boolean;
6
+ }
7
+ export interface InstallFromCurlParams {
8
+ installUrl: string;
9
+ executableName: string;
10
+ }
11
+ export interface InstallFromDirectTarballParams {
12
+ url: string;
13
+ executablePath: string;
14
+ stripComponents?: number;
15
+ }
16
+ export interface InstallFromGithubParams {
17
+ owner: string;
18
+ repo: string;
19
+ tag?: string;
20
+ assetName?: string;
21
+ executablePath?: string;
22
+ githubInstallationToken?: string;
23
+ }
24
+ export interface InstallFromGithubTarballParams {
25
+ owner: string;
26
+ repo: string;
27
+ tag?: string;
28
+ assetNamePattern: string;
29
+ executablePath: string;
30
+ githubInstallationToken?: string;
31
+ }
32
+ /**
33
+ * Install a CLI tool from an npm package tarball
34
+ * Downloads the tarball, extracts it to a temp directory, and returns the path to the CLI executable
35
+ * The temp directory will be cleaned up by the OS automatically
36
+ */
37
+ export declare function installFromNpmTarball(params: InstallFromNpmTarballParams): Promise<string>;
38
+ /**
39
+ * Install a CLI tool from GitHub releases
40
+ * Downloads the latest release asset from GitHub and returns the path to the executable
41
+ * The temp directory will be cleaned up by the OS automatically
42
+ */
43
+ export declare function installFromGithub(params: InstallFromGithubParams): Promise<string>;
44
+ /**
45
+ * Install a CLI tool from a GitHub release tarball
46
+ * Downloads the tar.gz from GitHub releases, extracts it, and returns the path to the CLI executable
47
+ * The temp directory will be cleaned up by the OS automatically
48
+ */
49
+ export declare function installFromGithubTarball(params: InstallFromGithubTarballParams): Promise<string>;
50
+ /**
51
+ * Install a CLI tool from a direct tarball URL.
52
+ * Downloads the tarball, extracts it to a temp directory, and returns the path to the CLI executable.
53
+ */
54
+ export declare function installFromDirectTarball(params: InstallFromDirectTarballParams): Promise<string>;
55
+ /**
56
+ * Install a CLI tool from a curl-based install script
57
+ * Downloads the install script, runs it with HOME set to temp directory, and returns the path to the CLI executable
58
+ * The temp directory will be cleaned up by the OS automatically
59
+ */
60
+ export declare function installFromCurl(params: InstallFromCurlParams): Promise<string>;
@@ -0,0 +1,48 @@
1
+ import { type AgentId } from "#app/external";
2
+ import type { Mode } from "#app/modes";
3
+ import type { ResolvedPayload } from "#app/utils/payload";
4
+ import type { LearningsHeading } from "#app/utils/runContext";
5
+ import type { RunContextData } from "#app/utils/runContextData";
6
+ interface InstructionsContext {
7
+ payload: ResolvedPayload;
8
+ repo: RunContextData["repo"];
9
+ modes: Mode[];
10
+ agentId: AgentId;
11
+ outputSchema?: Record<string, unknown> | undefined;
12
+ /** absolute path to the seeded learnings tmpfile, or null when the file
13
+ * couldn't be seeded for some reason. main.ts always seeds, so in
14
+ * practice this is always set; the null case keeps the type honest. */
15
+ learningsFilePath: string | null;
16
+ /** server-parsed TOC for the body of the learnings tmpfile. rendered
17
+ * inline into the LEARNINGS prompt section so the agent can `read_file`
18
+ * targeted line ranges instead of pulling the whole file into context. */
19
+ learningsHeadings: LearningsHeading[];
20
+ /** agent-facing description of a setup lifecycle hook failure (see
21
+ * `describeSetupFailure`), rendered as a SETUP HOOK FAILED banner. empty
22
+ * string when the hook succeeded, was skipped, or wasn't configured. */
23
+ setupHookFailure: string;
24
+ }
25
+ export interface ResolvedInstructions {
26
+ full: string;
27
+ system: string;
28
+ user: string;
29
+ eventInstructions: string;
30
+ event: string;
31
+ runtime: string;
32
+ }
33
+ /** render the heading list as an indented bullet TOC. ranges shown in
34
+ * parentheses (`(L3-L18)`); the start line is always the heading line
35
+ * itself, so reading the listed range gives the agent the heading +
36
+ * body together. shallowest heading depth in the body sits at the root
37
+ * column; deeper levels indent by `(depth - rootDepth) * 2` spaces. */
38
+ export declare function renderLearningsToc(headings: LearningsHeading[]): string;
39
+ /** assemble the LEARNINGS prompt section: file path + intro + either
40
+ * the rendered heading TOC (when the body has structure) or a no-headings
41
+ * affordance pointing the agent at the reflection turn for restructuring.
42
+ * empty string when the seed step failed and there's no path to surface. */
43
+ export declare function buildLearningsSection(ctx: {
44
+ filePath: string | null;
45
+ headings: LearningsHeading[];
46
+ }): string;
47
+ export declare function resolveInstructions(ctx: InstructionsContext): ResolvedInstructions;
48
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The prefix text for the initial "leaping into action" comment.
3
+ * Used to detect whether a progress comment is still in its initial state
4
+ * and hasn't been updated with real progress or error messages.
5
+ *
6
+ * Lives in `utils/` (not `mcp/`) so it can be re-exported via `terramend/internal`
7
+ * without dragging the MCP server's transitive imports into the Next.js app's
8
+ * type-check graph.
9
+ */
10
+ export declare const LEAPING_INTO_ACTION_PREFIX = "Leaping into action";
11
+ export declare function isLeapingIntoActionCommentBody(body: string): boolean;
@@ -0,0 +1,62 @@
1
+ import type { ToolContext } from "#app/mcp/server";
2
+ import { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary } from "#app/utils/learningsTruncate";
3
+ export { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary };
4
+ /**
5
+ * Repo-level learnings — operational facts about a repo (setup steps, test
6
+ * commands, conventions, gotchas) that accumulate across agent runs and feed
7
+ * back into future runs as durable context. Modeled on the PR-summary tmpfile
8
+ * pattern (see action/utils/prSummary.ts):
9
+ *
10
+ * 1. server seeds `terramend-learnings.md` with the verbatim body of
11
+ * `Repo.learnings` (or empty for fresh repos), and parses headings
12
+ * server-side (`utils/learningsToc.ts`) — the parsed TOC is rendered
13
+ * into the LEARNINGS prompt section, not into the file
14
+ * 2. the agent reads the TOC in the prompt and uses listed line ranges
15
+ * to read just the sections relevant to the current task — file can
16
+ * grow large, but only targeted ranges hit the agent's context
17
+ * 3. agent edits the file in place at end-of-run during the reflection
18
+ * turn (see action/agents/postRun.ts buildLearningsReflectionPrompt)
19
+ * 4. main.ts reads the file back at end-of-run and PATCHes
20
+ * `/api/repo/[owner]/[repo]/learnings` if the body changed
21
+ *
22
+ * Edit-in-place avoids stuffing the entire learnings list into both the
23
+ * prompt context and an `update_learnings` MCP tool call (which previously
24
+ * required passing the FULL merged list as a string parameter — an
25
+ * output-token tax that grew linearly with the learnings size).
26
+ *
27
+ * Section structure is agent-curated. The reflection prompt teaches
28
+ * hierarchy + a soft 300-line-per-section cap to keep TOC ranges
29
+ * agent-targetable on long-lived repos; there is no fixed taxonomy.
30
+ */
31
+ export declare const LEARNINGS_FILE_NAME = "terramend-learnings.md";
32
+ export declare function learningsFilePath(tmpdir: string): string;
33
+ /** seed the rolling learnings tmpfile with the verbatim DB body (or empty
34
+ * string for fresh repos). returns the absolute path. the parsed TOC is
35
+ * carried separately via `RepoSettings.learningsHeadings` and rendered
36
+ * into the prompt by `resolveInstructions`, so the file on disk is just
37
+ * the body — no markers, no scaffold, no in-file TOC. */
38
+ export declare function seedLearningsFile(params: {
39
+ tmpdir: string;
40
+ current: string | null;
41
+ }): Promise<string>;
42
+ /** read the agent-edited learnings file. returns null when the file is
43
+ * missing or unreadable (treated as "no change"). caps content at the
44
+ * server's max length to avoid a 400 round-trip. */
45
+ export declare function readLearningsFile(path: string): Promise<string | null>;
46
+ /**
47
+ * Read the agent-edited repo-level learnings tmpfile and PATCH it to
48
+ * `Repo.learnings`.
49
+ *
50
+ * Best-effort: any failure is logged and does not affect the run's success
51
+ * status. Skips the PATCH when the file is byte-trim-identical to its seed —
52
+ * the agent didn't touch it, so writing the same content back would just
53
+ * burn a `LearningsRevision` row and an API round-trip.
54
+ *
55
+ * `ctx.toolState.model` is forwarded so `LearningsRevision.model` keeps
56
+ * populating; it powers the per-revision attribution badge in the UI
57
+ * history view.
58
+ *
59
+ * `learningsPersistAttempted` guards against double-execution between the
60
+ * normal end-of-run path and the SIGINT/SIGTERM handler.
61
+ */
62
+ export declare function persistLearnings(ctx: ToolContext): Promise<void>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * pure string helpers for capping and line-boundary-truncating the
3
+ * `Repo.learnings` body. lives in its own module (vs alongside
4
+ * `learnings.ts`) so the proprietary root app can re-export it through
5
+ * `action/internal/index.ts` without dragging the entire MCP type graph
6
+ * along — `learnings.ts` imports `ToolContext` for its runtime helpers,
7
+ * and pulling that into the SDK-facing `internal` barrel expands the
8
+ * type graph reachable from root `tsc` and `cf-worker-indexing` to every
9
+ * tool module under `action/mcp/`. keeping these helpers MCP-free is the
10
+ * cheap structural fix.
11
+ *
12
+ * see `action/utils/learnings.ts` for the full learnings-file lifecycle.
13
+ */
14
+ /** maximum size of `Repo.learnings` body in chars. action truncates the
15
+ * read-back BEFORE the PATCH to avoid sending an oversized payload; the
16
+ * server applies the same truncation as a defense-in-depth backstop (any
17
+ * caller that misses the client-side step would otherwise persist a
18
+ * mid-line tail, breaking the next-run TOC parse).
19
+ *
20
+ * raised from 10k → 100k once the TOC affordance landed: with line-range
21
+ * reads via the server-parsed TOC the agent doesn't ingest the whole
22
+ * file, so the cap is governed by curation discipline rather than a
23
+ * tight byte ceiling. 100k holds ~400-500 short bullets. */
24
+ export declare const MAX_LEARNINGS_LENGTH = 100000;
25
+ export declare function truncateAtLineBoundary(body: string, cap: number): string;
@@ -0,0 +1,57 @@
1
+ export interface ExecuteLifecycleHookParams {
2
+ event: string;
3
+ script: string | null;
4
+ /**
5
+ * when true, after the hook runs (success or failure), discard tracked-file
6
+ * mods so the agent doesn't see hook-generated drift (e.g. `pnpm install`
7
+ * rewriting a lockfile). untracked files are preserved — hooks that
8
+ * intentionally materialize files (e.g. a `.env` from a template) stay
9
+ * visible to the agent. skipped (with a warning) if the tree had
10
+ * pre-existing tracked changes before the hook ran, so we never clobber
11
+ * pre-existing work; pre-existing untracked files are ignored for this
12
+ * gate because `git restore --staged --worktree .` doesn't touch them
13
+ * anyway. no-op when no script was configured.
14
+ */
15
+ normalizeWorkingTreeAfter?: boolean;
16
+ }
17
+ /** structured failure info — `output` on the `exit` variant is trimmed
18
+ * stderr, falling back to stdout when stderr is empty. */
19
+ export type LifecycleHookFailure = {
20
+ kind: "exit";
21
+ exitCode: number;
22
+ output: string;
23
+ } | {
24
+ kind: "timeout";
25
+ } | {
26
+ kind: "spawn";
27
+ spawnError: string;
28
+ };
29
+ /** one-line, agent-facing description of a hook failure. empty string when
30
+ * there was no failure, so callers can pass the result straight through to a
31
+ * prompt section that omits itself on empty. */
32
+ export declare function describeSetupFailure(failure: LifecycleHookFailure | undefined): string;
33
+ export interface LifecycleHookResult {
34
+ /**
35
+ * human-readable warning when the hook failed. includes retry guidance:
36
+ * transient spawn/exit errors are worth retrying, timeouts and
37
+ * persistent failures are not. absent when the hook succeeded or was
38
+ * skipped. setup/post-checkout callers surface this verbatim; prepush
39
+ * builds its own message from `failure` instead.
40
+ */
41
+ warning?: string;
42
+ /**
43
+ * structured failure info — undefined when the hook succeeded or was
44
+ * skipped. lets callers compose their own messaging without parsing the
45
+ * `warning` string.
46
+ */
47
+ failure?: LifecycleHookFailure;
48
+ }
49
+ /**
50
+ * execute a lifecycle hook script if one is configured.
51
+ *
52
+ * soft-fails: instead of throwing on hook errors, returns a warning string
53
+ * (and structured failure info) so callers can choose how to surface it
54
+ * (mcp tools relay it to the agent; setup logs it and adds a prompt banner).
55
+ * timeouts are flagged as non-retryable in the warning text.
56
+ */
57
+ export declare function executeLifecycleHook(params: ExecuteLifecycleHookParams): Promise<LifecycleHookResult>;