@innvisor/conny-ai 9.7.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 +68 -0
- package/CHANGELOG.md +54 -0
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/brand-assets/A_dark_luxury_web_background_202605210700.jpeg +0 -0
- package/brand-assets/Conny.web.logo.png +0 -0
- package/brand-assets/Logo_Conny_Petalo_Claro.png +0 -0
- package/brand-assets/cl-nica-de-las-am-ricas/manifest.json +22 -0
- package/brand-assets/cl-nica-de-las-am-ricas/processed/business-identity.txt +11 -0
- package/brand-assets/cl-nica-de-las-am-ricas/raw/business-identity.txt +11 -0
- package/brand-assets/cl-nica-las-am-ricas/manifest.json +22 -0
- package/brand-assets/cl-nica-las-am-ricas/processed/business-identity.txt +11 -0
- package/brand-assets/cl-nica-las-am-ricas/raw/business-identity.txt +11 -0
- package/brand-assets/conny-demo/manifest.json +22 -0
- package/brand-assets/conny-demo/processed/business-identity.txt +7 -0
- package/brand-assets/conny-demo/raw/business-identity.txt +7 -0
- package/brand-assets/conny-logo.png +0 -0
- package/brand-assets/web.background.png +0 -0
- package/brand_assets.py +323 -0
- package/conny +28 -0
- package/conny-chat.py +579 -0
- package/conny-omni.py +3843 -0
- package/conny.py +113 -0
- package/conny_agents/__init__.py +1 -0
- package/conny_agents/agenda.py +1 -0
- package/conny_agents/captacion.py +1 -0
- package/conny_agents/conocimiento.py +1 -0
- package/conny_agents/escalacion.py +1 -0
- package/conny_agents/objeciones.py +1 -0
- package/conny_agents/seguimiento.py +1 -0
- package/conny_app.py +287 -0
- package/conny_audio.py +350 -0
- package/conny_audio_learn.py +84 -0
- package/conny_brain_v10.py +804 -0
- package/conny_bridge.py +656 -0
- package/conny_calendar.py +169 -0
- package/conny_cli.py +11784 -0
- package/conny_cli_bb.py +437 -0
- package/conny_commands.py +243 -0
- package/conny_config.py +215 -0
- package/conny_core/__init__.py +3 -0
- package/conny_core/conversation_engine.py +446 -0
- package/conny_core/first_turn_ops.py +287 -0
- package/conny_core/persona_registry.py +157 -0
- package/conny_core/prompt_ops.py +561 -0
- package/conny_cron.py +72 -0
- package/conny_demo_v2.py +209 -0
- package/conny_demo_voice.py +134 -0
- package/conny_design.py +43 -0
- package/conny_doctor.py +319 -0
- package/conny_domino.py +696 -0
- package/conny_generator.py +447 -0
- package/conny_google_auth.py +159 -0
- package/conny_i18n.py +619 -0
- package/conny_init.py +509 -0
- package/conny_integrations/__init__.py +4 -0
- package/conny_integrations/llm.py +1 -0
- package/conny_integrations/vault.py +77 -0
- package/conny_integrations/whatsapp.py +1 -0
- package/conny_intelligence.py +65 -0
- package/conny_learning.py +154 -0
- package/conny_memory.py +243 -0
- package/conny_memory_engine.py +292 -0
- package/conny_nova_proxy.py +170 -0
- package/conny_nuke_robot_phrases.py +493 -0
- package/conny_pairing.py +253 -0
- package/conny_patch.py +291 -0
- package/conny_persona_cli.py +150 -0
- package/conny_router.py +308 -0
- package/conny_runtime_ops.py +271 -0
- package/conny_session.py +516 -0
- package/conny_skills/__init__.py +1 -0
- package/conny_skills/demo_mode.py +35 -0
- package/conny_skills/text_processing.py +1 -0
- package/conny_skills/tone_detection.py +1 -0
- package/conny_smart_features.py +333 -0
- package/conny_studio.py +161 -0
- package/conny_sync_fix.py +306 -0
- package/conny_tui.py +512 -0
- package/conny_tui_select.py +202 -0
- package/conny_ultra_config.py +411 -0
- package/conny_uncertainty.py +174 -0
- package/conny_utils.py +87 -0
- package/conny_voice.py +156 -0
- package/conny_voice_engine.py +124 -0
- package/conny_web_search.py +66 -0
- package/conny_weekly_report.py +85 -0
- package/conny_worm.py +88 -0
- package/core/__init__.py +25 -0
- package/ecosystem.config.js +24 -0
- package/fix_init.py +27 -0
- package/install.sh +78 -0
- package/knowledge_base.py +330 -0
- package/nova/rules/default.yaml +37 -0
- package/nova_bridge.py +509 -0
- package/npm/conny.js +471 -0
- package/package.json +102 -0
- package/personas/conny/base/default.yaml +35 -0
- package/personas/conny/base/estetica_whatsapp.yaml +36 -0
- package/requirements.txt +14 -0
- package/run.sh +47 -0
- package/search.py +465 -0
- package/smart_handoff.py +1150 -0
- package/src/__init__.py +0 -0
- package/src/conny/__init__.py +0 -0
- package/src/conny/admin/__init__.py +0 -0
- package/src/conny/admin/api.py +234 -0
- package/src/conny/admin/dashboard.py +772 -0
- package/src/conny/api/__init__.py +0 -0
- package/src/conny/api/routes.py +8851 -0
- package/src/conny/brain/__init__.py +15 -0
- package/src/conny/brain/engine.py +804 -0
- package/src/conny/brain/learning.py +154 -0
- package/src/conny/brain/memory.py +324 -0
- package/src/conny/brain/smart_features.py +333 -0
- package/src/conny/brain/uncertainty.py +167 -0
- package/src/conny/channels/__init__.py +0 -0
- package/src/conny/channels/audio.py +316 -0
- package/src/conny/channels/cli.py +11795 -0
- package/src/conny/channels/logo_art.py +11 -0
- package/src/conny/channels/voice.py +156 -0
- package/src/conny/core/__init__.py +0 -0
- package/src/conny/core/config.py +215 -0
- package/src/conny/core/cron.py +72 -0
- package/src/conny/core/messenger.py +563 -0
- package/src/conny/core/router.py +297 -0
- package/src/conny/core/session.py +312 -0
- package/src/conny/demo/__init__.py +0 -0
- package/src/conny/demo/handler.py +3110 -0
- package/src/conny/integrations/__init__.py +19 -0
- package/src/conny/integrations/calendar.py +169 -0
- package/src/conny/integrations/knowledge.py +312 -0
- package/src/conny/integrations/search.py +66 -0
- package/src/conny/personas/__init__.py +0 -0
- package/src/conny/personas/generator.py +447 -0
- package/src/conny/production/__init__.py +0 -0
- package/src/conny/production/domino.py +696 -0
- package/src/conny/production/guard.py +550 -0
- package/src/conny/production/handoff.py +1150 -0
- package/src/conny/production/monitor.py +353 -0
- package/src/conny/utils/__init__.py +2 -0
- package/src/conny/utils/helpers.py +75 -0
- package/src/conny/utils/i18n.py +619 -0
- package/src/core/admin_engines.py +772 -0
- package/src/core/globals.py +11845 -0
- package/src/core/orchestrator.py +273 -0
- package/src/core/production_monitor.py +353 -0
- package/src/core/runtime.py +5487 -0
- package/src/domain/onboarding_flow.py +230 -0
- package/src/domain/prompts/__init__.py +1 -0
- package/src/domain/prompts/prospect_pitch.py +282 -0
- package/src/domain/send_guard.py +636 -0
- package/src/domain/swarm/queen.py +96 -0
- package/src/infrastructure/llm_providers/engine.py +487 -0
- package/src/interfaces/mcp_server.py +73 -0
- package/src/interfaces/nova_bridge.py +58 -0
- package/src/interfaces/web/admin_api.py +1379 -0
- package/src/interfaces/web/app.py +9408 -0
- package/src/interfaces/web/demo_handler.py +3450 -0
- package/src/interfaces/web/static/generate_avatars.py +46 -0
- package/v7/__init__.py +46 -0
- package/v7/agents/__init__.py +46 -0
- package/v7/agents/agenda.py +77 -0
- package/v7/agents/base.py +216 -0
- package/v7/agents/captacion.py +60 -0
- package/v7/agents/conocimiento.py +69 -0
- package/v7/agents/escalacion.py +83 -0
- package/v7/agents/objeciones.py +109 -0
- package/v7/agents/seguimiento.py +71 -0
- package/v7/memory/__init__.py +46 -0
- package/v7/memory/patient_profile.py +200 -0
- package/v7/orchestrator.py +275 -0
- package/v7/postprocess.py +127 -0
- package/v7/router.py +239 -0
- package/verify_conversation_impl.py +48 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
conny_sync_fix.py — Parcha conny_cli.py con 3 correcciones críticas
|
|
4
|
+
|
|
5
|
+
Bugs que corrige:
|
|
6
|
+
1. INSTANCES_DIR apuntaba a ~/.conny/instances en vez de ~/conny-instances
|
|
7
|
+
2. 'personas' en SYNC_RUNTIME_DIRS sobrescribía identidades de clientes
|
|
8
|
+
3. _clone_runtime_entries usaba rmtree en directorios (destructivo)
|
|
9
|
+
|
|
10
|
+
Uso:
|
|
11
|
+
cd ~/conny
|
|
12
|
+
python3 conny_sync_fix.py
|
|
13
|
+
|
|
14
|
+
El script crea un backup antes de modificar.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import sys
|
|
18
|
+
import os
|
|
19
|
+
import shutil
|
|
20
|
+
import re
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
|
|
24
|
+
CLI_PATH = Path(__file__).resolve().parent / "conny_cli.py"
|
|
25
|
+
|
|
26
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
27
|
+
# Parches exactos (old_str → new_str)
|
|
28
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
29
|
+
|
|
30
|
+
PATCHES = [
|
|
31
|
+
|
|
32
|
+
# ── FIX 1: INSTANCES_DIR default path ────────────────────────────────────
|
|
33
|
+
{
|
|
34
|
+
"id": "fix-instances-dir",
|
|
35
|
+
"desc": "Corregir INSTANCES_DIR: ~/.conny/instances → ~/conny-instances",
|
|
36
|
+
"old": 'INSTANCES_DIR = os.getenv("INSTANCES_DIR", str(Path(CONNY_HOME) / "instances"))',
|
|
37
|
+
"new": 'INSTANCES_DIR = os.getenv("INSTANCES_DIR", str(Path.home() / "conny-instances"))',
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
# ── FIX 2: Remove 'personas' from SYNC_RUNTIME_DIRS ─────────────────────
|
|
41
|
+
{
|
|
42
|
+
"id": "fix-sync-dirs",
|
|
43
|
+
"desc": "Proteger directorios de identidad de instancias en sync",
|
|
44
|
+
"old": '''SYNC_RUNTIME_DIRS = [
|
|
45
|
+
"v7",
|
|
46
|
+
"conny_core",
|
|
47
|
+
"conny_agents",
|
|
48
|
+
"conny_skills",
|
|
49
|
+
"conny_integrations",
|
|
50
|
+
"personas",
|
|
51
|
+
]''',
|
|
52
|
+
"new": '''# ── Directorios que se sincronizan a todas las instancias ──────────────────
|
|
53
|
+
SYNC_RUNTIME_DIRS = [
|
|
54
|
+
"v7",
|
|
55
|
+
"conny_core",
|
|
56
|
+
"conny_agents",
|
|
57
|
+
"conny_skills",
|
|
58
|
+
"conny_integrations",
|
|
59
|
+
# "personas" INTENCIONALMENTE EXCLUIDO:
|
|
60
|
+
# cada instancia tiene su propia identidad, prompts y tono.
|
|
61
|
+
# Usa 'conny config <nombre>' para editar la persona de un cliente.
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
# ── Paths que NUNCA se tocan durante sync ──────────────────────────────────
|
|
65
|
+
INSTANCE_PROTECTED_PATHS = {
|
|
66
|
+
".env",
|
|
67
|
+
"conny.db", "conny.db-shm", "conny.db-wal",
|
|
68
|
+
"conny_ultra.db", "vectors.db", "data.db",
|
|
69
|
+
"logs",
|
|
70
|
+
"identity", # Nombre, voz, tono del agente
|
|
71
|
+
"soul", # Valores y ética del agente
|
|
72
|
+
"personas", # Prompts de sistema del cliente
|
|
73
|
+
"knowledge_base", # Base de conocimiento del cliente
|
|
74
|
+
"instance.json",
|
|
75
|
+
"auth_info_multi.txt",
|
|
76
|
+
"__pycache__",
|
|
77
|
+
"backups",
|
|
78
|
+
".venv",
|
|
79
|
+
}
|
|
80
|
+
''',
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
# ── FIX 3: Smart directory sync (no rmtree) ───────────────────────────────
|
|
84
|
+
{
|
|
85
|
+
"id": "fix-clone-entries",
|
|
86
|
+
"desc": "Sync inteligente: actualiza archivos sin borrar los específicos de la instancia",
|
|
87
|
+
"old": '''def _clone_runtime_entries(source_root: str, dest_root: str, entries: Optional[List[str]] = None) -> List[str]:
|
|
88
|
+
src_root = Path(source_root)
|
|
89
|
+
dst_root = Path(dest_root)
|
|
90
|
+
copied: List[str] = []
|
|
91
|
+
for rel_path in entries or _runtime_sync_entries(source_root):
|
|
92
|
+
src = src_root / rel_path
|
|
93
|
+
dst = dst_root / rel_path
|
|
94
|
+
if not src.exists():
|
|
95
|
+
continue
|
|
96
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
if src.is_dir():
|
|
98
|
+
_remove_runtime_target(dst)
|
|
99
|
+
shutil.copytree(src, dst)
|
|
100
|
+
else:
|
|
101
|
+
if dst.exists() or dst.is_symlink():
|
|
102
|
+
_remove_runtime_target(dst)
|
|
103
|
+
shutil.copy2(src, dst)
|
|
104
|
+
copied.append(rel_path)
|
|
105
|
+
return copied''',
|
|
106
|
+
"new": '''def _sync_dir_smart(src: Path, dst: Path) -> None:
|
|
107
|
+
"""
|
|
108
|
+
Sync de directorio que ACTUALIZA archivos sin borrar extras.
|
|
109
|
+
A diferencia de copytree(dirs_exist_ok=False), no elimina archivos
|
|
110
|
+
que solo existen en el destino (configuraciones del cliente).
|
|
111
|
+
"""
|
|
112
|
+
dst.mkdir(parents=True, exist_ok=True)
|
|
113
|
+
for item in src.rglob("*"):
|
|
114
|
+
rel = item.relative_to(src)
|
|
115
|
+
target = dst / rel
|
|
116
|
+
# Nunca pisar rutas protegidas dentro de subdirectorios
|
|
117
|
+
top = rel.parts[0] if rel.parts else ""
|
|
118
|
+
if top in INSTANCE_PROTECTED_PATHS:
|
|
119
|
+
continue
|
|
120
|
+
try:
|
|
121
|
+
if item.is_dir():
|
|
122
|
+
target.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
else:
|
|
124
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
125
|
+
shutil.copy2(item, target)
|
|
126
|
+
except Exception:
|
|
127
|
+
pass # permisos u otros errores no detienen el sync
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _clone_runtime_entries(source_root: str, dest_root: str, entries: Optional[List[str]] = None) -> List[str]:
|
|
131
|
+
src_root = Path(source_root)
|
|
132
|
+
dst_root = Path(dest_root)
|
|
133
|
+
copied: List[str] = []
|
|
134
|
+
for rel_path in entries or _runtime_sync_entries(source_root):
|
|
135
|
+
# Saltar rutas protegidas de la instancia
|
|
136
|
+
top_level = Path(rel_path).parts[0] if Path(rel_path).parts else rel_path
|
|
137
|
+
if top_level in INSTANCE_PROTECTED_PATHS:
|
|
138
|
+
continue
|
|
139
|
+
src = src_root / rel_path
|
|
140
|
+
dst = dst_root / rel_path
|
|
141
|
+
if not src.exists():
|
|
142
|
+
continue
|
|
143
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
144
|
+
if src.is_dir():
|
|
145
|
+
# Sync inteligente: actualiza sin borrar archivos del cliente
|
|
146
|
+
_sync_dir_smart(src, dst)
|
|
147
|
+
else:
|
|
148
|
+
if dst.exists() or dst.is_symlink():
|
|
149
|
+
_remove_runtime_target(dst)
|
|
150
|
+
shutil.copy2(src, dst)
|
|
151
|
+
copied.append(rel_path)
|
|
152
|
+
return copied''',
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
# ── FIX 4: Lanzar TUI cuando conny se corre sin args ───────────────────
|
|
156
|
+
{
|
|
157
|
+
"id": "fix-tui-launch",
|
|
158
|
+
"desc": "Lanzar conny_tui cuando no hay argumentos",
|
|
159
|
+
"old": ''' if cmd == "" and not args.help:
|
|
160
|
+
ensure_workspace_files()
|
|
161
|
+
if not workspace_is_configured() or not get_instances():
|
|
162
|
+
cmd_init(args)
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
# Help
|
|
166
|
+
if args.help or cmd in ("help", "--help", "-h", ""):
|
|
167
|
+
cmd_help_extended(args)
|
|
168
|
+
return''',
|
|
169
|
+
"new": ''' if cmd == "" and not args.help:
|
|
170
|
+
# ── Intentar lanzar TUI interactivo ──────────────────────────────
|
|
171
|
+
_tui_path = Path(__file__).resolve().parent / "conny_tui.py"
|
|
172
|
+
if sys.stdout.isatty() and _tui_path.exists():
|
|
173
|
+
try:
|
|
174
|
+
import importlib.util as _ilu
|
|
175
|
+
_spec = _ilu.spec_from_file_location("conny_tui", str(_tui_path))
|
|
176
|
+
_mod = _ilu.module_from_spec(_spec)
|
|
177
|
+
_spec.loader.exec_module(_mod)
|
|
178
|
+
_mod.run_tui()
|
|
179
|
+
return
|
|
180
|
+
except Exception:
|
|
181
|
+
pass # Fallback a help normal
|
|
182
|
+
|
|
183
|
+
ensure_workspace_files()
|
|
184
|
+
if not workspace_is_configured() or not get_instances():
|
|
185
|
+
cmd_init(args)
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
# Help
|
|
189
|
+
if args.help or cmd in ("help", "--help", "-h", ""):
|
|
190
|
+
cmd_help_extended(args)
|
|
191
|
+
return''',
|
|
192
|
+
},
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
197
|
+
# Motor del patcher
|
|
198
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
199
|
+
|
|
200
|
+
GREEN = "\033[32m"
|
|
201
|
+
RED = "\033[31m"
|
|
202
|
+
YELLOW = "\033[33m"
|
|
203
|
+
CYAN = "\033[36m"
|
|
204
|
+
DIM = "\033[2m"
|
|
205
|
+
BOLD = "\033[1m"
|
|
206
|
+
RESET = "\033[0m"
|
|
207
|
+
|
|
208
|
+
def _c(color, text): return f"{color}{text}{RESET}"
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def apply_patches(cli_path: Path) -> None:
|
|
212
|
+
print(f"\n {_c(BOLD, 'conny_sync_fix')} — Parcheando {cli_path.name}")
|
|
213
|
+
print()
|
|
214
|
+
|
|
215
|
+
if not cli_path.exists():
|
|
216
|
+
print(f" {_c(RED, '✗')} No encontré {cli_path}")
|
|
217
|
+
print(f" Asegúrate de correr este script desde ~/conny/")
|
|
218
|
+
sys.exit(1)
|
|
219
|
+
|
|
220
|
+
# Backup
|
|
221
|
+
stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
222
|
+
bak = cli_path.with_suffix(f".py.bak.{stamp}")
|
|
223
|
+
shutil.copy2(cli_path, bak)
|
|
224
|
+
print(f" {_c(GREEN, '✓')} Backup creado: {bak.name}")
|
|
225
|
+
print()
|
|
226
|
+
|
|
227
|
+
content = cli_path.read_text(encoding="utf-8", errors="replace")
|
|
228
|
+
applied = 0
|
|
229
|
+
skipped = 0
|
|
230
|
+
|
|
231
|
+
for patch in PATCHES:
|
|
232
|
+
pid = patch["id"]
|
|
233
|
+
desc = patch["desc"]
|
|
234
|
+
old = patch["old"]
|
|
235
|
+
new = patch["new"]
|
|
236
|
+
|
|
237
|
+
if old not in content:
|
|
238
|
+
# Verificar si el nuevo código ya está presente (ya parcheado)
|
|
239
|
+
if new.strip()[:40] in content:
|
|
240
|
+
print(f" {_c(DIM, '·')} [{pid}] Ya estaba aplicado — {_c(DIM, desc)}")
|
|
241
|
+
else:
|
|
242
|
+
print(f" {_c(YELLOW, '!')} [{pid}] No encontré el fragmento exacto — {_c(DIM, desc)}")
|
|
243
|
+
print(f" {_c(DIM, 'Puede que el código haya cambiado. Revisa manualmente.')}")
|
|
244
|
+
skipped += 1
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
content = content.replace(old, new, 1)
|
|
248
|
+
applied += 1
|
|
249
|
+
print(f" {_c(GREEN, '✓')} [{pid}] {desc}")
|
|
250
|
+
|
|
251
|
+
print()
|
|
252
|
+
|
|
253
|
+
if applied > 0:
|
|
254
|
+
cli_path.write_text(content, encoding="utf-8")
|
|
255
|
+
print(f" {_c(GREEN, '✓')} {applied} fix(es) aplicado(s) correctamente")
|
|
256
|
+
else:
|
|
257
|
+
print(f" {_c(YELLOW, '·')} Nada que aplicar — todos los fixes ya estaban presentes")
|
|
258
|
+
|
|
259
|
+
if skipped > 0 and applied == 0:
|
|
260
|
+
print(f" {_c(YELLOW, '!')} {skipped} patch(es) no coincidieron — revisa el CHANGELOG abajo")
|
|
261
|
+
print()
|
|
262
|
+
print(" ── Fixes manuales si el auto-patch no funcionó ─────────────────")
|
|
263
|
+
_print_manual_guide()
|
|
264
|
+
|
|
265
|
+
print()
|
|
266
|
+
print(f" {_c(CYAN, 'Siguiente paso:')} pm2 restart conny-clinica-americas")
|
|
267
|
+
print(f" {_c(CYAN, 'Probar sync:')} conny sync")
|
|
268
|
+
print()
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _print_manual_guide():
|
|
272
|
+
print("""
|
|
273
|
+
FIX 1 — INSTANCES_DIR (línea ~158 en conny_cli.py)
|
|
274
|
+
┌──────────────────────────────────────────────────────────────────
|
|
275
|
+
│ - INSTANCES_DIR = os.getenv("INSTANCES_DIR", str(Path(CONNY_HOME) / "instances"))
|
|
276
|
+
│ + INSTANCES_DIR = os.getenv("INSTANCES_DIR", str(Path.home() / "conny-instances"))
|
|
277
|
+
└──────────────────────────────────────────────────────────────────
|
|
278
|
+
|
|
279
|
+
FIX 2 — SYNC_RUNTIME_DIRS (línea ~192)
|
|
280
|
+
┌──────────────────────────────────────────────────────────────────
|
|
281
|
+
│ Elimina "personas" de la lista SYNC_RUNTIME_DIRS
|
|
282
|
+
│ (esa lista está al principio del archivo)
|
|
283
|
+
└──────────────────────────────────────────────────────────────────
|
|
284
|
+
|
|
285
|
+
FIX 3 — _clone_runtime_entries (función)
|
|
286
|
+
┌──────────────────────────────────────────────────────────────────
|
|
287
|
+
│ En el loop, agrega antes del if src.is_dir():
|
|
288
|
+
│ top_level = Path(rel_path).parts[0]
|
|
289
|
+
│ if top_level in {".env","conny.db","personas","identity","soul","logs"}:
|
|
290
|
+
│ continue
|
|
291
|
+
│ Y reemplaza:
|
|
292
|
+
│ _remove_runtime_target(dst)
|
|
293
|
+
│ shutil.copytree(src, dst)
|
|
294
|
+
│ Por un loop que copie solo archivos nuevos/modificados
|
|
295
|
+
└──────────────────────────────────────────────────────────────────
|
|
296
|
+
""")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
300
|
+
|
|
301
|
+
if __name__ == "__main__":
|
|
302
|
+
target = CLI_PATH
|
|
303
|
+
if len(sys.argv) > 1:
|
|
304
|
+
target = Path(sys.argv[1])
|
|
305
|
+
|
|
306
|
+
apply_patches(target)
|