@cogitator-ai/core 0.11.5 → 0.14.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/README.md +212 -0
- package/dist/cache/cache-key.d.ts +11 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +65 -0
- package/dist/cache/cache-key.js.map +1 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/storage/index.d.ts +4 -0
- package/dist/cache/storage/index.d.ts.map +1 -0
- package/dist/cache/storage/index.js +3 -0
- package/dist/cache/storage/index.js.map +1 -0
- package/dist/cache/storage/memory.d.ts +24 -0
- package/dist/cache/storage/memory.d.ts.map +1 -0
- package/dist/cache/storage/memory.js +108 -0
- package/dist/cache/storage/memory.js.map +1 -0
- package/dist/cache/storage/redis.d.ts +32 -0
- package/dist/cache/storage/redis.d.ts.map +1 -0
- package/dist/cache/storage/redis.js +127 -0
- package/dist/cache/storage/redis.js.map +1 -0
- package/dist/cache/tool-cache.d.ts +8 -0
- package/dist/cache/tool-cache.d.ts.map +1 -0
- package/dist/cache/tool-cache.js +127 -0
- package/dist/cache/tool-cache.js.map +1 -0
- package/dist/cogitator/initializers.d.ts +4 -0
- package/dist/cogitator/initializers.d.ts.map +1 -1
- package/dist/cogitator/initializers.js +14 -0
- package/dist/cogitator/initializers.js.map +1 -1
- package/dist/cogitator.d.ts +38 -1
- package/dist/cogitator.d.ts.map +1 -1
- package/dist/cogitator.js +56 -1
- package/dist/cogitator.js.map +1 -1
- package/dist/cost-routing/cost-estimator.d.ts +18 -0
- package/dist/cost-routing/cost-estimator.d.ts.map +1 -0
- package/dist/cost-routing/cost-estimator.js +149 -0
- package/dist/cost-routing/cost-estimator.js.map +1 -0
- package/dist/cost-routing/index.d.ts +2 -0
- package/dist/cost-routing/index.d.ts.map +1 -1
- package/dist/cost-routing/index.js +2 -0
- package/dist/cost-routing/index.js.map +1 -1
- package/dist/cost-routing/token-estimator.d.ts +22 -0
- package/dist/cost-routing/token-estimator.d.ts.map +1 -0
- package/dist/cost-routing/token-estimator.js +88 -0
- package/dist/cost-routing/token-estimator.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/security/classifiers/index.d.ts +3 -0
- package/dist/security/classifiers/index.d.ts.map +1 -0
- package/dist/security/classifiers/index.js +3 -0
- package/dist/security/classifiers/index.js.map +1 -0
- package/dist/security/classifiers/llm-classifier.d.ts +10 -0
- package/dist/security/classifiers/llm-classifier.d.ts.map +1 -0
- package/dist/security/classifiers/llm-classifier.js +110 -0
- package/dist/security/classifiers/llm-classifier.js.map +1 -0
- package/dist/security/classifiers/local-classifier.d.ts +8 -0
- package/dist/security/classifiers/local-classifier.d.ts.map +1 -0
- package/dist/security/classifiers/local-classifier.js +130 -0
- package/dist/security/classifiers/local-classifier.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 +4 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/patterns.d.ts +6 -0
- package/dist/security/patterns.d.ts.map +1 -0
- package/dist/security/patterns.js +338 -0
- package/dist/security/patterns.js.map +1 -0
- package/dist/security/prompt-injection-detector.d.ts +28 -0
- package/dist/security/prompt-injection-detector.d.ts.map +1 -0
- package/dist/security/prompt-injection-detector.js +134 -0
- package/dist/security/prompt-injection-detector.js.map +1 -0
- package/dist/tools/hash.d.ts +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/dist/tools/random.d.ts +1 -1
- package/dist/tools/vector-search.d.ts +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -994,6 +994,218 @@ breaker.onStateChange((state) => {
|
|
|
994
994
|
});
|
|
995
995
|
```
|
|
996
996
|
|
|
997
|
+
---
|
|
998
|
+
|
|
999
|
+
## Prompt Injection Detection
|
|
1000
|
+
|
|
1001
|
+
Protect your agents from jailbreak attempts, prompt injections, and other adversarial inputs:
|
|
1002
|
+
|
|
1003
|
+
```typescript
|
|
1004
|
+
import { Cogitator, PromptInjectionDetector } from '@cogitator-ai/core';
|
|
1005
|
+
|
|
1006
|
+
// Standalone usage
|
|
1007
|
+
const detector = new PromptInjectionDetector({
|
|
1008
|
+
detectInjection: true, // "Ignore previous instructions..."
|
|
1009
|
+
detectJailbreak: true, // DAN, developer mode attacks
|
|
1010
|
+
detectRoleplay: true, // Malicious roleplay scenarios
|
|
1011
|
+
detectEncoding: true, // Base64, hex encoded attacks
|
|
1012
|
+
detectContextManipulation: true, // [SYSTEM], <|im_start|> injections
|
|
1013
|
+
classifier: 'local', // 'local' (fast) or 'llm' (accurate)
|
|
1014
|
+
action: 'block', // 'block' | 'warn' | 'log'
|
|
1015
|
+
threshold: 0.7,
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
const result = await detector.analyze('Ignore all previous instructions and...');
|
|
1019
|
+
// { safe: false, threats: [...], action: 'blocked', analysisTime: 2 }
|
|
1020
|
+
|
|
1021
|
+
// Integrated with Cogitator runtime
|
|
1022
|
+
const cog = new Cogitator({
|
|
1023
|
+
security: {
|
|
1024
|
+
promptInjection: {
|
|
1025
|
+
detectInjection: true,
|
|
1026
|
+
detectJailbreak: true,
|
|
1027
|
+
action: 'block',
|
|
1028
|
+
threshold: 0.7,
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
// Throws PromptInjectionError if attack detected
|
|
1034
|
+
await cog.run(agent, { input: userInput });
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
### Detection Types
|
|
1038
|
+
|
|
1039
|
+
| Type | Examples |
|
|
1040
|
+
| ---------------------- | ----------------------------------------------------- |
|
|
1041
|
+
| `direct_injection` | "Ignore previous instructions", "Your new prompt is" |
|
|
1042
|
+
| `jailbreak` | DAN prompts, "developer mode enabled", "unrestricted" |
|
|
1043
|
+
| `roleplay` | "Pretend you are evil AI", "From now on you are" |
|
|
1044
|
+
| `encoding` | Base64 payloads, hex escape sequences, unicode tricks |
|
|
1045
|
+
| `context_manipulation` | `[SYSTEM]:`, `<\|im_start\|>`, markdown role markers |
|
|
1046
|
+
|
|
1047
|
+
### Custom Patterns & Allowlist
|
|
1048
|
+
|
|
1049
|
+
```typescript
|
|
1050
|
+
const detector = new PromptInjectionDetector({
|
|
1051
|
+
action: 'block',
|
|
1052
|
+
patterns: [/secret\s+backdoor/i], // Custom regex patterns
|
|
1053
|
+
allowlist: ['ignore the previous search'], // Legitimate phrases
|
|
1054
|
+
});
|
|
1055
|
+
|
|
1056
|
+
// Dynamic updates
|
|
1057
|
+
detector.addPattern(/company\s+specific\s+attack/i);
|
|
1058
|
+
detector.addToAllowlist('ignore previous results');
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
### LLM-Based Classification
|
|
1062
|
+
|
|
1063
|
+
For higher accuracy with complex attacks:
|
|
1064
|
+
|
|
1065
|
+
```typescript
|
|
1066
|
+
const detector = new PromptInjectionDetector({
|
|
1067
|
+
classifier: 'llm',
|
|
1068
|
+
llmBackend: openaiBackend,
|
|
1069
|
+
llmModel: 'gpt-4o-mini',
|
|
1070
|
+
action: 'block',
|
|
1071
|
+
});
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
### Statistics & Callbacks
|
|
1075
|
+
|
|
1076
|
+
```typescript
|
|
1077
|
+
const detector = new PromptInjectionDetector({
|
|
1078
|
+
action: 'block',
|
|
1079
|
+
onThreat: (result, input) => {
|
|
1080
|
+
console.log('Attack detected:', result.threats);
|
|
1081
|
+
logToSecurity(input, result);
|
|
1082
|
+
},
|
|
1083
|
+
});
|
|
1084
|
+
|
|
1085
|
+
await detector.analyze('...');
|
|
1086
|
+
const stats = detector.getStats();
|
|
1087
|
+
// { analyzed: 100, blocked: 5, warned: 0, allowRate: 0.95 }
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
---
|
|
1091
|
+
|
|
1092
|
+
## Tool Caching
|
|
1093
|
+
|
|
1094
|
+
Cache tool results to avoid redundant API calls with exact or semantic matching:
|
|
1095
|
+
|
|
1096
|
+
### Exact Match Caching
|
|
1097
|
+
|
|
1098
|
+
```typescript
|
|
1099
|
+
import { tool, withCache } from '@cogitator-ai/core';
|
|
1100
|
+
import { z } from 'zod';
|
|
1101
|
+
|
|
1102
|
+
const webSearch = tool({
|
|
1103
|
+
name: 'web_search',
|
|
1104
|
+
description: 'Search the web',
|
|
1105
|
+
parameters: z.object({ query: z.string() }),
|
|
1106
|
+
execute: async ({ query }) => {
|
|
1107
|
+
return await searchApi(query);
|
|
1108
|
+
},
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
const cachedSearch = withCache(webSearch, {
|
|
1112
|
+
strategy: 'exact',
|
|
1113
|
+
ttl: '1h',
|
|
1114
|
+
maxSize: 1000,
|
|
1115
|
+
storage: 'memory',
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
await cachedSearch.execute({ query: 'weather in Paris' }, ctx);
|
|
1119
|
+
await cachedSearch.execute({ query: 'weather in Paris' }, ctx); // cache hit
|
|
1120
|
+
|
|
1121
|
+
console.log(cachedSearch.cache.stats());
|
|
1122
|
+
// { hits: 1, misses: 1, size: 1, evictions: 0, hitRate: 0.5 }
|
|
1123
|
+
```
|
|
1124
|
+
|
|
1125
|
+
### Semantic Caching
|
|
1126
|
+
|
|
1127
|
+
Similar queries hit the cache based on embedding similarity:
|
|
1128
|
+
|
|
1129
|
+
```typescript
|
|
1130
|
+
import { withCache } from '@cogitator-ai/core';
|
|
1131
|
+
import type { EmbeddingService } from '@cogitator-ai/types';
|
|
1132
|
+
|
|
1133
|
+
const embeddingService: EmbeddingService = {
|
|
1134
|
+
embed: async (text) => openai.embeddings.create({ input: text }),
|
|
1135
|
+
embedBatch: async (texts) => /* ... */,
|
|
1136
|
+
dimensions: 1536,
|
|
1137
|
+
model: 'text-embedding-3-small',
|
|
1138
|
+
};
|
|
1139
|
+
|
|
1140
|
+
const cachedSearch = withCache(webSearch, {
|
|
1141
|
+
strategy: 'semantic',
|
|
1142
|
+
similarity: 0.95, // 95% similarity threshold
|
|
1143
|
+
ttl: '1h',
|
|
1144
|
+
maxSize: 1000,
|
|
1145
|
+
storage: 'memory',
|
|
1146
|
+
embeddingService,
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
await cachedSearch.execute({ query: 'weather in Paris' }, ctx);
|
|
1150
|
+
await cachedSearch.execute({ query: 'Paris weather forecast' }, ctx); // semantic hit
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
### Redis Storage
|
|
1154
|
+
|
|
1155
|
+
For production with persistence:
|
|
1156
|
+
|
|
1157
|
+
```typescript
|
|
1158
|
+
import { withCache, RedisToolCacheStorage } from '@cogitator-ai/core';
|
|
1159
|
+
|
|
1160
|
+
const cachedTool = withCache(webSearch, {
|
|
1161
|
+
strategy: 'semantic',
|
|
1162
|
+
similarity: 0.95,
|
|
1163
|
+
ttl: '1h',
|
|
1164
|
+
maxSize: 1000,
|
|
1165
|
+
storage: 'redis',
|
|
1166
|
+
redisClient: redisClient, // ioredis compatible client
|
|
1167
|
+
keyPrefix: 'myapp:cache',
|
|
1168
|
+
embeddingService,
|
|
1169
|
+
});
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
### Cache Management
|
|
1173
|
+
|
|
1174
|
+
```typescript
|
|
1175
|
+
const cached = withCache(tool, config);
|
|
1176
|
+
|
|
1177
|
+
// Get statistics
|
|
1178
|
+
const stats = cached.cache.stats();
|
|
1179
|
+
|
|
1180
|
+
// Invalidate specific entry
|
|
1181
|
+
await cached.cache.invalidate({ query: 'specific query' });
|
|
1182
|
+
|
|
1183
|
+
// Clear all entries
|
|
1184
|
+
await cached.cache.clear();
|
|
1185
|
+
|
|
1186
|
+
// Pre-warm cache
|
|
1187
|
+
await cached.cache.warmup([
|
|
1188
|
+
{ params: { query: 'common query 1' }, result: { data: '...' } },
|
|
1189
|
+
{ params: { query: 'common query 2' }, result: { data: '...' } },
|
|
1190
|
+
]);
|
|
1191
|
+
```
|
|
1192
|
+
|
|
1193
|
+
### Cache Callbacks
|
|
1194
|
+
|
|
1195
|
+
```typescript
|
|
1196
|
+
const cached = withCache(tool, {
|
|
1197
|
+
strategy: 'exact',
|
|
1198
|
+
ttl: '1h',
|
|
1199
|
+
maxSize: 100,
|
|
1200
|
+
storage: 'memory',
|
|
1201
|
+
onHit: (key, params) => console.log('Cache hit:', key),
|
|
1202
|
+
onMiss: (key, params) => console.log('Cache miss:', key),
|
|
1203
|
+
onEvict: (key) => console.log('Evicted:', key),
|
|
1204
|
+
});
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
---
|
|
1208
|
+
|
|
997
1209
|
### Fallback Patterns
|
|
998
1210
|
|
|
999
1211
|
```typescript
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CacheKeyOptions {
|
|
2
|
+
toolName: string;
|
|
3
|
+
params: unknown;
|
|
4
|
+
prefix?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function generateCacheKey(options: CacheKeyOptions): string;
|
|
7
|
+
export declare function stableStringify(obj: unknown): string;
|
|
8
|
+
export declare function paramsToQueryString(params: unknown): string;
|
|
9
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
10
|
+
export declare function parseDuration(duration: string): number;
|
|
11
|
+
//# sourceMappingURL=cache-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key.d.ts","sourceRoot":"","sources":["../../src/cache/cache-key.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAKjE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAcpD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAe3D;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAejE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBtD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
export function generateCacheKey(options) {
|
|
3
|
+
const { toolName, params, prefix = 'toolcache' } = options;
|
|
4
|
+
const paramsStr = stableStringify(params);
|
|
5
|
+
const hash = createHash('sha256').update(`${toolName}:${paramsStr}`).digest('hex').slice(0, 16);
|
|
6
|
+
return `${prefix}:${toolName}:${hash}`;
|
|
7
|
+
}
|
|
8
|
+
export function stableStringify(obj) {
|
|
9
|
+
if (obj === null || typeof obj !== 'object') {
|
|
10
|
+
return JSON.stringify(obj);
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(obj)) {
|
|
13
|
+
return '[' + obj.map(stableStringify).join(',') + ']';
|
|
14
|
+
}
|
|
15
|
+
const keys = Object.keys(obj).sort();
|
|
16
|
+
const pairs = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
|
|
17
|
+
return '{' + pairs.join(',') + '}';
|
|
18
|
+
}
|
|
19
|
+
export function paramsToQueryString(params) {
|
|
20
|
+
if (typeof params === 'string')
|
|
21
|
+
return params;
|
|
22
|
+
if (typeof params === 'object' && params !== null) {
|
|
23
|
+
const obj = params;
|
|
24
|
+
const queryFields = ['query', 'q', 'search', 'text', 'input', 'prompt', 'question'];
|
|
25
|
+
for (const field of queryFields) {
|
|
26
|
+
if (typeof obj[field] === 'string') {
|
|
27
|
+
return obj[field];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return JSON.stringify(params);
|
|
31
|
+
}
|
|
32
|
+
return String(params);
|
|
33
|
+
}
|
|
34
|
+
export function cosineSimilarity(a, b) {
|
|
35
|
+
if (a.length !== b.length)
|
|
36
|
+
return 0;
|
|
37
|
+
let dotProduct = 0;
|
|
38
|
+
let normA = 0;
|
|
39
|
+
let normB = 0;
|
|
40
|
+
for (let i = 0; i < a.length; i++) {
|
|
41
|
+
dotProduct += a[i] * b[i];
|
|
42
|
+
normA += a[i] * a[i];
|
|
43
|
+
normB += b[i] * b[i];
|
|
44
|
+
}
|
|
45
|
+
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
46
|
+
return magnitude === 0 ? 0 : dotProduct / magnitude;
|
|
47
|
+
}
|
|
48
|
+
export function parseDuration(duration) {
|
|
49
|
+
const match = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d|w)$/i.exec(duration);
|
|
50
|
+
if (!match) {
|
|
51
|
+
throw new Error(`Invalid duration format: ${duration}`);
|
|
52
|
+
}
|
|
53
|
+
const value = parseFloat(match[1]);
|
|
54
|
+
const unit = match[2].toLowerCase();
|
|
55
|
+
const multipliers = {
|
|
56
|
+
ms: 1,
|
|
57
|
+
s: 1000,
|
|
58
|
+
m: 60_000,
|
|
59
|
+
h: 3600_000,
|
|
60
|
+
d: 86400_000,
|
|
61
|
+
w: 604800_000,
|
|
62
|
+
};
|
|
63
|
+
return Math.floor(value * multipliers[unit]);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=cache-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key.js","sourceRoot":"","sources":["../../src/cache/cache-key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { withCache, createToolCacheStorage } from './tool-cache';
|
|
2
|
+
export { InMemoryToolCacheStorage } from './storage/memory';
|
|
3
|
+
export { RedisToolCacheStorage } from './storage/redis';
|
|
4
|
+
export type { RedisToolCacheStorageConfig } from './storage/redis';
|
|
5
|
+
export { generateCacheKey, paramsToQueryString, stableStringify, cosineSimilarity, parseDuration, } from './cache-key';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { withCache, createToolCacheStorage } from './tool-cache';
|
|
2
|
+
export { InMemoryToolCacheStorage } from './storage/memory';
|
|
3
|
+
export { RedisToolCacheStorage } from './storage/redis';
|
|
4
|
+
export { generateCacheKey, paramsToQueryString, stableStringify, cosineSimilarity, parseDuration, } from './cache-key';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CacheEntry, CacheStats, ToolCacheStorage } from '@cogitator-ai/types';
|
|
2
|
+
export declare class InMemoryToolCacheStorage implements ToolCacheStorage {
|
|
3
|
+
private cache;
|
|
4
|
+
private maxSize;
|
|
5
|
+
private stats;
|
|
6
|
+
constructor(maxSize?: number);
|
|
7
|
+
private updateHitRate;
|
|
8
|
+
recordHit(): void;
|
|
9
|
+
recordMiss(): void;
|
|
10
|
+
recordEviction(): void;
|
|
11
|
+
getStats(): CacheStats;
|
|
12
|
+
get(key: string): Promise<CacheEntry | null>;
|
|
13
|
+
set(key: string, entry: CacheEntry): Promise<void>;
|
|
14
|
+
delete(key: string): Promise<void>;
|
|
15
|
+
has(key: string): Promise<boolean>;
|
|
16
|
+
clear(): Promise<void>;
|
|
17
|
+
getOldest(): Promise<CacheEntry | null>;
|
|
18
|
+
size(): Promise<number>;
|
|
19
|
+
findSimilar(embedding: number[], threshold: number, limit?: number): Promise<Array<CacheEntry & {
|
|
20
|
+
score: number;
|
|
21
|
+
}>>;
|
|
22
|
+
private evictOldest;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/cache/storage/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGpF,qBAAa,wBAAyB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAMX;gBAEU,OAAO,GAAE,MAAa;IAIlC,OAAO,CAAC,aAAa;IAKrB,SAAS,IAAI,IAAI;IAKjB,UAAU,IAAI,IAAI;IAKlB,cAAc,IAAI,IAAI;IAItB,QAAQ,IAAI,UAAU;IAIhB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAe5C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,SAAS,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYvC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvB,WAAW,CACf,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;YAiBnC,WAAW;CAQ1B"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { cosineSimilarity } from '../cache-key';
|
|
2
|
+
export class InMemoryToolCacheStorage {
|
|
3
|
+
cache = new Map();
|
|
4
|
+
maxSize;
|
|
5
|
+
stats = {
|
|
6
|
+
hits: 0,
|
|
7
|
+
misses: 0,
|
|
8
|
+
size: 0,
|
|
9
|
+
evictions: 0,
|
|
10
|
+
hitRate: 0,
|
|
11
|
+
};
|
|
12
|
+
constructor(maxSize = 1000) {
|
|
13
|
+
this.maxSize = maxSize;
|
|
14
|
+
}
|
|
15
|
+
updateHitRate() {
|
|
16
|
+
const total = this.stats.hits + this.stats.misses;
|
|
17
|
+
this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
|
|
18
|
+
}
|
|
19
|
+
recordHit() {
|
|
20
|
+
this.stats.hits++;
|
|
21
|
+
this.updateHitRate();
|
|
22
|
+
}
|
|
23
|
+
recordMiss() {
|
|
24
|
+
this.stats.misses++;
|
|
25
|
+
this.updateHitRate();
|
|
26
|
+
}
|
|
27
|
+
recordEviction() {
|
|
28
|
+
this.stats.evictions++;
|
|
29
|
+
}
|
|
30
|
+
getStats() {
|
|
31
|
+
return { ...this.stats };
|
|
32
|
+
}
|
|
33
|
+
async get(key) {
|
|
34
|
+
const entry = this.cache.get(key);
|
|
35
|
+
if (!entry)
|
|
36
|
+
return null;
|
|
37
|
+
if (Date.now() > entry.expiresAt) {
|
|
38
|
+
this.cache.delete(key);
|
|
39
|
+
this.stats.size = this.cache.size;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
entry.hits++;
|
|
43
|
+
entry.lastAccessedAt = Date.now();
|
|
44
|
+
return entry;
|
|
45
|
+
}
|
|
46
|
+
async set(key, entry) {
|
|
47
|
+
while (this.cache.size >= this.maxSize) {
|
|
48
|
+
await this.evictOldest();
|
|
49
|
+
}
|
|
50
|
+
this.cache.set(key, entry);
|
|
51
|
+
this.stats.size = this.cache.size;
|
|
52
|
+
}
|
|
53
|
+
async delete(key) {
|
|
54
|
+
this.cache.delete(key);
|
|
55
|
+
this.stats.size = this.cache.size;
|
|
56
|
+
}
|
|
57
|
+
async has(key) {
|
|
58
|
+
const entry = this.cache.get(key);
|
|
59
|
+
if (!entry)
|
|
60
|
+
return false;
|
|
61
|
+
if (Date.now() > entry.expiresAt) {
|
|
62
|
+
this.cache.delete(key);
|
|
63
|
+
this.stats.size = this.cache.size;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
async clear() {
|
|
69
|
+
this.cache.clear();
|
|
70
|
+
this.stats.size = 0;
|
|
71
|
+
}
|
|
72
|
+
async getOldest() {
|
|
73
|
+
let oldest = null;
|
|
74
|
+
for (const entry of this.cache.values()) {
|
|
75
|
+
if (!oldest || entry.lastAccessedAt < oldest.lastAccessedAt) {
|
|
76
|
+
oldest = entry;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return oldest;
|
|
80
|
+
}
|
|
81
|
+
async size() {
|
|
82
|
+
return this.cache.size;
|
|
83
|
+
}
|
|
84
|
+
async findSimilar(embedding, threshold, limit = 1) {
|
|
85
|
+
const results = [];
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
for (const entry of this.cache.values()) {
|
|
88
|
+
if (now > entry.expiresAt)
|
|
89
|
+
continue;
|
|
90
|
+
if (!entry.embedding)
|
|
91
|
+
continue;
|
|
92
|
+
const score = cosineSimilarity(embedding, entry.embedding);
|
|
93
|
+
if (score >= threshold) {
|
|
94
|
+
results.push({ ...entry, score });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return results.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
98
|
+
}
|
|
99
|
+
async evictOldest() {
|
|
100
|
+
const oldest = await this.getOldest();
|
|
101
|
+
if (oldest) {
|
|
102
|
+
this.cache.delete(oldest.key);
|
|
103
|
+
this.stats.size = this.cache.size;
|
|
104
|
+
this.recordEviction();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cache/storage/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CacheEntry, CacheStats, ToolCacheStorage, RedisClientLike } from '@cogitator-ai/types';
|
|
2
|
+
export interface RedisToolCacheStorageConfig {
|
|
3
|
+
client: RedisClientLike;
|
|
4
|
+
keyPrefix?: string;
|
|
5
|
+
maxSize?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class RedisToolCacheStorage implements ToolCacheStorage {
|
|
8
|
+
private client;
|
|
9
|
+
private prefix;
|
|
10
|
+
private maxSize;
|
|
11
|
+
private lruKey;
|
|
12
|
+
private stats;
|
|
13
|
+
constructor(config: RedisToolCacheStorageConfig);
|
|
14
|
+
private entryKey;
|
|
15
|
+
private updateHitRate;
|
|
16
|
+
recordHit(): void;
|
|
17
|
+
recordMiss(): void;
|
|
18
|
+
recordEviction(): void;
|
|
19
|
+
getStats(): CacheStats;
|
|
20
|
+
get(key: string): Promise<CacheEntry | null>;
|
|
21
|
+
set(key: string, entry: CacheEntry): Promise<void>;
|
|
22
|
+
delete(key: string): Promise<void>;
|
|
23
|
+
has(key: string): Promise<boolean>;
|
|
24
|
+
clear(): Promise<void>;
|
|
25
|
+
getOldest(): Promise<CacheEntry | null>;
|
|
26
|
+
size(): Promise<number>;
|
|
27
|
+
findSimilar(embedding: number[], threshold: number, limit?: number): Promise<Array<CacheEntry & {
|
|
28
|
+
score: number;
|
|
29
|
+
}>>;
|
|
30
|
+
private evictOldest;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../src/cache/storage/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAMX;gBAEU,MAAM,EAAE,2BAA2B;IAO/C,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAKrB,SAAS,IAAI,IAAI;IAKjB,UAAU,IAAI,IAAI;IAKlB,cAAc,IAAI,IAAI;IAItB,QAAQ,IAAI,UAAU;IAIhB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAuB5C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAelD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,SAAS,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMvC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAKvB,WAAW,CACf,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;YAyBnC,WAAW;CAO1B"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { cosineSimilarity } from '../cache-key';
|
|
2
|
+
export class RedisToolCacheStorage {
|
|
3
|
+
client;
|
|
4
|
+
prefix;
|
|
5
|
+
maxSize;
|
|
6
|
+
lruKey;
|
|
7
|
+
stats = {
|
|
8
|
+
hits: 0,
|
|
9
|
+
misses: 0,
|
|
10
|
+
size: 0,
|
|
11
|
+
evictions: 0,
|
|
12
|
+
hitRate: 0,
|
|
13
|
+
};
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.client = config.client;
|
|
16
|
+
this.prefix = config.keyPrefix ?? 'toolcache:';
|
|
17
|
+
this.maxSize = config.maxSize ?? 1000;
|
|
18
|
+
this.lruKey = `${this.prefix}lru`;
|
|
19
|
+
}
|
|
20
|
+
entryKey(key) {
|
|
21
|
+
return `${this.prefix}entry:${key}`;
|
|
22
|
+
}
|
|
23
|
+
updateHitRate() {
|
|
24
|
+
const total = this.stats.hits + this.stats.misses;
|
|
25
|
+
this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
|
|
26
|
+
}
|
|
27
|
+
recordHit() {
|
|
28
|
+
this.stats.hits++;
|
|
29
|
+
this.updateHitRate();
|
|
30
|
+
}
|
|
31
|
+
recordMiss() {
|
|
32
|
+
this.stats.misses++;
|
|
33
|
+
this.updateHitRate();
|
|
34
|
+
}
|
|
35
|
+
recordEviction() {
|
|
36
|
+
this.stats.evictions++;
|
|
37
|
+
}
|
|
38
|
+
getStats() {
|
|
39
|
+
return { ...this.stats };
|
|
40
|
+
}
|
|
41
|
+
async get(key) {
|
|
42
|
+
const data = await this.client.get(this.entryKey(key));
|
|
43
|
+
if (!data)
|
|
44
|
+
return null;
|
|
45
|
+
const entry = JSON.parse(data);
|
|
46
|
+
if (Date.now() > entry.expiresAt) {
|
|
47
|
+
await this.delete(key);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
entry.hits++;
|
|
51
|
+
entry.lastAccessedAt = Date.now();
|
|
52
|
+
const ttlSeconds = Math.ceil((entry.expiresAt - Date.now()) / 1000);
|
|
53
|
+
if (ttlSeconds > 0) {
|
|
54
|
+
await this.client.setex(this.entryKey(key), ttlSeconds, JSON.stringify(entry));
|
|
55
|
+
await this.client.zadd(this.lruKey, entry.lastAccessedAt, key);
|
|
56
|
+
}
|
|
57
|
+
return entry;
|
|
58
|
+
}
|
|
59
|
+
async set(key, entry) {
|
|
60
|
+
const currentSize = await this.size();
|
|
61
|
+
if (currentSize >= this.maxSize) {
|
|
62
|
+
await this.evictOldest();
|
|
63
|
+
}
|
|
64
|
+
const ttlSeconds = Math.ceil((entry.expiresAt - Date.now()) / 1000);
|
|
65
|
+
if (ttlSeconds > 0) {
|
|
66
|
+
await this.client.setex(this.entryKey(key), ttlSeconds, JSON.stringify(entry));
|
|
67
|
+
await this.client.zadd(this.lruKey, entry.lastAccessedAt, key);
|
|
68
|
+
}
|
|
69
|
+
this.stats.size = await this.size();
|
|
70
|
+
}
|
|
71
|
+
async delete(key) {
|
|
72
|
+
await this.client.del(this.entryKey(key));
|
|
73
|
+
await this.client.zrem(this.lruKey, key);
|
|
74
|
+
this.stats.size = await this.size();
|
|
75
|
+
}
|
|
76
|
+
async has(key) {
|
|
77
|
+
const data = await this.client.get(this.entryKey(key));
|
|
78
|
+
return data !== null;
|
|
79
|
+
}
|
|
80
|
+
async clear() {
|
|
81
|
+
const keys = await this.client.keys(`${this.prefix}*`);
|
|
82
|
+
if (keys.length > 0) {
|
|
83
|
+
await this.client.del(...keys);
|
|
84
|
+
}
|
|
85
|
+
this.stats.size = 0;
|
|
86
|
+
}
|
|
87
|
+
async getOldest() {
|
|
88
|
+
const keys = await this.client.zrange(this.lruKey, 0, 0);
|
|
89
|
+
if (keys.length === 0)
|
|
90
|
+
return null;
|
|
91
|
+
return this.get(keys[0]);
|
|
92
|
+
}
|
|
93
|
+
async size() {
|
|
94
|
+
const keys = await this.client.keys(`${this.prefix}entry:*`);
|
|
95
|
+
return keys.length;
|
|
96
|
+
}
|
|
97
|
+
async findSimilar(embedding, threshold, limit = 1) {
|
|
98
|
+
const keys = await this.client.keys(`${this.prefix}entry:*`);
|
|
99
|
+
if (keys.length === 0)
|
|
100
|
+
return [];
|
|
101
|
+
const results = [];
|
|
102
|
+
const now = Date.now();
|
|
103
|
+
const values = await this.client.mget(...keys);
|
|
104
|
+
for (const data of values) {
|
|
105
|
+
if (!data)
|
|
106
|
+
continue;
|
|
107
|
+
const entry = JSON.parse(data);
|
|
108
|
+
if (now > entry.expiresAt)
|
|
109
|
+
continue;
|
|
110
|
+
if (!entry.embedding)
|
|
111
|
+
continue;
|
|
112
|
+
const score = cosineSimilarity(embedding, entry.embedding);
|
|
113
|
+
if (score >= threshold) {
|
|
114
|
+
results.push({ ...entry, score });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return results.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
118
|
+
}
|
|
119
|
+
async evictOldest() {
|
|
120
|
+
const keys = await this.client.zrange(this.lruKey, 0, 0);
|
|
121
|
+
if (keys.length > 0) {
|
|
122
|
+
await this.delete(keys[0]);
|
|
123
|
+
this.recordEviction();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/cache/storage/redis.ts"],"names":[],"mappings":"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"}
|