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