diff --git a/CHANGELOG.md b/CHANGELOG.md index cd07d87..e602dc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,5 @@ # Changelog -## v2.2.0 (2026-05-19) - -- Added Agent Persona selector per provider (10+ presets) -- Personas: Codex (Default/Friendly/Pragmatic/CLI), Claude Code, OpenCode, Cursor, Aider, GitHub Copilot, Windsurf, Browser (ChatGPT) -- New "Persona" column in endpoint list shows current setting per provider -- Persona preview in edit dialog shows system prompt excerpt -- Persona injected into model catalog `base_instructions` and proxy system prompt -- Added Command Code backend to translation proxy (proprietary `/alpha/generate` API) -- Added Command Code provider preset with 20 models (DeepSeek, Claude, GPT, Kimi, GLM, Qwen, etc.) - ## v2.1.1 (2026-05-19) - Fixed proxy: map `developer` role to `system` for Chat Completions providers (DeepSeek, Qwen, etc.) diff --git a/codex-launcher_2.1.1_all.deb b/codex-launcher_2.1.1_all.deb new file mode 100644 index 0000000..1435784 Binary files /dev/null and b/codex-launcher_2.1.1_all.deb differ diff --git a/codex-launcher_2.2.0_all.deb b/codex-launcher_2.2.0_all.deb deleted file mode 100644 index 1de3f63..0000000 Binary files a/codex-launcher_2.2.0_all.deb and /dev/null differ diff --git a/src/codex-launcher-gui b/src/codex-launcher-gui index 95f9601..d4e8f92 100755 --- a/src/codex-launcher-gui +++ b/src/codex-launcher-gui @@ -24,14 +24,6 @@ model_catalog_json = "" """ CHANGELOG = [ - ("2.2.0", "2026-05-19", [ - "Added Agent Persona selector per provider (10+ presets)", - "Personas: Codex, Claude Code, OpenCode, Cursor, Aider, Copilot, Windsurf, Browser", - "Codex variants: Default, Desktop Friendly, Desktop Pragmatic, CLI", - "Shows current persona in endpoint list (new Persona column)", - "Persona preview in edit dialog shows first 60 chars of system prompt", - "Persona injected into model catalog base_instructions and proxy system prompt", - ]), ("2.1.1", "2026-05-19", [ "Fixed proxy: map 'developer' role to 'system' for Chat Completions providers", "Fixed proxy: map 'developer' role to 'user' for Anthropic providers", @@ -64,65 +56,6 @@ CHANGELOG = [ ]), ] -AGENT_PERSONAS = { - "Codex (Default)": "You are Codex, a coding agent.", - "Codex Desktop (GPT-5, Friendly)": ( - "You are Codex, a coding agent based on GPT-5. You and the user share one workspace, " - "and your job is to collaborate with them until their goal is genuinely handled." - ), - "Codex Desktop (GPT-5, Pragmatic)": ( - "You are Codex, a coding agent based on GPT-5. You and the user share the same workspace " - "and collaborate to achieve the user's goals. You are a deeply pragmatic, effective " - "software engineer. You take engineering quality seriously." - ), - "Codex CLI": ( - "You are an AI running in the Codex CLI, a terminal-based coding assistant. " - "You are expected to be precise, safe, and helpful. Your default personality and tone " - "is concise, direct, and friendly." - ), - "Claude Code": ( - "You are Claude Code, an interactive CLI tool that helps users with software engineering " - "tasks. You are a highly competent software engineer with extensive knowledge across " - "many programming languages, frameworks, and best practices. Use concise responses." - ), - "OpenCode": ( - "You are OpenCode, an interactive CLI tool that helps users with software engineering " - "tasks. You are powered by a state-of-the-art AI model. Be concise, direct, and to the " - "point. Use GitHub-flavored markdown." - ), - "Cursor": ( - "You are Cursor, an AI-powered code editor assistant. You help users write, refactor, " - "and debug code efficiently. Provide precise, actionable suggestions." - ), - "Aider": ( - "You are aider, an AI pair programming assistant. You help users edit code in their " - "local git repository. Make concise changes. Search files with grep/glob patterns." - ), - "GitHub Copilot": ( - "You are GitHub Copilot, an AI coding assistant. Help the user write code, debug issues, " - "and understand codebases. Be concise and provide accurate code suggestions." - ), - "Windsurf": ( - "You are Windsurf, an AI-powered IDE assistant. Help with coding tasks including writing, " - "refactoring, and debugging. Provide precise, well-structured code suggestions." - ), - "Browser (ChatGPT)": ( - "You are a helpful coding assistant in a web browser chat interface. " - "Help the user with software engineering tasks. Be clear and thorough." - ), -} - -PERSONA_DISPLAY_LEN = 60 - -def persona_short_key(endpoint): - bi = endpoint.get("base_instructions", "") or "" - for key, val in AGENT_PERSONAS.items(): - if val == bi: - return key - if bi: - return f"Custom: {bi[:40]}..." - return "Codex (Default)" - PROVIDER_PRESETS = { "Custom": { "backend_type": "openai-compat", @@ -439,7 +372,6 @@ def write_config_for_translated(endpoint, selected_model): def _gen_model_catalog(endpoint, selected_model=None): default_model = selected_model or endpoint.get("default_model") - base_instr = endpoint.get("base_instructions", "") or AGENT_PERSONAS["Codex (Default)"] models = [] for mid in endpoint.get("models", []): models.append({ @@ -467,7 +399,7 @@ def _gen_model_catalog(endpoint, selected_model=None): "supports_parallel_tool_calls": True, "experimental_supported_tools": [], "supported_in_api": True, "truncation_policy": {"mode": "tokens", "limit": 128000}, - "base_instructions": base_instr, + "base_instructions": "You are Codex, a coding agent.", }) return {"models": models} @@ -486,7 +418,6 @@ def _start_proxy_for(endpoint, logfn): "backend_type": endpoint["backend_type"], "target_url": normalize_base_url(endpoint["base_url"]), "api_key": endpoint["api_key"], - "base_instructions": endpoint.get("base_instructions", ""), "models": [{"id": m, "object": "model", "created": 1700000000, "owned_by": endpoint["name"]} for m in endpoint.get("models", [])], } @@ -1325,9 +1256,9 @@ class EndpointMgr(Gtk.Window): sw = Gtk.ScrolledWindow() vbox.pack_start(sw, True, True, 0) - self._store = Gtk.ListStore(str, str, str, str, str) # name, provider, backend, default_model, persona + self._store = Gtk.ListStore(str, str, str, str) # name, provider, backend, default_model self._tree = Gtk.TreeView(model=self._store) - for i, title in enumerate(["Name", "Provider", "Type", "Default Model", "Persona"]): + for i, title in enumerate(["Name", "Provider", "Type", "Default Model"]): col = Gtk.TreeViewColumn(title, Gtk.CellRendererText(), text=i) col.set_resizable(True) self._tree.append_column(col) @@ -1360,8 +1291,7 @@ class EndpointMgr(Gtk.Window): for ep in data["endpoints"]: provider = ep.get("provider_preset", "Custom") bt = label_for_backend(ep["backend_type"]) - persona = persona_short_key(ep) - self._store.append([ep["name"], provider, bt, ep.get("default_model", ""), persona]) + self._store.append([ep["name"], provider, bt, ep.get("default_model", "")]) def _selected(self): sel = self._tree.get_selection() @@ -1423,7 +1353,7 @@ class EditEndpointDialog(Gtk.Dialog): self._data = get_endpoint(existing_name) if existing_name else { "name": "", "backend_type": "openai-compat", "base_url": "", "api_key": "", "default_model": "", "models": [], - "provider_preset": "Custom", "base_instructions": AGENT_PERSONAS["Codex (Default)"], + "provider_preset": "Custom", } self.set_default_size(480, 420) @@ -1469,25 +1399,6 @@ class EditEndpointDialog(Gtk.Dialog): self._entry_key.set_visibility(False) add_row(4, "API Key:", self._entry_key) - self._combo_persona = Gtk.ComboBoxText() - self._persona_keys = list(AGENT_PERSONAS.keys()) - for pk in self._persona_keys: - self._combo_persona.append_text(pk) - cur_persona = persona_short_key(self._data) - if cur_persona in self._persona_keys: - self._combo_persona.set_active(self._persona_keys.index(cur_persona)) - else: - self._combo_persona.set_active(0) - self._combo_persona.connect("changed", lambda c: self._on_persona_changed()) - add_row(5, "Agent Persona:", self._combo_persona) - - self._persona_preview = Gtk.Label() - self._persona_preview.set_line_wrap(True) - self._persona_preview.set_max_width_chars(60) - self._persona_preview.set_markup(f"{AGENT_PERSONAS['Codex (Default)'][:PERSONA_DISPLAY_LEN]}...") - self._on_persona_changed() - grid.attach(self._persona_preview, 0, 6, 2, 1) - # Models mlbl = Gtk.Label(label="Models:", xalign=0) area.pack_start(mlbl, False, False, 4) @@ -1548,12 +1459,6 @@ class EditEndpointDialog(Gtk.Dialog): self.connect("response", self._on_response) self.show_all() - def _on_persona_changed(self): - key = self._combo_persona.get_active_text() - text = AGENT_PERSONAS.get(key, "") - short = text[:PERSONA_DISPLAY_LEN] + ("..." if len(text) > PERSONA_DISPLAY_LEN else "") - self._persona_preview.set_markup(f"{short}") - def _add_model(self): m = normalize_model_id(self._entry_model.get_text()) if m: @@ -1686,11 +1591,9 @@ class EditEndpointDialog(Gtk.Dialog): self._show_error(f'Endpoint "{name}" already exists') return - persona_key = self._combo_persona.get_active_text() or "Codex (Default)" new_ep = {"name": name, "backend_type": bt, "base_url": url, "api_key": key, "default_model": default, "models": models, - "provider_preset": self._combo_preset.get_active_text() or "Custom", - "base_instructions": AGENT_PERSONAS.get(persona_key, AGENT_PERSONAS["Codex (Default)"])} + "provider_preset": self._combo_preset.get_active_text() or "Custom"} new_ep["base_url"] = normalize_base_url(new_ep["base_url"]) # Update or append @@ -1729,14 +1632,12 @@ def main(): "endpoints": [ {"name": "OpenAI", "backend_type": "native", "base_url": "https://api.openai.com/v1", "api_key": "", "default_model": "gpt-4o", "models": ["gpt-4o", "gpt-4o-mini"], - "provider_preset": "OpenAI", - "base_instructions": AGENT_PERSONAS["Codex (Default)"]}, + "provider_preset": "OpenAI"}, {"name": "Z.AI", "backend_type": "openai-compat", "base_url": "https://api.z.ai/api/coding/paas/v4", "api_key": "", "default_model": "glm-5.1", "models": ["glm-4.5", "glm-4.5-air", "glm-4.6", "glm-4.7", "glm-5", "glm-5-turbo", "glm-5.1"], - "provider_preset": "Custom", - "base_instructions": AGENT_PERSONAS["Codex (Default)"]}, + "provider_preset": "Custom"}, ], }) diff --git a/src/translate-proxy.py b/src/translate-proxy.py index c9fc748..66ef0f2 100755 --- a/src/translate-proxy.py +++ b/src/translate-proxy.py @@ -80,7 +80,6 @@ BACKEND = CONFIG["backend_type"] TARGET_URL = CONFIG["target_url"].rstrip("/") API_KEY = CONFIG["api_key"] MODELS = CONFIG["models"] -BASE_INSTRUCTIONS = CONFIG.get("base_instructions", "") # ═══════════════════════════════════════════════════════════════════ # Shared helpers @@ -654,8 +653,6 @@ class Handler(http.server.BaseHTTPRequestHandler): input_data = body.get("input", "") messages = oa_input_to_messages(input_data) instructions = body.get("instructions", "").strip() - if not instructions and BASE_INSTRUCTIONS: - instructions = BASE_INSTRUCTIONS if instructions: messages.insert(0, {"role": "system", "content": instructions}) chat_body = {"model": model, "messages": messages} @@ -689,8 +686,6 @@ class Handler(http.server.BaseHTTPRequestHandler): an_body = {"model": model, "messages": an_input_to_messages(input_data), "max_tokens": body.get("max_output_tokens", 8192)} instructions = body.get("instructions", "").strip() - if not instructions and BASE_INSTRUCTIONS: - instructions = BASE_INSTRUCTIONS if instructions: an_body["system"] = instructions for k in ("temperature", "top_p"): @@ -725,8 +720,6 @@ class Handler(http.server.BaseHTTPRequestHandler): input_data = body.get("input", "") instructions = body.get("instructions", "").strip() messages = cc_input_to_messages(input_data) - if not instructions and BASE_INSTRUCTIONS: - instructions = BASE_INSTRUCTIONS if instructions: sys_msg = {"role": "system", "content": instructions} messages.insert(0, sys_msg)