grip_hook.providers¶
grip_hook.providers ¶
LLM providers.
A provider turns a diff into questions and answers into grades. Add a new one by
implementing :class:grip_hook.providers.base.Provider and registering it in
:data:REGISTRY.
REGISTRY
module-attribute
¶
REGISTRY: dict[str, ProviderFactory] = {'anthropic': _anthropic, 'openai': _openai, 'ollama': _openai, 'claude-code': _claude_code, 'claude': _claude_code, 'codex': _codex, 'gemini': _gemini, 'fake': _fake}
Provider name to factory.
ollama is openai with a local default URL; claude is an alias of claude-code.
The agent providers shell out to a CLI that is already installed and signed in.
Provider ¶
Bases: Protocol
Something that can write quiz questions and grade answers.
Source code in src/grip_hook/providers/base.py
get_provider ¶
Instantiate the provider named by cfg.provider.
Source code in src/grip_hook/providers/__init__.py
grip_hook.providers.base ¶
Provider interface.
Provider ¶
Bases: Protocol
Something that can write quiz questions and grade answers.
Source code in src/grip_hook/providers/base.py
grip_hook.providers.anthropic ¶
Anthropic provider built on the official anthropic SDK.
AnthropicProvider ¶
Ask Claude for questions and grades using structured outputs.
Source code in src/grip_hook/providers/anthropic.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
grip_hook.providers.openai_compat ¶
Provider for any OpenAI-compatible chat completions API (OpenAI, Ollama, vLLM, ...).
Implemented with the standard library so grip carries no extra dependency for it.
JSON output is requested through response_format with a JSON schema, which
Ollama and most OpenAI-compatible servers honour; the reply is validated with the
same pydantic models the Anthropic provider uses.
OpenAICompatibleProvider ¶
Talk to {base_url}/chat/completions.
Source code in src/grip_hook/providers/openai_compat.py
grip_hook.providers.agents ¶
Providers that reuse a coding agent CLI already installed and signed in.
No API key is needed: each provider shells out to the agent in non-interactive mode, sends the same prompts the API providers use, and asks for JSON back.
claude-code:claude -pwith--json-schema(schema-enforced output).codex:codex execwith--output-schema(schema-enforced output).gemini:gemini --output-format json; the JSON is requested in the prompt and extracted from the reply.
Every agent runs with tools disabled where the CLI allows it, in an empty scratch directory, so it cannot read the repository, run commands, or pick up project-level instructions and hooks. It only ever sees the diff and the answers.
AgentCLIProvider ¶
Common machinery: build a command, run it, validate the JSON it returns.
Source code in src/grip_hook/providers/agents.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
enforces_schema
class-attribute
¶
Whether the CLI constrains its output to the schema; otherwise it is asked for.
system_flag
class-attribute
¶
Flag that takes the system prompt; empty means prepend it to the user prompt.
command ¶
parse_output ¶
generate_questions ¶
Write the question set for diff.
grade ¶
grade(diff: Diff, questions: list[Question], answers: list[Answer], difficulty: Difficulty) -> GradeSheet
Grade every answer in one call.
Source code in src/grip_hook/providers/agents.py
ClaudeCodeProvider ¶
Bases: AgentCLIProvider
Claude Code (claude) in print mode with schema-enforced structured output.
Source code in src/grip_hook/providers/agents.py
command ¶
claude -p with no tools, no session persistence, JSON envelope output.
Source code in src/grip_hook/providers/agents.py
parse_output ¶
Read structured_output from the JSON envelope.
Source code in src/grip_hook/providers/agents.py
CodexProvider ¶
Bases: AgentCLIProvider
OpenAI Codex CLI (codex exec) with --output-schema.
Source code in src/grip_hook/providers/agents.py
command ¶
Non-interactive, read-only sandbox, last message written to a file.
Source code in src/grip_hook/providers/agents.py
parse_output ¶
Prefer the last-message file; fall back to scanning stdout.
Source code in src/grip_hook/providers/agents.py
GeminiProvider ¶
Bases: AgentCLIProvider
Gemini CLI (gemini) in non-interactive JSON mode.
Source code in src/grip_hook/providers/agents.py
command ¶
Prompt comes from stdin; the reply is a JSON envelope with a response key.
Source code in src/grip_hook/providers/agents.py
parse_output ¶
Unwrap the envelope, then extract the JSON object from the reply text.
Source code in src/grip_hook/providers/agents.py
extract_json ¶
Parse the first JSON object in text, tolerating code fences and chatter.
Source code in src/grip_hook/providers/agents.py
grip_hook.providers.fake ¶
A deterministic provider for tests, demos and grip quiz --provider fake.
Two modes:
- Default. Questions are derived from the changed file names; an answer scores full
marks when it mentions the word
becauseor is at least twenty characters long, half marks when it is non-empty, and zero otherwise. - Scripted. When
GRIP_FAKE_SCRIPTpoints to a JSON file, questions, grading rules and verdicts come from that file (see :func:load_script). This is how the demo recording and some tests get realistic, reproducible output without a network.
GRIP_FAKE_DELAY (seconds, float) makes each call sleep, so the spinner is visible.
GradeRule ¶
Bases: BaseModel
Award score when the lower-cased answer contains match.
Source code in src/grip_hook/providers/fake.py
DefaultGrade ¶
Bases: BaseModel
Grade used when no rule matches.
Source code in src/grip_hook/providers/fake.py
ScriptedQuestion ¶
Bases: Question
A question plus the rules used to grade answers to it.
Source code in src/grip_hook/providers/fake.py
grade ¶
First matching rule wins; rules are checked in order.
Source code in src/grip_hook/providers/fake.py
Verdict ¶
Script ¶
Bases: BaseModel
The scripted provider's data file.
Source code in src/grip_hook/providers/fake.py
verdict_for ¶
Pick the verdict with the highest min not above total.
Source code in src/grip_hook/providers/fake.py
FakeProvider ¶
Offline stand-in for a real model.
Source code in src/grip_hook/providers/fake.py
generate_questions ¶
Produce five questions, scripted or templated over the changed files.
Source code in src/grip_hook/providers/fake.py
grade ¶
grade(diff: Diff, questions: list[Question], answers: list[Answer], difficulty: Difficulty) -> GradeSheet
Score answers deterministically, by script rules or by length.
Source code in src/grip_hook/providers/fake.py
load_script ¶
Read and validate a script file.