@johpaz/hive-agents 0.0.37 → 0.0.38

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 (70) hide show
  1. package/README.md +16 -16
  2. package/dist/hive.js +107 -105
  3. package/dist/tool-worker.js +25 -36
  4. package/dist/ui/assets/{AgentCreateForm-tJZv9FZC.js → AgentCreateForm-0oFbN3gj.js} +1 -1
  5. package/dist/ui/assets/{AgentDetailPage-Du-mRcAX.js → AgentDetailPage-BJ4L2fNJ.js} +1 -1
  6. package/dist/ui/assets/AgentNewPage-B3n0LUck.js +1 -0
  7. package/dist/ui/{dist/assets/AgentsPage-YvSgWRiw.js → assets/AgentsPage-DGNLDXjR.js} +1 -1
  8. package/dist/ui/assets/{CanvasPage-DtMwGvxf.js → CanvasPage-CnMO1FN8.js} +1 -1
  9. package/dist/ui/assets/{ChannelsPage-BdBXWHjj.js → ChannelsPage-fbF8K4MR.js} +1 -1
  10. package/dist/ui/{dist/assets/DashboardPage-ghl1ZguH.js → assets/DashboardPage-VyXXp3U1.js} +1 -1
  11. package/dist/ui/assets/{LoginPage-CAmSI9Vy.js → LoginPage-DPj2s2Qq.js} +1 -1
  12. package/dist/ui/{dist/assets/LogsPage-DAPBHkwK.js → assets/LogsPage-B2lY9maY.js} +1 -1
  13. package/dist/ui/{dist/assets/MeetingPage-WjjGOqqU.js → assets/MeetingPage-2ky_hKiG.js} +1 -1
  14. package/dist/ui/{dist/assets/ProvidersPage-Ct6HsAi1.js → assets/ProvidersPage-CEyUM2tD.js} +1 -1
  15. package/dist/ui/{dist/assets/RecoverPage-DpW3l-yv.js → assets/RecoverPage-B-hDZUM2.js} +1 -1
  16. package/dist/ui/{dist/assets/SettingsPage-DBJ7_E6C.js → assets/SettingsPage-eO0i3g8p.js} +1 -1
  17. package/dist/ui/assets/{SetupPage-DKmLVUaj.js → SetupPage-ByYqTELb.js} +1 -1
  18. package/dist/ui/assets/WebChatPage-BuGT2AL0.js +16 -0
  19. package/dist/ui/assets/{alert-C-NE-P3s.js → alert-Bq6awLlW.js} +1 -1
  20. package/dist/ui/{dist/assets/alert-dialog-C5mzbHdP.js → assets/alert-dialog-DQvltYmf.js} +1 -1
  21. package/dist/ui/assets/{badge-ChpACfWO.js → badge-DXUDdTed.js} +1 -1
  22. package/dist/ui/assets/{dialog-QnZ0ad8O.js → dialog-bI9jImCS.js} +1 -1
  23. package/dist/ui/assets/{es-NQNoaWDx.js → es-Cg8zdT52.js} +1 -1
  24. package/dist/ui/{dist/assets/index-DMCjjdqf.js → assets/index-CQ7fn00w.js} +2 -2
  25. package/dist/ui/assets/{label-D2H1IR_J.js → label-CrH0Jj3v.js} +1 -1
  26. package/dist/ui/assets/useProviders-CnlC_qCS.js +1 -0
  27. package/dist/ui/dist/assets/{AgentCreateForm-tJZv9FZC.js → AgentCreateForm-0oFbN3gj.js} +1 -1
  28. package/dist/ui/dist/assets/{AgentDetailPage-Du-mRcAX.js → AgentDetailPage-BJ4L2fNJ.js} +1 -1
  29. package/dist/ui/dist/assets/AgentNewPage-B3n0LUck.js +1 -0
  30. package/dist/ui/{assets/AgentsPage-YvSgWRiw.js → dist/assets/AgentsPage-DGNLDXjR.js} +1 -1
  31. package/dist/ui/dist/assets/{CanvasPage-DtMwGvxf.js → CanvasPage-CnMO1FN8.js} +1 -1
  32. package/dist/ui/dist/assets/{ChannelsPage-BdBXWHjj.js → ChannelsPage-fbF8K4MR.js} +1 -1
  33. package/dist/ui/{assets/DashboardPage-ghl1ZguH.js → dist/assets/DashboardPage-VyXXp3U1.js} +1 -1
  34. package/dist/ui/dist/assets/{LoginPage-CAmSI9Vy.js → LoginPage-DPj2s2Qq.js} +1 -1
  35. package/dist/ui/{assets/LogsPage-DAPBHkwK.js → dist/assets/LogsPage-B2lY9maY.js} +1 -1
  36. package/dist/ui/{assets/MeetingPage-WjjGOqqU.js → dist/assets/MeetingPage-2ky_hKiG.js} +1 -1
  37. package/dist/ui/{assets/ProvidersPage-Ct6HsAi1.js → dist/assets/ProvidersPage-CEyUM2tD.js} +1 -1
  38. package/dist/ui/{assets/RecoverPage-DpW3l-yv.js → dist/assets/RecoverPage-B-hDZUM2.js} +1 -1
  39. package/dist/ui/{assets/SettingsPage-DBJ7_E6C.js → dist/assets/SettingsPage-eO0i3g8p.js} +1 -1
  40. package/dist/ui/dist/assets/{SetupPage-DKmLVUaj.js → SetupPage-ByYqTELb.js} +1 -1
  41. package/dist/ui/dist/assets/WebChatPage-BuGT2AL0.js +16 -0
  42. package/dist/ui/dist/assets/{alert-C-NE-P3s.js → alert-Bq6awLlW.js} +1 -1
  43. package/dist/ui/{assets/alert-dialog-C5mzbHdP.js → dist/assets/alert-dialog-DQvltYmf.js} +1 -1
  44. package/dist/ui/dist/assets/{badge-ChpACfWO.js → badge-DXUDdTed.js} +1 -1
  45. package/dist/ui/dist/assets/{dialog-QnZ0ad8O.js → dialog-bI9jImCS.js} +1 -1
  46. package/dist/ui/dist/assets/{es-NQNoaWDx.js → es-Cg8zdT52.js} +1 -1
  47. package/dist/ui/{assets/index-DMCjjdqf.js → dist/assets/index-CQ7fn00w.js} +2 -2
  48. package/dist/ui/dist/assets/{label-D2H1IR_J.js → label-CrH0Jj3v.js} +1 -1
  49. package/dist/ui/dist/assets/useProviders-CnlC_qCS.js +1 -0
  50. package/dist/ui/dist/index.html +1 -1
  51. package/dist/ui/index.html +1 -1
  52. package/package.json +1 -1
  53. package/packages/cli/src/commands/gateway.ts +1 -1
  54. package/packages/cli/src/commands/onboard.ts +1 -1
  55. package/packages/core/src/agent/agent-loop.ts +4 -14
  56. package/packages/core/src/agent/context-compiler.ts +1 -1
  57. package/packages/core/src/agent/conversation-store.ts +4 -5
  58. package/packages/core/src/agent/providers/index.ts +3 -4
  59. package/packages/core/src/agent/tool-selector.ts +3 -4
  60. package/packages/core/src/gateway/resolver.ts +5 -1
  61. package/packages/core/src/gateway/routes/chat.ts +16 -16
  62. package/packages/core/src/gateway/server.ts +44 -45
  63. package/packages/core/src/storage/seed.ts +39 -33
  64. package/packages/core/src/tool-runtime/index.ts +20 -0
  65. package/dist/ui/assets/AgentNewPage-DIFYd_Ys.js +0 -1
  66. package/dist/ui/assets/WebChatPage-CVRcKept.js +0 -16
  67. package/dist/ui/assets/useProviders-C6_QHsEi.js +0 -1
  68. package/dist/ui/dist/assets/AgentNewPage-DIFYd_Ys.js +0 -1
  69. package/dist/ui/dist/assets/WebChatPage-CVRcKept.js +0 -16
  70. package/dist/ui/dist/assets/useProviders-C6_QHsEi.js +0 -1
