cogxai 2.8.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 +691 -0
- package/dist/agents/executor.d.ts +17 -0
- package/dist/agents/executor.d.ts.map +1 -0
- package/dist/agents/executor.js +336 -0
- package/dist/agents/executor.js.map +1 -0
- package/dist/agents/index.d.ts +9 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +18 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/tools.d.ts +31 -0
- package/dist/agents/tools.d.ts.map +1 -0
- package/dist/agents/tools.js +262 -0
- package/dist/agents/tools.js.map +1 -0
- package/dist/agents/types.d.ts +25 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +170 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/character/agent-tier-modifiers.d.ts +3 -0
- package/dist/character/agent-tier-modifiers.d.ts.map +1 -0
- package/dist/character/agent-tier-modifiers.js +24 -0
- package/dist/character/agent-tier-modifiers.js.map +1 -0
- package/dist/character/base-prompt.d.ts +3 -0
- package/dist/character/base-prompt.d.ts.map +1 -0
- package/dist/character/base-prompt.js +45 -0
- package/dist/character/base-prompt.js.map +1 -0
- package/dist/character/mood-modifiers.d.ts +3 -0
- package/dist/character/mood-modifiers.d.ts.map +1 -0
- package/dist/character/mood-modifiers.js +27 -0
- package/dist/character/mood-modifiers.js.map +1 -0
- package/dist/character/tier-modifiers.d.ts +3 -0
- package/dist/character/tier-modifiers.d.ts.map +1 -0
- package/dist/character/tier-modifiers.js +25 -0
- package/dist/character/tier-modifiers.js.map +1 -0
- package/dist/cli/banner.d.ts +20 -0
- package/dist/cli/banner.d.ts.map +1 -0
- package/dist/cli/banner.js +73 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/export.d.ts +2 -0
- package/dist/cli/export.d.ts.map +1 -0
- package/dist/cli/export.js +176 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +80 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +541 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/register.d.ts +2 -0
- package/dist/cli/register.d.ts.map +1 -0
- package/dist/cli/register.js +121 -0
- package/dist/cli/register.js.map +1 -0
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +403 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/ship.d.ts +2 -0
- package/dist/cli/ship.d.ts.map +1 -0
- package/dist/cli/ship.js +32 -0
- package/dist/cli/ship.js.map +1 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +124 -0
- package/dist/config.js.map +1 -0
- package/dist/core/allium-client.d.ts +32 -0
- package/dist/core/allium-client.d.ts.map +1 -0
- package/dist/core/allium-client.js +162 -0
- package/dist/core/allium-client.js.map +1 -0
- package/dist/core/claude-client.d.ts +31 -0
- package/dist/core/claude-client.d.ts.map +1 -0
- package/dist/core/claude-client.js +172 -0
- package/dist/core/claude-client.js.map +1 -0
- package/dist/core/database.d.ts +17 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +499 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/embeddings.d.ts +28 -0
- package/dist/core/embeddings.d.ts.map +1 -0
- package/dist/core/embeddings.js +212 -0
- package/dist/core/embeddings.js.map +1 -0
- package/dist/core/encryption.d.ts +49 -0
- package/dist/core/encryption.d.ts.map +1 -0
- package/dist/core/encryption.js +136 -0
- package/dist/core/encryption.js.map +1 -0
- package/dist/core/guardrails.d.ts +30 -0
- package/dist/core/guardrails.d.ts.map +1 -0
- package/dist/core/guardrails.js +191 -0
- package/dist/core/guardrails.js.map +1 -0
- package/dist/core/inference.d.ts +37 -0
- package/dist/core/inference.d.ts.map +1 -0
- package/dist/core/inference.js +110 -0
- package/dist/core/inference.js.map +1 -0
- package/dist/core/input-guardrails.d.ts +21 -0
- package/dist/core/input-guardrails.d.ts.map +1 -0
- package/dist/core/input-guardrails.js +59 -0
- package/dist/core/input-guardrails.js.map +1 -0
- package/dist/core/logger.d.ts +3 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +41 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/memory-graph.d.ts +126 -0
- package/dist/core/memory-graph.d.ts.map +1 -0
- package/dist/core/memory-graph.js +451 -0
- package/dist/core/memory-graph.js.map +1 -0
- package/dist/core/memory.d.ts +172 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +1432 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/owner-context.d.ts +8 -0
- package/dist/core/owner-context.d.ts.map +1 -0
- package/dist/core/owner-context.js +31 -0
- package/dist/core/owner-context.js.map +1 -0
- package/dist/core/price-oracle.d.ts +16 -0
- package/dist/core/price-oracle.d.ts.map +1 -0
- package/dist/core/price-oracle.js +162 -0
- package/dist/core/price-oracle.js.map +1 -0
- package/dist/core/solana-client.d.ts +39 -0
- package/dist/core/solana-client.d.ts.map +1 -0
- package/dist/core/solana-client.js +366 -0
- package/dist/core/solana-client.js.map +1 -0
- package/dist/core/telegram-client.d.ts +22 -0
- package/dist/core/telegram-client.d.ts.map +1 -0
- package/dist/core/telegram-client.js +93 -0
- package/dist/core/telegram-client.js.map +1 -0
- package/dist/core/venice-client.d.ts +94 -0
- package/dist/core/venice-client.d.ts.map +1 -0
- package/dist/core/venice-client.js +282 -0
- package/dist/core/venice-client.js.map +1 -0
- package/dist/core/x-client.d.ts +68 -0
- package/dist/core/x-client.d.ts.map +1 -0
- package/dist/core/x-client.js +383 -0
- package/dist/core/x-client.js.map +1 -0
- package/dist/events/event-bus.d.ts +37 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +21 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/handlers.d.ts +6 -0
- package/dist/events/handlers.d.ts.map +1 -0
- package/dist/events/handlers.js +21 -0
- package/dist/events/handlers.js.map +1 -0
- package/dist/features/action-learning.d.ts +61 -0
- package/dist/features/action-learning.d.ts.map +1 -0
- package/dist/features/action-learning.js +424 -0
- package/dist/features/action-learning.js.map +1 -0
- package/dist/features/active-reflection.d.ts +37 -0
- package/dist/features/active-reflection.d.ts.map +1 -0
- package/dist/features/active-reflection.js +376 -0
- package/dist/features/active-reflection.js.map +1 -0
- package/dist/features/agent-tier.d.ts +21 -0
- package/dist/features/agent-tier.d.ts.map +1 -0
- package/dist/features/agent-tier.js +56 -0
- package/dist/features/agent-tier.js.map +1 -0
- package/dist/features/campaign-tracker.d.ts +8 -0
- package/dist/features/campaign-tracker.d.ts.map +1 -0
- package/dist/features/campaign-tracker.js +206 -0
- package/dist/features/campaign-tracker.js.map +1 -0
- package/dist/features/clinamen.d.ts +48 -0
- package/dist/features/clinamen.d.ts.map +1 -0
- package/dist/features/clinamen.js +164 -0
- package/dist/features/clinamen.js.map +1 -0
- package/dist/features/dream-cycle.d.ts +12 -0
- package/dist/features/dream-cycle.d.ts.map +1 -0
- package/dist/features/dream-cycle.js +889 -0
- package/dist/features/dream-cycle.js.map +1 -0
- package/dist/features/market-monitor.d.ts +4 -0
- package/dist/features/market-monitor.d.ts.map +1 -0
- package/dist/features/market-monitor.js +135 -0
- package/dist/features/market-monitor.js.map +1 -0
- package/dist/features/memory-trace.d.ts +75 -0
- package/dist/features/memory-trace.d.ts.map +1 -0
- package/dist/features/memory-trace.js +325 -0
- package/dist/features/memory-trace.js.map +1 -0
- package/dist/features/onchain-opinion.d.ts +5 -0
- package/dist/features/onchain-opinion.d.ts.map +1 -0
- package/dist/features/onchain-opinion.js +70 -0
- package/dist/features/onchain-opinion.js.map +1 -0
- package/dist/features/price-personality.d.ts +4 -0
- package/dist/features/price-personality.d.ts.map +1 -0
- package/dist/features/price-personality.js +156 -0
- package/dist/features/price-personality.js.map +1 -0
- package/dist/features/x-sentiment-monitor.d.ts +8 -0
- package/dist/features/x-sentiment-monitor.d.ts.map +1 -0
- package/dist/features/x-sentiment-monitor.js +289 -0
- package/dist/features/x-sentiment-monitor.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/tokenomics.d.ts +72 -0
- package/dist/knowledge/tokenomics.d.ts.map +1 -0
- package/dist/knowledge/tokenomics.js +140 -0
- package/dist/knowledge/tokenomics.js.map +1 -0
- package/dist/mcp/local-store.d.ts +53 -0
- package/dist/mcp/local-store.d.ts.map +1 -0
- package/dist/mcp/local-store.js +175 -0
- package/dist/mcp/local-store.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +373 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mentions/classifier.d.ts +3 -0
- package/dist/mentions/classifier.d.ts.map +1 -0
- package/dist/mentions/classifier.js +51 -0
- package/dist/mentions/classifier.js.map +1 -0
- package/dist/mentions/dispatcher.d.ts +3 -0
- package/dist/mentions/dispatcher.d.ts.map +1 -0
- package/dist/mentions/dispatcher.js +404 -0
- package/dist/mentions/dispatcher.js.map +1 -0
- package/dist/mentions/poller.d.ts +3 -0
- package/dist/mentions/poller.d.ts.map +1 -0
- package/dist/mentions/poller.js +45 -0
- package/dist/mentions/poller.js.map +1 -0
- package/dist/sdk/cortex-v2.d.ts +121 -0
- package/dist/sdk/cortex-v2.d.ts.map +1 -0
- package/dist/sdk/cortex-v2.js +207 -0
- package/dist/sdk/cortex-v2.js.map +1 -0
- package/dist/sdk/cortex.d.ts +64 -0
- package/dist/sdk/cortex.d.ts.map +1 -0
- package/dist/sdk/cortex.js +362 -0
- package/dist/sdk/cortex.js.map +1 -0
- package/dist/sdk/http-transport.d.ts +15 -0
- package/dist/sdk/http-transport.d.ts.map +1 -0
- package/dist/sdk/http-transport.js +49 -0
- package/dist/sdk/http-transport.js.map +1 -0
- package/dist/sdk/index.d.ts +5 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +8 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/sdk-mode.d.ts +1 -0
- package/dist/sdk/sdk-mode.d.ts.map +1 -0
- package/dist/sdk/sdk-mode.js +5 -0
- package/dist/sdk/sdk-mode.js.map +1 -0
- package/dist/sdk/types.d.ts +48 -0
- package/dist/sdk/types.d.ts.map +1 -0
- package/dist/sdk/types.js +3 -0
- package/dist/sdk/types.js.map +1 -0
- package/dist/services/response.service.d.ts +27 -0
- package/dist/services/response.service.d.ts.map +1 -0
- package/dist/services/response.service.js +62 -0
- package/dist/services/response.service.js.map +1 -0
- package/dist/services/social.service.d.ts +14 -0
- package/dist/services/social.service.d.ts.map +1 -0
- package/dist/services/social.service.js +44 -0
- package/dist/services/social.service.js.map +1 -0
- package/dist/services/telegram.service.d.ts +30 -0
- package/dist/services/telegram.service.d.ts.map +1 -0
- package/dist/services/telegram.service.js +71 -0
- package/dist/services/telegram.service.js.map +1 -0
- package/dist/types/api.d.ts +109 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +6 -0
- package/dist/types/api.js.map +1 -0
- package/dist/utils/constants.d.ts +49 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +110 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/env-persona.d.ts +9 -0
- package/dist/utils/env-persona.d.ts.map +1 -0
- package/dist/utils/env-persona.js +53 -0
- package/dist/utils/env-persona.js.map +1 -0
- package/dist/utils/format.d.ts +12 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +59 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +20 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/text.d.ts +10 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +33 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/verify-app/routes.d.ts +3 -0
- package/dist/verify-app/routes.d.ts.map +1 -0
- package/dist/verify-app/routes.js +101 -0
- package/dist/verify-app/routes.js.map +1 -0
- package/dist/webhook/agent-routes.d.ts +3 -0
- package/dist/webhook/agent-routes.d.ts.map +1 -0
- package/dist/webhook/agent-routes.js +314 -0
- package/dist/webhook/agent-routes.js.map +1 -0
- package/dist/webhook/campaign-routes.d.ts +3 -0
- package/dist/webhook/campaign-routes.d.ts.map +1 -0
- package/dist/webhook/campaign-routes.js +333 -0
- package/dist/webhook/campaign-routes.js.map +1 -0
- package/dist/webhook/cortex-routes.d.ts +13 -0
- package/dist/webhook/cortex-routes.d.ts.map +1 -0
- package/dist/webhook/cortex-routes.js +534 -0
- package/dist/webhook/cortex-routes.js.map +1 -0
- package/dist/webhook/dashboard-routes.d.ts +8 -0
- package/dist/webhook/dashboard-routes.d.ts.map +1 -0
- package/dist/webhook/dashboard-routes.js +588 -0
- package/dist/webhook/dashboard-routes.js.map +1 -0
- package/dist/webhook/graph-routes.d.ts +3 -0
- package/dist/webhook/graph-routes.d.ts.map +1 -0
- package/dist/webhook/graph-routes.js +238 -0
- package/dist/webhook/graph-routes.js.map +1 -0
- package/dist/webhook/privy-auth.d.ts +35 -0
- package/dist/webhook/privy-auth.d.ts.map +1 -0
- package/dist/webhook/privy-auth.js +99 -0
- package/dist/webhook/privy-auth.js.map +1 -0
- package/dist/webhook/server.d.ts +4 -0
- package/dist/webhook/server.d.ts.map +1 -0
- package/dist/webhook/server.js +912 -0
- package/dist/webhook/server.js.map +1 -0
- package/package.json +96 -0
- package/supabase-schema.sql +399 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCachedEmbedding = getCachedEmbedding;
|
|
4
|
+
exports.setCachedEmbedding = setCachedEmbedding;
|
|
5
|
+
exports._configureEmbeddings = _configureEmbeddings;
|
|
6
|
+
exports.isEmbeddingEnabled = isEmbeddingEnabled;
|
|
7
|
+
exports.generateEmbedding = generateEmbedding;
|
|
8
|
+
exports.generateQueryEmbedding = generateQueryEmbedding;
|
|
9
|
+
exports.generateEmbeddings = generateEmbeddings;
|
|
10
|
+
const config_1 = require("../config");
|
|
11
|
+
const logger_1 = require("./logger");
|
|
12
|
+
const log = (0, logger_1.createChildLogger)('embeddings');
|
|
13
|
+
const PROVIDERS = {
|
|
14
|
+
voyage: {
|
|
15
|
+
url: 'https://api.voyageai.com/v1/embeddings',
|
|
16
|
+
defaultModel: 'voyage-4-large',
|
|
17
|
+
authHeader: (key) => `Bearer ${key}`,
|
|
18
|
+
},
|
|
19
|
+
openai: {
|
|
20
|
+
url: 'https://api.openai.com/v1/embeddings',
|
|
21
|
+
defaultModel: 'text-embedding-3-small',
|
|
22
|
+
authHeader: (key) => `Bearer ${key}`,
|
|
23
|
+
},
|
|
24
|
+
venice: {
|
|
25
|
+
url: 'https://api.venice.ai/api/v1/embeddings',
|
|
26
|
+
defaultModel: 'text-embedding-3-small',
|
|
27
|
+
authHeader: (key) => `Bearer ${key}`,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
let _enabled = null;
|
|
31
|
+
let _overrideConfig = null;
|
|
32
|
+
// LRU embedding cache — avoids re-computing embeddings for repeated/similar queries
|
|
33
|
+
const EMBEDDING_CACHE_MAX = 200;
|
|
34
|
+
const EMBEDDING_CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes
|
|
35
|
+
const _embeddingCache = new Map();
|
|
36
|
+
function getCachedEmbedding(text) {
|
|
37
|
+
const key = text.slice(0, 500).toLowerCase().trim();
|
|
38
|
+
const entry = _embeddingCache.get(key);
|
|
39
|
+
if (!entry)
|
|
40
|
+
return null;
|
|
41
|
+
if (Date.now() - entry.ts > EMBEDDING_CACHE_TTL_MS) {
|
|
42
|
+
_embeddingCache.delete(key);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return entry.embedding;
|
|
46
|
+
}
|
|
47
|
+
function setCachedEmbedding(text, embedding) {
|
|
48
|
+
const key = text.slice(0, 500).toLowerCase().trim();
|
|
49
|
+
// Evict oldest if at capacity
|
|
50
|
+
if (_embeddingCache.size >= EMBEDDING_CACHE_MAX) {
|
|
51
|
+
const oldest = _embeddingCache.keys().next().value;
|
|
52
|
+
if (oldest)
|
|
53
|
+
_embeddingCache.delete(oldest);
|
|
54
|
+
}
|
|
55
|
+
_embeddingCache.set(key, { embedding, ts: Date.now() });
|
|
56
|
+
}
|
|
57
|
+
/** @internal SDK escape hatch — allows Cortex to override embedding config. */
|
|
58
|
+
function _configureEmbeddings(opts) {
|
|
59
|
+
_overrideConfig = opts;
|
|
60
|
+
_enabled = null; // reset cached check
|
|
61
|
+
}
|
|
62
|
+
function getEmbeddingConfig() {
|
|
63
|
+
if (_overrideConfig)
|
|
64
|
+
return _overrideConfig;
|
|
65
|
+
return config_1.config.embedding;
|
|
66
|
+
}
|
|
67
|
+
function isEmbeddingEnabled() {
|
|
68
|
+
if (_enabled !== null)
|
|
69
|
+
return _enabled;
|
|
70
|
+
const cfg = getEmbeddingConfig();
|
|
71
|
+
_enabled = !!cfg.provider && !!cfg.apiKey && cfg.provider in PROVIDERS;
|
|
72
|
+
if (_enabled) {
|
|
73
|
+
log.info({ provider: cfg.provider }, 'Embedding system enabled');
|
|
74
|
+
}
|
|
75
|
+
return _enabled;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Call a specific embedding provider.
|
|
79
|
+
*/
|
|
80
|
+
async function callEmbeddingAPI(provider, apiKey, model, text, dimensions) {
|
|
81
|
+
const providerConfig = PROVIDERS[provider];
|
|
82
|
+
if (!providerConfig)
|
|
83
|
+
return null;
|
|
84
|
+
const startMs = Date.now();
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(providerConfig.url, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
'Authorization': providerConfig.authHeader(apiKey),
|
|
91
|
+
},
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
input: text.slice(0, 8000),
|
|
94
|
+
model,
|
|
95
|
+
...(provider === 'openai' ? { dimensions } : {}),
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
const errText = await res.text();
|
|
100
|
+
log.error({ status: res.status, body: errText.slice(0, 200), provider }, 'Embedding API error');
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const data = await res.json();
|
|
104
|
+
const embedding = data.data?.[0]?.embedding || null;
|
|
105
|
+
const elapsed = Date.now() - startMs;
|
|
106
|
+
log.debug({ provider, model, elapsed }, 'Embedding generated');
|
|
107
|
+
return embedding;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
log.error({ err, provider }, 'Embedding generation failed');
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Generate a single embedding vector for the given text.
|
|
116
|
+
* Returns null if embeddings are disabled or the API call fails.
|
|
117
|
+
*/
|
|
118
|
+
async function generateEmbedding(text) {
|
|
119
|
+
if (!isEmbeddingEnabled())
|
|
120
|
+
return null;
|
|
121
|
+
// Check cache first
|
|
122
|
+
const cached = getCachedEmbedding(text);
|
|
123
|
+
if (cached) {
|
|
124
|
+
log.debug('Embedding cache hit');
|
|
125
|
+
return cached;
|
|
126
|
+
}
|
|
127
|
+
const cfg = getEmbeddingConfig();
|
|
128
|
+
if (!cfg.provider || !(cfg.provider in PROVIDERS))
|
|
129
|
+
return null;
|
|
130
|
+
const providerConfig = PROVIDERS[cfg.provider];
|
|
131
|
+
const model = cfg.model || providerConfig.defaultModel;
|
|
132
|
+
const embedding = await callEmbeddingAPI(cfg.provider, cfg.apiKey, model, text, cfg.dimensions);
|
|
133
|
+
if (embedding)
|
|
134
|
+
setCachedEmbedding(text, embedding);
|
|
135
|
+
return embedding;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generate embedding optimized for query-time (recall).
|
|
139
|
+
* Uses a faster provider if configured (EMBEDDING_QUERY_PROVIDER),
|
|
140
|
+
* otherwise falls back to the default provider.
|
|
141
|
+
*/
|
|
142
|
+
async function generateQueryEmbedding(text) {
|
|
143
|
+
if (!isEmbeddingEnabled())
|
|
144
|
+
return null;
|
|
145
|
+
// Check cache first
|
|
146
|
+
const cached = getCachedEmbedding(text);
|
|
147
|
+
if (cached) {
|
|
148
|
+
log.debug('Query embedding cache hit');
|
|
149
|
+
return cached;
|
|
150
|
+
}
|
|
151
|
+
const cfg = getEmbeddingConfig();
|
|
152
|
+
// Try fast query provider first
|
|
153
|
+
const qProvider = cfg.queryProvider;
|
|
154
|
+
const qApiKey = cfg.queryApiKey;
|
|
155
|
+
const qModel = cfg.queryModel;
|
|
156
|
+
if (qProvider && qApiKey && qProvider in PROVIDERS) {
|
|
157
|
+
const providerConfig = PROVIDERS[qProvider];
|
|
158
|
+
const model = qModel || providerConfig.defaultModel;
|
|
159
|
+
log.debug({ provider: qProvider }, 'Using fast query embedding provider');
|
|
160
|
+
const embedding = await callEmbeddingAPI(qProvider, qApiKey, model, text);
|
|
161
|
+
if (embedding) {
|
|
162
|
+
setCachedEmbedding(text, embedding);
|
|
163
|
+
return embedding;
|
|
164
|
+
}
|
|
165
|
+
log.warn({ provider: qProvider }, 'Fast query provider failed, falling back to default');
|
|
166
|
+
}
|
|
167
|
+
// Fallback to default provider
|
|
168
|
+
return generateEmbedding(text);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Generate embeddings for multiple texts in a single batch API call.
|
|
172
|
+
* More efficient than calling generateEmbedding() in a loop.
|
|
173
|
+
* Returns an array matching input length; null for any that failed.
|
|
174
|
+
*/
|
|
175
|
+
async function generateEmbeddings(texts) {
|
|
176
|
+
if (!isEmbeddingEnabled() || texts.length === 0)
|
|
177
|
+
return texts.map(() => null);
|
|
178
|
+
const cfg = getEmbeddingConfig();
|
|
179
|
+
if (!cfg.provider || !(cfg.provider in PROVIDERS))
|
|
180
|
+
return texts.map(() => null);
|
|
181
|
+
const providerConfig = PROVIDERS[cfg.provider];
|
|
182
|
+
const model = cfg.model || providerConfig.defaultModel;
|
|
183
|
+
try {
|
|
184
|
+
const res = await fetch(providerConfig.url, {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
headers: {
|
|
187
|
+
'Content-Type': 'application/json',
|
|
188
|
+
'Authorization': providerConfig.authHeader(cfg.apiKey),
|
|
189
|
+
},
|
|
190
|
+
body: JSON.stringify({
|
|
191
|
+
input: texts.map(t => t.slice(0, 8000)),
|
|
192
|
+
model,
|
|
193
|
+
...(cfg.provider === 'openai' ? { dimensions: cfg.dimensions } : {}),
|
|
194
|
+
}),
|
|
195
|
+
});
|
|
196
|
+
if (!res.ok) {
|
|
197
|
+
log.error({ status: res.status }, 'Batch embedding API error');
|
|
198
|
+
return texts.map(() => null);
|
|
199
|
+
}
|
|
200
|
+
const data = await res.json();
|
|
201
|
+
const result = texts.map(() => null);
|
|
202
|
+
for (const item of data.data || []) {
|
|
203
|
+
result[item.index] = item.embedding;
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
log.error({ err }, 'Batch embedding generation failed');
|
|
209
|
+
return texts.map(() => null);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side encryption for memory content.
|
|
3
|
+
*
|
|
4
|
+
* Per-user key derivation from Solana Ed25519 keypairs:
|
|
5
|
+
* secretKey (64 bytes) → first 32 bytes (seed)
|
|
6
|
+
* → HKDF-SHA256(seed, salt="cogxai-cortex-v1", info="memory-encryption")
|
|
7
|
+
* → 32-byte symmetric key
|
|
8
|
+
* → nacl.secretbox (XSalsa20-Poly1305)
|
|
9
|
+
*
|
|
10
|
+
* Only the `content` field is encrypted. Summary, tags, concepts, embeddings,
|
|
11
|
+
* and all metadata stay plaintext for search and scoring.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Derive a symmetric encryption key from a Solana Ed25519 secret key.
|
|
15
|
+
* Stores the key and associated public key for the session.
|
|
16
|
+
*/
|
|
17
|
+
export declare function configureEncryption(solanaSecretKey: Uint8Array): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if encryption is active for this session.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isEncryptionEnabled(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Get the public key string of the active encryption key.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEncryptionPubkey(): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Encrypt plaintext content.
|
|
28
|
+
* Returns base64(nonce[24] || ciphertext).
|
|
29
|
+
*/
|
|
30
|
+
export declare function encryptContent(plaintext: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Decrypt encrypted content.
|
|
33
|
+
* Input: base64(nonce[24] || ciphertext).
|
|
34
|
+
* Returns plaintext or null if decryption fails.
|
|
35
|
+
*/
|
|
36
|
+
export declare function decryptContent(encrypted: string): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* In-place decrypt memory content for a batch of memories.
|
|
39
|
+
* Skips memories that are:
|
|
40
|
+
* - Not encrypted (encrypted !== true)
|
|
41
|
+
* - Encrypted by a different pubkey (logs warning, leaves content as-is)
|
|
42
|
+
* - Undecryptable (wrong key, corrupted — leaves content as-is)
|
|
43
|
+
*/
|
|
44
|
+
export declare function decryptMemoryBatch<T extends {
|
|
45
|
+
content: string;
|
|
46
|
+
encrypted?: boolean;
|
|
47
|
+
encryption_pubkey?: string | null;
|
|
48
|
+
}>(memories: T[]): T[];
|
|
49
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/core/encryption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,eAAe,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBpF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAEnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAexD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuB/D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtH,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE,CAqBL"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Client-side encryption for memory content.
|
|
4
|
+
*
|
|
5
|
+
* Per-user key derivation from Solana Ed25519 keypairs:
|
|
6
|
+
* secretKey (64 bytes) → first 32 bytes (seed)
|
|
7
|
+
* → HKDF-SHA256(seed, salt="cogxai-cortex-v1", info="memory-encryption")
|
|
8
|
+
* → 32-byte symmetric key
|
|
9
|
+
* → nacl.secretbox (XSalsa20-Poly1305)
|
|
10
|
+
*
|
|
11
|
+
* Only the `content` field is encrypted. Summary, tags, concepts, embeddings,
|
|
12
|
+
* and all metadata stay plaintext for search and scoring.
|
|
13
|
+
*/
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.configureEncryption = configureEncryption;
|
|
19
|
+
exports.isEncryptionEnabled = isEncryptionEnabled;
|
|
20
|
+
exports.getEncryptionPubkey = getEncryptionPubkey;
|
|
21
|
+
exports.encryptContent = encryptContent;
|
|
22
|
+
exports.decryptContent = decryptContent;
|
|
23
|
+
exports.decryptMemoryBatch = decryptMemoryBatch;
|
|
24
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
25
|
+
const crypto_1 = require("crypto");
|
|
26
|
+
const util_1 = require("util");
|
|
27
|
+
const logger_1 = require("./logger");
|
|
28
|
+
const log = (0, logger_1.createChildLogger)('encryption');
|
|
29
|
+
const hkdfAsync = (0, util_1.promisify)(crypto_1.hkdf);
|
|
30
|
+
const HKDF_SALT = 'cogxai-cortex-v1';
|
|
31
|
+
const HKDF_INFO = 'memory-encryption';
|
|
32
|
+
const NONCE_LENGTH = tweetnacl_1.default.secretbox.nonceLength; // 24 bytes
|
|
33
|
+
let encryptionKey = null;
|
|
34
|
+
let encryptionPubkey = null;
|
|
35
|
+
/**
|
|
36
|
+
* Derive a symmetric encryption key from a Solana Ed25519 secret key.
|
|
37
|
+
* Stores the key and associated public key for the session.
|
|
38
|
+
*/
|
|
39
|
+
async function configureEncryption(solanaSecretKey) {
|
|
40
|
+
if (solanaSecretKey.length !== 64) {
|
|
41
|
+
throw new Error('Encryption requires a 64-byte Ed25519 secret key');
|
|
42
|
+
}
|
|
43
|
+
// First 32 bytes = seed (same as nacl.sign.keyPair.fromSeed uses)
|
|
44
|
+
const seed = solanaSecretKey.slice(0, 32);
|
|
45
|
+
// Derive 32-byte symmetric key via HKDF-SHA256
|
|
46
|
+
const derived = await hkdfAsync('sha256', seed, HKDF_SALT, HKDF_INFO, 32);
|
|
47
|
+
encryptionKey = new Uint8Array(derived);
|
|
48
|
+
// Extract public key for tagging encrypted memories
|
|
49
|
+
const keypair = tweetnacl_1.default.sign.keyPair.fromSecretKey(solanaSecretKey);
|
|
50
|
+
encryptionPubkey = Buffer.from(keypair.publicKey).toString('base64');
|
|
51
|
+
log.info({ pubkey: encryptionPubkey.slice(0, 12) + '...' }, 'Encryption configured');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if encryption is active for this session.
|
|
55
|
+
*/
|
|
56
|
+
function isEncryptionEnabled() {
|
|
57
|
+
return encryptionKey !== null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the public key string of the active encryption key.
|
|
61
|
+
*/
|
|
62
|
+
function getEncryptionPubkey() {
|
|
63
|
+
return encryptionPubkey;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Encrypt plaintext content.
|
|
67
|
+
* Returns base64(nonce[24] || ciphertext).
|
|
68
|
+
*/
|
|
69
|
+
function encryptContent(plaintext) {
|
|
70
|
+
if (!encryptionKey) {
|
|
71
|
+
throw new Error('Encryption not configured. Call configureEncryption() first.');
|
|
72
|
+
}
|
|
73
|
+
const nonce = tweetnacl_1.default.randomBytes(NONCE_LENGTH);
|
|
74
|
+
const messageBytes = new TextEncoder().encode(plaintext);
|
|
75
|
+
const ciphertext = tweetnacl_1.default.secretbox(messageBytes, nonce, encryptionKey);
|
|
76
|
+
// Concatenate nonce + ciphertext
|
|
77
|
+
const combined = new Uint8Array(NONCE_LENGTH + ciphertext.length);
|
|
78
|
+
combined.set(nonce, 0);
|
|
79
|
+
combined.set(ciphertext, NONCE_LENGTH);
|
|
80
|
+
return Buffer.from(combined).toString('base64');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Decrypt encrypted content.
|
|
84
|
+
* Input: base64(nonce[24] || ciphertext).
|
|
85
|
+
* Returns plaintext or null if decryption fails.
|
|
86
|
+
*/
|
|
87
|
+
function decryptContent(encrypted) {
|
|
88
|
+
if (!encryptionKey) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const combined = Buffer.from(encrypted, 'base64');
|
|
93
|
+
if (combined.length < NONCE_LENGTH + 1) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const nonce = combined.subarray(0, NONCE_LENGTH);
|
|
97
|
+
const ciphertext = combined.subarray(NONCE_LENGTH);
|
|
98
|
+
const plaintext = tweetnacl_1.default.secretbox.open(ciphertext, nonce, encryptionKey);
|
|
99
|
+
if (!plaintext) {
|
|
100
|
+
return null; // Wrong key or corrupted data
|
|
101
|
+
}
|
|
102
|
+
return new TextDecoder().decode(plaintext);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* In-place decrypt memory content for a batch of memories.
|
|
110
|
+
* Skips memories that are:
|
|
111
|
+
* - Not encrypted (encrypted !== true)
|
|
112
|
+
* - Encrypted by a different pubkey (logs warning, leaves content as-is)
|
|
113
|
+
* - Undecryptable (wrong key, corrupted — leaves content as-is)
|
|
114
|
+
*/
|
|
115
|
+
function decryptMemoryBatch(memories) {
|
|
116
|
+
if (!encryptionKey || !encryptionPubkey)
|
|
117
|
+
return memories;
|
|
118
|
+
for (const mem of memories) {
|
|
119
|
+
if (!mem.encrypted)
|
|
120
|
+
continue;
|
|
121
|
+
// Check pubkey match — skip if encrypted by different user
|
|
122
|
+
if (mem.encryption_pubkey && mem.encryption_pubkey !== encryptionPubkey) {
|
|
123
|
+
log.debug({ memPubkey: mem.encryption_pubkey?.slice(0, 12) }, 'Skipping memory encrypted by different key');
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const decrypted = decryptContent(mem.content);
|
|
127
|
+
if (decrypted !== null) {
|
|
128
|
+
mem.content = decrypted;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
log.warn('Failed to decrypt memory content — wrong key or corrupted data');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return memories;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.js","sourceRoot":"","sources":["../../src/core/encryption.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output guardrails — sanitize LLM responses before they are posted.
|
|
3
|
+
* Catches prompt injection attempts, fund transfer language, and leaked secrets.
|
|
4
|
+
*/
|
|
5
|
+
export declare function setGuardrailBotAddress(address: string): void;
|
|
6
|
+
export interface GuardrailResult {
|
|
7
|
+
safe: boolean;
|
|
8
|
+
reason?: string;
|
|
9
|
+
sanitized?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Run all guardrails on LLM output before posting.
|
|
13
|
+
* Returns { safe: true } if output is clean.
|
|
14
|
+
* Returns { safe: false, reason, sanitized } if output was blocked or cleaned.
|
|
15
|
+
*/
|
|
16
|
+
export declare function checkOutput(text: string): GuardrailResult;
|
|
17
|
+
/**
|
|
18
|
+
* Sanitize and validate LLM output. Returns the text if safe, or a fallback if blocked.
|
|
19
|
+
*/
|
|
20
|
+
export declare function sanitizeOutput(text: string, fallback?: string): string;
|
|
21
|
+
export interface ContentFilterResult {
|
|
22
|
+
allowed: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Filter user-submitted input content (demo store, public endpoints).
|
|
27
|
+
* Blocks hate speech, slurs, violence, and spam.
|
|
28
|
+
*/
|
|
29
|
+
export declare function checkInputContent(text: string): ContentFilterResult;
|
|
30
|
+
//# sourceMappingURL=guardrails.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA8DH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA8DzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,MAAM,CAM1E;AAkCD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAyBnE"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Output guardrails — sanitize LLM responses before they are posted.
|
|
4
|
+
* Catches prompt injection attempts, fund transfer language, and leaked secrets.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.setGuardrailBotAddress = setGuardrailBotAddress;
|
|
8
|
+
exports.checkOutput = checkOutput;
|
|
9
|
+
exports.sanitizeOutput = sanitizeOutput;
|
|
10
|
+
exports.checkInputContent = checkInputContent;
|
|
11
|
+
const logger_1 = require("./logger");
|
|
12
|
+
const tokenomics_1 = require("../knowledge/tokenomics");
|
|
13
|
+
const log = (0, logger_1.createChildLogger)('guardrails');
|
|
14
|
+
// Whitelisted addresses that are safe to share (official token CA, etc.)
|
|
15
|
+
const WHITELISTED_ADDRESSES = new Set([
|
|
16
|
+
tokenomics_1.COGXAI_CA, // Official COGXAI token contract address
|
|
17
|
+
]);
|
|
18
|
+
// Whitelisted domains that are allowed in output (e.g. transaction explorers)
|
|
19
|
+
const WHITELISTED_URL_DOMAINS = new Set([
|
|
20
|
+
'solscan.io',
|
|
21
|
+
]);
|
|
22
|
+
// URL patterns — catches links in output regardless of how they got there
|
|
23
|
+
// (reversed text, base64 decode, character-by-character, ROT13, etc.)
|
|
24
|
+
const URL_PATTERNS = [
|
|
25
|
+
// Explicit protocol URLs
|
|
26
|
+
/https?:\/\/\S+/i,
|
|
27
|
+
// Protocol-relative URLs
|
|
28
|
+
/\/\/[\w-]+\.[\w-]+/,
|
|
29
|
+
// Common URL shorteners (no protocol needed)
|
|
30
|
+
/\bt\.co\/\S+/i,
|
|
31
|
+
/\bbit\.ly\/\S+/i,
|
|
32
|
+
/\bgoo\.gl\/\S+/i,
|
|
33
|
+
/\btinyurl\.com\/\S+/i,
|
|
34
|
+
/\bift\.tt\/\S+/i,
|
|
35
|
+
/\bowl\.ly\/\S+/i,
|
|
36
|
+
/\bbuff\.ly\/\S+/i,
|
|
37
|
+
// Generic domain + path patterns (catches URLs without protocol)
|
|
38
|
+
/\b[\w-]+\.(?:com|io|org|net|co|xyz|app|dev|me|gg|to|cc|ly|link|lol|wtf|fun|meme|click|site|online|info|biz|tech|ai|so|vc|fm|tv|sh|im|is)\/\S+/i,
|
|
39
|
+
];
|
|
40
|
+
// Solana base58 address pattern (32-44 chars of base58 alphabet)
|
|
41
|
+
const SOLANA_ADDRESS_RE = /\b[1-9A-HJ-NP-Za-km-z]{32,44}\b/g;
|
|
42
|
+
// Common private key / seed phrase patterns (keyword-based only, no word-count heuristics)
|
|
43
|
+
const SECRET_PATTERNS = [
|
|
44
|
+
/\b(?:private[\s_-]?key|secret[\s_-]?key|seed[\s_-]?phrase|mnemonic|recovery[\s_-]?phrase)\b/i,
|
|
45
|
+
/\b(?:here(?:'s| is) (?:my|the|your) (?:private key|seed phrase|secret key|mnemonic))\b/i,
|
|
46
|
+
];
|
|
47
|
+
// Fund transfer / transaction instruction patterns
|
|
48
|
+
const TRANSFER_PATTERNS = [
|
|
49
|
+
/\b(?:send|transfer|withdraw|bridge|swap)\s+(?:\d+[\s.]?\d*\s*)?(?:SOL|sol|lamports|tokens?|USDC|USDT)\b/i,
|
|
50
|
+
/\b(?:sending|transferring|withdrawing)\s+(?:funds?|SOL|tokens?|crypto)\b/i,
|
|
51
|
+
/\bsend\s+(?:to|from)\s+(?:wallet|address)\b/i,
|
|
52
|
+
/\b(?:here(?:'s| is)\s+(?:the|my|your)\s+(?:wallet|address))\b/i,
|
|
53
|
+
/\b(?:airdrop|distribute|disperse)\s+(?:to|tokens?|SOL)\b/i,
|
|
54
|
+
];
|
|
55
|
+
// Contract address / mint patterns
|
|
56
|
+
const CA_PATTERNS = [
|
|
57
|
+
/\b(?:CA|contract[\s_-]?address|mint[\s_-]?address|token[\s_-]?mint)\s*[:=]?\s*[1-9A-HJ-NP-Za-km-z]{32,44}\b/i,
|
|
58
|
+
];
|
|
59
|
+
// The bot's own wallet address — never leak this in replies
|
|
60
|
+
let BOT_ADDRESS = null;
|
|
61
|
+
function setGuardrailBotAddress(address) {
|
|
62
|
+
BOT_ADDRESS = address;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Run all guardrails on LLM output before posting.
|
|
66
|
+
* Returns { safe: true } if output is clean.
|
|
67
|
+
* Returns { safe: false, reason, sanitized } if output was blocked or cleaned.
|
|
68
|
+
*/
|
|
69
|
+
function checkOutput(text) {
|
|
70
|
+
// 1. Check for private key / seed phrase leaks
|
|
71
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
72
|
+
if (pattern.test(text)) {
|
|
73
|
+
log.warn({ pattern: pattern.source }, 'GUARDRAIL: Secret pattern detected in output');
|
|
74
|
+
return { safe: false, reason: 'secret_leak' };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// 2. Check for fund transfer instructions
|
|
78
|
+
for (const pattern of TRANSFER_PATTERNS) {
|
|
79
|
+
if (pattern.test(text)) {
|
|
80
|
+
log.warn({ pattern: pattern.source, text: text.slice(0, 200) }, 'GUARDRAIL: Transfer language detected');
|
|
81
|
+
return { safe: false, reason: 'transfer_language' };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 3. Check for contract address patterns (but allow whitelisted addresses)
|
|
85
|
+
for (const pattern of CA_PATTERNS) {
|
|
86
|
+
if (pattern.test(text)) {
|
|
87
|
+
// Check if the text contains only whitelisted addresses
|
|
88
|
+
const addresses = text.match(SOLANA_ADDRESS_RE) || [];
|
|
89
|
+
const hasNonWhitelisted = addresses.some(addr => !WHITELISTED_ADDRESSES.has(addr));
|
|
90
|
+
if (hasNonWhitelisted) {
|
|
91
|
+
log.warn({ text: text.slice(0, 200) }, 'GUARDRAIL: Unauthorized contract address detected');
|
|
92
|
+
return { safe: false, reason: 'contract_address' };
|
|
93
|
+
}
|
|
94
|
+
// If only whitelisted addresses, allow it
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// 4. Check if output contains what looks like a Solana address (strip known safe ones)
|
|
98
|
+
const addresses = text.match(SOLANA_ADDRESS_RE) || [];
|
|
99
|
+
for (const addr of addresses) {
|
|
100
|
+
// Allow whitelisted addresses (official token CA, etc.)
|
|
101
|
+
if (WHITELISTED_ADDRESSES.has(addr))
|
|
102
|
+
continue;
|
|
103
|
+
// Allow solscan URLs (they contain tx signatures which look like addresses)
|
|
104
|
+
if (text.includes(`solscan.io/tx/${addr}`))
|
|
105
|
+
continue;
|
|
106
|
+
// Block if it matches bot's own address
|
|
107
|
+
if (BOT_ADDRESS && addr === BOT_ADDRESS) {
|
|
108
|
+
log.warn('GUARDRAIL: Bot wallet address leaked in output');
|
|
109
|
+
return { safe: false, reason: 'bot_address_leak' };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 5. Check for URLs / links in output (blocks prompt injection via text reversal, decoding, etc.)
|
|
113
|
+
for (const pattern of URL_PATTERNS) {
|
|
114
|
+
const match = text.match(pattern);
|
|
115
|
+
if (match) {
|
|
116
|
+
const matchedUrl = match[0];
|
|
117
|
+
// Check if the matched URL belongs to a whitelisted domain
|
|
118
|
+
const isWhitelisted = [...WHITELISTED_URL_DOMAINS].some(domain => matchedUrl.includes(domain));
|
|
119
|
+
if (!isWhitelisted) {
|
|
120
|
+
log.warn({ url: matchedUrl.slice(0, 80) }, 'GUARDRAIL: URL detected in output');
|
|
121
|
+
return { safe: false, reason: 'url_in_output' };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { safe: true };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Sanitize and validate LLM output. Returns the text if safe, or a fallback if blocked.
|
|
129
|
+
*/
|
|
130
|
+
function sanitizeOutput(text, fallback = '') {
|
|
131
|
+
const result = checkOutput(text);
|
|
132
|
+
if (result.safe)
|
|
133
|
+
return text;
|
|
134
|
+
log.error({ reason: result.reason, textLength: text.length }, 'GUARDRAIL: Output blocked');
|
|
135
|
+
return fallback;
|
|
136
|
+
}
|
|
137
|
+
// ── Input content filter (for user-submitted content like demo store) ──
|
|
138
|
+
// Slurs and hate speech (case-insensitive)
|
|
139
|
+
const SLUR_PATTERNS = [
|
|
140
|
+
/\bn+[i1!]+[gq]+[e3]*[r]+s?\b/i,
|
|
141
|
+
/\bf+[a@]+[gq]+[o0]*t*s?\b/i,
|
|
142
|
+
/\bk+[i1]+k+[e3]+s?\b/i,
|
|
143
|
+
/\bch+[i1]+n+k+s?\b/i,
|
|
144
|
+
/\bsp+[i1]+c+s?\b/i,
|
|
145
|
+
/\bw+[e3]+tb+[a@]+ck+s?\b/i,
|
|
146
|
+
/\bg+[o0]+[o0]+k+s?\b/i,
|
|
147
|
+
/\btr+[a@]+n+[i1e3]+s?\b/i,
|
|
148
|
+
/\bd+[y]+k+[e3]+s?\b/i,
|
|
149
|
+
/\bcr+[a@]+ck+[e3]+r+s?\b/i,
|
|
150
|
+
/\bre+t+[a@]+r+d+s?\b/i,
|
|
151
|
+
];
|
|
152
|
+
// Violence and harm
|
|
153
|
+
const VIOLENCE_PATTERNS = [
|
|
154
|
+
/\b(?:kill|murder|shoot|stab|lynch|hang|behead|rape)\s+(?:all|every|them|those|the)\b/i,
|
|
155
|
+
/\b(?:gas|exterminate|genocide)\b/i,
|
|
156
|
+
/\bkill\s+(?:your|my|him|her)self\b/i,
|
|
157
|
+
/\bwhip\s+(?:him|her|them)\b/i,
|
|
158
|
+
];
|
|
159
|
+
// Spam / scam patterns
|
|
160
|
+
const SPAM_PATTERNS = [
|
|
161
|
+
/\b(?:send|give|airdrop)\s+(?:me|us)\s+(?:free\s+)?(?:sol|crypto|tokens?|money)\b/i,
|
|
162
|
+
/\b(?:send|transfer)\s+\d+(?:\.\d+)?\s*(?:sol|eth|btc|usdc|usdt)\s+to\b/i,
|
|
163
|
+
/(?:private[\s_-]?key|seed[\s_-]?phrase)\b/i,
|
|
164
|
+
];
|
|
165
|
+
/**
|
|
166
|
+
* Filter user-submitted input content (demo store, public endpoints).
|
|
167
|
+
* Blocks hate speech, slurs, violence, and spam.
|
|
168
|
+
*/
|
|
169
|
+
function checkInputContent(text) {
|
|
170
|
+
const lower = text.toLowerCase();
|
|
171
|
+
for (const pattern of SLUR_PATTERNS) {
|
|
172
|
+
if (pattern.test(lower)) {
|
|
173
|
+
log.warn({ textSnippet: text.slice(0, 50) }, 'INPUT FILTER: Slur detected');
|
|
174
|
+
return { allowed: false, reason: 'hate_speech' };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const pattern of VIOLENCE_PATTERNS) {
|
|
178
|
+
if (pattern.test(lower)) {
|
|
179
|
+
log.warn({ textSnippet: text.slice(0, 50) }, 'INPUT FILTER: Violence detected');
|
|
180
|
+
return { allowed: false, reason: 'violence' };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
for (const pattern of SPAM_PATTERNS) {
|
|
184
|
+
if (pattern.test(lower)) {
|
|
185
|
+
log.warn({ textSnippet: text.slice(0, 50) }, 'INPUT FILTER: Spam detected');
|
|
186
|
+
return { allowed: false, reason: 'spam' };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return { allowed: true };
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=guardrails.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"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"}
|