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. Excessively deep or large // JSON-shaped values are rejected for safety. 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 // AppendedMessages are already-rendered messages appended in caller order // after every prompt definition message. Promptkit neither templates nor // 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 // [RoleAssistant]. Any CacheControl is normalized as documented on that // type. // // 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 // TransientRetries overrides the engine's built-in HTTP retry budget for // this execution. Nil inherits the engine value; zero disables retries. // Negative values are invalid for Prepare, PrepareExecution, and Run. // Injected LLMClient implementations remain single-dispatch. TransientRetries *int // Observer receives metadata about an execution invocation synchronously. It is // excluded from JSON and is not invoked by Prepare or PrepareExecution. // Successful PrepareExecution retains the function for its RunPrepared call; // Discard or a completed claim clears that reference. The closure itself is // not copied, so callers must synchronize its shared state. Observer ExecutionObserver `json:"-"` } // 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 complete effective messages that Run or RunPrepared passes // to the LLM client: definition messages in rendered order followed by any // RunRequest.AppendedMessages in caller order. 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, where an empty value is valid, // 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 normalized absolute HTTP or HTTPS model-provider base URL. // It has a host and no user information, query, or fragment. 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 the resolved name of an optional environment lookup source, // not its credential value. The built-in client omits Authorization when no // usable direct or environment credential is available; injected clients may // resolve this metadata differently. 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. Preparation trims it and requires an // absolute HTTP or HTTPS URL with a host and no user information, query, or // fragment. 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 optional environment lookup // source when non-blank. A direct RunRequest.APIKey still takes precedence. // The built-in client omits Authorization when neither source has a usable // value; injected clients may resolve this metadata differently. 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 and // excessively deep or large values are invalid. ExtraParams map[string]any } // ExecutionTargetPresence reports which effective numeric settings should be // sent even when zero. It has a stable JSON representation and lets injected // clients preserve omission semantics. type ExecutionTargetPresence struct { // Temperature keeps a zero temperature explicit. Temperature bool `json:"temperature"` // MaxTokens keeps a zero token maximum explicit. MaxTokens bool `json:"max_tokens"` // TopP keeps a zero nucleus value explicit. TopP bool `json:"top_p"` // TimeoutSeconds keeps a zero timeout explicit. 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 performs bounded correction after a // failed eligible validation when RepairAttempts is positive. 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 an additional generation-call budget from zero through // three. Zero is single-pass. A positive value is valid only with basic, // json, or json_schema validation. 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 corrective generation calls actually // started for this result. 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 the effective messages in provider order: definition // messages in rendered order followed by any RunRequest.AppendedMessages. Messages []RenderedMessage `json:"messages"` } // RenderedMessage is a prepared, provider-bound text chat message and has a // stable JSON representation. At a request boundary its role is trimmed and // lowercased, then must be one of [RoleDeveloper], [RoleSystem], [RoleUser], // or [RoleAssistant]. type RenderedMessage struct { // Role is the provider-bound chat role. Role string `json:"role"` // 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"` // 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. 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 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. // // An arbitrary returned error makes Run or RunPrepared return ErrLLMGenerate // while preserving the client error through errors.Is rather than translating // it. A nil response with a nil error also produces ErrLLMGenerate and // ErrMalformedResponse. Promptkit copies the non-nil response before returning // from either method. When UsagePresence is nil, nonzero usage counts are // treated as known and zero counts as unknown for observation only; the legacy // interface cannot distinguish omitted zero from measured zero. An explicit // UsagePresence can report known zero counts. Result usage sums the supplied // Usage values independently of presence. 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 omitted or suppressed controls from explicit // numeric values, including zero. 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 may be explicitly empty; Promptkit // applies the effective output contract to classify it. Content string `json:"content"` // Usage is the client's token accounting. Usage TokenUsage `json:"usage"` // UsagePresence states which usage fields were reported, including zeros. // Nil uses the legacy observation fallback described by LLMClient. UsagePresence *TokenUsagePresence `json:"usage_presence,omitempty"` } // TokenUsagePresence identifies provider-reported token counts for observation. // It does not change TokenUsage values or successful-result accounting. type TokenUsagePresence struct { PromptTokens bool `json:"prompt_tokens"` CompletionTokens bool `json:"completion_tokens"` TotalTokens bool `json:"total_tokens"` CachedTokens bool `json:"cached_tokens"` CacheWriteTokens bool `json:"cache_write_tokens"` } // File returns a file-backed artifact reference whose URI is path. // // The default artifact reader accepts path only when it resolves to a regular // operating-system file, checking that condition before and after opening it. // It reads synchronously in bounded chunks and checks context cancellation // before opening, before and after each read, and before returning the // artifact; it cannot interrupt a filesystem operation already in progress. // It does not restrict path to an application root or impose 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. An empty body is a valid, explicitly supplied input. func Inline(body string) ArtifactRef { return ArtifactRef{Type: ArtifactRefInline, Body: body} } // InlineWithURI returns an inline artifact reference with body content and uri // provenance metadata. An empty body is a valid, explicitly supplied input. func InlineWithURI(uri string, body string) ArtifactRef { return ArtifactRef{Type: ArtifactRefInline, URI: uri, Body: body} }