@monotykamary/pi-better-openai 0.2.6 → 0.2.8
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 +14 -0
- package/README.md +67 -6
- package/index.ts +118 -30
- package/package.json +10 -7
- package/plans/devday-integration.md +48 -0
- package/src/codex-models.ts +20 -0
- package/src/config.ts +143 -6
- package/src/decisions.ts +405 -0
- package/src/fast-controller.ts +98 -23
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.8
|
|
4
|
+
|
|
5
|
+
- Add GPT-6.1 Sol fallback metadata and Fast support for the GPT-6 model family.
|
|
6
|
+
- Add `/openai-tier` for Standard, Fast, and capability-gated API Astra Ultrafast, with explicit pricing warnings, persistence, diagnostics, and footer labels.
|
|
7
|
+
- Add opt-in `openai_decide` and `/openai-decisions` through Pi's classifier API, with typed validation, cancellation, safe errors, and usage accounting.
|
|
8
|
+
- Include classifier tool usage in footer totals and preserve legacy Fast settings and customized model lists.
|
|
9
|
+
- Document remaining native OpenAI Decisions, Codex subscription Ultrafast, and hosted multi-agent integration gates; no undocumented endpoint or chat fallback is assumed.
|
|
10
|
+
|
|
11
|
+
## 0.2.7
|
|
12
|
+
|
|
13
|
+
- Validate against Pi 0.99.0, including an offline real-host package-loading probe.
|
|
14
|
+
- Declare imported host packages as wildcard peers and pin development dependencies to Pi 0.99.0.
|
package/README.md
CHANGED
|
@@ -30,8 +30,9 @@ Usage display, image generation, and live voice require pi's `openai-codex` OAut
|
|
|
30
30
|
|
|
31
31
|
## Features
|
|
32
32
|
|
|
33
|
-
- GPT-6 Astra and Daybreak Blue/Red model fallbacks for the built-in `openai-codex` provider.
|
|
34
|
-
- Fast
|
|
33
|
+
- GPT-6.1 Sol, GPT-6 Astra, and Daybreak Blue/Red model fallbacks for the built-in `openai-codex` provider.
|
|
34
|
+
- Standard, Fast, and capability-gated Ultrafast service tiers via `/openai-tier` or `/openai-settings`; `/fast` remains a quick Fast toggle.
|
|
35
|
+
- Opt-in typed decisions through `openai_decide`, using an explicitly selected Pi classifier provider (including Jev). Native OpenAI Decisions remains gated on a published adapter.
|
|
35
36
|
- OpenAI subscription usage display via `/openai-usage` and the footer.
|
|
36
37
|
- Interactive settings picker via `/openai-settings`.
|
|
37
38
|
- Footer customization for model, thinking, fast mode, usage, and token/cost context.
|
|
@@ -40,7 +41,9 @@ Usage display, image generation, and live voice require pi's `openai-codex` OAut
|
|
|
40
41
|
- Codex-backed realtime voice through `/live`, with an animated microphone waveform and coding-task delegation into the active pi session.
|
|
41
42
|
- Animated Codex custom pets rendered in the Better OpenAI footer.
|
|
42
43
|
- Commands:
|
|
43
|
-
- `/fast` toggles
|
|
44
|
+
- `/fast` toggles Fast and Standard; it never enables Ultrafast.
|
|
45
|
+
- `/openai-tier [standard|fast|ultrafast]` shows or selects the requested service tier.
|
|
46
|
+
- `/openai-decisions [models|use provider/model|off]` inspects or configures typed decisions.
|
|
44
47
|
- `/openai-image <prompt>` generates an image directly.
|
|
45
48
|
- `/openai-websearch <query>` searches the web and inserts the cited answer into the session.
|
|
46
49
|
- `/live` starts or stops realtime voice mode. `Ctrl+Shift+L` is the keyboard toggle.
|
|
@@ -72,7 +75,14 @@ Default supported models:
|
|
|
72
75
|
[
|
|
73
76
|
"openai/gpt-5.4",
|
|
74
77
|
"openai/gpt-5.5",
|
|
78
|
+
"openai/gpt-6-astra",
|
|
79
|
+
"openai/gpt-6.1-sol",
|
|
80
|
+
"openai/gpt-6-sol",
|
|
81
|
+
"openai/gpt-6-luna",
|
|
75
82
|
"openai-codex/gpt-6-astra",
|
|
83
|
+
"openai-codex/gpt-6.1-sol",
|
|
84
|
+
"openai-codex/gpt-6-sol",
|
|
85
|
+
"openai-codex/gpt-6-luna",
|
|
76
86
|
"openai-codex/gpt-5.6-sol",
|
|
77
87
|
"openai-codex/gpt-5.6-terra",
|
|
78
88
|
"openai-codex/gpt-5.6-luna",
|
|
@@ -87,8 +97,12 @@ Example config:
|
|
|
87
97
|
{
|
|
88
98
|
"persistState": true,
|
|
89
99
|
"notifyOnModelSwitch": true,
|
|
90
|
-
"
|
|
91
|
-
"
|
|
100
|
+
"serviceTier": "standard",
|
|
101
|
+
"decisions": {
|
|
102
|
+
"enabled": false,
|
|
103
|
+
"model": "",
|
|
104
|
+
"timeoutMs": 10000
|
|
105
|
+
},
|
|
92
106
|
"usage": {
|
|
93
107
|
"enabled": true,
|
|
94
108
|
"refreshIntervalMs": 60000,
|
|
@@ -125,9 +139,56 @@ Example config:
|
|
|
125
139
|
}
|
|
126
140
|
```
|
|
127
141
|
|
|
142
|
+
## Service tiers
|
|
143
|
+
|
|
144
|
+
`/openai-tier fast` requests `service_tier: "priority"`. `/openai-tier standard` explicitly requests `"default"`, clearing an inherited Fast/Ultrafast request tier on OpenAI providers. Legacy disabled configurations without an explicit tier leave payloads untouched. `/fast` and the `--fast` flag never select Ultrafast.
|
|
145
|
+
|
|
146
|
+
`/openai-tier ultrafast` explicitly opts into **6x Standard token prices** for `openai/gpt-6-astra` over the Responses API. Only the documented global (`https://api.openai.com/v1`) and US (`https://us.api.openai.com/v1`) endpoints are enabled. EU/regional endpoints, custom proxies, other models, and Codex subscription Ultrafast are not enabled without verified support. This does not promise account entitlement or available rate limits. Unsupported selections remain requested but inactive; the extension does not inject a lower-tier fallback or retry a rejected request.
|
|
147
|
+
|
|
148
|
+
The footer shows `fast` or `ultrafast` only when supported by the current model. Diagnostics distinguish the requested tier and last injected payload from server-confirmed service or billing. **Pi's host cost estimates may omit the Ultrafast premium**; use OpenAI billing for actual charges. The host's native transport is preserved; WebSockets are recommended by OpenAI but HTTP is also supported. See [Ultrafast documentation](https://developers.openai.com/api/docs/guides/ultrafast-mode) and [pricing](https://developers.openai.com/api/docs/pricing?latest-pricing=ultrafast).
|
|
149
|
+
|
|
150
|
+
`serviceTier` takes precedence over legacy `desiredActive`/`active` within each config layer; project state still overrides global state. `persistState: false` keeps tier changes session-only. `supportedModels` overrides the Fast allowlist, not Ultrafast capabilities. Unknown config fields and customized model lists are preserved.
|
|
151
|
+
|
|
152
|
+
## Typed decisions
|
|
153
|
+
|
|
154
|
+
The `openai_decide` tool returns typed judgments through Pi's classifier API, **not chat completions**. It is disabled by default and never chooses a provider automatically. To use an existing Jev classifier explicitly:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
/openai-decisions models
|
|
158
|
+
/openai-decisions use typesafe/jev-latest
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Configure that provider's credentials through Pi (for example, `TYPESAFE_API_KEY` for TypeSafe). The model list shows registered classifiers, not guaranteed credentials or entitlement. `/openai-decisions use` saves the selected model and enables decisions in the active project/global config; `/openai-decisions off` disables requests. These settings are independent of service-tier persistence. Provider-qualified IDs containing further slashes, such as `openrouter/typesafe/jev-1.13`, are supported when registered by the host. Prefer pinned versions for stable evaluations.
|
|
162
|
+
|
|
163
|
+
**Native OpenAI Decisions is not yet implemented:** as of the September 29, 2026 research checkpoint, no verifiable public endpoint/schema or SDK adapter was found. The bridge accepts OpenAI only once a classifier adapter is registered in Pi; it does not invent an endpoint, forward Codex OAuth to another service, or silently substitute a chat model. See the [integration status and remaining gates](plans/devday-integration.md).
|
|
164
|
+
|
|
165
|
+
Example tool input:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"state": { "testFailure": "connection to local test database timed out" },
|
|
170
|
+
"questions": {
|
|
171
|
+
"route": {
|
|
172
|
+
"type": "choice",
|
|
173
|
+
"instructions": "Classify the failure for human review.",
|
|
174
|
+
"criteria": { "environment": "Environment problem", "code": "Code defect" }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
- `state`: JSON object; send only the necessary context, never credentials or the entire session.
|
|
181
|
+
- `questions`: 1–32 named questions. `choice` uses 2–64 labeled criteria; `bool` uses `true`/`false` criteria; `score` uses 2–64 ordered criteria. Pi maps boolean questions to Jev's `noul` representation.
|
|
182
|
+
- Total input is capped at 64 KiB. `decisions.timeoutMs` defaults to 10000 and is clamped to 1000–60000. Cancellation/deadlines abort the provider request; there are no automatic retries. A timed-out upstream request may still incur charges.
|
|
183
|
+
- Results have `status: "ok"`, provider/model provenance, and typed `answers`; errors have `status: "error"` and mark the tool failed. Structured output is available to programmatic callers. Provider error text is withheld to prevent credential/state leakage.
|
|
184
|
+
- Probabilities and confidence remain uncertain judgments; scores retain their provider-specific scale. No claim of cross-provider calibration is made. Decisions never authorize tools, execute commands, change the active model, or start background polling.
|
|
185
|
+
- Reported classifier token usage/cost is included in tool results and the Better OpenAI footer. Missing usage or catalog pricing is not evidence that a request was free.
|
|
186
|
+
|
|
128
187
|
## Codex model fallbacks
|
|
129
188
|
|
|
130
|
-
The extension adds `gpt-6-astra`, `gpt-daybreak-blue-latest`, and `gpt-daybreak-red-latest` to the built-in `openai-codex` provider without requiring local `models.json` entries. Existing built-in models remain available, and metadata from pi's live catalog takes precedence when pi publishes an official entry with the same ID.
|
|
189
|
+
The extension adds `gpt-6.1-sol`, `gpt-6-astra`, `gpt-daybreak-blue-latest`, and `gpt-daybreak-red-latest` to the built-in `openai-codex` provider without requiring local `models.json` entries. Existing built-in models remain available, and metadata from pi's live catalog takes precedence when pi publishes an official entry with the same ID.
|
|
190
|
+
|
|
191
|
+
The GPT-6.1 Sol fallback uses Codex's conservative 272K context default, 128K output limit, and published short/long-context pricing. It maps Pi's `minimal` level to `low` and disables `off`; the model does not accept `none` or `minimal` reasoning efforts. See [model documentation](https://developers.openai.com/api/docs/models/gpt-6.1-sol) and the [upstream Codex catalog change](https://github.com/openai/codex/commit/b1e72963c3b71a9265a551e54beff078384efed9).
|
|
131
192
|
|
|
132
193
|
Daybreak models require separate OpenAI approval and provisioning. pi currently exposes reasoning levels through `max`; Codex's `ultra` automatic-delegation mode is not a pi thinking level.
|
|
133
194
|
|
package/index.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Better OpenAI for pi.
|
|
3
3
|
*
|
|
4
|
-
* Adds
|
|
5
|
-
* enabled and the selected model is in the configured allow-list.
|
|
4
|
+
* Adds capability-gated OpenAI service tiers and opt-in native typed decisions.
|
|
6
5
|
*/
|
|
7
6
|
import {
|
|
8
7
|
type ExtensionAPI,
|
|
@@ -17,6 +16,7 @@ import {
|
|
|
17
16
|
SettingsList,
|
|
18
17
|
type SettingsListTheme,
|
|
19
18
|
} from "@earendil-works/pi-tui";
|
|
19
|
+
import type { Usage } from "@earendil-works/pi-ai";
|
|
20
20
|
import { registerOpenAICodexModels } from "./src/codex-models.ts";
|
|
21
21
|
import { CONFIG_BASENAME, STATUS_KEY } from "./src/identity.ts";
|
|
22
22
|
import {
|
|
@@ -49,6 +49,8 @@ import {
|
|
|
49
49
|
LIVE_SETTING_DESCRIPTORS,
|
|
50
50
|
PET_SETTING_DESCRIPTORS,
|
|
51
51
|
FAST_SETTING_DESCRIPTORS,
|
|
52
|
+
DECISIONS_SETTING_DESCRIPTORS,
|
|
53
|
+
isServiceTier,
|
|
52
54
|
type SettingsOptionDescriptor,
|
|
53
55
|
configPaths,
|
|
54
56
|
type ResolvedConfig,
|
|
@@ -80,6 +82,7 @@ import { ResetController } from "./src/reset-controller.ts";
|
|
|
80
82
|
import { registerOpenAIImage, _imageTest } from "./src/image.ts";
|
|
81
83
|
import { registerOpenAIWebSearch, _websearchTest } from "./src/websearch.ts";
|
|
82
84
|
import { registerOpenAILive } from "./src/live/index.ts";
|
|
85
|
+
import { registerOpenAIDecisions } from "./src/decisions.ts";
|
|
83
86
|
import {
|
|
84
87
|
type CodexPetPackage,
|
|
85
88
|
codexHome,
|
|
@@ -91,7 +94,7 @@ import {
|
|
|
91
94
|
registerOpenAIPets,
|
|
92
95
|
_petsTest,
|
|
93
96
|
} from "./src/pets.ts";
|
|
94
|
-
import { FastController,
|
|
97
|
+
import { FastController, supportsFast } from "./src/fast-controller.ts";
|
|
95
98
|
import { isOpenAISubscriptionModel, UsageController } from "./src/usage-controller.ts";
|
|
96
99
|
import { PetFooterController } from "./src/pet-footer-controller.ts";
|
|
97
100
|
import {
|
|
@@ -338,12 +341,14 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
338
341
|
...nextConfig,
|
|
339
342
|
active: fastController.active,
|
|
340
343
|
desiredActive: fastController.desiredActive,
|
|
344
|
+
serviceTier: fastController.desiredTier,
|
|
341
345
|
};
|
|
342
346
|
if (!nextConfig.persistState) return;
|
|
343
347
|
writeConfig(nextConfig.configPath, {
|
|
344
348
|
...readRawConfig(nextConfig.configPath),
|
|
345
349
|
active: fastController.active,
|
|
346
350
|
desiredActive: fastController.desiredActive,
|
|
351
|
+
serviceTier: fastController.desiredTier,
|
|
347
352
|
});
|
|
348
353
|
}
|
|
349
354
|
|
|
@@ -368,15 +373,22 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
368
373
|
ctx.ui.notify(fastController.stateText(ctx, nextConfig), "info");
|
|
369
374
|
}
|
|
370
375
|
|
|
376
|
+
function addFooterUsage(usage: Usage | undefined): void {
|
|
377
|
+
if (!usage) return;
|
|
378
|
+
footerTotals.input += usage.input;
|
|
379
|
+
footerTotals.output += usage.output;
|
|
380
|
+
footerTotals.cacheRead += usage.cacheRead;
|
|
381
|
+
footerTotals.cacheWrite += usage.cacheWrite;
|
|
382
|
+
footerTotals.cost += usage.cost.total;
|
|
383
|
+
}
|
|
384
|
+
|
|
371
385
|
function refreshFooterTotals(ctx: ExtensionContext): void {
|
|
372
386
|
footerTotals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
|
|
373
387
|
for (const entry of ctx.sessionManager.getEntries()) {
|
|
374
|
-
if (entry.type !== "message"
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
footerTotals.cacheWrite += entry.message.usage.cacheWrite;
|
|
379
|
-
footerTotals.cost += entry.message.usage.cost.total;
|
|
388
|
+
if (entry.type !== "message") continue;
|
|
389
|
+
if (entry.message.role === "assistant" || entry.message.role === "toolResult") {
|
|
390
|
+
addFooterUsage(entry.message.usage);
|
|
391
|
+
}
|
|
380
392
|
}
|
|
381
393
|
}
|
|
382
394
|
|
|
@@ -433,6 +445,9 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
433
445
|
`Image default save: ${cfg.image.defaultSave}`,
|
|
434
446
|
`Websearch enabled: ${cfg.websearch.enabled}`,
|
|
435
447
|
`Websearch model: ${cfg.websearch.model} (${cfg.websearch.reasoningEffort}/${cfg.websearch.responseLength}, ${cfg.websearch.maxOutputTokens} tokens, ${cfg.websearch.timeoutMs}ms)`,
|
|
448
|
+
`Decisions enabled: ${cfg.decisions.enabled}`,
|
|
449
|
+
`Decision classifier: ${cfg.decisions.model || "not selected"} (${cfg.decisions.timeoutMs}ms)`,
|
|
450
|
+
"Native OpenAI Decisions requires a registered classifier adapter; no chat fallback.",
|
|
436
451
|
`Live enabled: ${cfg.live.enabled}`,
|
|
437
452
|
`Live voice: ${cfg.live.voice}`,
|
|
438
453
|
`Pet enabled: ${cfg.pets.enabled}`,
|
|
@@ -531,6 +546,37 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
531
546
|
},
|
|
532
547
|
});
|
|
533
548
|
|
|
549
|
+
pi.registerCommand("openai-tier", {
|
|
550
|
+
description: "Select standard, fast, or ultrafast (API Astra; 6x Standard token prices)",
|
|
551
|
+
handler: async (args, ctx) => {
|
|
552
|
+
const tier = args.trim().toLowerCase();
|
|
553
|
+
if (!tier) {
|
|
554
|
+
ctx.ui.notify(
|
|
555
|
+
`Requested tier: ${fastController.desiredTier}. ${fastController.stateText(ctx, config(ctx))}`,
|
|
556
|
+
"info",
|
|
557
|
+
);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (!isServiceTier(tier)) {
|
|
561
|
+
ctx.ui.notify(
|
|
562
|
+
"Usage: /openai-tier [standard | fast | ultrafast]. Ultrafast explicitly opts into 6x Standard token prices.",
|
|
563
|
+
"error",
|
|
564
|
+
);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
const cfg = refresh(ctx);
|
|
568
|
+
fastController.setTier(ctx, cfg, tier);
|
|
569
|
+
persist(cfg);
|
|
570
|
+
updateFooter(ctx);
|
|
571
|
+
ctx.ui.notify(
|
|
572
|
+
fastController.stateText(ctx, cfg),
|
|
573
|
+
tier === "ultrafast" || (fastController.desiredActive && !fastController.active)
|
|
574
|
+
? "warning"
|
|
575
|
+
: "info",
|
|
576
|
+
);
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
|
|
534
580
|
pi.registerCommand(OPENAI_STATUS_COMMAND, {
|
|
535
581
|
description: "Show OpenAI subscription usage status",
|
|
536
582
|
handler: async (_args, ctx) => {
|
|
@@ -798,16 +844,9 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
798
844
|
}
|
|
799
845
|
|
|
800
846
|
function buildFastSettingsItems(cfg: ResolvedConfig): SettingsPickerItem[] {
|
|
801
|
-
return
|
|
802
|
-
{
|
|
803
|
-
|
|
804
|
-
label: "Fast mode",
|
|
805
|
-
currentValue: String(fastController.desiredActive),
|
|
806
|
-
values: ["true", "false"],
|
|
807
|
-
description: `Request OpenAI fast mode. Activates for supported models: ${modelList(cfg.supportedModels)}.`,
|
|
808
|
-
},
|
|
809
|
-
...settingsItemsFromDescriptors(FAST_SETTING_DESCRIPTORS, cfg),
|
|
810
|
-
];
|
|
847
|
+
return settingsItemsFromDescriptors(FAST_SETTING_DESCRIPTORS, cfg, {
|
|
848
|
+
serviceTier: { currentValue: fastController.desiredTier },
|
|
849
|
+
});
|
|
811
850
|
}
|
|
812
851
|
|
|
813
852
|
function buildFooterSettingsItems(cfg: ResolvedConfig): SettingsPickerItem[] {
|
|
@@ -870,12 +909,13 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
870
909
|
return [
|
|
871
910
|
{
|
|
872
911
|
id: "section.fast",
|
|
873
|
-
label: "
|
|
912
|
+
label: "Service tier",
|
|
874
913
|
currentValue: fastSettingsSummary(ctx, cfg),
|
|
875
|
-
description:
|
|
914
|
+
description:
|
|
915
|
+
"Configure Standard, Fast, Ultrafast, and persistence. Ultrafast costs 6x Standard.",
|
|
876
916
|
submenu: (_value, done) =>
|
|
877
917
|
settingsSubmenu(
|
|
878
|
-
"
|
|
918
|
+
"Service tier settings",
|
|
879
919
|
() => buildFastSettingsItems(config(ctx)),
|
|
880
920
|
ctx,
|
|
881
921
|
() => done(fastSettingsSummary(ctx, config(ctx))),
|
|
@@ -933,6 +973,38 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
933
973
|
() => done(websearchSettingsSummary(config(ctx))),
|
|
934
974
|
),
|
|
935
975
|
},
|
|
976
|
+
{
|
|
977
|
+
id: "section.decisions",
|
|
978
|
+
label: "Typed decisions",
|
|
979
|
+
currentValue: cfg.decisions.enabled ? cfg.decisions.model || "model required" : "disabled",
|
|
980
|
+
description: "Opt-in native classifier requests; no chat fallback or automatic actions.",
|
|
981
|
+
submenu: (_value, done) =>
|
|
982
|
+
settingsSubmenu(
|
|
983
|
+
"Typed decision settings",
|
|
984
|
+
() => {
|
|
985
|
+
const next = config(ctx);
|
|
986
|
+
const models = ctx.modelRegistry.getModelsOfType("classifier");
|
|
987
|
+
return settingsItemsFromDescriptors(DECISIONS_SETTING_DESCRIPTORS, next, {
|
|
988
|
+
"decisions.model": {
|
|
989
|
+
values: [
|
|
990
|
+
...new Set([
|
|
991
|
+
"",
|
|
992
|
+
next.decisions.model,
|
|
993
|
+
...models.map((model) => `${model.provider}/${model.id}`),
|
|
994
|
+
]),
|
|
995
|
+
],
|
|
996
|
+
},
|
|
997
|
+
});
|
|
998
|
+
},
|
|
999
|
+
ctx,
|
|
1000
|
+
() =>
|
|
1001
|
+
done(
|
|
1002
|
+
config(ctx).decisions.enabled
|
|
1003
|
+
? config(ctx).decisions.model || "model required"
|
|
1004
|
+
: "disabled",
|
|
1005
|
+
),
|
|
1006
|
+
),
|
|
1007
|
+
},
|
|
936
1008
|
{
|
|
937
1009
|
id: "section.live",
|
|
938
1010
|
label: "Live voice",
|
|
@@ -998,14 +1070,29 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
998
1070
|
const bool = rawValue === "true";
|
|
999
1071
|
if (id === "fast.enabled") {
|
|
1000
1072
|
fastController.setDesired(ctx, cfg, bool);
|
|
1073
|
+
} else if (id === "serviceTier") {
|
|
1074
|
+
if (!isServiceTier(rawValue)) return;
|
|
1075
|
+
fastController.setTier(ctx, cfg, rawValue);
|
|
1076
|
+
ctx.ui.notify(
|
|
1077
|
+
fastController.stateText(ctx, cfg),
|
|
1078
|
+
rawValue === "ultrafast" || (fastController.desiredActive && !fastController.active)
|
|
1079
|
+
? "warning"
|
|
1080
|
+
: "info",
|
|
1081
|
+
);
|
|
1001
1082
|
}
|
|
1002
1083
|
const petKey = id.startsWith("pets.") ? id.slice("pets.".length) : undefined;
|
|
1003
1084
|
const nextRawConfig = applySettingToRawConfig(current, id, rawValue, {
|
|
1004
1085
|
persistState: cfg.persistState,
|
|
1005
1086
|
active: fastController.active,
|
|
1006
1087
|
desiredActive: fastController.desiredActive,
|
|
1088
|
+
serviceTier: fastController.desiredTier,
|
|
1007
1089
|
petEmptyValue: PET_EMPTY_VALUE,
|
|
1008
1090
|
});
|
|
1091
|
+
if (id === "persistState" && bool) {
|
|
1092
|
+
nextRawConfig.serviceTier = fastController.desiredTier;
|
|
1093
|
+
nextRawConfig.active = fastController.active;
|
|
1094
|
+
nextRawConfig.desiredActive = fastController.desiredActive;
|
|
1095
|
+
}
|
|
1009
1096
|
if (petKey) {
|
|
1010
1097
|
if (petKey === "enabled" || petKey === "sizeCells" || petKey === "slug")
|
|
1011
1098
|
petController.invalidateLoadKey();
|
|
@@ -1102,6 +1189,7 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
1102
1189
|
|
|
1103
1190
|
registerOpenAIImage(pi, config);
|
|
1104
1191
|
registerOpenAIWebSearch(pi, config);
|
|
1192
|
+
registerOpenAIDecisions(pi, config, refresh);
|
|
1105
1193
|
registerOpenAILive(pi, config);
|
|
1106
1194
|
registerOpenAIPets(pi, {
|
|
1107
1195
|
wake: async (ctx, slug) => {
|
|
@@ -1270,8 +1358,9 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
1270
1358
|
|
|
1271
1359
|
const modelName = ctx.model?.id || "no-model";
|
|
1272
1360
|
const thinkingLevel = pi.getThinkingLevel();
|
|
1273
|
-
const fastSuffix =
|
|
1274
|
-
|
|
1361
|
+
const fastSuffix = fastController.statusSegment(ctx, cfg)
|
|
1362
|
+
? ` ${fastController.desiredTier}`
|
|
1363
|
+
: "";
|
|
1275
1364
|
let rightWithoutProvider = modelName;
|
|
1276
1365
|
if (ctx.model?.reasoning) {
|
|
1277
1366
|
rightWithoutProvider =
|
|
@@ -1448,7 +1537,9 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
1448
1537
|
fastController.initializeForSession(ctx, nextConfig, pi.getFlag(FLAG) === true);
|
|
1449
1538
|
if (
|
|
1450
1539
|
fastController.desiredActive !== nextConfig.desiredActive ||
|
|
1451
|
-
fastController.active !== nextConfig.active
|
|
1540
|
+
fastController.active !== nextConfig.active ||
|
|
1541
|
+
fastController.desiredTier !==
|
|
1542
|
+
(nextConfig.serviceTier ?? (nextConfig.desiredActive ? "fast" : "standard"))
|
|
1452
1543
|
)
|
|
1453
1544
|
persist(nextConfig);
|
|
1454
1545
|
if (hasTerminalUI(ctx)) petController.installResizeGuard(ctx);
|
|
@@ -1489,11 +1580,8 @@ export default function betterOpenAI(pi: ExtensionAPI): void {
|
|
|
1489
1580
|
pi.on("turn_end", (event, ctx) => {
|
|
1490
1581
|
invalidateContextUsage();
|
|
1491
1582
|
if (event.message?.role === "assistant") {
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
footerTotals.cacheRead += event.message.usage.cacheRead;
|
|
1495
|
-
footerTotals.cacheWrite += event.message.usage.cacheWrite;
|
|
1496
|
-
footerTotals.cost += event.message.usage.cost.total;
|
|
1583
|
+
addFooterUsage(event.message.usage);
|
|
1584
|
+
for (const result of event.toolResults ?? []) addFooterUsage(result.usage);
|
|
1497
1585
|
} else refreshFooterTotals(ctx);
|
|
1498
1586
|
updateFooter(ctx);
|
|
1499
1587
|
void usageController.refresh(ctx);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monotykamary/pi-better-openai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Improve OpenAI in pi with fast mode, usage stats, realtime voice, image generation, and footer polish.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fast",
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"index.ts",
|
|
39
39
|
"src/",
|
|
40
40
|
"README.md",
|
|
41
|
+
"CHANGELOG.md",
|
|
42
|
+
"plans/devday-integration.md",
|
|
41
43
|
"LICENSE",
|
|
42
44
|
"THIRD_PARTY_NOTICES.md"
|
|
43
45
|
],
|
|
@@ -52,7 +54,8 @@
|
|
|
52
54
|
"lint": "oxlint --deny-warnings index.ts src/*.ts src/*/*.ts tests/*.ts",
|
|
53
55
|
"lint:fix": "oxlint --fix index.ts src/*.ts src/*/*.ts tests/*.ts",
|
|
54
56
|
"test": "vitest run",
|
|
55
|
-
"typecheck": "tsc --noEmit"
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"test:pi": "node scripts/test-pi-compat.mjs"
|
|
56
59
|
},
|
|
57
60
|
"dependencies": {
|
|
58
61
|
"https-proxy-agent": "9.1.0",
|
|
@@ -62,9 +65,9 @@
|
|
|
62
65
|
"ws": "8.21.2"
|
|
63
66
|
},
|
|
64
67
|
"devDependencies": {
|
|
65
|
-
"@earendil-works/pi-ai": "0.
|
|
66
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
67
|
-
"@earendil-works/pi-tui": "0.
|
|
68
|
+
"@earendil-works/pi-ai": "0.99.0",
|
|
69
|
+
"@earendil-works/pi-coding-agent": "0.99.0",
|
|
70
|
+
"@earendil-works/pi-tui": "0.99.0",
|
|
68
71
|
"@types/node": "~22.19.0",
|
|
69
72
|
"@types/proxy-from-env": "1.0.4",
|
|
70
73
|
"@types/ws": "8.18.1",
|
|
@@ -86,8 +89,8 @@
|
|
|
86
89
|
"@oh-my-pi/pi-natives-win32-x64": "17.2.9"
|
|
87
90
|
},
|
|
88
91
|
"overrides": {
|
|
89
|
-
"@earendil-works/pi-agent-core": "0.
|
|
90
|
-
"@earendil-works/pi-ai": "0.
|
|
92
|
+
"@earendil-works/pi-agent-core": "0.99.0",
|
|
93
|
+
"@earendil-works/pi-ai": "0.99.0",
|
|
91
94
|
"brace-expansion": "5.0.9",
|
|
92
95
|
"nanoid": "3.3.18",
|
|
93
96
|
"postcss": "8.5.25",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# DevDay integration status
|
|
2
|
+
|
|
3
|
+
Research checkpoint: September 29, 2026 (UTC). Announcements and account entitlements can change independently of source releases.
|
|
4
|
+
|
|
5
|
+
## Implemented
|
|
6
|
+
|
|
7
|
+
- GPT-6.1 Sol fallback metadata, with native Pi transport/auth and live catalog precedence preserved.
|
|
8
|
+
- Fast-mode defaults for GPT-6 Astra, 6.1 Sol, Sol, and Luna on OpenAI/Codex.
|
|
9
|
+
- Explicit Standard/Fast/Ultrafast selection, legacy state migration, model/endpoint capability gates, persistence, diagnostics, cost disclosure, and footer labels.
|
|
10
|
+
- `openai_decide`: an opt-in bridge to Pi's classifier API. Explicit model selection, bounded typed input/output, cancellation/deadlines, usage reporting, and no chat/provider fallback.
|
|
11
|
+
- No autonomous actions, model routing, approval bypasses, or inference-driven polling. Classification is an advisory primitive; application code owns policy and execution.
|
|
12
|
+
|
|
13
|
+
## Native OpenAI Decisions: blocked on a verifiable contract
|
|
14
|
+
|
|
15
|
+
The announcement is reported in [DevDay coverage](https://www.axios.com/2026/09/29/openai-dev-day-2026-dots-space-sol). At the research checkpoint, the public docs index and OpenAI Node SDK did not expose a verifiable Decisions contract; Codex search hits concerned existing approval decisions. This is not proof that private or later access is unavailable.
|
|
16
|
+
|
|
17
|
+
The tool works with explicitly selected registered classifiers, including Jev. It does not pretend this is OpenAI's new service. Once OpenAI publishes its contract:
|
|
18
|
+
|
|
19
|
+
1. Verify model IDs, schema, error/refusal behavior, modalities, endpoint, auth audience, rate limits, pricing, and data residency.
|
|
20
|
+
2. Prefer a native Pi classifier adapter rather than duplicating credentials and transport here. Register classifier models, not chat models; the current tool can then select them.
|
|
21
|
+
3. Preserve provider semantics. Do not equate arbitrary numeric scores or self-reported confidence with calibrated probabilities, or silently translate incompatible question types.
|
|
22
|
+
4. Keep API-key and Codex subscription access separate until subscription authorization is documented. Do not infer OAuth compatibility from a product announcement.
|
|
23
|
+
5. Add fixture tests and an opt-in live probe before claiming support. No default model ID is guessed today.
|
|
24
|
+
|
|
25
|
+
### Evaluation checklist
|
|
26
|
+
|
|
27
|
+
Before automated routing or background triage is enabled, compare pinned Jev/OpenAI classifier versions on the same consented, non-sensitive labeled cases:
|
|
28
|
+
|
|
29
|
+
- failure classification, candidate-tool ranking, task routing, and notification relevance;
|
|
30
|
+
- p50/p95 end-to-end latency, cost per useful decision, invalid-result/refusal/timeout rates;
|
|
31
|
+
- accuracy and abstention coverage; Brier score/calibration only for outputs documented as probabilities;
|
|
32
|
+
- low-confidence escalation and immutable policy/permission boundaries.
|
|
33
|
+
|
|
34
|
+
Do not automatically run paid benchmark requests. A typed result is not proof of truth or authorization. TypeSafe's [September 15 Jev announcement](https://typesafe.ai/blog/introducing-system-one-models-and-jev) establishes timing and the decision-oriented interface, not OpenAI implementation provenance.
|
|
35
|
+
|
|
36
|
+
## Codex subscription Ultrafast: capability gate remains closed
|
|
37
|
+
|
|
38
|
+
The [public Ultrafast guide](https://developers.openai.com/api/docs/guides/ultrafast-mode) documents API Astra support. Codex has catalog-driven tier controls and WebSocket tier-switch tests, but its inspected bundled Astra/Sol catalog advertises Fast, not a subscription Ultrafast entitlement.
|
|
39
|
+
|
|
40
|
+
Enable subscription Ultrafast only after an authenticated model/account capability contract is established, with tests for account switching, capability withdrawal, and unsupported requests. Arbitrary `supportedModels` configuration must not bypass this gate. Global/US API Astra is the verified path today. Host cost reporting currently may omit its 6x premium; never describe local estimates as actual billing.
|
|
41
|
+
|
|
42
|
+
## Hosted Responses multi-agent: deliberately deferred
|
|
43
|
+
|
|
44
|
+
[Responses multi-agent](https://developers.openai.com/api/docs/guides/responses-multi-agent) is a separate beta protocol, not a tier or ordinary thinking level. Adding only `multi_agent.enabled` is insufficient and could conflict with Fabric's orchestration.
|
|
45
|
+
|
|
46
|
+
A future opt-in integration must handle agent identities, hosted collaboration items versus client tool calls, interleaved streams, continuation routing, cancellation, concurrency and total-spend limits, and permission enforcement for every child. Do not assume `max_concurrent_subagents` limits total agents, tree depth, or total spend. Keep the existing local orchestration owner until these invariants are verified.
|
|
47
|
+
|
|
48
|
+
Dots, Space, and other consumer surfaces are not added without a documented integration contract.
|
package/src/codex-models.ts
CHANGED
|
@@ -59,6 +59,26 @@ export const CODEX_MODEL_FALLBACKS: CodexModel[] = [
|
|
|
59
59
|
},
|
|
60
60
|
compat: CODEX_COMPAT,
|
|
61
61
|
},
|
|
62
|
+
{
|
|
63
|
+
id: "gpt-6.1-sol",
|
|
64
|
+
name: "GPT-6.1 Sol",
|
|
65
|
+
api: CODEX_API,
|
|
66
|
+
provider: CODEX_PROVIDER_ID,
|
|
67
|
+
baseUrl: CODEX_BASE_URL,
|
|
68
|
+
reasoning: true,
|
|
69
|
+
thinkingLevelMap: { off: null, minimal: "low", xhigh: "xhigh", max: "max" },
|
|
70
|
+
input: ["text", "image"],
|
|
71
|
+
contextWindow: 272000,
|
|
72
|
+
maxTokens: 128000,
|
|
73
|
+
cost: {
|
|
74
|
+
input: 2,
|
|
75
|
+
output: 10,
|
|
76
|
+
cacheRead: 0.1,
|
|
77
|
+
cacheWrite: 2.5,
|
|
78
|
+
tiers: [{ inputTokensAbove: 272000, input: 4, output: 15, cacheRead: 0.2, cacheWrite: 5 }],
|
|
79
|
+
},
|
|
80
|
+
compat: CODEX_COMPAT,
|
|
81
|
+
},
|
|
62
82
|
{
|
|
63
83
|
id: "gpt-daybreak-blue-latest",
|
|
64
84
|
name: "Daybreak Blue",
|