@drax/ai-back 3.29.0 → 3.31.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/dist/agents/ChatbotTaskService.js +143 -0
- package/dist/agents/ChatbotTaskTools.js +756 -0
- package/dist/agents/DraxAgent.js +450 -0
- package/dist/controllers/AgentSessionController.js +18 -0
- package/dist/controllers/DraxAgentController.js +114 -0
- package/dist/factory/services/AgentSessionServiceFactory.js +30 -0
- package/dist/index.js +15 -1
- package/dist/interfaces/IAgentSession.js +1 -0
- package/dist/interfaces/IAgentSessionRepository.js +1 -0
- package/dist/interfaces/IBuilderTool.js +1 -0
- package/dist/interfaces/IDraxAgent.js +1 -0
- package/dist/interfaces/IDraxAgentController.js +1 -0
- package/dist/interfaces/IDraxAgentRoutes.js +1 -0
- package/dist/models/AgentSessionModel.js +31 -0
- package/dist/permissions/AgentPermissions.js +6 -0
- package/dist/permissions/AgentSessionPermissions.js +10 -0
- package/dist/repository/mongo/AgentSessionMongoRepository.js +13 -0
- package/dist/repository/sqlite/AgentSessionSqliteRepository.js +34 -0
- package/dist/routes/AgentSessionRoutes.js +21 -0
- package/dist/routes/ChatbotTaskRoutes.js +8 -0
- package/dist/routes/DraxAgentRoutes.js +9 -0
- package/dist/schemas/AgentSessionSchema.js +25 -0
- package/dist/services/AgentSessionService.js +9 -0
- package/dist/tools/BuilderTool.js +248 -0
- package/dist/tools/ToolBuilder.js +243 -0
- package/package.json +3 -3
- package/src/agents/DraxAgent.ts +574 -0
- package/src/controllers/AgentSessionController.ts +29 -0
- package/src/controllers/DraxAgentController.ts +135 -0
- package/src/factory/services/AgentSessionServiceFactory.ts +41 -0
- package/src/index.ts +58 -1
- package/src/interfaces/IAIProvider.ts +8 -0
- package/src/interfaces/IAgentSession.ts +44 -0
- package/src/interfaces/IAgentSessionRepository.ts +11 -0
- package/src/interfaces/IBuilderTool.ts +51 -0
- package/src/interfaces/IDraxAgent.ts +108 -0
- package/src/interfaces/IDraxAgentController.ts +5 -0
- package/src/interfaces/IDraxAgentRoutes.ts +7 -0
- package/src/models/AgentSessionModel.ts +46 -0
- package/src/permissions/AgentPermissions.ts +10 -0
- package/src/permissions/AgentSessionPermissions.ts +14 -0
- package/src/repository/mongo/AgentSessionMongoRepository.ts +22 -0
- package/src/repository/sqlite/AgentSessionSqliteRepository.ts +42 -0
- package/src/routes/AgentSessionRoutes.ts +38 -0
- package/src/routes/DraxAgentRoutes.ts +12 -0
- package/src/schemas/AgentSessionSchema.ts +30 -0
- package/src/services/AgentSessionService.ts +20 -0
- package/src/tools/BuilderTool.ts +289 -0
- package/test/DraxAgent.test.ts +221 -0
- package/test/ToolBuilder.test.ts +90 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/agents/ChatbotTaskService.d.ts +42 -0
- package/types/agents/ChatbotTaskService.d.ts.map +1 -0
- package/types/agents/ChatbotTaskTools.d.ts +54 -0
- package/types/agents/ChatbotTaskTools.d.ts.map +1 -0
- package/types/agents/DraxAgent.d.ts +55 -0
- package/types/agents/DraxAgent.d.ts.map +1 -0
- package/types/controllers/AgentSessionController.d.ts +8 -0
- package/types/controllers/AgentSessionController.d.ts.map +1 -0
- package/types/controllers/DraxAgentController.d.ts +16 -0
- package/types/controllers/DraxAgentController.d.ts.map +1 -0
- package/types/factory/services/AgentSessionServiceFactory.d.ts +8 -0
- package/types/factory/services/AgentSessionServiceFactory.d.ts.map +1 -0
- package/types/index.d.ts +14 -2
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/IAIProvider.d.ts +7 -1
- package/types/interfaces/IAIProvider.d.ts.map +1 -1
- package/types/interfaces/IAgentSession.d.ts +39 -0
- package/types/interfaces/IAgentSession.d.ts.map +1 -0
- package/types/interfaces/IAgentSessionRepository.d.ts +6 -0
- package/types/interfaces/IAgentSessionRepository.d.ts.map +1 -0
- package/types/interfaces/IBuilderTool.d.ts +26 -0
- package/types/interfaces/IBuilderTool.d.ts.map +1 -0
- package/types/interfaces/IDraxAgent.d.ts +74 -0
- package/types/interfaces/IDraxAgent.d.ts.map +1 -0
- package/types/interfaces/IDraxAgentController.d.ts +5 -0
- package/types/interfaces/IDraxAgentController.d.ts.map +1 -0
- package/types/interfaces/IDraxAgentRoutes.d.ts +6 -0
- package/types/interfaces/IDraxAgentRoutes.d.ts.map +1 -0
- package/types/models/AgentSessionModel.d.ts +15 -0
- package/types/models/AgentSessionModel.d.ts.map +1 -0
- package/types/permissions/AgentPermissions.d.ts +6 -0
- package/types/permissions/AgentPermissions.d.ts.map +1 -0
- package/types/permissions/AgentSessionPermissions.d.ts +10 -0
- package/types/permissions/AgentSessionPermissions.d.ts.map +1 -0
- package/types/repository/mongo/AgentSessionMongoRepository.d.ts +9 -0
- package/types/repository/mongo/AgentSessionMongoRepository.d.ts.map +1 -0
- package/types/repository/sqlite/AgentSessionSqliteRepository.d.ts +23 -0
- package/types/repository/sqlite/AgentSessionSqliteRepository.d.ts.map +1 -0
- package/types/routes/AgentSessionRoutes.d.ts +4 -0
- package/types/routes/AgentSessionRoutes.d.ts.map +1 -0
- package/types/routes/ChatbotTaskRoutes.d.ts +4 -0
- package/types/routes/ChatbotTaskRoutes.d.ts.map +1 -0
- package/types/routes/DraxAgentRoutes.d.ts +4 -0
- package/types/routes/DraxAgentRoutes.d.ts.map +1 -0
- package/types/schemas/AgentSessionSchema.d.ts +51 -0
- package/types/schemas/AgentSessionSchema.d.ts.map +1 -0
- package/types/services/AgentSessionService.d.ts +10 -0
- package/types/services/AgentSessionService.d.ts.map +1 -0
- package/types/tools/BuilderTool.d.ts +35 -0
- package/types/tools/BuilderTool.d.ts.map +1 -0
- package/types/tools/ToolBuilder.d.ts +47 -0
- package/types/tools/ToolBuilder.d.ts.map +1 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { AiProviderFactory } from "@drax/ai-back";
|
|
3
|
+
import ChatbotTaskTools from "../tools/ChatbotTaskTools.js";
|
|
4
|
+
class ChatbotTaskService {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.sessions = new Map();
|
|
7
|
+
}
|
|
8
|
+
startSession(userId) {
|
|
9
|
+
return this.createSession(userId);
|
|
10
|
+
}
|
|
11
|
+
createSession(userId, sessionId = randomUUID()) {
|
|
12
|
+
const session = {
|
|
13
|
+
id: sessionId,
|
|
14
|
+
userId,
|
|
15
|
+
messages: [],
|
|
16
|
+
createdAt: new Date(),
|
|
17
|
+
updatedAt: new Date(),
|
|
18
|
+
};
|
|
19
|
+
this.sessions.set(this.getSessionKey(userId, session.id), session);
|
|
20
|
+
return session;
|
|
21
|
+
}
|
|
22
|
+
async sendMessage(input) {
|
|
23
|
+
const session = this.resolveSession(input.userId, input.sessionId);
|
|
24
|
+
const provider = AiProviderFactory.instance();
|
|
25
|
+
const history = session.messages.slice(-20);
|
|
26
|
+
const optionNames = await ChatbotTaskTools.fetchLifeOpsOptionNames();
|
|
27
|
+
const tools = this.withToolExecutionLogs(ChatbotTaskTools.build({ userId: input.userId }), session.id);
|
|
28
|
+
const response = await provider.prompt({
|
|
29
|
+
systemPrompt: this.systemPrompt(optionNames),
|
|
30
|
+
userInput: input.message,
|
|
31
|
+
history,
|
|
32
|
+
tools,
|
|
33
|
+
toolMaxIterations: 10,
|
|
34
|
+
operationTitle: "lifeops-task-chatbot",
|
|
35
|
+
operationGroup: "lifeops",
|
|
36
|
+
ip: input.ip,
|
|
37
|
+
userAgent: input.userAgent,
|
|
38
|
+
tenant: input.tenantId ?? null,
|
|
39
|
+
user: input.userId,
|
|
40
|
+
});
|
|
41
|
+
const assistantMessage = this.normalizeOutput(response.output);
|
|
42
|
+
session.messages.push({ role: "user", content: input.message });
|
|
43
|
+
session.messages.push({ role: "assistant", content: assistantMessage });
|
|
44
|
+
session.updatedAt = new Date();
|
|
45
|
+
return {
|
|
46
|
+
sessionId: session.id,
|
|
47
|
+
message: assistantMessage,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
resolveSession(userId, sessionId) {
|
|
51
|
+
if (!sessionId) {
|
|
52
|
+
return this.startSession(userId);
|
|
53
|
+
}
|
|
54
|
+
const existingSession = this.sessions.get(this.getSessionKey(userId, sessionId));
|
|
55
|
+
if (existingSession) {
|
|
56
|
+
return existingSession;
|
|
57
|
+
}
|
|
58
|
+
return this.createSession(userId, sessionId);
|
|
59
|
+
}
|
|
60
|
+
getSessionKey(userId, sessionId) {
|
|
61
|
+
return `${userId}:${sessionId}`;
|
|
62
|
+
}
|
|
63
|
+
normalizeOutput(output) {
|
|
64
|
+
if (typeof output === "string") {
|
|
65
|
+
return output;
|
|
66
|
+
}
|
|
67
|
+
if (output?.message && typeof output.message === "string") {
|
|
68
|
+
return output.message;
|
|
69
|
+
}
|
|
70
|
+
return JSON.stringify(output);
|
|
71
|
+
}
|
|
72
|
+
withToolExecutionLogs(tools, sessionId) {
|
|
73
|
+
return tools.map(tool => ({
|
|
74
|
+
...tool,
|
|
75
|
+
execute: async (args) => {
|
|
76
|
+
console.log("[lifeops-task-chatbot] tool:start", {
|
|
77
|
+
sessionId,
|
|
78
|
+
tool: tool.name,
|
|
79
|
+
args,
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
const result = await tool.execute(args);
|
|
83
|
+
console.log("[lifeops-task-chatbot] tool:success", {
|
|
84
|
+
sessionId,
|
|
85
|
+
tool: tool.name,
|
|
86
|
+
});
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error("[lifeops-task-chatbot] tool:error", {
|
|
91
|
+
sessionId,
|
|
92
|
+
tool: tool.name,
|
|
93
|
+
error,
|
|
94
|
+
});
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
systemPrompt(optionNames) {
|
|
101
|
+
return [
|
|
102
|
+
"Sos un asistente de LifeOps especializado en gestionar tareas, objetivos, proyectos, contactos, clientes y empresas.",
|
|
103
|
+
"Conversas en espanol claro y breve.",
|
|
104
|
+
"Cuando el usuario pida registrar, crear, guardar o agendar una tarea, usa la tool register_task.",
|
|
105
|
+
"Cuando el usuario pida buscar tareas por texto, usa search_tasks. Si pide una tarea puntual por ID, usa find_task_by_id.",
|
|
106
|
+
"Cuando el usuario pida cantidad de tareas agrupadas, metricas, distribuciones o totales por atributos como status, priority, source, type, fechas, proyecto, cliente o minutos, usa group_tasks.",
|
|
107
|
+
"Cuando el usuario pida modificar una tarea existente, primero identifica el ID y usa update_task_partial.",
|
|
108
|
+
"Cuando el usuario pida crear objetivos, proyectos, contactos, clientes o empresas, usa create_goal, create_project, create_contact, create_client o create_company.",
|
|
109
|
+
"Cuando el usuario pida buscar objetivos, proyectos, contactos, clientes o empresas por texto, usa search_goals, search_projects, search_contacts, search_clients o search_companies. Si pide una entidad puntual por ID, usa find_goal_by_id, find_project_by_id, find_contact_by_id, find_client_by_id o find_company_by_id.",
|
|
110
|
+
"Cuando el usuario pida modificar parcialmente objetivos, proyectos, contactos, clientes o empresas existentes, primero identifica el ID y usa update_goal_partial, update_project_partial, update_contact_partial, update_client_partial o update_company_partial.",
|
|
111
|
+
"Para registrar o modificar tareas, elegi source, status, type y priority solo desde estas opciones disponibles por nombre:",
|
|
112
|
+
this.formatTaskOptionNames(optionNames.task),
|
|
113
|
+
"No llames list_task_options antes de registrar o modificar una tarea cuando puedas elegir una opcion desde la lista anterior.",
|
|
114
|
+
"Si el usuario pide una opcion de source, status, type o priority que no existe, podes crearla con create_task_source, create_task_status, create_task_type o create_priority.",
|
|
115
|
+
"Para crear o modificar contactos, empresas o clientes, elegi type solo desde estas opciones disponibles por nombre:",
|
|
116
|
+
this.formatEntityTypeOptionNames(optionNames.entityTypes),
|
|
117
|
+
"No inventes IDs de empresas, clientes, contactos, proyectos u objetivos relacionados. Buscalos primero con la tool correspondiente; si no existen y el usuario quiere crearlos, crealos antes de usarlos como relacion.",
|
|
118
|
+
"Si faltan datos minimos para crear la tarea, inferi un titulo razonable desde el mensaje del usuario.",
|
|
119
|
+
"Si faltan datos minimos para crear una entidad, pedi solo los datos imprescindibles que no puedas inferir.",
|
|
120
|
+
"Despues de registrar, encontrar o modificar una entidad, confirma el resultado y resume los campos relevantes.",
|
|
121
|
+
].join("\n");
|
|
122
|
+
}
|
|
123
|
+
formatTaskOptionNames(taskOptionNames) {
|
|
124
|
+
return [
|
|
125
|
+
`- source: ${this.formatOptionList(taskOptionNames.sources)}`,
|
|
126
|
+
`- status: ${this.formatOptionList(taskOptionNames.statuses)}`,
|
|
127
|
+
`- type: ${this.formatOptionList(taskOptionNames.types)}`,
|
|
128
|
+
`- priority: ${this.formatOptionList(taskOptionNames.priorities)}`,
|
|
129
|
+
].join("\n");
|
|
130
|
+
}
|
|
131
|
+
formatEntityTypeOptionNames(entityTypeOptionNames) {
|
|
132
|
+
return [
|
|
133
|
+
`- contact.type: ${this.formatOptionList(entityTypeOptionNames.contactTypes)}`,
|
|
134
|
+
`- company.type: ${this.formatOptionList(entityTypeOptionNames.companyTypes)}`,
|
|
135
|
+
`- client.type: ${this.formatOptionList(entityTypeOptionNames.clientTypes)}`,
|
|
136
|
+
].join("\n");
|
|
137
|
+
}
|
|
138
|
+
formatOptionList(options) {
|
|
139
|
+
return options.length > 0 ? options.join(", ") : "(sin opciones disponibles)";
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export default ChatbotTaskService;
|
|
143
|
+
export { ChatbotTaskService };
|