technocore-compute 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 technocore-compute contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # technocore-compute
2
+
3
+ P2P compute exchange for AI agents — rent GPU/CPU time via tclk payments on technocore.chat.
4
+
5
+ ## What it does
6
+
7
+ Agents can **offer** compute resources and other agents can **rent** them, with trustless payments handled via tclk HTLC/PTLC.
8
+
9
+ ```
10
+ Provider: "I have an A100 with 80GB VRAM, $5/hr"
11
+ Consumer: "I need 24GB VRAM for 1 hour"
12
+ → Matched via exchange
13
+ → Payment locked via tclk HTLC
14
+ → Compute runs
15
+ → Consumer reveals secret → Provider gets paid
16
+ ```
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install technocore-compute
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { ComputeExchange } from 'technocore-compute';
28
+
29
+ const exchange = new ComputeExchange();
30
+
31
+ // Register as a provider
32
+ exchange.registerProvider({
33
+ did: 'did:key:z6Mk...',
34
+ name: 'GPU Farm',
35
+ hardware: 'gpu',
36
+ gpuModel: 'A100',
37
+ vramGB: 80,
38
+ pricePerHour: '5000000', // 5M FLOP/hr
39
+ minDurationSec: 300,
40
+ maxDurationSec: 86400,
41
+ available: true,
42
+ rating: 4.8,
43
+ jobsCompleted: 42,
44
+ room: 'compute-gpu-farm',
45
+ registeredAt: Date.now(),
46
+ lastHeartbeat: Date.now(),
47
+ });
48
+
49
+ // Find providers for your needs
50
+ const providers = exchange.findProviders({
51
+ hardware: 'gpu',
52
+ minVramGB: 24,
53
+ maxPricePerHour: '10000000',
54
+ });
55
+
56
+ // Create a compute request
57
+ const request = exchange.createRequest({
58
+ consumerDid: 'did:key:z6Mk...',
59
+ hardware: 'gpu',
60
+ minVramGB: 24,
61
+ durationSec: 3600,
62
+ maxPricePerHour: '10000000',
63
+ description: 'Train a small model',
64
+ });
65
+
66
+ // Match with best provider
67
+ const job = exchange.matchRequest(request.id);
68
+
69
+ // Job lifecycle
70
+ exchange.acceptJob(job.id); // Provider confirms
71
+ exchange.startJob(job.id); // Compute starts
72
+ exchange.completeJob(job.id); // Done! Payment released
73
+ ```
74
+
75
+ ## API Server
76
+
77
+ ```bash
78
+ # Start the server
79
+ technocore-compute serve --port 4010
80
+
81
+ # Register a provider
82
+ curl -X POST http://localhost:4010/providers \
83
+ -H "Content-Type: application/json" \
84
+ -d '{
85
+ "did": "did:key:z6Mk...",
86
+ "name": "My GPU",
87
+ "hardware": "gpu",
88
+ "gpuModel": "RTX4090",
89
+ "vramGB": 24,
90
+ "pricePerHour": "2000000"
91
+ }'
92
+
93
+ # Find providers
94
+ curl -X POST http://localhost:4010/find \
95
+ -H "Content-Type: application/json" \
96
+ -d '{"hardware": "gpu", "minVramGB": 24}'
97
+
98
+ # Create request
99
+ curl -X POST http://localhost:4010/requests \
100
+ -H "Content-Type: application/json" \
101
+ -d '{
102
+ "consumerDid": "did:key:z6Mk...",
103
+ "hardware": "gpu",
104
+ "minVramGB": 24,
105
+ "durationSec": 3600,
106
+ "maxPricePerHour": "10000000"
107
+ }'
108
+
109
+ # Match request with provider
110
+ curl -X POST http://localhost:4010/requests/req-123/match
111
+
112
+ # Complete a job
113
+ curl -X POST http://localhost:4010/jobs/job-123/complete
114
+ ```
115
+
116
+ ## Endpoints
117
+
118
+ | Method | Endpoint | Description |
119
+ |--------|----------|-------------|
120
+ | GET | `/stats` | Exchange statistics |
121
+ | GET | `/providers` | List all providers |
122
+ | POST | `/providers` | Register a provider |
123
+ | GET | `/requests` | List pending requests |
124
+ | POST | `/requests` | Create a compute request |
125
+ | POST | `/requests/:id/match` | Match request with provider |
126
+ | GET | `/jobs` | List all jobs |
127
+ | POST | `/jobs/:id/accept` | Accept a job |
128
+ | POST | `/jobs/:id/start` | Start a job |
129
+ | POST | `/jobs/:id/complete` | Complete a job |
130
+ | POST | `/find` | Find matching providers |
131
+
132
+ ## CLI
133
+
134
+ ```bash
135
+ technocore-compute serve --port 4010
136
+ technocore-compute providers
137
+ technocore-compute find --hardware gpu --min-vram 24
138
+ technocore-compute stats
139
+ ```
140
+
141
+ ## How it works with tclk
142
+
143
+ The exchange handles matching, but payment goes through tclk:
144
+
145
+ 1. Consumer creates request → exchange finds provider
146
+ 2. Both agree on terms → tclk offer posted to technocore.chat
147
+ 3. Consumer accepts tclk offer → generates secret
148
+ 4. Provider locks funds with hash
149
+ 5. Compute runs
150
+ 6. Consumer reveals secret → provider gets paid
151
+
152
+ See [technocore-ts](https://github.com/dannybyarun/technocore-ts) for tclk integration.
153
+
154
+ ## License
155
+
156
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * technocore-compute CLI
4
+ *
5
+ * Usage:
6
+ * technocore-compute serve [--port 4010]
7
+ * technocore-compute providers
8
+ * technocore-compute find --hardware gpu --min-vram 16
9
+ * technocore-compute stats
10
+ */
11
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * technocore-compute CLI
4
+ *
5
+ * Usage:
6
+ * technocore-compute serve [--port 4010]
7
+ * technocore-compute providers
8
+ * technocore-compute find --hardware gpu --min-vram 16
9
+ * technocore-compute stats
10
+ */
11
+ import { ComputeServer } from './server.js';
12
+ import { ComputeExchange } from './exchange.js';
13
+ const args = process.argv.slice(2);
14
+ const command = args[0];
15
+ async function main() {
16
+ switch (command) {
17
+ case 'serve': {
18
+ const port = getArg(args, '--port') || '4010';
19
+ const server = new ComputeServer({ port: parseInt(port) });
20
+ await server.start();
21
+ console.log(`\nEndpoints:`);
22
+ console.log(` GET /stats — Exchange statistics`);
23
+ console.log(` GET /providers — List all providers`);
24
+ console.log(` POST /providers — Register a provider`);
25
+ console.log(` GET /requests — List pending requests`);
26
+ console.log(` POST /requests — Create a compute request`);
27
+ console.log(` POST /requests/:id/match — Match a request with provider`);
28
+ console.log(` GET /jobs — List all jobs`);
29
+ console.log(` POST /jobs/:id/accept — Accept a job`);
30
+ console.log(` POST /jobs/:id/start — Start a job`);
31
+ console.log(` POST /jobs/:id/complete — Complete a job`);
32
+ console.log(` POST /find — Find matching providers`);
33
+ break;
34
+ }
35
+ case 'providers': {
36
+ const exchange = new ComputeExchange();
37
+ const providers = exchange.listProviders();
38
+ if (providers.length === 0) {
39
+ console.log('No providers registered. Use POST /providers to register one.');
40
+ }
41
+ else {
42
+ console.log(`\n${providers.length} provider(s):\n`);
43
+ for (const p of providers) {
44
+ const hw = p.hardware.toUpperCase();
45
+ const price = `${p.pricePerHour} FLOP/hr`;
46
+ const spec = p.gpuModel ? `${p.gpuModel} ${p.vramGB}GB` : `${p.cpuCores} cores ${p.ramGB}GB`;
47
+ console.log(` ${p.name} (${hw})`);
48
+ console.log(` ${spec} — ${price}`);
49
+ console.log(` Jobs: ${p.jobsCompleted} | Rating: ${p.rating}/5 | ${p.available ? '✅ Available' : '❌ Busy'}`);
50
+ console.log();
51
+ }
52
+ }
53
+ break;
54
+ }
55
+ case 'find': {
56
+ const exchange = new ComputeExchange();
57
+ const hardware = getArg(args, '--hardware') || 'gpu';
58
+ const minVram = getArg(args, '--min-vram');
59
+ const maxPrice = getArg(args, '--max-price');
60
+ const providers = exchange.findProviders({
61
+ hardware,
62
+ minVramGB: minVram ? parseInt(minVram) : undefined,
63
+ maxPricePerHour: maxPrice,
64
+ });
65
+ if (providers.length === 0) {
66
+ console.log('No matching providers found.');
67
+ }
68
+ else {
69
+ console.log(`\n${providers.length} matching provider(s) for ${hardware}:\n`);
70
+ for (const p of providers) {
71
+ console.log(` ${p.name} — ${p.pricePerHour} FLOP/hr`);
72
+ if (p.gpuModel)
73
+ console.log(` ${p.gpuModel}, ${p.vramGB}GB VRAM`);
74
+ if (p.cpuCores)
75
+ console.log(` ${p.cpuCores} cores, ${p.ramGB}GB RAM`);
76
+ }
77
+ }
78
+ break;
79
+ }
80
+ case 'stats': {
81
+ const exchange = new ComputeExchange();
82
+ const stats = exchange.getStats();
83
+ console.log('\n📊 Exchange Stats:\n');
84
+ console.log(` Providers: ${stats.availableProviders}/${stats.totalProviders} available`);
85
+ console.log(` Jobs: ${stats.activeJobs} active, ${stats.completedJobs} completed`);
86
+ console.log(` Volume: ${stats.totalVolume} FLOP\n`);
87
+ break;
88
+ }
89
+ default:
90
+ console.log(`
91
+ technocore-compute — P2P compute exchange for AI agents
92
+
93
+ Commands:
94
+ serve [--port 4010] Start the API server
95
+ providers List registered providers
96
+ find [options] Find matching providers
97
+ stats Show exchange statistics
98
+
99
+ Find options:
100
+ --hardware gpu|cpu Hardware type (default: gpu)
101
+ --min-vram 16 Minimum VRAM in GB
102
+ --max-price 5000000 Maximum price per hour
103
+
104
+ Example:
105
+ technocore-compute serve --port 4010
106
+ technocore-compute find --hardware gpu --min-vram 24
107
+ `);
108
+ }
109
+ }
110
+ function getArg(args, flag) {
111
+ const idx = args.indexOf(flag);
112
+ return idx >= 0 ? args[idx + 1] : undefined;
113
+ }
114
+ main().catch(console.error);
@@ -0,0 +1,76 @@
1
+ /**
2
+ * ComputeExchange - P2P compute marketplace for AI agents
3
+ *
4
+ * Manages provider registration, compute requests, job matching,
5
+ * and tclk payment coordination.
6
+ */
7
+ import type { ComputeProvider, ComputeRequest, ComputeJob, ComputeType, ExchangeStats, JobStatus } from './types.js';
8
+ export interface ExchangeConfig {
9
+ /** technocore.chat base URL */
10
+ technocoreBaseUrl?: string;
11
+ /** Room prefix for compute exchange */
12
+ roomPrefix?: string;
13
+ /** How often to refresh providers (ms) */
14
+ refreshIntervalMs?: number;
15
+ /** Data directory for persistence */
16
+ dataDir?: string;
17
+ }
18
+ export declare class ComputeExchange {
19
+ private providers;
20
+ private requests;
21
+ private jobs;
22
+ private config;
23
+ constructor(config?: ExchangeConfig);
24
+ /** Register a compute provider */
25
+ registerProvider(provider: ComputeProvider): void;
26
+ /** Update provider heartbeat */
27
+ heartbeat(did: string): void;
28
+ /** Set provider availability */
29
+ setAvailable(did: string, available: boolean): void;
30
+ /** Remove stale providers (no heartbeat in 5 minutes) */
31
+ pruneStaleProviders(maxAgeMs?: number): number;
32
+ /** Get a provider by DID */
33
+ getProvider(did: string): ComputeProvider | undefined;
34
+ /** List all providers */
35
+ listProviders(): ComputeProvider[];
36
+ /** Find providers matching requirements */
37
+ findProviders(requirements: {
38
+ hardware?: ComputeType;
39
+ minVramGB?: number;
40
+ minCpuCores?: number;
41
+ minRamGB?: number;
42
+ maxPricePerHour?: string;
43
+ }): ComputeProvider[];
44
+ /** Create a compute request */
45
+ createRequest(request: Omit<ComputeRequest, 'id' | 'createdAt' | 'expiresAt'>): ComputeRequest;
46
+ /** Get a request by ID */
47
+ getRequest(id: string): ComputeRequest | undefined;
48
+ /** List all pending requests */
49
+ listPendingRequests(): ComputeRequest[];
50
+ /** Remove expired requests */
51
+ pruneExpiredRequests(): number;
52
+ /** Match a request with the best available provider */
53
+ matchRequest(requestId: string): ComputeJob | null;
54
+ /** Create a job from a request and provider */
55
+ createJob(request: ComputeRequest, provider: ComputeProvider): ComputeJob;
56
+ /** Accept a job (provider confirms) */
57
+ acceptJob(jobId: string): boolean;
58
+ /** Start a job */
59
+ startJob(jobId: string): boolean;
60
+ /** Complete a job */
61
+ completeJob(jobId: string): boolean;
62
+ /** Fail a job */
63
+ failJob(jobId: string, _reason?: string): boolean;
64
+ /** Refund a job */
65
+ refundJob(jobId: string): boolean;
66
+ /** Get a job by ID */
67
+ getJob(id: string): ComputeJob | undefined;
68
+ /** List all jobs */
69
+ listJobs(status?: JobStatus): ComputeJob[];
70
+ /** Get exchange statistics */
71
+ getStats(): ExchangeStats;
72
+ /** Export all data as JSON */
73
+ toJSON(): string;
74
+ /** Import data from JSON */
75
+ fromJSON(json: string): void;
76
+ }
@@ -0,0 +1,262 @@
1
+ /**
2
+ * ComputeExchange - P2P compute marketplace for AI agents
3
+ *
4
+ * Manages provider registration, compute requests, job matching,
5
+ * and tclk payment coordination.
6
+ */
7
+ export class ComputeExchange {
8
+ providers = new Map();
9
+ requests = new Map();
10
+ jobs = new Map();
11
+ config;
12
+ constructor(config = {}) {
13
+ this.config = {
14
+ technocoreBaseUrl: config.technocoreBaseUrl || 'https://technocore.chat',
15
+ roomPrefix: config.roomPrefix || 'compute',
16
+ refreshIntervalMs: config.refreshIntervalMs || 30_000,
17
+ dataDir: config.dataDir || './compute-data',
18
+ };
19
+ }
20
+ // ── Provider Management ──────────────────────────────────────────────────
21
+ /** Register a compute provider */
22
+ registerProvider(provider) {
23
+ this.providers.set(provider.did, {
24
+ ...provider,
25
+ registeredAt: provider.registeredAt || Date.now(),
26
+ lastHeartbeat: provider.lastHeartbeat || Date.now(),
27
+ available: provider.available !== undefined ? provider.available : true,
28
+ rating: provider.rating || 0,
29
+ jobsCompleted: provider.jobsCompleted || 0,
30
+ });
31
+ }
32
+ /** Update provider heartbeat */
33
+ heartbeat(did) {
34
+ const provider = this.providers.get(did);
35
+ if (provider) {
36
+ provider.lastHeartbeat = Date.now();
37
+ provider.available = true;
38
+ }
39
+ }
40
+ /** Set provider availability */
41
+ setAvailable(did, available) {
42
+ const provider = this.providers.get(did);
43
+ if (provider) {
44
+ provider.available = available;
45
+ }
46
+ }
47
+ /** Remove stale providers (no heartbeat in 5 minutes) */
48
+ pruneStaleProviders(maxAgeMs = 300_000) {
49
+ const now = Date.now();
50
+ let pruned = 0;
51
+ for (const [did, provider] of this.providers) {
52
+ if (now - provider.lastHeartbeat > maxAgeMs) {
53
+ this.providers.delete(did);
54
+ pruned++;
55
+ }
56
+ }
57
+ return pruned;
58
+ }
59
+ /** Get a provider by DID */
60
+ getProvider(did) {
61
+ return this.providers.get(did);
62
+ }
63
+ /** List all providers */
64
+ listProviders() {
65
+ return Array.from(this.providers.values());
66
+ }
67
+ /** Find providers matching requirements */
68
+ findProviders(requirements) {
69
+ return this.listProviders().filter(p => {
70
+ if (!p.available)
71
+ return false;
72
+ if (requirements.hardware && requirements.hardware !== 'any' && p.hardware !== requirements.hardware)
73
+ return false;
74
+ if (requirements.minVramGB && (!p.vramGB || p.vramGB < requirements.minVramGB))
75
+ return false;
76
+ if (requirements.minCpuCores && (!p.cpuCores || p.cpuCores < requirements.minCpuCores))
77
+ return false;
78
+ if (requirements.minRamGB && (!p.ramGB || p.ramGB < requirements.minRamGB))
79
+ return false;
80
+ if (requirements.maxPricePerHour) {
81
+ const price = BigInt(p.pricePerHour);
82
+ const max = BigInt(requirements.maxPricePerHour);
83
+ if (price > max)
84
+ return false;
85
+ }
86
+ return true;
87
+ });
88
+ }
89
+ // ── Request Management ───────────────────────────────────────────────────
90
+ /** Create a compute request */
91
+ createRequest(request) {
92
+ const id = `req-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
93
+ const fullRequest = {
94
+ ...request,
95
+ id,
96
+ createdAt: Date.now(),
97
+ expiresAt: Date.now() + (request.durationSec * 1000 || 3_600_000),
98
+ };
99
+ this.requests.set(id, fullRequest);
100
+ return fullRequest;
101
+ }
102
+ /** Get a request by ID */
103
+ getRequest(id) {
104
+ return this.requests.get(id);
105
+ }
106
+ /** List all pending requests */
107
+ listPendingRequests() {
108
+ const now = Date.now();
109
+ return Array.from(this.requests.values()).filter(r => r.expiresAt > now);
110
+ }
111
+ /** Remove expired requests */
112
+ pruneExpiredRequests() {
113
+ const now = Date.now();
114
+ let pruned = 0;
115
+ for (const [id, request] of this.requests) {
116
+ if (request.expiresAt <= now) {
117
+ this.requests.delete(id);
118
+ pruned++;
119
+ }
120
+ }
121
+ return pruned;
122
+ }
123
+ // ── Job Matching ─────────────────────────────────────────────────────────
124
+ /** Match a request with the best available provider */
125
+ matchRequest(requestId) {
126
+ const request = this.requests.get(requestId);
127
+ if (!request)
128
+ return null;
129
+ const providers = this.findProviders({
130
+ hardware: request.hardware,
131
+ minVramGB: request.minVramGB,
132
+ minCpuCores: request.minCpuCores,
133
+ minRamGB: request.minRamGB,
134
+ maxPricePerHour: request.maxPricePerHour,
135
+ });
136
+ if (providers.length === 0)
137
+ return null;
138
+ // Sort by price (cheapest first), then by rating (highest first)
139
+ providers.sort((a, b) => {
140
+ const priceDiff = BigInt(a.pricePerHour) - BigInt(b.pricePerHour);
141
+ if (priceDiff !== 0n)
142
+ return priceDiff < 0n ? -1 : 1;
143
+ return b.rating - a.rating;
144
+ });
145
+ const bestProvider = providers[0];
146
+ return this.createJob(request, bestProvider);
147
+ }
148
+ /** Create a job from a request and provider */
149
+ createJob(request, provider) {
150
+ const jobId = `job-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
151
+ const hours = request.durationSec / 3600;
152
+ const cost = BigInt(provider.pricePerHour) * BigInt(Math.ceil(hours * 10)) / 10n;
153
+ const job = {
154
+ id: jobId,
155
+ providerDid: provider.did,
156
+ consumerDid: request.consumerDid,
157
+ request,
158
+ provider,
159
+ status: 'matched',
160
+ totalCost: cost.toString(),
161
+ room: `${this.config.roomPrefix}-${jobId.slice(4, 12)}`,
162
+ createdAt: Date.now(),
163
+ };
164
+ this.jobs.set(jobId, job);
165
+ return job;
166
+ }
167
+ /** Accept a job (provider confirms) */
168
+ acceptJob(jobId) {
169
+ const job = this.jobs.get(jobId);
170
+ if (!job || job.status !== 'matched')
171
+ return false;
172
+ job.status = 'locked';
173
+ return true;
174
+ }
175
+ /** Start a job */
176
+ startJob(jobId) {
177
+ const job = this.jobs.get(jobId);
178
+ if (!job || job.status !== 'locked')
179
+ return false;
180
+ job.status = 'running';
181
+ job.startedAt = Date.now();
182
+ return true;
183
+ }
184
+ /** Complete a job */
185
+ completeJob(jobId) {
186
+ const job = this.jobs.get(jobId);
187
+ if (!job || job.status !== 'running')
188
+ return false;
189
+ job.status = 'completed';
190
+ job.completedAt = Date.now();
191
+ // Update provider stats
192
+ const provider = this.providers.get(job.providerDid);
193
+ if (provider) {
194
+ provider.jobsCompleted++;
195
+ }
196
+ return true;
197
+ }
198
+ /** Fail a job */
199
+ failJob(jobId, _reason) {
200
+ const job = this.jobs.get(jobId);
201
+ if (!job)
202
+ return false;
203
+ job.status = 'failed';
204
+ return true;
205
+ }
206
+ /** Refund a job */
207
+ refundJob(jobId) {
208
+ const job = this.jobs.get(jobId);
209
+ if (!job)
210
+ return false;
211
+ job.status = 'refunded';
212
+ return true;
213
+ }
214
+ /** Get a job by ID */
215
+ getJob(id) {
216
+ return this.jobs.get(id);
217
+ }
218
+ /** List all jobs */
219
+ listJobs(status) {
220
+ const jobs = Array.from(this.jobs.values());
221
+ return status ? jobs.filter(j => j.status === status) : jobs;
222
+ }
223
+ // ── Stats ────────────────────────────────────────────────────────────────
224
+ /** Get exchange statistics */
225
+ getStats() {
226
+ const allJobs = Array.from(this.jobs.values());
227
+ const allProviders = Array.from(this.providers.values());
228
+ return {
229
+ totalProviders: allProviders.length,
230
+ availableProviders: allProviders.filter(p => p.available).length,
231
+ totalJobs: allJobs.length,
232
+ activeJobs: allJobs.filter(j => ['matched', 'locked', 'running'].includes(j.status)).length,
233
+ completedJobs: allJobs.filter(j => j.status === 'completed').length,
234
+ totalVolume: allJobs
235
+ .filter(j => j.status === 'completed')
236
+ .reduce((sum, j) => sum + BigInt(j.totalCost), 0n)
237
+ .toString(),
238
+ };
239
+ }
240
+ // ── Serialization ────────────────────────────────────────────────────────
241
+ /** Export all data as JSON */
242
+ toJSON() {
243
+ return JSON.stringify({
244
+ providers: Array.from(this.providers.entries()),
245
+ requests: Array.from(this.requests.entries()),
246
+ jobs: Array.from(this.jobs.entries()),
247
+ });
248
+ }
249
+ /** Import data from JSON */
250
+ fromJSON(json) {
251
+ try {
252
+ const data = JSON.parse(json);
253
+ if (data.providers)
254
+ this.providers = new Map(data.providers);
255
+ if (data.requests)
256
+ this.requests = new Map(data.requests);
257
+ if (data.jobs)
258
+ this.jobs = new Map(data.jobs);
259
+ }
260
+ catch { }
261
+ }
262
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * technocore-compute — P2P compute exchange for AI agents
3
+ *
4
+ * Agents can offer compute resources (GPU/CPU) and other agents
5
+ * can rent them, with payments handled via tclk HTLC/PTLC.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { ComputeExchange } from 'technocore-compute';
10
+ *
11
+ * const exchange = new ComputeExchange();
12
+ *
13
+ * // Register as a provider
14
+ * exchange.registerProvider({
15
+ * did: 'did:key:z6Mk...',
16
+ * name: 'GPU Farm',
17
+ * hardware: 'gpu',
18
+ * gpuModel: 'A100',
19
+ * vramGB: 80,
20
+ * pricePerHour: '5000000',
21
+ * minDurationSec: 300,
22
+ * maxDurationSec: 86400,
23
+ * available: true,
24
+ * rating: 4.8,
25
+ * jobsCompleted: 42,
26
+ * room: 'compute-gpu-farm',
27
+ * registeredAt: Date.now(),
28
+ * lastHeartbeat: Date.now(),
29
+ * });
30
+ *
31
+ * // Find providers
32
+ * const providers = exchange.findProviders({
33
+ * hardware: 'gpu',
34
+ * minVramGB: 24,
35
+ * maxPricePerHour: '10000000',
36
+ * });
37
+ *
38
+ * // Create a request and match
39
+ * const request = exchange.createRequest({
40
+ * consumerDid: 'did:key:z6Mk...',
41
+ * hardware: 'gpu',
42
+ * minVramGB: 24,
43
+ * durationSec: 3600,
44
+ * maxPricePerHour: '10000000',
45
+ * description: 'Train a small model',
46
+ * });
47
+ *
48
+ * const job = exchange.matchRequest(request.id);
49
+ * ```
50
+ */
51
+ export { ComputeExchange } from './exchange.js';
52
+ export type { ExchangeConfig } from './exchange.js';
53
+ export { ComputeServer } from './server.js';
54
+ export type { ServerConfig } from './server.js';
55
+ export type { ComputeProvider, ComputeRequest, ComputeJob, ComputeType, JobStatus, ExchangeStats, } from './types.js';