pi-unigpt/DEVELOPMENT.md
Benjamin Hackl 46c1731a92
Some checks failed
CI / test (22) (push) Failing after 35s
CI / test (24) (push) Failing after 28s
Support pi 1.3 and newer
2026-11-03 21:07:18 +01:00

86 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Development
## Setup
```sh
pnpm install
pnpm run ci # type check + tests
```
To test your checkout in pi, install it from the local path:
```sh
pi install /absolute/path/to/pi-unigpt
```
Changes take effect after `/reload`.
Tests use fake keys, mocked discovery, and a local HTTP server. They never
contact uniGPT or read your pi configuration.
## Layout
| File | Purpose |
| --- | --- |
| `src/provider.ts` | The pi provider: login, model discovery, model metadata |
| `src/index.ts` | Extension entry point and the `/unigpt-refresh` command |
| `test/provider.test.ts` | Discovery, login, caching, and transport tests |
| `test/command.test.ts` | `/unigpt-refresh` behavior |
## How it works
**Endpoints.** The API base is
`https://api.mygpt.uni-graz.at/api/v1/llms/openai`. Discovery calls
`GET /models` with bearer auth; inference uses pi's built-in OpenAI
Responses transport on `POST /responses`. Every request must also carry a
`deployment-id` header naming the model, which each discovered model sets.
**Model metadata.** `/models` returns only IDs (e.g. `gpt-5.4`). Those IDs
are OpenAI model names, so `lookupCatalogMetadata` reads name, context
window, output limit, and image support from pi's bundled catalog
(`openai` and `azure` providers), taking the smaller value where the two
differ. This keeps the extension free of a hardcoded model table: new
models get correct limits when pi updates. Unknown IDs fall back to pi's
defaults for custom models (128k context, 16k output, text only).
The uniGPT web app has richer endpoints
(`/api/v1/tenants/uni/ai-models[/detailed]`) and an OpenAPI spec
(`/api/v1/docs/openapi.yaml`), but they require a browser session token
and reject API keys. If uniGPT ever exposes limits to API keys, prefer
them over the catalog lookup.
**Reasoning.** uniGPT ignores `reasoning.effort` and applies a fixed effort
per deployment (verified against the live API), so every model sets
`reasoning: false` to avoid offering thinking levels that do nothing.
**Caching and errors.** pi persists the discovered catalog and restores it
offline. A failed or malformed refresh keeps the previous catalog; single
malformed entries are skipped. Error messages never include the API key or
server response bodies.
**Login.** `/login unigpt` validates the key against `/models` before pi
stores it. Validation always uses the default endpoint, even if a user
overrides `baseUrl` in `models.json`.
## Compatibility
Supported: pi 1.3 and newer (`peerDependencies`). Development pins pi 1.5.
On 1.0–1.2 the tests pass and a live session worked, but `pnpm run check`
fails: pi's `Provider` typing rejects this provider, and 1.0–1.1 also lack
`RefreshModelsContext.baseUrl`, so `baseUrl` overrides are ignored there. To check another version, pin both
`@earendil-works/*` dev dependencies to it and run `pnpm run ci`.
## Known server-side issues
As of November 2026, `gpt-5-nano` and `gpt-4.1-nano` return HTTP 500
(`'NoneType' object has no attribute 'decrypt'`) for every request.
## Releasing
1. Run `pnpm run ci`.
2. Bump `version` in `package.json` and commit.
3. Tag and push: `git tag vX.Y.Z && git push origin main vX.Y.Z`.
4. Update the version in the README's "Pinning a version" example.
CI is defined in `.gitea/workflows/ci.yml` and runs once Gitea Actions are
enabled for the repository.