Adopt Promptkit v0.11 and maintained catalog profiles

This commit is contained in:
2026-09-26 15:24:55 +00:00
parent 5c3b0cf4f6
commit 2a06a911bc
16 changed files with 180 additions and 62 deletions

View File

@@ -6,7 +6,7 @@ OpenAI-compatible model endpoints, and returns generated output with validation
metadata.
The application uses
[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/)
[Promptkit v0.11.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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.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)
- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md)
- [Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md)
## Examples

View File

@@ -65,11 +65,13 @@ 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.9.0/docs/formats.md).
[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md).
Explicit zero values for the numeric fields are overrides; zero
`timeout_seconds` disables the per-generation deadline only, retaining the
`timeout_seconds` disables the per-attempt 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.9.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation).
the [Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation).
Each built-in transient retry gets a fresh generation timeout; the caller's
request context remains the outer cancellation boundary.
Raw API-key values are not accepted. `api_key` and any other unknown model
field cause `400 invalid_json`.

View File

@@ -69,12 +69,14 @@ Deprecated aliases: `--prompt-id` for `--prompt`, and `--profile-id` for
`--profile`.
Omitted numeric runtime flags preserve the selected effective value; explicit
zero values override it. `--timeout 0s` disables the per-generation deadline
zero values override it. `--timeout 0s` disables the per-attempt generation deadline
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.9.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation).
[Promptkit outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/integrations/openai-compatible-chat.md#timeout-and-cancellation).
With the built-in client, each transient retry gets a fresh generation timeout;
this flag does not limit the complete run.
There is no raw API-key flag. Use `--api-key-env`.

View File

@@ -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.9.0 format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md).
[Promptkit v0.11.0 format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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).
@@ -86,13 +86,20 @@ parse those framework file formats.
contracts.
See the
[tagged Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md)
[tagged Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md)
for all of those definitions. The files under
[`examples/prompts`](../examples/prompts/),
[`examples/profiles`](../examples/profiles/), and
[`examples/schemas`](../examples/schemas/) are maintained Scriptorium
application inputs using that tagged format.
Promptkit supplies the opt-in profile IDs `promptkit-openrouter-standard` and
`promptkit-openrouter-auto`. They can be selected as a prompt default or request
profile, and custom profile sources retain precedence. Their effective model
settings may change with a catalog upgrade; use a complete application-owned
profile when fixed settings are required. See the tagged format reference for
the maintained-profile contract.
## Credentials And Outbound Behavior
Scriptorium maps `--api-key-env` and HTTP `model.api_key_env` into Promptkit
@@ -113,8 +120,15 @@ 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 built-in client now makes up to two additional attempts for eligible
transient HTTP statuses by default. This can increase latency, request count,
and cost. Scriptorium currently uses that upstream default without an
application-level retry setting. Each initial or repair generation has its own
transient budget; an injected client retains its own retry behavior. The tagged
integration contract owns eligibility and timing.
Promptkit's
[OpenAI-compatible integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md)
[OpenAI-compatible integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/integrations/openai-compatible-chat.md)
defines outbound authentication, provider request mapping, transport limits,
and timeout layering.
@@ -123,4 +137,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.9.0/docs/formats.md)
- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md)

View File

@@ -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.9.0/docs/consumers/pkg-promptkit.md)
[Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md).
[Promptkit v0.11.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md).

View File

