- TypeScript 100%
prime-alibaba #
Prime Agent extension that registers Alibaba Model Studio token plan models
(https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1) as the
alibaba provider over the OpenAI-compatible API.
Install #
Installed as an auto-discovered global extension:
~/.prime/agent/extensions/prime-alibaba -> /Users/dawn/proj/prime-alibaba
Edits here are picked up by /reload in a running session; new sessions load it at startup.
For a one-off run without installing: prime-agent -e /Users/dawn/proj/prime-alibaba.
Auth #
Key resolution order:
- key stored by
/login-> pick Alibaba Model Studio (token plan), paste the key ALIBABA_API_KEY
There is no key file. Store the key with /login and it lives in
~/.prime/agent/auth.json, which Prime Agent checks before the extension's own config;
that is the durable source. ALIBABA_API_KEY exists for throwaway shells, and when
neither is present the provider reports an unresolved key rather than sending a
placeholder as the credential.
ALIBABA_BASE_URL overrides the endpoint (other region or gateway).
Model list #
models.json is the model list, committed and read at startup. Nothing about a model's
capabilities is looked up at runtime.
Regenerate it after a plan or catalog change:
npx tsx regen.ts
That asks the endpoint for /models (what the key is entitled to) and models.dev for
metadata (context window, output limit, reasoning, image input), then writes the file.
Non-chat entitlements (audio, image generation) are skipped, and the ids it refused are
recorded in skipped. Ids the alibaba-token-plan entry has not caught up with are filled
from another Alibaba catalog listing the same id (alibaba-cn and the -cn variants
describe the same models) and never from an unrelated provider, where a shared id is a name
collision: auto is a route on this gateway and model-oracle-ai's model elsewhere, so that
entry would hand the route someone else's 1M context and image input. Freezing the choice in
a committed file is the point, because resolving it live made deepseek-v4.1-flash gain and
lose image input between runs depending on which provider models.dev happened to list first.
At startup the extension still asks /models for entitlement only, and hides models the key
cannot call. The list is cached in ~/.prime/agent/alibaba-entitlement.json, so a slow or
failed call reuses the last known list. Entitlement can only hide, never add, so an id the
account gains after the last bake is invisible until regen.ts runs again; a session that
finds one notifies with the ids and says to regenerate, rather than dropping them in silence.
Thinking #
| family | switch | depth | levels offered |
|---|---|---|---|
| deepseek | thinking: {type} (verified) or enable_thinking (documented) |
reasoning_effort: low, medium, high, xhigh, max, default high |
off, low, medium, high, xhigh, max |
| qwen | enable_thinking |
thinking_budget (token cap) |
off, high |
| glm | none, thinking is on by default and glm-5.3 refuses to turn it off | reasoning_effort: glm-5.2 none..max, glm-5.3 low/high/max only |
glm-5.2 off, low, medium, high, xhigh, max; glm-5.3 low, high, max |
DeepSeek on Model Studio takes the full reasoning_effort ladder, unlike Prime's
built-in DeepSeek entries, which expose only high and max - so the levels are remapped
here rather than inherited.
GLM depth is reasoning_effort, measured against the endpoint rather than assumed. glm-5.3
answers invalid_parameter_error for every value outside low/high/max and for
enable_thinking: false ("restricted to True"), so it never sends enable_thinking and
hides off; a request already pinned to off clamps up to low instead of failing. glm-5.2
takes none through max, and none - what off maps to - suppresses reasoning the same way
enable_thinking: false does. The docs give enable_thinking priority over
reasoning_effort, which is the other reason not to send both.
Qwen still has no effort parameter. Its depth is a token cap (thinking_budget), which
Prime's OpenAI-completions path does not send, so every level above off is the same
request and only off/high are offered.
Sources: deep thinking, DeepSeek API, GLM.
Prompt caching #
Model Studio has two modes, and they are mutually exclusive per request:
- implicit: always on, no markers, 1024-token minimum, hit not guaranteed
- explicit:
cache_control: {"type": "ephemeral"}markers, 5 minute TTL that resets on each hit, deterministic, 1024-token minimum
Qwen honours the markers here (usage comes back with cache_type: ephemeral and
cache_creation_input_tokens), so qwen models get cacheControlFormat: "anthropic" and
Prime marks the system prompt, the last tool definition, and the last conversation
message. GLM and DeepSeek on this gateway ignore the markers and cache implicitly, so
they are left unmarked.
Measured in-session: turn 2 of a session reported cacheRead: 15042 of ~15.1K prompt
tokens. Separate --print runs never share a cache because the system prompt embeds the
per-session conversation log path about 2.6K characters in, which is under the 1024-token
minimum for the shared prefix.
Rate limits #
Model Studio limits are per account, per model, per minute (TPM) and per second (TPS =
TPM/60). A 429 reads Allocated quota exceeded and means TPM, not the 7-day plan quota.
The gateway sends no Retry-After and no x-ratelimit-* headers, so the only signal is
the failure itself.
Recovery is fast: in a measured session, 32 of 124 calls hit 429, never more than two in
a row, and the next successful call landed 2.6-3.1s later. Prime handles this with its
own retry, tuned in ~/.prime/agent/settings.json:
{ "retry": { "maxRetries": 5, "baseDelayMs": 1000 } }
That gives 1s, 2s, 4s, 8s, 16s. Sustained throughput in that session was 0.7-1.6M tokens/minute with 129K-token prompts, which is what pushes it over the limit; prompt caching does not help here, because cached tokens still count as prompt tokens.