@aliou/pi-synthetic 0.18.0 → 0.18.1

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
@@ -56,6 +56,8 @@ Once installed, select `synthetic` as your provider and choose from available mo
56
56
 
57
57
  All models are accessed through Synthetic's API. Some models are hosted by Synthetic directly (`provider: "synthetic"` in the model config); others are proxied by Synthetic to upstream backends such as Fireworks or Together.
58
58
 
59
+ Synthetic also provides permanent aliases (`syn:large:text`, `syn:small:text`, `syn:large:vision`, `syn:small:vision`) that route to the current best model for each category. These aliases are stable across model rotations — using an alias means no reconfiguration when models change. Alias models are always visible even when Proxied Models is disabled.
60
+
59
61
  By default, new installs show only Synthetic-hosted models. You can enable proxied models in `/synthetic:settings` under **Models > Proxied Models**. Existing configurations keep proxied models enabled to preserve prior behavior.
60
62
 
61
63
  The `provider` field in `src/extensions/provider/models.ts` is for maintenance only and is stripped before registering models with Pi, so users always select the `synthetic` provider.
@@ -109,13 +111,24 @@ The **Proxied Models** setting is not a loadable extension feature. It is a regu
109
111
 
110
112
  ## Adding or Updating Models
111
113
 
112
- Models are hardcoded in `src/extensions/provider/models.ts`. To add or update models:
114
+ Models are hardcoded in `src/extensions/provider/models.ts`. Entries are a union of concrete models and thin aliases (`syn:*` IDs).
115
+
116
+ ### Adding a concrete model
113
117
 
114
118
  1. Edit `src/extensions/provider/models.ts`
115
- 2. Add the model configuration following the `SyntheticModelConfig` interface
119
+ 2. Append a concrete model following the `SyntheticModelConfig` interface
116
120
  3. Set `provider` to the upstream backend Synthetic uses for that model, such as `synthetic`, `fireworks`, or `together`
117
121
  4. Run `pnpm run typecheck` to verify
118
122
 
123
+ ### Adding an alias model
124
+
125
+ 1. Add a thin `{ id, name, aliasFor }` entry at the top of `SYNTHETIC_MODELS`
126
+ 2. Set `id` and `name` from the Synthetic API
127
+ 3. Set `aliasFor` to `"hf:" + hugging_face_id` from the Synthetic API
128
+ 4. The resolved alias inherits all fields from the target at build time
129
+
130
+ When Synthetic changes which model an alias routes to, update only the `aliasFor` field.
131
+
119
132
  ## Development
120
133
 
121
134
  ### Setup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-synthetic",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,
@@ -28,19 +28,46 @@ import {
28
28
  } from "../../types/quotas";
29
29
  import { fetchQuotas } from "../../utils/quotas";
30
30
  import { SYNTHETIC_OVERFLOW_PATTERN } from "./context-overflow";
31
- import { SYNTHETIC_MODELS } from "./models";
31
+ import {
32
+ type ConcreteSyntheticModelConfig,
33
+ isAlias,
34
+ SYNTHETIC_MODELS,
35
+ } from "./models";
32
36
 
33
37
  export function buildSyntheticProviderModels(includeProxiedModels: boolean) {
34
- return SYNTHETIC_MODELS.filter(
35
- (model) => includeProxiedModels || model.provider === "synthetic",
36
- ).map(({ provider: _provider, ...model }) => ({
37
- ...model,
38
- compat: {
39
- supportsDeveloperRole: false,
40
- maxTokensField: "max_tokens" as const,
41
- ...model.compat,
42
- },
43
- }));
38
+ const concreteModels = SYNTHETIC_MODELS.filter(
39
+ (m): m is ConcreteSyntheticModelConfig => !isAlias(m),
40
+ );
41
+ const byId = new Map(concreteModels.map((m) => [m.id, m]));
42
+
43
+ const resolved = SYNTHETIC_MODELS.map((entry) => {
44
+ if (!isAlias(entry)) return entry;
45
+
46
+ const target = byId.get(entry.aliasFor);
47
+ if (!target) {
48
+ throw new Error(
49
+ `Synthetic alias "${entry.id}" references missing model "${entry.aliasFor}"`,
50
+ );
51
+ }
52
+
53
+ return {
54
+ ...target,
55
+ id: entry.id,
56
+ name: entry.name,
57
+ provider: "synthetic" as const,
58
+ };
59
+ });
60
+
61
+ return resolved
62
+ .filter((model) => includeProxiedModels || model.provider === "synthetic")
63
+ .map(({ provider: _provider, ...model }) => ({
64
+ ...model,
65
+ compat: {
66
+ supportsDeveloperRole: false,
67
+ maxTokensField: "max_tokens" as const,
68
+ ...model.compat,
69
+ },
70
+ }));
44
71
  }
45
72
 
