@versini/sassysaint-common 4.13.0 → 4.14.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/dist/index.d.ts CHANGED
@@ -71,7 +71,7 @@ declare const PROVIDER_ROLE_MAP: {
71
71
  * versions change over time.
72
72
  */
73
73
  declare const APPROXIMATE_MODELS_PER_PROVIDER: {
74
- readonly Anthropic: readonly ["claude-sonnet-4", "claude-3"];
74
+ readonly Anthropic: readonly ["claude-sonnet-4", "claude-haiku-4", "claude-3"];
75
75
  readonly OpenAI: readonly ["gpt-", "o3", "o4"];
76
76
  readonly Google: readonly ["gemini"];
77
77
  readonly Perplexity: readonly ["sonar"];
@@ -178,6 +178,109 @@ declare const findProvider: (modelName: string) => null | typeof PROVIDER_ANTHRO
178
178
  *
179
179
  */
180
180
  declare const getProvidersFromModels: (models: string[]) => Array<typeof PROVIDER_OPENAI | typeof PROVIDER_ANTHROPIC | typeof PROVIDER_GOOGLE>;
181
+ /**
182
+ * Groups allowed models by their respective providers. This function is used to
183
+ * create nested menu structures in the UI where users can select specific
184
+ * models within each provider category.
185
+ *
186
+ * The function analyzes the given array of model names and organizes them into
187
+ * a map where keys are provider names and values are arrays of models available
188
+ * for that provider. Only models that exist in the MODELS_PER_PROVIDER mapping
189
+ * are included.
190
+ *
191
+ * @param models - Array of model names available to the user (e.g., from
192
+ * allowedModels in policy configuration).
193
+ * @returns Map where keys are provider names (PROVIDER_OPENAI,
194
+ * PROVIDER_ANTHROPIC, PROVIDER_GOOGLE) and values are arrays of model names
195
+ * available for that provider. Returns empty map if no models are provided.
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * // User has multiple models per provider:
200
+ * getModelsGroupedByProvider([MODEL_GPT5, MODEL_GPT5_MINI, MODEL_CLAUDE_HAIKU]);
201
+ * // Returns: Map {
202
+ * // "OpenAI" => ["gpt-5", "gpt-5-mini"],
203
+ * // "Anthropic" => ["claude-haiku-4-5-20251001"]
204
+ * // }
205
+ *
206
+ * // Single model per provider:
207
+ * getModelsGroupedByProvider([MODEL_GPT5, MODEL_CLAUDE_HAIKU]);
208
+ * // Returns: Map {
209
+ * // "OpenAI" => ["gpt-5"],
210
+ * // "Anthropic" => ["claude-haiku-4-5-20251001"]
211
+ * // }
212
+ *
213
+ * // Empty models array:
214
+ * getModelsGroupedByProvider([]);
215
+ * // Returns: Map {}
216
+ * ```
217
+ *
218
+ */
219
+ declare const getModelsGroupedByProvider: (models: string[]) => Map<string, string[]>;
220
+ /**
221
+ * Checks if the user has multiple models available for at least one provider.
222
+ * This function is used to determine if the nested model selection feature
223
+ * should be available to the user.
224
+ *
225
+ * The function groups models by provider and checks if any provider has more
226
+ * than one model. This enables the UI to conditionally show the nested model
227
+ * selection toggle only to users who would benefit from it.
228
+ *
229
+ * @param models - Array of model names available to the user (e.g., from
230
+ * allowedModels in policy configuration).
231
+ * @returns True if at least one provider has multiple models available, false
232
+ * otherwise.
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * // Premium plan with multiple models per provider:
237
+ * hasMultipleModelsPerProvider([MODEL_GPT5, MODEL_GPT5_MINI, MODEL_CLAUDE_HAIKU]);
238
+ * // Returns: true (OpenAI has 2 models)
239
+ *
240
+ * // Plus plan with one model per provider:
241
+ * hasMultipleModelsPerProvider([MODEL_GPT5_MINI, MODEL_CLAUDE_HAIKU, MODEL_GEMINI_FLASH]);
242
+ * // Returns: false (each provider has only 1 model)
243
+ *
244
+ * // Basic plan with single model:
245
+ * hasMultipleModelsPerProvider([MODEL_GPT5_NANO]);
246
+ * // Returns: false
247
+ * ```
248
+ *
249
+ */
250
+ declare const hasMultipleModelsPerProvider: (models: string[]) => boolean;
251
+ /**
252
+ * Validates if a selected model is allowed for the user based on their current
253
+ * plan's allowed models. This function is used to prevent users from using
254
+ * models they selected under a previous (higher) plan after downgrading.
255
+ *
256
+ * The function checks if the model exists in the user's allowedModels array.
257
+ * Returns false if the model is undefined, null, or not in the allowed list.
258
+ *
259
+ * @param selectedModel - The model the user has selected (may be null/undefined
260
+ * if no selection was made).
261
+ * @param allowedModels - Array of model names the user is entitled to use based
262
+ * on their current plan.
263
+ * @returns True if the selected model is in the allowed models list, false
264
+ * otherwise.
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * // User downgrades from Premium to Plus:
269
+ * const selectedModel = "gpt-4o"; // Was selected when user had Premium
270
+ * const allowedModels = ["gpt-4o-mini"]; // Plus plan only has mini model
271
+ * isModelAllowedForPlan(selectedModel, allowedModels); // Returns: false
272
+ *
273
+ * // Model is still allowed:
274
+ * isModelAllowedForPlan("gpt-4o-mini", ["gpt-4o-mini", "claude-haiku"]);
275
+ * // Returns: true
276
+ *
277
+ * // No model selected:
278
+ * isModelAllowedForPlan(undefined, ["gpt-4o-mini"]);
279
+ * // Returns: false
280
+ * ```
281
+ *
282
+ */
283
+ declare const isModelAllowedForPlan: (selectedModel: string | undefined | null, allowedModels: string[]) => boolean;
181
284
  /**
182
285
  * Input type for capability checks. Can be a single capability string or an
183
286
  * array of capability strings for checking multiple capabilities at once.
@@ -322,4 +425,4 @@ declare function toCapabilitySet(capabilities: string[] | undefined | null): Set
322
425
  */
323
426
  declare function isEntitled(capabilitiesOrSet: string[] | Set<string> | null | undefined, required: CapabilityInput, options?: IsEntitledOptions): boolean;
324
427
 
325
- export { ALL_MODELS, ALL_PROVIDERS, ALL_REASONING_MODELS, APPLICATION_NAME, APPROXIMATE_MODELS_PER_PROVIDER, CAPABILITIES, type CapabilityInput, DEFAULT_PROVIDER, DIGGIDY_CHAT_ID_HEADER, type EntitlementStateLike, type IsEntitledOptions, MODELS_PER_PROVIDER, MODEL_CLAUDE_HAIKU, MODEL_CLAUDE_SONNET, MODEL_DEV, MODEL_DISPLAY_NAMES, MODEL_EMBEDDING_TEXT, MODEL_GEMINI_FLASH, MODEL_GEMINI_PRO, MODEL_GPT4_NANO, MODEL_GPT5, MODEL_GPT5_MINI, MODEL_GPT5_NANO, MODEL_MEMORY_INFERENCE, MODEL_SONAR, MODEL_SONAR_PRO, PLAN_BASIC, PLAN_PLUS, PLAN_PREMIUM, PROVIDER_ANTHROPIC, PROVIDER_GOOGLE, PROVIDER_MEMORY, PROVIDER_MISTRAL, PROVIDER_OPENAI, PROVIDER_PERPLEXITY, PROVIDER_ROLE_MAP, PROVIDER_SUMMARY, ROLE_ASSISTANT, ROLE_HIDDEN, ROLE_INTERNAL, ROLE_SYSTEM, ROLE_USER, SORT_BY_TIMESTAMP, SORT_BY_TOKEN_USAGE, findProvider, getProvidersFromModels, isEntitled, isEntitlementLoaded, toCapabilitySet };
428
+ export { ALL_MODELS, ALL_PROVIDERS, ALL_REASONING_MODELS, APPLICATION_NAME, APPROXIMATE_MODELS_PER_PROVIDER, CAPABILITIES, type CapabilityInput, DEFAULT_PROVIDER, DIGGIDY_CHAT_ID_HEADER, type EntitlementStateLike, type IsEntitledOptions, MODELS_PER_PROVIDER, MODEL_CLAUDE_HAIKU, MODEL_CLAUDE_SONNET, MODEL_DEV, MODEL_DISPLAY_NAMES, MODEL_EMBEDDING_TEXT, MODEL_GEMINI_FLASH, MODEL_GEMINI_PRO, MODEL_GPT4_NANO, MODEL_GPT5, MODEL_GPT5_MINI, MODEL_GPT5_NANO, MODEL_MEMORY_INFERENCE, MODEL_SONAR, MODEL_SONAR_PRO, PLAN_BASIC, PLAN_PLUS, PLAN_PREMIUM, PROVIDER_ANTHROPIC, PROVIDER_GOOGLE, PROVIDER_MEMORY, PROVIDER_MISTRAL, PROVIDER_OPENAI, PROVIDER_PERPLEXITY, PROVIDER_ROLE_MAP, PROVIDER_SUMMARY, ROLE_ASSISTANT, ROLE_HIDDEN, ROLE_INTERNAL, ROLE_SYSTEM, ROLE_USER, SORT_BY_TIMESTAMP, SORT_BY_TOKEN_USAGE, findProvider, getModelsGroupedByProvider, getProvidersFromModels, hasMultipleModelsPerProvider, isEntitled, isEntitlementLoaded, isModelAllowedForPlan, toCapabilitySet };
package/dist/index.js CHANGED
@@ -1,62 +1,63 @@
1
- const l = "system", E = "user", e = "assistant", X = "hidden", Y = "data", O = "OpenAI", _ = "Anthropic", c = "Google", d = "Summary", g = "Memory", M = "Perplexity", v = "Mistral", b = O, m = [
1
+ const S = "system", e = "user", E = "assistant", Y = "hidden", b = "data", r = "OpenAI", O = "Anthropic", c = "Google", d = "Summary", g = "Memory", I = "Perplexity", B = "Mistral", F = r, f = [
2
+ r,
2
3
  O,
3
- _,
4
4
  c
5
- ], A = "gpt-5", R = "gpt-5-mini", r = "gpt-5-nano", T = "gpt-4.1-nano", I = "claude-haiku-4-5-20251001", i = "claude-sonnet-4-5-20250929", D = "gemini-2.5-flash", a = "gemini-2.5-pro", S = "sonar", N = "sonar-pro", B = "mistralai/mistral-small-3.2-24b-instruct:free", F = "gpt-4o-mini", W = "text-embedding-3-small", x = {
6
- [A]: "GPT-5",
7
- [R]: "GPT-5 Mini",
8
- [r]: "GPT-5 Nano",
5
+ ], _ = "gpt-5", A = "gpt-5-mini", a = "gpt-5-nano", T = "gpt-4.1-nano", D = "claude-haiku-4-5-20251001", R = "claude-sonnet-4-5-20250929", L = "gemini-2.5-flash", P = "gemini-2.5-pro", l = "sonar", u = "sonar-pro", k = "mistralai/mistral-small-3.2-24b-instruct:free", W = "gpt-4o-mini", x = "text-embedding-3-small", j = {
6
+ [_]: "GPT-5",
7
+ [A]: "GPT-5 Mini",
8
+ [a]: "GPT-5 Nano",
9
9
  [T]: "GPT-4.1 Nano",
10
- [I]: "Claude Haiku 4.5",
11
- [i]: "Claude Sonnet 4.5",
12
- [D]: "Gemini 2.5 Flash",
13
- [a]: "Gemini 2.5 Pro",
14
- [S]: "Sonar",
15
- [N]: "Sonar Pro"
16
- }, k = [
10
+ [D]: "Claude Haiku 4.5",
11
+ [R]: "Claude Sonnet 4.5",
12
+ [L]: "Gemini 2.5 Flash",
13
+ [P]: "Gemini 2.5 Pro",
14
+ [l]: "Sonar",
15
+ [u]: "Sonar Pro"
16
+ }, K = [
17
+ _,
17
18
  A,
18
- R,
19
- r,
20
- I,
21
- i,
19
+ a,
22
20
  D,
23
- a
24
- ], j = [
21
+ R,
22
+ L,
23
+ P
24
+ ], w = [
25
+ _,
25
26
  A,
27
+ a,
26
28
  R,
27
- r,
28
- i,
29
- a
30
- ], u = {
31
- [O]: [
29
+ P
30
+ ], N = {
31
+ [r]: [
32
32
  T,
33
+ _,
33
34
  A,
34
- R,
35
- r
36
- ],
37
- [_]: [I, i],
38
- [c]: [D, a],
39
- [M]: [S, N]
40
- }, w = {
41
- [O]: [l, E, e],
42
- [_]: [E, e],
43
- [d]: [E, e],
44
- [g]: [E, e],
45
- [c]: [E, e],
46
- [M]: [E, e]
47
- }, G = "claude-sonnet-4", f = "claude-3", p = "gpt-", y = "o3", h = "o4", C = "gemini", U = "sonar", H = {
48
- [_]: [
49
- G,
50
- f
35
+ a
51
36
  ],
37
+ [O]: [D, R],
38
+ [c]: [L, P],
39
+ [I]: [l, u]
40
+ }, z = {
41
+ [r]: [S, e, E],
42
+ [O]: [e, E],
43
+ [d]: [e, E],
44
+ [g]: [e, E],
45
+ [c]: [e, E],
46
+ [I]: [e, E]
47
+ }, p = "claude-sonnet-4", G = "claude-haiku-4", m = "claude-3", h = "gpt-", y = "o3", C = "o4", U = "gemini", v = "sonar", H = {
52
48
  [O]: [
53
49
  p,
50
+ G,
51
+ m
52
+ ],
53
+ [r]: [
54
+ h,
54
55
  y,
55
- h
56
+ C
56
57
  ],
57
- [c]: [C],
58
- [M]: [U]
59
- }, z = "x-diggidy-chat-id", K = "timestamp", Z = "tokenUsage", J = "Diggidy", Q = "sassy:basic", $ = "sassy:plus", q = "sassy:advanced", tt = {
58
+ [c]: [U],
59
+ [I]: [v]
60
+ }, Z = "x-diggidy-chat-id", J = "timestamp", Q = "tokenUsage", $ = "Diggidy", q = "sassy:basic", tt = "sassy:plus", nt = "sassy:advanced", ot = {
60
61
  TOOL: {
61
62
  DATETIME: "getDateTime",
62
63
  IMAGES: "getImages",
@@ -74,81 +75,103 @@ const l = "system", E = "user", e = "assistant", X = "hidden", Y = "data", O = "
74
75
  REASONING: "addon:reasoning",
75
76
  CODEINTERPRETER: "addon:codeinterpreter"
76
77
  }
77
- }, nt = (t) => {
78
+ }, st = (t) => {
78
79
  for (const [n, s] of Object.entries(
79
80
  H
80
81
  ))
81
82
  if (s.some((o) => t.startsWith(o)))
82
83
  return n;
83
84
  return null;
84
- }, ot = (t) => {
85
+ }, et = (t) => {
85
86
  if (!t || t.length === 0)
86
87
  return [];
87
88
  const n = /* @__PURE__ */ new Set();
88
89
  for (const s of t)
89
- for (const [o, L] of Object.entries(
90
- u
90
+ for (const [o, i] of Object.entries(
91
+ N
91
92
  ))
92
- L.includes(s) && (o === O || o === _ || o === c) && n.add(o);
93
- return m.filter((s) => n.has(s));
94
- };
95
- function st(t) {
93
+ i.includes(s) && (o === r || o === O || o === c) && n.add(o);
94
+ return f.filter((s) => n.has(s));
95
+ }, V = (t) => {
96
+ const n = /* @__PURE__ */ new Map();
97
+ if (!t || t.length === 0)
98
+ return n;
99
+ for (const s of t)
100
+ for (const [o, i] of Object.entries(
101
+ N
102
+ ))
103
+ if (i.includes(s)) {
104
+ n.has(o) || n.set(o, []), n.get(o)?.push(s);
105
+ break;
106
+ }
107
+ return n;
108
+ }, Et = (t) => {
109
+ const n = V(t);
110
+ for (const s of n.values())
111
+ if (s.length > 1)
112
+ return !0;
113
+ return !1;
114
+ }, rt = (t, n) => !t || !n || n.length === 0 ? !1 : n.includes(t);
115
+ function Ot(t) {
96
116
  return !!t && Array.isArray(t.capabilities) && t.capabilities.length >= 0;
97
117
  }
98
- function V(t) {
118
+ function X(t) {
99
119
  return t ? new Set(t) : null;
100
120
  }
101
- function Et(t, n, s) {
121
+ function ct(t, n, s) {
102
122
  if (!n || Array.isArray(n) && n.length === 0)
103
123
  return !0;
104
- const o = t instanceof Set ? t : V(t);
105
- return !o || o.size === 0 ? !1 : typeof n == "string" ? o.has(n) : s?.any === !0 ? n.some((P) => o.has(P)) : n.every((P) => o.has(P));
124
+ const o = t instanceof Set ? t : X(t);
125
+ return !o || o.size === 0 ? !1 : typeof n == "string" ? o.has(n) : s?.any === !0 ? n.some((M) => o.has(M)) : n.every((M) => o.has(M));
106
126
  }
107
127
  export {
108
- k as ALL_MODELS,
109
- m as ALL_PROVIDERS,
110
- j as ALL_REASONING_MODELS,
111
- J as APPLICATION_NAME,
128
+ K as ALL_MODELS,
129
+ f as ALL_PROVIDERS,
130
+ w as ALL_REASONING_MODELS,
131
+ $ as APPLICATION_NAME,
112
132
  H as APPROXIMATE_MODELS_PER_PROVIDER,
113
- tt as CAPABILITIES,
114
- b as DEFAULT_PROVIDER,
115
- z as DIGGIDY_CHAT_ID_HEADER,
116
- u as MODELS_PER_PROVIDER,
117
- I as MODEL_CLAUDE_HAIKU,
118
- i as MODEL_CLAUDE_SONNET,
119
- B as MODEL_DEV,
120
- x as MODEL_DISPLAY_NAMES,
121
- W as MODEL_EMBEDDING_TEXT,
122
- D as MODEL_GEMINI_FLASH,
123
- a as MODEL_GEMINI_PRO,
133
+ ot as CAPABILITIES,
134
+ F as DEFAULT_PROVIDER,
135
+ Z as DIGGIDY_CHAT_ID_HEADER,
136
+ N as MODELS_PER_PROVIDER,
137
+ D as MODEL_CLAUDE_HAIKU,
138
+ R as MODEL_CLAUDE_SONNET,
139
+ k as MODEL_DEV,
140
+ j as MODEL_DISPLAY_NAMES,
141
+ x as MODEL_EMBEDDING_TEXT,
142
+ L as MODEL_GEMINI_FLASH,
143
+ P as MODEL_GEMINI_PRO,
124
144
  T as MODEL_GPT4_NANO,
125
- A as MODEL_GPT5,
126
- R as MODEL_GPT5_MINI,
127
- r as MODEL_GPT5_NANO,
128
- F as MODEL_MEMORY_INFERENCE,
129
- S as MODEL_SONAR,
130
- N as MODEL_SONAR_PRO,
131
- Q as PLAN_BASIC,
132
- $ as PLAN_PLUS,
133
- q as PLAN_PREMIUM,
134
- _ as PROVIDER_ANTHROPIC,
145
+ _ as MODEL_GPT5,
146
+ A as MODEL_GPT5_MINI,
147
+ a as MODEL_GPT5_NANO,
148
+ W as MODEL_MEMORY_INFERENCE,
149
+ l as MODEL_SONAR,
150
+ u as MODEL_SONAR_PRO,
151
+ q as PLAN_BASIC,
152
+ tt as PLAN_PLUS,
153
+ nt as PLAN_PREMIUM,
154
+ O as PROVIDER_ANTHROPIC,
135
155
  c as PROVIDER_GOOGLE,
136
156
  g as PROVIDER_MEMORY,
137
- v as PROVIDER_MISTRAL,
138
- O as PROVIDER_OPENAI,
139
- M as PROVIDER_PERPLEXITY,
140
- w as PROVIDER_ROLE_MAP,
157
+ B as PROVIDER_MISTRAL,
158
+ r as PROVIDER_OPENAI,
159
+ I as PROVIDER_PERPLEXITY,
160
+ z as PROVIDER_ROLE_MAP,
141
161
  d as PROVIDER_SUMMARY,
142
- e as ROLE_ASSISTANT,
143
- X as ROLE_HIDDEN,
144
- Y as ROLE_INTERNAL,
145
- l as ROLE_SYSTEM,
146
- E as ROLE_USER,
147
- K as SORT_BY_TIMESTAMP,
148
- Z as SORT_BY_TOKEN_USAGE,
149
- nt as findProvider,
150
- ot as getProvidersFromModels,
151
- Et as isEntitled,
152
- st as isEntitlementLoaded,
153
- V as toCapabilitySet
162
+ E as ROLE_ASSISTANT,
163
+ Y as ROLE_HIDDEN,
164
+ b as ROLE_INTERNAL,
165
+ S as ROLE_SYSTEM,
166
+ e as ROLE_USER,
167
+ J as SORT_BY_TIMESTAMP,
168
+ Q as SORT_BY_TOKEN_USAGE,
169
+ st as findProvider,
170
+ V as getModelsGroupedByProvider,
171
+ et as getProvidersFromModels,
172
+ Et as hasMultipleModelsPerProvider,
173
+ ct as isEntitled,
174
+ Ot as isEntitlementLoaded,
175
+ rt as isModelAllowedForPlan,
176
+ X as toCapabilitySet
154
177
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versini/sassysaint-common",
3
- "version": "4.13.0",
3
+ "version": "4.14.1",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "publishConfig": {
@@ -32,5 +32,5 @@
32
32
  "test:watch": "vitest",
33
33
  "watch": "npm-run-all dev"
34
34
  },
35
- "gitHead": "89572beafadc51e691166d4334c4ce4d1002f682"
35
+ "gitHead": "7e32500820075709b3e4d55ec008492513e67a1f"
36
36
  }