eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1// Pure helper for shaping the Claude message list, split out of runtime.mjs so
2// it's exercisable in Node tests (test/context.test.mjs) without the SDK/ws deps.
3
4// trimContext drops assistant turns from BOTH ends of the message list. The API
5// requires the first turn to be `user`; and with extended thinking on (the
6// runtime always sends `thinking:{adaptive}`) the conversation also can't END on
7// an assistant turn — there's no prefill under thinking, so a trailing assistant
8// turn is a hard "assistant message prefill" 400. A trailing assistant turn shows
9// up whenever the newest message we can see is our own reply (e.g. a redelivery
10// race where a message got processed after we'd already answered); trimming it
11// lets the request through instead of erroring. Returns a new array.
12export function trimContext(messages) {
13 const out = [...(messages || [])];
14 while (out.length && out[0].role === "assistant") out.shift();
15 while (out.length && out[out.length - 1].role === "assistant") out.pop();
16 return out;
17}
18
19// scrubSelfNotes removes the "[note to self: …]" history annotation from a
20// reply about to POST. The note is appended to past assistant turns (see
21// buildContext in runtime.mjs) so the model knows which of its old replies
22// carried buttons — but the model reads those turns as its own words and,
23// despite the system-prompt rule, eventually imitates the pattern into a live
24// reply. The note is for the model, never for members.
25export function scrubSelfNotes(text) {
26 return (text || "").replace(/\s*\[note to self:[^\]]*\]/g, "").trim();
27}
28