pi-wafer-provider 1.1.4 → 1.1.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/README.md CHANGED
@@ -76,13 +76,13 @@ pi
76
76
 
77
77
  | Model | Type | Context | Max Output | Input Cost | Output Cost | Cached Input |
78
78
  |-------|------|---------|------------|------------|-------------|--------------|
79
+ | DeepSeek-V4-Flash-0731-Fast | Text | 1M | 1M | $0.28 | $0.56 | $0.07 |
79
80
  | GLM-5.1 | Text | 203K | 33K | $1.00 | $3.20 | $0.10 |
80
81
  | GLM-5.2 | Text | 1M | 16K | $1.26 | $3.96 | $0.23 |
81
82
  | GLM5.2-Fast | Text | 1M | 16K | $2.10 | $6.60 | $0.21 |
82
83
  | Kimi-K2.6 | Text + Image | 262K | 33K | $1.14 | $4.80 | $0.19 |
83
- | Kimi-K3 | Text + Image | 912K | 16K | $3.00 | $15.00 | $0.30 |
84
+ | Kimi-K3 | Text + Image | 1M | 16K | $3.00 | $15.00 | $0.30 |
84
85
  | Kimi-K3-Fast | Text + Image | 1M | 16K | $4.50 | $22.50 | $0.45 |
85
- | MiniMax-M3 | Text + Image | 1M | 16K | $0.33 | $1.32 | $0.07 |
86
86
  | Qwen 3.5 397B (A17B) | Text | 262K | 33K | Free | Free | Free |
87
87
 
88
88
  *Costs are per million tokens. Prices based on official provider pricing.*
