@oh-my-pi/pi-ai 9.2.0 → 9.2.2
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/package.json +2 -2
- package/src/models.generated.ts +105 -70
- package/src/utils/oauth/index.ts +11 -0
- package/src/utils/oauth/opencode.ts +50 -0
- package/src/utils/oauth/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-ai",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.2",
|
|
4
4
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@connectrpc/connect-node": "^2.1.1",
|
|
64
64
|
"@google/genai": "^1.38.0",
|
|
65
65
|
"@mistralai/mistralai": "^1.13.0",
|
|
66
|
-
"@oh-my-pi/pi-utils": "9.2.
|
|
66
|
+
"@oh-my-pi/pi-utils": "9.2.2",
|
|
67
67
|
"@sinclair/typebox": "^0.34.48",
|
|
68
68
|
"@smithy/node-http-handler": "^4.4.8",
|
|
69
69
|
"ajv": "^8.17.1",
|
package/src/models.generated.ts
CHANGED
|
@@ -3102,8 +3102,8 @@ export const MODELS = {
|
|
|
3102
3102
|
reasoning: false,
|
|
3103
3103
|
input: ["text"],
|
|
3104
3104
|
cost: {
|
|
3105
|
-
input: 0,
|
|
3106
|
-
output:
|
|
3105
|
+
input: 0.4,
|
|
3106
|
+
output: 2,
|
|
3107
3107
|
cacheRead: 0,
|
|
3108
3108
|
cacheWrite: 0,
|
|
3109
3109
|
},
|
|
@@ -4357,6 +4357,23 @@ export const MODELS = {
|
|
|
4357
4357
|
contextWindow: 204800,
|
|
4358
4358
|
maxTokens: 131072,
|
|
4359
4359
|
} satisfies Model<"openai-completions">,
|
|
4360
|
+
"glm-4.7-free": {
|
|
4361
|
+
id: "glm-4.7-free",
|
|
4362
|
+
name: "GLM-4.7 Free",
|
|
4363
|
+
api: "openai-completions",
|
|
4364
|
+
provider: "opencode",
|
|
4365
|
+
baseUrl: "https://opencode.ai/zen/v1",
|
|
4366
|
+
reasoning: true,
|
|
4367
|
+
input: ["text"],
|
|
4368
|
+
cost: {
|
|
4369
|
+
input: 0,
|
|
4370
|
+
output: 0,
|
|
4371
|
+
cacheRead: 0,
|
|
4372
|
+
cacheWrite: 0,
|
|
4373
|
+
},
|
|
4374
|
+
contextWindow: 204800,
|
|
4375
|
+
maxTokens: 131072,
|
|
4376
|
+
} satisfies Model<"openai-completions">,
|
|
4360
4377
|
"gpt-5": {
|
|
4361
4378
|
id: "gpt-5",
|
|
4362
4379
|
name: "GPT-5",
|
|
@@ -4555,7 +4572,24 @@ export const MODELS = {
|
|
|
4555
4572
|
cost: {
|
|
4556
4573
|
input: 0.6,
|
|
4557
4574
|
output: 3,
|
|
4558
|
-
cacheRead: 0.
|
|
4575
|
+
cacheRead: 0.08,
|
|
4576
|
+
cacheWrite: 0,
|
|
4577
|
+
},
|
|
4578
|
+
contextWindow: 262144,
|
|
4579
|
+
maxTokens: 262144,
|
|
4580
|
+
} satisfies Model<"openai-completions">,
|
|
4581
|
+
"kimi-k2.5-free": {
|
|
4582
|
+
id: "kimi-k2.5-free",
|
|
4583
|
+
name: "Kimi K2.5 Free",
|
|
4584
|
+
api: "openai-completions",
|
|
4585
|
+
provider: "opencode",
|
|
4586
|
+
baseUrl: "https://opencode.ai/zen/v1",
|
|
4587
|
+
reasoning: true,
|
|
4588
|
+
input: ["text", "image"],
|
|
4589
|
+
cost: {
|
|
4590
|
+
input: 0,
|
|
4591
|
+
output: 0,
|
|
4592
|
+
cacheRead: 0,
|
|
4559
4593
|
cacheWrite: 0,
|
|
4560
4594
|
},
|
|
4561
4595
|
contextWindow: 262144,
|
|
@@ -4578,6 +4612,23 @@ export const MODELS = {
|
|
|
4578
4612
|
contextWindow: 204800,
|
|
4579
4613
|
maxTokens: 131072,
|
|
4580
4614
|
} satisfies Model<"openai-completions">,
|
|
4615
|
+
"minimax-m2.1-free": {
|
|
4616
|
+
id: "minimax-m2.1-free",
|
|
4617
|
+
name: "MiniMax M2.1 Free",
|
|
4618
|
+
api: "anthropic-messages",
|
|
4619
|
+
provider: "opencode",
|
|
4620
|
+
baseUrl: "https://opencode.ai/zen",
|
|
4621
|
+
reasoning: true,
|
|
4622
|
+
input: ["text"],
|
|
4623
|
+
cost: {
|
|
4624
|
+
input: 0,
|
|
4625
|
+
output: 0,
|
|
4626
|
+
cacheRead: 0,
|
|
4627
|
+
cacheWrite: 0,
|
|
4628
|
+
},
|
|
4629
|
+
contextWindow: 204800,
|
|
4630
|
+
maxTokens: 131072,
|
|
4631
|
+
} satisfies Model<"anthropic-messages">,
|
|
4581
4632
|
"qwen3-coder": {
|
|
4582
4633
|
id: "qwen3-coder",
|
|
4583
4634
|
name: "Qwen3 Coder",
|
|
@@ -4595,6 +4646,23 @@ export const MODELS = {
|
|
|
4595
4646
|
contextWindow: 262144,
|
|
4596
4647
|
maxTokens: 65536,
|
|
4597
4648
|
} satisfies Model<"openai-completions">,
|
|
4649
|
+
"trinity-large-preview-free": {
|
|
4650
|
+
id: "trinity-large-preview-free",
|
|
4651
|
+
name: "Trinity Large Preview",
|
|
4652
|
+
api: "openai-completions",
|
|
4653
|
+
provider: "opencode",
|
|
4654
|
+
baseUrl: "https://opencode.ai/zen/v1",
|
|
4655
|
+
reasoning: false,
|
|
4656
|
+
input: ["text"],
|
|
4657
|
+
cost: {
|
|
4658
|
+
input: 0,
|
|
4659
|
+
output: 0,
|
|
4660
|
+
cacheRead: 0,
|
|
4661
|
+
cacheWrite: 0,
|
|
4662
|
+
},
|
|
4663
|
+
contextWindow: 131072,
|
|
4664
|
+
maxTokens: 131072,
|
|
4665
|
+
} satisfies Model<"openai-completions">,
|
|
4598
4666
|
},
|
|
4599
4667
|
"openrouter": {
|
|
4600
4668
|
"ai21/jamba-large-1.7": {
|
|
@@ -5350,23 +5418,6 @@ export const MODELS = {
|
|
|
5350
5418
|
contextWindow: 1048576,
|
|
5351
5419
|
maxTokens: 8192,
|
|
5352
5420
|
} satisfies Model<"openai-completions">,
|
|
5353
|
-
"google/gemini-2.0-flash-exp:free": {
|
|
5354
|
-
id: "google/gemini-2.0-flash-exp:free",
|
|
5355
|
-
name: "Google: Gemini 2.0 Flash Experimental (free)",
|
|
5356
|
-
api: "openai-completions",
|
|
5357
|
-
provider: "openrouter",
|
|
5358
|
-
baseUrl: "https://openrouter.ai/api/v1",
|
|
5359
|
-
reasoning: false,
|
|
5360
|
-
input: ["text", "image"],
|
|
5361
|
-
cost: {
|
|
5362
|
-
input: 0,
|
|
5363
|
-
output: 0,
|
|
5364
|
-
cacheRead: 0,
|
|
5365
|
-
cacheWrite: 0,
|
|
5366
|
-
},
|
|
5367
|
-
contextWindow: 1048576,
|
|
5368
|
-
maxTokens: 8192,
|
|
5369
|
-
} satisfies Model<"openai-completions">,
|
|
5370
5421
|
"google/gemini-2.0-flash-lite-001": {
|
|
5371
5422
|
id: "google/gemini-2.0-flash-lite-001",
|
|
5372
5423
|
name: "Google: Gemini 2.0 Flash Lite",
|
|
@@ -6362,13 +6413,13 @@ export const MODELS = {
|
|
|
6362
6413
|
reasoning: true,
|
|
6363
6414
|
input: ["text", "image"],
|
|
6364
6415
|
cost: {
|
|
6365
|
-
input: 0.
|
|
6366
|
-
output:
|
|
6416
|
+
input: 0.5,
|
|
6417
|
+
output: 2.8,
|
|
6367
6418
|
cacheRead: 0,
|
|
6368
6419
|
cacheWrite: 0,
|
|
6369
6420
|
},
|
|
6370
6421
|
contextWindow: 262144,
|
|
6371
|
-
maxTokens:
|
|
6422
|
+
maxTokens: 4096,
|
|
6372
6423
|
} satisfies Model<"openai-completions">,
|
|
6373
6424
|
"nex-agi/deepseek-v3.1-nex-n1": {
|
|
6374
6425
|
id: "nex-agi/deepseek-v3.1-nex-n1",
|
|
@@ -6464,13 +6515,13 @@ export const MODELS = {
|
|
|
6464
6515
|
reasoning: true,
|
|
6465
6516
|
input: ["text"],
|
|
6466
6517
|
cost: {
|
|
6467
|
-
input: 0.
|
|
6468
|
-
output: 0.
|
|
6518
|
+
input: 0.049999999999999996,
|
|
6519
|
+
output: 0.19999999999999998,
|
|
6469
6520
|
cacheRead: 0,
|
|
6470
6521
|
cacheWrite: 0,
|
|
6471
6522
|
},
|
|
6472
6523
|
contextWindow: 262144,
|
|
6473
|
-
maxTokens:
|
|
6524
|
+
maxTokens: 4096,
|
|
6474
6525
|
} satisfies Model<"openai-completions">,
|
|
6475
6526
|
"nvidia/nemotron-3-nano-30b-a3b:free": {
|
|
6476
6527
|
id: "nvidia/nemotron-3-nano-30b-a3b:free",
|
|
@@ -8699,7 +8750,7 @@ export const MODELS = {
|
|
|
8699
8750
|
cacheWrite: 0,
|
|
8700
8751
|
},
|
|
8701
8752
|
contextWindow: 256000,
|
|
8702
|
-
maxTokens:
|
|
8753
|
+
maxTokens: 65536,
|
|
8703
8754
|
} satisfies Model<"anthropic-messages">,
|
|
8704
8755
|
"anthropic/claude-3-haiku": {
|
|
8705
8756
|
id: "anthropic/claude-3-haiku",
|
|
@@ -9611,9 +9662,9 @@ export const MODELS = {
|
|
|
9611
9662
|
reasoning: true,
|
|
9612
9663
|
input: ["text", "image"],
|
|
9613
9664
|
cost: {
|
|
9614
|
-
input:
|
|
9615
|
-
output:
|
|
9616
|
-
cacheRead: 0.
|
|
9665
|
+
input: 0.6,
|
|
9666
|
+
output: 3,
|
|
9667
|
+
cacheRead: 0.09999999999999999,
|
|
9617
9668
|
cacheWrite: 0,
|
|
9618
9669
|
},
|
|
9619
9670
|
contextWindow: 256000,
|
|
@@ -9732,7 +9783,7 @@ export const MODELS = {
|
|
|
9732
9783
|
cost: {
|
|
9733
9784
|
input: 0.09999999999999999,
|
|
9734
9785
|
output: 0.39999999999999997,
|
|
9735
|
-
cacheRead: 0.
|
|
9786
|
+
cacheRead: 0.03,
|
|
9736
9787
|
cacheWrite: 0,
|
|
9737
9788
|
},
|
|
9738
9789
|
contextWindow: 1047576,
|
|
@@ -9936,7 +9987,7 @@ export const MODELS = {
|
|
|
9936
9987
|
cost: {
|
|
9937
9988
|
input: 1.25,
|
|
9938
9989
|
output: 10,
|
|
9939
|
-
cacheRead: 0.
|
|
9990
|
+
cacheRead: 0.13,
|
|
9940
9991
|
cacheWrite: 0,
|
|
9941
9992
|
},
|
|
9942
9993
|
contextWindow: 128000,
|
|
@@ -9953,7 +10004,7 @@ export const MODELS = {
|
|
|
9953
10004
|
cost: {
|
|
9954
10005
|
input: 1.25,
|
|
9955
10006
|
output: 10,
|
|
9956
|
-
cacheRead: 0.
|
|
10007
|
+
cacheRead: 0.13,
|
|
9957
10008
|
cacheWrite: 0,
|
|
9958
10009
|
},
|
|
9959
10010
|
contextWindow: 400000,
|
|
@@ -9961,7 +10012,7 @@ export const MODELS = {
|
|
|
9961
10012
|
} satisfies Model<"anthropic-messages">,
|
|
9962
10013
|
"openai/gpt-5.2": {
|
|
9963
10014
|
id: "openai/gpt-5.2",
|
|
9964
|
-
name: "GPT
|
|
10015
|
+
name: "GPT 5.2",
|
|
9965
10016
|
api: "anthropic-messages",
|
|
9966
10017
|
provider: "vercel-ai-gateway",
|
|
9967
10018
|
baseUrl: "https://ai-gateway.vercel.sh",
|
|
@@ -9970,7 +10021,7 @@ export const MODELS = {
|
|
|
9970
10021
|
cost: {
|
|
9971
10022
|
input: 1.75,
|
|
9972
10023
|
output: 14,
|
|
9973
|
-
cacheRead: 0.
|
|
10024
|
+
cacheRead: 0.18,
|
|
9974
10025
|
cacheWrite: 0,
|
|
9975
10026
|
},
|
|
9976
10027
|
contextWindow: 400000,
|
|
@@ -10231,40 +10282,6 @@ export const MODELS = {
|
|
|
10231
10282
|
contextWindow: 131072,
|
|
10232
10283
|
maxTokens: 131072,
|
|
10233
10284
|
} satisfies Model<"anthropic-messages">,
|
|
10234
|
-
"stealth/sonoma-dusk-alpha": {
|
|
10235
|
-
id: "stealth/sonoma-dusk-alpha",
|
|
10236
|
-
name: "Sonoma Dusk Alpha",
|
|
10237
|
-
api: "anthropic-messages",
|
|
10238
|
-
provider: "vercel-ai-gateway",
|
|
10239
|
-
baseUrl: "https://ai-gateway.vercel.sh",
|
|
10240
|
-
reasoning: false,
|
|
10241
|
-
input: ["text", "image"],
|
|
10242
|
-
cost: {
|
|
10243
|
-
input: 0.19999999999999998,
|
|
10244
|
-
output: 0.5,
|
|
10245
|
-
cacheRead: 0.049999999999999996,
|
|
10246
|
-
cacheWrite: 0,
|
|
10247
|
-
},
|
|
10248
|
-
contextWindow: 2000000,
|
|
10249
|
-
maxTokens: 131072,
|
|
10250
|
-
} satisfies Model<"anthropic-messages">,
|
|
10251
|
-
"stealth/sonoma-sky-alpha": {
|
|
10252
|
-
id: "stealth/sonoma-sky-alpha",
|
|
10253
|
-
name: "Sonoma Sky Alpha",
|
|
10254
|
-
api: "anthropic-messages",
|
|
10255
|
-
provider: "vercel-ai-gateway",
|
|
10256
|
-
baseUrl: "https://ai-gateway.vercel.sh",
|
|
10257
|
-
reasoning: false,
|
|
10258
|
-
input: ["text", "image"],
|
|
10259
|
-
cost: {
|
|
10260
|
-
input: 0.19999999999999998,
|
|
10261
|
-
output: 0.5,
|
|
10262
|
-
cacheRead: 0.049999999999999996,
|
|
10263
|
-
cacheWrite: 0,
|
|
10264
|
-
},
|
|
10265
|
-
contextWindow: 2000000,
|
|
10266
|
-
maxTokens: 131072,
|
|
10267
|
-
} satisfies Model<"anthropic-messages">,
|
|
10268
10285
|
"vercel/v0-1.0-md": {
|
|
10269
10286
|
id: "vercel/v0-1.0-md",
|
|
10270
10287
|
name: "v0-1.0-md",
|
|
@@ -10552,7 +10569,7 @@ export const MODELS = {
|
|
|
10552
10569
|
cacheWrite: 0,
|
|
10553
10570
|
},
|
|
10554
10571
|
contextWindow: 65536,
|
|
10555
|
-
maxTokens:
|
|
10572
|
+
maxTokens: 16384,
|
|
10556
10573
|
} satisfies Model<"anthropic-messages">,
|
|
10557
10574
|
"zai/glm-4.6": {
|
|
10558
10575
|
id: "zai/glm-4.6",
|
|
@@ -11143,5 +11160,23 @@ export const MODELS = {
|
|
|
11143
11160
|
contextWindow: 204800,
|
|
11144
11161
|
maxTokens: 131072,
|
|
11145
11162
|
} satisfies Model<"openai-completions">,
|
|
11163
|
+
"glm-4.7-flash": {
|
|
11164
|
+
id: "glm-4.7-flash",
|
|
11165
|
+
name: "GLM-4.7-Flash",
|
|
11166
|
+
api: "openai-completions",
|
|
11167
|
+
provider: "zai",
|
|
11168
|
+
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
|
11169
|
+
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
|
|
11170
|
+
reasoning: true,
|
|
11171
|
+
input: ["text"],
|
|
11172
|
+
cost: {
|
|
11173
|
+
input: 0,
|
|
11174
|
+
output: 0,
|
|
11175
|
+
cacheRead: 0,
|
|
11176
|
+
cacheWrite: 0,
|
|
11177
|
+
},
|
|
11178
|
+
contextWindow: 200000,
|
|
11179
|
+
maxTokens: 131072,
|
|
11180
|
+
} satisfies Model<"openai-completions">,
|
|
11146
11181
|
},
|
|
11147
11182
|
} as const;
|
package/src/utils/oauth/index.ts
CHANGED
|
@@ -48,6 +48,8 @@ export { loginKimi, refreshKimiToken } from "./kimi";
|
|
|
48
48
|
export type { OpenAICodexLoginOptions } from "./openai-codex";
|
|
49
49
|
// OpenAI Codex (ChatGPT OAuth)
|
|
50
50
|
export { loginOpenAICodex, refreshOpenAICodexToken } from "./openai-codex";
|
|
51
|
+
// OpenCode (API key)
|
|
52
|
+
export { loginOpenCode } from "./opencode";
|
|
51
53
|
|
|
52
54
|
export * from "./types";
|
|
53
55
|
|
|
@@ -93,6 +95,10 @@ export async function refreshOAuthToken(
|
|
|
93
95
|
case "cursor":
|
|
94
96
|
newCredentials = await refreshCursorToken(credentials.refresh);
|
|
95
97
|
break;
|
|
98
|
+
case "opencode":
|
|
99
|
+
// API keys don't expire, return as-is
|
|
100
|
+
newCredentials = credentials;
|
|
101
|
+
break;
|
|
96
102
|
default:
|
|
97
103
|
throw new Error(`Unknown OAuth provider: ${provider}`);
|
|
98
104
|
}
|
|
@@ -173,5 +179,10 @@ export function getOAuthProviders(): OAuthProviderInfo[] {
|
|
|
173
179
|
name: "Cursor (Claude, GPT, etc.)",
|
|
174
180
|
available: true,
|
|
175
181
|
},
|
|
182
|
+
{
|
|
183
|
+
id: "opencode",
|
|
184
|
+
name: "OpenCode Zen",
|
|
185
|
+
available: true,
|
|
186
|
+
},
|
|
176
187
|
];
|
|
177
188
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Zen login flow.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode Zen is a subscription service that provides access to various AI models
|
|
5
|
+
* (GPT-5.x, Claude 4.x, Gemini 3, etc.) through a unified API at opencode.ai/zen.
|
|
6
|
+
*
|
|
7
|
+
* This is not OAuth - it's a simple API key flow:
|
|
8
|
+
* 1. Open browser to https://opencode.ai/auth
|
|
9
|
+
* 2. User logs in and copies their API key
|
|
10
|
+
* 3. User pastes the API key back into the CLI
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { OAuthController } from "./types";
|
|
14
|
+
|
|
15
|
+
const AUTH_URL = "https://opencode.ai/auth";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Login to OpenCode Zen.
|
|
19
|
+
*
|
|
20
|
+
* Opens browser to auth page, prompts user to paste their API key.
|
|
21
|
+
* Returns the API key directly (not OAuthCredentials - this isn't OAuth).
|
|
22
|
+
*/
|
|
23
|
+
export async function loginOpenCode(options: OAuthController): Promise<string> {
|
|
24
|
+
if (!options.onPrompt) {
|
|
25
|
+
throw new Error("OpenCode Zen login requires onPrompt callback");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Open browser to auth page
|
|
29
|
+
options.onAuth?.({
|
|
30
|
+
url: AUTH_URL,
|
|
31
|
+
instructions: "Log in and copy your API key",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Prompt user to paste their API key
|
|
35
|
+
const apiKey = await options.onPrompt({
|
|
36
|
+
message: "Paste your OpenCode Zen API key",
|
|
37
|
+
placeholder: "sk-...",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (options.signal?.aborted) {
|
|
41
|
+
throw new Error("Login cancelled");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const trimmed = apiKey.trim();
|
|
45
|
+
if (!trimmed) {
|
|
46
|
+
throw new Error("API key is required");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return trimmed;
|
|
50
|
+
}
|