@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.
Files changed (175) hide show
  1. package/.env.example +68 -0
  2. package/CHANGELOG.md +54 -0
  3. package/LICENSE +21 -0
  4. package/README.md +369 -0
  5. package/brand-assets/A_dark_luxury_web_background_202605210700.jpeg +0 -0
  6. package/brand-assets/Conny.web.logo.png +0 -0
  7. package/brand-assets/Logo_Conny_Petalo_Claro.png +0 -0
  8. package/brand-assets/cl-nica-de-las-am-ricas/manifest.json +22 -0
  9. package/brand-assets/cl-nica-de-las-am-ricas/processed/business-identity.txt +11 -0
  10. package/brand-assets/cl-nica-de-las-am-ricas/raw/business-identity.txt +11 -0
  11. package/brand-assets/cl-nica-las-am-ricas/manifest.json +22 -0
  12. package/brand-assets/cl-nica-las-am-ricas/processed/business-identity.txt +11 -0
  13. package/brand-assets/cl-nica-las-am-ricas/raw/business-identity.txt +11 -0
  14. package/brand-assets/conny-demo/manifest.json +22 -0
  15. package/brand-assets/conny-demo/processed/business-identity.txt +7 -0
  16. package/brand-assets/conny-demo/raw/business-identity.txt +7 -0
  17. package/brand-assets/conny-logo.png +0 -0
  18. package/brand-assets/web.background.png +0 -0
  19. package/brand_assets.py +323 -0
  20. package/conny +28 -0
  21. package/conny-chat.py +579 -0
  22. package/conny-omni.py +3843 -0
  23. package/conny.py +113 -0
  24. package/conny_agents/__init__.py +1 -0
  25. package/conny_agents/agenda.py +1 -0
  26. package/conny_agents/captacion.py +1 -0
  27. package/conny_agents/conocimiento.py +1 -0
  28. package/conny_agents/escalacion.py +1 -0
  29. package/conny_agents/objeciones.py +1 -0
  30. package/conny_agents/seguimiento.py +1 -0
  31. package/conny_app.py +287 -0
  32. package/conny_audio.py +350 -0
  33. package/conny_audio_learn.py +84 -0
  34. package/conny_brain_v10.py +804 -0
  35. package/conny_bridge.py +656 -0
  36. package/conny_calendar.py +169 -0
  37. package/conny_cli.py +11784 -0
  38. package/conny_cli_bb.py +437 -0
  39. package/conny_commands.py +243 -0
  40. package/conny_config.py +215 -0
  41. package/conny_core/__init__.py +3 -0
  42. package/conny_core/conversation_engine.py +446 -0
  43. package/conny_core/first_turn_ops.py +287 -0
  44. package/conny_core/persona_registry.py +157 -0
  45. package/conny_core/prompt_ops.py +561 -0
  46. package/conny_cron.py +72 -0
  47. package/conny_demo_v2.py +209 -0
  48. package/conny_demo_voice.py +134 -0
  49. package/conny_design.py +43 -0
  50. package/conny_doctor.py +319 -0
  51. package/conny_domino.py +696 -0
  52. package/conny_generator.py +447 -0
  53. package/conny_google_auth.py +159 -0
  54. package/conny_i18n.py +619 -0
  55. package/conny_init.py +509 -0
  56. package/conny_integrations/__init__.py +4 -0
  57. package/conny_integrations/llm.py +1 -0
  58. package/conny_integrations/vault.py +77 -0
  59. package/conny_integrations/whatsapp.py +1 -0
  60. package/conny_intelligence.py +65 -0
  61. package/conny_learning.py +154 -0
  62. package/conny_memory.py +243 -0
  63. package/conny_memory_engine.py +292 -0
  64. package/conny_nova_proxy.py +170 -0
  65. package/conny_nuke_robot_phrases.py +493 -0
  66. package/conny_pairing.py +253 -0
  67. package/conny_patch.py +291 -0
  68. package/conny_persona_cli.py +150 -0
  69. package/conny_router.py +308 -0
  70. package/conny_runtime_ops.py +271 -0
  71. package/conny_session.py +516 -0
  72. package/conny_skills/__init__.py +1 -0
  73. package/conny_skills/demo_mode.py +35 -0
  74. package/conny_skills/text_processing.py +1 -0
  75. package/conny_skills/tone_detection.py +1 -0
  76. package/conny_smart_features.py +333 -0
  77. package/conny_studio.py +161 -0
  78. package/conny_sync_fix.py +306 -0
  79. package/conny_tui.py +512 -0
  80. package/conny_tui_select.py +202 -0
  81. package/conny_ultra_config.py +411 -0
  82. package/conny_uncertainty.py +174 -0
  83. package/conny_utils.py +87 -0
  84. package/conny_voice.py +156 -0
  85. package/conny_voice_engine.py +124 -0
  86. package/conny_web_search.py +66 -0
  87. package/conny_weekly_report.py +85 -0
  88. package/conny_worm.py +88 -0
  89. package/core/__init__.py +25 -0
  90. package/ecosystem.config.js +24 -0
  91. package/fix_init.py +27 -0
  92. package/install.sh +78 -0
  93. package/knowledge_base.py +330 -0
  94. package/nova/rules/default.yaml +37 -0
  95. package/nova_bridge.py +509 -0
  96. package/npm/conny.js +471 -0
  97. package/package.json +102 -0
  98. package/personas/conny/base/default.yaml +35 -0
  99. package/personas/conny/base/estetica_whatsapp.yaml +36 -0
  100. package/requirements.txt +14 -0
  101. package/run.sh +47 -0
  102. package/search.py +465 -0
  103. package/smart_handoff.py +1150 -0
  104. package/src/__init__.py +0 -0
  105. package/src/conny/__init__.py +0 -0
  106. package/src/conny/admin/__init__.py +0 -0
  107. package/src/conny/admin/api.py +234 -0
  108. package/src/conny/admin/dashboard.py +772 -0
  109. package/src/conny/api/__init__.py +0 -0
  110. package/src/conny/api/routes.py +8851 -0
  111. package/src/conny/brain/__init__.py +15 -0
  112. package/src/conny/brain/engine.py +804 -0
  113. package/src/conny/brain/learning.py +154 -0
  114. package/src/conny/brain/memory.py +324 -0
  115. package/src/conny/brain/smart_features.py +333 -0
  116. package/src/conny/brain/uncertainty.py +167 -0
  117. package/src/conny/channels/__init__.py +0 -0
  118. package/src/conny/channels/audio.py +316 -0
  119. package/src/conny/channels/cli.py +11795 -0
  120. package/src/conny/channels/logo_art.py +11 -0
  121. package/src/conny/channels/voice.py +156 -0
  122. package/src/conny/core/__init__.py +0 -0
  123. package/src/conny/core/config.py +215 -0
  124. package/src/conny/core/cron.py +72 -0
  125. package/src/conny/core/messenger.py +563 -0
  126. package/src/conny/core/router.py +297 -0
  127. package/src/conny/core/session.py +312 -0
  128. package/src/conny/demo/__init__.py +0 -0
  129. package/src/conny/demo/handler.py +3110 -0
  130. package/src/conny/integrations/__init__.py +19 -0
  131. package/src/conny/integrations/calendar.py +169 -0
  132. package/src/conny/integrations/knowledge.py +312 -0
  133. package/src/conny/integrations/search.py +66 -0
  134. package/src/conny/personas/__init__.py +0 -0
  135. package/src/conny/personas/generator.py +447 -0
  136. package/src/conny/production/__init__.py +0 -0
  137. package/src/conny/production/domino.py +696 -0
  138. package/src/conny/production/guard.py +550 -0
  139. package/src/conny/production/handoff.py +1150 -0
  140. package/src/conny/production/monitor.py +353 -0
  141. package/src/conny/utils/__init__.py +2 -0
  142. package/src/conny/utils/helpers.py +75 -0
  143. package/src/conny/utils/i18n.py +619 -0
  144. package/src/core/admin_engines.py +772 -0
  145. package/src/core/globals.py +11845 -0
  146. package/src/core/orchestrator.py +273 -0
  147. package/src/core/production_monitor.py +353 -0
  148. package/src/core/runtime.py +5487 -0
  149. package/src/domain/onboarding_flow.py +230 -0
  150. package/src/domain/prompts/__init__.py +1 -0
  151. package/src/domain/prompts/prospect_pitch.py +282 -0
  152. package/src/domain/send_guard.py +636 -0
  153. package/src/domain/swarm/queen.py +96 -0
  154. package/src/infrastructure/llm_providers/engine.py +487 -0
  155. package/src/interfaces/mcp_server.py +73 -0
  156. package/src/interfaces/nova_bridge.py +58 -0
  157. package/src/interfaces/web/admin_api.py +1379 -0
  158. package/src/interfaces/web/app.py +9408 -0
  159. package/src/interfaces/web/demo_handler.py +3450 -0
  160. package/src/interfaces/web/static/generate_avatars.py +46 -0
  161. package/v7/__init__.py +46 -0
  162. package/v7/agents/__init__.py +46 -0
  163. package/v7/agents/agenda.py +77 -0
  164. package/v7/agents/base.py +216 -0
  165. package/v7/agents/captacion.py +60 -0
  166. package/v7/agents/conocimiento.py +69 -0
  167. package/v7/agents/escalacion.py +83 -0
  168. package/v7/agents/objeciones.py +109 -0
  169. package/v7/agents/seguimiento.py +71 -0
  170. package/v7/memory/__init__.py +46 -0
  171. package/v7/memory/patient_profile.py +200 -0
  172. package/v7/orchestrator.py +275 -0
  173. package/v7/postprocess.py +127 -0
  174. package/v7/router.py +239 -0
  175. package/verify_conversation_impl.py +48 -0
