Remove bundled catalog integration
This commit is contained in:
@@ -5,10 +5,10 @@ import (
|
|||||||
"gitea.maximumdirect.net/eric/promptkit/internal/backend"
|
"gitea.maximumdirect.net/eric/promptkit/internal/backend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackendOpenRouter identifies the maintained OpenRouter backend.
|
// BackendOpenRouter is the conventional ID for an OpenRouter backend.
|
||||||
const BackendOpenRouter = backend.OpenRouterID
|
const BackendOpenRouter = backend.OpenRouterID
|
||||||
|
|
||||||
// BackendRakestrawHome identifies the maintained Rakestrawhome backend.
|
// BackendRakestrawHome is the conventional ID for a Rakestrawhome backend.
|
||||||
const BackendRakestrawHome = backend.RakestrawHomeID
|
const BackendRakestrawHome = backend.RakestrawHomeID
|
||||||
|
|
||||||
// BackendLocal is a conventional ID for a caller-configured local backend.
|
// BackendLocal is a conventional ID for a caller-configured local backend.
|
||||||
|
|||||||
@@ -107,6 +107,36 @@ func TestPublicConstructionWithLocalBackendAndProgrammaticProfile(t *testing.T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFormerCatalogBackendIDsWorkWhenConfigured(t *testing.T) {
|
||||||
|
openRouterID, rakestrawhomeID := promptkit.BackendOpenRouter, promptkit.BackendRakestrawHome
|
||||||
|
openRouterEndpoint, rakestrawhomeEndpoint := "https://openrouter.example/v1", "https://inference.example/v1"
|
||||||
|
model := "configured-model"
|
||||||
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
||||||
|
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{
|
||||||
|
{Source: promptkit.BackendSource("application backends", map[string]promptkit.BackendConfig{
|
||||||
|
openRouterID: {Endpoint: &openRouterEndpoint},
|
||||||
|
rakestrawhomeID: {Endpoint: &rakestrawhomeEndpoint},
|
||||||
|
})},
|
||||||
|
{Source: promptkit.ProfileSource("application profiles", map[string]promptkit.ProfileConfig{
|
||||||
|
"openrouter-profile": {Backend: &openRouterID, Model: &model},
|
||||||
|
"rakestrawhome-profile": {Backend: &rakestrawhomeID, Model: &model},
|
||||||
|
})},
|
||||||
|
}}},
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("construct engine with explicitly configured provider IDs: %v", err)
|
||||||
|
}
|
||||||
|
for profileID, backendID := range map[string]string{
|
||||||
|
"openrouter-profile": openRouterID,
|
||||||
|
"rakestrawhome-profile": rakestrawhomeID,
|
||||||
|
} {
|
||||||
|
inspection, err := engine.InspectProfile(context.Background(), profileID)
|
||||||
|
if err != nil || inspection.EffectiveModelParams.BackendID != backendID {
|
||||||
|
t.Fatalf("inspect %q = (%+v, %v), want backend %q", profileID, inspection, err, backendID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPublicConstructionCombinesEmbeddedOperatorAndProgrammaticInputs(t *testing.T) {
|
func TestPublicConstructionCombinesEmbeddedOperatorAndProgrammaticInputs(t *testing.T) {
|
||||||
embedded, err := promptkit.FilesystemInputs("embedded defaults", fstest.MapFS{
|
embedded, err := promptkit.FilesystemInputs("embedded defaults", fstest.MapFS{
|
||||||
"config/default.yaml": &fstest.MapFile{Data: []byte(`
|
"config/default.yaml": &fstest.MapFile{Data: []byte(`
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ input := configkit.Input{Source: document}
|
|||||||
```
|
```
|
||||||
|
|
||||||
`ProfileSource` and `BackendSource` are smaller typed conveniences when null
|
`ProfileSource` and `BackendSource` are smaller typed conveniences when null
|
||||||
is not needed. A caller underlay can overlay catalog backend fields just as it
|
is not needed. Backend and profile definitions are supplied by the caller;
|
||||||
can overlay profiles; there is no registration-only backend namespace.
|
there is no registration-only backend namespace.
|
||||||
|
|
||||||
When configuration or message files change, build and validate a new engine,
|
When configuration or message files change, build and validate a new engine,
|
||||||
then switch the application to that engine for subsequent work. Existing
|
then switch the application to that engine for subsequent work. Existing
|
||||||
@@ -614,75 +614,14 @@ rules; the maintained examples show complete runnable workflows.
|
|||||||
|
|
||||||
### Choose A Profile Ownership Model
|
### Choose A Profile Ownership Model
|
||||||
|
|
||||||
Choose the profile source that matches the application's continuity needs:
|
Supply backend and profile definitions through the configuration sources your
|
||||||
|
application selects. PromptKit does not install provider catalogs or built-in
|
||||||
- Select `promptkit-openrouter-standard` or `promptkit-openrouter-auto` when
|
profile inventories; conventional backend ID constants are names only. Define
|
||||||
the maintained literal name is the desired consumer contract. Their current
|
the model, endpoint, credentials lookup, and settings that your application
|
||||||
selections are in the [format reference](../formats.md#built-in-profile-catalog).
|
intends to support. Profiles may inherit another configured profile using an
|
||||||
- Select an external catalog profile directly when the application accepts that
|
exact ID, and caller-selected source layers determine the final values. The
|
||||||
profile's catalog volatility. The selected external inventories are linked
|
[format reference](../formats.md) describes the definition fields and
|
||||||
from the [format reference](../formats.md#external-profile-inventories).
|
composition rules.
|
||||||
- Define a complete application-owned profile with an explicit backend or
|
|
||||||
endpoint, model, and settings when the application owns those choices.
|
|
||||||
|
|
||||||
An application profile that inherits an external base follows later changes to
|
|
||||||
that base and fails if the base disappears; it is not a frozen copy. Promptkit
|
|
||||||
tests the catalog versions selected in its module graph. Independently advancing
|
|
||||||
a catalog dependency can remove an inherited base and produce an untested
|
|
||||||
combination. Pinning the resolved module graph preserves the embedded data for
|
|
||||||
a build, but cannot preserve provider availability. Running binaries neither
|
|
||||||
download catalog updates nor automatically replace withdrawn models. See the
|
|
||||||
[release policy](../policy/release.md#catalog-profile-compatibility) for the exact
|
|
||||||
cross-version guarantees.
|
|
||||||
|
|
||||||
### Alias A Built-In Profile
|
|
||||||
|
|
||||||
Give an application-owned profile ID a built-in base when prompts should select
|
|
||||||
the application ID while inheriting the built-in target. The child can override
|
|
||||||
only the setting it owns:
|
|
||||||
|
|
||||||
```go
|
|
||||||
profile := promptkit.ProfileSource("application profiles", map[string]promptkit.ProfileConfig{
|
|
||||||
"weather-light": {
|
|
||||||
Extends: &standardID,
|
|
||||||
ReasoningEffort: &high,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Place `profile` in a ConfigKit underlay, with `standardID` set to
|
|
||||||
`"promptkit-openrouter-standard"` and `high` to `"high"`. Select
|
|
||||||
`weather-light` in a prompt or `RunRequest.ProfileID`; it remains the
|
|
||||||
reported selected profile. Definition IDs and inheritance references are exact
|
|
||||||
keys. If the base is an external profile, apply the volatility guidance
|
|
||||||
above when deciding whether to use an application-owned complete definition
|
|
||||||
instead.
|
|
||||||
|
|
||||||
### Use The Rakestrawhome Built-In Profile
|
|
||||||
|
|
||||||
Set `RAKESTRAWHOME_INFERENCE_API_KEY` in the application environment, then
|
|
||||||
select `rakestrawhome-gemma-4-31b` as an ordinary profile ID. For example, a
|
|
||||||
prepared result identifies the selected built-in through
|
|
||||||
`BackendRakestrawHome`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
prepared, err := engine.Prepare(ctx, promptkit.RunRequest{
|
|
||||||
PromptID: "meeting.summary",
|
|
||||||
ProfileID: "rakestrawhome-gemma-4-31b",
|
|
||||||
Inputs: inputs,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if prepared.SelectedBackendID != promptkit.BackendRakestrawHome {
|
|
||||||
return fmt.Errorf("unexpected backend %q", prepared.SelectedBackendID)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The maintained catalog supplies this backend, and callers may overlay its
|
|
||||||
effective configuration through a later ConfigKit source. Direct request credentials
|
|
||||||
and runtime endpoint overrides remain supported under their ordinary GoDoc and
|
|
||||||
format contracts.
|
|
||||||
|
|
||||||
### Inspect A Profile Before Prompt Work
|
### Inspect A Profile Before Prompt Work
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ Before starting work:
|
|||||||
| Root public API | The [architecture policy](policy/architecture.md), [consumer guide](consumers/pkg-promptkit.md), [testing policy](policy/testing.md), and existing GoDoc. |
|
| Root public API | The [architecture policy](policy/architecture.md), [consumer guide](consumers/pkg-promptkit.md), [testing policy](policy/testing.md), and existing GoDoc. |
|
||||||
| Prompt, profile, or schema formats | The [framework format reference](formats.md), owning parser or validator package, and [documentation policy](policy/documentation.md). |
|
| Prompt, profile, or schema formats | The [framework format reference](formats.md), owning parser or validator package, and [documentation policy](policy/documentation.md). |
|
||||||
| Source loading or validation | The [framework format reference](formats.md), [internal source document](internal/sources.md), and owning package tests. |
|
| Source loading or validation | The [framework format reference](formats.md), [internal source document](internal/sources.md), and owning package tests. |
|
||||||
| Maintained external catalogs or built-ins | The [internal source document](internal/sources.md), [framework format reference](formats.md), [testing policy](policy/testing.md), both catalog module repositories, each catalog's release procedure, and the selected module versions in `go.mod`. |
|
| Caller-supplied configuration sources | The [internal source document](internal/sources.md), [framework format reference](formats.md), and [testing policy](policy/testing.md). |
|
||||||
| Model-client behavior | The [OpenAI-compatible integration contract](integrations/openai-compatible-chat.md), [internal model-client document](internal/llm.md), and owning package tests. |
|
| Model-client behavior | The [OpenAI-compatible integration contract](integrations/openai-compatible-chat.md), [internal model-client document](internal/llm.md), and owning package tests. |
|
||||||
| Internal package implementation | The [architecture policy](policy/architecture.md), [internal component overview](internal/overview.md), and focused internal document listed for that package. |
|
| Internal package implementation | The [architecture policy](policy/architecture.md), [internal component overview](internal/overview.md), and focused internal document listed for that package. |
|
||||||
| Tests or test fixtures | The [testing policy](policy/testing.md), owning package, and focused internal document listed by the component overview. |
|
| Tests or test fixtures | The [testing policy](policy/testing.md), owning package, and focused internal document listed by the component overview. |
|
||||||
| Maintained example | The [preparation](../examples/go-library/prepare/main.go), [execution](../examples/go-library/run/main.go), and [observation](../examples/go-library/observe/main.go) examples, [consumer guide](consumers/pkg-promptkit.md), [framework format reference](formats.md), and [documentation policy](policy/documentation.md). |
|
| Maintained example | The [preparation](../examples/go-library/prepare/main.go), [execution](../examples/go-library/run/main.go), and [observation](../examples/go-library/observe/main.go) examples, [consumer guide](consumers/pkg-promptkit.md), [framework format reference](formats.md), and [documentation policy](policy/documentation.md). |
|
||||||
| Documentation | The [documentation policy](policy/documentation.md) and canonical owner of every affected contract. |
|
| Documentation | The [documentation policy](policy/documentation.md) and canonical owner of every affected contract. |
|
||||||
| Licensing, dependencies/catalog updates, copied material, or attribution | The [OSS policy](policy/oss.md), [project grant](../COPYRIGHT), [license texts](../LICENSE), and [attribution entries](oss/attribution.md); inspect the selected upstream source's notices. |
|
| Licensing, dependencies, copied material, or attribution | The [OSS policy](policy/oss.md), [project grant](../COPYRIGHT), [license texts](../LICENSE), and [attribution entries](oss/attribution.md); inspect the selected upstream source's notices. |
|
||||||
| Release preparation or publication, including release notes | The [release policy](policy/release.md), [release procedure](release.md), and [OSS discoverability rules](policy/oss.md#discoverability). |
|
| Release preparation or publication, including release notes | The [release policy](policy/release.md), [release procedure](release.md), and [OSS discoverability rules](policy/oss.md#discoverability). |
|
||||||
|
|
||||||
For cross-cutting changes, follow every applicable row. Do not create
|
For cross-cutting changes, follow every applicable row. Do not create
|
||||||
|
|||||||
@@ -155,16 +155,11 @@ last candidate and its failed validation result. Operational errors remain
|
|||||||
errors. A request-level `OutputContract` replaces the whole configured one,
|
errors. A request-level `OutputContract` replaces the whole configured one,
|
||||||
not individual fields; an empty request format defaults to `text`.
|
not individual fields; an empty request format defaults to `text`.
|
||||||
|
|
||||||
## Built-In Backends
|
## Backend Definitions
|
||||||
|
|
||||||
The selected catalog modules contribute these backend definitions as the
|
Backend definitions are supplied through caller-selected configuration
|
||||||
earliest underlay. Their settings can be overlaid by caller sources; these IDs
|
sources. The conventional backend IDs are names only; PromptKit does not
|
||||||
are not reserved against configuration changes.
|
install definitions for them.
|
||||||
|
|
||||||
| ID | Catalog endpoint | API-key environment name | Active generation limit |
|
|
||||||
| --- | --- | --- | ---: |
|
|
||||||
| `openrouter` | `https://openrouter.ai/api/v1` | `OPENROUTER_API_KEY` | 16 |
|
|
||||||
| `rakestrawhome` | `https://inference.ai.rakestrawhome.com/v1` | `RAKESTRAWHOME_INFERENCE_API_KEY` | 4 |
|
|
||||||
|
|
||||||
A backend definition may have `endpoint`, `api_key_env`,
|
A backend definition may have `endpoint`, `api_key_env`,
|
||||||
`concurrency_limit`, `queue_capacity`, `extra_params`, and `smoke_tests`. The
|
`concurrency_limit`, `queue_capacity`, `extra_params`, and `smoke_tests`. The
|
||||||
@@ -184,7 +179,7 @@ It may contain `default_profile`, `reachability`, and `authentication`:
|
|||||||
backends:
|
backends:
|
||||||
openrouter:
|
openrouter:
|
||||||
smoke_tests:
|
smoke_tests:
|
||||||
default_profile: promptkit-openrouter-standard
|
default_profile: application-profile
|
||||||
reachability:
|
reachability:
|
||||||
endpoint: https://status.example/ready?check=1
|
endpoint: https://status.example/ready?check=1
|
||||||
authentication:
|
authentication:
|
||||||
@@ -218,17 +213,6 @@ its documented fallback, while an explicit blank endpoint is invalid. The
|
|||||||
metadata does not change ordinary generation credential requirements or
|
metadata does not change ordinary generation credential requirements or
|
||||||
provider settings.
|
provider settings.
|
||||||
|
|
||||||
The selected v3 catalog modules ship diagnostic defaults in a separate,
|
|
||||||
opt-in `smoke-tests` root rather than changing the existing `catalog` root.
|
|
||||||
This Promptkit build selects [OpenRouter v3 `v3.20261013.0`](oss/attribution.md#promptkit-openrouter-catalog-v3)
|
|
||||||
with default profile `promptkit-openrouter-standard` and adapter
|
|
||||||
`openrouter_key`, and [Rakestrawhome v3 `v3.20261013.0`](oss/attribution.md#promptkit-rakestrawhome-catalog-v3)
|
|
||||||
with default profile `rakestrawhome-gemma-4-31b` and adapter `none`. The
|
|
||||||
attribution entries identify the selected module commits; these catalog
|
|
||||||
candidates are local and may not be publicly available. A consumer selecting
|
|
||||||
the extra root needs a compatible loader. These defaults do not promise
|
|
||||||
provider availability, account access, or free test requests.
|
|
||||||
|
|
||||||
## Profile Definitions
|
## Profile Definitions
|
||||||
|
|
||||||
Profiles are keyed by literal ID and may inherit a named parent with
|
Profiles are keyed by literal ID and may inherit a named parent with
|
||||||
@@ -289,11 +273,10 @@ does not disable the caller context or HTTP transport timeout.
|
|||||||
|
|
||||||
### Source And Profile Precedence
|
### Source And Profile Precedence
|
||||||
|
|
||||||
`NewEngine` composes catalog definitions first, Promptkit-owned definitions
|
`NewEngine` composes caller underlays in their given order, followed by an
|
||||||
next, then caller underlays in their given order, with an optional main input
|
optional main input. Later layers overlay earlier ones. Inputs within one
|
||||||
last. Later tiers overlay earlier ones. Inputs within one underlay group are
|
underlay group are strictly composed: conflicting contributions are errors,
|
||||||
strictly composed: conflicting contributions are errors, not priority
|
not priority signals. The directory helpers discover `.yaml` and `.yml` files recursively
|
||||||
signals. The directory helpers discover `.yaml` and `.yml` files recursively
|
|
||||||
in sorted order, but that order does not give one file higher precedence.
|
in sorted order, but that order does not give one file higher precedence.
|
||||||
An explicitly selected missing/unreadable root fails; an empty root contributes
|
An explicitly selected missing/unreadable root fails; an empty root contributes
|
||||||
nothing. Imports are disabled by these helpers unless the caller enables them
|
nothing. Imports are disabled by these helpers unless the caller enables them
|
||||||
@@ -315,31 +298,6 @@ second base-chain resolver. Missing references and cycles fail at construction.
|
|||||||
For generic inheritance and layer mechanics, consult
|
For generic inheritance and layer mechanics, consult
|
||||||
[ConfigKit](https://gitea.maximumdirect.net/eric/ConfigKit).
|
[ConfigKit](https://gitea.maximumdirect.net/eric/ConfigKit).
|
||||||
|
|
||||||
## Built-In Profile Catalog
|
|
||||||
|
|
||||||
Promptkit contributes two opt-in definitions; neither is selected by default:
|
|
||||||
|
|
||||||
| ID | Current definition |
|
|
||||||
| --- | --- |
|
|
||||||
| `promptkit-openrouter-standard` | Extends the selected OpenRouter catalog's `gemini-flash-latest` profile. |
|
|
||||||
| `promptkit-openrouter-auto` | Selects backend `openrouter` and model `openrouter/auto`. |
|
|
||||||
|
|
||||||
Select one through request `ProfileID` or prompt `default_profile`.
|
|
||||||
Caller layers may overlay these definitions or their catalog bases. The
|
|
||||||
[release policy](policy/release.md#catalog-profile-compatibility) owns their
|
|
||||||
cross-version compatibility boundary.
|
|
||||||
|
|
||||||
## External Profile Inventories
|
|
||||||
|
|
||||||
The selected catalog modules, not this document, own their profile inventories:
|
|
||||||
|
|
||||||
- [OpenRouter catalog v3.20261013.0 profiles](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/tag/v3.20261013.0/catalog/profiles)
|
|
||||||
- [Rakestrawhome catalog v3.20261013.0 profiles](https://gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/src/tag/v3.20261013.0/catalog/profiles)
|
|
||||||
|
|
||||||
These are tested local data, not a promise of live provider availability.
|
|
||||||
The [release policy](policy/release.md#catalog-profile-compatibility) owns
|
|
||||||
the compatibility boundary.
|
|
||||||
|
|
||||||
## Schemas
|
## Schemas
|
||||||
|
|
||||||
Schemas are JSON documents selected by a prompt or request `schema_path`.
|
Schemas are JSON documents selected by a prompt or request `schema_path`.
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ contributor workflow and validation.
|
|||||||
| `examples/go-library/run` | Demonstrates an offline downstream consumer using a prompt file, programmatic profile, inline input, an injected deterministic model client, and `Run`. It is not a public library package. | [Example program](../../examples/go-library/run/main.go) |
|
| `examples/go-library/run` | Demonstrates an offline downstream consumer using a prompt file, programmatic profile, inline input, an injected deterministic model client, and `Run`. It is not a public library package. | [Example program](../../examples/go-library/run/main.go) |
|
||||||
| `examples/go-library/observe` | Demonstrates offline built-in HTTP retry and synchronous metadata observation across structured proposal and assessment runs using embedded sources, two profiles on one finite backend, and an application decision. It is not a public library package. | [Example program](../../examples/go-library/observe/main.go) |
|
| `examples/go-library/observe` | Demonstrates offline built-in HTTP retry and synchronous metadata observation across structured proposal and assessment runs using embedded sources, two profiles on one finite backend, and an application decision. It is not a public library package. | [Example program](../../examples/go-library/observe/main.go) |
|
||||||
| `internal/backend` | Holds a defensive, immutable lookup of final backend definitions, including diagnostic metadata, plus capacity policies validated by the configuration adapter. | [Backend registry](../../internal/backend/registry.go) |
|
| `internal/backend` | Holds a defensive, immutable lookup of final backend definitions, including diagnostic metadata, plus capacity policies validated by the configuration adapter. | [Backend registry](../../internal/backend/registry.go) |
|
||||||
| `internal/catalog` | Selects released keyed catalog assets and PromptKit-owned profile definitions as ConfigKit underlays; effective validation belongs to the configuration loader. | [Catalog adapter](../../internal/catalog/catalog.go), [internal sources](sources.md#profiles-and-built-ins) |
|
|
||||||
| `internal/configuration` | Loads keyed backend, profile, and prompt configuration through ConfigKit; records effective field presence, validates final values including optional diagnostic metadata, captures indexed prompt definitions, referenced message content, compiled templates, input metadata snapshots, sorted identity-only profile and prompt inventories, backend and presence-aware profile snapshots, and an explicit read-only inspection view. | [Typed loader](../../internal/configuration/load.go), [identity listing](../../internal/configuration/listing.go), [internal sources](sources.md#typed-configuration-loading) |
|
| `internal/configuration` | Loads keyed backend, profile, and prompt configuration through ConfigKit; records effective field presence, validates final values including optional diagnostic metadata, captures indexed prompt definitions, referenced message content, compiled templates, input metadata snapshots, sorted identity-only profile and prompt inventories, backend and presence-aware profile snapshots, and an explicit read-only inspection view. | [Typed loader](../../internal/configuration/load.go), [identity listing](../../internal/configuration/listing.go), [internal sources](sources.md#typed-configuration-loading) |
|
||||||
| `internal/capacity` | Owns engine-local bounded execution admission and FIFO model-generation permits for limited backend IDs, including cancellation-safe waiter removal and client wrapping. | [Internal capacity management](capacity.md) |
|
| `internal/capacity` | Owns engine-local bounded execution admission and FIFO model-generation permits for limited backend IDs, including cancellation-safe waiter removal and client wrapping. | [Internal capacity management](capacity.md) |
|
||||||
| `internal/domain` | Defines internal framework values for requests, artifacts, prompt definitions, requirement inspection, profiles, execution targets, rendering, generation, validation, and source-neutral smoke diagnostics, and owns source-neutral invariants for shared execution settings, OpenAI-compatible base endpoints, session identifiers, output contracts, and resource-identity syntax and qualification. Source parsing, required fields, other source-specific normalization, defaulting, and boundary-specific error classification remain with their callers. | [Domain declarations](../../internal/domain/domain.go), [requirement values](../../internal/domain/requirements.go), [endpoint invariant](../../internal/domain/endpoint.go) |
|
| `internal/domain` | Defines internal framework values for requests, artifacts, prompt definitions, requirement inspection, profiles, execution targets, rendering, generation, validation, and source-neutral smoke diagnostics, and owns source-neutral invariants for shared execution settings, OpenAI-compatible base endpoints, session identifiers, output contracts, and resource-identity syntax and qualification. Source parsing, required fields, other source-specific normalization, defaulting, and boundary-specific error classification remain with their callers. | [Domain declarations](../../internal/domain/domain.go), [requirement values](../../internal/domain/requirements.go), [endpoint invariant](../../internal/domain/endpoint.go) |
|
||||||
| `internal/engine` | Assembles selected catalog and caller configuration into one snapshot, then constructs shared capacity, rendering, validation, generation, repair, the ordinary runner, and the smoke tester for each engine. Built-in engines provide the diagnostic HTTP collaborator; injected-client engines do not. It delegates identity listing directly to the captured configuration inventory rather than the runner. | [Engine assembly](../../internal/engine/engine.go), [internal sources](sources.md#profiles-and-built-ins), [internal runner](runner.md) |
|
| `internal/engine` | Assembles caller-selected configuration into one snapshot, then constructs shared capacity, rendering, validation, generation, repair, the ordinary runner, and the smoke tester for each engine. Built-in engines provide the diagnostic HTTP collaborator; injected-client engines do not. It delegates identity listing directly to the captured configuration inventory rather than the runner. | [Engine assembly](../../internal/engine/engine.go), [internal sources](sources.md#typed-configuration-loading), [internal runner](runner.md) |
|
||||||
| `internal/generation` | Coordinates frozen built-in HTTP attempts and one-shot injected calls through active backend permits, including bounded status retries, cancellable backoff, ordinary attempt observations, and invocation-local evidence for diagnostics. | [Internal generation coordination](generation.md) |
|
| `internal/generation` | Coordinates frozen built-in HTTP attempts and one-shot injected calls through active backend permits, including bounded status retries, cancellable backoff, ordinary attempt observations, and invocation-local evidence for diagnostics. | [Internal generation coordination](generation.md) |
|
||||||
| `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/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) |
|
| `internal/filecatalog` | Provides deterministic YAML discovery and path helpers for operating-system filesystems and `fs.FS` sources. | [File catalog](../../internal/filecatalog/catalog.go) |
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ of those inventories without consulting ConfigKit or copying definitions.
|
|||||||
The root `DirectoryInputs` and `FilesystemInputs` helpers discover sorted YAML
|
The root `DirectoryInputs` and `FilesystemInputs` helpers discover sorted YAML
|
||||||
files under an explicit root, provide resource context, and leave imports
|
files under an explicit root, provide resource context, and leave imports
|
||||||
disabled. Each returned slice belongs to one strict-composition group; file
|
disabled. Each returned slice belongs to one strict-composition group; file
|
||||||
order does not confer priority. The engine prepends selected catalog and
|
order does not confer priority. Caller underlays are composed in their given
|
||||||
Promptkit-owned definitions, then caller underlays and optional main. The
|
order, followed by the optional main input. The
|
||||||
[configuration tests](../../internal/configuration/load_test.go) exercise the
|
[configuration tests](../../internal/configuration/load_test.go) exercise the
|
||||||
real loader and final-value handoff.
|
real loader and final-value handoff.
|
||||||
|
|
||||||
@@ -112,19 +112,7 @@ dependency-bearing range scopes make discovery incomplete. Uncalled definitions
|
|||||||
and bypassed session templates are not traversed. This internal walker does not
|
and bypassed session templates are not traversed. This internal walker does not
|
||||||
change rendering behavior.
|
change rendering behavior.
|
||||||
|
|
||||||
## Profiles And Built-Ins
|
## Profiles
|
||||||
|
|
||||||
`internal/catalog` selects the tagged OpenRouter `v3.20261013.0` and
|
|
||||||
Rakestrawhome `v3.20261013.0` assets as one ConfigKit underlay and PromptKit-owned
|
|
||||||
profiles as the next. The selected catalog tags are local candidates and may not
|
|
||||||
be publicly available. It discovers YAML inputs, including each catalog's
|
|
||||||
opt-in `smoke-tests` root in addition to its existing `catalog` root, and
|
|
||||||
supplies passive filesystem context without parsing or pre-validating catalog
|
|
||||||
definitions. Catalog metadata remains separate from existing `/v3` assets for
|
|
||||||
strict-loader compatibility. The configuration loader
|
|
||||||
validates only the final effective backend and profile values, including
|
|
||||||
consumer overlays of maintained bases or backends. There is no catalog-only
|
|
||||||
preflight, reserved source namespace, or replay of backend registration.
|
|
||||||
|
|
||||||
ConfigKit resolves profile inheritance before the handoff. The configuration
|
ConfigKit resolves profile inheritance before the handoff. The configuration
|
||||||
adapter validates effective references and field values, then builds target
|
adapter validates effective references and field values, then builds target
|
||||||
@@ -135,8 +123,7 @@ provider work. Preparation applies runtime overrides and then checks target
|
|||||||
completeness. Identity-only profile selection can identify a partial captured
|
completeness. Identity-only profile selection can identify a partial captured
|
||||||
profile without copying its target or requiring readiness. The
|
profile without copying its target or requiring readiness. The
|
||||||
[target tests](../../internal/configuration/targets_test.go) cover effective
|
[target tests](../../internal/configuration/targets_test.go) cover effective
|
||||||
target interpretation, while the [catalog tests](../../internal/catalog/catalog_test.go)
|
target interpretation.
|
||||||
cover selected released assets.
|
|
||||||
|
|
||||||
The internal engine delegates listing through a narrow identity-inventory
|
The internal engine delegates listing through a narrow identity-inventory
|
||||||
interface directly to the configuration snapshot. The execution runner has no
|
interface directly to the configuration snapshot. The execution runner has no
|
||||||
|
|||||||
@@ -38,36 +38,6 @@ License and notices: [LGPL 3.0](../../LICENSE) |
|
|||||||
|
|
||||||
[Source](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/137769f3f18a370c68444242fb5d88e620e307e5).
|
[Source](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/137769f3f18a370c68444242fb5d88e620e307e5).
|
||||||
|
|
||||||
## Promptkit OpenRouter Catalog v3
|
|
||||||
|
|
||||||
Selected module: `gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v3`
|
|
||||||
at `v3.20261013.0`.
|
|
||||||
|
|
||||||
Copyright (C) 2026 Eric Rakestraw
|
|
||||||
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
License and notices: [MIT](licenses/MIT.txt) |
|
|
||||||
[COPYRIGHT](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/commit/2a69672b1bb220f1a730153341470f5ac67e15f4/COPYRIGHT) |
|
|
||||||
[LICENSE](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/commit/2a69672b1bb220f1a730153341470f5ac67e15f4/LICENSE).
|
|
||||||
|
|
||||||
[Source](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/commit/2a69672b1bb220f1a730153341470f5ac67e15f4).
|
|
||||||
|
|
||||||
## Promptkit Rakestrawhome Catalog v3
|
|
||||||
|
|
||||||
Selected module: `gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v3`
|
|
||||||
at `v3.20261013.0`.
|
|
||||||
|
|
||||||
Copyright (C) 2026 Eric Rakestraw
|
|
||||||
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
License and notices: [MIT](licenses/MIT.txt) |
|
|
||||||
[COPYRIGHT](https://gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/src/commit/d40a8aad50111c15d279469170f7b5032ac22529/COPYRIGHT) |
|
|
||||||
[LICENSE](https://gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/src/commit/d40a8aad50111c15d279469170f7b5032ac22529/LICENSE).
|
|
||||||
|
|
||||||
[Source](https://gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/src/commit/d40a8aad50111c15d279469170f7b5032ac22529).
|
|
||||||
|
|
||||||
## jsonschema
|
## jsonschema
|
||||||
|
|
||||||
Selected module: `github.com/santhosh-tekuri/jsonschema/v6` at `v6.0.2`.
|
Selected module: `github.com/santhosh-tekuri/jsonschema/v6` at `v6.0.2`.
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ The [internal component overview](../internal/overview.md) owns the inventory
|
|||||||
of implemented packages and their concrete responsibilities. This policy owns
|
of implemented packages and their concrete responsibilities. This policy owns
|
||||||
the boundaries and dependency rules those components must preserve.
|
the boundaries and dependency rules those components must preserve.
|
||||||
|
|
||||||
The internal engine composes selected catalog and caller ConfigKit inputs once,
|
The internal engine composes caller-selected ConfigKit inputs once, then
|
||||||
then assembles the captured definitions, capacity manager, renderer, validator,
|
assembles the captured definitions, capacity manager, renderer, validator,
|
||||||
outbound client, and use-case runner. The configuration adapter interprets and
|
outbound client, and use-case runner. The configuration adapter interprets and
|
||||||
validates only the final effective values, including presence, null, and
|
validates only the final effective values, including presence, null, and
|
||||||
resource context. It retains source history for explicit operator inspection,
|
resource context. It retains source history for explicit operator inspection,
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ secret values.
|
|||||||
| Release-note history | `docs/releases/` | One checked-in summary per source release under the procedure; the note at its immutable tag is the release record. | Current commands, behavior, contracts, and compatibility definitions. |
|
| Release-note history | `docs/releases/` | One checked-in summary per source release under the procedure; the note at its immutable tag is the release record. | Current commands, behavior, contracts, and compatibility definitions. |
|
||||||
| Complete copyable artifacts | `examples/` | Maintained configuration, inputs, and other copyable or runnable files. | Field-by-field reference, command reference, prose explanation. |
|
| Complete copyable artifacts | `examples/` | Maintained configuration, inputs, and other copyable or runnable files. | Field-by-field reference, command reference, prose explanation. |
|
||||||
| Exact exported Go API | Go declarations and GoDoc, as APIs are implemented | Exported names, signatures, types, values, errors, and exact behavioral contracts. | Task-oriented consumer walkthroughs, implementation details, and future API proposals. |
|
| Exact exported Go API | Go declarations and GoDoc, as APIs are implemented | Exported names, signatures, types, values, errors, and exact behavioral contracts. | Task-oriented consumer walkthroughs, implementation details, and future API proposals. |
|
||||||
| Framework file formats | `docs/formats.md` | Prompt-definition and profile YAML fields, schema references, defaults, validation modes, built-in profiles, credentials, and file-to-request precedence. | Exported Go declarations, outbound wire behavior, internal parsing mechanics, and application configuration. |
|
| Framework file formats | `docs/formats.md` | Prompt-definition and profile YAML fields, schema references, defaults, validation modes, credentials, and file-to-request precedence. | Exported Go declarations, outbound wire behavior, internal parsing mechanics, and application configuration. |
|
||||||
|
|
||||||
Create supporting documents for existing interfaces and responsibilities when
|
Create supporting documents for existing interfaces and responsibilities when
|
||||||
substantive content is available.
|
substantive content is available.
|
||||||
|
|||||||
@@ -278,29 +278,3 @@ captured publication endpoint before retrying; the repository-specific
|
|||||||
[procedure](../release.md#failure-recovery) links to the upstream recovery
|
[procedure](../release.md#failure-recovery) links to the upstream recovery
|
||||||
instructions. Do not wait for CI or Go module availability. Licensing footer
|
instructions. Do not wait for CI or Go module availability. Licensing footer
|
||||||
URLs are preparation work, not a network gate.
|
URLs are preparation work, not a network gate.
|
||||||
|
|
||||||
## Catalog Profile Compatibility
|
|
||||||
|
|
||||||
External catalog profile data may be added, removed, renamed, or modified
|
|
||||||
without deprecation or advance notice. This exception is limited to profile
|
|
||||||
data imported from the maintained catalog modules. It does not weaken ordinary
|
|
||||||
compatibility for Promptkit's public Go API, configuration and format semantics,
|
|
||||||
runtime behavior, catalog-module APIs, manifest schema, backend definitions, or
|
|
||||||
consumer-owned definitions.
|
|
||||||
|
|
||||||
Within the catalog versions selected and tested by a Promptkit release, and
|
|
||||||
unless a consumer overrides the name or its base, Promptkit keeps the literal
|
|
||||||
profile IDs `promptkit-openrouter-standard` and
|
|
||||||
`promptkit-openrouter-auto` available. The names do not promise a permanent
|
|
||||||
model, backend, routing behavior, settings, cost, output, or upstream
|
|
||||||
availability. The [framework format reference](../formats.md#built-in-profile-catalog)
|
|
||||||
owns their current definitions.
|
|
||||||
|
|
||||||
`v0.10.0` is the initial minor release for this compatibility transition.
|
|
||||||
Afterward, catalog-only updates and adjustments to the current selections may
|
|
||||||
ship in a patch release when all other compatibility obligations remain intact.
|
|
||||||
External profile removals can require consumer action; they are not automatic
|
|
||||||
migrations.
|
|
||||||
|
|
||||||
Catalog adoption and release validation remain local and offline. They do not
|
|
||||||
probe provider endpoints, request model lists, or make inference calls.
|
|
||||||
|
|||||||
@@ -97,11 +97,6 @@ the push outcome remains unknown. Successful publication needs no remote
|
|||||||
read-back, CI wait, or installation check. Provider probes and inference calls
|
read-back, CI wait, or installation check. Provider probes and inference calls
|
||||||
are not part of validation.
|
are not part of validation.
|
||||||
|
|
||||||
## Catalog Profile Compatibility
|
|
||||||
|
|
||||||
The [release policy](policy/release.md#catalog-profile-compatibility) owns the
|
|
||||||
catalog compatibility boundary. This heading preserves older incoming links.
|
|
||||||
|
|
||||||
## Failure Recovery
|
## Failure Recovery
|
||||||
|
|
||||||
For status 1, use the diagnostic to distinguish a validation failure from a
|
For status 1, use the diagnostic to distinguish a validation failure from a
|
||||||
|
|||||||
@@ -566,6 +566,17 @@ backend names still work when configured, and inference smoke tests retain their
|
|||||||
selection/capability behavior with caller-supplied metadata. Review `go.mod`,
|
selection/capability behavior with caller-supplied metadata. Review `go.mod`,
|
||||||
`go.sum`, imports, and notices for residual automatic catalog coupling.
|
`go.sum`, imports, and notices for residual automatic catalog coupling.
|
||||||
|
|
||||||
|
Completion: engine construction now composes only caller-selected underlays and
|
||||||
|
the optional main input; an empty configuration has empty profile and prompt
|
||||||
|
inventories. Removed the catalog adapter and its tests, provider catalog module
|
||||||
|
requirements and checksums, catalog attribution entries, and the built-in
|
||||||
|
profile compatibility exception. Current architecture, source, format, and
|
||||||
|
consumer documentation now describe caller-supplied definitions; historical
|
||||||
|
release notes remain unchanged. Explicit OpenRouter and Rakestrawhome backend
|
||||||
|
IDs continue to work when configured. Validation passed: `GOWORK=off go test
|
||||||
|
./...`, `GOWORK=off go vet ./...`, `GOWORK=off python3
|
||||||
|
scripts/check-examples.py`, and `git diff --check`.
|
||||||
|
|
||||||
## Stage 11: Add The Explicit Collection Input Helper
|
## Stage 11: Add The Explicit Collection Input Helper
|
||||||
|
|
||||||
Scope: the single public convenience function and its GoDoc.
|
Scope: the single public convenience function and its GoDoc.
|
||||||
|
|||||||
10
engine.go
10
engine.go
@@ -208,11 +208,11 @@ func WithSchemaFile(path string) Option {
|
|||||||
|
|
||||||
// NewEngine constructs an Engine from configuration and options.
|
// NewEngine constructs an Engine from configuration and options.
|
||||||
//
|
//
|
||||||
// ConfigKit composes maintained catalog inputs, PromptKit-owned definitions,
|
// ConfigKit composes caller-selected underlays in their given order, followed
|
||||||
// caller underlays, and the optional main input in that order. Construction
|
// by the optional main input. Construction validates the final effective
|
||||||
// validates the final effective backend, profile, and prompt definitions and
|
// backend, profile, and prompt definitions and captures referenced prompt
|
||||||
// captures referenced prompt content. A missing prompt collection is allowed.
|
// content. A missing prompt collection is allowed. Schema documents and
|
||||||
// Schema documents and request artifacts remain runtime resources.
|
// request artifacts remain runtime resources.
|
||||||
//
|
//
|
||||||
// NewEngine returns an error matching ErrInvalidConfig for invalid
|
// NewEngine returns an error matching ErrInvalidConfig for invalid
|
||||||
// configuration or options, preserving a ConfigKit LoadError when loading
|
// configuration or options, preserving a ConfigKit LoadError when loading
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -4,8 +4,6 @@ go 1.26.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.maximumdirect.net/eric/ConfigKit v0.8.0
|
gitea.maximumdirect.net/eric/ConfigKit v0.8.0
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v3 v3.20261013.0
|
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v3 v3.20261013.0
|
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -2,10 +2,6 @@ gitea.maximumdirect.net/eric/ConfigKit v0.8.0 h1:xCIhYnOHjw7rFvB+vIremPKGeROOxKT
|
|||||||
gitea.maximumdirect.net/eric/ConfigKit v0.8.0/go.mod h1:C82sbyKHYMV1OwaD2GJanFrwTfcZfjlW2JsGze5b0kA=
|
gitea.maximumdirect.net/eric/ConfigKit v0.8.0/go.mod h1:C82sbyKHYMV1OwaD2GJanFrwTfcZfjlW2JsGze5b0kA=
|
||||||
gitea.maximumdirect.net/eric/ReleaseKit v0.4.1 h1:Qn+mdebYOzCVCEXgCbuGSO/WHmJtItwaQ8e3XwY3qtI=
|
gitea.maximumdirect.net/eric/ReleaseKit v0.4.1 h1:Qn+mdebYOzCVCEXgCbuGSO/WHmJtItwaQ8e3XwY3qtI=
|
||||||
gitea.maximumdirect.net/eric/ReleaseKit v0.4.1/go.mod h1:LVodqNQ3OIKv9NBq+fFeyMByd1lHY25YOmmpah/NaNI=
|
gitea.maximumdirect.net/eric/ReleaseKit v0.4.1/go.mod h1:LVodqNQ3OIKv9NBq+fFeyMByd1lHY25YOmmpah/NaNI=
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v3 v3.20261013.0 h1:zhqxVDpQETGzCxYMsVGSWQcjsG4Xw+ftjEL/rCeh0GY=
|
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v3 v3.20261013.0/go.mod h1:HjS0f+3q0IdHCTEz+VVAEgIwIWJFAZUjuKdAtvtqKdg=
|
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v3 v3.20261013.0 h1:J10u3x+/siHz5ASC+Is4rfYA/ohW6colBT/8OuCA4qQ=
|
|
||||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v3 v3.20261013.0/go.mod h1:OEFBeKdjTsLzqJwLmXI2O5gG3r64FktcVJVb3mBrRfg=
|
|
||||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
||||||
@@ -18,5 +14,3 @@ golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
|
|||||||
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
|
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OpenRouterID identifies the maintained OpenRouter backend.
|
// OpenRouterID is the conventional OpenRouter backend identifier.
|
||||||
OpenRouterID = "openrouter"
|
OpenRouterID = "openrouter"
|
||||||
// RakestrawHomeID identifies the maintained Rakestrawhome backend.
|
// RakestrawHomeID is the conventional Rakestrawhome backend identifier.
|
||||||
RakestrawHomeID = "rakestrawhome"
|
RakestrawHomeID = "rakestrawhome"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
// Package catalog selects the maintained configuration assets supplied with
|
|
||||||
// PromptKit. ConfigKit owns their composition and effective validation.
|
|
||||||
package catalog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
|
|
||||||
"gitea.maximumdirect.net/eric/ConfigKit"
|
|
||||||
openrouter "gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v3"
|
|
||||||
rakestrawhome "gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v3"
|
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/backend"
|
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/filecatalog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Underlays selects external catalogs followed by PromptKit-owned profiles.
|
|
||||||
// Neither group is interpreted before the final effective configuration loads.
|
|
||||||
func Underlays() ([]configkit.Underlay, error) {
|
|
||||||
openrouterInputs, err := assetInputs("OpenRouter catalog", openrouter.FS(), openrouter.Root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rakestrawhomeInputs, err := assetInputs("Rakestrawhome catalog", rakestrawhome.FS(), rakestrawhome.Root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
catalogInputs := append(openrouterInputs, rakestrawhomeInputs...)
|
|
||||||
openrouterSmokeTestInputs, err := assetInputs("OpenRouter smoke-test catalog", openrouter.FS(), openrouter.SmokeTestsRoot)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rakestrawhomeSmokeTestInputs, err := assetInputs("Rakestrawhome smoke-test catalog", rakestrawhome.FS(), rakestrawhome.SmokeTestsRoot)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
catalogInputs = append(catalogInputs, openrouterSmokeTestInputs...)
|
|
||||||
catalogInputs = append(catalogInputs, rakestrawhomeSmokeTestInputs...)
|
|
||||||
owned := configkit.Input{Source: configkit.Mapping("PromptKit-owned profiles", map[string]any{
|
|
||||||
"profiles": map[string]any{
|
|
||||||
"promptkit-openrouter-standard": map[string]any{"extends": "gemini-flash-latest"},
|
|
||||||
"promptkit-openrouter-auto": map[string]any{"backend": backend.OpenRouterID, "model": "openrouter/auto"},
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
return []configkit.Underlay{{Inputs: catalogInputs}, {Inputs: []configkit.Input{owned}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func assetInputs(label string, filesystem fs.FS, root string) ([]configkit.Input, error) {
|
|
||||||
files, err := filecatalog.FindFSYAMLFiles(context.Background(), filesystem, root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("discover %s configuration: %w", label, err)
|
|
||||||
}
|
|
||||||
namespace := configkit.NewFilesystem(label, filesystem)
|
|
||||||
inputs := make([]configkit.Input, 0, len(files))
|
|
||||||
for _, name := range files {
|
|
||||||
inputs = append(inputs, configkit.Input{
|
|
||||||
Source: namespace.File(name),
|
|
||||||
Filesystem: &configkit.FilesystemContext{FS: &namespace, Root: root},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return inputs, nil
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
package catalog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gitea.maximumdirect.net/eric/ConfigKit"
|
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/configuration"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSelectedCatalogsResolveThroughEffectiveConfiguration(t *testing.T) {
|
|
||||||
underlays, err := Underlays()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
state, err := configuration.Load(configkit.Input{Source: configkit.NoSource()}, underlays)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
openrouter, err := state.GetBackend("openrouter")
|
|
||||||
if err != nil || openrouter.Endpoint != "https://openrouter.ai/api/v1" || openrouter.ConcurrencyLimit != 16 || openrouter.QueueCapacity != 1024 {
|
|
||||||
t.Fatalf("OpenRouter backend: %+v, %v", openrouter, err)
|
|
||||||
}
|
|
||||||
if openrouter.SmokeTests == nil || openrouter.SmokeTests.DefaultProfile == nil ||
|
|
||||||
*openrouter.SmokeTests.DefaultProfile != "promptkit-openrouter-standard" ||
|
|
||||||
openrouter.SmokeTests.Authentication == nil || openrouter.SmokeTests.Authentication.Kind == nil ||
|
|
||||||
*openrouter.SmokeTests.Authentication.Kind != "openrouter_key" {
|
|
||||||
t.Fatalf("OpenRouter smoke-test defaults: %+v", openrouter.SmokeTests)
|
|
||||||
}
|
|
||||||
rakestrawhome, err := state.GetBackend("rakestrawhome")
|
|
||||||
if err != nil || rakestrawhome.Endpoint != "https://inference.ai.rakestrawhome.com/v1" || rakestrawhome.ConcurrencyLimit != 4 {
|
|
||||||
t.Fatalf("Rakestrawhome backend: %+v, %v", rakestrawhome, err)
|
|
||||||
}
|
|
||||||
if rakestrawhome.SmokeTests == nil || rakestrawhome.SmokeTests.DefaultProfile == nil ||
|
|
||||||
*rakestrawhome.SmokeTests.DefaultProfile != "rakestrawhome-gemma-4-31b" ||
|
|
||||||
rakestrawhome.SmokeTests.Authentication == nil || rakestrawhome.SmokeTests.Authentication.Kind == nil ||
|
|
||||||
*rakestrawhome.SmokeTests.Authentication.Kind != "none" {
|
|
||||||
t.Fatalf("Rakestrawhome smoke-test defaults: %+v", rakestrawhome.SmokeTests)
|
|
||||||
}
|
|
||||||
for id, want := range map[string]string{
|
|
||||||
"promptkit-openrouter-standard": "~google/gemini-flash-latest",
|
|
||||||
"promptkit-openrouter-auto": "openrouter/auto",
|
|
||||||
"rakestrawhome-gemma-4-31b": "google/gemma-4-31b-it",
|
|
||||||
} {
|
|
||||||
profile, err := state.GetProfile(context.Background(), id)
|
|
||||||
if err != nil || profile.ResolvedTarget.Model != want {
|
|
||||||
t.Fatalf("profile %s: %+v, %v", id, profile, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConsumerCanReplaceOrClearSmokeTestDefaults(t *testing.T) {
|
|
||||||
underlays, err := Underlays()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
replacement := configkit.Input{Source: configkit.Mapping("operator replacement", map[string]any{
|
|
||||||
"backends": map[string]any{"openrouter": map[string]any{
|
|
||||||
"smoke_tests": map[string]any{
|
|
||||||
"default_profile": "operator-profile",
|
|
||||||
"authentication": nil,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
})}
|
|
||||||
state, err := configuration.Load(replacement, underlays)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("load replacement: %v", err)
|
|
||||||
}
|
|
||||||
backend, err := state.GetBackend("openrouter")
|
|
||||||
if err != nil || backend.SmokeTests == nil || backend.SmokeTests.DefaultProfile == nil ||
|
|
||||||
*backend.SmokeTests.DefaultProfile != "operator-profile" || backend.SmokeTests.Authentication != nil {
|
|
||||||
t.Fatalf("caller smoke-test replacement/null was not effective: %+v, %v", backend.SmokeTests, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cleared := configkit.Input{Source: configkit.Mapping("operator null", map[string]any{
|
|
||||||
"backends": map[string]any{"openrouter": map[string]any{"smoke_tests": nil}},
|
|
||||||
})}
|
|
||||||
state, err = configuration.Load(cleared, underlays)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("load null smoke_tests: %v", err)
|
|
||||||
}
|
|
||||||
backend, err = state.GetBackend("openrouter")
|
|
||||||
if err != nil || backend.SmokeTests != nil {
|
|
||||||
t.Fatalf("caller null did not clear smoke-test defaults: %+v, %v", backend.SmokeTests, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConsumerOverlayReplacesCatalogDefaultsBeforeValidation(t *testing.T) {
|
|
||||||
underlays, err := Underlays()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
underlays = append(underlays, configkit.Underlay{Inputs: []configkit.Input{{Source: configkit.Mapping("operator", map[string]any{
|
|
||||||
"backends": map[string]any{"openrouter": map[string]any{"endpoint": "invalid lower value"}},
|
|
||||||
})}}})
|
|
||||||
main := configkit.Input{Source: configkit.Mapping("application", map[string]any{
|
|
||||||
"backends": map[string]any{"openrouter": map[string]any{"endpoint": "https://alternate.example/v1"}},
|
|
||||||
"profiles": map[string]any{"gemini-flash-latest": map[string]any{"model": "consumer-model"}},
|
|
||||||
})}
|
|
||||||
state, err := configuration.Load(main, underlays)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("replaced lower-layer value failed final validation: %v", err)
|
|
||||||
}
|
|
||||||
profile, err := state.GetProfile(context.Background(), "promptkit-openrouter-standard")
|
|
||||||
if err != nil || profile.ResolvedTarget.Model != "consumer-model" || profile.ResolvedTarget.Endpoint != "https://alternate.example/v1" {
|
|
||||||
t.Fatalf("maintained profile did not observe final configuration: %+v, %v", profile, err)
|
|
||||||
}
|
|
||||||
_, err = configuration.Load(configkit.Input{Source: configkit.Mapping("invalid final", map[string]any{
|
|
||||||
"backends": map[string]any{"openrouter": map[string]any{"endpoint": "invalid final value"}},
|
|
||||||
})}, underlays[:2])
|
|
||||||
var loadError *configkit.LoadError
|
|
||||||
if !errors.As(err, &loadError) {
|
|
||||||
t.Fatalf("invalid final backend did not produce a ConfigKit load error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"gitea.maximumdirect.net/eric/ConfigKit"
|
"gitea.maximumdirect.net/eric/ConfigKit"
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/artifact"
|
"gitea.maximumdirect.net/eric/promptkit/internal/artifact"
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/capacity"
|
"gitea.maximumdirect.net/eric/promptkit/internal/capacity"
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/catalog"
|
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/configuration"
|
"gitea.maximumdirect.net/eric/promptkit/internal/configuration"
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/defaults"
|
"gitea.maximumdirect.net/eric/promptkit/internal/defaults"
|
||||||
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
|
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
|
||||||
@@ -98,11 +97,7 @@ func New(cfg Config, options Options) (*Engine, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
underlays, err := catalog.Underlays()
|
underlays := cfg.Sources.Underlays
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("select maintained configuration: %w", err)
|
|
||||||
}
|
|
||||||
underlays = append(underlays, cfg.Sources.Underlays...)
|
|
||||||
main := configkit.Input{Source: configkit.NoSource()}
|
main := configkit.Input{Source: configkit.NoSource()}
|
||||||
if cfg.Sources.Main != nil {
|
if cfg.Sources.Main != nil {
|
||||||
main = *cfg.Sources.Main
|
main = *cfg.Sources.Main
|
||||||
|
|||||||
@@ -185,11 +185,7 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestListIdentitiesEmptyEffectiveConfiguration(t *testing.T) {
|
func TestListIdentitiesEmptyEffectiveConfiguration(t *testing.T) {
|
||||||
main := configkit.Input{Source: configkit.Mapping("clear effective identities", map[string]any{
|
engine, err := promptkit.NewEngine(promptkit.Config{})
|
||||||
"profiles": nil,
|
|
||||||
"prompts": nil,
|
|
||||||
})}
|
|
||||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &main}})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user