244 lines
8.9 KiB
Markdown
244 lines
8.9 KiB
Markdown
# Promptkit v0.2.0
|
|
|
|
This supplemental changelog and migration guide summarizes the consumer-facing
|
|
changes from `v0.1.0` to `v0.2.0`. The annotated `v0.2.0` tag is the
|
|
authoritative release record. Exact current contracts belong to the linked
|
|
GoDoc and durable documentation.
|
|
|
|
## Summary
|
|
|
|
`v0.2.0` adds three major capabilities:
|
|
|
|
- an engine-scoped registry for reusable OpenAI-compatible backend
|
|
definitions;
|
|
- bounded, backend-specific run admission and model-generation concurrency;
|
|
and
|
|
- direct per-run session IDs and tri-state reasoning-effort overrides.
|
|
|
|
Existing endpoint-only profiles remain supported. Consumers can adopt backend
|
|
registration and runtime overrides incrementally rather than rewriting all
|
|
profiles during the upgrade.
|
|
|
|
## Compatibility At A Glance
|
|
|
|
Promptkit remains pre-`v1`, and this minor release includes source-level and
|
|
behavioral changes that deserve review.
|
|
|
|
| Area | `v0.1.0` consumer impact |
|
|
| --- | --- |
|
|
| Endpoint-only profiles | Continue to work without migration. |
|
|
| Built-in profiles | Continue to use OpenRouter and `OPENROUTER_API_KEY`; they now select the built-in `openrouter` backend. |
|
|
| Custom backends | Registration is optional. Existing profiles may keep their endpoint and credential configuration. |
|
|
| Reasoning overrides | String assignments must migrate to the new pointer field. |
|
|
| `RunRequest.Metadata` | Removed; delete assignments to this field. |
|
|
| OpenRouter concurrency | Now limited to 16 active generations with waiting capacity of 1024 per engine. |
|
|
| Public JSON | `v0.2.0` formalizes supported JSON representations; consumers relying on `v0.1.0` encodings should review the notes below. |
|
|
| Unkeyed public struct literals | May require updates because fields were added. Keyed literals are recommended. |
|
|
|
|
## Upgrade
|
|
|
|
After the `v0.2.0` tag is published, update the module dependency with:
|
|
|
|
```sh
|
|
go get gitea.maximumdirect.net/eric/promptkit@v0.2.0
|
|
go mod tidy
|
|
```
|
|
|
|
Run the consuming project's ordinary tests and race-enabled tests after the
|
|
upgrade, especially if it calls one engine concurrently or persists Promptkit
|
|
JSON values.
|
|
|
|
## Backend Registry
|
|
|
|
Consumers may now register reusable OpenAI-compatible backend definitions with
|
|
`WithBackend`, then select them by ID from file-backed or in-memory profiles.
|
|
A backend can supply its endpoint, API-key environment-variable name,
|
|
request-wide extra parameters, and optional capacity policy.
|
|
|
|
Registrations are immutable and belong to one engine. Consumer registrations
|
|
can add new IDs but cannot replace Promptkit's reserved `openrouter` backend.
|
|
Profiles that select a backend may still override its endpoint without losing
|
|
the backend's routing or capacity identity.
|
|
|
|
An existing endpoint-only in-memory profile remains valid:
|
|
|
|
```go
|
|
promptkit.Profile{
|
|
ID: "local",
|
|
Endpoint: "http://localhost:8000/v1",
|
|
Model: "example-model",
|
|
}
|
|
```
|
|
|
|
Adopting the registry is optional and can be done when several profiles should
|
|
share connection or capacity settings:
|
|
|
|
```go
|
|
engine, err := promptkit.NewEngine(
|
|
promptkit.Config{PromptDir: "prompts"},
|
|
promptkit.WithBackend(promptkit.Backend{
|
|
ID: "local",
|
|
Endpoint: "http://localhost:8000/v1",
|
|
APIKeyEnv: "LOCAL_LLM_API_KEY",
|
|
}),
|
|
promptkit.WithProfiles(promptkit.Profile{
|
|
ID: "local-summary",
|
|
BackendID: "local",
|
|
Model: "example-model",
|
|
}),
|
|
)
|
|
```
|
|
|
|
See the
|
|
[local-endpoint consumer guide](../consumers/pkg-promptkit.md#configure-a-local-openai-compatible-endpoint)
|
|
for task-oriented usage. The
|
|
[`Backend` and `WithBackend` GoDoc](../../backends.go) owns exact registration,
|
|
validation, copying, defaulting, and uniqueness semantics. The
|
|
[framework format reference](../formats.md) owns the profile `backend` field
|
|
and execution precedence.
|
|
|
|
## Backend-Specific Concurrency
|
|
|
|
Each registered backend may now define:
|
|
|
|
- an active model-generation limit; and
|
|
- a bounded number of additional admitted `Run` calls.
|
|
|
|
Promptkit owns scheduling for both its built-in model client and an injected
|
|
`LLMClient`. `Run` remains synchronous: an admitted caller waits for its
|
|
ordinary result, while a call beyond the bounded admission capacity returns
|
|
`ErrCapacityExceeded`. Capacity is engine-local and keyed by backend ID.
|
|
Endpoint-only profiles and custom backends without a configured limit remain
|
|
unlimited.
|
|
|
|
The built-in OpenRouter backend now permits 16 active generations and 1024
|
|
additional admitted calls per engine. Applications that can exceed this bound
|
|
should handle capacity exhaustion separately from provider and request
|
|
failures:
|
|
|
|
```go
|
|
result, err := engine.Run(ctx, request)
|
|
if errors.Is(err, promptkit.ErrCapacityExceeded) {
|
|
// Apply application-specific overload or retry policy.
|
|
}
|
|
```
|
|
|
|
Promptkit does not prescribe retries or map this error to an HTTP status. See
|
|
the
|
|
[concurrency consumer guidance](../consumers/pkg-promptkit.md#limit-backend-concurrency)
|
|
and the [`Backend` GoDoc](../../backends.go) for the canonical configuration
|
|
contract. Runtime behavior and public error identities belong to the
|
|
[`Engine.Run` GoDoc](../../engine.go).
|
|
|
|
## Per-Run Session IDs
|
|
|
|
`RunRequest.SessionID` can now supply a consumer-managed correlation ID for one
|
|
`Prepare` or `Run` invocation. A nonblank direct value overrides the prompt's
|
|
session template and is exposed in prepared values, results, injected-client
|
|
requests, and provider observability. Session IDs should therefore be stable,
|
|
non-secret values.
|
|
|
|
```go
|
|
result, err := engine.Run(ctx, promptkit.RunRequest{
|
|
PromptID: "meeting.summary",
|
|
SessionID: "conversation-42",
|
|
})
|
|
```
|
|
|
|
The built-in OpenAI-compatible client sends a nonempty effective session as the
|
|
top-level `session_id` request-body field, not as an `x-session-id` header. See
|
|
the
|
|
[session and reasoning consumer guide](../consumers/pkg-promptkit.md#set-a-per-run-session-and-reasoning),
|
|
the [`RunRequest` GoDoc](../../types.go), and the
|
|
[OpenAI-compatible request contract](../integrations/openai-compatible-chat.md#request-body)
|
|
for exact normalization, length, exposure, and wire behavior.
|
|
|
|
## Per-Run Reasoning Effort
|
|
|
|
`ExecutionTargetOverride.ReasoningEffort` changed from `string` to `*string` so
|
|
one request can distinguish inheritance, replacement, and explicit clearing.
|
|
|
|
Update a `v0.1.0` override like this:
|
|
|
|
```go
|
|
// v0.1.0
|
|
Execution: &promptkit.ExecutionTargetOverride{
|
|
ReasoningEffort: "high",
|
|
}
|
|
```
|
|
|
|
to:
|
|
|
|
```go
|
|
// v0.2.0
|
|
reasoning := "high"
|
|
Execution: &promptkit.ExecutionTargetOverride{
|
|
ReasoningEffort: &reasoning,
|
|
}
|
|
```
|
|
|
|
The three states are:
|
|
|
|
- `nil` inherits the selected profile's value;
|
|
- a pointer to a nonblank string replaces it for that invocation; and
|
|
- a pointer to an empty or whitespace-only string clears it for that
|
|
invocation.
|
|
|
|
This allows consumers to consolidate profiles that differed only by reasoning
|
|
effort. The [`ExecutionTargetOverride` GoDoc](../../types.go) owns the exact
|
|
override contract.
|
|
|
|
## Other Migration Notes
|
|
|
|
### Remove `RunRequest.Metadata`
|
|
|
|
`RunRequest.Metadata` is no longer part of the public request. Remove any
|
|
assignment to that field. Use application-owned state keyed by `RunResult.RunID`
|
|
or a direct `SessionID` when correlation is needed; these identifiers have
|
|
different purposes, so choose according to the application's lifecycle.
|
|
|
|
### Review Persisted JSON
|
|
|
|
`v0.2.0` defines stable JSON representations for the public result, artifact,
|
|
execution, validation, and model-client values listed in the
|
|
[package documentation](../../doc.go). Consumers that treated `v0.1.0`
|
|
reflection-derived encodings as stable should update fixtures and stored-data
|
|
adapters.
|
|
|
|
In particular:
|
|
|
|
- `RunResult` encodes elapsed time as integer milliseconds in `duration_ms`
|
|
instead of encoding `time.Duration` under `duration`;
|
|
- result JSON can include the new `session_id` and `selected_backend_id`
|
|
fields;
|
|
- execution-target JSON can include `backend_id`; and
|
|
- artifact and target-presence fields now use their documented lower-case
|
|
names.
|
|
|
|
The `v0.2.0` `RunResult` decoder reads `duration_ms`; it does not translate a
|
|
persisted `v0.1.0` `duration` field. Transform old payloads before decoding
|
|
when preserving their elapsed duration matters.
|
|
|
|
### Prefer Keyed Struct Literals
|
|
|
|
New fields were added to several public structs. Replace positional composite
|
|
literals with keyed literals so future additive fields do not cause another
|
|
source migration.
|
|
|
|
## Migration Checklist
|
|
|
|
- Update the module dependency and run the consumer's tests.
|
|
- Change reasoning overrides from strings to pointers.
|
|
- Remove uses of `RunRequest.Metadata`.
|
|
- Review unkeyed Promptkit struct literals.
|
|
- Decide whether shared endpoints should move into registered backends.
|
|
- If using built-in OpenRouter profiles at high concurrency, handle
|
|
`ErrCapacityExceeded` and review the new engine-local bound.
|
|
- Review stored JSON, fixtures, and downstream decoders.
|
|
- Optionally replace profile-specific session or reasoning variants with
|
|
per-run overrides.
|
|
|
|
For complete consumer workflows, use the
|
|
[package consumer guide](../consumers/pkg-promptkit.md) and maintained
|
|
[offline execution example](../../examples/go-library/run/main.go).
|