Publish the Promptkit engine facade

This commit is contained in:
2026-07-28 04:43:19 +00:00
parent 18b12a25c1
commit e4899fb54d
36 changed files with 4571 additions and 58 deletions

View File

@@ -0,0 +1,165 @@
# Package `promptkit`
Import path:
```go
import "gitea.maximumdirect.net/eric/promptkit"
```
Package `promptkit` is the supported Go contract for in-process prompt
preparation and execution. The declarations and their GoDoc in the
[root package](../../doc.go) own the exact API; this guide explains how the
pieces are used together.
## Engine Construction And Sources
Construct an engine with [`NewEngine`, `Config`, and
`Option`](../../engine.go). `PromptDir` is required unless a prompt source
option is supplied. `ProfileDir` optionally overlays built-in profiles, and an
empty `SchemaDir` uses the current directory. `Timeout` is the transport-wide
safety cap for the built-in OpenAI-compatible client. An optional `HTTPClient`
is cloned; its positive timeout takes precedence.
Nil options are ignored. Invalid construction, including a nil injected client
or artifact reader, returns an error matching `ErrInvalidConfig`.
The [source options](../../engine.go) replace their matching directory source:
- `WithPromptFS` and `WithPromptFile` select prompt definitions;
- `WithProfileFS` and `WithProfileFile` overlay built-in profiles;
- `WithProfiles` adds in-memory profiles ahead of file and built-in profiles;
- `WithSchemaFS` and `WithSchemaFile` select JSON Schema documents;
- `WithLLMClient` replaces the built-in model client; and
- `WithArtifactReader` replaces the default reader for every input.
Prompt-content and schema paths from an `fs.FS` stay within the configured
root. Single-file prompt and profile sources select definitions by YAML ID.
Relative prompt content resolves from its prompt file, while a single schema
is addressed by its base name.
Per-generation timeout values from profiles or requests are independent of
the transport cap and caller context. An explicit request value of zero
disables only the per-generation deadline. The
[outbound integration contract](../integrations/openai-compatible-chat.md#timeout-and-cancellation)
defines the complete timeout layering.
## Preparation And Execution
[`Engine.Prepare` and `Engine.Run`](../../engine.go) accept the public
[`RunRequest`](../../types.go). `Prepare` resolves the prompt, profile, input
artifacts, validation contract, and rendered messages without calling an LLM.
`Run` performs the same preparation, calls the configured client, and validates
the generated content.
```go
engine, err := promptkit.NewEngine(promptkit.Config{
PromptDir: "./prompts",
ProfileDir: "./profiles",
})
if err != nil {
return err
}
prepared, err := engine.Prepare(ctx, promptkit.RunRequest{
PromptID: "meeting.summary",
Inputs: map[string]promptkit.ArtifactRef{
"transcript": promptkit.File("./transcript.md"),
},
})
if err != nil {
return err
}
_ = prepared.Messages
```
[`PreparedRun` and `RunResult`](../../types.go) expose copied public values.
Preparation returns effective settings, hashes, rendered messages, selected
profile, structured-output information, and timing without resolved secrets or
model output. Execution adds the generated artifact and raw output, validation
state, model metadata, usage, run ID, and duration.
A generated-content validation failure returns a result with
`Validation.Status == ValidationFailed`. An inability to perform validation
returns an error matching `ErrValidation`.
## Requests, Inputs, And Overrides
The [request and value declarations](../../types.go) own the available fields,
serialized constants, and result shapes. Use `File`, `Inline`, or
`InlineWithURI` to construct artifact references. Required declared inputs and
every input referenced by a template must be supplied.
`ExecutionTargetOverride` uses pointers for numeric settings so an explicit
zero remains distinct from no override. `ExtraParams` accepts JSON-compatible
strings, booleans, finite numbers, string-keyed objects, arrays or slices, and
nil. Unsupported values, non-string map keys, non-finite numbers, and cycles
match `ErrInvalidConfig` in profiles or `ErrInvalidRequest` in request
overrides.
Returned requests, profiles, prepared values, results, artifacts, maps, and
slices are isolated from internal engine state. Consumers and injected
extensions should not retain or mutate values owned by another caller.
## Profiles And Credentials
[`OpenAICompatibleProfile`](../../profiles.go) constructs an ordinary
in-memory profile for an OpenAI-compatible chat-completions endpoint.
`WithProfiles` rejects duplicate IDs in one call and gives in-memory profiles
precedence over explicit file sources and built-ins.
Raw API keys do not belong in profiles. File-backed profiles may name an
environment variable, while an in-memory profile can require a request key.
A direct `RunRequest.APIKey` is request-scoped and takes precedence over an
environment lookup for the built-in client.
API keys are excluded from JSON, prepared values, and results. The public
`String` and `GoString` methods report only whether a direct key is present.
Avoid reflection-based dumps of request structs, which can bypass that
redaction.
## Extension Interfaces
The [`LLMClient`, `GenerateRequest`, and
`GenerateResponse`](../../types.go) boundary lets a consumer replace model
generation. Injected clients receive copied rendered messages, effective
settings, explicit numeric-setting presence, structured-output constraints,
and the request-scoped key. They return generated content and token usage.
The [`ArtifactReader`](../../types.go) boundary replaces the default inline and
file reader for every input. Readers provide artifact content and metadata; the
engine fills an empty artifact name from the input-map key. A reader error
matches `ErrArtifactLoad` while preserving the original identity for
`errors.Is`. A nil artifact with a nil error is also an artifact-load failure.
Extensions should honor context cancellation and avoid logging raw prompts,
artifacts, or credentials.
## Errors
The [public error declarations](../../engine.go) and
[mapping](../../errors.go) preserve these sentinel checks through `errors.Is`:
- `ErrInvalidConfig`
- `ErrInvalidRequest`
- `ErrPromptNotFound`
- `ErrProfileNotFound`
- `ErrProfileRequired`
- `ErrPromptLoad`
- `ErrProfileLoad`
- `ErrAPIKeyEnvMissing`
- `ErrArtifactLoad`
- `ErrPromptRender`
- `ErrLLMGenerate`
- `ErrValidation`
`ErrProfileRequired` and `ErrAPIKeyEnvMissing` also match
`ErrInvalidRequest`, allowing either broad request handling or a specific
condition. Wrapped collaborator errors retain their identity where the public
contract promises it.
## Consumer Boundary
Promptkit is an importable library. It does not own a command, inbound HTTP
API, process configuration, or deployment policy. Scriptorium is one
downstream application that maps this root package contract into those
application concerns.

View File

@@ -5,8 +5,8 @@
This document defines the outbound HTTP behavior implemented by Promptkit's
internal OpenAI-compatible model client. The
[internal model-client document](../internal/llm.md) owns implementation flow,
errors, and test ownership. The client is not yet available through a usable
public Promptkit engine.
errors, and test ownership. The root Promptkit engine uses this client by
default unless a consumer injects another implementation.
## Endpoint And Method

View File

@@ -8,8 +8,8 @@ and the
[OpenAI-compatible chat integration](../integrations/openai-compatible-chat.md)
owns the observable outbound HTTP contract.
The client is implemented only under `internal/llm`. The root package does not
yet assemble it into a usable public engine.
The concrete client remains under `internal/llm`. The root engine assembles it
as the default implementation behind Promptkit's public client boundary.
## Components And Flow
@@ -40,8 +40,8 @@ non-success provider statuses, and malformed successful responses. Provider
response bodies are not included in non-success errors.
Caller cancellation and deadline failures during the outbound request are
reported as request execution failures. The future runner can classify these
identities without depending on HTTP status mapping.
reported as request execution failures. The runner classifies these identities
without depending on HTTP status mapping.
## Test Ownership

View File

@@ -11,7 +11,7 @@ contributor workflow and validation.
| Component | Implemented responsibility | References |
| --- | --- | --- |
| Root `promptkit` package | Establishes the public package boundary for the Go module. It does not yet provide migrated framework behavior or exported APIs. | [Package declaration](../../doc.go) |
| Root `promptkit` package | Provides the supported engine facade, source and injection options, public request and result values, built-in profile construction, extension interfaces, value conversion, redacted formatting, and public error mapping. | [Package GoDoc](../../doc.go), [engine assembly](../../engine.go) |
| `internal/domain` | Defines internal framework values for requests, artifacts, prompt definitions, profiles, execution targets, rendering, generation, and validation. | [Domain declarations](../../internal/domain/domain.go) |
| `internal/defaults` | Defines application-neutral framework constants and constructs the default execution target. It contains no CLI, server, or inbound HTTP limits. | [Framework defaults](../../internal/defaults/defaults.go) |
| `internal/filecatalog` | Provides deterministic YAML discovery and path helpers for operating-system filesystems and `fs.FS` sources. | [File catalog](../../internal/filecatalog/catalog.go) |
@@ -24,9 +24,8 @@ contributor workflow and validation.
| `internal/llm` | Defines the internal generation boundary and implements outbound OpenAI-compatible chat requests, response decoding, authentication, and deadline handling. | [Internal model client](llm.md) |
| `internal/usecase` | Coordinates preparation and execution across internal sources, rendering, artifact loading, generation, validation, and optional repair. | [Internal runner](runner.md) |
These packages provide the internal model, source, rendering, validation, and
model-client workflow. A usable public engine is not implemented in Promptkit
yet.
The root package assembles these internal components without exposing their
representations. Consumers depend only on the root facade.
## Maintenance

View File

@@ -9,8 +9,8 @@ artifact, rendering, and validation behavior, while the
[model-client document](llm.md) owns generation behavior and failure
categories.
The runner remains under `internal/usecase`. The root package does not yet
assemble it into a usable public engine.
The runner remains under `internal/usecase` and is assembled by the root
Promptkit engine. Its concrete type is not part of the public API.
## Collaborators
@@ -65,8 +65,8 @@ input hashes, token usage, a generated run identifier, and UTC timing.
Package errors distinguish invalid requests, required profile selection,
credential failures, and prompt, profile, artifact, rendering, generation, and
validation failures. Wrapping preserves the package identities needed by the
future facade and retains collaborator identities where they are part of the
validation failures. Wrapping preserves the package identities mapped by the
public facade and retains collaborator identities where they are part of the
internal contract. Context cancellation propagates through the invoked
collaborator and is classified by the owning operation.

View File

@@ -6,7 +6,7 @@ This document describes Promptkit's implemented internal source, artifact,
rendering, and output-validation behavior. The
[architecture policy](../policy/architecture.md) owns the library boundary and
dependency rules. None of these internal packages is a supported consumer API,
and the root package does not yet assemble them into a usable engine.
and the root engine assembles them behind its public source options and values.
## Prompt Definitions

View File

@@ -13,8 +13,8 @@ Promptkit is an importable Go library. It does not provide a runnable command,
an HTTP service, or another application process.
The module root contains package `promptkit`, which is the public facade. It
declares the module's public package boundary but does not yet provide a usable
exported framework API.
provides the supported engine, configuration and source options, requests,
results, public values, extension interfaces, profiles, and error sentinels.
The implemented internal components consist of:
@@ -40,17 +40,19 @@ The implemented internal components consist of:
- `internal/usecase`, which coordinates preparation and execution across the
internal framework components.
The defaults and renderer depend on the domain model. Prompt-definition and
profile repositories use the domain model, file catalog, and YAML decoder. The
built-in profile repository supplies an embedded `fs.FS` to the profile
package. Artifact reading uses the domain model and application-neutral
defaults. Validation uses the domain model, file catalog, and JSON Schema
implementation. The model client uses the domain model, application-neutral
defaults, and an injected or standard-library HTTP client. The use-case runner
depends on the narrow interfaces owned by each internal component. The public
engine has not yet been extracted.
The root facade assembles the internal repositories, renderer, validator,
outbound client, and use-case runner while translating public values and
errors at the library boundary. The defaults and renderer depend on the domain
model. Prompt-definition and profile repositories use the domain model, file
catalog, and YAML decoder. The built-in profile repository supplies an
embedded `fs.FS` to the profile package. Artifact reading uses the domain model
and application-neutral defaults. Validation uses the domain model, file
catalog, and JSON Schema implementation. The model client uses the domain
model, application-neutral defaults, and an injected or standard-library HTTP
client. The use-case runner depends on the narrow interfaces owned by each
internal component.
Future framework extraction must follow this dependency direction:
The current implementation follows this dependency direction:
```text
downstream consumers, including Scriptorium
@@ -65,16 +67,13 @@ downstream consumers, including Scriptorium
narrow injected abstractions
```
The facade may coordinate internal components once the public engine is
extracted. Internal components must depend on narrow abstractions for behavior
supplied from outside the library; they must not depend on consumers or on
Scriptorium. This diagram is the target dependency direction for later
extraction and does not assert that the public facade already assembles the
implemented foundation.
The facade coordinates internal components and adapts the supported public
extension interfaces to narrow internal abstractions. Internal components must
not depend on consumers or on Scriptorium.
## Repository And Consumer Boundary
Scriptorium is a downstream application that will consume Promptkit through
Scriptorium is a downstream application that consumes Promptkit through
the supported public facade. It is not a Promptkit package and must not become
an internal dependency.
@@ -147,7 +146,6 @@ state.
## Current-State Maintenance
This policy distinguishes present implementation from constraints on future
framework extraction. Do not list planned packages as implemented components.
When extraction introduces a package, update the internal inventory and the
owning contract or subsystem document in the same change.
Do not list planned packages as implemented components. When implementation
introduces a package, update the internal inventory and the owning contract or
subsystem document in the same change.