mirror of
https://github.com/severian-dev/sucker.severian.dev.git
synced 2026-10-18 01:20:29 +00:00
Say what actually went wrong
Every failure produced the same reply: read the directions, and check your context size. For a card Janitor truncated that was fair. For a request shape the user never chose, or for a bug in sucker, it blamed them for something they could not have done anything about — and sent them back to directions they had already followed. Failures that can be explained now explain themselves: no card in the request, no greeting in the chat, a card that arrived truncated (which keeps the context-size advice, since that is where it belongs), and a request with nothing in it. Anything else is a bug nobody anticipated, so the reply says as much, says it is not the user's fault, and asks them to DM @lyseverian on Discord — an unexplained failure nobody reports never gets fixed. Internals are never echoed back. SuckerError is recognised by name as well as by identity, because Next can bundle a module into more than one chunk and a mismatched class would quietly send every explained error down the unknown-bug path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Telling people what actually went wrong.
|
||||
*
|
||||
* Every failure used to produce one message: "You dingus, read the directions
|
||||
* on sucker before trying again", with a note about context size. For a
|
||||
* truncated card that was fair. For a request shape the user never chose, or
|
||||
* for a bug in sucker, it blamed them for something they could not have done
|
||||
* anything about — and told them to check directions they had already followed.
|
||||
*
|
||||
* So: anything thrown as a SuckerError is written for the person who hit it
|
||||
* and is shown to them verbatim. Anything else is a bug nobody anticipated,
|
||||
* and the reply says so and asks them to report it, because an unexplained
|
||||
* failure that nobody hears about never gets fixed.
|
||||
*/
|
||||
|
||||
/** Where to send someone when sucker is at fault. */
|
||||
export const CONTACT = "DM @lyseverian on Discord";
|
||||
|
||||
export class SuckerError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "SuckerError";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `instanceof` is checked by name as well: Next can bundle the same module
|
||||
* into more than one chunk, and a class identity that differs between them
|
||||
* would quietly send every explained error down the "unknown bug" path.
|
||||
*/
|
||||
export function isSuckerError(error: unknown): error is SuckerError {
|
||||
return (
|
||||
error instanceof SuckerError ||
|
||||
(typeof error === "object" &&
|
||||
error !== null &&
|
||||
(error as { name?: unknown }).name === "SuckerError")
|
||||
);
|
||||
}
|
||||
|
||||
export function userFacingMessage(error: unknown): string {
|
||||
if (isSuckerError(error)) return error.message;
|
||||
return (
|
||||
"Something went wrong that sucker has no explanation for, and nothing was " +
|
||||
`saved. This one is not your fault — please ${CONTACT} and say what you ` +
|
||||
"were pulling, because unreported ones do not get fixed."
|
||||
);
|
||||
}
|
||||
|
||||
/** The card arrived without the markers sucker needs to read it. */
|
||||
export const TRUNCATED_CARD = new SuckerError(
|
||||
"The card came through incomplete — the markers sucker looks for are not in " +
|
||||
"it. That usually means the bot is larger than your context size and " +
|
||||
"Janitor cut it short, so raise Context Size in Generation Settings and " +
|
||||
`try again. If it is already generous, re-read the directions on sucker, and ${CONTACT} if it still will not go.`
|
||||
);
|
||||
|
||||
export const NO_CARD = new SuckerError(
|
||||
"There is no character card in that request — sucker could not find a " +
|
||||
"system message in it. Point sucker at a chat with a bot in it, not an " +
|
||||
"empty one, and try again."
|
||||
);
|
||||
|
||||
export const NO_GREETING = new SuckerError(
|
||||
"That chat has no message from the bot yet, so there is nothing to pull. " +
|
||||
"Open the chat until the bot's first message shows, then send again."
|
||||
);
|
||||
|
||||
export const TOO_FEW_MESSAGES = new SuckerError(
|
||||
"That request barely had anything in it — sucker needs a chat with a bot " +
|
||||
"and at least one message in it. Open the chat properly and try again."
|
||||
);
|
||||
Reference in New Issue
Block a user