mirror of
https://github.com/severian-dev/sucker.severian.dev.git
synced 2026-10-18 01:20:29 +00:00
Diagnose setup by what is certain, and deliver errors the way the client asked
Review of the branch found the persona diagnosis was mostly truncation wearing a name tag. The <.> marker sits at the start of the system message and the persona marker after the card, so a card Janitor cut short arrives with the prompt present and the persona gone — and was told its persona was wrong, with truncation as an afterthought. The original message was only ever about context size, which is the best evidence there is about what actually happens. diagnoseSetup() now says only what the markers make certain. A missing <.> is a missing prompt, since truncation cannot remove the first three characters. A persona marker that is present but not "." is a wrong description, quoted back so there is nothing to guess. A persona marker that is gone, or cut off mid-tag, leads with truncation and mentions the persona second. The error path decided "streaming?" from the Accept header while the success path used body.stream, so a client that sent stream:true without that header got JSON back for every error and never displayed it. The flag is hoisted above the try; the header is only a fallback for when the body could not be read. Token search is restricted to after the greeting, in order. A card built from a sucker-proxied chat could carry an expired token in its text, and a lookup on it would fail forever. Conversation order also means the token a chat was started with always wins over one pasted later. The system fallback now takes a role-less first message only; a request with roles but no system turn is reported as such rather than misdiagnosed as a missing prompt. The echo feature reads the parser's lastUser instead of its own case-sensitive lookup. "Nothing was saved" is dropped from the unknown-error message, since it is not guaranteed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
This commit is contained in:
+26
-2
@@ -62,13 +62,26 @@ test("the token is still found once later replies stop carrying it", () => {
|
||||
assert.match(found!, /\[sucker:conv=abc123\]/);
|
||||
});
|
||||
|
||||
test("a token the user just pasted outranks an older one", () => {
|
||||
test("the token a chat was started with outranks one pasted later, so a chat cannot flip between cards", () => {
|
||||
const candidates = tokenCandidates([
|
||||
...withProbe,
|
||||
{ role: "assistant", content: `created (v1). ${TOKEN}` },
|
||||
{ role: "user", content: "{{user}}: [sucker:conv=zzz999]" },
|
||||
]);
|
||||
assert.match(candidates[0], /zzz999/);
|
||||
const first = candidates.find((c) => c.includes("sucker:conv="));
|
||||
assert.match(first!, /abc123/);
|
||||
});
|
||||
|
||||
test("a token in the card or the greeting is never a candidate", () => {
|
||||
const stale = "[sucker:conv=stale00]";
|
||||
const candidates = tokenCandidates([
|
||||
{ role: "system", content: `${CARD} made with sucker: ${stale}` },
|
||||
{ role: "user", content: "." },
|
||||
{ role: "assistant", content: `${GREETING} ${stale}` },
|
||||
{ role: "user", content: NAME },
|
||||
]);
|
||||
assert.ok(!candidates.some((c) => c.includes(stale)), "an expired token baked into a card would make it unextractable forever");
|
||||
assert.deepEqual(candidates, [NAME]);
|
||||
});
|
||||
|
||||
test("roles are matched whatever their casing", () => {
|
||||
@@ -106,6 +119,17 @@ test("messages with no usable content are skipped, not treated as slots", () =>
|
||||
assert.equal(slots.nameSlot, NAME);
|
||||
});
|
||||
|
||||
test("a request with roles but no system turn has no card, rather than a misdiagnosed one", () => {
|
||||
const slots = selectMessageSlots([
|
||||
{ role: "assistant", content: GREETING },
|
||||
{ role: "user", content: NAME },
|
||||
]);
|
||||
// Taking the greeting as the card would produce a "custom prompt not set"
|
||||
// message for a request the user could never have fixed.
|
||||
assert.equal(slots.system, undefined);
|
||||
assert.equal(slots.greeting, GREETING);
|
||||
});
|
||||
|
||||
test("a card with no role on the system turn still resolves", () => {
|
||||
const slots = selectMessageSlots([
|
||||
{ content: CARD },
|
||||
|
||||
Reference in New Issue
Block a user