pi-openai-codex-compat 0.0.4 → 0.0.6
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 +20 -0
- package/README.md +9 -2
- package/extensions/index.ts +2 -0
- package/extensions/openai-codex-compat/codex-protocol.ts +7 -3
- package/extensions/openai-codex-compat/codex-stream.ts +1 -1
- package/extensions/openai-codex-compat/codex-transport.ts +1 -1
- package/extensions/openai-codex-compat/footer.ts +9 -0
- package/extensions/openai-codex-compat/remote-compaction.ts +4 -6
- package/extensions/openai-codex-compat/tool-runtime.ts +2 -2
- package/extensions/openai-codex-compat/vendor/pi-ai/README.md +1 -1
- package/extensions/openai-codex-compat/vendor/pi-ai/openai-responses-serialization.ts +1 -1
- package/package.json +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.0.6 - 2026-08-10
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Add `npm run pack:dry` to inspect the npm package contents before release.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Require Pi 0.84.x, use Pi 0.84.1 as the development integration baseline, and preserve Pi 0.84 header removals across Codex tools and native compaction.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Support Pi 0.84's subscription-aware default footer without crashing during startup.
|
|
18
|
+
|
|
19
|
+
## 0.0.5 - 2026-08-07
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Avoid repeating the extension name in Pi's startup display.
|
|
24
|
+
|
|
5
25
|
## 0.0.4 - 2026-08-07
|
|
6
26
|
|
|
7
27
|
### Added
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Pi provides the Codex OAuth flow and model catalog. At session start, this packa
|
|
|
20
20
|
## Requirements
|
|
21
21
|
|
|
22
22
|
- Node.js 22.19 or newer
|
|
23
|
-
- Pi `>=0.
|
|
23
|
+
- Pi `>=0.84.0 <0.85.0`
|
|
24
24
|
- An OpenAI Codex login in Pi
|
|
25
25
|
|
|
26
26
|
Authenticate through Pi if needed:
|
|
@@ -379,6 +379,7 @@ mise install
|
|
|
379
379
|
npm install
|
|
380
380
|
npm run check
|
|
381
381
|
npm test
|
|
382
|
+
npm run pack:dry
|
|
382
383
|
```
|
|
383
384
|
|
|
384
385
|
Run the credentialed Pi/Codex integration tests separately. They load the real
|
|
@@ -393,7 +394,13 @@ mise run test:live:codex
|
|
|
393
394
|
The task obtains the local Codex bearer token and runs the tests with
|
|
394
395
|
`gpt-5.6-luna` at medium reasoning effort.
|
|
395
396
|
|
|
396
|
-
The
|
|
397
|
+
The public package entrypoint is `extensions/index.ts`; implementation modules remain under
|
|
398
|
+
`extensions/openai-codex-compat/`. The focused Pi AI serializer copy lives under
|
|
399
|
+
`extensions/openai-codex-compat/vendor/pi-ai/`. The custom Codex provider transport and stream
|
|
400
|
+
parser are focused adaptations of Pi AI's corresponding implementation. Equivalence and protocol
|
|
401
|
+
tests cover canonical serialization, native namespace round-trips, raw native replay, sibling Codex
|
|
402
|
+
JSON endpoints, SSE request behavior, WebSocket reuse, grammar tools, image results, standalone
|
|
403
|
+
search, and compaction continuation.
|
|
397
404
|
|
|
398
405
|
## Release staging
|
|
399
406
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calculateCost, type Model, type Usage } from "@earendil-works/pi-ai";
|
|
1
|
+
import { calculateCost, type Model, type ProviderHeaders, type Usage } from "@earendil-works/pi-ai";
|
|
2
2
|
|
|
3
3
|
export const REMOTE_COMPACTION_BETA = "remote_compaction_v2";
|
|
4
4
|
export const RETAINED_CONTEXT_BUDGET = 64_000;
|
|
@@ -327,10 +327,14 @@ function accountIdFromToken(token: string): string {
|
|
|
327
327
|
|
|
328
328
|
export function remoteCompactionHeaders(options: {
|
|
329
329
|
token: string;
|
|
330
|
-
providerHeaders?:
|
|
330
|
+
providerHeaders?: ProviderHeaders | undefined;
|
|
331
331
|
sessionId: string;
|
|
332
332
|
}): Headers {
|
|
333
|
-
const headers = new Headers(
|
|
333
|
+
const headers = new Headers();
|
|
334
|
+
for (const [name, value] of Object.entries(options.providerHeaders ?? {})) {
|
|
335
|
+
if (value === null) headers.delete(name);
|
|
336
|
+
else headers.set(name, value);
|
|
337
|
+
}
|
|
334
338
|
headers.set("authorization", `Bearer ${options.token}`);
|
|
335
339
|
headers.set("chatgpt-account-id", accountIdFromToken(options.token));
|
|
336
340
|
headers.set("originator", "pi");
|
|
@@ -14,7 +14,7 @@ import { isObject, type JsonRecord } from "./codex-protocol.ts";
|
|
|
14
14
|
import { CODEX_NAMESPACED_TOOL_NAMES, namespacedToolCallName } from "./namespaced-tools.ts";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Focused adaptation of @earendil-works/pi-ai@0.
|
|
17
|
+
* Focused adaptation of @earendil-works/pi-ai@0.84.1
|
|
18
18
|
* src/api/openai-responses-shared.ts stream processing.
|
|
19
19
|
*/
|
|
20
20
|
|
|
@@ -21,7 +21,7 @@ import { normalizeReplayItem, stableResponsesJson } from "./responses-replay.ts"
|
|
|
21
21
|
import { applyResponsesLiteHeaders, responsesLiteSsePayload } from "./responses-lite.ts";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Focused adaptation of @earendil-works/pi-ai@0.
|
|
24
|
+
* Focused adaptation of @earendil-works/pi-ai@0.84.1
|
|
25
25
|
* src/api/openai-codex-responses.ts transport behavior.
|
|
26
26
|
*/
|
|
27
27
|
|
|
@@ -59,6 +59,15 @@ function footerSession(ctx: ExtensionContext, resolveConfig: ConfigResolver): Fo
|
|
|
59
59
|
model && model.provider === provider && ctx.modelRegistry.isUsingOAuth(model),
|
|
60
60
|
);
|
|
61
61
|
},
|
|
62
|
+
isUsingSubscription(provider: string) {
|
|
63
|
+
const model = ctx.model;
|
|
64
|
+
return Boolean(
|
|
65
|
+
model &&
|
|
66
|
+
model.provider === provider &&
|
|
67
|
+
ctx.modelRegistry.isUsingOAuth(model) &&
|
|
68
|
+
ctx.modelRegistry.getProvider(provider)?.auth.oauth?.isSubscription === true,
|
|
69
|
+
);
|
|
70
|
+
},
|
|
62
71
|
},
|
|
63
72
|
} as unknown as FooterSession;
|
|
64
73
|
}
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
SessionEntry,
|
|
7
7
|
ToolInfo,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import type { Model, OpenAICodexResponsesOptions } from "@earendil-works/pi-ai";
|
|
9
|
+
import type { Model, OpenAICodexResponsesOptions, ProviderHeaders } from "@earendil-works/pi-ai";
|
|
10
10
|
import { addRemoteCompactionFeature, type JsonRecord } from "./codex-protocol.ts";
|
|
11
11
|
import {
|
|
12
12
|
activeResponsesTools,
|
|
@@ -40,12 +40,10 @@ function appendFeatureHeader(headers: Record<string, string | null>): void {
|
|
|
40
40
|
else headers["x-codex-beta-features"] = addRemoteCompactionFeature(undefined);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function featureHeaders(headers:
|
|
44
|
-
const result:
|
|
43
|
+
function featureHeaders(headers: ProviderHeaders | undefined): ProviderHeaders {
|
|
44
|
+
const result: ProviderHeaders = { ...headers };
|
|
45
45
|
appendFeatureHeader(result);
|
|
46
|
-
return
|
|
47
|
-
Object.entries(result).filter((entry): entry is [string, string] => entry[1] !== null),
|
|
48
|
-
);
|
|
46
|
+
return result;
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
function markerSummary(): string {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext, SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { Model, ProviderHeaders } from "@earendil-works/pi-ai";
|
|
3
3
|
import { providerHistory } from "./compaction-checkpoint.ts";
|
|
4
4
|
import type { ImageDetail } from "./config.ts";
|
|
5
5
|
import type { ResponsesItem } from "./codex-protocol.ts";
|
|
@@ -7,7 +7,7 @@ import type { ResponsesItem } from "./codex-protocol.ts";
|
|
|
7
7
|
export async function codexToolAuthentication(
|
|
8
8
|
ctx: ExtensionContext,
|
|
9
9
|
model: Model<any>,
|
|
10
|
-
): Promise<{ apiKey: string; headers?:
|
|
10
|
+
): Promise<{ apiKey: string; headers?: ProviderHeaders }> {
|
|
11
11
|
const authentication = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
12
12
|
if (!authentication.ok) throw new Error(authentication.error);
|
|
13
13
|
if (!authentication.apiKey) throw new Error("OpenAI Codex authentication is unavailable.");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This directory intentionally contains only the Pi AI methods needed to serialize checkpoint and native replay history for OpenAI's Responses API. It does not contain Pi AI's complete source dependency graph.
|
|
4
4
|
|
|
5
|
-
[`openai-responses-serialization.ts`](openai-responses-serialization.ts) adapts the relevant methods from `@earendil-works/pi-ai@0.
|
|
5
|
+
[`openai-responses-serialization.ts`](openai-responses-serialization.ts) adapts the relevant methods from `@earendil-works/pi-ai@0.84.1`. Its header lists the upstream source files. Keep the behavioral equivalence test in [`test/pi-ai-serialization.test.ts`](../../../../test/pi-ai-serialization.test.ts) passing when updating the Pi dependencies.
|
|
6
6
|
|
|
7
7
|
The optional `namespacedToolNames`, `textContentItemToolResultNames`, and `toolResultImageDetail` paths are extension-owned additions. Without those options, serialization must continue to match Pi AI. `namespacedToolNames` groups only the fixed Codex allowlist into native Responses namespaces and replays namespace/member call identities. `textContentItemToolResultNames` preserves Codex tools such as `web.run` whose successful text output is transported as an `input_text` content-item array instead of Pi's usual plain string. `toolResultImageDetail` overrides the otherwise canonical `auto` detail used for image tool-result content.
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Focused copies of the methods used to serialize Pi messages for OpenAI's
|
|
16
|
-
* Responses API. Adapted from @earendil-works/pi-ai@0.
|
|
16
|
+
* Responses API. Adapted from @earendil-works/pi-ai@0.84.1:
|
|
17
17
|
*
|
|
18
18
|
* - src/api/openai-responses-shared.ts
|
|
19
19
|
* - src/api/transform-messages.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-openai-codex-compat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "OpenAI Codex compatibility for Pi with native compaction, fast mode, and Codex-optimized capabilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"url": "git+https://github.com/2h2d-co/pi-openai-codex-compat.git"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
|
-
"extensions
|
|
23
|
+
"extensions",
|
|
24
24
|
"README.md",
|
|
25
25
|
"CHANGELOG.md",
|
|
26
26
|
"LICENSE",
|
|
@@ -32,14 +32,15 @@
|
|
|
32
32
|
"check": "hk check --all --check",
|
|
33
33
|
"test": "node --test --test-concurrency=1 test/*.test.ts",
|
|
34
34
|
"test:live:codex": "PI_CODEX_LIVE_TEST=1 node --test --test-concurrency=1 test/codex-host.live.test.ts",
|
|
35
|
+
"pack:dry": "npm pack --dry-run --allow-directory=all",
|
|
35
36
|
"fmt": "oxfmt",
|
|
36
37
|
"lint": "oxlint",
|
|
37
38
|
"lint:fix": "oxlint --fix"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@earendil-works/pi-ai": "0.
|
|
41
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
42
|
-
"@earendil-works/pi-tui": "0.
|
|
41
|
+
"@earendil-works/pi-ai": "0.84.1",
|
|
42
|
+
"@earendil-works/pi-coding-agent": "0.84.1",
|
|
43
|
+
"@earendil-works/pi-tui": "0.84.1",
|
|
43
44
|
"@types/node": "22.20.1",
|
|
44
45
|
"oxfmt": "0.60.0",
|
|
45
46
|
"oxlint": "1.75.0",
|
|
@@ -48,9 +49,9 @@
|
|
|
48
49
|
"typescript": "7.0.2"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
|
-
"@earendil-works/pi-ai": ">=0.
|
|
52
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
53
|
-
"@earendil-works/pi-tui": ">=0.
|
|
52
|
+
"@earendil-works/pi-ai": ">=0.84.0 <0.85.0",
|
|
53
|
+
"@earendil-works/pi-coding-agent": ">=0.84.0 <0.85.0",
|
|
54
|
+
"@earendil-works/pi-tui": ">=0.84.0 <0.85.0",
|
|
54
55
|
"typebox": "*"
|
|
55
56
|
},
|
|
56
57
|
"engines": {
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
},
|
|
59
60
|
"pi": {
|
|
60
61
|
"extensions": [
|
|
61
|
-
"./extensions/
|
|
62
|
+
"./extensions/index.ts"
|
|
62
63
|
]
|
|
63
64
|
}
|
|
64
65
|
}
|