Skip to content

Implement OpenAI-compatible provider (Story 7) and switch default to OpenRouter + GLM 5.2#2

Merged
ericmann merged 1 commit into
mainfrom
agent/issue-1
Jun 21, 2026
Merged

Implement OpenAI-compatible provider (Story 7) and switch default to OpenRouter + GLM 5.2#2
ericmann merged 1 commit into
mainfrom
agent/issue-1

Conversation

@claude

@claude claude Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🤖 Agent-Generated PR

Closes #1
Agent Used: Claude Code (claude-sonnet-4-6)
Complexity: medium


Summary

  • Implements OpenAICompatProvider adapter (Story 7 / AD-4) with bearer auth, OpenRouter attribution headers, and json_schema structured output with a json_object fallback triggered only on schema-rejection 400s
  • Switches DEFAULT_SETTINGS.activeProvider to openai_compat + z-ai/glm-5.2 via OpenRouter (~3–4× cheaper than Claude Sonnet 4.6 for Slopwatch's prompt shape; verified slug and pricing from OpenRouter API)
  • Adds full options UI section for the provider (base URL, model, write-only key entry, Test connection)

Implementation Notes

  • json_schema fallback path: catches ProviderError with kind: 'bad_response' and detail containing json_schema, response_format, or unsupported, then retries once with json_object. Any other 4xx propagates immediately — no silent fallback.
  • Attribution headers: HTTP-Referer: https://github.com/DisplaceTech/slopwatch, X-Title: Slopwatch — always sent, harmless on non-OpenRouter gateways.
  • Pricing table: z-ai/glm-5.2 at $1.20/$4.10 per 1M tokens (verified 2026-06-21), gpt-4o-mini at $0.15/$0.60; returns undefined for unknown models.
  • Default change scope: only affects fresh installs / resetSettings(); existing users keep their configured provider via the v1 settings round-trip.
  • Existing component tests updated to reflect (a) the new default provider and (b) the options page now having multiple "API key" inputs — queries tightened to #anthropic-key selector.

Changes

  • lib/providers/openai-compat.ts — new adapter
  • lib/providers/openai-compat.test.ts — 11 unit tests covering happy path, json_object fallback, non-json_schema 400, auth, rate-limit, repair, validate, header assertions, URL trimming, and cost estimation
  • lib/providers/index.ts — factory wired; stub removed; OpenAICompatProvider exported
  • lib/storage/settings.ts — default flipped to openai_compat + z-ai/glm-5.2 / OpenRouter
  • wxt.config.tshttps://openrouter.ai/* added to optional_host_permissions
  • entrypoints/options/App.tsx — OpenAI-compatible section added; openai_compat in production PROVIDER_OPTIONS
  • lib/storage/secrets.test.ts — new: round-trips openai_compat secret through applyPersistencePreference
  • docs/LEARNINGS.md — note on provider default change and calibration watch items
  • tests/component/options.test.tsx, tests/component/popup.test.tsx — updated for new defaults and multiple key fields

Testing

Automated:

  • Unit tests added/updated
  • Integration tests added/updated
  • All existing tests pass (130 passed (22 test files))

Manual testing performed:

  • pnpm lint && pnpm typecheck && pnpm test && pnpm build && pnpm build:firefox all clean

Review Checklist

Correctness

  • Code actually solves the issue
  • Acceptance criteria are met
  • Edge cases handled

Code Quality

  • Follows existing codebase patterns
  • Follows project coding standards
  • Naming conventions consistent
  • No unnecessary complexity
  • Comments where needed (but code is self-documenting)

Security

  • Input validation present
  • No exposed secrets or credentials
  • Data properly sanitized/escaped
  • Authentication/authorization checks where needed

Performance

  • No obvious N+1 queries
  • Reasonable algorithmic complexity
  • Caching used where appropriate
  • No blocking operations in request lifecycle

Tests

  • Tests actually test behavior (not just coverage)
  • Edge cases covered
  • Failure modes tested

Reviewer Notes

The GLM 5.2 model slug on OpenRouter is z-ai/glm-5.2 (verified from https://openrouter.ai/api/v1/models). There's a // TODO(slopwatch): note to evaluate the canonical timestamped slug once it stabilizes. The pricing table ($1.20/$4.10 per 1M tokens) was verified from the same API on 2026-06-21.

🤖 Generated with Claude Code

…uter + GLM 5.2

Implements Story 7 (OpenAI-compat adapter) and AD-4 (gateway pattern):
- `OpenAICompatProvider` adapter with bearer auth, OpenRouter attribution headers,
  json_schema structured output with json_object fallback on schema-rejection 400
- Factory wired in `lib/providers/index.ts`; provider stub removed
- Default changed to `openai_compat` + `z-ai/glm-5.2` via OpenRouter (~3-4× cheaper
  than Sonnet for this workload); existing users keep their configured provider
- `https://openrouter.ai/*` added to optional_host_permissions
- OpenAI-compatible section in options UI (base URL, model, write-only key, Test connection)
- `openai_compat` added to production PROVIDER_OPTIONS
- Secrets migration test for `openai_compat` in `lib/storage/secrets.test.ts`
- LEARNINGS.md note on the default-provider change and calibration watch items
- Existing component tests updated to reflect new default provider and extra key field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude claude Bot added the agent-generated PR was created by an AI agent label Jun 21, 2026
@ericmann ericmann merged commit ca5f032 into main Jun 21, 2026
1 check passed
@ericmann ericmann deleted the agent/issue-1 branch June 21, 2026 03:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-generated PR was created by an AI agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement OpenAI-compatible provider (Story 7) and switch default to OpenRouter + GLM 5.2

1 participant