pi-wafer-provider 1.0.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/models.json ADDED
@@ -0,0 +1,220 @@
1
+ [
2
+ {
3
+ "id": "deepseek-v4-flash",
4
+ "name": "Deepseek V4 Flash",
5
+ "reasoning": false,
6
+ "input": [
7
+ "text"
8
+ ],
9
+ "cost": {
10
+ "input": 0,
11
+ "output": 0,
12
+ "cacheRead": 0,
13
+ "cacheWrite": 0
14
+ },
15
+ "contextWindow": 1000000,
16
+ "maxTokens": 16384,
17
+ "compat": {
18
+ "maxTokensField": "max_completion_tokens",
19
+ "supportsDeveloperRole": false,
20
+ "supportsStore": false,
21
+ "supportsZdr": true
22
+ }
23
+ },
24
+ {
25
+ "id": "deepseek-v4-pro",
26
+ "name": "Deepseek V4 Pro",
27
+ "reasoning": false,
28
+ "input": [
29
+ "text"
30
+ ],
31
+ "cost": {
32
+ "input": 0,
33
+ "output": 0,
34
+ "cacheRead": 0,
35
+ "cacheWrite": 0
36
+ },
37
+ "contextWindow": 1000000,
38
+ "maxTokens": 16384,
39
+ "compat": {
40
+ "maxTokensField": "max_completion_tokens",
41
+ "supportsDeveloperRole": false,
42
+ "supportsStore": false,
43
+ "supportsZdr": true
44
+ }
45
+ },
46
+ {
47
+ "id": "GLM-5.1",
48
+ "name": "GLM 5.1",
49
+ "reasoning": false,
50
+ "input": [
51
+ "text"
52
+ ],
53
+ "cost": {
54
+ "input": 1.5,
55
+ "output": 4.5,
56
+ "cacheRead": 0.15,
57
+ "cacheWrite": 0
58
+ },
59
+ "contextWindow": 202752,
60
+ "maxTokens": 32768,
61
+ "compat": {
62
+ "maxTokensField": "max_completion_tokens",
63
+ "supportsDeveloperRole": false,
64
+ "supportsZdr": true
65
+ }
66
+ },
67
+ {
68
+ "id": "GLM-5.2",
69
+ "name": "GLM 5.2",
70
+ "reasoning": false,
71
+ "input": [
72
+ "text"
73
+ ],
74
+ "cost": {
75
+ "input": 0,
76
+ "output": 0,
77
+ "cacheRead": 0,
78
+ "cacheWrite": 0
79
+ },
80
+ "contextWindow": 1048576,
81
+ "maxTokens": 16384,
82
+ "compat": {
83
+ "maxTokensField": "max_completion_tokens",
84
+ "supportsDeveloperRole": false,
85
+ "supportsStore": false,
86
+ "supportsZdr": true
87
+ }
88
+ },
89
+ {
90
+ "id": "Kimi-K2.6",
91
+ "name": "Kimi K2.6",
92
+ "reasoning": false,
93
+ "input": [
94
+ "text"
95
+ ],
96
+ "cost": {
97
+ "input": 1.1,
98
+ "output": 4.8,
99
+ "cacheRead": 0.11,
100
+ "cacheWrite": 0
101
+ },
102
+ "contextWindow": 262144,
103
+ "maxTokens": 32768,
104
+ "compat": {
105
+ "maxTokensField": "max_completion_tokens",
106
+ "supportsDeveloperRole": false,
107
+ "supportsZdr": false
108
+ }
109
+ },
110
+ {
111
+ "id": "Kimi-K2.7-Code",
112
+ "name": "Kimi K2.7 Code",
113
+ "reasoning": false,
114
+ "input": [
115
+ "text"
116
+ ],
117
+ "cost": {
118
+ "input": 0,
119
+ "output": 0,
120
+ "cacheRead": 0,
121
+ "cacheWrite": 0
122
+ },
123
+ "contextWindow": 262144,
124
+ "maxTokens": 16384,
125
+ "compat": {
126
+ "maxTokensField": "max_completion_tokens",
127
+ "supportsDeveloperRole": false,
128
+ "supportsStore": false,
129
+ "supportsZdr": false
130
+ }
131
+ },
132
+ {
133
+ "id": "MiniMax-M3",
134
+ "name": "MiniMax M3",
135
+ "reasoning": false,
136
+ "input": [
137
+ "text"
138
+ ],
139
+ "cost": {
140
+ "input": 0,
141
+ "output": 0,
142
+ "cacheRead": 0,
143
+ "cacheWrite": 0
144
+ },
145
+ "contextWindow": 1048576,
146
+ "maxTokens": 16384,
147
+ "compat": {
148
+ "maxTokensField": "max_completion_tokens",
149
+ "supportsDeveloperRole": false,
150
+ "supportsStore": false,
151
+ "supportsZdr": false
152
+ }
153
+ },
154
+ {
155
+ "id": "Qwen3.5-397B-A17B",
156
+ "name": "Qwen 3.5 397B (A17B)",
157
+ "reasoning": false,
158
+ "input": [
159
+ "text",
160
+ "image"
161
+ ],
162
+ "cost": {
163
+ "input": 0.6,
164
+ "output": 3.6,
165
+ "cacheRead": 0.06,
166
+ "cacheWrite": 0
167
+ },
168
+ "contextWindow": 262144,
169
+ "maxTokens": 32768,
170
+ "compat": {
171
+ "maxTokensField": "max_completion_tokens",
172
+ "supportsDeveloperRole": false,
173
+ "supportsZdr": false
174
+ }
175
+ },
176
+ {
177
+ "id": "Qwen3.6-35B-A3B",
178
+ "name": "Qwen3.6 35B A3B",
179
+ "reasoning": false,
180
+ "input": [
181
+ "text"
182
+ ],
183
+ "cost": {
184
+ "input": 0,
185
+ "output": 0,
186
+ "cacheRead": 0,
187
+ "cacheWrite": 0
188
+ },
189
+ "contextWindow": 256000,
190
+ "maxTokens": 16384,
191
+ "compat": {
192
+ "maxTokensField": "max_completion_tokens",
193
+ "supportsDeveloperRole": false,
194
+ "supportsStore": false,
195
+ "supportsZdr": false
196
+ }
197
+ },
198
+ {
199
+ "id": "qwen3.7-max",
200
+ "name": "Qwen3.7 Max",
201
+ "reasoning": false,
202
+ "input": [
203
+ "text"
204
+ ],
205
+ "cost": {
206
+ "input": 0,
207
+ "output": 0,
208
+ "cacheRead": 0,
209
+ "cacheWrite": 0
210
+ },
211
+ "contextWindow": 256000,
212
+ "maxTokens": 16384,
213
+ "compat": {
214
+ "maxTokensField": "max_completion_tokens",
215
+ "supportsDeveloperRole": false,
216
+ "supportsStore": false,
217
+ "supportsZdr": false
218
+ }
219
+ }
220
+ ]
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "pi-wafer-provider",
3
+ "version": "1.0.2",
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
+ "type": "module",
6
+ "main": "index.ts",
7
+ "keywords": [
8
+ "pi",
9
+ "extension",
10
+ "provider",
11
+ "wafer",
12
+ "wafer-serverless",
13
+ "ai",
14
+ "llm",
15
+ "qwen",
16
+ "glm"
17
+ ],
18
+ "author": "",
19
+ "license": "MIT",
20
+ "pi": {
21
+ "extensions": [
22
+ "./index.ts"
23
+ ]
24
+ },
25
+ "scripts": {
26
+ "clean": "echo 'nothing to clean'",
27
+ "build": "echo 'nothing to build'",
28
+ "check": "echo 'nothing to check'",
29
+ "update-models": "node scripts/update-models.js"
30
+ }
31
+ }
package/patch.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "Qwen3.5-397B-A17B": {
3
+ "providers": ["wafer-serverless"],
4
+ "reasoning": true,
5
+ "compat": {
6
+ "thinkingFormat": "qwen",
7
+ "maxTokensField": "max_completion_tokens",
8
+ "supportsDeveloperRole": false,
9
+ "supportsReasoningEffort": true
10
+ }
11
+ },
12
+ "GLM-5.1": {
13
+ "providers": ["wafer-serverless"],
14
+ "reasoning": true,
15
+ "compat": {
16
+ "thinkingFormat": "zai",
17
+ "maxTokensField": "max_completion_tokens",
18
+ "supportsDeveloperRole": false,
19
+ "supportsReasoningEffort": true
20
+ }
21
+ },
22
+ "Kimi-K2.6": {
23
+ "providers": ["wafer-serverless"],
24
+ "reasoning": true,
25
+ "compat": {
26
+ "maxTokensField": "max_completion_tokens",
27
+ "supportsDeveloperRole": false,
28
+ "supportsReasoningEffort": true
29
+ }
30
+ },
31
+ "Qwen3.6-35B-A3B": {
32
+ "providers": ["wafer-serverless"],
33
+ "reasoning": true,
34
+ "compat": {
35
+ "thinkingFormat": "qwen",
36
+ "maxTokensField": "max_completion_tokens",
37
+ "supportsDeveloperRole": false,
38
+ "supportsReasoningEffort": true
39
+ }
40
+ },
41
+ "deepseek-v4-flash": {
42
+ "providers": ["wafer-serverless"],
43
+ "reasoning": true,
44
+ "compat": {
45
+ "thinkingFormat": "deepseek",
46
+ "maxTokensField": "max_completion_tokens",
47
+ "supportsDeveloperRole": false,
48
+ "supportsReasoningEffort": true
49
+ }
50
+ },
51
+ "deepseek-v4-pro": {
52
+ "providers": ["wafer-serverless"],
53
+ "reasoning": true,
54
+ "contextWindow": 1000000,
55
+ "maxTokens": 384000,
56
+ "thinkingLevelMap": {
57
+ "minimal": null,
58
+ "low": null,
59
+ "medium": null,
60
+ "high": "high",
61
+ "xhigh": "max"
62
+ },
63
+ "compat": {
64
+ "thinkingFormat": "deepseek",
65
+ "maxTokensField": "max_completion_tokens",
66
+ "supportsDeveloperRole": false,
67
+ "supportsReasoningEffort": true
68
+ }
69
+ },
70
+ "qwen3.7-max": {
71
+ "providers": ["wafer-serverless"],
72
+ "reasoning": true,
73
+ "cost": {
74
+ "input": 5.0,
75
+ "output": 15.0,
76
+ "cacheRead": 0.5,
77
+ "cacheWrite": 0
78
+ },
79
+ "compat": {
80
+ "thinkingFormat": "qwen",
81
+ "maxTokensField": "max_completion_tokens",
82
+ "supportsDeveloperRole": false,
83
+ "supportsReasoningEffort": true
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * E2E test for Kimi K2.6 on Wafer (pass.wafer.ai).
4
+ *
5
+ * Tests:
6
+ * 1. Basic streaming with reasoning prompt (delta.reasoning / reasoning_content)
7
+ * 2. Non-streaming (reasoning_content structure)
8
+ * 3. Preserved Thinking via thinking.keep="all"
9
+ * 4. Preserved Thinking via chat_template_kwargs
10
+ */
11
+
12
+ const API_KEY = process.env.WAFER_SERVERLESS_API_KEY || process.env.WAFER_API_KEY;
13
+ const MODEL = process.env.MODEL || "Kimi-K2.6";
14
+ const BASE_URL = "https://pass.wafer.ai/v1/chat/completions";
15
+
16
+ if (!API_KEY) {
17
+ console.error("โŒ WAFER_SERVERLESS_API_KEY (or WAFER_API_KEY) is not set.");
18
+ process.exit(1);
19
+ }
20
+
21
+ async function streamRequest(label, body) {
22
+ console.log(`\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
23
+ console.log(` TEST: ${label}`);
24
+ console.log(` Model: ${MODEL}`);
25
+ console.log(` Base URL: ${BASE_URL}`);
26
+ console.log(`โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
27
+
28
+ const res = await fetch(BASE_URL, {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ Authorization: `Bearer ${API_KEY}`,
33
+ "Wafer-ZDR": "required",
34
+ },
35
+ body: JSON.stringify(body),
36
+ });
37
+
38
+ if (!res.ok) {
39
+ const text = await res.text();
40
+ console.error(`โŒ HTTP ${res.status}: ${text}`);
41
+ return { ok: false, error: text };
42
+ }
43
+
44
+ const reader = res.body.getReader();
45
+ const decoder = new TextDecoder();
46
+ let buffer = "";
47
+
48
+ let reasoningChunks = [];
49
+ let contentChunks = [];
50
+ let hasDone = false;
51
+
52
+ try {
53
+ while (true) {
54
+ const { done, value } = await reader.read();
55
+ if (done) break;
56
+
57
+ buffer += decoder.decode(value, { stream: true });
58
+ const lines = buffer.split("\n");
59
+ buffer = lines.pop() || "";
60
+
61
+ for (const line of lines) {
62
+ const trimmed = line.trim();
63
+ if (trimmed.startsWith("data: ")) {
64
+ const payload = trimmed.slice(6);
65
+ if (payload === "[DONE]") {
66
+ hasDone = true;
67
+ continue;
68
+ }
69
+ try {
70
+ const obj = JSON.parse(payload);
71
+ const delta = obj.choices?.[0]?.delta || {};
72
+ if (delta.reasoning) reasoningChunks.push(delta.reasoning);
73
+ if (delta.content) contentChunks.push(delta.content);
74
+ } catch {}
75
+ }
76
+ }
77
+ }
78
+ } catch (e) {
79
+ console.error(`๐Ÿ’ฅ Stream error: ${e.message}`);
80
+ } finally {
81
+ reader.releaseLock();
82
+ }
83
+
84
+ console.log(` Reasoning chunks: ${reasoningChunks.length}`);
85
+ console.log(` Content chunks: ${contentChunks.length}`);
86
+ console.log(` [DONE] seen: ${hasDone}`);
87
+
88
+ if (reasoningChunks.length > 0) {
89
+ console.log(`\n --- First reasoning chunk ---`);
90
+ console.log(` ${reasoningChunks[0].substring(0, 200)}`);
91
+ }
92
+ if (contentChunks.length > 0) {
93
+ const fullContent = contentChunks.join("");
94
+ console.log(`\n --- Final content (first 300 chars) ---`);
95
+ console.log(` ${fullContent.substring(0, 300)}`);
96
+ }
97
+
98
+ return { ok: true, reasoning: reasoningChunks, content: contentChunks };
99
+ }
100
+
101
+ async function nonStreamRequest(label, body) {
102
+ console.log(`\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
103
+ console.log(` TEST: ${label}`);
104
+ console.log(` Model: ${MODEL}`);
105
+ console.log(` Base URL: ${BASE_URL}`);
106
+ console.log(`โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
107
+
108
+ const res = await fetch(BASE_URL, {
109
+ method: "POST",
110
+ headers: {
111
+ "Content-Type": "application/json",
112
+ Authorization: `Bearer ${API_KEY}`,
113
+ "Wafer-ZDR": "required",
114
+ },
115
+ body: JSON.stringify(body),
116
+ });
117
+
118
+ const data = await res.json();
119
+
120
+ if (!res.ok) {
121
+ console.error(`โŒ HTTP ${res.status}: ${JSON.stringify(data)}`);
122
+ return { ok: false, error: data };
123
+ }
124
+
125
+ const choice = data.choices?.[0];
126
+ const msg = choice?.message || {};
127
+
128
+ console.log(` keys: ${JSON.stringify(Object.keys(msg))}`);
129
+ console.log(` has reasoning_content: ${"reasoning_content" in msg}`);
130
+ console.log(` has reasoning: ${"reasoning" in msg}`);
131
+ if (msg.reasoning_content) {
132
+ console.log(` reasoning_content len: ${msg.reasoning_content.length}`);
133
+ console.log(` --- reasoning_content (first 300) ---`);
134
+ console.log(` ${msg.reasoning_content.substring(0, 300)}`);
135
+ }
136
+ if (msg.reasoning) {
137
+ console.log(` reasoning: ${msg.reasoning.substring(0, 300)}`);
138
+ }
139
+ console.log(` content: ${(msg.content || "").substring(0, 300)}`);
140
+ console.log(` usage: ${JSON.stringify(data.usage)}`);
141
+
142
+ return { ok: true, message: msg, usage: data.usage };
143
+ }
144
+
145
+ async function main() {
146
+ console.log(`E2E Testing Kimi K2.6 on Wafer`);
147
+ console.log(`Base URL: ${BASE_URL}`);
148
+
149
+ // Test 1: Basic streaming
150
+ await streamRequest("Basic stream (reasoning prompt)", {
151
+ model: MODEL,
152
+ messages: [{ role: "user", content: "What is 13 ร— 17? Show your reasoning." }],
153
+ max_tokens: 500,
154
+ stream: true,
155
+ });
156
+
157
+ // Test 2: Non-streaming
158
+ await nonStreamRequest("Non-stream (inspect structure)", {
159
+ model: MODEL,
160
+ messages: [{ role: "user", content: "What is 13 ร— 17? Show your reasoning." }],
161
+ max_tokens: 500,
162
+ stream: false,
163
+ });
164
+
165
+ // Test 3: Preserved Thinking via extra_body thinking.keep
166
+ const r3 = await streamRequest("Stream with thinking.keep='all' (extra_body)", {
167
+ model: MODEL,
168
+ messages: [
169
+ { role: "user", content: "Tell me three random numbers." },
170
+ {
171
+ role: "assistant",
172
+ reasoning_content: "I generated five numbers and told the first three: 473, 921, 235, and the other two were 215, 222.",
173
+ content: "473, 921, 235",
174
+ },
175
+ { role: "user", content: "What are the other two numbers you have in mind?" },
176
+ ],
177
+ max_tokens: 500,
178
+ stream: true,
179
+ extra_body: { thinking: { type: "enabled", keep: "all" } },
180
+ });
181
+
182
+ if (r3.ok && r3.content.length > 0) {
183
+ const fullContent = r3.content.join("");
184
+ const got215 = fullContent.includes("215");
185
+ const got222 = fullContent.includes("222");
186
+ console.log(`\n ๐Ÿงช Preserved Thinking (extra_body) check: mentions 215=${got215}, mentions 222=${got222}`);
187
+ }
188
+
189
+ // Test 4: Preserved Thinking via chat_template_kwargs
190
+ const r4 = await streamRequest("Stream with chat_template_kwargs preserve_thinking", {
191
+ model: MODEL,
192
+ messages: [
193
+ { role: "user", content: "Tell me three random numbers." },
194
+ {
195
+ role: "assistant",
196
+ reasoning_content: "I generated five numbers and told the first three: 473, 921, 235, and kept 215 and 222 hidden.",
197
+ content: "473, 921, 235",
198
+ },
199
+ { role: "user", content: "What are the other two numbers you have in mind?" },
200
+ ],
201
+ max_tokens: 500,
202
+ stream: true,
203
+ extra_body: { chat_template_kwargs: { thinking: true, preserve_thinking: true } },
204
+ });
205
+
206
+ if (r4.ok && r4.content.length > 0) {
207
+ const fullContent = r4.content.join("");
208
+ const got215 = fullContent.includes("215");
209
+ const got222 = fullContent.includes("222");
210
+ console.log(`\n ๐Ÿงช Preserved Thinking (chat_template_kwargs) check: mentions 215=${got215}, mentions 222=${got222}`);
211
+ }
212
+
213
+ console.log(`\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
214
+ console.log(` E2E Test Complete`);
215
+ console.log(`โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
216
+ }
217
+
218
+ main().catch((e) => { console.error(e); process.exit(1); });