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 | |
|---|---|---|---|
|
|
1ae9b5cde6 |
@@ -185,8 +185,7 @@ The setup script will:
|
||||
1. Verify Claude CLI is installed and authenticated
|
||||
2. Start the proxy on port 3456
|
||||
3. Install auto-start (launchd on macOS, systemd on Linux)
|
||||
|
||||
After install the `ocp` CLI lives at `~/ocp/ocp`. To put it on your PATH, either symlink it manually (`ln -sf ~/ocp/ocp ~/.local/bin/ocp` if `~/.local/bin` is on your PATH, or `sudo ln -sf ~/ocp/ocp /usr/local/bin/ocp` for a system-wide symlink) or add an alias (`alias ocp=~/ocp/ocp`). Otherwise invoke it as `~/ocp/ocp <subcommand>`. The rest of this README assumes `ocp` is on your PATH.
|
||||
4. Symlink `ocp` to `/usr/local/bin` for CLI access
|
||||
|
||||
**Single-machine use** — just set your IDE to use the proxy:
|
||||
```bash
|
||||
@@ -396,15 +395,11 @@ In `multi` mode, the admin can designate a single well-known "anonymous" key tha
|
||||
|
||||
**Enable**:
|
||||
|
||||
The anonymous key is wired into the service unit (launchd plist on macOS, systemd unit on Linux) at install time. Export `PROXY_ANONYMOUS_KEY` in your shell before running `setup.mjs`, and `setup.mjs` will write it into the service unit env so the auto-started proxy picks it up:
|
||||
|
||||
```bash
|
||||
export PROXY_ANONYMOUS_KEY=ocp_public_anon # or any string of your choice
|
||||
node setup.mjs --bind 0.0.0.0 --auth-mode multi
|
||||
ocp start # or however you start the server
|
||||
```
|
||||
|
||||
If OCP is already installed without it, re-export the env var and re-run `node setup.mjs` (the installer is idempotent — it refreshes the service unit). Then `ocp restart` so the running proxy picks up the new env. Setting `PROXY_ANONYMOUS_KEY` only in your interactive shell **does not** affect the auto-started proxy — the service unit is the source of truth for its environment.
|
||||
|
||||
**Client side**: the anonymous key value is exposed via `GET /health` as the field `anonymousKey` (null when not set). Clients like `ocp-connect` can auto-discover and use it, so the end user doesn't need to get a personal key from the admin.
|
||||
|
||||
**Security note**: setting this env var is an **opt-in** to public access — anyone who can reach your OCP endpoint can use it, up to any rate limits you configure. Don't enable this on internet-exposed OCP instances without additional protection.
|
||||
|
||||
+48
-4
@@ -30,7 +30,7 @@
|
||||
import { createServer } from "node:http";
|
||||
import { spawn, execFileSync } from "node:child_process";
|
||||
import { randomUUID, timingSafeEqual } from "node:crypto";
|
||||
import { readFileSync, accessSync, existsSync, constants } from "node:fs";
|
||||
import { readFileSync, readdirSync, accessSync, existsSync, constants } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
@@ -41,8 +41,48 @@ const _pkg = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8"));
|
||||
const modelsConfig = JSON.parse(readFileSync(join(__dirname, "models.json"), "utf8"));
|
||||
|
||||
// ── Resolve claude binary ───────────────────────────────────────────────
|
||||
// Priority: CLAUDE_BIN env > well-known paths > which lookup
|
||||
// Fail-fast if not found — never start with an unresolvable binary.
|
||||
// Priority: CLAUDE_BIN env > well-known paths > nvm/fnm/asdf user-local
|
||||
// installs > which lookup. Fail-fast if not found — never start with an
|
||||
// unresolvable binary.
|
||||
function _listVersionDirs(parent) {
|
||||
try { return readdirSync(parent); } catch { return []; }
|
||||
}
|
||||
function _collectNodeManagerCandidates(home) {
|
||||
if (!home) return [];
|
||||
const out = [];
|
||||
|
||||
// nvm: $HOME/.nvm/versions/node/<version>/bin/claude
|
||||
const nvmRoot = join(home, ".nvm/versions/node");
|
||||
for (const v of _listVersionDirs(nvmRoot)) {
|
||||
out.push(join(nvmRoot, v, "bin/claude"));
|
||||
}
|
||||
// nvm default alias: resolve $HOME/.nvm/aliases/default if it points to a version
|
||||
try {
|
||||
const aliasFile = join(home, ".nvm/aliases/default");
|
||||
const aliasVer = readFileSync(aliasFile, "utf8").trim();
|
||||
if (aliasVer) {
|
||||
const direct = join(nvmRoot, aliasVer, "bin/claude");
|
||||
if (!out.includes(direct)) out.unshift(direct);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
// fnm: $HOME/.fnm/node-versions/<version>/installation/bin/claude
|
||||
const fnmRoot = join(home, ".fnm/node-versions");
|
||||
for (const v of _listVersionDirs(fnmRoot)) {
|
||||
out.push(join(fnmRoot, v, "installation/bin/claude"));
|
||||
}
|
||||
|
||||
// asdf: $HOME/.asdf/installs/nodejs/<version>/bin/claude
|
||||
const asdfRoot = join(home, ".asdf/installs/nodejs");
|
||||
for (const v of _listVersionDirs(asdfRoot)) {
|
||||
out.push(join(asdfRoot, v, "bin/claude"));
|
||||
}
|
||||
|
||||
// npm prefix-relocated: $HOME/.npm-global/bin/claude
|
||||
out.push(join(home, ".npm-global/bin/claude"));
|
||||
|
||||
return out;
|
||||
}
|
||||
function resolveClaude() {
|
||||
if (process.env.CLAUDE_BIN) {
|
||||
try {
|
||||
@@ -54,11 +94,13 @@ function resolveClaude() {
|
||||
}
|
||||
}
|
||||
|
||||
const home = process.env.HOME || "";
|
||||
const candidates = [
|
||||
"/opt/homebrew/bin/claude",
|
||||
"/usr/local/bin/claude",
|
||||
"/usr/bin/claude",
|
||||
join(process.env.HOME || "", ".local/bin/claude"),
|
||||
join(home, ".local/bin/claude"),
|
||||
..._collectNodeManagerCandidates(home),
|
||||
];
|
||||
for (const p of candidates) {
|
||||
try { accessSync(p, constants.X_OK); console.warn(`[init] CLAUDE_BIN not set, resolved to ${p}`); return p; } catch {}
|
||||
@@ -72,6 +114,8 @@ function resolveClaude() {
|
||||
console.error(
|
||||
"FATAL: claude binary not found.\n" +
|
||||
" Set CLAUDE_BIN=/path/to/claude or ensure claude is in PATH.\n" +
|
||||
" Hint: if you use nvm/fnm/asdf, set CLAUDE_BIN to the absolute path\n" +
|
||||
" shown by `which claude` in your interactive shell.\n" +
|
||||
" Checked: " + candidates.join(", ")
|
||||
);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user