@gonzih/meet-the-one-ai 1.0.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 (175) hide show
  1. package/.env.example +41 -0
  2. package/.node-version +1 -0
  3. package/basis/BERNAYS.md +233 -0
  4. package/basis/FOUNDING_TRANSCRIPT.md +218 -0
  5. package/basis/TECH_SPEC.md +303 -0
  6. package/basis/VALS.md +255 -0
  7. package/basis/layers/L1_IDENTITY_AUTH.md +78 -0
  8. package/basis/layers/L2_CONVERSATION.md +159 -0
  9. package/basis/layers/L3_RECORDING_STORE.md +104 -0
  10. package/basis/layers/L4_ANALYSIS_PIPELINE.md +257 -0
  11. package/basis/layers/L5_MATCHING_ENGINE.md +164 -0
  12. package/basis/layers/L6_CONSENT_INTRODUCTION.md +143 -0
  13. package/basis/layers/L7_PORTABLE_IDENTITY.md +139 -0
  14. package/basis/layers/STACK.md +64 -0
  15. package/basis/schema.sql +203 -0
  16. package/dist/agent.d.ts +2 -0
  17. package/dist/agent.d.ts.map +1 -0
  18. package/dist/agent.js +114 -0
  19. package/dist/agent.js.map +1 -0
  20. package/dist/api/routes/auth.d.ts +2 -0
  21. package/dist/api/routes/auth.d.ts.map +1 -0
  22. package/dist/api/routes/auth.js +79 -0
  23. package/dist/api/routes/auth.js.map +1 -0
  24. package/dist/api/routes/identity.d.ts +2 -0
  25. package/dist/api/routes/identity.d.ts.map +1 -0
  26. package/dist/api/routes/identity.js +92 -0
  27. package/dist/api/routes/identity.js.map +1 -0
  28. package/dist/api/routes/text-submission.d.ts +2 -0
  29. package/dist/api/routes/text-submission.d.ts.map +1 -0
  30. package/dist/api/routes/text-submission.js +56 -0
  31. package/dist/api/routes/text-submission.js.map +1 -0
  32. package/dist/api/webhooks/twilio.d.ts +2 -0
  33. package/dist/api/webhooks/twilio.d.ts.map +1 -0
  34. package/dist/api/webhooks/twilio.js +144 -0
  35. package/dist/api/webhooks/twilio.js.map +1 -0
  36. package/dist/api/webhooks/vapi.d.ts +2 -0
  37. package/dist/api/webhooks/vapi.d.ts.map +1 -0
  38. package/dist/api/webhooks/vapi.js +177 -0
  39. package/dist/api/webhooks/vapi.js.map +1 -0
  40. package/dist/bot.d.ts +3 -0
  41. package/dist/bot.d.ts.map +1 -0
  42. package/dist/bot.js +39 -0
  43. package/dist/bot.js.map +1 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +9 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/jobs/compact-identity.d.ts +2 -0
  49. package/dist/jobs/compact-identity.d.ts.map +1 -0
  50. package/dist/jobs/compact-identity.js +159 -0
  51. package/dist/jobs/compact-identity.js.map +1 -0
  52. package/dist/jobs/consent-call.d.ts +2 -0
  53. package/dist/jobs/consent-call.d.ts.map +1 -0
  54. package/dist/jobs/consent-call.js +70 -0
  55. package/dist/jobs/consent-call.js.map +1 -0
  56. package/dist/jobs/export-identity.d.ts +2 -0
  57. package/dist/jobs/export-identity.d.ts.map +1 -0
  58. package/dist/jobs/export-identity.js +129 -0
  59. package/dist/jobs/export-identity.js.map +1 -0
  60. package/dist/jobs/introduction-call.d.ts +2 -0
  61. package/dist/jobs/introduction-call.d.ts.map +1 -0
  62. package/dist/jobs/introduction-call.js +86 -0
  63. package/dist/jobs/introduction-call.js.map +1 -0
  64. package/dist/jobs/reanalyze-identity.d.ts +2 -0
  65. package/dist/jobs/reanalyze-identity.d.ts.map +1 -0
  66. package/dist/jobs/reanalyze-identity.js +56 -0
  67. package/dist/jobs/reanalyze-identity.js.map +1 -0
  68. package/dist/jobs/run-matching.d.ts +2 -0
  69. package/dist/jobs/run-matching.d.ts.map +1 -0
  70. package/dist/jobs/run-matching.js +200 -0
  71. package/dist/jobs/run-matching.js.map +1 -0
  72. package/dist/jobs/scheduled-matching.d.ts +2 -0
  73. package/dist/jobs/scheduled-matching.d.ts.map +1 -0
  74. package/dist/jobs/scheduled-matching.js +44 -0
  75. package/dist/jobs/scheduled-matching.js.map +1 -0
  76. package/dist/jobs/transcribe-session.d.ts +2 -0
  77. package/dist/jobs/transcribe-session.d.ts.map +1 -0
  78. package/dist/jobs/transcribe-session.js +66 -0
  79. package/dist/jobs/transcribe-session.js.map +1 -0
  80. package/dist/lib/anthropic.d.ts +4 -0
  81. package/dist/lib/anthropic.d.ts.map +1 -0
  82. package/dist/lib/anthropic.js +32 -0
  83. package/dist/lib/anthropic.js.map +1 -0
  84. package/dist/lib/config.d.ts +57 -0
  85. package/dist/lib/config.d.ts.map +1 -0
  86. package/dist/lib/config.js +73 -0
  87. package/dist/lib/config.js.map +1 -0
  88. package/dist/lib/deepgram.d.ts +15 -0
  89. package/dist/lib/deepgram.d.ts.map +1 -0
  90. package/dist/lib/deepgram.js +37 -0
  91. package/dist/lib/deepgram.js.map +1 -0
  92. package/dist/lib/inngest.d.ts +42 -0
  93. package/dist/lib/inngest.d.ts.map +1 -0
  94. package/dist/lib/inngest.js +7 -0
  95. package/dist/lib/inngest.js.map +1 -0
  96. package/dist/lib/openai.d.ts +3 -0
  97. package/dist/lib/openai.d.ts.map +1 -0
  98. package/dist/lib/openai.js +13 -0
  99. package/dist/lib/openai.js.map +1 -0
  100. package/dist/lib/prompts.d.ts +8 -0
  101. package/dist/lib/prompts.d.ts.map +1 -0
  102. package/dist/lib/prompts.js +258 -0
  103. package/dist/lib/prompts.js.map +1 -0
  104. package/dist/lib/r2.d.ts +7 -0
  105. package/dist/lib/r2.d.ts.map +1 -0
  106. package/dist/lib/r2.js +49 -0
  107. package/dist/lib/r2.js.map +1 -0
  108. package/dist/lib/session-helpers.d.ts +8 -0
  109. package/dist/lib/session-helpers.d.ts.map +1 -0
  110. package/dist/lib/session-helpers.js +31 -0
  111. package/dist/lib/session-helpers.js.map +1 -0
  112. package/dist/lib/supabase.d.ts +2 -0
  113. package/dist/lib/supabase.d.ts.map +1 -0
  114. package/dist/lib/supabase.js +11 -0
  115. package/dist/lib/supabase.js.map +1 -0
  116. package/dist/lib/twilio.d.ts +7 -0
  117. package/dist/lib/twilio.d.ts.map +1 -0
  118. package/dist/lib/twilio.js +34 -0
  119. package/dist/lib/twilio.js.map +1 -0
  120. package/dist/lib/vapi.d.ts +4 -0
  121. package/dist/lib/vapi.d.ts.map +1 -0
  122. package/dist/lib/vapi.js +59 -0
  123. package/dist/lib/vapi.js.map +1 -0
  124. package/dist/mcp-server.d.ts +3 -0
  125. package/dist/mcp-server.d.ts.map +1 -0
  126. package/dist/mcp-server.js +177 -0
  127. package/dist/mcp-server.js.map +1 -0
  128. package/dist/types/index.d.ts +104 -0
  129. package/dist/types/index.d.ts.map +1 -0
  130. package/dist/types/index.js +3 -0
  131. package/dist/types/index.js.map +1 -0
  132. package/package.json +28 -0
  133. package/railway.json +14 -0
  134. package/src/agent.ts +123 -0
  135. package/src/api/routes/auth.ts +95 -0
  136. package/src/api/routes/identity.ts +112 -0
  137. package/src/api/routes/text-submission.ts +64 -0
  138. package/src/api/webhooks/twilio.ts +181 -0
  139. package/src/api/webhooks/vapi.ts +219 -0
  140. package/src/bot.ts +44 -0
  141. package/src/index.ts +11 -0
  142. package/src/jobs/compact-identity.ts +211 -0
  143. package/src/jobs/consent-call.ts +87 -0
  144. package/src/jobs/export-identity.ts +166 -0
  145. package/src/jobs/introduction-call.ts +101 -0
  146. package/src/jobs/reanalyze-identity.ts +65 -0
  147. package/src/jobs/run-matching.ts +243 -0
  148. package/src/jobs/scheduled-matching.ts +59 -0
  149. package/src/jobs/transcribe-session.ts +77 -0
  150. package/src/lib/anthropic.ts +37 -0
  151. package/src/lib/config.ts +81 -0
  152. package/src/lib/deepgram.ts +57 -0
  153. package/src/lib/inngest.ts +33 -0
  154. package/src/lib/openai.ts +14 -0
  155. package/src/lib/prompts.ts +266 -0
  156. package/src/lib/r2.ts +79 -0
  157. package/src/lib/session-helpers.ts +37 -0
  158. package/src/lib/supabase.ts +15 -0
  159. package/src/lib/twilio.ts +49 -0
  160. package/src/lib/vapi.ts +80 -0
  161. package/src/mcp-server.ts +195 -0
  162. package/src/types/index.ts +146 -0
  163. package/supabase/.branches/_current_branch +1 -0
  164. package/supabase/.temp/cli-latest +1 -0
  165. package/supabase/.temp/gotrue-version +1 -0
  166. package/supabase/.temp/pooler-url +1 -0
  167. package/supabase/.temp/postgres-version +1 -0
  168. package/supabase/.temp/project-ref +1 -0
  169. package/supabase/.temp/rest-version +1 -0
  170. package/supabase/.temp/storage-migration +1 -0
  171. package/supabase/.temp/storage-version +1 -0
  172. package/supabase/config.toml +384 -0
  173. package/supabase/migrations/20260303000000_initial_schema.sql +203 -0
  174. package/supabase/migrations/20260304000000_brand_consents.sql +13 -0
  175. package/tsconfig.json +25 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/routes/auth.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,KAAW,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { Router } from "express";
