Skip to content

Provider seam (Anthropic solve) #27

Description

@jpka

Parent

Part of #25 (Screen Solver v1: implementation spec), itself under the map #1.

What to build

The single module the rest of the app calls to get a coding-exercise answer out of a screenshot — the seam a second vision provider would replace later without touching any other module.

createProvider(config) → Provider, where Provider.solve(image, {signal}) → AsyncIterable<Event>. Event is one of delta{text}, done{usage}, or error{kind} with kind ∈ {auth, refusal, transient}. The system prompt is passed in and fixed at construction, not per call — it is not this ticket's job to write the prompt's content (see the spec for the full text and rules: answer-first # heading → fenced code → two-to-three short paragraphs, the literal # No exercise on screen bail, the single > **Missing:** … line), only to carry it into the request unmodified and enable prompt caching on it (ttl: 1h). Transient errors (rate limit, overload, network) retry internally inside the seam with no caller involvement; auth and refusal surface on first occurrence with no retry. Model defaults: claude-sonnet-5, effort: medium, max_tokens: 8000.

This module has no dependency on the HTTP server, capture, or config — it is testable standalone against a fake Anthropic transport.

Acceptance criteria

  • solve(image, {signal}) against a real or faked successful response yields delta events followed by a terminal done{usage} with token usage populated.
  • A faked auth-rejecting response surfaces error{kind: 'auth'} immediately, with no retry attempted.
  • A faked refusal response surfaces error{kind: 'refusal'} immediately, with no retry attempted.
  • A faked transient failure (rate limit / overload / network) that succeeds on a later attempt retries internally and completes normally — the caller never sees an intermediate error.
  • A faked transient failure that never succeeds surfaces error{kind: 'transient'} only after retries are exhausted.
  • Aborting via the passed signal mid-stream stops the iterable without throwing an unhandled error.
  • The request sent to the provider has prompt caching enabled on the system prompt.

Blocked by

None — can start immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentImplementation-ready spec, ready to be picked up by an agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions