@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.
Files changed (85) hide show
  1. package/dist/core-gateway/auth.d.ts +7 -0
  2. package/dist/core-gateway/auth.d.ts.map +1 -0
  3. package/dist/core-gateway/auth.js +12 -0
  4. package/dist/core-gateway/auth.js.map +1 -0
  5. package/dist/core-gateway/claude-runner.d.ts +10 -0
  6. package/dist/core-gateway/claude-runner.d.ts.map +1 -0
  7. package/dist/core-gateway/claude-runner.js +206 -0
  8. package/dist/core-gateway/claude-runner.js.map +1 -0
  9. package/dist/core-gateway/config.d.ts +33 -0
  10. package/dist/core-gateway/config.d.ts.map +1 -0
  11. package/dist/core-gateway/config.js +84 -0
  12. package/dist/core-gateway/config.js.map +1 -0
  13. package/dist/core-gateway/email-sender.d.ts +36 -0
  14. package/dist/core-gateway/email-sender.d.ts.map +1 -0
  15. package/dist/core-gateway/email-sender.js +121 -0
  16. package/dist/core-gateway/email-sender.js.map +1 -0
  17. package/dist/core-gateway/mail-ingester.d.ts +3 -0
  18. package/dist/core-gateway/mail-ingester.d.ts.map +1 -0
  19. package/dist/core-gateway/mail-ingester.js +294 -0
  20. package/dist/core-gateway/mail-ingester.js.map +1 -0
  21. package/dist/core-gateway/mail-router.d.ts +18 -0
  22. package/dist/core-gateway/mail-router.d.ts.map +1 -0
  23. package/dist/core-gateway/mail-router.js +37 -0
  24. package/dist/core-gateway/mail-router.js.map +1 -0
  25. package/dist/core-gateway/mail-threads.d.ts +78 -0
  26. package/dist/core-gateway/mail-threads.d.ts.map +1 -0
  27. package/dist/core-gateway/mail-threads.js +100 -0
  28. package/dist/core-gateway/mail-threads.js.map +1 -0
  29. package/dist/core-gateway/rate-limiter.d.ts +9 -0
  30. package/dist/core-gateway/rate-limiter.d.ts.map +1 -0
  31. package/dist/core-gateway/rate-limiter.js +13 -0
  32. package/dist/core-gateway/rate-limiter.js.map +1 -0
  33. package/dist/core-gateway/registry.d.ts +14 -0
  34. package/dist/core-gateway/registry.d.ts.map +1 -0
  35. package/dist/core-gateway/registry.js +83 -0
  36. package/dist/core-gateway/registry.js.map +1 -0
  37. package/dist/core-gateway/routes/admin.d.ts +3 -0
  38. package/dist/core-gateway/routes/admin.d.ts.map +1 -0
  39. package/dist/core-gateway/routes/admin.js +91 -0
  40. package/dist/core-gateway/routes/admin.js.map +1 -0
  41. package/dist/core-gateway/routes/chat.d.ts +9 -0
  42. package/dist/core-gateway/routes/chat.d.ts.map +1 -0
  43. package/dist/core-gateway/routes/chat.js +149 -0
  44. package/dist/core-gateway/routes/chat.js.map +1 -0
  45. package/dist/core-gateway/routes/cron.d.ts +13 -0
  46. package/dist/core-gateway/routes/cron.d.ts.map +1 -0
  47. package/dist/core-gateway/routes/cron.js +79 -0
  48. package/dist/core-gateway/routes/cron.js.map +1 -0
  49. package/dist/core-gateway/routes/gmail.d.ts +8 -0
  50. package/dist/core-gateway/routes/gmail.d.ts.map +1 -0
  51. package/dist/core-gateway/routes/gmail.js +57 -0
  52. package/dist/core-gateway/routes/gmail.js.map +1 -0
  53. package/dist/core-gateway/routes/health.d.ts +3 -0
  54. package/dist/core-gateway/routes/health.d.ts.map +1 -0
  55. package/dist/core-gateway/routes/health.js +7 -0
  56. package/dist/core-gateway/routes/health.js.map +1 -0
  57. package/dist/core-gateway/routes/upload.d.ts +7 -0
  58. package/dist/core-gateway/routes/upload.d.ts.map +1 -0
  59. package/dist/core-gateway/routes/upload.js +31 -0
  60. package/dist/core-gateway/routes/upload.js.map +1 -0
  61. package/dist/core-gateway/scheduler.d.ts +68 -0
  62. package/dist/core-gateway/scheduler.d.ts.map +1 -0
  63. package/dist/core-gateway/scheduler.js +252 -0
  64. package/dist/core-gateway/scheduler.js.map +1 -0
  65. package/dist/core-gateway/server.d.ts +17 -0
  66. package/dist/core-gateway/server.d.ts.map +1 -0
  67. package/dist/core-gateway/server.js +45 -0
  68. package/dist/core-gateway/server.js.map +1 -0
  69. package/dist/core-gateway/session.d.ts +18 -0
  70. package/dist/core-gateway/session.d.ts.map +1 -0
  71. package/dist/core-gateway/session.js +178 -0
  72. package/dist/core-gateway/session.js.map +1 -0
  73. package/dist/core-gateway/skills.d.ts +4 -0
  74. package/dist/core-gateway/skills.d.ts.map +1 -0
  75. package/dist/core-gateway/skills.js +100 -0
  76. package/dist/core-gateway/skills.js.map +1 -0
  77. package/dist/core-gateway/supabase.d.ts +3 -0
  78. package/dist/core-gateway/supabase.d.ts.map +1 -0
  79. package/dist/core-gateway/supabase.js +18 -0
  80. package/dist/core-gateway/supabase.js.map +1 -0
  81. package/dist/gateway.d.ts +3 -0
  82. package/dist/gateway.d.ts.map +1 -0
  83. package/dist/gateway.js +3 -0
  84. package/dist/gateway.js.map +1 -0
  85. package/package.json +21 -1
