Files
scriptorium/docs/internal/adapters.md

6.6 KiB

Adapter Internals

Purpose

Adapters translate external interfaces into domain requests and translate domain results back out. They wire dependencies, apply app config, and own IO concerns, but they do not make runner decisions.

Source-loading behavior belongs in docs/internal/sources.md. User-facing CLI, HTTP, and package contracts belong in docs/cli.md, docs/api.md, and docs/consumers/pkg-scriptorium.md.

Adapter Map

  • cmd/scriptorium: process entrypoint.
  • internal/adapter/cli: command parsing, config handoff, runner construction, stdout/stderr, exit codes.
  • internal/adapter/http: POST /v1/runs request/response mapping and HTTP error/status mapping.
  • root package scriptorium: public Go facade over internal runner types and dependencies.

Supporting implementation packages used during adapter wiring:

  • internal/config
  • internal/defaults
  • internal/format
  • internal/llm
  • internal/prompt

Inputs And Outputs

CLI adapter:

  • Input: process args, optional config file, filesystem sources, environment variables.
  • Output: process exit code, stdout artifact/prepared output, stderr summaries and errors.

HTTP adapter:

  • Input: HTTP request method/path/headers/body for POST /v1/runs.
  • Output: JSON success or error body with mapped status code.

Public Go facade:

  • Input: typed scriptorium.Config, Option, and RunRequest values.
  • Output: typed PreparedRun and RunResult values plus public sentinel errors.

Boundaries

  • Adapters convert external shapes to domain.RunRequest and back.
  • Runner orchestration remains in internal/usecase.
  • Prompt/profile/schema/artifact source rules remain in repository, validator, and artifact packages.
  • LLM provider request serialization remains in internal/llm.
  • Public package types are facade types; internal domain types do not leak across the package boundary.

Config Fields Used

Adapter app settings:

  • prompt_dir
  • profile_dir
  • schema_dir
  • server.addr
  • server.artifact_root
  • server.max_request_bytes
  • server.max_artifact_bytes
  • server.max_response_bytes
  • defaults.render_format

Execution request/profile settings passed through the runner:

  • endpoint
  • model
  • temperature
  • max_tokens
  • top_p
  • timeout_seconds
  • service_tier
  • api_key_env
  • reasoning_effort
  • extra_params

CLI and HTTP preserve numeric override presence so omitted values and explicit zero values remain distinct.

CLI Adapter

Implemented commands:

  • run
  • render
  • serve

Behavior:

  • run constructs a runner with direct filesystem artifact reading and calls Runner.Run.
  • render constructs a runner and calls Runner.Prepare; it does not call the LLM.
  • serve constructs a restricted artifact reader and HTTP handler, then starts an unauthenticated HTTP server.
  • run exits 2 when generation succeeds but validation fails.
  • parse, runtime, and output-write errors exit 1.
  • deprecated --prompt-id and --profile-id aliases are accepted.

HTTP Adapter

Behavior:

  • Accepts only POST /v1/runs.
  • Decodes JSON strictly and rejects unknown fields and trailing JSON tokens.
  • Rejects empty prompt_id and empty inputs before calling the runner.
  • Does not accept raw API key values in the request body.
  • Returns validation failures as 200 responses with failed validation details.
  • Maps request-body, artifact, and encoded-response size failures to 413.
  • Maps domain and repository errors to stable error codes without returning wrapped internal cause text.

The HTTP adapter has no built-in authentication or authorization. Deployment controls must be provided outside the process.

Public Go Facade

Behavior:

  • NewEngine wires the same default runner components as CLI/HTTP unless options override them.
  • Prompt, profile, and schema sources may come from directories, single files, or fs.FS roots.
  • WithProfiles adds in-memory profiles ahead of file-backed and built-in profiles.
  • WithLLMClient injects custom model behavior.
  • RunRequest.APIKey is request-scoped and direct; it is used only for generation and is stripped from public results.
  • internal errors are mapped to public sentinels in errors.go.

Failure Behavior

Adapters should:

  • keep external error payloads concise and stable.
  • avoid leaking raw secret values.
  • use sentinels and typed errors for mapping.
  • preserve strict external input decoding.
  • keep validation content failures distinct from runtime errors.

CLI writes human-readable summaries to stderr. HTTP writes JSON error envelopes. The public Go facade returns typed errors.

State And Manifests

Adapters do not add durable run state.

  • No adapter writes run manifests.
  • No adapter implements checkpoint, skip, or resume behavior.
  • CLI output files are caller-selected artifacts, not internal state.

Tests To Inspect

  • internal/adapter/cli/run_test.go
  • internal/adapter/http/handler_test.go
  • engine_test.go
  • internal/format/prepared_run_test.go
  • internal/llm/openai_compatible_client_test.go

Change Recipes

Application Configuration Fields

  1. Add the field to the relevant internal/config shape and default handling.
  2. Parse and validate it, then preserve configuration and CLI-override precedence while wiring it through its consuming adapter.
  3. Add focused configuration and adapter tests for parsing, mapping, and effective behavior.
  4. Update the configuration contract and any external contract affected by the new behavior.

CLI Flags

  1. Add the flag to the relevant command in internal/adapter/cli/run.go.
  2. Keep command scope and application-configuration precedence intentional.
  3. Add or update parser and command tests in internal/adapter/cli/run_test.go.
  4. Update the CLI contract and any maintained examples affected by the invocation.

Adapter Capabilities

  1. Define or reuse the appropriate domain or use-case interface boundary.
  2. Implement translation and IO behavior in the adapter without moving use-case decisions out of internal/usecase.
  3. Add focused mapping, parsing, and error-behavior tests.
  4. Update this document and the affected canonical public or integration contract. Update source internals when source-loading behavior changes.

Architectural Invariants

  • Adapter packages stay thin and translation-focused.
  • App config is resolved before dependency construction.
  • External input strictness is part of contract stability.
  • CLI and HTTP construct runners without a repairer.
  • HTTP endpoint details remain canonical in docs/api.md.
  • Public Go package details remain canonical in docs/consumers/pkg-scriptorium.md.