@aliou/pi-synthetic 0.13.5 → 0.14.0

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Pi Synthetic Extension
4
4
 
5
- A Pi extension that adds [Synthetic](https://synthetic.new) as a model provider, giving you access to open-source models through an OpenAI-compatible API.
5
+ A Pi extension that adds [Synthetic](https://synthetic.new) as a model provider, giving you access to open-source models through Synthetic's OpenAI-compatible API.
6
6
 
7
7
  ## Installation
8
8
 
@@ -52,6 +52,12 @@ Once installed, select `synthetic` as your provider and choose from available mo
52
52
  /model synthetic hf:moonshotai/Kimi-K2.5
53
53
  ```
54
54
 
55
+ ### Model Hosting
56
+
57
+ All models are accessed through Synthetic's API. Some models are hosted by Synthetic directly; others are proxied by Synthetic to upstream backends such as Fireworks or Together.
58
+
59
+ The code tracks this in `src/extensions/provider/models.ts` with each model's `provider` field. That field is for maintenance only and is stripped before registering models with Pi, so users always select the `synthetic` provider.
60
+
55
61
  ### Web Search Tool
56
62
 
57
63
  The extension registers `synthetic_web_search` — a zero-data-retention web search tool. The tool is always visible; it fails with a clear message if credentials are missing or the account lacks a subscription.
@@ -89,21 +95,22 @@ The extension automatically notifies you when you approach or exceed your Synthe
89
95
 
90
96
  ## Disabling Features
91
97
 
92
- Each feature (provider, web search, quotas command, usage status, quota warnings) is a separate Pi extension. You can disable individual features using `pi config`:
98
+ Each feature (provider, web search, quotas command, sub bar integration, usage status, quota warnings) is a separate Pi extension. You can disable individual features using `pi config`:
93
99
 
94
100
  ```
95
101
  pi config extensions.disabled add @aliou/pi-synthetic/quota-warnings
96
102
  ```
97
103
 
98
- This prevents the quota-warnings extension from loading while keeping the rest of pi-synthetic active. Replace `quota-warnings` with `web-search`, `command-quotas`, or `provider` to disable other features.
104
+ This prevents the quota-warnings extension from loading while keeping the rest of pi-synthetic active. Replace `quota-warnings` with `web-search`, `command-quotas`, `sub-bar-integration`, `usage-status`, or `provider` to disable other features.
99
105
 
100
106
  ## Adding or Updating Models
101
107
 
102
- Models are hardcoded in `src/providers/models.ts`. To add or update models:
108
+ Models are hardcoded in `src/extensions/provider/models.ts`. To add or update models:
103
109
 
104
- 1. Edit `src/providers/models.ts`
110
+ 1. Edit `src/extensions/provider/models.ts`
105
111
  2. Add the model configuration following the `SyntheticModelConfig` interface
106
- 3. Run `pnpm run typecheck` to verify
112
+ 3. Set `provider` to the upstream backend Synthetic uses for that model, such as `synthetic`, `fireworks`, or `together`
113
+ 4. Run `pnpm run typecheck` to verify
107
114
 
108
115
  ## Development
109
116
 
@@ -156,7 +163,7 @@ This repository uses [Changesets](https://github.com/changesets/changesets) for
156
163
 
157
164
  ## Requirements
158
165
 
159
- - Pi coding agent v0.50.0+
166
+ - Pi coding agent v0.72.0+
160
167
  - Synthetic API key (configured in `~/.pi/agent/auth.json` or via `SYNTHETIC_API_KEY`)
161
168
 
162
169
  ## Links
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-synthetic",
3
- "version": "0.13.5",
3
+ "version": "0.14.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,
@@ -32,8 +32,8 @@
32
32
  "README.md"
33
33
  ],
34
34
  "peerDependencies": {
35
- "@mariozechner/pi-coding-agent": "0.61.0",
36
- "@mariozechner/pi-tui": "0.61.0"
35
+ "@mariozechner/pi-coding-agent": "0.72.0",
36
+ "@mariozechner/pi-tui": "0.72.0"
37
37
  },
38
38
  "dependencies": {
39
39
  "@aliou/pi-utils-settings": "^0.13.0",
@@ -43,8 +43,8 @@
43
43
  "@aliou/biome-plugins": "^0.7.0",
44
44
  "@biomejs/biome": "^2.4.2",
45
45
  "@changesets/cli": "^2.27.11",
46
- "@mariozechner/pi-coding-agent": "0.61.0",
47
- "@sinclair/typebox": "^0.34.48",
46
+ "@mariozechner/pi-coding-agent": "0.72.0",
47
+ "typebox": "^1.1.37",
48
48
  "@types/node": "^25.0.10",
49
49
  "husky": "^9.1.7",
50
50
  "typescript": "^5.9.3",
@@ -9,14 +9,6 @@ export interface SyntheticModelConfig extends ProviderModelConfig {
9
9
  provider: string;
10
10
  }
11
11
 
12
- const SYNTHETIC_REASONING_EFFORT_MAP = {
13
- minimal: "low",
14
- low: "low",
15
- medium: "medium",
16
- high: "high",
17
- xhigh: "high",
18
- } as const;
19
-
20
12
  export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
21
13
  // API: hf:zai-org/GLM-4.7 → ctx=202752
22
14
  {
@@ -24,9 +16,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
24
16
  name: "zai-org/GLM-4.7",
25
17
  provider: "synthetic",
26
18
  reasoning: true,
19
+ thinkingLevelMap: { minimal: null, xhigh: null },
27
20
  compat: {
28
21
  supportsReasoningEffort: true,
29
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
30
22
  },
31
23
  input: ["text"],
32
24
  cost: {
@@ -44,9 +36,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
44
36
  name: "zai-org/GLM-5",
45
37
  provider: "synthetic",
46
38
  reasoning: true,
39
+ thinkingLevelMap: { minimal: null, xhigh: null },
47
40
  compat: {
48
41
  supportsReasoningEffort: true,
49
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
50
42
  },
51
43
  input: ["text"],
52
44
  cost: {
@@ -64,9 +56,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
64
56
  name: "zai-org/GLM-5.1",
65
57
  provider: "synthetic",
66
58
  reasoning: true,
59
+ thinkingLevelMap: { minimal: null, xhigh: null },
67
60
  compat: {
68
61
  supportsReasoningEffort: true,
69
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
70
62
  supportsDeveloperRole: false,
71
63
  },
72
64
  input: ["text"],
@@ -85,9 +77,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
85
77
  name: "zai-org/GLM-4.7-Flash",
86
78
  provider: "synthetic",
87
79
  reasoning: true,
80
+ thinkingLevelMap: { minimal: null, xhigh: null },
88
81
  compat: {
89
82
  supportsReasoningEffort: true,
90
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
91
83
  },
92
84
  input: ["text"],
93
85
  cost: {
@@ -104,7 +96,7 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
104
96
  id: "hf:meta-llama/Llama-3.3-70B-Instruct",
105
97
  name: "meta-llama/Llama-3.3-70B-Instruct",
106
98
  provider: "together",
107
- reasoning: true,
99
+ reasoning: false,
108
100
  input: ["text"],
109
101
  cost: {
110
102
  input: 0.88,
@@ -121,10 +113,6 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
121
113
  name: "deepseek-ai/DeepSeek-R1-0528",
122
114
  provider: "together",
123
115
  reasoning: true,
124
- compat: {
125
- supportsReasoningEffort: true,
126
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
127
- },
128
116
  input: ["text"],
129
117
  cost: {
130
118
  input: 3,
@@ -173,10 +161,6 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
173
161
  name: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
174
162
  provider: "together",
175
163
  reasoning: true,
176
- compat: {
177
- supportsReasoningEffort: true,
178
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
179
- },
180
164
  input: ["text"],
181
165
  cost: {
182
166
  input: 2,
@@ -193,9 +177,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
193
177
  name: "moonshotai/Kimi-K2.6",
194
178
  provider: "synthetic",
195
179
  reasoning: true,
180
+ thinkingLevelMap: { minimal: null, low: null, xhigh: null },
196
181
  compat: {
197
182
  supportsReasoningEffort: true,
198
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
199
183
  },
200
184
  input: ["text", "image"],
201
185
  cost: {
@@ -207,16 +191,28 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
207
191
  contextWindow: 262144,
208
192
  maxTokens: 65536,
209
193
  },
194
+ // API: hf:moonshotai/Kimi-K2.5 → ctx=262144, out=65536
195
+ {
196
+ id: "hf:moonshotai/Kimi-K2.5",
197
+ name: "moonshotai/Kimi-K2.5",
198
+ provider: "together",
199
+ reasoning: true,
200
+ input: ["text", "image"],
201
+ cost: {
202
+ input: 0.5,
203
+ output: 2.8,
204
+ cacheRead: 0.5,
205
+ cacheWrite: 0,
206
+ },
207
+ contextWindow: 262144,
208
+ maxTokens: 65536,
209
+ },
210
210
  // API: hf:nvidia/Kimi-K2.5-NVFP4 → ctx=262144; models.dev: out=65536 (NVFP4 quantized)
211
211
  {
212
212
  id: "hf:nvidia/Kimi-K2.5-NVFP4",
213
213
  name: "nvidia/Kimi-K2.5-NVFP4",
214
214
  provider: "together",
215
215
  reasoning: true,
216
- compat: {
217
- supportsReasoningEffort: true,
218
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
219
- },
220
216
  input: ["text", "image"],
221
217
  cost: {
222
218
  input: 0.5,
@@ -249,10 +245,6 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
249
245
  name: "Qwen/Qwen3-235B-A22B-Thinking-2507",
250
246
  provider: "together",
251
247
  reasoning: true,
252
- compat: {
253
- supportsReasoningEffort: true,
254
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
255
- },
256
248
  input: ["text"],
257
249
  cost: {
258
250
  input: 0.65,
@@ -269,10 +261,6 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
269
261
  name: "Qwen/Qwen3.5-397B-A17B",
270
262
  provider: "together",
271
263
  reasoning: true,
272
- compat: {
273
- supportsReasoningEffort: true,
274
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
275
- },
276
264
  input: ["text", "image"],
277
265
  cost: {
278
266
  input: 0.6,
@@ -289,6 +277,7 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
289
277
  name: "MiniMaxAI/MiniMax-M2.5",
290
278
  provider: "synthetic",
291
279
  reasoning: true,
280
+ thinkingLevelMap: { off: null, minimal: null, low: null, xhigh: null },
292
281
  input: ["text"],
293
282
  cost: {
294
283
  input: 0.4,
@@ -300,7 +289,6 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
300
289
  maxTokens: 65536,
301
290
  compat: {
302
291
  supportsReasoningEffort: true,
303
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
304
292
  maxTokensField: "max_completion_tokens",
305
293
  },
306
294
  },
@@ -310,9 +298,9 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
310
298
  name: "nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4",
311
299
  provider: "synthetic",
312
300
  reasoning: true,
301
+ thinkingLevelMap: { minimal: null, low: null, xhigh: null },
313
302
  compat: {
314
303
  supportsReasoningEffort: true,
315
- reasoningEffortMap: SYNTHETIC_REASONING_EFFORT_MAP,
316
304
  },
317
305
  input: ["text"],
318
306
  cost: {
@@ -210,13 +210,20 @@ export default async function (pi: ExtensionAPI) {
210
210
  void refresher.refreshFor(ctx);
211
211
  });
212
212
 
213
- pi.on("session_switch", (_event, ctx) => {
214
- currentContext = ctx;
215
- currentProvider = ctx.model?.provider;
216
- if (enabled && ctx.model?.provider === "synthetic") {
217
- void refresher.refreshFor(ctx);
218
- } else {
219
- refresher.stopAutoRefresh(ctx);
213
+ pi.on("session_start", (event, ctx) => {
214
+ // Handle session switches (model_select handles mid-session provider changes)
215
+ if (
216
+ event.reason === "new" ||
217
+ event.reason === "resume" ||
218
+ event.reason === "fork"
219
+ ) {
220
+ currentContext = ctx;
221
+ currentProvider = ctx.model?.provider;
222
+ if (enabled && ctx.model?.provider === "synthetic") {
223
+ void refresher.refreshFor(ctx);
224
+ } else {
225
+ refresher.stopAutoRefresh(ctx);
226
+ }
220
227
  }
221
228
  });
222
229
 
@@ -8,7 +8,7 @@ import type {
8
8
  } from "@mariozechner/pi-coding-agent";
9
9
  import { getMarkdownTheme, keyHint } from "@mariozechner/pi-coding-agent";
10
10
  import { Container, Markdown, Text } from "@mariozechner/pi-tui";
11
- import { type Static, Type } from "@sinclair/typebox";
11
+ import { type Static, Type } from "typebox";
12
12
  import { configLoader } from "../../config";
13
13
  import { getSyntheticApiKey } from "../../lib/env";
14
14