/** * What a session is called. * * It was called whatever you typed first, truncated to eighty characters, for ever. So a session * that began "hi" and went on to build a ledger page was called "hi" — and the picker, which exists * to answer "which of these was the one about X", answered "hi", "ok", "continue" and "what is 2+2" * for a week's work. * * Two mistakes in one line of code. The first message is often not the request: it is a greeting, an * acknowledgement, a "carry on". And a title set once cannot follow a session that turned into * something else, which is what sessions do. * * So the name is derived from the substance and revised as the substance changes. Mechanically * first, because that always works and costs nothing: the earliest message that actually asks for * something, cleaned up. Then, once there is enough to summarise, the model is asked for a short * one — which is the only way to get "Stokvel dashboard with recharts" out of a conversation that * happens to open with "hi". That ask is cheap, happens once, and never blocks a turn; when it * fails the mechanical name stands. */ /** * Messages, as much of them as naming needs. * * Deliberately loose. The provider's own message type has a narrower role union and several content * shapes, some of which omit content altogether, and a stricter shape here would refuse the very * array it exists to read. Naming only needs to know who said something and what it said. */ export interface Said { role?: unknown; content?: unknown; } export declare function isPleasantry(text: string): boolean; /** The text of a message, whatever shape its content came in. */ export declare function textOf(message: Said | undefined): string; /** * A name from the conversation itself, with no model involved. * * The earliest thing said that asks for something: greetings are skipped, KONECK's own prefixes are * skipped, and a message too short to mean anything is skipped. Falls back to the first message * there is — because a session called "hi" is still better than one called nothing — and to a plain * label when even that is missing. */ export declare function mechanicalTitle(messages: readonly Said[], limit?: number): string; /** One line, no markdown fences, no newlines, trimmed to length at a word boundary. */ export declare function tidy(text: string, limit?: number): string; /** * Whether a session has enough in it to be worth naming properly. * * Asking a model to name "hi" wastes a call and produces a title about greetings. Two exchanges, or * one substantial request, is the point at which there is something to summarise. */ export declare function worthNaming(messages: readonly Said[]): boolean; /** * What to ask the model for. * * The instruction is narrow on purpose: a model asked to "summarise" writes a sentence, and a model * asked for a title writes "Session Summary: Implementation of...". Naming the shape wanted, giving * an example of the register, and forbidding the two habits it will otherwise reach for is what gets * a usable answer back in one attempt rather than three. */ export declare function titleQuestion(messages: readonly Said[], take?: number): string; /** * The model's answer, made safe to use as a title, or null when it is not usable. * * A model asked for six words will sometimes send a paragraph, a quoted phrase, a bulleted list or * an apology. Anything that does not look like a label is refused, and the mechanical name stands — * a bad title is worse than a plain one, because a picker full of "Certainly! Here is a title" is * unreadable in a way that "hi" at least is not. */ export declare function usableTitle(answer: string, limit?: number, /** * Text the title must not simply be. * * A model that ignores the instruction answers with whatever it would have said anyway, and an * echo of its own last reply looks exactly like a label: short, declarative, plausible. Caught in * a test where the stubbed model answered every question identically and the session ended up * named "Looked at it. One file, hello.txt" — which reads as a title and is not one. */ avoid?: readonly string[]): string | null; //# sourceMappingURL=session-title.d.ts.map