From 1806df9888d18a38c03d14afb361154b6a1208d2 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sat, 29 Aug 2026 14:08:35 +0000 Subject: [PATCH] Adopt the Promptkit v0.9 compatibility baseline --- README.md | 6 ++-- docs/api.md | 8 +++-- docs/cli.md | 2 +- docs/config.md | 20 ++++++++--- docs/consumers/api.md | 4 +-- docs/consumers/migrating-to-promptkit.md | 20 +++++------ docs/development.md | 8 ++--- docs/internal/adapters.md | 2 +- docs/internal/overview.md | 2 +- docs/internal/sources.md | 2 +- docs/operations.md | 2 +- docs/policy/architecture.md | 7 ++-- docs/release.md | 6 ++-- docs/roadmap/implementation.md | 2 ++ go.mod | 4 ++- go.sum | 8 +++-- internal/adapter/dependency_test.go | 30 ++++++++++++++-- internal/adapter/http/dto.go | 2 +- internal/adapter/http/handler_test.go | 44 +++++++++++++++++++++++- 19 files changed, 136 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 60eddb6..0652f00 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ OpenAI-compatible model endpoints, and returns generated output with validation metadata. The application uses -[Promptkit v0.1.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/) +[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/) for prompt, profile, schema, preparation, generation, and validation behavior. Scriptorium owns executable configuration, CLI and HTTP mapping, process behavior, output presentation, and HTTP artifact-containment policy. @@ -38,8 +38,8 @@ a model. For complete invocation and output behavior, see the - [Migration from the former Go package](docs/consumers/migrating-to-promptkit.md) - [Subprocess integration](docs/integrations/subprocess.md) - [Architecture policy](docs/policy/architecture.md) -- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) -- [Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) +- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md) +- [Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) ## Examples diff --git a/docs/api.md b/docs/api.md index 942d333..799b4f6 100644 --- a/docs/api.md +++ b/docs/api.md @@ -67,15 +67,19 @@ The optional `model` object accepts `endpoint`, `model`, `temperature`, `max_tokens`, `top_p`, `timeout_seconds`, `service_tier`, `reasoning_effort`, `api_key_env`, and `extra_params`. Numeric ranges and framework credential semantics are defined by the -[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md). +[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md). Explicit zero values for the numeric fields are overrides; zero `timeout_seconds` disables the per-generation deadline only, retaining the request context and configured transport cap. The timeout layers are defined in -the [Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation). +the [Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation). Raw API-key values are not accepted. `api_key` and any other unknown model field cause `400 invalid_json`. +`model.reasoning_effort` is an optional JSON string with three states: omission +inherits the selected profile, a non-empty string replaces its value, and an +empty string explicitly clears it. JSON `null` is treated as omission. + ### Strict JSON Request decoding rejects malformed JSON, unknown fields at every request level, diff --git a/docs/cli.md b/docs/cli.md index 5458532..45b01cf 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -69,7 +69,7 @@ only; the caller context and configured transport cap remain active. CLI durations are converted to whole seconds by truncation toward zero, so any duration whose absolute value is below one second becomes an explicit zero-second override. The timeout layers are defined in the -[Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation). +[Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation). There is no raw API-key flag. Use `--api-key-env`. diff --git a/docs/config.md b/docs/config.md index 0419897..9959321 100644 --- a/docs/config.md +++ b/docs/config.md @@ -3,7 +3,7 @@ This is the canonical reference for Scriptorium application settings. Prompt, profile, schema, execution-setting, built-in profile, and framework credential semantics are defined by the -[Promptkit v0.1.0 format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md). +[Promptkit v0.9.0 format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md). For command syntax, see the [CLI reference](cli.md); for HTTP request shapes and outcomes, see the [HTTP API reference](api.md). @@ -58,7 +58,7 @@ parse those framework file formats. contracts. See the -[tagged Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) +[tagged Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md) for all of those definitions. The files under [`examples/prompts`](../examples/prompts/), [`examples/profiles`](../examples/profiles/), and @@ -73,8 +73,20 @@ their names in configuration or framework source files. Do not place raw keys in configuration, prompts, profiles, CLI arguments, examples, or HTTP payloads. +An optional `api_key_env` whose environment value is absent or empty can result +in an unauthenticated provider request. A profile that declares credentials +required still fails as an invalid request when no credential source is +selected, and fails with `ErrAPIKeyEnvMissing` when its selected environment +source is absent or empty. Scriptorium never reads or emits the environment +value itself. + +Unset optional provider controls are omitted from compatible provider requests. +A positive Promptkit `repair_attempts` budget can add provider calls, latency, +token use, and cost; see the tagged format reference for its permitted values +and validation-mode requirements. + Promptkit's -[OpenAI-compatible integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md) +[OpenAI-compatible integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md) defines outbound authentication, provider request mapping, transport limits, and timeout layering. @@ -83,4 +95,4 @@ and timeout layering. - [CLI reference](cli.md) - [HTTP API reference](api.md) - [Operations guide](operations.md) -- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) +- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md) diff --git a/docs/consumers/api.md b/docs/consumers/api.md index f683f34..47f0a00 100644 --- a/docs/consumers/api.md +++ b/docs/consumers/api.md @@ -14,7 +14,7 @@ and the HTTP service according to the boundary your application needs. Go applications that need an in-process prompt framework should import Promptkit directly. The tagged -[Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) +[Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) owns that interface; Scriptorium does not provide a Go library package. Consumers arriving from the former Scriptorium Go API should follow the [migration guide](migrating-to-promptkit.md). @@ -35,4 +35,4 @@ Scriptorium does not persist run state. A retry can produce different output and can incur another provider request. CLI exits belong to the [CLI reference](../cli.md), HTTP status behavior belongs to the [HTTP API reference](../api.md), and framework semantics belong to -[Promptkit v0.1.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md). +[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md). diff --git a/docs/consumers/migrating-to-promptkit.md b/docs/consumers/migrating-to-promptkit.md index f89ff0f..183cf99 100644 --- a/docs/consumers/migrating-to-promptkit.md +++ b/docs/consumers/migrating-to-promptkit.md @@ -4,7 +4,7 @@ Scriptorium `v0.11.1` at `gitea.maximumdirect.net/eric/scriptorium` is the final release that provides -the former in-process Go framework. Promptkit `v0.1.0` at +the former in-process Go framework. Promptkit `v0.9.0` at `gitea.maximumdirect.net/eric/promptkit` is the destination for that framework API. Scriptorium `v0.12.0` and later provide the CLI and HTTP application only. @@ -19,7 +19,7 @@ Start from a clean consumer checkout and review the pending diff before committing it. Add the published Promptkit module: ```sh -go get gitea.maximumdirect.net/eric/promptkit@v0.1.0 +go get gitea.maximumdirect.net/eric/promptkit@v0.9.0 ``` For an ordinary consumer that imports the former root package under its @@ -51,14 +51,14 @@ go mod tidy go test ./... ``` -Confirm that `go.mod` selects Promptkit `v0.1.0` and that no Go file imports +Confirm that `go.mod` selects Promptkit `v0.9.0` and that no Go file imports the former Scriptorium package: ```sh test "$( go list -m -f '{{.Path}}@{{.Version}}' \ gitea.maximumdirect.net/eric/promptkit -)" = 'gitea.maximumdirect.net/eric/promptkit@v0.1.0' +)" = 'gitea.maximumdirect.net/eric/promptkit@v0.9.0' if git grep -n \ 'gitea.maximumdirect.net/eric/scriptorium' \ -- '*.go' @@ -73,20 +73,20 @@ fi Promptkit preserves the established engine, request, result, profile, source-option, model-client, artifact, validation-value, and public-error shapes where practical. Exact declarations and current behavior belong to the -tagged [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) +tagged [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) and Go source. Promptkit also includes migration-relevant public contracts that were not in Scriptorium `v0.11.1`: -- [`WithArtifactReader`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/engine.go#L96-L105) +- [`WithArtifactReader`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/engine.go#L182) and the - [`ArtifactReader` declaration](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/types.go#L129-L135) + [`ArtifactReader` declaration](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/types.go#L304) provide the artifact-reading extension described by the tagged - [extension-interface guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md#extension-interfaces). -- [`ErrProfileRequired` and `ErrAPIKeyEnvMissing`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/engine.go#L28-L40) + [extension-interface guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md#extension-interfaces). +- [`ErrProfileRequired` and `ErrAPIKeyEnvMissing`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/engine.go#L46-L61) provide the specific identities described by the tagged - [error guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md#errors). + [error guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md#errors). Use those tagged owners for exact signatures, wrapping guarantees, and extension behavior. diff --git a/docs/development.md b/docs/development.md index 4da4c53..1259c52 100644 --- a/docs/development.md +++ b/docs/development.md @@ -2,7 +2,7 @@ This is the contributor entry point for Scriptorium. Scriptorium is an application that consumes the public -[Promptkit v0.1.0 package](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md); +[Promptkit v0.9.0 package](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md); framework implementation work belongs in Promptkit. ## Initial Orientation @@ -27,12 +27,12 @@ tests. | HTTP routes, DTOs, limits, status mapping, or artifact policy | [HTTP API contract](api.md), [adapter internals](internal/adapters.md), and [source internals](internal/sources.md) | | Application configuration or precedence | [Configuration contract](config.md), [adapter internals](internal/adapters.md), and [source internals](internal/sources.md) | | Prepared-run presentation | [CLI contract](cli.md), [adapter internals](internal/adapters.md), and `internal/format` | -| Prompt, profile, schema, generation, or validation semantics | [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) and the [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) | -| OpenAI-compatible outbound behavior or timeout layering | [Promptkit integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md) | +| Prompt, profile, schema, generation, or validation semantics | [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md) and the [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) | +| OpenAI-compatible outbound behavior or timeout layering | [Promptkit integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md) | | Subprocess behavior | [Subprocess integration](integrations/subprocess.md) and [CLI contract](cli.md) | | Runtime operation or recovery | [Operations](operations.md) | | Release packaging or publication | The [release procedure](release.md), [hosted release workflow](../.woodpecker/release.yml), and [architecture policy](policy/architecture.md) | -| Examples or copyable assets | The owning Scriptorium contract, the relevant [Promptkit format contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md), and the related files under `examples/` | +| Examples or copyable assets | The owning Scriptorium contract, the relevant [Promptkit format contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md), and the related files under `examples/` | | Architecture decisions or future work | The [documentation policy](policy/documentation.md), relevant accepted ADRs, and relevant roadmap documents | Cross-project changes land and release in Promptkit before Scriptorium adopts diff --git a/docs/internal/adapters.md b/docs/internal/adapters.md index 5a50d4d..6c2cf58 100644 --- a/docs/internal/adapters.md +++ b/docs/internal/adapters.md @@ -9,7 +9,7 @@ own IO and presentation mechanics, not framework decisions. External contracts are canonical in the [CLI reference](../cli.md) and [HTTP API reference](../api.md). Promptkit's public engine contract is described by its tagged -[Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md). +[Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md). ## Components And Collaborators diff --git a/docs/internal/overview.md b/docs/internal/overview.md index 87d6799..71530ee 100644 --- a/docs/internal/overview.md +++ b/docs/internal/overview.md @@ -14,5 +14,5 @@ public behavior belongs in the linked contracts. | `internal/format` | Formats Promptkit prepared-run values for CLI text or JSON output. | [CLI contract](../cli.md), [adapter internals](adapters.md) | Framework implementation packages are provided by -[Promptkit v0.1.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) +[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) and are not part of this repository. diff --git a/docs/internal/sources.md b/docs/internal/sources.md index 925e999..2725d04 100644 --- a/docs/internal/sources.md +++ b/docs/internal/sources.md @@ -5,7 +5,7 @@ This document covers Scriptorium-owned source locations and the restricted HTTP artifact reader. Prompt, profile, schema, and ordinary artifact semantics are owned by the tagged -[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md). +[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md). ## Application Source Locations diff --git a/docs/operations.md b/docs/operations.md index ecf551b..d4defd8 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -9,7 +9,7 @@ fields, or HTTP wire behavior. - [CLI reference](cli.md): commands, output destinations, and exit codes. - [Configuration reference](config.md): application settings, source locations, defaults, and credential mapping. -- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md): +- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md): prompt, profile, schema, execution-setting, and framework credential contracts. - [HTTP API reference](api.md): route, request/response schema, status codes, diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index dfa1082..f796bc9 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -10,7 +10,7 @@ Scriptorium is an executable application with three entry paths: CLI `run`, CLI root Go package. The application consumes -[Promptkit v0.1.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) +[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md) through its supported root package. Promptkit owns prompt execution, preparation, source formats, built-in profiles, model-client behavior, and validation. Scriptorium owns application configuration, executable adapters, @@ -33,6 +33,7 @@ gitea.maximumdirect.net/eric/promptkit - Retained application packages may import Promptkit's root package. - They must not import Promptkit `internal` packages. +- They must not import Promptkit catalog modules directly. - They must not import the removed Scriptorium root facade or recreate former framework package families. - Adapter-owned interfaces use Promptkit public values when a consumer-side @@ -54,9 +55,9 @@ invariants. - `internal/defaults` owns Scriptorium application and HTTP defaults only. - `internal/format` owns deterministic prepared-run text and JSON presentation. - Promptkit owns framework orchestration and contracts. Its - [format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) + [format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md) and - [outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md) + [outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md) are canonical. ## HTTP Artifact Security Boundary diff --git a/docs/release.md b/docs/release.md index 37ae9f4..89b9ed5 100644 --- a/docs/release.md +++ b/docs/release.md @@ -103,7 +103,7 @@ test "$( )" = 'gitea.maximumdirect.net/eric/scriptorium 1.25.5' ``` -Require Promptkit `v0.1.0` as both the direct module-graph edge and the selected +Require Promptkit `v0.9.0` as both the direct module-graph edge and the selected module version: ```sh @@ -117,11 +117,11 @@ direct_promptkit=$( ' ) test "$direct_promptkit" = \ - 'gitea.maximumdirect.net/eric/promptkit@v0.1.0' + 'gitea.maximumdirect.net/eric/promptkit@v0.9.0' test "$( GOWORK=off go list -m -f '{{.Path}}@{{.Version}}' \ gitea.maximumdirect.net/eric/promptkit -)" = 'gitea.maximumdirect.net/eric/promptkit@v0.1.0' +)" = 'gitea.maximumdirect.net/eric/promptkit@v0.9.0' GOWORK=off go list -m all ``` diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index b9c51b2..74b257b 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -31,6 +31,8 @@ stage's completion conditions are unmet. ## Stage 1: Adopt The Promptkit v0.9.0 Compatibility Baseline +**Completion: Complete.** + Make the released dependency the build baseline before adding new application surface area. diff --git a/go.mod b/go.mod index 8a7fa2f..0856501 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ module gitea.maximumdirect.net/eric/scriptorium go 1.25.5 require ( - gitea.maximumdirect.net/eric/promptkit v0.1.0 + gitea.maximumdirect.net/eric/promptkit v0.9.0 gopkg.in/yaml.v3 v3.0.1 ) require ( + gitea.maximumdirect.net/eric/promptkit-backend-openrouter v1.0.0 // indirect + gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome v1.0.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 3c26d56..c99b921 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ -gitea.maximumdirect.net/eric/promptkit v0.1.0 h1:vuKeBxkiY8E54LRFbLQFjlJJCiOfMvB1++DYBCrD/ug= -gitea.maximumdirect.net/eric/promptkit v0.1.0/go.mod h1:R95NM6fbMDGDC0/UomgnSBP6ui2ns+8SZb8bESNvrDQ= +gitea.maximumdirect.net/eric/promptkit v0.9.0 h1:IpvDRC8L6xRxQ9hpuyKOmMc5b6MeLTKYyx+h1YAjy08= +gitea.maximumdirect.net/eric/promptkit v0.9.0/go.mod h1:oMJ/WUJImUtwJ5e+6MAGECPYAErAkOaKel0G+3T/b4E= +gitea.maximumdirect.net/eric/promptkit-backend-openrouter v1.0.0 h1:lc062euk2qseO//D762i3JaFyulDNML3eQQX7DkYTho= +gitea.maximumdirect.net/eric/promptkit-backend-openrouter v1.0.0/go.mod h1:AIa7kAu2mfrRQgcspe4L+DW51WqgnALQT60lqkEywJI= +gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome v1.0.0 h1:j9YY7wsTVjzke2kHH4YAzpU0oUpM+x+nXwl1IeS+2eg= +gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome v1.0.0/go.mod h1:4RNS+LILDg4JbS4Ts9Lwy1C92wauXJIbeQaalps4Koo= 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/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= diff --git a/internal/adapter/dependency_test.go b/internal/adapter/dependency_test.go index e4a614d..573c93a 100644 --- a/internal/adapter/dependency_test.go +++ b/internal/adapter/dependency_test.go @@ -14,8 +14,10 @@ import ( ) const ( - scriptoriumModulePath = "gitea.maximumdirect.net/eric/scriptorium" - promptkitInternalPath = "gitea.maximumdirect.net/eric/promptkit/internal" + scriptoriumModulePath = "gitea.maximumdirect.net/eric/scriptorium" + promptkitInternalPath = "gitea.maximumdirect.net/eric/promptkit/internal" + promptkitOpenRouterCatalogPath = "gitea.maximumdirect.net/eric/promptkit-backend-openrouter" + promptkitRakestrawhomeCatalogPath = "gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome" ) var ( @@ -120,6 +122,24 @@ func TestForbiddenImportScannerDetectsPromptkitInternalPackages(t *testing.T) { } } +func TestForbiddenImportScannerDetectsPromptkitCatalogPackages(t *testing.T) { + for _, importPath := range []string{ + promptkitOpenRouterCatalogPath, + promptkitRakestrawhomeCatalogPath, + } { + t.Run(importPath, func(t *testing.T) { + root := t.TempDir() + sourcePath := writeGoSource(t, root, "nested/consumer/catalog.go", importPath) + + violations, err := findForbiddenProductionImports(root) + if err != nil { + t.Fatalf("scan source fixture: %v", err) + } + assertSingleViolation(t, violations, sourcePath, importPath) + }) + } +} + func TestForbiddenImportScannerAllowsRetainedApplicationPackages(t *testing.T) { root := t.TempDir() sourcePath := filepath.Join(root, "nested/consumer/application.go") @@ -201,6 +221,12 @@ func isForbiddenProductionImport(importPath string) bool { if importPath == promptkitInternalPath || strings.HasPrefix(importPath, promptkitInternalPath+"/") { return true } + if importPath == promptkitOpenRouterCatalogPath || strings.HasPrefix(importPath, promptkitOpenRouterCatalogPath+"/") { + return true + } + if importPath == promptkitRakestrawhomeCatalogPath || strings.HasPrefix(importPath, promptkitRakestrawhomeCatalogPath+"/") { + return true + } for _, root := range removedFrameworkPackageRoots { if importPath == root || strings.HasPrefix(importPath, root+"/") { return true diff --git a/internal/adapter/http/dto.go b/internal/adapter/http/dto.go index 693034f..bd25e91 100644 --- a/internal/adapter/http/dto.go +++ b/internal/adapter/http/dto.go @@ -28,7 +28,7 @@ type modelOverrideRequestDTO struct { TopP *float64 `json:"top_p,omitempty"` TimeoutSeconds *int `json:"timeout_seconds,omitempty"` ServiceTier string `json:"service_tier,omitempty"` - ReasoningEffort string `json:"reasoning_effort,omitempty"` + ReasoningEffort *string `json:"reasoning_effort,omitempty"` APIKeyEnv string `json:"api_key_env,omitempty"` ExtraParams map[string]any `json:"extra_params,omitempty"` } diff --git a/internal/adapter/http/handler_test.go b/internal/adapter/http/handler_test.go index b80ba59..d350509 100644 --- a/internal/adapter/http/handler_test.go +++ b/internal/adapter/http/handler_test.go @@ -365,10 +365,12 @@ func TestHandlerModelOverrideMapsAllSupportedExecutionFields(t *testing.T) { if got.Endpoint != "http://override/v1" || got.Model != "override-model" || got.ServiceTier != "flex" || - got.ReasoningEffort != "medium" || got.APIKeyEnv != "SCRIPTORIUM_API_KEY" { t.Fatalf("unexpected mapped execution target: %+v", got) } + if got.ReasoningEffort == nil || *got.ReasoningEffort != "medium" { + t.Fatalf("unexpected mapped reasoning_effort: %#v", got.ReasoningEffort) + } if got.Temperature == nil || *got.Temperature != 0.6 { t.Fatalf("unexpected mapped temperature: %#v", got.Temperature) } @@ -386,6 +388,46 @@ func TestHandlerModelOverrideMapsAllSupportedExecutionFields(t *testing.T) { } } +func TestHandlerModelOverridePreservesReasoningEffortPresence(t *testing.T) { + tests := []struct { + name string + model string + wantPresent bool + wantValue string + }{ + {name: "omitted", model: `{}`}, + {name: "explicit empty", model: `{"reasoning_effort":""}`, wantPresent: true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := &fakeRunner{result: &promptkit.RunResult{ + Artifact: promptkit.Artifact{Body: []byte("ok")}, + Validation: promptkit.ValidationResult{Status: promptkit.ValidationPassed, Mode: promptkit.ValidationBasic, IsValid: true}, + EffectiveModelParams: promptkit.ExecutionTarget{Endpoint: "http://llm/v1", Model: "m1"}, + }} + h := NewHandler(r) + + req := httptest.NewRequest(http.MethodPost, "/v1/runs", bytes.NewBufferString(`{"prompt_id":"prompt-1","inputs":{"transcript":{"type":"file","uri":"./t.md"}},"model":`+tc.model+`}`)) + w := httptest.NewRecorder() + h.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("expected 200, got %d body=%s", w.Code, w.Body.String()) + } + if r.last.Execution == nil { + t.Fatal("expected execution override") + } + if (r.last.Execution.ReasoningEffort != nil) != tc.wantPresent { + t.Fatalf("unexpected reasoning_effort presence: %#v", r.last.Execution.ReasoningEffort) + } + if tc.wantPresent && *r.last.Execution.ReasoningEffort != tc.wantValue { + t.Fatalf("unexpected reasoning_effort: got %q want %q", *r.last.Execution.ReasoningEffort, tc.wantValue) + } + }) + } +} + func TestHandlerModelOverrideAcceptsJSONCompatibleExtraParams(t *testing.T) { r := &fakeRunner{result: &promptkit.RunResult{ Artifact: promptkit.Artifact{Body: []byte("ok")},