pi-nebius 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  Versions use Semantic Versioning. Entries describe changes included in the named version;
4
4
  a version is released only when its matching Git tag and GitHub release are published.
5
5
 
6
+ ## [0.3.2](https://github.com/PeterHdd/pi-nebius/compare/v0.3.1...v0.3.2) (2026-09-17)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * launch benchmark workers from installed packages ([f7e717a](https://github.com/PeterHdd/pi-nebius/commit/f7e717a3454ae700451e63f54d78bda1d155d1dd))
12
+ * launch benchmark workers from installed packages ([cf516f7](https://github.com/PeterHdd/pi-nebius/commit/cf516f724d0d85ce921e4b0a6347bdcb6b251493))
13
+
14
+ ## [0.3.1](https://github.com/PeterHdd/pi-nebius/compare/v0.3.0...v0.3.1) (2026-09-17)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * enable automated npm publishing and simplify user documentation ([a90b4a4](https://github.com/PeterHdd/pi-nebius/commit/a90b4a40ce7d5bdc8bf8bddb7dc4777c4c68a269))
20
+ * enable automated npm publishing and simplify user documentation ([81b6348](https://github.com/PeterHdd/pi-nebius/commit/81b6348f9710d786ff6f8ae18b56716e8c594e73))
21
+
6
22
  ## [0.3.0](https://github.com/PeterHdd/pi-nebius/compare/v0.2.1...v0.3.0) (2026-09-17)
7
23
 
8
24
 
package/CONTRIBUTING.md CHANGED
@@ -17,8 +17,8 @@ with the tested Pi peers. Both require network access. Tests need loopback socke
17
17
  and permission to launch/stop subprocesses. Do not provide live API keys to CI.
18
18
 
19
19
  Keep changes focused and add regression tests for behavior changes. Use a descriptive
20
- commit message; no special commit syntax or automatic version inference is required.
21
- Update the changelog for user-visible changes. Report whether a test used mocks or
20
+ Conventional Commit message (`feat:`, `fix:`, `docs:`, or `chore:`). Release Please
21
+ generates the version and changelog; do not bump them manually. Report whether a test used mocks or
22
22
  live Nebius; a scripted tool loop is not a hosted-model benchmark.
23
23
 
24
24
  Never commit credentials, `.env` files, private fixtures, `node_modules`, or generated
@@ -26,7 +26,10 @@ benchmark results. The secret scanner scans Git-visible files and history, so a
26
26
  credential committed and later deleted must still be revoked and removed from history.
27
27
 
28
28
  Release Please generates changelog/version updates in a release PR; merging it publishes
29
- the GitHub release after CI passes. Changes to workflow permissions,
29
+ the GitHub release after CI passes. The **Publish to npm** workflow then verifies the
30
+ tagged release and publishes the same version to npm with provenance. README updates
31
+ on npm ship with the next package version; pushing documentation alone does not publish.
32
+ Changes to workflow permissions,
30
33
  tool checksum pins, dependency lockfiles, and authentication deserve particular review.
31
34
 
32
35
  PR descriptions are maintained by the **PR description** workflow. Write meaningful
@@ -37,3 +40,24 @@ when CI runs. Add context or live-testing evidence under Notes, outside the
37
40
  alone. It uses the built-in GitHub token; no additional secret or AI service is needed.
38
41
  It becomes active after the workflow reaches the default branch. For existing PRs
39
42
  without markers, it appends its generated section without deleting your description.
43
+
44
+
45
+ ## npm trusted publishing setup
46
+
47
+ In the npm settings for `pi-nebius`, add a **GitHub Actions** trusted publisher:
48
+
49
+ - Organization or user: `PeterHdd`
50
+ - Repository: `pi-nebius`
51
+ - Workflow filename: `publish.yml`
52
+ - Environment: leave blank
53
+ - Allowed actions: enable direct publishing with `npm publish`
54
+
55
+ No npm token is required. Keep `RELEASE_PLEASE_TOKEN` configured: it allows the
56
+ GitHub release created by Release Please to trigger the publishing workflow.
57
+ See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
58
+
59
+ After merging a change, wait for CI and merge the generated release PR. Once the
60
+ GitHub release appears, check **Actions → Publish to npm**. If publishing fails,
61
+ fix the configuration and rerun the failed workflow. npm versions are immutable;
62
+ an already published version cannot be replaced. Do not republish `0.3.0` to update
63
+ its README: use the next Release Please version.
package/README.md CHANGED
@@ -1,30 +1,17 @@
1
1
  # pi-nebius
2
2
 
3
- Nebius Token Factory models in Pi's normal model picker, discovered using your API key.
3
+ Use Nebius Token Factory models in Pi and compare them on coding tasks directly inside your session.
4
4
 
5
- This package also includes **benchmarks inside Pi**: run `/nebius-benchmark` to enter your own task prompt and compare models on copies of your current project. Results appear in Pi. A standalone CLI also supports scripted tasks and deterministic validation. See [Benchmarking](docs/benchmarking.md) for the CLI, result schema, metrics, and four ready-to-run fixtures.
5
+ - Discover the models available to your Nebius account.
6
+ - Save per-model temperature, reasoning, and output-token settings.
7
+ - Benchmark models on your own prompt or a bundled coding task.
8
+ - Compare correctness, token usage, completion time, and time to first token.
6
9
 
7
- ```bash
8
- npm ci
9
- npm run build
10
- npm run benchmark -- --benchmark benchmarks/fix-auth-bug \
11
- --models 'EXACT_MODEL_ID_A,EXACT_MODEL_ID_B' --runs 3 \
12
- --output benchmark-results/auth-comparison
13
- ```
14
-
15
- Results appear directly in the terminal: each run prints its pass/fail status, followed by a comparison table of success counts, mean input/output tokens, median task duration, observed time to first token (TTFT), end-to-end output throughput, turns, and tool calls. Detailed JSON reports, traces, and workspaces are also saved under `benchmark-results/`; `--output` chooses the directory.
16
-
17
- Set `NEBIUS_API_KEY` first. `npm run benchmark:demo` exercises the real Pi runner with scripted model responses, without credentials.
18
-
19
- ```text
20
- Pi → pi-nebius → https://api.tokenfactory.nebius.com/v1 → model
21
- ```
10
+ Requires **Node.js 22.19+** and **Pi 0.85.1 or a compatible newer version**.
22
11
 
23
- Requires **Node.js 22.19+ and Pi 0.85.1** (the tested version). This targets the current `@earendil-works` Pi packages, not older `@mariozechner` releases. Pi's package instructions require wildcard peer dependencies; that is not a claim that every Pi version is compatible.
12
+ ## Install
24
13
 
25
- ## Installation
26
-
27
- With Pi already installed:
14
+ With Pi already installed, run in your terminal:
28
15
 
29
16
  ```bash
30
17
  pi install npm:pi-nebius
@@ -32,208 +19,155 @@ export NEBIUS_API_KEY="your-api-key"
32
19
  pi
33
20
  ```
34
21
 
35
- Run `/model`, search for `nebius`, and select a model.
36
-
37
- From this checkout:
22
+ Get your API key from [Nebius Token Factory](https://tokenfactory.nebius.com/).
23
+ Add the export to your shell profile if you want it available in future terminals.
24
+ Restart Pi after changing the key.
38
25
 
39
- ```bash
40
- cd /path/to/pi-nebius
41
- npm ci
42
- pi install /absolute/path/to/pi-nebius
43
- ```
26
+ Inside Pi, run `/model`, search for `nebius`, and choose a model.
44
27
 
45
- Or try it without adding it to Pi's settings:
46
-
47
- ```bash
48
- pi -e /absolute/path/to/pi-nebius
49
- ```
50
-
51
- The provider uses Pi's `pi.extensions` manifest and loads TypeScript directly. Pi installs Git packages with `npm install --omit=dev`; the extension needs no build step. To use the benchmark CLI from a source checkout, run `npm ci` and `npm run build` to generate `dist/`. YAML is the benchmark definition parser; neither component needs a separate server.
52
-
53
- GitHub installation is also supported:
28
+ You can also install from GitHub:
54
29
 
55
30
  ```bash
56
31
  pi install git:github.com/PeterHdd/pi-nebius
57
32
  ```
58
33
 
59
- Git installs require no compiler or development dependencies. Benchmark development uses a separate source checkout with development dependencies installed. Append a published tag (for example, `@v0.3.0`) to pin a Git installation; install a newer tag explicitly to upgrade.
34
+ ## Model settings
60
35
 
61
- See [CONTRIBUTING.md](CONTRIBUTING.md), [CHANGELOG.md](CHANGELOG.md), and [SECURITY.md](SECURITY.md).
36
+ Open the settings menu inside Pi:
62
37
 
63
- ## Authentication and usage
64
-
65
- ```bash
66
- export NEBIUS_API_KEY="your-key"
67
- pi
38
+ ```text
39
+ /nebius-model
68
40
  ```
69
41
 
70
- Inside Pi, run `/model` and search for `nebius`. Choose an exact model from the discovered list. Provider ID: `nebius`; display name: `Nebius Token Factory`. Nebius IDs such as `vendor/model` remain unchanged; Pi identifies the pair as `nebius/vendor/model`.
42
+ Choose a model to configure:
71
43
 
72
- You can also inspect the catalog and select a model explicitly:
44
+ | Setting | What it controls |
45
+ | --- | --- |
46
+ | Temperature | Response variability, from 0 to 2, where supported. |
47
+ | Reasoning effort | The model's reasoning effort, where supported. |
48
+ | Maximum output tokens | The response-length limit. |
49
+ | Advanced: context window | The context limit Pi uses for the model. |
50
+ | Advanced: reasoning support | Whether Pi treats the model as reasoning-capable. |
73
51
 
74
- ```bash
75
- pi --list-models nebius
76
- pi --provider nebius --model 'EXACT_ID_FROM_THE_LIST'
77
- ```
52
+ You can open a specific model directly with `/nebius-model MODEL_ID`.
78
53
 
79
- `/nebius-refresh` forces discovery again and updates Pi's registered models. If a selected model was removed, use `/model` to choose a current one.
54
+ Settings are saved across restarts and apply to new requests. Choose **Inherit**, clear a numeric
55
+ value, or use **Reset all overrides** to restore defaults. A saved reasoning effort takes precedence
56
+ over Pi's `/thinking` setting.
80
57
 
81
- The extension reads `NEBIUS_API_KEY` at startup for discovery and resolves it through Pi's native authentication interface for inference. It has no `/login` flow and never writes the key to a file. Set the variable in the shell that launches Pi; changing a parent shell's environment cannot change an already-running process. Restart Pi after changing it. Pi's explicit CLI/runtime authentication overrides remain Pi features, but discovery specifically requires `NEBIUS_API_KEY`.
58
+ Use values supported by the chosen model. Advanced settings change Pi's configuration, not the
59
+ model's actual capabilities. The default output limit is up to 4,096 tokens; increase it in the menu
60
+ if your model supports longer responses.
82
61
 
83
62
  ## Benchmark inside Pi
84
63
 
85
- After installing the extension, run this inside Pi:
64
+ To benchmark your selected Nebius model on your own task:
86
65
 
87
66
  ```text
88
67
  /nebius-benchmark
89
68
  ```
90
69
 
91
- An editor asks for your own task prompt. The benchmark uses your selected Nebius model and a copy of the project directory where Pi is running. To compare models, supply their exact IDs:
92
-
93
- ```text
94
- /nebius-benchmark --models zai-org/GLM-5.3,moonshotai/Kimi-K2.6 --runs 3
95
- ```
96
-
97
- This runs the same prompt three times per model, sequentially, starting from the same project snapshot each time. It shows progress and a comparison of input/output tokens, task duration, observed TTFT, output throughput, turns, and tools directly in Pi. Custom prompts report **correctness not checked**; completion does not prove the task was solved.
70
+ Enter your prompt in the editor. Run Pi from the project directory you want the models to work on.
98
71
 
99
- The snapshot includes current working files, including uncommitted changes, and respects Git ignores. It excludes `.git`, `.pi`, dependency/build folders, prior benchmark results, `.env` files, and `.pem`/`.key` files. Dependencies are not preinstalled; include setup instructions in your task if needed. Links and special files are rejected. Snapshots are limited to 10,000 files / 50 MiB. Run Pi from the project directory you want to benchmark.
100
-
101
- Runs use paid inference. Tools have normal host permissions: file copies are not an OS sandbox. Reports and each run's resulting files are retained under `benchmark-results/` in your project.
72
+ To compare two models, once each:
102
73
 
103
74
  ```text
104
- /nebius-benchmark cancel
105
- /nebius-benchmark help
75
+ /nebius-benchmark --models moonshotai/Kimi-K2.6,deepseek-ai/DeepSeek-V4-Flash-0731 --runs 1
106
76
  ```
107
77
 
108
- For an optional bundled coding task with automatic correctness tests:
78
+ Use exact model IDs from your `/model` list. Increase `--runs` to repeat the task for each model.
79
+ Runs execute one at a time, each starting from a fresh copy of the same project.
80
+
81
+ For a bundled task with automatic correctness tests:
109
82
 
110
83
  ```text
111
- /nebius-benchmark --task fix-auth-bug --runs 3
84
+ /nebius-benchmark --task fix-auth-bug --models moonshotai/Kimi-K2.6,deepseek-ai/DeepSeek-V4-Flash-0731 --runs 1
112
85
  ```
113
86
 
114
- Other bundled tasks: `add-api-endpoint`, `refactor-module`, and `multi-file-feature`. No build step or separate terminal is needed for these Pi commands.
87
+ Available tasks:
115
88
 
116
- ## Dynamic model discovery
117
-
118
- The async extension factory calls authenticated `GET /v1/models?verbose=true` before Pi finishes startup. This is the documented verbose variant of `/v1/models`, supplying metadata in addition to IDs. There is **no bundled model catalog**.
119
-
120
- | Nebius field | Pi mapping |
89
+ | Task | Work to complete |
121
90
  | --- | --- |
122
- | `id` | Exact, case-sensitive `model.id` |
123
- | `name` | Display name; defaults to ID |
124
- | `context_length` | `contextWindow`; defaults to 32,768 when absent/invalid |
125
- | `architecture.modality` | Text/image inputs; known non-text-output models are excluded |
126
- | `status` | Only `active` or unspecified models are included |
127
- | `supported_sampling_parameters` contains `reasoning_effort` | Enables reasoning and Pi's standard reasoning-effort control |
128
- | `supported_features` contains `reasoning` | Marks reasoning support without assuming an effort control |
129
- | No documented maximum output length | `maxTokens`: 4,096, capped at a quarter of the context window |
130
-
131
- Basic responses containing only IDs are supported. Missing capabilities default to text-only with no explicit reasoning control. Without modality metadata, the endpoint may include models unsuitable for chat; discovery cannot prove tool support. Pick a tool-capable model and run the integration test. Duplicate IDs are deduplicated; malformed lists are rejected rather than silently replacing a good cache with partial data.
91
+ | `fix-auth-bug` | Fix refresh-token expiry handling. |
92
+ | `add-api-endpoint` | Add an API endpoint. |
93
+ | `refactor-module` | Refactor an existing module. |
94
+ | `multi-file-feature` | Implement a feature across multiple files. |
132
95
 
133
- ### Cache and offline fallback
96
+ Results appear directly in Pi:
134
97
 
135
- The cache is under `getAgentDir()/cache/pi-nebius/` (normally `~/.pi/agent/cache/pi-nebius/`). Pi's `PI_CODING_AGENT_DIR` override is respected. Files contain normalized metadata and a timestamp, never the API key. Names use a SHA-256 fingerprint of the endpoint and key to avoid sharing one account's catalog with another key.
136
-
137
- - Fresh metadata is used for 24 hours without a discovery request.
138
- - Stale/missing metadata triggers one request, with an 8-second timeout and a 4 MiB response limit.
139
- - Transient failures use stale metadata and display a warning. No cache means no discovered models; Pi continues running.
140
- - A 401/403 invalidates this key's cache. A fresh cache does not validate credentials; inference can still reject a revoked key.
141
- - Successful refresh replaces the catalog, including an authoritative empty list. Failed refresh never updates the cache timestamp.
142
- - Cache writes are atomic and best-effort, with private directory/file permissions. Concurrent Pi processes may each perform discovery; there is no background service or cross-process lock.
143
-
144
- Pi now has a shared native model store, but its general provider-level cache is not scoped by the discovery key. This small extension-owned cache makes key isolation explicit and guarantees discovery before model selection. It does not participate in Pi's general remote-catalog refresh; use `/nebius-refresh` or restart Pi.
145
-
146
- ### Per-model settings
147
-
148
- Run `/nebius-model` to choose a discovered model, or `/nebius-model MODEL_ID` to open it directly.
149
- The menu saves temperature, reasoning effort, and maximum output tokens separately for each model.
150
- Blank numeric values or **Inherit** restore defaults; **Reset all overrides** clears that model's settings.
151
- Advanced settings let you override the context window and reasoning capability metadata. These do not
152
- change the server's capabilities. Use verified limits; the default output limit remains 4,096 tokens
153
- when the catalog does not provide a documented output limit.
154
-
155
- Temperature and reasoning-effort overrides are sent only when discovery advertises support.
156
- An advertised parameter does not guarantee every value is supported by every model; use its documented values.
157
- Saved request values take precedence over Pi's generated values (including `/thinking` for reasoning effort).
158
- Changes apply to new requests immediately and survive restarts in
159
- `~/.pi/agent/pi-nebius/model-settings.json` (respecting `PI_CODING_AGENT_DIR`).
160
- `/nebius-refresh` preserves saved overrides. External file edits require `/reload`.
98
+ | Metric | Meaning |
99
+ | --- | --- |
100
+ | Validated success | Runs that passed the task's correctness tests. |
101
+ | Input/output tokens | Average token usage per run, including all model requests. |
102
+ | Task duration | Median time to complete a run. |
103
+ | Observed TTFT | Median time from the first request to the first streamed text, reasoning, or tool content. |
104
+ | Throughput | Output tokens per second across the whole task, including tools and validation. |
105
+ | Agent turns / tool calls | Average number of turns and tool calls per run. |
161
106
 
162
- Both benchmark entry points use saved settings. In-Pi benchmarks snapshot them when the run starts,
163
- so changing the menu does not change an active comparison. Each run's `effectiveSettings` includes
164
- saved overrides, model limits, and `requestParameters`: the outgoing temperature, reasoning effort,
165
- output limit, and top-p where present, without prompt content. Omitted values mean the request did not
166
- specify them; server defaults are unknown. These parameters are in `results.json`, not the summary table.
107
+ **Mean** means average; **median** means the middle value after sorting (the average of the two
108
+ middle values for an even number of runs). With one run, both show that run's measurement.
109
+ Failed runs contribute to the performance metrics; missing measurements appear as `n/a`.
110
+ Custom prompts have no automatic correctness check, so a completed run does not establish success.
167
111
 
168
- ### Metadata overrides and user-defined fallback models
112
+ Detailed results, request settings, and resulting files are saved under `benchmark-results/`.
113
+ Benchmarks use your saved model settings at the start; later changes do not affect an active comparison.
169
114
 
170
- Merge the `nebius` provider entry from [examples/models.json](examples/models.json) into `~/.pi/agent/models.json`, replacing the placeholder ID and limits with verified values. Do not overwrite unrelated providers. The extension must remain installed.
115
+ Project copies include uncommitted changes and respect Git ignores. Dependencies, build output,
116
+ previous results, `.env`, and `.pem`/`.key` files are excluded. Include dependency setup in your prompt
117
+ if needed. Projects are limited to 10,000 files / 50 MiB; symlinks and special files are not supported.
171
118
 
172
- Use `modelOverrides` to adjust discovered models and `models` to add explicit models that remain available when discovery is offline. Native providers are composed beneath these settings by Pi. No `apiKey` field is needed in this configuration. Explicitly configured models remain until you remove them, even if the server no longer lists them.
119
+ Benchmarks use your Nebius account and incur inference charges. Model tools retain normal access to
120
+ your machine; project copies are not a security sandbox.
173
121
 
122
+ To stop a benchmark or view help:
174
123
 
175
- For reasoning models, verify the model's Nebius-specific behavior before overriding `reasoning`, `thinkingLevelMap`, or `compat`. Pi supports model-specific template controls, but this extension does not guess them from model names. Always-on reasoning may still appear in Pi even when explicit effort selection is unavailable.
124
+ ```text
125
+ /nebius-benchmark cancel
126
+ /nebius-benchmark help
127
+ ```
176
128
 
177
- ## Architecture and compatibility
129
+ See [Benchmarking](docs/benchmarking.md) for custom validated tasks and scripted CLI usage.
178
130
 
179
- `src/index.ts` is Pi's async extension factory. It registers a native provider with `pi.registerProvider(provider)`, adds `/nebius-refresh`, and supplies provider-specific error guidance through `message_end`.
131
+ ## Refresh and update
180
132
 
181
- `src/provider.ts` uses Pi's `createProvider()` and its exported `openAICompletionsApi()` adapter. Pi owns request/message serialization, SSE parsing, multi-turn conversation state, function calls/results, usage accounting, abort handling, retries, and the tool loop. A small fetch decorator retains retry/rate-limit/request-ID headers on HTTP errors; successful response streams pass through unchanged.
133
+ Refresh the list of available Nebius models inside Pi:
182
134
 
183
- Compatibility settings select `system` messages and `max_tokens`, request streamed usage, and disable unsupported assumptions about `store`, strict tools, grammar tools, and reasoning effort. These are model-level properties and can be overridden through Pi.
135
+ ```text
136
+ /nebius-refresh
137
+ ```
184
138
 
139
+ Model lists are cached for up to 24 hours. Refreshing preserves your saved settings.
185
140
 
186
- ## Testing
141
+ For an npm installation, update from your terminal:
187
142
 
188
143
  ```bash
189
- npm ci
190
- npm run typecheck
191
- npm run lint
192
- npm test
144
+ pi update npm:pi-nebius
193
145
  ```
194
146
 
195
- Tests cover model parsing/mapping, discovery errors, missing credentials, cache behavior, native authentication, and Pi's actual extension loader. Adapter tests use Pi itself with mocked HTTP responses. The CLI integration test starts a local HTTP server, loads this package in the real Pi CLI, checks `--list-models`, executes a streamed `write` call, checks the generated file, and verifies that the next request contains the tool result. It also checks cache reuse and `models.json` composition. These tests do not require or use a real Nebius key.
196
-
197
- ### Manual live integration test
198
-
199
- In a scratch directory, start Pi, select a tool-capable Nebius model with `/model`, then ask:
200
-
201
- > Create a file called nebius-test.txt containing 'Hello from Nebius'.
202
-
203
- Verify that Pi shows a successful write-tool execution, the file contains the expected text, and the model responds after receiving the tool result. Check Token Factory's usage view for the request. Ordinary text claiming the file was created is not sufficient.
204
-
205
- An opt-in automated equivalent runs a real Pi CLI in a temporary directory, limits its tools to `write`, requires an actual tool event and final response, checks exact file contents, and cleans up afterward:
147
+ For a GitHub installation:
206
148
 
207
149
  ```bash
208
- export NEBIUS_API_KEY="your-key"
209
- export NEBIUS_MODEL="EXACT_TOOL_CAPABLE_MODEL_ID"
210
- npm run test:live
150
+ pi update git:github.com/PeterHdd/pi-nebius
211
151
  ```
212
152
 
213
- This makes paid inference requests and has a three-minute timeout. It is not part of `npm test`. See [docs/validation.md](docs/validation.md) for what has actually been run.
153
+ Then run `/reload` inside Pi, or restart it.
214
154
 
215
155
  ## Troubleshooting
216
156
 
217
- | Problem | Action |
157
+ | Problem | What to do |
218
158
  | --- | --- |
219
- | Missing API key | Run `export NEBIUS_API_KEY="..."` in the launching shell and restart Pi. |
220
- | 401/403 | Token Factory rejected the key or project access. Check the key, permissions, and project; then restart Pi. |
221
- | Model unavailable / 404 | Run `/nebius-refresh`, then `/model`; remove obsolete explicit entries from `models.json`. |
222
- | 429 | Respect the preserved `retry-after` / rate-limit details. Pi handles its normal retry policy; discovery itself does not retry automatically. |
223
- | 5xx | Provider service failure. Retry later; discovery can use stale cached metadata. |
224
- | Connectivity / timeout | Check access to `api.tokenfactory.nebius.com` and Pi's network/proxy settings. Discovery times out after eight seconds. |
225
- | No models without a cache | Add an explicit verified model via the example configuration, or retry discovery once connectivity returns. |
226
- | Model talks but never uses tools | Verify that the chosen model supports functions on Nebius; run the live test or select another model. Discovery alone cannot certify this. |
227
- | Context/output limit errors | Set verified `contextWindow` and `maxTokens` in `modelOverrides`. Defaults are conservative assumptions, not guaranteed endpoint limits. |
228
-
229
- ## Current limitations
230
-
231
- - Live Nebius inference has not been verified in the development environment because no API key was available. Mocked Pi integration tests prove adapter wiring and the tool loop, not every hosted model's capabilities.
232
- - Metadata availability and capability vocabulary vary. Reasoning/vision detection is conservative; model-specific thinking templates require explicit configuration and testing.
233
- - Maximum output limits are defaults; the verbose schema does not expose a documented equivalent of Pi's `maxTokens`.
234
- - Pi's adapter handles `stop`, `length`, and `tool_calls` finish reasons. Its generic stream options do not expose custom stop sequences; advanced extensions can use Pi's `onPayload` hook if needed. No new stop-sequence API is invented here.
235
- - The normal picker/listing integration is tested through Pi's CLI and registry. An interactive terminal screenshot/UI test was not performed.
236
-
237
- ## License
238
-
239
- MIT; see [LICENSE](LICENSE).
159
+ | Missing API key | Set `NEBIUS_API_KEY` in the terminal that launches Pi, then restart Pi. |
160
+ | Authentication error (401/403) | Check your Nebius key and project permissions. |
161
+ | Missing or unavailable model | Run `/nebius-refresh`, then choose a model with `/model`. |
162
+ | Rate limit (429) | Wait before retrying or reduce request frequency. |
163
+ | Server error (5xx) | Retry later. |
164
+ | Connection timeout | Check your connection and access to `api.tokenfactory.nebius.com`. |
165
+ | Output cut short | Open `/nebius-model` and adjust maximum output tokens within the model's supported limits. |
166
+ | Model does not use tools | Select a model that supports tool calling. |
167
+ | Benchmark validation failed | Read the failure details: the model's solution did not pass the task's tests. |
168
+
169
+ ## More information
170
+
171
+ [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md)
172
+
173
+ MIT licensed. See [LICENSE](LICENSE).
package/SECURITY.md CHANGED
@@ -45,3 +45,11 @@ See [the review record](docs/security-review.md) for findings and residual limit
45
45
  The PR-description workflow uses `pull_request_target` and `workflow_run` only to
46
46
  read GitHub metadata and update the PR body with a scoped write token. It never
47
47
  checks out PR code, installs dependencies, or consumes workflow artifacts.
48
+
49
+
50
+ npm publishing runs only for stable, published GitHub releases in this repository.
51
+ The publishing workflow checks that the tagged commit belongs to `main`, verifies
52
+ that the tag matches the package version, and runs tests and package checks before
53
+ publishing. It uses npm trusted publishing with GitHub OIDC (`id-token: write`),
54
+ not a stored npm token, and attaches provenance. Release Please's separate token
55
+ is not passed to the npm publishing job.
@@ -5,6 +5,7 @@ import { tmpdir } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { parseArgs } from "node:util";
8
+ import { Text } from "@earendil-works/pi-tui";
8
9
  import { MISSING_KEY } from "../discovery.js";
9
10
  import { applyModelSettings } from "../model-settings.js";
10
11
  import { loadDefinition, positive } from "./definition.js";
@@ -33,6 +34,15 @@ export async function hostPiEntry() {
33
34
  return join(dirname(manifestPath), manifest.main);
34
35
  }
35
36
  export function registerBenchmarkCommand(pi, getSettings = () => ({})) {
37
+ pi.registerMessageRenderer("nebius-benchmark", (message, options, theme) => {
38
+ const content = typeof message.content === "string"
39
+ ? message.content
40
+ : message.content
41
+ .filter((part) => part.type === "text")
42
+ .map((part) => part.text)
43
+ .join("\n");
44
+ return new Text(`${theme.fg("customMessageLabel", "[nebius-benchmark]")}\n\n${content}`, options.outputPad ?? 1, 0);
45
+ });
36
46
  let starting = false;
37
47
  let active;
38
48
  const show = (content) => pi.sendMessage({ customType: "nebius-benchmark", content, display: true }, { triggerTurn: false });
@@ -149,7 +159,7 @@ export function registerBenchmarkCommand(pi, getSettings = () => ({})) {
149
159
  apiKey: key,
150
160
  signal: controller.signal,
151
161
  piEntry,
152
- workerPath: fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "./host-worker.ts" : "./host-worker.js", import.meta.url)),
162
+ workerPath: fileURLToPath(new URL("./host-worker.mjs", import.meta.url)),
153
163
  workerArgs: [piEntry],
154
164
  onRun: (run) => {
155
165
  ctx.ui.setStatus("nebius-benchmark", `Benchmark: ${task} (${++completed}/${total})`);
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { registerHooks, stripTypeScriptTypes } from "node:module";
3
+ import { pathToFileURL } from "node:url";
4
+ // Reuse the installed host's SDK; Git installs intentionally omit Pi dev dependencies.
5
+ const hostEntry = process.argv[2];
6
+ if (!hostEntry)
7
+ throw new Error("Missing host Pi entry");
8
+ const sourceRoot = new URL("../", import.meta.url).href;
9
+ registerHooks({
10
+ // Node's automatic type stripping rejects installed sources under node_modules.
11
+ // This JavaScript bootstrap explicitly strips only this package's own sources.
12
+ load(url, context, nextLoad) {
13
+ if (url.startsWith(sourceRoot) && url.endsWith(".ts")) {
14
+ return {
15
+ format: "module",
16
+ source: stripTypeScriptTypes(readFileSync(new URL(url), "utf8"), { sourceUrl: url }),
17
+ shortCircuit: true,
18
+ };
19
+ }
20
+ return nextLoad(url, context);
21
+ },
22
+ resolve(specifier, context, nextResolve) {
23
+ if (specifier.startsWith("@earendil-works/"))
24
+ return nextResolve(specifier, { ...context, parentURL: pathToFileURL(hostEntry).href });
25
+ return nextResolve(specifier, context);
26
+ },
27
+ });
28
+ await import("./worker.js");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-nebius",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Nebius Token Factory provider and agentic coding benchmarks for Pi",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,13 +42,15 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@earendil-works/pi-ai": "*",
45
- "@earendil-works/pi-coding-agent": "*"
45
+ "@earendil-works/pi-coding-agent": "*",
46
+ "@earendil-works/pi-tui": "*"
46
47
  },
47
48
  "devDependencies": {
49
+ "@biomejs/biome": "^2.2.0",
48
50
  "@earendil-works/pi-ai": "0.85.1",
49
51
  "@earendil-works/pi-coding-agent": "0.85.1",
52
+ "@earendil-works/pi-tui": "0.85.1",
50
53
  "@types/node": "^22.0.0",
51
- "@biomejs/biome": "^2.2.0",
52
54
  "tsx": "^4.20.0",
53
55
  "typescript": "^5.9.0"
54
56
  },
@@ -6,6 +6,7 @@ import { dirname, join } from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { parseArgs } from "node:util";
8
8
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+ import { Text } from "@earendil-works/pi-tui";
9
10
  import { MISSING_KEY } from "../discovery.ts";
10
11
  import { applyModelSettings, type ModelSettingsMap } from "../model-settings.ts";
11
12
  import type { NebiusModel } from "../models.ts";
@@ -42,6 +43,20 @@ export function registerBenchmarkCommand(
42
43
  pi: ExtensionAPI,
43
44
  getSettings: () => ModelSettingsMap = () => ({}),
44
45
  ) {
46
+ pi.registerMessageRenderer("nebius-benchmark", (message, options, theme) => {
47
+ const content =
48
+ typeof message.content === "string"
49
+ ? message.content
50
+ : message.content
51
+ .filter((part) => part.type === "text")
52
+ .map((part) => part.text)
53
+ .join("\n");
54
+ return new Text(
55
+ `${theme.fg("customMessageLabel", "[nebius-benchmark]")}\n\n${content}`,
56
+ options.outputPad ?? 1,
57
+ 0,
58
+ );
59
+ });
45
60
  let starting = false;
46
61
  let active: { controller: AbortController; done: Promise<void> } | undefined;
47
62
  const show = (content: string) =>
@@ -168,12 +183,7 @@ export function registerBenchmarkCommand(
168
183
  apiKey: key,
169
184
  signal: controller.signal,
170
185
  piEntry,
171
- workerPath: fileURLToPath(
172
- new URL(
173
- import.meta.url.endsWith(".ts") ? "./host-worker.ts" : "./host-worker.js",
174
- import.meta.url,
175
- ),
176
- ),
186
+ workerPath: fileURLToPath(new URL("./host-worker.mjs", import.meta.url)),
177
187
  workerArgs: [piEntry],
178
188
  onRun: (run) => {
179
189
  ctx.ui.setStatus("nebius-benchmark", `Benchmark: ${task} (${++completed}/${total})`);
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { registerHooks, stripTypeScriptTypes } from "node:module";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ // Reuse the installed host's SDK; Git installs intentionally omit Pi dev dependencies.
6
+ const hostEntry = process.argv[2];
7
+ if (!hostEntry) throw new Error("Missing host Pi entry");
8
+ const sourceRoot = new URL("../", import.meta.url).href;
9
+ registerHooks({
10
+ // Node's automatic type stripping rejects installed sources under node_modules.
11
+ // This JavaScript bootstrap explicitly strips only this package's own sources.
12
+ load(url, context, nextLoad) {
13
+ if (url.startsWith(sourceRoot) && url.endsWith(".ts")) {
14
+ return {
15
+ format: "module",
16
+ source: stripTypeScriptTypes(readFileSync(new URL(url), "utf8"), { sourceUrl: url }),
17
+ shortCircuit: true,
18
+ };
19
+ }
20
+ return nextLoad(url, context);
21
+ },
22
+ resolve(specifier, context, nextResolve) {
23
+ if (specifier.startsWith("@earendil-works/"))
24
+ return nextResolve(specifier, { ...context, parentURL: pathToFileURL(hostEntry).href });
25
+ return nextResolve(specifier, context);
26
+ },
27
+ });
28
+ await import("./worker.ts");
@@ -1,14 +0,0 @@
1
- import { registerHooks } from "node:module";
2
- import { pathToFileURL } from "node:url";
3
- // Reuse the installed host's SDK; Git installs intentionally omit Pi dev dependencies.
4
- const hostEntry = process.argv[2];
5
- if (!hostEntry)
6
- throw new Error("Missing host Pi entry");
7
- registerHooks({
8
- resolve(specifier, context, nextResolve) {
9
- if (specifier.startsWith("@earendil-works/"))
10
- return nextResolve(specifier, { ...context, parentURL: pathToFileURL(hostEntry).href });
11
- return nextResolve(specifier, context);
12
- },
13
- });
14
- await import("./worker.js");
@@ -1,14 +0,0 @@
1
- import { registerHooks } from "node:module";
2
- import { pathToFileURL } from "node:url";
3
-
4
- // Reuse the installed host's SDK; Git installs intentionally omit Pi dev dependencies.
5
- const hostEntry = process.argv[2];
6
- if (!hostEntry) throw new Error("Missing host Pi entry");
7
- registerHooks({
8
- resolve(specifier, context, nextResolve) {
9
- if (specifier.startsWith("@earendil-works/"))
10
- return nextResolve(specifier, { ...context, parentURL: pathToFileURL(hostEntry).href });
11
- return nextResolve(specifier, context);
12
- },
13
- });
14
- await import("./worker.ts");