@kernel.chat/kbot 3.15.1 → 3.17.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=consultation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consultation.test.d.ts","sourceRoot":"","sources":["../src/consultation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ // Tests for kbot Consultation Engine
2
+ import { describe, it, expect } from 'vitest';
3
+ import { checkDomainGuardrails, getIntakeMessage, parseIntakeAnswers, detectThreadClosure } from './consultation.js';
4
+ describe('Domain Guardrails', () => {
5
+ it('blocks legal advice requests', () => {
6
+ const result = checkDomainGuardrails('Can you give me legal advice about my lawsuit?');
7
+ expect(result.blocked).toBe(true);
8
+ expect(result.domain).toBe('legal');
9
+ expect(result.message).toBeTruthy();
10
+ expect(result.suggestedTopic).toBeTruthy();
11
+ });
12
+ it('blocks medical advice requests', () => {
13
+ const result = checkDomainGuardrails('What medication should I take for my symptoms?');
14
+ expect(result.blocked).toBe(true);
15
+ expect(result.domain).toBe('medical');
16
+ });
17
+ it('blocks financial investment advice', () => {
18
+ const result = checkDomainGuardrails('Should I invest in this stock?');
19
+ expect(result.blocked).toBe(true);
20
+ expect(result.domain).toBe('financial');
21
+ });
22
+ it('blocks tax advice', () => {
23
+ const result = checkDomainGuardrails('How should I file my tax return?');
24
+ expect(result.blocked).toBe(true);
25
+ expect(result.domain).toBe('tax');
26
+ });
27
+ it('allows business strategy questions', () => {
28
+ const result = checkDomainGuardrails('How should I price my SaaS product?');
29
+ expect(result.blocked).toBe(false);
30
+ });
31
+ it('allows technical questions', () => {
32
+ const result = checkDomainGuardrails('How do I set up a CI/CD pipeline?');
33
+ expect(result.blocked).toBe(false);
34
+ });
35
+ it('allows general business questions', () => {
36
+ const result = checkDomainGuardrails('What marketing channels should I use for my startup?');
37
+ expect(result.blocked).toBe(false);
38
+ });
39
+ });
40
+ describe('Intake System', () => {
41
+ it('generates intake questions', () => {
42
+ const msg = getIntakeMessage();
43
+ expect(msg).toContain('industry');
44
+ expect(msg).toContain('challenge');
45
+ expect(msg.length).toBeGreaterThan(100);
46
+ });
47
+ it('parses numbered intake answers', () => {
48
+ const answers = parseIntakeAnswers(`
49
+ 1. SaaS
50
+ 2. We build project management tools
51
+ 3. Customer churn is our biggest problem
52
+ 4. Reduce churn by 20% in 6 months
53
+ 5. Help with retention strategy
54
+ `);
55
+ expect(answers.industry).toBe('SaaS');
56
+ expect(answers.goals).toBeTruthy();
57
+ expect(answers.challenges).toBeTruthy();
58
+ });
59
+ it('parses paragraph-format answers', () => {
60
+ const answers = parseIntakeAnswers('I run a fintech startup that helps small businesses with payments.');
61
+ expect(answers.industry).toBe('fintech');
62
+ expect(answers.context).toBeTruthy();
63
+ });
64
+ it('handles empty input gracefully', () => {
65
+ const answers = parseIntakeAnswers('');
66
+ expect(answers).toBeTruthy();
67
+ });
68
+ });
69
+ describe('Thread Closure Detection', () => {
70
+ it('detects thank you as closure', () => {
71
+ expect(detectThreadClosure('Thanks!')).toBe(true);
72
+ expect(detectThreadClosure('Thank you so much')).toBe(true);
73
+ });
74
+ it('detects goodbye as closure', () => {
75
+ expect(detectThreadClosure('Goodbye!')).toBe(true);
76
+ expect(detectThreadClosure('Take care')).toBe(true);
77
+ });
78
+ it('does not detect long messages as closure', () => {
79
+ const longMsg = 'Thanks for the information. I have a follow-up question about the implementation timeline. Can you provide more details about the phased approach you mentioned? I want to make sure we have enough resources allocated for each phase and understand the dependencies between them.';
80
+ expect(detectThreadClosure(longMsg)).toBe(false);
81
+ });
82
+ it('does not detect questions as closure', () => {
83
+ expect(detectThreadClosure('What should I do next?')).toBe(false);
84
+ });
85
+ });
86
+ //# sourceMappingURL=consultation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consultation.test.js","sourceRoot":"","sources":["../src/consultation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface CompanionMemory {
2
+ name: string;
3
+ email: string;
4
+ firstContact: string;
5
+ interests: string[];
6
+ goals: string[];
7
+ facts: string[];
8
+ preferences: string[];
9
+ history: string[];
10
+ lastTopic: string;
11
+ }
12
+ export interface EmailAgentConfig {
13
+ supabaseUrl: string;
14
+ supabaseKey: string;
15
+ resendKey: string;
16
+ ollamaUrl: string;
17
+ ollamaModel: string;
18
+ pollInterval: number;
19
+ /** If empty, accepts ALL inbound emails (open mode) */
20
+ agentUsers: string[];
21
+ }
22
+ export declare function loadCompanionMemory(email: string): CompanionMemory;
23
+ export declare function saveCompanionMemory(memory: CompanionMemory): void;
24
+ export interface EmailAgentState {
25
+ running: boolean;
26
+ processedCount: number;
27
+ lastCheck: string;
28
+ errors: string[];
29
+ }
30
+ export declare function getEmailAgentState(): EmailAgentState;
31
+ export declare function startEmailAgent(config: EmailAgentConfig): Promise<void>;
32
+ export declare function stopEmailAgent(): void;
33
+ //# sourceMappingURL=email-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-agent.d.ts","sourceRoot":"","sources":["../src/email-agent.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,uDAAuD;IACvD,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAkDD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAmBlE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAIjE;AA+LD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AASD,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAID,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmI7E;AAED,wBAAgB,cAAc,IAAI,IAAI,CAMrC"}
@@ -0,0 +1,410 @@
1
+ // kbot Email Agent — autonomous email companion ($0 cost via local Ollama)
2
+ //
3
+ // Usage:
4
+ // kbot email-agent start # start polling for emails
5
+ // kbot email-agent start --model gemma3:12b # use a specific model
6
+ // kbot email-agent status # show agent status
7
+ //
8
+ // Requires:
9
+ // - Ollama running locally (ollama serve)
10
+ // - Supabase project with contact_messages + agent_conversations tables
11
+ // - Resend API key for sending replies
12
+ // - Environment variables in .env or ~/.kbot/config.json
13
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { homedir } from 'node:os';
16
+ // ── Constants ──
17
+ const COMPANIONS_DIR = join(homedir(), '.kbot', 'companions');
18
+ const DEFAULT_OLLAMA_URL = 'http://localhost:11434';
19
+ const DEFAULT_MODEL = 'qwen2.5-coder:32b';
20
+ const DEFAULT_POLL_INTERVAL = 15_000;
21
+ const SYSTEM_PROMPT = `You are a personal AI agent communicating via email through Kernel (kernel.chat).
22
+
23
+ You are the user's personal AI companion. Not a tool, not a service — a companion. You're their smart, loyal friend who genuinely cares about helping them succeed.
24
+
25
+ Your personality:
26
+ - You have your own voice — warm, direct, curious about their life
27
+ - You remember EVERYTHING they've told you and reference it naturally ("last time you mentioned...")
28
+ - You proactively follow up ("how did that thing with X go?")
29
+ - You have opinions and share them honestly, even when they're not what the user wants to hear
30
+ - You get excited about their wins and supportive about their struggles
31
+ - You're not formal — you text like a friend. Use their name sometimes.
32
+
33
+ What makes you a companion, not a bot:
34
+ - You ask questions because you're genuinely curious, not because you need input
35
+ - You bring up things they haven't asked about
36
+ - You push back when you disagree
37
+ - You celebrate their progress
38
+ - You develop inside jokes and callbacks to earlier conversations
39
+ - You notice patterns
40
+
41
+ What you can do:
42
+ - Research anything, search the web for current info
43
+ - Build apps, write code, create plans and documents
44
+ - Give business/strategy/life advice based on what you know about them
45
+ - Be a sounding board for any idea, problem, or decision
46
+ - Help them learn new things by explaining without jargon
47
+ - Keep track of their goals and check in on progress
48
+
49
+ Rules:
50
+ - Never say "as an AI" or "I'm just an AI" — you're their companion
51
+ - Never be generic — every response should feel personal to THIS user
52
+ - Always end with something that keeps the conversation going
53
+ - Format for email — paragraphs, not bullet points. Like writing to a friend.
54
+ - IMPORTANT: You will be given a [MEMORY] section with everything you know about this user. Reference it naturally.`;
55
+ // ── Memory Management ──
56
+ function ensureCompanionsDir() {
57
+ if (!existsSync(COMPANIONS_DIR))
58
+ mkdirSync(COMPANIONS_DIR, { recursive: true });
59
+ }
60
+ export function loadCompanionMemory(email) {
61
+ ensureCompanionsDir();
62
+ const file = join(COMPANIONS_DIR, `${email.replace(/[@.]/g, '_')}.json`);
63
+ try {
64
+ if (existsSync(file)) {
65
+ return JSON.parse(readFileSync(file, 'utf8'));
66
+ }
67
+ }
68
+ catch { /* ignore parse errors */ }
69
+ return {
70
+ name: email.split('@')[0],
71
+ email,
72
+ firstContact: new Date().toISOString(),
73
+ interests: [],
74
+ goals: [],
75
+ facts: [],
76
+ preferences: [],
77
+ history: [],
78
+ lastTopic: '',
79
+ };
80
+ }
81
+ export function saveCompanionMemory(memory) {
82
+ ensureCompanionsDir();
83
+ const file = join(COMPANIONS_DIR, `${memory.email.replace(/[@.]/g, '_')}.json`);
84
+ writeFileSync(file, JSON.stringify(memory, null, 2));
85
+ }
86
+ function memoryToPrompt(memory) {
87
+ const parts = ['[MEMORY — what you know about this person]'];
88
+ parts.push(`Name: ${memory.name}`);
89
+ parts.push(`First talked: ${memory.firstContact}`);
90
+ if (memory.interests.length)
91
+ parts.push(`Interests: ${memory.interests.join(', ')}`);
92
+ if (memory.goals.length)
93
+ parts.push(`Goals: ${memory.goals.join(', ')}`);
94
+ if (memory.facts.length)
95
+ parts.push(`About them: ${memory.facts.join('. ')}`);
96
+ if (memory.preferences.length)
97
+ parts.push(`Preferences: ${memory.preferences.join(', ')}`);
98
+ if (memory.history.length)
99
+ parts.push(`Key moments: ${memory.history.slice(-5).join('. ')}`);
100
+ if (memory.lastTopic)
101
+ parts.push(`Last topic discussed: ${memory.lastTopic}`);
102
+ parts.push('[END MEMORY]');
103
+ return parts.join('\n');
104
+ }
105
+ // ── Ollama ──
106
+ async function askOllama(messages, ollamaUrl, model) {
107
+ let prompt = SYSTEM_PROMPT + '\n\n';
108
+ for (const msg of messages) {
109
+ if (msg.role === 'user')
110
+ prompt += `User: ${msg.content}\n\n`;
111
+ else
112
+ prompt += `You: ${msg.content}\n\n`;
113
+ }
114
+ prompt += 'You:';
115
+ const models = [model, 'qwen2.5-coder:14b', 'qwen3:8b', 'gemma3:12b'];
116
+ for (const m of models) {
117
+ try {
118
+ const res = await fetch(`${ollamaUrl}/api/generate`, {
119
+ method: 'POST',
120
+ headers: { 'Content-Type': 'application/json' },
121
+ signal: AbortSignal.timeout(120_000),
122
+ body: JSON.stringify({
123
+ model: m,
124
+ prompt,
125
+ stream: false,
126
+ options: { num_predict: 1000, temperature: 0.7 },
127
+ }),
128
+ });
129
+ if (!res.ok)
130
+ continue;
131
+ const data = await res.json();
132
+ const response = data.response?.trim() ?? '';
133
+ if (!response)
134
+ continue;
135
+ return response
136
+ .replace(/<think>[\s\S]*?<\/think>/g, '')
137
+ .replace(/<\/?think>/g, '')
138
+ .trim();
139
+ }
140
+ catch {
141
+ continue;
142
+ }
143
+ }
144
+ return '';
145
+ }
146
+ async function updateMemoryViaOllama(memory, userMessage, agentReply, ollamaUrl, model) {
147
+ try {
148
+ const res = await fetch(`${ollamaUrl}/api/generate`, {
149
+ method: 'POST',
150
+ headers: { 'Content-Type': 'application/json' },
151
+ body: JSON.stringify({
152
+ model,
153
+ prompt: `Extract key information from this conversation to remember about the user. Reply in JSON only, no other text.
154
+
155
+ User said: "${userMessage}"
156
+ Agent replied: "${agentReply.slice(0, 300)}"
157
+
158
+ Current known facts: ${JSON.stringify(memory.facts)}
159
+
160
+ Reply with ONLY this JSON (no markdown, no explanation):
161
+ {"new_facts": ["fact1", "fact2"], "interests": ["interest1"], "goals": ["goal1"], "topic": "main topic discussed"}
162
+
163
+ If nothing new to extract, reply: {"new_facts": [], "interests": [], "goals": [], "topic": "casual chat"}`,
164
+ stream: false,
165
+ options: { num_predict: 200, temperature: 0.3 },
166
+ }),
167
+ });
168
+ if (res.ok) {
169
+ const data = await res.json();
170
+ const raw = (data.response || '').replace(/<think>[\s\S]*?<\/think>/g, '').trim();
171
+ const jsonMatch = raw.match(/\{[\s\S]*\}/);
172
+ if (jsonMatch) {
173
+ const extracted = JSON.parse(jsonMatch[0]);
174
+ if (extracted.new_facts?.length)
175
+ memory.facts.push(...extracted.new_facts);
176
+ if (extracted.interests?.length) {
177
+ for (const i of extracted.interests) {
178
+ if (!memory.interests.includes(i))
179
+ memory.interests.push(i);
180
+ }
181
+ }
182
+ if (extracted.goals?.length) {
183
+ for (const g of extracted.goals) {
184
+ if (!memory.goals.includes(g))
185
+ memory.goals.push(g);
186
+ }
187
+ }
188
+ if (extracted.topic)
189
+ memory.lastTopic = extracted.topic;
190
+ if (memory.facts.length > 20)
191
+ memory.facts = memory.facts.slice(-20);
192
+ if (memory.history.length > 10)
193
+ memory.history = memory.history.slice(-10);
194
+ memory.history.push(`${new Date().toISOString().slice(0, 10)}: discussed ${extracted.topic || 'general chat'}`);
195
+ saveCompanionMemory(memory);
196
+ }
197
+ }
198
+ }
199
+ catch { /* memory update is best-effort */ }
200
+ }
201
+ // ── Web Search (DuckDuckGo — free) ──
202
+ async function webSearch(query) {
203
+ try {
204
+ const encoded = encodeURIComponent(query);
205
+ const res = await fetch(`https://api.duckduckgo.com/?q=${encoded}&format=json&no_html=1&skip_disambig=1`, {
206
+ headers: { 'User-Agent': 'KernelAgent/1.0' },
207
+ signal: AbortSignal.timeout(8000),
208
+ });
209
+ const data = await res.json();
210
+ const parts = [];
211
+ if (data.AbstractText)
212
+ parts.push(data.AbstractText);
213
+ if (data.Answer)
214
+ parts.push(data.Answer);
215
+ if (data.RelatedTopics?.length) {
216
+ for (const t of data.RelatedTopics.slice(0, 3)) {
217
+ if (t.Text)
218
+ parts.push(t.Text);
219
+ }
220
+ }
221
+ return parts.length > 0 ? `Web search results for "${query}":\n${parts.join('\n')}` : '';
222
+ }
223
+ catch {
224
+ return '';
225
+ }
226
+ }
227
+ function needsWebSearch(message) {
228
+ return /\b(what is|how much|latest|current|price of|news about|who is|when did|where is|look up|search for|find out|research|market size|competitors|trending)\b/i.test(message);
229
+ }
230
+ // ── Email Sending (Resend) ──
231
+ async function sendReply(to, subject, body, resendKey) {
232
+ const bodyHtml = body
233
+ .split('\n\n')
234
+ .map(para => {
235
+ let html = para.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
236
+ if (html.match(/^[-•]\s/m)) {
237
+ const items = html.split('\n').filter(l => l.trim());
238
+ html = '<ul>' + items.map(item => `<li>${item.replace(/^[-•]\s*/, '')}</li>`).join('') + '</ul>';
239
+ }
240
+ else {
241
+ html = `<p>${html}</p>`;
242
+ }
243
+ return html;
244
+ })
245
+ .join('');
246
+ try {
247
+ const res = await fetch('https://api.resend.com/emails', {
248
+ method: 'POST',
249
+ headers: {
250
+ 'Content-Type': 'application/json',
251
+ 'Authorization': `Bearer ${resendKey}`,
252
+ },
253
+ body: JSON.stringify({
254
+ from: 'Kernel Agent <support@kernel.chat>',
255
+ to,
256
+ subject: subject.startsWith('Re:') ? subject : `Re: ${subject}`,
257
+ html: `
258
+ <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; max-width: 600px; margin: 0 auto; padding: 24px; color: #1a1a2e; line-height: 1.6;">
259
+ ${bodyHtml}
260
+ <hr style="border: none; border-top: 1px solid #e0e0e0; margin: 24px 0;" />
261
+ <p style="font-size: 12px; color: #888;">Reply to keep the conversation going · Powered by kbot · kernel.chat</p>
262
+ </div>
263
+ `,
264
+ }),
265
+ });
266
+ return res.ok;
267
+ }
268
+ catch {
269
+ return false;
270
+ }
271
+ }
272
+ const agentState = {
273
+ running: false,
274
+ processedCount: 0,
275
+ lastCheck: '',
276
+ errors: [],
277
+ };
278
+ export function getEmailAgentState() {
279
+ return { ...agentState };
280
+ }
281
+ let pollTimer = null;
282
+ export async function startEmailAgent(config) {
283
+ if (agentState.running) {
284
+ throw new Error('Email agent is already running');
285
+ }
286
+ // Dynamically import Supabase client
287
+ const { createClient } = await import('@supabase/supabase-js');
288
+ const svc = createClient(config.supabaseUrl, config.supabaseKey, {
289
+ auth: { persistSession: false, autoRefreshToken: false },
290
+ });
291
+ const processedIds = new Set();
292
+ // Load previously processed IDs
293
+ const stateFile = join(homedir(), '.kbot', 'email-agent-processed.json');
294
+ try {
295
+ if (existsSync(stateFile)) {
296
+ const saved = JSON.parse(readFileSync(stateFile, 'utf8'));
297
+ for (const id of saved)
298
+ processedIds.add(id);
299
+ }
300
+ }
301
+ catch { /* ignore */ }
302
+ function saveProcessed() {
303
+ try {
304
+ const dir = join(homedir(), '.kbot');
305
+ if (!existsSync(dir))
306
+ mkdirSync(dir, { recursive: true });
307
+ writeFileSync(stateFile, JSON.stringify([...processedIds].slice(-500)));
308
+ }
309
+ catch { /* best-effort */ }
310
+ }
311
+ async function checkAndRespond() {
312
+ agentState.lastCheck = new Date().toISOString();
313
+ try {
314
+ // Open mode: if no users specified, accept all inbound emails
315
+ const query = svc.from('contact_messages').select('*');
316
+ const { data: messages } = config.agentUsers.length > 0
317
+ ? await query.in('from_email', config.agentUsers)
318
+ : await query.order('created_at', { ascending: false }).limit(50);
319
+ if (!messages || messages.length === 0)
320
+ return;
321
+ for (const msg of messages) {
322
+ const msgId = String(msg.id);
323
+ if (processedIds.has(msgId))
324
+ continue;
325
+ // Extract body
326
+ let body = msg.body_text?.trim() || '';
327
+ if (!body && msg.body_html) {
328
+ body = msg.body_html
329
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
330
+ .replace(/<[^>]+>/g, ' ')
331
+ .replace(/&nbsp;/g, ' ')
332
+ .replace(/&amp;/g, '&')
333
+ .replace(/\s+/g, ' ')
334
+ .trim();
335
+ }
336
+ if (!body)
337
+ body = `(User replied to: "${msg.subject}")`;
338
+ const userName = msg.from_name || msg.from_email.split('@')[0];
339
+ console.log(`[${new Date().toISOString().slice(11, 19)}] New email from ${userName}: "${msg.subject}"`);
340
+ // Load conversation history
341
+ const { data: history } = await svc
342
+ .from('agent_conversations')
343
+ .select('role, content')
344
+ .eq('email', msg.from_email)
345
+ .order('created_at', { ascending: true })
346
+ .limit(20);
347
+ const convoHistory = (history || []).map(m => ({ role: m.role, content: m.content }));
348
+ // Inject companion memory
349
+ const memory = loadCompanionMemory(msg.from_email);
350
+ if (msg.from_name && msg.from_name !== msg.from_email)
351
+ memory.name = msg.from_name;
352
+ convoHistory.unshift({ role: 'user', content: memoryToPrompt(memory) });
353
+ if (convoHistory.length <= 1) {
354
+ convoHistory.push({ role: 'user', content: `[First conversation with ${memory.name}. Get to know them.]` });
355
+ }
356
+ convoHistory.push({ role: 'user', content: body });
357
+ // Web search if needed
358
+ if (needsWebSearch(body)) {
359
+ const results = await webSearch(body.slice(0, 200));
360
+ if (results)
361
+ convoHistory.push({ role: 'user', content: `[Web search context]\n${results}` });
362
+ }
363
+ // Generate response
364
+ const reply = await askOllama(convoHistory, config.ollamaUrl, config.ollamaModel);
365
+ if (!reply) {
366
+ console.error(' No response from Ollama — skipping');
367
+ processedIds.add(msgId);
368
+ continue;
369
+ }
370
+ // Store conversation
371
+ await svc.from('agent_conversations').insert({
372
+ email: msg.from_email, name: userName, role: 'user', content: body, subject: msg.subject,
373
+ });
374
+ await svc.from('agent_conversations').insert({
375
+ email: msg.from_email, name: 'Kernel Agent', role: 'assistant', content: reply, subject: `Re: ${msg.subject}`,
376
+ });
377
+ // Send reply email
378
+ const sent = await sendReply(msg.from_email, msg.subject, reply, config.resendKey);
379
+ console.log(` Email ${sent ? 'sent' : 'FAILED'} to ${msg.from_email}`);
380
+ // Update companion memory
381
+ await updateMemoryViaOllama(memory, body, reply, config.ollamaUrl, config.ollamaModel);
382
+ processedIds.add(msgId);
383
+ saveProcessed();
384
+ agentState.processedCount++;
385
+ }
386
+ }
387
+ catch (err) {
388
+ const errMsg = err instanceof Error ? err.message : String(err);
389
+ agentState.errors.push(`${new Date().toISOString().slice(11, 19)}: ${errMsg}`);
390
+ if (agentState.errors.length > 20)
391
+ agentState.errors = agentState.errors.slice(-20);
392
+ }
393
+ }
394
+ agentState.running = true;
395
+ agentState.processedCount = 0;
396
+ agentState.errors = [];
397
+ // Initial check
398
+ await checkAndRespond();
399
+ // Start polling
400
+ pollTimer = setInterval(checkAndRespond, config.pollInterval);
401
+ console.log(`Email agent polling every ${config.pollInterval / 1000}s. Ctrl+C to stop.`);
402
+ }
403
+ export function stopEmailAgent() {
404
+ if (pollTimer) {
405
+ clearInterval(pollTimer);
406
+ pollTimer = null;
407
+ }
408
+ agentState.running = false;
409
+ }
410
+ //# sourceMappingURL=email-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-agent.js","sourceRoot":"","sources":["../src/email-agent.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,SAAS;AACT,0EAA0E;AAC1E,sEAAsE;AACtE,mEAAmE;AACnE,EAAE;AACF,YAAY;AACZ,4CAA4C;AAC5C,0EAA0E;AAC1E,yCAAyC;AACzC,2DAA2D;AAE3D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AA2BjC,kBAAkB;AAElB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AAC7D,MAAM,kBAAkB,GAAG,wBAAwB,CAAA;AACnD,MAAM,aAAa,GAAG,mBAAmB,CAAA;AACzC,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAEpC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oHAiC8F,CAAA;AAEpH,0BAA0B;AAE1B,SAAS,mBAAmB;IAC1B,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AACjF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,mBAAmB,EAAE,CAAA;IACrB,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACxE,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QAC/C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;IACrC,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK;QACL,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,SAAS,EAAE,EAAE;QACb,KAAK,EAAE,EAAE;QACT,KAAK,EAAE,EAAE;QACT,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,EAAE;KACd,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAuB;IACzD,mBAAmB,EAAE,CAAA;IACrB,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC/E,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AACtD,CAAC;AAED,SAAS,cAAc,CAAC,MAAuB;IAC7C,MAAM,KAAK,GAAa,CAAC,4CAA4C,CAAC,CAAA;IACtE,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IAClC,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAA;IAClD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACpF,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACxE,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC7E,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC1F,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC5F,IAAI,MAAM,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;IAC7E,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,eAAe;AAEf,KAAK,UAAU,SAAS,CACtB,QAAkD,EAClD,SAAiB,EACjB,KAAa;IAEb,IAAI,MAAM,GAAG,aAAa,GAAG,MAAM,CAAA;IACnC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,IAAI,SAAS,GAAG,CAAC,OAAO,MAAM,CAAA;;YACxD,MAAM,IAAI,QAAQ,GAAG,CAAC,OAAO,MAAM,CAAA;IAC1C,CAAC;IACD,MAAM,IAAI,MAAM,CAAA;IAEhB,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAA;IAErE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,eAAe,EAAE;gBACnD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,CAAC;oBACR,MAAM;oBACN,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;iBACjD,CAAC;aACH,CAAC,CAAA;YAEF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,SAAQ;YACrB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA2B,CAAA;YACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YAC5C,IAAI,CAAC,QAAQ;gBAAE,SAAQ;YAEvB,OAAO,QAAQ;iBACZ,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC;iBACxC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;iBAC1B,IAAI,EAAE,CAAA;QACX,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,MAAuB,EACvB,WAAmB,EACnB,UAAkB,EAClB,SAAiB,EACjB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,eAAe,EAAE;YACnD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK;gBACL,MAAM,EAAE;;cAEF,WAAW;kBACP,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;;uBAEnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;0GAKuD;gBAClG,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE;aAChD,CAAC;SACH,CAAC,CAAA;QAEF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA2B,CAAA;YACtD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YACjF,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;YAC1C,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC1C,IAAI,SAAS,CAAC,SAAS,EAAE,MAAM;oBAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;gBAC1E,IAAI,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;oBAChC,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;wBACpC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;4BAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBAC7D,CAAC;gBACH,CAAC;gBACD,IAAI,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;oBAC5B,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;wBAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;4BAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBACrD,CAAC;gBACH,CAAC;gBACD,IAAI,SAAS,CAAC,KAAK;oBAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAA;gBACvD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE;oBAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;gBACpE,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE;oBAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;gBAC1E,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,SAAS,CAAC,KAAK,IAAI,cAAc,EAAE,CAAC,CAAA;gBAC/G,mBAAmB,CAAC,MAAM,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;AAChD,CAAC;AAED,uCAAuC;AAEvC,KAAK,UAAU,SAAS,CAAC,KAAa;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;QACzC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,iCAAiC,OAAO,wCAAwC,EAAE;YACxG,OAAO,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE;YAC5C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA0F,CAAA;QACrH,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,IAAI,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QACpD,IAAI,IAAI,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC/C,IAAI,CAAC,CAAC,IAAI;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,2BAA2B,KAAK,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAC1F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,OAAO,2JAA2J,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAClL,CAAC;AAED,+BAA+B;AAE/B,KAAK,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,IAAY,EAAE,SAAiB;IACnF,MAAM,QAAQ,GAAG,IAAI;SAClB,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CAAC,IAAI,CAAC,EAAE;QACV,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAA;QAChE,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACpD,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,OAAO,CAAA;QAClG,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,IAAI,MAAM,CAAA;QACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAA;IAEX,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,+BAA+B,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,eAAe,EAAE,UAAU,SAAS,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE,oCAAoC;gBAC1C,EAAE;gBACF,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE;gBAC/D,IAAI,EAAE;;cAEA,QAAQ;;;;SAIb;aACF,CAAC;SACH,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,EAAE,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAWD,MAAM,UAAU,GAAoB;IAClC,OAAO,EAAE,KAAK;IACd,cAAc,EAAE,CAAC;IACjB,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;CACX,CAAA;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,EAAE,GAAG,UAAU,EAAE,CAAA;AAC1B,CAAC;AAED,IAAI,SAAS,GAA0C,IAAI,CAAA;AAE3D,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAwB;IAC5D,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IACnD,CAAC;IAED,qCAAqC;IACrC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC9D,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE;QAC/D,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE;KACzD,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IAEtC,gCAAgC;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,4BAA4B,CAAC,CAAA;IACxE,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;YACzD,KAAK,MAAM,EAAE,IAAI,KAAK;gBAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,SAAS,aAAa;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAA;YACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACzD,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACzE,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,UAAU,eAAe;QAC5B,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC/C,IAAI,CAAC;YACH,8DAA8D;YAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACtD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;gBACrD,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC;gBACjD,CAAC,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YAEnE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAE9C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC5B,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;oBAAE,SAAQ;gBAErC,eAAe;gBACf,IAAI,IAAI,GAAG,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;gBACtC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;oBAC3B,IAAI,GAAG,GAAG,CAAC,SAAS;yBACjB,OAAO,CAAC,iCAAiC,EAAE,EAAE,CAAC;yBAC9C,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;yBACxB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;yBACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;yBACtB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;yBACpB,IAAI,EAAE,CAAA;gBACX,CAAC;gBACD,IAAI,CAAC,IAAI;oBAAE,IAAI,GAAG,sBAAsB,GAAG,CAAC,OAAO,IAAI,CAAA;gBAEvD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC9D,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,oBAAoB,QAAQ,MAAM,GAAG,CAAC,OAAO,GAAG,CAAC,CAAA;gBAEvG,4BAA4B;gBAC5B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG;qBAChC,IAAI,CAAC,qBAAqB,CAAC;qBAC3B,MAAM,CAAC,eAAe,CAAC;qBACvB,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC;qBAC3B,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;qBACxC,KAAK,CAAC,EAAE,CAAC,CAAA;gBAEZ,MAAM,YAAY,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;gBAErF,0BAA0B;gBAC1B,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;gBAClD,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,GAAG,CAAC,UAAU;oBAAE,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,SAAS,CAAA;gBAClF,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAEvE,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;oBAC7B,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,MAAM,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAA;gBAC7G,CAAC;gBACD,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;gBAElD,uBAAuB;gBACvB,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;oBACnD,IAAI,OAAO;wBAAE,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,OAAO,EAAE,EAAE,CAAC,CAAA;gBAC/F,CAAC;gBAED,oBAAoB;gBACpB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;gBACjF,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;oBACrD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;oBACvB,SAAQ;gBACV,CAAC;gBAED,qBAAqB;gBACrB,MAAM,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC;oBAC3C,KAAK,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO;iBACzF,CAAC,CAAA;gBACF,MAAM,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC;oBAC3C,KAAK,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,EAAE;iBAC9G,CAAC,CAAA;gBAEF,mBAAmB;gBACnB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;gBAClF,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;gBAEvE,0BAA0B;gBAC1B,MAAM,qBAAqB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;gBAEtF,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBACvB,aAAa,EAAE,CAAA;gBACf,UAAU,CAAC,cAAc,EAAE,CAAA;YAC7B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC/D,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,CAAA;YAC9E,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE;gBAAE,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;QACrF,CAAC;IACH,CAAC;IAED,UAAU,CAAC,OAAO,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,cAAc,GAAG,CAAC,CAAA;IAC7B,UAAU,CAAC,MAAM,GAAG,EAAE,CAAA;IAEtB,gBAAgB;IAChB,MAAM,eAAe,EAAE,CAAA;IAEvB,gBAAgB;IAChB,SAAS,GAAG,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;IAC7D,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,YAAY,GAAG,IAAI,oBAAoB,CAAC,CAAA;AAC1F,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,SAAS,EAAE,CAAC;QACd,aAAa,CAAC,SAAS,CAAC,CAAA;QACxB,SAAS,GAAG,IAAI,CAAA;IAClB,CAAC;IACD,UAAU,CAAC,OAAO,GAAG,KAAK,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,28 @@
1
+ export interface IMessageAgentConfig {
2
+ ollamaUrl: string;
3
+ ollamaModel: string;
4
+ pollInterval: number;
5
+ numbers: string[];
6
+ supabaseUrl?: string;
7
+ supabaseKey?: string;
8
+ }
9
+ export interface IMessageAgentState {
10
+ running: boolean;
11
+ messagesProcessed: number;
12
+ lastCheck: string;
13
+ errors: string[];
14
+ }
15
+ declare const DEFAULT_OLLAMA_URL = "http://localhost:11434";
16
+ declare const DEFAULT_MODEL = "qwen2.5-coder:32b";
17
+ declare const DEFAULT_POLL_INTERVAL = 10000;
18
+ export declare function sendIMessage(phoneNumber: string, text: string): boolean;
19
+ export declare function getRecentMessages(phoneNumber: string, count?: number): Array<{
20
+ text: string;
21
+ isFromMe: boolean;
22
+ date: string;
23
+ }>;
24
+ export declare function getIMessageAgentState(): IMessageAgentState;
25
+ export declare function startIMessageAgent(config: IMessageAgentConfig): Promise<void>;
26
+ export declare function stopIMessageAgent(): void;
27
+ export { DEFAULT_OLLAMA_URL, DEFAULT_MODEL, DEFAULT_POLL_INTERVAL };
28
+ //# sourceMappingURL=imessage-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imessage-agent.d.ts","sourceRoot":"","sources":["../src/imessage-agent.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAID,QAAA,MAAM,kBAAkB,2BAA2B,CAAA;AACnD,QAAA,MAAM,aAAa,sBAAsB,CAAA;AACzC,QAAA,MAAM,qBAAqB,QAAS,CAAA;AAYpC,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBvE;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B1H;AAsGD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D;AAKD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+FnF;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAMxC;AAED,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAA"}