mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-22 05:25:08 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f3355d415 |
@@ -1,11 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Unreleased
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- **Default `sonnet` alias → `claude-sonnet-5`.** The `sonnet` alias (the model used for every `/v1/chat/completions` request that omits `model`, and OpenClaw's OCP primary via `ocp-connect`) now resolves to `claude-sonnet-5` instead of `claude-sonnet-4-6`. `claude-sonnet-4-6` remains available by full ID for pinning. This is a behavior change for clients relying on the default — pin `claude-sonnet-4-6` explicitly to retain the previous model. Split out from the additive `claude-sonnet-5` model entry (#152) per Iron Rule 11.
|
|
||||||
|
|
||||||
## v3.22.1 — 2026-07-17
|
## v3.22.1 — 2026-07-17
|
||||||
|
|
||||||
Minor release: TUI-mode latency and streaming features — **all opt-in and off by default**, so the default request path (`-p` / `--output-format stream-json`) is byte-for-byte unchanged — plus hardening from an independent (Codex) re-review of the streaming work, Windows `claude.exe` startup resolution, and the Claude Sonnet 5 model entry. No new `cli.js` wire behavior and no new endpoint; the new surface is entirely OCP-owned TUI-mode configuration (env vars), startup binary discovery, model metadata, and `/health` observation. Every code PR carried a fresh-context reviewer (Iron Rule 10). (Version note: v3.22.0 was prepared but never tagged; its contents ship here as v3.22.1 together with the additions below.)
|
Minor release: TUI-mode latency and streaming features — **all opt-in and off by default**, so the default request path (`-p` / `--output-format stream-json`) is byte-for-byte unchanged — plus hardening from an independent (Codex) re-review of the streaming work, Windows `claude.exe` startup resolution, and the Claude Sonnet 5 model entry. No new `cli.js` wire behavior and no new endpoint; the new surface is entirely OCP-owned TUI-mode configuration (env vars), startup binary discovery, model metadata, and `/health` observation. Every code PR carried a fresh-context reviewer (Iron Rule 10). (Version note: v3.22.0 was prepared but never tagged; its contents ship here as v3.22.1 together with the additions below.)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ One proxy. Multiple IDEs. All models. **$0 API cost.**
|
|||||||
There are several Claude proxy projects. OCP picks a specific lane: **align tightly with what `cli.js` actually does, observe + multiplex what's already there, don't extend the protocol.** What you get:
|
There are several Claude proxy projects. OCP picks a specific lane: **align tightly with what `cli.js` actually does, observe + multiplex what's already there, don't extend the protocol.** What you get:
|
||||||
|
|
||||||
- **LAN multi-user keys** (v3.7.0) — reach one Claude Pro/Max subscription from your own devices across the LAN. Each device gets a per-key API token (no OAuth session leak), with independent usage tracking and one-line revocation. Pro/Max are **per-user** accounts — see [Sharing with family / a team — honest limits](#deployment-model--security-read-this) before extending access to other **people**.
|
- **LAN multi-user keys** (v3.7.0) — reach one Claude Pro/Max subscription from your own devices across the LAN. Each device gets a per-key API token (no OAuth session leak), with independent usage tracking and one-line revocation. Pro/Max are **per-user** accounts — see [Sharing with family / a team — honest limits](#deployment-model--security-read-this) before extending access to other **people**.
|
||||||
- **`ocp-connect` one-shot client setup** — one command on the client machine auto-configures OpenClaw, and detects Cursor, Cline, Continue.dev, and opencode to print ready-to-paste setup hints for each. No hunting for where each tool keeps its `OPENAI_BASE_URL`.
|
- **`ocp-connect` one-shot IDE setup** — one command on the client machine detects and configures Claude Code, Cursor, Cline, Continue.dev, OpenCode, and OpenClaw. No pasting `OPENAI_BASE_URL` six times.
|
||||||
- **Response cache with per-key isolation + singleflight** (v3.13.0). Optional SHA-256 prompt cache, isolated per API key (cross-user pollution is impossible by hash construction, not by application logic), with stampede protection on concurrent identical prompts. Off by default. ([PR #65](https://github.com/dtzp555-max/ocp/pull/65), [PR #66](https://github.com/dtzp555-max/ocp/pull/66))
|
- **Response cache with per-key isolation + singleflight** (v3.13.0). Optional SHA-256 prompt cache, isolated per API key (cross-user pollution is impossible by hash construction, not by application logic), with stampede protection on concurrent identical prompts. Off by default. ([PR #65](https://github.com/dtzp555-max/ocp/pull/65), [PR #66](https://github.com/dtzp555-max/ocp/pull/66))
|
||||||
- **Per-key request quotas** (v3.8.0). Daily / weekly / monthly limits per key — set a kid's iPad to 20/day, a partner's laptop to 100/week. ([PR #18](https://github.com/dtzp555-max/ocp/pull/18))
|
- **Per-key request quotas** (v3.8.0). Daily / weekly / monthly limits per key — set a kid's iPad to 20/day, a partner's laptop to 100/week. ([PR #18](https://github.com/dtzp555-max/ocp/pull/18))
|
||||||
- **SSE heartbeat for long reasoning** ([v3.12.0](https://github.com/dtzp555-max/ocp/releases/tag/v3.12.0), opt-in). If you've ever watched your IDE die at the 60s idle mark during a long Claude tool-use pause — that's nginx/Cloudflare default behavior. OCP emits an SSE comment frame to keep the connection alive without polluting the response. ([PR #49](https://github.com/dtzp555-max/ocp/pull/49))
|
- **SSE heartbeat for long reasoning** ([v3.12.0](https://github.com/dtzp555-max/ocp/releases/tag/v3.12.0), opt-in). If you've ever watched your IDE die at the 60s idle mark during a long Claude tool-use pause — that's nginx/Cloudflare default behavior. OCP emits an SSE comment frame to keep the connection alive without polluting the response. ([PR #49](https://github.com/dtzp555-max/ocp/pull/49))
|
||||||
@@ -121,7 +121,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/README.md
|
|||||||
installed and logged in (`claude auth status`). Install missing pieces
|
installed and logged in (`claude auth status`). Install missing pieces
|
||||||
using my system's package manager.
|
using my system's package manager.
|
||||||
2. git clone the repo, cd in, and run `node setup.mjs`.
|
2. git clone the repo, cd in, and run `node setup.mjs`.
|
||||||
3. Verify with `curl http://127.0.0.1:3456/v1/models` (should list 6 models).
|
3. Verify with `curl http://127.0.0.1:3456/v1/models` (should list 5 models).
|
||||||
4. Add `export OPENAI_BASE_URL=http://127.0.0.1:3456/v1` to my shell rc.
|
4. Add `export OPENAI_BASE_URL=http://127.0.0.1:3456/v1` to my shell rc.
|
||||||
5. Tell me to reload my shell and try a tool like Cline / Continue / Cursor.
|
5. Tell me to reload my shell and try a tool like Cline / Continue / Cursor.
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/README.md
|
|||||||
5. Add OCP_ADMIN_KEY to my shell rc (~/.zshrc or ~/.bashrc).
|
5. Add OCP_ADMIN_KEY to my shell rc (~/.zshrc or ~/.bashrc).
|
||||||
6. Run `ocp lan` to show me the LAN IP and connect command.
|
6. Run `ocp lan` to show me the LAN IP and connect command.
|
||||||
7. Optionally create example keys: `ocp keys add laptop`, `ocp keys add tablet`.
|
7. Optionally create example keys: `ocp keys add laptop`, `ocp keys add tablet`.
|
||||||
8. Verify: `curl http://127.0.0.1:3456/v1/models` returns 6 models.
|
8. Verify: `curl http://127.0.0.1:3456/v1/models` returns 5 models.
|
||||||
|
|
||||||
Tell me each step before running it. On error, diagnose before retrying.
|
Tell me each step before running it. On error, diagnose before retrying.
|
||||||
```
|
```
|
||||||
@@ -157,7 +157,8 @@ Tell me each step before running it. On error, diagnose before retrying.
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
There's an OCP server at <SERVER_IP> on my LAN. Configure this machine to
|
There's an OCP server at <SERVER_IP> on my LAN. Configure this machine to
|
||||||
use it for any local IDEs (Cursor, Cline, Continue.dev, OpenCode, OpenClaw).
|
use it for any local IDEs (Cursor, Cline, Continue.dev, OpenCode, Claude
|
||||||
|
Code, OpenClaw).
|
||||||
|
|
||||||
Server IP: <SERVER_IP>
|
Server IP: <SERVER_IP>
|
||||||
API key (leave blank if the server has anonymous mode enabled): <OPTIONAL_KEY>
|
API key (leave blank if the server has anonymous mode enabled): <OPTIONAL_KEY>
|
||||||
@@ -170,7 +171,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/README.md
|
|||||||
chmod +x ocp-connect
|
chmod +x ocp-connect
|
||||||
2. Run `./ocp-connect <SERVER_IP>` (add `--key <KEY>` if you have one).
|
2. Run `./ocp-connect <SERVER_IP>` (add `--key <KEY>` if you have one).
|
||||||
3. Follow any IDE-specific manual hints it prints.
|
3. Follow any IDE-specific manual hints it prints.
|
||||||
4. Verify: `curl http://<SERVER_IP>:3456/v1/models` returns 6 models.
|
4. Verify: `curl http://<SERVER_IP>:3456/v1/models` returns 5 models.
|
||||||
5. Tell me to reload my shell + restart any IDE that was already running.
|
5. Tell me to reload my shell + restart any IDE that was already running.
|
||||||
|
|
||||||
Don't auto-retry on error. Tell me the failure mode first.
|
Don't auto-retry on error. Tell me the failure mode first.
|
||||||
@@ -240,7 +241,7 @@ Run `ocp lan` to see your IP and ready-to-share instructions.
|
|||||||
**Verify:**
|
**Verify:**
|
||||||
```bash
|
```bash
|
||||||
curl http://127.0.0.1:3456/v1/models
|
curl http://127.0.0.1:3456/v1/models
|
||||||
# Returns: claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-5, claude-sonnet-4-6, claude-haiku-4-5-20251001
|
# Returns: claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5-20251001
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Headless install notes
|
#### Headless install notes
|
||||||
@@ -319,7 +320,7 @@ OCP Connect v1.3.0
|
|||||||
(set by admin via PROXY_ANONYMOUS_KEY; see issue #12 §14 Path A)
|
(set by admin via PROXY_ANONYMOUS_KEY; see issue #12 §14 Path A)
|
||||||
|
|
||||||
Testing API access...
|
Testing API access...
|
||||||
✓ API accessible (6 models available)
|
✓ API accessible (5 models available)
|
||||||
|
|
||||||
Shell config:
|
Shell config:
|
||||||
✓ .bashrc
|
✓ .bashrc
|
||||||
@@ -352,7 +353,6 @@ OCP Connect v1.3.0
|
|||||||
• ocp/claude-opus-4-8
|
• ocp/claude-opus-4-8
|
||||||
• ocp/claude-opus-4-7
|
• ocp/claude-opus-4-7
|
||||||
• ocp/claude-opus-4-6
|
• ocp/claude-opus-4-6
|
||||||
• ocp/claude-sonnet-5
|
|
||||||
• ocp/claude-sonnet-4-6
|
• ocp/claude-sonnet-4-6
|
||||||
• ocp/claude-haiku-4-5-20251001
|
• ocp/claude-haiku-4-5-20251001
|
||||||
Priority: PRIMARY (default model)
|
Priority: PRIMARY (default model)
|
||||||
@@ -577,9 +577,9 @@ The simplest path: ask your AI.
|
|||||||
|
|
||||||
What `ocp update` does:
|
What `ocp update` does:
|
||||||
|
|
||||||
- **Patch bump** (e.g. `v3.21.0 → v3.21.1`):
|
- **Patch bump** (e.g. `v3.14.0 → v3.14.1`):
|
||||||
light path (git pull + npm install + restart).
|
light path (git pull + npm install + restart).
|
||||||
- **Cross-minor** (e.g. `v3.18 → v3.22`):
|
- **Cross-minor** (e.g. `v3.10 → v3.14`):
|
||||||
full path: pre-flight check, snapshot, `setup.mjs` (with plist env-merge),
|
full path: pre-flight check, snapshot, `setup.mjs` (with plist env-merge),
|
||||||
service restart, post-flight `/health` and `/v1/models` verification.
|
service restart, post-flight `/health` and `/v1/models` verification.
|
||||||
- **Old version** (< v3.4.0):
|
- **Old version** (< v3.4.0):
|
||||||
@@ -716,8 +716,8 @@ Any tool use happens server-side, under the `--allowedTools` set configured on t
|
|||||||
| `claude-opus-4-8` | Most capable (default for `opus` alias) |
|
| `claude-opus-4-8` | Most capable (default for `opus` alias) |
|
||||||
| `claude-opus-4-7` | Previous Opus, retained for pinning |
|
| `claude-opus-4-7` | Previous Opus, retained for pinning |
|
||||||
| `claude-opus-4-6` | Older Opus, retained for pinning |
|
| `claude-opus-4-6` | Older Opus, retained for pinning |
|
||||||
| `claude-sonnet-5` | Latest Sonnet (default for `sonnet` alias) |
|
| `claude-sonnet-5` | Latest Sonnet (available by full ID; `sonnet` alias repoint tracked separately) |
|
||||||
| `claude-sonnet-4-6` | Previous Sonnet, retained for pinning |
|
| `claude-sonnet-4-6` | Good balance of speed/quality (default for `sonnet` alias) |
|
||||||
| `claude-haiku-4-5-20251001` | Fastest, lightweight (default for `haiku` alias) |
|
| `claude-haiku-4-5-20251001` | Fastest, lightweight (default for `haiku` alias) |
|
||||||
|
|
||||||
The canonical list lives in [`models.json`](./models.json) — the single source of truth as of v3.11.0. Both `server.mjs` (the `/v1/models` endpoint) and `setup.mjs` (the OpenClaw registration) derive from it. Adding a new model is now a one-file edit:
|
The canonical list lives in [`models.json`](./models.json) — the single source of truth as of v3.11.0. Both `server.mjs` (the `/v1/models` endpoint) and `setup.mjs` (the OpenClaw registration) derive from it. Adding a new model is now a one-file edit:
|
||||||
@@ -827,12 +827,11 @@ lsof -nP -iTCP:3456 -sTCP:LISTEN
|
|||||||
If it's an old OCP process, stop it before re-running setup:
|
If it's an old OCP process, stop it before re-running setup:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
launchctl bootout gui/$(id -u)/dev.ocp.proxy # macOS launchd
|
ocp stop # if the CLI is on PATH
|
||||||
systemctl --user stop ocp-proxy # Linux systemd (installed as a --user unit)
|
launchctl bootout gui/$(id -u)/dev.ocp.proxy # macOS launchd fallback
|
||||||
|
sudo systemctl stop ocp-proxy # Linux systemd fallback
|
||||||
```
|
```
|
||||||
|
|
||||||
(There is no `ocp stop` subcommand — the proxy runs as a service, so stopping it goes through the service manager above. `ocp restart` exists for the bounce case.)
|
|
||||||
|
|
||||||
### Setup fails with "node: command not found" or version error
|
### Setup fails with "node: command not found" or version error
|
||||||
|
|
||||||
OCP requires Node.js 22.5+. Install:
|
OCP requires Node.js 22.5+. Install:
|
||||||
@@ -949,7 +948,6 @@ See [Subscription-pool (TUI) mode](#subscription-pool-tui-mode) and ADR 0007 PR-
|
|||||||
| `CLAUDE_CACHE_TTL` | `0` | Response cache TTL (ms, 0 = disabled). Set to e.g. `300000` for 5-min cache |
|
| `CLAUDE_CACHE_TTL` | `0` | Response cache TTL (ms, 0 = disabled). Set to e.g. `300000` for 5-min cache |
|
||||||
| `CLAUDE_ALLOWED_TOOLS` | `Bash,Read,...,Agent` | Comma-separated tools to pre-approve |
|
| `CLAUDE_ALLOWED_TOOLS` | `Bash,Read,...,Agent` | Comma-separated tools to pre-approve |
|
||||||
| `CLAUDE_SKIP_PERMISSIONS` | `false` | Bypass all permission checks |
|
| `CLAUDE_SKIP_PERMISSIONS` | `false` | Bypass all permission checks |
|
||||||
| `CLAUDE_MCP_CONFIG` | *(unset)* | Path to an MCP server config JSON, passed to the spawned `claude` as `--mcp-config` (both the `-p` path and TUI `OCP_TUI_FULL_TOOLS` panes) |
|
|
||||||
| `CLAUDE_NO_CONTEXT` | `false` | Suppress CLAUDE.md and auto-memory injection (pure API mode) |
|
| `CLAUDE_NO_CONTEXT` | `false` | Suppress CLAUDE.md and auto-memory injection (pure API mode) |
|
||||||
| `PROXY_API_KEY` | *(unset)* | Bearer token for shared-mode authentication |
|
| `PROXY_API_KEY` | *(unset)* | Bearer token for shared-mode authentication |
|
||||||
| `PROXY_ANONYMOUS_KEY` | *(unset)* | Well-known anonymous key allowlist (multi mode). When set, this exact string bypasses `validateKey()` and grants public access. Exposed via `/health.anonymousKey` only to localhost, or to all callers when `PROXY_ADVERTISE_ANON_KEY=1`. See [Anonymous Access](#anonymous-access-optional). |
|
| `PROXY_ANONYMOUS_KEY` | *(unset)* | Well-known anonymous key allowlist (multi mode). When set, this exact string bypasses `validateKey()` and grants public access. Exposed via `/health.anonymousKey` only to localhost, or to all callers when `PROXY_ADVERTISE_ANON_KEY=1`. See [Anonymous Access](#anonymous-access-optional). |
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@
|
|||||||
],
|
],
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"opus": "claude-opus-4-8",
|
"opus": "claude-opus-4-8",
|
||||||
"sonnet": "claude-sonnet-5",
|
"sonnet": "claude-sonnet-4-6",
|
||||||
"haiku": "claude-haiku-4-5-20251001"
|
"haiku": "claude-haiku-4-5-20251001"
|
||||||
},
|
},
|
||||||
"legacyAliases": {
|
"legacyAliases": {
|
||||||
|
|||||||
+2
-7
@@ -202,13 +202,8 @@ for mid in model_ids:
|
|||||||
|
|
||||||
# Handle primary/backup
|
# Handle primary/backup
|
||||||
if priority == "1":
|
if priority == "1":
|
||||||
# OCP as primary — pick the best model (prefer the latest Sonnet for daily use,
|
# OCP as primary — pick the best model (prefer sonnet for daily use)
|
||||||
# tracking the `sonnet` alias default in models.json; fall back across versions).
|
primary_model = provider_name + "/claude-sonnet-4-6" if "claude-sonnet-4-6" in model_ids else provider_name + "/" + model_ids[0]
|
||||||
_sonnet_pref = ["claude-sonnet-5", "claude-sonnet-4-6"]
|
|
||||||
primary_model = next(
|
|
||||||
(provider_name + "/" + m for m in _sonnet_pref if m in model_ids),
|
|
||||||
provider_name + "/" + model_ids[0],
|
|
||||||
)
|
|
||||||
config["agents"]["defaults"].setdefault("model", {})
|
config["agents"]["defaults"].setdefault("model", {})
|
||||||
config["agents"]["defaults"]["model"]["primary"] = primary_model
|
config["agents"]["defaults"]["model"]["primary"] = primary_model
|
||||||
# Keep existing fallbacks
|
# Keep existing fallbacks
|
||||||
|
|||||||
+2
-2
@@ -3322,8 +3322,8 @@ test("models.json aliases.haiku === 'claude-haiku-4-5-20251001' (usage-probe SPO
|
|||||||
assert.equal(_spotModels.aliases.haiku, "claude-haiku-4-5-20251001");
|
assert.equal(_spotModels.aliases.haiku, "claude-haiku-4-5-20251001");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("models.json aliases.sonnet === 'claude-sonnet-5' (default-request-model SPOT)", () => {
|
test("models.json aliases.sonnet === 'claude-sonnet-4-6' (default-request-model SPOT)", () => {
|
||||||
assert.equal(_spotModels.aliases.sonnet, "claude-sonnet-5");
|
assert.equal(_spotModels.aliases.sonnet, "claude-sonnet-4-6");
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Referential integrity (PR #152 review) ──────────────────────────────────
|
// ── Referential integrity (PR #152 review) ──────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user