@cryptoquant_official/mcp 0.0.4 → 0.0.6-alpha
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 +330 -37
- package/dist/ai-sdk/anthropic.d.ts +125 -0
- package/dist/ai-sdk/anthropic.d.ts.map +1 -0
- package/dist/ai-sdk/anthropic.js +278 -0
- package/dist/ai-sdk/anthropic.js.map +1 -0
- package/dist/ai-sdk/execute.d.ts +35 -0
- package/dist/ai-sdk/execute.d.ts.map +1 -0
- package/dist/ai-sdk/execute.js +531 -0
- package/dist/ai-sdk/execute.js.map +1 -0
- package/dist/ai-sdk/index.d.ts +53 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +56 -0
- package/dist/ai-sdk/index.js.map +1 -0
- package/dist/ai-sdk/prompts.d.ts +34 -0
- package/dist/ai-sdk/prompts.d.ts.map +1 -0
- package/dist/ai-sdk/prompts.js +74 -0
- package/dist/ai-sdk/prompts.js.map +1 -0
- package/dist/ai-sdk/schemas.d.ts +66 -0
- package/dist/ai-sdk/schemas.d.ts.map +1 -0
- package/dist/ai-sdk/schemas.js +136 -0
- package/dist/ai-sdk/schemas.js.map +1 -0
- package/dist/ai-sdk/tools.d.ts +165 -0
- package/dist/ai-sdk/tools.d.ts.map +1 -0
- package/dist/ai-sdk/tools.js +152 -0
- package/dist/ai-sdk/tools.js.map +1 -0
- package/dist/ai-sdk/types.d.ts +149 -0
- package/dist/ai-sdk/types.d.ts.map +1 -0
- package/dist/ai-sdk/types.js +5 -0
- package/dist/ai-sdk/types.js.map +1 -0
- package/dist/core/auth/storage.d.ts.map +1 -0
- package/dist/core/auth/storage.js.map +1 -0
- package/dist/core/cache/storage.d.ts +110 -0
- package/dist/core/cache/storage.d.ts.map +1 -0
- package/dist/core/cache/storage.js +356 -0
- package/dist/core/cache/storage.js.map +1 -0
- package/dist/core/cache/summary.d.ts.map +1 -0
- package/dist/core/cache/summary.js.map +1 -0
- package/dist/{cache → core/cache}/types.d.ts +25 -0
- package/dist/{cache → core/cache}/types.d.ts.map +1 -1
- package/dist/core/cache/types.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/{discovery.js → core/discovery.js} +14 -2
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +19 -0
- package/dist/core/index.js.map +1 -0
- package/dist/{permissions.d.ts → core/permissions.d.ts} +2 -2
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/{permissions.js → core/permissions.js} +38 -14
- package/dist/core/permissions.js.map +1 -0
- package/dist/core/plan-limits.d.ts.map +1 -0
- package/dist/core/plan-limits.js.map +1 -0
- package/dist/{utils.d.ts → core/utils.d.ts} +13 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/{utils.js → core/utils.js} +34 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/data/metrics.toon +8 -5
- package/dist/http/chat-proxy.d.ts +32 -0
- package/dist/http/chat-proxy.d.ts.map +1 -0
- package/dist/http/chat-proxy.js +310 -0
- package/dist/http/chat-proxy.js.map +1 -0
- package/dist/http/index.d.ts +12 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +30 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/server.d.ts +20 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +231 -0
- package/dist/http/server.js.map +1 -0
- package/dist/shared/metrics-data.generated.d.ts +176 -0
- package/dist/shared/metrics-data.generated.d.ts.map +1 -0
- package/dist/shared/metrics-data.generated.js +3077 -0
- package/dist/shared/metrics-data.generated.js.map +1 -0
- package/dist/stdio/index.d.ts +10 -0
- package/dist/stdio/index.d.ts.map +1 -0
- package/dist/stdio/index.js +30 -0
- package/dist/stdio/index.js.map +1 -0
- package/dist/stdio/tools/auth.d.ts +3 -0
- package/dist/stdio/tools/auth.d.ts.map +1 -0
- package/dist/{tools → stdio/tools}/auth.js +38 -12
- package/dist/stdio/tools/auth.js.map +1 -0
- package/dist/stdio/tools/core.d.ts +3 -0
- package/dist/stdio/tools/core.d.ts.map +1 -0
- package/dist/{tools → stdio/tools}/core.js +122 -162
- package/dist/stdio/tools/core.js.map +1 -0
- package/package.json +55 -14
- package/dist/auth/storage.d.ts.map +0 -1
- package/dist/auth/storage.js.map +0 -1
- package/dist/cache/storage.d.ts +0 -47
- package/dist/cache/storage.d.ts.map +0 -1
- package/dist/cache/storage.js +0 -140
- package/dist/cache/storage.js.map +0 -1
- package/dist/cache/summary.d.ts.map +0 -1
- package/dist/cache/summary.js.map +0 -1
- package/dist/cache/types.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/discovery.d.ts.map +0 -1
- package/dist/discovery.js.map +0 -1
- package/dist/index.d.ts +0 -18
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -46
- package/dist/index.js.map +0 -1
- package/dist/permissions.d.ts.map +0 -1
- package/dist/permissions.js.map +0 -1
- package/dist/plan-limits.d.ts.map +0 -1
- package/dist/plan-limits.js.map +0 -1
- package/dist/tools/auth.d.ts +0 -3
- package/dist/tools/auth.d.ts.map +0 -1
- package/dist/tools/auth.js.map +0 -1
- package/dist/tools/core.d.ts +0 -3
- package/dist/tools/core.d.ts.map +0 -1
- package/dist/tools/core.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- /package/dist/{auth → core/auth}/storage.d.ts +0 -0
- /package/dist/{auth → core/auth}/storage.js +0 -0
- /package/dist/{cache → core/cache}/summary.d.ts +0 -0
- /package/dist/{cache → core/cache}/summary.js +0 -0
- /package/dist/{cache → core/cache}/types.js +0 -0
- /package/dist/{config.d.ts → core/config.d.ts} +0 -0
- /package/dist/{config.js → core/config.js} +0 -0
- /package/dist/{discovery.d.ts → core/discovery.d.ts} +0 -0
- /package/dist/{plan-limits.d.ts → core/plan-limits.d.ts} +0 -0
- /package/dist/{plan-limits.js → core/plan-limits.js} +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for AI SDK integration
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Context for tool execution
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolExecutionContext {
|
|
8
|
+
cryptoquantApiKey?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Result from initialize tool
|
|
12
|
+
*/
|
|
13
|
+
export interface InitializeResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
plan?: string;
|
|
16
|
+
message?: string;
|
|
17
|
+
error?: string;
|
|
18
|
+
from_cache?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result from discover_endpoints tool
|
|
22
|
+
*/
|
|
23
|
+
export interface DiscoverResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
total_found?: number;
|
|
26
|
+
showing?: number;
|
|
27
|
+
endpoints?: Record<string, Array<{
|
|
28
|
+
path: string;
|
|
29
|
+
metric: string;
|
|
30
|
+
}>>;
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Result from query_data tool
|
|
35
|
+
*/
|
|
36
|
+
export interface QueryResult {
|
|
37
|
+
success: boolean;
|
|
38
|
+
endpoint?: string;
|
|
39
|
+
data?: unknown[];
|
|
40
|
+
error?: string;
|
|
41
|
+
suggestions?: string[];
|
|
42
|
+
details?: string;
|
|
43
|
+
available_parameters?: unknown;
|
|
44
|
+
your_plan?: string;
|
|
45
|
+
required_plan?: string;
|
|
46
|
+
earliest_allowed?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Result from describe_metric tool
|
|
50
|
+
*/
|
|
51
|
+
export interface DescribeResult {
|
|
52
|
+
success: boolean;
|
|
53
|
+
metric?: {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
category: string;
|
|
57
|
+
definition: string;
|
|
58
|
+
interpretation: string;
|
|
59
|
+
thresholds: Array<{
|
|
60
|
+
range: string;
|
|
61
|
+
signal: string;
|
|
62
|
+
emoji: string;
|
|
63
|
+
meaning: string;
|
|
64
|
+
}>;
|
|
65
|
+
keyInsights: string[];
|
|
66
|
+
endpoint: string;
|
|
67
|
+
};
|
|
68
|
+
error?: string;
|
|
69
|
+
available?: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Metric signal in market summary
|
|
73
|
+
*/
|
|
74
|
+
export interface MetricSignal {
|
|
75
|
+
metric: string;
|
|
76
|
+
value: number | string;
|
|
77
|
+
signal: "bullish" | "neutral" | "caution" | "bearish";
|
|
78
|
+
emoji: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result from market_summary tool
|
|
82
|
+
*/
|
|
83
|
+
export interface MarketSummaryResult {
|
|
84
|
+
success: boolean;
|
|
85
|
+
asset?: string;
|
|
86
|
+
metrics?: MetricSignal[];
|
|
87
|
+
overall?: {
|
|
88
|
+
signal: string;
|
|
89
|
+
bullishCount: number;
|
|
90
|
+
bearishCount: number;
|
|
91
|
+
};
|
|
92
|
+
insight?: string;
|
|
93
|
+
error?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Metric score detail in trading signal
|
|
97
|
+
*/
|
|
98
|
+
export interface MetricScore {
|
|
99
|
+
metric: string;
|
|
100
|
+
value: number;
|
|
101
|
+
score: number;
|
|
102
|
+
weight: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Result from trading_signal tool
|
|
106
|
+
*/
|
|
107
|
+
export interface TradingSignalResult {
|
|
108
|
+
success: boolean;
|
|
109
|
+
asset?: string;
|
|
110
|
+
signal?: string;
|
|
111
|
+
confidence?: number;
|
|
112
|
+
metrics?: MetricScore[];
|
|
113
|
+
analysis?: {
|
|
114
|
+
bullish: string[];
|
|
115
|
+
neutral: string[];
|
|
116
|
+
bearish: string[];
|
|
117
|
+
};
|
|
118
|
+
disclaimer?: string;
|
|
119
|
+
error?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Result from whale_activity tool
|
|
123
|
+
*/
|
|
124
|
+
export interface WhaleActivityResult {
|
|
125
|
+
success: boolean;
|
|
126
|
+
asset?: string;
|
|
127
|
+
timeframe?: string;
|
|
128
|
+
whaleRatio?: number;
|
|
129
|
+
whaleStatus?: string;
|
|
130
|
+
flows?: {
|
|
131
|
+
inflow: number;
|
|
132
|
+
outflow: number;
|
|
133
|
+
netflow: number;
|
|
134
|
+
};
|
|
135
|
+
behavior?: string;
|
|
136
|
+
signal?: string;
|
|
137
|
+
error?: string;
|
|
138
|
+
note?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Configuration for creating CryptoQuant tools
|
|
142
|
+
*/
|
|
143
|
+
export interface CryptoQuantToolsConfig {
|
|
144
|
+
/**
|
|
145
|
+
* CryptoQuant API key for authentication
|
|
146
|
+
*/
|
|
147
|
+
cryptoquantApiKey: string;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai-sdk/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai-sdk/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/core/auth/storage.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAQ/C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAa/C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CASxC;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/auth/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/F,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAQ9D,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACjC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAsB;QAC9B,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACvC,CAAC;IAEF,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACtF,SAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,OAAO;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAsB,CAAC;QACtF,IAAI,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,gBAAgB,CAAC;YAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache storage operations for discovery response caching
|
|
3
|
+
* Supports file-based (CLI/local) and Redis-based (web server) storage
|
|
4
|
+
*/
|
|
5
|
+
import { type CacheStorage, type DiscoveryCacheSchema, type MyDiscoveryRawResponse, type DiscoverySummaryData, type StorageEnvironment } from "./types.js";
|
|
6
|
+
import type { UserPlan, PlanLimits, ApiRateLimit } from "../plan-limits.js";
|
|
7
|
+
/**
|
|
8
|
+
* Configure the storage environment.
|
|
9
|
+
* Call this before any cache operations to explicitly set the storage type.
|
|
10
|
+
*
|
|
11
|
+
* @param env - "file" for local/CLI, "redis" for web server, "auto" to detect
|
|
12
|
+
*/
|
|
13
|
+
export declare function configureStorage(env: StorageEnvironment): void;
|
|
14
|
+
/**
|
|
15
|
+
* Set Redis storage implementation for web server environments.
|
|
16
|
+
* This is required for caching in web server/serverless environments.
|
|
17
|
+
*
|
|
18
|
+
* @param storage - Redis storage implementation
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createClient } from 'redis';
|
|
23
|
+
* import { setRedisStorage, CacheStorage } from '@cryptoquant_official/mcp';
|
|
24
|
+
*
|
|
25
|
+
* const redis = createClient({ url: process.env.REDIS_URL });
|
|
26
|
+
* await redis.connect();
|
|
27
|
+
*
|
|
28
|
+
* setRedisStorage({
|
|
29
|
+
* type: 'redis',
|
|
30
|
+
* async read(apiUrl, apiKeyPrefix) {
|
|
31
|
+
* const key = `cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`;
|
|
32
|
+
* const data = await redis.get(key);
|
|
33
|
+
* return data ? JSON.parse(data) : null;
|
|
34
|
+
* },
|
|
35
|
+
* async write(apiUrl, cache) {
|
|
36
|
+
* const key = `cryptoquant:cache:${apiUrl}:${cache.metadata.api_key_prefix}`;
|
|
37
|
+
* const ttl = 7 * 24 * 60 * 60; // 7 days
|
|
38
|
+
* await redis.setEx(key, ttl, JSON.stringify(cache));
|
|
39
|
+
* },
|
|
40
|
+
* async invalidate(apiUrl, apiKeyPrefix) {
|
|
41
|
+
* if (apiKeyPrefix) {
|
|
42
|
+
* await redis.del(`cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`);
|
|
43
|
+
* } else {
|
|
44
|
+
* const keys = await redis.keys(`cryptoquant:cache:${apiUrl}:*`);
|
|
45
|
+
* if (keys.length > 0) await redis.del(keys);
|
|
46
|
+
* }
|
|
47
|
+
* },
|
|
48
|
+
* async clearAll() {
|
|
49
|
+
* const keys = await redis.keys('cryptoquant:cache:*');
|
|
50
|
+
* if (keys.length > 0) await redis.del(keys);
|
|
51
|
+
* },
|
|
52
|
+
* getPath() { return '[redis]'; }
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function setRedisStorage(storage: CacheStorage): void;
|
|
57
|
+
/**
|
|
58
|
+
* Clear Redis storage and revert to default behavior
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearRedisStorage(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Check if Redis storage is configured
|
|
63
|
+
*/
|
|
64
|
+
export declare function isRedisConfigured(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Get the current storage type
|
|
67
|
+
*/
|
|
68
|
+
export declare function getStorageType(): StorageEnvironment;
|
|
69
|
+
/**
|
|
70
|
+
* Get cache file path.
|
|
71
|
+
*/
|
|
72
|
+
export declare function getCacheFilePath(apiUrl: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Check if cache is still valid (not expired and version matches).
|
|
75
|
+
*/
|
|
76
|
+
export declare function isCacheValid(cache: DiscoveryCacheSchema, apiUrl: string, apiKeyPrefix: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Read cache from storage.
|
|
79
|
+
* Returns null if cache doesn't exist, is invalid, or storage is not configured.
|
|
80
|
+
*/
|
|
81
|
+
export declare function readCache(apiUrl: string, apiKeyPrefix?: string): Promise<DiscoveryCacheSchema | null>;
|
|
82
|
+
/**
|
|
83
|
+
* Write cache to storage.
|
|
84
|
+
*/
|
|
85
|
+
export declare function writeCache(apiUrl: string, apiKey: string, rawResponse: MyDiscoveryRawResponse, parsed: {
|
|
86
|
+
limits: PlanLimits | null;
|
|
87
|
+
statics: string[];
|
|
88
|
+
apiRateLimit: ApiRateLimit | null;
|
|
89
|
+
}, summary: DiscoverySummaryData, plan: UserPlan): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Delete cache for specific API URL.
|
|
92
|
+
*/
|
|
93
|
+
export declare function invalidateCache(apiUrl: string, apiKeyPrefix?: string): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Delete all caches.
|
|
96
|
+
*/
|
|
97
|
+
export declare function clearAllCaches(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Calculate cache age in days.
|
|
100
|
+
*/
|
|
101
|
+
export declare function getCacheAgeDays(cache: DiscoveryCacheSchema): number;
|
|
102
|
+
/**
|
|
103
|
+
* Get human-readable cache status string.
|
|
104
|
+
*/
|
|
105
|
+
export declare function getCacheStatus(cache: DiscoveryCacheSchema | null, fromCache: boolean): string;
|
|
106
|
+
/**
|
|
107
|
+
* Get cache directory path for user display.
|
|
108
|
+
*/
|
|
109
|
+
export declare function getCachePath(): string;
|
|
110
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/core/cache/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EAGxB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgM5E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,CAK9D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAG3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CAGnD;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAmBvG;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAI3G;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,sBAAsB,EACnC,MAAM,EAAE;IACN,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC,EACD,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAIpD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAKnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAM7F;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache storage operations for discovery response caching
|
|
3
|
+
* Supports file-based (CLI/local) and Redis-based (web server) storage
|
|
4
|
+
*/
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, chmodSync } from "fs";
|
|
8
|
+
import { CACHE_VERSION, CACHE_TTL_DAYS, } from "./types.js";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// FileStorage - for CLI and local development
|
|
11
|
+
// ============================================================================
|
|
12
|
+
class FileStorage {
|
|
13
|
+
type = "file";
|
|
14
|
+
cacheDir;
|
|
15
|
+
cacheFile;
|
|
16
|
+
constructor() {
|
|
17
|
+
this.cacheDir = join(homedir(), ".cryptoquant");
|
|
18
|
+
this.cacheFile = join(this.cacheDir, "discovery-cache.json");
|
|
19
|
+
}
|
|
20
|
+
read(_apiUrl, _apiKeyPrefix) {
|
|
21
|
+
// FileStorage uses single file - user isolation handled by isCacheValid()
|
|
22
|
+
try {
|
|
23
|
+
if (!existsSync(this.cacheFile)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const data = JSON.parse(readFileSync(this.cacheFile, "utf-8"));
|
|
27
|
+
// Basic structure validation
|
|
28
|
+
if (!data.version || !data.metadata || !data.raw_response || !data.summary) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
write(_apiUrl, cache) {
|
|
38
|
+
// Ensure directory exists
|
|
39
|
+
if (!existsSync(this.cacheDir)) {
|
|
40
|
+
mkdirSync(this.cacheDir, { recursive: true, mode: 0o700 });
|
|
41
|
+
}
|
|
42
|
+
writeFileSync(this.cacheFile, JSON.stringify(cache, null, 2), { encoding: "utf-8" });
|
|
43
|
+
// Set secure permissions (may fail on some platforms, that's ok)
|
|
44
|
+
try {
|
|
45
|
+
chmodSync(this.cacheFile, 0o600);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Ignore permission errors on platforms that don't support chmod
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
invalidate(_apiUrl, _apiKeyPrefix) {
|
|
52
|
+
try {
|
|
53
|
+
if (existsSync(this.cacheFile)) {
|
|
54
|
+
unlinkSync(this.cacheFile);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Already deleted or inaccessible
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
clearAll() {
|
|
62
|
+
this.invalidate("");
|
|
63
|
+
}
|
|
64
|
+
getPath(_apiUrl) {
|
|
65
|
+
return this.cacheFile;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// NullStorage - no-op storage for web server without Redis
|
|
70
|
+
// ============================================================================
|
|
71
|
+
class NullStorage {
|
|
72
|
+
type = "redis"; // Reports as redis (unconfigured)
|
|
73
|
+
read(_apiUrl, _apiKeyPrefix) {
|
|
74
|
+
return null; // Always cache miss
|
|
75
|
+
}
|
|
76
|
+
write(_apiUrl, _cache) {
|
|
77
|
+
// No-op
|
|
78
|
+
}
|
|
79
|
+
invalidate(_apiUrl, _apiKeyPrefix) {
|
|
80
|
+
// No-op
|
|
81
|
+
}
|
|
82
|
+
clearAll() {
|
|
83
|
+
// No-op
|
|
84
|
+
}
|
|
85
|
+
getPath(_apiUrl) {
|
|
86
|
+
return "[no cache - Redis not configured]";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Storage Factory and Configuration
|
|
91
|
+
// ============================================================================
|
|
92
|
+
let currentStorage = null;
|
|
93
|
+
let redisStorage = null;
|
|
94
|
+
let configuredEnvironment = "auto";
|
|
95
|
+
/**
|
|
96
|
+
* Check if running in a web server environment
|
|
97
|
+
*/
|
|
98
|
+
function isWebServerEnvironment() {
|
|
99
|
+
const isServerless = process.env.VERCEL ||
|
|
100
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
|
101
|
+
process.env.NETLIFY ||
|
|
102
|
+
process.env.CLOUDFLARE_WORKER;
|
|
103
|
+
const isWebServer = process.env.CRYPTOQUANT_STORAGE === "redis" || process.env.NODE_ENV === "production";
|
|
104
|
+
return !!(isServerless || isWebServer);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if file system is available
|
|
108
|
+
*/
|
|
109
|
+
function canUseFileSystem() {
|
|
110
|
+
try {
|
|
111
|
+
const home = homedir();
|
|
112
|
+
if (!home || typeof home !== "string" || home.length === 0) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
const testDir = join(home, ".cryptoquant");
|
|
116
|
+
return testDir.length > 0;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the cache storage instance (singleton per environment)
|
|
124
|
+
*/
|
|
125
|
+
function getStorage() {
|
|
126
|
+
// Redis storage takes priority when set
|
|
127
|
+
if (redisStorage) {
|
|
128
|
+
return redisStorage;
|
|
129
|
+
}
|
|
130
|
+
// If explicitly configured as redis but not set, return null storage
|
|
131
|
+
if (configuredEnvironment === "redis") {
|
|
132
|
+
if (!currentStorage || currentStorage.type !== "redis") {
|
|
133
|
+
currentStorage = new NullStorage();
|
|
134
|
+
}
|
|
135
|
+
return currentStorage;
|
|
136
|
+
}
|
|
137
|
+
// Auto-detect environment
|
|
138
|
+
if (configuredEnvironment === "auto") {
|
|
139
|
+
// Web server environment requires Redis
|
|
140
|
+
if (isWebServerEnvironment()) {
|
|
141
|
+
if (!currentStorage || currentStorage.type !== "redis") {
|
|
142
|
+
currentStorage = new NullStorage();
|
|
143
|
+
}
|
|
144
|
+
return currentStorage;
|
|
145
|
+
}
|
|
146
|
+
// Local environment uses file storage if available
|
|
147
|
+
if (canUseFileSystem()) {
|
|
148
|
+
if (!currentStorage || currentStorage.type !== "file") {
|
|
149
|
+
currentStorage = new FileStorage();
|
|
150
|
+
}
|
|
151
|
+
return currentStorage;
|
|
152
|
+
}
|
|
153
|
+
// Fallback to null storage
|
|
154
|
+
if (!currentStorage) {
|
|
155
|
+
currentStorage = new NullStorage();
|
|
156
|
+
}
|
|
157
|
+
return currentStorage;
|
|
158
|
+
}
|
|
159
|
+
// File storage
|
|
160
|
+
if (configuredEnvironment === "file") {
|
|
161
|
+
if (!currentStorage || currentStorage.type !== "file") {
|
|
162
|
+
currentStorage = new FileStorage();
|
|
163
|
+
}
|
|
164
|
+
return currentStorage;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Configure the storage environment.
|
|
170
|
+
* Call this before any cache operations to explicitly set the storage type.
|
|
171
|
+
*
|
|
172
|
+
* @param env - "file" for local/CLI, "redis" for web server, "auto" to detect
|
|
173
|
+
*/
|
|
174
|
+
export function configureStorage(env) {
|
|
175
|
+
if (currentStorage && configuredEnvironment !== env) {
|
|
176
|
+
currentStorage = null;
|
|
177
|
+
}
|
|
178
|
+
configuredEnvironment = env;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Set Redis storage implementation for web server environments.
|
|
182
|
+
* This is required for caching in web server/serverless environments.
|
|
183
|
+
*
|
|
184
|
+
* @param storage - Redis storage implementation
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* import { createClient } from 'redis';
|
|
189
|
+
* import { setRedisStorage, CacheStorage } from '@cryptoquant_official/mcp';
|
|
190
|
+
*
|
|
191
|
+
* const redis = createClient({ url: process.env.REDIS_URL });
|
|
192
|
+
* await redis.connect();
|
|
193
|
+
*
|
|
194
|
+
* setRedisStorage({
|
|
195
|
+
* type: 'redis',
|
|
196
|
+
* async read(apiUrl, apiKeyPrefix) {
|
|
197
|
+
* const key = `cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`;
|
|
198
|
+
* const data = await redis.get(key);
|
|
199
|
+
* return data ? JSON.parse(data) : null;
|
|
200
|
+
* },
|
|
201
|
+
* async write(apiUrl, cache) {
|
|
202
|
+
* const key = `cryptoquant:cache:${apiUrl}:${cache.metadata.api_key_prefix}`;
|
|
203
|
+
* const ttl = 7 * 24 * 60 * 60; // 7 days
|
|
204
|
+
* await redis.setEx(key, ttl, JSON.stringify(cache));
|
|
205
|
+
* },
|
|
206
|
+
* async invalidate(apiUrl, apiKeyPrefix) {
|
|
207
|
+
* if (apiKeyPrefix) {
|
|
208
|
+
* await redis.del(`cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`);
|
|
209
|
+
* } else {
|
|
210
|
+
* const keys = await redis.keys(`cryptoquant:cache:${apiUrl}:*`);
|
|
211
|
+
* if (keys.length > 0) await redis.del(keys);
|
|
212
|
+
* }
|
|
213
|
+
* },
|
|
214
|
+
* async clearAll() {
|
|
215
|
+
* const keys = await redis.keys('cryptoquant:cache:*');
|
|
216
|
+
* if (keys.length > 0) await redis.del(keys);
|
|
217
|
+
* },
|
|
218
|
+
* getPath() { return '[redis]'; }
|
|
219
|
+
* });
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export function setRedisStorage(storage) {
|
|
223
|
+
redisStorage = storage;
|
|
224
|
+
currentStorage = null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Clear Redis storage and revert to default behavior
|
|
228
|
+
*/
|
|
229
|
+
export function clearRedisStorage() {
|
|
230
|
+
redisStorage = null;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Check if Redis storage is configured
|
|
234
|
+
*/
|
|
235
|
+
export function isRedisConfigured() {
|
|
236
|
+
return redisStorage !== null;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get the current storage type
|
|
240
|
+
*/
|
|
241
|
+
export function getStorageType() {
|
|
242
|
+
const storage = getStorage();
|
|
243
|
+
return storage?.type ?? "redis";
|
|
244
|
+
}
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// Public API
|
|
247
|
+
// ============================================================================
|
|
248
|
+
/**
|
|
249
|
+
* Get cache file path.
|
|
250
|
+
*/
|
|
251
|
+
export function getCacheFilePath(apiUrl) {
|
|
252
|
+
const storage = getStorage();
|
|
253
|
+
return storage?.getPath(apiUrl) ?? "[no cache]";
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Check if cache is still valid (not expired and version matches).
|
|
257
|
+
*/
|
|
258
|
+
export function isCacheValid(cache, apiUrl, apiKeyPrefix) {
|
|
259
|
+
if (cache.version !== CACHE_VERSION) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
if (cache.metadata.api_url !== apiUrl) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
if (cache.metadata.api_key_prefix !== apiKeyPrefix) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
const expiresAt = new Date(cache.metadata.expires_at);
|
|
269
|
+
if (isNaN(expiresAt.getTime()) || expiresAt < new Date()) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Read cache from storage.
|
|
276
|
+
* Returns null if cache doesn't exist, is invalid, or storage is not configured.
|
|
277
|
+
*/
|
|
278
|
+
export async function readCache(apiUrl, apiKeyPrefix) {
|
|
279
|
+
const storage = getStorage();
|
|
280
|
+
if (!storage)
|
|
281
|
+
return null;
|
|
282
|
+
return storage.read(apiUrl, apiKeyPrefix);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Write cache to storage.
|
|
286
|
+
*/
|
|
287
|
+
export async function writeCache(apiUrl, apiKey, rawResponse, parsed, summary, plan) {
|
|
288
|
+
const storage = getStorage();
|
|
289
|
+
if (!storage)
|
|
290
|
+
return;
|
|
291
|
+
const now = new Date();
|
|
292
|
+
const expiresAt = new Date(now);
|
|
293
|
+
expiresAt.setDate(expiresAt.getDate() + CACHE_TTL_DAYS);
|
|
294
|
+
const cache = {
|
|
295
|
+
version: CACHE_VERSION,
|
|
296
|
+
metadata: {
|
|
297
|
+
api_url: apiUrl,
|
|
298
|
+
api_key_prefix: apiKey.slice(0, 8),
|
|
299
|
+
cached_at: now.toISOString(),
|
|
300
|
+
expires_at: expiresAt.toISOString(),
|
|
301
|
+
plan,
|
|
302
|
+
},
|
|
303
|
+
raw_response: rawResponse,
|
|
304
|
+
parsed,
|
|
305
|
+
summary,
|
|
306
|
+
};
|
|
307
|
+
await storage.write(apiUrl, cache);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Delete cache for specific API URL.
|
|
311
|
+
*/
|
|
312
|
+
export async function invalidateCache(apiUrl, apiKeyPrefix) {
|
|
313
|
+
const storage = getStorage();
|
|
314
|
+
if (!storage)
|
|
315
|
+
return;
|
|
316
|
+
await storage.invalidate(apiUrl, apiKeyPrefix);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Delete all caches.
|
|
320
|
+
*/
|
|
321
|
+
export async function clearAllCaches() {
|
|
322
|
+
const storage = getStorage();
|
|
323
|
+
if (!storage)
|
|
324
|
+
return;
|
|
325
|
+
await storage.clearAll();
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Calculate cache age in days.
|
|
329
|
+
*/
|
|
330
|
+
export function getCacheAgeDays(cache) {
|
|
331
|
+
const cachedAt = new Date(cache.metadata.cached_at);
|
|
332
|
+
const now = new Date();
|
|
333
|
+
const diffMs = now.getTime() - cachedAt.getTime();
|
|
334
|
+
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get human-readable cache status string.
|
|
338
|
+
*/
|
|
339
|
+
export function getCacheStatus(cache, fromCache) {
|
|
340
|
+
if (!fromCache || !cache) {
|
|
341
|
+
return "fresh";
|
|
342
|
+
}
|
|
343
|
+
const days = getCacheAgeDays(cache);
|
|
344
|
+
return `cached (${days}d old)`;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Get cache directory path for user display.
|
|
348
|
+
*/
|
|
349
|
+
export function getCachePath() {
|
|
350
|
+
const storage = getStorage();
|
|
351
|
+
if (!storage || storage.type === "redis") {
|
|
352
|
+
return isRedisConfigured() ? "[redis]" : "[no cache - Redis not configured]";
|
|
353
|
+
}
|
|
354
|
+
return join(homedir(), ".cryptoquant");
|
|
355
|
+
}
|
|
356
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/cache/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../../src/core/cache/summary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAiElG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,sBAAsB,GAAG,IAAI,CAqB/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/core/cache/summary.ts"],"names":[],"mappings":"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"}
|