| 92 | 92 | | import { buildMentionPrompt, describeThread, handleMention, jobTokenRefusal, planMention } from "./mentions"; |
| 93 | 93 | | import { instructionsFor, repoInstructions, withBlock } from "./repo-instructions"; |
| 94 | 94 | | import { cancelTask, enqueueTask, handedOverStep, selfHostedRoute, taskEnv, taskRepo } from "./self-hosted"; |
| 95 | | − | import { answered, describeError, tellStopped, withinTimeCap } from "./lifecycle"; |
| 95 | + | import { answered, capReached, describeError, stoppedShort, tellStopped, withinTimeCap } from "./lifecycle"; |
| 96 | 96 | | import { |
| 97 | 97 | | ABUSE_EXIT_CODE, |
| 98 | 98 | | ABUSE_HOST, |
| ⋯ |
| 480 | 480 | | throw error; |
| 481 | 481 | | } |
| 482 | 482 | | await this.ctx.storage.put("run", run); |
| 483 | | − | await this.ctx.storage.delete(["abuse", "stopReason", "remote", "misdirected"]); |
| 483 | + | // What an earlier attempt in this object left: its reason, its cap |
| 484 | + | // and its cap's alarm, which would otherwise stop this attempt when |
| 485 | + | // the earlier one's time ran out (re-runs use the same object). |
| 486 | + | await this.ctx.storage.delete(["abuse", "stopReason", "remote", "misdirected", "timeCap"]); |
| 487 | + | this.deleteSchedules("timeUp"); |
| 484 | 488 | | if (meter) await this.ctx.storage.put("meter", { ...meter, started: Date.now() }); |
| 485 | 489 | | await this.ctx.storage.put("started", Date.now()); |
| 486 | 490 | | const who = meter ? { workspace: meter.workspace, repo: meter.repo } : owner; |
| ⋯ |
| 681 | 685 | | |
| 682 | 686 | | /** The run's time cap has passed: stop it, as stopped for time. */ |
| 683 | 687 | | async timeUp(): Promise<void> { |
| 684 | | − | // It already stopped: nothing to stop. |
| 685 | | − | if (!(await this.ctx.storage.get<number>("started"))) return; |
| 686 | | − | const tracked = await this.ctx.storage.get<TrackedRun>("agentRun"); |
| 688 | + | // It already stopped (nothing to stop), or the run in it now is a later |
| 689 | + | // attempt whose cap has not passed: this alarm is an earlier attempt's, |
| 690 | + | // left by a version of g1t that did not clear it, and the run now has |
| 691 | + | // its own. |
| 692 | + | const started = await this.ctx.storage.get<number>("started"); |
| 687 | 693 | | const minutes = (await this.ctx.storage.get<number>("timeCap")) ?? 0; |
| 694 | + | if (!capReached(started, minutes, Date.now())) { |
| 695 | + | if (started) console.log("an earlier attempt's time cap passed; the run now keeps going", this.ctx.id.toString()); |
| 696 | + | return; |
| 697 | + | } |
| 698 | + | const tracked = await this.ctx.storage.get<TrackedRun>("agentRun"); |
| 688 | 699 | | // A workflow job or a build has no run to halt: it fails saying why. |
| 689 | 700 | | await this.ctx.storage.put("stopReason", timeCapMessage(minutes)); |
| 690 | 701 | | if (tracked) await reportRun(this.env.WORK, tracked, { halt: "time", error: timeCapMessage(minutes) }); |
| ⋯ |
| 816 | 827 | | const flagged = (await this.ctx.storage.get<boolean>("abuse")) ?? false; |
| 817 | 828 | | // Why it stopped, when g1t stopped it: said in place of a plain failure. |
| 818 | 829 | | const why = flagged ? ABUSE_MESSAGE : ((await this.ctx.storage.get<string>("stopReason")) ?? null); |
| 830 | + | // Stopped by g1t, it failed whatever exit code the library passed on. |
| 831 | + | const short = stoppedShort(exitCode, why); |
| 819 | 832 | | const ended = await this.closeRun( |
| 820 | | − | exitCode === 0 ? "succeeded" : "failed", |
| 821 | | − | exitCode === 0 ? undefined : (why ?? `The sandbox exited with ${exitCode}.`), |
| 833 | + | short ? "failed" : "succeeded", |
| 834 | + | short ? (why ?? `The sandbox exited with ${exitCode}.`) : undefined, |
| 822 | 835 | | ); |
| 823 | 836 | | await this.settleStopped(started, tracked); |
| 824 | 837 | | await this.ctx.storage.delete("started"); |
| 825 | | − | if (exitCode === 0 && !flagged) return; |
| 838 | + | if (!short) return; |
| 826 | 839 | | const run = await this.ctx.storage.get<Run>("run"); |
| 827 | 840 | | // A person stopped it: g1t has already left the pull request for them. |
| 828 | 841 | | if (ended === "stopped" && run && STOP_ENDS.has(run.kind)) return; |