mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-21 21:15:10 +00:00
feat+test+docs: D71+D72+D73 — olp-plugin/ (OpenClaw /olp Telegram+Discord) + docs/integrations/*.md + README cross-refs (#44)
Final Phase 4 substantive D-day group. 3 D-days bundled per Iron Rule 11 IDR (plugin consumes existing endpoints; integration docs reference plugin + olp CLI + olp-connect together; README index links all). After this PR merges, Phase 4 has shipped all 5 D-day groups (D60 charter + port / D61-D63 SSE heartbeat+ring+/status / D64-D67 olp CLI+doctor / D68-D70 olp-connect+anonymous-key+ADR0011 / D71-D73 plugin+docs). The v0.4.0 close PR is maintainer-triggered per CLAUDE.md release_kit overlay. ## D71 — olp-plugin/ (OpenClaw gateway plugin) Port OCP ocp-plugin/index.js (311 lines) → OLP olp-plugin/index.js (482 lines) as the /olp Telegram+Discord slash command, but MINUS mutations (no /olp keys keygen, no /olp keys revoke, no /olp restart, no /olp logs — all of these require SSH out of chat for security). Plugin shape: - olp-plugin/index.js — registers /olp command via OpenClaw api.registerCommand - olp-plugin/openclaw.plugin.json — manifest, apiKey REQUIRED, proxyUrl default http://127.0.0.1:4567 (matches D60) - olp-plugin/package.json — minimal: name/version/type:module + OpenClaw discovery block - olp-plugin/README.md — install + configure + use docs; documents the "no mutations from chat" security stance and the dedicated-bot-key pattern (don't share maintainer's personal key with the bot) Subcommand parity with olp CLI (D64-D67): - /olp status → GET /v0/management/status (owner-only) - /olp health → GET /health (public-ok) - /olp usage → GET /v0/management/dashboard-data (owner-only) - /olp models → GET /v1/models (public-ok) - /olp cache → GET /cache/stats (owner-only) - /olp providers → local cross-ref (public-ok) - /olp chain show [<model>] → local (public-ok, advisory if no FS access — defer to ssh + olp chain show) - /olp doctor → informational (HTTP doctor endpoint deferred; advisory to ssh + olp doctor for live use) - /olp help → usage text Port resolution: OLP_PROXY_URL env → OLP_PORT env → plugin config proxyUrl → http://127.0.0.1:4567. Output: Telegram/Discord monospace code block with status icons (🟢🟡🔴). Long responses truncated for the 4096-char message limit. No npm deps. OpenClaw provides Telegram/Discord transport; plugin uses fetch + node builtins only. ## D72 — docs/integrations/*.md (6 IDE pages + index) Per the Phase 4 brainstorm prior-art survey + ADR 0010 § Out-of-scope posture for Claude Code: - continue.md ✅ — config.yaml (NOT config.json); apiBase; requestOptions.headers - cline.md ✅ — "OpenAI Compatible" provider; Cline #7128 base-URL UI bug warning - cursor.md ⚠️ — known base-URL fragility; only enable models OLP serves - aider.md ✅ — OPENAI_API_BASE env + openai/ prefix; .env support - claude-code.md ❌ — explicitly NOT supported per ADR 0010 § /v1/messages defer rationale; recommended alternative: Cline + OLP - openclaw.md ✅ — install olp-plugin via CLI or symlink; configure apiKey; restart gateway Each ~60-120 lines: status / quick setup / known issues / OLP-specific notes / test-it command. docs/integrations/README.md is the index. ## D73 — README cross-references - New § "IDE Setup" links to docs/integrations/README.md - New § "Telegram / Discord Usage" — install + configure + restart + use - Quick Start mentions olp-connect <ip> as family-onboarding command - package.json `files` field extended to include olp-plugin/ so the published tarball ships the plugin ## Test count 672 → 696 (+24 D71-D73 tests in Suite 35: helpers / formatters / dispatch / error paths). All 696 pass locally. ## Scope discipline - server.mjs UNTOUCHED (plugin consumes EXISTING endpoints) - No new npm deps (no Telegram or Discord SDK — OpenClaw provides transport) - No /v1/messages (out of Phase 4 per ADR 0010) - No CHANGELOG / package.json version bump (Phase 4 close handles versioning; only package.json `files` extended for olp-plugin/ publication) ## Implementor flagged for reviewer 1. /olp doctor returns SSH advisory (no HTTP doctor endpoint yet). When future phase exposes /v0/management/doctor, swap advisory branch for real fetchJSON + fmtDoctor (already implemented + tested). 2. /olp providers + chain show have no FS access (plugin runs in OpenClaw gateway process); registry read via lazy-imported models-registry.json from repo root. For live enabled-state visibility users still need /olp status (owner-tier) or ssh + olp providers / olp chain show. 3. No live-server wire test in Suite 35 — existing Suites 31/32 already cover the integration path against the same endpoints; mock-fetch in Suite 35 is sufficient signal for the plugin layer. ## Authority - ADR 0010 § Phase 4 D-day plan D71-D73 line - OCP ocp-plugin/index.js (port reference) - ADR 0010 § Out-of-Phase-4-scope (claude-code.md ❌ rationale) - 2026-05-26 brainstorm (Top OCP inheritance candidates + prior-art survey IDE-specific quirks for cline/cursor/continue docs) Co-authored-by: dtzp555 <dtzp555@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# OLP IDE & client integrations
|
||||
|
||||
This directory documents per-tool setup for the IDEs and AI clients OLP
|
||||
supports. Every page follows the same shape: one-line description, status
|
||||
icon, copy-paste-able config block, known issues, OLP-specific notes, and a
|
||||
one-line verification command.
|
||||
|
||||
## Index
|
||||
|
||||
| Tool | Status | Path | Notes |
|
||||
|---|---|---|---|
|
||||
| [Continue.dev](./continue.md) | ✅ Supported | VS Code / JetBrains extension | `config.yaml` (NOT `config.json`); supports custom headers |
|
||||
| [Cline](./cline.md) | ✅ Supported | VS Code extension | OpenAI-compatible provider; UI field occasionally vanishes (Cline #7128) |
|
||||
| [Cursor](./cursor.md) | ⚠️ Best-effort | Cursor editor | "Override OpenAI Base URL" — known fragile across releases |
|
||||
| [Aider](./aider.md) | ✅ Supported | terminal CLI | `OPENAI_API_BASE` env + `openai/` model prefix |
|
||||
| [Claude Code](./claude-code.md) | ❌ Not supported | terminal CLI | Anthropic wire format only; OLP serves OpenAI wire format. Use Cline instead. |
|
||||
| [OpenClaw](./openclaw.md) | ✅ Supported | Telegram + Discord gateway | `/olp` slash command via the [`olp-plugin/`](../../olp-plugin/) plugin |
|
||||
|
||||
## Status legend
|
||||
|
||||
- ✅ **Supported** — works against OLP's OpenAI-compatible `/v1/chat/completions`
|
||||
endpoint; the tool's IR fields flow through OLP's IR without lossy translation
|
||||
warnings on the documented chain.
|
||||
- ⚠️ **Best-effort** — works in current versions but the tool has known
|
||||
upstream bugs around base-URL configuration; expect occasional weirdness.
|
||||
- ❌ **Not supported** — the tool's wire protocol or transport is incompatible
|
||||
with what OLP serves; recommended alternative is documented on the page.
|
||||
|
||||
## How OLP's response headers help debugging
|
||||
|
||||
Every response carries (see [README § Response Headers](../../README.md#response-headers)):
|
||||
|
||||
- `X-OLP-Provider-Used` — which provider's plugin served the request
|
||||
- `X-OLP-Model-Used` — which model the served provider used
|
||||
- `X-OLP-Fallback-Hops` — `0` = primary chain entry served it
|
||||
- `X-OLP-Cache` — `hit | miss | bypass`
|
||||
- `X-OLP-Latency-Ms` — end-to-end latency at the proxy
|
||||
|
||||
When something looks wrong in an IDE, the first sanity check is `curl -i`
|
||||
against `/v1/chat/completions` with the same key — those headers tell you
|
||||
whether the IDE config is broken or OLP routed somewhere unexpected.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [ADR 0010](../adr/0010-phase-4-charter-operator-and-client-ux.md) — Phase 4 charter; documents why `/v1/messages` is not supported and points to Cline as the recommended Anthropic-CLI replacement.
|
||||
- [ADR 0011](../adr/0011-anonymous-key-deployment-context.md) — trusted-LAN-only invariant for `auth.advertise_anonymous_key`.
|
||||
- [`bin/olp-connect`](../../bin/olp-connect) — automated client setup helper (D68-D70).
|
||||
@@ -0,0 +1,106 @@
|
||||
# Aider + OLP
|
||||
|
||||
[Aider](https://aider.chat) is a terminal-native pair programmer that
|
||||
edits files in your local git repo and commits each change. It speaks
|
||||
OpenAI's `/v1/chat/completions` wire format via the `openai/` model
|
||||
prefix.
|
||||
|
||||
**Status:** ✅ Supported.
|
||||
|
||||
**Tested against:** Aider v0.6x. Aider's OpenAI integration has been stable
|
||||
across many releases — this is the most reliable IDE/CLI binding to OLP.
|
||||
|
||||
## Quick setup
|
||||
|
||||
Three knobs, all environment variables or `.env`:
|
||||
|
||||
```bash
|
||||
# Required: point Aider at OLP's chat-completions endpoint
|
||||
export OPENAI_API_BASE=http://127.0.0.1:4567/v1
|
||||
|
||||
# Required: OLP plaintext token
|
||||
export OPENAI_API_KEY=olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
# Then invoke Aider with an OLP-routable model, prefixed `openai/`:
|
||||
aider --model openai/claude-sonnet-4-5
|
||||
```
|
||||
|
||||
The `openai/` prefix tells Aider to use its OpenAI-compatible adapter for
|
||||
the named model. Aider's litellm layer parses this and sends the request
|
||||
to whatever `OPENAI_API_BASE` resolves to.
|
||||
|
||||
Replace the API key with the plaintext token printed by `olp-keys keygen
|
||||
--name=aider`. Family members on the LAN should substitute the OLP host's
|
||||
IP for `127.0.0.1` (or use `olp-connect <ip>`).
|
||||
|
||||
## Aider's `.env` support
|
||||
|
||||
Aider auto-loads a `.env` file from the current directory or the git repo
|
||||
root. The accepted keys are:
|
||||
|
||||
```bash
|
||||
# .env at the project root
|
||||
OPENAI_API_BASE=http://127.0.0.1:4567/v1
|
||||
OPENAI_API_KEY=olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
# Optional: Aider's own AIDER_-prefixed equivalents work too
|
||||
AIDER_OPENAI_API_BASE=http://127.0.0.1:4567/v1
|
||||
```
|
||||
|
||||
The `AIDER_` prefix wins over the bare prefix when both are set. Pick one;
|
||||
mixing them invites surprises during debugging.
|
||||
|
||||
**Hygiene:** add `.env` to `.gitignore` if your repo doesn't already. The
|
||||
OLP token is plaintext-recoverable from disk only because the chat surface
|
||||
explicitly opts into it (see [ADR 0011](../adr/0011-anonymous-key-deployment-context.md))
|
||||
— do not let your IDE bind unintentionally.
|
||||
|
||||
## Known issues
|
||||
|
||||
- **No custom-headers support.** Aider does not expose a way to set extra
|
||||
HTTP headers on outgoing requests. OLP's optional `X-OLP-Chain` /
|
||||
`X-OLP-Bypass-Cache` headers are therefore not available via Aider —
|
||||
routing is determined by the model name alone.
|
||||
|
||||
- **`/v1` trailing matters.** `OPENAI_API_BASE` must end at `/v1` (without
|
||||
`/chat/completions`); Aider appends the remainder. Setting it to the bare
|
||||
host or with a trailing `/chat/completions` causes 404s.
|
||||
|
||||
- **Aider sends `max_tokens` by default.** OLP forwards `max_tokens` to
|
||||
every provider. If you see "model X does not support max_tokens" errors,
|
||||
the underlying provider rejects it — check `X-OLP-Provider-Used` and
|
||||
filter that provider out of the chain for the affected model.
|
||||
|
||||
## OLP-specific notes
|
||||
|
||||
Aider's request shape is faithful to OpenAI's `/v1/chat/completions`
|
||||
spec — `messages`, `model`, `max_tokens`, `stream`, `temperature`,
|
||||
`tools`. All map cleanly into OLP's IR with no lossy-translation warnings.
|
||||
|
||||
For long-context work (codebase summaries, large diffs), set
|
||||
`streaming.heartbeat_interval_ms: 15000` in `~/.olp/config.json` (see
|
||||
[README § Environment Variables](../../README.md#configjson-keys-introduced-at-phase-4))
|
||||
so the SSE stream stays alive through reverse proxies during silent
|
||||
windows.
|
||||
|
||||
## Test it
|
||||
|
||||
```bash
|
||||
# In a scratch dir:
|
||||
aider --model openai/claude-haiku-4-5 --no-stream --message "say ok"
|
||||
```
|
||||
|
||||
Then check OLP's audit log:
|
||||
|
||||
```bash
|
||||
npx olp logs 5
|
||||
```
|
||||
|
||||
The most recent entry should show `provider: anthropic` (or whatever
|
||||
provider haiku routes to in your chain) and `cache_status: miss`.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- Aider model config docs: https://aider.chat/docs/llms/openai-compat.html
|
||||
- [`olp-connect`](../../bin/olp-connect) writes `~/.aider/.env` if Aider is
|
||||
detected on PATH.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Claude Code + OLP
|
||||
|
||||
[Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) is
|
||||
Anthropic's official terminal-native agent. It speaks the Anthropic
|
||||
`/v1/messages` wire format and cannot be configured to use an
|
||||
OpenAI-compatible chat-completions endpoint.
|
||||
|
||||
**Status:** ❌ Not supported.
|
||||
|
||||
## Why
|
||||
|
||||
OLP serves only the OpenAI `/v1/chat/completions` wire format. Adding
|
||||
`/v1/messages` (the Anthropic shape) was explicitly considered for
|
||||
Phase 4 and rejected, per
|
||||
[ADR 0010 § Out of Phase 4 scope](../adr/0010-phase-4-charter-operator-and-client-ux.md).
|
||||
|
||||
The short version of the rationale:
|
||||
|
||||
- **No billing benefit.** After Anthropic's 2026-06-15 split, `claude -p` /
|
||||
Agent SDK / third-party agent traffic moves out of the Pro/Max
|
||||
subscription pool and into a separate paid Agent SDK Credit pool. OLP's
|
||||
fallback discipline ("when one provider's quota runs out, try the next")
|
||||
does not save money for this traffic — it just routes the same paid
|
||||
request to a different paid backend. The subscription leverage that
|
||||
makes OLP valuable for OpenAI-shape traffic does not exist for
|
||||
Anthropic-shape traffic.
|
||||
|
||||
- **Degrades worse on fallback.** When OLP's primary chain entry (Anthropic)
|
||||
is exhausted, the fallback hop is typically OpenAI Codex or Mistral Vibe.
|
||||
Those providers speak OpenAI tool-calling schema; OLP would have to
|
||||
translate Anthropic's `/v1/messages` tool shape into OpenAI tool shape on
|
||||
every fallback. That translation is lossy and is what ADR 0010 calls out
|
||||
as "net non-positive under P0 failure".
|
||||
|
||||
- **Same outcome reachable via the recommended alternative.** Cline, Cursor,
|
||||
Aider, and Continue.dev all speak OpenAI's wire format and have parity
|
||||
with Claude Code on the "AI edits files in my repo" use case. OLP serves
|
||||
them today.
|
||||
|
||||
## What to use instead
|
||||
|
||||
**Recommended:** [Cline](./cline.md). It's an in-IDE autonomous coder that
|
||||
operates on the same loop Claude Code does (read files, propose edits,
|
||||
run tools, iterate). The "OpenAI Compatible" provider points cleanly at
|
||||
OLP's `/v1/chat/completions` endpoint. You get OLP's full fallback chain
|
||||
(Anthropic → OpenAI Codex → Mistral) instead of being pinned to one
|
||||
provider.
|
||||
|
||||
For terminal users specifically:
|
||||
|
||||
- **[Aider](./aider.md)** if you want the Claude-Code-style git-aware
|
||||
pair programmer in the terminal.
|
||||
- **OpenClaw** if you want Telegram/Discord-driven access to the
|
||||
fallback chain (see [`openclaw.md`](./openclaw.md)).
|
||||
|
||||
## Re-open trigger
|
||||
|
||||
ADR 0010 documents the conditions under which OLP would reconsider
|
||||
`/v1/messages`:
|
||||
|
||||
> (a) ADR 0009 P0 confirms interactive-mode billing classification as
|
||||
> subscription (≥ 2026-07-15) AND (b) maintainer explicitly opens
|
||||
> Phase 5 "Anthropic-shape hub" scope with the name of at least one
|
||||
> family member who wants CC access.
|
||||
|
||||
Until both conditions fire, OLP intentionally does not implement
|
||||
`/v1/messages`. The decision is recorded in ADR 0010 § "Out of Phase 4
|
||||
scope" and ADR 0009 (Anthropic interactive-mode path placeholder).
|
||||
|
||||
## If you absolutely must use Claude Code
|
||||
|
||||
Point Claude Code at api.anthropic.com directly. OLP cannot proxy that
|
||||
traffic. You will:
|
||||
|
||||
- Burn against the Anthropic Pro/Max OAuth subscription (pre-2026-06-15) or
|
||||
the Agent SDK Credit pool (≥ 2026-06-15).
|
||||
- Lose every fallback property OLP provides — when Anthropic's quota is
|
||||
exhausted, Claude Code stops working until the quota resets.
|
||||
- Lose OLP's response headers (`X-OLP-Provider-Used` etc.), audit log
|
||||
entries, cache hits, and `/health` visibility.
|
||||
|
||||
This is documented here only so the trade-off is explicit, not as a
|
||||
recommendation.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [ADR 0010](../adr/0010-phase-4-charter-operator-and-client-ux.md) § "Out of Phase 4 scope" — full defer rationale.
|
||||
- [ADR 0009](../adr/0009-interactive-mode-path-placeholder.md) — Anthropic 2026-06-15 billing split and re-open trigger.
|
||||
- [`cline.md`](./cline.md) — the recommended alternative for Claude-Code-style workflows.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Cline + OLP
|
||||
|
||||
[Cline](https://github.com/cline/cline) is an autonomous-coder VS Code
|
||||
extension. It speaks OpenAI's `/v1/chat/completions` wire format via its
|
||||
"OpenAI Compatible" provider option.
|
||||
|
||||
**Status:** ✅ Supported.
|
||||
|
||||
**Tested against:** Cline v3.x (extension version visible in VS Code's
|
||||
extension panel). Cline's settings UI has shipped multiple variants of the
|
||||
base-URL field across 2025-2026; if your version doesn't show the field
|
||||
described below, see the Known Issues section.
|
||||
|
||||
## Quick setup
|
||||
|
||||
1. Open the Cline panel in VS Code (sidebar icon).
|
||||
2. Click the settings gear → "API Provider".
|
||||
3. Select **OpenAI Compatible**.
|
||||
4. Fill the fields:
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Base URL | `http://127.0.0.1:4567/v1` |
|
||||
| API Key | `olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` |
|
||||
| Model ID | `claude-sonnet-4-5` |
|
||||
|
||||
5. Save. Cline shows the model name in the bottom-right corner of the panel.
|
||||
|
||||
Replace the API key with the plaintext token printed by `olp-keys keygen
|
||||
--name=cline`. Family members on the LAN should substitute the OLP host's
|
||||
IP for `127.0.0.1` (or use `olp-connect <ip>`).
|
||||
|
||||
## Known issues
|
||||
|
||||
- **Cline issue [#7128](https://github.com/cline/cline/issues/7128) —
|
||||
base-URL UI field intermittently disappears.** Several Cline releases in
|
||||
2025-2026 shipped a settings UI where the "Base URL" field is hidden when
|
||||
the "OpenAI Compatible" provider is freshly selected. Workaround: switch
|
||||
to a different provider, save, switch back to "OpenAI Compatible" — the
|
||||
field returns. Verify the field is visible in your version BEFORE
|
||||
troubleshooting OLP itself.
|
||||
|
||||
- **Cline writes settings to `.vscode/settings.json` under a
|
||||
`cline.apiConfiguration` key (workspace-scoped) and to the VS Code global
|
||||
state (machine-scoped) depending on the "save to workspace" toggle.** If
|
||||
Cline keeps "forgetting" the OLP base URL across VS Code restarts, the
|
||||
workspace state is overriding the global state. Either save to workspace
|
||||
explicitly, or clear the workspace key and use global state.
|
||||
|
||||
- **Cline sometimes lowercases the model ID before sending.** OLP's
|
||||
`models-registry.json` uses canonical case (e.g. `claude-sonnet-4-5`).
|
||||
This is fine — OLP's router lowercases the requested model for chain
|
||||
lookup. But if you see `unknown model` errors, double-check the exact
|
||||
string Cline sent via the OLP response headers (curl test below).
|
||||
|
||||
## OLP-specific notes
|
||||
|
||||
Cline does not expose a custom-headers field in its OpenAI Compatible
|
||||
provider UI as of v3.x. The OLP routing chain is selected purely from the
|
||||
model ID — pick the canonical name (e.g. `claude-sonnet-4-5`) that matches
|
||||
a `routing.chains` key in your `~/.olp/config.json`.
|
||||
|
||||
OLP's response headers (`X-OLP-Provider-Used`, `X-OLP-Cache`,
|
||||
`X-OLP-Latency-Ms`) are not visible in Cline's UI but are captured by VS
|
||||
Code's Developer Tools Network panel when Cline runs the request.
|
||||
|
||||
## Test it
|
||||
|
||||
```bash
|
||||
# 1. Verify OLP accepts Cline-shape requests
|
||||
curl -sI -X POST http://127.0.0.1:4567/v1/chat/completions \
|
||||
-H "Authorization: Bearer olp_XXXXXX" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"ok"}],"max_tokens":5,"stream":false}' \
|
||||
| grep -i x-olp
|
||||
```
|
||||
|
||||
Expect `X-OLP-Provider-Used: anthropic` (or whichever provider serves
|
||||
sonnet in your chain) and `X-OLP-Cache: miss` on first request.
|
||||
|
||||
## Why not /v1/messages?
|
||||
|
||||
Cline supports Anthropic-shape requests via a separate "Anthropic" provider
|
||||
in its UI. OLP does not implement `/v1/messages`. Use Cline's **OpenAI
|
||||
Compatible** option pointed at OLP rather than Cline's **Anthropic** option
|
||||
pointed at api.anthropic.com — the OLP chain gives you fallback to OpenAI
|
||||
Codex / Mistral / etc. when the Anthropic subscription hits its quota
|
||||
ceiling. See [ADR 0010 § /v1/messages defer rationale](../adr/0010-phase-4-charter-operator-and-client-ux.md).
|
||||
|
||||
## Cross-references
|
||||
|
||||
- Cline issue tracker: https://github.com/cline/cline/issues
|
||||
- [`olp-connect`](../../bin/olp-connect) automates writing the Cline workspace
|
||||
state.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Continue.dev + OLP
|
||||
|
||||
[Continue.dev](https://continue.dev) is an open-source autocomplete +
|
||||
chat extension for VS Code and JetBrains IDEs. It speaks OpenAI's
|
||||
`/v1/chat/completions` wire format, so it works against OLP with no
|
||||
shim layer.
|
||||
|
||||
**Status:** ✅ Supported.
|
||||
|
||||
**Tested against:** Continue.dev v0.10.x (`config.yaml` schema). The
|
||||
older `config.json` schema (≤ v0.8) is **not** documented here — Continue
|
||||
deprecated it in late 2025 and emits a one-shot migration warning.
|
||||
|
||||
## Quick setup
|
||||
|
||||
Edit `~/.continue/config.yaml` (or open the Continue config from the IDE's
|
||||
extension panel and paste this in):
|
||||
|
||||
```yaml
|
||||
models:
|
||||
- name: olp-chat
|
||||
provider: openai
|
||||
model: claude-sonnet-4-5
|
||||
apiBase: http://127.0.0.1:4567/v1
|
||||
apiKey: olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
roles:
|
||||
- chat
|
||||
requestOptions:
|
||||
headers:
|
||||
# Optional: pin which routing chain key applies. If omitted, OLP
|
||||
# looks up the chain via the model name above.
|
||||
X-OLP-Chain: claude-sonnet-4-5
|
||||
- name: olp-autocomplete
|
||||
provider: openai
|
||||
model: claude-haiku-4-5
|
||||
apiBase: http://127.0.0.1:4567/v1
|
||||
apiKey: olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
roles:
|
||||
- autocomplete
|
||||
```
|
||||
|
||||
Replace the API key with the plaintext token printed by `olp-keys keygen
|
||||
--name=continue-dev`. Family members on the LAN should substitute the OLP
|
||||
host's IP for `127.0.0.1` (or use `olp-connect <ip>` to do this for them
|
||||
automatically).
|
||||
|
||||
## Known issues
|
||||
|
||||
- **`apiBase`, NOT `baseURL`.** Continue's YAML schema uses `apiBase` (no
|
||||
`URL` casing). The older `config.json` `baseURL` key was renamed during the
|
||||
v0.10 schema cut. If you copy a snippet from a 2024 blog post and it
|
||||
silently routes to api.openai.com, this is why.
|
||||
- **Trailing `/v1` matters.** OLP's chat-completions endpoint is at
|
||||
`/v1/chat/completions`; Continue appends `/chat/completions` to whatever
|
||||
`apiBase` resolves to. Set `apiBase: http://host:4567/v1` (with `/v1`),
|
||||
not the bare host.
|
||||
- **Provider stays `openai`.** Continue's `provider: anthropic` would send
|
||||
Anthropic-shape requests to `/v1/messages`, which OLP does not implement
|
||||
(see [`claude-code.md`](./claude-code.md) for the rationale).
|
||||
|
||||
## OLP-specific notes
|
||||
|
||||
Continue's `requestOptions.headers` lets you pin OLP-specific routing
|
||||
behaviour without altering the model name itself. Useful headers:
|
||||
|
||||
- `X-OLP-Chain: <chain-key>` — explicitly select the routing chain.
|
||||
- `X-OLP-Bypass-Cache: true` — force a fresh spawn for the next request
|
||||
(debugging cache-poisoning suspicions).
|
||||
|
||||
OLP's response headers (`X-OLP-Provider-Used`, `X-OLP-Cache`, etc.) are
|
||||
visible via VS Code's `Developer: Toggle Developer Tools` → Network panel
|
||||
when Continue runs the request.
|
||||
|
||||
## Test it
|
||||
|
||||
After config save, open the Continue chat panel and send a one-word
|
||||
message ("ok"). Then on the terminal:
|
||||
|
||||
```bash
|
||||
curl -sI -X POST http://127.0.0.1:4567/v1/chat/completions \
|
||||
-H "Authorization: Bearer olp_XXXXXX" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"claude-haiku-4-5","messages":[{"role":"user","content":"ok"}],"max_tokens":5}' \
|
||||
| grep -i x-olp
|
||||
```
|
||||
|
||||
Expect `X-OLP-Provider-Used: anthropic` (or whichever provider your chain
|
||||
routes haiku to) and `X-OLP-Cache: miss` on first request, `hit` on the
|
||||
second.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- Continue.dev config reference: https://docs.continue.dev/customization/models
|
||||
- [`olp-connect`](../../bin/olp-connect) automates the Continue.dev branch
|
||||
of this setup.
|
||||
@@ -0,0 +1,116 @@
|
||||
# Cursor + OLP
|
||||
|
||||
[Cursor](https://cursor.com) is an AI-first VS Code fork. It has an
|
||||
"Override OpenAI Base URL" setting that, when populated, routes its
|
||||
default-model traffic to your URL using the OpenAI wire format.
|
||||
|
||||
**Status:** ⚠️ Best-effort.
|
||||
|
||||
**Reason:** Cursor's base-URL override is known to be fragile across
|
||||
releases. Multiple 2025-2026 forum threads document the setting silently
|
||||
reverting, model-list dropdowns not populating from the override URL, and
|
||||
streaming responses falling back to the default backend on parse errors.
|
||||
The behaviour is not specific to OLP — every OpenAI-compatible proxy
|
||||
maintainer documents the same caveats — but Cursor's release cadence is
|
||||
faster than most third-party proxies can test against.
|
||||
|
||||
## Quick setup
|
||||
|
||||
1. Open Cursor → Settings → "Models" → enable **OpenAI API Key**.
|
||||
2. Paste your OLP plaintext token into the **API Key** field.
|
||||
3. Click "Override OpenAI Base URL" and paste:
|
||||
|
||||
```
|
||||
http://127.0.0.1:4567/v1
|
||||
```
|
||||
|
||||
4. Click "Verify". Cursor sends a probe; on success the indicator turns
|
||||
green.
|
||||
|
||||
5. **Crucial step:** in the model list, disable every model that is NOT
|
||||
in your `~/.olp/config.json` `routing.chains`. Cursor's chat will round-
|
||||
robin across enabled models and any model OLP can't route will error.
|
||||
|
||||
Replace the API key with the plaintext token printed by `olp-keys keygen
|
||||
--name=cursor`. Family members on the LAN should substitute the OLP host's
|
||||
IP for `127.0.0.1` (or use `olp-connect <ip>`).
|
||||
|
||||
## Known issues
|
||||
|
||||
- **Override URL silently reverts on Cursor update.** Two reported variants:
|
||||
(a) the field empties; (b) the field shows the OLP URL but Cursor still
|
||||
hits api.openai.com under the hood. Workaround: after every Cursor
|
||||
update, re-open settings, click "Verify" again, and check the OLP
|
||||
server's `/health` for incoming probe requests.
|
||||
|
||||
- **Model-list dropdown does not populate from the override URL.** Cursor
|
||||
hardcodes its model list rather than reading `GET /v1/models`. This is
|
||||
why step 5 above is required — there is no way to make Cursor "discover"
|
||||
your models. You have to disable each model individually that OLP can't
|
||||
serve.
|
||||
|
||||
- **Streaming response parsing is stricter than OpenAI's actual SSE spec.**
|
||||
Cursor occasionally falls back to the default backend if the SSE stream
|
||||
contains a slightly malformed chunk (e.g. an empty `data:` line that
|
||||
OpenAI's API does emit but Cursor's parser doesn't expect). OLP's SSE
|
||||
emitter follows the spec; this is on Cursor's side. If you see traffic
|
||||
hitting api.openai.com despite the override, this is the most likely
|
||||
cause.
|
||||
|
||||
- **Cursor's "Tab" autocomplete is NOT covered by the override.** Tab
|
||||
completion uses a Cursor-proprietary endpoint that is not affected by the
|
||||
OpenAI base URL setting. Only the chat panel is. This is documented
|
||||
Cursor behaviour and is not a bug.
|
||||
|
||||
## OLP-specific notes
|
||||
|
||||
Cursor sends `model: "gpt-4"` or `model: "gpt-3.5-turbo"` (legacy aliases)
|
||||
unless you explicitly select another from its dropdown. Add aliases to
|
||||
your `~/.olp/config.json` `routing.chains` so these route somewhere sane:
|
||||
|
||||
```json
|
||||
{
|
||||
"routing": {
|
||||
"chains": {
|
||||
"gpt-4": [ { "provider": "openai", "model": "gpt-5" } ],
|
||||
"gpt-3.5-turbo": [ { "provider": "openai", "model": "gpt-5-mini" } ]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
(Substitute the OpenAI Codex model names listed by `olp models`.)
|
||||
|
||||
## Recommendation
|
||||
|
||||
**Do not engineer workarounds for Cursor-side bugs.** Cursor's release
|
||||
cadence will fix or re-break the override URL handling at unpredictable
|
||||
intervals. If your daily-driver flow is unreliable, switch to Cline (see
|
||||
[`cline.md`](./cline.md)) — it has a stable OpenAI-compatible provider
|
||||
that does not break across releases.
|
||||
|
||||
## Test it
|
||||
|
||||
```bash
|
||||
curl -sI -X POST http://127.0.0.1:4567/v1/chat/completions \
|
||||
-H "Authorization: Bearer olp_XXXXXX" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"gpt-4","messages":[{"role":"user","content":"ok"}],"max_tokens":5}' \
|
||||
| grep -i x-olp
|
||||
```
|
||||
|
||||
After hitting "Send" in Cursor's chat, check the OLP server's recent
|
||||
requests via:
|
||||
|
||||
```bash
|
||||
npx olp logs 10
|
||||
```
|
||||
|
||||
If you don't see Cursor's request in the audit log, traffic isn't reaching
|
||||
OLP — re-check the override URL.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- Cursor forum threads on base-URL fragility: https://forum.cursor.com/ (search "OpenAI base URL")
|
||||
- [`olp-connect`](../../bin/olp-connect) writes Cursor's `cursorrc` if
|
||||
detected, but cannot guarantee the override survives a Cursor update.
|
||||
@@ -0,0 +1,146 @@
|
||||
# OpenClaw + OLP
|
||||
|
||||
[OpenClaw](https://github.com/openclaw/openclaw) is a multi-bot gateway
|
||||
that exposes slash commands on Telegram, Discord, and other chat
|
||||
surfaces. OLP ships [`olp-plugin/`](../../olp-plugin/) as a native
|
||||
OpenClaw plugin that registers a `/olp` slash command with read-only
|
||||
parity to the local `olp` CLI.
|
||||
|
||||
**Status:** ✅ Supported.
|
||||
|
||||
## What you get
|
||||
|
||||
After install, from Telegram or Discord:
|
||||
|
||||
| Slash command | Maps to | Tier |
|
||||
|---|---|---|
|
||||
| `/olp status` | GET `/v0/management/status` | owner |
|
||||
| `/olp health` | GET `/health` | public |
|
||||
| `/olp usage` | GET `/v0/management/dashboard-data` | owner |
|
||||
| `/olp models` | GET `/v1/models` | public |
|
||||
| `/olp cache` | GET `/cache/stats` | owner |
|
||||
| `/olp providers` | local registry view | public |
|
||||
| `/olp chain show [model]` | local chain view | public |
|
||||
| `/olp doctor` | informational (HTTP endpoint not yet shipped) | — |
|
||||
| `/olp help` | usage text | — |
|
||||
|
||||
**Mutating subcommands are deliberately not exposed via chat.** `keygen`,
|
||||
`revoke`, `restart`, `logs` are SSH-only. See
|
||||
[`olp-plugin/README.md`](../../olp-plugin/README.md#what-you-can-not-do-from-chat-by-design)
|
||||
for the rationale.
|
||||
|
||||
## Quick setup
|
||||
|
||||
### 1. Install the plugin
|
||||
|
||||
Two install paths — either works.
|
||||
|
||||
**Option A — OpenClaw CLI:**
|
||||
|
||||
```bash
|
||||
openclaw plugins install /path/to/olp/olp-plugin/
|
||||
```
|
||||
|
||||
**Option B — symlink:**
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.openclaw/extensions/
|
||||
ln -s /path/to/olp/olp-plugin/ ~/.openclaw/extensions/olp
|
||||
```
|
||||
|
||||
### 2. Mint a bot owner key
|
||||
|
||||
Run on the OLP host (NOT in chat):
|
||||
|
||||
```bash
|
||||
npx olp-keys keygen --owner --name=openclaw-bot
|
||||
```
|
||||
|
||||
Capture the printed plaintext token — it is shown exactly once.
|
||||
|
||||
### 3. Configure
|
||||
|
||||
Edit `~/.openclaw/openclaw.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"olp": {
|
||||
"proxyUrl": "http://127.0.0.1:4567",
|
||||
"apiKey": "olp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Restart the gateway
|
||||
|
||||
```bash
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
The plugin is now active. Try `/olp help` in your bot's chat.
|
||||
|
||||
## Known issues
|
||||
|
||||
- **`openclaw gateway restart` is required after install.** OpenClaw caches
|
||||
plugin discovery at gateway start. `openclaw plugins reload` does not
|
||||
guarantee a fresh import of the plugin module.
|
||||
|
||||
- **Owner key revocation kicks the plugin out immediately.** If you revoke
|
||||
the bot's owner key (`npx olp-keys revoke --id=<id>`), the next `/olp
|
||||
status` will return `401 unauthorized`. Mint a replacement key with a
|
||||
new name and edit `~/.openclaw/openclaw.json`; do NOT reuse the revoked
|
||||
key's UUID.
|
||||
|
||||
- **Long responses are truncated.** Telegram caps messages at ~4096
|
||||
characters. The plugin truncates with a `... [truncated, use SSH for
|
||||
full]` suffix when the rendered output would exceed ~3900 chars. Use
|
||||
SSH + the local `olp` CLI for full output.
|
||||
|
||||
## OLP-specific notes
|
||||
|
||||
The plugin honours these env vars on the OpenClaw gateway process:
|
||||
|
||||
- `OLP_PROXY_URL` — full URL, overrides plugin config `proxyUrl`.
|
||||
- `OLP_PORT` — port only, localhost assumed; overrides `proxyUrl` when
|
||||
`OLP_PROXY_URL` is unset.
|
||||
|
||||
If you run the OpenClaw gateway under launchd or systemd with custom env
|
||||
vars, set `OLP_PROXY_URL` there rather than editing the plugin config —
|
||||
that way the same plugin install can serve multiple OLP hosts.
|
||||
|
||||
## Per-bot vs maintainer key
|
||||
|
||||
**Always create a dedicated bot key**, never the maintainer's personal
|
||||
owner key. The bot key:
|
||||
|
||||
- Has its own `id` so you can revoke it without affecting other clients.
|
||||
- Has its own audit-log entries so you can attribute `/v0/management/*`
|
||||
traffic to the bot.
|
||||
- Can be rotated routinely (every 90 days etc.) without coordinating with
|
||||
the maintainer's daily-driver IDE configs.
|
||||
|
||||
## Test it
|
||||
|
||||
After restart, in Telegram or Discord:
|
||||
|
||||
```
|
||||
/olp health
|
||||
/olp status
|
||||
/olp models
|
||||
```
|
||||
|
||||
Each should return a code-block-wrapped response within a few seconds.
|
||||
|
||||
If you see `401 unauthorized`: the configured key is missing / wrong /
|
||||
revoked. If you see `403 forbidden`: the key is not owner-tier. If you
|
||||
see `OLP error: fetch failed` or similar: the `proxyUrl` is unreachable
|
||||
from the gateway host (test with `curl http://<proxyUrl>/health` from
|
||||
that host).
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [`olp-plugin/README.md`](../../olp-plugin/README.md) — full plugin docs.
|
||||
- [ADR 0010 § Phase 4 D71-D73](../adr/0010-phase-4-charter-operator-and-client-ux.md) — the plugin's charter.
|
||||
- [OCP `/ocp` plugin](https://github.com/dtzp555-max/ocp/tree/main/ocp-plugin) — the OCP predecessor (includes mutating subcommands that OLP deliberately drops).
|
||||
Reference in New Issue
Block a user