From 7df7e420aa91a41366ad82a4a61ef28cdba9b003 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 10 Nov 2026 15:14:31 +0000 Subject: [PATCH] Adopt ConfigKit 1.2.0 --- configuration_sources_test.go | 41 +++++++++++++++++++++++++++++++++ docs/consumers/pkg-promptkit.md | 41 ++++++++++++++++++++++++++++++--- docs/formats.md | 4 ++-- docs/internal/sources.md | 4 ++-- docs/oss/attribution.md | 8 +++---- go.mod | 2 +- go.sum | 4 ++-- 7 files changed, 90 insertions(+), 14 deletions(-) diff --git a/configuration_sources_test.go b/configuration_sources_test.go index 5350d5b..b629350 100644 --- a/configuration_sources_test.go +++ b/configuration_sources_test.go @@ -63,6 +63,47 @@ func TestCollectionInputLoadsNativeImportsAndLaterOverride(t *testing.T) { } } +func TestCollectionInputUsesMainRelativeContext(t *testing.T) { + filesystem := configkit.NewFilesystem("application", fstest.MapFS{ + "site/main.yaml": {Data: []byte("version: '2'\n")}, + "site/prompts/greeting.yaml": {Data: []byte(`id: greeting +messages: + - role: user + content_file: greeting.txt +output: {format: text, validation_mode: none} +`)}, + "site/prompts/greeting.txt": {Data: []byte("Hello from the imported prompt's directory.")}, + }) + companion, err := promptkit.CollectionInput("support", configkit.Bytes("companion prompts", []byte(` +config: + imports: + - dir: prompts + pattern: ["*.yaml", "*.yml"] + destination: [prompts] + placement: sequence-item + required: true +`))) + if err != nil { + t.Fatal(err) + } + companion.MainRelative = configkit.MainRelative() + main := configkit.Input{Source: filesystem.File("site/main.yaml")} + engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{ + Main: &main, + Underlays: []configkit.Underlay{{Inputs: []configkit.Input{companion}}}, + }}, promptkit.WithBundledOpenRouter(false)) + if err != nil { + t.Fatalf("construct engine with main-relative imports: %v", err) + } + inspection, err := engine.InspectPrompt(t.Context(), "support/greeting") + if err != nil { + t.Fatal(err) + } + if len(inspection.Messages) != 1 || inspection.Messages[0].Content != "Hello from the imported prompt's directory." { + t.Fatalf("unexpected imported messages: %+v", inspection.Messages) + } +} + func TestCollectionInputLoadsEmbeddedImportsAndLaterOverride(t *testing.T) { files := fstest.MapFS{ "collection.yaml": {Data: []byte("config:\n imports:\n - path: defaults.yaml\n required: true\n")}, diff --git a/docs/consumers/pkg-promptkit.md b/docs/consumers/pkg-promptkit.md index ad9b749..f6c53d4 100644 --- a/docs/consumers/pkg-promptkit.md +++ b/docs/consumers/pkg-promptkit.md @@ -18,7 +18,7 @@ import "go.maximumdirect.net/promptkit" For migration from the former module path, see [Update Go Imports](configuration-migration.md#update-go-imports). -Configuration APIs use `go.maximumdirect.net/configkit` v1.1.0. Its types are +Configuration APIs use `go.maximumdirect.net/configkit` v1.2.0. Its types are not interchangeable with the old ConfigKit module path. The maintained [offline preparation example](../../examples/go-library/prepare/main.go) @@ -102,6 +102,39 @@ new engine to observe configuration edits. See the [constructor GoDoc](../../eng for the exact public contract and the [framework format reference](../formats.md) for definition fields. +### Load Companion Prompts Relative To The Main Configuration + +A non-file underlay can use the selected main configuration's directory for +caller-declared imports. For example, this loads standalone prompt definitions +from the adjacent `prompts/` directory into the `support` collection: + +```go +main := configkit.Input{Source: configkit.File(configPath)} +companion, err := promptkit.CollectionInput("support", configkit.Bytes("companion prompts", []byte(` +config: + imports: + - dir: prompts + pattern: ["*.yaml", "*.yml"] + destination: [prompts] + placement: sequence-item + required: true +`))) +if err != nil { return err } +companion.MainRelative = configkit.MainRelative() +engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{ + Main: &main, + Underlays: []configkit.Underlay{{Inputs: []configkit.Input{companion}}}, +}}) +``` + +`CollectionInput` enables imports; for a raw `configkit.Input`, enable them with +`Imports: true`. The binding itself does not enable imports, and an explicit +`Input.Filesystem` takes precedence. Imported prompt `content_file` references +keep their source-local context. See ConfigKit's +[layered-loading contract](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.2.0/docs/config.md#layered-loading) +for eligible inputs, fallback contexts, and behavior when the main has no usable +filesystem context. + ### Use Scoped Engine Views Create a view when an application wants short request IDs to resolve within a @@ -181,7 +214,9 @@ input := configkit.Input{Source: document} null is not needed. Prompt and backend helpers, like profiles, support sibling inheritance via `Extends`; partial records can be completed by other layers. For relative prompt `content_file` references, supply the ordinary ConfigKit -`Input.Filesystem` context for that source. The helpers do not read files or +`Input.Filesystem` context for that source, or use a +[main-relative underlay](#load-companion-prompts-relative-to-the-main-configuration). +The helpers do not read files or validate final definitions. Profile and backend provider maps use ConfigKit Mapping input forms: built-in scalars, `[]any`, and `map[string]any` recursively. Convert `json.Number` or typed containers explicitly to an appropriate supported value, choosing numeric @@ -300,7 +335,7 @@ for _, difference := range differences { ``` See the [`ConfigurationInspection.Diff` GoDoc](../../configuration_inspection.go) -and ConfigKit's [v1.1.0 effective-configuration diff guidance](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.1.0/docs/config.md#effective-configuration-diffs) +and ConfigKit's [effective-configuration diff guidance](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.2.0/docs/config.md#effective-configuration-diffs) for the exact comparison contract. The operation compares only frozen effective configuration values: it does not reread external files or compare their contents, resolved credential contents, later execution preparation, or diff --git a/docs/formats.md b/docs/formats.md index 28af3aa..4740bba 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -6,7 +6,7 @@ This is the canonical reference for Promptkit's backend, profile, prompt, and schema definitions. The [Go consumer guide](consumers/pkg-promptkit.md) shows how to select sources and use an engine; the [OpenAI-compatible integration contract](integrations/openai-compatible-chat.md) -owns outbound wire behavior. [ConfigKit](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.1.0/docs/config.md) +owns outbound wire behavior. [ConfigKit](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.2.0/docs/config.md) owns the generic YAML grammar, imports, layering, inheritance, and diagnostics. This reference describes what Promptkit does with the final effective values. @@ -429,7 +429,7 @@ references are exact IDs and use their qualified form when they select a collection resource. There is no Promptkit-specific depth limit or second base-chain resolver. Missing references and cycles fail at construction. For generic inheritance and layer mechanics, consult -[ConfigKit](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.1.0/docs/config.md). +[ConfigKit](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.2.0/docs/config.md). ## Schemas diff --git a/docs/internal/sources.md b/docs/internal/sources.md index c10d8bf..12832d9 100644 --- a/docs/internal/sources.md +++ b/docs/internal/sources.md @@ -36,12 +36,12 @@ owns the exact source-header and collection contracts. The `ConfigurationInspection.Diff` facade method compares two retained results through a private wrapper and a narrow `internal/configuration.Diff` bridge. The wrapper keeps `Result[document]` inside the adapter; the bridge delegates -once to ConfigKit v1.1.0 and returns its public difference records. Comparison +once to ConfigKit and returns its public difference records. Comparison uses only frozen effective values and does not reopen sources, resolve runtime credentials, or enter the execution path. ConfigKit applies sensitivity from both results; reports may still contain ordinary application data. See the [consumer comparison guide](../consumers/pkg-promptkit.md#inspect-the-captured-configuration) -and ConfigKit's [v1.1.0 comparison contract](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.1.0/docs/config.md#effective-configuration-diffs). +and ConfigKit's [comparison contract](https://forge.maximumdirect.net/base-layer/configkit/src/tag/v1.2.0/docs/config.md#effective-configuration-diffs). After resource materialization and effective-profile snapshot construction, the adapter captures lexically ordered identity inventories for backends, profiles, diff --git a/docs/oss/attribution.md b/docs/oss/attribution.md index 3c3b020..0e78e59 100644 --- a/docs/oss/attribution.md +++ b/docs/oss/attribution.md @@ -26,17 +26,17 @@ License and notices: [CC BY-SA 4.0](licenses/CC-BY-SA-4.0.txt) | ## ConfigKit -Selected module: `go.maximumdirect.net/configkit` at `v1.1.0`. +Selected module: `go.maximumdirect.net/configkit` at `v1.2.0`. Copyright (C) 2026 Eric Rakestraw SPDX-License-Identifier: LGPL-3.0-or-later License and notices: [LGPL 3.0](../../LICENSE) | -[COPYRIGHT](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/COPYRIGHT) | -[LICENSE](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/LICENSE). +[COPYRIGHT](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/COPYRIGHT) | +[LICENSE](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/LICENSE). -[Source](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9). +[Source](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e). ## ReleaseKit diff --git a/go.mod b/go.mod index f547905..0874d23 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.27.0 require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 - go.maximumdirect.net/configkit v1.1.0 + go.maximumdirect.net/configkit v1.2.0 go.yaml.in/yaml/v4 v4.0.0-rc.6 ) diff --git a/go.sum b/go.sum index f02ee1b..89b6675 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEV github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/yuin/goldmark/v2 v2.1.6 h1:igy0q9JcqovoFXFx/XjtU8sHVhcUHavPj2sA3EoKJUE= github.com/yuin/goldmark/v2 v2.1.6/go.mod h1:G6M4/qOFtfn01/o14BU1UR2Lo5N3S9Qo7xCuz/sHjGQ= -go.maximumdirect.net/configkit v1.1.0 h1:UzXN2ZMnEkcL0O4YSLqD9qd9M1gb/NWCHQR/H8AaQzA= -go.maximumdirect.net/configkit v1.1.0/go.mod h1:s1zLJ9GGB/1Q4a+aOHMLISonJxWFgNWpA6SpPlOafeA= +go.maximumdirect.net/configkit v1.2.0 h1:c4tDJ6Xeh/Jg90UZplLxsnf500lvrZBVj0E3i1ysir8= +go.maximumdirect.net/configkit v1.2.0/go.mod h1:s1zLJ9GGB/1Q4a+aOHMLISonJxWFgNWpA6SpPlOafeA= go.maximumdirect.net/releasekit v0.9.0 h1:sK+Aoj6gS6ATU/1reocjwBekp4YETYENwkcX5ti6mrE= go.maximumdirect.net/releasekit v0.9.0/go.mod h1:QE4BLrAhVJTzi+/YTcVl21K/qZp9ojRLg5kuoy3Zb44= go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4=