The thinking row and the header menu both carry Stop while a bot has work open for the user anywhere: every pending or processing job of that bot in their conversations is failed as stopped, its task closed, a Stopped step recorded and one closing message posted per session, so the thread stops waiting and the bot goes idle. The handler running the job is aborted from this process through a registry, so a job stuck waiting on a model stops at once instead of on its next heartbeat, and a late face change after the abort is dropped. The release stage is now said in the app too: Settings > General reports "Cobble v0.1.5 (alpha)" next to development, and the README and RELEASING.md say what alpha means for installs.
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import { BotStoppedMessage } from "@/src/dict/bot-queue-dict";
|
|
|
|
type Job = {
|
|
session_id?: number | string | null;
|
|
kind?: string | null;
|
|
title?: string | null;
|
|
};
|
|
|
|
/**
|
|
* What the bot says in a conversation the user stopped it in. A task names
|
|
* the work that was cut off, so a long job that quietly went nowhere reads
|
|
* as stopped rather than as finished; a reply has no title worth quoting.
|
|
*/
|
|
export default function stoppedJobReport({ job }: { job: Job }): string {
|
|
const title = (job.title || "").trim();
|
|
|
|
return job.kind == "task" && title
|
|
? `${BotStoppedMessage} I was on **${title}**.`
|
|
: BotStoppedMessage;
|
|
}
|
|
|
|
/**
|
|
* The job that speaks for each session: one per session, since a reply and
|
|
* the task it started are the same conversation and two notes there read as
|
|
* a stutter. A task wins, because it's the one that can name the work.
|
|
*/
|
|
export function pickReportedJobs<T extends Job>({ jobs }: { jobs: T[] }): Map<number, T> {
|
|
const picked = new Map<number, T>();
|
|
|
|
for (const job of jobs) {
|
|
/**
|
|
* A job with no session is stopped all the same; it just has
|
|
* nowhere to report it.
|
|
*/
|
|
if (job.session_id === null || job.session_id === undefined) continue;
|
|
|
|
const known = picked.get(Number(job.session_id));
|
|
|
|
if (!known || (known.kind != "task" && job.kind == "task")) {
|
|
picked.set(Number(job.session_id), job);
|
|
}
|
|
}
|
|
|
|
return picked;
|
|
}
|