pi-openai-codex-compat 0.0.16 → 0.0.18
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 +39 -0
- package/README.md +75 -17
- package/extensions/openai-codex-compat/command-tools.ts +2 -0
- package/extensions/openai-codex-compat/config.ts +2 -56
- package/extensions/openai-codex-compat/footer.ts +23 -2
- package/extensions/openai-codex-compat/index.ts +9 -3
- package/extensions/openai-codex-compat/pi-runtime.ts +1 -1
- package/extensions/openai-codex-compat/responses-lite.ts +1 -0
- package/extensions/openai-codex-compat/settings-pane.ts +227 -536
- package/extensions/settings-menu.ts +618 -0
- package/extensions/settings-session.ts +130 -0
- package/extensions/settings-store.ts +240 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.0.18 - 2026-09-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Keep Pi 0.99 running in the terminal UI. Pi 0.99's footer reads session
|
|
10
|
+
methods the Codex footer did not provide, so Pi exited on its first render.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Opt-in Responses Lite for GPT-6.1 Sol. GPT-6.1 Sol uses standard reasoning
|
|
15
|
+
mode even when `pro` is configured.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Require Pi `>=0.99.1 <0.100.0`. Restart Pi after upgrading it.
|
|
20
|
+
|
|
21
|
+
## 0.0.17 - 2026-09-25
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Separate menu sections with blank rows, using compact spacing on short terminals.
|
|
26
|
+
- Align setting names on the left and values in a stable column on the right.
|
|
27
|
+
Render the search placeholder in muted gray instead of ordinary input text.
|
|
28
|
+
Keep Save and Discard hints visible in narrow terminals.
|
|
29
|
+
- Align settings with the Anthropic menu: Enter changes values, Ctrl+S saves and
|
|
30
|
+
applies drafts, and Escape discards unapplied drafts without changing active tools.
|
|
31
|
+
- Save only changed overrides, preserve inheritance and external edits, and
|
|
32
|
+
report conflicting saves without overwriting them.
|
|
33
|
+
- Block command-tool switches while persistent command sessions remain instead
|
|
34
|
+
of terminating them while browsing settings.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Apply to session without changing configuration files. Reopening settings shows
|
|
39
|
+
active session values, including after reload, restart, or resume.
|
|
40
|
+
Ctrl+S can save session-only changes later.
|
|
41
|
+
- Custom percentage editing, configuration-source and model-applicability labels,
|
|
42
|
+
inherited-value resets, and consistent keyboard, focus, and mouse support.
|
|
43
|
+
|
|
5
44
|
## 0.0.16 - 2026-09-23
|
|
6
45
|
|
|
7
46
|
### Added
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ OpenAI Codex compatibility for [Pi](https://github.com/earendil-works/pi-mono),
|
|
|
14
14
|
- **Dedicated Codex tool UI**: renders command tools, `apply_patch`, `image_gen.imagegen`, and `web.run` on a shared configurable surface with compact summaries and `Ctrl+O` expansion.
|
|
15
15
|
- **Hosted web-search fallback**: injects native `web_search` only when `web.run` is inactive, with cached, indexed, or live modes.
|
|
16
16
|
- **Native request controls**: configures Responses API text verbosity, reasoning summaries, and standard/pro reasoning mode on supported models.
|
|
17
|
-
- **
|
|
17
|
+
- **Draft settings pane**: `/codex-settings` stages edits before applying them. Apply to session stores them with the session without changing configuration files. Ctrl+S saves and applies them. Escape discards only unapplied drafts.
|
|
18
18
|
- **Session-aware footer**: shows the current Pi session ID on the first line and appends non-default Codex request modes to the model side of Pi's normal second line.
|
|
19
19
|
|
|
20
20
|
Pi provides the Codex OAuth flow and model catalog. At session start, this package overrides the built-in `openai-codex` runtime under the same provider id so ordinary responses and remote compaction share one transport, parser, native-history store, and sticky WebSocket session.
|
|
@@ -22,7 +22,7 @@ Pi provides the Codex OAuth flow and model catalog. At session start, this packa
|
|
|
22
22
|
## Requirements
|
|
23
23
|
|
|
24
24
|
- Node.js 22.19 or newer
|
|
25
|
-
- Pi `>=0.
|
|
25
|
+
- Pi `>=0.99.1 <0.100.0`
|
|
26
26
|
- An OpenAI Codex login in Pi
|
|
27
27
|
|
|
28
28
|
Restart Pi after upgrading its runtime. `/reload` reloads extensions but cannot
|
|
@@ -173,7 +173,56 @@ A trusted project can override it at:
|
|
|
173
173
|
<project>/.pi/openai-codex-compat.json
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
Each session inherits the effective file-backed settings.
|
|
176
|
+
Each session inherits the effective file-backed settings. `/codex-settings`
|
|
177
|
+
uses the same interaction contract as `/anthropic-settings`:
|
|
178
|
+
|
|
179
|
+
- **Enter** changes the selected value or opens its editor. It never implicitly saves.
|
|
180
|
+
- **Space** activates a result or inserts a space when search has focus.
|
|
181
|
+
- **Tab / Shift+Tab** move between search, results, and action controls.
|
|
182
|
+
- **F1** opens scrollable details, full errors, and the exact save target.
|
|
183
|
+
- Edits remain drafts until explicitly applied or saved.
|
|
184
|
+
- **Apply to session** applies drafts without writing configuration files and stays open.
|
|
185
|
+
- **Ctrl+S** saves and applies changes without closing.
|
|
186
|
+
- **Save and close** saves and applies changes, then closes on success.
|
|
187
|
+
- **Escape** cancels a field editor or discards unapplied drafts and closes the main menu.
|
|
188
|
+
It does not undo settings already applied to the session.
|
|
189
|
+
|
|
190
|
+
Search matches labels, configuration keys, and descriptions. The percentage
|
|
191
|
+
editor supports presets and custom fractional values. **Use inherited value**
|
|
192
|
+
removes an override. This differs from **Pi default**, which explicitly disables
|
|
193
|
+
an inherited percentage trigger. Rows show configuration sources, environment
|
|
194
|
+
locks, and model applicability. Pi's remapped selection and cancel keys are respected.
|
|
195
|
+
|
|
196
|
+
The global file is the normal save target. An existing trusted project override
|
|
197
|
+
is the target for that project. The target stays fixed while the menu is open.
|
|
198
|
+
Saving changes only edited overrides, preserves unknown keys and inherited values,
|
|
199
|
+
and preserves non-conflicting external edits. Conflicting edits are rejected for review.
|
|
200
|
+
Opening or closing without changes does not create a configuration file.
|
|
201
|
+
Reopening shows active session values, not freshly read file values. `*` marks
|
|
202
|
+
an unapplied draft. `~` marks an active session override or a value that differs
|
|
203
|
+
from the saved configuration. Details shows the saved value when it differs.
|
|
204
|
+
Ctrl+S also persists changes previously applied only to the session.
|
|
205
|
+
Session settings are stored as extension state entries in the Pi session,
|
|
206
|
+
outside model context. They survive menu closure, tree navigation, extension
|
|
207
|
+
reload, process restart, and switching away and back. Resuming the same session
|
|
208
|
+
restores its settings before provider operations. A new session, fork, or clone
|
|
209
|
+
has a separate identity and starts from configuration files.
|
|
210
|
+
Pi's `--no-session` mode cannot be resumed after exit. Pi also defers creating a
|
|
211
|
+
new session file until its first assistant message.
|
|
212
|
+
Environment-controlled fields remain locked and take precedence over restored
|
|
213
|
+
session preferences. Their values are not copied into session settings.
|
|
214
|
+
|
|
215
|
+
Applying and saving wait for Pi to become idle. Collect pending output with `write_stdin` or
|
|
216
|
+
stop running command sessions through `/ps` before applying or saving a command-tool switch.
|
|
217
|
+
Browsing settings and discarding drafts
|
|
218
|
+
never terminate those sessions. Escape cancels a pending operation without discarding
|
|
219
|
+
the draft. Failures leave the menu open. If a save reaches disk but cannot
|
|
220
|
+
be applied to the session, the menu reports that distinction and Ctrl+S retries
|
|
221
|
+
application. Cooperating writers use a `.settings-lock` file. An interrupted
|
|
222
|
+
writer can leave a lock that requires review; locks are not automatically
|
|
223
|
+
deleted. External editors do not participate in that lock.
|
|
224
|
+
Session overrides retain their original conflict checks across menu reopenings.
|
|
225
|
+
Conflicting external edits remain protected after reload or restart.
|
|
177
226
|
|
|
178
227
|
The effective settings are printed once when a TUI session starts. The footer shows the current Pi session ID alongside the working directory and optional session name. It shows `fast` and `pro` only when enabled, and shows text verbosity or reasoning summary only when they differ from their defaults.
|
|
179
228
|
|
|
@@ -220,12 +269,19 @@ Defaults:
|
|
|
220
269
|
| `reasoningMode` | `standard`, `pro` | `standard` | Controls supported models' execution mode independently of Pi's reasoning-effort control. The default omits `reasoning.mode`; `pro` sends `reasoning.mode: "pro"`. |
|
|
221
270
|
|
|
222
271
|
Responses Lite supports exactly `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`,
|
|
223
|
-
`gpt-6-astra`, `gpt-6-sol`, and `gpt-6-
|
|
224
|
-
`gpt-5.6`, `gpt-5.6-*`, and exactly `gpt-6-astra`. GPT-6 Sol
|
|
225
|
-
standard reasoning mode even when `pro` is configured.
|
|
226
|
-
opt-in. GPT-6 Sol
|
|
272
|
+
`gpt-6-astra`, `gpt-6-sol`, `gpt-6-luna`, and `gpt-6.1-sol`. Pro reasoning mode
|
|
273
|
+
supports `gpt-5.6`, `gpt-5.6-*`, and exactly `gpt-6-astra`. GPT-6 Sol, GPT-6
|
|
274
|
+
Luna, and GPT-6.1 Sol use standard reasoning mode even when `pro` is configured.
|
|
275
|
+
Both controls remain opt-in. GPT-6.1 Sol requires Pi 0.99.1's model catalog.
|
|
227
276
|
|
|
228
|
-
|
|
277
|
+
As of September 30, 2026, the Codex endpoint rejects `reasoning.mode` for every
|
|
278
|
+
tested model, including those listed above, so `pro` requests fail there. The
|
|
279
|
+
setting remains for providers that accept it. Releases do not test pro mode
|
|
280
|
+
against `openai-codex`.
|
|
281
|
+
|
|
282
|
+
Invalid JSON setting values are ignored and invalid JSON does not prevent Pi from
|
|
283
|
+
starting. The settings pane reports malformed JSON instead of overwriting it.
|
|
284
|
+
Project configuration is read only when the project is trusted.
|
|
229
285
|
|
|
230
286
|
Every setting can also be overridden for one Pi process with an environment variable:
|
|
231
287
|
|
|
@@ -533,7 +589,9 @@ The tool generates new images with `gpt-image-2` or edits up to five local/recen
|
|
|
533
589
|
~/.pi/agent/generated_images/<session-id>/<call-id>.png
|
|
534
590
|
```
|
|
535
591
|
|
|
536
|
-
The active Pi agent directory replaces `~/.pi/agent` when configured differently.
|
|
592
|
+
The active Pi agent directory replaces `~/.pi/agent` when configured differently.
|
|
593
|
+
Saving `imageGeneration: false` through `/codex-settings` removes the tool from
|
|
594
|
+
the current session.
|
|
537
595
|
|
|
538
596
|
The tool registers the server-reserved schema directly with a model-facing absolute-path annotation that names the supported image formats. OpenAI rejects additional schema keywords for image-count bounds and selector exclusivity, so the executor enforces those constraints before filesystem or network access. Local paths are lexically normalized before reading. A one-line system-prompt snippet and four high-signal guidelines cover normal model use. Local images are inspected with Pi's `read` tool, and generated image content is displayed and saved automatically without Codex Code Mode wrappers.
|
|
539
597
|
|
|
@@ -592,7 +650,7 @@ npm run pack:dry
|
|
|
592
650
|
`mise run check` runs the linters, formatters, type checks, and the offline
|
|
593
651
|
test suite; `mise run test` runs only the offline suite. Both tasks bind
|
|
594
652
|
`PI_PACKAGE_DIR` to `node_modules/@earendil-works/pi-coding-agent`, so tests
|
|
595
|
-
that load Pi in-process read this repository's Pi 0.
|
|
653
|
+
that load Pi in-process read this repository's Pi 0.99.1 resources even when a
|
|
596
654
|
global `PI_PACKAGE_DIR` points at another installation. Ordinary `pi` launches
|
|
597
655
|
outside these tasks are unaffected. Offline tests also exercise
|
|
598
656
|
`scripts/release.ts` with every child process mocked: they never run Git, npm,
|
|
@@ -608,11 +666,11 @@ mise run test:live:codex
|
|
|
608
666
|
```
|
|
609
667
|
|
|
610
668
|
The task obtains the local Codex bearer token and runs the tests with
|
|
611
|
-
`gpt-5.6-luna`, `gpt-6-sol`, and `gpt-6-
|
|
612
|
-
It also packs the extension and loads that archive through the shipped Pi
|
|
613
|
-
0.
|
|
669
|
+
`gpt-5.6-luna`, `gpt-6-sol`, `gpt-6-luna`, and `gpt-6.1-sol` at medium reasoning
|
|
670
|
+
effort. It also packs the extension and loads that archive through the shipped Pi
|
|
671
|
+
0.99.1 CLI. Ordinary Responses and Responses Lite tests exercise tool calls,
|
|
614
672
|
prompt reload, native compaction, and persisted-session resume against Codex.
|
|
615
|
-
All
|
|
673
|
+
All four models use standard reasoning mode. SDK tests verify Responses Lite
|
|
616
674
|
WebSocket history, prewarming, continuation, and the built-in read tool.
|
|
617
675
|
CLI tests also execute the built-in read tool after resume.
|
|
618
676
|
Test credentials stay in memory and child-process environments. Test sessions
|
|
@@ -626,9 +684,9 @@ The packaged-CLI test selects its archive and executable as follows:
|
|
|
626
684
|
existing regular file that `tar` can list, and an empty, missing, directory,
|
|
627
685
|
or invalid value fails the test instead of falling back to a fresh pack.
|
|
628
686
|
- `PI_CODEX_CLI_PATH` selects another Pi `cli.js`; the default is this
|
|
629
|
-
repository's Pi 0.
|
|
630
|
-
executable reports version 0.
|
|
631
|
-
is run against. The supported range is `>=0.
|
|
687
|
+
repository's Pi 0.99.1 dependency. The test asserts that the selected
|
|
688
|
+
executable reports version 0.99.1, the only Pi version the packaged CLI test
|
|
689
|
+
is run against. The supported range is `>=0.99.1 <0.100.0`.
|
|
632
690
|
- Each Pi child process receives `PI_PACKAGE_DIR` bound to the selected
|
|
633
691
|
executable's package directory, so the runtime under test reads its own
|
|
634
692
|
metadata.
|
|
@@ -59,6 +59,7 @@ export { formatBackgroundProcesses } from "./background-process-browser.ts";
|
|
|
59
59
|
export type CommandToolsApi = Pick<ExtensionAPI, "on" | "registerCommand" | "registerTool">;
|
|
60
60
|
|
|
61
61
|
export type CommandToolsController = {
|
|
62
|
+
hasPersistentSessions: () => boolean;
|
|
62
63
|
terminateUnifiedExecSessions: () => void;
|
|
63
64
|
};
|
|
64
65
|
|
|
@@ -352,6 +353,7 @@ export default function registerCommandTools(
|
|
|
352
353
|
pi.on("session_shutdown", () => manager.terminateAll());
|
|
353
354
|
|
|
354
355
|
return {
|
|
356
|
+
hasPersistentSessions: () => manager.activeSessionCount() > 0,
|
|
355
357
|
terminateUnifiedExecSessions() {
|
|
356
358
|
manager.terminateAll().catch((error: unknown) => {
|
|
357
359
|
console.error("Could not terminate unified exec sessions.", error);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { isBoolean, isNumber, nodeErrorCode } from "./value-contracts.ts";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
-
import {
|
|
5
|
-
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { join } from "node:path";
|
|
6
4
|
import { CONFIG_DIR_NAME, getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
7
5
|
import type { Static } from "typebox";
|
|
8
6
|
import { Value } from "typebox/value";
|
|
9
|
-
import { isObject
|
|
7
|
+
import { isObject } from "./codex-protocol.ts";
|
|
10
8
|
|
|
11
9
|
export const WEB_SEARCH_MODE_SCHEMA = {
|
|
12
10
|
enum: ["disabled", "cached", "indexed", "live"],
|
|
@@ -465,55 +463,3 @@ export function withoutEnvironmentOverrides(
|
|
|
465
463
|
}
|
|
466
464
|
return result;
|
|
467
465
|
}
|
|
468
|
-
|
|
469
|
-
async function readWritableConfig(filePath: string): Promise<JsonRecord> {
|
|
470
|
-
try {
|
|
471
|
-
const value: unknown = JSON.parse(await readFile(filePath, "utf8"));
|
|
472
|
-
if (!isObject(value)) throw new Error("the root value must be a JSON object");
|
|
473
|
-
return value;
|
|
474
|
-
} catch (error) {
|
|
475
|
-
if (nodeErrorCode(error) === "ENOENT") return {};
|
|
476
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
477
|
-
throw new Error(`Cannot update ${filePath}: ${detail}`, { cause: error });
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/**
|
|
482
|
-
* Merge known setting changes into the dedicated extension file. Unknown keys
|
|
483
|
-
* are retained, and an invalid existing file is never overwritten.
|
|
484
|
-
*/
|
|
485
|
-
export async function saveConfig(
|
|
486
|
-
cwd: string,
|
|
487
|
-
projectTrusted: boolean,
|
|
488
|
-
patch: ConfigLayer,
|
|
489
|
-
): Promise<string> {
|
|
490
|
-
const filePath = writableConfigPath(cwd, projectTrusted);
|
|
491
|
-
const current = await readWritableConfig(filePath);
|
|
492
|
-
const next = { ...current, ...patch };
|
|
493
|
-
const directory = dirname(filePath);
|
|
494
|
-
const temporaryPath = join(
|
|
495
|
-
directory,
|
|
496
|
-
`.${basename(filePath)}.${process.pid}.${randomUUID()}.tmp`,
|
|
497
|
-
);
|
|
498
|
-
|
|
499
|
-
await mkdir(directory, { recursive: true });
|
|
500
|
-
const existingMode = await stat(filePath)
|
|
501
|
-
.then((metadata) => metadata.mode & 0o777)
|
|
502
|
-
.catch((error: unknown) => {
|
|
503
|
-
if (nodeErrorCode(error) === "ENOENT") return 0o600;
|
|
504
|
-
throw error;
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
try {
|
|
508
|
-
await writeFile(temporaryPath, `${JSON.stringify(next, null, 2)}\n`, {
|
|
509
|
-
encoding: "utf8",
|
|
510
|
-
flag: "wx",
|
|
511
|
-
mode: existingMode,
|
|
512
|
-
});
|
|
513
|
-
await rename(temporaryPath, filePath);
|
|
514
|
-
} finally {
|
|
515
|
-
await rm(temporaryPath, { force: true });
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
return filePath;
|
|
519
|
-
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type ExtensionContext,
|
|
5
5
|
type ReadonlyFooterDataProvider,
|
|
6
6
|
type SessionEntry,
|
|
7
|
+
type SessionManager,
|
|
7
8
|
} from "@earendil-works/pi-coding-agent";
|
|
8
9
|
import type { Component } from "@earendil-works/pi-tui";
|
|
9
10
|
import type { CodexCompatConfig } from "./config.ts";
|
|
@@ -69,14 +70,23 @@ export function footerModel(
|
|
|
69
70
|
return { ...model, id, reasoning: false };
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
/**
|
|
74
|
+
* The part of Pi's `AgentSession` that `FooterComponent` reads. Pi constructs the
|
|
75
|
+
* footer with its own session, so the compiler cannot check this adapter against
|
|
76
|
+
* the footer's actual reads; the packaged TUI test renders it through Pi.
|
|
77
|
+
*/
|
|
72
78
|
interface FooterSessionAdapter {
|
|
73
79
|
readonly state: {
|
|
74
80
|
model: Model<Api> | undefined;
|
|
75
81
|
thinkingLevel: string;
|
|
76
82
|
};
|
|
83
|
+
/** Pi keys its cached session statistics on this identity. */
|
|
84
|
+
readonly model: Model<Api> | undefined;
|
|
85
|
+
/** Extensions cannot observe virtual-model routing, so the footer omits it. */
|
|
86
|
+
readonly routedModel: undefined;
|
|
77
87
|
sessionManager: Pick<
|
|
78
|
-
|
|
79
|
-
"getEntries" | "getCwd" | "getSessionName"
|
|
88
|
+
SessionManager,
|
|
89
|
+
"getEntries" | "getEntryCount" | "getCwd" | "getLeafId" | "getSessionId" | "getSessionName"
|
|
80
90
|
>;
|
|
81
91
|
getContextUsage: () => ReturnType<ExtensionContext["getContextUsage"]>;
|
|
82
92
|
modelRuntime: {
|
|
@@ -190,13 +200,20 @@ class CachedFooterSession implements FooterSessionAdapter {
|
|
|
190
200
|
|
|
191
201
|
readonly sessionManager: FooterSessionAdapter["sessionManager"];
|
|
192
202
|
readonly modelRuntime: FooterSessionAdapter["modelRuntime"];
|
|
203
|
+
readonly routedModel = undefined;
|
|
193
204
|
|
|
194
205
|
constructor(ctx: FooterContext, resolveConfig: ConfigResolver) {
|
|
195
206
|
this.ctx = ctx;
|
|
196
207
|
this.resolveConfig = resolveConfig;
|
|
208
|
+
// Pi's footer caches its statistics by session id, leaf id, entry count, and
|
|
209
|
+
// model. The aggregated snapshot is keyed by the same session and leaf, so
|
|
210
|
+
// both caches refresh together.
|
|
197
211
|
this.sessionManager = {
|
|
198
212
|
getEntries: () => this.getSnapshot().entries,
|
|
213
|
+
getEntryCount: () => this.getSnapshot().entries.length,
|
|
199
214
|
getCwd: () => ctx.sessionManager.getCwd(),
|
|
215
|
+
getLeafId: () => ctx.sessionManager.getLeafId(),
|
|
216
|
+
getSessionId: () => ctx.sessionManager.getSessionId(),
|
|
200
217
|
getSessionName: () => this.getSnapshot().displayName,
|
|
201
218
|
};
|
|
202
219
|
this.modelRuntime = {
|
|
@@ -220,6 +237,10 @@ class CachedFooterSession implements FooterSessionAdapter {
|
|
|
220
237
|
};
|
|
221
238
|
}
|
|
222
239
|
|
|
240
|
+
get model(): Model<Api> | undefined {
|
|
241
|
+
return selectedRegistryModel(this.ctx);
|
|
242
|
+
}
|
|
243
|
+
|
|
223
244
|
get state(): FooterSessionAdapter["state"] {
|
|
224
245
|
const model = selectedRegistryModel(this.ctx);
|
|
225
246
|
return {
|
|
@@ -12,7 +12,7 @@ import registerOutputLimitContinuation, {
|
|
|
12
12
|
} from "./output-limit-continuation.ts";
|
|
13
13
|
import registerRemoteCompaction, { remoteCompactionApi } from "./remote-compaction.ts";
|
|
14
14
|
import registerCodexRequestOptions from "./request-options.ts";
|
|
15
|
-
import registerCodexSettings from "./settings-pane.ts";
|
|
15
|
+
import registerCodexSettings, { loadSessionConfig } from "./settings-pane.ts";
|
|
16
16
|
import registerCodexThreadLineage, { codexThreadLineageApi } from "./codex-thread-lineage.ts";
|
|
17
17
|
import registerCodexTools, { syncCodexTools } from "./tools.ts";
|
|
18
18
|
|
|
@@ -26,8 +26,11 @@ export {
|
|
|
26
26
|
export default function registerOpenAICodexCompat(pi: ExtensionAPI): void {
|
|
27
27
|
requirePiTranscriptRuntime(piAi, piCodingAgent);
|
|
28
28
|
let activeConfig: CodexCompatConfig | undefined;
|
|
29
|
+
let sessionContext: Parameters<typeof loadSessionConfig>[0] | undefined;
|
|
29
30
|
const resolveConfig = (ctx: ConfigContext): CodexCompatConfig => {
|
|
30
|
-
activeConfig ??=
|
|
31
|
+
activeConfig ??= sessionContext
|
|
32
|
+
? loadSessionConfig(sessionContext)
|
|
33
|
+
: loadConfig(ctx.cwd, ctx.isProjectTrusted());
|
|
31
34
|
return activeConfig;
|
|
32
35
|
};
|
|
33
36
|
const resolveToolBackground = () => activeConfig?.toolBackground ?? DEFAULT_CONFIG.toolBackground;
|
|
@@ -37,7 +40,9 @@ export default function registerOpenAICodexCompat(pi: ExtensionAPI): void {
|
|
|
37
40
|
activeConfig?.applyPatchDiagnostics ?? DEFAULT_CONFIG.applyPatchDiagnostics;
|
|
38
41
|
|
|
39
42
|
pi.on("session_start", (event, ctx) => {
|
|
40
|
-
|
|
43
|
+
sessionContext = ctx;
|
|
44
|
+
activeConfig = undefined;
|
|
45
|
+
activeConfig = resolveConfig(ctx);
|
|
41
46
|
installCodexFooter(ctx, resolveConfig);
|
|
42
47
|
if (event.reason !== "reload" && ctx.mode === "tui") {
|
|
43
48
|
ctx.ui.notify("pi-openai-codex-compat loaded · /codex-settings", "info");
|
|
@@ -60,6 +65,7 @@ export default function registerOpenAICodexCompat(pi: ExtensionAPI): void {
|
|
|
60
65
|
registerCodexModelPolicy(modelPolicy, resolveConfig, commandTools);
|
|
61
66
|
registerCodexSettings(pi, {
|
|
62
67
|
getConfig: resolveConfig,
|
|
68
|
+
hasPersistentSessions: commandTools.hasPersistentSessions,
|
|
63
69
|
onChange(config, ctx) {
|
|
64
70
|
activeConfig = config;
|
|
65
71
|
codexProvider.updateSessionConfig(ctx.sessionId, config);
|
|
@@ -24,7 +24,7 @@ export const TRANSCRIPT_APIS = [
|
|
|
24
24
|
*/
|
|
25
25
|
export const SESSION_APIS = ["buildSessionProjection"] as const;
|
|
26
26
|
|
|
27
|
-
export const REQUIRED_PI = "Pi 0.
|
|
27
|
+
export const REQUIRED_PI = "Pi 0.99.x";
|
|
28
28
|
|
|
29
29
|
/** Check the loaded host, not package metadata that PI_PACKAGE_DIR can override. */
|
|
30
30
|
export function requirePiTranscriptRuntime(
|