pi-sensenova
v1.1.2
Published
Pi extension for the SenseNova provider
Readme
pi-sensenova
Pi extension for SenseNova, an OpenAI-compatible provider. It registers the sensenova provider with a seed model catalog, then refreshes the catalog from /v1/models in the background and persists it for offline starts.
Install
pi install npm:pi-sensenovaOr install from git:
pi install git:github.com/pgciq/pi-sensenovaTo try it for a single run without persisting:
pi -e .Configuration
Set the API key before starting pi:
export SENSENOVA_API_KEY="your-api-key"- Base URL:
https://token.sensenova.cn/v1 - Provider id:
sensenova - Auth:
SENSENOVA_API_KEYenv var (the key is kept as an env reference, so pi marks the provider unconfigured rather than sending a placeholder when the variable is absent)
Or let Pi manage the credential interactively:
/login sensenovaThe key is stored in ~/.pi/agent/auth.json; SENSENOVA_API_KEY remains a
fallback.
- OpenAI-compatible streaming — text models stream through pi-ai's
openai-completionsAPI. - Reasoning / thinking models —
deepseek-v4-flash,deepseek-v4-pro, andglm-5.2expose a thinking-effort level map (minimal,low,medium,high,xhigh,max). - Image generation — models matching
sensenova-u1,sensenova-u1.5,sensenova-u1-fast,sensenova-u1.5-fast(andsensenova-u1.5-lite) route to the verified/v1/images/generationsendpoint. Generated images are saved under.pi/generated-images/; supported terminals also receive a TUIImageentry (rendered inline when the terminal supports a graphics protocol), while the saved path is reported as a clickablefile://link in the TUI. Print/RPC mode reports the saved path as plain text. - Image editing —
sensenova-u1.5-literoutes to/v1/images/editswhen the prompt includes reference images. - Dynamic model discovery — a seed list is available immediately; the full list is fetched from
/v1/modelsand cached. Discovered models survive restarts and offline starts.
Seed models
| Model id | Notes |
| --------------------- | ------------------------------ |
| sensenova-6.7-flash-lite | Reasoning-capable text model |
| deepseek-v4-flash | Reasoning-capable text model |
| glm-5.2 | Reasoning-capable text model |
Models discovered via /v1/models are added automatically.
Model discovery (non-blocking)
pi-sensenova registers a seed model catalog synchronously at load (so pi starts instantly) and refreshes it from /v1/models in the background via pi's refreshModels callback — it never blocks startup on the network.
- The seed list is always available immediately, even offline or without
SENSENOVA_API_KEY. - A successful background refresh replaces the seed list and is persisted to pi's provider cache, so discovered models survive restarts and offline starts.
- Every network call is bounded by a timeout and degrades to the seed list on any failure.
Usage
pi --model sensenova/deepseek-v4-flash "你好"Generate an image (text prompt) with an image model:
pi --model sensenova/sensenova-u1.5-lite "一只戴帽子的猫"Commands
The extension registers the following commands:
| Command | Description |
|---|---|
| /sensenova-models [image\|vision\|audio\|video\|reasoning\|tools] | List SenseNova models with capabilities, context/output limits; an optional filter narrows the table. |
| /sensenova-usage | Show token/cost usage accumulated in the current Pi process. |
Examples:
/sensenova-models
/sensenova-models vision
/sensenova-models image
/sensenova-usage/sensenova-usage is based on message_end usage reported by completed assistant messages and is therefore local to the current Pi process. SenseNova's OpenAI-compatible API does not expose a uniform account-level billing/usage endpoint through this provider, so this command is not an account invoice.
Development
The extension depends on @earendil-works/pi-ai (a peer dependency provided by pi at runtime). createAssistantMessageEventStream is imported from the bare package, and openAICompletionsApi is resolved defensively: newer pi-ai builds expose it only via the @earendil-works/pi-ai/api/openai-completions.lazy subpath, while older builds export it from the bare package. The fallback import keeps the extension loading on both layouts. Validate with:
node --test