pi-actualyze
Native Actualyze model provider for pi with automatic model discovery
Package details
Install pi-actualyze from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-actualyze- Package
pi-actualyze- Version
1.0.0- Published
- Aug 20, 2026
- Downloads
- 170/mo · 29/wk
- Author
- actualyze-bot
- License
- MIT
- Types
- extension
- Size
- 53 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-actualyze
A native pi provider package for
Actualyze, the AI platform built by Actualyze AI.
Configure one Actualyze target and API key, and the provider discovers every
model advertised by that target automatically. No models.json, copied model
IDs, or per-model configuration required.
Quick Start
Install directly from GitHub:
pi install git:github.com/actualyze-ai/pi-actualyze
Start pi and authenticate:
/login actualyze
Enter:
- your Actualyze target label, the
fooinhttps://foo.actualyze.ai; and - the API key issued for that target.
Login validates the credentials, downloads the complete model catalog, and makes the discovered models available immediately. Open pi's model selector:
/model
Select any model under the actualyze provider.
The Problem
An Actualyze deployment can expose a changing catalog of direct models, routed
aliases, and workload-oriented model groups. Hard-coding that catalog in pi would
be incomplete as soon as Actualyze adds, removes, or updates an entry. Requiring
users to copy each model into models.json would also duplicate metadata that the
Actualyze API already publishes, including context limits, output limits,
modalities, reasoning support, and caching information.
pi-actualyze makes Actualyze a native dynamic pi provider. The target and API key are the only user configuration. The package queries Actualyze directly, validates the complete catalog as one atomic generation, converts every valid entry into a pi model, and routes inference through pi's native OpenAI Chat Completions implementation.
How It Works
The provider owns the complete lifecycle:
Configuration:
/login actualyzeasks for a target label and API key. The label is converted to the fixed endpointhttps://<target>.actualyze.ai/openai/v1.Credential validation: Before pi saves anything, the provider sends an authenticated
GET /modelsrequest through a guarded transport. Invalid credentials, malformed responses, and unsafe catalog entries fail the login.Automatic discovery: The OpenAI-style model list is authoritative for membership. Every unique, safely representable ID becomes a pi model. The provider does not filter entries by owner, price, or advisory capability flags.
Atomic publication: A generation is published only when the complete list validates. One malformed or duplicate entry rejects the new generation instead of silently presenting a partial catalog. An existing valid generation remains intact when refresh fails.
Target-scoped persistence: Pi can restore a cached catalog on startup only when every cached model belongs to
actualyzeand points at the active target's exact base URL. Switching targets discards mismatched cached and in-memory catalogs.Native inference: Requests use pi's OpenAI Chat Completions adapter with a conservative, explicit compatibility profile. Text, images, reasoning, streamed usage, function tools, and tool-result continuation use pi's normal model pipeline.
Routed aliases: Pi retains the requested Actualyze catalog ID as the model identity. If Actualyze reports the selected upstream model in stream chunks, pi records it separately as
responseModel.
Installation
GitHub
Install the current repository through pi's package manager:
pi install git:github.com/actualyze-ai/pi-actualyze
To pin a tag or commit:
pi install git:github.com/actualyze-ai/pi-actualyze@<tag-or-commit>
Git installations are managed by pi. Use pi update --extensions to reconcile
unpinned package installations and pi remove to uninstall:
pi remove git:github.com/actualyze-ai/pi-actualyze
The repository is currently private. GitHub access must already be configured for the account running pi.
Local checkout
For development, install the checkout by absolute path:
git clone git@github.com:actualyze-ai/pi-actualyze.git
cd pi-actualyze
npm install
npm run check
pi install "$PWD"
A local-path installation references the directory in place. Source edits are picked up the next time pi starts; no copy is made into pi's package directory.
To try the extension for one process without changing pi settings:
pi --no-extensions -e .
npm
Install the published package:
pi install npm:pi-actualyze
To pin a version:
pi install npm:pi-actualyze@1.0.0
Requirements
- pi
0.84.2or newer - Node.js
22.19.0or newer for development - Network access to the configured
*.actualyze.aitarget - An Actualyze API key valid for that target
Configuration
Interactive Login
Run:
/login actualyze
The flow asks for two values:
| Value | Example | Meaning |
|---|---|---|
| Target | customer |
One DNS label, not a hostname or URL |
| API key | … |
Bearer credential issued for that target |
The target customer resolves only to:
https://customer.actualyze.ai/openai/v1
Target labels may contain ASCII letters, digits, and internal hyphens. The provider rejects dots, schemes, paths, ports, whitespace, Unicode lookalikes, control characters, and labels longer than 63 characters. Uppercase ASCII letters are normalized to lowercase.
Login fetches and validates the catalog before returning the credential to pi. A failed validation stores nothing.
Environment Configuration
For non-interactive authentication, set both variables before starting pi:
export ACTUALYZE_TARGET=customer
export ACTUALYZE_API_KEY='your-api-key'
pi
| Variable | Required | Description |
|---|---|---|
ACTUALYZE_TARGET |
Yes | One Actualyze DNS label |
ACTUALYZE_API_KEY |
Yes | API key for that target |
Stored credential fields take precedence over the corresponding environment variables. Invalid ambient configuration is treated as unavailable authentication. Invalid stored configuration also makes the provider unavailable at availability check time (so one corrupt credential cannot blank the model picker for every provider); the underlying validation error surfaces when a request or refresh resolves the credential.
Credential Storage and Logout
Pi stores the API key in its provider credential store and stores only the non-secret target in credential metadata:
{
"type": "api_key",
"key": "<secret>",
"env": {
"ACTUALYZE_TARGET": "customer"
}
}
Remove the saved credential with:
/logout actualyze
After logout, Actualyze models are unavailable even if an in-memory catalog still exists. Environment variables can still provide authentication if they remain set.
Automatic Model Discovery
The provider requests:
GET https://<target>.actualyze.ai/openai/v1/models
Authorization: Bearer <api-key>
The list response, not a bundled static file, is authoritative for model membership. The provider registers exactly one model for every unique valid list ID.
Catalog Validation
A new generation is rejected atomically when:
- the response is not JSON;
- the envelope is not an object with a
dataarray; - a claimed model lacks a non-empty string ID;
- model IDs are duplicated;
- an ID is a dot segment, oversized, not URL-encodable, or contains unsafe terminal or bidirectional control characters; or
- required catalog structure cannot be represented safely.
Individual model-detail requests are not part of the version-1 critical path. The live list endpoint already advertises the metadata needed by pi, and one list request keeps refresh within pi's interactive deadline.
Refresh and Cache Behavior
- Login installs the validated catalog in memory immediately.
- Normal refresh fetches a complete new
/modelsgeneration. - The aggregate catalog request budget is 10 seconds.
- Only rate limits and transient 5xx responses are retried.
- Valid
Retry-Aftervalues are honored only when they fit the remaining budget. - Cancellation stops active fetches, response reads, and retry delays.
- Failed refresh never replaces a previously accepted generation.
- A cached generation is restored only for the exact active target URL.
- Same-target key rotation persists the newly validated login catalog instead of restoring the previous key's catalog.
Model Metadata
Actualyze model advertisements are mapped into pi as follows:
| Actualyze field | pi field | Behavior |
|---|---|---|
id |
id, name |
Preserved exactly after safety validation |
context_window |
contextWindow |
Preferred positive limit |
max_model_len |
contextWindow |
Fallback when context_window is absent |
max_output_tokens |
maxTokens |
Positive output limit |
modalities.input includes image |
input |
Enables image input |
capabilities.thinking |
reasoning |
Enables reasoning when true |
capabilities.thinking_adaptive |
reasoning |
Also enables reasoning when true |
cost.* |
cost |
Currently represented as unknown; see below |
Missing Limits
Pi requires numeric context and output limits. When Actualyze advertises no positive value, the provider uses compatibility sentinels:
- context window:
128,000tokens - maximum output:
16,384tokens
These values satisfy pi's model schema; they are not claims about an undisclosed upstream limit.
Pricing
Actualyze currently advertises numeric cost fields, but the inspected API response does not declare their currency or units. Pi interprets cost fields specifically as USD per million tokens, so pi-actualyze does not guess.
All cost fields currently use 0 as an unknown-price sentinel. Zero does not
mean inference is free. Advertised pricing will be mapped only after Actualyze's
currency and units are authoritatively confirmed.
Modalities
Pi currently represents text and image input metadata. Actualyze advertisements for PDF/document, audio, or video input are not converted to another modality and are not presented as supported by this provider.
Advisory Capability Flags
Actualyze's streaming and tool_use flags are treated as advisory:
- at least one live model advertising
streaming: falsesuccessfully streamed; - pi has no per-model tool-support metadata field; and
- advisory false values never remove a model from the discovered catalog.
The provider therefore keeps all valid models visible and uses the native pi request shape consistently. Proven model-specific incompatibilities should become explicit compatibility rules rather than hidden catalog filters.
OpenAI Compatibility
The provider uses pi's native OpenAI Chat Completions implementation and pins a conservative compatibility profile:
| Behavior | Setting |
|---|---|
| Output token field | max_completion_tokens |
| Streamed usage | Enabled |
reasoning_effort |
Enabled |
| Finish reasons | Enabled |
store |
Disabled |
| Developer role | Disabled; system role is used |
| Strict tool schemas | Disabled |
Contract tests cover exact outbound roles and fields, text and reasoning streams,
reasoning replay via reasoning_content, images, Unicode, incremental function
arguments, tool-result continuation, usage, cancellation, routed aliases, error
redaction, and pi's standard context-overflow classification. Context-overflow
messages matching pi's standard patterns retain pi's normal compaction behavior.
Security
Authenticated traffic is deliberately constrained:
- production targets are one validated ASCII DNS label;
- all requests must use HTTPS;
- the origin must exactly match the configured target;
- paths must remain beneath
/openai/v1; - redirects are rejected with
redirect: "error"; - cross-target cached models are discarded, so the catalog never mixes targets;
- inference refuses a request before sending credentials when the current catalog attributes the model id to another target's base URL, when the model object's base URL does not match the active target (direct provider use), or when the id is absent from the current non-empty discovered catalog (covering stale sessions after upstream catalog changes and models.json-defined entries, which this provider does not support);
- the guarded fetch confines credentials to the resolved origin regardless of model metadata;
- retries never switch origins;
- catalog and error bodies are size-bounded;
- provider error bodies and headers are sanitized before pi receives them; and
- API keys and authorization headers are redacted from transport errors.
Do not commit credentials, .env files, live API response captures, or generated pi
credential stores. Live tests are excluded from the default test suite and require
explicit opt-in flags.
Timeouts and Resilience
The provider is designed to fail without corrupting a valid catalog:
- Aggregate request budget: 10 seconds for list discovery, including retries, body reads, and backoff.
- Retry scope: HTTP 429 and transient 5xx responses only.
- Retry delay:
Retry-Afterwhen valid and affordable within the deadline; otherwise bounded exponential backoff. - Cancellation: Parent abort signals stop fetch, body consumption, and sleep.
- Response limits: Catalog and provider-error bodies are read with explicit byte limits.
- Atomic refresh: A malformed generation never partially replaces the current model list.
- Offline startup: A matching persisted catalog can remain available without a successful network refresh.
- Target isolation: A cache from another target is removed rather than exposed under the current credential.
pi Commands and CLI Behavior
| Command | Purpose |
|---|---|
/login actualyze |
Configure target and API key, validate, and discover models |
/model |
Browse and select discovered Actualyze models |
/logout actualyze |
Remove the stored Actualyze credential |
pi list |
Show installed pi packages |
pi remove … |
Uninstall the package |
--list-models Caveat
In pi 0.84.2, --list-models can reach availability lookup before the asynchronous
cache refresh triggered by native extension registration completes. A fresh process
may therefore print no dynamic Actualyze models even when matching credentials and a
persisted catalog exist.
Use an ordinary pi invocation and /model; do not add models.json. A brand-new
process using only environment credentials has the same upstream lifecycle
limitation because --list-models does not initiate a dynamic provider refresh.
Troubleshooting
pi fails while loading the extension
Start once without extensions:
pi --no-extensions
Then verify:
pi list
pi --version
The package requires pi 0.84.2 or newer. Local development must use the
loader-compatible @earendil-works/pi-ai/compat entrypoint; current source already
does this. Update the checkout and restart pi if an older commit reports a missing
openai-completions.lazy module.
actualyze does not appear in /login
Confirm the package is installed:
pi list
For a local checkout, ensure the listed path still exists. Reinstall if necessary:
pi remove /absolute/path/to/pi-actualyze
pi install /absolute/path/to/pi-actualyze
Login rejects the target
Enter only the DNS label:
customer
Do not enter customer.actualyze.ai, https://customer.actualyze.ai, a port, path,
or surrounding whitespace.
Login returns an authentication or catalog error
Check that:
- the API key belongs to the selected target;
- the target can reach
https://<target>.actualyze.ai/openai/v1/models; - a proxy is not returning HTML or a redirect; and
- the endpoint returns a complete OpenAI-style JSON model list.
The provider intentionally rejects redirects and non-JSON responses.
Models do not appear in --list-models
See the --list-models caveat. Start interactive pi and
open /model instead.
Costs display as zero
This means pricing is unknown to the plugin, not free. See Pricing.
Development
Install dependencies and run the complete offline validation suite:
npm install
npm run check
npm audit --audit-level=low
Useful commands:
| Command | Purpose |
|---|---|
npm run typecheck |
Strict TypeScript validation |
npm run lint |
Biome lint checks |
npm run format:check |
Verify formatting |
npm test |
Offline unit, lifecycle, and contract tests |
npm run build |
Build JavaScript and declarations into dist/ |
npm run pack:check |
Inspect the npm package allowlist |
npm run test:live |
Explicit credential-gated live tests |
The offline suite covers endpoint validation, transport boundaries, redirects, redaction, hostile catalogs, exact fixture parity, login and cache lifecycle, native request shape, reasoning replay, images, Unicode, tools, cancellation, context overflow, and isolated pi package loading.
Live Tests
Live tests never run through npm test or npm run check.
Catalog-only parity check:
ACTUALYZE_TARGET=customer \
ACTUALYZE_API_KEY='...' \
npm run test:live
Paid streamed tool-loop check:
ACTUALYZE_TARGET=customer \
ACTUALYZE_API_KEY='...' \
ACTUALYZE_LIVE_INFERENCE=1 \
ACTUALYZE_LIVE_MODEL='budget-models' \
npm run test:live
Optional advisory-capability model:
ACTUALYZE_TARGET=customer \
ACTUALYZE_API_KEY='...' \
ACTUALYZE_LIVE_INFERENCE=1 \
ACTUALYZE_LIVE_ADVISORY_MODEL='fugu' \
npm run test:live
Choose the main live model from catalog entries advertising streaming and tool use; the advisory model is expected to advertise both as false. The default live command fetches only the catalog and verifies raw-to-parsed ID parity; the paid streamed tool loop runs only with the explicit inference flag and model.
Never enable live tests for untrusted pull requests. Supply credentials only through protected local or CI secret environments.
Package Contents
The npm file allowlist contains only:
src/README.mdLICENSEand npm-generated package metadata
Tests, .env.example, .pi/ reports, credentials, build output, coverage, and live
response captures are excluded.
Project Status
The provider implementation, offline suite, package-loading integration, live catalog parity check, and live streamed tool loop have been completed. One release decision is intentionally not guessed: authoritative currency and units for Actualyze's advertised pricing.
Conservative OpenAI compatibility flags remain disabled until live evidence supports promoting them.
Contributing
See CONTRIBUTING.md for the architecture overview, development workflow, invariants that must not regress, and known caveats.
License
MIT © Actualyze AI, Inc.