/**
* Conversation-shape rules for the OpenAI Chat Completions API. Pure — no
* React, no HTTP — so the domain harness can test them.
*
* What the standards require, and where each rule comes from:
*
* - Every `tool_calls` entry on an assistant message must be answered by a
* `role: "tool"` message carrying the same `tool_call_id`, directly after
* that assistant message. Chat Completions rejects the request otherwise
* ("An assistant message with 'tool_calls' must be followed by tool messages
* responding to each 'tool_call_id'"). LiteLLM only repairs this for
* Anthropic, and only with `modify_params` on
* (docs.litellm.ai/docs/completion/message_sanitization), so the client owns
* it: a turn is only kept in history once it is well-formed.
*
* - Prompt caching is an exact-prefix match over tools → system → messages.
* OpenAI: "Put stable developer instructions and shared reference material
* first … place [dynamic content] at the end rather than the beginning"
* (developers.openai.com/api/docs/guides/prompt-caching). Anthropic: "For a
* prompt with a varying suffix (timestamps, per-request context, the
* incoming message), place the breakpoint at the end of the static prefix"
* (platform.claude.com/docs/en/docs/build-with-claude/prompt-caching). So
* the system prompt carries only the stable part and live state rides in
* the current user message, after the history.
*
* - Anthropic has no `system` role inside `messages` ("there is no 'system'
* role for input messages in the Messages API") and "consecutive user or
* assistant turns … will be combined into a single turn"
* (platform.claude.com/docs/en/api/messages); LiteLLM merges consecutive
* same-role messages for it. A mid-conversation note is therefore a `user`
* message, never a `system` one, and two user messages in a row are fine.
*/
export interface ConversationToolCall {
id: string;
[key: string]: unknown;
}
export interface ConversationMessage {
role: string;
content: string | null;
tool_calls?: ConversationToolCall[];
tool_call_id?: string;
[key: string]: unknown;
}
/** One exchange: the user's message and everything the model did in reply. */
export type Turn = ConversationMessage[];
export declare const CONTEXT_OPEN = "";
export declare const CONTEXT_CLOSE = "";
/** Appended to the system prompt whenever a context block is in use. */
export declare const CONTEXT_PREAMBLE = "A user message may begin with a block: the live state of the application at the moment that message was sent. It is authoritative and more current than anything said in earlier turns.";
/** The user's text, prefixed with the live context block when there is one. */
export declare const withContext: (text: string, context: string) => string;
/**
* The messages array for one request: stable system prompt, the kept turns
* verbatim, then the incoming message carrying the per-request context.
*/
export declare const buildRequestMessages: (systemPrompt: string, history: readonly Turn[], userText: string, context: string) => ConversationMessage[];
/**
* Keeps the newest `max` turns. Whole turns only, so an assistant `tool_calls`
* message is never separated from the tool messages that answer it.
*/
export declare const trimTurns: (turns: readonly Turn[], max: number) => {
turns: Turn[];
dropped: number;
};
/** Tool calls in `turn` that no tool message answers. */
export declare const unansweredToolCalls: (turn: readonly ConversationMessage[]) => ConversationToolCall[];
/**
* Makes `turn` valid to resend by inserting a tool message for every
* unanswered tool call, directly after the assistant message that made it.
* `result(call)` supplies the content (JSON-stringified). Mutates `turn`;
* returns the messages it inserted.
*/
export declare const answerUnansweredToolCalls: (turn: ConversationMessage[], result: (call: ConversationToolCall) => unknown) => ConversationMessage[];
//# sourceMappingURL=conversation.d.ts.map