pi-parasail-provider 1.0.7 → 1.0.8

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
@@ -77,7 +77,6 @@ Get your API key at [parasail.io](https://parasail.io/).
77
77
  | Gemma 3 27B | 131K | ❌ | Text + Image | 16K | $0.08 | $0.45 | $0.04 |
78
78
  | Gemma 4 26B (A4B) | 262K | ✅ | Text + Image | 16K | $0.13 | $0.40 | $0.05 |
79
79
  | Gemma 4 31B | 262K | ✅ | Text + Image | 16K | $0.15 | $0.40 | $0.06 |
80
- | GLM 5 | 203K | ✅ | Text | 16K | $1.00 | $3.20 | $0.20 |
81
80
  | GLM 5.1 | 203K | ✅ | Text | 16K | $1.40 | $4.40 | $0.26 |
82
81
  | Glm 52 | 262K | ✅ | Text | 16K | $1.40 | $4.40 | $0.26 |
83
82
  | Googlegemma 3 4b It | 131K | ❌ | Text | 16K | $0.05 | Free | Free |
@@ -87,12 +86,10 @@ Get your API key at [parasail.io](https://parasail.io/).
87
86
  | Kimi K2.6 | 262K | ✅ | Text + Image | 16K | $0.75 | $3.50 | $0.16 |
88
87
  | Kimi K27 Code | 262K | ✅ | Text + Image | 16K | $0.76 | $3.50 | $0.16 |
89
88
  | Kimi K3 | 1M | ✅ | Text + Image | 16K | $3.00 | $15.00 | $0.30 |
90
- | Kimi K3 Fast | 1M | ✅ | Text + Image | 16K | $3.00 | $15.00 | $0.30 |
91
89
  | Llama 3.3 70B | 131K | ❌ | Text | 16K | $0.22 | $0.50 | $0.11 |
92
90
  | Llama 32 3b Instruct | 131K | ❌ | Text | 16K | $0.05 | $0.33 | Free |
93
91
  | Llama 4 Maverick 17B-128E | 524K | ❌ | Text + Image | 16K | $0.35 | $1.00 | $0.17 |
94
92
  | Mimo V25 | 1M | ✅ | Text | 16K | $0.14 | $0.28 | $0.05 |
95
- | MiniMax M2.5 | 197K | ✅ | Text | 16K | $0.30 | $1.20 | $0.03 |
96
93
  | Minimax M3 | 1M | ✅ | Text + Image | 16K | $0.30 | $1.20 | $0.06 |
97
94
  | Mistral Small 32 24b | 131K | ❌ | Text | 16K | $0.09 | $0.30 | $0.05 |
98
95
  | Mistralaimistral Nemo | 131K | ❌ | Text | 16K | $0.03 | $0.03 | Free |
@@ -103,8 +100,6 @@ Get your API key at [parasail.io](https://parasail.io/).
103
100
  | Qwen2.5-VL 72B | 128K | ❌ | Text + Image | 8K | $0.80 | $1.00 | $0.40 |
104
101
  | Qwen3 235B (A22B) | 131K | ✅ | Text | 33K | $0.14 | $0.80 | $0.05 |
105
102
  | Qwen3 Coder Next | 262K | ✅ | Text | 33K | $0.12 | $0.80 | $0.07 |
106
- | Qwen3 Embedding 4b | 41K | ❌ | Text | 16K | $0.02 | Free | Free |
107
- | Qwen3 Embedding 8b | 41K | ❌ | Text | 16K | $0.03 | Free | Free |
108
103
  | Qwen3 Next 80B (A3B) | 262K | ✅ | Text | 33K | $0.10 | $1.10 | $0.07 |
109
104
  | Qwen3-VL 235B (A22B) | 131K | ✅ | Text + Image | 33K | $0.21 | $1.90 | $0.10 |
110
105
  | Qwen3-VL 8B | 262K | ✅ | Text + Image | 8K | $0.25 | $0.75 | $0.12 |
@@ -1 +1,113 @@
1
- {}
1
+ {
2
+ "parasail-glm-5": {
3
+ "id": "parasail-glm-5",
4
+ "name": "GLM 5",
5
+ "reasoning": true,
6
+ "input": [
7
+ "text"
8
+ ],
9
+ "cost": {
10
+ "input": 1,
11
+ "output": 3.2,
12
+ "cacheRead": 0.2,
13
+ "cacheWrite": 0
14
+ },
15
+ "contextWindow": 202752,
16
+ "maxTokens": 16384,
17
+ "compat": {
18
+ "thinkingFormat": "zai",
19
+ "maxTokensField": "max_completion_tokens",
20
+ "supportsDeveloperRole": false,
21
+ "supportsStore": false
22
+ },
23
+ "deprecatedAt": "2026-08-05T02:00:25.555Z"
24
+ },
25
+ "parasail-minimax-m25": {
26
+ "id": "parasail-minimax-m25",
27
+ "name": "MiniMax M2.5",
28
+ "reasoning": true,
29
+ "input": [
30
+ "text"
31
+ ],
32
+ "cost": {
33
+ "input": 0.3,
34
+ "output": 1.2,
35
+ "cacheRead": 0.03,
36
+ "cacheWrite": 0
37
+ },
38
+ "contextWindow": 196608,
39
+ "maxTokens": 16384,
40
+ "compat": {
41
+ "maxTokensField": "max_completion_tokens",
42
+ "supportsDeveloperRole": false,
43
+ "supportsStore": false
44
+ },
45
+ "deprecatedAt": "2026-08-05T02:00:25.555Z"
46
+ },
47
+ "parasail-kimi-k3-fast": {
48
+ "id": "parasail-kimi-k3-fast",
49
+ "name": "Kimi K3 Fast",
50
+ "reasoning": false,
51
+ "input": [
52
+ "text"
53
+ ],
54
+ "cost": {
55
+ "input": 3,
56
+ "output": 15,
57
+ "cacheRead": 0.3,
58
+ "cacheWrite": 0
59
+ },
60
+ "contextWindow": 1048576,
61
+ "maxTokens": 16384,
62
+ "compat": {
63
+ "maxTokensField": "max_completion_tokens",
64
+ "supportsDeveloperRole": false,
65
+ "supportsStore": false
66
+ },
67
+ "deprecatedAt": "2026-08-07T02:00:20.111Z"
68
+ },
69
+ "parasail-qwen3-embedding-4b": {
70
+ "id": "parasail-qwen3-embedding-4b",
71
+ "name": "Qwen3 Embedding 4b",
72
+ "reasoning": false,
73
+ "input": [
74
+ "text"
75
+ ],
76
+ "cost": {
77
+ "input": 0.019,
78
+ "output": 0,
79
+ "cacheRead": 0,
80
+ "cacheWrite": 0
81
+ },
82
+ "contextWindow": 40960,
83
+ "maxTokens": 16384,
84
+ "compat": {
85
+ "maxTokensField": "max_completion_tokens",
86
+ "supportsDeveloperRole": false,
87
+ "supportsStore": false
88
+ },
89
+ "deprecatedAt": "2026-08-08T02:00:20.692Z"
90
+ },
91
+ "parasail-qwen3-embedding-8b": {
92
+ "id": "parasail-qwen3-embedding-8b",
93
+ "name": "Qwen3 Embedding 8b",
94
+ "reasoning": false,
95
+ "input": [
96
+ "text"
97
+ ],
98
+ "cost": {
99
+ "input": 0.03,
100
+ "output": 0,
101
+ "cacheRead": 0,
102
+ "cacheWrite": 0
103
+ },
104
+ "contextWindow": 40960,
105
+ "maxTokens": 16384,
106
+ "compat": {
107
+ "maxTokensField": "max_completion_tokens",
108
+ "supportsDeveloperRole": false,
109
+ "supportsStore": false
110
+ },
111
+ "deprecatedAt": "2026-08-08T02:00:20.692Z"
112
+ }
113
+ }
package/models.json CHANGED
@@ -200,28 +200,6 @@
200
200
  "supportsStore": false
201
201
  }
202
202
  },
203
- {
204
- "id": "parasail-glm-5",
205
- "name": "GLM 5",
206
- "reasoning": true,
207
- "input": [
208
- "text"
209
- ],
210
- "cost": {
211
- "input": 1,
212
- "output": 3.2,
213
- "cacheRead": 0.2,
214
- "cacheWrite": 0
215
- },
216
- "contextWindow": 202752,
217
- "maxTokens": 16384,
218
- "compat": {
219
- "thinkingFormat": "zai",
220
- "maxTokensField": "max_completion_tokens",
221
- "supportsDeveloperRole": false,
222
- "supportsStore": false
223
- }
224
- },
225
203
  {
226
204
  "id": "parasail-glm-51",
227
205
  "name": "GLM 5.1",
@@ -244,27 +222,6 @@
244
222
  "supportsStore": false
245
223
  }
246
224
  },
