pelagora 0.1.5
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/CHANGELOG.md +40 -0
- package/LICENSE +663 -0
- package/README.md +139 -0
- package/dist/ai/product-lookup.d.ts +26 -0
- package/dist/ai/product-lookup.d.ts.map +1 -0
- package/dist/ai/product-lookup.js +153 -0
- package/dist/ai/product-lookup.js.map +1 -0
- package/dist/api/collections.d.ts +3 -0
- package/dist/api/collections.d.ts.map +1 -0
- package/dist/api/collections.js +69 -0
- package/dist/api/collections.js.map +1 -0
- package/dist/api/favorites.d.ts +3 -0
- package/dist/api/favorites.d.ts.map +1 -0
- package/dist/api/favorites.js +43 -0
- package/dist/api/favorites.js.map +1 -0
- package/dist/api/health.d.ts +12 -0
- package/dist/api/health.d.ts.map +1 -0
- package/dist/api/health.js +54 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +56 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/items.d.ts +3 -0
- package/dist/api/items.d.ts.map +1 -0
- package/dist/api/items.js +170 -0
- package/dist/api/items.js.map +1 -0
- package/dist/api/media.d.ts +3 -0
- package/dist/api/media.d.ts.map +1 -0
- package/dist/api/media.js +241 -0
- package/dist/api/media.js.map +1 -0
- package/dist/api/negotiations.d.ts +3 -0
- package/dist/api/negotiations.d.ts.map +1 -0
- package/dist/api/negotiations.js +244 -0
- package/dist/api/negotiations.js.map +1 -0
- package/dist/api/offers.d.ts +3 -0
- package/dist/api/offers.d.ts.map +1 -0
- package/dist/api/offers.js +57 -0
- package/dist/api/offers.js.map +1 -0
- package/dist/api/refs.d.ts +3 -0
- package/dist/api/refs.d.ts.map +1 -0
- package/dist/api/refs.js +390 -0
- package/dist/api/refs.js.map +1 -0
- package/dist/api/scans.d.ts +3 -0
- package/dist/api/scans.d.ts.map +1 -0
- package/dist/api/scans.js +384 -0
- package/dist/api/scans.js.map +1 -0
- package/dist/api/settings.d.ts +3 -0
- package/dist/api/settings.d.ts.map +1 -0
- package/dist/api/settings.js +442 -0
- package/dist/api/settings.js.map +1 -0
- package/dist/db/index.d.ts +4 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +18 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/queries.d.ts +237 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +891 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +6 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +531 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/dht/discovery.d.ts +33 -0
- package/dist/dht/discovery.d.ts.map +1 -0
- package/dist/dht/discovery.js +281 -0
- package/dist/dht/discovery.js.map +1 -0
- package/dist/dht/index.d.ts +2 -0
- package/dist/dht/index.d.ts.map +1 -0
- package/dist/dht/index.js +6 -0
- package/dist/dht/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +215 -0
- package/dist/index.js.map +1 -0
- package/dist/ref-schemas.d.ts +59 -0
- package/dist/ref-schemas.d.ts.map +1 -0
- package/dist/ref-schemas.js +1038 -0
- package/dist/ref-schemas.js.map +1 -0
- package/dist/skills/export.d.ts +12 -0
- package/dist/skills/export.d.ts.map +1 -0
- package/dist/skills/export.js +54 -0
- package/dist/skills/export.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +11 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +37 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +183 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/registry.d.ts +37 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +136 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/sync/index.d.ts +58 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +331 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/reffo-client.d.ts +144 -0
- package/dist/sync/reffo-client.d.ts.map +1 -0
- package/dist/sync/reffo-client.js +279 -0
- package/dist/sync/reffo-client.js.map +1 -0
- package/dist/taxonomy.d.ts +4 -0
- package/dist/taxonomy.d.ts.map +1 -0
- package/dist/taxonomy.js +141 -0
- package/dist/taxonomy.js.map +1 -0
- package/dist/types/index.d.ts +198 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +25 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui.d.ts +2 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +6786 -0
- package/dist/ui.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +14 -0
- package/dist/version.js.map +1 -0
- package/footer-brand.png +0 -0
- package/header-brand.png +0 -0
- package/package.json +61 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PeerMessage, QueryPayload } from '@pelagora/pim-protocol';
|
|
2
|
+
export declare class DhtDiscovery {
|
|
3
|
+
private swarm;
|
|
4
|
+
private beaconId;
|
|
5
|
+
private peers;
|
|
6
|
+
private beaconIdMap;
|
|
7
|
+
private messageHandlers;
|
|
8
|
+
private onPeerConnect?;
|
|
9
|
+
httpPort: number;
|
|
10
|
+
constructor(beaconId: string);
|
|
11
|
+
start(onPeerConnect?: (count: number) => void): Promise<void>;
|
|
12
|
+
private sendAnnouncement;
|
|
13
|
+
/** Register a custom message handler for skill-defined message types */
|
|
14
|
+
registerMessageHandler(type: string, handler: (fromBeaconId: string, payload: unknown) => void): void;
|
|
15
|
+
/** Broadcast a message to all connected peers */
|
|
16
|
+
broadcastToPeers(msg: PeerMessage): void;
|
|
17
|
+
private handleMessage;
|
|
18
|
+
private handleQuery;
|
|
19
|
+
/** Map a Hyperswarm peer stream to its Reffo beaconId */
|
|
20
|
+
private updatePeerBeaconId;
|
|
21
|
+
/** Send a message to a specific peer by their Reffo beaconId */
|
|
22
|
+
sendToPeer(targetBeaconId: string, msg: PeerMessage): boolean;
|
|
23
|
+
/** Handle incoming proposal from a buyer */
|
|
24
|
+
private handleProposal;
|
|
25
|
+
/** Handle incoming proposal response from a seller */
|
|
26
|
+
private handleProposalResponse;
|
|
27
|
+
/** Query all connected peers and collect responses */
|
|
28
|
+
queryPeers(query: QueryPayload, timeoutMs?: number): Promise<PeerMessage[]>;
|
|
29
|
+
get peerCount(): number;
|
|
30
|
+
get isConnected(): boolean;
|
|
31
|
+
stop(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/dht/discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAA6D,MAAM,wBAAwB,CAAC;AAMnI,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAA6D;IAC1E,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,eAAe,CAAuE;IAC9F,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,QAAQ,SAAK;gBAED,QAAQ,EAAE,MAAM;IAKtB,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCnE,OAAO,CAAC,gBAAgB;IAkCxB,wEAAwE;IACxE,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAIrG,iDAAiD;IACjD,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAWxC,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,WAAW;IA+DnB,yDAAyD;IACzD,OAAO,CAAC,kBAAkB;IAS1B,gEAAgE;IAChE,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO;IAsB7D,4CAA4C;IAC5C,OAAO,CAAC,cAAc;IAkBtB,sDAAsD;IACtD,OAAO,CAAC,sBAAsB;IAkB9B,sDAAsD;IACtD,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA2BzE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DhtDiscovery = void 0;
|
|
7
|
+
const hyperswarm_1 = __importDefault(require("hyperswarm"));
|
|
8
|
+
const b4a_1 = __importDefault(require("b4a"));
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const db_1 = require("../db");
|
|
11
|
+
const pim_protocol_1 = require("@pelagora/pim-protocol");
|
|
12
|
+
// All Reffo beacons join this topic to find each other
|
|
13
|
+
const REFFO_TOPIC = crypto_1.default.createHash('sha256').update('reffo-beacon-v1').digest();
|
|
14
|
+
class DhtDiscovery {
|
|
15
|
+
swarm;
|
|
16
|
+
beaconId;
|
|
17
|
+
peers = new Map();
|
|
18
|
+
beaconIdMap = new Map(); // reffoBeaconId -> hyperswarm peerId
|
|
19
|
+
messageHandlers = new Map();
|
|
20
|
+
onPeerConnect;
|
|
21
|
+
httpPort = 0;
|
|
22
|
+
constructor(beaconId) {
|
|
23
|
+
this.swarm = new hyperswarm_1.default();
|
|
24
|
+
this.beaconId = beaconId;
|
|
25
|
+
}
|
|
26
|
+
async start(onPeerConnect) {
|
|
27
|
+
this.onPeerConnect = onPeerConnect;
|
|
28
|
+
this.swarm.on('connection', (stream, info) => {
|
|
29
|
+
const peerId = b4a_1.default.toString(stream.remotePublicKey, 'hex');
|
|
30
|
+
console.log(`[DHT] Peer connected: ${peerId.slice(0, 8)}...`);
|
|
31
|
+
this.peers.set(peerId, { stream, beaconId: peerId });
|
|
32
|
+
this.onPeerConnect?.(this.peers.size);
|
|
33
|
+
// Send our announcement on connect
|
|
34
|
+
this.sendAnnouncement(stream);
|
|
35
|
+
stream.on('data', (data) => {
|
|
36
|
+
const msg = (0, pim_protocol_1.parseDhtMessage)(b4a_1.default.toString(data));
|
|
37
|
+
if (msg)
|
|
38
|
+
this.handleMessage(msg, stream);
|
|
39
|
+
});
|
|
40
|
+
stream.on('close', () => {
|
|
41
|
+
this.peers.delete(peerId);
|
|
42
|
+
console.log(`[DHT] Peer disconnected: ${peerId.slice(0, 8)}...`);
|
|
43
|
+
this.onPeerConnect?.(this.peers.size);
|
|
44
|
+
});
|
|
45
|
+
stream.on('error', () => {
|
|
46
|
+
this.peers.delete(peerId);
|
|
47
|
+
this.onPeerConnect?.(this.peers.size);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
// Join the Reffo topic so all beacons can discover each other
|
|
51
|
+
const discovery = this.swarm.join(REFFO_TOPIC, { server: true, client: true });
|
|
52
|
+
await discovery.flushed();
|
|
53
|
+
console.log(`[DHT] Joined Pelagora network. Topic: ${b4a_1.default.toString(REFFO_TOPIC, 'hex').slice(0, 16)}...`);
|
|
54
|
+
}
|
|
55
|
+
sendAnnouncement(stream) {
|
|
56
|
+
const refs = new db_1.RefQueries();
|
|
57
|
+
const offers = new db_1.OfferQueries();
|
|
58
|
+
const discoverableRefs = refs.listDiscoverable();
|
|
59
|
+
const discoverableRefIds = new Set(discoverableRefs.map(i => i.id));
|
|
60
|
+
const payload = {
|
|
61
|
+
refs: discoverableRefs.map(i => {
|
|
62
|
+
const blurred = (i.locationLat != null && i.locationLng != null)
|
|
63
|
+
? (0, pim_protocol_1.blurLocation)(i.locationLat, i.locationLng) : null;
|
|
64
|
+
return {
|
|
65
|
+
id: i.id, name: i.name, category: i.category, subcategory: i.subcategory, listingStatus: i.listingStatus,
|
|
66
|
+
locationLat: blurred?.lat, locationLng: blurred?.lng,
|
|
67
|
+
locationCity: i.locationCity, locationState: i.locationState,
|
|
68
|
+
locationZip: i.locationZip, locationCountry: i.locationCountry,
|
|
69
|
+
sellingScope: i.sellingScope, sellingRadiusMiles: i.sellingRadiusMiles,
|
|
70
|
+
};
|
|
71
|
+
}),
|
|
72
|
+
offers: offers.list().filter(o => discoverableRefIds.has(o.refId)).map(o => ({
|
|
73
|
+
id: o.id, refId: o.refId, price: o.price,
|
|
74
|
+
priceCurrency: o.priceCurrency, status: o.status,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
const msg = {
|
|
78
|
+
type: 'announce',
|
|
79
|
+
beaconId: this.beaconId,
|
|
80
|
+
payload,
|
|
81
|
+
};
|
|
82
|
+
stream.write(b4a_1.default.from(JSON.stringify(msg)));
|
|
83
|
+
}
|
|
84
|
+
/** Register a custom message handler for skill-defined message types */
|
|
85
|
+
registerMessageHandler(type, handler) {
|
|
86
|
+
this.messageHandlers.set(type, handler);
|
|
87
|
+
}
|
|
88
|
+
/** Broadcast a message to all connected peers */
|
|
89
|
+
broadcastToPeers(msg) {
|
|
90
|
+
const msgBuf = b4a_1.default.from(JSON.stringify(msg));
|
|
91
|
+
for (const [, peer] of this.peers) {
|
|
92
|
+
try {
|
|
93
|
+
peer.stream.write(msgBuf);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Ignore write errors to individual peers
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
handleMessage(msg, stream) {
|
|
101
|
+
switch (msg.type) {
|
|
102
|
+
case 'query':
|
|
103
|
+
this.handleQuery(msg.payload, stream, msg.beaconId);
|
|
104
|
+
break;
|
|
105
|
+
case 'announce':
|
|
106
|
+
console.log(`[DHT] Received announcement from ${msg.beaconId.slice(0, 8)}...`);
|
|
107
|
+
this.updatePeerBeaconId(stream, msg.beaconId);
|
|
108
|
+
break;
|
|
109
|
+
case 'response':
|
|
110
|
+
// Responses are handled by the caller
|
|
111
|
+
break;
|
|
112
|
+
case 'proposal':
|
|
113
|
+
this.handleProposal(msg.beaconId, msg.payload);
|
|
114
|
+
break;
|
|
115
|
+
case 'proposal_response':
|
|
116
|
+
this.handleProposalResponse(msg.beaconId, msg.payload);
|
|
117
|
+
break;
|
|
118
|
+
default: {
|
|
119
|
+
// Check for skill-registered message handlers
|
|
120
|
+
const handler = this.messageHandlers.get(msg.type);
|
|
121
|
+
if (handler) {
|
|
122
|
+
handler(msg.beaconId, msg.payload);
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
handleQuery(query, stream, fromBeacon) {
|
|
129
|
+
console.log(`[DHT] Query from ${fromBeacon.slice(0, 8)}...:`, query);
|
|
130
|
+
const refs = new db_1.RefQueries();
|
|
131
|
+
const offers = new db_1.OfferQueries();
|
|
132
|
+
const mediaQ = new db_1.MediaQueries();
|
|
133
|
+
const searchTerm = query.search ? (0, pim_protocol_1.sanitizeField)(query.search, 'search') : undefined;
|
|
134
|
+
let results = searchTerm
|
|
135
|
+
? refs.searchDiscoverable(searchTerm)
|
|
136
|
+
: refs.listDiscoverable(query.category, query.subcategory);
|
|
137
|
+
// Build response with matching offers
|
|
138
|
+
const matchingOffers = results.flatMap(ref => {
|
|
139
|
+
const refOffers = offers.list(ref.id).filter(o => o.status === 'active');
|
|
140
|
+
if (query.maxPrice !== undefined) {
|
|
141
|
+
return refOffers.filter(o => o.price <= query.maxPrice);
|
|
142
|
+
}
|
|
143
|
+
return refOffers;
|
|
144
|
+
});
|
|
145
|
+
// Geo-filter if query has lat/lng/radiusMiles
|
|
146
|
+
if (query.lat != null && query.lng != null && query.radiusMiles != null) {
|
|
147
|
+
results = results.filter(ref => {
|
|
148
|
+
const scope = ref.sellingScope || 'global';
|
|
149
|
+
if (scope === 'global')
|
|
150
|
+
return true;
|
|
151
|
+
if (scope === 'national')
|
|
152
|
+
return true;
|
|
153
|
+
if (ref.locationLat == null || ref.locationLng == null)
|
|
154
|
+
return true; // no location = show everywhere
|
|
155
|
+
const dist = (0, pim_protocol_1.haversineDistanceMiles)(query.lat, query.lng, ref.locationLat, ref.locationLng);
|
|
156
|
+
if (scope === 'range')
|
|
157
|
+
return dist <= (ref.sellingRadiusMiles || Infinity);
|
|
158
|
+
return dist <= query.radiusMiles;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
// Include media metadata per item
|
|
162
|
+
const mediaMap = {};
|
|
163
|
+
for (const ref of results) {
|
|
164
|
+
const media = mediaQ.listForRef(ref.id);
|
|
165
|
+
if (media.length > 0) {
|
|
166
|
+
mediaMap[ref.id] = media.map(m => ({ id: m.id, filePath: m.filePath, mediaType: m.mediaType }));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Blur location in response — never send exact lat/lng or address
|
|
170
|
+
const blurredResults = results.map(ref => {
|
|
171
|
+
const blurred = (ref.locationLat != null && ref.locationLng != null)
|
|
172
|
+
? (0, pim_protocol_1.blurLocation)(ref.locationLat, ref.locationLng) : null;
|
|
173
|
+
return {
|
|
174
|
+
...ref,
|
|
175
|
+
locationLat: blurred?.lat,
|
|
176
|
+
locationLng: blurred?.lng,
|
|
177
|
+
locationAddress: undefined, // never share street address
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
const response = {
|
|
181
|
+
type: 'response',
|
|
182
|
+
beaconId: this.beaconId,
|
|
183
|
+
payload: { refs: blurredResults, offers: matchingOffers, media: mediaMap, httpPort: this.httpPort },
|
|
184
|
+
};
|
|
185
|
+
stream.write(b4a_1.default.from(JSON.stringify(response)));
|
|
186
|
+
}
|
|
187
|
+
/** Map a Hyperswarm peer stream to its Reffo beaconId */
|
|
188
|
+
updatePeerBeaconId(stream, reffoBeaconId) {
|
|
189
|
+
const peerId = b4a_1.default.toString(stream.remotePublicKey, 'hex');
|
|
190
|
+
const peer = this.peers.get(peerId);
|
|
191
|
+
if (peer) {
|
|
192
|
+
peer.beaconId = reffoBeaconId;
|
|
193
|
+
this.beaconIdMap.set(reffoBeaconId, peerId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** Send a message to a specific peer by their Reffo beaconId */
|
|
197
|
+
sendToPeer(targetBeaconId, msg) {
|
|
198
|
+
// Look up by beaconId map first
|
|
199
|
+
const peerId = this.beaconIdMap.get(targetBeaconId);
|
|
200
|
+
if (peerId) {
|
|
201
|
+
const peer = this.peers.get(peerId);
|
|
202
|
+
if (peer) {
|
|
203
|
+
peer.stream.write(b4a_1.default.from(JSON.stringify(msg)));
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Fallback: search all peers
|
|
208
|
+
for (const [, peer] of this.peers) {
|
|
209
|
+
if (peer.beaconId === targetBeaconId) {
|
|
210
|
+
peer.stream.write(b4a_1.default.from(JSON.stringify(msg)));
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
/** Handle incoming proposal from a buyer */
|
|
217
|
+
handleProposal(fromBeaconId, payload) {
|
|
218
|
+
console.log(`[DHT] Received proposal from ${fromBeaconId.slice(0, 8)}... for ref ${payload.refId}`);
|
|
219
|
+
const negotiations = new db_1.NegotiationQueries();
|
|
220
|
+
const clean = (0, pim_protocol_1.sanitizeObject)(payload);
|
|
221
|
+
negotiations.create({
|
|
222
|
+
id: clean.negotiationId,
|
|
223
|
+
refId: clean.refId,
|
|
224
|
+
refName: clean.refName || '',
|
|
225
|
+
buyerBeaconId: fromBeaconId,
|
|
226
|
+
sellerBeaconId: this.beaconId,
|
|
227
|
+
price: clean.price,
|
|
228
|
+
priceCurrency: clean.priceCurrency || 'USD',
|
|
229
|
+
message: clean.message || '',
|
|
230
|
+
role: 'seller',
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/** Handle incoming proposal response from a seller */
|
|
234
|
+
handleProposalResponse(fromBeaconId, payload) {
|
|
235
|
+
console.log(`[DHT] Received proposal response from ${fromBeaconId.slice(0, 8)}... for negotiation ${payload.negotiationId}`);
|
|
236
|
+
const negotiations = new db_1.NegotiationQueries();
|
|
237
|
+
const existing = negotiations.get(payload.negotiationId);
|
|
238
|
+
if (!existing || existing.role !== 'buyer') {
|
|
239
|
+
console.log(`[DHT] Unknown or invalid negotiation: ${payload.negotiationId}`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
negotiations.updateStatus(payload.negotiationId, payload.status, payload.counterPrice, payload.responseMessage);
|
|
243
|
+
}
|
|
244
|
+
/** Query all connected peers and collect responses */
|
|
245
|
+
queryPeers(query, timeoutMs = 5000) {
|
|
246
|
+
return new Promise((resolve) => {
|
|
247
|
+
const responses = [];
|
|
248
|
+
const msg = {
|
|
249
|
+
type: 'query',
|
|
250
|
+
beaconId: this.beaconId,
|
|
251
|
+
payload: query,
|
|
252
|
+
};
|
|
253
|
+
const msgBuf = b4a_1.default.from(JSON.stringify(msg));
|
|
254
|
+
for (const [, peer] of this.peers) {
|
|
255
|
+
const handler = (data) => {
|
|
256
|
+
const resp = (0, pim_protocol_1.parseDhtMessage)(b4a_1.default.toString(data));
|
|
257
|
+
if (resp && resp.type === 'response') {
|
|
258
|
+
responses.push(resp);
|
|
259
|
+
peer.stream.off('data', handler);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
peer.stream.on('data', handler);
|
|
263
|
+
peer.stream.write(msgBuf);
|
|
264
|
+
}
|
|
265
|
+
setTimeout(() => resolve(responses), timeoutMs);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
get peerCount() {
|
|
269
|
+
return this.peers.size;
|
|
270
|
+
}
|
|
271
|
+
get isConnected() {
|
|
272
|
+
return true; // Swarm is always "connected" once started
|
|
273
|
+
}
|
|
274
|
+
async stop() {
|
|
275
|
+
await this.swarm.destroy();
|
|
276
|
+
this.peers.clear();
|
|
277
|
+
console.log('[DHT] Disconnected from Pelagora network');
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.DhtDiscovery = DhtDiscovery;
|
|
281
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/dht/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dht/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DhtDiscovery = void 0;
|
|
4
|
+
var discovery_1 = require("./discovery");
|
|
5
|
+
Object.defineProperty(exports, "DhtDiscovery", { enumerable: true, get: function () { return discovery_1.DhtDiscovery; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dht/index.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAAlC,yGAAA,YAAY,OAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const api_1 = require("./api");
|
|
10
|
+
const health_1 = require("./api/health");
|
|
11
|
+
const dht_1 = require("./dht");
|
|
12
|
+
const db_1 = require("./db");
|
|
13
|
+
const sync_1 = require("./sync");
|
|
14
|
+
const reffo_client_1 = require("./sync/reffo-client");
|
|
15
|
+
const version_1 = require("./version");
|
|
16
|
+
const skills_1 = require("./skills");
|
|
17
|
+
// Load .env into process.env (no dotenv dependency)
|
|
18
|
+
function loadEnv() {
|
|
19
|
+
const envPath = path_1.default.join(process.cwd(), '.env');
|
|
20
|
+
if (!fs_1.default.existsSync(envPath))
|
|
21
|
+
return;
|
|
22
|
+
const content = fs_1.default.readFileSync(envPath, 'utf-8');
|
|
23
|
+
for (const line of content.split('\n')) {
|
|
24
|
+
const trimmed = line.split('#')[0].trim();
|
|
25
|
+
if (!trimmed)
|
|
26
|
+
continue;
|
|
27
|
+
const eqIdx = trimmed.indexOf('=');
|
|
28
|
+
if (eqIdx === -1)
|
|
29
|
+
continue;
|
|
30
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
31
|
+
const value = trimmed.slice(eqIdx + 1).trim();
|
|
32
|
+
if (!process.env[key])
|
|
33
|
+
process.env[key] = value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
loadEnv();
|
|
37
|
+
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
38
|
+
function getOrCreateBeaconId() {
|
|
39
|
+
if (process.env.BEACON_ID)
|
|
40
|
+
return process.env.BEACON_ID;
|
|
41
|
+
const idFile = path_1.default.join(process.cwd(), 'data', 'beacon-id');
|
|
42
|
+
try {
|
|
43
|
+
return fs_1.default.readFileSync(idFile, 'utf-8').trim();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
const id = crypto_1.default.randomUUID();
|
|
47
|
+
fs_1.default.mkdirSync(path_1.default.dirname(idFile), { recursive: true });
|
|
48
|
+
fs_1.default.writeFileSync(idFile, id);
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const BEACON_ID = getOrCreateBeaconId();
|
|
53
|
+
async function main() {
|
|
54
|
+
// Ensure uploads directory exists
|
|
55
|
+
fs_1.default.mkdirSync(path_1.default.join(process.cwd(), 'uploads'), { recursive: true });
|
|
56
|
+
// Initialize database
|
|
57
|
+
(0, db_1.getDb)();
|
|
58
|
+
console.log('[DB] SQLite initialized');
|
|
59
|
+
// Create Express app
|
|
60
|
+
const app = (0, api_1.createApp)();
|
|
61
|
+
app.set('beaconId', BEACON_ID);
|
|
62
|
+
app.set('startTime', Date.now());
|
|
63
|
+
(0, health_1.setBeaconId)(BEACON_ID);
|
|
64
|
+
// Initialize Reffo.ai sync if API key is configured
|
|
65
|
+
const reffoApiKey = process.env.REFFO_API_KEY;
|
|
66
|
+
if (reffoApiKey) {
|
|
67
|
+
const reffoUrl = process.env.REFFO_API_URL || 'https://reffo.ai';
|
|
68
|
+
const syncManager = new sync_1.SyncManager(reffoApiKey, BEACON_ID, reffoUrl);
|
|
69
|
+
const beaconUrl = process.env.BEACON_URL || `http://localhost:${PORT}`;
|
|
70
|
+
app.set('syncManager', syncManager);
|
|
71
|
+
syncManager.registerBeacon('Reffo Beacon', (0, version_1.getVersion)(), beaconUrl)
|
|
72
|
+
.then(result => {
|
|
73
|
+
if (result.ok) {
|
|
74
|
+
syncManager.registered = true;
|
|
75
|
+
syncManager.lastError = null;
|
|
76
|
+
console.log('[Sync] Registered with Reffo.ai');
|
|
77
|
+
syncManager.startHeartbeat();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
syncManager.registered = false;
|
|
81
|
+
syncManager.lastError = result.error || 'Registration failed';
|
|
82
|
+
console.warn('[Sync] Registration failed:', result.error);
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
.catch(err => {
|
|
86
|
+
syncManager.lastError = err.message;
|
|
87
|
+
console.warn('[Sync] Registration error:', err.message);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Start DHT discovery
|
|
91
|
+
const dht = new dht_1.DhtDiscovery(BEACON_ID);
|
|
92
|
+
dht.httpPort = PORT;
|
|
93
|
+
app.set('dht', dht);
|
|
94
|
+
// Load skill plugins
|
|
95
|
+
const db = (0, db_1.getDb)();
|
|
96
|
+
const skillLoader = new skills_1.SkillLoader(db, BEACON_ID, dht);
|
|
97
|
+
await skillLoader.loadAll(app);
|
|
98
|
+
// Mount skill registry API and export routes
|
|
99
|
+
app.use('/skills', (0, skills_1.createSkillRegistryRouter)(skillLoader.getRegistry()));
|
|
100
|
+
app.use('/skills', (0, skills_1.createSkillExportRouter)(skillLoader.getSkills()));
|
|
101
|
+
// Expose DHT + Reffo search endpoint
|
|
102
|
+
app.get('/search', async (req, res) => {
|
|
103
|
+
const { q, c, sc, maxPrice, lat, lng, radius, source } = req.query;
|
|
104
|
+
const searchSource = typeof source === 'string' ? source : 'all';
|
|
105
|
+
const query = {
|
|
106
|
+
search: typeof q === 'string' ? q : undefined,
|
|
107
|
+
category: typeof c === 'string' ? c : undefined,
|
|
108
|
+
subcategory: typeof sc === 'string' ? sc : undefined,
|
|
109
|
+
maxPrice: typeof maxPrice === 'string' ? parseFloat(maxPrice) : undefined,
|
|
110
|
+
lat: typeof lat === 'string' ? parseFloat(lat) : undefined,
|
|
111
|
+
lng: typeof lng === 'string' ? parseFloat(lng) : undefined,
|
|
112
|
+
radiusMiles: typeof radius === 'string' ? parseFloat(radius) : undefined,
|
|
113
|
+
};
|
|
114
|
+
const dhtPromise = (searchSource === 'reffo')
|
|
115
|
+
? Promise.resolve([])
|
|
116
|
+
: dht.queryPeers(query);
|
|
117
|
+
const reffoUrl = process.env.REFFO_API_URL || 'https://reffo.ai';
|
|
118
|
+
const reffoPromise = (searchSource === 'beacons')
|
|
119
|
+
? Promise.resolve({ results: [], total: 0 })
|
|
120
|
+
: (0, reffo_client_1.searchReffo)({
|
|
121
|
+
search: query.search,
|
|
122
|
+
category: query.category,
|
|
123
|
+
lat: query.lat,
|
|
124
|
+
lng: query.lng,
|
|
125
|
+
radiusMiles: query.radiusMiles,
|
|
126
|
+
sort: typeof req.query.sort === 'string' ? req.query.sort : undefined,
|
|
127
|
+
}, reffoUrl);
|
|
128
|
+
const [dhtResult, reffoResult] = await Promise.allSettled([dhtPromise, reffoPromise]);
|
|
129
|
+
const dhtResponses = dhtResult.status === 'fulfilled' ? dhtResult.value : [];
|
|
130
|
+
const reffoData = reffoResult.status === 'fulfilled' ? reffoResult.value : { results: [], total: 0 };
|
|
131
|
+
// Build DHT results with source tag
|
|
132
|
+
const dhtResults = dhtResponses.map(r => ({
|
|
133
|
+
beaconId: r.beaconId,
|
|
134
|
+
source: 'dht',
|
|
135
|
+
...r.payload,
|
|
136
|
+
}));
|
|
137
|
+
// Convert Reffo results to peer-like format with source tag
|
|
138
|
+
const reffoResults = reffoData.results.map(r => ({
|
|
139
|
+
beaconId: r.beaconId,
|
|
140
|
+
source: 'reffo',
|
|
141
|
+
refs: [{
|
|
142
|
+
id: r.localId,
|
|
143
|
+
name: r.name,
|
|
144
|
+
description: r.description,
|
|
145
|
+
category: r.category,
|
|
146
|
+
subcategory: r.subcategory,
|
|
147
|
+
listingStatus: r.listingStatus,
|
|
148
|
+
condition: r.condition,
|
|
149
|
+
locationCity: r.location?.city || null,
|
|
150
|
+
locationState: r.location?.state || null,
|
|
151
|
+
locationZip: r.location?.zip || null,
|
|
152
|
+
createdAt: r.createdAt,
|
|
153
|
+
}],
|
|
154
|
+
offers: r.price != null ? [{
|
|
155
|
+
refId: r.localId,
|
|
156
|
+
price: r.price,
|
|
157
|
+
priceCurrency: r.currency,
|
|
158
|
+
status: 'active',
|
|
159
|
+
}] : [],
|
|
160
|
+
media: r.photos.length > 0 ? {
|
|
161
|
+
[r.localId]: r.photos.map((url, i) => ({
|
|
162
|
+
mediaType: 'photo',
|
|
163
|
+
filePath: url,
|
|
164
|
+
sortOrder: i,
|
|
165
|
+
})),
|
|
166
|
+
} : {},
|
|
167
|
+
}));
|
|
168
|
+
res.json({
|
|
169
|
+
peers: dhtResults.length,
|
|
170
|
+
reffoTotal: reffoData.total,
|
|
171
|
+
results: [...dhtResults, ...reffoResults],
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
await dht.start((peerCount) => {
|
|
175
|
+
(0, health_1.setDhtStatus)({ connected: dht.isConnected, peers: peerCount });
|
|
176
|
+
});
|
|
177
|
+
(0, health_1.setDhtStatus)({ connected: dht.isConnected, peers: dht.peerCount });
|
|
178
|
+
// Start HTTP server
|
|
179
|
+
const server = app.listen(PORT, () => {
|
|
180
|
+
console.log(`[Beacon] Reffo Beacon running on http://localhost:${PORT}`);
|
|
181
|
+
console.log(`[Beacon] ID: ${BEACON_ID.slice(0, 16)}...`);
|
|
182
|
+
console.log(`[Beacon] Endpoints:`);
|
|
183
|
+
console.log(` GET / - Web UI`);
|
|
184
|
+
console.log(` GET /health - Beacon status`);
|
|
185
|
+
console.log(` GET /taxonomy - Category taxonomy`);
|
|
186
|
+
console.log(` GET /refs - List refs`);
|
|
187
|
+
console.log(` POST /refs - Create ref`);
|
|
188
|
+
console.log(` POST /refs/:id/media - Upload media`);
|
|
189
|
+
console.log(` GET /offers - List offers`);
|
|
190
|
+
console.log(` POST /offers - Create offer`);
|
|
191
|
+
console.log(` GET /negotiations - List negotiations`);
|
|
192
|
+
console.log(` POST /negotiations - Create proposal`);
|
|
193
|
+
console.log(` GET /search?q=... - Search peer network`);
|
|
194
|
+
});
|
|
195
|
+
// Graceful shutdown
|
|
196
|
+
const shutdown = async () => {
|
|
197
|
+
console.log('\n[Beacon] Shutting down...');
|
|
198
|
+
server.close();
|
|
199
|
+
// Force exit after 2s if DHT hangs
|
|
200
|
+
const forceExit = setTimeout(() => process.exit(0), 2000);
|
|
201
|
+
try {
|
|
202
|
+
await dht.stop();
|
|
203
|
+
}
|
|
204
|
+
catch { }
|
|
205
|
+
clearTimeout(forceExit);
|
|
206
|
+
process.exit(0);
|
|
207
|
+
};
|
|
208
|
+
process.on('SIGINT', shutdown);
|
|
209
|
+
process.on('SIGTERM', shutdown);
|
|
210
|
+
}
|
|
211
|
+
main().catch((err) => {
|
|
212
|
+
console.error('[Beacon] Fatal error:', err);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Category Schema Definitions for Reffo Refs
|
|
3
|
+
*
|
|
4
|
+
* Each category schema defines:
|
|
5
|
+
* - schemaOrgType: The Schema.org type (e.g., "Car", "SingleFamilyResidence")
|
|
6
|
+
* - traits: Array of trait names this category composes
|
|
7
|
+
* - conditionOptions: Category-appropriate condition values
|
|
8
|
+
* - attributes: Form field definitions with Schema.org property mappings
|
|
9
|
+
* - buildSchemaOrg(): Transforms flat attributes into Schema.org JSON-LD
|
|
10
|
+
*/
|
|
11
|
+
export interface AttributeField {
|
|
12
|
+
key: string;
|
|
13
|
+
label: string;
|
|
14
|
+
type: 'text' | 'number' | 'select' | 'boolean';
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
options?: string[];
|
|
17
|
+
schemaOrg?: string;
|
|
18
|
+
summary?: boolean;
|
|
19
|
+
unit?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CategorySchema {
|
|
22
|
+
schemaOrgType: string;
|
|
23
|
+
additionalType?: string;
|
|
24
|
+
traits: string[];
|
|
25
|
+
conditionOptions: string[];
|
|
26
|
+
attributes: AttributeField[];
|
|
27
|
+
buildSchemaOrg(attrs: Record<string, unknown>): Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
declare const defaultSchema: CategorySchema;
|
|
30
|
+
/**
|
|
31
|
+
* Map of "Category|Subcategory" → CategorySchema.
|
|
32
|
+
* Use getCategorySchema(category, subcategory) for lookup.
|
|
33
|
+
*/
|
|
34
|
+
declare const CATEGORY_SCHEMAS: Record<string, CategorySchema>;
|
|
35
|
+
/**
|
|
36
|
+
* Look up the CategorySchema for a given category + subcategory.
|
|
37
|
+
* Returns defaultSchema when no exact match found.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getCategorySchema(category?: string, subcategory?: string): CategorySchema;
|
|
40
|
+
/**
|
|
41
|
+
* Build a Schema.org JSON-LD object from a ref's attributes and category schema.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildSchemaOrgLD(category: string | undefined, subcategory: string | undefined, attrs: Record<string, unknown>, baseFields: {
|
|
44
|
+
name?: string;
|
|
45
|
+
description?: string;
|
|
46
|
+
price?: number;
|
|
47
|
+
currency?: string;
|
|
48
|
+
condition?: string;
|
|
49
|
+
image?: string;
|
|
50
|
+
sku?: string;
|
|
51
|
+
createdAt?: string;
|
|
52
|
+
updatedAt?: string;
|
|
53
|
+
offerStatus?: string;
|
|
54
|
+
sellerId?: string;
|
|
55
|
+
offerLocation?: string;
|
|
56
|
+
}): Record<string, unknown>;
|
|
57
|
+
export declare function getAttributeKeys(category?: string, subcategory?: string): string[];
|
|
58
|
+
export { CATEGORY_SCHEMAS, defaultSchema };
|
|
59
|
+
//# sourceMappingURL=ref-schemas.d.ts.map
|