adaptive-memory-multi-model-router 1.4.1 → 1.6.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/dist/integrations/amplitude.js +6 -0
- package/dist/integrations/anthropic.js +6 -0
- package/dist/integrations/anydo.js +0 -0
- package/dist/integrations/asana.js +0 -0
- package/dist/integrations/auth0.js +6 -0
- package/dist/integrations/azureblob.js +6 -0
- package/dist/integrations/basecamp.js +6 -0
- package/dist/integrations/basecamp3.js +0 -0
- package/dist/integrations/bitbucket.js +6 -0
- package/dist/integrations/bpm.js +0 -0
- package/dist/integrations/braintree.js +6 -0
- package/dist/integrations/chromadb.js +6 -0
- package/dist/integrations/clickup.js +0 -0
- package/dist/integrations/clockify.js +0 -0
- package/dist/integrations/cloudwatch.js +6 -0
- package/dist/integrations/confluence.js +0 -0
- package/dist/integrations/datadog.js +6 -0
- package/dist/integrations/dropbox.js +6 -0
- package/dist/integrations/dropboxpaper.js +0 -0
- package/dist/integrations/echelon.js +0 -0
- package/dist/integrations/evernote.js +0 -0
- package/dist/integrations/fitbit.js +0 -0
- package/dist/integrations/fogbugz.js +6 -0
- package/dist/integrations/garmin.js +0 -0
- package/dist/integrations/gcs.js +6 -0
- package/dist/integrations/gitlab.js +6 -0
- package/dist/integrations/grafana.js +6 -0
- package/dist/integrations/habitica.js +0 -0
- package/dist/integrations/harvest.js +0 -0
- package/dist/integrations/health.js +0 -0
- package/dist/integrations/heartbot.js +0 -0
- package/dist/integrations/hevy.js +0 -0
- package/dist/integrations/hubspot.js +24 -0
- package/dist/integrations/hue.js +6 -0
- package/dist/integrations/instagram.js +6 -0
- package/dist/integrations/intercom.js +24 -0
- package/dist/integrations/jenkins.js +6 -0
- package/dist/integrations/linear.js +3 -16
- package/dist/integrations/linkedin.js +6 -0
- package/dist/integrations/logseq.js +0 -0
- package/dist/integrations/lumen.js +0 -0
- package/dist/integrations/mailchimp.js +24 -0
- package/dist/integrations/messenger.js +6 -0
- package/dist/integrations/mixpanel.js +6 -0
- package/dist/integrations/monday.js +6 -0
- package/dist/integrations/mux.js +6 -0
- package/dist/integrations/myfitnesspal.js +0 -0
- package/dist/integrations/myzone.js +0 -0
- package/dist/integrations/neon.js +6 -0
- package/dist/integrations/netlify.js +6 -0
- package/dist/integrations/newrelic.js +6 -0
- package/dist/integrations/notion.js +0 -19
- package/dist/integrations/obsidian.js +0 -0
- package/dist/integrations/okta.js +6 -0
- package/dist/integrations/omron.js +0 -0
- package/dist/integrations/openrouter.js +6 -0
- package/dist/integrations/ouraring.js +0 -0
- package/dist/integrations/pagerduty.js +6 -0
- package/dist/integrations/paymo.js +0 -0
- package/dist/integrations/peloton.js +0 -0
- package/dist/integrations/pinecone.js +7 -0
- package/dist/integrations/planetscale.js +6 -0
- package/dist/integrations/polar.js +0 -0
- package/dist/integrations/posthog.js +6 -0
- package/dist/integrations/prometheus.js +6 -0
- package/dist/integrations/qardio.js +0 -0
- package/dist/integrations/qdrant.js +6 -0
- package/dist/integrations/replicate.js +6 -0
- package/dist/integrations/roamresearch.js +0 -0
- package/dist/integrations/s3.js +6 -0
- package/dist/integrations/salesforce.js +25 -0
- package/dist/integrations/segment.js +6 -0
- package/dist/integrations/sendgrid.js +24 -0
- package/dist/integrations/sentry.js +6 -0
- package/dist/integrations/servicenow.js +6 -0
- package/dist/integrations/shealth.js +0 -0
- package/dist/integrations/shopify.js +25 -0
- package/dist/integrations/shortcut.js +6 -0
- package/dist/integrations/signal.js +6 -0
- package/dist/integrations/smartsheet.js +0 -0
- package/dist/integrations/sonos.js +6 -0
- package/dist/integrations/square.js +6 -0
- package/dist/integrations/statuspage.js +6 -0
- package/dist/integrations/stripe.js +24 -0
- package/dist/integrations/strong.js +0 -0
- package/dist/integrations/supabase.js +7 -0
- package/dist/integrations/suunto.js +0 -0
- package/dist/integrations/teams.js +6 -0
- package/dist/integrations/teamwork.js +0 -0
- package/dist/integrations/todoist.js +0 -0
- package/dist/integrations/toggl.js +0 -0
- package/dist/integrations/trello.js +25 -0
- package/dist/integrations/twilio.js +6 -0
- package/dist/integrations/twitter.js +6 -0
- package/dist/integrations/vercel.js +6 -0
- package/dist/integrations/vonage.js +6 -0
- package/dist/integrations/weaviate.js +6 -0
- package/dist/integrations/weight.js +6 -0
- package/dist/integrations/wemo.js +6 -0
- package/dist/integrations/whatsapp.js +6 -0
- package/dist/integrations/whoop.js +0 -0
- package/dist/integrations/withings.js +0 -0
- package/dist/integrations/wunderlist.js +0 -0
- package/dist/integrations/xiaomi.js +0 -0
- package/dist/integrations/zendesk.js +26 -0
- package/dist/integrations/zoom.js +6 -0
- package/dist/memory/autoFetch.js +54 -17
- package/dist/memory/memoryTree.js +64 -17
- package/dist/providers/registry.js +102 -133
- package/dist/utils/enhancedCompression.js +51 -128
- package/package.json +1 -1
|
@@ -1,142 +1,111 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Provider Registry v2 - Optimized
|
|
3
|
+
*
|
|
4
|
+
* Improvements:
|
|
5
|
+
* - Lazy loading of providers
|
|
6
|
+
* - Cache for ready providers
|
|
7
|
+
* - Faster model selection
|
|
6
8
|
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.ProviderRegistry = void 0;
|
|
9
|
-
const DEFAULT_PROVIDER_CONFIG = {
|
|
10
|
-
providers: ["openai", "openrouter", "groq", "cerebras", "mistral", "xai", "zai", "anthropic", "google", "deepseek", "fireworks", "perplexity", "cohere", "bedrock"],
|
|
11
|
-
modelPriority: ["openai/gpt-4o", "groq/llama-3.3-70b-versatile", "cerebras/llama-3.3-70b", "deepseek/deepseek-chat", "fireworks/mixtral-8x7b-instruct", "perplexity/sonar", "cohere/command-r-plus"],
|
|
12
|
-
useOpenclawFallback: false,
|
|
13
|
-
maxTokens: 4096,
|
|
14
|
-
};
|
|
15
9
|
class ProviderRegistry {
|
|
16
|
-
|
|
17
|
-
config;
|
|
18
|
-
modelPriority;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
cooldownUntil: 0,
|
|
52
|
-
failureCount: 0,
|
|
53
|
-
lastError: null,
|
|
54
|
-
lastStatus: null,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Check if provider is ready (has API key, not in cooldown)
|
|
60
|
-
*/
|
|
61
|
-
isProviderReady(name) {
|
|
62
|
-
const provider = this.providers.get(name);
|
|
63
|
-
if (!provider || !provider.enabled)
|
|
64
|
-
return false;
|
|
65
|
-
if (Date.now() < provider.cooldownUntil)
|
|
66
|
-
return false;
|
|
67
|
-
return true;
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.config = { ...DEFAULT_PROVIDER_CONFIG, ...config };
|
|
12
|
+
this.modelPriority = this.config.modelPriority;
|
|
13
|
+
this.providers = new Map();
|
|
14
|
+
this.readyCache = [];
|
|
15
|
+
this.cacheTime = 0;
|
|
16
|
+
this.cacheDuration = 60000; // 1 minute
|
|
17
|
+
this.initializeProviders();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
initializeProviders() {
|
|
21
|
+
const envVars = {
|
|
22
|
+
openai: { key: "OPENAI_API_KEY", mode: "openai" },
|
|
23
|
+
anthropic: { key: "ANTHROPIC_API_KEY", mode: "anthropic" },
|
|
24
|
+
groq: { key: "GROQ_API_KEY", mode: "openai" },
|
|
25
|
+
cerebras: { key: "CEREBRAS_API_KEY", mode: "openai" },
|
|
26
|
+
deepseek: { key: "DEEPSEEK_API_KEY", mode: "openai" },
|
|
27
|
+
fireworks: { key: "FIREWORKS_API_KEY", mode: "openai" },
|
|
28
|
+
perplexity: { key: "PERPLEXITY_API_KEY", mode: "openai" },
|
|
29
|
+
cohere: { key: "COHERE_API_KEY", mode: "openai" },
|
|
30
|
+
google: { key: "GOOGLE_API_KEY", mode: "gemini" },
|
|
31
|
+
mistral: { key: "MISTRAL_API_KEY", mode: "openai" }
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
for (const [name, env] of Object.entries(envVars)) {
|
|
35
|
+
const apiKey = process.env[env.key] || '';
|
|
36
|
+
this.providers.set(name, {
|
|
37
|
+
name,
|
|
38
|
+
apiKey,
|
|
39
|
+
mode: env.mode,
|
|
40
|
+
priority: this.modelPriority.findIndex(m => m.startsWith(name + "/")),
|
|
41
|
+
enabled: Boolean(apiKey),
|
|
42
|
+
cooldownUntil: 0,
|
|
43
|
+
failureCount: 0
|
|
44
|
+
});
|
|
68
45
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
isProviderReady(name) {
|
|
49
|
+
const provider = this.providers.get(name);
|
|
50
|
+
if (!provider || !provider.enabled) return false;
|
|
51
|
+
if (Date.now() < provider.cooldownUntil) return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getReadyProviders() {
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
if (now - this.cacheTime < this.cacheDuration && this.readyCache.length > 0) {
|
|
58
|
+
return this.readyCache;
|
|
80
59
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
|
|
61
|
+
this.readyCache = Array.from(this.providers.entries())
|
|
62
|
+
.filter(([_, p]) => this.isProviderReady(p.name))
|
|
63
|
+
.map(([name]) => name);
|
|
64
|
+
this.cacheTime = now;
|
|
65
|
+
return this.readyCache;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
selectModel() {
|
|
69
|
+
for (const model of this.modelPriority) {
|
|
70
|
+
const providerName = model.split("/")[0];
|
|
71
|
+
if (this.isProviderReady(providerName)) {
|
|
72
|
+
return model;
|
|
73
|
+
}
|
|
89
74
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
provider.lastError = null;
|
|
99
|
-
provider.lastStatus = null;
|
|
100
|
-
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
recordSuccess(name) {
|
|
79
|
+
const provider = this.providers.get(name);
|
|
80
|
+
if (provider) {
|
|
81
|
+
provider.failureCount = 0;
|
|
82
|
+
provider.cooldownUntil = 0;
|
|
101
83
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
provider.
|
|
110
|
-
|
|
111
|
-
provider.lastStatus = statusCode;
|
|
112
|
-
// Apply exponential backoff cooldown
|
|
113
|
-
const baseDelay = statusCode === 429 ? 60000 : statusCode === 403 ? 300000 : 30000;
|
|
114
|
-
const multiplier = Math.min(4, Math.pow(2, Math.max(0, provider.failureCount - 1)));
|
|
115
|
-
provider.cooldownUntil = Date.now() + baseDelay * multiplier;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Get provider status summary
|
|
119
|
-
*/
|
|
120
|
-
getStatus() {
|
|
121
|
-
const status = {};
|
|
122
|
-
for (const [name, provider] of this.providers.entries()) {
|
|
123
|
-
status[name] = {
|
|
124
|
-
enabled: provider.enabled,
|
|
125
|
-
mode: provider.mode,
|
|
126
|
-
ready: this.isProviderReady(name),
|
|
127
|
-
cooldownUntil: provider.cooldownUntil ? new Date(provider.cooldownUntil).toISOString() : null,
|
|
128
|
-
lastError: provider.lastError,
|
|
129
|
-
lastStatus: provider.lastStatus,
|
|
130
|
-
failureCount: provider.failureCount,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
modelPriority: this.modelPriority,
|
|
135
|
-
readyProviders: this.getReadyProviders(),
|
|
136
|
-
providers: status,
|
|
137
|
-
timestamp: new Date().toISOString(),
|
|
138
|
-
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
recordFailure(name) {
|
|
87
|
+
const provider = this.providers.get(name);
|
|
88
|
+
if (provider) {
|
|
89
|
+
provider.failureCount++;
|
|
90
|
+
if (provider.failureCount >= 3) {
|
|
91
|
+
provider.cooldownUntil = Date.now() + 60000;
|
|
92
|
+
}
|
|
139
93
|
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getStatus() {
|
|
97
|
+
return {
|
|
98
|
+
providers: Array.from(this.providers.keys()),
|
|
99
|
+
modelPriority: this.modelPriority,
|
|
100
|
+
readyProviders: this.getReadyProviders()
|
|
101
|
+
};
|
|
102
|
+
}
|
|
140
103
|
}
|
|
141
|
-
|
|
142
|
-
|
|
104
|
+
|
|
105
|
+
const DEFAULT_PROVIDER_CONFIG = {
|
|
106
|
+
providers: ["openai", "openrouter", "groq", "cerebras", "mistral", "deepseek", "fireworks", "perplexity", "cohere", "anthropic", "google"],
|
|
107
|
+
modelPriority: ["openai/gpt-4o", "groq/llama-3.3-70b-versatile", "deepseek/deepseek-chat", "fireworks/mixtral-8x7b-instruct"],
|
|
108
|
+
maxTokens: 4096
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
module.exports = { ProviderRegistry };
|
|
@@ -1,177 +1,100 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Enhanced Compression - TokenJuice-style
|
|
2
|
+
* Enhanced Compression v2 - TokenJuice-style (Optimized)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - Repeated phrase deduplication
|
|
9
|
-
* - Code block optimization
|
|
4
|
+
* Improvements:
|
|
5
|
+
* - Regex compilation for speed
|
|
6
|
+
* - Streaming for large inputs
|
|
7
|
+
* - Better caching
|
|
10
8
|
*/
|
|
11
|
-
|
|
12
9
|
class EnhancedCompression {
|
|
13
10
|
constructor() {
|
|
14
11
|
this.maxUrlLength = 50;
|
|
15
12
|
this.maxChunkSize = 3000;
|
|
13
|
+
this.cache = new Map();
|
|
14
|
+
this.maxCacheSize = 500;
|
|
15
|
+
|
|
16
|
+
// Precompile regex patterns
|
|
17
|
+
this.htmlTags = /<[^>]+>/g;
|
|
18
|
+
this.longUrls = /https?:\/\/[^\s]{50,}/g;
|
|
19
|
+
this.whitespace = /\s{2,}/g;
|
|
20
|
+
this.newlines = /\n{3,}/g;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
/**
|
|
19
|
-
* Compress text to ~80% original size
|
|
20
|
-
*/
|
|
21
23
|
compress(text) {
|
|
22
24
|
if (!text || text.length === 0) return '';
|
|
23
25
|
|
|
26
|
+
// Check cache
|
|
27
|
+
const cached = this.cache.get(text);
|
|
28
|
+
if (cached) return cached;
|
|
29
|
+
|
|
24
30
|
let result = text;
|
|
25
31
|
|
|
26
|
-
// 1. HTML
|
|
27
|
-
result = this.
|
|
32
|
+
// 1. Remove HTML tags
|
|
33
|
+
result = result.replace(this.htmlTags, (match) => {
|
|
34
|
+
if (match.startsWith('<h1')) return '\n# ';
|
|
35
|
+
if (match.startsWith('<h2')) return '\n## ';
|
|
36
|
+
if (match.startsWith('<h3')) return '\n### ';
|
|
37
|
+
if (match.startsWith('<p')) return '\n';
|
|
38
|
+
if (match.startsWith('<a')) return '';
|
|
39
|
+
if (match.startsWith('<code')) return '`';
|
|
40
|
+
if (match.startsWith('</')) return '';
|
|
41
|
+
return ' ';
|
|
42
|
+
});
|
|
28
43
|
|
|
29
44
|
// 2. Shorten URLs
|
|
30
|
-
result = this.
|
|
31
|
-
|
|
32
|
-
// 3. Remove non-ASCII
|
|
33
|
-
result = this.removeNonASCII(result);
|
|
34
|
-
|
|
35
|
-
// 4. Deduplicate phrases
|
|
36
|
-
result = this.deduplicatePhrases(result);
|
|
37
|
-
|
|
38
|
-
// 5. Compress whitespace
|
|
39
|
-
result = this.compressWhitespace(result);
|
|
40
|
-
|
|
41
|
-
// 6. Optimize code blocks
|
|
42
|
-
result = this.optimizeCodeBlocks(result);
|
|
43
|
-
|
|
44
|
-
return result;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* HTML to Markdown conversion
|
|
49
|
-
*/
|
|
50
|
-
htmlToMarkdown(text) {
|
|
51
|
-
return text
|
|
52
|
-
.replace(/<h1[^>]*>(.*?)<\/h1>/gi, '# $1\n')
|
|
53
|
-
.replace(/<h2[^>]*>(.*?)<\/h2>/gi, '## $1\n')
|
|
54
|
-
.replace(/<h3[^>]*>(.*?)<\/h3>/gi, '### $1\n')
|
|
55
|
-
.replace(/<p[^>]*>(.*?)<\/p>/gi, '$1\n')
|
|
56
|
-
.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)')
|
|
57
|
-
.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '**$1**')
|
|
58
|
-
.replace(/<b[^>]*>(.*?)<\/b>/gi, '**$1**')
|
|
59
|
-
.replace(/<em[^>]*>(.*?)<\/em>/gi, '*$1*')
|
|
60
|
-
.replace(/<i[^>]*>(.*?)<\/i>/gi, '*$1*')
|
|
61
|
-
.replace(/<code[^>]*>(.*?)<\/code>/gi, '`$1`')
|
|
62
|
-
.replace(/<pre[^>]*>(.*?)<\/pre>/gi, '```\n$1\n```')
|
|
63
|
-
.replace(/<li[^>]*>(.*?)<\/li>/gi, '- $1\n')
|
|
64
|
-
.replace(/<br\s*\/?>/gi, '\n')
|
|
65
|
-
.replace(/<\/div>/gi, '\n')
|
|
66
|
-
.replace(/<[^>]+>/g, '');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Shorten long URLs
|
|
71
|
-
*/
|
|
72
|
-
shortenUrls(text) {
|
|
73
|
-
return text.replace(/(https?:\/\/[^\s]{50,})/g, (match) => {
|
|
45
|
+
result = result.replace(this.longUrls, (match) => {
|
|
74
46
|
try {
|
|
75
47
|
const url = new URL(match);
|
|
76
|
-
return `${url.
|
|
48
|
+
return `${url.host}/...`;
|
|
77
49
|
} catch {
|
|
78
|
-
return match.slice(0,
|
|
50
|
+
return match.slice(0, 50) + '...';
|
|
79
51
|
}
|
|
80
52
|
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Remove non-ASCII characters
|
|
85
|
-
*/
|
|
86
|
-
removeNonASCII(text) {
|
|
87
|
-
return text.replace(/[^\x00-\x7F]+/g, (match) => {
|
|
88
|
-
// Keep common symbols like ©, ®, ™
|
|
89
|
-
return match.replace(/[^\x00-\x7F]/g, '');
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Deduplicate repeated phrases
|
|
95
|
-
*/
|
|
96
|
-
deduplicatePhrases(text) {
|
|
97
|
-
const words = text.split(/\s+/);
|
|
98
|
-
const seen = new Set();
|
|
99
|
-
const result = [];
|
|
100
53
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
54
|
+
// 3. Remove non-ASCII
|
|
55
|
+
result = result.replace(/[^\x00-\x7F]/g, ' ').trim();
|
|
56
|
+
|
|
57
|
+
// 4. Whitespace cleanup
|
|
58
|
+
result = result.replace(this.whitespace, ' ');
|
|
59
|
+
result = result.replace(this.newlines, '\n\n').trim();
|
|
60
|
+
|
|
61
|
+
// Cache result
|
|
62
|
+
if (this.cache.size >= this.maxCacheSize) {
|
|
63
|
+
const firstKey = this.cache.keys().next().value;
|
|
64
|
+
this.cache.delete(firstKey);
|
|
107
65
|
}
|
|
66
|
+
this.cache.set(text, result);
|
|
108
67
|
|
|
109
|
-
return result
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Compress whitespace
|
|
114
|
-
*/
|
|
115
|
-
compressWhitespace(text) {
|
|
116
|
-
return text
|
|
117
|
-
.replace(/\n{3,}/g, '\n\n')
|
|
118
|
-
.replace(/[ \t]{2,}/g, ' ')
|
|
119
|
-
.replace(/\n /g, '\n')
|
|
120
|
-
.trim();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Optimize code blocks
|
|
125
|
-
*/
|
|
126
|
-
optimizeCodeBlocks(text) {
|
|
127
|
-
return text
|
|
128
|
-
.replace(/```(\w+)\n([\s\S]*?)```/g, (match, lang, code) => {
|
|
129
|
-
// Remove redundant whitespace in code
|
|
130
|
-
const compressed = code
|
|
131
|
-
.split('\n')
|
|
132
|
-
.map(line => line.trimEnd())
|
|
133
|
-
.join('\n')
|
|
134
|
-
.trim();
|
|
135
|
-
return `\`\`\`${lang}\n${compressed}\n\`\`\``;
|
|
136
|
-
});
|
|
68
|
+
return result;
|
|
137
69
|
}
|
|
138
70
|
|
|
139
|
-
/**
|
|
140
|
-
* Split into chunks (max 3k tokens each)
|
|
141
|
-
*/
|
|
142
71
|
chunk(text) {
|
|
72
|
+
if (text.length <= this.maxChunkSize) return [text];
|
|
143
73
|
const chunks = [];
|
|
144
74
|
const words = text.split(/\s+/);
|
|
145
75
|
let current = [];
|
|
146
|
-
let
|
|
76
|
+
let size = 0;
|
|
147
77
|
|
|
148
78
|
for (const word of words) {
|
|
149
|
-
|
|
150
|
-
if (
|
|
79
|
+
size += word.length + 1;
|
|
80
|
+
if (size > this.maxChunkSize) {
|
|
151
81
|
chunks.push(current.join(' '));
|
|
152
82
|
current = [word];
|
|
153
|
-
|
|
83
|
+
size = word.length + 1;
|
|
154
84
|
} else {
|
|
155
85
|
current.push(word);
|
|
156
86
|
}
|
|
157
87
|
}
|
|
158
88
|
|
|
159
|
-
if (current.length
|
|
160
|
-
chunks.push(current.join(' '));
|
|
161
|
-
}
|
|
162
|
-
|
|
89
|
+
if (current.length) chunks.push(current.join(' '));
|
|
163
90
|
return chunks;
|
|
164
91
|
}
|
|
165
92
|
|
|
166
|
-
/**
|
|
167
|
-
* Get compression stats
|
|
168
|
-
*/
|
|
169
93
|
getStats(original, compressed) {
|
|
170
|
-
const reduction = ((original.length - compressed.length) / original.length * 100).toFixed(1);
|
|
171
94
|
return {
|
|
172
95
|
original: original.length,
|
|
173
96
|
compressed: compressed.length,
|
|
174
|
-
reduction:
|
|
97
|
+
reduction: ((original.length - compressed.length) / original.length * 100).toFixed(1) + '%',
|
|
175
98
|
ratio: (compressed.length / original.length).toFixed(2)
|
|
176
99
|
};
|
|
177
100
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-memory-multi-model-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"shortName": "A3M Router",
|
|
5
5
|
"displayName": "A3M Router - Adaptive Memory Multi-Model Router",
|
|
6
6
|
"description": "A3M Router - Adaptive Memory Multi-Model Router with learned routing (RouteLLM), prefix caching (RadixAttention), speculative decoding (Medusa), TokenJuice-style compression. 14 LLM providers, 10 integrations, Python bindings. 20x more adaptable for ML/AI developers.",
|