247
- {
248
- "id": "parasail-minimax-m25",
249
- "name": "MiniMax M2.5",
250
- "reasoning": true,
251
- "input": [
252
- "text"
253
- ],
254
- "cost": {
255
- "input": 0.3,
256
- "output": 1.2,
257
- "cacheRead": 0.03,
258
- "cacheWrite": 0
259
- },
260
- "contextWindow": 196608,
261
- "maxTokens": 16384,
262
- "compat": {
263
- "maxTokensField": "max_completion_tokens",
264
- "supportsDeveloperRole": false,
265
- "supportsStore": false
266
- }
267
- },
268
225
  {
269
226
  "id": "parasail-qwen3-235b-a22b-instruct-2507",
270
227
  "name": "Qwen3 235B (A22B)",
@@ -352,27 +309,6 @@
352
309
  "supportsStore": false
353
310
  }
354
311
  },
355
- {
356
- "id": "parasail-kimi-k3-fast",
357
- "name": "Kimi K3 Fast",
358
- "reasoning": false,
359
- "input": [
360
- "text"
361
- ],
362
- "cost": {
363
- "input": 3,
364
- "output": 15,
365
- "cacheRead": 0.3,
366
- "cacheWrite": 0
367
- },
368
- "contextWindow": 1048576,
369
- "maxTokens": 16384,
370
- "compat": {
371
- "maxTokensField": "max_completion_tokens",
372
- "supportsDeveloperRole": false,
373
- "supportsStore": false
374
- }
375
- },
376
312
  {
377
313
  "id": "parasail-mimo-v25",
378
314
  "name": "Mimo V25",
@@ -840,48 +776,6 @@
840
776
  "supportsStore": false
841
777
  }
