78 lines
2.9 KiB
Markdown
78 lines
2.9 KiB
Markdown
# 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`.
|
|
|
|
## 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.
|