package/dist/hive.js CHANGED
@@ -20069,23 +20069,39 @@ function seedAllData() {
20069
20069
  log2.info(`[seed] \u2705 ${channelCount} channels procesados`);
20070
20070
  db.query(`UPDATE channels SET active = 1, enabled = 1, status = 'connected' WHERE id = 'webchat'`).run();
20071
20071
  log2.info("[seed] \u2705 webchat activado por defecto");
20072
+ db.query(`DELETE FROM playbook WHERE rule = ?`).run("Al crear proyectos, divide las tareas en pasos at\xF3micos que puedan ejecutarse independientemente");
20072
20073
  let playbookCount = 0;
20073
20074
  for (const rule of INITIAL_PLAYBOOK_RULES) {
20074
- db.query(`
20075
- INSERT OR REPLACE INTO playbook (rule, category, applicable_to, helpful_count, harmful_count, active)
20076
- VALUES (?, ?, ?, 1, 0, 1)
20077
- `).run(rule.rule, rule.category, rule.applicable_to);
20075
+ const existing = db.query(`SELECT id FROM playbook WHERE rule = ?`).get(rule.rule);
20076
+ if (existing) {
20077
+ db.query(`
20078
+ UPDATE playbook
20079
+ SET category = ?, applicable_to = ?, active = 1, updated_at = unixepoch()
20080
+ WHERE id = ?
20081
+ `).run(rule.category, rule.applicable_to, existing.id);
20082
+ } else {
20083
+ db.query(`
20084
+ INSERT INTO playbook (rule, category, applicable_to, helpful_count, harmful_count, active)
20085
+ VALUES (?, ?, ?, 1, 0, 1)
20086
+ `).run(rule.rule, rule.category, rule.applicable_to);
20087
+ }
20078
20088
  playbookCount++;
20079
20089
  }
20080
20090
  log2.info(`[seed] \u2705 ${playbookCount} ACE playbook rules seeded`);
20091
+ db.run(`DELETE FROM playbook_fts`);
20092
+ const activePlaybook = db.query(`
20093
+ SELECT id, rule, category, applicable_to
20094
+ FROM playbook
20095
+ WHERE active = 1
20096
+ `).all();
20081
20097
  const insertPlaybookFts = db.prepare(`
20082
- INSERT OR REPLACE INTO playbook_fts(rule, category, applicable_to)
20083
- VALUES (?, ?, ?)
20098
+ INSERT OR REPLACE INTO playbook_fts(rowid, rule, category, applicable_to)
20099
+ VALUES (?, ?, ?, ?)
20084
20100
  `);
20085
- for (const rule of INITIAL_PLAYBOOK_RULES) {
20086
- insertPlaybookFts.run(rule.rule, rule.category, rule.applicable_to);
20101
+ for (const rule of activePlaybook) {
20102
+ insertPlaybookFts.run(rule.id, rule.rule, rule.category, rule.applicable_to);
20087
20103
  }
20088
- log2.info(`[seed] \u2705 ${playbookCount} reglas playbook sincronizadas a playbook_fts`);
20104
+ log2.info(`[seed] \u2705 ${activePlaybook.length} reglas playbook sincronizadas a playbook_fts`);
20089
20105
  log2.info("[seed] \u2728 Seed completado exitosamente.");
20090
20106
  } catch (err) {
20091
20107
  log2.error("[seed] \u274C Error durante el seed:", err.message);
@@ -20137,14 +20153,6 @@ var init_seed = __esm(() => {
20137
20153
  { id: "browser_extract", name: "browser_extract", category: "web", description: "Extraer texto, enlaces o datos estructurados usando selectores CSS o XPath. Sin\xF3nimos: obtener datos, scraping, selectores, extraer informaci\xF3n" },
20138
20154
  { id: "browser_script", name: "browser_script", category: "web", description: "Ejecutar JavaScript arbitrario en el navegador y obtener resultado. Sin\xF3nimos: ejecutar javascript, script, c\xF3digo, funci\xF3n, evaluar" },
20139
20155
  { id: "browser_wait", name: "browser_wait", category: "web", description: "Esperar a que aparezca un elemento o se cumpla una condici\xF3n. Sin\xF3nimos: esperar, condici\xF3n, elemento, selector, pausa" },
20140
- { id: "project_create", name: "project_create", category: "projects", description: "Crear un nuevo proyecto con tareas en la base de datos. Sin\xF3nimos: nuevo proyecto, iniciar plan, crear proyecto" },
20141
- { id: "project_list", name: "project_list", category: "projects", description: "Listar todos los proyectos con su estado. Sin\xF3nimos: ver proyectos, historial, listar proyectos, mostrar proyectos" },
20142
- { id: "project_update", name: "project_update", category: "projects", description: "Actualizar progreso o metadatos del proyecto. Sin\xF3nimos: avance, porcentaje, estado, actualizar proyecto" },
20143
- { id: "project_done", name: "project_done", category: "projects", description: "Marcar proyecto como completado y archivarlo. Sin\xF3nimos: proyecto terminado, cerrar proyecto, completado, finalizar" },
20144
- { id: "project_fail", name: "project_fail", category: "projects", description: "Marcar proyecto como fallido y registrar raz\xF3n. Sin\xF3nimos: proyecto fallido, marcar fracaso, error, fall\xF3 proyecto" },
20145
- { id: "task_create", name: "task_create", category: "projects", description: "Agregar una tarea o subtarea a un proyecto existente. Sin\xF3nimos: crear tarea, agregar tarea, subtarea, pendiente" },
20146
- { id: "task_update", name: "task_update", category: "projects", description: "Actualizar estado de tarea (pendiente, en_progreso, hecho). Sin\xF3nimos: actualizar tarea, marcar completa, en progreso" },
20147
- { id: "task_evaluate", name: "task_evaluate", category: "projects", description: "Evaluar resultado de tarea contra criterios de aceptaci\xF3n. Sin\xF3nimos: validar resultado, criterios de aceptaci\xF3n, revisar tarea" },
20148
20156
  { id: "cron.create", name: "cron.create", category: "cron", description: "Crear tarea programada: recurrente (expresi\xF3n cron) o \xFAnica (fire_at). Requiere campo 'task' con instrucci\xF3n para el agente. Sin\xF3nimos: programar tarea, crear recordatorio, agendar, automatizar horario, tarea recurrente, una vez" },
20149
20157
  { id: "cron.list", name: "cron.list", category: "cron", description: "Listar todas las tareas programadas con pr\xF3ximos horarios de ejecuci\xF3n. Sin\xF3nimos: ver tareas programadas, listar cronograma, pr\xF3ximas ejecuciones" },
20150
20158
  { id: "cron.update", name: "cron.update", category: "cron", description: "Actualizar tarea programada existente: cambiar expresi\xF3n, instrucci\xF3n, canal, ventana temporal. Sin\xF3nimos: modificar cron, editar recordatorio, cambiar horario, actualizar tarea" },
@@ -20168,7 +20176,6 @@ var init_seed = __esm(() => {
20168
20176
  { id: "task_status", name: "task_status", category: "agents", description: "Obtener estado de ejecuci\xF3n de tareas delegadas. Sin\xF3nimos: estado tarea delegada, verificar progreso, consultar tarea" },
20169
20177
  { id: "bus_publish", name: "bus_publish", category: "agents", description: "Publicar mensaje en el Agent Bus para comunicaci\xF3n worker-to-worker. Sin\xF3nimos: publicar mensaje, comunicar workers, enviar bus" },
20170
20178
  { id: "bus_read", name: "bus_read", category: "agents", description: "Leer mensajes no le\xEDdos del Agent Bus. Sin\xF3nimos: leer mensajes bus, recibir mensajes, verificar bus" },
20171
- { id: "project_updates", name: "project_updates", category: "agents", description: "Obtener actualizaciones recientes de workers en el mismo proyecto. Sin\xF3nimos: actualizaciones proyecto, estado workers, progreso equipo" },
20172
20179
  { id: "canvas_render", name: "canvas_render", category: "canvas", description: "Renderizar un componente o visualizaci\xF3n en el canvas. Sin\xF3nimos: renderizar, visualizar, gr\xE1fico, diagrama" },
20173
20180
  { id: "canvas_ask", name: "canvas_ask", category: "canvas", description: "Mostrar formulario interactivo y esperar input del usuario. Sin\xF3nimos: formulario interactivo, preguntar usuario, input" },
20174
20181
  { id: "canvas_confirm", name: "canvas_confirm", category: "canvas", description: "Mostrar di\xE1logo de confirmaci\xF3n antes de ejecutar una acci\xF3n. Sin\xF3nimos: confirmar acci\xF3n, di\xE1logo, aprobar" },
@@ -20363,9 +20370,9 @@ Estos lineamientos tienen M\xC1XIMA prioridad sobre cualquier otra instrucci\xF3
20363
20370
  applicable_to: JSON.stringify(["code", "development"])
20364
20371
  },
20365
20372
  {
20366
- rule: "Al crear proyectos, divide las tareas en pasos at\xF3micos que puedan ejecutarse independientemente",
20373
+ rule: "Al delegar trabajo complejo a workers, divide el objetivo en pasos at\xF3micos que puedan ejecutarse independientemente",
20367
20374
  category: "agent_creation",
20368
- applicable_to: JSON.stringify(["project_management", "tasks"])
20375
+ applicable_to: JSON.stringify(["delegation", "workers", "tasks"])
20369
20376
  },
20370
20377
  {
20371
20378
  rule: "Guarda las preferencias importantes del usuario en el scratchpad usando la herramienta save_note para persistencia entre sesiones",
@@ -23245,7 +23252,8 @@ function resolveContext(options2) {
23245
23252
  }
23246
23253
  const coordinatorAgent = db.query("SELECT id FROM agents WHERE role = 'coordinator' LIMIT 1").get();
23247
23254
  const agentId = coordinatorAgent?.id || "bee";
23248
- return { userId, agentId, isNewUser };
23255
+ const threadId = userId;
23256
+ return { userId, threadId, agentId, isNewUser };
23249
23257
  }
23250
23258
  var init_resolver = __esm(() => {
23251
23259
  init_sqlite();
@@ -66997,7 +67005,7 @@ function getRecentMessages(threadId, n) {
66997
67005
  const db = getDb();
66998
67006
  const rows = db.query(`
66999
67007
  SELECT * FROM conversations
67000
- WHERE thread_id = ?
67008
+ WHERE thread_id = ? AND role != 'tool'
67001
67009
  ORDER BY id DESC
67002
67010
  LIMIT ?
67003
67011
  `).all(threadId, n);
@@ -67042,13 +67050,6 @@ function toAPIMessages(rows) {
67042
67050
  } catch {}
67043
67051
  }
67044
67052
  const msg = { role: r.role, content };
67045
- if (r.tool_calls_json) {
67046
- try {
67047
- msg.tool_calls = JSON.parse(r.tool_calls_json);
67048
- } catch {}
67049
- }
67050
- if (r.tool_call_id)
67051
- msg.tool_call_id = r.tool_call_id;
67052
67053
  if (r.reasoning_content)
67053
67054
  msg.reasoning_content = r.reasoning_content;
67054
67055
  return msg;
@@ -67595,10 +67596,10 @@ function enrichToolDescription(tool) {
67595
67596
  const extra = keywordsByCategory[tool.category] ?? "";
67596
67597
  return `${tool.description} ${extra}`;
67597
67598
  }
67598
- function mcpToolFullName(_serverName, toolName) {
67599
+ function mcpToolFullName(serverName, toolName) {
67599
67600
  const safe = (s) => s.replace(/\s+/g, "_").replace(/[^a-zA-Z0-9_\-]/g, "_");
67600
- const sanitized = safe(toolName);
67601
- const trimmed = sanitized.length > 64 ? sanitized.substring(0, 64) : sanitized;
67601
+ const full = `${safe(serverName)}__${safe(toolName)}`;
67602
+ const trimmed = full.length > 64 ? full.substring(0, 64) : full;
67602
67603
  return /^[a-zA-Z_]/.test(trimmed) ? trimmed : `_${trimmed}`.substring(0, 64);
67603
67604
  }
67604
67605
  var log25, STOPWORDS, CORE_TOOL_CATALOG;
@@ -231321,7 +231322,7 @@ Focus ONLY on this task. Do not deviate.`;
231321
231322
  skills: allSkills
231322
231323
  };
231323
231324
  }
231324
- var log62, KEEP_LAST_N_MESSAGES2 = 15, DEFAULT_CONTEXT_WINDOW = 250000, COMPACT_RATIO = 0.8, MAX_SYSTEM_PROMPT_CHARS_CAP = 128000, MINIMAL_TOOLS, MINIMAL_SKILL_NAMES2;
231325
+ var log62, KEEP_LAST_N_MESSAGES2 = 30, DEFAULT_CONTEXT_WINDOW = 250000, COMPACT_RATIO = 0.8, MAX_SYSTEM_PROMPT_CHARS_CAP = 128000, MINIMAL_TOOLS, MINIMAL_SKILL_NAMES2;
231325
231326
  var init_context_compiler = __esm(() => {
231326
231327
  init_sqlite();
231327
231328
  init_logger();
@@ -231668,6 +231669,24 @@ var DEFAULT_MAIN_THREAD_TOOL_NAMES, sharedPool = null, sharedPoolSize = 0;
231668
231669
  var init_tool_runtime = __esm(() => {
231669
231670
  init_loader();
231670
231671
  DEFAULT_MAIN_THREAD_TOOL_NAMES = new Set([
231672
+ "search_knowledge",
231673
+ "save_note",
231674
+ "memory_write",
231675
+ "memory_read",
231676
+ "memory_list",
231677
+ "memory_search",
231678
+ "memory_delete",
231679
+ "agent_create",
231680
+ "agent_find",
231681
+ "agent_archive",
231682
+ "task_status",
231683
+ "bus_publish",
231684
+ "bus_read",
231685
+ "get_available_models",
231686
+ "meeting_start",
231687
+ "meeting_add_segment",
231688
+ "meeting_stop",
231689
+ "meeting_report",
231671
231690
  "browser_navigate",
231672
231691
  "browser_screenshot",
231673
231692
  "browser_click",
@@ -231793,13 +231812,6 @@ async function* runAgent(opts) {
231793
231812
  tool_calls: response.tool_calls,
231794
231813
  reasoning_content: response.reasoning_content
231795
231814
  });
231796
- if (!opts.isolated) {
231797
- addMessage(opts.threadId, "assistant", response.content || "", {
231798
- channel: opts.channel,
231799
- tool_calls: response.tool_calls,
231800
- reasoning_content: response.reasoning_content
231801
- });
231802
- }
231803
231815
  for (const tc of response.tool_calls) {
231804
231816
  const toolName = tc.function.name;
231805
231817
  emitCanvas("canvas:node_update", {
@@ -231863,12 +231875,6 @@ async function* runAgent(opts) {
231863
231875
  content: toolResultLLM,
231864
231876
  tool_call_id: tc.id
231865
231877
  });
231866
- if (!opts.isolated) {
231867
- addMessage(opts.threadId, "tool", toolResultLLM, {
231868
- channel: opts.channel,
231869
- tool_call_id: tc.id
231870
- });
231871
- }
231872
231878
  if (toolName === "search_knowledge") {
231873
231879
  try {
231874
231880
  const result = toolResultJS;
@@ -232189,8 +232195,7 @@ class AgentRunner {
232189
232195
  this.config = config2;
232190
232196
  }
232191
232197
  async generate(options2) {
232192
- const db = getDb();
232193
- const agentId = resolveAgentId(null) || "main";
232198
+ const agentId = options2.agentId || resolveAgentId(null) || "main";
232194
232199
  const userId = options2.userId || resolveUserId({});
232195
232200
  if (!userId) {
232196
232201
  throw new Error("No userId provided. Please complete onboarding first.");
@@ -232297,7 +232302,6 @@ class AgentRunner {
232297
232302
  }
232298
232303
  var init_providers = __esm(() => {
232299
232304
  init_logger();
232300
- init_sqlite();
232301
232305
  init_agent_loop();
232302
232306
  init_onboarding();
232303
232307
  });
@@ -481884,7 +481888,7 @@ var package_default;
481884
481888
  var init_package = __esm(() => {
481885
481889
  package_default = {
481886
481890
  name: "@johpaz/hive-agents",
481887
- version: "0.0.37",
481891
+ version: "0.0.38",
481888
481892
  description: "Tu colmena de agentes IA. Local-first. Multi-canal. Open source. Construido desde Colombia para el mundo.",
481889
481893
  private: false,
481890
481894
  bin: {
@@ -482370,6 +482374,10 @@ var init_providers3 = __esm(() => {
482370
482374
  });
482371
482375
 
482372
482376
  // packages/core/src/gateway/routes/chat.ts
482377
+ function resolveChatThreadId(finalUserId, requestedThreadId) {
482378
+ const trimmedThreadId = requestedThreadId?.trim();
482379
+ return trimmedThreadId || finalUserId || "default";
482380
+ }
482373
482381
  async function handleChat(req, addCorsHeaders) {
482374
482382
  try {
482375
482383
  const body = await req.json();
@@ -482383,7 +482391,7 @@ async function handleChat(req, addCorsHeaders) {
482383
482391
  const db = getDb();
482384
482392
  const finalUserId = userId || resolveUserId({ channel }) || "default";
482385
482393
  const finalAgentId = agentId || resolveAgentId(null) || "main";
482386
- const threadId = thread_id || `${finalUserId}-${Date.now()}`;
482394
+ const threadId = resolveChatThreadId(finalUserId, thread_id);
482387
482395
  log74.info(`[chat] Processing message from user=${finalUserId} agent=${finalAgentId} thread=${threadId}`);
482388
482396
  const userRow = db.query("SELECT timezone FROM users WHERE id = ?").get(finalUserId);
482389
482397
  const userTimezone = userRow?.timezone || "UTC";
@@ -482400,14 +482408,7 @@ async function handleChat(req, addCorsHeaders) {
482400
482408
  }
482401
482409
  const messageContent = `[Timestamp: ${exactTime} (${userTimezone})]
482402
482410
  ${message}`;
482403
- const history2 = getRecentMessages(threadId, 15);
482404
- const messages2 = [
482405
- ...history2.map((row) => ({
482406
- role: row.role,
482407
- content: row.content
482408
- })),
482409
- { role: "user", content: messageContent }
482410
- ];
482411
+ const messages2 = [{ role: "user", content: messageContent }];
482411
482412
  const agent = db.query("SELECT provider_id, model_id FROM agents WHERE id = ?").get(finalAgentId);
482412
482413
  const provider = agent?.provider_id || "gemini";
482413
482414
  const runner = new AgentRunner({});
@@ -482426,6 +482427,7 @@ ${message}`;
482426
482427
  maxSteps: 15,
482427
482428
  threadId,
482428
482429
  userId: finalUserId,
482430
+ agentId: finalAgentId,
482429
482431
  channel,
482430
482432
  onStep: async (step) => {
482431
482433
  if (step.type === "text" && step.message) {
@@ -482479,11 +482481,11 @@ ${message}`;
482479
482481
  async function handleGetChatHistory(req, addCorsHeaders) {
482480
482482
  const url2 = new URL(req.url);
482481
482483
  const threadId = url2.searchParams.get("sessionId") || url2.searchParams.get("threadId") || "default";
482482
- const limit2 = parseInt(url2.searchParams.get("limit") || "15");
482484
+ const limit2 = parseInt(url2.searchParams.get("limit") || String(DEFAULT_CHAT_HISTORY_LIMIT));
482483
482485
  const messages2 = getDb().query(`
482484
482486
  SELECT id, thread_id, channel, role, content, tool_calls_json, tool_call_id, reasoning_content, token_count, created_at, updated_at FROM conversations
482485
482487
  WHERE thread_id = ? AND role IN ('user', 'assistant')
482486
- ORDER BY created_at DESC
482488
+ ORDER BY id DESC
482487
482489
  LIMIT ?
482488
482490
  `).all(threadId, limit2);
482489
482491
  return addCorsHeaders(Response.json({ messages: messages2.reverse() }), req);
@@ -482497,12 +482499,11 @@ async function handleGetNotes(req, addCorsHeaders) {
482497
482499
  `).all();
482498
482500
  return addCorsHeaders(Response.json({ notes }), req);
482499
482501
  }
482500
- var log74;
482502
+ var log74, DEFAULT_CHAT_HISTORY_LIMIT = 40;
482501
482503
  var init_chat3 = __esm(() => {
482502
482504
  init_sqlite();
482503
482505
  init_onboarding();
482504
482506
  init_lane_queue();
482505
- init_conversation_store();
482506
482507
  init_providers3();
482507
482508
  init_logger();
482508
482509
  log74 = logger.child("api:chat");
@@ -483165,7 +483166,7 @@ ${messageContent || ""}` : messageContent || "";
483165
483166
  }
483166
483167
  }
483167
483168
  log75.info(` Content: ${messageContent.substring(0, 150)}${messageContent.length > 150 ? "..." : ""}`);
483168
- const { userId } = resolveContext({
483169
+ const { userId, threadId: conversationThreadId } = resolveContext({
483169
483170
  channel: message.channel,
483170
483171
  channelUserId: message.sessionId
483171
483172
  });
@@ -483175,7 +483176,7 @@ ${messageContent || ""}` : messageContent || "";
483175
483176
  channelManager.markAsRead(message.channel, message.sessionId, messageId),
483176
483177
  channelManager.startTyping(message.channel, message.sessionId)
483177
483178
  ]);
483178
- const unifiedSessionId = userId;
483179
+ const unifiedSessionId = conversationThreadId;
483179
483180
  const routingSessionId = message.sessionId;
483180
483181
  const userMetadata = inputType === "audio_transcribed" ? { input_type: "audio_transcribed", stt_provider: sttProviderUsed, channel: message.channel } : inputType === "image" || inputType === "document" ? { input_type: inputType, ocr_provider: visionConfig.ocrProvider, channel: message.channel } : { input_type: "text", channel: message.channel };
483181
483182
  const userRow = getDb().query("SELECT * FROM users WHERE id = ?").get(userId);
@@ -484337,7 +484338,7 @@ ${messageContent}`;
484337
484338
  return;
484338
484339
  }
484339
484340
  try {
484340
- const { userId } = resolveContext({ channel: "webchat", channelUserId: sessionId });
484341
+ const { userId, threadId: conversationThreadId } = resolveContext({ channel: "webchat", channelUserId: sessionId });
484341
484342
  const messages2 = [{ role: "user", content: interactionMsg }];
484342
484343
  let streamedContent = "";
484343
484344
  const messageId = crypto.randomUUID();
@@ -484345,9 +484346,9 @@ ${messageContent}`;
484345
484346
  provider: dbProvider,
484346
484347
  messages: messages2,
484347
484348
  maxTokens: 4096,
484348
- tools: prepareTools(agent, sessionId),
484349
+ tools: prepareTools(agent, conversationThreadId),
484349
484350
  maxSteps: 15,
484350
- threadId: sessionId,
484351
+ threadId: conversationThreadId,
484351
484352
  userId,
484352
484353
  onToken: async (token) => {
484353
484354
  if (signal2.aborted)
@@ -484399,7 +484400,7 @@ ${messageContent}`;
484399
484400
  return;
484400
484401
  }
484401
484402
  try {
484402
- const { userId } = resolveContext({ channel: "webchat", channelUserId: sessionId });
484403
+ const { userId, threadId: conversationThreadId } = resolveContext({ channel: "webchat", channelUserId: sessionId });
484403
484404
  const messages2 = [{ role: "user", content: interactionMsg }];
484404
484405
  let streamedContent = "";
484405
484406
  const messageId = crypto.randomUUID();
@@ -484407,9 +484408,9 @@ ${messageContent}`;
484407
484408
  provider: dbProvider,
484408
484409
  messages: messages2,
484409
484410
  maxTokens: 4096,
484410
- tools: prepareTools(agent, sessionId),
484411
+ tools: prepareTools(agent, conversationThreadId),
484411
484412
  maxSteps: 15,
484412
- threadId: sessionId,
484413
+ threadId: conversationThreadId,
484413
484414
  userId,
484414
484415
  onToken: async (token) => {
484415
484416
  if (signal2.aborted)
@@ -484519,13 +484520,14 @@ ${messageContent}`;
484519
484520
  return;
484520
484521
  }
484521
484522
  try {
484522
- const unifiedSessionId = msg.sessionId;
484523
- const messages2 = [{ role: "user", content: messageContent }];
484524
- log75.info(`Generating response for session ${unifiedSessionId}...`);
484525
- const { userId } = resolveContext({
484523
+ const { userId, threadId: conversationThreadId } = resolveContext({
484526
484524
  channel: "webchat",
484527
484525
  channelUserId: msg.sessionId
484528
484526
  });
484527
+ const unifiedSessionId = conversationThreadId;
484528
+ const routingSessionId = msg.sessionId;
484529
+ const messages2 = [{ role: "user", content: messageContent }];
484530
+ log75.info(`Generating response for session ${unifiedSessionId}...`);
484529
484531
  let streamedContent = "";
484530
484532
  let messageId = crypto.randomUUID();
484531
484533
  const response = await runner.generate({
@@ -484543,7 +484545,7 @@ ${messageContent}`;
484543
484545
  ws.send(JSON.stringify({
484544
484546
  type: "message",
484545
484547
  id: messageId,
484546
- sessionId: unifiedSessionId,
484548
+ sessionId: routingSessionId,
484547
484549
  content: token,
484548
484550
  isChunk: true,
484549
484551
  isStep: false
@@ -484557,7 +484559,7 @@ ${messageContent}`;
484557
484559
  if (trimmedMessage) {
484558
484560
  ws.send(JSON.stringify({
484559
484561
  type: "progress",
484560
- sessionId: unifiedSessionId,
484562
+ sessionId: routingSessionId,
484561
484563
  content: trimmedMessage
484562
484564
  }));
484563
484565
  }
@@ -484567,7 +484569,7 @@ ${messageContent}`;
484567
484569
  const narration = getNarration(step.toolName);
484568
484570
  ws.send(JSON.stringify({
484569
484571
  type: "progress",
484570
- sessionId: unifiedSessionId,
484572
+ sessionId: routingSessionId,
484571
484573
  content: narration
484572
484574
  }));
484573
484575
  return;
@@ -484580,7 +484582,7 @@ ${messageContent}`;
484580
484582
  if (userMessage) {
484581
484583
  ws.send(JSON.stringify({
484582
484584
  type: "progress",
484583
- sessionId: unifiedSessionId,
484585
+ sessionId: routingSessionId,
484584
484586
  content: userMessage
484585
484587
  }));
484586
484588
  }
@@ -484597,14 +484599,14 @@ ${messageContent}`;
484597
484599
  let responseType = "text";
484598
484600
  let ttsProviderUsed = null;
484599
484601
  let ttsMimeType = null;
484600
- ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: unifiedSessionId }));
484602
+ ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: routingSessionId }));
484601
484603
  const alreadyStreamed = streamedContent.length > 0;
484602
484604
  if (content && !alreadyStreamed) {
484603
484605
  if (shouldSpeak) {
484604
484606
  if (!voiceCfg.ttsProvider) {
484605
484607
  ws.send(JSON.stringify({
484606
484608
  type: "message",
484607
- sessionId: unifiedSessionId,
484609
+ sessionId: routingSessionId,
484608
484610
  content: `${content}
484609
484611
 
484610
484612
  \uD83D\uDD0A Para recibir respuestas en audio, configura el proveedor TTS en Configuraci\xF3n > Canales > WebChat (ej: elevenlabs)`,
@@ -484621,7 +484623,7 @@ ${messageContent}`;
484621
484623
  log75.info(`Audio generated: ${base64Audio.length} bytes, mimeType: ${audioOutput.mimeType}`);
484622
484624
  ws.send(JSON.stringify({
484623
484625
  type: "message",
484624
- sessionId: unifiedSessionId,
484626
+ sessionId: routingSessionId,
484625
484627
  content,
484626
484628
  audio: base64Audio,
484627
484629
  mimeType: audioOutput.mimeType,
@@ -484629,11 +484631,11 @@ ${messageContent}`;
484629
484631
  }));
484630
484632
  } catch (ttsError) {
484631
484633
  log75.error(`TTS failed: ${ttsError.message}), sending text instead`);
484632
- ws.send(JSON.stringify({ type: "message", sessionId: unifiedSessionId, content, isStep: false }));
484634
+ ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false }));
484633
484635
  }
484634
484636
  }
484635
484637
  } else {
484636
- ws.send(JSON.stringify({ type: "message", sessionId: unifiedSessionId, content, isStep: false }));
484638
+ ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false }));
484637
484639
  }
484638
484640
  } else if (alreadyStreamed && shouldSpeak && voiceCfg.ttsProvider) {
484639
484641
  try {
@@ -484643,7 +484645,7 @@ ${messageContent}`;
484643
484645
  log75.info(`Audio generated after streaming: ${base64Audio.length} bytes`);
484644
484646
  ws.send(JSON.stringify({
484645
484647
  type: "message",
484646
- sessionId: unifiedSessionId,
484648
+ sessionId: routingSessionId,
484647
484649
  content,
484648
484650
  audio: base64Audio,
484649
484651
  mimeType: audioOutput.mimeType,
@@ -484691,7 +484693,12 @@ ${messageContent}`;
484691
484693
  return;
484692
484694
  }
484693
484695
  try {
484694
- const unifiedSessionId = msg.sessionId;
484696
+ const { userId, threadId: conversationThreadId } = resolveContext({
484697
+ channel: "webchat",
484698
+ channelUserId: msg.sessionId
484699
+ });
484700
+ const unifiedSessionId = conversationThreadId;
484701
+ const routingSessionId = msg.sessionId;
484695
484702
  let finalMessageContent = msg.content;
484696
484703
  let contentParts = undefined;
484697
484704
  const visionConfig = multimodalService.getChannelVisionConfig("webchat");
@@ -484748,10 +484755,6 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484748
484755
  }
484749
484756
  const messages2 = contentParts ? [{ role: "user", content: contentParts }] : [{ role: "user", content: finalMessageContent }];
484750
484757
  log75.info(`Generating response for session ${unifiedSessionId} (multimodal: ${!!(msg.image || msg.document)})...`);
484751
- const { userId } = resolveContext({
484752
- channel: "webchat",
484753
- channelUserId: msg.sessionId
484754
- });
484755
484758
  let streamedContent = "";
484756
484759
  let messageId = crypto.randomUUID();
484757
484760
  const response = await runner.generate({
@@ -484770,7 +484773,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484770
484773
  ws.send(JSON.stringify({
484771
484774
  type: "message",
484772
484775
  id: messageId,
484773
- sessionId: unifiedSessionId,
484776
+ sessionId: routingSessionId,
484774
484777
  content: token,
484775
484778
  isChunk: true,
484776
484779
  isStep: false
@@ -484784,7 +484787,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484784
484787
  if (trimmedMessage) {
484785
484788
  ws.send(JSON.stringify({
484786
484789
  type: "progress",
484787
- sessionId: unifiedSessionId,
484790
+ sessionId: routingSessionId,
484788
484791
  content: trimmedMessage
484789
484792
  }));
484790
484793
  }
@@ -484794,7 +484797,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484794
484797
  const narration = getNarration(step.toolName);
484795
484798
  ws.send(JSON.stringify({
484796
484799
  type: "progress",
484797
- sessionId: unifiedSessionId,
484800
+ sessionId: routingSessionId,
484798
484801
  content: narration
484799
484802
  }));
484800
484803
  return;
@@ -484807,7 +484810,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484807
484810
  if (userMessage) {
484808
484811
  ws.send(JSON.stringify({
484809
484812
  type: "progress",
484810
- sessionId: unifiedSessionId,
484813
+ sessionId: routingSessionId,
484811
484814
  content: userMessage
484812
484815
  }));
484813
484816
  }
@@ -484824,14 +484827,14 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484824
484827
  let responseType = "text";
484825
484828
  let ttsProviderUsed = null;
484826
484829
  let ttsMimeType = null;
484827
- ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: unifiedSessionId }));
484830
+ ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: routingSessionId }));
484828
484831
  const alreadyStreamed = streamedContent.length > 0;