842
778
  },
843
- {
844
- "id": "parasail-qwen3-embedding-4b",
845
- "name": "Qwen3 Embedding 4b",
846
- "reasoning": false,
847
- "input": [
848
- "text"
849
- ],
850
- "cost": {
851
- "input": 0.019,
852
- "output": 0,
853
- "cacheRead": 0,
854
- "cacheWrite": 0
855
- },
856
- "contextWindow": 40960,
857
- "maxTokens": 16384,
858
- "compat": {
859
- "maxTokensField": "max_completion_tokens",
860
- "supportsDeveloperRole": false,
861
- "supportsStore": false
862
- }
863
- },
864
- {
865
- "id": "parasail-qwen3-embedding-8b",
866
- "name": "Qwen3 Embedding 8b",
867
- "reasoning": false,
868
- "input": [
869
- "text"
870
- ],
871
- "cost": {
872
- "input": 0.03,
873
- "output": 0,
874
- "cacheRead": 0,
875
- "cacheWrite": 0
876
- },
877
- "contextWindow": 40960,
878
- "maxTokens": 16384,
879
- "compat": {
880
- "maxTokensField": "max_completion_tokens",
881
- "supportsDeveloperRole": false,
882
- "supportsStore": false
883
- }
884
- },
885
779
  {
886
780
  "id": "parasail-skyfall-36b-v2-fp8",
887
781
  "name": "Skyfall 36b V2 Fp8",
package/package.json CHANGED
@@ -1,16 +1,9 @@
1
1
  {
2
2
  "name": "pi-parasail-provider",
3
- "version": "1.0.7",
4
- "packageManager": "pnpm@11.18.0",
3
+ "version": "1.0.8",
5
4
  "description": "Parasail provider extension for pi - Access top open-source models (DeepSeek, Qwen, GLM, Kimi, Llama, Gemma, Mistral) through the Parasail API",
6
5
  "type": "module",
7
6
  "main": "index.ts",
8
- "scripts": {
9
- "clean": "echo 'nothing to clean'",
10
- "build": "echo 'nothing to build'",
11
- "check": "echo 'nothing to check'",
12
- "update-models": "node scripts/update-models.js"
13
- },
14
7
  "keywords": [
15
8
  "pi",
16
9
  "extension",
@@ -32,5 +25,11 @@
32
25
  "extensions": [
33
26
  "./index.ts"
34
27
  ]
28
+ },
29
+ "scripts": {
30
+ "clean": "echo 'nothing to clean'",
31
+ "build": "echo 'nothing to build'",
32
+ "check": "echo 'nothing to check'",
33
+ "update-models": "node scripts/update-models.js"
35
34
  }
36
- }
35
+ }
@@ -15,15 +15,119 @@
15
15
  * patch.json and custom-models.json are applied at runtime by the provider.
16
16
  * They are NOT baked into models.json, but ARE used to generate the README table.
17
17
  *
18
- * Requires PARASAIL_API_KEY environment variable.
18
+ * API key: the stored `parasail` credential in ~/.pi/agent/auth.json wins, then
19
+ * the PARASAIL_API_KEY environment variable. The script refuses to run without one.
19
20
  */
20
21
 
21
22
  import fs from 'fs';
23
+ import os from 'os';
24
+ import { execSync } from 'child_process';
22
25
  import path from 'path';
23
26
  import { fileURLToPath } from 'url';
24
27
 
25
28
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
29
 
