pi-io-provider 1.1.47 → 1.1.49
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/CHANGELOG.md +6 -0
- package/README.md +14 -14
- package/bun.lock +9 -9
- package/models.json +44 -44
- package/package.json +2 -2
- package/scripts/test-pi-compat.mjs +85 -46
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.48
|
|
4
|
+
|
|
5
|
+
- Pin Pi SDK development dependencies to 1.0.0 while retaining wildcard host peers.
|
|
6
|
+
- Verify real manifest loading, provider catalogs, startup/shutdown and native/bundled Pi hosts offline.
|
|
7
|
+
- Exercise real transport adapters with Unicode text, tool calls, empty responses, usage, request hooks and cancellation; no live provider calls.
|
|
8
|
+
|
|
3
9
|
## 1.1.45
|
|
4
10
|
|
|
5
11
|
- Test against Pi 0.99.0 and declare host-provided modules as wildcard peers.
|
package/README.md
CHANGED
|
@@ -16,38 +16,38 @@ A [pi](https://github.com/badlogic/pi-mono) extension that adds [IO Intelligence
|
|
|
16
16
|
|
|
17
17
|
| Model | ID | Context | Max Output | Vision | Reasoning | Cache | Input $/M | Output $/M |
|
|
18
18
|
|-------|----|---------|------------|--------|-----------|-------|-----------|------------|
|
|
19
|
-
| DeepSeek V4.1 Flash | `deepseek-ai/DeepSeek-V4.1-Flash` | 1.0M | 131K | ✅ | ✅ | ✅ | $0.
|
|
20
|
-
| Gemma 4 26B A4B | `google/gemma-4-26b-a4b-it` | 262K | 262K | ✅ | ✅ | ✅ | $0.08 | $0.
|
|
19
|
+
| DeepSeek V4.1 Flash | `deepseek-ai/DeepSeek-V4.1-Flash` | 1.0M | 131K | ✅ | ✅ | ✅ | $0.34 | $1.38 |
|
|
20
|
+
| Gemma 4 26B A4B | `google/gemma-4-26b-a4b-it` | 262K | 262K | ✅ | ✅ | ✅ | $0.08 | $0.30 |
|
|
21
21
|
| Gemma 4 31B Instruct | `google/gemma-4-31b-it` | 262K | 16K | ✅ | ✅ | ✅ | $0.38 | $1.15 |
|
|
22
22
|
| Kimi K2.5 | `moonshotai/Kimi-K2.5` | 262K | 262K | ✅ | ✅ | ✅ | $0.53 | $2.79 |
|
|
23
23
|
| Kimi K2.6 | `moonshotai/Kimi-K2.6` | 262K | 262K | ✅ | ✅ | ✅ | $0.79 | $3.49 |
|
|
24
24
|
| Kimi K2.7 Code | `moonshotai/Kimi-K2.7-Code` | 262K | 262K | ✅ | ✅ | ✅ | $1.08 | $4.67 |
|
|
25
|
-
| Kimi K3 | `moonshotai/Kimi-K3` | 1.0M | 1.0M | ✅ | ✅ | ✅ | $3.
|
|
25
|
+
| Kimi K3 | `moonshotai/Kimi-K3` | 1.0M | 1.0M | ✅ | ✅ | ✅ | $3.26 | $16.30 |
|
|
26
26
|
| Qwen3.6 27B | `Qwen/Qwen3.6-27B` | 33K | 33K | ✅ | ✅ | ✅ | $0.34 | $3.01 |
|
|
27
27
|
| Qwen3.6 35B A3B | `Qwen/Qwen3.6-35B-A3B` | 262K | 262K | ✅ | ✅ | ✅ | $0.18 | $1.26 |
|
|
28
28
|
| Qwen3.8 27B | `Qwen/Qwen3.8-27B` | 66K | 66K | ✅ | ✅ | ✅ | $0.34 | $2.69 |
|
|
29
29
|
| GLM 5.3 Flash | `zai-org/GLM-5.3-Flash` | 262K | 131K | ✅ | ✅ | ✅ | $0.21 | $0.70 |
|
|
30
30
|
| DeepSeek R1 0528 | `deepseek-ai/DeepSeek-R1-0528` | 128K | 128K | ❌ | ✅ | ✅ | $0.57 | $2.28 |
|
|
31
31
|
| DeepSeek V3.2 | `deepseek-ai/DeepSeek-V3.2` | 164K | 164K | ❌ | ✅ | ✅ | $1.42 | $2.38 |
|
|
32
|
-
| DeepSeek V4 Flash | `deepseek-ai/DeepSeek-V4-Flash` | 33K | 33K | ❌ | ✅ | ✅ | $0.
|
|
33
|
-
| DeepSeek V4 Flash 0731 | `deepseek-ai/DeepSeek-V4-Flash-0731` | 262K | 66K | ❌ | ✅ | ✅ | $0.
|
|
34
|
-
| DeepSeek V4 Pro | `deepseek-ai/DeepSeek-V4-Pro` | 1.0M | 600K | ❌ | ✅ | ✅ | $1.
|
|
35
|
-
| DeepSeek V4 Pro 0813 | `deepseek-ai/DeepSeek-V4-Pro-0813` | 1.0M | 393K | ❌ | ✅ | ✅ | $0.
|
|
32
|
+
| DeepSeek V4 Flash | `deepseek-ai/DeepSeek-V4-Flash` | 33K | 33K | ❌ | ✅ | ✅ | $0.11 | $0.51 |
|
|
33
|
+
| DeepSeek V4 Flash 0731 | `deepseek-ai/DeepSeek-V4-Flash-0731` | 262K | 66K | ❌ | ✅ | ✅ | $0.20 | $0.70 |
|
|
34
|
+
| DeepSeek V4 Pro | `deepseek-ai/DeepSeek-V4-Pro` | 1.0M | 600K | ❌ | ✅ | ✅ | $1.37 | $3.32 |
|
|
35
|
+
| DeepSeek V4 Pro 0813 | `deepseek-ai/DeepSeek-V4-Pro-0813` | 1.0M | 393K | ❌ | ✅ | ✅ | $0.89 | $3.77 |
|
|
36
36
|
| MiniMax M2.5 | `MiniMaxAI/MiniMax-M2.5` | 197K | 197K | ❌ | ✅ | ✅ | $0.29 | $1.18 |
|
|
37
|
-
| MiniMax M2.7 | `MiniMaxAI/MiniMax-M2.7` | 262K | 66K | ❌ | ✅ | ✅ | $0.40 | $1.
|
|
37
|
+
| MiniMax M2.7 | `MiniMaxAI/MiniMax-M2.7` | 262K | 66K | ❌ | ✅ | ✅ | $0.40 | $1.46 |
|
|
38
38
|
| Kimi K2 Thinking | `moonshotai/Kimi-K2-Thinking` | 262K | 262K | ❌ | ✅ | ✅ | $0.60 | $2.50 |
|
|
39
39
|
| Nemotron 3.5 Lightning | `nvidia/nemotron-3.5-lightning` | 262K | 131K | ❌ | ✅ | ✅ | $0.06 | $0.18 |
|
|
40
|
-
| gpt-oss-120b | `openai/gpt-oss-120b` | 131K | 131K | ❌ | ✅ | ✅ | $0.
|
|
41
|
-
| gpt-oss-20b | `openai/gpt-oss-20b` | 64K | 64K | ❌ | ✅ | ✅ | $0.06 | $0.
|
|
40
|
+
| gpt-oss-120b | `openai/gpt-oss-120b` | 131K | 131K | ❌ | ✅ | ✅ | $0.17 | $0.63 |
|
|
41
|
+
| gpt-oss-20b | `openai/gpt-oss-20b` | 64K | 64K | ❌ | ✅ | ✅ | $0.06 | $0.20 |
|
|
42
42
|
| MiMo-V2.5 | `XiaomiMiMo/MiMo-V2.5` | 1.0M | 1.0M | ❌ | ✅ | ✅ | $0.20 | $0.64 |
|
|
43
43
|
| GLM-4.5-Air | `zai-org/GLM-4.5-Air` | 131K | 131K | ❌ | ✅ | ✅ | $0.16 | $0.94 |
|
|
44
44
|
| GLM 4.6 | `zai-org/GLM-4.6` | 131K | 131K | ❌ | ✅ | ✅ | $0.52 | $2.04 |
|
|
45
45
|
| GLM 4.7 | `zai-org/GLM-4.7` | 203K | 203K | ❌ | ✅ | ✅ | $0.52 | $2.05 |
|
|
46
46
|
| GLM 4.7 Flash | `zai-org/GLM-4.7-Flash` | 200K | 200K | ❌ | ✅ | ✅ | $0.06 | $0.40 |
|
|
47
|
-
| GLM 5 | `zai-org/GLM-5` | 203K | 203K | ❌ | ✅ | ✅ | $0.
|
|
48
|
-
| GLM 5.1 | `zai-org/GLM-5.1` | 203K | 33K | ❌ | ✅ | ✅ | $1.
|
|
49
|
-
| GLM 5.2 | `zai-org/GLM-5.2` | 262K | 131K | ❌ | ✅ | ✅ | $1.
|
|
50
|
-
| GLM 5.3 | `zai-org/GLM-5.3` | 262K | 131K | ❌ | ✅ | ✅ | $1.
|
|
47
|
+
| GLM 5 | `zai-org/GLM-5` | 203K | 203K | ❌ | ✅ | ✅ | $0.78 | $2.50 |
|
|
48
|
+
| GLM 5.1 | `zai-org/GLM-5.1` | 203K | 33K | ❌ | ✅ | ✅ | $1.27 | $3.99 |
|
|
49
|
+
| GLM 5.2 | `zai-org/GLM-5.2` | 262K | 131K | ❌ | ✅ | ✅ | $1.49 | $5.48 |
|
|
50
|
+
| GLM 5.3 | `zai-org/GLM-5.3` | 262K | 131K | ❌ | ✅ | ✅ | $1.47 | $4.62 |
|
|
51
51
|
| Llama 4 Maverick 17B 128E Instruct FP8 | `meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8` | 430K | 430K | ✅ | ❌ | ✅ | $0.25 | $0.83 |
|
|
52
52
|
| Qwen3 Coder 480B A35B Instruct INT4 Mixed AR | `Intel/Qwen3-Coder-480B-A35B-Instruct-int4-mixed-ar` | 106K | 106K | ❌ | ❌ | ✅ | $0.45 | $2.15 |
|
|
53
53
|
| Llama 3.3 70B Instruct | `meta-llama/Llama-3.3-70B-Instruct` | 128K | 128K | ❌ | ❌ | ✅ | $0.57 | $1.06 |
|
package/bun.lock
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "pi-io-provider",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
8
|
+
"@earendil-works/pi-coding-agent": "1.0.0",
|
|
9
9
|
"@types/node": "^25.9.1",
|
|
10
10
|
"typescript": "6.0.3",
|
|
11
11
|
},
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
|
|
58
58
|
"@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="],
|
|
59
59
|
|
|
60
|
-
"@earendil-works/chord": ["@earendil-works/chord@0.
|
|
60
|
+
"@earendil-works/chord": ["@earendil-works/chord@1.0.0", "", { "dependencies": { "esbuild": "0.28.2" } }, "sha512-BIfWfrByM0pKq6tfKYXuwx0ed2CvaqIM3EDA7Dps+fP+d3CiPWdlHi1cDsJC05llqKJoRz5//G0hz0yQwwjISQ=="],
|
|
61
61
|
|
|
62
|
-
"@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@0.
|
|
62
|
+
"@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@1.0.0", "", { "dependencies": { "@earendil-works/pi-ai": "^1.0.0", "typebox": "1.3.27" } }, "sha512-bHFONjtEBDqiV+g1DmmtkSlfAaqHELr+XO+6I5Nah4gswwZrLJO4yZB/JjsnlI4AKWTayBLfgS6DCbeBBz9e2Q=="],
|
|
63
63
|
|
|
64
|
-
"@earendil-works/pi-ai": ["@earendil-works/pi-ai@0.
|
|
64
|
+
"@earendil-works/pi-ai": ["@earendil-works/pi-ai@1.0.0", "", { "dependencies": { "@anthropic-ai/sdk": "0.124.0", "@aws-sdk/client-bedrock-runtime": "3.1127.0", "@earendil-works/pi-telemetry": "^1.0.0", "@google/genai": "2.21.0", "@smithy/node-http-handler": "4.12.1", "http-proxy-agent": "9.1.0", "https-proxy-agent": "9.1.0", "openai": "7.19.0", "partial-json": "0.1.7", "typebox": "1.3.27" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-3/W1vdDaVtpeMd23ElvJC12HLA5yS/BGqqcXF+0SK082dN7cbgNcCwguTBRBC258Ke8SzSvUW1B75iAf8w8IxA=="],
|
|
65
65
|
|
|
66
|
-
"@earendil-works/pi-codemode": ["@earendil-works/pi-codemode@0.
|
|
66
|
+
"@earendil-works/pi-codemode": ["@earendil-works/pi-codemode@1.0.0", "", { "dependencies": { "quickjs-wasi": "3.6.2" } }, "sha512-LPpFI4+T9NzDnhBDs15izWAolaoM8xnwqdziRd6Zx8BQeoEPvzefD2vMMzSyF0rOtq34TfQqkZ0ki16f6cGdMg=="],
|
|
67
67
|
|
|
68
|
-
"@earendil-works/pi-coding-agent": ["@earendil-works/pi-coding-agent@0.
|
|
68
|
+
"@earendil-works/pi-coding-agent": ["@earendil-works/pi-coding-agent@1.0.0", "", { "dependencies": { "@earendil-works/chord": "^1.0.0", "@earendil-works/pi-agent-core": "^1.0.0", "@earendil-works/pi-ai": "^1.0.0", "@earendil-works/pi-codemode": "^1.0.0", "@earendil-works/pi-mcp": "^1.0.0", "@earendil-works/pi-tui": "^1.0.0", "@silvia-odwyer/photon-node": "0.3.4", "chalk": "6.0.0", "cross-spawn": "7.0.6", "diff": "8.0.4", "grok-mermaid": "0.2.3", "highlight.js": "10.7.3", "hosted-git-info": "9.0.3", "ignore": "7.0.8", "jiti": "2.7.0", "minimatch": "10.2.6", "proper-lockfile": "4.1.2", "quickjs-wasi": "3.6.2", "semver": "7.8.5", "typebox": "1.3.27", "undici": "8.10.2", "yaml": "2.9.0" }, "bin": { "pi": "dist/bundle/cli.js" } }, "sha512-/FtbxoSQU/mEv1QnichJjRjqteqaIaMWxmhB4G367+MwZfX7/DI5B9YAg5lqbN7nztFskBEtUSZ+FlmMBECtMw=="],
|
|
69
69
|
|
|
70
|
-
"@earendil-works/pi-mcp": ["@earendil-works/pi-mcp@0.
|
|
70
|
+
"@earendil-works/pi-mcp": ["@earendil-works/pi-mcp@1.0.0", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-rYra0aF5iPmJd+fsB+VBuqxWNABGJ3Iiyhg0CqIc/91ta2n7IvQmCp0Cac/YkUTNnvRsVZnjgAiBkRi6+ouWuw=="],
|
|
71
71
|
|
|
72
|
-
"@earendil-works/pi-telemetry": ["@earendil-works/pi-telemetry@0.
|
|
72
|
+
"@earendil-works/pi-telemetry": ["@earendil-works/pi-telemetry@1.0.0", "", {}, "sha512-WjNBj5TYIiPZFQEz2WlULcDwPLaKwIlmsKjVeYM+LJSbnSp38kWsHUJysIDGnu23IcLbKoPtywsvYfUJCeZePA=="],
|
|
73
73
|
|
|
74
|
-
"@earendil-works/pi-tui": ["@earendil-works/pi-tui@0.
|
|
74
|
+
"@earendil-works/pi-tui": ["@earendil-works/pi-tui@1.0.0", "", { "dependencies": { "get-east-asian-width": "1.6.0", "marked": "18.0.11" } }, "sha512-JsT7kXnpZA2YOtQu6RyriyxEO0eJIzPyfiH09bH+OLN5+s18HYkwaUD/tBkjhnSfMu6/50CQPRYJagzSP6HdPw=="],
|
|
75
75
|
|
|
76
76
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="],
|
|
77
77
|
|
package/models.json
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"image"
|
|
9
9
|
],
|
|
10
10
|
"cost": {
|
|
11
|
-
"input": 0.
|
|
12
|
-
"output": 1.
|
|
13
|
-
"cacheRead": 0.
|
|
11
|
+
"input": 0.34494,
|
|
12
|
+
"output": 1.37976,
|
|
13
|
+
"cacheRead": 0.17247,
|
|
14
14
|
"cacheWrite": 0
|
|
15
15
|
},
|
|
16
16
|
"contextWindow": 1048320,
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"text"
|
|
54
54
|
],
|
|
55
55
|
"cost": {
|
|
56
|
-
"input": 1.
|
|
57
|
-
"output":
|
|
58
|
-
"cacheRead": 0.
|
|
56
|
+
"input": 1.47,
|
|
57
|
+
"output": 4.62,
|
|
58
|
+
"cacheRead": 0.735,
|
|
59
59
|
"cacheWrite": 0
|
|
60
60
|
},
|
|
61
61
|
"contextWindow": 262144,
|
|
@@ -98,9 +98,9 @@
|
|
|
98
98
|
"text"
|
|
99
99
|
],
|
|
100
100
|
"cost": {
|
|
101
|
-
"input": 0.
|
|
102
|
-
"output": 0.
|
|
103
|
-
"cacheRead": 0.
|
|
101
|
+
"input": 0.2026,
|
|
102
|
+
"output": 0.7028,
|
|
103
|
+
"cacheRead": 0.1013,
|
|
104
104
|
"cacheWrite": 0
|
|
105
105
|
},
|
|
106
106
|
"contextWindow": 262100,
|
|
@@ -121,9 +121,9 @@
|
|
|
121
121
|
"image"
|
|
122
122
|
],
|
|
123
123
|
"cost": {
|
|
124
|
-
"input": 3.
|
|
125
|
-
"output": 16.
|
|
126
|
-
"cacheRead": 1.
|
|
124
|
+
"input": 3.26,
|
|
125
|
+
"output": 16.3,
|
|
126
|
+
"cacheRead": 1.63,
|
|
127
127
|
"cacheWrite": 0
|
|
128
128
|
},
|
|
129
129
|
"contextWindow": 1048576,
|
|
@@ -165,9 +165,9 @@
|
|
|
165
165
|
"text"
|
|
166
166
|
],
|
|
167
167
|
"cost": {
|
|
168
|
-
"input": 1.
|
|
169
|
-
"output":
|
|
170
|
-
"cacheRead": 0.
|
|
168
|
+
"input": 1.49498,
|
|
169
|
+
"output": 5.478,
|
|
170
|
+
"cacheRead": 0.74749,
|
|
171
171
|
"cacheWrite": 0
|
|
172
172
|
},
|
|
173
173
|
"contextWindow": 262144,
|
|
@@ -256,9 +256,9 @@
|
|
|
256
256
|
"text"
|
|
257
257
|
],
|
|
258
258
|
"cost": {
|
|
259
|
-
"input": 0.
|
|
260
|
-
"output": 1.
|
|
261
|
-
"cacheRead": 0.
|
|
259
|
+
"input": 0.396,
|
|
260
|
+
"output": 1.464,
|
|
261
|
+
"cacheRead": 0.198,
|
|
262
262
|
"cacheWrite": 0
|
|
263
263
|
},
|
|
264
264
|
"contextWindow": 262100,
|
|
@@ -278,9 +278,9 @@
|
|
|
278
278
|
"text"
|
|
279
279
|
],
|
|
280
280
|
"cost": {
|
|
281
|
-
"input": 0.
|
|
282
|
-
"output": 0.
|
|
283
|
-
"cacheRead": 0.
|
|
281
|
+
"input": 0.113008,
|
|
282
|
+
"output": 0.509296,
|
|
283
|
+
"cacheRead": 0.056504,
|
|
284
284
|
"cacheWrite": 0
|
|
285
285
|
},
|
|
286
286
|
"contextWindow": 32768,
|
|
@@ -300,9 +300,9 @@
|
|
|
300
300
|
"text"
|
|
301
301
|
],
|
|
302
302
|
"cost": {
|
|
303
|
-
"input": 1.
|
|
304
|
-
"output": 3.
|
|
305
|
-
"cacheRead": 0.
|
|
303
|
+
"input": 1.3656,
|
|
304
|
+
"output": 3.322,
|
|
305
|
+
"cacheRead": 0.6828,
|
|
306
306
|
"cacheWrite": 0
|
|
307
307
|
},
|
|
308
308
|
"contextWindow": 1048576,
|
|
@@ -345,9 +345,9 @@
|
|
|
345
345
|
"text"
|
|
346
346
|
],
|
|
347
347
|
"cost": {
|
|
348
|
-
"input": 1.
|
|
349
|
-
"output":
|
|
350
|
-
"cacheRead": 0.
|
|
348
|
+
"input": 1.27092,
|
|
349
|
+
"output": 3.99432,
|
|
350
|
+
"cacheRead": 0.63546,
|
|
351
351
|
"cacheWrite": 0
|
|
352
352
|
},
|
|
353
353
|
"contextWindow": 202750,
|
|
@@ -367,9 +367,9 @@
|
|
|
367
367
|
"text"
|
|
368
368
|
],
|
|
369
369
|
"cost": {
|
|
370
|
-
"input": 0.
|
|
370
|
+
"input": 0.293,
|
|
371
371
|
"output": 1.176,
|
|
372
|
-
"cacheRead": 0.
|
|
372
|
+
"cacheRead": 0.1465,
|
|
373
373
|
"cacheWrite": 0
|
|
374
374
|
},
|
|
375
375
|
"contextWindow": 196600,
|
|
@@ -412,9 +412,9 @@
|
|
|
412
412
|
"text"
|
|
413
413
|
],
|
|
414
414
|
"cost": {
|
|
415
|
-
"input": 0.
|
|
416
|
-
"output": 2.
|
|
417
|
-
"cacheRead": 0.
|
|
415
|
+
"input": 0.78,
|
|
416
|
+
"output": 2.496,
|
|
417
|
+
"cacheRead": 0.39,
|
|
418
418
|
"cacheWrite": 0
|
|
419
419
|
},
|
|
420
420
|
"contextWindow": 202752,
|
|
@@ -501,9 +501,9 @@
|
|
|
501
501
|
"image"
|
|
502
502
|
],
|
|
503
503
|
"cost": {
|
|
504
|
-
"input": 0.
|
|
505
|
-
"output": 0.
|
|
506
|
-
"cacheRead": 0.
|
|
504
|
+
"input": 0.0813,
|
|
505
|
+
"output": 0.305,
|
|
506
|
+
"cacheRead": 0.04065,
|
|
507
507
|
"cacheWrite": 0
|
|
508
508
|
},
|
|
509
509
|
"contextWindow": 262142,
|
|
@@ -588,9 +588,9 @@
|
|
|
588
588
|
"text"
|
|
589
589
|
],
|
|
590
590
|
"cost": {
|
|
591
|
-
"input": 0.
|
|
592
|
-
"output": 0.
|
|
593
|
-
"cacheRead": 0.
|
|
591
|
+
"input": 0.168,
|
|
592
|
+
"output": 0.63,
|
|
593
|
+
"cacheRead": 0.084,
|
|
594
594
|
"cacheWrite": 0.04
|
|
595
595
|
},
|
|
596
596
|
"contextWindow": 131072,
|
|
@@ -739,9 +739,9 @@
|
|
|
739
739
|
"text"
|
|
740
740
|
],
|
|
741
741
|
"cost": {
|
|
742
|
-
"input": 0.
|
|
743
|
-
"output": 0.
|
|
744
|
-
"cacheRead": 0.
|
|
742
|
+
"input": 0.063,
|
|
743
|
+
"output": 0.196,
|
|
744
|
+
"cacheRead": 0.0315,
|
|
745
745
|
"cacheWrite": 0.03
|
|
746
746
|
},
|
|
747
747
|
"contextWindow": 64000,
|
|
@@ -782,9 +782,9 @@
|
|
|
782
782
|
"text"
|
|
783
783
|
],
|
|
784
784
|
"cost": {
|
|
785
|
-
"input": 0.
|
|
786
|
-
"output": 3.
|
|
787
|
-
"cacheRead": 0.
|
|
785
|
+
"input": 0.89358,
|
|
786
|
+
"output": 3.774,
|
|
787
|
+
"cacheRead": 0.44679,
|
|
788
788
|
"cacheWrite": 0
|
|
789
789
|
},
|
|
790
790
|
"contextWindow": 1048576,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-io-provider",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.49",
|
|
4
4
|
"description": "IO Intelligence provider extension for pi - Access DeepSeek, Kimi, GLM, Llama, Qwen, Mistral, and more through the IO Intelligence API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
]
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
30
|
+
"@earendil-works/pi-coding-agent": "1.0.0",
|
|
31
31
|
"typescript": "6.0.3",
|
|
32
32
|
"@types/node": "^25.9.1"
|
|
33
33
|
},
|
|
@@ -1,76 +1,115 @@
|
|
|
1
|
+
// Offline Pi 1.0 manifest, lifecycle, catalog and real transport regression.
|
|
1
2
|
import assert from 'node:assert/strict';
|
|
2
3
|
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
3
4
|
import { tmpdir } from 'node:os';
|
|
4
5
|
import { dirname, join, resolve } from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
7
|
|
|
7
|
-
// Import Pi only after selecting a disposable agent directory. Never read user auth/cache.
|
|
8
8
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
9
|
const home = await mkdtemp(join(tmpdir(), 'pi-provider-compat-'));
|
|
10
10
|
const previousHome = process.env.PI_CODING_AGENT_DIR;
|
|
11
11
|
const previousFetch = globalThis.fetch;
|
|
12
12
|
process.env.PI_CODING_AGENT_DIR = home;
|
|
13
|
+
// Never allow a background catalog/account request to reach a real endpoint.
|
|
13
14
|
globalThis.fetch = async () => new Response('', { status: 503 });
|
|
14
15
|
let session;
|
|
15
16
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
17
|
+
const host = process.env.PI1_HOST_PACKAGE;
|
|
18
|
+
const hostEntry = process.env.PI1_HOST_ENTRY === 'bundle' ? 'dist/bundle/index.js' : 'dist/index.js';
|
|
19
|
+
const sdk = await import(host ? pathToFileURL(join(host, hostEntry)).href : '@earendil-works/pi-coding-agent');
|
|
20
|
+
const { createAgentSession, DefaultResourceLoader, ModelRuntime, SessionManager, SettingsManager, VERSION } = sdk;
|
|
21
|
+
assert.equal(VERSION, '1.0.0', 'executing host version');
|
|
22
|
+
assert.equal((await import('@earendil-works/pi-coding-agent')).VERSION, '1.0.0', 'development host version');
|
|
18
23
|
const manifest = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
assert.equal(manifest.dependencies?.[name], undefined, `${name} must not be installed as a runtime dependency`);
|
|
24
|
+
for (const name of ['@earendil-works/pi-ai', '@earendil-works/pi-agent-core', '@earendil-works/pi-coding-agent', '@earendil-works/pi-tui', 'typebox']) {
|
|
25
|
+
assert.equal(manifest.dependencies?.[name], undefined, `${name}: do not bundle host packages`);
|
|
22
26
|
if (manifest.peerDependencies?.[name] !== undefined) assert.equal(manifest.peerDependencies[name], '*');
|
|
27
|
+
if (name !== 'typebox' && manifest.devDependencies?.[name]) assert.equal(manifest.devDependencies[name], '1.0.0');
|
|
23
28
|
}
|
|
24
|
-
const settingsManager = SettingsManager.inMemory({ compaction: { enabled: false }, retry: { enabled: false } });
|
|
25
|
-
const resourceLoader = new DefaultResourceLoader({
|
|
26
|
-
|
|
27
|
-
additionalExtensionPaths: [join(root, 'index.ts')],
|
|
28
|
-
noSkills: true, noPromptTemplates: true, noThemes: true, noContextFiles: true,
|
|
29
|
-
});
|
|
29
|
+
const settingsManager = SettingsManager.inMemory({ packages: [root], compaction: { enabled: false }, retry: { enabled: false } });
|
|
30
|
+
const resourceLoader = new DefaultResourceLoader({ cwd: home, agentDir: home, settingsManager,
|
|
31
|
+
noSkills: true, noPromptTemplates: true, noThemes: true, noContextFiles: true });
|
|
30
32
|
await resourceLoader.reload();
|
|
31
33
|
const loaded = resourceLoader.getExtensions();
|
|
32
|
-
assert.deepEqual(loaded.errors, []
|
|
33
|
-
assert.deepEqual(loaded.warnings ?? [], []
|
|
34
|
-
assert.equal(loaded.extensions.length,
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
assert.deepEqual(loaded.errors, []);
|
|
35
|
+
assert.deepEqual(loaded.warnings ?? [], []);
|
|
36
|
+
assert.equal(loaded.extensions.length, manifest.pi.extensions.length, 'all manifest entrypoints load');
|
|
37
|
+
// Endpoint/header-only re-registration (e.g. MCR) retains the prior catalog.
|
|
38
|
+
const registrations = [...loaded.runtime.pendingProviderRegistrations.reduce((byName, { name, config }) =>
|
|
39
|
+
byName.set(name, { name, config: { ...byName.get(name)?.config, ...config } }), new Map()).values()];
|
|
40
|
+
assert(registrations.length > 0, 'providers register before session startup');
|
|
37
41
|
const modelRuntime = await ModelRuntime.create({ authPath: join(home, 'auth.json'), modelsPath: null, modelsStorePath: join(home, 'models-cache'), allowModelNetwork: false });
|
|
38
|
-
({ session } = await createAgentSession({ cwd: home, agentDir: home, resourceLoader, modelRuntime, settingsManager, sessionManager: SessionManager.inMemory(home)
|
|
42
|
+
({ session } = await createAgentSession({ cwd: home, agentDir: home, resourceLoader, modelRuntime, settingsManager, sessionManager: SessionManager.inMemory(home) }));
|
|
39
43
|
const errors = [];
|
|
40
|
-
await session.bindExtensions({ mode: 'print', onError:
|
|
41
|
-
await new Promise(
|
|
42
|
-
|
|
44
|
+
await session.bindExtensions({ mode: 'print', onError: error => errors.push(error) });
|
|
45
|
+
await new Promise(done => setImmediate(done));
|
|
46
|
+
const tools = new Set();
|
|
47
|
+
for (const extension of loaded.extensions) for (const [name, { definition }] of extension.tools) {
|
|
48
|
+
assert.equal(definition.name, name); assert.equal(typeof definition.execute, 'function');
|
|
49
|
+
assert.equal(typeof definition.parameters, 'object'); assert(!tools.has(name)); tools.add(name);
|
|
50
|
+
assert(session.getAllTools().some(tool => tool.name === name));
|
|
51
|
+
}
|
|
52
|
+
let modelCount = 0, streamChecks = 0;
|
|
43
53
|
for (const { name, config } of registrations) {
|
|
44
54
|
const models = modelRuntime.getAllModels(name);
|
|
45
|
-
assert.equal(models.length, config.models.length, `${name}:
|
|
46
|
-
assert
|
|
47
|
-
assert.equal(new Set(models.map(
|
|
55
|
+
assert.equal(models.length, config.models.length, `${name}: catalog survives registration`);
|
|
56
|
+
assert(models.length > 0);
|
|
57
|
+
assert.equal(new Set(models.map(m => `${m.type}/${m.id}`)).size, models.length);
|
|
48
58
|
for (const model of models) {
|
|
49
|
-
assert.equal(model.provider, name);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
for (const cost of Object.values(model.cost)) assert.ok(Number.isFinite(cost) && cost >= 0);
|
|
59
|
+
assert.equal(model.provider, name); assert(model.api && model.baseUrl && model.id && model.name);
|
|
60
|
+
if (model.type === 'image') assert(model.output.includes('image'));
|
|
61
|
+
else assert(model.contextWindow > 0);
|
|
62
|
+
if ((model.type ?? 'chat') === 'chat') assert(model.maxTokens > 0);
|
|
63
|
+
assert(model.input.includes('text'));
|
|
64
|
+
for (const cost of Object.values(model.cost)) assert(Number.isFinite(cost) && cost >= 0);
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
const chatModels = modelRuntime.getModels(name);
|
|
67
|
+
const model = chatModels.find(m => m.api === 'openai-completions') ?? chatModels[0];
|
|
68
|
+
assert(model, 'a chat model is available for offline transport checks');
|
|
69
|
+
const user = { role: 'user', content: 'hello', timestamp: 1 };
|
|
70
|
+
async function probe(tool = false, empty = false) {
|
|
71
|
+
let payloadCalls = 0, responseCalls = 0, observed = 0, wire;
|
|
72
|
+
const fetch = async (_url, init) => {
|
|
73
|
+
wire = JSON.parse(init.body);
|
|
74
|
+
const delta = tool ? { tool_calls: [{ index: 0, id: 'call_probe', type: 'function', function: { name: 'probe', arguments: '{"value":7}' } }] } : { content: empty ? '' : 'Hello 界' };
|
|
75
|
+
const chunks = [{ id: 'offline', choices: [{ index: 0, delta: { role: 'assistant', ...delta }, finish_reason: null }] }, { id: 'offline', choices: [{ index: 0, delta: {}, finish_reason: tool ? 'tool_calls' : 'stop' }], usage: { prompt_tokens: 10, completion_tokens: 2, total_tokens: 12 } }];
|
|
76
|
+
return new Response(chunks.map(c => `data: ${JSON.stringify(c)}\n\n`).join('') + 'data: [DONE]\n\n', { headers: { 'content-type': 'text/event-stream' } });
|
|
77
|
+
};
|
|
78
|
+
const stream = modelRuntime.streamSimple(model, { messages: [{ role: 'system', content: 'Offline probe', toolsAdded: [{ name: 'probe', description: 'Probe', parameters: { type: 'object', properties: { value: { type: 'integer' } }, required: ['value'] } }], timestamp: 0 }, user] }, {
|
|
79
|
+
apiKey: 'offline-placeholder', maxTokens: 32, maxRetries: 0, fetch,
|
|
80
|
+
onPayload: p => { payloadCalls++; return { ...p, temperature: 0.123 }; },
|
|
81
|
+
onResponse: () => { responseCalls++; }, onProviderStreamEvent: () => { observed++; },
|
|
82
|
+
});
|
|
83
|
+
const events = []; for await (const event of stream) events.push(event.type);
|
|
84
|
+
const result = await stream.result();
|
|
85
|
+
assert.equal(result.stopReason, tool ? 'toolUse' : 'stop', result.errorMessage);
|
|
86
|
+
assert.equal(events.filter(e => e === 'start').length, 1);
|
|
87
|
+
assert.equal(events.filter(e => e === 'done' || e === 'error').length, 1);
|
|
88
|
+
assert.equal(events.at(-1), 'done');
|
|
89
|
+
assert.equal(payloadCalls, 1); assert.equal(responseCalls, 1); assert(observed >= 2);
|
|
90
|
+
assert.equal(wire.temperature, 0.123); assert.equal(wire.tools[0].function.name, 'probe');
|
|
91
|
+
assert.equal(result.usage.totalTokens, 12);
|
|
92
|
+
if (tool) assert.deepEqual(result.content.find(c => c.type === 'toolCall').arguments, { value: 7 });
|
|
93
|
+
else if (!empty) assert.equal(result.content.find(c => c.type === 'text').text, 'Hello 界');
|
|
94
|
+
streamChecks++;
|
|
64
95
|
}
|
|
96
|
+
await probe(); await probe(true); await probe(false, true);
|
|
97
|
+
// Abort after preflight: the SDK's lazy preflight reports an already-aborted
|
|
98
|
+
// auth operation as an error; this checks provider transport cancellation.
|
|
99
|
+
const controller = new AbortController();
|
|
100
|
+
const aborted = await modelRuntime.streamSimple(model, { messages: [user] }, {
|
|
101
|
+
apiKey: 'offline-placeholder', signal: controller.signal, maxRetries: 0,
|
|
102
|
+
onPayload: () => { controller.abort(); },
|
|
103
|
+
fetch: async () => { throw new DOMException('Aborted', 'AbortError'); },
|
|
104
|
+
}).result();
|
|
105
|
+
assert.equal(aborted.stopReason, 'aborted', aborted.errorMessage); streamChecks++;
|
|
65
106
|
modelCount += models.length;
|
|
66
107
|
}
|
|
67
|
-
await session.extensionRunner.emit({ type: 'session_shutdown' });
|
|
68
|
-
assert.deepEqual(errors, []
|
|
69
|
-
console.log(
|
|
108
|
+
await session.extensionRunner.emit({ type: 'session_shutdown', reason: 'quit' });
|
|
109
|
+
assert.deepEqual(errors, []);
|
|
110
|
+
console.log(JSON.stringify({ repo: manifest.name, pi: VERSION, hostEntry, extensions: loaded.extensions.length, tools: tools.size, models: modelCount, streamChecks, lifecycle: 'passed' }));
|
|
70
111
|
} finally {
|
|
71
|
-
session?.dispose();
|
|
72
|
-
|
|
73
|
-
if (previousHome === undefined) delete process.env.PI_CODING_AGENT_DIR;
|
|
74
|
-
else process.env.PI_CODING_AGENT_DIR = previousHome;
|
|
112
|
+
session?.dispose(); globalThis.fetch = previousFetch;
|
|
113
|
+
if (previousHome === undefined) delete process.env.PI_CODING_AGENT_DIR; else process.env.PI_CODING_AGENT_DIR = previousHome;
|
|
75
114
|
await rm(home, { recursive: true, force: true });
|
|
76
115
|
}
|