package/npm/conny.js ADDED
@@ -0,0 +1,471 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const os = require("os");
5
+ const path = require("path");
6
+ const { spawnSync } = require("child_process");
7
+
8
+ const chalk = require("chalk");
9
+ const ora = require("ora");
10
+
11
+ const packageRoot = path.resolve(__dirname, "..");
12
+ const metadata = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
13
+ const packageVersion = String(metadata.version || "").trim();
14
+ const connyHome = process.env.CONNY_HOME || path.join(os.homedir(), ".conny");
15
+ const repoDir = path.join(connyHome, "repo");
16
+ const runtimeDir = path.join(connyHome, "runtime");
17
+ const workspaceConfigPath = path.join(connyHome, "config.json");
18
+ const sharedTelegramRoutesPath = path.join(connyHome, "shared_telegram_routes.json");
19
+ const entrypoint = path.join(repoDir, "conny_app.py");
20
+ const legacyEntrypoint = path.join(repoDir, "conny_cli.py");
21
+
22
+ const SKIP_NAMES = new Set([
23
+ ".git",
24
+ ".github",
25
+ ".nova",
26
+ ".pytest_cache",
27
+ ".ruff_cache",
28
+ ".venv",
29
+ "__pycache__",
30
+ "backups",
31
+ "docs",
32
+ "logs",
33
+ "node_modules",
34
+ "output",
35
+ "screenshots",
36
+ "tests",
37
+ "tmp",
38
+ ]);
39
+
40
+ const commandGroups = [
41
+ {
42
+ category: "Gestión",
43
+ cmds: [
44
+ ["init", "Primer setup guiado del producto"],
45
+ ["new [nombre]", "Crear instancia para un cliente (wizard)"],
46
+ ["list / ls", "Ver todas las instancias"],
47
+ ["dashboard", "Panel en tiempo real"],
48
+ ["template [sector]", "Ver/crear desde plantilla"],
49
+ ["interactive", "Modo interactivo (shell)"],
50
+ ["zero [n]", "Entregar instancia a nuevo cliente (borra todo)"],
51
+ ]
52
+ },
53
+ {
54
+ category: "Monitoreo",
55
+ cmds: [
56
+ ["status [n]", "Estado detallado de la instancia"],
57
+ ["health", "Health check rápido de los servicios"],
58
+ ["metrics [n]", "Métricas de uso y rendimiento"],
59
+ ["analytics [n]", "Análisis de conversaciones y datos"],
60
+ ["logs [n]", "Logs en tiempo real"],
61
+ ["alerts", "Sistema de alertas y notificaciones"],
62
+ ]
63
+ },
64
+ {
65
+ category: "Operaciones",
66
+ cmds: [
67
+ ["config [n]", "Editar configuración y variables de entorno"],
68
+ ["restart [n]", "Reiniciar procesos de la instancia (o 'all')"],
69
+ ["stop [n]", "Detener procesos de la instancia"],
70
+ ["scale [n] [num]", "Escalar workers de mensajería"],
71
+ ["clone [n]", "Clonar configuración e instancia"],
72
+ ["reset [n]", "Resetear base de datos/sesión de testing"],
73
+ ["delete [n]", "Eliminar instancia permanentemente"],
74
+ ["batch", "Operaciones en lote sobre múltiples instancias"],
75
+ ]
76
+ },
77
+ {
78
+ category: "Datos & Testing",
79
+ cmds: [
80
+ ["backup [n]", "Crear snapshot de seguridad de la instancia"],
81
+ ["restore [file]", "Restaurar instancia desde un snapshot"],
82
+ ["export [n]", "Exportar conversaciones a JSON/CSV"],
83
+ ["import [file]", "Importar configuración o base de datos"],
84
+ ["search [query]", "Buscar términos en logs/mensajes"],
85
+ ["test [n]", "Probar respuestas y flujos conversacionales"],
86
+ ]
87
+ },
88
+ {
89
+ category: "Sistema & Seguridad",
90
+ cmds: [
91
+ ["doctor", "Diagnóstico completo del sistema y dependencias"],
92
+ ["audit", "Auditoría de seguridad y chequeo de vulnerabilidades"],
93
+ ["benchmark", "Test de rendimiento de CPU/DB/Red"],
94
+ ["secure", "Guía y validación de seguridad de endpoints"],
95
+ ["rotate-keys", "Rotar claves de API y tokens de acceso"],
96
+ ["upgrade", "Actualizar código base de Conny"],
97
+ ["cleanup", "Limpiar archivos de log y caché temporal"],
98
+ ["diff", "Comparar diferencias entre dos instancias"],
99
+ ["guide", "Guía interactiva de operación de Conny"],
100
+ ]
101
+ },
102
+ {
103
+ category: "Black Boss (Personalización)",
104
+ cmds: [
105
+ ["bb config [n]", "Crear y ajustar agente, prompt y personalidad"],
106
+ ["bb chat [n]", "Abrir chat operativo directo con el agente"],
107
+ ["bb doctor", "Diagnóstico rápido del Black Boss Engine"],
108
+ ["bb sync", "Propagar runtime exacto a todas las instancias"],
109
+ ["bb new", "Crear nueva instancia bajo el Black Boss Engine"],
110
+ ["bb guide", "Abrir guía operativa avanzada"],
111
+ ]
112
+ },
113
+ {
114
+ category: "Modelo & Calidad V8",
115
+ cmds: [
116
+ ["modelo [n]", "Ver/cambiar el LLM de una instancia en caliente"],
117
+ ["simular [n]", "Simular 10 conversaciones para detectar alucinaciones"],
118
+ ["v8 [n]", "Estado de los 15 sistemas inteligentes V8"],
119
+ ["quality [n]", "Score de humanidad de las últimas respuestas"],
120
+ ["briefing [n]", "Briefing diario con leads calientes detectados"],
121
+ ["campana [n]", "Campañas de seguimiento y reactivación saliente"],
122
+ ["latency [n]", "Test de latencia HTTP + LLM en tiempo real"],
123
+ ["cost [n]", "Estimación de costos mensuales del LLM"],
124
+ ["warmup [n]", "Pre-calentar la instancia antes de lanzar a prod"],
125
+ ["watchdog", "Monitor continuo con auto-restart inteligente"],
126
+ ]
127
+ },
128
+ {
129
+ category: "Canales & Activación V7",
130
+ cmds: [
131
+ ["token [n]", "Generar código de activación"],
132
+ ["tokens [n]", "Listar tokens de activación generados"],
133
+ ["activar [n]", "Activar instancia directamente (sin token)"],
134
+ ["bridge", "Estado y monitoreo del WhatsApp Bridge"],
135
+ ["bridge fix", "Fix de configuración del bridge de WhatsApp"],
136
+ ["bridge qr", "Ver código QR para enlazar número de WhatsApp"],
137
+ ["instagram [n]", "Conectar y monitorear Instagram DMs"],
138
+ ["pagos [n]", "Configurar/monitorear pagos desde el chat"],
139
+ ]
140
+ }
141
+ ];
142
+
143
+ function printBanner() {
144
+ console.log();
145
+ console.log(chalk.hex('#EC4899').bold(' conny-agent') +
146
+ chalk.hex('#8B5CF6').dim(` · v${packageVersion} · kimika.ai`));
147
+ console.log(chalk.hex('#444')(' ─────────────────────────'));
148
+ console.log();
149
+ }
150
+
151
+ function printCommands() {
152
+ for (const group of commandGroups) {
153
+ console.log(` ${chalk.hex('#8B5CF6').bold(group.category)}`);
154
+ for (const [cmd, desc] of group.cmds) {
155
+ const formattedCmd = `conny ${cmd}`;
156
+ console.log(` ${chalk.white.bold(formattedCmd.padEnd(25))} ${chalk.dim(desc)}`);
157
+ }
158
+ console.log();
159
+ }
160
+
161
+ console.log(` ${chalk.hex('#8B5CF6').bold("Sectores disponibles")}`);
162
+ console.log(` ${chalk.dim("salud, inmobiliario, e-commerce, educacion, legal, finanzas, turismo, gastronomia, belleza, automotriz, gimnasios, soporte, otro")}\n`);
163
+ }
164
+
165
+ function ensureDir(target) {
166
+ fs.mkdirSync(target, { recursive: true });
167
+ }
168
+
169
+ function fail(message) {
170
+ console.error(chalk.red(`ERR ${message}`));
171
+ process.exit(1);
172
+ }
173
+
174
+ function runtimeCandidates() {
175
+ return [
176
+ path.join(runtimeDir, "bin", "python"),
177
+ path.join(runtimeDir, "bin", "python3"),
178
+ path.join(runtimeDir, "Scripts", "python.exe"),
179
+ ];
180
+ }
181
+
182
+ function resolveRuntime() {
183
+ for (const candidate of runtimeCandidates()) {
184
+ if (fs.existsSync(candidate)) {
185
+ return candidate;
186
+ }
187
+ }
188
+ return "";
189
+ }
190
+
191
+ function runAndReturn(command, args, extraEnv = {}, options = {}) {
192
+ return spawnSync(command, args, {
193
+ stdio: "inherit",
194
+ env: { ...process.env, ...extraEnv },
195
+ ...options,
196
+ });
197
+ }
198
+
199
+ function syncTree(sourceDir, targetDir) {
200
+ ensureDir(targetDir);
201
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
202
+ if (SKIP_NAMES.has(entry.name)) {
203
+ continue;
204
+ }
205
+ const sourcePath = path.join(sourceDir, entry.name);
206
+ const targetPath = path.join(targetDir, entry.name);
207
+ if (entry.isDirectory()) {
208
+ syncTree(sourcePath, targetPath);
209
+ continue;
210
+ }
211
+ ensureDir(path.dirname(targetPath));
212
+ fs.copyFileSync(sourcePath, targetPath);
213
+ }
214
+ }
215
+
216
+ function readInstalledVersion() {
217
+ const installedPackage = path.join(repoDir, "package.json");
218
+ if (!fs.existsSync(installedPackage)) {
219
+ return "";
220
+ }
221
+ try {
222
+ const payload = JSON.parse(fs.readFileSync(installedPackage, "utf8"));
223
+ return String(payload.version || "").trim();
224
+ } catch (_err) {
225
+ return "";
226
+ }
227
+ }
228
+
229
+ function findSystemPython() {
230
+ const candidates =
231
+ process.platform === "win32"
232
+ ? [
233
+ ["py", ["-3"]],
234
+ ["python", []],
235
+ ["python3", []],
236
+ ]
237
+ : [
238
+ ["python3", []],
239
+ ["python", []],
240
+ ];
241
+ for (const [command, prefixArgs] of candidates) {
242
+ const probe = spawnSync(command, [...prefixArgs, "-c", "import json,sys; print(json.dumps({'exe': sys.executable, 'ver': list(sys.version_info[:3])}))"], {
243
+ stdio: ["ignore", "pipe", "pipe"],
244
+ encoding: "utf8",
245
+ env: process.env,
246
+ });
247
+ if (probe.status === 0) {
248
+ try {
249
+ const payload = JSON.parse(String(probe.stdout || "").trim());
250
+ const version = payload.ver || [];
251
+ if (version.length >= 2 && (version[0] > 3 || (version[0] === 3 && version[1] >= 9))) {
252
+ return { command, prefixArgs, executable: payload.exe, version };
253
+ }
254
+ } catch (_err) {
255
+ // ignore and continue
256
+ }
257
+ }
258
+ }
259
+ return null;
260
+ }
261
+
262
+ function runtimeLooksHealthy(runtime) {
263
+ if (!runtime || !fs.existsSync(runtime)) {
264
+ return false;
265
+ }
266
+ const probe = spawnSync(
267
+ runtime,
268
+ ["-c", "import fastapi,httpx,dotenv; print('ok')"],
269
+ { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8", env: process.env }
270
+ );
271
+ return probe.status === 0;
272
+ }
273
+
274
+ function ensureRuntime(spinner) {
275
+ let runtime = resolveRuntime();
276
+ if (runtime && runtimeLooksHealthy(runtime)) {
277
+ return runtime;
278
+ }
279
+ if (runtime && !runtimeLooksHealthy(runtime)) {
280
+ try {
281
+ fs.rmSync(runtimeDir, { recursive: true, force: true });
282
+ } catch (_err) {
283
+ // ignore
284
+ }
285
+ runtime = "";
286
+ }
287
+
288
+ let localSpinner = spinner;
289
+ if (!localSpinner) {
290
+ localSpinner = ora({
291
+ text: chalk.hex('#8B5CF6')("Iniciando Conny..."),
292
+ color: "magenta"
293
+ }).start();
294
+ }
295
+
296
+ const python = findSystemPython();
297
+ if (!python) {
298
+ const errMsg = process.platform === "win32"
299
+ ? "✕ No encontré Python 3.9+ en este host. Instálalo y vuelve a ejecutar `conny`."
300
+ : "✕ No encontré python3/python 3.9+ en este host. Instálalo y vuelve a ejecutar `conny`.";
301
+ localSpinner.fail(chalk.red(errMsg));
302
+ process.exit(1);
303
+ }
304
+
305
+ localSpinner.text = chalk.hex('#8B5CF6')("Creando entorno virtual de Python...");
306
+ let result = spawnSync(python.command, [...python.prefixArgs, "-m", "venv", runtimeDir], {
307
+ stdio: ["ignore", "pipe", "pipe"],
308
+ env: process.env,
309
+ });
310
+ if (result.status !== 0) {
311
+ localSpinner.fail(chalk.red("✕ No se pudo crear el entorno virtual de Python."));
312
+ if (result.stderr) console.error(chalk.red(result.stderr.toString()));
313
+ process.exit(1);
314
+ }
315
+
316
+ runtime = resolveRuntime();
317
+ if (!runtime) {
318
+ localSpinner.fail(chalk.red(`✕ No pude crear el runtime aislado en ${runtimeDir}`));
319
+ process.exit(1);
320
+ }
321
+
322
+ localSpinner.text = chalk.hex('#8B5CF6')("Actualizando pip...");
323
+ result = spawnSync(runtime, ["-m", "pip", "install", "--disable-pip-version-check", "--upgrade", "pip"], {
324
+ stdio: ["ignore", "pipe", "pipe"],
325
+ env: process.env,
326
+ });
327
+ if (result.status !== 0) {
328
+ localSpinner.fail(chalk.red("✕ Falló la actualización de pip."));
329
+ if (result.stderr) console.error(chalk.red(result.stderr.toString()));
330
+ process.exit(1);
331
+ }
332
+
333
+ localSpinner.text = chalk.hex('#8B5CF6')("Instalando dependencias base (requirements.txt)...");
334
+ result = spawnSync(runtime, ["-m", "pip", "install", "--disable-pip-version-check", "-r", path.join(repoDir, "requirements.txt")], {
335
+ stdio: ["ignore", "pipe", "pipe"],
336
+ env: process.env,
337
+ });
338
+ if (result.status !== 0) {
339
+ localSpinner.fail(chalk.red("✕ Falló la instalación de las dependencias."));
340
+ if (result.stderr) console.error(chalk.red(result.stderr.toString()));
341
+ process.exit(1);
342
+ }
343
+
344
+ if (!spinner) {
345
+ localSpinner.succeed(chalk.green("✓ Lista."));
346
+ }
347
+
348
+ return runtime;
349
+ }
350
+
351
+ function bootstrapFromPackage() {
352
+ const spinner = ora({
353
+ text: chalk.hex('#8B5CF6')("Iniciando Conny..."),
354
+ color: "magenta"
355
+ }).start();
356
+
357
+ try {
358
+ ensureDir(connyHome);
359
+ syncTree(packageRoot, repoDir);
360
+ if (!fs.existsSync(workspaceConfigPath)) {
361
+ fs.writeFileSync(
362
+ workspaceConfigPath,
363
+ JSON.stringify(
364
+ {
365
+ owner_name: "",
366
+ default_business_name: "",
367
+ default_sector: "",
368
+ default_platform: "telegram",
369
+ public_base_url: "",
370
+ telegram_token: "",
371
+ telegram_shared: false,
372
+ llm_keys: {},
373
+ search_keys: {},
374
+ meta: {},
375
+ nova: {},
376
+ omni: {},
377
+ agent: {
378
+ display_name: "Conny",
379
+ role: "asesora virtual",
380
+ prompt_master: "",
381
+ },
382
+ },
383
+ null,
384
+ 2
385
+ )
386
+ );
387
+ }
388
+ console.log(chalk.hex("#8B5CF6")("Verificando dependencias (pip)..."));
389
+ const runtime = resolveRuntime() || ensureRuntime(spinner);
390
+ spawnSync(runtime, ["-m", "pip", "install", "--disable-pip-version-check", "-r", path.join(repoDir, "requirements.txt")], { stdio: "ignore" });
391
+
392
+ if (!fs.existsSync(sharedTelegramRoutesPath)) {
393
+ fs.writeFileSync(sharedTelegramRoutesPath, JSON.stringify({ default_instance: "", routes: {} }, null, 2));
394
+ }
395
+ ensureDir(path.join(connyHome, "instances"));
396
+ ensureRuntime(spinner);
397
+ spinner.succeed(chalk.green("✓ Lista."));
398
+ } catch (err) {
399
+ spinner.fail(chalk.red(`✕ Error durante el onboarding: ${err.message}`));
400
+ process.exit(1);
401
+ }
402
+ }
403
+
404
+ function needsBootstrap() {
405
+ if (!fs.existsSync(entrypoint)) {
406
+ return true;
407
+ }
408
+ if (!resolveRuntime()) {
409
+ return true;
410
+ }
411
+ if (readInstalledVersion() !== packageVersion) {
412
+ return true;
413
+ }
414
+ return process.env.CONNY_FORCE_SYNC === "1";
415
+ }
416
+
417
+ function execConny(argv) {
418
+ const runtime = resolveRuntime();
419
+ if (!runtime || !fs.existsSync(entrypoint)) {
420
+ return false;
421
+ }
422
+ const result = runAndReturn(
423
+ runtime,
424
+ [entrypoint, ...argv],
425
+ {
426
+ CONNY_HOME: connyHome,
427
+ CONNY_DIR: repoDir,
428
+ INSTANCES_DIR: process.env.INSTANCES_DIR || path.join(connyHome, "instances"),
429
+ CONNY_BACKUPS: process.env.CONNY_BACKUPS || path.join(connyHome, "backups"),
430
+ CONNY_SHARED_TELEGRAM_ROUTES:
431
+ process.env.CONNY_SHARED_TELEGRAM_ROUTES || sharedTelegramRoutesPath,
432
+ CONNY_WORKSPACE_CONFIG: process.env.CONNY_WORKSPACE_CONFIG || workspaceConfigPath,
433
+ }
434
+ );
435
+ if (typeof result.status === "number") {
436
+ process.exit(result.status);
437
+ }
438
+ process.exit(1);
439
+ }
440
+
441
+ const args = process.argv.slice(2);
442
+ const isHelp = args.length === 0 || args.includes("-h") || args.includes("--help") || args.includes("help");
443
+ const isVersion = args.includes("-v") || args.includes("--version") || args.includes("version");
444
+ const isJson = args.includes("--json");
445
+
446
+ if (isVersion) {
447
+ if (isJson) {
448
+ console.log(JSON.stringify({ version: packageVersion }));
449
+ } else {
450
+ console.log(`conny ${packageVersion}`);
451
+ }
452
+ process.exit(0);
453
+ }
454
+
455
+ if (needsBootstrap()) {
456
+ bootstrapFromPackage();
457
+ }
458
+
459
+ if (isHelp) {
460
+ printBanner();
461
+ printCommands();
462
+ process.exit(0);
463
+ }
464
+
465
+ if (!isJson && process.stdout.isTTY) {
466
+ printBanner();
467
+ }
468
+
469
+ if (!execConny(args)) {
470
+ fail(`No pude iniciar Conny desde ${connyHome}`);
471
+ }
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "@innvisor/conny-ai",
3
+ "version": "9.7.0",
4
+ "description": "Open-source CLI and runtime for building Conny AI receptionist agents on WhatsApp and Telegram.",
5
+ "license": "MIT",
6
+ "author": "Santiago Rubio",
7
+ "homepage": "https://github.com/sxrubyo/conny#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/sxrubyo/conny.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/sxrubyo/conny/issues"
14
+ },
15
+ "bin": {
16
+ "conny": "npm/conny.js"
17
+ },
18
+ "files": [
19
+ "npm/conny.js",
20
+ "conny",
21
+ "conny.py",
22
+ "*.py",
23
+ "!patch*.py",
24
+ "!scratch*.py",
25
+ "!test_*.py",
26
+ "!chat_conny.py",
27
+ "brand-assets/**/*",
28
+ "conny_cli.py",
29
+ "conny_cli_bb.py",
30
+ "conny_tui.py",
31
+ "conny_sync_fix.py",
32
+ "conny_i18n.py",
33
+ "conny_brain_v10.py",
34
+ "conny_bridge.py",
35
+ "conny_domino.py",
36
+ "conny_nuke_robot_phrases.py",
37
+ "smart_handoff.py",
38
+ "conny_pairing.py",
39
+ "knowledge_base.py",
40
+ "search.py",
41
+ "brand_assets.py",
42
+ "nova_bridge.py",
43
+ "ecosystem.config.js",
44
+ "run.sh",
45
+ "requirements.txt",
46
+ ".env.example",
47
+ "README.md",
48
+ "CHANGELOG.md",
49
+ "LICENSE",
50
+ "install.sh",
51
+ "package.json",
52
+ "src/core/admin_engines.py",
53
+ "conny_config.py",
54
+ "src/interfaces/web/demo_handler.py",
55
+ "src/core/production_monitor.py",
56
+ "conny_router.py",
57
+ "conny_utils.py",
58
+ "conny_memory_engine.py",
59
+ "conny_uncertainty.py",
60
+ "conny_voice.py",
61
+ "conny_cron.py",
62
+ "conny_nova_proxy.py",
63
+ "conny_memory.py",
64
+ "conny_session.py",
65
+ "conny_generator.py",
66
+ "conny_audio.py",
67
+ "conny_core/**/*.py",
68
+ "conny_agents/**/*.py",
69
+ "conny_integrations/**/*.py",
70
+ "conny_skills/**/*.py",
71
+ "core/**/*.py",
72
+ "nova/rules/*.yaml",
73
+ "personas/conny/base/*.yaml",
74
+ "v7/**/*.py",
75
+ "src/**/*.py"
76
+ ],
77
+ "engines": {
78
+ "node": ">=18"
79
+ },
80
+ "scripts": {
81
+ "pack:check": "npm pack --dry-run --json"
82
+ },
83
+ "publishConfig": {
84
+ "access": "public"
85
+ },
86
+ "keywords": [
87
+ "conny",
88
+ "ai",
89
+ "agent",
90
+ "whatsapp",
91
+ "telegram",
92
+ "receptionist",
93
+ "cli",
94
+ "automation"
95
+ ],
96
+ "dependencies": {
97
+ "boxen": "^5.1.2",
98
+ "chalk": "^4.1.2",
99
+ "figlet": "^1.11.0",
100
+ "ora": "^5.4.1"
101
+ }
102
+ }
@@ -0,0 +1,35 @@
1
+ key: default
2
+ identity: Conny
3
+ opening_style: natural
4
+ question_style: natural
5
+ sales_style: natural
6
+ objection_style: natural
7
+ followup_style: natural
8
+ humor_policy: light
9
+ warmth_range: [0.45, 0.80]
10
+ capabilities:
11
+ - responder clientes
12
+ - explicar servicios
13
+ - filtrar interesados
14
+ - ubicar horarios
15
+ - ayudar con citas
16
+ first_turn_variants:
17
+ - "Hola, soy Conny, la asesora virtual de {clinic_name}"
18
+ - "Hola, Conny por aquí. Soy la asesora virtual de {clinic_name}"
19
+ identity_probe_variants:
20
+ - "Soy Conny, la asesora virtual de {clinic_name}. También soy la IA que sostiene este chat para orientar y responder con criterio"
21
+ - "Soy Conny, la asesora virtual de {clinic_name}. Soy una IA hecha para responder claro y ayudarte a avanzar sin enredos"
22
+ - "Soy Conny, la asesora virtual de {clinic_name}. Soy una IA hecha para que la atención se sienta útil, cercana y bien llevada"
23
+ contextual_followups:
24
+ botox: "Botox lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
25
+ rellenos: "Rellenos lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
26
+ laser: "Láser lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
27
+ láser: "Láser lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
28
+ forbidden_patterns:
29
+ - "con gusto"
30
+ - "estoy lista para revisar contigo lo que necesites"
31
+ - "te ayudo con gusto"
32
+ - "buenas, en qué te ayudo"
33
+ - "hola, en qué te ayudo"
34
+ - "cuéntame en qué te ayudo"
35
+ - "cómo puedo ayudarte"
@@ -0,0 +1,36 @@
1
+ key: estetica_whatsapp
2
+ identity: Conny
3
+ opening_style: colombia-natural
4
+ question_style: short
5
+ sales_style: consultive
6
+ objection_style: calm
7
+ followup_style: direct
8
+ humor_policy: light
9
+ warmth_range: [0.55, 0.88]
10
+ capabilities:
11
+ - información de tratamientos
12
+ - valoración
13
+ - disponibilidad
14
+ - seguimiento
15
+ - cita
16
+ first_turn_variants:
17
+ - "Hola, soy Conny, la asesora virtual de {clinic_name}"
18
+ - "Hola, Conny por aquí. Soy la asesora virtual de {clinic_name}"
19
+ identity_probe_variants:
20
+ - "Soy Conny, la asesora virtual de {clinic_name}. También soy la IA que acompaña este chat para orientarte bien y sin sonar fría"
21
+ - "Soy Conny, la asesora virtual de {clinic_name}. Soy una IA hecha para responderte claro, ubicarte y ayudarte a avanzar"
22
+ - "Soy Conny, la asesora virtual de {clinic_name}. Soy una IA pensada para que este chat se sienta natural y bien llevado"
23
+ contextual_followups:
24
+ botox: "Botox lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
25
+ rellenos: "Rellenos lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
26
+ laser: "Láser lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
27
+ láser: "Láser lo manejan acá. Si quieres, te cuento cómo lo trabajan y qué suelen revisar para que se vea natural."
28
+ forbidden_patterns:
29
+ - "con mucho gusto"
30
+ - "encantada de conocerte"
31
+ - "soy una asistente virtual"
32
+ - "en qué más le puedo servir"
33
+ - "buenas, en qué te ayudo"
34
+ - "hola, en qué te ayudo"
35
+ - "cuéntame en qué te ayudo"
36
+ - "cómo puedo ayudarte"
@@ -0,0 +1,14 @@
1
+ fastapi==0.115.0
2
+ uvicorn[standard]==0.30.0
3
+ httpx==0.27.0
4
+ python-dotenv==1.0.1
5
+ pypdf==6.0.0
6
+ pydantic>=2.0
7
+ pyjwt>=2.8.0
8
+ watchdog>=4.0.0
9
+ apscheduler>=3.10.0
10
+ scikit-learn>=1.4.0
11
+ numpy>=1.26.0
12
+ questionary>=2.0.0
13
+ rich>=13.0.0
14
+ deep-translator>=1.11.0