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.
- package/LICENSE +661 -0
- package/README.md +145 -0
- package/dist/agents/claude.d.ts +73 -0
- package/dist/agents/claudePretoolGate.d.ts +99 -0
- package/dist/agents/gateServer.d.ts +7 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/nativeFsDenies.d.ts +28 -0
- package/dist/agents/opencode.d.ts +231 -0
- package/dist/agents/opencodePlugin.d.ts +85 -0
- package/dist/agents/opencodeShared.d.ts +40 -0
- package/dist/agents/postRun.d.ts +132 -0
- package/dist/agents/reviewer.d.ts +38 -0
- package/dist/agents/sessionLabeler.d.ts +97 -0
- package/dist/agents/shared.d.ts +189 -0
- package/dist/agents/subagentModels.d.ts +19 -0
- package/dist/agents/subagentToolGates.d.ts +55 -0
- package/dist/cli.mjs +197426 -0
- package/dist/external.d.ts +227 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +196783 -0
- package/dist/internal/index.d.ts +18 -0
- package/dist/internal.js +1714 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/main.d.ts +8 -0
- package/dist/mcp/arkConfig.d.ts +1 -0
- package/dist/mcp/checkSuite.d.ts +25 -0
- package/dist/mcp/checkout.d.ts +77 -0
- package/dist/mcp/comment.d.ts +119 -0
- package/dist/mcp/commitInfo.d.ts +9 -0
- package/dist/mcp/crosswalk.d.ts +105 -0
- package/dist/mcp/dependencies.d.ts +8 -0
- package/dist/mcp/geminiSanitizer.d.ts +28 -0
- package/dist/mcp/git.d.ts +46 -0
- package/dist/mcp/guardrails.d.ts +104 -0
- package/dist/mcp/issue.d.ts +18 -0
- package/dist/mcp/issueComments.d.ts +9 -0
- package/dist/mcp/issueEvents.d.ts +9 -0
- package/dist/mcp/issueInfo.d.ts +9 -0
- package/dist/mcp/labels.d.ts +12 -0
- package/dist/mcp/localContext.d.ts +19 -0
- package/dist/mcp/moduleExtraction.d.ts +71 -0
- package/dist/mcp/moduleTests.d.ts +104 -0
- package/dist/mcp/modules.d.ts +179 -0
- package/dist/mcp/output.d.ts +12 -0
- package/dist/mcp/pathSafety.d.ts +14 -0
- package/dist/mcp/policy.d.ts +48 -0
- package/dist/mcp/pr.d.ts +49 -0
- package/dist/mcp/prInfo.d.ts +9 -0
- package/dist/mcp/providerSchema.d.ts +50 -0
- package/dist/mcp/review.d.ts +199 -0
- package/dist/mcp/reviewComments.d.ts +178 -0
- package/dist/mcp/roots.d.ts +58 -0
- package/dist/mcp/scope.d.ts +15 -0
- package/dist/mcp/selectMode.d.ts +18 -0
- package/dist/mcp/server.d.ts +48 -0
- package/dist/mcp/shared.d.ts +47 -0
- package/dist/mcp/shell.d.ts +37 -0
- package/dist/mcp/staleFix.d.ts +51 -0
- package/dist/mcp/terraform/cost.d.ts +55 -0
- package/dist/mcp/terraform/currency.d.ts +94 -0
- package/dist/mcp/terraform/decisions.d.ts +178 -0
- package/dist/mcp/terraform/findings.d.ts +75 -0
- package/dist/mcp/terraform/plan.d.ts +157 -0
- package/dist/mcp/terraform/scanners.d.ts +131 -0
- package/dist/mcp/terraform/tools.d.ts +63 -0
- package/dist/mcp/terraform/types.d.ts +172 -0
- package/dist/mcp/terraform.d.ts +22 -0
- package/dist/mcp/terratest.d.ts +83 -0
- package/dist/mcp/upload.d.ts +6 -0
- package/dist/models.d.ts +171 -0
- package/dist/modes.d.ts +26 -0
- package/dist/prep/index.d.ts +7 -0
- package/dist/prep/installNodeDependencies.d.ts +2 -0
- package/dist/prep/installPythonDependencies.d.ts +2 -0
- package/dist/prep/types.d.ts +31 -0
- package/dist/reviewQuality.d.ts +64 -0
- package/dist/skills/terraform-best-practices/SKILL.md +369 -0
- package/dist/toolState.d.ts +135 -0
- package/dist/utils/activity.d.ts +40 -0
- package/dist/utils/agent.d.ts +20 -0
- package/dist/utils/agentHangReport.d.ts +38 -0
- package/dist/utils/apiFetch.d.ts +19 -0
- package/dist/utils/apiKeys.d.ts +41 -0
- package/dist/utils/apiUrl.d.ts +20 -0
- package/dist/utils/assets.d.ts +8 -0
- package/dist/utils/billingErrors.d.ts +85 -0
- package/dist/utils/body.d.ts +34 -0
- package/dist/utils/buildTerramendFooter.d.ts +25 -0
- package/dist/utils/byokFallback.d.ts +85 -0
- package/dist/utils/claudeSubscription.d.ts +30 -0
- package/dist/utils/cli.d.ts +10 -0
- package/dist/utils/codexHome.d.ts +29 -0
- package/dist/utils/codexOAuth.d.ts +60 -0
- package/dist/utils/diffCoverage.d.ts +63 -0
- package/dist/utils/errorReport.d.ts +17 -0
- package/dist/utils/exitHandler.d.ts +8 -0
- package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
- package/dist/utils/gitAuth.d.ts +84 -0
- package/dist/utils/gitAuthServer.d.ts +24 -0
- package/dist/utils/github.d.ts +78 -0
- package/dist/utils/globals.d.ts +3 -0
- package/dist/utils/install.d.ts +60 -0
- package/dist/utils/instructions.d.ts +48 -0
- package/dist/utils/leapingComment.d.ts +11 -0
- package/dist/utils/learnings.d.ts +62 -0
- package/dist/utils/learningsTruncate.d.ts +25 -0
- package/dist/utils/lifecycle.d.ts +57 -0
- package/dist/utils/log.d.ts +111 -0
- package/dist/utils/normalizeEnv.d.ts +30 -0
- package/dist/utils/openCodeModels.d.ts +11 -0
- package/dist/utils/overrides.d.ts +40 -0
- package/dist/utils/packageManager.d.ts +49 -0
- package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
- package/dist/utils/payload.d.ts +105 -0
- package/dist/utils/prSummary.d.ts +61 -0
- package/dist/utils/progressComment.d.ts +146 -0
- package/dist/utils/providerErrors.d.ts +31 -0
- package/dist/utils/rangeDiff.d.ts +51 -0
- package/dist/utils/remediationCommand.d.ts +55 -0
- package/dist/utils/retry.d.ts +13 -0
- package/dist/utils/reviewCleanup.d.ts +14 -0
- package/dist/utils/run.d.ts +9 -0
- package/dist/utils/runContext.d.ts +60 -0
- package/dist/utils/runContextData.d.ts +23 -0
- package/dist/utils/runErrorRenderer.d.ts +64 -0
- package/dist/utils/runLifecycle.d.ts +86 -0
- package/dist/utils/runStartupLog.d.ts +15 -0
- package/dist/utils/secrets.d.ts +22 -0
- package/dist/utils/setup.d.ts +90 -0
- package/dist/utils/shell.d.ts +32 -0
- package/dist/utils/skills.d.ts +10 -0
- package/dist/utils/subprocess.d.ts +80 -0
- package/dist/utils/terraformMcp.d.ts +42 -0
- package/dist/utils/time.d.ts +15 -0
- package/dist/utils/timer.d.ts +23 -0
- package/dist/utils/todoTracking.d.ts +16 -0
- package/dist/utils/token.d.ts +39 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/versioning.d.ts +7 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/dist/utils/workflow.d.ts +13 -0
- package/package.json +119 -0
- package/src/agents/claude.test.ts +1016 -0
- package/src/agents/claude.ts +1246 -0
- package/src/agents/claudePretoolGate.test.ts +28 -0
- package/src/agents/claudePretoolGate.ts +173 -0
- package/src/agents/gateServer.test.ts +204 -0
- package/src/agents/gateServer.ts +124 -0
- package/src/agents/index.ts +10 -0
- package/src/agents/nativeFsDenies.ts +82 -0
- package/src/agents/opencode.test.ts +1440 -0
- package/src/agents/opencode.ts +1312 -0
- package/src/agents/opencodePlugin.ts +222 -0
- package/src/agents/opencodeShared.test.ts +34 -0
- package/src/agents/opencodeShared.ts +121 -0
- package/src/agents/postRun.test.ts +549 -0
- package/src/agents/postRun.ts +535 -0
- package/src/agents/reviewer.ts +104 -0
- package/src/agents/sessionLabeler.test.ts +247 -0
- package/src/agents/sessionLabeler.ts +178 -0
- package/src/agents/shared.test.ts +76 -0
- package/src/agents/shared.ts +292 -0
- package/src/agents/subagentModels.test.ts +113 -0
- package/src/agents/subagentModels.ts +40 -0
- package/src/agents/subagentRegistration.test.ts +41 -0
- package/src/agents/subagentToolGates.ts +114 -0
- package/src/cli.test.ts +129 -0
- package/src/cli.ts +105 -0
- package/src/commands/gha.test.ts +192 -0
- package/src/commands/gha.ts +188 -0
- package/src/commands/mcp.ts +122 -0
- package/src/config.ts +1 -0
- package/src/entry.ts +7 -0
- package/src/entryPost.stdlibOnly.test.ts +109 -0
- package/src/entryPost.ts +99 -0
- package/src/external.test.ts +16 -0
- package/src/external.ts +302 -0
- package/src/index.ts +11 -0
- package/src/internal/index.ts +71 -0
- package/src/lifecycle.ts +2 -0
- package/src/main.test.ts +873 -0
- package/src/main.ts +712 -0
- package/src/mcp/__fixtures__/terramend-scratch-pr-49-review-3485940013.json +110 -0
- package/src/mcp/__fixtures__/terramend-scratch-pr-64-review-3531000326.json +14 -0
- package/src/mcp/__fixtures__/terramend-test-repo-pr-1.diff.json +67 -0
- package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
- package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
- package/src/mcp/arkConfig.ts +7 -0
- package/src/mcp/checkSuite.test.ts +245 -0
- package/src/mcp/checkSuite.ts +255 -0
- package/src/mcp/checkout.test.ts +752 -0
- package/src/mcp/checkout.ts +886 -0
- package/src/mcp/comment.test.ts +772 -0
- package/src/mcp/comment.ts +582 -0
- package/src/mcp/commitInfo.test.ts +127 -0
- package/src/mcp/commitInfo.ts +61 -0
- package/src/mcp/crosswalk.test.ts +106 -0
- package/src/mcp/crosswalk.ts +339 -0
- package/src/mcp/dependencies.test.ts +309 -0
- package/src/mcp/dependencies.ts +189 -0
- package/src/mcp/geminiSanitizer.test.ts +287 -0
- package/src/mcp/geminiSanitizer.ts +207 -0
- package/src/mcp/git.test.ts +1083 -0
- package/src/mcp/git.ts +890 -0
- package/src/mcp/guardrails.test.ts +705 -0
- package/src/mcp/guardrails.ts +465 -0
- package/src/mcp/issue.test.ts +113 -0
- package/src/mcp/issue.ts +73 -0
- package/src/mcp/issueComments.test.ts +69 -0
- package/src/mcp/issueComments.ts +48 -0
- package/src/mcp/issueEvents.test.ts +134 -0
- package/src/mcp/issueEvents.ts +100 -0
- package/src/mcp/issueInfo.test.ts +104 -0
- package/src/mcp/issueInfo.ts +72 -0
- package/src/mcp/labels.test.ts +52 -0
- package/src/mcp/labels.ts +34 -0
- package/src/mcp/localContext.ts +28 -0
- package/src/mcp/localServer.test.ts +75 -0
- package/src/mcp/localServer.ts +131 -0
- package/src/mcp/moduleExtraction.test.ts +261 -0
- package/src/mcp/moduleExtraction.ts +313 -0
- package/src/mcp/moduleTests.test.ts +269 -0
- package/src/mcp/moduleTests.ts +421 -0
- package/src/mcp/modules.test.ts +640 -0
- package/src/mcp/modules.ts +696 -0
- package/src/mcp/output.test.ts +96 -0
- package/src/mcp/output.ts +70 -0
- package/src/mcp/pathSafety.test.ts +44 -0
- package/src/mcp/pathSafety.ts +28 -0
- package/src/mcp/policy.test.ts +282 -0
- package/src/mcp/policy.ts +199 -0
- package/src/mcp/pr.test.ts +387 -0
- package/src/mcp/pr.ts +194 -0
- package/src/mcp/prInfo.test.ts +96 -0
- package/src/mcp/prInfo.ts +91 -0
- package/src/mcp/providerSchema.test.ts +85 -0
- package/src/mcp/providerSchema.ts +175 -0
- package/src/mcp/review.test.ts +936 -0
- package/src/mcp/review.ts +923 -0
- package/src/mcp/reviewComments.test.ts +549 -0
- package/src/mcp/reviewComments.ts +896 -0
- package/src/mcp/roots.test.ts +175 -0
- package/src/mcp/roots.ts +217 -0
- package/src/mcp/scope.test.ts +59 -0
- package/src/mcp/scope.ts +65 -0
- package/src/mcp/security.test.ts +720 -0
- package/src/mcp/selectMode.test.ts +210 -0
- package/src/mcp/selectMode.ts +181 -0
- package/src/mcp/server.test.ts +292 -0
- package/src/mcp/server.ts +403 -0
- package/src/mcp/shared.ts +100 -0
- package/src/mcp/shell.test.ts +520 -0
- package/src/mcp/shell.ts +505 -0
- package/src/mcp/staleFix.test.ts +237 -0
- package/src/mcp/staleFix.ts +277 -0
- package/src/mcp/terraform/cost.ts +163 -0
- package/src/mcp/terraform/currency.test.ts +338 -0
- package/src/mcp/terraform/currency.ts +336 -0
- package/src/mcp/terraform/decisions.ts +527 -0
- package/src/mcp/terraform/findings.ts +333 -0
- package/src/mcp/terraform/plan.ts +348 -0
- package/src/mcp/terraform/scanners.ts +809 -0
- package/src/mcp/terraform/tools.test.ts +1071 -0
- package/src/mcp/terraform/tools.ts +908 -0
- package/src/mcp/terraform/types.ts +305 -0
- package/src/mcp/terraform.test.ts +1957 -0
- package/src/mcp/terraform.ts +23 -0
- package/src/mcp/terratest.test.ts +105 -0
- package/src/mcp/terratest.ts +196 -0
- package/src/mcp/toolFiltering.test.ts +85 -0
- package/src/mcp/upload.test.ts +180 -0
- package/src/mcp/upload.ts +112 -0
- package/src/models.test.ts +300 -0
- package/src/models.ts +708 -0
- package/src/modes.test.ts +107 -0
- package/src/modes.ts +880 -0
- package/src/prep/index.ts +43 -0
- package/src/prep/installNodeDependencies.test.ts +298 -0
- package/src/prep/installNodeDependencies.ts +196 -0
- package/src/prep/installPythonDependencies.test.ts +268 -0
- package/src/prep/installPythonDependencies.ts +199 -0
- package/src/prep/types.ts +38 -0
- package/src/reviewQuality.test.ts +63 -0
- package/src/reviewQuality.ts +134 -0
- package/src/runCli.test.ts +214 -0
- package/src/runCli.ts +282 -0
- package/src/skills/terraform-best-practices/SKILL.md +369 -0
- package/src/toolState.test.ts +45 -0
- package/src/toolState.ts +252 -0
- package/src/utils/activity.test.ts +188 -0
- package/src/utils/activity.ts +210 -0
- package/src/utils/agent.test.ts +251 -0
- package/src/utils/agent.ts +139 -0
- package/src/utils/agentHangReport.test.ts +203 -0
- package/src/utils/agentHangReport.ts +170 -0
- package/src/utils/apiFetch.test.ts +115 -0
- package/src/utils/apiFetch.ts +62 -0
- package/src/utils/apiKeys.test.ts +344 -0
- package/src/utils/apiKeys.ts +206 -0
- package/src/utils/apiUrl.test.ts +30 -0
- package/src/utils/apiUrl.ts +59 -0
- package/src/utils/assets.test.ts +153 -0
- package/src/utils/assets.ts +107 -0
- package/src/utils/billingErrors.test.ts +121 -0
- package/src/utils/billingErrors.ts +189 -0
- package/src/utils/body.test.ts +217 -0
- package/src/utils/body.ts +168 -0
- package/src/utils/buildTerramendFooter.test.ts +38 -0
- package/src/utils/buildTerramendFooter.ts +82 -0
- package/src/utils/byokFallback.test.ts +205 -0
- package/src/utils/byokFallback.ts +128 -0
- package/src/utils/claudeSubscription.test.ts +179 -0
- package/src/utils/claudeSubscription.ts +93 -0
- package/src/utils/cli.ts +31 -0
- package/src/utils/codexHome.test.ts +190 -0
- package/src/utils/codexHome.ts +191 -0
- package/src/utils/codexOAuth.ts +147 -0
- package/src/utils/codexRefreshDetect.test.ts +85 -0
- package/src/utils/codexRefreshDetect.ts +35 -0
- package/src/utils/diffCoverage.test.ts +468 -0
- package/src/utils/diffCoverage.ts +404 -0
- package/src/utils/errorReport.test.ts +135 -0
- package/src/utils/errorReport.ts +83 -0
- package/src/utils/exitHandler.ts +35 -0
- package/src/utils/fixDoubleEscapedString.ts +9 -0
- package/src/utils/ghaCore.ts +13 -0
- package/src/utils/gitAuth.test.ts +322 -0
- package/src/utils/gitAuth.ts +263 -0
- package/src/utils/gitAuthServer.test.ts +260 -0
- package/src/utils/gitAuthServer.ts +182 -0
- package/src/utils/github.test.ts +615 -0
- package/src/utils/github.ts +538 -0
- package/src/utils/globals.ts +9 -0
- package/src/utils/humanEditCapture.test.ts +100 -0
- package/src/utils/humanEditCapture.ts +193 -0
- package/src/utils/install.test.ts +768 -0
- package/src/utils/install.ts +492 -0
- package/src/utils/instructions.test.ts +240 -0
- package/src/utils/instructions.ts +543 -0
- package/src/utils/leapingComment.test.ts +51 -0
- package/src/utils/leapingComment.ts +18 -0
- package/src/utils/learnings.test.ts +87 -0
- package/src/utils/learnings.ts +138 -0
- package/src/utils/learningsTocRender.test.ts +116 -0
- package/src/utils/learningsTruncate.test.ts +39 -0
- package/src/utils/learningsTruncate.ts +42 -0
- package/src/utils/lifecycle.test.ts +195 -0
- package/src/utils/lifecycle.ts +198 -0
- package/src/utils/log.test.ts +402 -0
- package/src/utils/log.ts +432 -0
- package/src/utils/normalizeEnv.test.ts +91 -0
- package/src/utils/normalizeEnv.ts +106 -0
- package/src/utils/openCodeModels.ts +82 -0
- package/src/utils/overrides.test.ts +89 -0
- package/src/utils/overrides.ts +98 -0
- package/src/utils/packageManager.test.ts +321 -0
- package/src/utils/packageManager.ts +257 -0
- package/src/utils/patchWorkflowRunFields.test.ts +92 -0
- package/src/utils/patchWorkflowRunFields.ts +150 -0
- package/src/utils/payload.test.ts +497 -0
- package/src/utils/payload.ts +371 -0
- package/src/utils/postApiFetch.ts +51 -0
- package/src/utils/prSummary.test.ts +224 -0
- package/src/utils/prSummary.ts +147 -0
- package/src/utils/progressComment.ts +261 -0
- package/src/utils/providerErrors.test.ts +315 -0
- package/src/utils/providerErrors.ts +172 -0
- package/src/utils/rangeDiff.test.ts +236 -0
- package/src/utils/rangeDiff.ts +182 -0
- package/src/utils/remediationCommand.test.ts +163 -0
- package/src/utils/remediationCommand.ts +119 -0
- package/src/utils/retry.test.ts +153 -0
- package/src/utils/retry.ts +58 -0
- package/src/utils/reviewCleanup.ts +106 -0
- package/src/utils/run.ts +99 -0
- package/src/utils/runContext.ts +145 -0
- package/src/utils/runContextData.ts +58 -0
- package/src/utils/runErrorRenderer.test.ts +95 -0
- package/src/utils/runErrorRenderer.ts +259 -0
- package/src/utils/runFixture.ts +76 -0
- package/src/utils/runLifecycle.ts +237 -0
- package/src/utils/runStartupLog.ts +60 -0
- package/src/utils/secrets.test.ts +103 -0
- package/src/utils/secrets.ts +177 -0
- package/src/utils/setup.test.ts +509 -0
- package/src/utils/setup.ts +352 -0
- package/src/utils/shell.ts +103 -0
- package/src/utils/skills.test.ts +46 -0
- package/src/utils/skills.ts +67 -0
- package/src/utils/subprocess.test.ts +170 -0
- package/src/utils/subprocess.ts +438 -0
- package/src/utils/terraformMcp.test.ts +63 -0
- package/src/utils/terraformMcp.ts +83 -0
- package/src/utils/time.test.ts +105 -0
- package/src/utils/time.ts +59 -0
- package/src/utils/timer.test.ts +91 -0
- package/src/utils/timer.ts +72 -0
- package/src/utils/todoTracking.test.ts +223 -0
- package/src/utils/todoTracking.ts +167 -0
- package/src/utils/token.test.ts +239 -0
- package/src/utils/token.ts +186 -0
- package/src/utils/version.ts +10 -0
- package/src/utils/versioning.test.ts +34 -0
- package/src/utils/versioning.ts +44 -0
- package/src/utils/vertex.ts +85 -0
- package/src/utils/workflow.ts +25 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
type ComputeIncrementalDiffParams = {
|
|
2
|
+
baseBranch: string;
|
|
3
|
+
beforeSha: string;
|
|
4
|
+
headSha: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* computes the incremental diff between two versions of a PR using range-diff
|
|
8
|
+
* on virtual squash commits created via `git commit-tree`.
|
|
9
|
+
*
|
|
10
|
+
* each PR version is squashed into a single synthetic commit (merge-base → tip tree),
|
|
11
|
+
* then range-diff compares those two single-commit ranges. this:
|
|
12
|
+
* - isolates each version's net effect (base branch noise eliminated via per-version merge bases)
|
|
13
|
+
* - avoids commit-matching issues that raw range-diff has with rebases/squashes/reordering
|
|
14
|
+
* - creates only loose git objects, no branches or refs (unlike temp-branch squash approaches)
|
|
15
|
+
*
|
|
16
|
+
* unlike fetchAndFormatPrDiff/formatFilesWithLineNumbers, this output has no line numbers.
|
|
17
|
+
* range-diff compares *patches* (diffs-of-diffs), not file trees — its hunk headers are
|
|
18
|
+
* `@@ file.ts` breadcrumbs, not positional `@@ -X,Y +A,B @@` markers. reconstructing
|
|
19
|
+
* line numbers would require cross-referencing with the v2 diff or content-matching against
|
|
20
|
+
* file trees, both of which are fragile (duplicate lines, hunk boundary shifts after rebase).
|
|
21
|
+
* a structured interdiff approach (diff two parsed patches, compare only +/- keys via Myers)
|
|
22
|
+
* could approximate line numbers but loses semantic precision: range-diff understands patch
|
|
23
|
+
* structure natively (rename detection, hunk-aware matching, dual-prefix inner/outer changes),
|
|
24
|
+
* while flat key-sequence comparison can misalign duplicate lines and can't distinguish
|
|
25
|
+
* "new addition to the PR" from "existing code newly modified by the PR". range-diff is the
|
|
26
|
+
* right abstraction here — the incremental diff answers "how did the changeset evolve?",
|
|
27
|
+
* not "where in the file is this?", and forcing positional line numbers onto it would be
|
|
28
|
+
* semantically misleading.
|
|
29
|
+
*
|
|
30
|
+
* alternatives considered:
|
|
31
|
+
* - plain git diff (two-tree or three-dot): includes base branch changes, no PR isolation
|
|
32
|
+
* - patch-text diffing (interdiff / diff-of-diffs): fragile, hunk offset noise on rebase
|
|
33
|
+
* - range-diff on raw commit ranges: confused by commit reorganization across force-pushes
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeIncrementalDiff(params: ComputeIncrementalDiffParams): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* transforms git range-diff output into a clean incremental diff.
|
|
38
|
+
*
|
|
39
|
+
* range-diff content lines have two prefix characters:
|
|
40
|
+
* 1st (outer): range-diff level — space (same in both), + (new only), - (old only)
|
|
41
|
+
* 2nd (inner): original diff level — space (context), + (added), - (removed)
|
|
42
|
+
*
|
|
43
|
+
* stripping the inner prefix produces a standard unified-diff-like output where
|
|
44
|
+
* +/- means "changed between PR versions" rather than "changed vs base branch".
|
|
45
|
+
*
|
|
46
|
+
* uses a streaming approach: a ring buffer of before-context lines is flushed when
|
|
47
|
+
* a change is hit, then afterCount lines of after-context are emitted directly.
|
|
48
|
+
* nearest preceding ## / @@ headers are force-included when outside the context window.
|
|
49
|
+
*/
|
|
50
|
+
export declare function postProcessRangeDiff(raw: string, contextLines?: number): string | null;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §3.12 Comment-command interface. A developer can scope a remediation run from
|
|
3
|
+
* a PR/issue comment that mentions the bot:
|
|
4
|
+
*
|
|
5
|
+
* @terramend fix #3a9f1c2 → fix exactly one concern (by id or short id)
|
|
6
|
+
* @terramend fix all high-severity → fix every concern at/above a severity
|
|
7
|
+
* @terramend fix all → fix everything (still bounded by max_prs)
|
|
8
|
+
* @terramend fix main.tf → fix one file's group
|
|
9
|
+
*
|
|
10
|
+
* §26 Propose, then let me steer — when a non-trivial finding has several
|
|
11
|
+
* genuinely distinct valid fixes, Remediate proposes 2–3 labelled strategies in
|
|
12
|
+
* a comment instead of guessing, and the reviewer picks one by replying:
|
|
13
|
+
*
|
|
14
|
+
* @terramend fix #3a9f1c2 with strategy B → apply strategy B to that concern
|
|
15
|
+
* @terramend strategy 2 → pick strategy 2 (concern from the thread)
|
|
16
|
+
*
|
|
17
|
+
* The parsing is pure + deterministic so the scoping doesn't depend on the
|
|
18
|
+
* model's reading of the comment. The Remediate mode applies the parsed scope
|
|
19
|
+
* (which group(s) to act on, and which strategy) instead of the default
|
|
20
|
+
* "highest-severity group, agent's-choice fix".
|
|
21
|
+
*/
|
|
22
|
+
export type RemediationCommand = {
|
|
23
|
+
kind: "concern";
|
|
24
|
+
concernRef: string;
|
|
25
|
+
strategy?: string;
|
|
26
|
+
} | {
|
|
27
|
+
kind: "severity";
|
|
28
|
+
severity: Severity;
|
|
29
|
+
} | {
|
|
30
|
+
kind: "file";
|
|
31
|
+
file: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "strategy";
|
|
34
|
+
strategy: string;
|
|
35
|
+
} | {
|
|
36
|
+
kind: "all";
|
|
37
|
+
};
|
|
38
|
+
declare const SEVERITIES: readonly ["critical", "high", "medium", "low", "info"];
|
|
39
|
+
type Severity = (typeof SEVERITIES)[number];
|
|
40
|
+
/**
|
|
41
|
+
* §26 — the canonical phrasing the proposal comment must tell reviewers to reply
|
|
42
|
+
* with. Lives next to the parser that accepts it so the proposal template (in
|
|
43
|
+
* the Remediate prompt) and the parser can never drift apart. `<concern-id>` and
|
|
44
|
+
* `<A|B|C>` are placeholders the agent fills with the real id and the offered
|
|
45
|
+
* strategy labels.
|
|
46
|
+
*/
|
|
47
|
+
export declare const STRATEGY_REPLY_HINT = "@terramend fix #<concern-id> with strategy <A|B|C>";
|
|
48
|
+
/**
|
|
49
|
+
* Parse a `@terramend fix …` command out of a comment body. Returns null when
|
|
50
|
+
* the body isn't a recognised fix command (the run then falls back to its
|
|
51
|
+
* default scope). Tolerant of surrounding prose — it scans for the mention then
|
|
52
|
+
* the `fix` verb and its argument.
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseRemediationCommand(body: string | undefined): RemediationCommand | null;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type RetryOptions = {
|
|
2
|
+
maxAttempts?: number;
|
|
3
|
+
delayMs?: number;
|
|
4
|
+
/**
|
|
5
|
+
* explicit delay schedule — one entry per retry (length N ⇒ N+1 attempts).
|
|
6
|
+
* when set, overrides `maxAttempts` and `delayMs`. e.g. `[1_000, 3_000]`
|
|
7
|
+
* means up to 3 attempts, sleeping 1s before retry 2 and 3s before retry 3.
|
|
8
|
+
*/
|
|
9
|
+
delaysMs?: readonly number[];
|
|
10
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
11
|
+
label?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ToolContext } from "#app/mcp/server";
|
|
2
|
+
/**
|
|
3
|
+
* post-agent review lifecycle: runs after the agent exits (success or timeout).
|
|
4
|
+
*
|
|
5
|
+
* normally the agent handles new commits inline: create_pull_request_review
|
|
6
|
+
* detects HEAD movement and tells the agent to pull and review the delta.
|
|
7
|
+
* this dispatch is a safety net for cases where the agent couldn't handle
|
|
8
|
+
* it (timeout, error, etc).
|
|
9
|
+
*
|
|
10
|
+
* ordering matters: reportReviewNodeId marks this run "done" FIRST so push
|
|
11
|
+
* webhooks stop being suppressed by dedup. the HEAD check runs SECOND to
|
|
12
|
+
* catch any pushes that were suppressed while this run was in-flight.
|
|
13
|
+
*/
|
|
14
|
+
export declare function postReviewCleanup(ctx: ToolContext): Promise<void>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentResult } from "#app/agents/shared";
|
|
2
|
+
import type { MainResult } from "#app/main";
|
|
3
|
+
import type { ToolContext } from "#app/mcp/server";
|
|
4
|
+
export interface HandleAgentResultParams {
|
|
5
|
+
result: AgentResult;
|
|
6
|
+
toolContext: ToolContext;
|
|
7
|
+
silent: boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleAgentResult(ctx: HandleAgentResultParams): Promise<MainResult>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { PushPermission, ShellPermission } from "#app/external";
|
|
2
|
+
import type { RepoContext } from "#app/utils/github";
|
|
3
|
+
export interface Mode {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* server-parsed TOC entry for `Repo.learnings`. depth is 1-6 (h1-h6),
|
|
11
|
+
* line numbers are 1-indexed against the raw body. computed by
|
|
12
|
+
* `parseLearningsHeadings` in `utils/learningsToc.ts` (server side) and
|
|
13
|
+
* shipped over the run-context JSON boundary; the canonical declaration
|
|
14
|
+
* lives there. duplicated here because the action runtime can't reach
|
|
15
|
+
* across into the proprietary root-level codebase, and the JSON wire
|
|
16
|
+
* means typecheck can't enforce shape equality across both sides.
|
|
17
|
+
*/
|
|
18
|
+
export interface LearningsHeading {
|
|
19
|
+
depth: 1 | 2 | 3 | 4 | 5 | 6;
|
|
20
|
+
title: string;
|
|
21
|
+
startLine: number;
|
|
22
|
+
endLine: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RepoSettings {
|
|
25
|
+
model: string | null;
|
|
26
|
+
modes: Mode[];
|
|
27
|
+
setupScript: string | null;
|
|
28
|
+
postCheckoutScript: string | null;
|
|
29
|
+
prepushScript: string | null;
|
|
30
|
+
stopScript: string | null;
|
|
31
|
+
push: PushPermission;
|
|
32
|
+
shell: ShellPermission;
|
|
33
|
+
prApproveEnabled: boolean;
|
|
34
|
+
modeInstructions: Record<string, string>;
|
|
35
|
+
learnings: string | null;
|
|
36
|
+
learningsHeadings: LearningsHeading[];
|
|
37
|
+
envAllowlist: string | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Account-level billing plan. Orthogonal to repo-level OSS status. Mirrors
|
|
41
|
+
* the server's `AccountPlan` in `utils/billing.ts`. `"none"` = free tier,
|
|
42
|
+
* `"payg"` = card on file / pay-as-you-go.
|
|
43
|
+
*/
|
|
44
|
+
export type AccountPlan = "none" | "payg";
|
|
45
|
+
export interface RunContext {
|
|
46
|
+
settings: RepoSettings;
|
|
47
|
+
apiToken: string;
|
|
48
|
+
oss: boolean;
|
|
49
|
+
plan: AccountPlan;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* fetch run context from Terramend API
|
|
53
|
+
* returns settings + API token for subsequent calls
|
|
54
|
+
* returns defaults if fetch fails
|
|
55
|
+
*/
|
|
56
|
+
export declare function fetchRunContext(params: {
|
|
57
|
+
token: string;
|
|
58
|
+
repoContext: RepoContext;
|
|
59
|
+
oidcToken?: string | undefined;
|
|
60
|
+
}): Promise<RunContext>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Octokit } from "@octokit/rest";
|
|
2
|
+
import { type OctokitWithPlugins } from "#app/utils/github";
|
|
3
|
+
import { type AccountPlan, type RepoSettings } from "#app/utils/runContext";
|
|
4
|
+
export interface RunContextData {
|
|
5
|
+
repo: {
|
|
6
|
+
owner: string;
|
|
7
|
+
name: string;
|
|
8
|
+
data: Awaited<ReturnType<Octokit["repos"]["get"]>>["data"];
|
|
9
|
+
};
|
|
10
|
+
repoSettings: RepoSettings;
|
|
11
|
+
apiToken: string;
|
|
12
|
+
oss: boolean;
|
|
13
|
+
plan: AccountPlan;
|
|
14
|
+
}
|
|
15
|
+
interface ResolveRunContextDataParams {
|
|
16
|
+
octokit: OctokitWithPlugins;
|
|
17
|
+
token: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* initialize run context data: parse context, fetch repo info and settings
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveRunContextData(params: ResolveRunContextDataParams): Promise<RunContextData>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify + render the error thrown out of the main run try-block into a
|
|
3
|
+
* pair of user-facing markdown bodies — one for the GitHub Actions job
|
|
4
|
+
* summary tab, one for the PR progress comment.
|
|
5
|
+
*
|
|
6
|
+
* Classifications, in dispatch order (first match wins; the api-key
|
|
7
|
+
* branch additionally folds in the activity-timeout hang body as a
|
|
8
|
+
* sub-source so a hang masking an api-key error still surfaces the api-key
|
|
9
|
+
* CTA):
|
|
10
|
+
*
|
|
11
|
+
* 1. `BillingError` — either the proxy-token mint already threw one (402
|
|
12
|
+
* handled inline) or the agent runtime surfaced an OpenRouter
|
|
13
|
+
* "key budget exhausted" string mid-run. Both render via
|
|
14
|
+
* `formatBillingErrorSummary` so the user sees actionable copy.
|
|
15
|
+
*
|
|
16
|
+
* 2. BYOK provider billing-exhausted (#835) — DeepSeek "Insufficient
|
|
17
|
+
* Balance", Anthropic "credit balance is too low", OpenCode Zen
|
|
18
|
+
* `CreditsError`, Gemini "spending cap". Checked before api-key auth
|
|
19
|
+
* because billing-exhausted responses often carry 401 status codes
|
|
20
|
+
* that `isApiKeyAuthError` would otherwise mis-classify.
|
|
21
|
+
*
|
|
22
|
+
* 3. API-key auth error — `isApiKeyAuthError` sniffs the raw error string
|
|
23
|
+
* (or the activity-timeout hang body when present, since that's where
|
|
24
|
+
* the underlying provider error often lands); `formatApiKeyErrorSummary`
|
|
25
|
+
* renders provider + console-link copy.
|
|
26
|
+
*
|
|
27
|
+
* 4. ProviderModelNotFoundError — stale free-fallback model id no longer
|
|
28
|
+
* in the OpenCode catalog; renders a nudge to add a BYOK key.
|
|
29
|
+
*
|
|
30
|
+
* 5. Activity-timeout hang — `errorMessage` starts with
|
|
31
|
+
* `"activity timeout"` or `"agent still pending"` AND none of the
|
|
32
|
+
* above matched. The harness keeps structured diagnostic state on
|
|
33
|
+
* `toolState.agentDiagnostic`; `formatAgentHangBody` renders that into
|
|
34
|
+
* the job summary. The PR comment instead collapses to a one-line
|
|
35
|
+
* `**Run failed.** [View the logs →]` — the watchdog jargon, event
|
|
36
|
+
* counts, and benign stderr tail are operator-grade detail that only
|
|
37
|
+
* alarm the average user. The one exception is a hang masking billing
|
|
38
|
+
* exhaustion (#778), where `formatAgentHangBody` emits an actionable
|
|
39
|
+
* top-up CTA that the comment keeps verbatim.
|
|
40
|
+
*
|
|
41
|
+
* 6. Default — the job summary gets a plain-English lead sentence plus the
|
|
42
|
+
* raw error in a fenced code block under the `### ❌ Terramend failed`
|
|
43
|
+
* banner; the PR comment collapses to the same one-line logs link as
|
|
44
|
+
* the hang case, since the raw internal string helps nobody on the PR.
|
|
45
|
+
*
|
|
46
|
+
* Net: the actionable classifications (billing, API-key, model-not-found)
|
|
47
|
+
* render identical bodies on both surfaces; the non-actionable ones (hang,
|
|
48
|
+
* generic) keep the forensics in the Actions job summary and show a calm
|
|
49
|
+
* one-liner in the PR comment, whose footer already carries Terramend
|
|
50
|
+
* branding + rerun links.
|
|
51
|
+
*/
|
|
52
|
+
import type { AgentDiagnostic } from "#app/utils/agentHangReport";
|
|
53
|
+
export type RenderedRunError = {
|
|
54
|
+
summary: string;
|
|
55
|
+
comment: string;
|
|
56
|
+
};
|
|
57
|
+
export declare function renderRunError(input: {
|
|
58
|
+
errorMessage: string;
|
|
59
|
+
repo: {
|
|
60
|
+
owner: string;
|
|
61
|
+
name: string;
|
|
62
|
+
};
|
|
63
|
+
agentDiagnostic: AgentDiagnostic | undefined;
|
|
64
|
+
}): RenderedRunError;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-of-run cleanup phases extracted out of `main.ts`. Three shapes:
|
|
3
|
+
*
|
|
4
|
+
* - `persistRunArtifacts`: best-effort post-review cleanup + summary +
|
|
5
|
+
* learnings persistence. Shared by both the success path and the
|
|
6
|
+
* error-catch path; idempotent (each step has its own guard against
|
|
7
|
+
* double-execution).
|
|
8
|
+
*
|
|
9
|
+
* - `finalizeSuccessRun`: success-only — calls `persistRunArtifacts`
|
|
10
|
+
* first, then surfaces harness-side failures in the progress comment,
|
|
11
|
+
* deletes stranded progress comments, writes the GitHub Actions job
|
|
12
|
+
* summary, and emits the structured output marker.
|
|
13
|
+
*
|
|
14
|
+
* - `writeRunErrorOutputs`: error-only — writes the rendered error
|
|
15
|
+
* summary to the Actions summary tab and mirrors it to the PR
|
|
16
|
+
* progress comment. The catch path calls this and then
|
|
17
|
+
* `persistRunArtifacts` separately so the rendered error lands before
|
|
18
|
+
* the persistence calls, in case the latter throw.
|
|
19
|
+
*
|
|
20
|
+
* All three swallow their own non-fatal errors (`log.debug` or empty
|
|
21
|
+
* `catch {}`) so a cleanup failure can't flip an already-decided run
|
|
22
|
+
* outcome.
|
|
23
|
+
*/
|
|
24
|
+
import type { AgentResult } from "#app/agents/shared";
|
|
25
|
+
import type { ToolContext } from "#app/mcp/server";
|
|
26
|
+
import type { ToolState } from "#app/toolState";
|
|
27
|
+
import { type RenderedRunError } from "#app/utils/runErrorRenderer";
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort cleanup shared by both run-end paths:
|
|
30
|
+
* 1. post-review cleanup (dispatch follow-up re-review on submitted reviews)
|
|
31
|
+
* 2. persist the agent-edited PR summary tmpfile
|
|
32
|
+
* 3. persist the agent-edited repo-level learnings tmpfile
|
|
33
|
+
*
|
|
34
|
+
* Each step is idempotent and swallows its own errors. Safe to call from
|
|
35
|
+
* both `main()`'s success path and its catch path.
|
|
36
|
+
*/
|
|
37
|
+
export declare function persistRunArtifacts(toolContext: ToolContext): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Run the success-path cleanup waterfall:
|
|
40
|
+
*
|
|
41
|
+
* 1. shared best-effort cleanup via `persistRunArtifacts`
|
|
42
|
+
* 2. when the harness returned `success=false` (e.g. unsubmitted-review
|
|
43
|
+
* gate exhausted retries, stop-hook persistently failing), render via
|
|
44
|
+
* `renderRunError` and surface the error in BOTH the progress comment
|
|
45
|
+
* (rendered.comment) and the Actions job summary (rendered.summary,
|
|
46
|
+
* prepended below in step 4) — same classifier as the catch path so
|
|
47
|
+
* the user sees it instead of a deleted-comment void / empty summary
|
|
48
|
+
* tab
|
|
49
|
+
* 3. when the run succeeded, some write landed (`wasUpdated`), but the
|
|
50
|
+
* progress comment was never finalized via `report_progress`, delete
|
|
51
|
+
* the stranded comment (abandoned checklist, or a substantive artifact
|
|
52
|
+
* written via another MCP write tool that skipped report_progress). a
|
|
53
|
+
* run where NO write landed keeps its comment for handleAgentResult to
|
|
54
|
+
* salvage into — see the `wasUpdated` guard below and #868
|
|
55
|
+
* 4. write the GitHub Actions step summary (best-effort — a write
|
|
56
|
+
* failure must not throw past this point because we'd hit the outer
|
|
57
|
+
* catch and clobber any progress comment we just wrote)
|
|
58
|
+
* 5. emit the structured output marker for tests + workflow consumers
|
|
59
|
+
*/
|
|
60
|
+
export declare function finalizeSuccessRun(input: {
|
|
61
|
+
toolContext: ToolContext;
|
|
62
|
+
toolState: ToolState;
|
|
63
|
+
result: AgentResult;
|
|
64
|
+
repo: {
|
|
65
|
+
owner: string;
|
|
66
|
+
name: string;
|
|
67
|
+
};
|
|
68
|
+
}): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Write the rendered error to the GitHub Actions job summary tab + mirror
|
|
71
|
+
* to the PR progress comment when one exists. Catch path only.
|
|
72
|
+
*
|
|
73
|
+
* `lastProgressBody` and the usage table are appended to the summary so the
|
|
74
|
+
* partial work the agent did before failing isn't lost.
|
|
75
|
+
*
|
|
76
|
+
* `createIfMissing: true` is symmetric with `finalizeSuccessRun` — silent
|
|
77
|
+
* triggers (IncrementalReview / pull_request_synchronize / auto-label) that
|
|
78
|
+
* throw past `finalizeSuccessRun` (e.g. timeout race kills the agent
|
|
79
|
+
* mid-billing-exhausted-retry) reach this catch path with no progress
|
|
80
|
+
* comment to update, and without `createIfMissing` the terminal error
|
|
81
|
+
* lands only in the GH job summary that most users never open. see #835.
|
|
82
|
+
*/
|
|
83
|
+
export declare function writeRunErrorOutputs(input: {
|
|
84
|
+
rendered: RenderedRunError;
|
|
85
|
+
toolState: ToolState;
|
|
86
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup log formatting for the resolver pipeline. Computes the
|
|
3
|
+
* "model / agent / push / shell / timeout" block that main.ts prints
|
|
4
|
+
* after resolving the agent + model + payload.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedPayload } from "#app/utils/payload";
|
|
7
|
+
/**
|
|
8
|
+
* Emit the startup block ("» model / agent / push / shell / timeout") after
|
|
9
|
+
* the agent and model are resolved. Single side-effect; no return.
|
|
10
|
+
*/
|
|
11
|
+
export declare function logRunStartup(ctx: {
|
|
12
|
+
payload: ResolvedPayload;
|
|
13
|
+
resolvedModel: string | undefined;
|
|
14
|
+
agentName: string;
|
|
15
|
+
}): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret detection and env filtering utilities
|
|
3
|
+
*
|
|
4
|
+
* subprocess env filtering: default-deny allowlist model.
|
|
5
|
+
* only vars in the safe set or user allowlist are passed to child processes.
|
|
6
|
+
*
|
|
7
|
+
* log redaction: SENSITIVE_PATTERNS are used to identify secret values
|
|
8
|
+
* for redaction in logs and GHA masking (independent of subprocess filtering).
|
|
9
|
+
*/
|
|
10
|
+
export declare const SENSITIVE_PATTERNS: RegExp[];
|
|
11
|
+
export declare function isSensitiveEnvName(key: string): boolean;
|
|
12
|
+
export declare function setEnvAllowlist(raw: string): void;
|
|
13
|
+
/** filter env vars using default-deny allowlist: safe set + user allowlist */
|
|
14
|
+
export declare function filterEnv(): Record<string, string>;
|
|
15
|
+
export type EnvMode = "restricted" | "inherit" | Record<string, string>;
|
|
16
|
+
/**
|
|
17
|
+
* resolve env mode to actual env object
|
|
18
|
+
* - "restricted" (default): filterEnv() — only safe set + user allowlist
|
|
19
|
+
* - "inherit": full process.env
|
|
20
|
+
* - object: custom env merged with restricted base
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveEnv(mode: EnvMode | undefined): Record<string, string | undefined>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { ShellPermission } from "#app/external";
|
|
2
|
+
import type { ToolState } from "#app/toolState";
|
|
3
|
+
import type { OctokitWithPlugins } from "#app/utils/github";
|
|
4
|
+
export interface SetupOptions {
|
|
5
|
+
tempDir: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create a shared temp directory for the action
|
|
9
|
+
*/
|
|
10
|
+
export declare function createTempDirectory(): string;
|
|
11
|
+
/**
|
|
12
|
+
* snapshot-and-delete the GHA runner's known credential leak surfaces inside
|
|
13
|
+
* `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
|
|
14
|
+
* can grep:
|
|
15
|
+
* - `_runner_file_commands/set_output_*` for `core.setOutput('token', ghs_…)`
|
|
16
|
+
* calls made by earlier composite-action steps (e.g.
|
|
17
|
+
* terramend/terramend/get-installation-token);
|
|
18
|
+
* - `<uuid>.sh` rendered step scripts whose `run: |` body embeds
|
|
19
|
+
* `${{ steps.token.outputs.token }}` literally (GHA expands BEFORE writing);
|
|
20
|
+
* - `git-credentials-*.config` written by `actions/checkout@v6` for the
|
|
21
|
+
* workflow GITHUB_TOKEN.
|
|
22
|
+
*
|
|
23
|
+
* the running bash process already has its own `.sh` open via fd, so the
|
|
24
|
+
* unlink is safe — `unlink` removes the dirent, the kernel keeps reading.
|
|
25
|
+
*
|
|
26
|
+
* preserves every `_runner_file_commands/` file path the runner pre-allocated
|
|
27
|
+
* for OUR step — `$GITHUB_OUTPUT`, `$GITHUB_ENV`, `$GITHUB_PATH`,
|
|
28
|
+
* `$GITHUB_STATE`, `$GITHUB_STEP_SUMMARY`. those are read by the runner
|
|
29
|
+
* AFTER we exit (or by our own `post:` hook), and wiping them would break
|
|
30
|
+
* terramend's `result` output, `post:` state handoff, and job summary.
|
|
31
|
+
*
|
|
32
|
+
* silent no-op when `$RUNNER_TEMP` is unset (local dev, `pnpm dev:run`).
|
|
33
|
+
* per-file errors are tolerated — the runner may delete files between
|
|
34
|
+
* our readdir and our unlink.
|
|
35
|
+
*/
|
|
36
|
+
export declare function wipeRunnerLeakSurface(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Setup the test repository for running actions
|
|
39
|
+
*/
|
|
40
|
+
export declare function setupTestRepo(options: SetupOptions): void;
|
|
41
|
+
/**
|
|
42
|
+
* remove any `[includeIf ...]` entries from the local git config so that
|
|
43
|
+
* actions/checkout-persisted credentials don't ride alongside ASKPASS-provided
|
|
44
|
+
* auth for subsequent git operations.
|
|
45
|
+
*
|
|
46
|
+
* SECURITY: git config subsection values can contain arbitrary characters
|
|
47
|
+
* including `$(...)` command substitutions, and `${IFS}` spacing tricks defeat
|
|
48
|
+
* naive split-on-space filtering. we read keys via the `-z` (null-terminated)
|
|
49
|
+
* output format and feed them to a spawn-array `git config --unset-all` so
|
|
50
|
+
* the shell never interpolates key contents — closing the RCE path that a
|
|
51
|
+
* string-interpolated `execSync(...)` would expose.
|
|
52
|
+
*/
|
|
53
|
+
export declare function removeIncludeIfEntries(repoDir: string): void;
|
|
54
|
+
export interface GitContext {
|
|
55
|
+
gitToken: string;
|
|
56
|
+
owner: string;
|
|
57
|
+
name: string;
|
|
58
|
+
octokit: OctokitWithPlugins;
|
|
59
|
+
toolState: ToolState;
|
|
60
|
+
shell: ShellPermission;
|
|
61
|
+
postCheckoutScript: string | null;
|
|
62
|
+
}
|
|
63
|
+
export type SetupGitParams = GitContext;
|
|
64
|
+
/**
|
|
65
|
+
* setup git configuration and authentication for the repository.
|
|
66
|
+
* - configures git identity (user.email, user.name)
|
|
67
|
+
* - sets up authentication via gitToken (minimal contents:write)
|
|
68
|
+
*
|
|
69
|
+
* gitToken is a minimal-permission token (contents + workflows) used for git operations.
|
|
70
|
+
* it is assumed to be potentially exfiltratable, so it has limited scope.
|
|
71
|
+
*/
|
|
72
|
+
export declare function setupGit(params: SetupGitParams): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* snapshot the current HEAD as either a branch name (when on a named branch)
|
|
75
|
+
* or a literal SHA (when detached). used by setupGit to pin the run-entry
|
|
76
|
+
* position and by checkout_pr to compare the live HEAD against it.
|
|
77
|
+
*
|
|
78
|
+
* splitting the two cases is load-bearing: `git rev-parse --abbrev-ref HEAD`
|
|
79
|
+
* returns the sentinel string `"HEAD"` on detached entry — which is the
|
|
80
|
+
* default `actions/checkout` state for `pull_request` events. storing that
|
|
81
|
+
* raw string would make any future detached state (including a subagent's
|
|
82
|
+
* `git checkout --detach <sha>`) compare equal.
|
|
83
|
+
*/
|
|
84
|
+
export declare function captureInitialHead(repoDir: string): {
|
|
85
|
+
kind: "branch";
|
|
86
|
+
name: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: "detached";
|
|
89
|
+
sha: string;
|
|
90
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type EnvMode } from "#app/utils/secrets";
|
|
2
|
+
interface ShellOptions {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
encoding?: "utf-8" | "utf8" | "ascii" | "base64" | "base64url" | "hex" | "latin1" | "ucs-2" | "ucs2" | "utf16le";
|
|
5
|
+
log?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* env mode: "restricted" (default) filters secrets, "inherit" passes full env,
|
|
8
|
+
* or provide a custom env object (merged with restricted base)
|
|
9
|
+
*/
|
|
10
|
+
env?: EnvMode;
|
|
11
|
+
onError?: (result: {
|
|
12
|
+
status: number;
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Execute a shell command safely using spawnSync with argument arrays.
|
|
19
|
+
* Prevents shell injection by avoiding string interpolation in shell commands.
|
|
20
|
+
*
|
|
21
|
+
* SECURITY: by default, env vars are filtered to remove secrets (tokens, keys, passwords).
|
|
22
|
+
* this prevents malicious code (git hooks, npm scripts, etc.) from exfiltrating credentials.
|
|
23
|
+
* use env: "inherit" only when absolutely necessary.
|
|
24
|
+
*
|
|
25
|
+
* @param cmd - The command to execute
|
|
26
|
+
* @param args - Array of arguments to pass to the command
|
|
27
|
+
* @param options - Optional configuration (cwd, encoding, onError)
|
|
28
|
+
* @returns The trimmed stdout output
|
|
29
|
+
* @throws Error if command fails and no onError handler is provided
|
|
30
|
+
*/
|
|
31
|
+
export declare function $(cmd: string, args: string[], options?: ShellOptions): string;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write all bundled skills into the fake HOME so OpenCode / Claude Code discover
|
|
3
|
+
* them via their auto-scan directories.
|
|
4
|
+
*
|
|
5
|
+
* called once per agent run from each agent's `run()`. cheap (small file
|
|
6
|
+
* writes), no network, idempotent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function installBundledSkills(params: {
|
|
9
|
+
home: string;
|
|
10
|
+
}): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
export type TrackChildOptions = {
|
|
3
|
+
child: ChildProcess;
|
|
4
|
+
killGroup?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const SPAWN_TIMEOUT_CODE = "E_SPAWN_TIMEOUT";
|
|
7
|
+
export declare const SPAWN_ACTIVITY_TIMEOUT_CODE = "E_SPAWN_ACTIVITY_TIMEOUT";
|
|
8
|
+
export declare class SpawnTimeoutError extends Error {
|
|
9
|
+
readonly code: typeof SPAWN_TIMEOUT_CODE | typeof SPAWN_ACTIVITY_TIMEOUT_CODE;
|
|
10
|
+
constructor(message: string, code: typeof SPAWN_TIMEOUT_CODE | typeof SPAWN_ACTIVITY_TIMEOUT_CODE);
|
|
11
|
+
}
|
|
12
|
+
export type SignalHandler = (signal: NodeJS.Signals) => void;
|
|
13
|
+
export declare function trackChild(options: TrackChildOptions): void;
|
|
14
|
+
export declare function untrackChild(child: ChildProcess): void;
|
|
15
|
+
export declare function setSignalHandler(handler: SignalHandler | null): void;
|
|
16
|
+
export declare function killTrackedChildren(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Controls what the wrapper retains in memory across the child's lifetime
|
|
19
|
+
* for the post-hoc `SpawnResult.stdout` / `SpawnResult.stderr` snapshots.
|
|
20
|
+
*
|
|
21
|
+
* Streaming callbacks (`onStdout` / `onStderr`) fire regardless — `retain`
|
|
22
|
+
* only governs the buffered snapshot returned in `SpawnResult`.
|
|
23
|
+
*
|
|
24
|
+
* - `"tail"` (default): keep the last `maxRetainedBytes` UTF-16 code units
|
|
25
|
+
* of each stream. Once the cap is exceeded, oldest bytes are sliced off
|
|
26
|
+
* and the result is prefixed with a `... [N MiB truncated] ...` sentinel.
|
|
27
|
+
* Right default for short-lived commands whose failure mode is in their
|
|
28
|
+
* final output (git errors, install failures, hook scripts).
|
|
29
|
+
* - `"none"`: skip the buffer entirely. `SpawnResult.stdout` / `.stderr`
|
|
30
|
+
* are empty strings. Use this for long-lived streaming agents that already
|
|
31
|
+
* drain via `onStdout` / `onStderr` and never read the buffered snapshot.
|
|
32
|
+
*
|
|
33
|
+
* Default cap is 8 MiB — well below V8's ~1 GiB `kMaxLength` so `+= chunk`
|
|
34
|
+
* can never throw `RangeError: Invalid string length`.
|
|
35
|
+
*/
|
|
36
|
+
export type RetainMode = "tail" | "none";
|
|
37
|
+
export declare const DEFAULT_MAX_RETAINED_BYTES: number;
|
|
38
|
+
export interface SpawnOptions {
|
|
39
|
+
cmd: string;
|
|
40
|
+
args: string[];
|
|
41
|
+
env?: NodeJS.ProcessEnv;
|
|
42
|
+
input?: string;
|
|
43
|
+
timeout?: number;
|
|
44
|
+
activityTimeout?: number;
|
|
45
|
+
onActivityTimeout?: (() => void) | undefined;
|
|
46
|
+
cwd?: string;
|
|
47
|
+
stdio?: ("pipe" | "ignore" | "inherit")[];
|
|
48
|
+
onStdout?: (chunk: string) => void;
|
|
49
|
+
onStderr?: (chunk: string) => void;
|
|
50
|
+
killGroup?: boolean;
|
|
51
|
+
retain?: RetainMode;
|
|
52
|
+
maxRetainedBytes?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Bounded string accumulator that keeps the tail of appended chunks.
|
|
56
|
+
* Once the cap is exceeded, oldest bytes are sliced off and `toString()`
|
|
57
|
+
* prefixes the survivors with a sentinel describing the elided byte count.
|
|
58
|
+
*
|
|
59
|
+
* Exported because long-lived agent runtimes (opencode, claude) also
|
|
60
|
+
* accumulate per-run narration strings independently of the spawn wrapper
|
|
61
|
+
* and need the same protection against V8's `kMaxLength`.
|
|
62
|
+
*/
|
|
63
|
+
export declare class TailBuffer {
|
|
64
|
+
private readonly cap;
|
|
65
|
+
private buffer;
|
|
66
|
+
private truncatedBytes;
|
|
67
|
+
constructor(cap: number);
|
|
68
|
+
append(chunk: string): void;
|
|
69
|
+
toString(): string;
|
|
70
|
+
}
|
|
71
|
+
export interface SpawnResult {
|
|
72
|
+
stdout: string;
|
|
73
|
+
stderr: string;
|
|
74
|
+
exitCode: number;
|
|
75
|
+
durationMs: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Spawn a subprocess with streaming callbacks and buffered results
|
|
79
|
+
*/
|
|
80
|
+
export declare function spawn(options: SpawnOptions): Promise<SpawnResult>;
|