@@ -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.9.0` at
the former in-process Go framework. Promptkit `v0.11.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.9.0
go get gitea.maximumdirect.net/eric/promptkit@v0.11.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.9.0` and that no Go file imports
Confirm that `go.mod` selects Promptkit `v0.11.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.9.0'
)" = 'gitea.maximumdirect.net/eric/promptkit@v0.11.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.9.0/docs/consumers/pkg-promptkit.md)
tagged [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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.9.0/engine.go#L182)
- [`WithArtifactReader`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/engine.go#L169-L174)
and the
[`ArtifactReader` declaration](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/types.go#L304)
[`ArtifactReader` declaration](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/types.go#L315)
provide the artifact-reading extension described by the tagged
[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)
[extension-interface guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md#extension-interfaces).
- [`ErrProfileRequired` and `ErrAPIKeyEnvMissing`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/engine.go#L33-L48)
provide the specific identities described by the tagged
[error guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md#errors).
[error guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md#handle-errors).
Use those tagged owners for exact signatures, wrapping guarantees, and
extension behavior.

View File

@@ -2,7 +2,7 @@
This is the contributor entry point for Scriptorium. Scriptorium is an
application that consumes the public
[Promptkit v0.9.0 package](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md);
[Promptkit v0.11.0 package](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md);
framework implementation work belongs in Promptkit.
## Initial Orientation
@@ -28,12 +28,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.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) |
| Prompt, profile, schema, generation, or validation semantics | [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md) and the [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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.11.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 policy](policy/release.md), [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.9.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.11.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

View File

@@ -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.9.0/docs/consumers/pkg-promptkit.md).
[Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md).
## Components And Collaborators

View File

@@ -14,5 +14,5 @@ public behavior belongs in the linked contracts.
| `internal/format` | Formats Promptkit prepared-run and prompt/profile inspection values for CLI text or JSON output. | [CLI contract](../cli.md), [adapter internals](adapters.md) |
Framework implementation packages are provided by
[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md)
[Promptkit v0.11.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/consumers/pkg-promptkit.md)
and are not part of this repository.

View File

@@ -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.9.0/docs/formats.md).
[Promptkit format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md).
## Application Source Locations

View File

@@ -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.9.0/docs/formats.md):
- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md):
prompt, profile, schema, execution-setting, and framework credential
contracts.
- [HTTP API reference](api.md): route, request/response schema, status codes,
@@ -34,6 +34,13 @@ schema sources that follow the tagged framework formats. For an HTTP deployment
that accepts file artifacts, use a dedicated, narrow artifact directory rather
than a general-purpose or sensitive filesystem tree.
When upgrading existing definitions, review selected profile IDs.
`deepseek-3-2`, `deepseek-4-flash`, and `deepseek-4-pro` were removed from the
selected catalog. Choose an available catalog profile, one of Promptkit's
maintained names, or a complete application-owned profile. New DeepSeek names
are not aliases for the removed ones; see the
[v0.10 migration guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.10.0/docs/releases/v0.10.0.md).
Run Scriptorium under an identity that can:
- read only the prompt, profile, schema, and allowed input-artifact paths it
@@ -102,6 +109,16 @@ runs. When admission is exhausted, HTTP returns `503 capacity_exceeded` without
retry timing; callers choose any retry policy that is safe for another model
call.
Promptkit's built-in client now allows two additional attempts for eligible
transient provider statuses by default. Account for added calls, latency, and
cost when planning capacity. Each repair generation has its own transient
budget, separate from the structural repair count. The current Scriptorium
interfaces use this upstream retry default. Existing generation timeouts apply
per attempt, while the caller context covers the complete operation. Provider
`Retry-After` timing can exceed Promptkit's ordinary backoff cap; consult the
[outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/integrations/openai-compatible-chat.md)
for details.
Before increasing a limit:
1. measure representative input, generated-output, and optional raw-output

View File

@@ -25,7 +25,7 @@ The `inspect` command has prompt and profile modes. Scriptorium does not expose
a reusable root Go package.
The application consumes
[Promptkit v0.9.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/consumers/pkg-promptkit.md)
[Promptkit v0.11.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.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,
@@ -86,9 +86,9 @@ vendored Promptkit implementation, or unpublished dependency assumptions.
- `internal/format` owns deterministic prepared-run and definition-inspection
text and JSON presentation.
- Promptkit owns framework orchestration and contracts. Its
[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/formats.md)
[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/formats.md)
and
[outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.9.0/docs/integrations/openai-compatible-chat.md)
[outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.0/docs/integrations/openai-compatible-chat.md)
are canonical.
## HTTP Artifact Security Boundary

View File

@@ -2,8 +2,8 @@
## Status And Authority
Planned on 2026-09-26; no stage in this plan is implemented yet. Execute Stage 1
through Stage 10 in order. Each stage is intended to fit one focused
Planned on 2026-09-26. Execute Stage 1 through Stage 10 in order; each section
records its own completion status. Each stage is intended to fit one focused
gpt-5.6-terra implementation task, including its tests and documentation.
The [feature roadmap](upgrade-kit.md) owns desired scope and end state.
@@ -70,7 +70,7 @@ No stage authorizes a tag, push, publication, or changes to historical releases.
## Stage 1: Adopt The Released Dependency And Catalog Baseline
**Status: Pending.**
**Status: Complete.**
1. Upgrade `gitea.maximumdirect.net/eric/promptkit` to v0.11.0 and tidy the
module graph. Review the resulting go.mod/go.sum changes. Expected indirect

6
go.mod
View File

@@ -3,13 +3,13 @@ module gitea.maximumdirect.net/eric/scriptorium
go 1.25.5
require (
gitea.maximumdirect.net/eric/promptkit v0.9.0
gitea.maximumdirect.net/eric/promptkit v0.11.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
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1 // indirect
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
golang.org/x/text v0.14.0 // indirect
)

12
go.sum
View File

@@ -1,9 +1,9 @@
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=
gitea.maximumdirect.net/eric/promptkit v0.11.0 h1:x7JguOUiInPVXK0GEitjyoRFqqvcuSTjYUvqJ+whtik=
gitea.maximumdirect.net/eric/promptkit v0.11.0/go.mod h1:0zEBVlJJC+ldDdXazAgybYBXNSe74vwFx5dyOuSos/w=
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1 h1:S2/Q/JDE+m8Ca3pDhAjVbfYrdlEhs9blj0STgNopHo0=
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1/go.mod h1:a3VBbh9oaGXD6ruxhtwHj+AWW6DY/SSyby1QtMmYSUo=
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0 h1:Y0EXc3eh12eKW2NrOviVqdk3oBo6UUjopt1YAa1B3Oc=
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0/go.mod h1:mtgD1E0SGm0e/I8Ffhz+AYX7GN7RKUWJXehNFIKHs4Y=
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=

View File

@@ -1201,9 +1201,9 @@ func TestInspectionParsersPreserveExplicitEmptyConfigPath(t *testing.T) {
}
}
func TestPromptkitV09DefinitionsRenderThroughCLI(t *testing.T) {
fixtureRoot := promptkitV09FixtureRoot(t)
configPath := writePromptkitV09Config(t, fixtureRoot, true)
func TestPromptkitDefinitionsRenderThroughCLI(t *testing.T) {
fixtureRoot := definitionFixtureRoot(t)
configPath := writeDefinitionFixtureConfig(t, fixtureRoot, true)
inputPath := filepath.Join(fixtureRoot, "inputs", "source.md")
code, stdout, stderr := runCLICommand(t, renderCommand, []string{
@@ -1258,9 +1258,9 @@ func TestPromptkitV09DefinitionsRenderThroughCLI(t *testing.T) {
}
}
func TestPromptkitV09PromptInspectionSelectsVersionsAndContracts(t *testing.T) {
fixtureRoot := promptkitV09FixtureRoot(t)
configPath := writePromptkitV09Config(t, fixtureRoot, true)
func TestPromptkitPromptInspectionSelectsVersionsAndContracts(t *testing.T) {
fixtureRoot := definitionFixtureRoot(t)
configPath := writeDefinitionFixtureConfig(t, fixtureRoot, true)
tests := []struct {
promptID string
version string
@@ -1296,12 +1296,12 @@ func TestPromptkitV09PromptInspectionSelectsVersionsAndContracts(t *testing.T) {
}
}
func TestPromptkitV09ProfileInspectionResolvesSupportedTargets(t *testing.T) {
func TestPromptkitProfileInspectionResolvesSupportedTargets(t *testing.T) {
const secret = "sentinel-profile-secret"
t.Setenv("FIXTURE_PROFILE_API_KEY", secret)
fixtureRoot := promptkitV09FixtureRoot(t)
configPath := writePromptkitV09Config(t, fixtureRoot, true)
fixtureRoot := definitionFixtureRoot(t)
configPath := writeDefinitionFixtureConfig(t, fixtureRoot, true)
tests := []struct {
name string
profileID string
@@ -1311,7 +1311,7 @@ func TestPromptkitV09ProfileInspectionResolvesSupportedTargets(t *testing.T) {
}{
{name: "inherited custom backend", profileID: "custom-derived", wantBackend: "fixture-custom", wantModel: "fixture-derived-model", wantAPIKeyEnv: "FIXTURE_PROFILE_API_KEY"},
{name: "endpoint only", profileID: "endpoint-only", wantModel: "fixture-endpoint-model"},
{name: "built in", profileID: "deepseek-4-flash", wantBackend: "openrouter", wantModel: "deepseek/deepseek-v4-flash", wantAPIKeyEnv: "OPENROUTER_API_KEY"},
{name: "built in", profileID: "promptkit-openrouter-auto", wantBackend: "openrouter", wantModel: "openrouter/auto", wantAPIKeyEnv: "OPENROUTER_API_KEY"},
}
for _, tc := range tests {
@@ -1340,7 +1340,7 @@ func TestPromptkitV09ProfileInspectionResolvesSupportedTargets(t *testing.T) {
})
}
configWithoutPromptDir := writePromptkitV09Config(t, fixtureRoot, false)
configWithoutPromptDir := writeDefinitionFixtureConfig(t, fixtureRoot, false)
code, _, stderr := runCLICommand(t, inspectCommand, []string{
"profile",
"--config", configWithoutPromptDir,
@@ -1352,9 +1352,92 @@ func TestPromptkitV09ProfileInspectionResolvesSupportedTargets(t *testing.T) {
}
}
func TestMaintainedProfilesResolveAcrossSelectionAndSourcePrecedence(t *testing.T) {
promptDir := t.TempDir()
profileDir := t.TempDir()
writePromptDefinition(t, promptDir, "maintained.yaml", `id: maintained
version: "1.0.0"
default_profile: promptkit-openrouter-standard
messages:
- role: user
content: Hello
output:
format: text
validation_mode: none
`)
configPath := writeAppConfigFile(t, fmt.Sprintf("prompt_dir: %q\nprofile_dir: %q\n", promptDir, profileDir))
for _, profileID := range []string{"promptkit-openrouter-standard", "promptkit-openrouter-auto"} {
t.Run(profileID+" inspection", func(t *testing.T) {
code, stdout, stderr := runCLICommand(t, inspectCommand, []string{"profile", "--config", configPath, "--profile", profileID, "--format", "json"})
if code != ExitOK {
t.Fatalf("inspect %s: code=%d stderr=%q", profileID, code, stderr)
}
var inspection renderformat.ProfileInspection
if err := json.Unmarshal([]byte(stdout), &inspection); err != nil {
t.Fatal(err)
}
if inspection.ProfileID != profileID || inspection.EffectiveModelParams.BackendID != "openrouter" || inspection.EffectiveModelParams.Model == "" {
t.Fatalf("maintained profile did not resolve: %+v", inspection)
}
if profileID == "promptkit-openrouter-auto" && inspection.EffectiveModelParams.Model != "openrouter/auto" {
t.Fatalf("unexpected auto target: %+v", inspection.EffectiveModelParams)
}
})
}
for _, tc := range []struct {
name string
selection []string
wantID string
}{
{name: "prompt default", wantID: "promptkit-openrouter-standard"},
{name: "explicit selection", selection: []string{"--profile", "promptkit-openrouter-auto"}, wantID: "promptkit-openrouter-auto"},
} {
t.Run(tc.name, func(t *testing.T) {
args := append([]string{"--config", configPath, "--prompt", "maintained", "--format", "json"}, tc.selection...)
code, stdout, stderr := runCLICommand(t, renderCommand, args)
if code != ExitOK {
t.Fatalf("render: code=%d stderr=%q", code, stderr)
}
var rendered struct {
SelectedProfileID string `json:"selected_profile_id"`
SelectedBackendID string `json:"selected_backend_id"`
}
if err := json.Unmarshal([]byte(stdout), &rendered); err != nil {
t.Fatal(err)
}
if rendered.SelectedProfileID != tc.wantID || rendered.SelectedBackendID != "openrouter" {
t.Fatalf("unexpected selection: %+v", rendered)
}
})
}
writePromptDefinition(t, profileDir, "derived.yaml", "id: derived-maintained\nbase_profile: promptkit-openrouter-standard\nmodel: fixture-inherited-model\n")
writePromptDefinition(t, profileDir, "replacement.yaml", "id: promptkit-openrouter-auto\nbackend: openrouter\nmodel: fixture-override-model\n")
for _, tc := range []struct{ id, model string }{
{id: "derived-maintained", model: "fixture-inherited-model"},
{id: "promptkit-openrouter-auto", model: "fixture-override-model"},
} {
t.Run(tc.id+" source", func(t *testing.T) {
code, stdout, stderr := runCLICommand(t, inspectCommand, []string{"profile", "--config", configPath, "--profile", tc.id, "--format", "json"})
if code != ExitOK {
t.Fatalf("inspect: code=%d stderr=%q", code, stderr)
}
var inspection renderformat.ProfileInspection
if err := json.Unmarshal([]byte(stdout), &inspection); err != nil {
t.Fatal(err)
}
if inspection.EffectiveModelParams.BackendID != "openrouter" || inspection.EffectiveModelParams.Model != tc.model {
t.Fatalf("unexpected effective target: %+v", inspection)
}
})
}
}
func TestProfileInspectionHonorsDirectoryPrecedenceOutputAndFailures(t *testing.T) {
fixtureRoot := promptkitV09FixtureRoot(t)
configPath := writePromptkitV09Config(t, fixtureRoot, true)
fixtureRoot := definitionFixtureRoot(t)
configPath := writeDefinitionFixtureConfig(t, fixtureRoot, true)
overrideDir := t.TempDir()
writeProfileFile(t, overrideDir, "custom-derived", "http://127.0.0.1:9000/v1", "override-model")
outPath := filepath.Join(t.TempDir(), "inspection.json")
@@ -1971,7 +2054,7 @@ func runCLICommand(t *testing.T, command func([]string, io.Writer, io.Writer) in
return code, stdout.String(), stderr.String()
}
func promptkitV09FixtureRoot(t *testing.T) string {
func definitionFixtureRoot(t *testing.T) string {
t.Helper()
root, err := filepath.Abs(filepath.Join("..", "..", "..", "testdata", "promptkit-v0.9"))
if err != nil {
@@ -1983,7 +2066,7 @@ func promptkitV09FixtureRoot(t *testing.T) string {
return root
}
func writePromptkitV09Config(t *testing.T, fixtureRoot string, includeSources bool) string {
func writeDefinitionFixtureConfig(t *testing.T, fixtureRoot string, includeSources bool) string {
t.Helper()
sources := ""
if includeSources {