120 lines
4.5 KiB
Markdown
120 lines
4.5 KiB
Markdown
# Runner Internals
|
|
|
|
## Purpose
|
|
|
|
`internal/usecase.Runner` is the prompt-execution orchestrator. It prepares
|
|
domain requests, invokes an injected LLM client, validates output, and returns
|
|
domain results. Transport parsing, response mapping, and public type conversion
|
|
remain outside this package.
|
|
|
|
The [configuration reference](../config.md) owns prompt, profile, schema, and
|
|
runtime-setting definitions. Public error behavior is defined by the
|
|
[HTTP API](../api.md) and [Go package](../consumers/pkg-scriptorium.md)
|
|
contracts.
|
|
|
|
## Dependencies And Construction
|
|
|
|
`Runner` receives these collaborators:
|
|
|
|
- `promptdef.Repository`;
|
|
- `profile.Repository`;
|
|
- `artifact.Reader`;
|
|
- `prompt.Renderer`;
|
|
- `llm.Client`;
|
|
- `validate.Validator`; and
|
|
- an optional `OutputRepairer`.
|
|
|
|
`NewRunner` constructs a runner without a repairer. `NewRunnerWithRepairer`
|
|
accepts one explicitly. Adapters and the public engine choose concrete
|
|
repositories and readers; the runner does not load application configuration.
|
|
|
|
## Prepare Flow
|
|
|
|
`Prepare` performs one deterministic preparation pass for a request:
|
|
|
|
1. validate the prompt ID and load the prompt definition;
|
|
2. hash the definition and select the explicit or default profile;
|
|
3. load the profile and resolve effective execution settings;
|
|
4. validate endpoint, model, and credential availability;
|
|
5. resolve the output contract and, for JSON Schema output, load a structured
|
|
schema document before model execution;
|
|
6. read and hash input artifacts;
|
|
7. render messages and the session ID; and
|
|
8. return a `PreparedRun` containing the effective state and rendered-prompt
|
|
hash.
|
|
|
|
Execution settings merge defaults, profile values, and a request override.
|
|
Numeric override presence is retained so explicit zero values are not confused
|
|
with omissions.
|
|
|
|
## Run And Validation Flow
|
|
|
|
`Run` creates a run ID and timestamps, then calls `Prepare` rather than
|
|
duplicating preparation. It sends the prepared prompt, effective target,
|
|
target-presence state, and optional structured-output specification to the LLM
|
|
client. It converts the returned content to an output artifact, validates it,
|
|
and returns the artifact, validation, hashes, usage, and timing metadata.
|
|
|
|
A validator can return a content result or an operational error. Content
|
|
failures stay in the result; schema loading, compilation, and validator
|
|
operational failures are returned as `ErrValidation`. The canonical distinction
|
|
for callers is documented by the public contracts.
|
|
|
|
## Repair Boundary
|
|
|
|
Repair is an internal optional loop. It starts only when a repairer is present,
|
|
the output contract permits one or more attempts, validation failed, and the
|
|
validation mode is JSON or JSON Schema. Each repair receives the previous
|
|
output, validation errors, effective target, structured-output specification,
|
|
and attempt metadata; every repaired result is validated again.
|
|
|
|
`NewDefaultOutputRepairer` delegates to the injected LLM client. CLI, HTTP, and
|
|
the public engine use `NewRunner` and therefore do not inject this repairer.
|
|
|
|
## Error Translation
|
|
|
|
Runner sentinels identify failure categories for adapters:
|
|
|
|
- `ErrInvalidRequest`
|
|
- `ErrProfileRequired`
|
|
- `ErrAPIKeyEnvMissing` and `ErrAPIKeyRequired`
|
|
- `ErrPromptLoad`, `ErrProfileLoad`, and `ErrArtifactLoad`
|
|
- `ErrPromptRender`
|
|
- `ErrLLMGenerate`
|
|
- `ErrValidation`
|
|
|
|
Wrap errors with those sentinels and preserve their identities through
|
|
`errors.Is`; adapters must not classify errors by message text. The runner
|
|
passes direct keys only to the LLM boundary and never includes resolved key
|
|
values in prepared or run results.
|
|
|
|
## Package-Local Guarantees
|
|
|
|
- `Run` always reuses `Prepare`.
|
|
- Schema documents are loaded before the initial LLM call when structured output
|
|
is required.
|
|
- Output validation records attempts used, including repair attempts.
|
|
- Runner state is per request; the package does not create a durable run store
|
|
or manifest.
|
|
- Source, renderer, validator, and LLM implementations remain injected
|
|
boundaries.
|
|
|
|
## Verification And Change Recipe
|
|
|
|
Inspect:
|
|
|
|
- `internal/usecase/runner_test.go`
|
|
- `internal/usecase/integration_test.go`
|
|
- `engine_test.go`
|
|
|
|
When changing orchestration:
|
|
|
|
1. identify the collaborator boundary and the affected `Prepare` or `Run` state;
|
|
2. preserve the `Run`-through-`Prepare` path and error identity;
|
|
3. add focused runner or integration tests for changed state transitions,
|
|
validation, or repair behavior; and
|
|
4. update the owning external contract and any affected source or LLM internal
|
|
document.
|
|
|
|
The [testing policy](../policy/testing.md) owns global test sufficiency.
|