Files
promptkit/types.go

719 lines
32 KiB
Go

package promptkit
import (
"context"
"time"
)
// ArtifactRefType identifies how an [ArtifactRef] supplies content.
type ArtifactRefType string
const (
// ArtifactRefInline selects ArtifactRef.Body as the content.
ArtifactRefInline ArtifactRefType = "inline"
// ArtifactRefFile selects the filesystem path in ArtifactRef.URI.
ArtifactRefFile ArtifactRefType = "file"
)
// OutputFormat identifies the media format of generated output.
// OutputFormat has a stable JSON string representation.
type OutputFormat string
const (
// FormatText identifies plain-text output.
FormatText OutputFormat = "text"
// FormatMarkdown identifies Markdown output.
FormatMarkdown OutputFormat = "markdown"
// FormatJSON identifies JSON output.
FormatJSON OutputFormat = "json"
)
// ValidationMode identifies how generated output is checked.
// ValidationMode has a stable JSON string representation.
type ValidationMode string
const (
// ValidationNone skips content validation.
ValidationNone ValidationMode = "none"
// ValidationBasic requires non-empty output.
ValidationBasic ValidationMode = "basic"
// ValidationJSON requires syntactically valid JSON.
ValidationJSON ValidationMode = "json"
// ValidationJSONSchema requires JSON that satisfies OutputContract.SchemaPath.
ValidationJSONSchema ValidationMode = "json_schema"
)
// ValidationStatus identifies the completed state of an output check.
// ValidationStatus has a stable JSON string representation.
type ValidationStatus string
const (
// ValidationPassed means the generated output satisfied its contract.
ValidationPassed ValidationStatus = "passed"
// ValidationFailed means validation completed and rejected the generated
// output. Engine.Run and Engine.RunPrepared return this status in a result,
// not as an error.
ValidationFailed ValidationStatus = "failed"
// ValidationSkipped means ValidationNone selected no content check.
ValidationSkipped ValidationStatus = "skipped"
)
// CacheControlType identifies provider cache behavior for prompt content.
// CacheControlType has a stable JSON string representation.
type CacheControlType string
const (
// CacheControlEphemeral requests provider-defined ephemeral caching.
CacheControlEphemeral CacheControlType = "ephemeral"
)
// StructuredOutputType identifies provider-level structured output modes.
// StructuredOutputType has a stable JSON string representation.
type StructuredOutputType string
const (
// StructuredOutputJSONSchema supplies JSON Schema response constraints.
StructuredOutputJSONSchema StructuredOutputType = "json_schema"
)
// RunRequest selects one prompt execution. It has no stable JSON
// representation.
//
// Prepare, PrepareExecution, and Run copy the request's maps, pointers, and
// nested JSON-compatible values before using them. The caller may mutate the
// request after any method returns. A successful PrepareExecution retains its
// own private execution snapshot for RunPrepared.
type RunRequest struct {
// PromptID is the required non-empty prompt identifier.
PromptID string
// PromptVersion optionally selects one version of PromptID. When empty, the
// prompt source must contain exactly one matching version.
PromptVersion string
// ProfileID selects an execution profile. When empty, the prompt's default
// profile is used; if both are empty, the error matches ErrProfileRequired
// and ErrInvalidRequest.
ProfileID string
// SessionID optionally supplies a direct per-run session identifier. A
// nonblank value is trimmed and overrides the prompt definition's
// session_id template. A blank value supplies no direct override. The
// maximum is 256 Unicode code points after trimming. A direct value is
// opaque consumer metadata, not a credential, and may be exposed in
// prepared values, results, collaborator requests, provider requests, and
// provider observability. Callers should use stable, non-sensitive
// identifiers. An overlong direct value makes Prepare, PrepareExecution, or
// Run return an error matching ErrInvalidRequest.
SessionID string
// APIKey is a request-scoped direct credential. It takes precedence over
// APIKeyEnv, is passed to the selected LLMClient, and is never included in
// prepared values, results, hashes, JSON, String, or GoString output. A
// successful PrepareExecution retains it only in the opaque handle until
// RunPrepared claims the handle or Discard invalidates it.
APIKey string `json:"-"`
// Inputs maps prompt input names to references. A nil or empty map is valid
// only when the selected prompt and its templates require no inputs.
Inputs map[string]ArtifactRef
// Vars supplies Go-template data for messages and the session ID. Nil and
// empty maps are equivalent.
Vars map[string]string
// Execution optionally overrides individual execution settings. Nil uses
// the selected profile over its backend, when any, and the framework
// baseline.
Execution *ExecutionTargetOverride
// Validation optionally replaces the prompt's complete output contract. It
// does not merge individual fields. Nil uses the prompt contract.
Validation *OutputContract
}
// PreparedRun contains prepared prompt execution state returned by
// [Engine.Prepare] or [PreparedExecution.Details]. It does not include resolved
// API key values, model output, validation results, or internal target presence
// metadata. PreparedRun has a stable JSON representation.
//
// All maps, slices, pointers, and schema values are caller-owned copies. JSON
// timestamps use RFC 3339 and zero timing values are omitted. Hash formats are
// opaque.
type PreparedRun struct {
// PromptID is the selected prompt identifier.
PromptID string `json:"prompt_id"`
// PromptVersion is the selected prompt version.
PromptVersion string `json:"prompt_version,omitempty"`
// PromptHash is an opaque equality value for the selected definition.
PromptHash string `json:"prompt_hash,omitempty"`
// SelectedProfileID is the explicit request profile or prompt default that
// supplied execution settings.
SelectedProfileID string `json:"selected_profile_id"`
// SelectedBackendID equals EffectiveModelParams.BackendID. It is empty for
// an endpoint-only profile.
SelectedBackendID string `json:"selected_backend_id,omitempty"`
// EffectiveModelParams contains settings resolved from the framework timeout
// baseline, selected backend, profile, and then request overrides. Unset
// optional provider controls remain zero rather than reporting a provider
// default. It excludes resolved API-key values.
EffectiveModelParams ExecutionTarget `json:"effective_model_params"`
// OutputContract is the complete effective output contract.
OutputContract OutputContract `json:"output_contract"`
// StructuredOutput is non-nil for JSON Schema validation and contains the
// provider-facing response constraint passed to an LLM client.
StructuredOutput *StructuredOutputSpec `json:"structured_output,omitempty"`
// InputHashes maps every supplied input name to its opaque artifact hash.
InputHashes map[string]string `json:"input_hashes,omitempty"`
// SessionID is the effective direct or rendered session identifier, if any.
SessionID string `json:"session_id,omitempty"`
// RenderedPromptHash is an opaque equality value for SessionID and Messages.
RenderedPromptHash string `json:"rendered_prompt_hash"`
// Messages are the rendered messages that Run or RunPrepared passes to the
// LLM client.
Messages []RenderedMessage `json:"messages"`
// StartTime is the UTC time at which preparation began.
StartTime time.Time `json:"start_time,omitempty"`
// EndTime is the UTC time at which preparation completed.
EndTime time.Time `json:"end_time,omitempty"`
// DurationMS is preparation elapsed time in integer milliseconds. JSON uses
// duration_ms and omits a zero value.
DurationMS int64 `json:"duration_ms,omitempty"`
}
// RunResult contains generated output, validation state, and run metadata.
// RunResult has a stable JSON representation and round-trips its Duration
// through the duration_ms JSON field.
//
// All maps, slices, and nested values are caller-owned copies. JSON timestamps
// use RFC 3339 and zero timing values are omitted. Run IDs and hash formats are
// opaque.
type RunResult struct {
// RunID is an opaque identifier for this invocation.
RunID string `json:"run_id"`
// Artifact contains the generated output and derived metadata.
Artifact Artifact `json:"artifact"`
// RawOutput is the exact generated content before artifact classification
// and validation.
RawOutput string `json:"raw_output"`
// Validation records the completed content check.
Validation ValidationResult `json:"validation"`
// PromptID is the selected prompt identifier.
PromptID string `json:"prompt_id"`
// PromptVersion is the selected prompt version.
PromptVersion string `json:"prompt_version,omitempty"`
// PromptHash is the same opaque definition equality value exposed by
// PreparedRun.
PromptHash string `json:"prompt_hash,omitempty"`
// SessionID is the effective direct or rendered session identifier, if any.
// JSON omits an empty value.
SessionID string `json:"session_id,omitempty"`
// RenderedPromptHash is the same opaque rendered-prompt equality value
// computed during preparation.
RenderedPromptHash string `json:"rendered_prompt_hash"`
// SelectedProfileID identifies the profile used for execution.
SelectedProfileID string `json:"selected_profile_id"`
// SelectedBackendID equals EffectiveModelParams.BackendID. It is empty for
// an endpoint-only profile.
SelectedBackendID string `json:"selected_backend_id,omitempty"`
// ModelName is the effective model name and equals
// EffectiveModelParams.Model.
ModelName string `json:"model_name"`
// Endpoint is the effective base endpoint and equals
// EffectiveModelParams.Endpoint.
Endpoint string `json:"endpoint"`
// EffectiveModelParams contains the settings supplied to the LLM client,
// excluding resolved API-key values.
EffectiveModelParams ExecutionTarget `json:"effective_model_params"`
// InputHashes are the opaque input equality values computed during
// preparation.
InputHashes map[string]string `json:"input_hashes,omitempty"`
// Usage is the token accounting reported by the LLM client.
Usage TokenUsage `json:"usage"`
// StartTime is the UTC time immediately before ordinary Run preparation or
// after RunPrepared claims its handle.
StartTime time.Time `json:"start_time,omitempty"`
// EndTime is the UTC time after generation and validation complete.
EndTime time.Time `json:"end_time,omitempty"`
// Duration covers preparation, generation, and validation for Run. For
// RunPrepared it covers only the execution attempt after claim and excludes
// preparation and consumer-held delay. JSON represents it as integer
// milliseconds in duration_ms and omits a zero value.
Duration time.Duration `json:"-"`
}
// ArtifactRef identifies prompt input content. It has no stable JSON
// representation. Prefer [File], [Inline], or [InlineWithURI] to construct one.
type ArtifactRef struct {
// Type must be ArtifactRefInline or ArtifactRefFile.
Type ArtifactRefType
// URI is the file path for ArtifactRefFile and optional provenance metadata
// for ArtifactRefInline.
URI string
// Body is the content for ArtifactRefInline and is ignored for
// ArtifactRefFile.
Body string
}
// Artifact represents loaded or generated content and has a stable JSON
// representation. Body uses encoding/json's base64 representation for []byte.
type Artifact struct {
// Name is artifact metadata. During input preparation the engine fills an
// empty reader-supplied name with the request input-map key.
Name string `json:"name"`
// ContentType is the media type reported by the reader or derived for
// generated output.
ContentType string `json:"content_type"`
// Body is the artifact content. Engine boundaries copy this slice.
Body []byte `json:"body"`
// URI is optional source or result provenance metadata.
URI string `json:"uri"`
// Size is content-size metadata in bytes.
Size int64 `json:"size"`
// Hash is an opaque content equality value when the producing reader
// supplies one. Its format and algorithm are not API contracts.
Hash string `json:"hash"`
}
// ArtifactReader resolves a prompt input reference into its content.
//
// Read may be called concurrently. It must honor ctx cancellation to make
// Prepare, PrepareExecution, and Run responsive to cancellation. The engine
// passes a copied ref and immediately copies the returned Artifact.Body; it
// does not retain either value. Readers supply artifact metadata, and the
// engine assigns an input-map name only when the returned artifact name is
// empty.
//
// An injected reader owns any application-specific path containment,
// authorization, content-size, and content-type policy. It must protect
// sensitive references and bodies in its logging and in any copies it retains.
// It may reuse or mutate the returned artifact and body after Read returns.
//
// Returning a non-nil error makes the engine return an error matching
// ErrArtifactLoad while preserving the reader error through errors.Is.
// Returning a nil artifact with a nil error also produces ErrArtifactLoad.
type ArtifactReader interface {
Read(context.Context, ArtifactRef) (*Artifact, error)
}
// ExecutionTarget represents effective model runtime settings and has a stable
// JSON representation. It never exposes a resolved API-key value.
type ExecutionTarget struct {
// BackendID is the effective routing identity selected by the profile. It
// remains unchanged when a profile or request overrides Endpoint and is
// empty for endpoint-only profiles. It is supplied to injected LLMClient
// implementations as part of the effective target.
BackendID string `json:"backend_id,omitempty"`
// Endpoint is the model-provider base URL.
Endpoint string `json:"endpoint"`
// Model is the provider model identifier.
Model string `json:"model"`
// Temperature is the resolved sampling temperature from 0 through 2. Zero
// leaves the field unspecified to compatible providers unless the
// corresponding ExecutionTargetPresence bit is true.
Temperature float64 `json:"temperature"`
// MaxTokens is the non-negative resolved output-token limit. Zero leaves
// the limit unspecified to compatible providers unless the corresponding
// ExecutionTargetPresence bit is true.
MaxTokens int `json:"max_tokens"`
// TopP is the resolved nucleus-sampling value from 0 through 1. Zero leaves
// the field unspecified to compatible providers unless the corresponding
// ExecutionTargetPresence bit is true.
TopP float64 `json:"top_p"`
// TimeoutSeconds is the non-negative per-generation deadline. Zero disables
// this deadline without disabling caller cancellation or the transport cap.
TimeoutSeconds int `json:"timeout_seconds"`
// ServiceTier is an optional provider-specific request tier.
ServiceTier string `json:"service_tier"`
// ReasoningEffort is the effective opaque provider-specific reasoning
// setting. An empty value instructs model clients to omit reasoning.
ReasoningEffort string `json:"reasoning_effort"`
// APIKeyEnv is an environment-variable name, not its credential value.
APIKeyEnv string `json:"api_key_env"`
// ExtraParams contains copied JSON-compatible provider parameters.
ExtraParams map[string]any `json:"extra_params"`
}
// ProfileInspection is the caller-owned result of [Engine.InspectProfile].
// It has no stable JSON representation.
//
// EffectiveModelParams contains a copied effective target. APIKeyRequired is
// separate from that target to preserve ExecutionTarget's general execution
// and stable JSON contracts.
type ProfileInspection struct {
// ProfileID is the trimmed, exact profile ID inspected by the engine.
ProfileID string
// EffectiveModelParams contains settings resolved from the framework timeout
// baseline, selected backend, and then profile, without a request override.
// Unset optional provider controls remain zero rather than reporting a
// provider default. APIKeyEnv is an environment-variable name, never its
// credential value.
EffectiveModelParams ExecutionTarget
// APIKeyRequired reports that a later execution must supply a direct API
// key or an explicit request environment override. It is mutually exclusive
// with a nonblank EffectiveModelParams.APIKeyEnv.
APIKeyRequired bool
}
// PromptInputDefinition describes one declared prompt input.
// It has no stable JSON representation.
type PromptInputDefinition struct {
// Name is the normalized prompt input name.
Name string
// Required is the prompt definition's declared required flag. When true,
// preparation fails if the input is omitted. A false value does not account
// for input references in message or session-ID templates.
Required bool
// ContentType is the declared input media-type metadata.
ContentType string
// Description is the declared human-readable input description.
Description string
}
// PromptInspection is the caller-owned result of [Engine.InspectPrompt].
// It has no stable JSON representation.
//
// Inputs contains copied declared input metadata in definition order.
// OutputContract is the normalized contract declared by the prompt definition,
// rather than a request-level effective override. PromptHash is opaque.
type PromptInspection struct {
// PromptID is the normalized ID of the selected prompt definition.
PromptID string
// PromptVersion is the normalized version of the selected prompt definition.
PromptVersion string
// PromptHash is the opaque equality value for the selected definition.
PromptHash string
// DefaultProfileID is declared metadata and is not resolved by inspection.
DefaultProfileID string
// Inputs contains caller-owned declared input metadata in definition order.
Inputs []PromptInputDefinition
// OutputContract is the normalized contract declared by the definition.
OutputContract OutputContract
}
// ExecutionTargetOverride represents per-request runtime setting overrides and
// has no stable JSON representation.
//
// Non-empty string fields replace profile and backend values. Non-nil pointer
// fields replace profile values and preserve explicit zero or empty values. A
// non-empty ExtraParams map replaces the complete profile or backend map
// rather than merging keys. Empty string fields, nil pointers, and a nil or
// empty ExtraParams map inherit lower-precedence values. An optional provider
// control that remains zero is unspecified; TimeoutSeconds retains its
// framework deadline when no higher-precedence value is present.
type ExecutionTargetOverride struct {
// Endpoint replaces the profile or backend endpoint when non-empty without
// changing the effective BackendID.
Endpoint string
// Model replaces the profile model when non-empty.
Model string
// Temperature, when non-nil, must point to a value from 0 through 2. A
// pointed-to zero is explicitly present; nil inherits a lower-precedence
// value and otherwise leaves the provider control unspecified.
Temperature *float64
// MaxTokens, when non-nil, must point to a non-negative value. A pointed-to
// zero is explicitly present; nil inherits a lower-precedence value and
// otherwise leaves the provider control unspecified.
MaxTokens *int
// TopP, when non-nil, must point to a value from 0 through 1. A pointed-to
// zero is explicitly present; nil inherits a lower-precedence value and
// otherwise leaves the provider control unspecified.
TopP *float64
// TimeoutSeconds, when non-nil, must point to a non-negative value. A
// pointed-to zero disables the per-generation deadline.
TimeoutSeconds *int
// ServiceTier replaces the profile value when non-blank.
ServiceTier string
// ReasoningEffort controls the per-run reasoning setting. Nil inherits the
// profile value. A pointer to a non-blank string trims and replaces the
// profile value. A pointer to an empty or whitespace-only string clears the
// inherited value and disables reasoning for this run. Non-blank values
// are opaque and are not validated against a fixed vocabulary.
ReasoningEffort *string
// APIKeyEnv replaces the profile or backend environment-variable name when
// non-blank. A direct RunRequest.APIKey still takes precedence over
// environment lookup.
APIKeyEnv string
// ExtraParams, when non-empty, replaces the complete profile or backend map.
// Values must be JSON-compatible: nil, booleans, finite numbers, strings,
// arrays or slices, and maps with non-empty string keys. Cycles are invalid.
ExtraParams map[string]any
}
// Profile is an in-memory execution profile for library consumers.
//
// It is equivalent to a loaded profile file after validation. Raw API keys do
// not belong in profiles; use APIKeyRequired to require callers to provide a
// RunRequest.APIKey or explicit request ExecutionTargetOverride.APIKeyEnv, or
// use profile YAML api_key_env with file and FS profile sources. Profile has no
// stable JSON representation.
//
// WithProfiles validates and copies Profile values during NewEngine. Zero
// Temperature, MaxTokens, and TopP values and blank ServiceTier and
// ReasoningEffort values leave those provider controls unspecified. A zero
// TimeoutSeconds retains the framework deadline, while an empty ExtraParams map
// inherits backend request defaults. Use ExecutionTargetOverride pointer fields
// to request an explicit numeric zero.
type Profile struct {
// ID is the required non-blank profile identifier. WithProfiles trims it.
ID string
// BackendID optionally selects an engine backend. WithProfiles trims it.
// Backend membership is checked when a request selects the profile; an
// unknown ID makes preparation fail with ErrProfileLoad.
BackendID string
// Endpoint is the model-provider base URL. It is required only when
// BackendID is blank and otherwise overrides the backend endpoint when
// non-blank.
Endpoint string
// Model is the required non-blank provider model identifier.
Model string
// Temperature is from 0 through 2. Zero leaves the provider control
// unspecified.
Temperature float64
// MaxTokens is non-negative. Zero leaves the provider control unspecified.
MaxTokens int
// TopP is from 0 through 1. Zero leaves the provider control unspecified
// rather than selecting an explicit zero.
TopP float64
// TimeoutSeconds is non-negative. Zero retains the framework deadline.
TimeoutSeconds int
// ServiceTier is optional; a blank value leaves it unspecified.
ServiceTier string
// ReasoningEffort is optional; a blank value leaves it unspecified.
ReasoningEffort string
// APIKeyRequired clears a backend's inherited API-key environment name and
// requires a non-blank RunRequest.APIKey unless the request explicitly
// supplies ExecutionTargetOverride.APIKeyEnv. It does not store a credential.
APIKeyRequired bool
// ExtraParams contains provider-specific JSON-compatible values. An empty
// map inherits backend request defaults, when any. WithProfiles validates
// and deeply copies it during NewEngine.
ExtraParams map[string]any
}
// OpenAICompatibleProfileConfig configures an OpenAI-compatible in-memory
// profile.
//
// It contains ordinary profile fields for OpenAI-compatible chat-completions
// endpoints. APIKeyRequired follows Profile.APIKeyRequired. Raw API keys do not
// belong in this config. OpenAICompatibleProfileConfig has no stable JSON
// representation and is not validated until its resulting Profile is supplied
// through WithProfiles to NewEngine.
type OpenAICompatibleProfileConfig struct {
// ID becomes Profile.ID.
ID string
// BackendID becomes Profile.BackendID.
BackendID string
// Endpoint becomes Profile.Endpoint.
Endpoint string
// Model becomes Profile.Model.
Model string
// APIKeyRequired becomes Profile.APIKeyRequired.
APIKeyRequired bool
// Temperature becomes Profile.Temperature.
Temperature float64
// MaxTokens becomes Profile.MaxTokens.
MaxTokens int
// TopP becomes Profile.TopP.
TopP float64
// TimeoutSeconds becomes Profile.TimeoutSeconds.
TimeoutSeconds int
// ServiceTier becomes Profile.ServiceTier.
ServiceTier string
// ReasoningEffort becomes Profile.ReasoningEffort.
ReasoningEffort string
// ExtraParams becomes a shallow-copied Profile.ExtraParams map. NewEngine
// performs validation and a deep copy when WithProfiles applies the result.
ExtraParams map[string]any
}
// ExecutionTargetPresence tracks which numeric runtime settings were explicit
// request overrides, including explicit zero values. It has a stable JSON
// representation and is supplied to injected LLM clients so they can preserve
// omission semantics.
type ExecutionTargetPresence struct {
// Temperature reports a non-nil ExecutionTargetOverride.Temperature.
Temperature bool `json:"temperature"`
// MaxTokens reports a non-nil ExecutionTargetOverride.MaxTokens.
MaxTokens bool `json:"max_tokens"`
// TopP reports a non-nil ExecutionTargetOverride.TopP.
TopP bool `json:"top_p"`
// TimeoutSeconds reports a non-nil ExecutionTargetOverride.TimeoutSeconds.
TimeoutSeconds bool `json:"timeout_seconds"`
}
// OutputContract defines output and validation requirements and has a stable
// JSON representation.
//
// A non-nil RunRequest.Validation replaces the complete prompt contract. It
// does not merge fields. The public Engine validates generated output once and
// does not install an output repairer.
type OutputContract struct {
// Format selects generated artifact metadata. An empty value in a non-nil
// request replacement defaults to FormatText.
Format OutputFormat `json:"format"`
// ValidationMode selects the content check. Use one of the declared
// ValidationMode constants.
ValidationMode ValidationMode `json:"validation_mode"`
// SchemaPath is required when ValidationMode is ValidationJSONSchema and is
// ignored by other modes.
SchemaPath string `json:"schema_path"`
// RepairAttempts is a non-negative requested repair limit. Zero requests no
// repairs. The public Engine performs no repairs even when this value is
// positive, so its runs report zero attempts used.
RepairAttempts int `json:"repair_attempts"`
}
// ValidationResult represents a completed output check and has a stable JSON
// representation. An operational inability to perform validation is returned
// as ErrValidation instead of a ValidationResult.
type ValidationResult struct {
// Status is Passed, Failed, or Skipped.
Status ValidationStatus `json:"status"`
// Mode is the effective validation mode.
Mode ValidationMode `json:"mode"`
// Errors contains validation diagnostics when Status is ValidationFailed.
Errors []string `json:"errors,omitempty"`
// SchemaPath is the effective schema path for JSON Schema validation.
SchemaPath string `json:"schema_path,omitempty"`
// RepairAttempts is the number of repairs actually attempted. It is always
// zero for the public Engine.
RepairAttempts int `json:"repair_attempts"`
// IsValid is true for ValidationPassed and ValidationSkipped and false for
// ValidationFailed.
IsValid bool `json:"is_valid"`
}
// TokenUsage contains model-client token accounting and has a stable JSON
// representation. Promptkit preserves values reported by the client and does
// not derive or reconcile them.
type TokenUsage struct {
// PromptTokens is the reported input-token count.
PromptTokens int `json:"prompt_tokens"`
// CompletionTokens is the reported generated-token count.
CompletionTokens int `json:"completion_tokens"`
// TotalTokens is the reported total-token count.
TotalTokens int `json:"total_tokens"`
// CachedTokens is the reported cached-input-token count.
CachedTokens int `json:"cached_tokens"`
// CacheWriteTokens is the reported cache-write-token count.
CacheWriteTokens int `json:"cache_write_tokens"`
}
// RenderedPrompt is the fully rendered prompt passed to an LLM client and has
// a stable JSON representation.
type RenderedPrompt struct {
// SessionID is the optional effective direct or rendered session
// identifier supplied to the model client.
SessionID string `json:"session_id,omitempty"`
// Messages contains rendered messages in definition order.
Messages []RenderedMessage `json:"messages"`
}
// RenderedMessage is a rendered chat message and has a stable JSON
// representation.
type RenderedMessage struct {
// Role is the definition-supplied chat role.
Role string `json:"role"`
// Content is the rendered message text.
Content string `json:"content"`
// CacheControl is optional provider cache metadata.
CacheControl *CacheControl `json:"cache_control,omitempty"`
}
// CacheControl describes provider cache metadata attached to prompt content
// and has a stable JSON representation.
type CacheControl struct {
// Type identifies the cache behavior.
Type CacheControlType `json:"type"`
// TTL is an optional provider cache lifetime.
TTL string `json:"ttl,omitempty"`
}
// StructuredOutputSpec describes provider-level structured output and has a
// stable JSON representation.
type StructuredOutputSpec struct {
// Type identifies the structured-output mechanism.
Type StructuredOutputType `json:"type"`
// JSONSchema contains constraints when Type is StructuredOutputJSONSchema.
JSONSchema *StructuredOutputJSONSpec `json:"json_schema,omitempty"`
}
// StructuredOutputJSONSpec contains provider-facing JSON Schema output
// constraints and has a stable JSON representation.
type StructuredOutputJSONSpec struct {
// Name is the provider-facing schema name.
Name string `json:"name"`
// Strict requests strict provider enforcement of Schema.
Strict bool `json:"strict"`
// Schema is a caller-owned copy of the loaded JSON Schema document.
Schema any `json:"schema"`
}
// LLMClient executes rendered prompts for [Engine.Run] and
// [Engine.RunPrepared].
//
// Generate is scheduled according to the resolved backend's capacity policy.
// It may still be called concurrently for different backend pools or unlimited
// backends. Cancellation while waiting for capacity can prevent Generate from
// being called. Once invoked, it must honor context cancellation to make Run
// and RunPrepared responsive to cancellation. The request and all nested maps,
// slices, and pointers are client-owned copies and may be mutated or retained
// without affecting engine state.
//
// Generate receives rendered messages and may receive a direct API key. A
// client must protect those values and any raw output in its logging, storage,
// and retained copies. It is responsible for the cancellation behavior of any
// work it starts and for synchronizing access to retained or shared data.
//
// A returned error makes Run or RunPrepared return ErrLLMGenerate while
// preserving the client error through errors.Is. A nil response with a nil
// error also produces ErrLLMGenerate. Promptkit copies the non-nil response
// before returning from either method.
type LLMClient interface {
Generate(context.Context, GenerateRequest) (*GenerateResponse, error)
}
// GenerateRequest is passed to an injected LLM client and has a stable JSON
// representation. Its String and GoString methods omit rendered content and
// direct credentials.
type GenerateRequest struct {
// Prompt contains the rendered session ID and messages.
Prompt RenderedPrompt `json:"prompt"`
// Target contains effective model settings without the direct API key.
Target ExecutionTarget `json:"target"`
// TargetPresence distinguishes inherited numeric zeros from explicit
// request overrides.
TargetPresence ExecutionTargetPresence `json:"target_presence"`
// StructuredOutput contains provider response constraints when requested.
StructuredOutput *StructuredOutputSpec `json:"structured_output,omitempty"`
// APIKey is the direct request-scoped credential, if any. It is excluded
// from JSON, String, and GoString output.
APIKey string `json:"-"`
}
// GenerateResponse is returned by an injected LLM client and has a stable JSON
// representation.
type GenerateResponse struct {
// Content is the generated output. It must be non-empty when using the
// built-in client; injected clients may return empty content for Promptkit
// validation to classify.
Content string `json:"content"`
// Usage is the client's token accounting.
Usage TokenUsage `json:"usage"`
}
// File returns a file-backed artifact reference whose URI is path.
//
// The default artifact reader opens path as a caller-selected operating-system
// path without restricting it to an application root or imposing a size limit.
// Applications accepting untrusted paths must validate them before calling
// Promptkit or use [WithArtifactReader] to enforce application policy.
func File(path string) ArtifactRef {
return ArtifactRef{Type: ArtifactRefFile, URI: path}
}
// Inline returns an inline artifact reference whose Body is body and whose URI
// is empty.
func Inline(body string) ArtifactRef {
return ArtifactRef{Type: ArtifactRefInline, Body: body}
}
// InlineWithURI returns an inline artifact reference with body content and uri
// provenance metadata.
func InlineWithURI(uri string, body string) ArtifactRef {
return ArtifactRef{Type: ArtifactRefInline, URI: uri, Body: body}
}