pi-openai-toolkit 0.20.3 → 0.20.4
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/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Remote context windows, Responses compaction, web search, image generation, and
|
|
|
9
9
|
|
|
10
10
|
## Install and start
|
|
11
11
|
|
|
12
|
-
Requires Node.js **22.19.0+** and Pi **0.87.0+**. Current development dependencies pin Pi **0.
|
|
12
|
+
Requires Node.js **22.19.0+** and Pi **0.87.0+**. Current development dependencies pin Pi **1.0.0**; backend features also depend on the selected model, API, and account access.
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
pi install npm:pi-openai-toolkit
|
package/README.zh.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-openai-toolkit",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -129,10 +129,10 @@
|
|
|
129
129
|
"@earendil-works/pi-tui": ">=0.87.0"
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
|
-
"@earendil-works/pi-agent-core": "0.
|
|
133
|
-
"@earendil-works/pi-ai": "0.
|
|
134
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
135
|
-
"@earendil-works/pi-tui": "0.
|
|
132
|
+
"@earendil-works/pi-agent-core": "1.0.0",
|
|
133
|
+
"@earendil-works/pi-ai": "1.0.0",
|
|
134
|
+
"@earendil-works/pi-coding-agent": "1.0.0",
|
|
135
|
+
"@earendil-works/pi-tui": "1.0.0",
|
|
136
136
|
"@types/node": "24.12.4",
|
|
137
137
|
"bun": "1.2.23",
|
|
138
138
|
"typescript": "5.9.3"
|
|
@@ -5,6 +5,7 @@ import { resolveToolkitConfig, type ResolvedToolkitConfig } from "../config";
|
|
|
5
5
|
import { isAutoModeEligible } from "../auto-mode/policy";
|
|
6
6
|
import { protectAutoModeSelection } from "../auto-mode/model-selection-guard";
|
|
7
7
|
import { parseModelSpec } from "../runtime";
|
|
8
|
+
import { THINKING_LEVELS } from "../types";
|
|
8
9
|
import { resolveCodexContextProvider } from "./codex-provider";
|
|
9
10
|
import { findLatestNotesCheckpointSinceBoundary, findLatestWindowBoundaryEntry, type CodexContextWindowManager } from "./window-manager";
|
|
10
11
|
import { isNonEmptyString, isRecord, type CodexContextProvider, type ContextWindowIdentity } from "./types";
|
|
@@ -14,7 +15,6 @@ export const MANUAL_COMPACT_ENTRY_TYPE = "pi-openai-toolkit:manual-compact";
|
|
|
14
15
|
const PHASES = ["requested", "switching", "checkpointing", "rollover-scheduled", "restoring", "restore-needed", "completed", "failed", "cancelled", "superseded"] as const;
|
|
15
16
|
type Phase = typeof PHASES[number];
|
|
16
17
|
const TERMINAL = new Set<Phase>(["completed", "failed", "cancelled", "superseded"]);
|
|
17
|
-
const THINKING = new Set<string>(["off", "minimal", "low", "medium", "high", "xhigh"]);
|
|
18
18
|
const REQUIRED_TOOLS = ["notes", "history", "new_context", "get_context_remaining"];
|
|
19
19
|
|
|
20
20
|
/** Non-LLM recovery state. No auth, model object, transcript or note text belongs here. */
|
|
@@ -36,7 +36,7 @@ export function decodeManualCompactRecord(value: unknown): ManualCompactRecord |
|
|
|
36
36
|
|| ![value.operationId, value.sessionId, value.sourceWindowId, value.anchorId].every(isNonEmptyString)
|
|
37
37
|
|| typeof value.originalModel !== "string" || !parseModelSpec(value.originalModel)
|
|
38
38
|
|| typeof value.targetModel !== "string" || !parseModelSpec(value.targetModel)
|
|
39
|
-
|| typeof value.originalThinking !== "string" || !
|
|
39
|
+
|| typeof value.originalThinking !== "string" || !(THINKING_LEVELS as readonly string[]).includes(value.originalThinking)
|
|
40
40
|
|| !PHASES.includes(value.phase as Phase)
|
|
41
41
|
|| (value.targetWindowId !== undefined && !isNonEmptyString(value.targetWindowId))) return undefined;
|
|
42
42
|
return value as ManualCompactRecord;
|
|
@@ -4,7 +4,22 @@ import { loadToolkitConfig, resolveToolkitConfig } from "../config";
|
|
|
4
4
|
import { createResponsesWebSocketProvider } from "./transport";
|
|
5
5
|
|
|
6
6
|
const SOURCE_ID = "pi-openai-toolkit:openai-responses-websocket";
|
|
7
|
-
|
|
7
|
+
type ApiProviderInternal = NonNullable<ReturnType<typeof getApiProvider>>;
|
|
8
|
+
type ResponsesWebSocketRegistryState = {
|
|
9
|
+
baseProvider?: ApiProviderInternal;
|
|
10
|
+
installedProvider?: ApiProviderInternal;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const REGISTRY_STATE_KEY = Symbol.for("pi-openai-toolkit.responses-websocket.registry");
|
|
14
|
+
|
|
15
|
+
function registryState(): ResponsesWebSocketRegistryState {
|
|
16
|
+
const global = globalThis as typeof globalThis & { [key: symbol]: ResponsesWebSocketRegistryState | undefined };
|
|
17
|
+
return global[REGISTRY_STATE_KEY] ??= {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function rememberInstalledProvider(state: ResponsesWebSocketRegistryState): void {
|
|
21
|
+
state.installedProvider = getApiProvider("openai-responses");
|
|
22
|
+
}
|
|
8
23
|
|
|
9
24
|
/**
|
|
10
25
|
* Add the transport branch at the API-adapter boundary instead of registering
|
|
@@ -15,16 +30,31 @@ let baseProvider: ReturnType<typeof getApiProvider>;
|
|
|
15
30
|
export function installResponsesWebSocketTransport(
|
|
16
31
|
loadConfig: typeof loadToolkitConfig = loadToolkitConfig,
|
|
17
32
|
): boolean {
|
|
33
|
+
const state = registryState();
|
|
34
|
+
const currentProvider = getApiProvider("openai-responses");
|
|
35
|
+
const ownsCurrentProvider = currentProvider !== undefined && currentProvider === state.installedProvider;
|
|
36
|
+
if (currentProvider && !ownsCurrentProvider) state.baseProvider = currentProvider;
|
|
37
|
+
const baseProvider = state.baseProvider ?? currentProvider;
|
|
38
|
+
const resolved = resolveToolkitConfig(loadConfig());
|
|
39
|
+
|
|
18
40
|
// Re-installation can happen during Pi reloads. Remove only this extension's prior
|
|
19
|
-
// adapter so a config change cannot leave a stale enabled wrapper behind.
|
|
41
|
+
// adapter so a config change cannot leave a stale enabled wrapper behind. When the
|
|
42
|
+
// current entry is ours, the saved base is re-registered as a pass-through below
|
|
43
|
+
// for disabled config; this keeps the compat registry populated without resetting
|
|
44
|
+
// providers owned by other extensions.
|
|
20
45
|
unregisterApiProviders(SOURCE_ID);
|
|
21
|
-
|
|
22
|
-
|
|
46
|
+
state.installedProvider = undefined;
|
|
47
|
+
const enabled = resolved.policy.responsesWebSocket.enabled && !resolved.invalidFeatures.includes("responsesWebSocket");
|
|
48
|
+
if (!enabled) {
|
|
49
|
+
if ((ownsCurrentProvider || !currentProvider) && baseProvider) {
|
|
50
|
+
registerApiProvider(baseProvider, SOURCE_ID);
|
|
51
|
+
rememberInstalledProvider(state);
|
|
52
|
+
}
|
|
23
53
|
return false;
|
|
24
54
|
}
|
|
25
|
-
baseProvider ??= getApiProvider("openai-responses");
|
|
26
55
|
if (!baseProvider) return false;
|
|
27
56
|
registerApiProvider(createResponsesWebSocketProvider(baseProvider, true), SOURCE_ID);
|
|
57
|
+
rememberInstalledProvider(state);
|
|
28
58
|
return true;
|
|
29
59
|
}
|
|
30
60
|
|
package/src/runtime.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { Api, Message, Model, ModelThinkingLevel, ProviderHeaders } from "@earendil-works/pi-ai";
|
|
3
|
-
import type
|
|
3
|
+
import { convertToLlm, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { isExactModelAllowed } from "./model-scope";
|
|
5
5
|
import {
|
|
6
6
|
CODEX_AFFINITY_SCOPE,
|