@@ -1 +1,27 @@
1
- {}
1
+ {
2
+ "MiniMax-M3": {
3
+ "id": "MiniMax-M3",
4
+ "name": "MiniMax-M3",
5
+ "reasoning": true,
6
+ "input": [
7
+ "text",
8
+ "image"
9
+ ],
10
+ "cost": {
11
+ "input": 0.33,
12
+ "output": 1.32,
13
+ "cacheRead": 0.07,
14
+ "cacheWrite": 0
15
+ },
16
+ "contextWindow": 1048576,
17
+ "maxTokens": 16384,
18
+ "compat": {
19
+ "maxTokensField": "max_completion_tokens",
20
+ "supportsDeveloperRole": false,
21
+ "supportsStore": false,
22
+ "supportsZdr": false,
23
+ "supportsReasoningEffort": true
24
+ },
25
+ "deprecatedAt": "2026-08-10T02:00:21.380Z"
26
+ }
27
+ }
package/index.ts CHANGED
@@ -97,6 +97,7 @@ function applyPatch(model: JsonModel, patch: PatchEntry): JsonModel {
97
97
  if (patch.contextWindow !== undefined) result.contextWindow = patch.contextWindow;
98
98
  if (patch.maxTokens !== undefined) result.maxTokens = patch.maxTokens;
99
99
  if (patch.providers !== undefined) result.providers = patch.providers;
100
+ if (patch.thinkingLevelMap !== undefined) result.thinkingLevelMap = { ...patch.thinkingLevelMap };
100
101
 
101
102
  if (patch.cost) {
102
103
  result.cost = {
package/models.json CHANGED
@@ -1,4 +1,27 @@
1
1
  [
2
+ {
3
+ "id": "DeepSeek-V4-Flash-0731-Fast",
4
+ "name": "DeepSeek-V4-Flash-0731-Fast",
5
+ "reasoning": true,
6
+ "input": [
7
+ "text"
8
+ ],
9
+ "cost": {
10
+ "input": 0.28,
11
+ "output": 0.56,
12
+ "cacheRead": 0.07,
13
+ "cacheWrite": 0
14
+ },
15
+ "contextWindow": 1048576,
16
+ "maxTokens": 1048576,
17
+ "compat": {
18
+ "maxTokensField": "max_completion_tokens",
19
+ "supportsDeveloperRole": false,
20
+ "supportsStore": false,
21
+ "supportsZdr": true,
22
+ "supportsReasoningEffort": true
23
+ }
24
+ },
2
25
  {
3
26
  "id": "GLM-5.1",
4
27
  "name": "GLM-5.1",
@@ -106,7 +129,7 @@
106
129
  "cacheRead": 0.3,
107
130
  "cacheWrite": 0
108
131
  },
109
- "contextWindow": 912384,
132
+ "contextWindow": 1048576,
110
133
  "maxTokens": 16384,
111
134
  "compat": {
112
135
  "maxTokensField": "max_completion_tokens",
@@ -140,30 +163,6 @@
140
163
  "supportsReasoningEffort": true
141
164
  }
142
165
  },
143
- {
144
- "id": "MiniMax-M3",
145
- "name": "MiniMax-M3",
146
- "reasoning": true,
147
- "input": [
148
- "text",
149
- "image"
150
- ],
151
- "cost": {
152
- "input": 0.33,
153
- "output": 1.32,
154
- "cacheRead": 0.07,
155
- "cacheWrite": 0
156
- },
157
- "contextWindow": 1048576,
158
- "maxTokens": 16384,
159
- "compat": {
160
- "maxTokensField": "max_completion_tokens",
161
- "supportsDeveloperRole": false,
162
- "supportsStore": false,
163
- "supportsZdr": false,
164
- "supportsReasoningEffort": true
165
- }
166
- },
167
166
  {
168
167
  "id": "Qwen3.5-397B-A17B",
169
168
  "name": "Qwen 3.5 397B (A17B)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-wafer-provider",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Wafer Serverless provider extension for pi - Access Qwen3.5-397B-A17B, GLM-5.1, Kimi K2.6, and DeepSeek-V4 through the Wafer Serverless API",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/patch.json CHANGED
@@ -1,4 +1,15 @@
1
1
  {
2
+ "kimi-k3-fast": {
3
+ "thinkingLevelMap": {
4
+ "off": null,
5
+ "minimal": null,
6
+ "low": "low",
7
+ "medium": null,
8
+ "high": "high",
9
+ "xhigh": null,
10
+ "max": "max"
11
+ }
12
+ },
2
13
  "Qwen3.5-397B-A17B": {
3
14
  "providers": [
4
15
  "wafer-serverless"
@@ -12,15 +12,119 @@
12
12
  *
13
13
  * patch.json is applied at runtime by the provider — not baked into models.json.
14
14
  *
15
- * Requires WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) environment variable.
15
+ * API key: the stored `wafer-serverless` credential in ~/.pi/agent/auth.json wins, then
16
+ * the WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) environment variable. The script refuses to run without one.
16
17
  */
17
18
 
18
19
  import fs from 'fs';
20
+ import os from 'os';
21
+ import { execSync } from 'child_process';
19
22
  import path from 'path';
20
23
  import { fileURLToPath } from 'url';
21
24
 
22
25
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
23
26
 
27
+ // pi's agent directory: PI_CODING_AGENT_DIR (with ~ expansion) or ~/.pi/agent.
28
+ function piAgentDir() {
29
+ const envDir = process.env.PI_CODING_AGENT_DIR;
30
+ if (envDir) {
31
+ return envDir.startsWith('~/') || envDir === '~'
32
+ ? path.join(os.homedir(), envDir.slice(1))
33
+ : envDir;
34
+ }
35
+ return path.join(os.homedir(), '.pi', 'agent');
36
+ }
37
+
38
+ const AUTH_JSON_PATH = path.join(piAgentDir(), 'auth.json');
39
+
40
+ /**
41
+ * Resolve a configured value using pi's semantics (resolve-config-value.ts in
42
+ * pi-mono): "!command" runs via the shell (10s timeout) and uses trimmed
43
+ * stdout; "$VAR" / "${VAR}" interpolate environment variables ("$$" escapes a
44
+ * literal "$", "$!" a literal "!"); anything else is a literal. Returns
45
+ * undefined when a referenced env var is unset or a command fails.
46
+ */
47
+ function resolveConfigValue(config, env) {
48
+ if (typeof config !== 'string' || config.length === 0) return undefined;
49
+ if (config.startsWith('!')) {
50
+ try {
51
+ const out = execSync(config.slice(1), {
52
+ encoding: 'utf8',
53
+ timeout: 10000,
54
+ stdio: ['ignore', 'pipe', 'ignore'],
55
+ });
56
+ return out.trim() || undefined;
57
+ } catch {
58
+ return undefined;
59
+ }
60
+ }
61
+ const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
62
+ let resolved = '';
63
+ let index = 0;
64
+ while (index < config.length) {
65
+ const dollar = config.indexOf('$', index);
66
+ if (dollar < 0) {
67
+ resolved += config.slice(index);
68
+ break;
69
+ }
70
+ resolved += config.slice(index, dollar);
71
+ const next = config[dollar + 1];
72
+ let name;
73
+ if (next === '$' || next === '!') {
74
+ resolved += next;
75
+ index = dollar + 2;
76
+ continue;
77
+ } else if (next === '{') {
78
+ const end = config.indexOf('}', dollar + 2);
79
+ if (end < 0) {
80
+ resolved += '$';
81
+ index = dollar + 1;
82
+ continue;
83
+ }
84
+ const inner = config.slice(dollar + 2, end);
85
+ if (!ENV_NAME_RE.test(inner)) {
86
+ resolved += config.slice(dollar, end + 1);
87
+ index = end + 1;
88
+ continue;
89
+ }
90
+ name = inner;
91
+ index = end + 1;
92
+ } else {
93
+ const match = config.slice(dollar + 1).match(/^[A-Za-z_][A-Za-z0-9_]*/);
94
+ if (!match) {
95
+ resolved += '$';
96
+ index = dollar + 1;
97
+ continue;
98
+ }
99
+ name = match[0];
100
+ index = dollar + 1 + name.length;
101
+ }
102
+ const value = (env && env[name]) || process.env[name] || undefined;
103
+ if (value === undefined) return undefined;
104
+ resolved += value;
105
+ }
106
+ return resolved;
107
+ }
108
+
109
+ /**
110
+ * The API key, resolved the way pi itself resolves it for this provider: the
111
+ * stored `wafer-serverless` credential in ~/.pi/agent/auth.json wins, then
112
+ * the WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) environment variable.
113
+ */
114
+ function resolveApiKey() {
115
+ try {
116
+ const auth = JSON.parse(fs.readFileSync(AUTH_JSON_PATH, 'utf8'));
117
+ const credential = auth?.['wafer-serverless'];
118
+ if (credential && credential.type === 'api_key' && typeof credential.key === 'string') {
119
+ const key = resolveConfigValue(credential.key, credential.env);
120
+ if (key) return key;
121
+ }
122
+ } catch {
123
+ // Missing or unparseable auth.json: fall through to the env var.
124
+ }
125
+ return process.env.WAFER_SERVERLESS_API_KEY || process.env.WAFER_API_KEY || undefined;
126
+ }
127
+
24
128
  const MODELS_API_URL = 'https://pass.wafer.ai/v1/models';
25
129
  const MODELS_JSON_PATH = path.join(__dirname, '..', 'models.json');
26
130
  const PATCH_JSON_PATH = path.join(__dirname, '..', 'patch.json');
@@ -45,9 +149,9 @@ function saveJson(filePath, data) {
45
149
  // ─── API fetch ───────────────────────────────────────────────────────────────
46
150
 
47
151
  async function fetchModels() {
48
- const apiKey = process.env.WAFER_SERVERLESS_API_KEY || process.env.WAFER_API_KEY;
152
+ const apiKey = resolveApiKey();
49
153
  if (!apiKey) {
50
- throw new Error('WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) environment variable is required');
154
+ throw new Error('No API key found: no `wafer-serverless` credential resolved from ' + AUTH_JSON_PATH + ' and WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) is not set');
51
155
  }
52
156
 
53
157
  console.log(`Fetching models from ${MODELS_API_URL}...`);