foon-sdk 1.0.0
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/LICENSE +21 -0
- package/README.md +574 -0
- package/dist/cache/LRUCache.d.ts +36 -0
- package/dist/cache/LRUCache.d.ts.map +1 -0
- package/dist/cache/LRUCache.js +54 -0
- package/dist/cache/LRUCache.js.map +1 -0
- package/dist/cache/cache-key-generator.d.ts +9 -0
- package/dist/cache/cache-key-generator.d.ts.map +1 -0
- package/dist/cache/cache-key-generator.js +50 -0
- package/dist/cache/cache-key-generator.js.map +1 -0
- package/dist/cache/index.d.ts +3 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +21 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/engine/MappingEngine.d.ts +29 -0
- package/dist/engine/MappingEngine.d.ts.map +1 -0
- package/dist/engine/MappingEngine.js +196 -0
- package/dist/engine/MappingEngine.js.map +1 -0
- package/dist/engine/executor.d.ts +15 -0
- package/dist/engine/executor.d.ts.map +1 -0
- package/dist/engine/executor.js +137 -0
- package/dist/engine/executor.js.map +1 -0
- package/dist/engine/index.d.ts +5 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +23 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/jsonpath.d.ts +17 -0
- package/dist/engine/jsonpath.d.ts.map +1 -0
- package/dist/engine/jsonpath.js +73 -0
- package/dist/engine/jsonpath.js.map +1 -0
- package/dist/engine/type-converter.d.ts +12 -0
- package/dist/engine/type-converter.d.ts.map +1 -0
- package/dist/engine/type-converter.js +106 -0
- package/dist/engine/type-converter.js.map +1 -0
- package/dist/errors/error-factory.d.ts +30 -0
- package/dist/errors/error-factory.d.ts.map +1 -0
- package/dist/errors/error-factory.js +53 -0
- package/dist/errors/error-factory.js.map +1 -0
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +22 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/express/FonRouter.d.ts +56 -0
- package/dist/express/FonRouter.d.ts.map +1 -0
- package/dist/express/FonRouter.js +151 -0
- package/dist/express/FonRouter.js.map +1 -0
- package/dist/express/error-handler.d.ts +10 -0
- package/dist/express/error-handler.d.ts.map +1 -0
- package/dist/express/error-handler.js +55 -0
- package/dist/express/error-handler.js.map +1 -0
- package/dist/express/index.d.ts +33 -0
- package/dist/express/index.d.ts.map +1 -0
- package/dist/express/index.js +41 -0
- package/dist/express/index.js.map +1 -0
- package/dist/express/route-registry.d.ts +33 -0
- package/dist/express/route-registry.d.ts.map +1 -0
- package/dist/express/route-registry.js +52 -0
- package/dist/express/route-registry.js.map +1 -0
- package/dist/express/transform-middleware.d.ts +21 -0
- package/dist/express/transform-middleware.d.ts.map +1 -0
- package/dist/express/transform-middleware.js +62 -0
- package/dist/express/transform-middleware.js.map +1 -0
- package/dist/express/types.d.ts +73 -0
- package/dist/express/types.d.ts.map +1 -0
- package/dist/express/types.js +3 -0
- package/dist/express/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/base/Provider.d.ts +17 -0
- package/dist/providers/base/Provider.d.ts.map +1 -0
- package/dist/providers/base/Provider.js +43 -0
- package/dist/providers/base/Provider.js.map +1 -0
- package/dist/providers/base/index.d.ts +3 -0
- package/dist/providers/base/index.d.ts.map +1 -0
- package/dist/providers/base/index.js +21 -0
- package/dist/providers/base/index.js.map +1 -0
- package/dist/providers/base/prompt-builder.d.ts +22 -0
- package/dist/providers/base/prompt-builder.d.ts.map +1 -0
- package/dist/providers/base/prompt-builder.js +105 -0
- package/dist/providers/base/prompt-builder.js.map +1 -0
- package/dist/providers/gemini/GeminiProvider.d.ts +16 -0
- package/dist/providers/gemini/GeminiProvider.d.ts.map +1 -0
- package/dist/providers/gemini/GeminiProvider.js +48 -0
- package/dist/providers/gemini/GeminiProvider.js.map +1 -0
- package/dist/providers/gemini/gemini-client.d.ts +16 -0
- package/dist/providers/gemini/gemini-client.d.ts.map +1 -0
- package/dist/providers/gemini/gemini-client.js +83 -0
- package/dist/providers/gemini/gemini-client.js.map +1 -0
- package/dist/providers/gemini/index.d.ts +3 -0
- package/dist/providers/gemini/index.d.ts.map +1 -0
- package/dist/providers/gemini/index.js +8 -0
- package/dist/providers/gemini/index.js.map +1 -0
- package/dist/providers/index.d.ts +6 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +27 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama/OllamaProvider.d.ts +17 -0
- package/dist/providers/ollama/OllamaProvider.d.ts.map +1 -0
- package/dist/providers/ollama/OllamaProvider.js +47 -0
- package/dist/providers/ollama/OllamaProvider.js.map +1 -0
- package/dist/providers/ollama/index.d.ts +3 -0
- package/dist/providers/ollama/index.d.ts.map +1 -0
- package/dist/providers/ollama/index.js +8 -0
- package/dist/providers/ollama/index.js.map +1 -0
- package/dist/providers/ollama/ollama-client.d.ts +17 -0
- package/dist/providers/ollama/ollama-client.d.ts.map +1 -0
- package/dist/providers/ollama/ollama-client.js +83 -0
- package/dist/providers/ollama/ollama-client.js.map +1 -0
- package/dist/providers/openai/OpenAIProvider.d.ts +16 -0
- package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -0
- package/dist/providers/openai/OpenAIProvider.js +48 -0
- package/dist/providers/openai/OpenAIProvider.js.map +1 -0
- package/dist/providers/openai/index.d.ts +3 -0
- package/dist/providers/openai/index.d.ts.map +1 -0
- package/dist/providers/openai/index.js +8 -0
- package/dist/providers/openai/index.js.map +1 -0
- package/dist/providers/openai/openai-client.d.ts +16 -0
- package/dist/providers/openai/openai-client.d.ts.map +1 -0
- package/dist/providers/openai/openai-client.js +85 -0
- package/dist/providers/openai/openai-client.js.map +1 -0
- package/dist/schema/SchemaAdapter.d.ts +34 -0
- package/dist/schema/SchemaAdapter.d.ts.map +1 -0
- package/dist/schema/SchemaAdapter.js +59 -0
- package/dist/schema/SchemaAdapter.js.map +1 -0
- package/dist/schema/field-extractor.d.ts +10 -0
- package/dist/schema/field-extractor.d.ts.map +1 -0
- package/dist/schema/field-extractor.js +58 -0
- package/dist/schema/field-extractor.js.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +13 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/normalizer.d.ts +6 -0
- package/dist/schema/normalizer.d.ts.map +1 -0
- package/dist/schema/normalizer.js +17 -0
- package/dist/schema/normalizer.js.map +1 -0
- package/dist/schema/validator.d.ts +17 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +50 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/security/index.d.ts +5 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +21 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/input-validator.d.ts +6 -0
- package/dist/security/input-validator.d.ts.map +1 -0
- package/dist/security/input-validator.js +76 -0
- package/dist/security/input-validator.js.map +1 -0
- package/dist/security/prompt-sanitizer.d.ts +12 -0
- package/dist/security/prompt-sanitizer.d.ts.map +1 -0
- package/dist/security/prompt-sanitizer.js +66 -0
- package/dist/security/prompt-sanitizer.js.map +1 -0
- package/dist/security/redactor.d.ts +5 -0
- package/dist/security/redactor.d.ts.map +1 -0
- package/dist/security/redactor.js +37 -0
- package/dist/security/redactor.js.map +1 -0
- package/dist/security/security-config.d.ts +10 -0
- package/dist/security/security-config.d.ts.map +1 -0
- package/dist/security/security-config.js +26 -0
- package/dist/security/security-config.js.map +1 -0
- package/dist/trace/TraceBuilder.d.ts +58 -0
- package/dist/trace/TraceBuilder.d.ts.map +1 -0
- package/dist/trace/TraceBuilder.js +117 -0
- package/dist/trace/TraceBuilder.js.map +1 -0
- package/dist/trace/confidence-analyzer.d.ts +6 -0
- package/dist/trace/confidence-analyzer.d.ts.map +1 -0
- package/dist/trace/confidence-analyzer.js +30 -0
- package/dist/trace/confidence-analyzer.js.map +1 -0
- package/dist/trace/index.d.ts +4 -0
- package/dist/trace/index.d.ts.map +1 -0
- package/dist/trace/index.js +22 -0
- package/dist/trace/index.js.map +1 -0
- package/dist/trace/trace-utils.d.ts +20 -0
- package/dist/trace/trace-utils.d.ts.map +1 -0
- package/dist/trace/trace-utils.js +33 -0
- package/dist/trace/trace-utils.js.map +1 -0
- package/dist/transform.d.ts +30 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/transform.js +62 -0
- package/dist/transform.js.map +1 -0
- package/dist/types/cache.types.d.ts +41 -0
- package/dist/types/cache.types.d.ts.map +1 -0
- package/dist/types/cache.types.js +3 -0
- package/dist/types/cache.types.js.map +1 -0
- package/dist/types/errors.types.d.ts +22 -0
- package/dist/types/errors.types.d.ts.map +1 -0
- package/dist/types/errors.types.js +31 -0
- package/dist/types/errors.types.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mapping.types.d.ts +48 -0
- package/dist/types/mapping.types.d.ts.map +1 -0
- package/dist/types/mapping.types.js +3 -0
- package/dist/types/mapping.types.js.map +1 -0
- package/dist/types/provider.types.d.ts +62 -0
- package/dist/types/provider.types.d.ts.map +1 -0
- package/dist/types/provider.types.js +3 -0
- package/dist/types/provider.types.js.map +1 -0
- package/dist/types/schema.types.d.ts +68 -0
- package/dist/types/schema.types.d.ts.map +1 -0
- package/dist/types/schema.types.js +3 -0
- package/dist/types/schema.types.js.map +1 -0
- package/dist/types/security.types.d.ts +32 -0
- package/dist/types/security.types.d.ts.map +1 -0
- package/dist/types/security.types.js +3 -0
- package/dist/types/security.types.js.map +1 -0
- package/dist/types/trace.types.d.ts +129 -0
- package/dist/types/trace.types.d.ts.map +1 -0
- package/dist/types/trace.types.js +3 -0
- package/dist/types/trace.types.js.map +1 -0
- package/dist/types/transform.types.d.ts +56 -0
- package/dist/types/transform.types.d.ts.map +1 -0
- package/dist/types/transform.types.js +3 -0
- package/dist/types/transform.types.js.map +1 -0
- package/package.json +107 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Achraf Achkari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
# FOON SDK
|
|
2
|
+
|
|
3
|
+
> TypeScript SDK for semantic JSON transformation using LLMs
|
|
4
|
+
|
|
5
|
+
FOON SDK transforms free-form JSON to schema-compliant JSON using AI-powered semantic mapping. It accepts structurally incorrect but semantically correct JSON and transforms it to match your target schema.
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- **Semantic Mapping**: Uses LLMs to understand intent and map fields intelligently
|
|
10
|
+
- **Schema Validation**: Ensures output always matches your JSON Schema
|
|
11
|
+
- **Explainability**: Comprehensive trace of all mapping decisions with confidence scores
|
|
12
|
+
- **Type Safety**: Full TypeScript support with type definitions
|
|
13
|
+
- **Caching**: Built-in LRU cache reduces API calls for repeated patterns
|
|
14
|
+
- **Security**: Input validation, redaction, and prompt injection protection
|
|
15
|
+
- **Multiple Providers**: Supports Gemini, OpenAI, and Ollama
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install foon-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { transform, OpenAIProvider } from 'foon-sdk';
|
|
27
|
+
|
|
28
|
+
// Define your target schema
|
|
29
|
+
const userSchema = {
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: {
|
|
32
|
+
name: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
given: { type: 'string' },
|
|
36
|
+
family: { type: 'string' },
|
|
37
|
+
},
|
|
38
|
+
required: ['given', 'family'],
|
|
39
|
+
},
|
|
40
|
+
email: { type: 'string', format: 'email' },
|
|
41
|
+
},
|
|
42
|
+
required: ['name', 'email'],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Transform messy input
|
|
46
|
+
const result = await transform(
|
|
47
|
+
{
|
|
48
|
+
firstname: 'John',
|
|
49
|
+
lastname: 'Doe',
|
|
50
|
+
email: 'john.doe@example.com',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
schema: userSchema,
|
|
54
|
+
provider: new OpenAIProvider({
|
|
55
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
56
|
+
model: 'gpt-5-nano',
|
|
57
|
+
}),
|
|
58
|
+
confidenceThreshold: 0.85,
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (result.ok) {
|
|
63
|
+
console.log('Output:', result.output);
|
|
64
|
+
// Output: { name: { given: 'John', family: 'Doe' }, email: 'john.doe@example.com' }
|
|
65
|
+
} else {
|
|
66
|
+
console.error('Error:', result.error);
|
|
67
|
+
console.log('Trace:', result.trace);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Express Middleware
|
|
72
|
+
|
|
73
|
+
FOON SDK includes Express middleware for seamless integration with Express applications.
|
|
74
|
+
|
|
75
|
+
### Quick Start
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import express from 'express';
|
|
79
|
+
import { createFonRouter } from 'foon-sdk/express';
|
|
80
|
+
import { OpenAIProvider } from 'foon-sdk';
|
|
81
|
+
|
|
82
|
+
const app = express();
|
|
83
|
+
app.use(express.json());
|
|
84
|
+
|
|
85
|
+
// Create FOON router
|
|
86
|
+
const fonRouter = createFonRouter({
|
|
87
|
+
provider: new OpenAIProvider({
|
|
88
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
89
|
+
model: 'gpt-5-nano'
|
|
90
|
+
}),
|
|
91
|
+
prefix: '/foon', // Default: '/foon'
|
|
92
|
+
confidenceThreshold: 0.85, // Default: 0.85
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Register routes with schemas
|
|
96
|
+
fonRouter.post('/users', {
|
|
97
|
+
schema: userCreateSchema,
|
|
98
|
+
handler: (req, res) => {
|
|
99
|
+
// req.body is now transformed and validated
|
|
100
|
+
res.json({ success: true, user: req.body });
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
fonRouter.put('/users/:id', {
|
|
105
|
+
schema: userUpdateSchema,
|
|
106
|
+
handler: updateUserHandler,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Mount the router
|
|
110
|
+
app.use(fonRouter.getRouter());
|
|
111
|
+
|
|
112
|
+
app.listen(3000);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### How It Works
|
|
116
|
+
|
|
117
|
+
The Express middleware creates **two routes** for each registration:
|
|
118
|
+
|
|
119
|
+
1. **Original route** (e.g., `/users`) - Works normally without transformation
|
|
120
|
+
2. **FOON route** (e.g., `/foon/users`) - Applies FOON transformation before handler
|
|
121
|
+
|
|
122
|
+
Requests to FOON routes:
|
|
123
|
+
|
|
124
|
+
- Transform `req.body` using the configured schema
|
|
125
|
+
- Replace `req.body` with validated output
|
|
126
|
+
- Add trace ID header (`X-FON-Trace-Id`)
|
|
127
|
+
- Forward to the same handler
|
|
128
|
+
|
|
129
|
+
### Configuration
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
interface FonRouterConfig {
|
|
133
|
+
provider: Provider; // LLM provider (required)
|
|
134
|
+
prefix?: string; // Route prefix (default: '/foon')
|
|
135
|
+
methods?: HttpMethod[]; // Methods to transform (default: ['POST', 'PUT', 'PATCH'])
|
|
136
|
+
confidenceThreshold?: number; // Confidence threshold (default: 0.85)
|
|
137
|
+
cache?: Cache; // Cache instance
|
|
138
|
+
security?: SecurityOptions; // Security options
|
|
139
|
+
traceHeader?: string; // Trace header name (default: 'X-FON-Trace-Id')
|
|
140
|
+
onError?: ErrorHandler; // Custom error handler
|
|
141
|
+
createOriginalRoutes?: boolean; // Create original routes (default: true)
|
|
142
|
+
verbose?: boolean; // Verbose logging (default: false)
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Route Configuration
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface RouteConfig {
|
|
150
|
+
schema: object; // JSON Schema for this route
|
|
151
|
+
handler: RequestHandler; // Express handler
|
|
152
|
+
createOriginal?: boolean; // Override: create original route
|
|
153
|
+
confidenceThreshold?: number; // Override: confidence threshold for this route
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Examples
|
|
158
|
+
|
|
159
|
+
#### Basic Usage
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
fonRouter.post('/users', {
|
|
163
|
+
schema: userSchema,
|
|
164
|
+
handler: (req, res) => {
|
|
165
|
+
// req.body is transformed and validated
|
|
166
|
+
res.json(req.body);
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Now you have:
|
|
171
|
+
// POST /users - Original route (untransformed)
|
|
172
|
+
// POST /foon/users - FOON route (transformed)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Custom Error Handler
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const fonRouter = createFonRouter({
|
|
179
|
+
provider,
|
|
180
|
+
onError: (error, req, res, next) => {
|
|
181
|
+
res.status(400).json({
|
|
182
|
+
error: error.category,
|
|
183
|
+
message: error.message,
|
|
184
|
+
traceId: error.traceId,
|
|
185
|
+
// Include trace for debugging
|
|
186
|
+
trace: req.fonTrace,
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Disable Original Routes
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const fonRouter = createFonRouter({
|
|
196
|
+
provider,
|
|
197
|
+
createOriginalRoutes: false, // Only create FOON routes
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Now only /foon/users exists, not /users
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Custom Prefix
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const fonRouter = createFonRouter({
|
|
207
|
+
provider,
|
|
208
|
+
prefix: '/api/semantic',
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
fonRouter.post('/users', { schema, handler });
|
|
212
|
+
// Creates: POST /api/semantic/users
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Per-Route Configuration
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
fonRouter.post('/users', {
|
|
219
|
+
schema: userSchema,
|
|
220
|
+
handler: createUserHandler,
|
|
221
|
+
createOriginal: false, // Don't create /users for this route
|
|
222
|
+
confidenceThreshold: 0.9, // Higher threshold for this route
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Trace Headers
|
|
227
|
+
|
|
228
|
+
FOON routes automatically add headers to responses:
|
|
229
|
+
|
|
230
|
+
- `X-FON-Trace-Id`: Unique trace ID for debugging
|
|
231
|
+
- `X-FON-Timing-Total`: Total processing time (verbose mode)
|
|
232
|
+
- `X-FON-Timing-Proposal`: LLM call time (verbose mode)
|
|
233
|
+
- `X-FON-Cache-Hit`: Whether cache was hit (verbose mode)
|
|
234
|
+
|
|
235
|
+
### Error Handling
|
|
236
|
+
|
|
237
|
+
When transformation fails, the default error handler returns:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"error": "CONFIDENCE_TOO_LOW",
|
|
242
|
+
"message": "1 assignment(s) below confidence threshold 0.85",
|
|
243
|
+
"traceId": "uuid",
|
|
244
|
+
"details": { ... }
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
HTTP status codes:
|
|
249
|
+
|
|
250
|
+
- `400` - Bad Request (validation error, confidence too low)
|
|
251
|
+
- `413` - Payload Too Large (security limits exceeded)
|
|
252
|
+
- `500` - Internal Server Error (execution error)
|
|
253
|
+
- `502` - Bad Gateway (provider error)
|
|
254
|
+
|
|
255
|
+
### Accessing Trace Data
|
|
256
|
+
|
|
257
|
+
The trace is attached to the request object:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
fonRouter.post('/users', {
|
|
261
|
+
schema: userSchema,
|
|
262
|
+
handler: (req, res) => {
|
|
263
|
+
const trace = (req as any).fonTrace;
|
|
264
|
+
console.log('Confidence:', trace.confidenceSummary);
|
|
265
|
+
console.log('Timings:', trace.timings);
|
|
266
|
+
res.json(req.body);
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## How It Works
|
|
272
|
+
|
|
273
|
+
1. **LLM Generates Mapping Plan**: The LLM analyzes your input and target schema, returning a mapping plan (not the final JSON)
|
|
274
|
+
2. **Deterministic Execution**: The SDK applies the mapping plan using JSONPath resolution and safe type conversions
|
|
275
|
+
3. **Validation**: Output is validated against your schema with detailed error reporting
|
|
276
|
+
4. **Trace Output**: Complete trace includes confidence scores, warnings, dropped fields, and timing
|
|
277
|
+
|
|
278
|
+
### Key Principle
|
|
279
|
+
|
|
280
|
+
FOON SDK does NOT let the LLM generate the final JSON. Instead:
|
|
281
|
+
|
|
282
|
+
- LLM returns a **mapping plan** with confidence scores
|
|
283
|
+
- SDK executes the plan **deterministically**
|
|
284
|
+
- Output is **always validated** against your schema
|
|
285
|
+
|
|
286
|
+
This approach ensures reliability, explainability, and prevents hallucinations.
|
|
287
|
+
|
|
288
|
+
## API Reference
|
|
289
|
+
|
|
290
|
+
### `transform(input, options)`
|
|
291
|
+
|
|
292
|
+
Main transformation function.
|
|
293
|
+
|
|
294
|
+
**Parameters:**
|
|
295
|
+
|
|
296
|
+
- `input: unknown` - The input JSON to transform
|
|
297
|
+
- `options: TransformOptions` - Transformation options
|
|
298
|
+
|
|
299
|
+
**Options:**
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
interface TransformOptions {
|
|
303
|
+
mode?: 'SEMANTIC'; // Only SEMANTIC mode in v1.0
|
|
304
|
+
schema: object | SchemaAdapter; // JSON Schema object
|
|
305
|
+
provider: Provider; // LLM provider instance
|
|
306
|
+
confidenceThreshold?: number; // Default: 0.85
|
|
307
|
+
cache?: Cache; // Optional cache instance
|
|
308
|
+
verbose?: boolean; // Enable verbose output
|
|
309
|
+
security?: SecurityOptions; // Security settings
|
|
310
|
+
hooks?: TransformHooks; // Observability hooks
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Returns:** `Promise<TransformResult>`
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
interface TransformResult {
|
|
318
|
+
ok: boolean; // Success flag
|
|
319
|
+
output?: unknown; // Transformed output (if successful)
|
|
320
|
+
error?: FONError; // Error details (if failed)
|
|
321
|
+
trace: TraceReport; // Complete trace report
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Providers
|
|
326
|
+
|
|
327
|
+
#### GeminiProvider
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
import { GeminiProvider } from 'foon-sdk';
|
|
331
|
+
|
|
332
|
+
const provider = new GeminiProvider({
|
|
333
|
+
apiKey: process.env.GEMINI_API_KEY,
|
|
334
|
+
model: 'gemini-1.5-flash', // Optional, default: gemini-1.5-flash
|
|
335
|
+
timeout: 30000, // Optional, default: 30s
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### OpenAIProvider
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { OpenAIProvider } from 'foon-sdk';
|
|
343
|
+
|
|
344
|
+
const provider = new OpenAIProvider({
|
|
345
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
346
|
+
model: 'gpt-4o-mini', // Optional, default: gpt-4o-mini
|
|
347
|
+
timeout: 30000, // Optional, default: 30s
|
|
348
|
+
baseUrl: 'https://api.openai.com/v1', // Optional, for custom endpoints
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### OllamaProvider
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { OllamaProvider } from 'foon-sdk';
|
|
356
|
+
|
|
357
|
+
const provider = new OllamaProvider({
|
|
358
|
+
apiKey: process.env.OLLAMA_API_KEY, // Optional for local Ollama
|
|
359
|
+
model: 'llama2', // Optional, default: llama2
|
|
360
|
+
timeout: 60000, // Optional, default: 30s (Ollama can be slower)
|
|
361
|
+
baseUrl: 'http://localhost:11434', // Optional, default: http://localhost:11434
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Note:** Ollama can run locally without an API key. If using a hosted Ollama instance, provide the `apiKey` and `baseUrl`.
|
|
366
|
+
|
|
367
|
+
### Security Options
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
const result = await transform(input, {
|
|
371
|
+
schema,
|
|
372
|
+
provider,
|
|
373
|
+
security: {
|
|
374
|
+
maxInputSize: 1024 * 1024, // 1MB default
|
|
375
|
+
maxDepth: 10, // Max nesting depth
|
|
376
|
+
maxKeys: 1000, // Max number of keys
|
|
377
|
+
redactKeys: ['password', 'token'], // Keys to redact
|
|
378
|
+
sanitizePrompt: true, // Prompt injection protection
|
|
379
|
+
includeValues: false, // Don't send values to LLM (structure only)
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Examples
|
|
385
|
+
|
|
386
|
+
### Type Conversion
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
const result = await transform(
|
|
390
|
+
{ age: '30' }, // String instead of number
|
|
391
|
+
{
|
|
392
|
+
schema: {
|
|
393
|
+
type: 'object',
|
|
394
|
+
properties: {
|
|
395
|
+
age: { type: 'integer' },
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
provider,
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
// Output: { age: 30 } - Automatically converted to number
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Nested Field Mapping
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
const result = await transform(
|
|
408
|
+
{
|
|
409
|
+
city: 'San Francisco',
|
|
410
|
+
country: 'USA',
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
schema: {
|
|
414
|
+
type: 'object',
|
|
415
|
+
properties: {
|
|
416
|
+
address: {
|
|
417
|
+
type: 'object',
|
|
418
|
+
properties: {
|
|
419
|
+
city: { type: 'string' },
|
|
420
|
+
country: { type: 'string' },
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
provider,
|
|
426
|
+
}
|
|
427
|
+
);
|
|
428
|
+
// Output: { address: { city: 'San Francisco', country: 'USA' } }
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Confidence Threshold
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
const result = await transform(input, {
|
|
435
|
+
schema,
|
|
436
|
+
provider,
|
|
437
|
+
confidenceThreshold: 0.9, // Fail if any mapping < 90% confidence
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
if (!result.ok && result.error?.category === 'CONFIDENCE_TOO_LOW') {
|
|
441
|
+
console.log('Rejected assignments:', result.trace.execution.assignmentsRejected);
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Using Cache
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import { transform, OpenAIProvider, LRUCache } from 'foon-sdk';
|
|
449
|
+
|
|
450
|
+
const cache = new LRUCache({ max: 100, ttl: 3600000 }); // 100 entries, 1 hour TTL
|
|
451
|
+
|
|
452
|
+
const result = await transform(input, {
|
|
453
|
+
schema,
|
|
454
|
+
provider: new OpenAIProvider({
|
|
455
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
456
|
+
model: 'gpt-5-nano',
|
|
457
|
+
}),
|
|
458
|
+
cache,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
console.log('Cache hit:', result.trace.cache.hit);
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Error Handling
|
|
465
|
+
|
|
466
|
+
FOON SDK provides detailed error categories:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
if (!result.ok) {
|
|
470
|
+
switch (result.error?.category) {
|
|
471
|
+
case 'SCHEMA_LOAD_ERROR':
|
|
472
|
+
// Invalid schema
|
|
473
|
+
break;
|
|
474
|
+
case 'PROVIDER_ERROR':
|
|
475
|
+
// LLM API error
|
|
476
|
+
break;
|
|
477
|
+
case 'MAPPING_PLAN_PARSE_ERROR':
|
|
478
|
+
// LLM returned invalid mapping plan
|
|
479
|
+
break;
|
|
480
|
+
case 'CONFIDENCE_TOO_LOW':
|
|
481
|
+
// Mapping confidence below threshold
|
|
482
|
+
break;
|
|
483
|
+
case 'EXECUTION_ERROR':
|
|
484
|
+
// Error applying mapping plan
|
|
485
|
+
break;
|
|
486
|
+
case 'VALIDATION_ERROR':
|
|
487
|
+
// Output doesn't match schema
|
|
488
|
+
break;
|
|
489
|
+
case 'SECURITY_LIMIT_EXCEEDED':
|
|
490
|
+
// Input exceeded security limits
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Trace Output
|
|
497
|
+
|
|
498
|
+
Every transformation includes a comprehensive trace:
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
interface TraceReport {
|
|
502
|
+
traceId: string; // Unique trace ID
|
|
503
|
+
mode: 'SEMANTIC';
|
|
504
|
+
provider: string; // Provider name
|
|
505
|
+
promptVersion: string; // Prompt version
|
|
506
|
+
timings: {
|
|
507
|
+
total: number; // Total time (ms)
|
|
508
|
+
proposal: number; // LLM call time
|
|
509
|
+
execution: number; // Execution time
|
|
510
|
+
validation: number; // Validation time
|
|
511
|
+
};
|
|
512
|
+
mappingPlan: {
|
|
513
|
+
raw: string; // Raw LLM response
|
|
514
|
+
parsed: MappingPlan; // Parsed mapping plan
|
|
515
|
+
};
|
|
516
|
+
execution: {
|
|
517
|
+
assignmentsApplied: AssignmentTrace[];
|
|
518
|
+
assignmentsRejected: RejectedAssignment[];
|
|
519
|
+
droppedFields: Drop[];
|
|
520
|
+
warnings: Warning[];
|
|
521
|
+
conflicts: Conflict[];
|
|
522
|
+
};
|
|
523
|
+
validation: {
|
|
524
|
+
success: boolean;
|
|
525
|
+
errors: ValidationError[];
|
|
526
|
+
};
|
|
527
|
+
cache: {
|
|
528
|
+
hit: boolean;
|
|
529
|
+
key: string;
|
|
530
|
+
};
|
|
531
|
+
confidenceSummary: {
|
|
532
|
+
min: number;
|
|
533
|
+
max: number;
|
|
534
|
+
avg: number;
|
|
535
|
+
countBelowThreshold: number;
|
|
536
|
+
threshold: number;
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
## Testing
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# Run deterministic tests (unit + integration, no external providers)
|
|
545
|
+
npm test
|
|
546
|
+
|
|
547
|
+
# Run all tests (including e2e provider tests)
|
|
548
|
+
npm run test:all
|
|
549
|
+
|
|
550
|
+
# Unit tests only
|
|
551
|
+
npm run test:unit
|
|
552
|
+
|
|
553
|
+
# Integration tests
|
|
554
|
+
npm run test:integration
|
|
555
|
+
|
|
556
|
+
# E2E tests (requires provider credentials in .env.local)
|
|
557
|
+
npm run test:e2e
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
## Building
|
|
561
|
+
|
|
562
|
+
```bash
|
|
563
|
+
npm run build
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
MIT License - Copyright (c) 2026 Achraf Achkari
|
|
569
|
+
|
|
570
|
+
See [LICENSE](LICENSE) for details.
|
|
571
|
+
|
|
572
|
+
## Contributing
|
|
573
|
+
|
|
574
|
+
Issues and pull requests are welcome.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Cache as ICache, CachedMappingPlan } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* LRU Cache implementation
|
|
4
|
+
*/
|
|
5
|
+
export declare class LRUCache implements ICache {
|
|
6
|
+
private cache;
|
|
7
|
+
constructor(options?: {
|
|
8
|
+
max?: number;
|
|
9
|
+
ttl?: number;
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Get cached mapping plan
|
|
13
|
+
*/
|
|
14
|
+
get(key: string): Promise<CachedMappingPlan | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Store mapping plan in cache
|
|
17
|
+
*/
|
|
18
|
+
set(key: string, value: CachedMappingPlan, ttl?: number): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if key exists
|
|
21
|
+
*/
|
|
22
|
+
has(key: string): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Delete entry
|
|
25
|
+
*/
|
|
26
|
+
delete(key: string): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Clear all entries
|
|
29
|
+
*/
|
|
30
|
+
clear(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Get cache size
|
|
33
|
+
*/
|
|
34
|
+
size(): number;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=LRUCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LRUCache.d.ts","sourceRoot":"","sources":["../../src/cache/LRUCache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE9D;;GAEG;AACH,qBAAa,QAAS,YAAW,MAAM;IACrC,OAAO,CAAC,KAAK,CAAiC;gBAElC,OAAO,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAO;IAOxD;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAKzD;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LRUCache = void 0;
|
|
4
|
+
const lru_cache_1 = require("lru-cache");
|
|
5
|
+
/**
|
|
6
|
+
* LRU Cache implementation
|
|
7
|
+
*/
|
|
8
|
+
class LRUCache {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.cache = new lru_cache_1.LRUCache({
|
|
11
|
+
max: options.max || 100, // Default: 100 entries
|
|
12
|
+
ttl: options.ttl || 1000 * 60 * 60, // Default: 1 hour
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get cached mapping plan
|
|
17
|
+
*/
|
|
18
|
+
async get(key) {
|
|
19
|
+
const value = this.cache.get(key);
|
|
20
|
+
return value || null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Store mapping plan in cache
|
|
24
|
+
*/
|
|
25
|
+
async set(key, value, ttl) {
|
|
26
|
+
this.cache.set(key, value, { ttl });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if key exists
|
|
30
|
+
*/
|
|
31
|
+
async has(key) {
|
|
32
|
+
return this.cache.has(key);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Delete entry
|
|
36
|
+
*/
|
|
37
|
+
async delete(key) {
|
|
38
|
+
return this.cache.delete(key);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Clear all entries
|
|
42
|
+
*/
|
|
43
|
+
async clear() {
|
|
44
|
+
this.cache.clear();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get cache size
|
|
48
|
+
*/
|
|
49
|
+
size() {
|
|
50
|
+
return this.cache.size;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.LRUCache = LRUCache;
|
|
54
|
+
//# sourceMappingURL=LRUCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LRUCache.js","sourceRoot":"","sources":["../../src/cache/LRUCache.ts"],"names":[],"mappings":";;;AAAA,yCAA4C;AAG5C;;GAEG;AACH,MAAa,QAAQ;IAGnB,YAAY,UAA0C,EAAE;QACtD,IAAI,CAAC,KAAK,GAAG,IAAI,oBAAG,CAA4B;YAC9C,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,uBAAuB;YAChD,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,GAAG,EAAE,EAAE,kBAAkB;SACvD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,KAAK,IAAI,IAAI,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAwB,EAAE,GAAY;QAC3D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AApDD,4BAoDC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate stable cache key from inputs
|
|
3
|
+
*/
|
|
4
|
+
export declare function generateCacheKey(schemaVersion: string, inputSignature: string, confidenceThreshold: number, providerName: string, promptVersion: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Generate input signature (hash of keys + structure, not values)
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateInputSignature(input: unknown): string;
|
|
9
|
+
//# sourceMappingURL=cache-key-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key-generator.d.ts","sourceRoot":"","sources":["../../src/cache/cache-key-generator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAI7D"}
|