diff --git a/README.md b/README.md index 1f81c21..aaa5379 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,19 @@ Notarius is a Go CLI for extracting structured artifacts from source material with explicit, configurable pipeline modules. The current implementation reads Seriatim transcript JSON, chunks the source -units, extracts D&D spell-cast artifacts with an OpenAI-compatible LLM, and -writes JSON output plus diagnostics for each run. +units, extracts D&D spell-cast artifacts with a Scriptorium-backed LLM runtime, +and writes JSON output plus diagnostics for each run. ```sh -NOTARIUS_LLM_DEFAULT_BASE_URL=http://127.0.0.1:8080/v1 \ -NOTARIUS_LLM_DEFAULT_MODEL=your-model \ +OPENROUTER_API_KEY=... \ go run ./cmd/notarius run dnd-session \ --config examples/dnd-spells.config.yml \ --input examples/seriatim-minimal-transcript.json ``` -If the provider requires authentication, set -`NOTARIUS_LLM_DEFAULT_API_KEY` in the environment before running the command. -Outputs are written under `./notarius-output//` unless `--output-dir` -is provided. +The maintained example uses Scriptorium's built-in `mistral-small-3` profile, +which reads `OPENROUTER_API_KEY`. Outputs are written under +`./notarius-output//` unless `--output-dir` is provided. Useful references: @@ -27,7 +25,6 @@ Useful references: - [Operations](docs/operations.md) - [Troubleshooting](docs/troubleshooting.md) - [Seriatim input contract](docs/integrations/seriatim.md) -- [OpenAI-compatible provider contract](docs/integrations/openai-compatible.md) - [JSON output contract](docs/integrations/json-output.md) - [D&D spell artifact contract](docs/integrations/dnd-spell-artifacts.md) - [Developer workflow](docs/policy/development.md) diff --git a/docs/cli.md b/docs/cli.md index a12ae85..9446733 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -6,21 +6,22 @@ interface. ## Quick Run ```sh -NOTARIUS_LLM_DEFAULT_BASE_URL=http://127.0.0.1:8080/v1 \ -NOTARIUS_LLM_DEFAULT_MODEL=your-model \ +OPENROUTER_API_KEY=... \ go run ./cmd/notarius run dnd-session \ --config examples/dnd-spells.config.yml \ --input examples/seriatim-minimal-transcript.json ``` -Set `NOTARIUS_LLM_DEFAULT_API_KEY` if the OpenAI-compatible provider requires -a bearer token. +The maintained example uses prompt defaults and Scriptorium's built-in +`mistral-small-3` profile, which reads `OPENROUTER_API_KEY`. To use another +endpoint or model, configure a Scriptorium profile source and select its profile +ID in config or with `--llm-profile`. ## Commands ```text notarius help -notarius run --input path/to/source.json [--config path/to/config.yml] [--only lane-a,lane-b] [--reference selector=path] [--without-reference selector] +notarius run --input path/to/source.json [--config path/to/config.yml] [--only lane-a,lane-b] [--session-id id] [--reference selector=path] [--without-reference selector] notarius config validate --config path/to/config.yml [--pipeline pipeline-id] [--only lane-a,lane-b] notarius pipelines list --config path/to/config.yml [--json] ``` @@ -44,8 +45,10 @@ Flags: Defaults to `./notarius-output`. - `--diagnostics-dir path`: diagnostics work directory override for this invocation. -- `--llm-profile id`: override every effective module binding to use one LLM - profile. +- `--llm-profile id`: override every effective LLM-capable module binding to + use one Scriptorium profile ID. +- `--session-id id`: pass a stable prompt session identifier through LLM-backed + module calls. - `--reference selector=path`: bind a reference path to a chunk, extractor, or normalizer reference slot. Repeatable. - `--without-reference selector`: remove a configured optional reference binding. @@ -122,12 +125,19 @@ go run ./cmd/notarius run dnd-session \ --without-reference glossary ``` +Use `--session-id` when an external orchestrator needs all prompt calls from one +run to share an identifier: + +```sh +go run ./cmd/notarius run dnd-session \ + --config examples/dnd-spells.config.yml \ + --input examples/seriatim-minimal-transcript.json \ + --session-id campaign-17-session-04 +``` + For durable output, diagnostics, retention, and failure inspection, see [Operations](operations.md). -The current `run` command requires the resolved pipeline to use exactly one -distinct LLM profile after defaults and overrides are applied. - ## `config validate` `notarius config validate` loads and validates configuration. @@ -196,5 +206,5 @@ The production CLI currently registers these module keys: The production CLI does not currently register validator modules. -For YAML structure, defaults, environment overrides, and module binding syntax, -see [Configuration](config.md). +For YAML structure, Scriptorium profile sources, environment overrides, and +module binding syntax, see [Configuration](config.md). diff --git a/docs/config.md b/docs/config.md index daac6f8..25f0d07 100644 --- a/docs/config.md +++ b/docs/config.md @@ -2,7 +2,7 @@ This is the canonical reference for implemented Notarius configuration. -Notarius reads YAML config files with `version: 1`. File config is applied over +Notarius reads YAML config files with `version: 2`. File config is applied over built-in defaults, then environment overrides are applied. ## Discovery @@ -18,12 +18,7 @@ If none is available, the command fails with a config file not found error. ## Minimal Example ```yaml -version: 1 -llm_profiles: - default: - provider: openai-compatible - base_url: http://127.0.0.1:8080/v1 - model: your-model +version: 2 pipelines: dnd-session: input: seriatim @@ -43,25 +38,20 @@ The maintained fixture is [examples/dnd-spells.config.yml](../examples/dnd-spell ## Top-Level Fields -- `version`: required. The only supported value is `1`. -- `llm_profiles`: optional map of LLM profile IDs to profile settings. +- `version`: required. The only supported value is `2`. +- `scriptorium`: optional Scriptorium profile source settings. - `pipelines`: optional map of pipeline IDs to pipeline definitions. - `concurrency`: optional global concurrency settings. - `diagnostics`: optional diagnostics settings. -Unknown YAML fields are rejected. +Unknown YAML fields are rejected. The removed top-level `llm_profiles` field is +rejected; execution profiles now come from Scriptorium. ## Defaults Built-in defaults: ```yaml -llm_profiles: - default: - provider: openai-compatible - timeout: 600 - max_retries: 3 - max_concurrency: 1 concurrency: total_llm: 1 diagnostics: @@ -71,44 +61,52 @@ diagnostics: No pipelines are built in. A run requires a configured pipeline. -## LLM Profiles +If `scriptorium` is omitted, Notarius uses Scriptorium's built-in profile +catalog. Prompt definitions may also name default profile IDs. The current D&D +scene and spell prompts use Scriptorium prompt defaults when a module binding +does not set `llm_profile`. -Each `llm_profiles` entry may contain: +## Scriptorium Profiles -- `provider`: optional provider key. Empty means `openai-compatible`; any other - non-empty value must be `openai-compatible`. -- `base_url`: provider base URL. Required for actual LLM calls. -- `model`: provider model name. Required for actual LLM calls. -- `api_key_env`: environment variable name to read for the API key. -- `timeout`: request timeout as whole seconds or a Go-style duration string such - as `10m`. -- `max_retries`: retry count for provider calls. Must be zero or greater. -- `max_concurrency`: per-profile LLM concurrency. Must be zero or greater; when - zero, Notarius uses `concurrency.total_llm`. +`scriptorium` fields: -Raw API keys are not accepted as file config fields. Use `api_key_env` or an -environment override. +- `profile_dir`: optional directory containing Scriptorium profile YAML files. +- `profile_file`: optional Scriptorium profile YAML file. + +`profile_dir` and `profile_file` are mutually exclusive. Custom profiles +overlay Scriptorium built-in profiles by profile ID. + +Scriptorium profile files use Scriptorium's profile schema. A minimal profile +looks like: + +```yaml +id: local-fast +endpoint: http://127.0.0.1:8080/v1 +model: your-model +api_key_env: SCRIPTORIUM_API_KEY +timeout_seconds: 180 +``` + +Notarius does not accept raw API keys in Notarius config. For file-backed +Scriptorium profiles, store the environment variable name in `api_key_env` and +set that variable in the run environment. Scriptorium rejects raw `api_key` +fields in profile YAML. ## Environment Overrides These environment variables are applied after the config file: - `NOTARIUS_CONFIG`: config discovery path. -- `NOTARIUS_LLM_DEFAULT_API_KEY`: API key for the `default` LLM profile. -- `NOTARIUS_LLM_DEFAULT_BASE_URL`: base URL for the `default` LLM profile. -- `NOTARIUS_LLM_DEFAULT_MODEL`: model for the `default` LLM profile. -- `NOTARIUS_LLM_DEFAULT_TIMEOUT_SECONDS`: integer timeout seconds for the - `default` LLM profile. -- `NOTARIUS_LLM_DEFAULT_MAX_RETRIES`: integer retry count for the `default` LLM - profile. -- `NOTARIUS_LLM_DEFAULT_MAX_CONCURRENCY`: integer max concurrency for the - `default` LLM profile. - `NOTARIUS_TOTAL_LLM_CONCURRENCY`: integer global LLM concurrency. - `NOTARIUS_WORK_DIR`: diagnostics work directory. - `NOTARIUS_DIAGNOSTICS_RETENTION`: diagnostics retention mode. Integer environment values must parse as base-10 integers. +The removed `NOTARIUS_LLM_DEFAULT_*` variables are not read. Configure provider +endpoint, model, and credential environment variable names through Scriptorium +profiles. + ## Pipelines A pipeline defines the fixed Notarius workflow: @@ -152,10 +150,9 @@ directory. Materialized bound files must be UTF-8 text. Materialized reference provenance is recorded for chunk, extractor, and normalizer targets, and runtime reference content is passed to the target that declares the slot. Reference media types are inferred from file extensions, recorded as canonical base media -types, and checked only when a module declares -`AcceptedMediaTypes`; unknown extensions are recorded as -`application/octet-stream`. Reference content is not written to diagnostics, -logs, errors, or manifests. +types, and checked only when a module declares `AcceptedMediaTypes`; unknown +extensions are recorded as `application/octet-stream`. Reference content is not +written to diagnostics, logs, errors, or manifests. Pipeline-level `references` are defaults. They are valid when at least one eligible target in the full configured pipeline declares the slot, including @@ -199,7 +196,7 @@ bindings. They override pipeline-level defaults for slots declared by the chunk or normalizer module. Extractor-local references apply only to the extractor, and normalizer-local references apply only to the normalizer. -Stage-local reference fields use the same map shape at: +Target-local reference fields use the same map shape at: - `pipelines..chunk.references` - `pipelines..artifacts..extract.references` @@ -219,23 +216,22 @@ or object form: ```yaml chunk: - module: generic - llm_profile: default - options: - max_units: 50 + module: dnd/scenes + llm_profile: local-fast ``` Binding fields: - `module`: module key. -- `llm_profile`: optional LLM profile ID. Empty means `default`. +- `llm_profile`: optional Scriptorium profile ID. Empty or omitted lets the + Scriptorium prompt default select the profile. - `options`: optional module-specific settings. - `references`: optional reference bindings. Supported only for `chunk`, `extract`, and `normalize` bindings. `input`, `merge`, validator, and `output` bindings reject this field during validation. -The `--llm-profile` run flag overrides every effective module binding to use -one configured profile. +The `--llm-profile` run flag overrides every effective LLM-capable module +binding to use one Scriptorium profile ID. ## Implemented Production Modules @@ -256,7 +252,7 @@ The `generic` chunker accepts: `max_units`. The `dnd/scenes` chunker requires transcript source capabilities, calls the -configured structured LLM provider, and does not accept module options. +configured structured LLM runtime, and does not accept module options. The `dnd/spells` extractor declares optional text reference slots: @@ -285,11 +281,11 @@ invocation. Configuration validation checks: - supported config version and known YAML fields; +- mutually exclusive `scriptorium.profile_dir` and `scriptorium.profile_file`; - non-empty, non-duplicated IDs after trimming; -- supported LLM provider and non-negative profile limits; - positive global LLM concurrency; - supported diagnostics retention and non-empty work directory; -- module binding LLM profiles refer to configured profiles. +- stale removed fields such as `llm_profiles`. Pipeline resolution additionally checks: @@ -298,7 +294,7 @@ Pipeline resolution additionally checks: - selected lanes exist when `--only` is used; - required module keys are present; - module keys are registered for the expected slot; -- module capability requirements are satisfied. +- module capability requirements are satisfied; - bound reference slots are declared by selected chunk, extractor, or normalizer targets; - required reference slots are bound for selected targets. diff --git a/docs/integrations/json-output.md b/docs/integrations/json-output.md index 46c922a..cfff589 100644 --- a/docs/integrations/json-output.md +++ b/docs/integrations/json-output.md @@ -85,8 +85,8 @@ approved. ], "llm_profiles": [ { - "id": "default", - "provider": "openai-compatible", + "id": "mistral-small-3", + "provider": "scriptorium", "model": "configured-model" } ], diff --git a/docs/integrations/openai-compatible.md b/docs/integrations/openai-compatible.md deleted file mode 100644 index 48b4819..0000000 --- a/docs/integrations/openai-compatible.md +++ /dev/null @@ -1,128 +0,0 @@ -# OpenAI-Compatible Structured Output - -This document describes the external LLM provider contract implemented by the -production Notarius LLM client. - -## Provider - -- Provider key: `openai-compatible` -- HTTP method: `POST` -- Endpoint: `/chat/completions` -- Request body: JSON -- Response mode: chat completions with structured JSON schema output - -`base_url` is trimmed of trailing slashes before `/chat/completions` is -appended. Configure provider settings in [Configuration](../config.md). - -## Request - -The client sends a JSON object with: - -```json -{ - "model": "configured-model", - "messages": [ - { - "role": "system", - "content": "..." - }, - { - "role": "user", - "content": "..." - } - ], - "response_format": { - "type": "json_schema", - "json_schema": { - "name": "schema_name", - "strict": true, - "schema": {} - } - } -} -``` - -Implemented request behavior: - -- `model` comes from the structured completion request when set, otherwise from - the configured LLM profile. -- `messages` must be non-empty; each role and content must be non-empty after - trimming. -- `response_format.type` is always `json_schema`. -- `response_format.json_schema.strict` is always `true`. -- `response_format.json_schema.name` and `schema` come from the extractor or - validator making the call. - -If an API key is configured, the client sends: - -```text -Authorization: Bearer -``` - -The client always sends `Content-Type: application/json`. - -## Response - -The client expects a JSON response with at least one choice: - -```json -{ - "model": "provider-model", - "choices": [ - { - "message": { - "content": "{\"field\":\"value\"}" - } - } - ], - "usage": { - "prompt_tokens": 10, - "completion_tokens": 5, - "total_tokens": 15 - } -} -``` - -`choices[0].message.content` may be either: - -- a JSON string whose contents are valid JSON; or -- raw JSON. - -The decoded content is unmarshaled into the caller-provided structured output -target. If `usage` is present, prompt, completion, and total token counts are -copied into the completion response. - -## Errors And Retries - -The client validates base URL, model, response schema name, response schema -JSON, messages, and output target before or during the call. - -Retryable failures: - -- HTTP request failure; -- response body read failure; -- HTTP `429`; -- HTTP `5xx`; -- malformed provider response envelope; -- missing choices; -- missing, empty, or invalid assistant JSON content; -- structured-output decode failure. - -Non-retryable provider status codes include non-`429` `4xx` responses. - -Provider error bodies are parsed for `error.message` or `message` when present. -Configured API key values and bearer-token values are redacted from returned -provider errors. - -## Timeouts And Concurrency - -The configured profile timeout is applied per provider request when greater -than zero. Context cancellation is respected. - -The production CLI wraps the provider client with the LLM scheduler. Effective -concurrency is described in [LLM runtime internals](../internal/llm.md). - -## Limits - -This contract documents only the fields the implemented client sends and reads. -Provider-specific extensions are ignored unless they affect those fields. diff --git a/docs/internal/llm.md b/docs/internal/llm.md index 63a1cd5..7e4e6aa 100644 --- a/docs/internal/llm.md +++ b/docs/internal/llm.md @@ -21,13 +21,18 @@ Modules that call the LLM own their prompts, schemas, prompt IDs, validators, and domain-specific interpretation. Provider adapters should not contain domain-specific prompt logic. +Prompt input materials carry source or reference bytes with optional origin +metadata. The Scriptorium-backed runtime receives them as named artifacts rather +than rendered prompt strings owned by Notarius modules. + ## Production Client Construction `internal/cli` builds the production LLM client from the effective config: 1. collect production Scriptorium prompt and schema assets from module packages; 2. create a Scriptorium-backed structured client using effective Scriptorium - profile source settings; + profile source settings from `scriptorium.profile_dir` or + `scriptorium.profile_file`; 3. create a scheduler from global LLM concurrency; 4. wrap the client with `NewScheduledClient`; 5. let the runtime report non-secret profile manifest metadata after calls. @@ -42,8 +47,10 @@ profile ID before pipeline execution. Notarius prompt requests into Scriptorium `RunRequest` values. It: - validates the caller output target and prompt ID; -- converts `LLMInputMaterial` values into inline Scriptorium artifacts; -- passes `session_id` through Scriptorium variables when present; +- converts `LLMInputMaterial` values into inline Scriptorium artifacts, using a + single space for empty material so optional blank references remain explicit; +- passes `session_id` through Scriptorium variables and request metadata when + present; - sends explicit profile IDs only when the request supplies one; - lets Scriptorium render prompts, call the configured provider, and validate structured output; @@ -53,7 +60,9 @@ Notarius prompt requests into Scriptorium `RunRequest` values. It: Generated-output validation failures are returned as Notarius errors. Provider and runtime errors are wrapped with prompt context and bearer tokens are -redacted from error strings. +redacted from error strings. Prompt text, raw source input, reference content, +schema JSON, API keys, and bearer tokens are not added to default diagnostics or +run manifests. ## Scheduler diff --git a/docs/internal/modules.md b/docs/internal/modules.md index bacbb76..8ab87ed 100644 --- a/docs/internal/modules.md +++ b/docs/internal/modules.md @@ -40,12 +40,20 @@ uses references, pass them as prompt input materials through the structured LLM request. Prompt metadata hashes remain based on prompt asset source, not rendered reference bytes. -Chunk modules receive the structured LLM client through `contracts.ChunkRequest` -when they need model-backed chunking. The pipeline runner validates generic -chunk result invariants before extraction; module-owned policies may be stricter -but must stay within the module package. +LLM-backed modules own Scriptorium prompt definitions and response schemas in +their embedded assets. Module contracts should expose prompt IDs, versions, +input material names, and non-secret prompt/schema hashes through manifest +metadata; they should not expose Scriptorium public types through chunk, +extract, or normalize contracts. -Normalize modules receive the structured LLM client through +Chunk modules receive the structured LLM client, configured Scriptorium profile +ID, prompt session ID, and raw source input material through +`contracts.ChunkRequest` when they need model-backed chunking. The pipeline +runner validates generic chunk result invariants before extraction; module-owned +policies may be stricter but must stay within the module package. + +Normalize modules receive the structured LLM client, configured Scriptorium +profile ID, prompt session ID, and reference material through `contracts.NormalizeRequest` when they need model-backed reconciliation. ## `seriatim` Input @@ -91,9 +99,10 @@ Provides: Package: `internal/modules/chunk/dnd/scenes` The `dnd/scenes` chunker uses the structured LLM client to divide transcript -source units into coherent D&D scenes. It renders embedded prompts, loads the -embedded structured response schema, validates model-authored source-unit -boundaries, and converts each scene into a deterministic source chunk. +source units into coherent D&D scenes. It supplies the embedded Scriptorium +prompt ID, prompt version, transcript input material, response schema, and +session ID to the runtime; validates model-authored source-unit boundaries; and +converts each scene into a deterministic source chunk. Requires: @@ -123,10 +132,11 @@ text, or secrets. Package: `internal/modules/extract/dnd/spells` -The `dnd/spells` extractor owns D&D spell-cast artifact semantics. It renders -embedded prompts, loads the embedded structured response schema, calls the -structured LLM client, converts spell-cast responses into artifact candidates, -and supplies deterministic validators. +The `dnd/spells` extractor owns D&D spell-cast artifact semantics. It supplies +the embedded Scriptorium prompt ID, prompt version, transcript and reference +input materials, response schema, and session ID to the runtime; converts +spell-cast responses into artifact candidates; and supplies deterministic +validators. Requires: diff --git a/docs/internal/pipeline.md b/docs/internal/pipeline.md index 5a3cc07..b6c6ff3 100644 --- a/docs/internal/pipeline.md +++ b/docs/internal/pipeline.md @@ -23,7 +23,8 @@ before execution: - merge: `appendorder` - normalize: `noop` - output: `json` - - LLM profile: `default` + - LLM profile: empty, which lets Scriptorium prompt defaults choose a + profile. 4. The module catalog is checked for each bound module key. 5. Module capabilities are checked in workflow order. 6. A digest is calculated from the resolved pipeline without the digest field. @@ -54,13 +55,19 @@ empty bound files. Media-type acceptance is checked only when a slot declares manifests. The CLI writes provenance-only resolved reference diagnostics, and the run manifest records target-stage reference provenance separately from source digests. Runtime reference content is passed to the matching chunker, -extractor, or normalizer request. +extractor, or normalizer request. LLM-backed modules pass that material onward +as named Scriptorium prompt inputs. -Prompt bundles can declare reference slots and use `reference` and -`hasreference` template functions. Bundle loading validates string-literal slot -names against the declaration. Rendering receives a target reference set from the -caller; unbound optional slots render as empty strings, and `hasreference` -returns true only when at least one bound item has content. +The CLI carries raw input bytes into `pipeline.RunInput`. Input adapters parse +those bytes into the source document, while LLM-backed modules that need the +original transcript material can pass the same bytes as a prompt input with +origin metadata. The raw input payload is not written to manifests or default +diagnostics. + +The CLI also carries an optional run `session_id`. The runner makes it available +to chunk, extract, and normalize requests; LLM-backed modules forward it through +their structured completion requests so Scriptorium can include it in prompt +execution metadata. ## Registries And Module Specs diff --git a/docs/operations.md b/docs/operations.md index 0ae64cc..0d378d8 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -5,8 +5,8 @@ This is the canonical reference for operating implemented Notarius runs. ## Normal Run A run reads one source file, resolves one configured pipeline, calls the -configured OpenAI-compatible LLM profile, writes durable JSON output, and writes -diagnostics for inspection. +configured Scriptorium-backed LLM runtime, writes durable JSON output, and +writes diagnostics for inspection. ```sh go run ./cmd/notarius run dnd-session \ @@ -61,7 +61,7 @@ Implemented diagnostics artifacts: - `invocation.json`: command metadata such as operation, config path, input path, selected lanes, run ID, and pipeline digest when available. -- `effective-config.json`: resolved config with API keys redacted. +- `effective-config.json`: resolved config without raw API keys. - `resolved-pipeline.json`: resolved module bindings and pipeline digest. - `resolved-references.json`: resolved reference provenance, including target stage, lane ID when present, origin, digest, media type, byte size, and @@ -133,8 +133,8 @@ directories unless they are part of your own operational policy. There is no command to resume a failed run. Re-run `notarius run` after fixing the cause. -Provider retries are limited to the OpenAI-compatible client retry behavior -configured by the effective LLM profile. There is no separate CLI retry command. +Provider retries and timeouts are handled by Scriptorium according to the +selected execution profile. There is no separate CLI retry command. Notarius writes local files only. Remote storage and archive management are not part of the implemented CLI. diff --git a/docs/roadmap/future.md b/docs/roadmap/future.md index 520d7d7..be78b4f 100644 --- a/docs/roadmap/future.md +++ b/docs/roadmap/future.md @@ -21,17 +21,9 @@ future work only. - Cross-lane entity normalization. - Cross-chunk semantic deduplication. - Configurable validator chains with production validator modules. -- Multiple effective LLM profiles in one run. - Parallel execution where it preserves deterministic manifests and diagnostics. - Additional output encoders. -## Candidate Architecture Work - -- Evaluate replacing the local LLM adapter with an import from - `gitea.maximumdirect.net/eric/scriptorium`, provided it preserves Notarius - boundaries around provider plumbing, prompt ownership, diagnostics, and secret - handling. - ## Candidate Operational Work - Packaged release artifacts for alpha distribution. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 96a6e77..12051e9 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,474 +1,16 @@ -# Scriptorium Cutover Implementation Plan +# Scriptorium Runtime Migration -This plan implements the target state in -[scriptorium.md](scriptorium.md): a hard cutover from Notarius' local -OpenAI-compatible adapter, local LLM profile schema, and local system/user -prompt renderer to Scriptorium-backed prompt execution. +The Scriptorium-backed LLM runtime migration is complete. -The target implementer is an LLM coding agent. Complete each stage in order. -Do not preserve backward compatibility for removed local LLM-profile or -prompt-rendering behavior unless a stage explicitly says to keep a temporary -test seam. +Current implemented behavior is documented in: -## Global Constraints +- [Configuration](../config.md) +- [CLI Reference](../cli.md) +- [Operations](../operations.md) +- [Troubleshooting](../troubleshooting.md) +- [LLM Runtime Internals](../internal/llm.md) +- [Module Internals](../internal/modules.md) +- [Pipeline Internals](../internal/pipeline.md) +- [JSON Output](../integrations/json-output.md) -- Keep Scriptorium types out of chunk, extract, and normalize module contracts. - Module-facing requests should use Notarius-owned contract types. -- Keep provider plumbing behind `internal/framework/llm` and CLI construction. -- Keep module-owned prompt intent, prompt IDs, response schemas, validators, and - source-reference validation with the relevant modules. -- Keep raw input material, raw references, raw prompts, raw schemas, and API - keys out of manifests and default diagnostics. -- Treat the original source input and large references as prompt input - materials. They may be passed to Scriptorium as inline/file inputs, but should - not be copied into durable provenance. -- Use Scriptorium profile configuration directly. Do not keep Notarius' - `llm_profiles` schema as a second profile system. -- Use Scriptorium structured-output execution and validation behavior for - production calls. Notarius should still unmarshal successful structured JSON - into module-owned response structs and run module-owned deterministic - validation afterward. - -## Stage 1: Dependency And API Grounding - -Goal: add the Scriptorium dependency and establish the exact public API surface -used by the rest of the implementation. - -Work: - -- Add `gitea.maximumdirect.net/eric/scriptorium` to `go.mod` with `go get`. -- Inspect the installed package with `go doc` or source reads before coding the - adapter. Confirm names and fields for: - - `NewEngine`; - - `Config`; - - `WithPromptFS`, `WithPromptFile`, or equivalent prompt source options; - - `WithProfileFile`, `WithProfileFS`, profile directory config, and built-in - profile behavior; - - `WithSchemaFS` or equivalent schema source options; - - `RunRequest`, including prompt ID, prompt version, profile ID, inputs, - variables, metadata, direct API key, and validation override fields; - - `RunResult`, including raw output, output artifact, validation status, - prompt/profile/model metadata, usage, and timings; - - public sentinel errors. -- Add a short internal implementation note as a code comment only where needed; - do not add user-facing docs in this stage except if a package-level test - helper needs explanation. - -Acceptance checks: - -- `go test ./internal/framework/llm` -- `go test ./internal/cli` -- `go test ./...` - -## Stage 2: Prompt Input Materials And Session IDs - -Goal: make raw source input and references available to module prompt execution -without storing large content in manifests or default diagnostics. - -Work: - -- Add Notarius-owned contract types under `internal/framework/contracts`: - - `LLMInputMaterial` with at least `Name`, `MediaType`, `Content`, `Digest`, - `OriginURI`, and `SizeBytes`; - - a helper-friendly collection type, such as `LLMInputSet`, if useful. -- Add prompt-execution fields to `StructuredCompletionRequest`: - - `PromptID`; - - `PromptVersion`; - - `ProfileID` or reuse the request `LLMProfile` value when called from stage - requests; - - `SessionID`; - - `Inputs map[string]LLMInputMaterial`; - - `Vars map[string]any`. -- Keep or remove the old `Messages`, `Model`, `ResponseSchemaName`, and - `ResponseSchema` fields according to what makes the cutover cleanest. The - final production path must not require modules to pass rendered messages or - raw schema JSON directly to the provider adapter. -- Add `SourceInput contracts.LLMInputMaterial` and `SessionID string` to - `ChunkRequest`, `ExtractionRequest`, and `NormalizeRequest`. -- Add `SessionID string` to `pipeline.RunInput`. -- In `pipeline.Run`, build a source input material from `RunInput.RawInput` and - `RunInput.Path`: - - preserve the bytes exactly; - - infer media type from the input path extension, using `application/json` - for `.json` and a deterministic fallback for unknown extensions; - - compute a SHA-256 digest; - - use a file URI or path-derived origin URI; - - do not put the bytes in manifest metadata. -- Pass the same source input material and session ID to chunk, extract, and - normalize requests. -- Reuse existing materialized `ReferenceSet` content for reference prompt - inputs. Do not introduce a second file-reading path for references. -- Add CLI support for `--session-id ` on `notarius run`. - - Empty means use a deterministic default derived from the parsed source - document ID. - - The deterministic default must be stable across runs over the same parsed - source document. - - The explicit value should be trimmed and rejected if empty after trimming. -- Because the default depends on the parsed source document, compute and attach - the final session ID inside the runner after input parsing, or return enough - information from parsing for the CLI to resolve it before LLM calls. -- Record the non-secret session ID in run metadata or manifest metadata, but - never record raw prompt content. - -Acceptance tests: - -- Contract tests proving `LLMInputMaterial.Content` is defensively copied where - relevant and omitted from JSON. -- Pipeline tests proving chunk, extract, and normalize requests receive the same - source input bytes and session ID. -- CLI tests for `--session-id`, including explicit value, missing value, - trimming, and default behavior. -- Redaction/diagnostics tests proving raw source bytes and reference content do - not appear in manifests or default diagnostics. - -Focused checks: - -- `go test ./internal/framework/contracts` -- `go test ./internal/framework/pipeline` -- `go test ./internal/cli` - -## Stage 3: Configuration Hard Cutover To Scriptorium Profiles - -Goal: replace Notarius' local LLM profile schema with Scriptorium profile -selection and profile sources. - -Work: - -- Bump the Notarius file config version because this is an incompatible config - schema change. -- Remove the top-level `llm_profiles` file-config schema and the local - `config.LLMProfile` model. -- Add a top-level Scriptorium config block. Use this shape unless Scriptorium's - installed API requires a small naming adjustment: - - ```yaml - scriptorium: - profile_dir: ./profiles - profile_file: ./profiles.yml - ``` - -- Treat `profile_dir` and `profile_file` as mutually exclusive in Notarius - config validation. Built-in Scriptorium profiles remain available when neither - is set. -- Keep existing module binding field name `llm_profile`; it now names a - Scriptorium profile ID. -- Stop forcing empty module `llm_profile` bindings to - `pipeline.DefaultLLMProfile`. Empty means "use the Scriptorium prompt's - `default_profile`." -- Keep `--llm-profile` as a run-level operational override. It should set the - same explicit Scriptorium profile ID for every LLM-eligible selected target. -- Remove `OpenAICompatibleClientConfig` construction from `internal/core/config`. -- Remove local OpenAI-compatible provider validation from config validation. -- Add config validation for: - - config version; - - mutually exclusive `scriptorium.profile_dir` and - `scriptorium.profile_file`; - - non-empty profile source paths when fields are present; - - non-empty explicit `llm_profile` strings after trimming. -- Add CLI/config validation that uses Scriptorium profile loading to reject - unknown explicit profile IDs when possible. Prompt-default profile failures - may surface during Scriptorium prepare/run if Scriptorium owns that lookup. -- Remove or replace environment override behavior tied to - `NOTARIUS_LLM_DEFAULT_*`. Secrets should come from Scriptorium profile - `api_key_env` values or direct request-scoped Scriptorium behavior. -- Update redacted effective config behavior for the new Scriptorium config - shape. - -Acceptance tests: - -- Config parsing accepts `scriptorium.profile_dir`. -- Config parsing accepts `scriptorium.profile_file`. -- Config validation rejects both fields set at once. -- Config validation rejects stale `llm_profiles`. -- Existing pipeline bindings with explicit `llm_profile` resolve to trimmed - Scriptorium profile IDs. -- Empty `llm_profile` remains empty through resolution unless `--llm-profile` - is supplied. -- CLI config validation fails cleanly for an unknown explicit profile ID. -- Redacted config diagnostics do not contain raw API keys. - -Focused checks: - -- `go test ./internal/core/config` -- `go test ./internal/cli` - -## Stage 4: Scriptorium Prompt And Schema Assets - -Goal: move production LLM prompts and schemas to Scriptorium-compatible assets -while preserving module ownership. - -Work: - -- Create a prompt/schema asset registration mechanism that does not put - D&D-specific prompt content in framework packages. - - Recommended shape: add a small prompt-asset registry in - `internal/framework/llm` or a sibling framework package that can collect - `fs.FS` roots for Scriptorium prompt and schema sources. - - Production module packages should register their own Scriptorium prompt and - schema assets through production catalog/registry wiring in `internal/cli`. - - Shared D&D prompt assets may live in a D&D-specific module package such as - `internal/modules/dnd/promptassets`; they must not live in `internal/core` - or source-agnostic framework packages. -- Add shared D&D prompt assets: - - stable shared system message, if needed; - - stable cacheable transcript user message: - - ```text - A transcript of a Dungeons & Dragons gameplay session is provided below. - - {{ input "transcript" }} - ``` - - - stable cacheable reference/context message templates for roster, glossary, - previous recap, or other large references used by current D&D modules. -- Convert `dnd/scenes` to a Scriptorium prompt definition: - - prompt ID: `dnd.scenes`; - - prompt version: current module prompt version; - - input `transcript`, required, `application/json`; - - messages ordered for cache reuse: shared system, shared transcript user - message with cache control, scene task, scene instructions; - - output JSON schema path pointing at the existing scene schema asset; - - schema IDs/names/versions remain module-owned and manifest-safe. -- Convert `dnd/spells` to a Scriptorium prompt definition: - - prompt ID: `dnd.spells`; - - prompt version: current module prompt version; - - input `transcript`, required, `application/json`; - - optional inputs for `roster` and `glossary`; - - messages ordered for cache reuse: shared system, shared transcript user - message with cache control, optional/reference context message with cache - control, spell task, spell instructions; - - output JSON schema path pointing at the existing spell schema asset. -- For optional references, pass empty inline input material when the slot is - unbound unless Scriptorium's template/input semantics support missing - optional inputs cleanly. Do not let optional missing references make prompt - rendering fail. -- For multiple reference items in one slot, concatenate deterministically with - stable headings that include only non-secret provenance, then pass the result - as that prompt input. Existing single-item slots should keep their current - behavior. -- Replace current prompt hash metadata with hashes derived from the - Scriptorium prompt definition plus message assets, or with Scriptorium - prepared-run prompt metadata if it is available without raw prompt content. -- Preserve existing manifest metadata keys where practical: - - `prompt_id`; - - `prompt_version`; - - `prompt_sha256`; - - `response_schema_key`; - - `response_schema_id`; - - `response_schema_name`; - - `response_schema_version`; - - `response_schema_sha256`. - -Acceptance tests: - -- Prompt asset loading fails fast for missing prompt files or schemas. -- `dnd/scenes` prepared prompt contains separate transcript and task messages. -- `dnd/spells` prepared prompt contains separate transcript, reference, and - task messages. -- The transcript message body is byte-identical to the expected shared template - plus original Seriatim JSON bytes. -- Reference prompt input rendering is deterministic. -- Prompt/schema diagnostics omit raw prompt text, raw transcript bytes, raw - reference content, and raw schema JSON. - -Focused checks: - -- `go test ./internal/framework/llm` -- `go test ./internal/modules/chunk/dnd/scenes` -- `go test ./internal/modules/extract/dnd/spells` - -## Stage 5: Scriptorium-Backed LLM Runtime - -Goal: implement the production `StructuredLLMClient` using Scriptorium. - -Work: - -- Add a Scriptorium-backed client under `internal/framework/llm`. -- Its constructor should accept: - - Scriptorium profile source settings from effective Notarius config; - - registered prompt/schema assets; - - request timeout or HTTP client settings only if still owned by Notarius - after the profile cutover; - - optional Scriptorium engine options for tests. -- Implement `CompleteStructured(ctx, req, out)` by: - - validating `out` is a non-nil pointer; - - validating `req.PromptID` is non-empty; - - converting Notarius `LLMInputMaterial` values to Scriptorium artifact refs; - - adding `session_id` to Scriptorium request vars when non-empty; - - passing explicit profile ID only when the module binding or CLI override - supplied one; - - passing no raw API key unless a deliberate request-scoped secret path is - implemented; - - calling Scriptorium `Run`; - - converting final validation failure into a Notarius error; - - unmarshaling successful structured JSON into `out`; - - returning `StructuredCompletionResponse` with raw JSON content, provider, - model, profile ID when available, token usage, and non-secret metadata. -- Add a profile recorder or response accumulator so `RunManifest.LLMProfiles` - records the actual Scriptorium profile/provider/model values used during the - run. - - Do not rely on one precomputed profile ID before pipeline execution. - - Deduplicate profile manifest entries deterministically. -- Keep the existing `Scheduler` and scheduled client wrapper unless Scriptorium - provides an equivalent Notarius-approved concurrency mechanism. -- Ensure all Scriptorium errors are wrapped with context and converted to - concise CLI-facing errors. Preserve `errors.Is` checks internally when - practical. -- Apply Notarius secret redaction to errors before writing diagnostics. -- Remove production construction of `OpenAICompatibleClient`. - -Acceptance tests: - -- Scriptorium adapter maps Notarius prompt request fields into the expected - Scriptorium run request using an injected fake Scriptorium LLM client. -- Successful structured output unmarshals into the caller target. -- Scriptorium validation failure returns an error. -- Provider/runtime failure returns an error with operation context. -- Context cancellation is respected. -- Token usage maps into `StructuredCompletionResponse`. -- Used Scriptorium profile/provider/model metadata appears in the run manifest - without secrets. -- API keys or bearer tokens in synthetic errors are redacted. -- Scheduler still bounds concurrent Scriptorium-backed calls. - -Focused checks: - -- `go test ./internal/framework/llm` -- `go test ./internal/framework/pipeline` -- `go test ./internal/cli` - -## Stage 6: Module Cutover And Legacy Runtime Removal - -Goal: update production modules to call the prompt-based contract and remove -obsolete local prompt/runtime code. - -Work: - -- Update `dnd/scenes`: - - stop rendering local system/user prompt strings; - - call `CompleteStructured` with `PromptID`, `PromptVersion`, `SessionID`, - `ProfileID` or request LLM profile, `transcript` input material, and any - required vars; - - keep existing response validation, chunk canonicalization, caveat handling, - and manifest metadata policy. -- Update `dnd/spells`: - - stop rendering local system/user prompt strings; - - call `CompleteStructured` with `transcript`, optional `roster`, optional - `glossary`, session ID, profile ID, and vars; - - keep existing spell response validation, source-reference validation, and - manifest metadata policy. -- Update any LLM-backed normalize modules if present. If only noop normalize is - present, ensure the contract and tests prove normalizers can receive the same - Scriptorium-capable client and prompt inputs. -- Remove the old `internal/framework/prompt` renderer if no remaining code uses - it. If generic tests still need prompt rendering, replace them with - Scriptorium prompt asset tests or delete obsolete tests. -- Remove `internal/framework/llm/openai_compatible_client.go` and its tests - after the Scriptorium adapter tests cover replacement behavior. -- Remove local OpenAI-compatible integration docs after current-behavior docs - are updated in Stage 7. -- Remove stale schema registry helpers only if they are no longer needed for - module-owned schema metadata. Keep lightweight schema hashing/loading helpers - if modules still use them for manifest metadata. - -Acceptance tests: - -- `dnd/scenes` fake-client tests assert the module sends prompt ID, - transcript input, session ID, and schema/prompt metadata rather than rendered - message text. -- `dnd/spells` fake-client tests assert roster/glossary inputs are passed as - inputs and not interpolated locally. -- Existing malformed LLM response tests still fail as malformed structured - output. -- Existing source-reference validation tests still pass. -- No production code imports the old prompt renderer or local - OpenAI-compatible client. - -Focused checks: - -- `go test ./internal/modules/chunk/dnd/scenes` -- `go test ./internal/modules/extract/dnd/spells` -- If `internal/framework/prompt` is deleted, do not run a package-specific test - for it; instead verify with `rg -n "internal/framework/prompt|RenderUserSystem" internal` - that no production code still depends on it. - -## Stage 7: CLI, Examples, Docs, And Full Validation - -Goal: finish user-facing behavior, examples, and canonical docs for the new -runtime. - -Work: - -- Update `examples/dnd-spells.config.yml` and any maintained test configs to - the new config version and Scriptorium profile source behavior. -- Update `docs/config.md`: - - new config version; - - `scriptorium.profile_dir` and `scriptorium.profile_file`; - - `llm_profile` now means Scriptorium profile ID; - - empty `llm_profile` behavior; - - removed `llm_profiles`; - - removed `NOTARIUS_LLM_DEFAULT_*` env behavior if removed; - - secret-handling policy through Scriptorium profile `api_key_env`. -- Update `docs/cli.md`: - - add `--session-id`; - - update `--llm-profile` wording to Scriptorium profile override; - - update run examples if needed. -- Update `docs/internal/llm.md`: - - Scriptorium-backed runtime; - - prompt asset loading; - - input material handling; - - scheduling; - - structured-output validation; - - profile manifest recording; - - secret redaction. -- Update `docs/internal/modules.md`: - - module prompt ownership through Scriptorium prompt definitions; - - chunk/extract/normalize request input materials and session ID; - - D&D scenes/spells prompt metadata. -- Update `docs/internal/pipeline.md`: - - raw input material lifecycle; - - reference material lifecycle into prompt inputs; - - session ID lifecycle; - - actual LLM profile provenance. -- Update `docs/integrations/json-output.md` for any manifest changes. -- Remove or rewrite `docs/integrations/openai-compatible.md`. If no local - OpenAI-compatible adapter remains, do not document it as current Notarius - behavior. -- Update `docs/troubleshooting.md` for: - - Scriptorium profile-not-found; - - prompt-not-found; - - schema/validation failures; - - missing API key env values; - - session ID usage if relevant. -- Update `docs/operations.md` if diagnostics or retention behavior changes. -- Remove the Scriptorium migration item from `docs/roadmap/future.md` once the - feature is implemented. -- Replace `docs/roadmap/implementation.md` with a completed note or remove it - after implementation is complete, according to the repository's current - roadmap cleanup pattern. - -Acceptance tests and inspections: - -- `rg -n "llm_profiles|OpenAICompatibleClient|openai-compatible|RenderUserSystem|NOTARIUS_LLM_DEFAULT" internal docs examples` - should return only intentional historical/deferred references, if any. -- `rg -n "scriptorium|session-id|profile_dir|profile_file" docs examples` - should show current-behavior docs and examples are updated. -- `go test ./...` -- `go vet ./...` -- `go build ./cmd/notarius` - -## Cross-Stage Review Checklist - -Before considering the implementation complete, verify: - -- No Scriptorium public types appear in chunk, extract, or normalize contracts. -- No raw source input, reference content, prompt text, schema JSON, API key, or - bearer token appears in manifests or default diagnostics. -- The shared transcript message uses original Seriatim JSON bytes exactly. -- Large reference content can be supplied as Scriptorium prompt inputs without - changing module-facing reference slot contracts. -- `--session-id` is easy for an external orchestrator to pass. -- Empty `llm_profile` lets prompt defaults work; explicit `llm_profile` and - `--llm-profile` select Scriptorium profile IDs. -- Production Notarius LLM execution goes through Scriptorium. -- Current-behavior documentation describes only implemented behavior. +Remaining product and operational ideas belong in [Future Work](future.md). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 53ec9e2..777c9e2 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -34,7 +34,7 @@ Symptoms include: Fix: -- Use `version: 1`. +- Use `version: 2`. - Remove unknown YAML fields. - Validate with: @@ -157,21 +157,31 @@ Fix: whitespace. - `end` must be greater than or equal to `start`. -## Missing LLM Base URL Or Model +## Scriptorium Profile Source Failure Symptoms include: -- `LLM profile "default" base URL must not be empty` -- `LLM profile "default" model must not be empty` -- `base URL must be valid` +- `scriptorium profile_dir and profile_file are mutually exclusive` +- `scriptorium.profile_dir must not be empty when set` +- `scriptorium.profile_file must not be empty when set` +- `profile load` +- `profile not found` Fix: -- Set `base_url` and `model` in `llm_profiles.default`. -- Or set `NOTARIUS_LLM_DEFAULT_BASE_URL` and - `NOTARIUS_LLM_DEFAULT_MODEL`. -- If a profile needs authentication, set `api_key_env` in YAML or set - `NOTARIUS_LLM_DEFAULT_API_KEY`. +- Configure at most one of `scriptorium.profile_dir` or + `scriptorium.profile_file`. +- Confirm the selected Scriptorium profile ID exists in the configured profile + source or Scriptorium built-in profiles. +- If using `--llm-profile`, pass a Scriptorium profile ID, not a removed + Notarius profile ID. +- Validate the config and selected pipeline: + +```sh +go run ./cmd/notarius config validate \ + --config path/to/config.yml \ + --pipeline dnd-session +``` ## LLM Profile Override Failure @@ -183,38 +193,49 @@ notarius: LLM profile override "..." is not configured Fix: -- Add the profile under `llm_profiles`. -- Or use an existing profile ID with `--llm-profile`. +- Add the profile to the configured Scriptorium profile source. +- Or use an existing Scriptorium profile ID with `--llm-profile`. -Current runs require exactly one distinct effective LLM profile. If a pipeline -uses several profiles, run with `--llm-profile ` or align the bindings in -configuration. +Use `--llm-profile ` when one run should force every LLM-backed binding to +the same Scriptorium profile. -## Provider HTTP Or Response Failure +## Missing API Key Environment Variable Symptoms include: -- `provider request failed` -- `provider returned status 400` -- `provider returned status 403` -- `provider response missing choices` -- `provider response assistant message content is not valid JSON` +- `api_key_env` +- `unset environment variable` +- provider authentication failures after selecting a profile that needs a key + +Fix: + +- Check the selected Scriptorium profile's `api_key_env` field. +- Set that environment variable before running Notarius. +- Do not put raw API keys in Notarius config or file-backed Scriptorium + profiles. + +## Prompt Or Structured Output Failure + +Symptoms include: + +- `prompt not found` +- `prompt render` +- `schema` +- `validation` - `decode structured output` Fix: -- Confirm the `base_url` points to an OpenAI-compatible endpoint root. Notarius - posts to `/chat/completions`. -- Check `model` and provider credentials. -- Inspect the retained diagnostics `error.log`. -- For 400 and 403 responses, fix the request configuration or credentials. -- For 429 and 5xx responses, the client retries according to `max_retries`; if - the failure persists, inspect the provider response and adjust capacity, - credentials, or model settings. -- The assistant message content must decode as JSON matching the extractor's - structured response schema. - -Provider error messages are redacted for configured API key values. +- Ensure production modules register their embedded Scriptorium prompt and + schema assets. +- If the error names a profile, select a Scriptorium profile that is available + through the configured profile source or built-in catalog. +- If the error names generated output validation, retry with a model that + follows JSON schema instructions reliably. +- Inspect retained diagnostics `error.log`, `resolved-pipeline.json`, and + `run-manifest.json` when available. Prompt text, source text, reference + content, raw schema JSON, and secrets are not written to default diagnostics. +- Provider errors are redacted for bearer tokens and configured API key values. ## Scene Chunking Failure @@ -234,8 +255,8 @@ Fix: - Validate the pipeline configuration and confirm the input module provides a transcript source when using `chunk: dnd/scenes`. -- Confirm the LLM profile has a working OpenAI-compatible `base_url`, `model`, - and credentials. +- Confirm the selected Scriptorium profile has a working endpoint, model, and + credentials. - Inspect retained diagnostics for the run error and resolved pipeline. - If the error names malformed structured output, retry with a model that follows structured response schemas reliably. @@ -244,6 +265,16 @@ Fix: - Scene boundaries must use exact source-unit IDs, cover the full source document, be contiguous, and not overlap. +## Session ID + +Symptom: external logs or provider traces cannot be correlated with a Notarius +run. + +Fix: + +- Pass `--session-id ` to `notarius run`. +- Use a stable, non-secret identifier from the external orchestrator. + ## Output Write Failure Symptoms include: diff --git a/internal/core/artifacts/artifacts_test.go b/internal/core/artifacts/artifacts_test.go index cf7faf9..0a63c13 100644 --- a/internal/core/artifacts/artifacts_test.go +++ b/internal/core/artifacts/artifacts_test.go @@ -128,7 +128,7 @@ func TestRunManifestIncludesPipelineAndArtifactLaneFields(t *testing.T) { PipelineID: "pipeline-1", PipelineDigest: "sha256:abc123", LLMProfiles: []LLMProfileManifest{ - {ID: "default", Provider: "openai-compatible", Model: "model-a"}, + {ID: "default", Provider: "scriptorium", Model: "model-a"}, }, ArtifactLanes: []ArtifactLaneManifest{ { diff --git a/internal/framework/llm/scriptorium_client.go b/internal/framework/llm/scriptorium_client.go index ce8f6dd..b5f888f 100644 --- a/internal/framework/llm/scriptorium_client.go +++ b/internal/framework/llm/scriptorium_client.go @@ -16,7 +16,7 @@ import ( "gitea.maximumdirect.net/eric/scriptorium" ) -const scriptoriumProviderName = "openai-compatible" +const scriptoriumProviderName = "scriptorium" type ScriptoriumClientConfig struct { ProfileDir string diff --git a/internal/framework/pipeline/runner_test.go b/internal/framework/pipeline/runner_test.go index bcc7d4d..5a3194f 100644 --- a/internal/framework/pipeline/runner_test.go +++ b/internal/framework/pipeline/runner_test.go @@ -1184,7 +1184,7 @@ func TestRunManifestIncludesPipelineAndLaneDetails(t *testing.T) { func TestRunManifestIncludesRunTimingAndLLMProfiles(t *testing.T) { startedAt := time.Now().Add(-time.Minute).UTC() profiles := []artifacts.LLMProfileManifest{ - {ID: "default", Provider: "openai-compatible", Model: "model-a"}, + {ID: "default", Provider: "scriptorium", Model: "model-a"}, } output, err := New(newRunnerRegistries(t, nil)).Run(context.Background(), RunInput{ @@ -1216,9 +1216,9 @@ func TestRunManifestIncludesProfilesReportedByLLMClient(t *testing.T) { output, err := New(newRunnerRegistries(t, nil)).Run(context.Background(), RunInput{ Pipeline: resolvedPipeline(), LLMClient: manifestReportingLLMClient{profiles: []artifacts.LLMProfileManifest{ - {ID: "profile-b", Provider: "openai-compatible", Model: "model-b"}, - {ID: "profile-a", Provider: "openai-compatible", Model: "model-a"}, - {ID: "profile-b", Provider: "openai-compatible", Model: "model-b"}, + {ID: "profile-b", Provider: "scriptorium", Model: "model-b"}, + {ID: "profile-a", Provider: "scriptorium", Model: "model-a"}, + {ID: "profile-b", Provider: "scriptorium", Model: "model-b"}, }}, }) if err != nil { @@ -1226,8 +1226,8 @@ func TestRunManifestIncludesProfilesReportedByLLMClient(t *testing.T) { } want := []artifacts.LLMProfileManifest{ - {ID: "profile-a", Provider: "openai-compatible", Model: "model-a"}, - {ID: "profile-b", Provider: "openai-compatible", Model: "model-b"}, + {ID: "profile-a", Provider: "scriptorium", Model: "model-a"}, + {ID: "profile-b", Provider: "scriptorium", Model: "model-b"}, } if !reflect.DeepEqual(output.Manifest.LLMProfiles, want) { t.Fatalf("LLMProfiles = %#v, want %#v", output.Manifest.LLMProfiles, want)