neuronum 6.0.0__tar.gz → 7.0.0__tar.gz
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.
Potentially problematic release.
This version of neuronum might be problematic. Click here for more details.
- {neuronum-6.0.0/neuronum.egg-info → neuronum-7.0.0}/PKG-INFO +15 -89
- {neuronum-6.0.0 → neuronum-7.0.0}/README.md +13 -88
- {neuronum-6.0.0 → neuronum-7.0.0}/cli/main.py +304 -217
- {neuronum-6.0.0 → neuronum-7.0.0/neuronum.egg-info}/PKG-INFO +15 -89
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum.egg-info/requires.txt +1 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/setup.py +2 -1
- {neuronum-6.0.0 → neuronum-7.0.0}/LICENSE.md +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/cli/__init__.py +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum/__init__.py +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum/neuronum.py +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum.egg-info/SOURCES.txt +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum.egg-info/dependency_links.txt +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum.egg-info/entry_points.txt +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/neuronum.egg-info/top_level.txt +0 -0
- {neuronum-6.0.0 → neuronum-7.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -19,6 +19,7 @@ Requires-Dist: questionary
|
|
|
19
19
|
Requires-Dist: python-dotenv
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: psutil
|
|
22
|
+
Requires-Dist: jinja2
|
|
22
23
|
Dynamic: author
|
|
23
24
|
Dynamic: author-email
|
|
24
25
|
Dynamic: classifier
|
|
@@ -104,102 +105,27 @@ neuronum connect-cell # connect Cell
|
|
|
104
105
|
|
|
105
106
|
|
|
106
107
|
### **Build On Neuronum**
|
|
107
|
-
|
|
108
|
+
Visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples) to gain deeper knowledge on how to build on Neuronum.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
To get started, initialize a new Node with the command below.
|
|
110
111
|
```sh
|
|
111
|
-
neuronum init-node
|
|
112
|
+
neuronum init-node
|
|
112
113
|
```
|
|
113
114
|
|
|
114
|
-
This command
|
|
115
|
+
This command will prompt you for a description (e.g., Test App) and will create
|
|
115
116
|
|
|
116
|
-
.
|
|
117
|
-
|
|
118
|
-
NODE=your_node_id
|
|
119
|
-
HOST=your_cell_id
|
|
120
|
-
PASSWORD=your_password
|
|
121
|
-
NETWORK=neuronum.net
|
|
122
|
-
SYNAPSE=your_synapse # auth token
|
|
123
|
-
```
|
|
117
|
+
1. A Stream (STX) so your App can receive requests, and a Transmitter (TX) to match those requests
|
|
118
|
+
2. A new directory named "Test App_<your_node_id>" with the following files
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
```python
|
|
127
|
-
import asyncio
|
|
128
|
-
import neuronum
|
|
129
|
-
import os
|
|
130
|
-
from dotenv import load_dotenv
|
|
131
|
-
|
|
132
|
-
load_dotenv()
|
|
133
|
-
host = os.getenv("HOST")
|
|
134
|
-
password = os.getenv("PASSWORD")
|
|
135
|
-
network = os.getenv("NETWORK")
|
|
136
|
-
synapse = os.getenv("SYNAPSE")
|
|
137
|
-
|
|
138
|
-
cell = neuronum.Cell(
|
|
139
|
-
host=host,
|
|
140
|
-
password=password,
|
|
141
|
-
network=network,
|
|
142
|
-
synapse=synapse
|
|
143
|
-
)
|
|
120
|
+
.env: Stores your Node's credentials for connecting to the network.
|
|
144
121
|
|
|
145
|
-
|
|
146
|
-
STX = "id::stx"
|
|
147
|
-
async for operation in cell.sync(STX):
|
|
148
|
-
txID = operation.get("txID")
|
|
149
|
-
client = operation.get("operator")
|
|
150
|
-
|
|
151
|
-
if txID == "id::tx":
|
|
152
|
-
data = {
|
|
153
|
-
"json": f"Hello {client}",
|
|
154
|
-
"html": f"""
|
|
155
|
-
<!DOCTYPE html>
|
|
156
|
-
<html>
|
|
157
|
-
<head>
|
|
158
|
-
<meta charset="UTF-8">
|
|
159
|
-
<title>Greeting Node</title>
|
|
160
|
-
</head>
|
|
161
|
-
<body>
|
|
162
|
-
<div class="card">
|
|
163
|
-
<h1>Hello, {client}</h1>
|
|
164
|
-
</div>
|
|
165
|
-
</body>
|
|
166
|
-
</html>
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
await cell.tx_response(txID, client, data)
|
|
122
|
+
app.py: The main Python script that contains your Node's core logic.
|
|
171
123
|
|
|
172
|
-
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
config.json (required if you want to make your app accessible to Cellai (currently in testing))
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"data_gateways": [
|
|
179
|
-
{
|
|
180
|
-
"type": "stream",
|
|
181
|
-
"id": "id::stx",
|
|
182
|
-
"info": "provide a detailed description about the stream"
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"type": "transmitter",
|
|
186
|
-
"id": "id::tx",
|
|
187
|
-
"info": "provide a detailed description about the transmitter"
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
"type": "circuit",
|
|
191
|
-
"id": "id::ctx",
|
|
192
|
-
"info": "provide a detailed description about the circuit"
|
|
193
|
-
}
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
```
|
|
124
|
+
NODE.md: Public documentation that provides instructions for interacting with your Node.
|
|
197
125
|
|
|
198
|
-
|
|
199
|
-
```
|
|
200
|
-
### NODE.md: Create a detailed Markdown File on how to interact with this Node
|
|
201
|
-
```
|
|
126
|
+
config.json: A configuration file that stores metadata about your app and enables Cellai to interact with your Node's data gateways.
|
|
202
127
|
|
|
128
|
+
ping.html: A static HTML file used to render web-based responses.
|
|
203
129
|
|
|
204
130
|
Change into Node folder
|
|
205
131
|
```sh
|
|
@@ -247,6 +173,6 @@ asyncio.run(main())
|
|
|
247
173
|
neuronum activate --tx id::tx 'say:hello'
|
|
248
174
|
```
|
|
249
175
|
|
|
250
|
-
#### **Cellai**
|
|
251
|
-
Cellai is
|
|
176
|
+
#### **Cellai (in Testing)**
|
|
177
|
+
Cellai is an AI tool for developers to test their apps built on Neuronum and will soon be published to the Google Play Store.
|
|
252
178
|
|
|
@@ -71,102 +71,27 @@ neuronum connect-cell # connect Cell
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
### **Build On Neuronum**
|
|
74
|
-
|
|
74
|
+
Visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples) to gain deeper knowledge on how to build on Neuronum.
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
To get started, initialize a new Node with the command below.
|
|
77
77
|
```sh
|
|
78
|
-
neuronum init-node
|
|
78
|
+
neuronum init-node
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
This command
|
|
81
|
+
This command will prompt you for a description (e.g., Test App) and will create
|
|
82
82
|
|
|
83
|
-
.
|
|
84
|
-
|
|
85
|
-
NODE=your_node_id
|
|
86
|
-
HOST=your_cell_id
|
|
87
|
-
PASSWORD=your_password
|
|
88
|
-
NETWORK=neuronum.net
|
|
89
|
-
SYNAPSE=your_synapse # auth token
|
|
90
|
-
```
|
|
83
|
+
1. A Stream (STX) so your App can receive requests, and a Transmitter (TX) to match those requests
|
|
84
|
+
2. A new directory named "Test App_<your_node_id>" with the following files
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
```python
|
|
94
|
-
import asyncio
|
|
95
|
-
import neuronum
|
|
96
|
-
import os
|
|
97
|
-
from dotenv import load_dotenv
|
|
98
|
-
|
|
99
|
-
load_dotenv()
|
|
100
|
-
host = os.getenv("HOST")
|
|
101
|
-
password = os.getenv("PASSWORD")
|
|
102
|
-
network = os.getenv("NETWORK")
|
|
103
|
-
synapse = os.getenv("SYNAPSE")
|
|
104
|
-
|
|
105
|
-
cell = neuronum.Cell(
|
|
106
|
-
host=host,
|
|
107
|
-
password=password,
|
|
108
|
-
network=network,
|
|
109
|
-
synapse=synapse
|
|
110
|
-
)
|
|
86
|
+
.env: Stores your Node's credentials for connecting to the network.
|
|
111
87
|
|
|
112
|
-
|
|
113
|
-
STX = "id::stx"
|
|
114
|
-
async for operation in cell.sync(STX):
|
|
115
|
-
txID = operation.get("txID")
|
|
116
|
-
client = operation.get("operator")
|
|
117
|
-
|
|
118
|
-
if txID == "id::tx":
|
|
119
|
-
data = {
|
|
120
|
-
"json": f"Hello {client}",
|
|
121
|
-
"html": f"""
|
|
122
|
-
<!DOCTYPE html>
|
|
123
|
-
<html>
|
|
124
|
-
<head>
|
|
125
|
-
<meta charset="UTF-8">
|
|
126
|
-
<title>Greeting Node</title>
|
|
127
|
-
</head>
|
|
128
|
-
<body>
|
|
129
|
-
<div class="card">
|
|
130
|
-
<h1>Hello, {client}</h1>
|
|
131
|
-
</div>
|
|
132
|
-
</body>
|
|
133
|
-
</html>
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
await cell.tx_response(txID, client, data)
|
|
88
|
+
app.py: The main Python script that contains your Node's core logic.
|
|
138
89
|
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
config.json (required if you want to make your app accessible to Cellai (currently in testing))
|
|
143
|
-
```json
|
|
144
|
-
{
|
|
145
|
-
"data_gateways": [
|
|
146
|
-
{
|
|
147
|
-
"type": "stream",
|
|
148
|
-
"id": "id::stx",
|
|
149
|
-
"info": "provide a detailed description about the stream"
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
"type": "transmitter",
|
|
153
|
-
"id": "id::tx",
|
|
154
|
-
"info": "provide a detailed description about the transmitter"
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"type": "circuit",
|
|
158
|
-
"id": "id::ctx",
|
|
159
|
-
"info": "provide a detailed description about the circuit"
|
|
160
|
-
}
|
|
161
|
-
]
|
|
162
|
-
}
|
|
163
|
-
```
|
|
90
|
+
NODE.md: Public documentation that provides instructions for interacting with your Node.
|
|
164
91
|
|
|
165
|
-
|
|
166
|
-
```
|
|
167
|
-
### NODE.md: Create a detailed Markdown File on how to interact with this Node
|
|
168
|
-
```
|
|
92
|
+
config.json: A configuration file that stores metadata about your app and enables Cellai to interact with your Node's data gateways.
|
|
169
93
|
|
|
94
|
+
ping.html: A static HTML file used to render web-based responses.
|
|
170
95
|
|
|
171
96
|
Change into Node folder
|
|
172
97
|
```sh
|
|
@@ -214,6 +139,6 @@ asyncio.run(main())
|
|
|
214
139
|
neuronum activate --tx id::tx 'say:hello'
|
|
215
140
|
```
|
|
216
141
|
|
|
217
|
-
#### **Cellai**
|
|
218
|
-
Cellai is
|
|
142
|
+
#### **Cellai (in Testing)**
|
|
143
|
+
Cellai is an AI tool for developers to test their apps built on Neuronum and will soon be published to the Google Play Store.
|
|
219
144
|
|
|
@@ -249,17 +249,14 @@ def delete_cell():
|
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
@click.command()
|
|
252
|
-
|
|
253
|
-
@click.option('--stream', multiple=True, default=None, help="Optional stream ID for stream.")
|
|
254
|
-
@click.option('--app', is_flag=True, help="Generate a Node with app template")
|
|
255
|
-
def init_node(sync, stream, app):
|
|
252
|
+
def init_node():
|
|
256
253
|
descr = click.prompt("Node description: Type up to 25 characters").strip()
|
|
257
254
|
if descr and len(descr) > 25:
|
|
258
255
|
click.echo("Description too long. Max 25 characters allowed.")
|
|
259
256
|
return
|
|
260
|
-
asyncio.run(async_init_node(
|
|
257
|
+
asyncio.run(async_init_node(descr))
|
|
261
258
|
|
|
262
|
-
async def async_init_node(
|
|
259
|
+
async def async_init_node(descr):
|
|
263
260
|
credentials_folder_path = Path.home() / ".neuronum"
|
|
264
261
|
env_path = credentials_folder_path / ".env"
|
|
265
262
|
|
|
@@ -308,51 +305,37 @@ async def async_init_node(sync, stream, app, descr):
|
|
|
308
305
|
click.echo(f"Error sending request: {e}")
|
|
309
306
|
return
|
|
310
307
|
|
|
311
|
-
node_filename = "
|
|
308
|
+
node_filename = descr + "_" + nodeID.replace("::node", "")
|
|
312
309
|
project_path = Path(node_filename)
|
|
313
310
|
project_path.mkdir(exist_ok=True)
|
|
314
311
|
|
|
315
312
|
env_path = project_path / ".env"
|
|
316
313
|
await asyncio.to_thread(env_path.write_text, f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
317
|
-
|
|
318
|
-
if app:
|
|
319
|
-
config_path = project_path / "config.json"
|
|
320
|
-
await asyncio.to_thread(config_path.write_text, """{
|
|
321
|
-
"data_gateways": [
|
|
322
|
-
{
|
|
323
|
-
"type": "stream",
|
|
324
|
-
"id": "id::stx",
|
|
325
|
-
"info": "provide a detailed description about the stream"
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
"type": "transmitter",
|
|
329
|
-
"id": "id::tx",
|
|
330
|
-
"info": "provide a detailed description about the transmitter"
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
"type": "circuit",
|
|
334
|
-
"id": "id::ctx",
|
|
335
|
-
"info": "provide a detailed description about the circuit"
|
|
336
|
-
}
|
|
337
|
-
]
|
|
338
|
-
}
|
|
339
|
-
"""
|
|
340
|
-
)
|
|
341
314
|
|
|
342
|
-
|
|
343
|
-
|
|
315
|
+
stx_descr = f"{nodeID} App"
|
|
316
|
+
partners = ["private"]
|
|
317
|
+
stxID = await cell.create_stx(stx_descr, partners)
|
|
344
318
|
|
|
345
|
-
|
|
319
|
+
tx_descr = f"Greet {nodeID}"
|
|
320
|
+
key_values = {
|
|
321
|
+
"ping": "pong",
|
|
322
|
+
}
|
|
323
|
+
STX = stxID
|
|
324
|
+
label = "ping:pong"
|
|
325
|
+
partners = ["private"]
|
|
326
|
+
txID = await cell.create_tx(tx_descr, key_values, STX, label, partners)
|
|
346
327
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
sync_path = project_path / f"sync_{stx.replace('::stx', '')}.py"
|
|
350
|
-
sync_path.write_text(f"""\
|
|
328
|
+
app_path = project_path / "app.py"
|
|
329
|
+
app_path.write_text(f"""\
|
|
351
330
|
import asyncio
|
|
352
331
|
import neuronum
|
|
353
332
|
import os
|
|
354
333
|
from dotenv import load_dotenv
|
|
334
|
+
from jinja2 import Environment, FileSystemLoader
|
|
355
335
|
|
|
336
|
+
env = Environment(loader=FileSystemLoader('.'))
|
|
337
|
+
template = env.get_template('ping.html')
|
|
338
|
+
|
|
356
339
|
load_dotenv()
|
|
357
340
|
host = os.getenv("HOST")
|
|
358
341
|
password = os.getenv("PASSWORD")
|
|
@@ -366,188 +349,281 @@ cell = neuronum.Cell(
|
|
|
366
349
|
synapse=synapse
|
|
367
350
|
)
|
|
368
351
|
|
|
369
|
-
async def main():
|
|
370
|
-
STX = "{
|
|
371
|
-
async for operation in cell.sync(STX):
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
ts = operation.get("time")
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
352
|
+
async def main():
|
|
353
|
+
STX = "{stxID}"
|
|
354
|
+
async for operation in cell.sync(STX):
|
|
355
|
+
txID = operation.get("txID")
|
|
356
|
+
client = operation.get("operator")
|
|
357
|
+
ts = operation.get("time")
|
|
358
|
+
data = operation.get("data")
|
|
359
|
+
operation_id = operation.get("operationID")
|
|
360
|
+
|
|
361
|
+
if txID == "{txID}":
|
|
362
|
+
|
|
363
|
+
def render_html_template(client, ts, data, operation_id):
|
|
364
|
+
return template.render(client=client, ts=ts, data=data, operation_id=operation_id)
|
|
381
365
|
|
|
366
|
+
html_content = render_html_template(client, ts, data, operation_id)
|
|
382
367
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
import asyncio
|
|
388
|
-
import neuronum
|
|
389
|
-
import os
|
|
390
|
-
from dotenv import load_dotenv
|
|
391
|
-
import time
|
|
392
|
-
|
|
393
|
-
load_dotenv()
|
|
394
|
-
host = os.getenv("HOST")
|
|
395
|
-
password = os.getenv("PASSWORD")
|
|
396
|
-
network = os.getenv("NETWORK")
|
|
397
|
-
synapse = os.getenv("SYNAPSE")
|
|
368
|
+
data = {{
|
|
369
|
+
"json": f"{{operation_id}} - Reply from {nodeID}: Pinged by {{client}} at {{ts}} with data: {{data}}",
|
|
370
|
+
"html": html_content
|
|
371
|
+
}}
|
|
398
372
|
|
|
399
|
-
cell
|
|
400
|
-
host=host,
|
|
401
|
-
password=password,
|
|
402
|
-
network=network,
|
|
403
|
-
synapse=synapse
|
|
404
|
-
)
|
|
373
|
+
await cell.notify(f"{{client}}", "{nodeID} Ping","Pinged successfully")
|
|
405
374
|
|
|
406
|
-
|
|
407
|
-
STX = "{stx}"
|
|
408
|
-
label = "your_label"
|
|
409
|
-
|
|
410
|
-
while True:
|
|
411
|
-
data = {{
|
|
412
|
-
"key1": "value1",
|
|
413
|
-
"key2": "value2",
|
|
414
|
-
"key3": "value3",
|
|
415
|
-
}}
|
|
416
|
-
await cell.stream(label, data, STX)
|
|
417
|
-
time.sleep(5)
|
|
375
|
+
await cell.tx_response(txID, client, data)
|
|
418
376
|
|
|
419
377
|
asyncio.run(main())
|
|
420
378
|
""")
|
|
421
379
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
380
|
+
html_path = project_path / "ping.html"
|
|
381
|
+
html_content = f"""\
|
|
382
|
+
<!DOCTYPE html>
|
|
383
|
+
<html>
|
|
384
|
+
<head>
|
|
385
|
+
<style>
|
|
386
|
+
body {{
|
|
387
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
388
|
+
background-color: #121212;
|
|
389
|
+
color: #e0e0e0;
|
|
390
|
+
margin: 0;
|
|
391
|
+
padding: 0;
|
|
392
|
+
display: flex;
|
|
393
|
+
justify-content: center;
|
|
394
|
+
align-items: center;
|
|
395
|
+
min-height: 100vh;
|
|
396
|
+
}}
|
|
397
|
+
|
|
398
|
+
.container {{
|
|
399
|
+
background-color: #1e1e1e;
|
|
400
|
+
border-radius: 12px;
|
|
401
|
+
padding: 40px;
|
|
402
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
403
|
+
width: 100%;
|
|
404
|
+
max-width: 500px;
|
|
405
|
+
text-align: center;
|
|
406
|
+
box-sizing: border-box;
|
|
407
|
+
}}
|
|
408
|
+
|
|
409
|
+
.logo {{
|
|
410
|
+
width: 80px;
|
|
411
|
+
margin-bottom: 25px;
|
|
412
|
+
filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.1));
|
|
413
|
+
}}
|
|
414
|
+
|
|
415
|
+
h1 {{
|
|
416
|
+
font-size: 1.5em;
|
|
417
|
+
font-weight: 600;
|
|
418
|
+
margin-bottom: 5px;
|
|
419
|
+
color: #f5f5f5;
|
|
420
|
+
}}
|
|
421
|
+
|
|
422
|
+
.subtitle {{
|
|
423
|
+
font-size: 0.9em;
|
|
424
|
+
color: #a0a0a0;
|
|
425
|
+
margin-bottom: 30px;
|
|
426
|
+
}}
|
|
427
|
+
|
|
428
|
+
.data-row {{
|
|
429
|
+
background-color: #2a2a2a;
|
|
430
|
+
padding: 12px 15px;
|
|
431
|
+
border-radius: 8px;
|
|
432
|
+
margin-bottom: 10px;
|
|
433
|
+
display: flex;
|
|
434
|
+
justify-content: space-between;
|
|
435
|
+
align-items: center;
|
|
436
|
+
}}
|
|
437
|
+
|
|
438
|
+
.data-label {{
|
|
439
|
+
font-weight: 400;
|
|
440
|
+
color: #a0a0a0;
|
|
441
|
+
margin: 0;
|
|
442
|
+
}}
|
|
443
|
+
|
|
444
|
+
.data-value {{
|
|
445
|
+
font-weight: 500;
|
|
446
|
+
color: #e0e0e0;
|
|
447
|
+
margin: 0;
|
|
448
|
+
}}
|
|
449
|
+
|
|
450
|
+
.data-value.truncated {{
|
|
451
|
+
white-space: nowrap;
|
|
452
|
+
overflow: hidden;
|
|
453
|
+
text-overflow: ellipsis;
|
|
454
|
+
max-width: 60%;
|
|
455
|
+
}}
|
|
456
|
+
|
|
457
|
+
.data-value.client {{
|
|
458
|
+
color: #8cafff;
|
|
459
|
+
}}
|
|
460
|
+
.data-value.timestamp {{
|
|
461
|
+
color: #a1e8a1;
|
|
462
|
+
}}
|
|
463
|
+
.data-value.operation-id {{
|
|
464
|
+
color: #f7a2a2;
|
|
465
|
+
}}
|
|
466
|
+
</style>
|
|
467
|
+
</head>
|
|
468
|
+
<body>
|
|
469
|
+
<div class="container">
|
|
470
|
+
<img class="logo" src="https://neuronum.net/static/logo.png" alt="Neuronum Logo">
|
|
471
|
+
|
|
472
|
+
<h1>Reply from {nodeID}</h1>
|
|
473
|
+
<p class="subtitle">Pinged successfully.</p>
|
|
474
|
+
|
|
475
|
+
<div class="data-row">
|
|
476
|
+
<p class="data-label">Client</p>
|
|
477
|
+
<p class="data-value client">{{{{client}}}}</p>
|
|
478
|
+
</div>
|
|
479
|
+
|
|
480
|
+
<div class="data-row">
|
|
481
|
+
<p class="data-label">Timestamp</p>
|
|
482
|
+
<p class="data-value timestamp">{{{{ts}}}}</p>
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
<div class="data-row">
|
|
486
|
+
<p class="data-label">Data</p>
|
|
487
|
+
<p class="data-value">{{{{data}}}}</p>
|
|
488
|
+
</div>
|
|
489
|
+
|
|
490
|
+
<div class="data-row">
|
|
491
|
+
<p class="data-label">Operation ID</p>
|
|
492
|
+
<p class="data-value operation-id truncated">{{{{operation_id}}}}</p>
|
|
493
|
+
</div>
|
|
494
|
+
|
|
495
|
+
<button id="send-request-btn" class="api-button">Ping again</button>
|
|
496
|
+
</div>
|
|
429
497
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
network = os.getenv("NETWORK")
|
|
434
|
-
synapse = os.getenv("SYNAPSE")
|
|
498
|
+
<script>
|
|
499
|
+
document.getElementById('send-request-btn').addEventListener('click', () => {{
|
|
500
|
+
const apiEndpoint = 'https://neuronum.net/api/activate/{{{{txID}}}}';
|
|
435
501
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
502
|
+
const dataToSend = {{
|
|
503
|
+
"data": {{"ping": "node"}},
|
|
504
|
+
"cell": {{
|
|
505
|
+
"host": CLIENT_CELL,
|
|
506
|
+
"session": CLIENT_SESSION,
|
|
507
|
+
}}
|
|
508
|
+
}};
|
|
509
|
+
|
|
510
|
+
fetch(apiEndpoint, {{
|
|
511
|
+
method: 'POST',
|
|
512
|
+
headers: {{
|
|
513
|
+
'Content-Type': 'application/json',
|
|
514
|
+
'Accept': 'application/json'
|
|
515
|
+
}},
|
|
516
|
+
body: JSON.stringify(dataToSend)
|
|
517
|
+
}})
|
|
518
|
+
.then(response => {{
|
|
519
|
+
if (!response.ok) {{
|
|
520
|
+
throw new Error(`HTTP error! status: ${{response.status}}`);
|
|
521
|
+
}}
|
|
522
|
+
return response.json();
|
|
523
|
+
}})
|
|
524
|
+
.then(data => {{
|
|
525
|
+
if (data.success && data.response && data.response.html) {{
|
|
526
|
+
document.open();
|
|
527
|
+
document.write(data.response.html);
|
|
528
|
+
document.close();
|
|
529
|
+
console.log('API Response: Page replaced with new HTML.');
|
|
530
|
+
}} else {{
|
|
531
|
+
console.error('API Response does not contain HTML to replace the page:', data);
|
|
532
|
+
alert('API response error: Expected HTML content to replace the page.');
|
|
533
|
+
}}
|
|
534
|
+
}})
|
|
535
|
+
.catch(error => {{
|
|
536
|
+
console.error('API request failed:', error);
|
|
537
|
+
alert('API request failed. See the console for details.');
|
|
538
|
+
}});
|
|
539
|
+
}});
|
|
540
|
+
</script>
|
|
541
|
+
</body>
|
|
542
|
+
</html>
|
|
543
|
+
"""
|
|
544
|
+
html_path.write_text(html_content)
|
|
545
|
+
|
|
546
|
+
config_path = project_path / "config.json"
|
|
547
|
+
await asyncio.to_thread(
|
|
548
|
+
config_path.write_text,
|
|
549
|
+
f"""{{
|
|
550
|
+
"app_metadata": {{
|
|
551
|
+
"name": "{descr}",
|
|
552
|
+
"version": "1.0.0",
|
|
553
|
+
"author": "{host}"
|
|
554
|
+
}},
|
|
555
|
+
"data_gateways": [
|
|
556
|
+
{{
|
|
557
|
+
"type": "transmitter",
|
|
558
|
+
"id": "{txID}",
|
|
559
|
+
"info": "Ping Your Node"
|
|
560
|
+
}}
|
|
561
|
+
],
|
|
562
|
+
"legals": {{
|
|
563
|
+
"terms_and_conditions": "https://neuronum.net/legals",
|
|
564
|
+
"data_privacy": "https://neuronum.net/legals"
|
|
565
|
+
}}
|
|
566
|
+
}}"""
|
|
441
567
|
)
|
|
442
568
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
message = operation.get("data").get("message")
|
|
446
|
-
print(message)
|
|
569
|
+
nodemd_path = project_path / "NODE.md"
|
|
570
|
+
await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
|
|
447
571
|
|
|
448
|
-
|
|
449
|
-
""")
|
|
450
|
-
|
|
451
|
-
stream_path = project_path / f"stream_{stx.replace('::stx', '')}.py"
|
|
452
|
-
stream_path.write_text(f"""\
|
|
453
|
-
import asyncio
|
|
454
|
-
import neuronum
|
|
455
|
-
import os
|
|
456
|
-
from dotenv import load_dotenv
|
|
457
|
-
import time
|
|
572
|
+
Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
|
|
458
573
|
|
|
459
|
-
|
|
460
|
-
host = os.getenv("HOST")
|
|
461
|
-
password = os.getenv("PASSWORD")
|
|
462
|
-
network = os.getenv("NETWORK")
|
|
463
|
-
synapse = os.getenv("SYNAPSE")
|
|
574
|
+
***
|
|
464
575
|
|
|
465
|
-
|
|
466
|
-
host=host,
|
|
467
|
-
password=password,
|
|
468
|
-
network=network,
|
|
469
|
-
synapse=synapse
|
|
470
|
-
)
|
|
576
|
+
### 💻 Using the CLI
|
|
471
577
|
|
|
472
|
-
|
|
473
|
-
label = "Welcome to Neuronum"
|
|
474
|
-
|
|
475
|
-
while True:
|
|
476
|
-
data = {{
|
|
477
|
-
"message": "Hello, Neuronum!"
|
|
478
|
-
}}
|
|
479
|
-
await cell.stream(label, data)
|
|
480
|
-
time.sleep(5)
|
|
578
|
+
To ping this Node via the command-line interface, use the following command:
|
|
481
579
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
if app and nodeID:
|
|
580
|
+
`neuronum activate --tx {txID} 'ping:node'`
|
|
581
|
+
|
|
582
|
+
***
|
|
486
583
|
|
|
487
|
-
|
|
488
|
-
partners = ["private"]
|
|
489
|
-
stxID = await cell.create_stx(descr, partners)
|
|
584
|
+
### 🌐 Via the Web
|
|
490
585
|
|
|
586
|
+
You can also interact with this Node by simply visiting this URL in your web browser:
|
|
491
587
|
|
|
492
|
-
|
|
493
|
-
key_values = {
|
|
494
|
-
"say": "hello",
|
|
495
|
-
}
|
|
496
|
-
STX = stxID
|
|
497
|
-
label = "say:hello"
|
|
498
|
-
partners = ["private"]
|
|
499
|
-
txID = await cell.create_tx(descr, key_values, STX, label, partners)
|
|
588
|
+
[https://neuronum.net/tx/{txID}](https://neuronum.net/tx/{txID})
|
|
500
589
|
|
|
590
|
+
***
|
|
501
591
|
|
|
502
|
-
|
|
503
|
-
|
|
592
|
+
### 🐍 With Python
|
|
593
|
+
|
|
594
|
+
For programmatic access, use the following Python code snippet. This script utilizes the `neuronum` library to activate the transaction and receive a response.
|
|
595
|
+
|
|
596
|
+
```python
|
|
504
597
|
import asyncio
|
|
505
598
|
import neuronum
|
|
506
|
-
import os
|
|
507
|
-
from dotenv import load_dotenv
|
|
508
|
-
|
|
509
|
-
load_dotenv()
|
|
510
|
-
host = os.getenv("HOST")
|
|
511
|
-
password = os.getenv("PASSWORD")
|
|
512
|
-
network = os.getenv("NETWORK")
|
|
513
|
-
synapse = os.getenv("SYNAPSE")
|
|
514
599
|
|
|
600
|
+
# Set up Cell connection parameters
|
|
515
601
|
cell = neuronum.Cell(
|
|
516
|
-
host=host,
|
|
517
|
-
password=password,
|
|
518
|
-
network=network
|
|
519
|
-
synapse=synapse
|
|
602
|
+
host="host", # Cell host
|
|
603
|
+
password="password", # Cell password
|
|
604
|
+
network="neuronum.net", # Cell network
|
|
605
|
+
synapse="synapse" # Cell synapse
|
|
520
606
|
)
|
|
521
607
|
|
|
522
|
-
async def main():
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
</head>
|
|
538
|
-
<body>
|
|
539
|
-
<div class="card">
|
|
540
|
-
<h1>Hello, {{client}}</h1>
|
|
541
|
-
<p>Greetings from <span class="node">{nodeID}</span></p>
|
|
542
|
-
</div>
|
|
543
|
-
</body>
|
|
544
|
-
</html>
|
|
545
|
-
\"\"\"
|
|
546
|
-
|
|
547
|
-
}}
|
|
548
|
-
await cell.tx_response(txID, client, data)
|
|
608
|
+
async def main():
|
|
609
|
+
# Define the transaction ID and data payload
|
|
610
|
+
TX = "{txID}"
|
|
611
|
+
data = {{"ping": "node"}}
|
|
612
|
+
|
|
613
|
+
# Activate the transaction and get the response
|
|
614
|
+
tx_response = await cell.activate_tx(TX, data)
|
|
615
|
+
|
|
616
|
+
# Print the response from the Node
|
|
617
|
+
print(tx_response)
|
|
618
|
+
|
|
619
|
+
# Run the main asynchronous function
|
|
620
|
+
if __name__ == "__main__":
|
|
621
|
+
asyncio.run(main())
|
|
622
|
+
```
|
|
549
623
|
|
|
550
|
-
|
|
624
|
+
🤖 Via Cellai (Android App - Currently in Testing)
|
|
625
|
+
Download the app from the Google Play Store.
|
|
626
|
+
Send the command "Ping Node" to Cellai
|
|
551
627
|
""")
|
|
552
628
|
|
|
553
629
|
click.echo(f"Neuronum Node '{nodeID}' initialized!")
|
|
@@ -556,6 +632,7 @@ asyncio.run(main())
|
|
|
556
632
|
@click.command()
|
|
557
633
|
@click.option('--d', is_flag=True, help="Start node in detached mode")
|
|
558
634
|
def start_node(d):
|
|
635
|
+
update_node()
|
|
559
636
|
pid_file = Path.cwd() / "status.txt"
|
|
560
637
|
system_name = platform.system()
|
|
561
638
|
active_pids = []
|
|
@@ -586,27 +663,24 @@ def start_node(d):
|
|
|
586
663
|
click.echo("Starting Node...")
|
|
587
664
|
|
|
588
665
|
project_path = Path.cwd()
|
|
589
|
-
script_files = glob.glob("
|
|
666
|
+
script_files = glob.glob("stream.py") + glob.glob("app.py")
|
|
590
667
|
processes = []
|
|
591
668
|
|
|
592
669
|
for script in script_files:
|
|
593
670
|
script_path = project_path / script
|
|
594
671
|
if script_path.exists():
|
|
595
|
-
python_cmd = "pythonw" if system_name == "Windows" else "python"
|
|
596
672
|
|
|
597
673
|
if d:
|
|
598
674
|
process = subprocess.Popen(
|
|
599
|
-
["nohup",
|
|
600
|
-
else [
|
|
675
|
+
["nohup", sys.executable, str(script_path), "&"] if system_name != "Windows"
|
|
676
|
+
else ["pythonw", str(script_path)],
|
|
601
677
|
stdout=subprocess.DEVNULL,
|
|
602
678
|
stderr=subprocess.DEVNULL,
|
|
603
679
|
start_new_session=True
|
|
604
680
|
)
|
|
605
681
|
else:
|
|
606
682
|
process = subprocess.Popen(
|
|
607
|
-
[sys.executable, str(script_path)]
|
|
608
|
-
stdout=None,
|
|
609
|
-
stderr=None
|
|
683
|
+
[sys.executable, str(script_path)]
|
|
610
684
|
)
|
|
611
685
|
|
|
612
686
|
processes.append(process.pid)
|
|
@@ -678,11 +752,6 @@ def check_node():
|
|
|
678
752
|
continue
|
|
679
753
|
|
|
680
754
|
if running_pids:
|
|
681
|
-
for pid in running_pids:
|
|
682
|
-
proc = psutil.Process(pid)
|
|
683
|
-
mem = proc.memory_info().rss / (1024 * 1024) # in MB
|
|
684
|
-
cpu = proc.cpu_percent(interval=0.1)
|
|
685
|
-
click.echo(f"PID {pid} → Memory: {mem:.2f} MB | CPU: {cpu:.1f}%")
|
|
686
755
|
click.echo(f"Node {nodeID} is running. Active PIDs: {', '.join(map(str, running_pids))}")
|
|
687
756
|
else:
|
|
688
757
|
click.echo(f"Node {nodeID} is not running.")
|
|
@@ -691,6 +760,7 @@ def check_node():
|
|
|
691
760
|
@click.command()
|
|
692
761
|
@click.option('--d', is_flag=True, help="Restart node in detached mode")
|
|
693
762
|
def restart_node(d):
|
|
763
|
+
update_node()
|
|
694
764
|
pid_file = Path.cwd() / "status.txt"
|
|
695
765
|
system_name = platform.system()
|
|
696
766
|
|
|
@@ -740,27 +810,23 @@ def restart_node(d):
|
|
|
740
810
|
|
|
741
811
|
click.echo(f"Starting Node {nodeID}...")
|
|
742
812
|
project_path = Path.cwd()
|
|
743
|
-
script_files = glob.glob("
|
|
813
|
+
script_files = glob.glob("stream.py") + glob.glob("app.py")
|
|
744
814
|
processes = []
|
|
745
815
|
|
|
746
|
-
python_cmd = "pythonw" if system_name == "Windows" else "python"
|
|
747
|
-
|
|
748
816
|
for script in script_files:
|
|
749
817
|
script_path = project_path / script
|
|
750
818
|
if script_path.exists():
|
|
751
819
|
if d:
|
|
752
820
|
process = subprocess.Popen(
|
|
753
|
-
["nohup",
|
|
754
|
-
else [
|
|
821
|
+
["nohup", sys.executable, str(script_path), "&"] if system_name != "Windows"
|
|
822
|
+
else ["pythonw", str(script_path)],
|
|
755
823
|
stdout=subprocess.DEVNULL,
|
|
756
824
|
stderr=subprocess.DEVNULL,
|
|
757
825
|
start_new_session=True
|
|
758
826
|
)
|
|
759
827
|
else:
|
|
760
828
|
process = subprocess.Popen(
|
|
761
|
-
[sys.executable, str(script_path)]
|
|
762
|
-
stdout=None,
|
|
763
|
-
stderr=None
|
|
829
|
+
[sys.executable, str(script_path)]
|
|
764
830
|
)
|
|
765
831
|
|
|
766
832
|
processes.append(process.pid)
|
|
@@ -825,13 +891,35 @@ async def async_stop_node():
|
|
|
825
891
|
click.echo("Error: Unable to stop some node processes.")
|
|
826
892
|
|
|
827
893
|
|
|
828
|
-
@click.command()
|
|
829
894
|
def update_node():
|
|
830
895
|
click.echo("Update your Node")
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
896
|
+
env_data = {}
|
|
897
|
+
|
|
898
|
+
try:
|
|
899
|
+
with open(".env", "r") as f:
|
|
900
|
+
for line in f:
|
|
901
|
+
key, value = line.strip().split("=")
|
|
902
|
+
env_data[key] = value
|
|
903
|
+
|
|
904
|
+
host = env_data.get("HOST", "")
|
|
905
|
+
|
|
906
|
+
except FileNotFoundError:
|
|
907
|
+
click.echo("Error: .env with credentials not found")
|
|
908
|
+
return
|
|
909
|
+
except Exception as e:
|
|
910
|
+
click.echo(f"Error reading .env file: {e}")
|
|
911
|
+
return
|
|
912
|
+
|
|
913
|
+
if host.startswith("CMTY_"):
|
|
914
|
+
node_type = questionary.select(
|
|
915
|
+
"Community Cells can only create private Nodes",
|
|
916
|
+
choices=["private"]
|
|
917
|
+
).ask()
|
|
918
|
+
else:
|
|
919
|
+
node_type = questionary.select(
|
|
920
|
+
"Who can view your Node?:",
|
|
921
|
+
choices=["public", "private", "partners"]
|
|
922
|
+
).ask()
|
|
835
923
|
partners = "None"
|
|
836
924
|
if node_type == "partners":
|
|
837
925
|
prompt_msg = (
|
|
@@ -1103,7 +1191,6 @@ cli.add_command(start_node)
|
|
|
1103
1191
|
cli.add_command(restart_node)
|
|
1104
1192
|
cli.add_command(stop_node)
|
|
1105
1193
|
cli.add_command(check_node)
|
|
1106
|
-
cli.add_command(update_node)
|
|
1107
1194
|
cli.add_command(delete_node)
|
|
1108
1195
|
cli.add_command(activate)
|
|
1109
1196
|
cli.add_command(load)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -19,6 +19,7 @@ Requires-Dist: questionary
|
|
|
19
19
|
Requires-Dist: python-dotenv
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: psutil
|
|
22
|
+
Requires-Dist: jinja2
|
|
22
23
|
Dynamic: author
|
|
23
24
|
Dynamic: author-email
|
|
24
25
|
Dynamic: classifier
|
|
@@ -104,102 +105,27 @@ neuronum connect-cell # connect Cell
|
|
|
104
105
|
|
|
105
106
|
|
|
106
107
|
### **Build On Neuronum**
|
|
107
|
-
|
|
108
|
+
Visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples) to gain deeper knowledge on how to build on Neuronum.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
To get started, initialize a new Node with the command below.
|
|
110
111
|
```sh
|
|
111
|
-
neuronum init-node
|
|
112
|
+
neuronum init-node
|
|
112
113
|
```
|
|
113
114
|
|
|
114
|
-
This command
|
|
115
|
+
This command will prompt you for a description (e.g., Test App) and will create
|
|
115
116
|
|
|
116
|
-
.
|
|
117
|
-
|
|
118
|
-
NODE=your_node_id
|
|
119
|
-
HOST=your_cell_id
|
|
120
|
-
PASSWORD=your_password
|
|
121
|
-
NETWORK=neuronum.net
|
|
122
|
-
SYNAPSE=your_synapse # auth token
|
|
123
|
-
```
|
|
117
|
+
1. A Stream (STX) so your App can receive requests, and a Transmitter (TX) to match those requests
|
|
118
|
+
2. A new directory named "Test App_<your_node_id>" with the following files
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
```python
|
|
127
|
-
import asyncio
|
|
128
|
-
import neuronum
|
|
129
|
-
import os
|
|
130
|
-
from dotenv import load_dotenv
|
|
131
|
-
|
|
132
|
-
load_dotenv()
|
|
133
|
-
host = os.getenv("HOST")
|
|
134
|
-
password = os.getenv("PASSWORD")
|
|
135
|
-
network = os.getenv("NETWORK")
|
|
136
|
-
synapse = os.getenv("SYNAPSE")
|
|
137
|
-
|
|
138
|
-
cell = neuronum.Cell(
|
|
139
|
-
host=host,
|
|
140
|
-
password=password,
|
|
141
|
-
network=network,
|
|
142
|
-
synapse=synapse
|
|
143
|
-
)
|
|
120
|
+
.env: Stores your Node's credentials for connecting to the network.
|
|
144
121
|
|
|
145
|
-
|
|
146
|
-
STX = "id::stx"
|
|
147
|
-
async for operation in cell.sync(STX):
|
|
148
|
-
txID = operation.get("txID")
|
|
149
|
-
client = operation.get("operator")
|
|
150
|
-
|
|
151
|
-
if txID == "id::tx":
|
|
152
|
-
data = {
|
|
153
|
-
"json": f"Hello {client}",
|
|
154
|
-
"html": f"""
|
|
155
|
-
<!DOCTYPE html>
|
|
156
|
-
<html>
|
|
157
|
-
<head>
|
|
158
|
-
<meta charset="UTF-8">
|
|
159
|
-
<title>Greeting Node</title>
|
|
160
|
-
</head>
|
|
161
|
-
<body>
|
|
162
|
-
<div class="card">
|
|
163
|
-
<h1>Hello, {client}</h1>
|
|
164
|
-
</div>
|
|
165
|
-
</body>
|
|
166
|
-
</html>
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
await cell.tx_response(txID, client, data)
|
|
122
|
+
app.py: The main Python script that contains your Node's core logic.
|
|
171
123
|
|
|
172
|
-
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
config.json (required if you want to make your app accessible to Cellai (currently in testing))
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"data_gateways": [
|
|
179
|
-
{
|
|
180
|
-
"type": "stream",
|
|
181
|
-
"id": "id::stx",
|
|
182
|
-
"info": "provide a detailed description about the stream"
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"type": "transmitter",
|
|
186
|
-
"id": "id::tx",
|
|
187
|
-
"info": "provide a detailed description about the transmitter"
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
"type": "circuit",
|
|
191
|
-
"id": "id::ctx",
|
|
192
|
-
"info": "provide a detailed description about the circuit"
|
|
193
|
-
}
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
```
|
|
124
|
+
NODE.md: Public documentation that provides instructions for interacting with your Node.
|
|
197
125
|
|
|
198
|
-
|
|
199
|
-
```
|
|
200
|
-
### NODE.md: Create a detailed Markdown File on how to interact with this Node
|
|
201
|
-
```
|
|
126
|
+
config.json: A configuration file that stores metadata about your app and enables Cellai to interact with your Node's data gateways.
|
|
202
127
|
|
|
128
|
+
ping.html: A static HTML file used to render web-based responses.
|
|
203
129
|
|
|
204
130
|
Change into Node folder
|
|
205
131
|
```sh
|
|
@@ -247,6 +173,6 @@ asyncio.run(main())
|
|
|
247
173
|
neuronum activate --tx id::tx 'say:hello'
|
|
248
174
|
```
|
|
249
175
|
|
|
250
|
-
#### **Cellai**
|
|
251
|
-
Cellai is
|
|
176
|
+
#### **Cellai (in Testing)**
|
|
177
|
+
Cellai is an AI tool for developers to test their apps built on Neuronum and will soon be published to the Google Play Store.
|
|
252
178
|
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='neuronum',
|
|
5
|
-
version='
|
|
5
|
+
version='7.0.0',
|
|
6
6
|
author='Neuronum Cybernetics',
|
|
7
7
|
author_email='welcome@neuronum.net',
|
|
8
8
|
description='Official client library to interact with the Neuronum Network',
|
|
@@ -27,6 +27,7 @@ setup(
|
|
|
27
27
|
'python-dotenv',
|
|
28
28
|
'requests',
|
|
29
29
|
'psutil',
|
|
30
|
+
'jinja2',
|
|
30
31
|
],
|
|
31
32
|
entry_points={
|
|
32
33
|
"console_scripts": [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|