@oneciel-ai/ciel-runtime 0.2.28 → 0.2.29
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.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/ciel_runtime.py +2 -2
- package/ciel_runtime_support/claude_environment.py +5 -1
- package/ciel_runtime_support/cli_parser.py +5 -0
- package/ciel_runtime_support/managed_mcp_config.py +2 -2
- package/ciel_runtime_support/prelaunch.py +9 -1
- package/ciel_runtime_support/prelaunch_panel_context.py +11 -8
- package/ciel_runtime_support/provider_adapters.py +27 -1
- package/ciel_runtime_support/provider_administration_context.py +23 -5
- package/ciel_runtime_support/provider_compatibility.py +12 -0
- package/ciel_runtime_support/provider_runtime_modes.py +1 -1
- package/ciel_runtime_support/providers/__init__.py +9 -1
- package/ciel_runtime_support/providers/constants.py +3 -0
- package/ciel_runtime_support/providers/zai.py +190 -12
- package/ciel_runtime_support/runtime_constants.py +12 -2
- package/ciel_runtime_support/zai_oauth.py +84 -24
- package/ciel_runtime_support/zcode_runtime_context.py +12 -1
- package/docs/CLI-Reference.md +20 -11
- package/docs/Installation.md +7 -3
- package/docs/Providers.md +43 -12
- package/docs/journal/2026/08/24/mia-zai-plan-profile-429-diagnosis.okf +101 -0
- package/docs/journal/2026/08/24/zai-localhost-oauth-callback.okf +12 -0
- package/docs/journal/2026/08/24/zai-plan-provider-login-separation.okf +96 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
This file records stable Ciel Runtime releases. Changes are grouped by user-visible
|
|
4
4
|
capability, followed by the complete commit ledger merged into each release.
|
|
5
5
|
|
|
6
|
+
## 0.2.29 — 2026-08-24
|
|
7
|
+
|
|
8
|
+
- Split Z.AI general API, Coding Plan, and Start Plan into independent provider
|
|
9
|
+
profiles so OAuth login never overwrites the legacy/manual `zai` API key.
|
|
10
|
+
- Added the verified general API and Coding Plan OpenAI/Anthropic endpoints and
|
|
11
|
+
plan-scoped `zai-oauth --profile coding-plan|start-plan` credential handling.
|
|
12
|
+
- Added official GLM-5.1, GLM-5.2, and GLM-5.3 context/output profiles.
|
|
13
|
+
- Registered the installed ZCode Start Plan endpoints and JWT credential shape,
|
|
14
|
+
but fail launch explicitly because a live request proved that the private
|
|
15
|
+
runtime's fresh Aliyun CAPTCHA header is required; Ciel does not fabricate or
|
|
16
|
+
bypass it.
|
|
17
|
+
|
|
6
18
|
## 0.2.28 — 2026-08-24
|
|
7
19
|
|
|
8
20
|
- Replaced manual `zcode://` callback pasting in the Z.AI authorization-code
|
package/README.md
CHANGED
|
@@ -164,7 +164,7 @@ Common commands:
|
|
|
164
164
|
ciel-runtimectl provider [NAME]
|
|
165
165
|
ciel-runtimectl models [PROVIDER]
|
|
166
166
|
ciel-runtimectl model MODEL_ID
|
|
167
|
-
ciel-runtimectl zai-oauth login
|
|
167
|
+
ciel-runtimectl zai-oauth login --profile coding-plan
|
|
168
168
|
ciel-runtimectl status
|
|
169
169
|
ciel-runtimectl remote-memory
|
|
170
170
|
ciel-runtimectl transcript-events
|
package/ciel_runtime.py
CHANGED
|
@@ -3160,7 +3160,7 @@ portable_language_menu = _CONFIGURATION_CLI_API.portable_language_menu
|
|
|
3160
3160
|
|
|
3161
3161
|
def credential_cli_controller() -> CredentialCliController:
|
|
3162
3162
|
return CredentialCliController(
|
|
3163
|
-
policy=CredentialCliPolicy(frozenset({"anthropic", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "nvidia-hosted", "openrouter", "fireworks"})),
|
|
3163
|
+
policy=CredentialCliPolicy(frozenset({"anthropic", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "nvidia-hosted", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan"})),
|
|
3164
3164
|
ports=CredentialCliPorts(normalize_provider, load_config, provider_api_key_count, provider_primary_api_key, mask_secret, secret_fingerprint,
|
|
3165
3165
|
api_key_clear_requested, clear_api_key_config, store_api_key_input_config, store_api_keys_config),
|
|
3166
3166
|
io=CredentialCliIO(sys.stdin.isatty, getpass.getpass, print),
|
|
@@ -3238,7 +3238,7 @@ def cmd_ollama_native(args: argparse.Namespace) -> None: provider_option_cli_con
|
|
|
3238
3238
|
def provider_option_policy() -> ProviderOptionPolicy: return ProviderOptionPolicy(normalize_claude_code_supported_capabilities, normalize_ip_family, normalize_model_id, normalize_opencode_endpoint_kind, parse_bool, parse_config_value, positive_int, ProviderSamplingPolicy())
|
|
3239
3239
|
def apply_ollama_option(pcfg: dict[str, Any], token: str) -> None: mutate_ollama_option(pcfg, token, policy=provider_option_policy())
|
|
3240
3240
|
def cmd_ollama_options(args: argparse.Namespace) -> None: provider_option_cli_controller().ollama_options(args)
|
|
3241
|
-
PROVIDER_OPTION_PROVIDERS = ("anthropic", "agy", "codex", "vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "ollama", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "openrouter", "fireworks", "zai")
|
|
3241
|
+
PROVIDER_OPTION_PROVIDERS = ("anthropic", "agy", "codex", "vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "ollama", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan")
|
|
3242
3242
|
PROVIDER_SAMPLING_OPTION_PROVIDERS = ("vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "openrouter")
|
|
3243
3243
|
PROVIDER_SAMPLING_OPTIONS = ("temperature", "top_p", "top_k")
|
|
3244
3244
|
def sampling_option_key(key: str) -> str | None: return ProviderSamplingPolicy().option_key(key)
|
|
@@ -222,7 +222,11 @@ class ClaudeModelAliasPolicy:
|
|
|
222
222
|
):
|
|
223
223
|
selected = ""
|
|
224
224
|
selected_from_config = False
|
|
225
|
-
configured =
|
|
225
|
+
configured = (
|
|
226
|
+
str(config.get(f"{family}_model") or "").strip()
|
|
227
|
+
if provider in {"zai", "zai-api", "zai-coding-plan", "zai-start-plan"}
|
|
228
|
+
else ""
|
|
229
|
+
)
|
|
226
230
|
if configured:
|
|
227
231
|
selected = self._ports.normalize_model_id(provider, configured)
|
|
228
232
|
selected_from_config = bool(selected)
|
|
@@ -147,6 +147,11 @@ def build_cli_parser(services: CliParserServices) -> argparse.ArgumentParser:
|
|
|
147
147
|
default="status",
|
|
148
148
|
)
|
|
149
149
|
zai_oauth.add_argument("--no-browser", action="store_true")
|
|
150
|
+
zai_oauth.add_argument(
|
|
151
|
+
"--profile",
|
|
152
|
+
choices=("coding-plan", "start-plan"),
|
|
153
|
+
default="coding-plan",
|
|
154
|
+
)
|
|
150
155
|
zai_oauth.set_defaults(func=services.provider.oauth["zai"])
|
|
151
156
|
_add_values_command(commands, "model", services.models.model, argument_name="value")
|
|
152
157
|
_add_values_command(commands, "advisor-model", services.models.advisor_model, argument_name="value")
|
|
@@ -67,7 +67,7 @@ class ManagedMcpConfigService:
|
|
|
67
67
|
return path
|
|
68
68
|
|
|
69
69
|
def write_zai(self, provider: str, provider_config: dict[str, Any]) -> Path | None:
|
|
70
|
-
if provider
|
|
70
|
+
if provider not in {"zai", "zai-api", "zai-coding-plan"} or not bool(provider_config.get("managed_mcp", True)):
|
|
71
71
|
return None
|
|
72
72
|
key = self.ports.primary_api_key(provider, provider_config)
|
|
73
73
|
if not self.ports.meaningful_key(key):
|
|
@@ -93,7 +93,7 @@ class ManagedMcpConfigService:
|
|
|
93
93
|
return self.paths.zai
|
|
94
94
|
|
|
95
95
|
def reset_zai_if_inactive(self, provider: str) -> None:
|
|
96
|
-
if provider
|
|
96
|
+
if provider in {"zai", "zai-api", "zai-coding-plan"}:
|
|
97
97
|
return
|
|
98
98
|
try:
|
|
99
99
|
self.paths.zai.unlink()
|
|
@@ -577,8 +577,16 @@ def run_prelaunch_menu(passthrough: list[str] | None = None,
|
|
|
577
577
|
panel_rows, panel_values = api_key_panel_rows(provider, pcfg)
|
|
578
578
|
panel_idx = 0
|
|
579
579
|
elif value.startswith("zai-oauth-"):
|
|
580
|
+
oauth_value = value.removeprefix("zai-oauth-")
|
|
581
|
+
profile = "start-plan" if oauth_value.startswith("start-plan-") else "coding-plan"
|
|
582
|
+
action = oauth_value.removeprefix("start-plan-")
|
|
580
583
|
messages = guarded_zai_oauth_action(
|
|
581
|
-
|
|
584
|
+
action,
|
|
585
|
+
(
|
|
586
|
+
(lambda selected_action: zai_oauth_action(selected_action, profile=profile))
|
|
587
|
+
if profile == "start-plan"
|
|
588
|
+
else zai_oauth_action
|
|
589
|
+
),
|
|
582
590
|
)
|
|
583
591
|
refresh_checks()
|
|
584
592
|
cfg = load_config()
|
|
@@ -247,29 +247,32 @@ class PrelaunchPanelContext:
|
|
|
247
247
|
def api_key_panel_rows(
|
|
248
248
|
self, provider: str, provider_config: dict[str, Any] | None = None
|
|
249
249
|
) -> PanelRows:
|
|
250
|
-
if provider
|
|
250
|
+
if provider in {"zai", "zai-coding-plan", "zai-start-plan"}:
|
|
251
251
|
config = provider_config or {}
|
|
252
252
|
source = str(config.get("credential_source") or "").strip()
|
|
253
253
|
configured = bool(self.configuration.api_key_count(provider, config))
|
|
254
254
|
status = "connected" if configured and source == "zai-oauth" else (
|
|
255
255
|
"API key configured" if configured else "login required"
|
|
256
256
|
)
|
|
257
|
+
profile = "start-plan" if provider == "zai-start-plan" else "coding-plan"
|
|
258
|
+
action_prefix = "zai-oauth-start-plan-" if profile == "start-plan" else "zai-oauth-"
|
|
259
|
+
label = "Start Plan" if profile == "start-plan" else "Coding Plan"
|
|
257
260
|
rows, values = self.configuration_panel_projection().api_key_rows(
|
|
258
261
|
provider, provider_config
|
|
259
262
|
)
|
|
260
263
|
return (
|
|
261
264
|
[
|
|
262
|
-
f"Z.AI OAuth: {status}",
|
|
263
|
-
"Login with Z.AI OAuth (
|
|
264
|
-
"Refresh Z.AI OAuth status",
|
|
265
|
-
"Logout
|
|
265
|
+
f"Z.AI OAuth {label}: {status}",
|
|
266
|
+
f"Login with Z.AI OAuth ({label})",
|
|
267
|
+
f"Refresh Z.AI OAuth {label} status",
|
|
268
|
+
f"Logout Z.AI OAuth {label} credential",
|
|
266
269
|
*rows,
|
|
267
270
|
],
|
|
268
271
|
[
|
|
269
272
|
"__info__",
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
"
|
|
273
|
+
f"{action_prefix}login",
|
|
274
|
+
f"{action_prefix}status",
|
|
275
|
+
f"{action_prefix}logout",
|
|
273
276
|
*values,
|
|
274
277
|
],
|
|
275
278
|
)
|
|
@@ -25,7 +25,12 @@ from .providers.nim import SelfHostedNimProviderAdapter
|
|
|
25
25
|
from .providers.nvidia import NvidiaHostedProviderAdapter
|
|
26
26
|
from .providers.vllm import VllmProviderAdapter
|
|
27
27
|
from .providers.deepseek import DeepSeekProviderAdapter
|
|
28
|
-
from .providers.zai import
|
|
28
|
+
from .providers.zai import (
|
|
29
|
+
ZaiApiProviderAdapter,
|
|
30
|
+
ZaiCodingPlanProviderAdapter,
|
|
31
|
+
ZaiProviderAdapter,
|
|
32
|
+
ZaiStartPlanProviderAdapter,
|
|
33
|
+
)
|
|
29
34
|
from .providers.kimi import KimiProviderAdapter
|
|
30
35
|
from .providers.fireworks import FireworksProviderAdapter
|
|
31
36
|
from .providers.meta import MetaModelProviderAdapter
|
|
@@ -60,6 +65,24 @@ PROVIDER_DESCRIPTORS = ProviderDescriptorRegistry(
|
|
|
60
65
|
ProviderDescriptor("opencode-go", "OpenCode Go", OpenCodeGoProviderAdapter),
|
|
61
66
|
ProviderDescriptor("kimi", "Kimi.com", KimiProviderAdapter),
|
|
62
67
|
ProviderDescriptor("zai", "Z.AI GLM", ZaiProviderAdapter),
|
|
68
|
+
ProviderDescriptor(
|
|
69
|
+
"zai-api",
|
|
70
|
+
"Z.AI Model API (API Key)",
|
|
71
|
+
ZaiApiProviderAdapter,
|
|
72
|
+
aliases=("zai-general", "zai-payg"),
|
|
73
|
+
),
|
|
74
|
+
ProviderDescriptor(
|
|
75
|
+
"zai-coding-plan",
|
|
76
|
+
"Z.AI Coding Plan",
|
|
77
|
+
ZaiCodingPlanProviderAdapter,
|
|
78
|
+
aliases=("zai-coding",),
|
|
79
|
+
),
|
|
80
|
+
ProviderDescriptor(
|
|
81
|
+
"zai-start-plan",
|
|
82
|
+
"Z.AI Start Plan",
|
|
83
|
+
ZaiStartPlanProviderAdapter,
|
|
84
|
+
aliases=("zai-start",),
|
|
85
|
+
),
|
|
63
86
|
ProviderDescriptor("vllm", "vLLM", VllmProviderAdapter),
|
|
64
87
|
ProviderDescriptor("lm-studio", "LM Studio", LMStudioProviderAdapter),
|
|
65
88
|
ProviderDescriptor("nvidia-hosted", "Nvidia Hosted", NvidiaHostedProviderAdapter),
|
|
@@ -192,5 +215,8 @@ __all__ = [
|
|
|
192
215
|
"VllmProviderAdapter",
|
|
193
216
|
"XaiProviderAdapter",
|
|
194
217
|
"ZaiProviderAdapter",
|
|
218
|
+
"ZaiApiProviderAdapter",
|
|
219
|
+
"ZaiCodingPlanProviderAdapter",
|
|
220
|
+
"ZaiStartPlanProviderAdapter",
|
|
195
221
|
"ZAI_MODEL_FALLBACK_IDS",
|
|
196
222
|
]
|
|
@@ -70,13 +70,23 @@ class ProviderAdministrationContext:
|
|
|
70
70
|
for line in self.run_copilot_oauth_action(args.action):
|
|
71
71
|
self.infrastructure.output(line, flush=True)
|
|
72
72
|
|
|
73
|
-
def run_zai_oauth_action(
|
|
74
|
-
|
|
73
|
+
def run_zai_oauth_action(
|
|
74
|
+
self,
|
|
75
|
+
action: str,
|
|
76
|
+
*,
|
|
77
|
+
no_browser: bool = False,
|
|
78
|
+
profile: str = "coding-plan",
|
|
79
|
+
) -> list[str]:
|
|
80
|
+
return self.infrastructure.zai_oauth().action(
|
|
81
|
+
action, no_browser=no_browser, profile=profile
|
|
82
|
+
)
|
|
75
83
|
|
|
76
84
|
def cmd_zai_oauth(self, args: argparse.Namespace) -> None:
|
|
77
85
|
try:
|
|
78
86
|
lines = self.run_zai_oauth_action(
|
|
79
|
-
args.action,
|
|
87
|
+
args.action,
|
|
88
|
+
no_browser=bool(getattr(args, "no_browser", False)),
|
|
89
|
+
profile=str(getattr(args, "profile", "coding-plan")),
|
|
80
90
|
)
|
|
81
91
|
except RuntimeError as exc:
|
|
82
92
|
raise SystemExit(f"Z.AI OAuth failed: {exc}") from exc
|
|
@@ -161,8 +171,16 @@ class ProviderAdministrationCompatibilityApi:
|
|
|
161
171
|
def cmd_copilot_oauth(self, args: argparse.Namespace) -> None:
|
|
162
172
|
self.context().cmd_copilot_oauth(args)
|
|
163
173
|
|
|
164
|
-
def run_zai_oauth_action(
|
|
165
|
-
|
|
174
|
+
def run_zai_oauth_action(
|
|
175
|
+
self,
|
|
176
|
+
action: str,
|
|
177
|
+
*,
|
|
178
|
+
no_browser: bool = False,
|
|
179
|
+
profile: str = "coding-plan",
|
|
180
|
+
) -> list[str]:
|
|
181
|
+
return self.context().run_zai_oauth_action(
|
|
182
|
+
action, no_browser=no_browser, profile=profile
|
|
183
|
+
)
|
|
166
184
|
|
|
167
185
|
def cmd_zai_oauth(self, args: argparse.Namespace) -> None:
|
|
168
186
|
self.context().cmd_zai_oauth(args)
|
|
@@ -154,6 +154,18 @@ PROVIDER_COMPATIBILITY = ProviderCompatibilityRegistry(
|
|
|
154
154
|
auto_web_search=_zai_auto_web_search,
|
|
155
155
|
tool_use_blocker=_zai_tool_use_blocker,
|
|
156
156
|
),
|
|
157
|
+
"zai-api": ProviderCompatibilityPolicy(
|
|
158
|
+
auto_web_search=_zai_auto_web_search,
|
|
159
|
+
tool_use_blocker=_zai_tool_use_blocker,
|
|
160
|
+
),
|
|
161
|
+
"zai-coding-plan": ProviderCompatibilityPolicy(
|
|
162
|
+
auto_web_search=_zai_auto_web_search,
|
|
163
|
+
tool_use_blocker=_zai_tool_use_blocker,
|
|
164
|
+
),
|
|
165
|
+
"zai-start-plan": ProviderCompatibilityPolicy(
|
|
166
|
+
auto_web_search=_zai_auto_web_search,
|
|
167
|
+
tool_use_blocker=_zai_tool_use_blocker,
|
|
168
|
+
),
|
|
157
169
|
}
|
|
158
170
|
)
|
|
159
171
|
|
|
@@ -144,7 +144,7 @@ def build_default_native_compatibility_policy(
|
|
|
144
144
|
"deepseek": frozenset({"deepseek"}),
|
|
145
145
|
"opencode": frozenset(OPENCODE_PROVIDER_NAMES),
|
|
146
146
|
"kimi": frozenset({"kimi"}),
|
|
147
|
-
"zai": frozenset({"zai"}),
|
|
147
|
+
"zai": frozenset({"zai", "zai-coding-plan", "zai-start-plan"}),
|
|
148
148
|
"fireworks": frozenset({"fireworks"}),
|
|
149
149
|
},
|
|
150
150
|
)
|
|
@@ -17,7 +17,12 @@ from .nvidia import NvidiaHostedProviderAdapter
|
|
|
17
17
|
from .vllm import VllmProviderAdapter
|
|
18
18
|
from .deepseek import DeepSeekProviderAdapter
|
|
19
19
|
from .fireworks import FireworksProviderAdapter
|
|
20
|
-
from .zai import
|
|
20
|
+
from .zai import (
|
|
21
|
+
ZaiApiProviderAdapter,
|
|
22
|
+
ZaiCodingPlanProviderAdapter,
|
|
23
|
+
ZaiProviderAdapter,
|
|
24
|
+
ZaiStartPlanProviderAdapter,
|
|
25
|
+
)
|
|
21
26
|
from .kimi import KimiProviderAdapter
|
|
22
27
|
from .opencode import OpenCodeProviderAdapter
|
|
23
28
|
from .opencode_go import OpenCodeGoProviderAdapter
|
|
@@ -65,6 +70,9 @@ __all__ = [
|
|
|
65
70
|
"DeepSeekProviderAdapter",
|
|
66
71
|
"FireworksProviderAdapter",
|
|
67
72
|
"ZaiProviderAdapter",
|
|
73
|
+
"ZaiApiProviderAdapter",
|
|
74
|
+
"ZaiCodingPlanProviderAdapter",
|
|
75
|
+
"ZaiStartPlanProviderAdapter",
|
|
68
76
|
"KimiProviderAdapter",
|
|
69
77
|
"OpenCodeProviderAdapter",
|
|
70
78
|
"OpenCodeGoProviderAdapter",
|
|
@@ -14,6 +14,9 @@ PROVIDER_DEFAULT_BASE_URLS: dict[str, str] = {
|
|
|
14
14
|
"opencode-go": "https://opencode.ai/zen/go",
|
|
15
15
|
"kimi": "https://api.kimi.com/coding",
|
|
16
16
|
"zai": "https://api.z.ai/api/anthropic",
|
|
17
|
+
"zai-api": "https://api.z.ai/api/paas/v4",
|
|
18
|
+
"zai-coding-plan": "https://api.z.ai/api/coding/paas/v4",
|
|
19
|
+
"zai-start-plan": "https://zcode.z.ai/api/v1/zcode-plan",
|
|
17
20
|
"vllm": "http://127.0.0.1:8000",
|
|
18
21
|
"lm-studio": "http://127.0.0.1:1234/v1",
|
|
19
22
|
"nvidia-hosted": "https://integrate.api.nvidia.com/v1",
|
|
@@ -11,6 +11,7 @@ from ..architecture import (
|
|
|
11
11
|
ProviderOptionPresentationPolicy,
|
|
12
12
|
ProviderRequestPolicy,
|
|
13
13
|
ProviderStatusPolicy,
|
|
14
|
+
MessageProtocol,
|
|
14
15
|
)
|
|
15
16
|
from .base import HttpBearerProviderAdapter, provider_configuration
|
|
16
17
|
from .constants import PROVIDER_DEFAULT_BASE_URLS, ZAI_MODEL_FALLBACK_IDS
|
|
@@ -85,19 +86,37 @@ class ZaiProviderAdapter(HttpBearerProviderAdapter):
|
|
|
85
86
|
self, config: ProviderConfig
|
|
86
87
|
) -> tuple[Mapping[str, Any], str | None]:
|
|
87
88
|
model = self.normalize_model_id(config.model).split("[", 1)[0].lower()
|
|
88
|
-
|
|
89
|
+
documented_profiles: dict[str, tuple[int, str]] = {
|
|
90
|
+
"glm-5.1": (200_000, "200K"),
|
|
91
|
+
"glm-5.2": (1_000_000, "1M"),
|
|
92
|
+
"glm-5.3": (1_000_000, "1M"),
|
|
93
|
+
}
|
|
94
|
+
documented = documented_profiles.get(model)
|
|
95
|
+
if documented is None:
|
|
89
96
|
return {}, None
|
|
97
|
+
context_window, context_label = documented
|
|
98
|
+
profile: dict[str, Any] = {
|
|
99
|
+
"context_window": context_window,
|
|
100
|
+
"max_model_len": context_window,
|
|
101
|
+
"auto_compact_window": context_window,
|
|
102
|
+
"max_output_tokens": 131_072,
|
|
103
|
+
"context_reserve_tokens": 131_072,
|
|
104
|
+
"model_profile": f"{model}-{context_label.lower()}",
|
|
105
|
+
}
|
|
106
|
+
if model == "glm-5.3":
|
|
107
|
+
profile["effort_level"] = "max"
|
|
108
|
+
notice = (
|
|
109
|
+
"GLM-5.3 profile applied: 1M context, 128K maximum output, "
|
|
110
|
+
"and max reasoning effort. Start a new session."
|
|
111
|
+
)
|
|
112
|
+
else:
|
|
113
|
+
notice = (
|
|
114
|
+
f"{model.upper()} profile applied: {context_label} context and "
|
|
115
|
+
"128K maximum output. Start a new session."
|
|
116
|
+
)
|
|
90
117
|
return (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"max_model_len": 1_000_000,
|
|
94
|
-
"auto_compact_window": 1_000_000,
|
|
95
|
-
"max_output_tokens": 131_072,
|
|
96
|
-
"context_reserve_tokens": 131_072,
|
|
97
|
-
"effort_level": "max",
|
|
98
|
-
"model_profile": "glm-5.3-1m",
|
|
99
|
-
},
|
|
100
|
-
"GLM-5.3 profile applied: 1M context, 128K maximum output, and max reasoning effort. Start a new session.",
|
|
118
|
+
profile,
|
|
119
|
+
notice,
|
|
101
120
|
)
|
|
102
121
|
|
|
103
122
|
def normalize_request_options(
|
|
@@ -165,4 +184,163 @@ class ZaiProviderAdapter(HttpBearerProviderAdapter):
|
|
|
165
184
|
)
|
|
166
185
|
|
|
167
186
|
|
|
168
|
-
|
|
187
|
+
@dataclass(frozen=True)
|
|
188
|
+
class ZaiApiProviderAdapter(ZaiProviderAdapter):
|
|
189
|
+
"""General pay-as-you-go Z.AI API using the documented OpenAI surface."""
|
|
190
|
+
|
|
191
|
+
name: str = "zai-api"
|
|
192
|
+
base_url: str = PROVIDER_DEFAULT_BASE_URLS["zai-api"]
|
|
193
|
+
include_x_api_key: bool = False
|
|
194
|
+
capabilities_value: ProviderCapabilities = field(
|
|
195
|
+
default_factory=lambda: ProviderCapabilities(
|
|
196
|
+
upstream_protocol="openai_chat",
|
|
197
|
+
supports_thinking=True,
|
|
198
|
+
requires_api_key=True,
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
request_policy_value: ProviderRequestPolicy = field(
|
|
202
|
+
default_factory=lambda: ProviderRequestPolicy(
|
|
203
|
+
chat_path="/chat/completions", models_path="/models"
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
api_key_display_name_value: str = "Z.AI Model API"
|
|
207
|
+
api_key_launch_error_value: str = (
|
|
208
|
+
"Launch blocked: Z.AI Model API requires a pay-as-you-go API key."
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
def supported_protocols(
|
|
212
|
+
self, config: ProviderConfig, model: str | None = None
|
|
213
|
+
) -> frozenset[MessageProtocol]:
|
|
214
|
+
del config, model
|
|
215
|
+
return frozenset({"openai_chat"})
|
|
216
|
+
|
|
217
|
+
def select_protocol(
|
|
218
|
+
self,
|
|
219
|
+
operation: MessageProtocol,
|
|
220
|
+
config: ProviderConfig,
|
|
221
|
+
model: str | None = None,
|
|
222
|
+
) -> MessageProtocol:
|
|
223
|
+
del operation, config, model
|
|
224
|
+
return "openai_chat"
|
|
225
|
+
|
|
226
|
+
def router_native_anthropic_enabled(
|
|
227
|
+
self, config: ProviderConfig, model: str | None = None
|
|
228
|
+
) -> bool:
|
|
229
|
+
del config, model
|
|
230
|
+
return False
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@dataclass(frozen=True)
|
|
234
|
+
class ZaiCodingPlanProviderAdapter(ZaiApiProviderAdapter):
|
|
235
|
+
"""Explicit Coding Plan profile with distinct OpenAI and Anthropic URLs."""
|
|
236
|
+
|
|
237
|
+
name: str = "zai-coding-plan"
|
|
238
|
+
base_url: str = PROVIDER_DEFAULT_BASE_URLS["zai-coding-plan"]
|
|
239
|
+
include_x_api_key: bool = True
|
|
240
|
+
configuration_defaults_value: dict = field(
|
|
241
|
+
default_factory=lambda: {
|
|
242
|
+
**ZaiProviderAdapter().configuration_defaults_value,
|
|
243
|
+
"native_compat": True,
|
|
244
|
+
"plan_type": "coding-plan",
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
api_key_display_name_value: str = "Z.AI Coding Plan"
|
|
248
|
+
api_key_launch_error_value: str = (
|
|
249
|
+
"Launch blocked: Z.AI Coding Plan requires a Coding Plan API key or OAuth login."
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
def supported_protocols(
|
|
253
|
+
self, config: ProviderConfig, model: str | None = None
|
|
254
|
+
) -> frozenset[MessageProtocol]:
|
|
255
|
+
del model
|
|
256
|
+
protocols: set[MessageProtocol] = {"openai_chat"}
|
|
257
|
+
if bool(config.options.get("native_compat", True)):
|
|
258
|
+
protocols.add("anthropic_messages")
|
|
259
|
+
return frozenset(protocols)
|
|
260
|
+
|
|
261
|
+
def select_protocol(
|
|
262
|
+
self,
|
|
263
|
+
operation: MessageProtocol,
|
|
264
|
+
config: ProviderConfig,
|
|
265
|
+
model: str | None = None,
|
|
266
|
+
) -> MessageProtocol:
|
|
267
|
+
return (
|
|
268
|
+
"anthropic_messages"
|
|
269
|
+
if operation == "anthropic_messages"
|
|
270
|
+
and "anthropic_messages" in self.supported_protocols(config, model)
|
|
271
|
+
else "openai_chat"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def anthropic_base_url(self, config: ProviderConfig) -> str:
|
|
275
|
+
del config
|
|
276
|
+
return PROVIDER_DEFAULT_BASE_URLS["zai"]
|
|
277
|
+
|
|
278
|
+
def router_native_anthropic_enabled(
|
|
279
|
+
self, config: ProviderConfig, model: str | None = None
|
|
280
|
+
) -> bool:
|
|
281
|
+
del model
|
|
282
|
+
return bool(config.options.get("native_compat", True))
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@dataclass(frozen=True)
|
|
286
|
+
class ZaiStartPlanProviderAdapter(ZaiCodingPlanProviderAdapter):
|
|
287
|
+
"""ZCode Start Plan gateway profile backed by an OAuth JWT."""
|
|
288
|
+
|
|
289
|
+
name: str = "zai-start-plan"
|
|
290
|
+
base_url: str = PROVIDER_DEFAULT_BASE_URLS["zai-start-plan"]
|
|
291
|
+
include_x_api_key: bool = False
|
|
292
|
+
configuration_defaults_value: dict = field(
|
|
293
|
+
default_factory=lambda: {
|
|
294
|
+
**ZaiProviderAdapter().configuration_defaults_value,
|
|
295
|
+
"native_compat": True,
|
|
296
|
+
"plan_type": "start-plan",
|
|
297
|
+
"zcode_app_version": "3.8.1",
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
api_key_display_name_value: str = "Z.AI Start Plan OAuth"
|
|
301
|
+
api_key_launch_error_value: str = (
|
|
302
|
+
"Launch blocked: Z.AI Start Plan requires its own OAuth login."
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
def anthropic_base_url(self, config: ProviderConfig) -> str:
|
|
306
|
+
del config
|
|
307
|
+
return "https://zcode.z.ai/api/v1/zcode-plan/anthropic"
|
|
308
|
+
|
|
309
|
+
def build_headers(
|
|
310
|
+
self, config: ProviderConfig, api_key: str | None
|
|
311
|
+
) -> Mapping[str, str]:
|
|
312
|
+
headers = dict(super().build_headers(config, api_key))
|
|
313
|
+
version = str(config.options.get("zcode_app_version") or "3.8.1").strip()
|
|
314
|
+
headers.update(
|
|
315
|
+
{
|
|
316
|
+
"User-Agent": f"ZCode/{version}",
|
|
317
|
+
"HTTP-Referer": "https://zcode.z.ai",
|
|
318
|
+
"X-ZCode-App-Version": version,
|
|
319
|
+
"X-ZCode-Agent": "glm",
|
|
320
|
+
"X-Title": "Z Code@cli",
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
return headers
|
|
324
|
+
|
|
325
|
+
def build_model_headers(
|
|
326
|
+
self, config: ProviderConfig, api_key: str | None
|
|
327
|
+
) -> Mapping[str, str]:
|
|
328
|
+
return self.build_headers(config, api_key)
|
|
329
|
+
|
|
330
|
+
def launch_api_key_error(self, config: ProviderConfig) -> str | None:
|
|
331
|
+
if not config.api_keys:
|
|
332
|
+
return self.api_key_launch_error_value
|
|
333
|
+
return (
|
|
334
|
+
"Launch blocked: Z.AI Start Plan requires a fresh Aliyun CAPTCHA "
|
|
335
|
+
"runtime header before each model request. The installed ZCode "
|
|
336
|
+
"runtime provides that private interactive flow; Ciel Runtime does "
|
|
337
|
+
"not bypass or fabricate it for routed clients."
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
__all__ = [
|
|
342
|
+
"ZaiApiProviderAdapter",
|
|
343
|
+
"ZaiCodingPlanProviderAdapter",
|
|
344
|
+
"ZaiProviderAdapter",
|
|
345
|
+
"ZaiStartPlanProviderAdapter",
|
|
346
|
+
]
|
|
@@ -87,7 +87,7 @@ OPENCODE_ENDPOINT_ALIASES = {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
APP_NAME = "Ciel Runtime"
|
|
90
|
-
VERSION = "0.2.
|
|
90
|
+
VERSION = "0.2.29"
|
|
91
91
|
CREDITS = "Credits: One Ciel LLC"
|
|
92
92
|
PRELAUNCH_CANCEL = 10
|
|
93
93
|
PRELAUNCH_LAUNCH_CODEX = 11
|
|
@@ -135,9 +135,19 @@ CODEX_OPENAI_COMPATIBLE_ROUTER_PROVIDERS = (
|
|
|
135
135
|
*OPENAI_COMPATIBLE_ROUTER_PROVIDERS,
|
|
136
136
|
"kimi",
|
|
137
137
|
"fireworks",
|
|
138
|
+
"zai-api",
|
|
139
|
+
"zai-coding-plan",
|
|
140
|
+
"zai-start-plan",
|
|
138
141
|
)
|
|
139
142
|
AUTO_DETECT_NATIVE_COMPAT_PROVIDERS = ("vllm", "lm-studio", "self-hosted-nim")
|
|
140
|
-
CLAUDE_ANTHROPIC_ENDPOINT_PROVIDERS = (
|
|
143
|
+
CLAUDE_ANTHROPIC_ENDPOINT_PROVIDERS = (
|
|
144
|
+
"deepseek",
|
|
145
|
+
"kimi",
|
|
146
|
+
"zai",
|
|
147
|
+
"zai-coding-plan",
|
|
148
|
+
"zai-start-plan",
|
|
149
|
+
"fireworks",
|
|
150
|
+
)
|
|
141
151
|
ROUTED_COMPAT_PROMPT = (
|
|
142
152
|
"You are running inside Claude Code through the ciel-runtime router. Do not stop after announcing what you plan to do. "
|
|
143
153
|
"When the user asks you to create, edit, or run code, immediately use the available Claude Code tools such as Write, Edit, Read, and Bash as appropriate, "
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
"""Z.AI CLI OAuth
|
|
1
|
+
"""Z.AI CLI OAuth with plan-scoped credential storage.
|
|
2
2
|
|
|
3
3
|
The wire contract mirrors the cross-platform init/poll flow exposed by the
|
|
4
|
-
ZCode runtime.
|
|
5
|
-
|
|
4
|
+
ZCode runtime. Coding Plan stores its resolved API key, while Start Plan stores
|
|
5
|
+
the ZCode JWT required by its separate gateway. Credentials are never written
|
|
6
|
+
into the legacy/manual ``zai`` provider profile.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
from __future__ import annotations
|
|
@@ -55,6 +56,8 @@ class ZaiOAuthInit:
|
|
|
55
56
|
class ZaiOAuthResult:
|
|
56
57
|
api_key: str
|
|
57
58
|
user_id: str
|
|
59
|
+
access_token: str = ""
|
|
60
|
+
jwt_token: str = ""
|
|
58
61
|
|
|
59
62
|
|
|
60
63
|
class ZaiOAuthHttp:
|
|
@@ -337,7 +340,13 @@ class ZaiOAuthService:
|
|
|
337
340
|
random_token: Callable[[], str] = lambda: secrets.token_hex(32)
|
|
338
341
|
timeout_seconds: float = ZAI_OAUTH_TIMEOUT_SECONDS
|
|
339
342
|
|
|
340
|
-
def login(
|
|
343
|
+
def login(
|
|
344
|
+
self,
|
|
345
|
+
*,
|
|
346
|
+
no_browser: bool = False,
|
|
347
|
+
on_authorize_url: Callable[[str], None],
|
|
348
|
+
profile: str = "coding-plan",
|
|
349
|
+
) -> ZaiOAuthResult:
|
|
341
350
|
poll_token = self.random_token()
|
|
342
351
|
try:
|
|
343
352
|
initialized = self.client.initialize(poll_token)
|
|
@@ -348,6 +357,7 @@ class ZaiOAuthService:
|
|
|
348
357
|
state=poll_token,
|
|
349
358
|
no_browser=no_browser,
|
|
350
359
|
on_authorize_url=on_authorize_url,
|
|
360
|
+
profile=profile,
|
|
351
361
|
)
|
|
352
362
|
on_authorize_url(initialized.authorize_url)
|
|
353
363
|
if not no_browser:
|
|
@@ -359,7 +369,7 @@ class ZaiOAuthService:
|
|
|
359
369
|
if status == "failed":
|
|
360
370
|
raise ZaiOAuthError("Z.AI OAuth authorization was denied or failed.")
|
|
361
371
|
if status == "ready":
|
|
362
|
-
return self._resolve_result(result)
|
|
372
|
+
return self._resolve_result(result, profile=profile)
|
|
363
373
|
self.sleep(min(initialized.poll_interval_seconds, max(0.0, deadline - self.now())))
|
|
364
374
|
raise ZaiOAuthError("Z.AI OAuth authorization timed out.")
|
|
365
375
|
|
|
@@ -369,6 +379,7 @@ class ZaiOAuthService:
|
|
|
369
379
|
state: str,
|
|
370
380
|
no_browser: bool,
|
|
371
381
|
on_authorize_url: Callable[[str], None],
|
|
382
|
+
profile: str,
|
|
372
383
|
) -> ZaiOAuthResult:
|
|
373
384
|
try:
|
|
374
385
|
with self.callback_receiver_factory(state, self.timeout_seconds) as receiver:
|
|
@@ -385,10 +396,13 @@ class ZaiOAuthService:
|
|
|
385
396
|
callback_url,
|
|
386
397
|
state,
|
|
387
398
|
redirect_uri=redirect_uri,
|
|
388
|
-
)
|
|
399
|
+
),
|
|
400
|
+
profile=profile,
|
|
389
401
|
)
|
|
390
402
|
|
|
391
|
-
def _resolve_result(
|
|
403
|
+
def _resolve_result(
|
|
404
|
+
self, result: Mapping[str, Any], *, profile: str
|
|
405
|
+
) -> ZaiOAuthResult:
|
|
392
406
|
zai = result.get("zai")
|
|
393
407
|
access_token = (
|
|
394
408
|
str(zai.get("access_token") or "").strip()
|
|
@@ -401,12 +415,27 @@ class ZaiOAuthService:
|
|
|
401
415
|
if isinstance(user, Mapping)
|
|
402
416
|
else ""
|
|
403
417
|
)
|
|
404
|
-
|
|
418
|
+
jwt_token = str(result.get("token") or "").strip()
|
|
419
|
+
if not access_token or not jwt_token or not user_id:
|
|
405
420
|
raise ZaiOAuthError(
|
|
406
421
|
"Z.AI OAuth ready response is missing credentials or user identity."
|
|
407
422
|
)
|
|
423
|
+
if profile == "start-plan":
|
|
424
|
+
return ZaiOAuthResult(
|
|
425
|
+
api_key=jwt_token,
|
|
426
|
+
user_id=user_id,
|
|
427
|
+
access_token=access_token,
|
|
428
|
+
jwt_token=jwt_token,
|
|
429
|
+
)
|
|
430
|
+
if profile != "coding-plan":
|
|
431
|
+
raise ZaiOAuthError(f"Unsupported Z.AI OAuth profile: {profile}")
|
|
408
432
|
api_key = self.client.resolve_coding_plan_api_key(access_token)
|
|
409
|
-
return ZaiOAuthResult(
|
|
433
|
+
return ZaiOAuthResult(
|
|
434
|
+
api_key=api_key,
|
|
435
|
+
user_id=user_id,
|
|
436
|
+
access_token=access_token,
|
|
437
|
+
jwt_token=jwt_token,
|
|
438
|
+
)
|
|
410
439
|
|
|
411
440
|
|
|
412
441
|
@dataclass(frozen=True, slots=True)
|
|
@@ -424,19 +453,35 @@ class ZaiOAuthRuntime:
|
|
|
424
453
|
service: ZaiOAuthService
|
|
425
454
|
ports: ZaiOAuthRuntimePorts
|
|
426
455
|
|
|
427
|
-
|
|
456
|
+
@staticmethod
|
|
457
|
+
def _provider_id(profile: str) -> str:
|
|
458
|
+
normalized = str(profile or "coding-plan").strip().lower()
|
|
459
|
+
if normalized == "coding-plan":
|
|
460
|
+
return "zai-coding-plan"
|
|
461
|
+
if normalized == "start-plan":
|
|
462
|
+
return "zai-start-plan"
|
|
463
|
+
raise ZaiOAuthError(f"Unsupported Z.AI OAuth profile: {profile}")
|
|
464
|
+
|
|
465
|
+
def token(self, profile: str = "coding-plan") -> str:
|
|
428
466
|
config = self.ports.load_config()
|
|
429
|
-
provider = config.get("providers", {}).get(
|
|
467
|
+
provider = config.get("providers", {}).get(self._provider_id(profile), {})
|
|
430
468
|
if provider.get("credential_source") != "zai-oauth":
|
|
431
469
|
return ""
|
|
432
470
|
return str(provider.get("api_key") or "").strip()
|
|
433
471
|
|
|
434
|
-
def import_api_key(
|
|
472
|
+
def import_api_key(
|
|
473
|
+
self,
|
|
474
|
+
api_key: str,
|
|
475
|
+
*,
|
|
476
|
+
source: str = "zcode",
|
|
477
|
+
profile: str = "coding-plan",
|
|
478
|
+
) -> list[str]:
|
|
435
479
|
key = str(api_key or "").strip()
|
|
436
480
|
if not key:
|
|
437
481
|
return ["Z.AI OAuth import skipped: no Coding Plan API key was found."]
|
|
438
482
|
config = self.ports.load_config()
|
|
439
|
-
|
|
483
|
+
provider_id = self._provider_id(profile)
|
|
484
|
+
provider = config.setdefault("providers", {}).setdefault(provider_id, {})
|
|
440
485
|
if (
|
|
441
486
|
str(provider.get("api_key") or "").strip() == key
|
|
442
487
|
and provider.get("credential_source") == "zai-oauth"
|
|
@@ -447,7 +492,7 @@ class ZaiOAuthRuntime:
|
|
|
447
492
|
provider["credential_source"] = "zai-oauth"
|
|
448
493
|
provider["oauth_authenticated_at"] = datetime.now(timezone.utc).isoformat()
|
|
449
494
|
provider["oauth_import_source"] = str(source or "zcode")
|
|
450
|
-
config["current_provider"] =
|
|
495
|
+
config["current_provider"] = provider_id
|
|
451
496
|
self.ports.save_config(config)
|
|
452
497
|
self.ports.clear_model_cache()
|
|
453
498
|
return [
|
|
@@ -455,25 +500,34 @@ class ZaiOAuthRuntime:
|
|
|
455
500
|
f"Credential: {self.ports.mask(key)}; fp {self.ports.fingerprint(key)}",
|
|
456
501
|
]
|
|
457
502
|
|
|
458
|
-
def action(
|
|
503
|
+
def action(
|
|
504
|
+
self,
|
|
505
|
+
action: str,
|
|
506
|
+
*,
|
|
507
|
+
no_browser: bool = False,
|
|
508
|
+
profile: str = "coding-plan",
|
|
509
|
+
) -> list[str]:
|
|
510
|
+
provider_id = self._provider_id(profile)
|
|
511
|
+
profile_label = "Coding Plan" if profile == "coding-plan" else "Start Plan"
|
|
459
512
|
if action == "status":
|
|
460
|
-
token = self.token()
|
|
513
|
+
token = self.token(profile)
|
|
461
514
|
if not token:
|
|
462
|
-
return ["Z.AI OAuth: not connected."]
|
|
515
|
+
return [f"Z.AI OAuth {profile_label}: not connected."]
|
|
463
516
|
return [
|
|
464
|
-
"Z.AI OAuth: connected
|
|
517
|
+
f"Z.AI OAuth {profile_label}: connected.",
|
|
465
518
|
f"Credential: {self.ports.mask(token)}; fp {self.ports.fingerprint(token)}",
|
|
466
519
|
]
|
|
467
520
|
if action == "logout":
|
|
468
521
|
config = self.ports.load_config()
|
|
469
|
-
provider = config.get("providers", {}).get(
|
|
522
|
+
provider = config.get("providers", {}).get(provider_id, {})
|
|
470
523
|
if provider.get("credential_source") != "zai-oauth":
|
|
471
|
-
return ["Z.AI OAuth: no OAuth-derived local credential to clear."]
|
|
524
|
+
return [f"Z.AI OAuth {profile_label}: no OAuth-derived local credential to clear."]
|
|
472
525
|
provider.pop("api_key", None)
|
|
473
526
|
provider.pop("api_keys", None)
|
|
474
527
|
provider.pop("credential_source", None)
|
|
475
528
|
provider.pop("oauth_authenticated_at", None)
|
|
476
529
|
provider.pop("oauth_user_id", None)
|
|
530
|
+
provider.pop("oauth_access_token", None)
|
|
477
531
|
self.ports.save_config(config)
|
|
478
532
|
self.ports.clear_model_cache()
|
|
479
533
|
return ["Z.AI OAuth-derived local credential cleared. Remote authorization was not revoked."]
|
|
@@ -481,24 +535,30 @@ class ZaiOAuthRuntime:
|
|
|
481
535
|
return [f"Unsupported Z.AI OAuth action: {action}"]
|
|
482
536
|
result = self.service.login(
|
|
483
537
|
no_browser=no_browser,
|
|
538
|
+
profile=profile,
|
|
484
539
|
on_authorize_url=lambda url: self.ports.output(
|
|
485
540
|
f"Open this URL to authorize Z.AI:\n{url}", flush=True
|
|
486
541
|
),
|
|
487
542
|
)
|
|
488
543
|
config = self.ports.load_config()
|
|
489
|
-
provider = config.setdefault("providers", {}).setdefault(
|
|
544
|
+
provider = config.setdefault("providers", {}).setdefault(provider_id, {})
|
|
490
545
|
provider["api_key"] = result.api_key
|
|
491
546
|
provider.pop("api_keys", None)
|
|
492
547
|
provider["credential_source"] = "zai-oauth"
|
|
493
548
|
provider["oauth_authenticated_at"] = datetime.now(timezone.utc).isoformat()
|
|
494
549
|
provider["oauth_user_id"] = result.user_id
|
|
495
|
-
config["current_provider"] =
|
|
550
|
+
config["current_provider"] = provider_id
|
|
496
551
|
self.ports.save_config(config)
|
|
497
552
|
self.ports.clear_model_cache()
|
|
498
|
-
|
|
499
|
-
"Z.AI OAuth login completed; the
|
|
553
|
+
lines = [
|
|
554
|
+
f"Z.AI OAuth login completed; the {profile_label} credential is active.",
|
|
500
555
|
f"Credential: {self.ports.mask(result.api_key)}; fp {self.ports.fingerprint(result.api_key)}",
|
|
501
556
|
]
|
|
557
|
+
if profile == "start-plan":
|
|
558
|
+
lines.append(
|
|
559
|
+
"Start Plan routed launch remains blocked because ZCode requires a fresh interactive CAPTCHA runtime header for model requests."
|
|
560
|
+
)
|
|
561
|
+
return lines
|
|
502
562
|
|
|
503
563
|
|
|
504
564
|
__all__ = [
|
|
@@ -104,10 +104,21 @@ class ZcodeRuntimeContext:
|
|
|
104
104
|
return "logout"
|
|
105
105
|
return None
|
|
106
106
|
|
|
107
|
+
@staticmethod
|
|
108
|
+
def _shared_oauth_profile(argv: list[str]) -> str:
|
|
109
|
+
for index, value in enumerate(argv):
|
|
110
|
+
if value.startswith("--profile="):
|
|
111
|
+
return value.split("=", 1)[1].strip() or "coding-plan"
|
|
112
|
+
if value == "--profile" and index + 1 < len(argv):
|
|
113
|
+
return str(argv[index + 1]).strip() or "coding-plan"
|
|
114
|
+
return "coding-plan"
|
|
115
|
+
|
|
107
116
|
def _run_shared_oauth(self, action: str, argv: list[str]) -> int:
|
|
108
117
|
try:
|
|
109
118
|
lines = self.lifecycle.oauth_action(
|
|
110
|
-
action,
|
|
119
|
+
action,
|
|
120
|
+
no_browser="--no-browser" in argv,
|
|
121
|
+
profile=self._shared_oauth_profile(argv),
|
|
111
122
|
)
|
|
112
123
|
except RuntimeError as exc:
|
|
113
124
|
self.process.print_line(f"Z.AI OAuth failed: {exc}", flush=True)
|
package/docs/CLI-Reference.md
CHANGED
|
@@ -44,13 +44,16 @@ Codex 런처는 `~/.codex/config.toml`을 수정하지 않는다. 실행 시점
|
|
|
44
44
|
ciel-runtime zcode
|
|
45
45
|
ciel-runtime --ca-runtime zcode -- --continue
|
|
46
46
|
ciel-runtimectl launch-zcode --prompt "작업 내용"
|
|
47
|
+
ciel-runtime zcode login --oauth --profile coding-plan
|
|
48
|
+
ciel-runtime zcode login --oauth --profile start-plan
|
|
47
49
|
```
|
|
48
50
|
|
|
49
51
|
ZCode는 워크스페이스별 Ciel 관리 홈과 `ZCODE_STORAGE_DIR`을 사용한다. 선택된
|
|
50
52
|
provider/model은 로컬 Anthropic Router 설정으로 투영되며 사용자의 일반
|
|
51
53
|
`%USERPROFILE%\.zcode` 또는 `~/.zcode` 설정은 덮어쓰지 않는다. `ciel-runtime
|
|
52
|
-
zcode login --oauth`와 API-key 패널의 Z.AI OAuth는
|
|
53
|
-
Coding Plan 키를 저장하므로 다른
|
|
54
|
+
zcode login --oauth`와 API-key 패널의 Z.AI OAuth는 별도 `zai-coding-plan`
|
|
55
|
+
profile에 Coding Plan 키를 저장하므로 다른 routed runtime도 같은 키를 사용한다.
|
|
56
|
+
기존 `zai` 수동 키는 변경하지 않는다.
|
|
54
57
|
|
|
55
58
|
---
|
|
56
59
|
|
|
@@ -112,21 +115,27 @@ ciel-runtimectl base-url ollama http://remote-server:11434
|
|
|
112
115
|
#### `zai-oauth`
|
|
113
116
|
|
|
114
117
|
```bash
|
|
115
|
-
ciel-runtimectl zai-oauth login
|
|
116
|
-
ciel-runtimectl zai-oauth login --no-browser
|
|
117
|
-
ciel-runtimectl zai-oauth status
|
|
118
|
-
ciel-runtimectl zai-oauth logout
|
|
118
|
+
ciel-runtimectl zai-oauth login --profile coding-plan
|
|
119
|
+
ciel-runtimectl zai-oauth login --profile coding-plan --no-browser
|
|
120
|
+
ciel-runtimectl zai-oauth status --profile coding-plan
|
|
121
|
+
ciel-runtimectl zai-oauth logout --profile coding-plan
|
|
122
|
+
ciel-runtimectl zai-oauth login --profile start-plan
|
|
123
|
+
ciel-runtimectl zai-oauth status --profile start-plan
|
|
124
|
+
ciel-runtimectl zai-oauth logout --profile start-plan
|
|
119
125
|
```
|
|
120
126
|
|
|
121
|
-
ZCode CLI의 Z.AI init/poll OAuth 흐름으로
|
|
122
|
-
발급한다. init endpoint가 404이면
|
|
127
|
+
기본 profile은 `coding-plan`이다. ZCode CLI의 Z.AI init/poll OAuth 흐름으로
|
|
128
|
+
로그인하고 Coding Plan API key를 발급한다. init endpoint가 404이면 확인된
|
|
129
|
+
authorization-code
|
|
123
130
|
계약으로 전환하며, `http://localhost:9899/callback`의 일회성 loopback listener가
|
|
124
131
|
브라우저 콜백을 자동으로 수신한다. `--no-browser`는 브라우저를 자동으로 열지
|
|
125
132
|
않지만 동일한 listener에서 기다린다. 브라우저와 Ciel Runtime이 서로 다른
|
|
126
133
|
머신이면 먼저 `ssh -L 9899:127.0.0.1:9899 user@runtime-host`처럼 callback port를
|
|
127
|
-
전달해야 한다.
|
|
128
|
-
|
|
129
|
-
않는다.
|
|
134
|
+
전달해야 한다. Coding Plan은 최종 API key만 저장한다. Start Plan은 별도
|
|
135
|
+
`zai-start-plan` profile에 ZCode JWT만 저장하고 OAuth access token은 저장하지
|
|
136
|
+
않는다. Start Plan의 모델 요청은 fresh Aliyun CAPTCHA runtime header가 필요하다는
|
|
137
|
+
실제 응답이 확인되어 routed launch가 차단된다. `logout`은 선택한 profile의 로컬
|
|
138
|
+
credential만 지우며 원격 승인을 철회하지 않는다.
|
|
130
139
|
|
|
131
140
|
#### `api-key`
|
|
132
141
|
```bash
|
package/docs/Installation.md
CHANGED
|
@@ -127,9 +127,13 @@ ciel-runtime zcode --continue
|
|
|
127
127
|
|
|
128
128
|
ZCode가 없으면 `zcode-app-cli`를 npm으로 설치한다. 실행 시 워크스페이스별
|
|
129
129
|
Ciel 관리 홈을 사용하고 선택된 provider/model을 로컬 Router로 연결한다.
|
|
130
|
-
Z.AI OAuth는 `ciel-runtimectl zai-oauth login
|
|
131
|
-
--oauth`로
|
|
132
|
-
저장되어 Claude, Codex, AGY, ZCode 등
|
|
130
|
+
Z.AI Coding Plan OAuth는 `ciel-runtimectl zai-oauth login --profile coding-plan`
|
|
131
|
+
또는 `ciel-runtime zcode login --oauth`로 등록한다. 최종 Coding Plan API key는
|
|
132
|
+
별도 `zai-coding-plan` provider 설정에 저장되어 Claude, Codex, AGY, ZCode 등
|
|
133
|
+
routed client가 함께 사용하며 기존 `zai` 수동 API key를 덮어쓰지 않는다.
|
|
134
|
+
`--profile start-plan`은 별도 JWT를 저장하지만, Start Plan 모델 요청에 필요한
|
|
135
|
+
fresh Aliyun CAPTCHA runtime header를 Ciel이 생성하지 않으므로 routed launch는
|
|
136
|
+
명시적으로 차단한다.
|
|
133
137
|
|
|
134
138
|
---
|
|
135
139
|
|
package/docs/Providers.md
CHANGED
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
| `opencode-go` | OpenCode Go | Anthropic Messages / OpenAI Chat | `https://opencode.ai/zen/go` |
|
|
17
17
|
| `kimi` | Kimi.com | Anthropic Messages / OpenAI Chat | `https://api.kimi.com/coding` |
|
|
18
18
|
| `zai` | Z.AI GLM | Anthropic Messages | `https://api.z.ai/api/anthropic` |
|
|
19
|
+
| `zai-api` | Z.AI Model API (API Key) | OpenAI Chat | `https://api.z.ai/api/paas/v4` |
|
|
20
|
+
| `zai-coding-plan` | Z.AI Coding Plan | Anthropic Messages / OpenAI Chat | `https://api.z.ai/api/coding/paas/v4` |
|
|
21
|
+
| `zai-start-plan` | Z.AI Start Plan | 프로필 등록됨, routed launch 차단 | `https://zcode.z.ai/api/v1/zcode-plan` |
|
|
19
22
|
| `vllm` | vLLM | OpenAI Chat | 로컬/원격 vLLM |
|
|
20
23
|
| `lm-studio` | LM Studio | OpenAI Chat | 로컬 LM Studio |
|
|
21
24
|
| `nvidia-hosted` | Nvidia Hosted | OpenAI Chat | NVIDIA NIM Cloud |
|
|
@@ -181,20 +184,48 @@ Anthropic thinking 객체나 문서로 확인되지 않은 GLM-5.2 effort 문자
|
|
|
181
184
|
|
|
182
185
|
## ZAI (Z.AI GLM)
|
|
183
186
|
|
|
184
|
-
|
|
187
|
+
Z.AI의 API key, Coding Plan, Start Plan을 서로 다른 provider profile로 보존한다.
|
|
188
|
+
기존 `zai` provider와 그 수동 API key는 마이그레이션하거나 덮어쓰지 않는다.
|
|
189
|
+
|
|
190
|
+
| profile | 인증 | Ciel OpenAI 경로 | Anthropic 경로 |
|
|
191
|
+
|---------|------|------------------|----------------|
|
|
192
|
+
| `zai` | 기존 수동 API key | 해당 없음 | `https://api.z.ai/api/anthropic` |
|
|
193
|
+
| `zai-api` | 일반 종량제 API key | `https://api.z.ai/api/paas/v4` | 공식 모델 문서에서 일반 API용 별도 Anthropic URL을 확인하지 못했으므로 사용하지 않음 |
|
|
194
|
+
| `zai-coding-plan` | Coding Plan API key 또는 `--profile coding-plan` OAuth | `https://api.z.ai/api/coding/paas/v4` | `https://api.z.ai/api/anthropic` |
|
|
195
|
+
| `zai-start-plan` | `--profile start-plan` OAuth JWT | `https://zcode.z.ai/api/v1/zcode-plan` | `https://zcode.z.ai/api/v1/zcode-plan/anthropic` |
|
|
196
|
+
|
|
197
|
+
Coding Plan의 OpenAI Chat/Anthropic URL은 Z.AI 공식 Tool Integration 문서에
|
|
198
|
+
기재된 값이다. Start Plan URL과 JWT 저장 형태는 설치된 ZCode 3.8.1-15 runtime의
|
|
199
|
+
provider 설정에서 확인했다. 그러나 실제 Start Plan JWT 요청은 fresh
|
|
200
|
+
`x-aliyun-captcha-verify-param`이 없으면 `400`, provider code `3007`,
|
|
201
|
+
`captcha verify failed`로 거절됐다. 이 값은 ZCode의 대화형 private runtime이
|
|
202
|
+
요청마다 갱신한다. Ciel은 CAPTCHA를 우회하거나 값을 위조하지 않으며, 따라서
|
|
203
|
+
`zai-start-plan`을 routed client로 실행하려 하면 원인을 표시하고 launch를 차단한다.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
ciel-runtimectl zai-oauth login --profile coding-plan
|
|
207
|
+
ciel-runtimectl zai-oauth status --profile coding-plan
|
|
208
|
+
ciel-runtimectl zai-oauth login --profile start-plan
|
|
209
|
+
ciel-runtimectl zai-oauth status --profile start-plan
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Coding Plan 로그인은 최종 plan API key만 `zai-coding-plan`에 저장한다. Start Plan
|
|
213
|
+
로그인은 ZCode JWT만 `zai-start-plan`에 저장하며 OAuth access token은 저장하지
|
|
214
|
+
않는다. 두 로그인 모두 기존 `zai` credential을 변경하지 않는다.
|
|
215
|
+
|
|
185
216
|
- 기본 모델: `glm-5.3[1m]`
|
|
186
|
-
- ZCode CLI의 init/poll 및 localhost:9899 authorization-code fallback OAuth 흐름: `ciel-runtimectl zai-oauth login`
|
|
187
|
-
- OAuth access token과 ZCode JWT는 메모리에만 유지하고, 최종 Coding Plan API key만 기존 Ciel credential 규칙으로 저장한다.
|
|
188
217
|
- GLM-5.3은 reasoning을 끌 수 없으며 `low`, `high`, `max` effort만 사용한다.
|
|
189
|
-
- Managed MCP 서버
|
|
190
|
-
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
| `glm-5.
|
|
196
|
-
| `glm-5
|
|
197
|
-
| `glm-
|
|
218
|
+
- `zai`, `zai-api`, `zai-coding-plan`은 Managed MCP 서버 `web-search-prime`,
|
|
219
|
+
`web-reader`, `zread`를 사용할 수 있다.
|
|
220
|
+
- 공식 모델 한도:
|
|
221
|
+
|
|
222
|
+
| 모델 접두사 | 컨텍스트 | 최대 출력 |
|
|
223
|
+
|-----------|---------:|----------:|
|
|
224
|
+
| `glm-5.3` | 1,000,000 | 131,072 |
|
|
225
|
+
| `glm-5.2` | 1,000,000 | 131,072 |
|
|
226
|
+
| `glm-5.1` | 200,000 | 131,072 |
|
|
227
|
+
| `glm-5-turbo` | 200,000 | 모델별 동적 값 |
|
|
228
|
+
| `glm-4.7` | 200,000 | 모델별 동적 값 |
|
|
198
229
|
|
|
199
230
|
---
|
|
200
231
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: mia-zai-plan-profile-429-diagnosis-20260824
|
|
5
|
+
date: "2026-08-24"
|
|
6
|
+
objective: >-
|
|
7
|
+
Determine how Z.AI Start Plan, Coding Plan, and general API usage are
|
|
8
|
+
distinguished and identify the evidence-backed cause of Mia's OAuth-login
|
|
9
|
+
success followed by HTTP 429.
|
|
10
|
+
status: diagnosis-complete
|
|
11
|
+
|
|
12
|
+
observed_runtime:
|
|
13
|
+
host: mia@100.95.132.58
|
|
14
|
+
provider: zai
|
|
15
|
+
model: glm-5.3
|
|
16
|
+
request_endpoint: https://api.z.ai/api/anthropic
|
|
17
|
+
error:
|
|
18
|
+
http_status: 429
|
|
19
|
+
provider_code: "1113"
|
|
20
|
+
provider_message: Insufficient balance or no resource package. Please recharge.
|
|
21
|
+
credential_status_text: connected (Coding Plan API key)
|
|
22
|
+
|
|
23
|
+
provider_evidence:
|
|
24
|
+
official_zai:
|
|
25
|
+
coding_plan_anthropic_endpoint: https://api.z.ai/api/anthropic
|
|
26
|
+
coding_plan_openai_endpoint: https://api.z.ai/api/coding/paas/v4
|
|
27
|
+
general_api_endpoint: https://api.z.ai/api/paas/v4
|
|
28
|
+
quota_probe_endpoint: https://api.z.ai/api/monitor/usage/quota/limit
|
|
29
|
+
mia_quota_probe:
|
|
30
|
+
code: 500
|
|
31
|
+
message: 当前用户不存在coding plan
|
|
32
|
+
translated_fact: current user has no Coding Plan
|
|
33
|
+
limits: []
|
|
34
|
+
installed_zcode:
|
|
35
|
+
package: zcode-app-cli
|
|
36
|
+
version: 3.8.1-15
|
|
37
|
+
provider_ids:
|
|
38
|
+
start_plan: builtin:zai-start-plan
|
|
39
|
+
coding_plan: builtin:zai-coding-plan
|
|
40
|
+
general_api: builtin:zai
|
|
41
|
+
start_plan_anthropic_endpoint: https://zcode.z.ai/api/v1/zcode-plan/anthropic
|
|
42
|
+
coding_plan_openai_endpoint: https://api.z.ai/api/coding/paas/v4
|
|
43
|
+
general_api_openai_endpoint: https://api.z.ai/api/paas/v4
|
|
44
|
+
start_plan_runtime_requirements:
|
|
45
|
+
- provider runtime headers refreshed before each request
|
|
46
|
+
- fresh x-aliyun-captcha-verify-param request header
|
|
47
|
+
- dedicated zcode-plan routes
|
|
48
|
+
start_plan_model_paths_signing:
|
|
49
|
+
required: false
|
|
50
|
+
evidence: >-
|
|
51
|
+
Installed ZCode source explicitly excludes the Start Plan Anthropic
|
|
52
|
+
and OpenAI model paths from client signing.
|
|
53
|
+
|
|
54
|
+
ciel_implementation_evidence:
|
|
55
|
+
result_fields_retained:
|
|
56
|
+
- api_key
|
|
57
|
+
- user_id
|
|
58
|
+
oauth_resolution: >-
|
|
59
|
+
The OAuth access token is unconditionally converted to a business API key
|
|
60
|
+
named zcode-api-key.
|
|
61
|
+
stored_provider: zai
|
|
62
|
+
stored_credential_source: zai-oauth
|
|
63
|
+
plan_identity_persisted: false
|
|
64
|
+
start_plan_access_token_persisted: false
|
|
65
|
+
zcode_jwt_persisted: false
|
|
66
|
+
status_entitlement_probe: false
|
|
67
|
+
|
|
68
|
+
direct_start_plan_probe:
|
|
69
|
+
credential_type: ZCode JWT
|
|
70
|
+
endpoint: https://zcode.z.ai/api/v1/zcode-plan/anthropic/v1/messages
|
|
71
|
+
authorization_bearer_result:
|
|
72
|
+
http_status: 400
|
|
73
|
+
provider_code: "3007"
|
|
74
|
+
provider_message: captcha verify failed
|
|
75
|
+
x_api_key_result:
|
|
76
|
+
http_status: 401
|
|
77
|
+
confirmed_boundary: >-
|
|
78
|
+
A Start Plan JWT and endpoint are insufficient for routed requests. A
|
|
79
|
+
fresh Aliyun CAPTCHA verification header is required by the observed
|
|
80
|
+
gateway response.
|
|
81
|
+
|
|
82
|
+
conclusion:
|
|
83
|
+
confirmed: >-
|
|
84
|
+
Ciel Runtime currently cannot distinguish the authorization page's Start
|
|
85
|
+
Plan selection from Coding Plan. OAuth success proves identity
|
|
86
|
+
authorization only. The resulting API key is routed to the Coding Plan
|
|
87
|
+
endpoint, while Z.AI's quota API says the Mia credential has no Coding
|
|
88
|
+
Plan. This mismatch produced provider code 1113 and the observed HTTP 429.
|
|
89
|
+
not_claimed: >-
|
|
90
|
+
The available evidence does not identify a documented public API that maps
|
|
91
|
+
the authorization-page selection directly to a stable plan identifier.
|
|
92
|
+
|
|
93
|
+
implementation_follow_up:
|
|
94
|
+
provider_profiles:
|
|
95
|
+
- zai-api
|
|
96
|
+
- zai-coding-plan
|
|
97
|
+
- zai-start-plan
|
|
98
|
+
legacy_zai_credential_preserved: true
|
|
99
|
+
coding_plan_oauth_target: zai-coding-plan
|
|
100
|
+
start_plan_oauth_target: zai-start-plan
|
|
101
|
+
start_plan_routed_launch: blocked-with-evidence
|
|
@@ -68,3 +68,15 @@ knowledge:
|
|
|
68
68
|
tests: 255
|
|
69
69
|
skipped: 12
|
|
70
70
|
full_test_exit_code: 0
|
|
71
|
+
deployment:
|
|
72
|
+
functional_commit: d4ce317d36eba4cc91a3b852a217fbea2852bffb
|
|
73
|
+
main_ci: success
|
|
74
|
+
nightly_ci: success
|
|
75
|
+
main_publish: success
|
|
76
|
+
nightly_publish: success
|
|
77
|
+
npm_latest: 0.2.28
|
|
78
|
+
npm_nightly: 0.2.28-nightly.20260824-070710.d4ce317
|
|
79
|
+
registry_package_smoke_version: 0.2.28
|
|
80
|
+
mia_installed_version: 0.2.28-nightly.20260824-070710.d4ce317
|
|
81
|
+
mia_callback_http_status: 200
|
|
82
|
+
mia_callback_uri: http://localhost:9899/callback
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: zai-plan-provider-login-separation-20260824
|
|
5
|
+
date: "2026-08-24"
|
|
6
|
+
objective: >-
|
|
7
|
+
Separate Z.AI general API, Coding Plan, and Start Plan provider and OAuth
|
|
8
|
+
state while preserving the existing manual Z.AI API-key profile.
|
|
9
|
+
status: release-pending
|
|
10
|
+
|
|
11
|
+
evidence:
|
|
12
|
+
official_model_docs:
|
|
13
|
+
glm_5_1:
|
|
14
|
+
url: https://docs.z.ai/guides/llm/glm-5.1
|
|
15
|
+
model_id: glm-5.1
|
|
16
|
+
general_openai_base_url: https://api.z.ai/api/paas/v4
|
|
17
|
+
context_tokens: 200000
|
|
18
|
+
maximum_output_tokens: 131072
|
|
19
|
+
glm_5_2:
|
|
20
|
+
url: https://docs.z.ai/guides/llm/glm-5.2
|
|
21
|
+
model_id: glm-5.2
|
|
22
|
+
general_openai_base_url: https://api.z.ai/api/paas/v4
|
|
23
|
+
context_tokens: 1000000
|
|
24
|
+
maximum_output_tokens: 131072
|
|
25
|
+
glm_5_3:
|
|
26
|
+
url: https://docs.z.ai/guides/llm/glm-5.3
|
|
27
|
+
model_id: glm-5.3
|
|
28
|
+
context_tokens: 1000000
|
|
29
|
+
maximum_output_tokens: 131072
|
|
30
|
+
official_coding_plan:
|
|
31
|
+
url: https://docs.z.ai/devpack/tool/others
|
|
32
|
+
openai_chat_base_url: https://api.z.ai/api/coding/paas/v4
|
|
33
|
+
openai_responses_base_url: https://api.z.ai/api/v1
|
|
34
|
+
anthropic_base_url: https://api.z.ai/api/anthropic
|
|
35
|
+
installed_zcode_3_8_1_15:
|
|
36
|
+
start_openai_base_url: https://zcode.z.ai/api/v1/zcode-plan
|
|
37
|
+
start_anthropic_base_url: https://zcode.z.ai/api/v1/zcode-plan/anthropic
|
|
38
|
+
start_credential_type: ZCode OAuth JWT
|
|
39
|
+
model_paths_exempt_from_client_signing: true
|
|
40
|
+
live_start_probe:
|
|
41
|
+
bearer_jwt_http_status: 400
|
|
42
|
+
bearer_jwt_provider_code: "3007"
|
|
43
|
+
bearer_jwt_provider_message: captcha verify failed
|
|
44
|
+
x_api_key_http_status: 401
|
|
45
|
+
|
|
46
|
+
implementation:
|
|
47
|
+
profiles:
|
|
48
|
+
legacy_manual: zai
|
|
49
|
+
general_api_key: zai-api
|
|
50
|
+
coding_plan: zai-coding-plan
|
|
51
|
+
start_plan: zai-start-plan
|
|
52
|
+
oauth:
|
|
53
|
+
default_profile: coding-plan
|
|
54
|
+
accepted_profiles:
|
|
55
|
+
- coding-plan
|
|
56
|
+
- start-plan
|
|
57
|
+
legacy_manual_key_overwritten: false
|
|
58
|
+
oauth_access_token_persisted: false
|
|
59
|
+
safety_boundary:
|
|
60
|
+
start_plan_routed_launch: blocked
|
|
61
|
+
reason: fresh Aliyun CAPTCHA runtime header is unavailable
|
|
62
|
+
bypass_or_fabrication_implemented: false
|
|
63
|
+
|
|
64
|
+
validation:
|
|
65
|
+
targeted_zai_tests:
|
|
66
|
+
status: passed
|
|
67
|
+
count: 44
|
|
68
|
+
full_test_suite:
|
|
69
|
+
status: passed
|
|
70
|
+
unit:
|
|
71
|
+
passed: 1174
|
|
72
|
+
skipped: 44
|
|
73
|
+
router:
|
|
74
|
+
passed: 947
|
|
75
|
+
channel:
|
|
76
|
+
passed: 381
|
|
77
|
+
skipped: 80
|
|
78
|
+
runtime:
|
|
79
|
+
passed: 255
|
|
80
|
+
skipped: 12
|
|
81
|
+
static_checks:
|
|
82
|
+
ruff: passed
|
|
83
|
+
project_metadata: passed
|
|
84
|
+
diff_check: passed
|
|
85
|
+
main_module_line_count: 4980
|
|
86
|
+
package:
|
|
87
|
+
dry_run_version: 0.2.29
|
|
88
|
+
local_deployment:
|
|
89
|
+
installed_home: C:\Users\djlov\.local\share\ciel-runtime
|
|
90
|
+
version: 0.2.29
|
|
91
|
+
cli_profile_help_verified: true
|
|
92
|
+
provider_catalog_verified:
|
|
93
|
+
- zai-api
|
|
94
|
+
- zai-coding-plan
|
|
95
|
+
remaining:
|
|
96
|
+
- stable and nightly release verification
|
package/package.json
CHANGED