Clarify appended messages and streamline repair

This commit is contained in:
2026-08-26 02:37:47 +00:00
parent 174516cb39
commit 404a4c331d
2 changed files with 30 additions and 17 deletions

View File

@@ -55,19 +55,20 @@ func (r *defaultOutputRepairer) Repair(ctx context.Context, req RepairRequest) (
return nil, err return nil, err
} }
messages := domain.ConcatRenderedMessages(req.OriginalMessages, nil) hasPreviousOutput := strings.TrimSpace(req.PreviousOutput) != ""
if strings.TrimSpace(req.PreviousOutput) != "" { suffix := make([]domain.RenderedMessage, 0, 2)
messages = append(messages, domain.RenderedMessage{ if hasPreviousOutput {
suffix = append(suffix, domain.RenderedMessage{
Role: domain.RoleAssistant, Role: domain.RoleAssistant,
Content: req.PreviousOutput, Content: req.PreviousOutput,
}) })
} }
previousResponse := "The previous response was empty." previousResponse := "The previous response was empty."
if strings.TrimSpace(req.PreviousOutput) != "" { if hasPreviousOutput {
previousResponse = "The previous response is included immediately before this instruction." previousResponse = "The previous response is included immediately before this instruction."
} }
messages = append(messages, domain.RenderedMessage{ suffix = append(suffix, domain.RenderedMessage{
Role: domain.RoleUser, Role: domain.RoleUser,
Content: fmt.Sprintf( Content: fmt.Sprintf(
"Repair attempt %d of %d for validation mode %s.\n"+ "Repair attempt %d of %d for validation mode %s.\n"+
@@ -82,6 +83,7 @@ func (r *defaultOutputRepairer) Repair(ctx context.Context, req RepairRequest) (
formatRepairDiagnostics(req.ValidationErrors), formatRepairDiagnostics(req.ValidationErrors),
), ),
}) })
messages := domain.ConcatRenderedMessages(req.OriginalMessages, suffix)
resp, err := r.llm.Generate(ctx, newGenerationRequest( resp, err := r.llm.Generate(ctx, newGenerationRequest(
domain.RenderedPrompt{Messages: messages}, domain.RenderedPrompt{Messages: messages},

View File

@@ -123,13 +123,20 @@ type RunRequest struct {
// Validation optionally replaces the prompt's complete output contract. It // Validation optionally replaces the prompt's complete output contract. It
// does not merge individual fields. Nil uses the prompt contract. // does not merge individual fields. Nil uses the prompt contract.
Validation *OutputContract Validation *OutputContract
// AppendedMessages are already-rendered messages appended after every prompt // AppendedMessages are already-rendered messages appended in caller order
// definition message. Promptkit neither templates nor resolves files in // after every prompt definition message. Promptkit neither templates nor
// them, and preserves valid content exactly. Roles are trimmed and // resolves files in them. Content must be valid UTF-8 and is preserved
// exactly, including empty or whitespace-only content. Roles are trimmed and
// lowercased, then must be [RoleDeveloper], [RoleSystem], [RoleUser], or // lowercased, then must be [RoleDeveloper], [RoleSystem], [RoleUser], or
// [RoleAssistant]. Nil and empty slices are equivalent. Prepare, // [RoleAssistant]. Any CacheControl is normalized as documented on that
// PrepareExecution, and Run validate and copy the messages before source or // type.
// model work; malformed values return an error matching ErrInvalidRequest. //
// Nil and empty slices are equivalent. Promptkit imposes no message-count,
// byte-size, token, or context-window limit and does not truncate content;
// an upstream rejection follows the ordinary generation-error contract.
// Prepare, PrepareExecution, and Run validate and copy the messages before
// source or model work. Malformed values return an error matching
// ErrInvalidRequest.
AppendedMessages []RenderedMessage AppendedMessages []RenderedMessage
} }
@@ -170,8 +177,9 @@ type PreparedRun struct {
SessionID string `json:"session_id,omitempty"` SessionID string `json:"session_id,omitempty"`
// RenderedPromptHash is an opaque equality value for SessionID and Messages. // RenderedPromptHash is an opaque equality value for SessionID and Messages.
RenderedPromptHash string `json:"rendered_prompt_hash"` RenderedPromptHash string `json:"rendered_prompt_hash"`
// Messages are the rendered messages that Run or RunPrepared passes to the // Messages are the complete effective messages that Run or RunPrepared passes
// LLM client. // to the LLM client: definition messages in rendered order followed by any
// RunRequest.AppendedMessages in caller order.
Messages []RenderedMessage `json:"messages"` Messages []RenderedMessage `json:"messages"`
// StartTime is the UTC time at which preparation began. // StartTime is the UTC time at which preparation began.
StartTime time.Time `json:"start_time,omitempty"` StartTime time.Time `json:"start_time,omitempty"`
@@ -633,8 +641,8 @@ type RenderedPrompt struct {
// SessionID is the optional effective direct or rendered session // SessionID is the optional effective direct or rendered session
// identifier supplied to the model client. // identifier supplied to the model client.
SessionID string `json:"session_id,omitempty"` SessionID string `json:"session_id,omitempty"`
// Messages contains the frozen effective messages: definition messages in // Messages contains the effective messages in provider order: definition
// their rendered order followed by any RunRequest.AppendedMessages. // messages in rendered order followed by any RunRequest.AppendedMessages.
Messages []RenderedMessage `json:"messages"` Messages []RenderedMessage `json:"messages"`
} }
@@ -645,14 +653,17 @@ type RenderedPrompt struct {
type RenderedMessage struct { type RenderedMessage struct {
// Role is the provider-bound chat role. // Role is the provider-bound chat role.
Role string `json:"role"` Role string `json:"role"`
// Content is the provider-bound message text and may be empty or whitespace. // Content is the provider-bound message text. Request-supplied content must
// be valid UTF-8 and may be empty or whitespace-only.
Content string `json:"content"` Content string `json:"content"`
// CacheControl is optional provider cache metadata. // CacheControl is optional provider cache metadata.
CacheControl *CacheControl `json:"cache_control,omitempty"` CacheControl *CacheControl `json:"cache_control,omitempty"`
} }
// CacheControl describes provider cache metadata attached to prompt content // CacheControl describes provider cache metadata attached to prompt content
// and has a stable JSON representation. // and has a stable JSON representation. At a request boundary Type and TTL
// must be valid UTF-8 and are trimmed. Type must be [CacheControlEphemeral],
// and TTL must be empty or "1h"; other values make the request invalid.
type CacheControl struct { type CacheControl struct {
// Type identifies the cache behavior. // Type identifies the cache behavior.
Type CacheControlType `json:"type"` Type CacheControlType `json:"type"`