README.md

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:

  1. key stored by /login -> pick Alibaba Model Studio (token plan), paste the key
  2. 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.