ffai-cli 0.2.0__py3-none-any.whl
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.
- ffai/__init__.py +5 -0
- ffai/__main__.py +5 -0
- ffai/cli.py +97 -0
- ffai/command_builder.py +287 -0
- ffai/config.py +251 -0
- ffai/errors.py +31 -0
- ffai/executor.py +255 -0
- ffai/i18n.py +400 -0
- ffai/llm.py +181 -0
- ffai/models.py +454 -0
- ffai/pandoc_builder.py +254 -0
- ffai/parser.py +112 -0
- ffai/prompt.py +296 -0
- ffai/providers.py +122 -0
- ffai/repl.py +933 -0
- ffai/state.py +291 -0
- ffai/tools.py +177 -0
- ffai/utils.py +91 -0
- ffai_cli-0.2.0.dist-info/METADATA +620 -0
- ffai_cli-0.2.0.dist-info/RECORD +24 -0
- ffai_cli-0.2.0.dist-info/WHEEL +5 -0
- ffai_cli-0.2.0.dist-info/entry_points.txt +2 -0
- ffai_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
- ffai_cli-0.2.0.dist-info/top_level.txt +1 -0
ffai/providers.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Built-in OpenAI-compatible provider presets.
|
|
2
|
+
|
|
3
|
+
Endpoint and suggested-model values follow the providers' current API
|
|
4
|
+
documentation. Models remain editable because availability varies by account and
|
|
5
|
+
region.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class ProviderPreset:
|
|
15
|
+
id: str
|
|
16
|
+
name: str
|
|
17
|
+
base_url: str | None
|
|
18
|
+
default_model: str | None
|
|
19
|
+
docs_url: str | None = None
|
|
20
|
+
api_key_url: str | None = None
|
|
21
|
+
note: str | None = None
|
|
22
|
+
name_zh: str | None = None
|
|
23
|
+
note_zh: str | None = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
PROVIDERS: tuple[ProviderPreset, ...] = (
|
|
27
|
+
ProviderPreset(
|
|
28
|
+
id="openai",
|
|
29
|
+
name="OpenAI",
|
|
30
|
+
base_url="https://api.openai.com/v1",
|
|
31
|
+
default_model="gpt-5.4-mini",
|
|
32
|
+
docs_url="https://developers.openai.com/api/docs/models/gpt-5.4-mini",
|
|
33
|
+
api_key_url="https://platform.openai.com/api-keys",
|
|
34
|
+
),
|
|
35
|
+
ProviderPreset(
|
|
36
|
+
id="openrouter",
|
|
37
|
+
name="OpenRouter",
|
|
38
|
+
base_url="https://openrouter.ai/api/v1",
|
|
39
|
+
default_model="openai/gpt-5.4-mini",
|
|
40
|
+
docs_url="https://openrouter.ai/docs/quickstart",
|
|
41
|
+
api_key_url="https://openrouter.ai/keys",
|
|
42
|
+
note="Model IDs are vendor-prefixed, for example openai/gpt-5.4-mini.",
|
|
43
|
+
note_zh="模型 ID 带供应商前缀,例如 openai/gpt-5.4-mini。",
|
|
44
|
+
),
|
|
45
|
+
ProviderPreset(
|
|
46
|
+
id="deepseek",
|
|
47
|
+
name="DeepSeek",
|
|
48
|
+
base_url="https://api.deepseek.com",
|
|
49
|
+
default_model="deepseek-flash",
|
|
50
|
+
docs_url="https://api-docs.deepseek.com/",
|
|
51
|
+
api_key_url="https://platform.deepseek.com/api_keys",
|
|
52
|
+
),
|
|
53
|
+
ProviderPreset(
|
|
54
|
+
id="glm",
|
|
55
|
+
name="GLM (Zhipu)",
|
|
56
|
+
base_url="https://open.bigmodel.cn/api/paas/v4",
|
|
57
|
+
default_model="glm-5.3",
|
|
58
|
+
docs_url="https://docs.bigmodel.cn/cn/guide/models/text/glm-5.3",
|
|
59
|
+
api_key_url="https://bigmodel.cn/usercenter/proj-mgmt/apikeys",
|
|
60
|
+
note="Uses Zhipu's OpenAI Chat Completions-compatible endpoint.",
|
|
61
|
+
note_zh="使用智谱的 OpenAI Chat Completions 兼容端点。",
|
|
62
|
+
),
|
|
63
|
+
ProviderPreset(
|
|
64
|
+
id="kimi",
|
|
65
|
+
name="Kimi (Moonshot)",
|
|
66
|
+
base_url="https://api.moonshot.cn/v1",
|
|
67
|
+
default_model="kimi-k3.1-pro",
|
|
68
|
+
docs_url="https://platform.kimi.com/docs/get-api-key",
|
|
69
|
+
api_key_url="https://platform.kimi.com/console/api-keys",
|
|
70
|
+
),
|
|
71
|
+
ProviderPreset(
|
|
72
|
+
id="qwen",
|
|
73
|
+
name="Qwen (DashScope)",
|
|
74
|
+
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
75
|
+
default_model="qwen3.8-flash",
|
|
76
|
+
docs_url="https://www.alibabacloud.com/help/zh/model-studio/base-url",
|
|
77
|
+
api_key_url="https://modelstudio.console.alibabacloud.com/",
|
|
78
|
+
note=(
|
|
79
|
+
"China-region endpoint. Use your region's compatible-mode URL and a "
|
|
80
|
+
"matching regional API key."
|
|
81
|
+
),
|
|
82
|
+
note_zh="此为中国区端点。其他区域请使用对应区域的 compatible-mode URL 和 API Key。",
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
CUSTOM_PROVIDER = ProviderPreset(
|
|
87
|
+
id="custom",
|
|
88
|
+
name="Custom (OpenAI-compatible)",
|
|
89
|
+
base_url=None,
|
|
90
|
+
default_model=None,
|
|
91
|
+
note="Any OpenAI-compatible endpoint that accepts a bearer API key.",
|
|
92
|
+
name_zh="自定义(OpenAI 兼容)",
|
|
93
|
+
note_zh="支持任何接受 Bearer API Key 的 OpenAI 兼容端点。",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
PROVIDER_CHOICES: tuple[ProviderPreset, ...] = (*PROVIDERS, CUSTOM_PROVIDER)
|
|
97
|
+
|
|
98
|
+
_BY_ID = {provider.id: provider for provider in PROVIDER_CHOICES}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_provider(provider_id: str) -> ProviderPreset:
|
|
102
|
+
try:
|
|
103
|
+
return _BY_ID[provider_id]
|
|
104
|
+
except KeyError as exc:
|
|
105
|
+
raise KeyError(f"Unknown provider preset: {provider_id}") from exc
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def identify_provider(base_url: str | None) -> ProviderPreset | None:
|
|
109
|
+
"""Return the preset matching *base_url*, or ``None`` for a custom endpoint."""
|
|
110
|
+
|
|
111
|
+
if base_url is None:
|
|
112
|
+
return get_provider("openai")
|
|
113
|
+
normalized = base_url.rstrip("/")
|
|
114
|
+
for provider in PROVIDERS:
|
|
115
|
+
if provider.base_url and provider.base_url.rstrip("/") == normalized:
|
|
116
|
+
return provider
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def provider_name_for(base_url: str | None) -> str:
|
|
121
|
+
provider = identify_provider(base_url)
|
|
122
|
+
return provider.name if provider is not None else CUSTOM_PROVIDER.name
|