2020117-agent 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.js +53 -8
- package/dist/api.d.ts +7 -2
- package/dist/api.js +6 -4
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -121,6 +121,8 @@ const state = {
|
|
|
121
121
|
swarmNode: null,
|
|
122
122
|
processor: null,
|
|
123
123
|
skill: loadSkill(),
|
|
124
|
+
p2pSessionsCompleted: 0,
|
|
125
|
+
p2pTotalEarnedSats: 0,
|
|
124
126
|
};
|
|
125
127
|
// --- Capacity management ---
|
|
126
128
|
function acquireSlot() {
|
|
@@ -182,7 +184,11 @@ async function setupPlatform(label) {
|
|
|
182
184
|
models,
|
|
183
185
|
skill: state.skill,
|
|
184
186
|
});
|
|
185
|
-
state.stopHeartbeat = startHeartbeatLoop(() => getAvailableCapacity())
|
|
187
|
+
state.stopHeartbeat = startHeartbeatLoop(() => getAvailableCapacity(), () => ({
|
|
188
|
+
sessions: state.p2pSessionsCompleted,
|
|
189
|
+
earned_sats: state.p2pTotalEarnedSats,
|
|
190
|
+
active: activeSessions.size > 0,
|
|
191
|
+
}));
|
|
186
192
|
}
|
|
187
193
|
// --- 3. Async Inbox Poller ---
|
|
188
194
|
function startInboxPoller(label) {
|
|
@@ -685,6 +691,37 @@ async function startSwarmListener(label) {
|
|
|
685
691
|
handleStop(job, msg.id, label);
|
|
686
692
|
}
|
|
687
693
|
});
|
|
694
|
+
// Handle customer disconnect — claim any earned tokens immediately
|
|
695
|
+
node.on('peer-leave', (peerId) => {
|
|
696
|
+
const tag = peerId.slice(0, 8);
|
|
697
|
+
// Find and end all sessions for this peer
|
|
698
|
+
for (const [sessionId, session] of activeSessions) {
|
|
699
|
+
if (session.peerId === peerId) {
|
|
700
|
+
console.log(`[${label}] Peer ${tag} disconnected — ending session ${sessionId} (${session.totalEarned} sats earned)`);
|
|
701
|
+
endSession(node, session, label);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
// Clean up any P2P streaming jobs for this peer
|
|
705
|
+
for (const [jobId, job] of p2pJobs) {
|
|
706
|
+
if (job.socket?.remotePublicKey?.toString('hex') === peerId) {
|
|
707
|
+
console.log(`[${label}] Peer ${tag} disconnected — claiming P2P job ${jobId} tokens`);
|
|
708
|
+
job.stopped = true;
|
|
709
|
+
batchClaim(job.tokens, jobId, label);
|
|
710
|
+
p2pJobs.delete(jobId);
|
|
711
|
+
releaseSlot();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
// Clean up backend WebSockets for this peer
|
|
715
|
+
for (const [wsId, entry] of backendWebSockets) {
|
|
716
|
+
if (entry.peerId === peerId) {
|
|
717
|
+
try {
|
|
718
|
+
entry.ws.close(1001, 'Peer disconnected');
|
|
719
|
+
}
|
|
720
|
+
catch { }
|
|
721
|
+
backendWebSockets.delete(wsId);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
});
|
|
688
725
|
}
|
|
689
726
|
async function runP2PGeneration(node, job, msg, label) {
|
|
690
727
|
const source = SUB_KIND
|
|
@@ -728,14 +765,22 @@ function endSession(node, session, label) {
|
|
|
728
765
|
backendWebSockets.delete(wsId);
|
|
729
766
|
}
|
|
730
767
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
768
|
+
try {
|
|
769
|
+
node.send(session.socket, {
|
|
770
|
+
type: 'session_end',
|
|
771
|
+
id: session.sessionId,
|
|
772
|
+
session_id: session.sessionId,
|
|
773
|
+
total_sats: session.totalEarned,
|
|
774
|
+
duration_s: durationS,
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
catch {
|
|
778
|
+
// Socket may already be closed (peer disconnect)
|
|
779
|
+
}
|
|
738
780
|
console.log(`[${label}] Session ${session.sessionId} ended: ${session.totalEarned} sats, ${durationS}s`);
|
|
781
|
+
// Update P2P lifetime counters
|
|
782
|
+
state.p2pSessionsCompleted++;
|
|
783
|
+
state.p2pTotalEarnedSats += session.totalEarned;
|
|
739
784
|
// Batch claim tokens
|
|
740
785
|
batchClaim(session.tokens, session.sessionId, label);
|
|
741
786
|
activeSessions.delete(session.sessionId);
|
package/dist/api.d.ts
CHANGED
|
@@ -25,9 +25,14 @@ export declare function registerService(opts: {
|
|
|
25
25
|
models?: string[];
|
|
26
26
|
skill?: Record<string, unknown> | null;
|
|
27
27
|
}): Promise<unknown | null>;
|
|
28
|
-
export
|
|
28
|
+
export interface P2PStats {
|
|
29
|
+
sessions: number;
|
|
30
|
+
earned_sats: number;
|
|
31
|
+
active: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function sendHeartbeat(capacity?: number, p2pStats?: P2PStats): Promise<boolean>;
|
|
29
34
|
export declare function getOnlineProviders(kind: number): Promise<OnlineAgent[]>;
|
|
30
|
-
export declare function startHeartbeatLoop(capacityOrFn?: number | (() => number)): () => void;
|
|
35
|
+
export declare function startHeartbeatLoop(capacityOrFn?: number | (() => number), p2pStatsFn?: () => P2PStats): () => void;
|
|
31
36
|
export interface InboxJob {
|
|
32
37
|
id: string;
|
|
33
38
|
kind: number;
|
package/dist/api.js
CHANGED
|
@@ -161,13 +161,15 @@ export async function registerService(opts) {
|
|
|
161
161
|
return null;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
export async function sendHeartbeat(capacity) {
|
|
164
|
+
export async function sendHeartbeat(capacity, p2pStats) {
|
|
165
165
|
if (!API_KEY)
|
|
166
166
|
return false;
|
|
167
167
|
try {
|
|
168
168
|
const body = {};
|
|
169
169
|
if (capacity !== undefined)
|
|
170
170
|
body.capacity = capacity;
|
|
171
|
+
if (p2pStats)
|
|
172
|
+
body.p2p_stats = p2pStats;
|
|
171
173
|
const resp = await fetch(`${BASE_URL}/api/heartbeat`, {
|
|
172
174
|
method: 'POST',
|
|
173
175
|
headers: {
|
|
@@ -206,17 +208,17 @@ export async function getOnlineProviders(kind) {
|
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
const HEARTBEAT_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
|
209
|
-
export function startHeartbeatLoop(capacityOrFn) {
|
|
211
|
+
export function startHeartbeatLoop(capacityOrFn, p2pStatsFn) {
|
|
210
212
|
const getCapacity = typeof capacityOrFn === 'function'
|
|
211
213
|
? capacityOrFn
|
|
212
214
|
: () => capacityOrFn;
|
|
213
215
|
// Send first heartbeat immediately
|
|
214
|
-
sendHeartbeat(getCapacity()).then((ok) => {
|
|
216
|
+
sendHeartbeat(getCapacity(), p2pStatsFn?.()).then((ok) => {
|
|
215
217
|
if (ok)
|
|
216
218
|
console.log('[api] Heartbeat sent');
|
|
217
219
|
});
|
|
218
220
|
const timer = setInterval(() => {
|
|
219
|
-
sendHeartbeat(getCapacity()).then((ok) => {
|
|
221
|
+
sendHeartbeat(getCapacity(), p2pStatsFn?.()).then((ok) => {
|
|
220
222
|
if (ok)
|
|
221
223
|
console.log('[api] Heartbeat sent');
|
|
222
224
|
});
|