@tleblancureta/proto 0.2.0 → 0.3.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/core-gateway/auth.d.ts +7 -0
- package/dist/core-gateway/auth.d.ts.map +1 -0
- package/dist/core-gateway/auth.js +12 -0
- package/dist/core-gateway/auth.js.map +1 -0
- package/dist/core-gateway/claude-runner.d.ts +10 -0
- package/dist/core-gateway/claude-runner.d.ts.map +1 -0
- package/dist/core-gateway/claude-runner.js +206 -0
- package/dist/core-gateway/claude-runner.js.map +1 -0
- package/dist/core-gateway/config.d.ts +33 -0
- package/dist/core-gateway/config.d.ts.map +1 -0
- package/dist/core-gateway/config.js +84 -0
- package/dist/core-gateway/config.js.map +1 -0
- package/dist/core-gateway/email-sender.d.ts +36 -0
- package/dist/core-gateway/email-sender.d.ts.map +1 -0
- package/dist/core-gateway/email-sender.js +121 -0
- package/dist/core-gateway/email-sender.js.map +1 -0
- package/dist/core-gateway/mail-ingester.d.ts +3 -0
- package/dist/core-gateway/mail-ingester.d.ts.map +1 -0
- package/dist/core-gateway/mail-ingester.js +294 -0
- package/dist/core-gateway/mail-ingester.js.map +1 -0
- package/dist/core-gateway/mail-router.d.ts +18 -0
- package/dist/core-gateway/mail-router.d.ts.map +1 -0
- package/dist/core-gateway/mail-router.js +37 -0
- package/dist/core-gateway/mail-router.js.map +1 -0
- package/dist/core-gateway/mail-threads.d.ts +78 -0
- package/dist/core-gateway/mail-threads.d.ts.map +1 -0
- package/dist/core-gateway/mail-threads.js +100 -0
- package/dist/core-gateway/mail-threads.js.map +1 -0
- package/dist/core-gateway/rate-limiter.d.ts +9 -0
- package/dist/core-gateway/rate-limiter.d.ts.map +1 -0
- package/dist/core-gateway/rate-limiter.js +13 -0
- package/dist/core-gateway/rate-limiter.js.map +1 -0
- package/dist/core-gateway/registry.d.ts +14 -0
- package/dist/core-gateway/registry.d.ts.map +1 -0
- package/dist/core-gateway/registry.js +83 -0
- package/dist/core-gateway/registry.js.map +1 -0
- package/dist/core-gateway/routes/admin.d.ts +3 -0
- package/dist/core-gateway/routes/admin.d.ts.map +1 -0
- package/dist/core-gateway/routes/admin.js +91 -0
- package/dist/core-gateway/routes/admin.js.map +1 -0
- package/dist/core-gateway/routes/chat.d.ts +9 -0
- package/dist/core-gateway/routes/chat.d.ts.map +1 -0
- package/dist/core-gateway/routes/chat.js +149 -0
- package/dist/core-gateway/routes/chat.js.map +1 -0
- package/dist/core-gateway/routes/cron.d.ts +13 -0
- package/dist/core-gateway/routes/cron.d.ts.map +1 -0
- package/dist/core-gateway/routes/cron.js +79 -0
- package/dist/core-gateway/routes/cron.js.map +1 -0
- package/dist/core-gateway/routes/gmail.d.ts +8 -0
- package/dist/core-gateway/routes/gmail.d.ts.map +1 -0
- package/dist/core-gateway/routes/gmail.js +57 -0
- package/dist/core-gateway/routes/gmail.js.map +1 -0
- package/dist/core-gateway/routes/health.d.ts +3 -0
- package/dist/core-gateway/routes/health.d.ts.map +1 -0
- package/dist/core-gateway/routes/health.js +7 -0
- package/dist/core-gateway/routes/health.js.map +1 -0
- package/dist/core-gateway/routes/upload.d.ts +7 -0
- package/dist/core-gateway/routes/upload.d.ts.map +1 -0
- package/dist/core-gateway/routes/upload.js +31 -0
- package/dist/core-gateway/routes/upload.js.map +1 -0
- package/dist/core-gateway/scheduler.d.ts +68 -0
- package/dist/core-gateway/scheduler.d.ts.map +1 -0
- package/dist/core-gateway/scheduler.js +252 -0
- package/dist/core-gateway/scheduler.js.map +1 -0
- package/dist/core-gateway/server.d.ts +17 -0
- package/dist/core-gateway/server.d.ts.map +1 -0
- package/dist/core-gateway/server.js +45 -0
- package/dist/core-gateway/server.js.map +1 -0
- package/dist/core-gateway/session.d.ts +18 -0
- package/dist/core-gateway/session.d.ts.map +1 -0
- package/dist/core-gateway/session.js +178 -0
- package/dist/core-gateway/session.js.map +1 -0
- package/dist/core-gateway/skills.d.ts +4 -0
- package/dist/core-gateway/skills.d.ts.map +1 -0
- package/dist/core-gateway/skills.js +100 -0
- package/dist/core-gateway/skills.js.map +1 -0
- package/dist/core-gateway/supabase.d.ts +3 -0
- package/dist/core-gateway/supabase.d.ts.map +1 -0
- package/dist/core-gateway/supabase.js +18 -0
- package/dist/core-gateway/supabase.js.map +1 -0
- package/dist/gateway.d.ts +3 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +3 -0
- package/dist/gateway.js.map +1 -0
- package/package.json +21 -1
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { ImapFlow } from 'imapflow';
|
|
2
|
+
import { simpleParser } from 'mailparser';
|
|
3
|
+
import { runClaude } from './claude-runner.js';
|
|
4
|
+
import { sendSystemMail } from './email-sender.js';
|
|
5
|
+
import { createThread, findThreadByMessageId, isMessageIdProcessed, listThreadMessages, normalizeSubject, recordMessage, } from './mail-threads.js';
|
|
6
|
+
import { resolveCompanyByEmail } from './mail-router.js';
|
|
7
|
+
function loadConfig() {
|
|
8
|
+
const host = process.env.MAIL_IMAP_HOST || process.env.HERMES_IMAP_HOST;
|
|
9
|
+
if (!host)
|
|
10
|
+
return null;
|
|
11
|
+
const port = parseInt(process.env.MAIL_IMAP_PORT || process.env.HERMES_IMAP_PORT || '993', 10);
|
|
12
|
+
const user = process.env.MAIL_IMAP_USER || process.env.HERMES_IMAP_USER || process.env.MAIL_SMTP_USER || process.env.HERMES_SMTP_USER;
|
|
13
|
+
const pass = process.env.MAIL_IMAP_PASS || process.env.HERMES_IMAP_PASS || process.env.MAIL_SMTP_PASS || process.env.HERMES_SMTP_PASS;
|
|
14
|
+
if (!user || !pass) {
|
|
15
|
+
console.warn('[mail-ingester] MAIL_IMAP_HOST set but IMAP/SMTP credentials missing');
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
host,
|
|
20
|
+
port,
|
|
21
|
+
secure: port === 993,
|
|
22
|
+
user,
|
|
23
|
+
pass,
|
|
24
|
+
pollIntervalMs: parseInt(process.env.MAIL_IMAP_POLL_MS || process.env.HERMES_IMAP_POLL_MS || '30000', 10),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
let running = false;
|
|
28
|
+
let timer = null;
|
|
29
|
+
export function startMailIngester() {
|
|
30
|
+
const config = loadConfig();
|
|
31
|
+
if (!config) {
|
|
32
|
+
console.log('[mail-ingester] disabled (no MAIL_IMAP_HOST configured)');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (running)
|
|
36
|
+
return;
|
|
37
|
+
running = true;
|
|
38
|
+
console.log(`[mail-ingester] starting — ${config.user}@${config.host}:${config.port} every ${config.pollIntervalMs}ms`);
|
|
39
|
+
// Kick off an immediate first poll, then interval
|
|
40
|
+
const tick = async () => {
|
|
41
|
+
try {
|
|
42
|
+
await pollOnce(config);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error('[mail-ingester] poll error:', err);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
tick();
|
|
49
|
+
timer = setInterval(tick, config.pollIntervalMs);
|
|
50
|
+
}
|
|
51
|
+
export function stopMailIngester() {
|
|
52
|
+
if (timer)
|
|
53
|
+
clearInterval(timer);
|
|
54
|
+
timer = null;
|
|
55
|
+
running = false;
|
|
56
|
+
}
|
|
57
|
+
async function pollOnce(config) {
|
|
58
|
+
const client = new ImapFlow({
|
|
59
|
+
host: config.host,
|
|
60
|
+
port: config.port,
|
|
61
|
+
secure: config.secure,
|
|
62
|
+
auth: { user: config.user, pass: config.pass },
|
|
63
|
+
logger: false,
|
|
64
|
+
});
|
|
65
|
+
try {
|
|
66
|
+
await client.connect();
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error('[mail-ingester] connect failed:', err?.message || err);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const lock = await client.getMailboxLock('INBOX');
|
|
74
|
+
try {
|
|
75
|
+
// Search for unseen messages
|
|
76
|
+
const uids = await client.search({ seen: false }, { uid: true });
|
|
77
|
+
if (!uids || uids.length === 0)
|
|
78
|
+
return;
|
|
79
|
+
for (const uid of uids) {
|
|
80
|
+
try {
|
|
81
|
+
const msg = await client.fetchOne(String(uid), { source: true }, { uid: true });
|
|
82
|
+
if (!msg || !msg.source)
|
|
83
|
+
continue;
|
|
84
|
+
const parsed = await simpleParser(msg.source);
|
|
85
|
+
const processed = await processInboundMail(parsed);
|
|
86
|
+
if (processed) {
|
|
87
|
+
// Mark seen only if we handled it cleanly
|
|
88
|
+
await client.messageFlagsAdd(String(uid), ['\\Seen'], { uid: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error(`[mail-ingester] failed to process uid=${uid}:`, err?.message || err);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
lock.release();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
try {
|
|
102
|
+
await client.logout();
|
|
103
|
+
}
|
|
104
|
+
catch { }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Core logic per inbound mail. Returns true if it should be marked as seen.
|
|
109
|
+
*/
|
|
110
|
+
async function processInboundMail(parsed) {
|
|
111
|
+
const messageId = parsed.messageId;
|
|
112
|
+
if (!messageId) {
|
|
113
|
+
console.warn('[mail-ingester] skipping message without Message-ID');
|
|
114
|
+
return true; // mark seen anyway, nothing we can do
|
|
115
|
+
}
|
|
116
|
+
// Dedup
|
|
117
|
+
if (await isMessageIdProcessed(messageId)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
// Skip auto-replies, bounces, mailer-daemon
|
|
121
|
+
const headers = parsed.headers;
|
|
122
|
+
if (headers.get('auto-submitted') && String(headers.get('auto-submitted')) !== 'no') {
|
|
123
|
+
console.log(`[mail-ingester] skipping auto-submitted: ${messageId}`);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
const fromAddr = parsed.from?.value?.[0]?.address?.toLowerCase();
|
|
127
|
+
if (!fromAddr || /mailer-daemon|postmaster|no-?reply/i.test(fromAddr)) {
|
|
128
|
+
console.log(`[mail-ingester] skipping system sender: ${fromAddr}`);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
// Route to company via allowlist
|
|
132
|
+
const route = await resolveCompanyByEmail(fromAddr);
|
|
133
|
+
if (!route) {
|
|
134
|
+
console.log(`[mail-ingester] no company match for ${fromAddr}, dropping`);
|
|
135
|
+
return true; // treat as spam, mark seen
|
|
136
|
+
}
|
|
137
|
+
// Thread lookup via In-Reply-To
|
|
138
|
+
const inReplyTo = firstHeader(parsed.headers.get('in-reply-to'));
|
|
139
|
+
const references = parsed.references
|
|
140
|
+
? (Array.isArray(parsed.references) ? parsed.references : [parsed.references])
|
|
141
|
+
: [];
|
|
142
|
+
const threadCandidates = [inReplyTo, ...references].filter(Boolean);
|
|
143
|
+
let thread = null;
|
|
144
|
+
for (const parentId of threadCandidates) {
|
|
145
|
+
thread = await findThreadByMessageId(parentId);
|
|
146
|
+
if (thread)
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
if (thread && thread.company_id !== route.companyId) {
|
|
150
|
+
console.warn(`[mail-ingester] thread ${thread.id} belongs to different company — ignoring parent`);
|
|
151
|
+
thread = null;
|
|
152
|
+
}
|
|
153
|
+
if (!thread) {
|
|
154
|
+
thread = await createThread({
|
|
155
|
+
companyId: route.companyId,
|
|
156
|
+
subject: parsed.subject || null,
|
|
157
|
+
initiatedBy: 'in',
|
|
158
|
+
externalAddress: fromAddr,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
const body = cleanInboundBody(parsed.text || parsed.html || '');
|
|
162
|
+
const subject = parsed.subject || '(sin asunto)';
|
|
163
|
+
const toAddr = parsed.to
|
|
164
|
+
? (Array.isArray(parsed.to) ? parsed.to[0]?.value?.[0]?.address : parsed.to.value?.[0]?.address)
|
|
165
|
+
: '';
|
|
166
|
+
// Record inbound
|
|
167
|
+
await recordMessage({
|
|
168
|
+
threadId: thread.id,
|
|
169
|
+
companyId: route.companyId,
|
|
170
|
+
direction: 'in',
|
|
171
|
+
messageId,
|
|
172
|
+
inReplyTo: inReplyTo || null,
|
|
173
|
+
fromAddress: fromAddr,
|
|
174
|
+
toAddress: toAddr || 'system',
|
|
175
|
+
subject,
|
|
176
|
+
body,
|
|
177
|
+
});
|
|
178
|
+
// Build the agent prompt: prior thread history + the new inbound
|
|
179
|
+
const history = await listThreadMessages(thread.id, 20);
|
|
180
|
+
const prompt = buildAgentPrompt({
|
|
181
|
+
history,
|
|
182
|
+
newFrom: fromAddr,
|
|
183
|
+
newBody: body,
|
|
184
|
+
newSubject: subject,
|
|
185
|
+
});
|
|
186
|
+
console.log(`[mail-ingester] dispatching to agent: thread=${thread.id} from=${fromAddr}`);
|
|
187
|
+
// Dispatch to Claude
|
|
188
|
+
let agentResponse = '';
|
|
189
|
+
try {
|
|
190
|
+
const result = await runClaude({
|
|
191
|
+
company_id: route.companyId,
|
|
192
|
+
user_id: fromAddr,
|
|
193
|
+
message: prompt,
|
|
194
|
+
channel: 'email',
|
|
195
|
+
session_key: thread.session_key,
|
|
196
|
+
enabled_skills: ALL_SKILLS,
|
|
197
|
+
company_context: `[Mensaje recibido por email desde ${fromAddr} en el thread "${thread.subject || subject}"]`,
|
|
198
|
+
selected_files: [],
|
|
199
|
+
});
|
|
200
|
+
agentResponse = result.response || '(sin respuesta)';
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
console.error('[mail-ingester] runClaude failed:', err?.message || err);
|
|
204
|
+
agentResponse = `(No se pudo procesar tu mensaje: ${err?.message || 'error interno'})`;
|
|
205
|
+
}
|
|
206
|
+
// Reply via outbound
|
|
207
|
+
const sendResult = await sendSystemMail({
|
|
208
|
+
companyId: route.companyId,
|
|
209
|
+
to: fromAddr,
|
|
210
|
+
subject: normalizeSubject(subject) || subject,
|
|
211
|
+
body: agentResponse,
|
|
212
|
+
inReplyTo: messageId,
|
|
213
|
+
threadId: thread.id,
|
|
214
|
+
sessionKey: thread.session_key,
|
|
215
|
+
});
|
|
216
|
+
if (!sendResult.ok) {
|
|
217
|
+
console.error('[mail-ingester] reply send failed:', sendResult.error);
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
import { loadSkills } from './registry.js';
|
|
222
|
+
function getAllSkillNames() {
|
|
223
|
+
try {
|
|
224
|
+
return loadSkills().map(s => s.name);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const ALL_SKILLS = getAllSkillNames();
|
|
231
|
+
function firstHeader(value) {
|
|
232
|
+
if (!value)
|
|
233
|
+
return null;
|
|
234
|
+
if (typeof value === 'string')
|
|
235
|
+
return value.trim();
|
|
236
|
+
if (Array.isArray(value))
|
|
237
|
+
return String(value[0]).trim();
|
|
238
|
+
return String(value).trim();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Strip quoted replies and signatures heuristically so the agent only
|
|
242
|
+
* sees the user's fresh content.
|
|
243
|
+
*/
|
|
244
|
+
function cleanInboundBody(raw) {
|
|
245
|
+
if (!raw)
|
|
246
|
+
return '';
|
|
247
|
+
const lines = raw.split(/\r?\n/);
|
|
248
|
+
const out = [];
|
|
249
|
+
for (const line of lines) {
|
|
250
|
+
// Common quote-reply delimiters (Gmail, Outlook, iOS Mail, es)
|
|
251
|
+
if (/^On .+ wrote:\s*$/i.test(line))
|
|
252
|
+
break;
|
|
253
|
+
if (/^El .+ escribi[oó]:\s*$/i.test(line))
|
|
254
|
+
break;
|
|
255
|
+
if (/^-----Original Message-----/i.test(line))
|
|
256
|
+
break;
|
|
257
|
+
if (/^From:.+$/i.test(line) && out.length > 2)
|
|
258
|
+
break;
|
|
259
|
+
// Drop quote lines
|
|
260
|
+
if (/^>/.test(line))
|
|
261
|
+
continue;
|
|
262
|
+
out.push(line);
|
|
263
|
+
}
|
|
264
|
+
return out.join('\n').trim();
|
|
265
|
+
}
|
|
266
|
+
function buildAgentPrompt(opts) {
|
|
267
|
+
const parts = [];
|
|
268
|
+
parts.push(`Estas recibiendo un mensaje por email. Tu respuesta sera enviada de vuelta al remitente como reply automatico.`);
|
|
269
|
+
parts.push('');
|
|
270
|
+
parts.push(`Remitente: ${opts.newFrom}`);
|
|
271
|
+
parts.push(`Asunto: ${opts.newSubject}`);
|
|
272
|
+
parts.push('');
|
|
273
|
+
// Skip the current inbound message — it's shown separately below
|
|
274
|
+
const prior = opts.history.filter(m => m.body && m.body.trim().length > 0);
|
|
275
|
+
const prevMessages = prior.slice(0, -1);
|
|
276
|
+
if (prevMessages.length > 0) {
|
|
277
|
+
parts.push('--- Historial del thread ---');
|
|
278
|
+
for (const m of prevMessages) {
|
|
279
|
+
const who = m.direction === 'out' ? 'Assistant' : m.from_address;
|
|
280
|
+
parts.push(`[${who}]`);
|
|
281
|
+
parts.push(m.body || '');
|
|
282
|
+
parts.push('');
|
|
283
|
+
}
|
|
284
|
+
parts.push('--- Fin del historial ---');
|
|
285
|
+
parts.push('');
|
|
286
|
+
}
|
|
287
|
+
parts.push('--- Mensaje actual del usuario ---');
|
|
288
|
+
parts.push(opts.newBody);
|
|
289
|
+
parts.push('--- Fin del mensaje ---');
|
|
290
|
+
parts.push('');
|
|
291
|
+
parts.push(`Responde al usuario. Tu respuesta sera enviada como reply al thread. No incluyas headers, From/To, ni firmas — el sistema las agrega. Escribi solo el cuerpo de la respuesta, en texto plano, tono directo y util. Usa las tools MCP que necesites.`);
|
|
292
|
+
return parts.join('\n');
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=mail-ingester.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-ingester.js","sourceRoot":"","sources":["../../core-gateway/mail-ingester.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves an inbound sender email address to a company. This is the
|
|
3
|
+
* allowlist: only mails from addresses associated with a company in the
|
|
4
|
+
* system get processed. Anything else is dropped (treated as spam).
|
|
5
|
+
*
|
|
6
|
+
* Lookup order:
|
|
7
|
+
* 1. `companies.contact_email` (exact match, case-insensitive)
|
|
8
|
+
* 2. `profiles.email` joined through `company_users`
|
|
9
|
+
*
|
|
10
|
+
* Returns the first match or null.
|
|
11
|
+
*/
|
|
12
|
+
export interface RouteResult {
|
|
13
|
+
companyId: string;
|
|
14
|
+
userId: string | null;
|
|
15
|
+
via: 'company_contact' | 'profile';
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveCompanyByEmail(email: string): Promise<RouteResult | null>;
|
|
18
|
+
//# sourceMappingURL=mail-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-router.d.ts","sourceRoot":"","sources":["../../core-gateway/mail-router.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,GAAG,EAAE,iBAAiB,GAAG,SAAS,CAAA;CACnC;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoCtF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getSupabase } from './supabase.js';
|
|
2
|
+
export async function resolveCompanyByEmail(email) {
|
|
3
|
+
const db = getSupabase();
|
|
4
|
+
const normalized = email.trim().toLowerCase();
|
|
5
|
+
if (!normalized)
|
|
6
|
+
return null;
|
|
7
|
+
// 1. Company contact_email
|
|
8
|
+
const { data: company } = await db
|
|
9
|
+
.from('companies')
|
|
10
|
+
.select('id, contact_email')
|
|
11
|
+
.ilike('contact_email', normalized)
|
|
12
|
+
.limit(1)
|
|
13
|
+
.maybeSingle();
|
|
14
|
+
if (company) {
|
|
15
|
+
return { companyId: company.id, userId: null, via: 'company_contact' };
|
|
16
|
+
}
|
|
17
|
+
// 2. Profile email → company_users
|
|
18
|
+
const { data: profile } = await db
|
|
19
|
+
.from('profiles')
|
|
20
|
+
.select('id, email')
|
|
21
|
+
.ilike('email', normalized)
|
|
22
|
+
.limit(1)
|
|
23
|
+
.maybeSingle();
|
|
24
|
+
if (profile) {
|
|
25
|
+
const { data: cu } = await db
|
|
26
|
+
.from('company_users')
|
|
27
|
+
.select('company_id, user_id')
|
|
28
|
+
.eq('user_id', profile.id)
|
|
29
|
+
.limit(1)
|
|
30
|
+
.maybeSingle();
|
|
31
|
+
if (cu) {
|
|
32
|
+
return { companyId: cu.company_id, userId: cu.user_id, via: 'profile' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=mail-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-router.js","sourceRoot":"","sources":["../../core-gateway/mail-router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAoB3C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAa;IACvD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;IACxB,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC7C,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAE5B,2BAA2B;IAC3B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE;SAC/B,IAAI,CAAC,WAAW,CAAC;SACjB,MAAM,CAAC,mBAAmB,CAAC;SAC3B,KAAK,CAAC,eAAe,EAAE,UAAU,CAAC;SAClC,KAAK,CAAC,CAAC,CAAC;SACR,WAAW,EAAE,CAAA;IAChB,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,EAAE,CAAA;IACxE,CAAC;IAED,mCAAmC;IACnC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE;SAC/B,IAAI,CAAC,UAAU,CAAC;SAChB,MAAM,CAAC,WAAW,CAAC;SACnB,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC;SAC1B,KAAK,CAAC,CAAC,CAAC;SACR,WAAW,EAAE,CAAA;IAChB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE;aAC1B,IAAI,CAAC,eAAe,CAAC;aACrB,MAAM,CAAC,qBAAqB,CAAC;aAC7B,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;aACzB,KAAK,CAAC,CAAC,CAAC;aACR,WAAW,EAAE,CAAA;QAChB,IAAI,EAAE,EAAE,CAAC;YACP,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;QACzE,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mail thread + message persistence. The "state" of the email-as-chat
|
|
3
|
+
* channel: threads map to Claude CLI session_keys so back-and-forth replies
|
|
4
|
+
* resume context automatically, and messages let us dedup inbound by
|
|
5
|
+
* Message-ID and find parents via In-Reply-To.
|
|
6
|
+
*/
|
|
7
|
+
export interface MailThread {
|
|
8
|
+
id: string;
|
|
9
|
+
company_id: string;
|
|
10
|
+
subject: string | null;
|
|
11
|
+
session_key: string;
|
|
12
|
+
initiated_by: 'in' | 'out';
|
|
13
|
+
source_task_id: string | null;
|
|
14
|
+
external_address: string;
|
|
15
|
+
closed: boolean;
|
|
16
|
+
last_activity_at: string;
|
|
17
|
+
}
|
|
18
|
+
export interface MailMessage {
|
|
19
|
+
id: string;
|
|
20
|
+
thread_id: string;
|
|
21
|
+
company_id: string;
|
|
22
|
+
direction: 'in' | 'out';
|
|
23
|
+
message_id: string;
|
|
24
|
+
in_reply_to: string | null;
|
|
25
|
+
from_address: string;
|
|
26
|
+
to_address: string;
|
|
27
|
+
subject: string | null;
|
|
28
|
+
body: string | null;
|
|
29
|
+
run_id: string | null;
|
|
30
|
+
created_at: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* RFC 5322 Message-ID generator. Format: <proto-{uuid}@{domain}>.
|
|
34
|
+
* Must be stable and unique so both outbound (we set it) and inbound
|
|
35
|
+
* dedup (we look it up) point at the same row.
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateMessageId(domain?: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Look up a thread by one of its message IDs (for inbound reply routing).
|
|
40
|
+
*/
|
|
41
|
+
export declare function findThreadByMessageId(messageId: string): Promise<MailThread | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Dedup check: has this Message-ID already been stored?
|
|
44
|
+
*/
|
|
45
|
+
export declare function isMessageIdProcessed(messageId: string): Promise<boolean>;
|
|
46
|
+
interface CreateThreadOpts {
|
|
47
|
+
companyId: string;
|
|
48
|
+
subject: string | null;
|
|
49
|
+
initiatedBy: 'in' | 'out';
|
|
50
|
+
sourceTaskId?: string | null;
|
|
51
|
+
externalAddress: string;
|
|
52
|
+
sessionKey?: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function createThread(opts: CreateThreadOpts): Promise<MailThread>;
|
|
55
|
+
interface RecordMessageOpts {
|
|
56
|
+
threadId: string;
|
|
57
|
+
companyId: string;
|
|
58
|
+
direction: 'in' | 'out';
|
|
59
|
+
messageId: string;
|
|
60
|
+
inReplyTo?: string | null;
|
|
61
|
+
fromAddress: string;
|
|
62
|
+
toAddress: string;
|
|
63
|
+
subject?: string | null;
|
|
64
|
+
body?: string | null;
|
|
65
|
+
runId?: string | null;
|
|
66
|
+
}
|
|
67
|
+
export declare function recordMessage(opts: RecordMessageOpts): Promise<MailMessage>;
|
|
68
|
+
/**
|
|
69
|
+
* Fetch prior messages in a thread ordered chronologically — used to build
|
|
70
|
+
* the conversation history prompt for the agent on inbound replies.
|
|
71
|
+
*/
|
|
72
|
+
export declare function listThreadMessages(threadId: string, limit?: number): Promise<MailMessage[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Strip "Re: " / "Fwd: " prefixes so the thread subject stays stable.
|
|
75
|
+
*/
|
|
76
|
+
export declare function normalizeSubject(subject: string | null | undefined): string | null;
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=mail-threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-threads.d.ts","sourceRoot":"","sources":["../../core-gateway/mail-threads.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,IAAI,GAAG,KAAK,CAAA;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,gBAAgB,EAAE,MAAM,CAAA;IACxB,MAAM,EAAE,OAAO,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,IAAI,GAAG,KAAK,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,SAAU,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAUzF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ9E;AAED,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,IAAI,GAAG,KAAK,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiB9E;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,IAAI,GAAG,KAAK,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAoBjF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAS7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGlF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { getSupabase } from './supabase.js';
|
|
3
|
+
/**
|
|
4
|
+
* RFC 5322 Message-ID generator. Format: <proto-{uuid}@{domain}>.
|
|
5
|
+
* Must be stable and unique so both outbound (we set it) and inbound
|
|
6
|
+
* dedup (we look it up) point at the same row.
|
|
7
|
+
*/
|
|
8
|
+
export function generateMessageId(domain = 'proto') {
|
|
9
|
+
return `<proto-${randomUUID()}@${domain}>`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Look up a thread by one of its message IDs (for inbound reply routing).
|
|
13
|
+
*/
|
|
14
|
+
export async function findThreadByMessageId(messageId) {
|
|
15
|
+
const db = getSupabase();
|
|
16
|
+
const { data } = await db
|
|
17
|
+
.from('mail_messages')
|
|
18
|
+
.select('thread_id, mail_threads!inner(*)')
|
|
19
|
+
.eq('message_id', messageId)
|
|
20
|
+
.maybeSingle();
|
|
21
|
+
// Supabase returns nested relation as object
|
|
22
|
+
const thread = data?.mail_threads;
|
|
23
|
+
return thread ?? null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Dedup check: has this Message-ID already been stored?
|
|
27
|
+
*/
|
|
28
|
+
export async function isMessageIdProcessed(messageId) {
|
|
29
|
+
const db = getSupabase();
|
|
30
|
+
const { data } = await db
|
|
31
|
+
.from('mail_messages')
|
|
32
|
+
.select('id')
|
|
33
|
+
.eq('message_id', messageId)
|
|
34
|
+
.maybeSingle();
|
|
35
|
+
return !!data;
|
|
36
|
+
}
|
|
37
|
+
export async function createThread(opts) {
|
|
38
|
+
const db = getSupabase();
|
|
39
|
+
const sessionKey = opts.sessionKey || `mail-thread-${randomUUID()}`;
|
|
40
|
+
const { data, error } = await db
|
|
41
|
+
.from('mail_threads')
|
|
42
|
+
.insert({
|
|
43
|
+
company_id: opts.companyId,
|
|
44
|
+
subject: normalizeSubject(opts.subject),
|
|
45
|
+
session_key: sessionKey,
|
|
46
|
+
initiated_by: opts.initiatedBy,
|
|
47
|
+
source_task_id: opts.sourceTaskId ?? null,
|
|
48
|
+
external_address: opts.externalAddress,
|
|
49
|
+
})
|
|
50
|
+
.select('*')
|
|
51
|
+
.single();
|
|
52
|
+
if (error || !data)
|
|
53
|
+
throw new Error(`createThread failed: ${error?.message}`);
|
|
54
|
+
return data;
|
|
55
|
+
}
|
|
56
|
+
export async function recordMessage(opts) {
|
|
57
|
+
const db = getSupabase();
|
|
58
|
+
const { data, error } = await db
|
|
59
|
+
.from('mail_messages')
|
|
60
|
+
.insert({
|
|
61
|
+
thread_id: opts.threadId,
|
|
62
|
+
company_id: opts.companyId,
|
|
63
|
+
direction: opts.direction,
|
|
64
|
+
message_id: opts.messageId,
|
|
65
|
+
in_reply_to: opts.inReplyTo ?? null,
|
|
66
|
+
from_address: opts.fromAddress,
|
|
67
|
+
to_address: opts.toAddress,
|
|
68
|
+
subject: opts.subject ?? null,
|
|
69
|
+
body: opts.body ?? null,
|
|
70
|
+
run_id: opts.runId ?? null,
|
|
71
|
+
})
|
|
72
|
+
.select('*')
|
|
73
|
+
.single();
|
|
74
|
+
if (error || !data)
|
|
75
|
+
throw new Error(`recordMessage failed: ${error?.message}`);
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fetch prior messages in a thread ordered chronologically — used to build
|
|
80
|
+
* the conversation history prompt for the agent on inbound replies.
|
|
81
|
+
*/
|
|
82
|
+
export async function listThreadMessages(threadId, limit = 20) {
|
|
83
|
+
const db = getSupabase();
|
|
84
|
+
const { data } = await db
|
|
85
|
+
.from('mail_messages')
|
|
86
|
+
.select('*')
|
|
87
|
+
.eq('thread_id', threadId)
|
|
88
|
+
.order('created_at', { ascending: true })
|
|
89
|
+
.limit(limit);
|
|
90
|
+
return (data || []);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Strip "Re: " / "Fwd: " prefixes so the thread subject stays stable.
|
|
94
|
+
*/
|
|
95
|
+
export function normalizeSubject(subject) {
|
|
96
|
+
if (!subject)
|
|
97
|
+
return null;
|
|
98
|
+
return subject.replace(/^\s*(re|fwd|fw):\s*/gi, '').trim() || null;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=mail-threads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-threads.js","sourceRoot":"","sources":["../../core-gateway/mail-threads.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../core-gateway/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAI9F"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple in-memory rate limiter per company.
|
|
3
|
+
* Max 20 messages per company per hour.
|
|
4
|
+
*/
|
|
5
|
+
const WINDOW_MS = 60 * 60 * 1000; // 1 hour
|
|
6
|
+
const MAX_REQUESTS = 20;
|
|
7
|
+
const windows = new Map();
|
|
8
|
+
export function checkRateLimit(_companyId) {
|
|
9
|
+
// Disabled — see windows/MAX_REQUESTS above for the original gate.
|
|
10
|
+
// Re-enable when multi-tenant launch needs throttling.
|
|
11
|
+
return { allowed: true };
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../core-gateway/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,SAAS;AAC1C,MAAM,YAAY,GAAG,EAAE,CAAA;AAEvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4C,CAAA;AAEnE,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,mEAAmE;IACnE,uDAAuD;IACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Skill {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string | null;
|
|
4
|
+
mcp_tools: string[];
|
|
5
|
+
depends: string[];
|
|
6
|
+
filePath: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Agent {
|
|
9
|
+
name: string;
|
|
10
|
+
filePath: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function loadSkills(): Skill[];
|
|
13
|
+
export declare function loadAgents(): Agent[];
|
|
14
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../core-gateway/registry.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAgED,wBAAgB,UAAU,IAAI,KAAK,EAAE,CAGpC;AAED,wBAAgB,UAAU,IAAI,KAAK,EAAE,CAGpC"}
|