holosphere 1.0.1 → 1.0.2
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/index.js +63 -164
- package/package.json +1 -2
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import h3 from 'h3-js';
|
|
1
|
+
import * as h3 from 'h3-js';
|
|
2
2
|
import OpenAI from 'openai';
|
|
3
3
|
import Gun from 'gun'
|
|
4
4
|
import Ajv2019 from 'ajv/dist/2019.js'
|
|
@@ -6,141 +6,53 @@ import { createHash } from "crypto";
|
|
|
6
6
|
|
|
7
7
|
class HoloSphere {
|
|
8
8
|
constructor(appname, openaikey = null) {
|
|
9
|
+
this.appname = appname;
|
|
9
10
|
this.validator = new Ajv2019({ allErrors: false, strict: false });
|
|
10
11
|
this.gun = Gun({
|
|
11
12
|
peers: ['https://59.src.eco/gun'],
|
|
12
|
-
axe: false
|
|
13
|
-
// uuid: (content) => { // generate a unique id for each node
|
|
14
|
-
// console.log('uuid', content);
|
|
15
|
-
// return content;}
|
|
13
|
+
axe: false
|
|
16
14
|
});
|
|
17
15
|
|
|
18
|
-
this.gun = gun.get(appname)
|
|
19
16
|
if (openaikey != null) {
|
|
20
17
|
this.openai = new OpenAI({
|
|
21
18
|
apiKey: openaikey,
|
|
22
19
|
});
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
//this.bot.command('sethex', async (ctx) => { this.setHex(ctx) }) TODO: MOVE HERE FROM SETTINGS
|
|
26
|
-
|
|
27
|
-
this.bot.command('resethex', async (ctx) => {
|
|
28
|
-
let chatID = ctx.message.chat.id;
|
|
29
|
-
let hex = (await this.db.get('settings', chatID)).hex
|
|
30
|
-
this.delete(hex, ctx.message.text.split(' ')[1])
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
this.bot.command('get', async (ctx) => {
|
|
34
|
-
const chatID = ctx.message.chat.id;
|
|
35
|
-
const lense = ctx.message.text.split(' ')[1];
|
|
36
|
-
if (!lense) {
|
|
37
|
-
return ctx.reply('Please specify a tag.');
|
|
38
|
-
}
|
|
39
|
-
let hex = (await this.db.get('settings', chatID)).hex
|
|
40
|
-
//let hex = settings.hex
|
|
41
|
-
console.log('hex', hex)
|
|
42
|
-
|
|
43
|
-
let data = await this.get(ctx, hex, lense)
|
|
44
|
-
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
this.bot.command('gethex', async (ctx) => {
|
|
48
|
-
let settings = await this.db.get('settings', chatID)
|
|
49
|
-
let id = settings.hex ? settings.hex : 'Hex not set, use /sethex'
|
|
50
|
-
ctx.reply(id)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
this.bot.command('compute', async (ctx) => {
|
|
54
|
-
const chatID = ctx.message.chat.id;
|
|
55
|
-
let operation = ctx.message.text.split(' ')[1];
|
|
56
|
-
if (operation != 'sum') {
|
|
57
|
-
ctx.reply('Operation not implemented')
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
let lense = ctx.message.text.split(' ')[2]
|
|
61
|
-
if (!lense) {
|
|
62
|
-
ctx.reply('Please specify a lense where to perform the operation ')
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
let hex = (await this.db.get('settings', chatID)).hex
|
|
66
|
-
await this.compute(hex, lense, operation)
|
|
67
|
-
|
|
68
|
-
// let parentInfo = await this.getCellInfo(parent)
|
|
69
|
-
// parentInfo.wisdom[id] = report
|
|
70
|
-
// //update summary
|
|
71
|
-
// let summary = await this.summarize(Object.values(parentInfo.wisdom).join('\n'))
|
|
72
|
-
// parentInfo.summary = summary
|
|
73
|
-
|
|
74
|
-
// await this.db.put('cell', parentInfo)
|
|
75
|
-
// return parentInfo
|
|
76
|
-
|
|
77
|
-
// let content = await this.db.getAll(hex+'/tags')
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
this.bot.command('cast', async (ctx) => {
|
|
84
|
-
if (!ctx.message.reply_to_message) {
|
|
85
|
-
return ctx.reply('Please reply to a message you want to tag.');
|
|
86
|
-
}
|
|
87
|
-
const tags = ctx.message.text.split(' ').slice(1);
|
|
88
|
-
if (tags.length === 0) {
|
|
89
|
-
return ctx.reply('Please provide at least one tag.');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const messageID = ctx.message.reply_to_message.message_id;
|
|
93
|
-
const chatID = ctx.message.chat.id;
|
|
94
|
-
const messageContent = ctx.message.reply_to_message.text;
|
|
95
|
-
let settings = await this.db.get('settings', chatID)
|
|
96
|
-
let id = settings.hex ? settings.hex : 'Hex not set, use /sethex'
|
|
97
|
-
//create root node for the item
|
|
98
|
-
let node = await this.gun.get(chatID + '/' + messageID).put({ id: chatID + '/' + messageID, content: messageContent })
|
|
99
|
-
for (let tag of tags) {
|
|
100
|
-
await this.gun.get(id).get(tag).set(node)
|
|
101
|
-
this.upcast(id, tag, node)
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
this.bot.command('publish', async (ctx) => {
|
|
106
|
-
console.log(ctx.message)
|
|
107
|
-
if (!ctx.message.reply_to_message) {
|
|
108
|
-
return ctx.reply('Please reply to a message you want to tag.');
|
|
109
|
-
}
|
|
110
|
-
const tags = ctx.message.text.split(' ').slice(1);
|
|
111
|
-
if (tags.length === 0) {
|
|
112
|
-
return ctx.reply('Please provide at least one tag.');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const messageID = ctx.message.reply_to_message.message_id;
|
|
116
|
-
const chatID = ctx.message.chat.id;
|
|
117
|
-
const messageContent = ctx.message.reply_to_message.text;
|
|
118
|
-
let settings = await this.db.get('settings', chatID)
|
|
119
|
-
let hex = settings.hex
|
|
120
|
-
|
|
121
|
-
for (let tag of tags) {
|
|
122
|
-
let node = await this.gun.get(chatID + '/' + messageID).put({ id: chatID + '/' + messageID, content: messageContent })
|
|
123
|
-
await this.put(hex, tag, node)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
ctx.reply('Tag published.');
|
|
127
|
-
});
|
|
128
|
-
|
|
129
22
|
}
|
|
130
23
|
|
|
131
24
|
async setSchema(lense, schema) {
|
|
132
25
|
return new Promise((resolve, reject) => {
|
|
133
|
-
this.
|
|
26
|
+
this.gun.get(this.appname).get(lense).get('schema').put(JSON.stringify(schema), ack => {
|
|
134
27
|
if (ack.err) {
|
|
135
28
|
resolve(new Error('Failed to add schema: ' + ack.err));
|
|
136
29
|
} else {
|
|
137
|
-
console.log('Schema added successfully under
|
|
30
|
+
console.log('Schema added successfully under lense:', lense);
|
|
138
31
|
resolve(ack);
|
|
139
32
|
}
|
|
140
33
|
})
|
|
141
34
|
})
|
|
142
35
|
}
|
|
143
36
|
|
|
37
|
+
async getSchema(lense) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
this.gun.get(this.appname).get(lense).get('schema').once(data => {
|
|
40
|
+
if (data) {
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(data);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
resolve(null)
|
|
47
|
+
}
|
|
48
|
+
resolve(parsed);
|
|
49
|
+
} else {
|
|
50
|
+
resolve(null);
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
144
56
|
async setHex(ctx) {
|
|
145
57
|
const chatID = ctx.message.chat.id;
|
|
146
58
|
const hex = ctx.message.text.split(' ')[1];
|
|
@@ -159,32 +71,20 @@ class HoloSphere {
|
|
|
159
71
|
}
|
|
160
72
|
|
|
161
73
|
async delete(id, tag) {
|
|
162
|
-
await this.gun.get(id).get(tag).put(null)
|
|
74
|
+
await this.gun.get(this.appname).get(id).get(tag).put(null)
|
|
163
75
|
}
|
|
164
76
|
|
|
165
77
|
async put(hex, lense, content) {
|
|
166
78
|
// Retrieve the schema for the lense
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
} catch (error) {
|
|
179
|
-
console.error(`Error fetching schema for "${lense}": ${error}`);
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Validate the content against the schema
|
|
184
|
-
const valid = this.validator.validate(schemaData, content);
|
|
185
|
-
if (!valid) {
|
|
186
|
-
console.error('Invalid content:', this.validator.errors);
|
|
187
|
-
return null;
|
|
79
|
+
console.log('HoloSphere: Putting content in lense:', lense, 'at hex:', hex, 'content:', content)
|
|
80
|
+
let schema = await this.getSchema(lense)
|
|
81
|
+
if (schema) {
|
|
82
|
+
// Validate the content against the schema
|
|
83
|
+
const valid = this.validator.validate(schema, content);
|
|
84
|
+
if (!valid) {
|
|
85
|
+
console.error('Not committing invalid content:', this.validator.errors);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
188
88
|
}
|
|
189
89
|
|
|
190
90
|
// Create a node for the content
|
|
@@ -193,16 +93,16 @@ class HoloSphere {
|
|
|
193
93
|
let noderef;
|
|
194
94
|
|
|
195
95
|
if (content.id) { //use the user-defined id. Important to be able to send updates using put
|
|
196
|
-
noderef = this.gun.get(lense).get(content.id).put(payload)
|
|
197
|
-
this.gun.get(hex.toString()).get(lense).get(content.id).put(payload)
|
|
96
|
+
noderef = this.gun.get(this.appname).get(lense).get(content.id).put(payload)
|
|
97
|
+
this.gun.get(this.appname).get(hex.toString()).get(lense).get(content.id).put(payload)
|
|
198
98
|
} else { // create a content-addressable reference like IPFS. Note: no updates possible using put
|
|
199
99
|
const hash = createHash("sha256").update(payload).digest("hex");
|
|
200
|
-
noderef = this.gun.get(lense).get(hash).put(payload)
|
|
201
|
-
this.gun.get(hex.toString()).get(lense).get(hash).put(payload)
|
|
100
|
+
noderef = this.gun.get(this.appname).get(lense).get(hash).put(payload)
|
|
101
|
+
this.gun.get(this.appname).get(hex.toString()).get(lense).get(hash).put(payload)
|
|
202
102
|
}
|
|
203
103
|
|
|
204
104
|
// return new Promise((resolve, reject) => {
|
|
205
|
-
// this.gun.get(hex.toString()).get(lense).set(noderef, ack => {
|
|
105
|
+
// this.gun.get(this.appname).get(hex.toString()).get(lense).set(noderef, ack => {
|
|
206
106
|
// if (ack.err) {
|
|
207
107
|
// reject(new Error('Failed to add content: ' + ack.err));
|
|
208
108
|
// } else {
|
|
@@ -217,36 +117,26 @@ class HoloSphere {
|
|
|
217
117
|
async get(hex, lense) {
|
|
218
118
|
// Wrap the GunDB operation in a promise
|
|
219
119
|
//retrieve lense schema
|
|
220
|
-
const
|
|
221
|
-
this.gun.get(lense).get('schema').once(data => {
|
|
222
|
-
if (data) {
|
|
223
|
-
resolve(data);
|
|
224
|
-
} else {
|
|
225
|
-
resolve(null);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
})
|
|
229
|
-
)
|
|
120
|
+
const schema = await this.getSchema(lense);
|
|
230
121
|
|
|
231
|
-
if (!
|
|
122
|
+
if (!schema) {
|
|
232
123
|
console.log('The schema for "' + lense + '" is not defined');
|
|
233
|
-
return null;
|
|
124
|
+
// return null; // No schema found, return null if strict about it
|
|
234
125
|
}
|
|
235
126
|
|
|
236
127
|
return new Promise(async (resolve, reject) => {
|
|
237
128
|
let output = []
|
|
238
129
|
let counter = 0
|
|
239
|
-
this.gun.get(hex.toString()).get(lense).once((data, key) => {
|
|
130
|
+
this.gun.get(this.appname).get(hex.toString()).get(lense).once((data, key) => {
|
|
240
131
|
if (data) {
|
|
241
132
|
const maplenght = Object.keys(data).length - 1
|
|
242
|
-
|
|
133
|
+
console.log('Map length:', maplenght)
|
|
134
|
+
this.gun.get(this.appname).get(hex.toString()).get(lense).map().once(async (itemdata, key) => {
|
|
243
135
|
counter += 1
|
|
244
136
|
if (itemdata) {
|
|
245
|
-
|
|
246
|
-
|
|
247
137
|
// if (itemdata._["#"]) {
|
|
248
138
|
// // If the data is a reference, fetch the actual content
|
|
249
|
-
// itemdata = await this.gun.get(itemdata._['#']).then();
|
|
139
|
+
// itemdata = await this.gun.get(this.appname).get(itemdata._['#']).then();
|
|
250
140
|
// console.log("Data :",itemdata)
|
|
251
141
|
// }
|
|
252
142
|
var parsed = {}
|
|
@@ -254,14 +144,20 @@ class HoloSphere {
|
|
|
254
144
|
parsed = JSON.parse(itemdata);
|
|
255
145
|
} catch (e) {
|
|
256
146
|
console.log('Invalid JSON:', itemdata);
|
|
147
|
+
parsed = itemdata //return the raw data
|
|
257
148
|
}
|
|
258
149
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
150
|
+
if (schema) {
|
|
151
|
+
let valid = this.validator.validate(schema, parsed);
|
|
152
|
+
if (!valid || parsed == null || parsed == undefined) {
|
|
153
|
+
console.log('Removing Invalid content:', this.validator.errors);
|
|
154
|
+
this.gun.get(this.appname).get(hex).get(lense).get(key).put(null);
|
|
263
155
|
|
|
264
|
-
|
|
156
|
+
} else {
|
|
157
|
+
output.push(parsed);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
265
161
|
output.push(parsed);
|
|
266
162
|
}
|
|
267
163
|
}
|
|
@@ -312,7 +208,7 @@ class HoloSphere {
|
|
|
312
208
|
console.log('Content:', content);
|
|
313
209
|
let computed = await this.summarize(content.join('\n'))
|
|
314
210
|
console.log('Computed:', computed)
|
|
315
|
-
let node = await this.gun.get(parent + '_summary').put({ id: parent + '_summary', content: computed })
|
|
211
|
+
let node = await this.gun.get(this.appname).get(parent + '_summary').put({ id: parent + '_summary', content: computed })
|
|
316
212
|
|
|
317
213
|
this.put(parent, lense, node);
|
|
318
214
|
this.compute(parent, lense, operation)
|
|
@@ -322,10 +218,10 @@ class HoloSphere {
|
|
|
322
218
|
let entities = {};
|
|
323
219
|
|
|
324
220
|
// Get list out of Gun
|
|
325
|
-
this.gun.get(hex).get(lense).map().once((data, key) => {
|
|
221
|
+
this.gun.get(this.appname).get(hex).get(lense).map().once((data, key) => {
|
|
326
222
|
//entities = data;
|
|
327
223
|
//const id = Object.keys(entities)[0] // since this would be in object form, you can manipulate it as you would like.
|
|
328
|
-
this.gun.get(hex).get(lense).put({ [key]: null })
|
|
224
|
+
this.gun.get(this.appname).get(hex).get(lense).put({ [key]: null })
|
|
329
225
|
})
|
|
330
226
|
}
|
|
331
227
|
|
|
@@ -364,15 +260,18 @@ class HoloSphere {
|
|
|
364
260
|
|
|
365
261
|
async upcast(hex, lense, content) {
|
|
366
262
|
let res = h3.getResolution(hex)
|
|
263
|
+
|
|
367
264
|
if (res == 0)
|
|
368
265
|
return content
|
|
369
266
|
|
|
370
267
|
console.log('Upcasting ', hex, lense, content)
|
|
371
268
|
let parent = h3.cellToParent(hex, res - 1)
|
|
372
269
|
await this.put(parent, lense, content)
|
|
270
|
+
|
|
373
271
|
return this.upcast(parent, lense, content)
|
|
374
272
|
}
|
|
375
273
|
|
|
274
|
+
|
|
376
275
|
// send information upwards, triggers the parent to update its summary
|
|
377
276
|
async updateParent(id, report) {
|
|
378
277
|
let cellinfo = await this.getCellInfo(id)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holosphere",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Holonic Geospatial Communication Infrastructure based on h3.js and gun.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"license": "GPL-3.0-or-later",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"ajv": "^8.12.0",
|
|
14
|
-
"dotenv": "^16.4.5",
|
|
15
14
|
"gun": "^0.2020.1239",
|
|
16
15
|
"h3-js": "^4.1.0",
|
|
17
16
|
"openai": "^4.29.2"
|