@pasko70/pibo 1.7.8 → 1.7.9
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.
|
Binary file
|
|
Binary file
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { getModels } from "@mariozechner/pi-ai";
|
|
2
|
+
import { getOAuthProvider } from "@mariozechner/pi-ai/oauth";
|
|
2
3
|
export const OPENAI_PROVIDER_ID = "openai";
|
|
3
4
|
export const OPENAI_RESPONSES_API = "openai-responses";
|
|
4
5
|
export const OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
5
6
|
export const OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
|
6
|
-
const
|
|
7
|
+
export const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
|
|
8
|
+
export const OPENAI_CODEX_RESPONSES_API = "openai-codex-responses";
|
|
9
|
+
export const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
10
|
+
const OPENAI_GPT_56_CONTEXT_WINDOW = 1_050_000;
|
|
11
|
+
const OPENAI_CODEX_GPT_56_CONTEXT_WINDOW = 272_000;
|
|
7
12
|
const GPT_56_MAX_TOKENS = 128_000;
|
|
8
|
-
// Register GPT-5.6 on the normal OpenAI API provider only.
|
|
9
|
-
// This keeps Pibo on the existing token-plan path (OPENAI_API_KEY) and does not
|
|
10
|
-
// route these models through ChatGPT/Codex OAuth (`openai-codex`).
|
|
11
13
|
export const OPENAI_GPT_56_MODELS = [
|
|
12
14
|
{
|
|
13
15
|
id: "gpt-5.6",
|
|
@@ -30,62 +32,122 @@ export const OPENAI_GPT_56_MODELS = [
|
|
|
30
32
|
cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 1.25 },
|
|
31
33
|
},
|
|
32
34
|
];
|
|
35
|
+
const OPENAI_GPT_56_MODEL_IDS = new Set(OPENAI_GPT_56_MODELS.map((model) => model.id));
|
|
33
36
|
export function getBuiltInOpenAiModels() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
37
|
+
return getBuiltInProviderModels(OPENAI_PROVIDER_ID);
|
|
38
|
+
}
|
|
39
|
+
export function getBuiltInOpenAiCodexModels() {
|
|
40
|
+
return getBuiltInProviderModels(OPENAI_CODEX_PROVIDER_ID);
|
|
40
41
|
}
|
|
41
42
|
export function buildOpenAiGpt56Models(baseModels = getBuiltInOpenAiModels()) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
return buildProviderGpt56Models({
|
|
44
|
+
providerId: OPENAI_PROVIDER_ID,
|
|
45
|
+
api: OPENAI_RESPONSES_API,
|
|
46
|
+
baseUrl: OPENAI_BASE_URL,
|
|
47
|
+
contextWindow: OPENAI_GPT_56_CONTEXT_WINDOW,
|
|
48
|
+
thinkingLevelMap: { off: null, xhigh: "xhigh" },
|
|
49
|
+
baseModels,
|
|
50
|
+
modelCost: (model) => model.cost,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function buildOpenAiCodexGpt56Models(baseModels = getBuiltInOpenAiCodexModels()) {
|
|
54
|
+
return buildProviderGpt56Models({
|
|
55
|
+
providerId: OPENAI_CODEX_PROVIDER_ID,
|
|
56
|
+
api: OPENAI_CODEX_RESPONSES_API,
|
|
57
|
+
baseUrl: OPENAI_CODEX_BASE_URL,
|
|
58
|
+
contextWindow: OPENAI_CODEX_GPT_56_CONTEXT_WINDOW,
|
|
59
|
+
thinkingLevelMap: { xhigh: "xhigh", minimal: "low" },
|
|
60
|
+
baseModels,
|
|
61
|
+
modelCost: (model) => ({ ...model.cost, cacheWrite: 0 }),
|
|
62
|
+
});
|
|
56
63
|
}
|
|
57
64
|
export function registerOpenAiGpt56Models(modelRegistry, options = {}) {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const added = OPENAI_GPT_56_MODELS.filter((model) => !baseOpenAiIds.has(model.id)).length;
|
|
65
|
+
const baseOpenAiModels = options.baseOpenAiModels ?? getBuiltInOpenAiModels();
|
|
66
|
+
const openAiModels = buildOpenAiGpt56Models(baseOpenAiModels);
|
|
67
|
+
const openAiAdded = countMissingGpt56Models(baseOpenAiModels, OPENAI_PROVIDER_ID);
|
|
62
68
|
modelRegistry.registerProvider(OPENAI_PROVIDER_ID, {
|
|
63
69
|
baseUrl: OPENAI_BASE_URL,
|
|
64
70
|
api: OPENAI_RESPONSES_API,
|
|
65
71
|
apiKey: OPENAI_API_KEY_ENV,
|
|
66
|
-
models,
|
|
72
|
+
models: openAiModels,
|
|
73
|
+
});
|
|
74
|
+
const baseOpenAiCodexModels = options.baseOpenAiCodexModels ?? getBuiltInOpenAiCodexModels();
|
|
75
|
+
const openAiCodexModels = buildOpenAiCodexGpt56Models(baseOpenAiCodexModels);
|
|
76
|
+
const openAiCodexAdded = countMissingGpt56Models(baseOpenAiCodexModels, OPENAI_CODEX_PROVIDER_ID);
|
|
77
|
+
const openAiCodexOAuth = getOpenAiCodexOAuthConfig();
|
|
78
|
+
modelRegistry.registerProvider(OPENAI_CODEX_PROVIDER_ID, {
|
|
79
|
+
name: openAiCodexOAuth.name,
|
|
80
|
+
baseUrl: OPENAI_CODEX_BASE_URL,
|
|
81
|
+
api: OPENAI_CODEX_RESPONSES_API,
|
|
82
|
+
oauth: openAiCodexOAuth,
|
|
83
|
+
models: openAiCodexModels,
|
|
67
84
|
});
|
|
68
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
registered: true,
|
|
87
|
+
providers: 2,
|
|
88
|
+
models: openAiModels.length + openAiCodexModels.length,
|
|
89
|
+
added: openAiAdded + openAiCodexAdded,
|
|
90
|
+
};
|
|
69
91
|
}
|
|
70
92
|
export function findOpenAiGpt56Model(modelRegistry, model) {
|
|
71
|
-
if (model?.provider
|
|
93
|
+
if (!model?.provider || !model.id)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (model.provider !== OPENAI_PROVIDER_ID && model.provider !== OPENAI_CODEX_PROVIDER_ID)
|
|
72
96
|
return undefined;
|
|
73
|
-
if (!
|
|
97
|
+
if (!OPENAI_GPT_56_MODEL_IDS.has(model.id))
|
|
74
98
|
return undefined;
|
|
75
|
-
return modelRegistry.find(
|
|
99
|
+
return modelRegistry.find(model.provider, model.id);
|
|
76
100
|
}
|
|
77
|
-
function
|
|
101
|
+
function getBuiltInProviderModels(providerId) {
|
|
102
|
+
try {
|
|
103
|
+
return getModels(providerId);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function buildProviderGpt56Models(options) {
|
|
110
|
+
const providerBaseModels = options.baseModels
|
|
111
|
+
.filter((model) => model.provider === options.providerId)
|
|
112
|
+
.map(cloneModel);
|
|
113
|
+
const existingIds = new Set(providerBaseModels.map((model) => model.id));
|
|
114
|
+
const additions = OPENAI_GPT_56_MODELS
|
|
115
|
+
.filter((model) => !existingIds.has(model.id))
|
|
116
|
+
.map((model) => openAiGpt56ModelToRegistryModel(model, options));
|
|
117
|
+
return [...providerBaseModels, ...additions];
|
|
118
|
+
}
|
|
119
|
+
function countMissingGpt56Models(baseModels, providerId) {
|
|
120
|
+
const existingIds = new Set(baseModels.filter((model) => model.provider === providerId).map((model) => model.id));
|
|
121
|
+
return OPENAI_GPT_56_MODELS.filter((model) => !existingIds.has(model.id)).length;
|
|
122
|
+
}
|
|
123
|
+
function cloneModel(model) {
|
|
124
|
+
return {
|
|
125
|
+
...model,
|
|
126
|
+
input: [...model.input],
|
|
127
|
+
cost: { ...model.cost },
|
|
128
|
+
headers: model.headers ? { ...model.headers } : undefined,
|
|
129
|
+
compat: model.compat ? { ...model.compat } : undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function openAiGpt56ModelToRegistryModel(model, options) {
|
|
78
133
|
return {
|
|
79
134
|
id: model.id,
|
|
80
135
|
name: model.name,
|
|
81
|
-
api:
|
|
82
|
-
provider:
|
|
83
|
-
baseUrl:
|
|
136
|
+
api: options.api,
|
|
137
|
+
provider: options.providerId,
|
|
138
|
+
baseUrl: options.baseUrl,
|
|
84
139
|
reasoning: true,
|
|
85
|
-
thinkingLevelMap:
|
|
140
|
+
thinkingLevelMap: options.thinkingLevelMap,
|
|
86
141
|
input: ["text", "image"],
|
|
87
|
-
cost:
|
|
88
|
-
contextWindow:
|
|
142
|
+
cost: options.modelCost(model),
|
|
143
|
+
contextWindow: options.contextWindow,
|
|
89
144
|
maxTokens: GPT_56_MAX_TOKENS,
|
|
90
145
|
};
|
|
91
146
|
}
|
|
147
|
+
function getOpenAiCodexOAuthConfig() {
|
|
148
|
+
const provider = getOAuthProvider(OPENAI_CODEX_PROVIDER_ID);
|
|
149
|
+
if (!provider)
|
|
150
|
+
throw new Error("OpenAI Codex OAuth provider is unavailable.");
|
|
151
|
+
const { id: _id, ...oauth } = provider;
|
|
152
|
+
return oauth;
|
|
153
|
+
}
|