Last active
June 1, 2026 05:43
-
-
Save m13253/40a8f5255c1994ce813317767c61420d to your computer and use it in GitHub Desktop.
Convert Floway model list to OpenCode, LiteLLM, and Zed settings files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Usage: | |
| # curl -H 'Authorization: Bearer <TOKEN>' http://localhost:8000/api/models | ./floway-to-zed.py | |
| import json | |
| import sys | |
| import yaml | |
| def translate_name(model_id: str) -> str: | |
| model_id_fold = model_id.casefold() | |
| if model_id_fold.startswith("claude-"): | |
| return "anthropic/" + model_id | |
| elif model_id_fold.startswith("gemini-"): | |
| return "gemini/" + model_id | |
| else: | |
| return "openai/" + model_id | |
| def translate_api_base(model_id: str) -> str: | |
| model_id_fold = model_id.casefold() | |
| # Note: api_base must not end with "/" | |
| if model_id_fold.startswith("claude-"): | |
| # export FLOWAY_API_BASE_ANTHROPIC=http://localhost:8000 | |
| return "os.environ/FLOWAY_API_BASE_ANTHROPIC" | |
| elif model_id_fold.startswith("gemini-"): | |
| # export FLOWAY_API_BASE_GETMINI=http://localhost:8000/v1beta | |
| return "os.environ/FLOWAY_API_BASE_GEMINI" | |
| else: | |
| # export FLOWAY_API_BASE_OPENAI=http://localhost:8000/v1 | |
| return "os.environ/FLOWAY_API_BASE_OPENAI" | |
| def translate_cost(cost: dict[str, float]) -> dict[str, float | None]: | |
| input_cost = cost.get("input") | |
| output_cost = cost.get("output") | |
| input_cache_cost = cost.get("input_cache_read") | |
| return { | |
| "input": None if input_cost is None else (input_cost * 1e-6), | |
| "output": None if output_cost is None else (output_cost * 1e-6), | |
| "cache_read_input_token_cost": ( | |
| None if input_cache_cost is None else (input_cache_cost * 1e-6) | |
| ), | |
| } | |
| def main() -> None: | |
| print( | |
| yaml.safe_dump( | |
| { | |
| "model_list": [ | |
| { | |
| "model_name": "floway/" + model["id"], | |
| "litellm_params": { | |
| "model": translate_name(model["id"]), | |
| "api_base": translate_api_base(model["id"]), | |
| "api_key": "os.environ/FLOWAY_API_KEY", | |
| }, | |
| "model_info": { | |
| k: v | |
| for k, v in ( | |
| { | |
| "id": "floway/" + model["id"], | |
| "mode": "embedding" | |
| if model["kind"] == "embedding" | |
| else None, | |
| "max_tokens": model["limits"].get( | |
| "max_context_window_tokens" | |
| ), | |
| "max_input_tokens": model["limits"].get( | |
| "max_prompt_tokens" | |
| ), | |
| "max_output_tokens": model["limits"].get( | |
| "max_output_tokens" | |
| ), | |
| } | |
| | translate_cost(model.get("cost", {})) | |
| ).items() | |
| if v is not None | |
| }, | |
| } | |
| for model in json.load(sys.stdin.buffer)["data"] | |
| if model["type"] == "model" | |
| ] | |
| + [ | |
| { | |
| "model_name": "floway/claude-*", | |
| "litellm_params": { | |
| "model": "anthropic/claude-*", | |
| "api_base": "os.environ/FLOWAY_API_BASE_ANTHROPIC", | |
| "api_key": "os.environ/FLOWAY_API_KEY", | |
| }, | |
| "model_info": { | |
| "id": "floway/claude-*", | |
| }, | |
| }, | |
| { | |
| "model_name": "floway/gemini-*", | |
| "litellm_params": { | |
| "model": "gemini/gemini-*", | |
| "api_base": "os.environ/FLOWAY_API_BASE_GEMINI", | |
| "api_key": "os.environ/FLOWAY_API_KEY", | |
| }, | |
| "model_info": { | |
| "id": "floway/gemini-*", | |
| }, | |
| }, | |
| { | |
| "model_name": "floway/*", | |
| "litellm_params": { | |
| "model": "openai/*", | |
| "api_base": "os.environ/FLOWAY_API_BASE_OPENAI", | |
| "api_key": "os.environ/FLOWAY_API_KEY", | |
| }, | |
| "model_info": { | |
| "id": "floway/*", | |
| }, | |
| }, | |
| ], | |
| } | |
| ) | |
| .rstrip() | |
| .replace("\n", "\n ") | |
| ) | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Usage: | |
| # curl -H 'Authorization: Bearer <TOKEN>' http://localhost:8000/api/models | ./floway-to-zed.py | |
| import json | |
| import sys | |
| def main() -> None: | |
| print( | |
| "{\n" | |
| ' "$schema": "https://opencode.ai/config.json",\n' | |
| ' "provider": {\n' | |
| ' "floway": {\n' | |
| ' "name": "Floway",\n' | |
| ' "npm": "@ai-sdk/openai-compatible",\n' | |
| ' "options": {\n' | |
| ' "baseURL": "http://localhost:8000/v1" // https://github.com/Menci/floway\n' | |
| " },\n" | |
| ' "models": ', | |
| end="", | |
| ) | |
| print( | |
| json.dumps( | |
| { | |
| model["id"]: { | |
| k: v | |
| for k, v in { | |
| "id": model["id"], | |
| "name": model["display_name"], | |
| "tool_call": True, | |
| "cost": { | |
| k: v | |
| for k, v in { | |
| "input": model.get("cost", {}).get("input"), | |
| "output": model.get("cost", {}).get("output"), | |
| "cache_read": model.get("cost", {}).get( | |
| "input_cache_read" | |
| ), | |
| }.items() | |
| if v is not None | |
| }, | |
| "limit": { | |
| "context": model["limits"]["max_context_window_tokens"], | |
| "input": model["limits"]["max_prompt_tokens"], | |
| "output": model["limits"]["max_output_tokens"], | |
| }, | |
| "modalities": { | |
| "input": ["text", "image"], | |
| "output": ["text"], | |
| }, | |
| }.items() | |
| if v != {} | |
| } | |
| for model in json.load(sys.stdin.buffer)["data"] | |
| if model["type"] == "model" and model["kind"] == "chat" | |
| }, | |
| ensure_ascii=False, | |
| indent=2, | |
| ).replace("\n", "\n ") | |
| ) | |
| print(" }\n }\n}") | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Usage: | |
| # curl -H 'Authorization: Bearer <TOKEN>' http://localhost:8000/api/models | ./floway-to-zed.py | |
| import json | |
| import sys | |
| def main() -> None: | |
| print( | |
| "// Zed settings\n" | |
| "//\n" | |
| "// For information on how to configure Zed, see the Zed\n" | |
| "// documentation: https://zed.dev/docs/configuring-zed\n" | |
| "{\n" | |
| ' "language_models": {\n' | |
| ' "openai_compatible": {\n' | |
| ' "Floway": {\n' | |
| ' "api_url": "http://localhost:8000/v1", // https://github.com/Menci/floway\n' | |
| ' "available_models": ', | |
| end="", | |
| ) | |
| print( | |
| json.dumps( | |
| [ | |
| { | |
| "name": model["id"], | |
| "display_name": model["display_name"], | |
| "max_tokens": model["limits"]["max_context_window_tokens"], | |
| "max_output_tokens": model["limits"]["max_output_tokens"], | |
| "max_completion_tokens": model["limits"]["max_output_tokens"], | |
| "capabilities": { | |
| "tools": True, | |
| "images": True, | |
| "parallel_tool_calls": True, | |
| "prompt_cache_key": True, | |
| }, | |
| } | |
| for model in json.load(sys.stdin.buffer)["data"] | |
| if model["type"] == "model" and model["kind"] == "chat" | |
| ], | |
| ensure_ascii=False, | |
| indent=2, | |
| ).replace("\n", "\n ") | |
| ) | |
| print(" }\n }\n }\n}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment