agentvault 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dfx/local/network-id +4 -0
- package/.next/trace +2 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/PLAN_VAULT_INTEGRATION.md +318 -0
- package/README.md +253 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
- package/backups/test-backup.json +28 -0
- package/dist/cli/commands/approve.d.ts +4 -0
- package/dist/cli/commands/approve.js +232 -0
- package/dist/cli/commands/archive.d.ts +4 -0
- package/dist/cli/commands/archive.js +192 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.js +164 -0
- package/dist/cli/commands/cloud-backup.d.ts +4 -0
- package/dist/cli/commands/cloud-backup.js +221 -0
- package/dist/cli/commands/cycles.d.ts +8 -0
- package/dist/cli/commands/cycles.js +83 -0
- package/dist/cli/commands/decrypt.d.ts +16 -0
- package/dist/cli/commands/decrypt.js +101 -0
- package/dist/cli/commands/deploy.d.ts +32 -0
- package/dist/cli/commands/deploy.js +208 -0
- package/dist/cli/commands/exec.d.ts +26 -0
- package/dist/cli/commands/exec.js +109 -0
- package/dist/cli/commands/fetch.d.ts +23 -0
- package/dist/cli/commands/fetch.js +164 -0
- package/dist/cli/commands/health.d.ts +8 -0
- package/dist/cli/commands/health.js +72 -0
- package/dist/cli/commands/identity.d.ts +8 -0
- package/dist/cli/commands/identity.js +140 -0
- package/dist/cli/commands/inference.d.ts +4 -0
- package/dist/cli/commands/inference.js +225 -0
- package/dist/cli/commands/info.d.ts +8 -0
- package/dist/cli/commands/info.js +59 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.js +135 -0
- package/dist/cli/commands/instrument.d.ts +8 -0
- package/dist/cli/commands/instrument.js +35 -0
- package/dist/cli/commands/list.d.ts +36 -0
- package/dist/cli/commands/list.js +173 -0
- package/dist/cli/commands/logs.d.ts +8 -0
- package/dist/cli/commands/logs.js +96 -0
- package/dist/cli/commands/monitor.d.ts +8 -0
- package/dist/cli/commands/monitor.js +84 -0
- package/dist/cli/commands/network.d.ts +14 -0
- package/dist/cli/commands/network.js +258 -0
- package/dist/cli/commands/package.d.ts +36 -0
- package/dist/cli/commands/package.js +188 -0
- package/dist/cli/commands/profile.d.ts +8 -0
- package/dist/cli/commands/profile.js +76 -0
- package/dist/cli/commands/promote.d.ts +8 -0
- package/dist/cli/commands/promote.js +89 -0
- package/dist/cli/commands/rebuild.d.ts +21 -0
- package/dist/cli/commands/rebuild.js +140 -0
- package/dist/cli/commands/rollback.d.ts +8 -0
- package/dist/cli/commands/rollback.js +120 -0
- package/dist/cli/commands/show.d.ts +36 -0
- package/dist/cli/commands/show.js +200 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.js +34 -0
- package/dist/cli/commands/status.d.ts +14 -0
- package/dist/cli/commands/status.js +83 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +109 -0
- package/dist/cli/commands/tokens.d.ts +8 -0
- package/dist/cli/commands/tokens.js +62 -0
- package/dist/cli/commands/trace.d.ts +8 -0
- package/dist/cli/commands/trace.js +68 -0
- package/dist/cli/commands/wallet-export.d.ts +13 -0
- package/dist/cli/commands/wallet-export.js +140 -0
- package/dist/cli/commands/wallet-history.d.ts +10 -0
- package/dist/cli/commands/wallet-history.js +127 -0
- package/dist/cli/commands/wallet-import.d.ts +10 -0
- package/dist/cli/commands/wallet-import.js +209 -0
- package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
- package/dist/cli/commands/wallet-multi-send.js +195 -0
- package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
- package/dist/cli/commands/wallet-process-queue.js +209 -0
- package/dist/cli/commands/wallet-sign.d.ts +13 -0
- package/dist/cli/commands/wallet-sign.js +207 -0
- package/dist/cli/commands/wallet.d.ts +12 -0
- package/dist/cli/commands/wallet.js +794 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +96 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.js +14 -0
- package/fixup_1_0_OSS_release.md +136 -0
- package/fixup_REALEASE_PRD.md +136 -0
- package/package.json +79 -0
- package/pnpm-workspace.yaml +5 -0
- package/scripts/dev-dashboard.mjs +84 -0
- package/site/README.md +63 -0
- package/site/docusaurus.config.ts +148 -0
- package/site/package-lock.json +18383 -0
- package/site/package.json +47 -0
- package/site/sidebars.ts +86 -0
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +28 -0
- package/site/static/img/og-image.svg +35 -0
- package/src/archival/archive-manager.ts +372 -0
- package/src/archival/arweave-client.ts +289 -0
- package/src/archival/index.ts +8 -0
- package/src/backup/backup.ts +315 -0
- package/src/backup/index.ts +7 -0
- package/src/cloud-storage/cloud-sync.ts +461 -0
- package/src/cloud-storage/index.ts +11 -0
- package/src/cloud-storage/provider-detector.ts +198 -0
- package/src/cloud-storage/types.ts +104 -0
- package/src/debugging/index.ts +6 -0
- package/src/debugging/logs.ts +193 -0
- package/src/debugging/types.ts +100 -0
- package/src/deployment/deployer.ts +274 -0
- package/src/deployment/icpClient.ts +620 -0
- package/src/deployment/index.ts +46 -0
- package/src/deployment/promotion.ts +161 -0
- package/src/deployment/types.ts +111 -0
- package/src/icp/batch.ts +374 -0
- package/src/icp/cycles.ts +50 -0
- package/src/icp/environment.ts +215 -0
- package/src/icp/icpcli.ts +438 -0
- package/src/icp/icwasm.ts +222 -0
- package/src/icp/identity.ts +77 -0
- package/src/icp/index.ts +94 -0
- package/src/icp/optimization.ts +242 -0
- package/src/icp/tokens.ts +36 -0
- package/src/icp/tool-detector.ts +110 -0
- package/src/icp/types.ts +574 -0
- package/src/index.ts +25 -0
- package/src/inference/bittensor-client.ts +304 -0
- package/src/inference/index.ts +8 -0
- package/src/inference/inference-manager.ts +327 -0
- package/src/metrics/index.ts +7 -0
- package/src/metrics/metrics.ts +186 -0
- package/src/monitoring/alerting.ts +190 -0
- package/src/monitoring/health.ts +197 -0
- package/src/monitoring/index.ts +38 -0
- package/src/monitoring/info.ts +114 -0
- package/src/monitoring/types.ts +99 -0
- package/src/network/index.ts +5 -0
- package/src/network/network-config.ts +129 -0
- package/src/packaging/compiler.ts +647 -0
- package/src/packaging/config-persistence.ts +135 -0
- package/src/packaging/config-schemas.ts +156 -0
- package/src/packaging/detector.ts +220 -0
- package/src/packaging/index.ts +90 -0
- package/src/packaging/packager.ts +118 -0
- package/src/packaging/parsers/clawdbot.ts +278 -0
- package/src/packaging/parsers/cline.ts +223 -0
- package/src/packaging/parsers/generic.ts +266 -0
- package/src/packaging/parsers/goose.ts +214 -0
- package/src/packaging/parsers/index.ts +11 -0
- package/src/packaging/serializer.ts +260 -0
- package/src/packaging/types.ts +144 -0
- package/src/packaging/wasmedge-compiler.ts +406 -0
- package/src/security/index.ts +17 -0
- package/src/security/multisig.ts +415 -0
- package/src/security/types.ts +416 -0
- package/src/security/vetkeys.ts +655 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/local-runner.ts +264 -0
- package/src/testing/types.ts +104 -0
- package/src/wallet/cbor-serializer.ts +323 -0
- package/src/wallet/chain-dispatcher.ts +313 -0
- package/src/wallet/cross-chain-aggregator.ts +346 -0
- package/src/wallet/index.ts +76 -0
- package/src/wallet/key-derivation.ts +425 -0
- package/src/wallet/providers/base-provider.ts +154 -0
- package/src/wallet/providers/cketh-provider.ts +434 -0
- package/src/wallet/providers/polkadot-provider.ts +503 -0
- package/src/wallet/providers/solana-provider.ts +490 -0
- package/src/wallet/transaction-queue.ts +284 -0
- package/src/wallet/types.ts +178 -0
- package/src/wallet/vetkeys-adapter.ts +431 -0
- package/src/wallet/wallet-manager.ts +597 -0
- package/src/wallet/wallet-storage.ts +380 -0
- package/vercel.json +8 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bittensor Client
|
|
3
|
+
*
|
|
4
|
+
* Handles interaction with Bittensor network for AI inference queries.
|
|
5
|
+
* Supports subnet discovery, module queries, and response handling.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export interface BittensorConfig {
|
|
11
|
+
apiEndpoint?: string;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SubnetInfo {
|
|
17
|
+
netuid: number;
|
|
18
|
+
name: string;
|
|
19
|
+
founder: string;
|
|
20
|
+
tempo: number;
|
|
21
|
+
modality: string;
|
|
22
|
+
registered: number;
|
|
23
|
+
last_emit_block: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ModuleInfo {
|
|
27
|
+
uid: number;
|
|
28
|
+
name: string;
|
|
29
|
+
address: string;
|
|
30
|
+
stake: number;
|
|
31
|
+
dividend: number;
|
|
32
|
+
emission: number;
|
|
33
|
+
incentive: number;
|
|
34
|
+
consensus: number;
|
|
35
|
+
trust: number;
|
|
36
|
+
rank: number;
|
|
37
|
+
validator_permit: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface InferenceRequest {
|
|
41
|
+
netuid: number;
|
|
42
|
+
uid?: number;
|
|
43
|
+
inputs: Record<string, any>;
|
|
44
|
+
timeout?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface InferenceResponse {
|
|
48
|
+
success: boolean;
|
|
49
|
+
data?: Record<string, any>;
|
|
50
|
+
metadata?: {
|
|
51
|
+
uid: number;
|
|
52
|
+
name: string;
|
|
53
|
+
netuid: number;
|
|
54
|
+
responseTime: number;
|
|
55
|
+
};
|
|
56
|
+
error?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class BittensorClient {
|
|
60
|
+
private config: Required<BittensorConfig>;
|
|
61
|
+
private axiosInstance: any = null;
|
|
62
|
+
|
|
63
|
+
constructor(config: BittensorConfig = {}) {
|
|
64
|
+
this.config = {
|
|
65
|
+
apiEndpoint: config.apiEndpoint || 'https://api.bittensor.com',
|
|
66
|
+
timeout: config.timeout || 30000,
|
|
67
|
+
apiKey: config.apiKey || '',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Initialize HTTP client (lazy loading)
|
|
73
|
+
*/
|
|
74
|
+
private async getClient(): Promise<any> {
|
|
75
|
+
if (!this.axiosInstance) {
|
|
76
|
+
const axios = await this.importAxios();
|
|
77
|
+
this.axiosInstance = axios.create({
|
|
78
|
+
baseURL: this.config.apiEndpoint,
|
|
79
|
+
timeout: this.config.timeout,
|
|
80
|
+
headers: {
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
...(this.config.apiKey && { 'X-API-Key': this.config.apiKey }),
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return this.axiosInstance;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Dynamically import axios (optional dependency)
|
|
91
|
+
*/
|
|
92
|
+
private async importAxios(): Promise<any> {
|
|
93
|
+
try {
|
|
94
|
+
const dynamicImport = new Function('modulePath', 'return import(modulePath)') as (
|
|
95
|
+
modulePath: string
|
|
96
|
+
) => Promise<{ default: any }>;
|
|
97
|
+
const axiosModule = await dynamicImport('axios');
|
|
98
|
+
return axiosModule.default;
|
|
99
|
+
} catch (_error) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
'axios is required for BittensorClient. Install with: npm install axios',
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get all subnets
|
|
108
|
+
*/
|
|
109
|
+
async getSubnets(): Promise<SubnetInfo[]> {
|
|
110
|
+
try {
|
|
111
|
+
const client = await this.getClient();
|
|
112
|
+
const response = await client.get('/subnets');
|
|
113
|
+
|
|
114
|
+
return response.data.subnets || [];
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('Failed to fetch subnets:', error);
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get subnet by ID
|
|
123
|
+
*/
|
|
124
|
+
async getSubnet(netuid: number): Promise<SubnetInfo | null> {
|
|
125
|
+
try {
|
|
126
|
+
const subnets = await this.getSubnets();
|
|
127
|
+
return subnets.find((s) => s.netuid === netuid) || null;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error(`Failed to fetch subnet ${netuid}:`, error);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get modules for a subnet
|
|
136
|
+
*/
|
|
137
|
+
async getModules(netuid: number): Promise<ModuleInfo[]> {
|
|
138
|
+
try {
|
|
139
|
+
const client = await this.getClient();
|
|
140
|
+
const response = await client.get(`/subnets/${netuid}/modules`);
|
|
141
|
+
|
|
142
|
+
return response.data.modules || [];
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error(`Failed to fetch modules for subnet ${netuid}:`, error);
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get module by UID
|
|
151
|
+
*/
|
|
152
|
+
async getModule(netuid: number, uid: number): Promise<ModuleInfo | null> {
|
|
153
|
+
try {
|
|
154
|
+
const modules = await this.getModules(netuid);
|
|
155
|
+
return modules.find((m) => m.uid === uid) || null;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(`Failed to fetch module ${netuid}/${uid}:`, error);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Send inference request
|
|
164
|
+
*/
|
|
165
|
+
async infer(request: InferenceRequest): Promise<InferenceResponse> {
|
|
166
|
+
const startTime = Date.now();
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const client = await this.getClient();
|
|
170
|
+
const response = await client.post(`/subnets/${request.netuid}/infer`, {
|
|
171
|
+
uid: request.uid,
|
|
172
|
+
inputs: request.inputs,
|
|
173
|
+
timeout: request.timeout || this.config.timeout,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const responseTime = Date.now() - startTime;
|
|
177
|
+
|
|
178
|
+
if (response.data.success) {
|
|
179
|
+
return {
|
|
180
|
+
success: true,
|
|
181
|
+
data: response.data.output,
|
|
182
|
+
metadata: {
|
|
183
|
+
uid: response.data.uid,
|
|
184
|
+
name: response.data.name,
|
|
185
|
+
netuid: request.netuid,
|
|
186
|
+
responseTime,
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
} else {
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: response.data.error || 'Inference failed',
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
return {
|
|
197
|
+
success: false,
|
|
198
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Find best module for a subnet
|
|
205
|
+
*/
|
|
206
|
+
async findBestModule(
|
|
207
|
+
netuid: number,
|
|
208
|
+
criteria: 'stake' | 'trust' | 'rank' | 'consensus' = 'rank',
|
|
209
|
+
): Promise<ModuleInfo | null> {
|
|
210
|
+
try {
|
|
211
|
+
const modules = await this.getModules(netuid);
|
|
212
|
+
if (modules.length === 0) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return modules
|
|
217
|
+
.sort((a, b) => b[criteria] - a[criteria])
|
|
218
|
+
.slice(0, 1)[0] || null;
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error('Failed to find best module:', error);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Batch inference to multiple modules
|
|
227
|
+
*/
|
|
228
|
+
async batchInfer(
|
|
229
|
+
request: InferenceRequest,
|
|
230
|
+
limit: number = 5,
|
|
231
|
+
): Promise<InferenceResponse[]> {
|
|
232
|
+
try {
|
|
233
|
+
const modules = await this.getModules(request.netuid);
|
|
234
|
+
const topModules = modules
|
|
235
|
+
.sort((a, b) => b.rank - a.rank)
|
|
236
|
+
.slice(0, limit);
|
|
237
|
+
|
|
238
|
+
const promises = topModules.map((module) =>
|
|
239
|
+
this.infer({ ...request, uid: module.uid }),
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
return Promise.all(promises);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error('Failed to batch infer:', error);
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Health check for subnet
|
|
251
|
+
*/
|
|
252
|
+
async checkSubnetHealth(netuid: number): Promise<{
|
|
253
|
+
healthy: boolean;
|
|
254
|
+
moduleCount: number;
|
|
255
|
+
avgResponseTime: number;
|
|
256
|
+
}> {
|
|
257
|
+
const startTime = Date.now();
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
const modules = await this.getModules(netuid);
|
|
261
|
+
if (modules.length === 0) {
|
|
262
|
+
return {
|
|
263
|
+
healthy: false,
|
|
264
|
+
moduleCount: 0,
|
|
265
|
+
avgResponseTime: 0,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const responseTime = Date.now() - startTime;
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
healthy: true,
|
|
273
|
+
moduleCount: modules.length,
|
|
274
|
+
avgResponseTime: responseTime,
|
|
275
|
+
};
|
|
276
|
+
} catch (_error) {
|
|
277
|
+
return {
|
|
278
|
+
healthy: false,
|
|
279
|
+
moduleCount: 0,
|
|
280
|
+
avgResponseTime: 0,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Get API status
|
|
287
|
+
*/
|
|
288
|
+
async getApiStatus(): Promise<{ online: boolean; version?: string; error?: string }> {
|
|
289
|
+
try {
|
|
290
|
+
const client = await this.getClient();
|
|
291
|
+
const response = await client.get('/status');
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
online: response.data.online || false,
|
|
295
|
+
version: response.data.version,
|
|
296
|
+
};
|
|
297
|
+
} catch (error) {
|
|
298
|
+
return {
|
|
299
|
+
online: false,
|
|
300
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inference Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages AI inference requests through Bittensor network.
|
|
5
|
+
* Handles caching, rate limiting, and result aggregation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import crypto from 'node:crypto';
|
|
12
|
+
|
|
13
|
+
const AGENTVAULT_DIR = path.join(os.homedir(), '.agentvault');
|
|
14
|
+
const INFERENCE_CACHE_DIR = path.join(AGENTVAULT_DIR, 'inference-cache');
|
|
15
|
+
|
|
16
|
+
export interface InferenceConfig {
|
|
17
|
+
netuid: number;
|
|
18
|
+
uid?: number;
|
|
19
|
+
batchSize?: number;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
cacheTTL?: number;
|
|
22
|
+
enableCache?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface InferenceResult {
|
|
26
|
+
success: boolean;
|
|
27
|
+
data?: any;
|
|
28
|
+
metadata?: {
|
|
29
|
+
netuid: number;
|
|
30
|
+
uid: number;
|
|
31
|
+
timestamp: Date;
|
|
32
|
+
responseTime: number;
|
|
33
|
+
};
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface CachedInference {
|
|
38
|
+
key: string;
|
|
39
|
+
request: any;
|
|
40
|
+
result: any;
|
|
41
|
+
timestamp: Date;
|
|
42
|
+
expiresAt: Date;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function ensureCacheDir(): void {
|
|
46
|
+
if (!fs.existsSync(AGENTVAULT_DIR)) {
|
|
47
|
+
fs.mkdirSync(AGENTVAULT_DIR, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
if (!fs.existsSync(INFERENCE_CACHE_DIR)) {
|
|
50
|
+
fs.mkdirSync(INFERENCE_CACHE_DIR, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function generateCacheKey(
|
|
55
|
+
netuid: number,
|
|
56
|
+
inputs: Record<string, any>,
|
|
57
|
+
): string {
|
|
58
|
+
const sortedInputs = JSON.stringify(inputs, Object.keys(inputs).sort());
|
|
59
|
+
return `inference-${netuid}-${crypto.createHash('sha256').update(sortedInputs).digest('hex')}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getCacheFilePath(key: string): string {
|
|
63
|
+
ensureCacheDir();
|
|
64
|
+
return path.join(INFERENCE_CACHE_DIR, `${key}.json`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get cached inference result
|
|
69
|
+
*/
|
|
70
|
+
export function getCachedInference(
|
|
71
|
+
netuid: number,
|
|
72
|
+
inputs: Record<string, any>,
|
|
73
|
+
_ttlMs: number = 3600000,
|
|
74
|
+
): CachedInference | null {
|
|
75
|
+
try {
|
|
76
|
+
const key = generateCacheKey(netuid, inputs);
|
|
77
|
+
const cachePath = getCacheFilePath(key);
|
|
78
|
+
|
|
79
|
+
if (!fs.existsSync(cachePath)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const content = fs.readFileSync(cachePath, 'utf8');
|
|
84
|
+
const cached: CachedInference = JSON.parse(content);
|
|
85
|
+
|
|
86
|
+
if (new Date(cached.expiresAt) < new Date()) {
|
|
87
|
+
fs.unlinkSync(cachePath);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return cached;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('Failed to get cached inference:', error);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Set cached inference result
|
|
100
|
+
*/
|
|
101
|
+
export function setCachedInference(
|
|
102
|
+
netuid: number,
|
|
103
|
+
inputs: Record<string, any>,
|
|
104
|
+
result: any,
|
|
105
|
+
ttlMs: number = 3600000,
|
|
106
|
+
): void {
|
|
107
|
+
try {
|
|
108
|
+
const key = generateCacheKey(netuid, inputs);
|
|
109
|
+
const cachePath = getCacheFilePath(key);
|
|
110
|
+
|
|
111
|
+
const now = new Date();
|
|
112
|
+
const cached: CachedInference = {
|
|
113
|
+
key,
|
|
114
|
+
request: inputs,
|
|
115
|
+
result,
|
|
116
|
+
timestamp: now,
|
|
117
|
+
expiresAt: new Date(now.getTime() + ttlMs),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
fs.writeFileSync(cachePath, JSON.stringify(cached), 'utf8');
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('Failed to cache inference:', error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Clear all cached inferences
|
|
128
|
+
*/
|
|
129
|
+
export function clearCache(): void {
|
|
130
|
+
try {
|
|
131
|
+
ensureCacheDir();
|
|
132
|
+
const files = fs.readdirSync(INFERENCE_CACHE_DIR);
|
|
133
|
+
|
|
134
|
+
for (const file of files) {
|
|
135
|
+
if (file.endsWith('.json')) {
|
|
136
|
+
const filePath = path.join(INFERENCE_CACHE_DIR, file);
|
|
137
|
+
fs.unlinkSync(filePath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('Failed to clear cache:', error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Clear expired cached inferences
|
|
147
|
+
*/
|
|
148
|
+
export function clearExpiredCache(): number {
|
|
149
|
+
let cleared = 0;
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
ensureCacheDir();
|
|
153
|
+
const files = fs.readdirSync(INFERENCE_CACHE_DIR);
|
|
154
|
+
const now = new Date();
|
|
155
|
+
|
|
156
|
+
for (const file of files) {
|
|
157
|
+
if (file.endsWith('.json')) {
|
|
158
|
+
const filePath = path.join(INFERENCE_CACHE_DIR, file);
|
|
159
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
160
|
+
const cached: CachedInference = JSON.parse(content);
|
|
161
|
+
|
|
162
|
+
if (new Date(cached.expiresAt) < now) {
|
|
163
|
+
fs.unlinkSync(filePath);
|
|
164
|
+
cleared++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error('Failed to clear expired cache:', error);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return cleared;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get cache statistics
|
|
177
|
+
*/
|
|
178
|
+
export function getCacheStats(): {
|
|
179
|
+
total: number;
|
|
180
|
+
expired: number;
|
|
181
|
+
sizeBytes: number;
|
|
182
|
+
} {
|
|
183
|
+
try {
|
|
184
|
+
ensureCacheDir();
|
|
185
|
+
const files = fs.readdirSync(INFERENCE_CACHE_DIR);
|
|
186
|
+
const now = new Date();
|
|
187
|
+
let expired = 0;
|
|
188
|
+
let sizeBytes = 0;
|
|
189
|
+
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
if (file.endsWith('.json')) {
|
|
192
|
+
const filePath = path.join(INFERENCE_CACHE_DIR, file);
|
|
193
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
194
|
+
const cached: CachedInference = JSON.parse(content);
|
|
195
|
+
|
|
196
|
+
if (new Date(cached.expiresAt) < now) {
|
|
197
|
+
expired++;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
sizeBytes += Buffer.byteLength(content);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
total: files.length,
|
|
206
|
+
expired,
|
|
207
|
+
sizeBytes,
|
|
208
|
+
};
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Failed to get cache stats:', error);
|
|
211
|
+
return { total: 0, expired: 0, sizeBytes: 0 };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Aggregate multiple inference results
|
|
217
|
+
*/
|
|
218
|
+
export function aggregateResults(
|
|
219
|
+
results: InferenceResult[],
|
|
220
|
+
method: 'average' | 'majority' | 'first' = 'majority',
|
|
221
|
+
): any {
|
|
222
|
+
if (results.length === 0) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (results.length === 1) {
|
|
227
|
+
return results[0]?.data || null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const validResults = results.filter((r) => r.success && r.data);
|
|
231
|
+
|
|
232
|
+
if (validResults.length === 0) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const firstResult = validResults[0];
|
|
237
|
+
if (!firstResult) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
switch (method) {
|
|
242
|
+
case 'first':
|
|
243
|
+
return firstResult.data;
|
|
244
|
+
|
|
245
|
+
case 'average':
|
|
246
|
+
if (typeof firstResult.data === 'number') {
|
|
247
|
+
return (
|
|
248
|
+
validResults.reduce((sum: number, r: any) => sum + (r.data as number), 0) / validResults.length
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
return firstResult.data;
|
|
252
|
+
|
|
253
|
+
case 'majority':
|
|
254
|
+
default: {
|
|
255
|
+
const counts = new Map<string, number>();
|
|
256
|
+
|
|
257
|
+
for (const result of validResults) {
|
|
258
|
+
const key = JSON.stringify(result.data);
|
|
259
|
+
counts.set(key, (counts.get(key) || 0) + 1);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let maxCount = 0;
|
|
263
|
+
let majorityResult: any = null;
|
|
264
|
+
|
|
265
|
+
for (const [key, count] of counts.entries()) {
|
|
266
|
+
if (count > maxCount) {
|
|
267
|
+
maxCount = count;
|
|
268
|
+
majorityResult = JSON.parse(key);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return majorityResult;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Format inference time
|
|
279
|
+
*/
|
|
280
|
+
export function formatInferenceTime(ms: number): string {
|
|
281
|
+
if (ms < 1000) {
|
|
282
|
+
return `${ms.toFixed(0)}ms`;
|
|
283
|
+
}
|
|
284
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get inference statistics
|
|
289
|
+
*/
|
|
290
|
+
export interface InferenceStats {
|
|
291
|
+
total: number;
|
|
292
|
+
success: number;
|
|
293
|
+
failed: number;
|
|
294
|
+
cached: number;
|
|
295
|
+
avgResponseTime: number;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function getInferenceStats(
|
|
299
|
+
history: InferenceResult[],
|
|
300
|
+
): InferenceStats {
|
|
301
|
+
if (history.length === 0) {
|
|
302
|
+
return {
|
|
303
|
+
total: 0,
|
|
304
|
+
success: 0,
|
|
305
|
+
failed: 0,
|
|
306
|
+
cached: 0,
|
|
307
|
+
avgResponseTime: 0,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const success = history.filter((r) => r.success).length;
|
|
312
|
+
const cached = history.filter((r) => r.success && r.metadata !== undefined).length;
|
|
313
|
+
const responseTimes = history
|
|
314
|
+
.filter((r) => r.metadata)
|
|
315
|
+
.map((r) => r.metadata!.responseTime);
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
total: history.length,
|
|
319
|
+
success,
|
|
320
|
+
failed: history.length - success,
|
|
321
|
+
cached,
|
|
322
|
+
avgResponseTime:
|
|
323
|
+
responseTimes.length > 0
|
|
324
|
+
? responseTimes.reduce((sum: number, t: number) => sum + t, 0) / responseTimes.length
|
|
325
|
+
: 0,
|
|
326
|
+
};
|
|
327
|
+
}
|