| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import { |
| | ModelVendor, |
| | SymbolicPrimitive, |
| | GrammarStyle, |
| | SymbolicOperation, |
| | VendorImplementation, |
| | SYMBOLIC_RUNTIME_SCHEMA |
| | } from './universal-symbolics-runtime'; |
| |
|
| | import { SymbolicsRegistry } from './universal-symbolics-registry'; |
| |
|
| | |
| | |
| | |
| | export interface HarmonizationOptions { |
| | preserveStructure?: boolean; |
| | adaptToCapabilities?: boolean; |
| | includeComments?: boolean; |
| | embedTraceability?: boolean; |
| | formatOutput?: boolean; |
| | handleResidue?: boolean; |
| | fallbackBehavior?: 'omit' | 'emulate' | 'comment'; |
| | } |
| |
|
| | |
| | |
| | |
| | export interface HarmonizationResult { |
| | transformed: string; |
| | originalVendor: ModelVendor; |
| | targetVendor: ModelVendor; |
| | operations: { |
| | original: SymbolicPrimitive; |
| | target: SymbolicPrimitive | null; |
| | success: boolean; |
| | message?: string; |
| | }[]; |
| | residue: { |
| | pattern: string; |
| | position: number; |
| | possiblePrimitive?: SymbolicPrimitive; |
| | }[]; |
| | metrics: { |
| | totalOperations: number; |
| | successfulOperations: number; |
| | unsupportedOperations: number; |
| | adaptedOperations: number; |
| | }; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | export class SymbolicHarmonizer { |
| | private registry: SymbolicsRegistry; |
| | |
| | constructor(registry?: SymbolicsRegistry) { |
| | this.registry = registry || new SymbolicsRegistry(); |
| | } |
| | |
| | |
| | |
| | |
| | public harmonize( |
| | content: string, |
| | sourceVendor: ModelVendor, |
| | targetVendor: ModelVendor, |
| | options: HarmonizationOptions = {} |
| | ): HarmonizationResult { |
| | |
| | const opts: Required<HarmonizationOptions> = { |
| | preserveStructure: options.preserveStructure !== undefined ? options.preserveStructure : true, |
| | adaptToCapabilities: options.adaptToCapabilities !== undefined ? options.adaptToCapabilities : true, |
| | includeComments: options.includeComments !== undefined ? options.includeComments : false, |
| | embedTraceability: options.embedTraceability !== undefined ? options.embedTraceability : false, |
| | formatOutput: options.formatOutput !== undefined ? options.formatOutput : true, |
| | handleResidue: options.handleResidue !== undefined ? options.handleResidue : true, |
| | fallbackBehavior: options.fallbackBehavior || 'emulate' |
| | }; |
| | |
| | |
| | const result: HarmonizationResult = { |
| | transformed: '', |
| | originalVendor: sourceVendor, |
| | targetVendor: targetVendor, |
| | operations: [], |
| | residue: [], |
| | metrics: { |
| | totalOperations: 0, |
| | successfulOperations: 0, |
| | unsupportedOperations: 0, |
| | adaptedOperations: 0 |
| | } |
| | }; |
| | |
| | |
| | if (sourceVendor === targetVendor) { |
| | result.transformed = content; |
| | return result; |
| | } |
| | |
| | |
| | if (opts.handleResidue) { |
| | result.residue = this.registry.findSymbolicResidue(content, sourceVendor); |
| | |
| | |
| | if (result.residue.length > 0) { |
| | content = this.registry.repairSymbolicResidue(content, sourceVendor); |
| | } |
| | } |
| | |
| | |
| | const extractedOperations = this.registry.extractAllSymbolicOperations(content, sourceVendor); |
| | result.metrics.totalOperations = extractedOperations.length; |
| | |
| | |
| | const operationPositions = this.mapOperationPositions(content, sourceVendor); |
| | |
| | |
| | const operationResults: { primitive: SymbolicPrimitive, params: any, success: boolean, message?: string, transformed?: string }[] = []; |
| | |
| | for (const { primitive, params } of extractedOperations) { |
| | const operationResult = this.transformOperation(primitive, params, sourceVendor, targetVendor, opts); |
| | operationResults.push({ |
| | primitive, |
| | params, |
| | success: operationResult.success, |
| | message: operationResult.message, |
| | transformed: operationResult.transformed |
| | }); |
| | |
| | |
| | if (operationResult.success) { |
| | result.metrics.successfulOperations++; |
| | |
| | if (operationResult.adapted) { |
| | result.metrics.adaptedOperations++; |
| | } |
| | } else { |
| | result.metrics.unsupportedOperations++; |
| | } |
| | |
| | |
| | result.operations.push({ |
| | original: primitive, |
| | target: operationResult.targetPrimitive, |
| | success: operationResult.success, |
| | message: operationResult.message |
| | }); |
| | } |
| | |
| | |
| | result.transformed = this.generateTransformedContent( |
| | content, |
| | operationPositions, |
| | operationResults, |
| | sourceVendor, |
| | targetVendor, |
| | opts |
| | ); |
| | |
| | |
| | if (opts.formatOutput) { |
| | result.transformed = this.formatOutput(result.transformed, targetVendor); |
| | } |
| | |
| | return result; |
| | } |
| | |
| | |
| | |
| | |
| | private transformOperation( |
| | primitive: SymbolicPrimitive, |
| | params: any, |
| | sourceVendor: ModelVendor, |
| | targetVendor: ModelVendor, |
| | options: Required<HarmonizationOptions> |
| | ): { |
| | success: boolean; |
| | message?: string; |
| | transformed?: string; |
| | targetPrimitive: SymbolicPrimitive | null; |
| | adapted: boolean; |
| | } { |
| | |
| | const targetSupport = this.registry.vendorSupports(targetVendor, primitive); |
| | |
| | |
| | let targetPrimitive = primitive; |
| | let adapted = false; |
| | |
| | if (!targetSupport && options.adaptToCapabilities) { |
| | const alternativePrimitive = this.findAlternativePrimitive(primitive, targetVendor); |
| | |
| | if (alternativePrimitive) { |
| | targetPrimitive = alternativePrimitive; |
| | adapted = true; |
| | } |
| | } |
| | |
| | |
| | const finalSupport = this.registry.vendorSupports(targetVendor, targetPrimitive); |
| | |
| | if (!finalSupport) { |
| | |
| | switch (options.fallbackBehavior) { |
| | case 'omit': |
| | return { |
| | success: false, |
| | message: `Operation ${primitive} not supported by ${targetVendor} and omitted`, |
| | targetPrimitive: null, |
| | adapted: false |
| | }; |
| | |
| | case 'comment': |
| | return { |
| | success: false, |
| | message: `Operation ${primitive} not supported by ${targetVendor}`, |
| | transformed: this.generateCommentForUnsupported(primitive, params, sourceVendor, targetVendor), |
| | targetPrimitive: null, |
| | adapted: false |
| | }; |
| | |
| | case 'emulate': |
| | |
| | const emulatedTransformation = this.emulateOperation(primitive, params, sourceVendor, targetVendor); |
| | |
| | if (emulatedTransformation) { |
| | return { |
| | success: true, |
| | message: `Operation ${primitive} emulated for ${targetVendor}`, |
| | transformed: emulatedTransformation, |
| | targetPrimitive: targetPrimitive, |
| | adapted: true |
| | }; |
| | } |
| | |
| | |
| | return { |
| | success: false, |
| | message: `Operation ${primitive} not supported by ${targetVendor} and cannot be emulated`, |
| | transformed: this.generateCommentForUnsupported(primitive, params, sourceVendor, targetVendor), |
| | targetPrimitive: null, |
| | adapted: false |
| | }; |
| | } |
| | } |
| | |
| | |
| | const implementation = this.registry.getVendorImplementation(targetPrimitive, targetVendor); |
| | if (!implementation) { |
| | return { |
| | success: false, |
| | message: `Could not find implementation for ${targetPrimitive} in ${targetVendor}`, |
| | targetPrimitive: null, |
| | adapted: false |
| | }; |
| | } |
| | |
| | |
| | let adaptedParams = params; |
| | if (adapted) { |
| | adaptedParams = this.adaptParameters(params, primitive, targetPrimitive); |
| | } |
| | |
| | |
| | const transformed = this.generateTransformation(targetPrimitive, adaptedParams, implementation); |
| | |
| | |
| | let finalTransformed = transformed; |
| | |
| | if (options.includeComments) { |
| | finalTransformed = this.addComments(transformed, primitive, sourceVendor, targetPrimitive, targetVendor, adapted); |
| | } |
| | |
| | if (options.embedTraceability) { |
| | finalTransformed = this.embedTraceability(finalTransformed, primitive, sourceVendor, targetVendor); |
| | } |
| | |
| | return { |
| | success: true, |
| | message: adapted ? `Operation ${primitive} adapted to ${targetPrimitive} for ${targetVendor}` : undefined, |
| | transformed: finalTransformed, |
| | targetPrimitive: targetPrimitive, |
| | adapted: adapted |
| | }; |
| | } |
| | |
| | |
| | |
| | |
| | private mapOperationPositions(content: string, vendor: ModelVendor): Map<SymbolicPrimitive, number[]> { |
| | const positions = new Map<SymbolicPrimitive, number[]>(); |
| | |
| | |
| | for (const primitive of Object.values(SymbolicPrimitive)) { |
| | positions.set(primitive, []); |
| | } |
| | |
| | |
| | switch (vendor) { |
| | case ModelVendor.ANTHROPIC: |
| | |
| | for (const primitive of Object.values(SymbolicPrimitive)) { |
| | const implementation = this.registry.getVendorImplementation(primitive, vendor); |
| | if (!implementation || implementation.style !== GrammarStyle.XML_TAGS) continue; |
| | |
| | if (implementation.prefix && implementation.suffix) { |
| | const regex = new RegExp(`${escapeRegExp(implementation.prefix)}[\\s\\S]*?${escapeRegExp(implementation.suffix)}`, 'g'); |
| | let match; |
| | const primitivePositions = positions.get(primitive) || []; |
| | |
| | while ((match = regex.exec(content)) !== null) { |
| | primitivePositions.push(match.index); |
| | } |
| | |
| | positions.set(primitive, primitivePositions); |
| | } |
| | } |
| | break; |
| | |
| | case ModelVendor.QWEN: |
| | case ModelVendor.OPENAI: |
| | |
| | for (const primitive of Object.values(SymbolicPrimitive)) { |
| | const implementation = this.registry.getVendorImplementation(primitive, vendor); |
| | if (!implementation || implementation.style !== GrammarStyle.SLASH_COMMANDS) continue; |
| | |
| | if (implementation.prefix) { |
| | const regex = new RegExp(`${escapeRegExp(implementation.prefix)}\\s+[^\\n]*`, 'g'); |
| | let match; |
| | const primitivePositions = positions.get(primitive) || []; |
| | |
| | while ((match = regex.exec(content)) !== null) { |
| | primitivePositions.push(match.index); |
| | } |
| | |
| | positions.set(primitive, primitivePositions); |
| | } |
| | } |
| | break; |
| | |
| | |
| | } |
| | |
| | return positions; |
| | } |
| |
|