Add real SWI-Prolog OpenRouter provider and live CI (#5) #22

Merged
lost-rob0t merged 15 commits from feature/issue-5-openrouter-provider into main 2026-08-12 01:49:14 +00:00
lost-rob0t commented 2026-08-12 01:47:57 +00:00 (Migrated from github.com)

Closes #5.

Production provider path

  • add provider-neutral model_complete/3 dispatch in rlm_chain
  • add direct SWI-Prolog OpenAI-compatible HTTPS adapter
  • add OpenRouter production configuration using credential(env('OPENROUTER_API_KEY'))
  • resolve credentials only at request execution time
  • default OPENROUTER_TEST_MODEL to openrouter/free when unset/empty
  • normalize text, tool-call, finish-reason, provider/model, HTTP, response-id, and usage metadata into canonical model responses
  • convert validation, provider, HTTP, timeout, and transport failures into structured Prolog outcomes
  • redact credential material from caught transport exceptions
  • no Python runtime and no fake-provider fallback

Test split

Deterministic unit/conformance

  • runs with OpenRouter environment variables explicitly blank
  • validates response normalization, usage metadata, tool calls, malformed requests, capability denial, missing credentials, timeout classification, and secret redaction
  • never makes network requests

REAL OpenRouter integration

  • separate REAL OpenRouter integration job
  • receives OPENROUTER_API_KEY from the repository secret and optional OPENROUTER_TEST_MODEL repository variable
  • only runs for trusted same-repository PRs, pushes to main, and manual dispatch
  • hard-fails if the expected secret is absent
  • performs a real HTTPS request through the production provider path
  • requires a non-empty assistant result, provider/model metadata, HTTP 200, and validates usage metadata when returned
  • has no mock, fixture, interception, or fake fallback path
  • emits only whitelisted non-secret evidence as a GitHub Actions notice

Security validation so far

  • full branch diff inspected
  • no sk-or- credential material found
  • no literal Bearer sk- material found
  • no environment/header dumps are present

This PR MUST NOT merge until the same-repository PR workflow proves the REAL OpenRouter job executed (not skipped) and returned successful non-secret evidence.

Closes #5. ## Production provider path - add provider-neutral `model_complete/3` dispatch in `rlm_chain` - add direct SWI-Prolog OpenAI-compatible HTTPS adapter - add OpenRouter production configuration using `credential(env('OPENROUTER_API_KEY'))` - resolve credentials only at request execution time - default `OPENROUTER_TEST_MODEL` to `openrouter/free` when unset/empty - normalize text, tool-call, finish-reason, provider/model, HTTP, response-id, and usage metadata into canonical model responses - convert validation, provider, HTTP, timeout, and transport failures into structured Prolog outcomes - redact credential material from caught transport exceptions - no Python runtime and no fake-provider fallback ## Test split ### Deterministic unit/conformance - runs with OpenRouter environment variables explicitly blank - validates response normalization, usage metadata, tool calls, malformed requests, capability denial, missing credentials, timeout classification, and secret redaction - never makes network requests ### REAL OpenRouter integration - separate `REAL OpenRouter integration` job - receives `OPENROUTER_API_KEY` from the repository secret and optional `OPENROUTER_TEST_MODEL` repository variable - only runs for trusted same-repository PRs, pushes to `main`, and manual dispatch - hard-fails if the expected secret is absent - performs a real HTTPS request through the production provider path - requires a non-empty assistant result, provider/model metadata, HTTP 200, and validates usage metadata when returned - has no mock, fixture, interception, or fake fallback path - emits only whitelisted non-secret evidence as a GitHub Actions notice ## Security validation so far - full branch diff inspected - no `sk-or-` credential material found - no literal `Bearer sk-` material found - no environment/header dumps are present This PR MUST NOT merge until the same-repository PR workflow proves the REAL OpenRouter job executed (not skipped) and returned successful non-secret evidence.
Sign in to join this conversation.
No description provided.