11import { type } from 'arktype' ;
22import { nanoid } from 'nanoid/non-secure' ;
3- import { TRANSFORMATION_STEP_TYPES } from '$lib/constants/database' ;
43import {
5- ANTHROPIC_INFERENCE_MODELS ,
6- GOOGLE_INFERENCE_MODELS ,
7- GROQ_INFERENCE_MODELS ,
8- INFERENCE_PROVIDER_IDS ,
9- OPENAI_INFERENCE_MODELS ,
10- } from '$lib/constants/inference' ;
11-
12- /**
13- * The current version of the TransformationStep schema.
14- * Increment this when adding new fields or making breaking changes.
15- */
16- const CURRENT_TRANSFORMATION_STEP_VERSION = 2 as const ;
4+ TransformationStep ,
5+ TransformationStepV1 ,
6+ TransformationStepV2 ,
7+ } from './transformation-steps.js' ;
178
189// ============================================================================
1910// VERSION 1 (FROZEN)
2011// ============================================================================
2112
22- /**
23- * V1: Original schema without Custom provider fields.
24- * Old data has no version field, so we default to 1.
25- *
26- * FROZEN: Do not modify. This represents the historical V1 schema.
27- */
28- const TransformationStepV1 = type ( {
29- id : 'string' ,
30- type : type . enumerated ( ...TRANSFORMATION_STEP_TYPES ) ,
31- 'prompt_transform.inference.provider' : type . enumerated (
32- ...INFERENCE_PROVIDER_IDS ,
33- ) ,
34- 'prompt_transform.inference.provider.OpenAI.model' : type . enumerated (
35- ...OPENAI_INFERENCE_MODELS ,
36- ) ,
37- 'prompt_transform.inference.provider.Groq.model' : type . enumerated (
38- ...GROQ_INFERENCE_MODELS ,
39- ) ,
40- 'prompt_transform.inference.provider.Anthropic.model' : type . enumerated (
41- ...ANTHROPIC_INFERENCE_MODELS ,
42- ) ,
43- 'prompt_transform.inference.provider.Google.model' : type . enumerated (
44- ...GOOGLE_INFERENCE_MODELS ,
45- ) ,
46- // OpenRouter model is a free string (user can enter any model)
47- 'prompt_transform.inference.provider.OpenRouter.model' : 'string' ,
48- 'prompt_transform.systemPromptTemplate' : 'string' ,
49- 'prompt_transform.userPromptTemplate' : 'string' ,
50- 'find_replace.findText' : 'string' ,
51- 'find_replace.replaceText' : 'string' ,
52- 'find_replace.useRegex' : 'boolean' ,
53- version : '1 = 1' ,
54- } ) ;
55-
56- export type TransformationStepV1 = typeof TransformationStepV1 . infer ;
57-
5813/**
5914 * Transformation type containing V1 steps (before Custom provider fields).
6015 * Used only for typing old data during Dexie migration in web.ts.
6116 *
6217 * Note: The Transformation fields themselves are unchanged; only the step
6318 * schema differs between "V1" and "V2".
6419 */
65- export type TransformationV1 = {
66- id : string ;
67- title : string ;
68- description : string ;
69- createdAt : string ;
70- updatedAt : string ;
71- steps : TransformationStepV1 [ ] ;
72- } ;
20+ const TransformationV1 = type ( {
21+ id : 'string' ,
22+ title : 'string' ,
23+ description : 'string' ,
24+ createdAt : 'string' ,
25+ updatedAt : 'string' ,
26+ steps : [ TransformationStepV1 , '[]' ] ,
27+ } ) ;
28+
29+ export type TransformationV1 = typeof TransformationV1 . infer ;
7330
7431// ============================================================================
7532// VERSION 2 (CURRENT)
7633// ============================================================================
7734
78- /**
79- * V2: Added Custom provider fields for local LLM endpoints.
80- * Extends V1 with:
81- * - Custom.model: Model name for custom endpoints
82- * - Custom.baseUrl: Per-step base URL (falls back to global setting)
83- *
84- * CURRENT VERSION: This is the latest schema.
85- */
86- const TransformationStepV2 = TransformationStepV1 . merge ( {
87- version : '2' ,
88- /** Custom provider for local LLM endpoints (Ollama, LM Studio, llama.cpp, etc.) */
89- 'prompt_transform.inference.provider.Custom.model' : 'string' ,
90- /**
91- * Per-step base URL for custom endpoints. Allows different steps to use
92- * different local services (e.g., Ollama on :11434, LM Studio on :1234).
93- * Falls back to global `completion.Custom.baseUrl` setting if empty.
94- */
95- 'prompt_transform.inference.provider.Custom.baseUrl' : 'string' ,
96- } ) ;
97-
98- export type TransformationStepV2 = typeof TransformationStepV2 . infer ;
99-
10035/**
10136 * Current Transformation schema with V2 steps.
37+ * Extends V1 by using V2 steps.
10238 *
10339 * The Transformation container fields (id, title, description, createdAt, updatedAt)
10440 * have not changed since V1. Only TransformationStep has versioning.
10541 */
106- const TransformationV2 = type ( {
107- id : 'string' ,
108- title : 'string' ,
109- description : 'string' ,
110- createdAt : 'string' ,
111- updatedAt : 'string' ,
42+ const TransformationV2 = TransformationV1 . merge ( {
11243 steps : [ TransformationStepV2 , '[]' ] ,
11344} ) ;
11445
11546export type TransformationV2 = typeof TransformationV2 . infer ;
11647
11748// ============================================================================
118- // MIGRATING VALIDATORS
119- // ============================================================================
120- // These accept any version and migrate to the latest (V2).
121- // Use these when reading data that might be from an older schema version.
49+ // MIGRATING VALIDATOR
12250// ============================================================================
12351
124- /**
125- * TransformationStep validator with automatic migration.
126- * Accepts V1 or V2 and always outputs V2.
127- */
128- export const TransformationStep = TransformationStepV1 . or (
129- TransformationStepV2 ,
130- ) . pipe ( ( step ) : TransformationStepV2 => {
131- if ( step . version === 1 ) {
132- return {
133- ...step ,
134- version : 2 ,
135- 'prompt_transform.inference.provider.Custom.model' : '' ,
136- 'prompt_transform.inference.provider.Custom.baseUrl' : '' ,
137- } ;
138- }
139- return step ;
140- } ) ;
141-
142- export type TransformationStep = TransformationStepV2 ;
143-
14452/**
14553 * Transformation validator with automatic step migration.
14654 * Accepts transformations with V1 or V2 steps and migrates all steps to V2.
@@ -153,10 +61,10 @@ export const Transformation = TransformationV2.merge({
15361export type Transformation = TransformationV2 ;
15462
15563// ============================================================================
156- // FACTORY FUNCTIONS
64+ // FACTORY FUNCTION
15765// ============================================================================
15866
159- export function generateDefaultTransformation ( ) : TransformationV2 {
67+ export function generateDefaultTransformation ( ) : Transformation {
16068 const now = new Date ( ) . toISOString ( ) ;
16169 return {
16270 id : nanoid ( ) ,
@@ -167,29 +75,3 @@ export function generateDefaultTransformation(): TransformationV2 {
16775 updatedAt : now ,
16876 } ;
16977}
170-
171- export function generateDefaultTransformationStep ( ) : TransformationStepV2 {
172- return {
173- version : CURRENT_TRANSFORMATION_STEP_VERSION ,
174- id : nanoid ( ) ,
175- type : 'prompt_transform' ,
176- 'prompt_transform.inference.provider' : 'Google' ,
177- 'prompt_transform.inference.provider.OpenAI.model' : 'gpt-4o' ,
178- 'prompt_transform.inference.provider.Groq.model' : 'llama-3.3-70b-versatile' ,
179- 'prompt_transform.inference.provider.Anthropic.model' : 'claude-sonnet-4-0' ,
180- 'prompt_transform.inference.provider.Google.model' : 'gemini-2.5-flash' ,
181- 'prompt_transform.inference.provider.OpenRouter.model' :
182- 'mistralai/mixtral-8x7b' ,
183- // Empty strings for Custom provider - user must configure when switching to Custom
184- // baseUrl falls back to global setting in transformer.ts
185- 'prompt_transform.inference.provider.Custom.model' : '' ,
186- 'prompt_transform.inference.provider.Custom.baseUrl' : '' ,
187-
188- 'prompt_transform.systemPromptTemplate' : '' ,
189- 'prompt_transform.userPromptTemplate' : '' ,
190-
191- 'find_replace.findText' : '' ,
192- 'find_replace.replaceText' : '' ,
193- 'find_replace.useRegex' : false ,
194- } ;
195- }
0 commit comments