neuronum 5.2.0__py3-none-any.whl → 5.4.0__py3-none-any.whl
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.
- cellai/__init__.py +0 -0
- cellai/cellai.py +118 -0
- cli/main.py +80 -39
- neuronum/neuronum.py +0 -2
- {neuronum-5.2.0.dist-info → neuronum-5.4.0.dist-info}/METADATA +24 -20
- neuronum-5.4.0.dist-info/RECORD +12 -0
- {neuronum-5.2.0.dist-info → neuronum-5.4.0.dist-info}/top_level.txt +1 -0
- neuronum-5.2.0.dist-info/RECORD +0 -10
- {neuronum-5.2.0.dist-info → neuronum-5.4.0.dist-info}/WHEEL +0 -0
- {neuronum-5.2.0.dist-info → neuronum-5.4.0.dist-info}/entry_points.txt +0 -0
- {neuronum-5.2.0.dist-info → neuronum-5.4.0.dist-info}/licenses/LICENSE +0 -0
cellai/__init__.py
ADDED
|
File without changes
|
cellai/cellai.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from rapidfuzz import process
|
|
3
|
+
import neuronum
|
|
4
|
+
import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def log_interaction(user_input, output, log_path=Path("cellai.log")):
|
|
9
|
+
log_path = Path(log_path)
|
|
10
|
+
|
|
11
|
+
timestamp = datetime.datetime.now().isoformat()
|
|
12
|
+
with open(log_path, "a", encoding="utf-8") as log_file:
|
|
13
|
+
log_file.write(f"[{timestamp}]\n")
|
|
14
|
+
log_file.write(f"USER: {user_input}")
|
|
15
|
+
log_file.write(f"{output}\n\n")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def main(host, password, network, synapse):
|
|
19
|
+
cell = neuronum.Cell(
|
|
20
|
+
host=host,
|
|
21
|
+
password=password,
|
|
22
|
+
network=network,
|
|
23
|
+
synapse=synapse
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
tx = await cell.list_tx()
|
|
27
|
+
nodes = await cell.list_nodes()
|
|
28
|
+
|
|
29
|
+
transmitters = tx
|
|
30
|
+
transmitters_by_id = {t["txID"]: t for t in transmitters}
|
|
31
|
+
|
|
32
|
+
info_to_gateway = []
|
|
33
|
+
for node in nodes:
|
|
34
|
+
for g in node["Node.md"]["gateways"]:
|
|
35
|
+
info_to_gateway.append({
|
|
36
|
+
"nodeID": node["nodeID"],
|
|
37
|
+
"gateway": g,
|
|
38
|
+
"info": g["info"],
|
|
39
|
+
"descr": node["descr"]
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
print("Cellai: Ready for your instruction!")
|
|
43
|
+
loop = asyncio.get_event_loop()
|
|
44
|
+
|
|
45
|
+
while True:
|
|
46
|
+
try:
|
|
47
|
+
user_input = await loop.run_in_executor(None, input, ">> ")
|
|
48
|
+
user_input = user_input.strip()
|
|
49
|
+
if user_input.lower() in {"exit", "quit"}:
|
|
50
|
+
log_interaction(user_input, "Session ended by user.")
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
match, score, idx = process.extractOne(user_input, [x["info"] for x in info_to_gateway])
|
|
54
|
+
best = info_to_gateway[idx]
|
|
55
|
+
|
|
56
|
+
output_log = (
|
|
57
|
+
f"\nMatched: {match} ({score:.1f}%)\n"
|
|
58
|
+
f"Node: {best['descr']} [{best['nodeID']}]\n"
|
|
59
|
+
f"Gateway: {best['gateway']['id']} ({best['gateway']['type']})"
|
|
60
|
+
)
|
|
61
|
+
print(output_log)
|
|
62
|
+
|
|
63
|
+
if best['gateway']['type'] == "transmitter":
|
|
64
|
+
tx_id = best['gateway']['id']
|
|
65
|
+
tx_data = transmitters_by_id.get(tx_id)
|
|
66
|
+
if tx_data:
|
|
67
|
+
print(f"Executing transmitter: {tx_data['descr']}")
|
|
68
|
+
|
|
69
|
+
dynamic_payload = {}
|
|
70
|
+
for key in tx_data["data"].keys():
|
|
71
|
+
prompt = f"Enter value for '{key}': "
|
|
72
|
+
value = await loop.run_in_executor(None, input, prompt)
|
|
73
|
+
dynamic_payload[key] = value
|
|
74
|
+
|
|
75
|
+
print(f"Payload: {dynamic_payload}")
|
|
76
|
+
TX = tx_id
|
|
77
|
+
tx_response = await cell.activate_tx(TX, dynamic_payload)
|
|
78
|
+
print(tx_response["json"])
|
|
79
|
+
output_log += f"\nTransmitter executed: {tx_data['descr']}\nPayload: {dynamic_payload}\nResponse: {tx_response['json']}"
|
|
80
|
+
else:
|
|
81
|
+
warning = "Transmitter not found."
|
|
82
|
+
print(warning)
|
|
83
|
+
output_log += f"{warning}"
|
|
84
|
+
|
|
85
|
+
elif best['gateway']['type'] == "stream":
|
|
86
|
+
STX = best['gateway']['id']
|
|
87
|
+
print(f"Starting stream sync for STX: {STX}")
|
|
88
|
+
async for operation in cell.sync(STX):
|
|
89
|
+
label = operation.get("label")
|
|
90
|
+
data = operation.get("data")
|
|
91
|
+
ts = operation.get("time")
|
|
92
|
+
stxID = operation.get("stxID")
|
|
93
|
+
operator = operation.get("operator")
|
|
94
|
+
line = f"[{ts}] {label} | Operator: {operator} | STX: {stxID}\nData: {data}"
|
|
95
|
+
print(line)
|
|
96
|
+
output_log += f"\n{line}"
|
|
97
|
+
elif best['gateway']['type'] == "circuit":
|
|
98
|
+
CTX = best['gateway']['id']
|
|
99
|
+
label = await loop.run_in_executor(None, input, "Enter label to load from circuit: ")
|
|
100
|
+
label = label.strip()
|
|
101
|
+
data = await cell.load(label, CTX)
|
|
102
|
+
print(data)
|
|
103
|
+
output_log += f"\nCircuit loaded from CTX: {CTX} with label '{label}'\nData: {data}"
|
|
104
|
+
else:
|
|
105
|
+
msg = "Unknown gateway type."
|
|
106
|
+
print(msg)
|
|
107
|
+
output_log += f"{msg}"
|
|
108
|
+
|
|
109
|
+
log_interaction(user_input, output_log)
|
|
110
|
+
|
|
111
|
+
except KeyboardInterrupt:
|
|
112
|
+
print("\nExiting.")
|
|
113
|
+
log_interaction("KeyboardInterrupt", "Session exited with Ctrl+C")
|
|
114
|
+
break
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
asyncio.run(main(host, password, network, synapse))
|
cli/main.py
CHANGED
|
@@ -324,40 +324,24 @@ async def async_init_node(sync, stream, app):
|
|
|
324
324
|
|
|
325
325
|
```json
|
|
326
326
|
{
|
|
327
|
-
"info": {
|
|
328
|
-
"use_case": "This Node...",
|
|
329
|
-
"github": "https://github.com/user"
|
|
330
|
-
},
|
|
331
327
|
"gateways": [
|
|
332
328
|
{
|
|
333
329
|
"type": "stream",
|
|
334
330
|
"id": "id::stx",
|
|
335
|
-
"link": "https://neuronum.net/stream/id::stx"
|
|
331
|
+
"link": "https://neuronum.net/stream/id::stx",
|
|
332
|
+
"info": "stream info"
|
|
336
333
|
},
|
|
337
334
|
{
|
|
338
335
|
"type": "transmitter",
|
|
339
336
|
"id": "id::tx",
|
|
340
|
-
"link": "https://neuronum.net/tx/id::tx",
|
|
341
|
-
|
|
337
|
+
"link": "https://neuronum.net/tx/id::tx",
|
|
338
|
+
"info": "transmitter info"
|
|
339
|
+
},
|
|
342
340
|
{
|
|
343
341
|
"type": "circuit",
|
|
344
342
|
"id": "id::ctx",
|
|
345
|
-
"link": "https://neuronum.net/circuit/id::ctx",
|
|
346
|
-
|
|
347
|
-
],
|
|
348
|
-
"initialization": {
|
|
349
|
-
"command": "neuronum init-node --sync id::stx"
|
|
350
|
-
},
|
|
351
|
-
"requirements": [
|
|
352
|
-
{
|
|
353
|
-
"name": "Python",
|
|
354
|
-
"version": ">= 3.8",
|
|
355
|
-
"link": "https://www.python.org/downloads/"
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
"name": "neuronum",
|
|
359
|
-
"version": ">= 5.1.0",
|
|
360
|
-
"link": "https://pypi.org/project/neuronum/"
|
|
343
|
+
"link": "https://neuronum.net/circuit/id::ctx",
|
|
344
|
+
"info": "circuit info"
|
|
361
345
|
}
|
|
362
346
|
]
|
|
363
347
|
}
|
|
@@ -500,7 +484,23 @@ async def main():
|
|
|
500
484
|
asyncio.run(main())
|
|
501
485
|
""")
|
|
502
486
|
|
|
503
|
-
if app:
|
|
487
|
+
if app and nodeID:
|
|
488
|
+
|
|
489
|
+
descr = f"{nodeID} App"
|
|
490
|
+
partners = ["public"]
|
|
491
|
+
stxID = await cell.create_stx(descr, partners)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
descr = f"Greet {nodeID}"
|
|
495
|
+
key_values = {
|
|
496
|
+
"say": "hello",
|
|
497
|
+
}
|
|
498
|
+
STX = stxID
|
|
499
|
+
label = "say:hello"
|
|
500
|
+
partners = ["public"]
|
|
501
|
+
txID = await cell.create_tx(descr, key_values, STX, label, partners)
|
|
502
|
+
|
|
503
|
+
|
|
504
504
|
app_path = project_path / "app.py"
|
|
505
505
|
app_path.write_text(f"""\
|
|
506
506
|
import asyncio
|
|
@@ -521,27 +521,31 @@ cell = neuronum.Cell(
|
|
|
521
521
|
synapse=synapse
|
|
522
522
|
)
|
|
523
523
|
|
|
524
|
-
async def main():
|
|
525
|
-
STX = "
|
|
524
|
+
async def main():
|
|
525
|
+
STX = "{stxID}"
|
|
526
526
|
async for operation in cell.sync(STX):
|
|
527
527
|
txID = operation.get("txID")
|
|
528
528
|
client = operation.get("operator")
|
|
529
529
|
|
|
530
|
-
if txID == "
|
|
531
|
-
data = {{
|
|
532
|
-
"response": "TX activated!"
|
|
533
|
-
}}
|
|
534
|
-
await cell.tx_response(txID, client, data)
|
|
535
|
-
|
|
536
|
-
if txID == "id::tx":
|
|
530
|
+
if txID == "{txID}":
|
|
537
531
|
data = {{
|
|
538
|
-
"
|
|
539
|
-
|
|
540
|
-
|
|
532
|
+
"json": f"Hello {{client}} from {nodeID}",
|
|
533
|
+
"html": f\"\"\"
|
|
534
|
+
<!DOCTYPE html>
|
|
535
|
+
<html>
|
|
536
|
+
<head>
|
|
537
|
+
<meta charset="UTF-8">
|
|
538
|
+
<title>Greeting Node</title>
|
|
539
|
+
</head>
|
|
540
|
+
<body>
|
|
541
|
+
<div class="card">
|
|
542
|
+
<h1>Hello, {{client}}</h1>
|
|
543
|
+
<p>Greetings from <span class="node">{nodeID}</span></p>
|
|
544
|
+
</div>
|
|
545
|
+
</body>
|
|
546
|
+
</html>
|
|
547
|
+
\"\"\"
|
|
541
548
|
|
|
542
|
-
if txID == "id::tx":
|
|
543
|
-
data = {{
|
|
544
|
-
"response": "TX activated!"
|
|
545
549
|
}}
|
|
546
550
|
await cell.tx_response(txID, client, data)
|
|
547
551
|
|
|
@@ -868,6 +872,42 @@ async def async_delete_node():
|
|
|
868
872
|
click.echo(f"Neuronum Node '{nodeID}' deleted!")
|
|
869
873
|
|
|
870
874
|
|
|
875
|
+
@click.command()
|
|
876
|
+
def call_cellai():
|
|
877
|
+
try:
|
|
878
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
879
|
+
env_path = credentials_folder_path / ".env"
|
|
880
|
+
|
|
881
|
+
env_data = {}
|
|
882
|
+
|
|
883
|
+
try:
|
|
884
|
+
with open(env_path, "r") as f:
|
|
885
|
+
for line in f:
|
|
886
|
+
key, value = line.strip().split("=")
|
|
887
|
+
env_data[key] = value
|
|
888
|
+
|
|
889
|
+
host = env_data.get("HOST", "")
|
|
890
|
+
password = env_data.get("PASSWORD", "")
|
|
891
|
+
network = env_data.get("NETWORK", "")
|
|
892
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
893
|
+
except FileNotFoundError:
|
|
894
|
+
click.echo("No cell connected. Connect your cell with command neuronum connect-cell")
|
|
895
|
+
return
|
|
896
|
+
except Exception as e:
|
|
897
|
+
click.echo(f"Error reading .env file: {e}")
|
|
898
|
+
return
|
|
899
|
+
|
|
900
|
+
from cellai import cellai
|
|
901
|
+
asyncio.run(cellai.main(host, password, network, synapse))
|
|
902
|
+
|
|
903
|
+
except FileNotFoundError:
|
|
904
|
+
click.echo("Error: .env with credentials not found")
|
|
905
|
+
except ImportError:
|
|
906
|
+
click.echo("Cellai not found. Please check the necessary dependencies.")
|
|
907
|
+
except Exception as e:
|
|
908
|
+
click.echo(f"Unexpected error: {e}")
|
|
909
|
+
|
|
910
|
+
|
|
871
911
|
cli.add_command(create_cell)
|
|
872
912
|
cli.add_command(connect_cell)
|
|
873
913
|
cli.add_command(view_cell)
|
|
@@ -880,6 +920,7 @@ cli.add_command(connect_node)
|
|
|
880
920
|
cli.add_command(update_node)
|
|
881
921
|
cli.add_command(disconnect_node)
|
|
882
922
|
cli.add_command(delete_node)
|
|
923
|
+
cli.add_command(call_cellai)
|
|
883
924
|
|
|
884
925
|
|
|
885
926
|
if __name__ == "__main__":
|
neuronum/neuronum.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.4.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
|
|
@@ -18,6 +18,7 @@ Requires-Dist: click
|
|
|
18
18
|
Requires-Dist: questionary
|
|
19
19
|
Requires-Dist: python-dotenv
|
|
20
20
|
Requires-Dist: requests
|
|
21
|
+
Requires-Dist: rapidfuzz
|
|
21
22
|
Dynamic: author
|
|
22
23
|
Dynamic: author-email
|
|
23
24
|
Dynamic: classifier
|
|
@@ -39,6 +40,7 @@ Dynamic: summary
|
|
|
39
40
|
- Learn about Neuronum
|
|
40
41
|
- Connect to Neuronum
|
|
41
42
|
- Build on Neuronum
|
|
43
|
+
- Interact with Neuronum
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
### **About Neuronum**
|
|
@@ -55,10 +57,13 @@ Neuronum is a framework to build serverless connected app & data gateways automa
|
|
|
55
57
|
- Circuits (CTX): Store data in cloud-based key-value-label databases
|
|
56
58
|
- Streams (STX): Stream, synchronize, and control data in real time
|
|
57
59
|
|
|
60
|
+
**Cellai**
|
|
61
|
+
Cellai is a CLI-based assistant that helps you interact with Neuronum
|
|
62
|
+
|
|
58
63
|
|
|
59
64
|
#### Requirements
|
|
60
65
|
- Python >= 3.8 -> https://www.python.org/downloads/
|
|
61
|
-
- neuronum >= 4.0
|
|
66
|
+
- neuronum >= 5.4.0 -> https://pypi.org/project/neuronum/
|
|
62
67
|
|
|
63
68
|
|
|
64
69
|
------------------
|
|
@@ -82,22 +87,18 @@ Connect Cell:
|
|
|
82
87
|
neuronum connect-cell # connect Cell
|
|
83
88
|
```
|
|
84
89
|
|
|
85
|
-
View connected Cell:
|
|
86
|
-
```sh
|
|
87
|
-
neuronum view-cell # view Cell / output = Connected Cell: 'cell_id'"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|
|
91
90
|
------------------
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
### **Build on Neuronum**
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
Initialize Node (app template):
|
|
95
|
+
```sh
|
|
96
|
+
neuronum init-node --app # initialize a Node with app template
|
|
97
|
+
```
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
Change into Node folder
|
|
99
100
|
```sh
|
|
100
|
-
|
|
101
|
+
cd node_node_id # change directory
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
Start Node:
|
|
@@ -105,12 +106,15 @@ Start Node:
|
|
|
105
106
|
neuronum start-node # start Node
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
neuronum stop-node # stop Node
|
|
111
|
-
```
|
|
109
|
+
**Node Examples**
|
|
110
|
+
Visit: https://github.com/neuronumcybernetics/neuronum/tree/main/how_tos/nodes
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
|
|
113
|
+
------------------
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### **Interact with Neuronum**
|
|
117
|
+
1. Visit: https://neuronum.net
|
|
118
|
+
2. Connect your Cell
|
|
119
|
+
3. Explore Transmitters
|
|
120
|
+
4. Activate Transmitters
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
cellai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cellai/cellai.py,sha256=LjJqF0dpk1Vjq-QLiGdzUi6IIDZwPcgvsn4Cjjp4JJ8,4559
|
|
3
|
+
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
cli/main.py,sha256=wu0oggPk-VzONIzcyPKibyWhiT4kbI_6SZUsSrOkVYo,28479
|
|
5
|
+
neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
|
|
6
|
+
neuronum/neuronum.py,sha256=gaQTvv8llmc36yBG8UwijCOoi6_uvifJyJ4z3KuiQqQ,17382
|
|
7
|
+
neuronum-5.4.0.dist-info/licenses/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
|
|
8
|
+
neuronum-5.4.0.dist-info/METADATA,sha256=vQWIvtNj8F8-WltrDA-CqBjuSSylbNR4TOXGRCS4sn0,3145
|
|
9
|
+
neuronum-5.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
neuronum-5.4.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
11
|
+
neuronum-5.4.0.dist-info/top_level.txt,sha256=gqN5tyGnBKMPSzvWQONO4rpTf4gQPMi77O3KAKx88LQ,20
|
|
12
|
+
neuronum-5.4.0.dist-info/RECORD,,
|
neuronum-5.2.0.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
cli/main.py,sha256=D-QZ7__wBMzuB2O1H-hsw_05UB_umWg_eUESkM4cTg0,26768
|
|
3
|
-
neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
|
|
4
|
-
neuronum/neuronum.py,sha256=9oNS8e1d95XfnKieycpQTK8huZY3rwGdNGBy9O0eVEQ,17433
|
|
5
|
-
neuronum-5.2.0.dist-info/licenses/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
|
|
6
|
-
neuronum-5.2.0.dist-info/METADATA,sha256=Xb7jfgOMTJKWBbrqNL09G-1bYzVDCSLHi6Gk4yTR6_4,3060
|
|
7
|
-
neuronum-5.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
neuronum-5.2.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
9
|
-
neuronum-5.2.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
|
|
10
|
-
neuronum-5.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|