@inetafrica/open-claudia 1.16.0 → 1.16.1

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/bot.js +55 -23
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.16.1
4
+ - `/model` is now a single unified picker — all Claude, Cursor, and Codex models in one keyboard, with section dividers per backend
5
+ - Tapping any model auto-switches the active backend if needed (e.g. picking gpt-5 from Claude flips you to Codex). No more `/codex` + `/model` two-step
6
+ - Only backends with a detected CLI binary appear in the picker (Cursor/Codex rows hidden if not installed)
7
+
3
8
  ## v1.16.0
4
9
  - OpenAI Codex backend support: `/codex` to switch, `/backend` picker now has 3 options
5
10
  - Auto-detects `codex` binary via `which codex` at startup; opt-in via `CODEX_PATH` in .env
package/bot.js CHANGED
@@ -1750,30 +1750,43 @@ bot.onText(/\/sessions$/, (msg) => {
1750
1750
 
1751
1751
  bot.onText(/\/model$/, (msg) => {
1752
1752
  if (!isAuthorized(msg)) return;
1753
- let keyboard, label;
1754
- if (settings.backend === "cursor") {
1755
- keyboard = [
1756
- [{ text: "Composer 2", callback_data: "m:composer-2" }, { text: "Composer 2 Fast", callback_data: "m:composer-2-fast" }],
1757
- [{ text: "Opus 4.6 Thinking", callback_data: "m:claude-4.6-opus-high-thinking" }, { text: "Sonnet 4.6", callback_data: "m:claude-4.6-sonnet-medium" }],
1758
- [{ text: "GPT-5.4", callback_data: "m:gpt-5.4-medium" }, { text: "GPT-5.4 High", callback_data: "m:gpt-5.4-high" }],
1759
- [{ text: "Auto", callback_data: "m:auto" }, { text: "Default", callback_data: "m:default" }],
1760
- ];
1761
- label = "Cursor Agent";
1762
- } else if (settings.backend === "codex") {
1763
- keyboard = [
1764
- [{ text: "gpt-5", callback_data: "m:gpt-5" }, { text: "gpt-5-codex", callback_data: "m:gpt-5-codex" }],
1765
- [{ text: "o3", callback_data: "m:o3" }, { text: "o4-mini", callback_data: "m:o4-mini" }],
1766
- [{ text: "Default", callback_data: "m:default" }],
1767
- ];
1768
- label = "Codex";
1769
- } else {
1770
- keyboard = [
1771
- [{ text: "Opus 4.7", callback_data: "m:claude-opus-4-7" }, { text: "Opus 4.6", callback_data: "m:claude-opus-4-6" }, { text: "Sonnet 4.6", callback_data: "m:claude-sonnet-4-6" }, { text: "Haiku", callback_data: "m:claude-haiku-4-5-20251001" }],
1772
- [{ text: "Default", callback_data: "m:default" }],
1773
- ];
1774
- label = "Claude Code";
1753
+ // Unified picker: every model from every available backend in one keyboard.
1754
+ // Tapping a button switches backend (if needed) and sets the model.
1755
+ // Callback format: `mb:<backend>:<model>` (model may itself contain `-`).
1756
+ const rows = [];
1757
+ rows.push([{ text: "── Claude ──", callback_data: "noop" }]);
1758
+ rows.push([
1759
+ { text: "Opus 4.7", callback_data: "mb:claude:claude-opus-4-7" },
1760
+ { text: "Opus 4.6", callback_data: "mb:claude:claude-opus-4-6" },
1761
+ { text: "Sonnet 4.6", callback_data: "mb:claude:claude-sonnet-4-6" },
1762
+ { text: "Haiku", callback_data: "mb:claude:claude-haiku-4-5-20251001" },
1763
+ ]);
1764
+ if (resolvedCursorPath) {
1765
+ rows.push([{ text: "── Cursor ──", callback_data: "noop" }]);
1766
+ rows.push([
1767
+ { text: "Composer 2", callback_data: "mb:cursor:composer-2" },
1768
+ { text: "Composer 2 Fast", callback_data: "mb:cursor:composer-2-fast" },
1769
+ { text: "Auto", callback_data: "mb:cursor:auto" },
1770
+ ]);
1771
+ rows.push([
1772
+ { text: "Opus 4.6 Thinking", callback_data: "mb:cursor:claude-4.6-opus-high-thinking" },
1773
+ { text: "GPT-5.4", callback_data: "mb:cursor:gpt-5.4-medium" },
1774
+ ]);
1775
+ }
1776
+ if (resolvedCodexPath) {
1777
+ rows.push([{ text: "── Codex ──", callback_data: "noop" }]);
1778
+ rows.push([
1779
+ { text: "gpt-5", callback_data: "mb:codex:gpt-5" },
1780
+ { text: "gpt-5-codex", callback_data: "mb:codex:gpt-5-codex" },
1781
+ ]);
1782
+ rows.push([
1783
+ { text: "o3", callback_data: "mb:codex:o3" },
1784
+ { text: "o4-mini", callback_data: "mb:codex:o4-mini" },
1785
+ ]);
1775
1786
  }
1776
- send(`${label} model: ${settings.model || "default"}\n\nOr type /model <name> for any model.`, { keyboard: { inline_keyboard: keyboard } });
1787
+ rows.push([{ text: "Default (current backend)", callback_data: "m:default" }]);
1788
+ const beLabel = settings.backend === "cursor" ? "Cursor" : settings.backend === "codex" ? "Codex" : "Claude";
1789
+ send(`Current: ${beLabel} · ${settings.model || "default"}\n\nPick a model — backend switches automatically.\nOr type /model <name>.`, { keyboard: { inline_keyboard: rows } });
1777
1790
  });
1778
1791
  bot.onText(/\/model (.+)/, (msg, match) => { if (!isAuthorized(msg)) return; settings.model = match[1].trim().toLowerCase(); if (settings.model === "default") settings.model = null; send(`Model: ${settings.model || "default"}`); });
1779
1792
 
@@ -2143,6 +2156,25 @@ bot.on("callback_query", async (q) => {
2143
2156
  }
2144
2157
  if (d === "a:continue") { if (currentSession) await runClaude("continue", currentSession.dir); else send("No session."); return; }
2145
2158
  if (d === "a:end") { if (currentSession) { const n = currentSession.name; currentSession = null; lastSessionId = null; messageQueue = []; resetSettings(); resetSessionUsage(); saveState(); await send(`Ended: ${n}`, { keyboard: { inline_keyboard: [[{ text: "New", callback_data: "show:projects" }]] } }); } return; }
2159
+ if (d === "noop") { return; }
2160
+ if (d.startsWith("mb:")) {
2161
+ // Unified picker: switch backend + set model in one tap.
2162
+ // Format: mb:<backend>:<model>. Model may contain `:` itself (unlikely), so split on first two.
2163
+ const rest = d.slice(3);
2164
+ const colon = rest.indexOf(":");
2165
+ if (colon < 0) return;
2166
+ const be = rest.slice(0, colon);
2167
+ const model = rest.slice(colon + 1);
2168
+ if (be === "cursor" && !resolvedCursorPath) { await send("Cursor Agent CLI not found."); return; }
2169
+ if (be === "codex" && !resolvedCodexPath) { await send("Codex CLI not found. Install: npm install -g @openai/codex"); return; }
2170
+ const switched = settings.backend !== be;
2171
+ settings.backend = be;
2172
+ settings.model = model;
2173
+ saveState();
2174
+ const beLabel = be === "cursor" ? "Cursor Agent" : be === "codex" ? "Codex" : "Claude Code";
2175
+ await send(switched ? `Switched to ${beLabel}.\nModel: ${model}` : `Model: ${model}`);
2176
+ return;
2177
+ }
2146
2178
  if (d.startsWith("m:")) { settings.model = d.slice(2) === "default" ? null : d.slice(2); await send(`Model: ${settings.model || "default"}`); return; }
2147
2179
  if (d.startsWith("e:")) { const e = d.slice(2); settings.effort = e === "default" ? null : e; await send(`Effort: ${settings.effort || "default"}`); return; }
2148
2180
  if (d.startsWith("b:")) { const b = d.slice(2); settings.budget = b === "none" ? null : parseFloat(b); await send(`Budget: ${settings.budget ? "$"+settings.budget : "none"}`); return; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inetafrica/open-claudia",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "description": "Your always-on AI coding assistant — Claude Code, Cursor Agent, and OpenAI Codex via Telegram",
5
5
  "main": "bot.js",
6
6
  "bin": {