@elvatis_com/openclaw-cli-bridge-elvatis 0.2.12 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,3 +70,32 @@ package.json / tsconfig.json
70
70
  - `SKILL.md` — if commands or config changed
71
71
 
72
72
  Skipping documentation = incomplete release. No exceptions.
73
+
74
+ ---
75
+
76
+ ## 🚨 Release-Regel: Erst fertig, dann publishen (gilt für ALLE Plattformen)
77
+
78
+ **IMMER erst alles fertigstellen, danach publishen. Kein einziger Commit mehr dazwischen.**
79
+ Gilt für GitHub, npm, ClawHub, PyPI — egal ob ein Projekt auf einer oder mehreren Plattformen ist.
80
+ Sonst divergieren die Tarballs/Releases zwangsläufig.
81
+
82
+ ### Reihenfolge (nie abweichen)
83
+ 1. Alle Änderungen + Versionsbumps in **einem einzigen Commit** abschließen
84
+ 2. `git push` → Plattform 1 (z.B. GitHub)
85
+ 3. `npm publish` / `clawhub publish` / etc. — alle weiteren Plattformen
86
+ 4. Kein weiterer Commit bis zum nächsten Release (außer reine interne Doku)
87
+
88
+ ### Vor jedem Release: Alle Versionsstellen prüfen
89
+ ```bash
90
+ grep -rn "X\.Y\.Z\|Current version\|Version:" \
91
+ --include="*.md" --include="*.json" \
92
+ --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git
93
+ ```
94
+ Typische vergessene Stellen: `README.md` Header, `SKILL.md` Footer, `package.json`,
95
+ `openclaw.plugin.json`, `.ai/handoff/STATUS.md` (Header + Plattform-Zeilen), Changelog-Eintrag.
96
+
97
+ ### Secrets & private Pfade — NIEMALS in Repos
98
+ - Keine API Keys, Tokens, Passwörter, Secrets in Code oder Docs
99
+ - Keine absoluten lokalen Pfade (`/home/user/...`) in publizierten Dateien
100
+ - Keine `.env`-Dateien committen — immer in `.gitignore`
101
+ - Vor jedem Push: `git diff --staged` auf Secrets prüfen
@@ -2,13 +2,13 @@
2
2
 
3
3
  _Last updated: 2026-03-07 by Akido (claude-sonnet-4-6)_
4
4
 
5
- ## Current Version: 0.2.12 — STABLE
5
+ ## Current Version: 0.2.14 — STABLE
6
6
 
7
7
  ## What is done
8
8
 
9
9
  - ✅ Repo: `https://github.com/elvatis/openclaw-cli-bridge-elvatis`
10
- - ✅ npm: `@elvatis_com/openclaw-cli-bridge-elvatis@0.2.12`
11
- - ✅ ClawHub: `openclaw-cli-bridge-elvatis@0.2.12`
10
+ - ✅ npm: `@elvatis_com/openclaw-cli-bridge-elvatis@0.2.14`
11
+ - ✅ ClawHub: `openclaw-cli-bridge-elvatis@0.2.14`
12
12
  - ✅ Phase 1: `openai-codex` provider via `~/.codex/auth.json` (no re-login)
13
13
  - ✅ Phase 2: Local OpenAI-compatible proxy on `127.0.0.1:31337` (Gemini + Claude CLI)
14
14
  - ✅ Phase 3: 10 slash commands (`/cli-sonnet`, `/cli-opus`, `/cli-haiku`, `/cli-gemini`, `/cli-gemini-flash`, `/cli-gemini3`, `/cli-codex`, `/cli-codex-mini`, `/cli-back`, `/cli-test`)
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > OpenClaw plugin that bridges locally installed AI CLIs (Codex, Gemini, Claude Code) as model providers — with slash commands for instant model switching, restore, and health testing.
4
4
 
5
- **Current version:** `0.2.12`
5
+ **Current version:** `0.2.14`
6
6
 
7
7
  ---
8
8
 
@@ -234,7 +234,7 @@ npm test # vitest run (5 unit tests for formatPrompt)
234
234
 
235
235
  ## Changelog
236
236
 
237
- ### v0.2.12
237
+ ### v0.2.14
238
238
  - **docs:** Fix changelog (v0.2.10 entry was lost by sed, v0.2.11 description was wrong); enforce single-commit publish discipline
239
239
 
240
240
  ### v0.2.11
package/SKILL.md CHANGED
@@ -53,4 +53,4 @@ Each command runs `openclaw models set <model>` atomically and replies with a co
53
53
 
54
54
  See `README.md` for full configuration reference and architecture diagram.
55
55
 