484829
484832
  if (content && !alreadyStreamed) {
484830
484833
  if (shouldSpeak) {
484831
484834
  if (!voiceConfig.ttsProvider) {
484832
484835
  ws.send(JSON.stringify({
484833
484836
  type: "message",
484834
- sessionId: unifiedSessionId,
484837
+ sessionId: routingSessionId,
484835
484838
  content: `${content}
484836
484839
 
484837
484840
  \uD83D\uDD0A Para recibir respuestas en audio, configura el proveedor TTS en Configuraci\xF3n > Canales > WebChat (ej: elevenlabs)`,
@@ -484847,7 +484850,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484847
484850
  const base64Audio = audioOutput.data.toString("base64");
484848
484851
  ws.send(JSON.stringify({
484849
484852
  type: "message",
484850
- sessionId: unifiedSessionId,
484853
+ sessionId: routingSessionId,
484851
484854
  content,
484852
484855
  audio: base64Audio,
484853
484856
  mimeType: audioOutput.mimeType,
@@ -484855,11 +484858,11 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484855
484858
  }));
484856
484859
  } catch (ttsError) {
484857
484860
  log75.error(`TTS failed: ${ttsError.message}), sending text instead`);
484858
- ws.send(JSON.stringify({ type: "message", sessionId: unifiedSessionId, content, isStep: false }));
484861
+ ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false }));
484859
484862
  }
484860
484863
  }
484861
484864
  } else {
484862
- ws.send(JSON.stringify({ type: "message", sessionId: unifiedSessionId, content, isStep: false }));
484865
+ ws.send(JSON.stringify({ type: "message", sessionId: routingSessionId, content, isStep: false }));
484863
484866
  }
