Files
promptkit/docs/consumers/configuration-migration.md

9.1 KiB

Configuration And API Migration

This breaking pre-v1 minor migration adopts Promptkit's vanity module path, changes the v0.16-era keyed resources to identified lists, adopts ConfigKit v1, and removes prompt-version labels. Promptkit does not install a provider catalog; applications choose configuration inputs explicitly, and execution selects one prompt by its exact ID. This guide explains the shape changes and decisions an application must make; it is not an automatic migration tool. The framework format reference owns the current configuration contract, and the root package GoDoc owns exact API signatures and errors.

Update Go Imports

Promptkit's module and public package import path is now go.maximumdirect.net/promptkit, replacing gitea.maximumdirect.net/eric/promptkit. Update application, library, test, and generated imports, then select a release using the new declaration:

go get go.maximumdirect.net/promptkit@VERSION
go mod tidy

Replace VERSION with a release that declares the vanity module path. Earlier tags, including v0.16.0, retain their original module declaration and use the former import path. No permanent replace directive is needed for the cutover. Source browser, licensing, and hosted-release links continue to use the Forge repository URLs, independently of Go's module identifier.

The package name remains promptkit. The path change itself does not rename exported APIs or change their behavior, but Go treats packages imported through the two paths as distinct. Update dependent packages that exchange Promptkit types together and review any old-path dependencies retained after tidying. The configuration and API adaptations below are also part of this migration.

Select And Compose The Configuration You Need

Supply each backend, profile, prompt, schema, and collection source that the application intends to use. Promptkit does not discover directories or install provider definitions implicitly. An application may select an explicit collection input with CollectionInput:

input, err := promptkit.CollectionInput(
	"openrouter",
	configkit.File("config/openrouter.yaml"),
)
if err != nil {
	return err
}
engine, err := promptkit.NewEngine(promptkit.Config{
	Sources: promptkit.ConfigurationSources{
		Underlays: []configkit.Underlay{{Inputs: []configkit.Input{input}}},
	},
})

Collection resource IDs are local IDs, while their runtime identities are qualified. For example, a profile with id: gemini-flash-latest in collection openrouter is selected as openrouter/gemini-flash-latest. Stored backend, prompt-default, and other resource references must use their exact intended IDs; Promptkit does not rewrite references when a source is mounted. extends selects a sibling ID in the same list, not a cross-collection reference. Review collisions and all references when moving resources into collections.

The optional source-root version header now accepts 2 or "2"; headerless sources remain valid. A collection's release_version remains an optional label. Prompt-version labels have been removed: choose one definition per ID and store any application-specific release label outside Promptkit. In a standalone imported prompt item, root version is a source header, not a label.

For example, change a version-keyed definition:

prompts:
  report:
    "2.0":
      messages:
        - role: user
          content: Review this report.
      output:
        format: text
        validation_mode: none

to one identified definition:

prompts:
  - id: report
    messages:
      - role: user
        content: Review this report.
    output:
      format: text
      validation_mode: none

The same conversion applies to backends and profiles. Sibling inheritance uses identity references, and a later same-ID record replaces the whole lower record:

profiles:
  - id: base
    endpoint: https://example.invalid/v1
    model: example-model
  - id: fast
    extends: {id: base}
    timeout_seconds: 30

To customize a lower resource's fields, add a distinct inherited variant as above; when replacing the same ID, supply the complete intended record. Generic append, replace, imports, and inheritance are described by the ConfigKit v1 configuration contract. Source-root controls are now config:, not configkit:. Imports are optional unless the selected import declares required: true.

Update ConfigKit imports to go.maximumdirect.net/configkit at v1.0.0: its Go types are incompatible with the old module path. Promptkit now requires Go 1.27.0 or newer. Source builders take ordered slices with explicit IDs:

endpoint, model := "https://example.invalid/v1", "example-model"
base := "base"
source := promptkit.ProfileSource("application", []promptkit.ProfileConfig{
	{ID: "base", Endpoint: &endpoint, Model: &model},
	{ID: "fast", Extends: &base},
})

Replace former maps passed to BackendSource in the same way, setting each BackendConfig.ID. Duplicates are retained for loading to reject. Resource inspection paths now address list indexes, for example configkit.Keys("profiles").Index(0).Key("model"). Configuration inspection and diffs expose composed values and provenance, while InspectProfile and other interpreted views expose Promptkit normalization and defaults; the views are not promised to be identical.

Remove PromptVersion and PromptIdentity.Version uses and the corresponding prompt_version JSON members. Prompt hashes are opaque equality values and may change when the removed field no longer participates in hashing.

Identity Mapping

The reviewed catalog identities have slash-free profile keys. Their documented mapping is:

Previous identity Namespaced identity or action
Backend openrouter openrouter/default
Backend rakestrawhome rakestrawhome/default
Each OpenRouter catalog profile p openrouter/p, retaining the exact local key p
Profile rakestrawhome-gemma-4-31b rakestrawhome/rakestrawhome-gemma-4-31b
Built-in promptkit-openrouter-standard No automatic replacement; optionally define caller profile openrouter/standard
Built-in promptkit-openrouter-auto No automatic replacement; optionally define caller profile openrouter/auto

These are conversion examples, not aliases or bundled resources. Mounting old /v3 assets does not update backend references, profile inheritance, prompt defaults, or diagnostic defaults inside them. Edit those values to the exact qualified IDs you chose.

For example, an optional caller-owned standard profile may extend a selected Gemini profile in the same openrouter collection:

collections:
  openrouter:
    profiles:
      - id: standard
        extends: {id: gemini-flash-latest}

An optional auto profile may instead select the exact backend and model values:

collections:
  openrouter:
    profiles:
      - id: auto
        backend: openrouter/default
        model: openrouter/auto

Neither optional profile name is a Promptkit contract. Keep provider model strings and settings as selected by the application, including any meaningful prefixes. If a backend declares diagnostic defaults, update them to exact qualified IDs; an unselected diagnostic default is not automatically made resolvable by migration.

Prompt Selection API

Prompt selection is ID-only. Remove version selectors from calls to Run, Prepare, PrepareExecution, ValidateRequest, InspectRequirements, and SmokeTest. Remove the PromptVersion field from RunRequest, RequirementInspectionRequest, and SmokeTestRequest; InspectPrompt now has the form InspectPrompt(ctx, promptID). For example, select the prompt explicitly in the request rather than setting a version selector:

request := promptkit.RunRequest{
	PromptID:  "support/report",
	ProfileID: "support/standard",
}
_, err = engine.Run(ctx, request)
if err != nil {
	return err
}

If the former format contained multiple versions under one ID, choose the one definition the application should install. Promptkit no longer retains or returns its former descriptive label.

The public inventory APIs can help an operator inspect a captured effective configuration: ListProfiles, ListPrompts, and ListBackends return exact identities, while ListNamespaces and ListCollections expose resource-bearing namespaces and effective collection declarations. Inventory does not select which configuration version the application should deploy.

Deployment Selection Remains With The Application

Applications decide which checked-in, embedded, operator-supplied, or programmatic inputs to compose for each deployment. They also decide when to construct a replacement engine after changing those sources. Promptkit does not fetch catalog updates, select provider availability, validate upstream catalog release status, or automatically migrate arbitrary consumer files. The maintained offline collection example shows explicit source selection, local imports, layering, a scoped view, and operator inventory without a provider call.