2
+ import { z } from "zod";
3
+ import { send_otp, verify_otp, normalize_phone } from "../../lib/twilio.js";
4
+ import { supabase } from "../../lib/supabase.js";
5
+ import { trigger_intake_call } from "../../lib/vapi.js";
6
+ export const auth_router = Router();
7
+ const RequestOtpBody = z.object({
8
+ phone: z.string().min(7),
9
+ brand: z.string().optional().default("flagship"),
10
+ });
11
+ const VerifyOtpBody = z.object({
12
+ phone: z.string().min(7),
13
+ code: z.string().length(6),
14
+ brand: z.string().optional().default("flagship"),
15
+ });
16
+ // POST /api/auth/request-otp
17
+ auth_router.post("/request-otp", async (req, res) => {
18
+ const parsed = RequestOtpBody.safeParse(req.body);
19
+ if (!parsed.success) {
20
+ res.status(400).json({ error: parsed.error.flatten() });
21
+ return;
22
+ }
23
+ let phone;
24
+ try {
25
+ phone = normalize_phone(parsed.data.phone);
26
+ }
27
+ catch {
28
+ res.status(400).json({ error: "Invalid phone number" });
29
+ return;
30
+ }
31
+ try {
32
+ await send_otp(phone);
33
+ res.json({ ok: true });
34
+ }
35
+ catch (err) {
36
+ console.error("send_otp error", err);
37
+ res.status(500).json({ error: "Failed to send OTP" });
38
+ }
39
+ });
40
+ // POST /api/auth/verify-otp
41
+ auth_router.post("/verify-otp", async (req, res) => {
42
+ const parsed = VerifyOtpBody.safeParse(req.body);
43
+ if (!parsed.success) {
44
+ res.status(400).json({ error: parsed.error.flatten() });
45
+ return;
46
+ }
47
+ let phone;
48
+ try {
49
+ phone = normalize_phone(parsed.data.phone);
50
+ }
51
+ catch {
52
+ res.status(400).json({ error: "Invalid phone number" });
53
+ return;
54
+ }
55
+ const ok = await verify_otp(phone, parsed.data.code);
56
+ if (!ok) {
57
+ res.status(401).json({ error: "Invalid or expired code" });
58
+ return;
59
+ }
60
+ // Upsert user
61
+ const { data: user, error } = await supabase
62
+ .from("users")
63
+ .upsert({ phone, brand: parsed.data.brand, last_active: new Date().toISOString() }, { onConflict: "phone" })
64
+ .select("id, phone, brand, created_at")
65
+ .single();
66
+ if (error || !user) {
67
+ console.error("upsert user error", error);
68
+ res.status(500).json({ error: "Failed to create user" });
69
+ return;
70
+ }
71
+ // New user (created_at === last_active within a few ms) → trigger intake call
72
+ const is_new_user = new Date(user.created_at).getTime() > Date.now() - 5000;
73
+ if (is_new_user) {
74
+ // Fire-and-forget — don't block the auth response
75
+ trigger_intake_call(phone, user.id).catch((err) => console.error("trigger_intake_call error", err));
76
+ }
77
+ res.json({ ok: true, user, is_new_user });
78
+ });
79
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/api/routes/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const identity_router: any;
2
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../src/api/routes/identity.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,KAAW,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { Router } from "express";
2
+ import { z } from "zod";
3
+ import { supabase } from "../../lib/supabase.js";
4
+ import { inngest } from "../../lib/inngest.js";
5
+ export const identity_router = Router();
6
+ const UserParams = z.object({ user_id: z.string().uuid() });
7
+ // GET /api/identity/:user_id/export
8
+ // Triggers async export — user gets SMS when ready
9
+ identity_router.get("/:user_id/export", async (req, res) => {
10
+ const parsed = UserParams.safeParse(req.params);
11
+ if (!parsed.success) {
12
+ res.status(400).json({ error: "Invalid user_id" });
13
+ return;
14
+ }
15
+ const { user_id } = parsed.data;
16
+ // Verify user exists and has an identity
17
+ const { data: identity } = await supabase
18
+ .from("identities")
19
+ .select("signal_completeness_score, session_count")
20
+ .eq("user_id", user_id)
21
+ .single();
22
+ if (!identity) {
23
+ res.status(404).json({ error: "No identity found — complete at least one session first" });
24
+ return;
25
+ }
26
+ await inngest.send({ name: "identity/export", data: { user_id } });
27
+ res.json({
28
+ ok: true,
29
+ message: "Export started — you'll receive a download link via SMS shortly",
30
+ completeness: identity.signal_completeness_score,
31
+ sessions: identity.session_count,
32
+ });
33
+ });
34
+ // GET /api/identity/:user_id
35
+ // Returns current identity profile (for web portal)
36
+ identity_router.get("/:user_id", async (req, res) => {
37
+ const parsed = UserParams.safeParse(req.params);
38
+ if (!parsed.success) {
39
+ res.status(400).json({ error: "Invalid user_id" });
40
+ return;
41
+ }
42
+ const { data, error } = await supabase
43
+ .from("identities")
44
+ .select("base_profile, modality_weights, signal_completeness_score, session_count, ready_for_matching, last_updated")
45
+ .eq("user_id", parsed.data.user_id)
46
+ .single();
47
+ if (error || !data) {
48
+ res.status(404).json({ error: "Identity not found" });
49
+ return;
50
+ }
51
+ res.json(data);
52
+ });
53
+ // DELETE /api/identity/:user_id
54
+ // GDPR hard delete — removes all user data
55
+ identity_router.delete("/:user_id", async (req, res) => {
56
+ const parsed = UserParams.safeParse(req.params);
57
+ if (!parsed.success) {
58
+ res.status(400).json({ error: "Invalid user_id" });
59
+ return;
60
+ }
61
+ const { user_id } = parsed.data;
62
+ // Verify user exists
63
+ const { data: user } = await supabase
64
+ .from("users")
65
+ .select("id")
66
+ .eq("id", user_id)
67
+ .single();
68
+ if (!user) {
69
+ res.status(404).json({ error: "User not found" });
70
+ return;
71
+ }
72
+ // Cascade delete — all child records deleted via ON DELETE CASCADE:
73
+ // sessions, identities, identity_modality_embeddings, matches (partial — see note)
74
+ // matches where user is user_b won't cascade — delete explicitly
75
+ await Promise.all([
76
+ supabase.from("matches").delete().eq("user_a_id", user_id),
77
+ supabase.from("matches").delete().eq("user_b_id", user_id),
78
+ supabase.from("declined_pairs").delete().eq("user_a_id", user_id),
79
+ supabase.from("declined_pairs").delete().eq("user_b_id", user_id),
80
+ ]);
81
+ // Delete user — cascades to sessions, identities, embeddings
82
+ const { error } = await supabase.from("users").delete().eq("id", user_id);
83
+ if (error) {
84
+ console.error("GDPR delete error", error);
85
+ res.status(500).json({ error: "Deletion failed — contact support" });
86
+ return;
87
+ }
88
+ // Note: R2 audio/transcript files are NOT deleted here — add async cleanup job
89
+ // for production. R2 lifecycle rules can auto-expire after 30 days.
90
+ res.json({ ok: true, message: "All data deleted" });
91
+ });
92
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/api/routes/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const text_submission_router: any;
2
+ //# sourceMappingURL=text-submission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-submission.d.ts","sourceRoot":"","sources":["../../../src/api/routes/text-submission.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,sBAAsB,KAAW,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { Router } from "express";
2
+ import { z } from "zod";
3
+ import { supabase } from "../../lib/supabase.js";
4
+ import { inngest } from "../../lib/inngest.js";
5
+ import { create_session } from "../../lib/session-helpers.js";
6
+ export const text_submission_router = Router();
7
+ const TextBody = z.object({
8
+ user_id: z.string().uuid(),
9
+ text: z.string().min(10).max(10000),
10
+ });
11
+ // POST /api/session/text
12
+ // Accepts a free-text submission (alternative to voice intake)
13
+ text_submission_router.post("/text", async (req, res) => {
14
+ const parsed = TextBody.safeParse(req.body);
15
+ if (!parsed.success) {
16
+ res.status(400).json({ error: parsed.error.flatten() });
17
+ return;
18
+ }
19
+ const { user_id, text } = parsed.data;
20
+ // Verify user exists
21
+ const { data: user, error: user_error } = await supabase
22
+ .from("users")
23
+ .select("id")
24
+ .eq("id", user_id)
25
+ .single();
26
+ if (user_error || !user) {
27
+ res.status(404).json({ error: "User not found" });
28
+ return;
29
+ }
30
+ let session_id;
31
+ try {
32
+ session_id = await create_session(user_id, "text", { raw_text: text });
33
+ }
34
+ catch (err) {
35
+ console.error("create_session error", err);
36
+ res.status(500).json({ error: "Failed to create session" });
37
+ return;
38
+ }
39
+ // Fire Inngest event — triggers compact-identity pipeline
40
+ // Text sessions skip transcription and go straight to analysis
41
+ await inngest.send({
42
+ name: "session/transcribed",
43
+ data: {
44
+ user_id,
45
+ session_id,
46
+ transcript_r2_key: "", // empty — compact-identity reads raw_text instead
47
+ },
48
+ });
49
+ // Update last_active
50
+ await supabase
51
+ .from("users")
52
+ .update({ last_active: new Date().toISOString() })
53
+ .eq("id", user_id);
54
+ res.json({ ok: true, session_id });
55
+ });
56
+ //# sourceMappingURL=text-submission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-submission.js","sourceRoot":"","sources":["../../../src/api/routes/text-submission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,EAAE,CAAC;AAE/C,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;CACpC,CAAC,CAAC;AAEH,yBAAyB;AACzB,+DAA+D;AAC/D,sBAAsB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAEtC,qBAAqB;IACrB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,QAAQ;SACrD,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC,IAAI,CAAC;SACZ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;SACjB,MAAM,EAAE,CAAC;IAEZ,IAAI,UAAU,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;QAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,0DAA0D;IAC1D,+DAA+D;IAC/D,MAAM,OAAO,CAAC,IAAI,CAAC;QACjB,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE;YACJ,OAAO;YACP,UAAU;YACV,iBAAiB,EAAE,EAAE,EAAE,kDAAkD;SAC1E;KACF,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,QAAQ;SACX,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;SACjD,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAErB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const twilio_webhook_router: any;
2
+ //# sourceMappingURL=twilio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../../src/api/webhooks/twilio.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,qBAAqB,KAAW,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { Router } from "express";
2
+ import { supabase } from "../../lib/supabase.js";
3
+ import { inngest } from "../../lib/inngest.js";
4
+ import { normalize_phone, send_sms } from "../../lib/twilio.js";
5
+ export const twilio_webhook_router = Router();
6
+ // POST /api/webhooks/twilio/sms
7
+ // Handles inbound SMS — consent responses and export triggers
8
+ twilio_webhook_router.post("/sms", async (req, res) => {
9
+ // Twilio sends form-encoded body
10
+ const from = req.body.From ?? "";
11
+ const body = (req.body.Body ?? "").trim();
12
+ // Always respond with empty TwiML to suppress Twilio error
13
+ res.set("Content-Type", "text/xml");
14
+ res.send(`<?xml version="1.0" encoding="UTF-8"?><Response></Response>`);
15
+ if (!from || !body)
16
+ return;
17
+ const phone = normalize_phone(from);
18
+ const text = body.toUpperCase();
19
+ try {
20
+ await handle_sms(phone, text, body);
21
+ }
22
+ catch (err) {
23
+ console.error("twilio sms webhook error", err);
24
+ }
25
+ });
26
+ // POST /api/webhooks/twilio/conference
27
+ // Status callback when conference ends — no action needed yet
28
+ twilio_webhook_router.post("/conference", (_req, res) => {
29
+ res.sendStatus(204);
30
+ });
31
+ async function handle_sms(phone, text, raw_body) {
32
+ // Look up user by phone
33
+ const { data: user } = await supabase
34
+ .from("users")
35
+ .select("id, phone, brand")
36
+ .eq("phone", phone)
37
+ .single();
38
+ if (!user) {
39
+ console.warn(`Inbound SMS from unknown phone: ${phone}`);
40
+ return;
41
+ }
42
+ // ── EXPORT trigger ────────────────────────────────────────────────────────
43
+ if (text === "EXPORT" || text === "EXPORT IDENTITY" || text === "SEND ME MY IDENTITY") {
44
+ await inngest.send({
45
+ name: "identity/export",
46
+ data: { user_id: user.id },
47
+ });
48
+ await send_sms(phone, "Preparing your identity export — you'll receive a download link shortly.", user.brand);
49
+ return;
50
+ }
51
+ // ── DELETE trigger ────────────────────────────────────────────────────────
52
+ if (text === "DELETE MY DATA" || text === "DELETE") {
53
+ // Fire deletion via API — use internal fetch to keep logic in one place
54
+ // In production replace with direct service call
55
+ await supabase.from("users").delete().eq("id", user.id);
56
+ // Note: cascades handle sessions, identities, embeddings
57
+ // matches deleted separately
58
+ await Promise.all([
59
+ supabase.from("matches").delete().eq("user_a_id", user.id),
60
+ supabase.from("matches").delete().eq("user_b_id", user.id),
61
+ supabase.from("declined_pairs").delete().eq("user_a_id", user.id),
62
+ supabase.from("declined_pairs").delete().eq("user_b_id", user.id),
63
+ ]);
64
+ // Can't send SMS after deletion since user no longer exists — no reply needed
65
+ return;
66
+ }
67
+ // ── Consent responses (ACCEPT / DECLINE with match reference) ────────────
68
+ // Format: "ACCEPT [match:uuid]" or just "ACCEPT" (applies to oldest pending)
69
+ const match_ref = raw_body.match(/\[match:([a-f0-9-]{36})\]/i);
70
+ const match_id_from_msg = match_ref?.[1];
71
+ if (text.startsWith("ACCEPT") || text.startsWith("YES")) {
72
+ await handle_consent_sms(user.id, "accepted", match_id_from_msg ?? null);
73
+ return;
74
+ }
75
+ if (text.startsWith("DECLINE") || text.startsWith("NO") || text.startsWith("PASS")) {
76
+ await handle_consent_sms(user.id, "declined", match_id_from_msg ?? null);
77
+ return;
78
+ }
79
+ // Unknown — send help
80
+ await send_sms(phone, "Reply ACCEPT or DECLINE to respond to a match. Reply EXPORT to get your identity file.", user.brand);
81
+ }
82
+ async function handle_consent_sms(user_id, decision, explicit_match_id) {
83
+ // Find the relevant pending match
84
+ let match_id = explicit_match_id;
85
+ if (!match_id) {
86
+ // Find oldest pending_consent match for this user
87
+ const { data } = await supabase
88
+ .from("matches")
89
+ .select("id, user_a_id, user_b_id, status")
90
+ .or(`user_a_id.eq.${user_id},user_b_id.eq.${user_id}`)
91
+ .eq("status", "pending_consent")
92
+ .order("created_at", { ascending: true })
93
+ .limit(1)
94
+ .single();
95
+ if (!data)
96
+ return; // no pending match
97
+ match_id = data.id;
98
+ }
99
+ const { data: match } = await supabase
100
+ .from("matches")
101
+ .select("id, user_a_id, user_b_id, status")
102
+ .eq("id", match_id)
103
+ .single();
104
+ if (!match)
105
+ return;
106
+ const is_user_a = user_id === match.user_a_id;
107
+ if (decision === "declined") {
108
+ await supabase.from("declined_pairs").upsert({
109
+ user_a_id: match.user_a_id,
110
+ user_b_id: match.user_b_id,
111
+ declined_by: user_id,
112
+ reason: "sms_declined",
113
+ created_at: new Date().toISOString(),
114
+ }, { onConflict: "user_a_id,user_b_id" });
115
+ await supabase
116
+ .from("matches")
117
+ .update({
118
+ status: is_user_a ? "a_declined" : "b_declined",
119
+ updated_at: new Date().toISOString(),
120
+ })
121
+ .eq("id", match_id);
122
+ return;
123
+ }
124
+ // accepted
125
+ const current_status = match.status;
126
+ let new_status;
127
+ if (is_user_a) {
128
+ new_status = current_status === "b_accepted" ? "both_accepted" : "a_accepted";
129
+ }
130
+ else {
131
+ new_status = current_status === "a_accepted" ? "both_accepted" : "b_accepted";
132
+ }
133
+ await supabase
134
+ .from("matches")
135
+ .update({ status: new_status, updated_at: new Date().toISOString() })
136
+ .eq("id", match_id);
137
+ if (new_status === "both_accepted") {
138
+ await inngest.send({
139
+ name: "match/both-accepted",
140
+ data: { match_id },
141
+ });
142
+ }
143
+ }
144
+ //# sourceMappingURL=twilio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio.js","sourceRoot":"","sources":["../../../src/api/webhooks/twilio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const vapi_webhook_router: any;
2
+ //# sourceMappingURL=vapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vapi.d.ts","sourceRoot":"","sources":["../../../src/api/webhooks/vapi.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,KAAW,CAAC"}
@@ -0,0 +1,177 @@
1
+ import { Router } from "express";
2
+ import { supabase } from "../../lib/supabase.js";
3
+ import { inngest } from "../../lib/inngest.js";
4
+ import { upload_buffer } from "../../lib/r2.js";
5
+ export const vapi_webhook_router = Router();
6
+ // POST /api/webhooks/vapi
7
+ vapi_webhook_router.post("/", async (req, res) => {
8
+ const event = req.body;
9
+ res.json({ ok: true });
10
+ try {
11
+ await handle_vapi_event(event);
12
+ }
13
+ catch (err) {
14
+ console.error("vapi webhook handler error", err);
15
+ }
16
+ });
17
+ async function handle_vapi_event(event) {
18
+ switch (event.message?.type) {
19
+ case "end-of-call-report":
20
+ await handle_call_ended(event);
21
+ break;
22
+ default:
23
+ break;
24
+ }
25
+ }
26
+ async function handle_call_ended(event) {
27
+ const { call, recordingUrl, durationSeconds } = event.message ?? {};
28
+ if (!call?.id)
29
+ return;
30
+ const vars = call.assistantOverrides?.variableValues ?? {};
31
+ const user_id = vars.user_id;
32
+ const match_id = vars.match_id;
33
+ // ── Consent call outcome ──────────────────────────────────────────────────
34
+ if (match_id) {
35
+ await handle_consent_outcome(call, match_id);
36
+ return;
37
+ }
38
+ // ── Intake call — create session ─────────────────────────────────────────
39
+ if (!user_id) {
40
+ console.warn("vapi call ended but no user_id or match_id in variableValues", call.id);
41
+ return;
42
+ }
43
+ const { data: session, error } = await supabase
44
+ .from("sessions")
45
+ .insert({
46
+ user_id,
47
+ source: "vapi",
48
+ duration_seconds: durationSeconds ? Math.round(durationSeconds) : null,
49
+ analysis_status: "pending",
50
+ })
51
+ .select("id")
52
+ .single();
53
+ if (error || !session) {
54
+ console.error("Failed to create session for vapi call", error);
55
+ return;
56
+ }
57
+ const session_id = session.id;
58
+ if (recordingUrl) {
59
+ try {
60
+ const audio_res = await fetch(recordingUrl);
61
+ const audio_buf = Buffer.from(await audio_res.arrayBuffer());
62
+ const audio_r2_key = `audio/${user_id}/${session_id}.wav`;
63
+ await upload_buffer(audio_r2_key, audio_buf, "audio/wav");
64
+ await supabase.from("sessions").update({ audio_r2_key }).eq("id", session_id);
65
+ await inngest.send({
66
+ name: "session/completed",
67
+ data: { user_id, session_id },
68
+ });
69
+ }
70
+ catch (err) {
71
+ console.error("Failed to store audio for session", session_id, err);
72
+ }
73
+ }
74
+ else {
75
+ const transcript_text = call.transcript ?? "";
76
+ if (transcript_text) {
77
+ await supabase.from("sessions").update({ raw_text: transcript_text }).eq("id", session_id);
78
+ await inngest.send({
79
+ name: "session/transcribed",
80
+ data: { user_id, session_id, transcript_r2_key: "" },
81
+ });
82
+ }
83
+ }
84
+ await supabase
85
+ .from("users")
86
+ .update({ last_active: new Date().toISOString() })
87
+ .eq("id", user_id);
88
+ }
89
+ async function handle_consent_outcome(call, match_id) {
90
+ if (!call)
91
+ return;
92
+ // Vapi assistant sets call.summary or transcript to indicate decision
93
+ // Convention: assistant ends call with structured summary JSON
94
+ // e.g. {"decision": "accepted"} or {"decision": "declined"}
95
+ const transcript = call.transcript ?? "";
96
+ const summary = call.summary ?? "";
97
+ const decision = extract_decision(summary || transcript);
98
+ if (!decision) {
99
+ console.warn(`No consent decision found for match ${match_id}, call ${call.id}`);
100
+ return;
101
+ }
102
+ // Load match to determine which user this call was for
103
+ const { data: match, error } = await supabase
104
+ .from("matches")
105
+ .select("id, user_a_id, user_b_id, status")
106
+ .eq("id", match_id)
107
+ .single();
108
+ if (error || !match) {
109
+ console.error(`Match not found for consent outcome: ${match_id}`);
110
+ return;
111
+ }
112
+ // Identify which user answered (match call.id to stored call reference — simplified:
113
+ // use variableValues.user_id if present, else infer from status)
114
+ const vars = call.assistantOverrides?.variableValues ?? {};
115
+ const answering_user_id = vars.user_id;
116
+ if (!answering_user_id) {
117
+ console.warn(`Cannot identify consenting user for match ${match_id}`);
118
+ return;
119
+ }
120
+ const is_user_a = answering_user_id === match.user_a_id;
121
+ if (decision === "declined") {
122
+ // Record decline — insert to declined_pairs and update match
123
+ await supabase.from("declined_pairs").upsert({
124
+ user_a_id: match.user_a_id,
125
+ user_b_id: match.user_b_id,
126
+ declined_by: answering_user_id,
127
+ reason: "consent_call_declined",
128
+ created_at: new Date().toISOString(),
129
+ }, { onConflict: "user_a_id,user_b_id" });
130
+ const new_status = is_user_a ? "a_declined" : "b_declined";
131
+ await supabase
132
+ .from("matches")
133
+ .update({ status: new_status, updated_at: new Date().toISOString() })
134
+ .eq("id", match_id);
135
+ return;
136
+ }
137
+ // decision === "accepted"
138
+ const current_status = match.status;
139
+ let new_status;
140
+ if (is_user_a) {
141
+ new_status = current_status === "b_accepted" ? "both_accepted" : "a_accepted";
142
+ }
143
+ else {
144
+ new_status = current_status === "a_accepted" ? "both_accepted" : "b_accepted";
145
+ }
146
+ await supabase
147
+ .from("matches")
148
+ .update({ status: new_status, updated_at: new Date().toISOString() })
149
+ .eq("id", match_id);
150
+ if (new_status === "both_accepted") {
151
+ await inngest.send({
152
+ name: "match/both-accepted",
153
+ data: { match_id },
154
+ });
155
+ }
156
+ }
157
+ // Extract accept/decline from Vapi call summary or transcript
158
+ function extract_decision(text) {
159
+ // Try structured JSON first (Vapi assistant summary)
160
+ try {
161
+ const parsed = JSON.parse(text);
162
+ if (parsed.decision === "accepted")
163
+ return "accepted";
164
+ if (parsed.decision === "declined")
165
+ return "declined";
166
+ }
167
+ catch {
168
+ // not JSON — fall through to keyword search
169
+ }
170
+ const lower = text.toLowerCase();
171
+ if (/\b(accept|yes|interested|connect)\b/.test(lower))
172
+ return "accepted";
173
+ if (/\b(decline|no|pass|not interested)\b/.test(lower))
174
+ return "declined";
175
+ return null;
176
+ }
177
+ //# sourceMappingURL=vapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vapi.js","sourceRoot":"","sources":["../../../src/api/webhooks/vapi.ts"],"names":[],"mappings":"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"}
package/dist/bot.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Telegraf } from "telegraf";
2
+ export declare function createBot(): Telegraf;
3
+ //# sourceMappingURL=bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKpC,wBAAgB,SAAS,IAAI,QAAQ,CAsCpC"}