46
73
  interface RegisterSyntheticProviderOptions {
@@ -9,14 +9,68 @@ export interface SyntheticModelConfig extends ProviderModelConfig {
9
9
  provider: string;
10
10
  }
11
11
 
12
- export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
12
+ /** A thin alias that resolves to a concrete model at build time. */
13
+ export interface SyntheticModelAliasConfig {
14
+ id: string;
15
+ name: string;
16
+ /** Full model ID of the concrete target this alias resolves to. */
17
+ aliasFor: string;
18
+ }
19
+
20
+ /** Concrete model with full spec; aliases are excluded. */
21
+ export type ConcreteSyntheticModelConfig = SyntheticModelConfig & {
22
+ aliasFor?: never;
23
+ };
24
+
25
+ export function isAlias(
26
+ entry: ConcreteSyntheticModelConfig | SyntheticModelAliasConfig,
27
+ ): entry is SyntheticModelAliasConfig {
28
+ return "aliasFor" in entry;
29
+ }
30
+
31
+ export type SyntheticModelEntry =
32
+ | ConcreteSyntheticModelConfig
33
+ | SyntheticModelAliasConfig;
34
+
35
+ export const SYNTHETIC_MODELS: SyntheticModelEntry[] = [
36
+ // API: syn:large:text → alias for hf:zai-org/GLM-5.1
37
+ {
38
+ id: "syn:large:text",
39
+ name: "syn:large:text",
40
+ aliasFor: "hf:zai-org/GLM-5.1",
41
+ },
42
+ // API: syn:small:text → alias for hf:zai-org/GLM-4.7-Flash
43
+ {
44
+ id: "syn:small:text",
45
+ name: "syn:small:text",
46
+ aliasFor: "hf:zai-org/GLM-4.7-Flash",
47
+ },
48
+ // API: syn:large:vision → alias for hf:moonshotai/Kimi-K2.6
49
+ {
50
+ id: "syn:large:vision",
51
+ name: "syn:large:vision",
52
+ aliasFor: "hf:moonshotai/Kimi-K2.6",
53
+ },
54
+ // API: syn:small:vision → alias for hf:moonshotai/Kimi-K2.6
55
+ {
56
+ id: "syn:small:vision",
57
+ name: "syn:small:vision",
58
+ aliasFor: "hf:moonshotai/Kimi-K2.6",
59
+ },
13
60
  // API: hf:zai-org/GLM-4.7 → ctx=202752
14
61
  {
15
62
  id: "hf:zai-org/GLM-4.7",
16
63
  name: "zai-org/GLM-4.7",
17
64
  provider: "synthetic",
18
65
  reasoning: true,
19
- thinkingLevelMap: { minimal: null, xhigh: null },
66
+ thinkingLevelMap: {
67
+ off: "none",
68
+ minimal: null,
69
+ low: null,
70
+ medium: "medium",
71
+ high: null,
72
+ xhigh: null,
73
+ },
20
74
  compat: {
21
75
  supportsReasoningEffort: true,
22
76
  },
@@ -36,7 +90,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
36
90
  name: "zai-org/GLM-5",
37
91
  provider: "synthetic",
38
92
  reasoning: true,
39
- thinkingLevelMap: { minimal: null, xhigh: null },
93
+ thinkingLevelMap: {
94
+ off: "none",
95
+ minimal: null,
96
+ low: null,
97
+ medium: "medium",
98
+ high: null,
99
+ xhigh: null,
100
+ },
40
101
  compat: {
41
102
  supportsReasoningEffort: true,
42
103
  },
@@ -56,7 +117,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
56
117
  name: "zai-org/GLM-5.1",
57
118
  provider: "synthetic",
58
119
  reasoning: true,
59
- thinkingLevelMap: { minimal: null, xhigh: null },
120
+ thinkingLevelMap: {
121
+ off: "none",
122
+ minimal: null,
123
+ low: null,
124
+ medium: "medium",
125
+ high: null,
126
+ xhigh: null,
127
+ },
60
128
  compat: {
61
129
  supportsReasoningEffort: true,
62
130
  supportsDeveloperRole: false,
@@ -77,7 +145,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
77
145
  name: "zai-org/GLM-4.7-Flash",
78
146
  provider: "synthetic",
79
147
  reasoning: true,
80
- thinkingLevelMap: { minimal: null, xhigh: null },
148
+ thinkingLevelMap: {
149
+ off: "none",
150
+ minimal: null,
151
+ low: null,
152
+ medium: "medium",
153
+ high: null,
154
+ xhigh: null,
155
+ },
81
156
  compat: {
82
157
  supportsReasoningEffort: true,
83
158
  },
@@ -97,6 +172,17 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
97
172
  name: "deepseek-ai/DeepSeek-V3.2",
98
173
  provider: "fireworks",
99
174
  reasoning: true,
175
+ thinkingLevelMap: {
176
+ off: "none",
177
+ minimal: null,
178
+ low: null,
179
+ medium: "medium",
180
+ high: null,
181
+ xhigh: null,
182
+ },
183
+ compat: {
184
+ supportsReasoningEffort: true,
185
+ },
100
186
  input: ["text"],
101
187
  cost: {
102
188
  input: 0.56,
@@ -145,7 +231,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
145
231
  name: "moonshotai/Kimi-K2.6",
146
232
  provider: "synthetic",
147
233
  reasoning: true,
148
- thinkingLevelMap: { minimal: null, low: null, xhigh: null },
234
+ thinkingLevelMap: {
235
+ off: "none",
236
+ minimal: null,
237
+ low: null,
238
+ medium: "medium",
239
+ high: null,
240
+ xhigh: null,
241
+ },
149
242
  compat: {
150
243
  supportsReasoningEffort: true,
151
244
  },
@@ -165,6 +258,17 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
165
258
  name: "Qwen/Qwen3.5-397B-A17B",
166
259
  provider: "together",
167
260
  reasoning: true,
261
+ thinkingLevelMap: {
262
+ off: "none",
263
+ minimal: null,
264
+ low: null,
265
+ medium: "medium",
266
+ high: null,
267
+ xhigh: null,
268
+ },
269
+ compat: {
270
+ supportsReasoningEffort: true,
271
+ },
168
272
  input: ["text", "image"],
169
273
  cost: {
170
274
  input: 0.6,
@@ -181,7 +285,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
181
285
  name: "MiniMaxAI/MiniMax-M2.5",
182
286
  provider: "synthetic",
183
287
  reasoning: true,
184
- thinkingLevelMap: { off: null, minimal: null, low: null, xhigh: null },
288
+ thinkingLevelMap: {
289
+ off: null,
290
+ minimal: null,
291
+ low: null,
292
+ medium: "medium",
293
+ high: null,
294
+ xhigh: null,
295
+ },
185
296
  input: ["text"],
186
297
  cost: {
187
298
  input: 0.4,
@@ -202,7 +313,14 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
202
313
  name: "nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4",
203
314
  provider: "synthetic",
204
315
  reasoning: true,
205
- thinkingLevelMap: { minimal: null, low: null, xhigh: null },
316
+ thinkingLevelMap: {
317
+ off: "none",
318
+ minimal: null,
319
+ low: null,
320
+ medium: "medium",
321
+ high: null,
322
+ xhigh: null,
323
+ },
206
324
  compat: {
207
325
  supportsReasoningEffort: true,
208
326
  },
@@ -216,85 +334,4 @@ export const SYNTHETIC_MODELS: SyntheticModelConfig[] = [
216
334
  contextWindow: 262144,
217
335
  maxTokens: 65536,
218
336
  },
219
- // API: syn:large:text → alias for hf:zai-org/GLM-5.1 → ctx=196608, out=65536
220
- {
221
- id: "syn:large:text",
222
- name: "syn:large:text",
223
- provider: "synthetic",
224
- reasoning: true,
225
- thinkingLevelMap: { minimal: null, xhigh: null },
226
- compat: {
227
- supportsReasoningEffort: true,
228
- supportsDeveloperRole: false,
229
- },
230
- input: ["text"],
231
- cost: {
232
- input: 1,
233
- output: 3,
234
- cacheRead: 1,
235
- cacheWrite: 0,
236
- },
237
- contextWindow: 196608,
238
- maxTokens: 65536,
239
- },
240
- // API: syn:small:text → alias for hf:zai-org/GLM-4.7-Flash → ctx=196608, out=65536
241
- {
242
- id: "syn:small:text",
243
- name: "syn:small:text",
244
- provider: "synthetic",
245
- reasoning: true,
246
- thinkingLevelMap: { minimal: null, xhigh: null },
247
- compat: {
248
- supportsReasoningEffort: true,
249
- },
250
- input: ["text"],
251
- cost: {
252
- input: 0.1,
253
- output: 0.5,
254
- cacheRead: 0.1,
255
- cacheWrite: 0,
256
- },
257
- contextWindow: 196608,
258
- maxTokens: 65536,
259
- },
260
- // API: syn:large:vision → alias for hf:moonshotai/Kimi-K2.6 → ctx=262144, out=65536
261
- {
262
- id: "syn:large:vision",
263
- name: "syn:large:vision",
264
- provider: "synthetic",
265
- reasoning: true,
266
- thinkingLevelMap: { minimal: null, low: null, xhigh: null },
267
- compat: {
268
- supportsReasoningEffort: true,
269
- },
270
- input: ["text", "image"],
271
- cost: {
272
- input: 0.95,
273
- output: 4,
274
- cacheRead: 0.95,
275
- cacheWrite: 0,
276
- },
277
- contextWindow: 262144,
278
- maxTokens: 65536,
279
- },
280
- // API: syn:small:vision → alias for hf:moonshotai/Kimi-K2.6 → ctx=262144, out=65536
281
- {
282
- id: "syn:small:vision",
283
- name: "syn:small:vision",
284
- provider: "synthetic",
285
- reasoning: true,
286
- thinkingLevelMap: { minimal: null, low: null, xhigh: null },
287
- compat: {
288
- supportsReasoningEffort: true,
289
- },
290
- input: ["text", "image"],
291
- cost: {
292
- input: 0.95,
293
- output: 4,
294
- cacheRead: 0.95,
295
- cacheWrite: 0,
296
- },
297
- contextWindow: 262144,
298
- maxTokens: 65536,
299
- },
300
337
  ];