Files
scriptorium/docs/consumers/pkg-scriptorium.md

8.2 KiB

Package scriptorium

Import path:

import "gitea.maximumdirect.net/eric/scriptorium"

This is the canonical public Go contract for in-process prompt preparation and execution. Prompt, profile, and schema file formats are defined in the configuration reference.

Engine Construction

NewEngine(Config, ...Option) constructs an engine. Config has these fields:

Field Meaning
PromptDir Prompt-definition directory, required unless a prompt source option is supplied.
ProfileDir Optional custom profile directory over built-ins.
SchemaDir Schema directory; empty uses ..
Timeout Transport-wide safety cap for the built-in OpenAI-compatible client when HTTPClient is absent or has a non-positive timeout. A non-positive value uses the internal ten-minute default.
HTTPClient Optional HTTP client for that built-in client. It is cloned; a positive Timeout on it is the transport cap and takes precedence over Config.Timeout. A non-positive client timeout is treated as unset.

Nil options are ignored. Invalid construction, including WithLLMClient(nil) and WithArtifactReader(nil), returns an error matching ErrInvalidConfig.

Profile and request timeout_seconds values select a per-generation-call deadline independently of the transport cap. An explicit request override of zero disables that generation deadline only. The complete interaction with the caller context is defined in the OpenAI-compatible integration contract.

Source options replace their matching directory source:

  • prompts: WithPromptFS(fsys, root), WithPromptFile(path);
  • profiles: WithProfileFS(fsys, root), WithProfileFile(path), and WithProfiles(profiles...);
  • schemas: WithSchemaFS(fsys, root), WithSchemaFile(path); and
  • LLM client: WithLLMClient(client); and
  • artifact reader: WithArtifactReader(reader).

fs.FS prompt-content and schema paths stay inside their configured roots. Single-file prompt and profile sources are selected by their YAML id, not their file names. WithPromptFile resolves relative content_file paths from the prompt file's directory. WithSchemaFile exposes its schema by the schema file's base name. In-memory profiles take precedence over an explicit or directory-backed profile source, which in turn takes precedence over built-ins. File and filesystem sources use the format and credential rules in the configuration reference.

Prepare And Run

Prepare(ctx, request) resolves the prompt, profile, input artifacts, validation contract, and rendered messages without calling an LLM. Run(ctx, request) performs that preparation, calls the configured client, and validates generated content.

engine, err := scriptorium.NewEngine(scriptorium.Config{
	PromptDir:  "./examples/prompts",
	ProfileDir: "./examples/profiles",
})
if err != nil {
	return err
}

prepared, err := engine.Prepare(ctx, scriptorium.RunRequest{
	PromptID: "generic.markdown_summary",
	Inputs: map[string]scriptorium.ArtifactRef{
		"transcript": scriptorium.File("./examples/fixtures/transcript.md"),
	},
})
if err != nil {
	return err
}
_ = prepared.Messages

The maintained package example is examples/go-library/prepare.

PreparedRun exposes prompt, selected-profile, effective-model, output contract, structured-output, input-hash, rendered-message, and timing information. It does not include a resolved API key, model output, validation result, or target-presence metadata.

RunResult adds run ID, artifact, raw output, validation, model metadata, usage, and duration. Generated-content validation failures return a result with Validation.Status == ValidationFailed; schema or validator runtime failures return an error matching ErrValidation.

Public Values

ArtifactRef has Type, URI, and Body; Artifact has Name, ContentType, Body, URI, Size, and Hash. ExecutionTarget exposes the effective endpoint, model, numeric settings, credential-environment name, service tier, reasoning effort, and extra parameters. ValidationResult contains status, mode, errors, schema path, repair attempts, and validity.

The exported constants define these serialized values:

  • artifact types: inline and file;
  • output formats: text, markdown, and json;
  • validation modes: none, basic, json, and json_schema; and
  • validation statuses: passed, failed, and skipped.

TokenUsage reports prompt, completion, total, cached, and cache-write token counts. RenderedPrompt, RenderedMessage, CacheControl, and StructuredOutputSpec are the public shapes used by injected LLM clients.

ArtifactReader implements Read(context.Context, ArtifactRef) (*Artifact, error). Supplying it through WithArtifactReader replaces, rather than extends, the engine's default inline and file reader for every input. Omitting the option retains that default; WithArtifactReader(nil) makes engine construction fail with ErrInvalidConfig.

Reader failures are surfaced as errors matching ErrArtifactLoad while preserving the reader's original error identity for errors.Is. A (nil, nil) reader response is also an artifact-load failure. Readers are responsible for artifact metadata, although the engine assigns the input-map name when the returned name is empty; readers should not retain or mutate caller values.

Requests, Inputs, And Overrides

RunRequest fields are PromptID, PromptVersion, ProfileID, APIKey, Inputs, Vars, Execution, Validation, and Metadata.

Input helpers are:

  • File(path) for a file-backed artifact;
  • Inline(body) for inline content; and
  • InlineWithURI(uri, body) for inline content with URI metadata.

Required declared inputs must be supplied. Template rendering must also resolve every input name the prompt actually references. Extra entries in Inputs are not rejected solely because they are undeclared.

ExecutionTargetOverride supplies endpoint, model, credential-environment, service-tier, reasoning-effort, and extra-parameter overrides. Its numeric fields (Temperature, MaxTokens, TopP, and TimeoutSeconds) are pointers so explicit zero values are preserved. OutputContract supplies Format, ValidationMode, SchemaPath, and RepairAttempts.

ExtraParams accepts JSON-compatible values: strings, booleans, finite numbers, objects with string keys, arrays or slices, and nil. Unsupported values, non-string map keys, non-finite floats, and cycles return ErrInvalidConfig for profiles or ErrInvalidRequest for request overrides.

Profiles And Credentials

OpenAICompatibleProfile(OpenAICompatibleProfileConfig) creates an in-memory Profile. Its public fields are ID, Endpoint, Model, Temperature, MaxTokens, TopP, TimeoutSeconds, ServiceTier, ReasoningEffort, APIKeyRequired, and ExtraParams. WithProfiles rejects duplicate IDs in one call.

A direct RunRequest.APIKey is request-scoped and takes precedence over api_key_env for the built-in client. It is excluded from JSON output and from PreparedRun and RunResult. The package's String and GoString methods report only whether a direct key is set. Do not use reflection-based dumps of request structs, which can bypass that redaction.

Injected LLM Clients

LLMClient implements:

Generate(context.Context, GenerateRequest) (*GenerateResponse, error)

Injected clients receive the rendered prompt, effective execution target, numeric target-presence metadata, optional structured-output specification, and direct request API key. GenerateResponse returns content and TokenUsage. Custom clients should avoid logging raw prompts or credentials.

Errors

Public methods preserve these sentinel checks through errors.Is:

  • ErrInvalidConfig
  • ErrInvalidRequest
  • ErrPromptNotFound
  • ErrProfileNotFound
  • ErrProfileRequired
  • ErrPromptLoad
  • ErrProfileLoad
  • ErrAPIKeyEnvMissing
  • ErrArtifactLoad
  • ErrPromptRender
  • ErrLLMGenerate
  • ErrValidation

ErrProfileRequired and ErrAPIKeyEnvMissing each also match ErrInvalidRequest, so callers can select either the broad request category or the specific condition.

For the HTTP interface, see the HTTP API reference.