@todoist/doistbot-cli 0.0.0-stage → 1.0.16
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/dist/actions/auth.js +225 -0
- package/dist/actions/doctor.js +39 -0
- package/dist/actions/review-usage.js +25 -0
- package/dist/actions/review.js +311 -0
- package/dist/actions/setup.js +14 -0
- package/dist/auth.js +202 -0
- package/dist/config.js +145 -0
- package/dist/env.js +10 -0
- package/dist/file-store.js +112 -0
- package/dist/index.js +164 -0
- package/dist/input.js +40 -0
- package/dist/runtime.js +105 -0
- package/dist/secure-store.js +148 -0
- package/dist/terminal.js +185 -0
- package/dist/test-utils/secure-store-mocks.js +29 -0
- package/dist/update-cache-entrypoint.js +16 -0
- package/dist/update-check.js +235 -0
- package/package.json +65 -5
- package/sandbox/_node_modules/doistbot-logging/dist/index.d.ts +23 -0
- package/sandbox/_node_modules/doistbot-logging/dist/index.js +51 -0
- package/sandbox/_node_modules/doistbot-logging/package.json +12 -0
- package/sandbox/_node_modules/doistbot-repo-config/dist/index.d.ts +93 -0
- package/sandbox/_node_modules/doistbot-repo-config/dist/index.js +197 -0
- package/sandbox/_node_modules/doistbot-repo-config/package.json +12 -0
- package/sandbox/dist/core/autofix-resources.js +58 -0
- package/sandbox/dist/core/autofix-service-query.js +69 -0
- package/sandbox/dist/core/autofix-test-policy.js +11 -0
- package/sandbox/dist/core/autofix-verification.js +355 -0
- package/sandbox/dist/core/bot-logins.js +14 -0
- package/sandbox/dist/core/check-run.js +158 -0
- package/sandbox/dist/core/datadog-metrics.js +113 -0
- package/sandbox/dist/core/environment.js +49 -0
- package/sandbox/dist/core/git-auth.js +17 -0
- package/sandbox/dist/core/github-history.js +4 -0
- package/sandbox/dist/core/github-issues.js +18 -0
- package/sandbox/dist/core/label-parsing.js +1 -0
- package/sandbox/dist/core/langfuse-observation.js +33 -0
- package/sandbox/dist/core/langfuse-session.js +39 -0
- package/sandbox/dist/core/logger-span-processor.js +90 -0
- package/sandbox/dist/core/logging.js +18 -0
- package/sandbox/dist/core/pi-autofix-extension.js +188 -0
- package/sandbox/dist/core/pi-execution-limits-extension.js +79 -0
- package/sandbox/dist/core/pi-progress-logging.js +51 -0
- package/sandbox/dist/core/pi-tool-output-filter-extension.js +65 -0
- package/sandbox/dist/core/pi.js +870 -0
- package/sandbox/dist/core/pii-scrubber.js +31 -0
- package/sandbox/dist/core/prompt-template.js +63 -0
- package/sandbox/dist/core/reactions.js +36 -0
- package/sandbox/dist/core/regexp.js +3 -0
- package/sandbox/dist/core/repository-map.js +1 -0
- package/sandbox/dist/core/repository-resolver.js +1 -0
- package/sandbox/dist/core/retry.js +29 -0
- package/sandbox/dist/core/s3-utils.js +42 -0
- package/sandbox/dist/core/shared.js +124 -0
- package/sandbox/dist/core/snapshot-helpers.js +17 -0
- package/sandbox/dist/core/span-test-helpers.js +13 -0
- package/sandbox/dist/core/tool-environment.js +83 -0
- package/sandbox/dist/core/tool-output.js +18 -0
- package/sandbox/dist/core/tracing-setup.js +92 -0
- package/sandbox/dist/core/tracing.js +81 -0
- package/sandbox/dist/main.js +51 -0
- package/sandbox/dist/providers/config.js +23 -0
- package/sandbox/dist/providers/credentials.js +40 -0
- package/sandbox/dist/providers/gemini.js +28 -0
- package/sandbox/dist/providers/helpers.js +253 -0
- package/sandbox/dist/providers/index.js +27 -0
- package/sandbox/dist/providers/openai.js +23 -0
- package/sandbox/dist/providers/openrouter-pi.js +25 -0
- package/sandbox/dist/providers/pi-review.js +301 -0
- package/sandbox/dist/providers/process.js +34 -0
- package/sandbox/dist/providers/schemas.js +61 -0
- package/sandbox/dist/providers/types.js +4 -0
- package/sandbox/dist/tasks/chat/chat.js +440 -0
- package/sandbox/dist/tasks/chat/prompt.js +20 -0
- package/sandbox/dist/tasks/issue-fix-retry/fix-retry.js +304 -0
- package/sandbox/dist/tasks/issue-summarize/context.js +21 -0
- package/sandbox/dist/tasks/issue-summarize/media.js +335 -0
- package/sandbox/dist/tasks/issue-summarize/model.js +230 -0
- package/sandbox/dist/tasks/issue-summarize/output.js +45 -0
- package/sandbox/dist/tasks/issue-summarize/prompt.js +11 -0
- package/sandbox/dist/tasks/issue-summarize/summarize.js +238 -0
- package/sandbox/dist/tasks/issue-summarize/thread.js +123 -0
- package/sandbox/dist/tasks/issue-summarize/types.js +1 -0
- package/sandbox/dist/tasks/issue-triage/assignee-review.js +114 -0
- package/sandbox/dist/tasks/issue-triage/autofix-capabilities.js +22 -0
- package/sandbox/dist/tasks/issue-triage/autofix-checkpoint.js +122 -0
- package/sandbox/dist/tasks/issue-triage/autofix-policy.js +36 -0
- package/sandbox/dist/tasks/issue-triage/clone.js +40 -0
- package/sandbox/dist/tasks/issue-triage/context.js +57 -0
- package/sandbox/dist/tasks/issue-triage/diff-validator.js +102 -0
- package/sandbox/dist/tasks/issue-triage/fix-attempt.js +617 -0
- package/sandbox/dist/tasks/issue-triage/fix-context.js +5 -0
- package/sandbox/dist/tasks/issue-triage/fix-dispatch.js +263 -0
- package/sandbox/dist/tasks/issue-triage/fix-failure-reasons.js +2 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/effects.js +526 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/effects.types.js +1 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/fake-effects.js +65 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/promotion-task.js +108 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/recovery.js +512 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/runners.js +233 -0
- package/sandbox/dist/tasks/issue-triage/fix-loop/state-machine.js +171 -0
- package/sandbox/dist/tasks/issue-triage/github-request.js +2 -0
- package/sandbox/dist/tasks/issue-triage/hero-group-map.js +206 -0
- package/sandbox/dist/tasks/issue-triage/markers.js +6 -0
- package/sandbox/dist/tasks/issue-triage/model.js +124 -0
- package/sandbox/dist/tasks/issue-triage/output.js +164 -0
- package/sandbox/dist/tasks/issue-triage/pr-creator.js +585 -0
- package/sandbox/dist/tasks/issue-triage/pr-readiness.js +25 -0
- package/sandbox/dist/tasks/issue-triage/prompt.js +63 -0
- package/sandbox/dist/tasks/issue-triage/repo-config.js +47 -0
- package/sandbox/dist/tasks/issue-triage/repo-prompts.js +77 -0
- package/sandbox/dist/tasks/issue-triage/report-fixture.js +53 -0
- package/sandbox/dist/tasks/issue-triage/report-history.js +113 -0
- package/sandbox/dist/tasks/issue-triage/report-schema.js +63 -0
- package/sandbox/dist/tasks/issue-triage/report.js +111 -0
- package/sandbox/dist/tasks/issue-triage/resolution.js +30 -0
- package/sandbox/dist/tasks/issue-triage/routing.js +169 -0
- package/sandbox/dist/tasks/issue-triage/sandbox-environment.js +59 -0
- package/sandbox/dist/tasks/issue-triage/shared.js +86 -0
- package/sandbox/dist/tasks/issue-triage/side-effects.js +102 -0
- package/sandbox/dist/tasks/issue-triage/triage.js +442 -0
- package/sandbox/dist/tasks/issue-triage/types.js +1 -0
- package/sandbox/dist/tasks/persist-logs/context.js +19 -0
- package/sandbox/dist/tasks/persist-logs/dd-proxy.js +116 -0
- package/sandbox/dist/tasks/persist-logs/llm-query-planner.js +156 -0
- package/sandbox/dist/tasks/persist-logs/persist-logs.js +491 -0
- package/sandbox/dist/tasks/refresh-s3-urls/refresh-s3-urls.js +214 -0
- package/sandbox/dist/tasks/review/check-run.js +326 -0
- package/sandbox/dist/tasks/review/comment-mapper.js +46 -0
- package/sandbox/dist/tasks/review/conversation-context.js +477 -0
- package/sandbox/dist/tasks/review/diff.js +95 -0
- package/sandbox/dist/tasks/review/engines/dedupe.js +291 -0
- package/sandbox/dist/tasks/review/engines/multi-focus.js +419 -0
- package/sandbox/dist/tasks/review/engines/shared.js +87 -0
- package/sandbox/dist/tasks/review/engines/types.js +1 -0
- package/sandbox/dist/tasks/review/finding-output.js +18 -0
- package/sandbox/dist/tasks/review/format.js +17 -0
- package/sandbox/dist/tasks/review/github-comment-format.js +94 -0
- package/sandbox/dist/tasks/review/local-git.js +374 -0
- package/sandbox/dist/tasks/review/local.js +118 -0
- package/sandbox/dist/tasks/review/multi-focus-prompt.js +59 -0
- package/sandbox/dist/tasks/review/prompt.js +81 -0
- package/sandbox/dist/tasks/review/review-feedback.js +48 -0
- package/sandbox/dist/tasks/review/review-mode-github.js +58 -0
- package/sandbox/dist/tasks/review/review-mode-policy.js +232 -0
- package/sandbox/dist/tasks/review/review-mode-types.js +1 -0
- package/sandbox/dist/tasks/review/review-mode.js +296 -0
- package/sandbox/dist/tasks/review/review-summary.js +123 -0
- package/sandbox/dist/tasks/review/review.js +391 -0
- package/sandbox/dist/tasks/review/runner.js +255 -0
- package/sandbox/dist/tasks/review/severity.js +5 -0
- package/sandbox/dist/tasks/review/summary-model.js +271 -0
- package/sandbox/dist/tasks/review/thinking-level.js +14 -0
- package/sandbox/dist/tasks/review/translation-review-policy.js +37 -0
- package/sandbox/dist/tasks/review/types.js +1 -0
- package/sandbox/dist/tasks/review-slice-plan/context.js +66 -0
- package/sandbox/dist/tasks/review-slice-plan/plan.js +210 -0
- package/sandbox/dist/tasks/review-slice-plan/prompt.js +59 -0
- package/sandbox/dist/tasks/review-slice-plan/review-slice-plan.js +367 -0
- package/sandbox/dist/tasks/sentry-triage/store.js +133 -0
- package/sandbox/dist/tasks/sentry-triage/triage.js +217 -0
- package/sandbox/node_modules/doistbot-logging/dist/index.d.ts +23 -0
- package/sandbox/node_modules/doistbot-logging/dist/index.js +51 -0
- package/sandbox/node_modules/doistbot-logging/package.json +12 -0
- package/sandbox/node_modules/doistbot-repo-config/dist/index.d.ts +93 -0
- package/sandbox/node_modules/doistbot-repo-config/dist/index.js +197 -0
- package/sandbox/node_modules/doistbot-repo-config/package.json +12 -0
- package/sandbox/src/review/prompts/ai-internal-tools.md +254 -0
- package/sandbox/src/review/prompts/backend-repository-standards.md +102 -0
- package/sandbox/src/review/prompts/observability-standard.md +169 -0
- package/sandbox/src/review/prompts/outline-map.json +26 -0
- package/sandbox/src/review/prompts/secrets-management.md +286 -0
- package/sandbox/src/review/prompts/service-production-readiness.md +122 -0
- package/sandbox/src/review/prompts/workload-placement.md +345 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/efficiency.md +16 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/general.md +32 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/quality.md +20 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/reuse.md +13 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/security.md +18 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/standards.md +21 -0
- package/sandbox/src/tasks/review/prompts/review-focus-prompts/tests.md +19 -0
- package/sandbox/src/tasks/review/prompts/review-mode.md +40 -0
- package/sandbox/src/tasks/review/prompts/review-multi-focus-base-prompt.md +142 -0
- package/scripts/restore-runtime-assets.mjs +21 -0
- package/README.md +0 -3
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
import { repositoryKey } from 'doistbot-issue-routing';
|
|
3
|
+
import { logger } from '../../core/logging.js';
|
|
4
|
+
import { withPhase } from '../../core/tracing.js';
|
|
5
|
+
import { DefaultLoopEffects } from './fix-loop/effects.js';
|
|
6
|
+
import { IssueFixRecovery } from './fix-loop/recovery.js';
|
|
7
|
+
import { runFixLoop } from './fix-loop/runners.js';
|
|
8
|
+
import { buildFixAssessmentSkipReason, shouldAttemptFix } from './fix-attempt.js';
|
|
9
|
+
import { fixSource } from './fix-context.js';
|
|
10
|
+
import { FIX_LOOP_FAILED_REASON_PREFIX } from './fix-failure-reasons.js';
|
|
11
|
+
function fallbackRepository(input) {
|
|
12
|
+
return (input.fixAssessment.targetRepo ??
|
|
13
|
+
(input.clonedRepos.length === 1
|
|
14
|
+
? input.clonedRepos[0].repository.fullName
|
|
15
|
+
: `${input.ctx.owner}/${input.ctx.repo}`));
|
|
16
|
+
}
|
|
17
|
+
function resolveFixTarget(input) {
|
|
18
|
+
if (input.clonedRepos.length === 0) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
repository: fallbackRepository(input),
|
|
22
|
+
reason: 'No cloned repositories available for fix attempt.',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (input.fixAssessment.targetRepo) {
|
|
26
|
+
const targetRepo = input.clonedRepos.find((repo) => repositoryKey(repo.repository.fullName) ===
|
|
27
|
+
repositoryKey(input.fixAssessment.targetRepo));
|
|
28
|
+
if (targetRepo) {
|
|
29
|
+
return { ok: true, targetRepo };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
repository: fallbackRepository(input),
|
|
34
|
+
reason: `Unable to resolve a unique target repository from assessment: ${input.fixAssessment.targetRepo}`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (input.clonedRepos.length === 1) {
|
|
38
|
+
return { ok: true, targetRepo: input.clonedRepos[0] };
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
repository: fallbackRepository(input),
|
|
43
|
+
reason: 'Unable to resolve a unique target repository from assessment: missing targetRepo',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function stateLogMeta(state) {
|
|
47
|
+
return {
|
|
48
|
+
kind: state.kind,
|
|
49
|
+
...(state.kind !== 'AWAITING_FIRST_FIX' && 'iteration' in state
|
|
50
|
+
? { iteration: state.iteration }
|
|
51
|
+
: {}),
|
|
52
|
+
...('branch' in state && state.branch !== undefined ? { branch: state.branch } : {}),
|
|
53
|
+
...('prNumber' in state && state.prNumber !== undefined
|
|
54
|
+
? { pr_number: state.prNumber }
|
|
55
|
+
: {}),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function logDryRunTransition({ from, event, to }) {
|
|
59
|
+
logger.info('DRY RUN: fix loop state transition', {
|
|
60
|
+
task: 'fix-loop',
|
|
61
|
+
from: stateLogMeta(from),
|
|
62
|
+
event: event.kind,
|
|
63
|
+
to: stateLogMeta(to),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function errorReason(error) {
|
|
67
|
+
return error instanceof Error ? error.message : String(error);
|
|
68
|
+
}
|
|
69
|
+
function prUrlFor(targetRepo, prNumber) {
|
|
70
|
+
return `https://github.com/${targetRepo.repository.fullName}/pull/${prNumber}`;
|
|
71
|
+
}
|
|
72
|
+
export async function runConfiguredFix(input) {
|
|
73
|
+
return withPhase(input.phaseName ?? 'triage.fix-attempt', { 'gen_ai.operation.name': 'invoke_agent', 'gen_ai.agent.name': 'codex.fix' }, async (span) => {
|
|
74
|
+
function finish(result) {
|
|
75
|
+
const prCreated = 'prCreated' in result ? result.prCreated : false;
|
|
76
|
+
// Only a real PR number counts as PR-evidence — dry-run loop
|
|
77
|
+
// states can carry a placeholder prNumber of 0.
|
|
78
|
+
const prNumber = 'prNumber' in result && result.prNumber !== undefined && result.prNumber > 0
|
|
79
|
+
? result.prNumber
|
|
80
|
+
: undefined;
|
|
81
|
+
// Dry-run skips are expected outcomes, not failures — signaled
|
|
82
|
+
// by the stable dryRun flag on the result, never by parsing
|
|
83
|
+
// the human-readable reason copy.
|
|
84
|
+
const isDryRunSkip = 'dryRun' in result && result.dryRun === true;
|
|
85
|
+
let outcome;
|
|
86
|
+
if (prCreated) {
|
|
87
|
+
outcome = 'pr-created';
|
|
88
|
+
}
|
|
89
|
+
else if (isDryRunSkip) {
|
|
90
|
+
outcome = 'dry-run';
|
|
91
|
+
}
|
|
92
|
+
else if (prNumber !== undefined) {
|
|
93
|
+
// The loop opened a PR earlier (REVIEWING/ITERATING) but
|
|
94
|
+
// ended needing a human: a PR exists, the autonomous
|
|
95
|
+
// attempt did not finish.
|
|
96
|
+
outcome = 'pr-opened-needs-human';
|
|
97
|
+
}
|
|
98
|
+
else if (result.attempted) {
|
|
99
|
+
outcome = 'attempted-no-pr';
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
outcome = 'not-attempted';
|
|
103
|
+
}
|
|
104
|
+
span.setAttributes({
|
|
105
|
+
'fix.attempted': result.attempted,
|
|
106
|
+
'fix.repository': result.repository,
|
|
107
|
+
'fix.pr_created': prCreated,
|
|
108
|
+
...(prNumber !== undefined ? { 'fix.pr_number': prNumber } : {}),
|
|
109
|
+
'fix.outcome': outcome,
|
|
110
|
+
});
|
|
111
|
+
// A real attempt that did not deliver a ready PR is a failure
|
|
112
|
+
// (including pr-opened-needs-human — someone must take over);
|
|
113
|
+
// a legitimate skip or a dry-run is not. withPhase does not
|
|
114
|
+
// force OK on a normal return, so this ERROR survives to
|
|
115
|
+
// phase.end.
|
|
116
|
+
if (result.attempted && !prCreated && !isDryRunSkip && 'reason' in result) {
|
|
117
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: result.reason });
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
const target = resolveFixTarget(input);
|
|
122
|
+
if (!target.ok) {
|
|
123
|
+
return finish({
|
|
124
|
+
attempted: false,
|
|
125
|
+
repository: target.repository,
|
|
126
|
+
reason: target.reason,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const targetRepo = target.targetRepo;
|
|
130
|
+
if (!input.retry && !shouldAttemptFix(input.fixAssessment)) {
|
|
131
|
+
return finish({
|
|
132
|
+
attempted: false,
|
|
133
|
+
repository: targetRepo.repository.fullName,
|
|
134
|
+
reason: buildFixAssessmentSkipReason(input.fixAssessment),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
let recovery;
|
|
138
|
+
let initial;
|
|
139
|
+
try {
|
|
140
|
+
if (!input.ctx.dryRun) {
|
|
141
|
+
recovery = new IssueFixRecovery({
|
|
142
|
+
issueUrl: input.issueUrl,
|
|
143
|
+
...fixSource(input.ctx),
|
|
144
|
+
triageOutput: input.triageOutput,
|
|
145
|
+
targetRepo,
|
|
146
|
+
githubToken: input.ctx.githubToken,
|
|
147
|
+
octokit: input.octokit,
|
|
148
|
+
bucket: process.env.LOG_SNAPSHOT_BUCKET,
|
|
149
|
+
});
|
|
150
|
+
initial = await recovery.prepare(input.retry === true);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
return finish({
|
|
155
|
+
attempted: true,
|
|
156
|
+
prCreated: false,
|
|
157
|
+
repository: targetRepo.repository.fullName,
|
|
158
|
+
reason: `Could not restore saved fix: ${errorReason(error)}`,
|
|
159
|
+
recoveryRefused: true,
|
|
160
|
+
...(recovery?.existingPR ? { prNumber: recovery.existingPR } : {}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const session = {
|
|
164
|
+
kind: 'fix-loop',
|
|
165
|
+
ctx: input.ctx,
|
|
166
|
+
octokit: input.octokit,
|
|
167
|
+
triageOutput: input.triageOutput,
|
|
168
|
+
fixAssessment: input.fixAssessment,
|
|
169
|
+
targetRepo,
|
|
170
|
+
issueTitle: input.issueTitle,
|
|
171
|
+
issueUrl: input.issueUrl,
|
|
172
|
+
ghToken: input.ghToken,
|
|
173
|
+
pushToken: input.ctx.githubToken,
|
|
174
|
+
assigneeReview: input.assigneeReview,
|
|
175
|
+
manualRetry: input.retry,
|
|
176
|
+
modelPhaseName: `${input.phaseName ?? 'triage.fix-attempt'}.model`,
|
|
177
|
+
apiKeys: {
|
|
178
|
+
openai: input.ctx.openaiApiKey,
|
|
179
|
+
...(input.ctx.geminiApiKey !== undefined && { gemini: input.ctx.geminiApiKey }),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
const effects = new DefaultLoopEffects(session, { dryRun: input.ctx.dryRun, recovery });
|
|
183
|
+
let recoverySaved = false;
|
|
184
|
+
const saveRecovery = recovery
|
|
185
|
+
? async (state) => {
|
|
186
|
+
await recovery.beforeStep(state);
|
|
187
|
+
if (!recoverySaved) {
|
|
188
|
+
if (input.onRecoverySaved && !recovery.shared)
|
|
189
|
+
throw new Error('Could not save the shared fix checkpoint');
|
|
190
|
+
await input.onRecoverySaved?.();
|
|
191
|
+
recoverySaved = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
: undefined;
|
|
195
|
+
let finalState;
|
|
196
|
+
try {
|
|
197
|
+
finalState = await runFixLoop({
|
|
198
|
+
effects,
|
|
199
|
+
initial,
|
|
200
|
+
beforeStep: saveRecovery,
|
|
201
|
+
beforeFinish: saveRecovery
|
|
202
|
+
? (state) => effects.interruption ? Promise.resolve() : saveRecovery(state)
|
|
203
|
+
: undefined,
|
|
204
|
+
...(input.ctx.dryRun ? { onTransition: logDryRunTransition } : {}),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
return finish({
|
|
209
|
+
attempted: true,
|
|
210
|
+
repository: targetRepo.repository.fullName,
|
|
211
|
+
prCreated: false,
|
|
212
|
+
reason: `${FIX_LOOP_FAILED_REASON_PREFIX} ${errorReason(error)}`,
|
|
213
|
+
...(recovery && 'prNumber' in recovery.state
|
|
214
|
+
? { prNumber: recovery.state.prNumber }
|
|
215
|
+
: {}),
|
|
216
|
+
...(recovery
|
|
217
|
+
? {
|
|
218
|
+
interruption: {
|
|
219
|
+
stage: recovery.state.kind === 'REVIEWING' ? 'review' : 'fix',
|
|
220
|
+
saved: recovery.shared,
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
: {}),
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (finalState.kind === 'PUSHED_AWAITING_CI') {
|
|
227
|
+
if (input.ctx.dryRun) {
|
|
228
|
+
return finish({
|
|
229
|
+
attempted: true,
|
|
230
|
+
repository: targetRepo.repository.fullName,
|
|
231
|
+
prCreated: false,
|
|
232
|
+
reason: 'Dry run: PR not created.',
|
|
233
|
+
dryRun: true,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
const prNumber = finalState.prNumber;
|
|
237
|
+
const prUrl = prUrlFor(targetRepo, prNumber);
|
|
238
|
+
return finish({
|
|
239
|
+
attempted: true,
|
|
240
|
+
repository: targetRepo.repository.fullName,
|
|
241
|
+
prCreated: true,
|
|
242
|
+
prUrl,
|
|
243
|
+
prNumber,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const reason = finalState.kind === 'DONE_NEEDS_HUMAN'
|
|
247
|
+
? finalState.reason
|
|
248
|
+
: `Fix loop ended in ${finalState.kind}`;
|
|
249
|
+
return finish({
|
|
250
|
+
attempted: true,
|
|
251
|
+
repository: targetRepo.repository.fullName,
|
|
252
|
+
prCreated: false,
|
|
253
|
+
reason,
|
|
254
|
+
...(effects.interruption ? { interruption: effects.interruption } : {}),
|
|
255
|
+
// If a PR was opened earlier in the loop (REVIEWING/ITERATING reached
|
|
256
|
+
// before DONE_NEEDS_HUMAN), surface it so callers can distinguish a
|
|
257
|
+
// silent failure from an in-progress PR.
|
|
258
|
+
...('prNumber' in finalState && finalState.prNumber !== undefined
|
|
259
|
+
? { prNumber: finalState.prNumber }
|
|
260
|
+
: {}),
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
}
|