30
+ // pi's agent directory: PI_CODING_AGENT_DIR (with ~ expansion) or ~/.pi/agent.
31
+ function piAgentDir() {
32
+ const envDir = process.env.PI_CODING_AGENT_DIR;
33
+ if (envDir) {
34
+ return envDir.startsWith('~/') || envDir === '~'
35
+ ? path.join(os.homedir(), envDir.slice(1))
36
+ : envDir;
37
+ }
38
+ return path.join(os.homedir(), '.pi', 'agent');
39
+ }
40
+
41
+ const AUTH_JSON_PATH = path.join(piAgentDir(), 'auth.json');
42
+
43
+ /**
44
+ * Resolve a configured value using pi's semantics (resolve-config-value.ts in
45
+ * pi-mono): "!command" runs via the shell (10s timeout) and uses trimmed
46
+ * stdout; "$VAR" / "${VAR}" interpolate environment variables ("$$" escapes a
47
+ * literal "$", "$!" a literal "!"); anything else is a literal. Returns
48
+ * undefined when a referenced env var is unset or a command fails.
49
+ */
50
+ function resolveConfigValue(config, env) {
51
+ if (typeof config !== 'string' || config.length === 0) return undefined;
52
+ if (config.startsWith('!')) {
53
+ try {
54
+ const out = execSync(config.slice(1), {
55
+ encoding: 'utf8',
56
+ timeout: 10000,
57
+ stdio: ['ignore', 'pipe', 'ignore'],
58
+ });
59
+ return out.trim() || undefined;
60
+ } catch {
61
+ return undefined;
62
+ }
63
+ }
64
+ const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
65
+ let resolved = '';
66
+ let index = 0;
67
+ while (index < config.length) {
68
+ const dollar = config.indexOf('$', index);
69
+ if (dollar < 0) {
70
+ resolved += config.slice(index);
71
+ break;
72
+ }
73
+ resolved += config.slice(index, dollar);
74
+ const next = config[dollar + 1];
75
+ let name;
76
+ if (next === '$' || next === '!') {
77
+ resolved += next;
78
+ index = dollar + 2;
79
+ continue;
80
+ } else if (next === '{') {
81
+ const end = config.indexOf('}', dollar + 2);
82
+ if (end < 0) {
83
+ resolved += '$';
84
+ index = dollar + 1;
85
+ continue;
86
+ }
87
+ const inner = config.slice(dollar + 2, end);
88
+ if (!ENV_NAME_RE.test(inner)) {
89
+ resolved += config.slice(dollar, end + 1);
90
+ index = end + 1;
91
+ continue;
92
+ }
93
+ name = inner;
94
+ index = end + 1;
95
+ } else {
96
+ const match = config.slice(dollar + 1).match(/^[A-Za-z_][A-Za-z0-9_]*/);
97
+ if (!match) {
98
+ resolved += '$';
99
+ index = dollar + 1;
100
+ continue;
101
+ }
102
+ name = match[0];
103
+ index = dollar + 1 + name.length;
104
+ }
105
+ const value = (env && env[name]) || process.env[name] || undefined;
106
+ if (value === undefined) return undefined;
107
+ resolved += value;
108
+ }
109
+ return resolved;
110
+ }
111
+
112
+ /**
113
+ * The API key, resolved the way pi itself resolves it for this provider: the
114
+ * stored `parasail` credential in ~/.pi/agent/auth.json wins, then
115
+ * the PARASAIL_API_KEY environment variable.
116
+ */
117
+ function resolveApiKey() {
118
+ try {
119
+ const auth = JSON.parse(fs.readFileSync(AUTH_JSON_PATH, 'utf8'));
120
+ const credential = auth?.parasail;
121
+ if (credential && credential.type === 'api_key' && typeof credential.key === 'string') {
122
+ const key = resolveConfigValue(credential.key, credential.env);
123
+ if (key) return key;
124
+ }
125
+ } catch {
126
+ // Missing or unparseable auth.json: fall through to the env var.
127
+ }
128
+ return process.env.PARASAIL_API_KEY || undefined;
129
+ }
130
+
27
131
  const MODELS_API_URL = 'https://api.parasail.io/v1/models';
28
132
  const PRICING_API_URL = 'https://www.saas.parasail.io/api/v1/prices/serverlessEndpoints';
29
133
  const MODELS_JSON_PATH = path.join(__dirname, '..', 'models.json');
@@ -52,9 +156,9 @@ function saveJson(filePath, data) {
52
156
  // ─── API fetch ───────────────────────────────────────────────────────────────
53
157
 
54
158
  async function fetchModels() {
55
- const apiKey = process.env.PARASAIL_API_KEY;
159
+ const apiKey = resolveApiKey();
56
160
  if (!apiKey) {
57
- throw new Error('PARASAIL_API_KEY environment variable is required');
161
+ throw new Error('No API key found: no `parasail` credential resolved from ' + AUTH_JSON_PATH + ' and PARASAIL_API_KEY is not set');
58
162
  }
59
163
 
60
164
  console.log(`Fetching models from ${MODELS_API_URL}...`);