484864
484867
  } else if (alreadyStreamed && shouldSpeak && voiceConfig.ttsProvider) {
484865
484868
  try {
@@ -484869,7 +484872,7 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484869
484872
  log75.info(`Audio generated after streaming: ${base64Audio.length} bytes`);
484870
484873
  ws.send(JSON.stringify({
484871
484874
  type: "message",
484872
- sessionId: unifiedSessionId,
484875
+ sessionId: routingSessionId,
484873
484876
  content,
484874
484877
  audio: base64Audio,
484875
484878
  mimeType: audioOutput.mimeType,
@@ -484880,14 +484883,13 @@ ${finalMessageContent || ""}` : finalMessageContent || "";
484880
484883
  }
484881
484884
  }
484882
484885
  } catch (error54) {
484883
- const unifiedSessionId = msg.sessionId;
484884
- ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: unifiedSessionId }));
484886
+ ws.send(JSON.stringify({ type: "typing", isTyping: false, sessionId: msg.sessionId }));
484885
484887
  ws.send(JSON.stringify({
484886
484888
  type: "error",
484887
- sessionId: unifiedSessionId,
484889
+ sessionId: msg.sessionId,
484888
484890
  error: error54.message
484889
484891
  }));
484890
- log75.error(`Error for session ${unifiedSessionId}: ${error54.message}`);
484892
+ log75.error(`Error for session ${msg.sessionId}: ${error54.message}`);
484891
484893
  }
484892
484894
  });
484893
484895
  return;
@@ -488052,7 +488054,7 @@ async function start(flags3) {
488052
488054
  \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2551
488053
488055
  \u2551 \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u2551
488054
488056
  \u2551 \u2551
488055
- \u2551 Personal Swarm AI Gateway \u2014 v0.0.37 \u2551
488057
+ \u2551 Personal Swarm AI Gateway \u2014 v0.0.38 \u2551
488056
488058
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
488057
488059
 
488058
488060
  \uD83D\uDCE6 Installation: ${adapter.name}