56
- **Version:** 0.2.12
56
+ **Version:** 0.2.14
package/index.ts CHANGED
@@ -277,7 +277,7 @@ function proxyTestRequest(
277
277
  const plugin = {
278
278
  id: "openclaw-cli-bridge-elvatis",
279
279
  name: "OpenClaw CLI Bridge",
280
- version: "0.2.5",
280
+ version: "0.2.14",
281
281
  description:
282
282
  "Phase 1: openai-codex auth bridge. " +
283
283
  "Phase 2: HTTP proxy for gemini/claude CLIs. " +
@@ -458,7 +458,7 @@ const plugin = {
458
458
  api.registerCommand({
459
459
  name,
460
460
  description,
461
- requireAuth: true,
461
+ requireAuth: false,
462
462
  handler: async (ctx: PluginCommandContext): Promise<PluginCommandResult> => {
463
463
  api.logger.info(`[cli-bridge] /${name} by ${ctx.senderId ?? "?"}`);
464
464
  return switchModel(api, model, label);
@@ -470,7 +470,7 @@ const plugin = {
470
470
  api.registerCommand({
471
471
  name: "cli-back",
472
472
  description: "Restore the model that was active before the last /cli-* switch",
473
- requireAuth: true,
473
+ requireAuth: false,
474
474
  handler: async (ctx: PluginCommandContext): Promise<PluginCommandResult> => {
475
475
  api.logger.info(`[cli-bridge] /cli-back by ${ctx.senderId ?? "?"}`);
476
476
 
@@ -508,7 +508,7 @@ const plugin = {
508
508
  name: "cli-test",
509
509
  description: "Test the CLI bridge proxy without switching your active model. Usage: /cli-test [model]",
510
510
  acceptsArgs: true,
511
- requireAuth: true,
511
+ requireAuth: false,
512
512
  handler: async (ctx: PluginCommandContext): Promise<PluginCommandResult> => {
513
513
  const targetModel = ctx.args?.trim() || CLI_TEST_DEFAULT_MODEL;
514
514
  // Accept short names like "cli-sonnet" or full "vllm/cli-claude/claude-sonnet-4-6"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-cli-bridge-elvatis",
3
3
  "name": "OpenClaw CLI Bridge",
4
- "version": "0.2.12",
4
+ "version": "0.2.14",
5
5
  "description": "Phase 1: openai-codex auth bridge. Phase 2: local HTTP proxy routing model calls through gemini/claude CLIs (vllm provider).",
6
6
  "providers": [
7
7
  "openai-codex"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elvatis_com/openclaw-cli-bridge-elvatis",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Bridges gemini, claude, and codex CLI tools as OpenClaw model providers. Reads existing CLI auth without re-login.",
5
5
  "type": "module",
6
6
  "openclaw": {
package/src/cli-runner.ts CHANGED
@@ -254,11 +254,16 @@ export async function routeToCliRunner(
254
254
  ): Promise<string> {
255
255
  const prompt = formatPrompt(messages);
256
256
 
257
- if (model.startsWith("cli-gemini/")) return runGemini(prompt, model, timeoutMs);
258
- if (model.startsWith("cli-claude/")) return runClaude(prompt, model, timeoutMs);
257
+ // Strip "vllm/" prefix if present — OpenClaw sends the full provider path
258
+ // (e.g. "vllm/cli-claude/claude-sonnet-4-6") but the router only needs the
259
+ // "cli-<type>/<model>" portion.
260
+ const normalized = model.startsWith("vllm/") ? model.slice(5) : model;
261
+
262
+ if (normalized.startsWith("cli-gemini/")) return runGemini(prompt, normalized, timeoutMs);
263
+ if (normalized.startsWith("cli-claude/")) return runClaude(prompt, normalized, timeoutMs);
259
264
 
260
265
  throw new Error(
261
- `Unknown CLI bridge model: "${model}". Use "cli-gemini/<model>" or "cli-claude/<model>".`
266
+ `Unknown CLI bridge model: "${model}". Use "vllm/cli-gemini/<model>" or "vllm/cli-claude/<model>".`
262
267
  );
263
268
  }
264
269
 
@@ -1,5 +1,5 @@
1
- import { describe, it, expect } from "vitest";
2
- import { formatPrompt } from "../src/cli-runner.js";
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { formatPrompt, routeToCliRunner } from "../src/cli-runner.js";
3
3
 
4
4
  describe("formatPrompt", () => {
5
5
  it("returns empty string for empty messages", () => {
@@ -44,3 +44,31 @@ describe("formatPrompt", () => {
44
44
  expect(result).toContain("truncated");
45
45
  });
46
46
  });
47
+
48
+ describe("routeToCliRunner — model normalization", () => {
49
+ it("rejects unknown model without vllm prefix", async () => {
50
+ await expect(
51
+ routeToCliRunner("unknown/model", [], 1000)
52
+ ).rejects.toThrow("Unknown CLI bridge model");
53
+ });
54
+
55
+ it("rejects unknown model with vllm prefix", async () => {
56
+ await expect(
57
+ routeToCliRunner("vllm/unknown/model", [], 1000)
58
+ ).rejects.toThrow("Unknown CLI bridge model");
59
+ });
60
+
61
+ it("accepts cli-claude/ without vllm prefix (calls runClaude path)", async () => {
62
+ // Should throw CLI spawn error (no real claude), not "Unknown CLI bridge model"
63
+ await expect(
64
+ routeToCliRunner("cli-claude/claude-sonnet-4-6", [{ role: "user", content: "hi" }], 500)
65
+ ).rejects.not.toThrow("Unknown CLI bridge model");
66
+ });
67
+
68
+ it("accepts vllm/cli-claude/ — strips vllm prefix before routing", async () => {
69
+ // Should throw CLI spawn error (no real claude), not "Unknown CLI bridge model"
70
+ await expect(
71
+ routeToCliRunner("vllm/cli-claude/claude-sonnet-4-6", [{ role: "user", content: "hi" }], 500)
72
+ ).rejects.not.toThrow("Unknown CLI bridge model");
73
+ });
74
+ });