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,135 @@
|
|
|
1
|
+
import type { AgentUsage } from "#app/agents/shared";
|
|
2
|
+
import type { Concern } from "#app/mcp/terraform/types";
|
|
3
|
+
import type { PrepResult } from "#app/prep/types";
|
|
4
|
+
import type { AgentDiagnostic } from "#app/utils/agentHangReport";
|
|
5
|
+
import type { DiffCoverageState } from "#app/utils/diffCoverage";
|
|
6
|
+
import { type ProgressComment, type ProgressCommentType } from "#app/utils/progressComment";
|
|
7
|
+
import type { TodoTracker } from "#app/utils/todoTracking";
|
|
8
|
+
export type BackgroundProcess = {
|
|
9
|
+
pid: number;
|
|
10
|
+
outputPath: string;
|
|
11
|
+
pidPath: string;
|
|
12
|
+
};
|
|
13
|
+
export type StoredPushDest = {
|
|
14
|
+
remoteName: string;
|
|
15
|
+
remoteBranch: string;
|
|
16
|
+
localBranch: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Valid inline-comment anchor lines per side at a particular checkout SHA.
|
|
20
|
+
* Lives here (not in `mcp/review.ts`) so `ToolState` — which caches
|
|
21
|
+
* `Map<path, CommentableLines>` per checkout — does not pull the MCP server
|
|
22
|
+
* graph into every consumer of run state (the action's main loop, agent
|
|
23
|
+
* harnesses, cf-worker indexing).
|
|
24
|
+
*/
|
|
25
|
+
export type CommentableLines = {
|
|
26
|
+
RIGHT: Set<number>;
|
|
27
|
+
LEFT: Set<number>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* mutable per-run record of facts that occurred during execution. shared
|
|
31
|
+
* between the action process and the MCP server (one process — toolState is
|
|
32
|
+
* just a JS object passed by reference into both surfaces).
|
|
33
|
+
*
|
|
34
|
+
* design rule: ToolState is LITERAL. each field records a thing that
|
|
35
|
+
* happened — `review` is set when `create_pull_request_review` succeeded,
|
|
36
|
+
* `finalSummaryWritten` flips when `report_progress` wrote a non-plan body,
|
|
37
|
+
* `selectedMode` is set when `select_mode` was called. fields should never
|
|
38
|
+
* encode the absence of an event ("unsubmittedReview", "missingArtifact"),
|
|
39
|
+
* speculative state, or values derived from other fields.
|
|
40
|
+
*
|
|
41
|
+
* any predicate the rest of the code needs ("the agent picked review mode but
|
|
42
|
+
* never produced a review or progress write") is computed inline at the call
|
|
43
|
+
* site, not stored. derived state in this struct invariably drifts from the
|
|
44
|
+
* literal fields under refactors and is the wrong layer for the check.
|
|
45
|
+
*
|
|
46
|
+
* write narrowly: prefer adding state inside the tool that mutates it (e.g.
|
|
47
|
+
* `create_pull_request_review` populates `toolState.review`) and reading
|
|
48
|
+
* narrowly elsewhere. don't introduce flags from main.ts that mirror what an
|
|
49
|
+
* MCP tool already records.
|
|
50
|
+
*/
|
|
51
|
+
export interface ToolState {
|
|
52
|
+
pushUrl?: string;
|
|
53
|
+
pushDest?: StoredPushDest;
|
|
54
|
+
initialHead?: {
|
|
55
|
+
kind: "branch";
|
|
56
|
+
name: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "detached";
|
|
59
|
+
sha: string;
|
|
60
|
+
};
|
|
61
|
+
issueNumber?: number;
|
|
62
|
+
createdTargets?: Set<number>;
|
|
63
|
+
checkoutSha?: string;
|
|
64
|
+
commentableLinesByFile?: Map<string, CommentableLines>;
|
|
65
|
+
commentableLinesPullNumber?: number;
|
|
66
|
+
commentableLinesCheckoutSha?: string | undefined;
|
|
67
|
+
beforeSha?: string;
|
|
68
|
+
selectedMode?: string;
|
|
69
|
+
remediationPrsOpened?: number;
|
|
70
|
+
plannedDestroy?: {
|
|
71
|
+
stateful: {
|
|
72
|
+
address: string;
|
|
73
|
+
action: string;
|
|
74
|
+
type: string;
|
|
75
|
+
}[];
|
|
76
|
+
ephemeral: {
|
|
77
|
+
address: string;
|
|
78
|
+
action: string;
|
|
79
|
+
type: string;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
baselineConcernIds?: string[];
|
|
83
|
+
lastScanConcerns?: Concern[];
|
|
84
|
+
emittedSarifPath?: string;
|
|
85
|
+
lastBlastTier?: "low" | "medium" | "high";
|
|
86
|
+
lastIdempotent?: boolean;
|
|
87
|
+
lastCostDirection?: "increase" | "decrease" | "no-change" | "unknown";
|
|
88
|
+
prepushFailureCount: number;
|
|
89
|
+
backgroundProcesses: Map<string, BackgroundProcess>;
|
|
90
|
+
review?: {
|
|
91
|
+
id: number;
|
|
92
|
+
nodeId: string;
|
|
93
|
+
reviewedSha: string | undefined;
|
|
94
|
+
};
|
|
95
|
+
reviewReplies?: Map<number, {
|
|
96
|
+
commentId: number;
|
|
97
|
+
url: string | undefined;
|
|
98
|
+
bodyWithFooter: string;
|
|
99
|
+
}>;
|
|
100
|
+
dependencyInstallation?: {
|
|
101
|
+
status: "not_started" | "in_progress" | "completed" | "failed";
|
|
102
|
+
promise: Promise<PrepResult[]> | undefined;
|
|
103
|
+
results: PrepResult[] | undefined;
|
|
104
|
+
};
|
|
105
|
+
progressComment: ProgressComment | null | undefined;
|
|
106
|
+
hadProgressComment: boolean;
|
|
107
|
+
lastProgressBody?: string;
|
|
108
|
+
wasUpdated?: boolean;
|
|
109
|
+
finalSummaryWritten?: boolean;
|
|
110
|
+
existingPlanCommentId?: number;
|
|
111
|
+
previousPlanBody?: string;
|
|
112
|
+
summaryFilePath?: string;
|
|
113
|
+
summarySeed?: string;
|
|
114
|
+
summaryPersistAttempted?: boolean;
|
|
115
|
+
learningsFilePath?: string;
|
|
116
|
+
learningsSeed?: string;
|
|
117
|
+
learningsPersistAttempted?: boolean;
|
|
118
|
+
output?: string | undefined;
|
|
119
|
+
usageEntries: AgentUsage[];
|
|
120
|
+
model?: string | undefined;
|
|
121
|
+
modelFallback?: {
|
|
122
|
+
from: string;
|
|
123
|
+
} | undefined;
|
|
124
|
+
todoTracker?: TodoTracker | undefined;
|
|
125
|
+
diffCoverage?: DiffCoverageState | undefined;
|
|
126
|
+
agentDiagnostic?: AgentDiagnostic | undefined;
|
|
127
|
+
}
|
|
128
|
+
interface InitToolStateParams {
|
|
129
|
+
progressComment: {
|
|
130
|
+
id: string;
|
|
131
|
+
type: ProgressCommentType;
|
|
132
|
+
} | undefined;
|
|
133
|
+
}
|
|
134
|
+
export declare function initToolState(params: InitToolStateParams): ToolState;
|
|
135
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generic `spawn()` idle default for ordinary short-lived subprocesses (prep
|
|
3
|
+
* probes, package-manager invocations, dependency installs). these should be
|
|
4
|
+
* producing output steadily, so a comparatively tight budget catches a wedged
|
|
5
|
+
* command promptly. the long-silent-tool tolerance the agent harnesses need
|
|
6
|
+
* lives in AGENT_ACTIVITY_TIMEOUT_MS, applied explicitly at those sites.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_ACTIVITY_TIMEOUT_MS = 300000;
|
|
9
|
+
/**
|
|
10
|
+
* flat idle budget for the agent activity watchdog (the outer process-output
|
|
11
|
+
* monitor, the v1 harness spawns, and the v2 inner event-silence watchdog).
|
|
12
|
+
* sized to exceed the worst-case legitimate silent tool window (issue #760:
|
|
13
|
+
* `checkout_pr` git fetch+deepen on a large monorepo, ~4-5min) with generous
|
|
14
|
+
* headroom, so no single in-flight tool call can be mistaken for a stall. a
|
|
15
|
+
* timeout this generous needs no suspend/resume bracketing — the cost of a
|
|
16
|
+
* genuinely hung run is only GitHub Actions minutes, not tokens.
|
|
17
|
+
*/
|
|
18
|
+
export declare const AGENT_ACTIVITY_TIMEOUT_MS = 900000;
|
|
19
|
+
export declare const DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5000;
|
|
20
|
+
export declare const ACTIVITY_NOISE_PATTERNS: readonly RegExp[];
|
|
21
|
+
export declare function isActivityNoise(chunk: string | Uint8Array): boolean;
|
|
22
|
+
type ActivityTimeoutContext = {
|
|
23
|
+
timeoutMs: number;
|
|
24
|
+
checkIntervalMs: number;
|
|
25
|
+
};
|
|
26
|
+
export type ActivityTimeout = {
|
|
27
|
+
promise: Promise<never>;
|
|
28
|
+
stop: () => void;
|
|
29
|
+
/** force the timeout to reject immediately with a custom reason */
|
|
30
|
+
forceReject: (reason: string) => void;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* mark activity to reset the no-output timeout.
|
|
34
|
+
* call this whenever the agent emits any event, even if it isn't logged to stdout.
|
|
35
|
+
*/
|
|
36
|
+
export declare function markActivity(): void;
|
|
37
|
+
/** get the time since last activity in milliseconds. */
|
|
38
|
+
export declare function getIdleMs(): number;
|
|
39
|
+
export declare function createProcessOutputActivityTimeout(ctx: ActivityTimeoutContext): ActivityTimeout;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Agent } from "#app/agents/index";
|
|
2
|
+
/**
|
|
3
|
+
* resolve the effective model for this run.
|
|
4
|
+
*
|
|
5
|
+
* priority:
|
|
6
|
+
* 1. TERRAMEND_MODEL env var — resolved through the alias registry first,
|
|
7
|
+
* so values like "anthropic/claude-opus" become "anthropic/claude-opus-4-7".
|
|
8
|
+
* raw specifiers (e.g. "anthropic/claude-opus-4-6") pass through unchanged.
|
|
9
|
+
* always wins — bypasses Bedrock routing entirely. to test a different
|
|
10
|
+
* Bedrock model, change `BEDROCK_MODEL_ID`, not `TERRAMEND_MODEL`.
|
|
11
|
+
* 2. slug from repo config / payload → alias registry. routing slugs
|
|
12
|
+
* (e.g. `bedrock/byok`) defer to a separate env var (`BEDROCK_MODEL_ID`).
|
|
13
|
+
* 3. undefined — agent will auto-select.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveModel(ctx: {
|
|
16
|
+
slug?: string | undefined;
|
|
17
|
+
}): string | undefined;
|
|
18
|
+
export declare function resolveAgent(ctx: {
|
|
19
|
+
model?: string | undefined;
|
|
20
|
+
}): Agent;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mutable per-run handle the agent harness writes to as a run progresses.
|
|
3
|
+
* the action's outer try/catch in `main.ts` reads this off `toolState` when
|
|
4
|
+
* the activity-timeout watchdog wins the race against the harness's own
|
|
5
|
+
* catch — the bare timer reject reason ("activity timeout: no output for
|
|
6
|
+
* 302s") tells the user nothing actionable, but `recentStderr` +
|
|
7
|
+
* `lastProviderError` together usually point straight at the upstream cause.
|
|
8
|
+
*
|
|
9
|
+
* `recentStderr` is shared by reference with the harness's bounded ring
|
|
10
|
+
* buffer, so the diagnostic always reflects the latest captured tail.
|
|
11
|
+
*/
|
|
12
|
+
export type AgentDiagnostic = {
|
|
13
|
+
/** display label for the agent, e.g. "Terramend". used in the headline. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** shared reference to the harness's bounded stderr ring buffer. */
|
|
16
|
+
recentStderr: string[];
|
|
17
|
+
/** most-recent provider-error label from `detectProviderError`, if any. */
|
|
18
|
+
lastProviderError: string | undefined;
|
|
19
|
+
/** count of stdout events successfully parsed before the failure. */
|
|
20
|
+
eventCount: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Build a user-facing markdown body for an agent hang or failure.
|
|
24
|
+
*
|
|
25
|
+
* Rendered into both the PR progress comment and the GitHub Actions job
|
|
26
|
+
* summary. Returns `null` when no diagnostic is available, which signals to
|
|
27
|
+
* the caller to fall back to its bare-error rendering.
|
|
28
|
+
*
|
|
29
|
+
* `errorMessage` is the underlying timer / spawn reject string (e.g.
|
|
30
|
+
* `activity timeout: no output for 301s`). The idle seconds are parsed out
|
|
31
|
+
* of it for the hang explanation — total runtime would overstate the stall
|
|
32
|
+
* for runs that streamed for a long time before going quiet.
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatAgentHangBody(input: {
|
|
35
|
+
diagnostic: AgentDiagnostic | undefined;
|
|
36
|
+
isHang: boolean;
|
|
37
|
+
errorMessage: string;
|
|
38
|
+
}): string | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type ApiFetchOptions = {
|
|
2
|
+
path: string;
|
|
3
|
+
method?: string | undefined;
|
|
4
|
+
headers?: Record<string, string> | undefined;
|
|
5
|
+
body?: string | undefined;
|
|
6
|
+
signal?: AbortSignal | undefined;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* fetch wrapper for hitting the Terramend API with Vercel deployment protection bypass.
|
|
10
|
+
*
|
|
11
|
+
* adds the bypass secret as BOTH a query parameter and a header for maximum reliability.
|
|
12
|
+
* the server-side forwarding code uses query params, and the Vercel docs say both work,
|
|
13
|
+
* so we do both as belt-and-suspenders.
|
|
14
|
+
*
|
|
15
|
+
* the query param approach is the primary bypass mechanism (matches server-side forwarding).
|
|
16
|
+
* the header is added as a fallback.
|
|
17
|
+
*/
|
|
18
|
+
export declare function apiFetch(options: ApiFetchOptions): Promise<Response>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate that the resolved model can actually be served by the chosen
|
|
3
|
+
* agent. For routing slugs (Bedrock / Vertex) the auth shape is multi-var
|
|
4
|
+
* (auth + region/location + model-id) and `opencode models` doesn't catch
|
|
5
|
+
* gaps in the latter two — keep dedicated setup validators. For the
|
|
6
|
+
* opencode path, the authoritative answer comes from OpenCode's own model
|
|
7
|
+
* introspection (`authorized` set captured in `openCodeModels.ts`). For
|
|
8
|
+
* the claude path, fall back to the static check (`ANTHROPIC_API_KEY` /
|
|
9
|
+
* `CLAUDE_CODE_OAUTH_TOKEN`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateAgentApiKey(params: {
|
|
12
|
+
agent: {
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
model: string | undefined;
|
|
16
|
+
authorized: Set<string>;
|
|
17
|
+
owner: string;
|
|
18
|
+
name: string;
|
|
19
|
+
}): void;
|
|
20
|
+
/**
|
|
21
|
+
* Detect agent-runtime auth failures that should be reformatted as an actionable
|
|
22
|
+
* key-fix CTA before being shown to the user. Covers the shapes we see:
|
|
23
|
+
* - missing key (validateAgentApiKey throw): contains MISSING_KEY_MARKER
|
|
24
|
+
* - revoked / invalid key (Claude CLI 401 surfaced via api_error_status):
|
|
25
|
+
* "Invalid API key · Fix external API key" + similar provider variants
|
|
26
|
+
* - direct-Anthropic 401 (`Failed to authenticate. API Error: 401 ...
|
|
27
|
+
* {"type":"error","error":{"type":"authentication_error", ...
|
|
28
|
+
* "Invalid bearer token"}}`) emitted by the Claude CLI for revoked /
|
|
29
|
+
* mistyped / rotated `ANTHROPIC_API_KEY`. see #782.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isApiKeyAuthError(text: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Friendly Markdown summary for both the missing-key and invalid-key cases.
|
|
34
|
+
* Used in the catch / result-failure paths in `main.ts` to overwrite the raw
|
|
35
|
+
* agent error before it's posted to the PR progress comment.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatApiKeyErrorSummary(params: {
|
|
38
|
+
owner: string;
|
|
39
|
+
name: string;
|
|
40
|
+
raw: string;
|
|
41
|
+
}): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* resolve the Terramend API base URL.
|
|
3
|
+
*
|
|
4
|
+
* in the action: API_URL is not explicitly set, so this falls back to https://terramend.com.
|
|
5
|
+
* in local dev: API_URL=http://localhost:3000 (from .env).
|
|
6
|
+
*
|
|
7
|
+
* enforces https:// for non-local URLs to prevent cleartext credential transmission.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getApiUrl(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a real Terramend backend is configured.
|
|
12
|
+
*
|
|
13
|
+
* Standalone BYOK runs (the OSS default) leave `API_URL` unset — `getApiUrl`
|
|
14
|
+
* then falls back to the marketing host, which serves no API. The dormant
|
|
15
|
+
* open-core persistence seams (repo learnings, run-field PATCHes) must no-op
|
|
16
|
+
* in that case rather than POST into the void and surface the host's 404 as a
|
|
17
|
+
* CI warning. A real backend — the hosted SaaS, or local dev with
|
|
18
|
+
* `API_URL=http://localhost:3000` — sets `API_URL` explicitly.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isBackendConfigured(): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* downloads any github-hosted image/video assets referenced in `markdown` to
|
|
3
|
+
* `<tmpdir>/assets` and rewrites the urls to the local file paths, so the agent can
|
|
4
|
+
* read screenshots directly instead of relying on remote (often short-lived, signed)
|
|
5
|
+
* urls. unique urls are downloaded once and every occurrence is rewritten. assets that
|
|
6
|
+
* fail to download are left untouched.
|
|
7
|
+
*/
|
|
8
|
+
export declare function downloadAssetsInMarkdown(markdown: string, tmpdir: string, githubToken: string): Promise<string>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Billing-error classification + user-facing copy for `/api/proxy-token`
|
|
3
|
+
* failures and OpenRouter mid-run exhaustion. Two error classes (Billing vs.
|
|
4
|
+
* Transient) keep the framing honest: a card decline is *not* the same UX as
|
|
5
|
+
* a 503 from the proxy service. Both originate in `utils/proxy.ts` (mint
|
|
6
|
+
* failures) and `utils/runErrorRenderer.ts` (mid-run keylimit reclassify).
|
|
7
|
+
*
|
|
8
|
+
* Renderers return markdown bodies that are written into both the GitHub
|
|
9
|
+
* Actions job summary and the PR progress comment.
|
|
10
|
+
*
|
|
11
|
+
* Lives outside `main.ts` so adding a new error `code` branch is a one-file
|
|
12
|
+
* edit that does not retrigger the full LLM CI matrix (`action/main.ts` is
|
|
13
|
+
* in `action/test/coverage.ts::ALWAYS_RUN_ALL`).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Billing-layer error surfaced from `/api/proxy-token` as a 402. User-actionable
|
|
17
|
+
* — distinct from TransientError (503 / transient sync issue) so the job
|
|
18
|
+
* summary + PR comment can use affirmative "you need to do X" copy rather than
|
|
19
|
+
* the ambiguous "billing error" label that makes transient outages look like
|
|
20
|
+
* the user's fault.
|
|
21
|
+
*
|
|
22
|
+
* `code` is a server-side discriminator: `router_requires_card` (no card + no
|
|
23
|
+
* wallet balance on Router), or null for unclassified. `declineCode` is
|
|
24
|
+
* Stripe's more specific sub-reason on `card_declined` (e.g.
|
|
25
|
+
* `insufficient_funds`, `lost_card`). `needsReauthentication` is the 3DS case
|
|
26
|
+
* broken out for convenience.
|
|
27
|
+
*/
|
|
28
|
+
export declare class BillingError extends Error {
|
|
29
|
+
code: string | null;
|
|
30
|
+
declineCode: string | null;
|
|
31
|
+
needsReauthentication: boolean;
|
|
32
|
+
constructor(message: string, opts?: {
|
|
33
|
+
code?: string | null;
|
|
34
|
+
declineCode?: string | null;
|
|
35
|
+
needsReauthentication?: boolean;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Transient service failures from `/api/proxy-token` (503: partial OpenRouter
|
|
40
|
+
* usage sync, DB flake, in-flight payment intent). Not the user's fault — the
|
|
41
|
+
* summary uses "temporarily unavailable" framing, and the non-zero exit lets
|
|
42
|
+
* GH Actions apply whatever retry policy the workflow has configured.
|
|
43
|
+
*/
|
|
44
|
+
export declare class TransientError extends Error {
|
|
45
|
+
constructor(message: string);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Render a BillingError as user-facing markdown (shared between GH job summary
|
|
49
|
+
* and the PR progress comment). Goals:
|
|
50
|
+
*
|
|
51
|
+
* - quiet, not alarmist — bold first line instead of an `### ❌` H3, since
|
|
52
|
+
* the comment already has Terramend branding in the footer
|
|
53
|
+
* - actionable — every branch ends in a single CTA deep-linked to the
|
|
54
|
+
* correct section of the owner's console
|
|
55
|
+
* - honest — say what actually went wrong (card declined vs. balance
|
|
56
|
+
* empty vs. 3DS required), don't lump them under "billing error"
|
|
57
|
+
*
|
|
58
|
+
* Branches:
|
|
59
|
+
* - `router_requires_card`: user is on Router mode with no card AND no
|
|
60
|
+
* wallet balance (signup credit exhausted or not granted). Frame as
|
|
61
|
+
* "add a card to continue", link to `#model-access` where the Add
|
|
62
|
+
* Card flow lives.
|
|
63
|
+
* - `router_balance_exhausted`: user has a card on file but auto-reload is
|
|
64
|
+
* disabled and they've spent past their $5 overdraft buffer. Frame as
|
|
65
|
+
* "balance ran out" and surface both remediation paths (top up, or flip
|
|
66
|
+
* on auto-reload).
|
|
67
|
+
* - `router_keylimit_exhausted`: OpenRouter rejected mid-run because the
|
|
68
|
+
* per-run key budget was exhausted while the agent was working. The
|
|
69
|
+
* wallet is now negative; same remediation as `router_balance_exhausted`
|
|
70
|
+
* but framed for the after-the-fact case ("this run was cut short").
|
|
71
|
+
* - `needsReauthentication`: issuer requires 3DS on every off-session
|
|
72
|
+
* charge. Re-adding the card won't help — the only escape is a manual
|
|
73
|
+
* top-up where 3DS runs interactively in Stripe Checkout.
|
|
74
|
+
* - `declineCode` set: Stripe declined a real charge. Show the sub-code
|
|
75
|
+
* so support can act on it; tell the user we'll retry on next dispatch.
|
|
76
|
+
* - default: balance hit zero with no in-flight charge (auto-reload off
|
|
77
|
+
* or amount below threshold). Direct them to top up or enable auto-reload.
|
|
78
|
+
*/
|
|
79
|
+
export declare function formatBillingErrorSummary(error: BillingError, owner: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Render a TransientError as user-facing markdown. Distinct framing from
|
|
82
|
+
* BillingError so the user doesn't read an alarm and assume their card
|
|
83
|
+
* failed — this branch is "our fault, retry shortly", not theirs.
|
|
84
|
+
*/
|
|
85
|
+
export declare function formatTransientErrorSummary(error: TransientError, owner: string): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PayloadEvent } from "#app/external";
|
|
2
|
+
import type { OctokitWithPlugins } from "#app/utils/github";
|
|
3
|
+
import type { RunContextData } from "#app/utils/runContextData";
|
|
4
|
+
interface ResolveBodyContext {
|
|
5
|
+
event: PayloadEvent;
|
|
6
|
+
octokit: OctokitWithPlugins;
|
|
7
|
+
repo: RunContextData["repo"];
|
|
8
|
+
tmpdir: string;
|
|
9
|
+
githubToken: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* resolves the body of an event by fetching body_html and converting to markdown.
|
|
13
|
+
* only fetches body_html if the body contains images (to avoid unnecessary API calls).
|
|
14
|
+
* this ensures agents receive markdown with working signed image URLs instead of
|
|
15
|
+
* broken user-attachments URLs.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveBody(ctx: ResolveBodyContext): Promise<string | null>;
|
|
18
|
+
interface ResolveBodyAssetsContext {
|
|
19
|
+
body: string | null | undefined;
|
|
20
|
+
bodyHtml: string | null | undefined;
|
|
21
|
+
tmpdir: string;
|
|
22
|
+
githubToken: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* downloads github-hosted image assets in a body to disk and rewrites the urls to local
|
|
26
|
+
* paths so the agent can read them. when the body has images and a rendered `bodyHtml`
|
|
27
|
+
* is supplied, the html is turndowned first: github only exposes attachments as signed,
|
|
28
|
+
* self-authenticating `*.githubusercontent.com` urls through body_html — the raw
|
|
29
|
+
* `github.com/user-attachments/...` urls in unrendered markdown 404 for the installation
|
|
30
|
+
* token. callers that fetch a body should request it with the `application/vnd.github.full+json`
|
|
31
|
+
* media type and pass `body_html` here.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveBodyAssets(ctx: ResolveBodyAssetsContext): Promise<string | null>;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const TERRAMEND_DIVIDER = "<!-- TERRAMEND_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
|
2
|
+
export interface BuildTerramendFooterParams {
|
|
3
|
+
/** add "via Terramend" link */
|
|
4
|
+
triggeredBy?: boolean;
|
|
5
|
+
/** arbitrary custom parts (e.g., action links) */
|
|
6
|
+
customParts?: string[] | undefined;
|
|
7
|
+
/** model slug from payload (e.g., "anthropic/claude-opus"). shown in footer as "Using `Model Name`" */
|
|
8
|
+
model?: string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* When the action engaged the BYOK fallback, this is the slug the user
|
|
11
|
+
* had configured (e.g. "anthropic/claude-opus") — the footer renders
|
|
12
|
+
* `Using <free model> (credentials for <configured> not configured)`
|
|
13
|
+
* so the substitution is visible in PR comments + reviews.
|
|
14
|
+
*/
|
|
15
|
+
fallbackFrom?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* build a terramend footer with configurable parts
|
|
19
|
+
* order: action links (customParts) > model > attribution
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildTerramendFooter(params: BuildTerramendFooterParams): string;
|
|
22
|
+
/**
|
|
23
|
+
* strip any existing terramend footer from a comment body
|
|
24
|
+
*/
|
|
25
|
+
export declare function stripExistingFooter(body: string): string;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { AgentId } from "#app/external";
|
|
2
|
+
/**
|
|
3
|
+
* Slug we fall back to when a BYOK-required model is configured but the
|
|
4
|
+
* runner has no provider key in env. Picked because it's free, stable, and
|
|
5
|
+
* currently served by OpenCode Zen without a key.
|
|
6
|
+
*
|
|
7
|
+
* The slug is intentionally hard-coded and not a config knob — the
|
|
8
|
+
* fallback is a safety net, not a user-facing preference, and adding a
|
|
9
|
+
* config surface here would just push the same "what to fall back to"
|
|
10
|
+
* decision into another setting that goes stale the same way.
|
|
11
|
+
*/
|
|
12
|
+
export declare const FREE_FALLBACK_SLUG = "opencode/big-pickle";
|
|
13
|
+
/**
|
|
14
|
+
* Outcome of the BYOK model gate.
|
|
15
|
+
*
|
|
16
|
+
* - `use-resolved`: run the configured model as-is.
|
|
17
|
+
* - `fallback`: the runner has NO provider key for this model's provider,
|
|
18
|
+
* so swap to the free OpenCode slug — a genuine no-key safety net.
|
|
19
|
+
* - `unavailable`: a provider key IS present but the configured model is
|
|
20
|
+
* not one OpenCode can route with it. This is almost always a wrong or
|
|
21
|
+
* mistyped model id (or a key scoped to other models). We must NOT
|
|
22
|
+
* silently downgrade to the free model — that hides the misconfiguration
|
|
23
|
+
* and produces a free run the user didn't ask for (see PR #2). The caller
|
|
24
|
+
* fails loudly with the authorized-model list instead.
|
|
25
|
+
*/
|
|
26
|
+
export type FallbackDecision = {
|
|
27
|
+
kind: "use-resolved";
|
|
28
|
+
} | {
|
|
29
|
+
kind: "fallback";
|
|
30
|
+
from: string;
|
|
31
|
+
to: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "unavailable";
|
|
34
|
+
model: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Does the runner have a provider credential for `resolvedModel`'s provider?
|
|
38
|
+
*
|
|
39
|
+
* Uses the provider→envVars map in `models.ts` (provider-level, since a
|
|
40
|
+
* resolved specifier like `google/gemini-3.5-flash-lite` won't match a catalog
|
|
41
|
+
* model key and correctly falls through to the provider's env vars). A present
|
|
42
|
+
* key is what distinguishes the two not-authorized situations: key present =
|
|
43
|
+
* wrong/unavailable model id (fail loudly); no key = genuine BYOK gap (free
|
|
44
|
+
* fallback).
|
|
45
|
+
*/
|
|
46
|
+
export declare function hasProviderKeyForModel(resolvedModel: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Decide whether to run the configured model, fall back to the free model, or
|
|
49
|
+
* fail because the model is unavailable to the present key.
|
|
50
|
+
*
|
|
51
|
+
* `authorized` is OpenCode's authoritative "what can I route right now"
|
|
52
|
+
* snapshot, captured after Codex auth.json is in place.
|
|
53
|
+
*
|
|
54
|
+
* Skip cases (always `use-resolved`, without consulting `authorized`):
|
|
55
|
+
* - No resolved model: auto-select handles it downstream.
|
|
56
|
+
* - Resolved model is the free fallback already.
|
|
57
|
+
* - Resolved model is a raw Bedrock / Vertex ID (no `/`): the routing
|
|
58
|
+
* validators (`validateBedrockSetup` / `validateVertexSetup`) cover
|
|
59
|
+
* auth + region/location/model-id; `opencode models` does not.
|
|
60
|
+
* - The selected agent is `claude`: the Claude Code harness brings its own
|
|
61
|
+
* auth and `resolveAgent` only returns it when that auth is present.
|
|
62
|
+
* `opencode models` can't see `CLAUDE_CODE_OAUTH_TOKEN`, so without this
|
|
63
|
+
* an OAuth-subscription run on an Anthropic model would land in
|
|
64
|
+
* `unavailable` (the token counts as a present provider key) and fail a
|
|
65
|
+
* run the claude harness serves fine. `validateAgentApiKey` still covers
|
|
66
|
+
* the claude path with its own Anthropic auth check.
|
|
67
|
+
*/
|
|
68
|
+
export declare function selectFallbackModelIfNeeded(input: {
|
|
69
|
+
resolvedModel: string | undefined;
|
|
70
|
+
authorized: Set<string>;
|
|
71
|
+
/** whether a provider key for the resolved model's provider is present in env */
|
|
72
|
+
providerKeyPresent: boolean;
|
|
73
|
+
/** which agent harness `resolveAgent` picks for the resolved model */
|
|
74
|
+
agentName: AgentId;
|
|
75
|
+
}): FallbackDecision;
|
|
76
|
+
/**
|
|
77
|
+
* Loud, actionable error for the `unavailable` decision: a provider key is
|
|
78
|
+
* present but the configured model isn't one the key can serve. Lists the
|
|
79
|
+
* models OpenCode CAN route (same-provider first) so the user can copy a valid
|
|
80
|
+
* slug instead of getting a silent free downgrade.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildUnavailableModelError(input: {
|
|
83
|
+
model: string;
|
|
84
|
+
authorized: Set<string>;
|
|
85
|
+
}): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type SubscriptionPreflight = {
|
|
2
|
+
usable: true;
|
|
3
|
+
} | {
|
|
4
|
+
usable: false;
|
|
5
|
+
reason: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* preflight a Claude subscription OAuth token (`CLAUDE_CODE_OAUTH_TOKEN`)
|
|
9
|
+
* with a 1-token Messages call, so the agent can fall back to
|
|
10
|
+
* `ANTHROPIC_API_KEY` when the subscription is exhausted or revoked instead
|
|
11
|
+
* of failing the whole run at its first model call. rides the same de-facto
|
|
12
|
+
* OAuth surface Claude Code itself uses: Bearer auth + the
|
|
13
|
+
* `claude-code-20250219,oauth-2025-04-20` betas + the identity system prompt.
|
|
14
|
+
*
|
|
15
|
+
* probes the run's own model when known — subscription limits can be
|
|
16
|
+
* per-model ("You've hit your Opus limit"), so a cheaper stand-in could pass
|
|
17
|
+
* preflight and still leave the run dead on arrival.
|
|
18
|
+
*
|
|
19
|
+
* fail-open by design: only 401 (revoked/expired token) and 429
|
|
20
|
+
* (session/weekly/per-model limit) mark the token unusable. network errors,
|
|
21
|
+
* 5xx, and request-shape drift (400) all keep today's subscription-first
|
|
22
|
+
* behavior, so the preflight can never fail a run that would have worked —
|
|
23
|
+
* the worst wrong answer is a run that bills the API key instead of the
|
|
24
|
+
* subscription.
|
|
25
|
+
*/
|
|
26
|
+
export declare function preflightClaudeSubscription(params: {
|
|
27
|
+
token: string;
|
|
28
|
+
/** bare Anthropic model id the run will use (e.g. "claude-fable-5") */
|
|
29
|
+
model: string | undefined;
|
|
30
|
+
}): Promise<SubscriptionPreflight>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
export { formatIndentedField, formatJsonValue, formatUsageSummary, log, writeSummary, } from "#app/utils/log";
|
|
5
|
+
/**
|
|
6
|
+
* Finds a CLI executable path by checking if it's installed globally
|
|
7
|
+
* @param name The name of the CLI executable to find
|
|
8
|
+
* @returns The path to the CLI executable, or null if not found
|
|
9
|
+
*/
|
|
10
|
+
export declare function findCliPath(name: string): string | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** sandbox-hidden home for terramend-managed on-disk secrets in CI. bash via
|
|
2
|
+
* MCP shell tmpfs-overlays this path; opencode's internal auth module
|
|
3
|
+
* bypasses external_directory and reaches the real file. mirrors the
|
|
4
|
+
* pattern in action/agents/claude.ts installManagedSettings.
|
|
5
|
+
*
|
|
6
|
+
* not used for codex auth in local dev — the sandbox is no-op there, so
|
|
7
|
+
* the path doesn't matter. local dev keeps the existing $HOME path. */
|
|
8
|
+
export declare const TERRAMEND_DATA_DIR = "/var/lib/terramend";
|
|
9
|
+
export interface InstalledCodexAuth {
|
|
10
|
+
/** absolute path of the auth.json we wrote — caller passes this to the
|
|
11
|
+
* post-hook via core.saveState for refresh-detection later. */
|
|
12
|
+
authPath: string;
|
|
13
|
+
/** value to set as XDG_DATA_HOME for the OpenCode subprocess. */
|
|
14
|
+
xdgDataHome: string;
|
|
15
|
+
/** refresh_token from the env at materialization time. post-hook
|
|
16
|
+
* compares against the on-disk file after the run to detect whether
|
|
17
|
+
* OpenCode refreshed during the session (only happens on long runs
|
|
18
|
+
* that span >50min — see wiki/codex-auth.md "Concurrency"). */
|
|
19
|
+
originalRefresh: string;
|
|
20
|
+
}
|
|
21
|
+
/** materialize CODEX_AUTH_JSON from env into a disk path OpenCode reads from.
|
|
22
|
+
* returns null when the env var is absent, malformed, or wrong auth mode —
|
|
23
|
+
* caller treats null as "no codex auth, fall through to API key flow".
|
|
24
|
+
*
|
|
25
|
+
* The env value is read as-is — we parse + write it here and set
|
|
26
|
+
* `process.env.XDG_DATA_HOME` so every opencode subprocess discovers the
|
|
27
|
+
* auth.json; no refresh and no DB interaction. Freshness is the supplier's
|
|
28
|
+
* responsibility (see the header caveat on static-secret expiry). */
|
|
29
|
+
export declare function installCodexAuth(): InstalledCodexAuth | null;
|