Skip to content

Instantly share code, notes, and snippets.

@m13253
Last active June 1, 2026 05:43
Show Gist options
  • Select an option

  • Save m13253/40a8f5255c1994ce813317767c61420d to your computer and use it in GitHub Desktop.

Select an option

Save m13253/40a8f5255c1994ce813317767c61420d to your computer and use it in GitHub Desktop.
Convert Floway model list to OpenCode, LiteLLM, and Zed settings files
#!/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()
#!/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()
#!/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