hormigasais-edge-starter 0.1.0

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/.env.example ADDED
@@ -0,0 +1,4 @@
1
+ LBH_SECRET=
2
+ NODE_NAME=
3
+ OWNER_NAME=
4
+ OWNER_EMAIL=
@@ -0,0 +1,27 @@
1
+ {
2
+ "schema": "LBH_NODE_CONFIG_V1",
3
+ "node_id": "A16-u0_a350",
4
+ "node_name": "mi-colonia",
5
+ "protocol": "LBH_BINARY_V2",
6
+ "version": "2.0.0",
7
+ "owner": {
8
+ "name": "YOUR-NAME",
9
+ "email": "YOUR-EMAIL"
10
+ },
11
+ "location": {
12
+ "country": "SV",
13
+ "city": "San Miguel"
14
+ },
15
+ "master_node": "A16-SanMiguel-SV",
16
+ "created_at": "2026-07-24T02:27:25Z",
17
+ "status": "INITIALIZED",
18
+ "agents": [
19
+ "hormiga_centinela",
20
+ "hormiga_relevo"
21
+ ],
22
+ "security": {
23
+ "hmac_required": true,
24
+ "algorithm": "HMAC-SHA256"
25
+ },
26
+ "certificate": "PENDING"
27
+ }
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # 🐜 HormigasAIS Edge Starter
2
+
3
+ Starter oficial para desplegar un **nodo soberano** de HormigasAIS con agentes LBH.
4
+
5
+ > "Soberanía digital en el edge"
6
+
7
+ ## 🚀 Instalación Rápida
8
+
9
+ ### Opción 1: Desde GitHub (Recomendada actualmente)
10
+
11
+ \`\`\`bash
12
+ npx create-hormigas-node@latest
13
+ \`\`\`
14
+
15
+ O manualmente:
16
+
17
+ \`\`\`bash
18
+ git clone https://github.com/Thrumanshow/hormigasais-edge-starter.git
19
+ cd hormigasais-edge-starter
20
+ bash bootstrap.sh
21
+ python3 generator.py
22
+ \`\`\`
23
+
24
+ ### Opción 2: Cuando esté publicado en npm (próximamente)
25
+
26
+ \`\`\`bash
27
+ npx create-hormigas-node
28
+ \`\`\`
29
+
30
+ ## ¿Qué incluye?
31
+
32
+ - **Bootstrap automático** del entorno en Termux
33
+ - **SDK LBH completo** (encoder, decoder, signer, verifier)
34
+ - **Agentes autónomos**: \`hormiga_centinela\` y \`hormiga_relevo\`
35
+ - **Generadores modulares** (config, protocols, scripts, agents, contracts)
36
+ - **Verificación POST** del SDK (\`verify_sdk.py\`)
37
+ - Soporte para secretos en \`~/.hormigas_secrets\`
38
+
39
+ ## Comandos útiles
40
+
41
+ \`\`\`bash
42
+ ./bootstrap.sh # Preparar entorno
43
+ python3 generator.py # Ejecutar generadores
44
+ python3 scripts/verify_sdk.py # Test completo del SDK LBH
45
+ \`\`\`
46
+
47
+ ## Estructura del proyecto
48
+
49
+ \`\`\`
50
+ hormigasais-edge-starter/
51
+ ├── bootstrap.sh
52
+ ├── generator.py
53
+ ├── package.json
54
+ ├── protocols/ # SDK LBH
55
+ ├── agents/ # Agentes autónomos
56
+ ├── scripts/ # Scripts de verificación
57
+ ├── utils/ # Utilidades
58
+ ├── .hormigasais/ # Configuración del nodo
59
+ └── logs/
60
+ \`\`\`
61
+
62
+ ---
63
+
64
+ **Made with ❤️ for digital sovereignty**
65
+
66
+ [hormigasais.com](https://hormigasais.com) | [@Thrumanshow](https://github.com/Thrumanshow)
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ hormiga_centinela.py
4
+ """
5
+ import time
6
+ import json
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ ROOT = Path(__file__).resolve().parent.parent
11
+ sys.path.insert(0, str(ROOT))
12
+
13
+ from utils.env_loader import load_termux_secrets
14
+ load_termux_secrets()
15
+
16
+ from protocols.encoder import make_header, encode_packet
17
+ from protocols.constants import TYPE_CODES
18
+ from protocols.signer import seal_action
19
+
20
+ NODE_ID = "A16"
21
+ OWNER = "Cristhiam Leonardo Hernández Quiñonez"
22
+ INTERVAL = 30
23
+
24
+ def emit_pulse():
25
+ payload = json.dumps({
26
+ "agent": "hormiga_centinela",
27
+ "status": "ACTIVE",
28
+ "node": NODE_ID,
29
+ "ts": int(time.time())
30
+ })
31
+ header = make_header(NODE_ID[:3], "00")
32
+ frame = encode_packet(header, TYPE_CODES["FUEL"], payload)
33
+ seal = seal_action(payload, OWNER)
34
+ print("[CENTINELA] FUEL pulse emitido")
35
+ return frame
36
+
37
+ if __name__ == "__main__":
38
+ print(f"[CENTINELA] Iniciando en nodo {NODE_ID}")
39
+ while True:
40
+ emit_pulse()
41
+ time.sleep(INTERVAL)
package/generator.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { execSync } = require('child_process');
5
+
6
+ const targetName = process.argv[2] || 'mi-colonia';
7
+ const targetDir = path.join(process.cwd(), targetName);
8
+
9
+ console.log(`🐜 [HormigasAIS] Desplegando nodo soberano en edge: ${targetName}...`);
10
+
11
+ if (!fs.existsSync(targetDir)) {
12
+ fs.mkdirSync(targetDir, { recursive: true });
13
+ }
14
+
15
+ // Estructura de directorios
16
+ const subdirs = ['agents', 'protocols', 'scripts', '.hormigasais'];
17
+ subdirs.forEach(dir => {
18
+ const p = path.join(targetDir, dir);
19
+ if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
20
+ });
21
+
22
+ // Copiar o generar archivos base en el directorio destino
23
+ const fecha = new Date().toISOString();
24
+
25
+ const config = {
26
+ "node_id": "NODE-" + Math.random().toString(36).substring(2, 8).toUpperCase(),
27
+ "node_name": targetName,
28
+ "protocol": "LBH_BINARY_V1",
29
+ "version": "2.0",
30
+ "owner": "Cristhiam Leonardo Hernández Quiñonez",
31
+ "location": "San Miguel, El Salvador",
32
+ "nodo_maestro": "A16-SanMiguel-SV",
33
+ "created": fecha,
34
+ "agents": ["hormiga_centinela", "hormiga_relevo"],
35
+ "cert": "SELLADO-SOBERANO-LBH"
36
+ };
37
+
38
+ fs.writeFileSync(path.join(targetDir, '.hormigasais', 'node_config.json'), JSON.stringify(config, null, 2));
39
+
40
+ console.log(`✅ Nodo configurado en ${targetDir}`);
41
+ console.log(`
42
+ Siguiente paso:\n cd ${targetName}\n ./scripts/ignicion.sh`);
package/generator.py ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ HormigasAIS Edge Starter
4
+ generator.py
5
+
6
+ Orquestador principal del starter.
7
+
8
+ Responsabilidades:
9
+ - Crear la estructura base.
10
+ - Ejecutar cada generador especializado.
11
+ - No sobrescribir archivos existentes salvo indicación explícita.
12
+ """
13
+
14
+ from pathlib import Path
15
+ import importlib
16
+ import sys
17
+
18
+ ROOT = Path(__file__).resolve().parent
19
+ GENERATORS = ROOT / "generators"
20
+
21
+ sys.path.insert(0, str(ROOT))
22
+
23
+ MODULES = [
24
+ "config_generator",
25
+ "readme_generator",
26
+ "protocol_generator",
27
+ "contracts_generator",
28
+ "agents_generator",
29
+ "scripts_generator",
30
+ ]
31
+
32
+
33
+ def main():
34
+
35
+ GENERATORS.mkdir(exist_ok=True)
36
+
37
+ init = GENERATORS / "__init__.py"
38
+
39
+ if not init.exists():
40
+ init.write_text(
41
+ "# HormigasAIS Generators Package\n",
42
+ encoding="utf-8"
43
+ )
44
+
45
+ print("============================================")
46
+ print("🐜 HormigasAIS Generator")
47
+ print("============================================")
48
+
49
+ for module_name in MODULES:
50
+
51
+ print(f"[LOAD] {module_name}")
52
+
53
+ try:
54
+
55
+ module = importlib.import_module(
56
+ f"generators.{module_name}"
57
+ )
58
+
59
+ if hasattr(module, "generate"):
60
+
61
+ module.generate(ROOT)
62
+
63
+ print(f"[ OK ] {module_name}")
64
+
65
+ else:
66
+
67
+ print(f"[SKIP] {module_name} (sin generate())")
68
+
69
+ except ModuleNotFoundError:
70
+
71
+ print(f"[WAIT] {module_name} aún no existe")
72
+
73
+ except Exception as e:
74
+
75
+ print(f"[FAIL] {module_name}")
76
+ print(e)
77
+
78
+ print("")
79
+ print("Proceso terminado.")
80
+ print("============================================")
81
+
82
+
83
+ if __name__ == "__main__":
84
+ main()
File without changes
@@ -0,0 +1,68 @@
1
+ """
2
+ agents_generator.py
3
+ HormigasAIS Edge Starter
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ def write_if_missing(path: Path, content: str):
9
+ if path.exists():
10
+ print(f" └── {path.name} ya existe")
11
+ return
12
+ path.parent.mkdir(parents=True, exist_ok=True)
13
+ path.write_text(content, encoding="utf-8")
14
+ print(f" └── {path.name} creado")
15
+
16
+ def generate(root: Path):
17
+ print("[LOAD] agents_generator")
18
+ agents_dir = root / "agents"
19
+ agents_dir.mkdir(exist_ok=True)
20
+
21
+ centinela_code = '''#!/usr/bin/env python3
22
+ """
23
+ hormiga_centinela.py
24
+ """
25
+ import time
26
+ import json
27
+ import sys
28
+ from pathlib import Path
29
+
30
+ ROOT = Path(__file__).resolve().parent.parent
31
+ sys.path.insert(0, str(ROOT))
32
+
33
+ from utils.env_loader import load_termux_secrets
34
+ load_termux_secrets()
35
+
36
+ from protocols.encoder import make_header, encode_packet
37
+ from protocols.constants import TYPE_CODES
38
+ from protocols.signer import seal_action
39
+
40
+ NODE_ID = "A16"
41
+ OWNER = "Cristhiam Leonardo Hernández Quiñonez"
42
+ INTERVAL = 30
43
+
44
+ def emit_pulse():
45
+ payload = json.dumps({
46
+ "agent": "hormiga_centinela",
47
+ "status": "ACTIVE",
48
+ "node": NODE_ID,
49
+ "ts": int(time.time())
50
+ })
51
+ header = make_header(NODE_ID[:3], "00")
52
+ frame = encode_packet(header, TYPE_CODES["FUEL"], payload)
53
+ seal = seal_action(payload, OWNER)
54
+ print("[CENTINELA] FUEL pulse emitido")
55
+ return frame
56
+
57
+ if __name__ == "__main__":
58
+ print(f"[CENTINELA] Iniciando en nodo {NODE_ID}")
59
+ while True:
60
+ emit_pulse()
61
+ time.sleep(INTERVAL)
62
+ '''
63
+
64
+ c_path = agents_dir / "hormiga_centinela.py"
65
+ write_if_missing(c_path, centinela_code)
66
+ c_path.chmod(0o755)
67
+
68
+ print("[ OK ] agents_generator")
@@ -0,0 +1,65 @@
1
+ """
2
+ config_generator.py
3
+ HormigasAIS Edge Starter
4
+
5
+ Genera la configuración inicial del nodo.
6
+ No sobrescribe configuraciones existentes.
7
+ """
8
+
9
+ from pathlib import Path
10
+ import json
11
+ import datetime
12
+ import getpass
13
+ import socket
14
+
15
+
16
+ def generate(root: Path):
17
+
18
+ config_dir = root / ".hormigasais"
19
+ config_dir.mkdir(exist_ok=True)
20
+
21
+ config_file = config_dir / "node_config.json"
22
+
23
+ if config_file.exists():
24
+ print(" └── node_config.json ya existe")
25
+ return
26
+
27
+ now = datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
28
+
29
+ hostname = socket.gethostname()
30
+
31
+ if hostname == "localhost":
32
+ hostname = "A16"
33
+
34
+ config = {
35
+ "schema": "LBH_NODE_CONFIG_V1",
36
+ "node_id": f"{hostname}-{getpass.getuser()}",
37
+ "node_name": "mi-colonia",
38
+ "protocol": "LBH_BINARY_V2",
39
+ "version": "2.0.0",
40
+ "owner": {
41
+ "name": "YOUR-NAME",
42
+ "email": "YOUR-EMAIL"
43
+ },
44
+ "location": {
45
+ "country": "SV",
46
+ "city": "San Miguel"
47
+ },
48
+ "master_node": "A16-SanMiguel-SV",
49
+ "created_at": now,
50
+ "status": "INITIALIZED",
51
+ "agents": [
52
+ "hormiga_centinela",
53
+ "hormiga_relevo"
54
+ ],
55
+ "security": {
56
+ "hmac_required": True,
57
+ "algorithm": "HMAC-SHA256"
58
+ },
59
+ "certificate": "PENDING"
60
+ }
61
+
62
+ with open(config_file, "w", encoding="utf-8") as f:
63
+ json.dump(config, f, indent=4, ensure_ascii=False)
64
+
65
+ print(" └── node_config.json creado")
@@ -0,0 +1,38 @@
1
+ """
2
+ contracts_generator.py
3
+ HormigasAIS Edge Starter
4
+ """
5
+
6
+ from pathlib import Path
7
+ import datetime
8
+
9
+ def write_if_missing(path: Path, content: str):
10
+ if path.exists():
11
+ print(f" └── {path.name} ya existe")
12
+ return
13
+ path.parent.mkdir(parents=True, exist_ok=True)
14
+ path.write_text(content, encoding="utf-8")
15
+ print(f" └── {path.name} creado")
16
+
17
+ def generate(root: Path):
18
+ print("[LOAD] contracts_generator")
19
+ protocols_dir = root / "protocols"
20
+ protocols_dir.mkdir(exist_ok=True)
21
+
22
+ fecha = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
23
+
24
+ contract_content = f"""\
25
+ ==============================================================================
26
+ .human GOVERNANCE CONTRACT — HormigasAIS Edge Starter
27
+ ==============================================================================
28
+ NODE: A16
29
+ OWNER: Cristhiam Leonardo Hernández Quiñonez
30
+ CREATED: {fecha}
31
+ SOVEREIGNTY DECLARATION:
32
+ This node operates under full digital sovereignty.
33
+ CERT::LBH-HUMAN-STARTER-V1-CLHQ
34
+ ==============================================================================
35
+ """
36
+ contract_path = protocols_dir / "human_contract.lbh"
37
+ write_if_missing(contract_path, contract_content)
38
+ print("[ OK ] contracts_generator")
@@ -0,0 +1,167 @@
1
+ """
2
+ protocol_generator.py
3
+ HormigasAIS Edge Starter
4
+
5
+ Genera el paquete protocols/ modular del SDK LBH.
6
+ No sobrescribe archivos existentes.
7
+ """
8
+
9
+ from pathlib import Path
10
+
11
+
12
+ def write_if_missing(path: Path, content: str):
13
+ if path.exists():
14
+ print(f" └── {path.name} ya existe")
15
+ return
16
+ path.write_text(content, encoding="utf-8")
17
+ print(f" └── {path.name} creado")
18
+
19
+
20
+ def generate(root: Path):
21
+
22
+ protocols = root / "protocols"
23
+ protocols.mkdir(exist_ok=True)
24
+
25
+ write_if_missing(
26
+ protocols / "__init__.py",
27
+ '''"""
28
+ LBH Protocol SDK
29
+ """
30
+
31
+ from .constants import TYPE_CODES
32
+ from .encoder import encode_packet
33
+ from .decoder import decode_packet
34
+ from .signer import seal_action
35
+ from .verifier import verify_signature
36
+ '''
37
+ )
38
+
39
+ write_if_missing(
40
+ protocols / "constants.py",
41
+ '''"""
42
+ Constantes oficiales LBH
43
+ """
44
+
45
+ TYPE_CODES = {
46
+ "SEAL":"5345414c",
47
+ "VERI":"56455249",
48
+ "SYNC":"53594e43",
49
+ "PING":"50494e47",
50
+ "FUEL":"4655454c",
51
+ "ACKK":"41434b4b",
52
+ "ERRR":"45525252",
53
+ }
54
+ '''
55
+ )
56
+
57
+ write_if_missing(
58
+ protocols / "encoder.py",
59
+ '''from .constants import TYPE_CODES
60
+
61
+ def make_header(node_id="A16", version="00"):
62
+ return (
63
+ node_id.encode().hex()[:4].ljust(4,"0") +
64
+ version.encode().hex()[:4].ljust(4,"0")
65
+ )
66
+
67
+ def encode_packet(header, type_code, payload):
68
+ payload_hex = payload.encode().hex()
69
+ length = format(len(payload_hex)//2,"08x")
70
+ return f"{header}{type_code}{length}{payload_hex}"
71
+ '''
72
+ )
73
+
74
+ write_if_missing(
75
+ protocols / "decoder.py",
76
+ '''def decode_packet(frame):
77
+ return {
78
+ "header":frame[:8],
79
+ "type_code":frame[8:16],
80
+ "length":int(frame[16:24],16),
81
+ "payload":bytes.fromhex(frame[24:]).decode()
82
+ }
83
+ '''
84
+ )
85
+
86
+ write_if_missing(
87
+ protocols / "signer.py",
88
+ '''import hashlib
89
+ import hmac
90
+ import os
91
+ import time
92
+
93
+ def seal_action(content, owner):
94
+
95
+ secret = os.environ.get("LBH_SECRET")
96
+
97
+ if not secret:
98
+ raise RuntimeError(
99
+ "LBH_SECRET no definido."
100
+ )
101
+
102
+ sha = hashlib.sha256(content.encode()).hexdigest()
103
+
104
+ ts = int(time.time())
105
+
106
+ payload = f"{sha}|{owner}|{ts}"
107
+
108
+ sig = hmac.new(
109
+ secret.encode(),
110
+ payload.encode(),
111
+ hashlib.sha256
112
+ ).hexdigest()
113
+
114
+ return {
115
+ "sha256":sha,
116
+ "firma":sig,
117
+ "timestamp":ts,
118
+ "owner":owner
119
+ }
120
+ '''
121
+ )
122
+
123
+ write_if_missing(
124
+ protocols / "verifier.py",
125
+ '''import hashlib
126
+ import hmac
127
+ import os
128
+
129
+ def verify_signature(content, signature, owner, timestamp):
130
+
131
+ secret = os.environ.get("LBH_SECRET")
132
+
133
+ if not secret:
134
+ return False
135
+
136
+ sha = hashlib.sha256(content.encode()).hexdigest()
137
+
138
+ payload = f"{sha}|{owner}|{timestamp}"
139
+
140
+ expected = hmac.new(
141
+ secret.encode(),
142
+ payload.encode(),
143
+ hashlib.sha256
144
+ ).hexdigest()
145
+
146
+ return hmac.compare_digest(
147
+ expected,
148
+ signature
149
+ )
150
+ '''
151
+ )
152
+
153
+ write_if_missing(
154
+ protocols / "lbh_core.py",
155
+ '''"""
156
+ Compatibilidad con versiones anteriores.
157
+
158
+ Importa automáticamente todos los módulos del SDK.
159
+ """
160
+
161
+ from .constants import *
162
+ from .encoder import *
163
+ from .decoder import *
164
+ from .signer import *
165
+ from .verifier import *
166
+ '''
167
+ )
@@ -0,0 +1,283 @@
1
+ """
2
+ scripts_generator.py
3
+ HormigasAIS Edge Starter
4
+
5
+ Genera scripts auxiliares del starter.
6
+
7
+ Fase:
8
+ - utils/env_loader.py
9
+ - scripts/verify_sdk.py (POST del SDK LBH)
10
+ """
11
+
12
+ from pathlib import Path
13
+
14
+
15
+ def write_if_missing(path: Path, content: str):
16
+ if path.exists():
17
+ print(f" └── {path.name} ya existe")
18
+ return
19
+
20
+ path.parent.mkdir(parents=True, exist_ok=True)
21
+ path.write_text(content, encoding="utf-8")
22
+ print(f" └── {path.name} creado")
23
+
24
+
25
+ def generate(root: Path):
26
+
27
+ print("[LOAD] scripts_generator")
28
+
29
+ # ============================================================
30
+ # utils/env_loader.py
31
+ # ============================================================
32
+
33
+ utils = root / "utils"
34
+ utils.mkdir(exist_ok=True)
35
+
36
+ env_loader = r'''
37
+ """
38
+ env_loader.py
39
+ HormigasAIS Secret Loader
40
+
41
+ Carga secretos desde:
42
+ - Variables de entorno
43
+ - ~/.hormigas_secrets
44
+ """
45
+
46
+ from pathlib import Path
47
+ import os
48
+
49
+
50
+ def load_termux_secrets():
51
+
52
+ secret_file = Path.home() / ".hormigas_secrets"
53
+
54
+ if not secret_file.exists():
55
+ return
56
+
57
+ for line in secret_file.read_text(
58
+ encoding="utf-8"
59
+ ).splitlines():
60
+
61
+ line = line.strip()
62
+
63
+ if (
64
+ not line
65
+ or line.startswith("#")
66
+ or "=" not in line
67
+ ):
68
+ continue
69
+
70
+ key, value = line.split("=", 1)
71
+
72
+ os.environ.setdefault(
73
+ key.strip(),
74
+ value.strip()
75
+ .strip('"')
76
+ .strip("'")
77
+ )
78
+ '''
79
+
80
+ write_if_missing(
81
+ utils / "env_loader.py",
82
+ env_loader
83
+ )
84
+
85
+
86
+ # ============================================================
87
+ # scripts/verify_sdk.py
88
+ # ============================================================
89
+
90
+ scripts = root / "scripts"
91
+ scripts.mkdir(exist_ok=True)
92
+
93
+
94
+ verify_sdk = r'''#!/usr/bin/env python3
95
+
96
+ """
97
+ verify_sdk.py
98
+ HormigasAIS LBH SDK Power-On Self Test (POST)
99
+ """
100
+
101
+ import json
102
+ import os
103
+ import sys
104
+ from pathlib import Path
105
+
106
+
107
+ ROOT = Path(__file__).resolve().parent.parent
108
+
109
+ sys.path.insert(
110
+ 0,
111
+ str(ROOT)
112
+ )
113
+
114
+
115
+ from utils.env_loader import load_termux_secrets
116
+
117
+ load_termux_secrets()
118
+
119
+
120
+ print("========================================")
121
+ print("🐜 HormigasAIS :: SDK POST")
122
+ print("========================================")
123
+
124
+
125
+ try:
126
+
127
+ from protocols.encoder import (
128
+ make_header,
129
+ encode_packet
130
+ )
131
+
132
+ from protocols.decoder import (
133
+ decode_packet
134
+ )
135
+
136
+ from protocols.constants import (
137
+ TYPE_CODES
138
+ )
139
+
140
+ from protocols.signer import (
141
+ seal_action
142
+ )
143
+
144
+ from protocols.verifier import (
145
+ verify_signature
146
+ )
147
+
148
+
149
+ except Exception as e:
150
+
151
+ print("[FAIL] Importación del SDK")
152
+ print(e)
153
+ sys.exit(1)
154
+
155
+
156
+ print("[ OK ] Importación del SDK")
157
+
158
+
159
+ secret = os.environ.get(
160
+ "LBH_SECRET"
161
+ )
162
+
163
+
164
+ if not secret:
165
+
166
+ print(
167
+ "[FAIL] LBH_SECRET no definido"
168
+ )
169
+
170
+ print(
171
+ "Configure ~/.hormigas_secrets"
172
+ )
173
+
174
+ sys.exit(1)
175
+
176
+
177
+ print(
178
+ "[ OK ] LBH_SECRET disponible"
179
+ )
180
+
181
+
182
+ payload = json.dumps(
183
+ {
184
+ "action": "sdk_post",
185
+ "node": "SELFTEST"
186
+ }
187
+ )
188
+
189
+
190
+ frame = encode_packet(
191
+ make_header(
192
+ "A16",
193
+ "00"
194
+ ),
195
+ TYPE_CODES["FUEL"],
196
+ payload
197
+ )
198
+
199
+
200
+ print(
201
+ "[ OK ] Codificación LBH"
202
+ )
203
+
204
+
205
+ decoded = decode_packet(frame)
206
+
207
+
208
+ if decoded["payload"] != payload:
209
+
210
+ print(
211
+ "[FAIL] Decodificación"
212
+ )
213
+
214
+ sys.exit(1)
215
+
216
+
217
+ print(
218
+ "[ OK ] Decodificación"
219
+ )
220
+
221
+
222
+ seal = seal_action(
223
+ payload,
224
+ "SELFTEST"
225
+ )
226
+
227
+
228
+ print(
229
+ "[ OK ] Firma HMAC"
230
+ )
231
+
232
+
233
+ valid = verify_signature(
234
+ payload,
235
+ seal["firma"],
236
+ seal["owner"],
237
+ seal["timestamp"]
238
+ )
239
+
240
+
241
+ if not valid:
242
+
243
+ print(
244
+ "[FAIL] Verificación HMAC"
245
+ )
246
+
247
+ sys.exit(1)
248
+
249
+
250
+ print(
251
+ "[ OK ] Verificación HMAC"
252
+ )
253
+
254
+
255
+ print("")
256
+
257
+ print(
258
+ "========================================"
259
+ )
260
+
261
+ print(
262
+ "SDK LBH OPERATIVO"
263
+ )
264
+
265
+ print(
266
+ "========================================"
267
+ )
268
+ '''
269
+
270
+
271
+ verify = scripts / "verify_sdk.py"
272
+
273
+ write_if_missing(
274
+ verify,
275
+ verify_sdk
276
+ )
277
+
278
+ verify.chmod(0o755)
279
+
280
+
281
+ print("[ OK ] scripts_generator")
282
+
283
+
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "hormigasais-edge-starter",
3
+ "version": "0.1.0",
4
+ "description": "Starter template para desplegar un nodo soberano HormigasAIS con agentes LBH. Incluye SDK de protocolos LBH, generadores automáticos y agentes edge.",
5
+ "main": "generator.js",
6
+ "bin": {
7
+ "create-hormigas-node": "./generator.js"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/Thrumanshow/hormigasais-edge-starter.git"
12
+ },
13
+ "keywords": [
14
+ "hormigasais",
15
+ "edge-computing",
16
+ "sovereign-node",
17
+ "lbh-protocol",
18
+ "agent-based",
19
+ "termux",
20
+ "offline-first"
21
+ ],
22
+ "author": "Cristhiam Leonardo Hernández Quiñonez",
23
+ "license": "MIT",
24
+ "bugs": {
25
+ "url": "https://github.com/Thrumanshow/hormigasais-edge-starter/issues"
26
+ },
27
+ "homepage": "https://github.com/Thrumanshow/hormigasais-edge-starter#readme",
28
+ "scripts": {
29
+ "start": "python3 generator.py",
30
+ "bootstrap": "bash bootstrap.sh",
31
+ "verify": "python3 scripts/verify_sdk.py",
32
+ "postinstall": "python3 generator.py --quick || echo 'HormigasAIS Edge Starter instalado'",
33
+ "test": "python3 scripts/verify_sdk.py"
34
+ },
35
+ "dependencies": {
36
+ "jspdf": "^2.5.1"
37
+ },
38
+ "engines": {
39
+ "node": ">=14.0.0"
40
+ }
41
+ }
@@ -0,0 +1,9 @@
1
+ """
2
+ LBH Protocol SDK
3
+ """
4
+
5
+ from .constants import TYPE_CODES
6
+ from .encoder import encode_packet
7
+ from .decoder import decode_packet
8
+ from .signer import seal_action
9
+ from .verifier import verify_signature
@@ -0,0 +1,13 @@
1
+ """
2
+ Constantes oficiales LBH
3
+ """
4
+
5
+ TYPE_CODES = {
6
+ "SEAL":"5345414c",
7
+ "VERI":"56455249",
8
+ "SYNC":"53594e43",
9
+ "PING":"50494e47",
10
+ "FUEL":"4655454c",
11
+ "ACKK":"41434b4b",
12
+ "ERRR":"45525252",
13
+ }
@@ -0,0 +1,7 @@
1
+ def decode_packet(frame):
2
+ return {
3
+ "header":frame[:8],
4
+ "type_code":frame[8:16],
5
+ "length":int(frame[16:24],16),
6
+ "payload":bytes.fromhex(frame[24:]).decode()
7
+ }
@@ -0,0 +1,12 @@
1
+ from .constants import TYPE_CODES
2
+
3
+ def make_header(node_id="A16", version="00"):
4
+ return (
5
+ node_id.encode().hex()[:4].ljust(4,"0") +
6
+ version.encode().hex()[:4].ljust(4,"0")
7
+ )
8
+
9
+ def encode_packet(header, type_code, payload):
10
+ payload_hex = payload.encode().hex()
11
+ length = format(len(payload_hex)//2,"08x")
12
+ return f"{header}{type_code}{length}{payload_hex}"
@@ -0,0 +1,10 @@
1
+ ==============================================================================
2
+ .human GOVERNANCE CONTRACT — HormigasAIS Edge Starter
3
+ ==============================================================================
4
+ NODE: A16
5
+ OWNER: Cristhiam Leonardo Hernández Quiñonez
6
+ CREATED: 2026-07-24T05:54:01Z
7
+ SOVEREIGNTY DECLARATION:
8
+ This node operates under full digital sovereignty.
9
+ CERT::LBH-HUMAN-STARTER-V1-CLHQ
10
+ ==============================================================================
@@ -0,0 +1,11 @@
1
+ """
2
+ Compatibilidad con versiones anteriores.
3
+
4
+ Importa automáticamente todos los módulos del SDK.
5
+ """
6
+
7
+ from .constants import *
8
+ from .encoder import *
9
+ from .decoder import *
10
+ from .signer import *
11
+ from .verifier import *
@@ -0,0 +1,32 @@
1
+ import hashlib
2
+ import hmac
3
+ import os
4
+ import time
5
+
6
+ def seal_action(content, owner):
7
+
8
+ secret = os.environ.get("LBH_SECRET")
9
+
10
+ if not secret:
11
+ raise RuntimeError(
12
+ "LBH_SECRET no definido."
13
+ )
14
+
15
+ sha = hashlib.sha256(content.encode()).hexdigest()
16
+
17
+ ts = int(time.time())
18
+
19
+ payload = f"{sha}|{owner}|{ts}"
20
+
21
+ sig = hmac.new(
22
+ secret.encode(),
23
+ payload.encode(),
24
+ hashlib.sha256
25
+ ).hexdigest()
26
+
27
+ return {
28
+ "sha256":sha,
29
+ "firma":sig,
30
+ "timestamp":ts,
31
+ "owner":owner
32
+ }
@@ -0,0 +1,25 @@
1
+ import hashlib
2
+ import hmac
3
+ import os
4
+
5
+ def verify_signature(content, signature, owner, timestamp):
6
+
7
+ secret = os.environ.get("LBH_SECRET")
8
+
9
+ if not secret:
10
+ return False
11
+
12
+ sha = hashlib.sha256(content.encode()).hexdigest()
13
+
14
+ payload = f"{sha}|{owner}|{timestamp}"
15
+
16
+ expected = hmac.new(
17
+ secret.encode(),
18
+ payload.encode(),
19
+ hashlib.sha256
20
+ ).hexdigest()
21
+
22
+ return hmac.compare_digest(
23
+ expected,
24
+ signature
25
+ )
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ verify_sdk.py
4
+ LBH SDK Power-On Self Test (POST)
5
+ """
6
+
7
+ import json
8
+ import os
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ ROOT = Path(__file__).resolve().parent.parent
13
+ sys.path.insert(0, str(ROOT))
14
+
15
+ print("========================================")
16
+ print("🐜 HormigasAIS :: SDK POST")
17
+ print("========================================")
18
+
19
+ try:
20
+ from protocols.encoder import make_header, encode_packet
21
+ from protocols.decoder import decode_packet
22
+ from protocols.constants import TYPE_CODES
23
+ from protocols.signer import seal_action
24
+ from protocols.verifier import verify_signature
25
+ except Exception as e:
26
+ print("[FAIL] Importación del SDK")
27
+ print(e)
28
+ sys.exit(1)
29
+
30
+ print("[ OK ] Importación del SDK")
31
+
32
+ secret = os.environ.get("LBH_SECRET")
33
+
34
+ if not secret:
35
+ print("[FAIL] LBH_SECRET no definido")
36
+ sys.exit(1)
37
+
38
+ print("[ OK ] LBH_SECRET disponible")
39
+
40
+ payload = json.dumps({
41
+ "action":"sdk_post",
42
+ "node":"SELFTEST"
43
+ })
44
+
45
+ frame = encode_packet(
46
+ make_header("A16","00"),
47
+ TYPE_CODES["FUEL"],
48
+ payload
49
+ )
50
+
51
+ print("[ OK ] Codificación LBH")
52
+
53
+ decoded = decode_packet(frame)
54
+
55
+ if decoded["payload"] != payload:
56
+ print("[FAIL] Decodificación")
57
+ sys.exit(1)
58
+
59
+ print("[ OK ] Decodificación")
60
+
61
+ seal = seal_action(
62
+ payload,
63
+ "SELFTEST"
64
+ )
65
+
66
+ print("[ OK ] Firma HMAC")
67
+
68
+ valid = verify_signature(
69
+ payload,
70
+ seal["firma"],
71
+ seal["owner"],
72
+ seal["timestamp"]
73
+ )
74
+
75
+ if not valid:
76
+ print("[FAIL] Verificación HMAC")
77
+ sys.exit(1)
78
+
79
+ print("[ OK ] Verificación HMAC")
80
+
81
+ print("")
82
+ print("========================================")
83
+ print("SDK LBH OPERATIVO")
84
+ print("========================================")
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env bash
2
+ cd ~/hormigasais-edge-starter
3
+
4
+ echo "🐜 Actualizando agents_generator.py y contracts_generator.py..."
5
+
6
+ # agents_generator.py
7
+ cat << 'AGENT' > generators/agents_generator.py
8
+ """
9
+ agents_generator.py
10
+ HormigasAIS Edge Starter
11
+ """
12
+
13
+ from pathlib import Path
14
+
15
+ def write_if_missing(path: Path, content: str):
16
+ if path.exists():
17
+ print(f" └── {path.name} ya existe")
18
+ return
19
+ path.parent.mkdir(parents=True, exist_ok=True)
20
+ path.write_text(content, encoding="utf-8")
21
+ print(f" └── {path.name} creado")
22
+
23
+ def generate(root: Path):
24
+ print("[LOAD] agents_generator")
25
+ agents_dir = root / "agents"
26
+ agents_dir.mkdir(exist_ok=True)
27
+
28
+ centinela_code = '''#!/usr/bin/env python3
29
+ """
30
+ hormiga_centinela.py
31
+ """
32
+ import time
33
+ import json
34
+ import sys
35
+ from pathlib import Path
36
+
37
+ ROOT = Path(__file__).resolve().parent.parent
38
+ sys.path.insert(0, str(ROOT))
39
+
40
+ from utils.env_loader import load_termux_secrets
41
+ load_termux_secrets()
42
+
43
+ from protocols.encoder import make_header, encode_packet
44
+ from protocols.constants import TYPE_CODES
45
+ from protocols.signer import seal_action
46
+
47
+ NODE_ID = "A16"
48
+ OWNER = "Cristhiam Leonardo Hernández Quiñonez"
49
+ INTERVAL = 30
50
+
51
+ def emit_pulse():
52
+ payload = json.dumps({
53
+ "agent": "hormiga_centinela",
54
+ "status": "ACTIVE",
55
+ "node": NODE_ID,
56
+ "ts": int(time.time())
57
+ })
58
+ header = make_header(NODE_ID[:3], "00")
59
+ frame = encode_packet(header, TYPE_CODES["FUEL"], payload)
60
+ seal = seal_action(payload, OWNER)
61
+ print("[CENTINELA] FUEL pulse emitido")
62
+ return frame
63
+
64
+ if __name__ == "__main__":
65
+ print(f"[CENTINELA] Iniciando en nodo {NODE_ID}")
66
+ while True:
67
+ emit_pulse()
68
+ time.sleep(INTERVAL)
69
+ '''
70
+
71
+ c_path = agents_dir / "hormiga_centinela.py"
72
+ write_if_missing(c_path, centinela_code)
73
+ c_path.chmod(0o755)
74
+
75
+ print("[ OK ] agents_generator")
76
+ AGENT
77
+
78
+ # contracts_generator.py
79
+ cat << 'CONTRACT' > generators/contracts_generator.py
80
+ """
81
+ contracts_generator.py
82
+ HormigasAIS Edge Starter
83
+ """
84
+
85
+ from pathlib import Path
86
+ import datetime
87
+
88
+ def write_if_missing(path: Path, content: str):
89
+ if path.exists():
90
+ print(f" └── {path.name} ya existe")
91
+ return
92
+ path.parent.mkdir(parents=True, exist_ok=True)
93
+ path.write_text(content, encoding="utf-8")
94
+ print(f" └── {path.name} creado")
95
+
96
+ def generate(root: Path):
97
+ print("[LOAD] contracts_generator")
98
+ protocols_dir = root / "protocols"
99
+ protocols_dir.mkdir(exist_ok=True)
100
+
101
+ fecha = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
102
+
103
+ contract_content = f"""\
104
+ ==============================================================================
105
+ .human GOVERNANCE CONTRACT — HormigasAIS Edge Starter
106
+ ==============================================================================
107
+ NODE: A16
108
+ OWNER: Cristhiam Leonardo Hernández Quiñonez
109
+ CREATED: {fecha}
110
+ SOVEREIGNTY DECLARATION:
111
+ This node operates under full digital sovereignty.
112
+ CERT::LBH-HUMAN-STARTER-V1-CLHQ
113
+ ==============================================================================
114
+ """
115
+ contract_path = protocols_dir / "human_contract.lbh"
116
+ write_if_missing(contract_path, contract_content)
117
+ print("[ OK ] contracts_generator")
118
+ CONTRACT
119
+
120
+ echo "✅ Generadores actualizados"
121
+
122
+ python3 generator.py
123
+ echo "✅ agents y contracts actualizados correctamente."
@@ -0,0 +1,42 @@
1
+
2
+ """
3
+ env_loader.py
4
+ HormigasAIS Secret Loader
5
+
6
+ Carga secretos desde:
7
+ - Variables de entorno
8
+ - ~/.hormigas_secrets
9
+ """
10
+
11
+ from pathlib import Path
12
+ import os
13
+
14
+
15
+ def load_termux_secrets():
16
+
17
+ secret_file = Path.home() / ".hormigas_secrets"
18
+
19
+ if not secret_file.exists():
20
+ return
21
+
22
+ for line in secret_file.read_text(
23
+ encoding="utf-8"
24
+ ).splitlines():
25
+
26
+ line = line.strip()
27
+
28
+ if (
29
+ not line
30
+ or line.startswith("#")
31
+ or "=" not in line
32
+ ):
33
+ continue
34
+
35
+ key, value = line.split("=", 1)
36
+
37
+ os.environ.setdefault(
38
+ key.strip(),
39
+ value.strip()
40
+ .strip('"')
41
+ .strip("'")
42
+ )