1- import { getAllBlobs , getBlob } from "@/routes/ai/spell/behavior/effects.ts" ;
2- import { generateText } from "@/lib/llm.ts" ;
3- import { performSearch } from "@/routes/ai/spell/behavior/search.ts" ;
4- import { checkSchemaMatch } from "@/lib/schema-match.ts" ;
1+ import * as HttpStatusCodes from "stoker/http-status-codes" ;
2+ import { z } from "zod" ;
3+ import { getAllBlobs } from "@/routes/ai/spell/behavior/effects.ts" ;
4+
5+ import type { AppRouteHandler } from "@/lib/types.ts" ;
6+ import type { FulfillSchemaRoute } from "@/routes/ai/spell/spell.routes.ts" ;
7+ import { Spell } from "@/routes/ai/spell/spell.ts" ;
8+ import { performSearch } from "../behavior/search.ts" ;
59import { Logger } from "@/lib/prefixed-logger.ts" ;
6- import {
7- ProcessSchemaRequest ,
8- ProcessSchemaResponse ,
9- } from "@/routes/ai/spell/spell.handlers.ts" ;
10+ import { candidates } from "@/routes/ai/spell/caster.ts" ;
11+ import { CasterSchemaRoute } from "@/routes/ai/spell/spell.routes.ts" ;
12+ import { processSpellSearch } from "@/routes/ai/spell/behavior/spell-search.ts" ;
13+ import { captureException } from "@sentry/deno" ;
14+ import { areSchemaCompatible } from "@/routes/ai/spell/schema-compatibility.ts" ;
15+
16+ import { generateText } from "@/lib/llm.ts" ;
1017import {
1118 decomposeSchema ,
1219 findExactMatches ,
1320 findFragmentMatches ,
1421 reassembleFragments ,
1522 SchemaFragment ,
1623} from "@/routes/ai/spell/schema.ts" ;
24+ import { extractJSON } from "@/routes/ai/spell/json.ts" ;
25+
26+ export const FulfillSchemaRequestSchema = z . object ( {
27+ schema : z . record (
28+ z
29+ . string ( )
30+ . or (
31+ z . number ( ) . or ( z . boolean ( ) . or ( z . array ( z . any ( ) ) . or ( z . record ( z . any ( ) ) ) ) ) ,
32+ ) ,
33+ ) . openapi ( {
34+ example : {
35+ title : { type : "string" } ,
36+ url : { type : "string" } ,
37+ } ,
38+ } ) ,
39+ tags : z . array ( z . string ( ) ) . optional ( ) ,
40+ many : z . boolean ( ) . optional ( ) ,
41+ prompt : z . string ( ) . optional ( ) ,
42+ options : z
43+ . object ( {
44+ format : z . enum ( [ "json" , "yaml" ] ) . optional ( ) ,
45+ validate : z . boolean ( ) . optional ( ) ,
46+ maxExamples : z . number ( ) . default ( 5 ) . optional ( ) ,
47+ exact : z . boolean ( ) . optional ( ) ,
48+ } )
49+ . optional ( ) ,
50+ } ) ;
51+
52+ export const FulfillSchemaResponseSchema = z . object ( {
53+ result : z . union ( [ z . record ( z . any ( ) ) , z . array ( z . record ( z . any ( ) ) ) ] ) ,
54+ metadata : z . object ( {
55+ processingTime : z . number ( ) ,
56+ schemaFormat : z . string ( ) ,
57+ fragments : z . array (
58+ z . object ( {
59+ matches : z . array (
60+ z . object ( {
61+ key : z . string ( ) ,
62+ data : z . record ( z . any ( ) ) ,
63+ similarity : z . number ( ) ,
64+ } ) ,
65+ ) ,
66+ path : z . array ( z . string ( ) ) ,
67+ schema : z . record ( z . any ( ) ) ,
68+ } ) ,
69+ ) ,
70+ reassembledExample : z . record ( z . any ( ) ) ,
71+ tagMatchInfo : z . object ( {
72+ usedTags : z . any ( ) ,
73+ matchRanks : z . array ( z . object ( {
74+ path : z . any ( ) ,
75+ matches : z . any ( ) ,
76+ } ) ) ,
77+ } ) ,
78+ } ) ,
79+ } ) ;
80+
81+ export type FulfillSchemaRequest = z . infer < typeof FulfillSchemaRequestSchema > ;
82+ export type FulfillSchemaResponse = z . infer < typeof FulfillSchemaResponseSchema > ;
1783
1884function calculateTagRank (
1985 data : Record < string , unknown > ,
@@ -34,10 +100,10 @@ function calculateTagRank(
34100}
35101
36102export async function processSchema (
37- body : ProcessSchemaRequest ,
103+ body : FulfillSchemaRequest ,
38104 logger : Logger ,
39105 startTime : number ,
40- ) : Promise < ProcessSchemaResponse > {
106+ ) : Promise < FulfillSchemaResponse > {
41107 const tags = body . tags || [ ] ;
42108 logger . info (
43109 { schema : body . schema , many : body . many , options : body . options , tags } ,
@@ -162,28 +228,6 @@ export async function processSchema(
162228 ) ;
163229
164230 let result : Record < string , unknown > | Array < Record < string , unknown > > ;
165- function extractJSON (
166- text : string ,
167- ) : Record < string , unknown > | Array < Record < string , unknown > > {
168- try {
169- // Try to extract from markdown code block first
170- const markdownMatch = text . match ( / ` ` ` (?: j s o n ) ? \s * ( [ \s \S ] * ?) \s * ` ` ` / ) ;
171- if ( markdownMatch ) {
172- return JSON . parse ( markdownMatch [ 1 ] . trim ( ) ) ;
173- }
174-
175- // If not in markdown, try to find JSON-like content
176- const jsonMatch = text . match ( / \{ [ \s \S ] * \} | \[ [ \s \S ] * \] / ) ;
177- if ( jsonMatch ) {
178- return JSON . parse ( jsonMatch [ 0 ] . trim ( ) ) ;
179- }
180-
181- // If no special formatting, try parsing the original text
182- return JSON . parse ( text . trim ( ) ) ;
183- } catch ( error ) {
184- return { } ;
185- }
186- }
187231
188232 try {
189233 logger . debug ( "Parsing LLM response" ) ;
@@ -318,3 +362,26 @@ Respond with ${
318362 many ? "an array of valid JSON objects" : "a single valid JSON object"
319363 } .`;
320364}
365+
366+ export const fulfill : AppRouteHandler < FulfillSchemaRoute > = async ( c ) => {
367+ const logger : Logger = c . get ( "logger" ) ;
368+ const body = ( await c . req . json ( ) ) as FulfillSchemaRequest ;
369+ const startTime = performance . now ( ) ;
370+
371+ try {
372+ const response = await processSchema ( body , logger , startTime ) ;
373+
374+ logger . info (
375+ { processingTime : response . metadata . processingTime } ,
376+ "Request completed" ,
377+ ) ;
378+ return c . json ( response , HttpStatusCodes . OK ) ;
379+ } catch ( error ) {
380+ logger . error ( { error } , "Error processing schema" ) ;
381+ captureException ( error ) ;
382+ return c . json (
383+ { error : "Failed to process schema" } ,
384+ HttpStatusCodes . INTERNAL_SERVER_ERROR ,
385+ ) ;
386+ }
387+ } ;
0 commit comments