@sudobility/shapeshyft_types 1.0.44 → 1.0.46

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.
Files changed (3) hide show
  1. package/README.md +51 -0
  2. package/package.json +6 -10
  3. package/dist/index.cjs +0 -333
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # @sudobility/shapeshyft_types
2
+
3
+ Shared TypeScript type definitions for the ShapeShyft LLM structured output platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @sudobility/shapeshyft_types
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import type {
15
+ User, Project, Endpoint, LlmProvider,
16
+ AiExecutionRequest, AiExecutionResponse,
17
+ } from '@sudobility/shapeshyft_types';
18
+
19
+ import { successResponse, errorResponse } from '@sudobility/shapeshyft_types';
20
+ ```
21
+
22
+ ## Types
23
+
24
+ - **Enums**: `LlmProvider` (openai, gemini, anthropic, lm_studio), `HttpMethod`
25
+ - **Entities**: `User`, `LlmApiKey` / `LlmApiKeySafe`, `Project`, `Endpoint`, `UsageAnalytics`, `UserSettings`
26
+ - **Requests**: Create/Update types for users, keys, projects, endpoints, plus `AiExecutionRequest`
27
+ - **Responses**: `AiExecutionResponse`, `AiPromptResponse`, `AnalyticsResponse`, `HealthCheckData`
28
+ - **Query Params**: `ProjectQueryParams`, `EndpointQueryParams`, `UsageAnalyticsQueryParams`
29
+ - **Utilities**: `JsonSchema`, `ApiResponse<T>`, `PaginatedResponse<T>` (re-exported from `@sudobility/types`)
30
+ - **Helpers**: `successResponse()`, `errorResponse()` (runtime functions)
31
+
32
+ ## Development
33
+
34
+ ```bash
35
+ bun run build # Build ESM + CJS
36
+ bun run test # Run Vitest
37
+ bun run typecheck # TypeScript check
38
+ bun run lint # ESLint
39
+ bun run verify # Typecheck + lint + build
40
+ ```
41
+
42
+ ## Related Packages
43
+
44
+ - `@sudobility/shapeshyft_client` -- React hooks for ShapeShyft API
45
+ - `@sudobility/shapeshyft_lib` -- Business logic with Zustand stores
46
+ - `shapeshyft_api` -- Backend API server
47
+ - `shapeshyft_app` -- Frontend web application
48
+
49
+ ## License
50
+
51
+ BUSL-1.1
package/package.json CHANGED
@@ -1,22 +1,18 @@
1
1
  {
2
2
  "name": "@sudobility/shapeshyft_types",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "TypeScript types for ShapeShyft API - LLM structured output platform",
5
- "main": "./dist/index.cjs",
6
- "module": "./dist/index.js",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/index.js",
11
- "require": "./dist/index.cjs",
12
11
  "types": "./dist/index.d.ts"
13
12
  }
14
13
  },
15
14
  "scripts": {
16
- "build": "bun run build:esm && bun run build:cjs",
17
- "build:esm": "bunx tsc -p tsconfig.esm.json",
18
- "build:cjs": "bunx tsc -p tsconfig.cjs.json && bun run build:cjs-rename && rm -rf dist-cjs",
19
- "build:cjs-rename": "find dist-cjs -name '*.js' -exec sh -c 'cp \"$1\" \"dist/$(basename \"${1%.js}.cjs\")\"' _ {} \\;",
15
+ "build": "tsc -p tsconfig.esm.json",
20
16
  "clean": "rm -rf dist",
21
17
  "dev": "bunx tsc --watch",
22
18
  "typecheck": "bunx tsc --noEmit",
@@ -43,11 +39,11 @@
43
39
  "author": "Sudobility",
44
40
  "license": "BUSL-1.1",
45
41
  "peerDependencies": {
46
- "@sudobility/types": "^1.9.54"
42
+ "@sudobility/types": "^1.9.57"
47
43
  },
48
44
  "devDependencies": {
49
45
  "@eslint/js": "^9.39.2",
50
- "@sudobility/types": "^1.9.54",
46
+ "@sudobility/types": "^1.9.57",
51
47
  "@typescript-eslint/eslint-plugin": "^8.50.0",
52
48
  "@typescript-eslint/parser": "^8.50.0",
53
49
  "eslint": "^9.39.2",
package/dist/index.cjs DELETED
@@ -1,333 +0,0 @@
1
- "use strict";
2
- /**
3
- * @sudobility/shapeshyft_types
4
- * TypeScript types for ShapeShyft API - LLM structured output platform
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.PROVIDER_MODELS = exports.LLM_PROVIDERS = void 0;
8
- exports.isValidModelForProvider = isValidModelForProvider;
9
- exports.detectRequiredCapabilities = detectRequiredCapabilities;
10
- exports.estimateCost = estimateCost;
11
- exports.estimateMultimodalCost = estimateMultimodalCost;
12
- exports.formatCost = formatCost;
13
- exports.formatCostPerMillion = formatCostPerMillion;
14
- exports.successResponse = successResponse;
15
- exports.errorResponse = errorResponse;
16
- /** List of available providers */
17
- exports.LLM_PROVIDERS = [
18
- 'openai',
19
- 'anthropic',
20
- 'gemini',
21
- 'mistral',
22
- 'cohere',
23
- 'groq',
24
- 'xai',
25
- 'deepseek',
26
- 'perplexity',
27
- 'lm_studio',
28
- ];
29
- /**
30
- * Mapping of each LLM provider to its known valid model IDs.
31
- * Useful for both server-side validation and client-side form validation.
32
- *
33
- * Note: `lm_studio` has an empty list because it accepts arbitrary
34
- * user-supplied model names (any string is valid).
35
- */
36
- exports.PROVIDER_MODELS = {
37
- openai: [
38
- 'gpt-4.1',
39
- 'gpt-4.1-mini',
40
- 'gpt-4.1-nano',
41
- 'gpt-4o',
42
- 'gpt-4o-mini',
43
- 'o3',
44
- 'o3-pro',
45
- 'o4-mini',
46
- 'gpt-4-turbo',
47
- 'o1',
48
- ],
49
- anthropic: [
50
- 'claude-opus-4-5-20251124',
51
- 'claude-sonnet-4-5-20251124',
52
- 'claude-opus-4-1-20250805',
53
- 'claude-sonnet-4-20250514',
54
- 'claude-opus-4-20250514',
55
- 'claude-3-5-haiku-20241022',
56
- ],
57
- gemini: [
58
- 'gemini-3-pro-preview',
59
- 'gemini-3-flash-preview',
60
- 'gemini-3-pro-image-preview',
61
- 'gemini-2.5-pro',
62
- 'gemini-2.5-flash',
63
- 'gemini-2.5-flash-lite',
64
- 'gemini-2.5-flash-image',
65
- 'gemini-2.5-flash-native-audio-preview',
66
- 'gemini-2.0-flash',
67
- 'gemini-2.0-flash-lite',
68
- ],
69
- mistral: [
70
- 'mistral-large-2512',
71
- 'mistral-large-latest',
72
- 'mistral-medium-3.1',
73
- 'mistral-medium-latest',
74
- 'mistral-small-3.2',
75
- 'mistral-small-latest',
76
- 'ministral-3b-2512',
77
- 'ministral-8b-2512',
78
- 'ministral-14b-2512',
79
- 'codestral-2501',
80
- 'codestral-latest',
81
- 'pixtral-large-2411',
82
- 'pixtral-large-latest',
83
- 'voxtral-small',
84
- 'voxtral-mini',
85
- 'mistral-ocr-2512',
86
- ],
87
- cohere: [
88
- 'command-a-03-2025',
89
- 'command-a-reasoning',
90
- 'command-a-vision',
91
- 'command-r-plus-08-2024',
92
- 'command-r-08-2024',
93
- 'command-r-plus',
94
- 'command-r',
95
- ],
96
- groq: [
97
- 'llama-3.3-70b-versatile',
98
- 'llama-3.1-8b-instant',
99
- 'openai/gpt-oss-120b',
100
- 'openai/gpt-oss-20b',
101
- 'groq/compound',
102
- 'groq/compound-mini',
103
- 'meta-llama/llama-guard-4-12b',
104
- 'whisper-large-v3',
105
- 'whisper-large-v3-turbo',
106
- ],
107
- xai: [
108
- 'grok-4',
109
- 'grok-4.1-fast',
110
- 'grok-3',
111
- 'grok-3-mini',
112
- 'grok-3-vision',
113
- 'grok-2',
114
- 'grok-2-vision',
115
- ],
116
- deepseek: [
117
- 'deepseek-chat',
118
- 'deepseek-reasoner',
119
- ],
120
- perplexity: [
121
- 'sonar',
122
- 'sonar-pro',
123
- 'sonar-reasoning',
124
- 'sonar-reasoning-pro',
125
- 'sonar-deep-research',
126
- ],
127
- lm_studio: [],
128
- };
129
- /**
130
- * Check whether a model ID is valid for the given provider.
131
- * For `lm_studio`, any string is valid (returns true) since users
132
- * can run arbitrary models on their local server.
133
- *
134
- * @param provider - The LLM provider to validate against
135
- * @param model - The model ID string to check
136
- * @returns true if the model is a known valid model for the provider
137
- */
138
- function isValidModelForProvider(provider, model) {
139
- const models = exports.PROVIDER_MODELS[provider];
140
- // lm_studio accepts any model string
141
- if (provider === 'lm_studio')
142
- return true;
143
- return models.includes(model);
144
- }
145
- /**
146
- * Detect media type from contentMediaType string
147
- */
148
- function detectMediaType(contentMediaType) {
149
- if (contentMediaType.startsWith('image/'))
150
- return 'image';
151
- if (contentMediaType.startsWith('audio/'))
152
- return 'audio';
153
- if (contentMediaType.startsWith('video/'))
154
- return 'video';
155
- return null;
156
- }
157
- /**
158
- * Recursively scan a JSON schema for media type properties.
159
- * Returns detected media types.
160
- */
161
- function scanSchemaForMediaTypes(schema, result) {
162
- if (!schema || typeof schema !== 'object')
163
- return;
164
- // Check if this property has contentMediaType
165
- const contentMediaType = schema['contentMediaType'];
166
- if (typeof contentMediaType === 'string') {
167
- const mediaType = detectMediaType(contentMediaType);
168
- if (mediaType) {
169
- result.add(mediaType);
170
- }
171
- }
172
- // Recurse into properties
173
- const properties = schema['properties'];
174
- if (properties && typeof properties === 'object') {
175
- for (const prop of Object.values(properties)) {
176
- if (prop && typeof prop === 'object') {
177
- scanSchemaForMediaTypes(prop, result);
178
- }
179
- }
180
- }
181
- // Recurse into array items
182
- const items = schema['items'];
183
- if (items && typeof items === 'object') {
184
- scanSchemaForMediaTypes(items, result);
185
- }
186
- }
187
- /**
188
- * Detect required capabilities from input and output schemas.
189
- * Returns which media capabilities are required.
190
- */
191
- function detectRequiredCapabilities(inputSchema, outputSchema) {
192
- const result = {};
193
- // Scan input schema for required input capabilities
194
- if (inputSchema) {
195
- const inputMediaTypes = new Set();
196
- scanSchemaForMediaTypes(inputSchema, inputMediaTypes);
197
- if (inputMediaTypes.has('image'))
198
- result.visionInput = true;
199
- if (inputMediaTypes.has('audio'))
200
- result.audioInput = true;
201
- if (inputMediaTypes.has('video'))
202
- result.videoInput = true;
203
- }
204
- // Scan output schema for required output capabilities
205
- if (outputSchema) {
206
- const outputMediaTypes = new Set();
207
- scanSchemaForMediaTypes(outputSchema, outputMediaTypes);
208
- if (outputMediaTypes.has('image'))
209
- result.imageOutput = true;
210
- if (outputMediaTypes.has('audio'))
211
- result.audioOutput = true;
212
- if (outputMediaTypes.has('video'))
213
- result.videoOutput = true;
214
- }
215
- return result;
216
- }
217
- /**
218
- * Estimate cost in cents for token usage (text only)
219
- * @param pricing - Model pricing configuration
220
- * @param inputTokens - Number of input tokens
221
- * @param outputTokens - Number of output tokens
222
- */
223
- function estimateCost(pricing, inputTokens, outputTokens) {
224
- const inputCost = (inputTokens / 1000000) * pricing.input;
225
- const outputCost = (outputTokens / 1000000) * pricing.output;
226
- return Math.round((inputCost + outputCost) * 100) / 100; // Round to 2 decimal places
227
- }
228
- /**
229
- * Estimate cost in cents for multimodal usage
230
- * @param pricing - Model pricing configuration
231
- * @param usage - Multimodal usage details
232
- */
233
- function estimateMultimodalCost(pricing, usage) {
234
- let totalCost = 0;
235
- // Text token costs
236
- if (usage.inputTokens) {
237
- totalCost += (usage.inputTokens / 1000000) * pricing.input;
238
- }
239
- if (usage.outputTokens) {
240
- totalCost += (usage.outputTokens / 1000000) * pricing.output;
241
- }
242
- // Image costs
243
- if (usage.imagesInput && pricing.imageInput) {
244
- totalCost += usage.imagesInput * pricing.imageInput;
245
- }
246
- if (usage.imagesOutput && pricing.imageOutput) {
247
- totalCost += usage.imagesOutput * pricing.imageOutput;
248
- }
249
- // Audio costs
250
- if (usage.audioInputMinutes && pricing.audioInput) {
251
- totalCost += usage.audioInputMinutes * pricing.audioInput;
252
- }
253
- if (usage.audioOutputMinutes && pricing.audioOutput) {
254
- totalCost += usage.audioOutputMinutes * pricing.audioOutput;
255
- }
256
- // Video costs
257
- if (usage.videoInputMinutes && pricing.videoInput) {
258
- totalCost += usage.videoInputMinutes * pricing.videoInput;
259
- }
260
- if (usage.videoOutputMinutes && pricing.videoOutput) {
261
- totalCost += usage.videoOutputMinutes * pricing.videoOutput;
262
- }
263
- return Math.round(totalCost * 100) / 100; // Round to 2 decimal places
264
- }
265
- /**
266
- * Format cost in cents to a readable string (e.g., "$0.0015" or "$1.50")
267
- */
268
- function formatCost(costCents) {
269
- const dollars = costCents / 100;
270
- if (dollars < 0.01) {
271
- return `$${dollars.toFixed(4)}`;
272
- }
273
- else if (dollars < 1) {
274
- return `$${dollars.toFixed(3)}`;
275
- }
276
- else {
277
- return `$${dollars.toFixed(2)}`;
278
- }
279
- }
280
- /**
281
- * Format cost per million tokens for display
282
- */
283
- function formatCostPerMillion(pricing) {
284
- const inputDollars = pricing.input / 100;
285
- const outputDollars = pricing.output / 100;
286
- return `$${inputDollars.toFixed(2)} / $${outputDollars.toFixed(2)} per 1M tokens`;
287
- }
288
- // =============================================================================
289
- // Response Helper Functions
290
- // =============================================================================
291
- /**
292
- * Create a typed success response wrapping the given data.
293
- *
294
- * @example
295
- * ```typescript
296
- * import { successResponse, type Project } from '@sudobility/shapeshyft_types';
297
- *
298
- * const project: Project = { uuid: '...', entity_id: '...', project_name: 'my-project', display_name: 'My Project', description: null, is_active: true, api_key_prefix: null, api_key_created_at: null, created_at: new Date(), updated_at: new Date() };
299
- * const response = successResponse<Project>(project);
300
- * // { success: true, data: { uuid: '...', project_name: 'my-project', ... }, timestamp: '2026-01-15T...' }
301
- * ```
302
- */
303
- function successResponse(data) {
304
- return {
305
- success: true,
306
- data,
307
- timestamp: new Date().toISOString(),
308
- };
309
- }
310
- /**
311
- * Create a typed error response with the given error message.
312
- *
313
- * @example
314
- * ```typescript
315
- * import { errorResponse } from '@sudobility/shapeshyft_types';
316
- *
317
- * const response = errorResponse('Project not found');
318
- * // { success: false, error: 'Project not found', timestamp: '2026-01-15T...' }
319
- *
320
- * // In an API handler:
321
- * if (!project) {
322
- * return c.json(errorResponse('Project not found'), 404);
323
- * }
324
- * ```
325
- */
326
- function errorResponse(error) {
327
- return {
328
- success: false,
329
- error,
330
- timestamp: new Date().toISOString(),
331
- };
332
- }
333
- //# sourceMappingURL=index.js.map