@@ -0,0 +1,68 @@
1
+ import type { TaskNotifyTrigger, TaskOutputChannel } from '@tleblancureta/proto/shared';
2
+ /**
3
+ * Scheduler core: next-run calculation, due-task scan, dispatch.
4
+ *
5
+ * The scheduling model is "next_run_at is canonical". On any schedule change
6
+ * (insert, update, or after a run finishes) we compute the next_run_at from
7
+ * the cron expression + timezone and store it. `scanDueTasks` just queries
8
+ * for rows where next_run_at <= now() AND enabled = true. This is cheap and
9
+ * race-free.
10
+ */
11
+ export interface ScheduledTaskRow {
12
+ id: string;
13
+ company_id: string;
14
+ name: string;
15
+ description: string | null;
16
+ cron_expr: string;
17
+ timezone: string;
18
+ prompt: string;
19
+ enabled_skills: string[];
20
+ session_key: string | null;
21
+ user_id: string;
22
+ enabled: boolean;
23
+ max_runtime_seconds: number;
24
+ next_run_at: string | null;
25
+ last_run_at: string | null;
26
+ last_run_status: string | null;
27
+ output_channel: TaskOutputChannel;
28
+ output_recipient: string | null;
29
+ notify_on: TaskNotifyTrigger;
30
+ }
31
+ /**
32
+ * Compute the next firing instant of `expr` strictly after `from`.
33
+ * Returns null if the expression is invalid.
34
+ */
35
+ export declare function computeNextRun(expr: string, timezone: string, from?: Date): Date | null;
36
+ /**
37
+ * Recompute and persist next_run_at for a task. Call this after INSERT/UPDATE
38
+ * and after a run finishes.
39
+ */
40
+ export declare function recalcNextRun(taskId: string): Promise<Date | null>;
41
+ /**
42
+ * Find tasks whose next_run_at has passed. Returns at most `limit` rows.
43
+ */
44
+ export declare function scanDueTasks(limit?: number): Promise<ScheduledTaskRow[]>;
45
+ interface DispatchOptions {
46
+ trigger: 'scheduled' | 'manual' | 'retry';
47
+ triggeredBy?: string;
48
+ }
49
+ /**
50
+ * Execute a task: creates a task_runs row, invokes runClaude with the task's
51
+ * prompt/skills, then writes back the result and recomputes next_run_at.
52
+ *
53
+ * Runs are non-blocking from the caller's perspective — the tick endpoint
54
+ * fires these and returns immediately while dispatch continues in the
55
+ * background. We guard against double-dispatch by claiming the row first
56
+ * (set last_run_at + clear next_run_at).
57
+ */
58
+ export declare function dispatchTask(task: ScheduledTaskRow, opts: DispatchOptions): Promise<void>;
59
+ /**
60
+ * Scan + dispatch in background. Called by the pg_cron webhook.
61
+ * Returns immediately with the number of tasks claimed; actual execution
62
+ * runs async.
63
+ */
64
+ export declare function tick(): Promise<{
65
+ dispatched: number;
66
+ }>;
67
+ export {};
68
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../core-gateway/scheduler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAEvF;;;;;;;;GAQG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,cAAc,EAAE,iBAAiB,CAAA;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,iBAAiB,CAAA;CAC7B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CAQnG;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAexE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAe1E;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAA;IACzC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiH/F;AA8ED;;;;GAIG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAS5D"}
@@ -0,0 +1,252 @@
1
+ import { Cron } from 'croner';
2
+ import { getSupabase } from './supabase.js';
3
+ import { runClaude } from './claude-runner.js';
4
+ import { sendSystemMail } from './email-sender.js';
5
+ import { config } from './config.js';
6
+ /**
7
+ * Compute the next firing instant of `expr` strictly after `from`.
8
+ * Returns null if the expression is invalid.
9
+ */
10
+ export function computeNextRun(expr, timezone, from = new Date()) {
11
+ try {
12
+ const c = new Cron(expr, { timezone });
13
+ const next = c.nextRun(from);
14
+ return next ?? null;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ /**
21
+ * Recompute and persist next_run_at for a task. Call this after INSERT/UPDATE
22
+ * and after a run finishes.
23
+ */
24
+ export async function recalcNextRun(taskId) {
25
+ const db = getSupabase();
26
+ const { data: t, error } = await db
27
+ .from('scheduled_tasks')
28
+ .select('id, cron_expr, timezone, enabled')
29
+ .eq('id', taskId)
30
+ .single();
31
+ if (error || !t)
32
+ return null;
33
+ if (!t.enabled) {
34
+ await db.from('scheduled_tasks').update({ next_run_at: null }).eq('id', taskId);
35
+ return null;
36
+ }
37
+ const next = computeNextRun(t.cron_expr, t.timezone);
38
+ await db.from('scheduled_tasks').update({ next_run_at: next?.toISOString() ?? null }).eq('id', taskId);
39
+ return next;
40
+ }
41
+ /**
42
+ * Find tasks whose next_run_at has passed. Returns at most `limit` rows.
43
+ */
44
+ export async function scanDueTasks(limit = 20) {
45
+ const db = getSupabase();
46
+ const nowIso = new Date().toISOString();
47
+ const { data, error } = await db
48
+ .from('scheduled_tasks')
49
+ .select('*')
50
+ .eq('enabled', true)
51
+ .lte('next_run_at', nowIso)
52
+ .order('next_run_at', { ascending: true })
53
+ .limit(limit);
54
+ if (error) {
55
+ console.error('[scheduler] scan error', error);
56
+ return [];
57
+ }
58
+ return (data || []);
59
+ }
60
+ /**
61
+ * Execute a task: creates a task_runs row, invokes runClaude with the task's
62
+ * prompt/skills, then writes back the result and recomputes next_run_at.
63
+ *
64
+ * Runs are non-blocking from the caller's perspective — the tick endpoint
65
+ * fires these and returns immediately while dispatch continues in the
66
+ * background. We guard against double-dispatch by claiming the row first
67
+ * (set last_run_at + clear next_run_at).
68
+ */
69
+ export async function dispatchTask(task, opts) {
70
+ const db = getSupabase();
71
+ const startedAt = new Date();
72
+ // 1. Claim the row. For scheduled runs, use an optimistic lock on
73
+ // next_run_at to prevent races between overlapping ticks. For manual
74
+ // triggers the user explicitly wants it to run now, so we skip the
75
+ // lock — otherwise we'd also fail when next_run_at is null (e.g.,
76
+ // task created via direct DB insert without recalc).
77
+ let claimQuery = db
78
+ .from('scheduled_tasks')
79
+ .update({
80
+ next_run_at: null, // cleared; recomputed after run
81
+ last_run_at: startedAt.toISOString(),
82
+ last_run_status: 'running',
83
+ })
84
+ .eq('id', task.id);
85
+ if (opts.trigger === 'scheduled' && task.next_run_at) {
86
+ claimQuery = claimQuery.eq('next_run_at', task.next_run_at);
87
+ }
88
+ const { data: claimed, error: claimErr } = await claimQuery.select('id').single();
89
+ if (claimErr || !claimed) {
90
+ // Someone else claimed it (scheduled race), or it was edited mid-flight.
91
+ return;
92
+ }
93
+ // 2. Insert run row
94
+ const { data: run, error: runErr } = await db
95
+ .from('task_runs')
96
+ .insert({
97
+ task_id: task.id,
98
+ company_id: task.company_id,
99
+ status: 'running',
100
+ trigger: opts.trigger,
101
+ triggered_by: opts.triggeredBy ?? 'cron',
102
+ started_at: startedAt.toISOString(),
103
+ })
104
+ .select('id')
105
+ .single();
106
+ if (runErr || !run) {
107
+ console.error('[scheduler] failed to insert task_run', runErr);
108
+ return;
109
+ }
110
+ // 3. Link run id to task
111
+ await db.from('scheduled_tasks').update({ last_run_id: run.id }).eq('id', task.id);
112
+ // 4. Invoke the agent
113
+ let status = 'success';
114
+ let response = null;
115
+ let errorText = null;
116
+ let costUsd;
117
+ let sessionId;
118
+ try {
119
+ const sessionKey = task.session_key || `cron-${task.name}-${Date.now()}`;
120
+ const result = await runClaude({
121
+ company_id: task.company_id,
122
+ user_id: task.user_id,
123
+ message: task.prompt,
124
+ channel: 'cron',
125
+ session_key: sessionKey,
126
+ enabled_skills: task.enabled_skills,
127
+ company_context: `[Cron task "${task.name}" firing via ${opts.trigger}]`,
128
+ selected_files: [],
129
+ });
130
+ response = result.response;
131
+ costUsd = result.cost_usd;
132
+ sessionId = result.session_id;
133
+ }
134
+ catch (err) {
135
+ status = 'error';
136
+ errorText = err?.message || String(err);
137
+ console.error(`[scheduler] task ${task.name} failed:`, err);
138
+ }
139
+ const finishedAt = new Date();
140
+ const durationMs = finishedAt.getTime() - startedAt.getTime();
141
+ // 5. Write run result
142
+ await db
143
+ .from('task_runs')
144
+ .update({
145
+ status,
146
+ finished_at: finishedAt.toISOString(),
147
+ duration_ms: durationMs,
148
+ response,
149
+ error: errorText,
150
+ metadata: { cost_usd: costUsd, session_id: sessionId },
151
+ })
152
+ .eq('id', run.id);
153
+ // 6. Recompute next_run_at + update last_run_status on task
154
+ const next = computeNextRun(task.cron_expr, task.timezone);
155
+ await db
156
+ .from('scheduled_tasks')
157
+ .update({
158
+ next_run_at: next?.toISOString() ?? null,
159
+ last_run_status: status,
160
+ })
161
+ .eq('id', task.id);
162
+ // 7. Deliver via output channel (email) if configured
163
+ await maybeNotify(task, {
164
+ runId: run.id,
165
+ status,
166
+ response,
167
+ errorText,
168
+ previousStatus: task.last_run_status,
169
+ });
170
+ }
171
+ /**
172
+ * Decide whether + how to notify for a finished run and perform delivery.
173
+ * Writes back `notified_at` / `notify_error` on the task_runs row.
174
+ */
175
+ async function maybeNotify(task, ctx) {
176
+ if (task.output_channel === 'silent')
177
+ return;
178
+ if (!task.output_recipient)
179
+ return;
180
+ // Apply notify_on filter
181
+ const shouldNotify = (() => {
182
+ switch (task.notify_on) {
183
+ case 'never': return false;
184
+ case 'always': return true;
185
+ case 'on_error': return ctx.status === 'error';
186
+ case 'on_change': return ctx.status !== ctx.previousStatus;
187
+ }
188
+ })();
189
+ if (!shouldNotify)
190
+ return;
191
+ // Build the message
192
+ const subject = ctx.status === 'error'
193
+ ? `[${config.display_name}] Tarea "${task.name}" fallo`
194
+ : `[${config.display_name}] ${task.name}`;
195
+ const bodyLines = [];
196
+ bodyLines.push(`Tarea: ${task.name}`);
197
+ if (task.description)
198
+ bodyLines.push(`Descripcion: ${task.description}`);
199
+ bodyLines.push(`Estado: ${ctx.status}`);
200
+ bodyLines.push(`Cron: ${task.cron_expr}`);
201
+ bodyLines.push('');
202
+ if (ctx.status === 'error') {
203
+ bodyLines.push('Error:');
204
+ bodyLines.push(ctx.errorText ?? '(sin detalle)');
205
+ }
206
+ else {
207
+ bodyLines.push('Resultado:');
208
+ bodyLines.push(ctx.response ?? '(sin respuesta)');
209
+ }
210
+ bodyLines.push('');
211
+ bodyLines.push('---');
212
+ bodyLines.push(`${config.display_name} · tarea programada`);
213
+ const body = bodyLines.join('\n');
214
+ if (task.output_channel === 'email') {
215
+ const result = await sendSystemMail({
216
+ companyId: task.company_id,
217
+ to: task.output_recipient,
218
+ subject,
219
+ body,
220
+ sourceTaskId: task.id,
221
+ sessionKey: task.session_key || undefined,
222
+ });
223
+ const db = getSupabase();
224
+ if (result.ok) {
225
+ await db
226
+ .from('task_runs')
227
+ .update({ notified_at: new Date().toISOString() })
228
+ .eq('id', ctx.runId);
229
+ }
230
+ else {
231
+ await markNotifyError(ctx.runId, result.error || 'unknown send error');
232
+ }
233
+ }
234
+ }
235
+ async function markNotifyError(runId, msg) {
236
+ const db = getSupabase();
237
+ await db.from('task_runs').update({ notify_error: msg }).eq('id', runId);
238
+ }
239
+ /**
240
+ * Scan + dispatch in background. Called by the pg_cron webhook.
241
+ * Returns immediately with the number of tasks claimed; actual execution
242
+ * runs async.
243
+ */
244
+ export async function tick() {
245
+ const due = await scanDueTasks();
246
+ for (const task of due) {
247
+ // Fire and forget — each dispatch logs its own errors
248
+ dispatchTask(task, { trigger: 'scheduled', triggeredBy: 'cron' }).catch(err => console.error(`[scheduler] dispatch error for ${task.name}:`, err));
249
+ }
250
+ return { dispatched: due.length };
251
+ }
252
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../core-gateway/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Hono } from 'hono';
2
+ export interface GatewayOptions {
3
+ /** Override the port (default: PORT env or 8090). */
4
+ port?: number;
5
+ }
6
+ /**
7
+ * Create and start the Proto gateway server.
8
+ *
9
+ * Usage:
10
+ * import { createProtoGateway } from '@tleblancureta/proto/gateway'
11
+ * await createProtoGateway()
12
+ */
13
+ export declare function createProtoGateway(opts?: GatewayOptions): Promise<{
14
+ app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
15
+ server: import("@hono/node-server").ServerType;
16
+ }>;
17
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../core-gateway/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAc3B,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,CAAC,EAAE,cAAc;;;GA8B7D"}
@@ -0,0 +1,45 @@
1
+ import { Hono } from 'hono';
2
+ import { cors } from 'hono/cors';
3
+ import { createNodeWebSocket } from '@hono/node-ws';
4
+ import { serve } from '@hono/node-server';
5
+ import { verifySecret } from './auth.js';
6
+ import { config, PORT } from './config.js';
7
+ import { registerChatRoutes } from './routes/chat.js';
8
+ import { registerUploadRoutes } from './routes/upload.js';
9
+ import { registerGmailRoutes } from './routes/gmail.js';
10
+ import { registerHealthRoutes } from './routes/health.js';
11
+ import { registerCronRoutes } from './routes/cron.js';
12
+ import { registerAdminRoutes } from './routes/admin.js';
13
+ import { startMailIngester } from './mail-ingester.js';
14
+ /**
15
+ * Create and start the Proto gateway server.
16
+ *
17
+ * Usage:
18
+ * import { createProtoGateway } from '@tleblancureta/proto/gateway'
19
+ * await createProtoGateway()
20
+ */
21
+ export async function createProtoGateway(opts) {
22
+ const port = opts?.port ?? PORT;
23
+ const app = new Hono();
24
+ const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
25
+ app.use('*', cors());
26
+ // Auth middleware for REST endpoints (WS uses its own auth handshake)
27
+ app.use('/chat', verifySecret);
28
+ app.use('/chat/*', verifySecret);
29
+ app.use('/upload/*', verifySecret);
30
+ // Mount routes
31
+ registerChatRoutes(app, upgradeWebSocket);
32
+ registerUploadRoutes(app);
33
+ registerGmailRoutes(app);
34
+ registerHealthRoutes(app);
35
+ registerCronRoutes(app);
36
+ registerAdminRoutes(app);
37
+ // Start
38
+ console.log(`${config.display_name} Gateway starting on port ${port}`);
39
+ const server = serve({ fetch: app.fetch, port });
40
+ injectWebSocket(server);
41
+ // Start the IMAP ingester (no-op if MAIL_IMAP_HOST not configured)
42
+ startMailIngester();
43
+ return { app, server };
44
+ }
45
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../core-gateway/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAOtD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAqB;IAC5D,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,IAAI,CAAA;IAE/B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IAE1E,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;IAEpB,sEAAsE;IACtE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IAC9B,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;IAChC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IAElC,eAAe;IACf,kBAAkB,CAAC,GAAG,EAAE,gBAAuB,CAAC,CAAA;IAChD,oBAAoB,CAAC,GAAG,CAAC,CAAA;IACzB,mBAAmB,CAAC,GAAG,CAAC,CAAA;IACxB,oBAAoB,CAAC,GAAG,CAAC,CAAA;IACzB,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACvB,mBAAmB,CAAC,GAAG,CAAC,CAAA;IAExB,QAAQ;IACR,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,YAAY,6BAA6B,IAAI,EAAE,CAAC,CAAA;IACtE,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAChD,eAAe,CAAC,MAAM,CAAC,CAAA;IAEvB,mEAAmE;IACnE,iBAAiB,EAAE,CAAA;IAEnB,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;AACxB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ChatRequest } from '@tleblancureta/proto/shared';
2
+ interface SessionResult {
3
+ sessionId: string;
4
+ sessionDir: string;
5
+ env: Record<string, string>;
6
+ promptFile: string;
7
+ mcpConfigFile: string;
8
+ claudeConfigDir: string;
9
+ }
10
+ export declare function prepareSession(request: ChatRequest): Promise<SessionResult>;
11
+ /**
12
+ * Copy refreshed credentials from session config back to global config.
13
+ * Claude Code may refresh the OAuth token during a session — sync it back
14
+ * so future sessions use the fresh token.
15
+ */
16
+ export declare function syncCredentialsBack(claudeConfigDir: string): void;
17
+ export {};
18
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../core-gateway/session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAc9D,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAmDjF;AAgHD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAajE"}
@@ -0,0 +1,178 @@
1
+ import { mkdirSync, writeFileSync, existsSync, readdirSync, copyFileSync, statSync, rmSync } from 'node:fs';
2
+ import { resolve, join } from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import { config } from './config.js';
5
+ import { buildSystemPrompt } from './skills.js';
6
+ import { loadSkills, loadAgents } from './registry.js';
7
+ /**
8
+ * Deterministic session ID from project name + company_id + optional session_key.
9
+ * Uses a simple hash to create a stable identifier (UUID v5 equivalent).
10
+ */
11
+ function getSessionId(companyId, sessionKey) {
12
+ const seed = `${config.name}-${companyId}${sessionKey ? `-${sessionKey}` : ''}`;
13
+ return createHash('sha256').update(seed).digest('hex').slice(0, 32);
14
+ }
15
+ export async function prepareSession(request) {
16
+ const sessionId = getSessionId(request.company_id, request.session_key);
17
+ const dataRoot = process.env.DATA_DIR || '/data';
18
+ const sessionSlug = request.session_key
19
+ ? `${request.company_id}/${request.session_key}`
20
+ : request.company_id;
21
+ const sessionDir = resolve(dataRoot, 'sessions', sessionSlug);
22
+ mkdirSync(sessionDir, { recursive: true });
23
+ // Claude config dir: use per-session dir in Docker, default (~/.claude) in local dev
24
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR
25
+ ? resolve(dataRoot, 'claude-config', sessionSlug)
26
+ : join(process.env.HOME || '', '.claude');
27
+ if (process.env.CLAUDE_CONFIG_DIR) {
28
+ mkdirSync(claudeConfigDir, { recursive: true });
29
+ copyCredentials(claudeConfigDir);
30
+ }
31
+ // Load skills + agents from filesystem
32
+ const skills = loadSkills();
33
+ const agents = loadAgents();
34
+ // Write system prompt (uses skill metadata for tool restrictions)
35
+ const systemPrompt = buildSystemPrompt(request, skills);
36
+ const promptFile = join(sessionDir, 'system-prompt.md');
37
+ writeFileSync(promptFile, systemPrompt);
38
+ // Copy enabled skills + all agents into session dir
39
+ writeSkills(sessionDir, request, skills);
40
+ writeAgents(sessionDir, agents);
41
+ // Write MCP config (without secrets — secrets passed via env inheritance)
42
+ const mcpConfigFile = writeMcpConfig(sessionDir, request);
43
+ // Build environment for claude subprocess
44
+ const env = {
45
+ ...process.env,
46
+ COMPANY_ID: request.company_id,
47
+ USER_ID: request.user_id,
48
+ CHANNEL: request.channel,
49
+ };
50
+ // Only override CLAUDE_CONFIG_DIR in Docker (where we isolate per session)
51
+ if (process.env.CLAUDE_CONFIG_DIR) {
52
+ env.CLAUDE_CONFIG_DIR = claudeConfigDir;
53
+ }
54
+ return { sessionId, sessionDir, env, promptFile, mcpConfigFile, claudeConfigDir };
55
+ }
56
+ /**
57
+ * Copy enabled skills from repo into session dir.
58
+ * Channel exclusions and per-request enabled_skills are applied here.
59
+ */
60
+ function writeSkills(sessionDir, request, skills) {
61
+ const enabledSet = new Set(request.enabled_skills);
62
+ const channelExcluded = config.channel_excluded_skills[request.channel] || new Set();
63
+ for (const s of channelExcluded)
64
+ enabledSet.delete(s);
65
+ const skillsDir = join(sessionDir, '.claude', 'skills');
66
+ mkdirSync(skillsDir, { recursive: true });
67
+ for (const entry of readdirSync(skillsDir)) {
68
+ try {
69
+ rmSync(join(skillsDir, entry), { recursive: true, force: true });
70
+ }
71
+ catch { }
72
+ }
73
+ for (const skill of skills) {
74
+ if (!enabledSet.has(skill.name))
75
+ continue;
76
+ const dir = join(skillsDir, skill.name);
77
+ mkdirSync(dir, { recursive: true });
78
+ copyFileSync(skill.filePath, join(dir, 'SKILL.md'));
79
+ }
80
+ }
81
+ /**
82
+ * Copy all agents from repo into session dir.
83
+ */
84
+ function writeAgents(sessionDir, agents) {
85
+ const agentsDir = join(sessionDir, '.claude', 'agents');
86
+ mkdirSync(agentsDir, { recursive: true });
87
+ for (const entry of readdirSync(agentsDir)) {
88
+ try {
89
+ rmSync(join(agentsDir, entry), { force: true });
90
+ }
91
+ catch { }
92
+ }
93
+ for (const agent of agents) {
94
+ copyFileSync(agent.filePath, join(agentsDir, `${agent.name}.md`));
95
+ }
96
+ }
97
+ function writeMcpConfig(sessionDir, request) {
98
+ const mcpServers = {};
99
+ for (const [name, serverConfig] of Object.entries(config.mcp_servers)) {
100
+ if (serverConfig.type === 'http') {
101
+ // HTTP MCP server — just pass the URL
102
+ mcpServers[name] = { type: 'http', url: serverConfig.url };
103
+ continue;
104
+ }
105
+ // Stdio MCP server — resolve args and env
106
+ const resolvedArgs = serverConfig.args.map(arg => arg.startsWith('$') ? (process.env[arg.slice(1)] || '') : arg);
107
+ const resolvedEnv = {};
108
+ for (const [mcpVar, source] of Object.entries(serverConfig.env)) {
109
+ if (source === '__COMPANY_ID__') {
110
+ resolvedEnv[mcpVar] = request.company_id;
111
+ }
112
+ else if (source === '__ALLOWED_TOOLS__') {
113
+ continue;
114
+ }
115
+ else {
116
+ resolvedEnv[mcpVar] = process.env[source] || '';
117
+ }
118
+ }
119
+ resolvedEnv.USER_ID = request.user_id;
120
+ resolvedEnv.COMPANY_ID = request.company_id;
121
+ if (request.session_key?.startsWith('order-')) {
122
+ resolvedEnv.ACTIVE_ORDER_ID = request.session_key.slice('order-'.length);
123
+ }
124
+ if (process.env.SUPABASE_URL)
125
+ resolvedEnv.SUPABASE_URL = process.env.SUPABASE_URL;
126
+ if (process.env.SUPABASE_SERVICE_ROLE_KEY)
127
+ resolvedEnv.SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
128
+ mcpServers[name] = {
129
+ command: serverConfig.command,
130
+ ...(resolvedArgs.length > 0 && { args: resolvedArgs }),
131
+ env: resolvedEnv,
132
+ };
133
+ }
134
+ const mcpConfig = { mcpServers };
135
+ const configFile = join(sessionDir, 'mcp-config.json');
136
+ writeFileSync(configFile, JSON.stringify(mcpConfig));
137
+ return configFile;
138
+ }
139
+ /**
140
+ * Copy Claude OAuth credentials from the global config to a session-specific config dir.
141
+ * This allows each session to have its own CLAUDE_CONFIG_DIR while sharing the same auth.
142
+ */
143
+ function copyCredentials(claudeConfigDir) {
144
+ const credsFile = join(claudeConfigDir, '.credentials.json');
145
+ const candidates = [
146
+ join(process.env.HOME || '', '.claude', '.credentials.json'),
147
+ join(process.env.CLAUDE_CONFIG_DIR || '/data/claude', '.credentials.json'),
148
+ '/data/claude-host/.credentials.json',
149
+ ];
150
+ for (const candidate of candidates) {
151
+ if (existsSync(candidate)) {
152
+ copyFileSync(candidate, credsFile);
153
+ console.log(`[credentials] Copied from ${candidate}`);
154
+ return;
155
+ }
156
+ }
157
+ console.warn('[credentials] No credentials found. Run: claude login');
158
+ }
159
+ /**
160
+ * Copy refreshed credentials from session config back to global config.
161
+ * Claude Code may refresh the OAuth token during a session — sync it back
162
+ * so future sessions use the fresh token.
163
+ */
164
+ export function syncCredentialsBack(claudeConfigDir) {
165
+ const sessionCreds = join(claudeConfigDir, '.credentials.json');
166
+ if (!existsSync(sessionCreds))
167
+ return;
168
+ const globalDir = process.env.CLAUDE_CONFIG_DIR || '/data/claude';
169
+ const globalCreds = join(globalDir, '.credentials.json');
170
+ try {
171
+ if (!existsSync(globalCreds) || statSync(sessionCreds).mtimeMs > statSync(globalCreds).mtimeMs) {
172
+ mkdirSync(globalDir, { recursive: true });
173
+ copyFileSync(sessionCreds, globalCreds);
174
+ }
175
+ }
176
+ catch { }
177
+ }
178
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../core-gateway/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ChatRequest } from '@tleblancureta/proto/shared';
2
+ import type { Skill } from './registry.js';
3
+ export declare function buildSystemPrompt(request: ChatRequest, allSkills?: Skill[]): string;
4
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../core-gateway/skills.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAE9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AA0B1C,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,GAAE,KAAK,EAAO,GAAG,MAAM,CAsFvF"}