Strict Chat-Completion Compatibility
Nội dung này hiện chưa có sẵn bằng ngôn ngữ của bạn.
Different LLM provider APIs enforce conflicting message structure requirements. TomoriBot normalizes role alternation, prefix completion, and assistant media behind a shared seam in src/providers/utils/strictChatCompat.ts so built-in and custom-endpoint proxies can communicate with strict backends.
The three normalizations
Section titled “The three normalizations”| Normalization | Setting | Mechanism |
|---|---|---|
| Role alternation | strict_role_alternation | Merges consecutive same-role messages into one and prepends a synthetic leading user turn ([System: Conversation start]) when the dialogue opens with an assistant turn. Tool-bearing turns act as merge boundaries so tool_calls and tool_call_id metadata are preserved. |
| Prefix completion | supports_prefix_completion | Stamps prefix: true on the trailing assistant message (applyAssistantPrefixCompletion) to activate vendor continuation modes (DeepSeek, Z.ai). |
| Media relocation | Shared serialization policy | Moves assistant media into following synthetic user turns (relocateAssistantMediaContextItems) with sender attribution. This gives adapters a common representation that strict backends can accept. |
Orthogonal compatibility toggles
Section titled “Orthogonal compatibility toggles”Role alternation and prefix completion address independent backend constraints and remain decoupled:
- A proxy fronting Claude requires role alternation enabled and prefix completion disabled; sending
prefix: truecauses request rejection. - A proxy fronting DeepSeek or vLLM continue modes requires prefix completion enabled, without needing same-role turn merging.
A single bundled toggle would prevent configuring backends that need only one of these behaviors.
Assistant prefill capability
Section titled “Assistant prefill capability”supports_assistant_prefill records whether the backend accepts and continues a trailing assistant turn instead of rejecting it with an HTTP 400 error (such as Claude 4.6+ or Gemini 3.5 Flash-Lite) or restarting output from the beginning. It is distinct from prefix completion: prefix completion designates the prefix: true request field, while assistant prefill designates whether the model accepts the trailing turn.
- Tool conflicts on DeepSeek: DeepSeek rejects
prefix: truein requests that also carrytools. When tool calling is active, the prefill resolver (resolvePrefillBlockerinsrc/utils/chat/assistantPrefill.ts) skips server prefills and converts/respondprefills into written prompt instructions. - Tool loop folding: When a model initiates a tool call, trailing prefill text is folded into the first tool call’s assistant message (
foldPrefillIntoToolHistory). This prevents consecutive assistant turns that strict-alternation backends would reject. - Persona’s own message last: A turn that starts without new user input (a self-triggered or system-initiated turn) can build history that ends on the persona’s own delivered message.
applyAssistantPrefillthen appends a user directive asking for the next message, because only this attempt’s own prefill may end the request. NovelAI is exempt: text completion continues from a trailing persona line by design.
Media relocation
Section titled “Media relocation”The structured request builders apply media relocation independently of the alternation and prefix-completion toggles. When dialogue history includes images sent by an assistant (such as generated images), the media parts are extracted into an immediately following synthetic user message:
[System: The following image was sent by {name}.]When no sender name is available, the notice falls back to [System: The following image was sent]. Relocation runs on structured context items before provider-specific serialization, preserving participant indices and mention metadata.
Prompt layout and cache identity
Section titled “Prompt layout and cache identity”Serializers use isPromptSystemItem() from the prompt-layout registry for system routing. A system
role alone does not determine placement for tagged items. Untagged preset nodes keep their authored
roles. Normalization preserves the cacheable-prefix marker through media relocation and same-role
merging, including when the boundary item ends in media.
Direct Anthropic and Anthropic models through OpenRouter request two five-minute cache breakpoints:
the system-message end and the final serialized item above the tail slot. Each is admitted only when
the local text estimate reaches the model minimum; missing boundaries or undersized prefixes omit
that marker. src/providers/utils/anthropicCache.ts owns this policy. Explicit rejection of
cache_control removes it for a targeted retry.
resolveToolCallId() in src/providers/utils/toolCallIds.ts preserves usable unique provider IDs
and generates deterministic IDs in interaction-history order otherwise. OpenRouter, OpenAI-compatible,
and Anthropic serializers reuse the resolved ID for the call and result, so appending tool-loop steps
does not change IDs already serialized into the prefix.
Resolution and persistence
Section titled “Resolution and persistence”Compatibility settings are stored as boolean columns on llms and custom_endpoints:
- Built-in providers: Seeded with required flags in
src/db/seed/catalog/models.ts(Anthropic enables alternation; DeepSeek, Z.ai, and Z.ai Coding enable prefix completion).supports_assistant_prefillis configured per measured model. - Custom endpoints: Expose these settings as checkboxes under Chat Completion Compatibilities in
/providersand/setup. Values sync to the custom endpoint’s syntheticllmsrow viaupsertSyntheticCustomLlm. - Runtime safety net:
providerRequiresAlternation()andproviderRequiresPrefixCompletion()instrictChatCompat.tsOR-combine with stored database flags, preventing mis-seeded catalog rows from emitting invalid bodies. - Verification gate:
bun run check-seed-catalogsvalidates required flags at boot and in CI (collectStrictChatFlagViolationsinsrc/db/seed/catalog/modelSeed.ts) to keep built-in requirements synchronized.
Source pointers
Section titled “Source pointers”src/providers/utils/strictChatCompat.ts: Message normalization functions (mergeConsecutiveSameRole,ensureLeadingUserTurn,applyAssistantPrefixCompletion,relocateAssistantMediaContextItems).src/utils/chat/assistantPrefill.ts: Prefill capability resolution and tool conflict detection (resolvePrefillBlocker).src/db/seed/catalog/models.ts: Seed definitions for built-in provider model flags.src/db/seed/catalog/modelSeed.ts: Seed verification gates (collectStrictChatFlagViolations).