@intelligo-dev/core 1.0.0-beta.1 → 1.0.0-beta.13

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 (355) hide show
  1. package/NOTICE +6 -0
  2. package/README.md +102 -0
  3. package/dist/attachments/errors.d.ts +7 -0
  4. package/dist/attachments/errors.d.ts.map +1 -0
  5. package/dist/attachments/errors.js +11 -0
  6. package/dist/attachments/errors.js.map +1 -0
  7. package/dist/attachments/index.d.ts +8 -0
  8. package/dist/attachments/index.d.ts.map +1 -0
  9. package/dist/attachments/index.js +7 -0
  10. package/dist/attachments/index.js.map +1 -0
  11. package/dist/attachments/service.d.ts +45 -0
  12. package/dist/attachments/service.d.ts.map +1 -0
  13. package/dist/attachments/service.js +100 -0
  14. package/dist/attachments/service.js.map +1 -0
  15. package/dist/attachments/types.d.ts +6 -0
  16. package/dist/attachments/types.d.ts.map +1 -0
  17. package/dist/attachments/types.js +2 -0
  18. package/dist/attachments/types.js.map +1 -0
  19. package/dist/conversations/errors.d.ts +2 -8
  20. package/dist/conversations/errors.d.ts.map +1 -1
  21. package/dist/conversations/errors.js +2 -8
  22. package/dist/conversations/errors.js.map +1 -1
  23. package/dist/conversations/index.d.ts +4 -12
  24. package/dist/conversations/index.d.ts.map +1 -1
  25. package/dist/conversations/index.js +2 -11
  26. package/dist/conversations/index.js.map +1 -1
  27. package/dist/conversations/service.d.ts +49 -61
  28. package/dist/conversations/service.d.ts.map +1 -1
  29. package/dist/conversations/service.js +110 -83
  30. package/dist/conversations/service.js.map +1 -1
  31. package/dist/conversations/types.d.ts +1 -4
  32. package/dist/conversations/types.d.ts.map +1 -1
  33. package/dist/conversations/types.js +0 -3
  34. package/dist/conversations/types.js.map +1 -1
  35. package/dist/db/client.d.ts +21 -10
  36. package/dist/db/client.d.ts.map +1 -1
  37. package/dist/db/client.js +43 -18
  38. package/dist/db/client.js.map +1 -1
  39. package/dist/db/index.d.ts +3 -3
  40. package/dist/db/index.d.ts.map +1 -1
  41. package/dist/db/index.js +3 -7
  42. package/dist/db/index.js.map +1 -1
  43. package/dist/db/schema/agents.d.ts +14 -51
  44. package/dist/db/schema/agents.d.ts.map +1 -1
  45. package/dist/db/schema/agents.js +9 -21
  46. package/dist/db/schema/agents.js.map +1 -1
  47. package/dist/db/schema/ai.d.ts +86 -1556
  48. package/dist/db/schema/ai.d.ts.map +1 -1
  49. package/dist/db/schema/ai.js +32 -236
  50. package/dist/db/schema/ai.js.map +1 -1
  51. package/dist/db/schema/auth.d.ts +5 -34
  52. package/dist/db/schema/auth.d.ts.map +1 -1
  53. package/dist/db/schema/auth.js +25 -56
  54. package/dist/db/schema/auth.js.map +1 -1
  55. package/dist/db/schema/billing.d.ts +136 -107
  56. package/dist/db/schema/billing.d.ts.map +1 -1
  57. package/dist/db/schema/billing.js +72 -60
  58. package/dist/db/schema/billing.js.map +1 -1
  59. package/dist/db/schema/feature-flags.d.ts +3 -12
  60. package/dist/db/schema/feature-flags.d.ts.map +1 -1
  61. package/dist/db/schema/feature-flags.js +3 -12
  62. package/dist/db/schema/feature-flags.js.map +1 -1
  63. package/dist/db/schema/identity.d.ts +12 -274
  64. package/dist/db/schema/identity.d.ts.map +1 -1
  65. package/dist/db/schema/identity.js +19 -104
  66. package/dist/db/schema/identity.js.map +1 -1
  67. package/dist/db/schema/index.d.ts +8 -15
  68. package/dist/db/schema/index.d.ts.map +1 -1
  69. package/dist/db/schema/index.js +12 -42
  70. package/dist/db/schema/index.js.map +1 -1
  71. package/dist/db/schema/notifications.d.ts +3 -17
  72. package/dist/db/schema/notifications.d.ts.map +1 -1
  73. package/dist/db/schema/notifications.js +3 -17
  74. package/dist/db/schema/notifications.js.map +1 -1
  75. package/dist/db/schema/usage.d.ts +94 -77
  76. package/dist/db/schema/usage.d.ts.map +1 -1
  77. package/dist/db/schema/usage.js +59 -89
  78. package/dist/db/schema/usage.js.map +1 -1
  79. package/dist/db/validate.d.ts +2 -11
  80. package/dist/db/validate.d.ts.map +1 -1
  81. package/dist/db/validate.js +6 -17
  82. package/dist/db/validate.js.map +1 -1
  83. package/dist/db/workspace-queries.d.ts +5 -29
  84. package/dist/db/workspace-queries.d.ts.map +1 -1
  85. package/dist/db/workspace-queries.js +5 -29
  86. package/dist/db/workspace-queries.js.map +1 -1
  87. package/dist/documents/classifier.d.ts +5 -12
  88. package/dist/documents/classifier.d.ts.map +1 -1
  89. package/dist/documents/classifier.js +16 -16
  90. package/dist/documents/classifier.js.map +1 -1
  91. package/dist/documents/errors.d.ts +2 -10
  92. package/dist/documents/errors.d.ts.map +1 -1
  93. package/dist/documents/errors.js +2 -10
  94. package/dist/documents/errors.js.map +1 -1
  95. package/dist/documents/index.d.ts +4 -13
  96. package/dist/documents/index.d.ts.map +1 -1
  97. package/dist/documents/index.js +3 -12
  98. package/dist/documents/index.js.map +1 -1
  99. package/dist/documents/service.d.ts +19 -26
  100. package/dist/documents/service.d.ts.map +1 -1
  101. package/dist/documents/service.js +44 -38
  102. package/dist/documents/service.js.map +1 -1
  103. package/dist/documents/types.d.ts +6 -10
  104. package/dist/documents/types.d.ts.map +1 -1
  105. package/dist/documents/types.js +0 -3
  106. package/dist/documents/types.js.map +1 -1
  107. package/dist/email/brand.d.ts +17 -0
  108. package/dist/email/brand.d.ts.map +1 -0
  109. package/dist/email/brand.js +9 -0
  110. package/dist/email/brand.js.map +1 -0
  111. package/dist/email/index.d.ts +4 -4
  112. package/dist/email/index.js +4 -4
  113. package/dist/email/provider.d.ts +1 -7
  114. package/dist/email/provider.d.ts.map +1 -1
  115. package/dist/email/provider.js +10 -19
  116. package/dist/email/provider.js.map +1 -1
  117. package/dist/email/send.d.ts +12 -12
  118. package/dist/email/send.d.ts.map +1 -1
  119. package/dist/email/send.js +5 -19
  120. package/dist/email/send.js.map +1 -1
  121. package/dist/email/senders.d.ts +17 -30
  122. package/dist/email/senders.d.ts.map +1 -1
  123. package/dist/email/senders.js +33 -47
  124. package/dist/email/senders.js.map +1 -1
  125. package/dist/email/templates/base-layout.d.ts +1 -1
  126. package/dist/email/templates/base-layout.d.ts.map +1 -1
  127. package/dist/email/templates/base-layout.js +4 -6
  128. package/dist/email/templates/base-layout.js.map +1 -1
  129. package/dist/email/templates/index.d.ts +10 -10
  130. package/dist/email/templates/index.d.ts.map +1 -1
  131. package/dist/email/templates/index.js +10 -16
  132. package/dist/email/templates/index.js.map +1 -1
  133. package/dist/email/templates/password-reset.d.ts +2 -2
  134. package/dist/email/templates/password-reset.d.ts.map +1 -1
  135. package/dist/email/templates/password-reset.js +10 -22
  136. package/dist/email/templates/password-reset.js.map +1 -1
  137. package/dist/email/templates/payment-failed.d.ts +2 -2
  138. package/dist/email/templates/payment-failed.d.ts.map +1 -1
  139. package/dist/email/templates/payment-failed.js +11 -24
  140. package/dist/email/templates/payment-failed.js.map +1 -1
  141. package/dist/email/templates/quota-warning.d.ts +4 -4
  142. package/dist/email/templates/quota-warning.d.ts.map +1 -1
  143. package/dist/email/templates/quota-warning.js +19 -39
  144. package/dist/email/templates/quota-warning.js.map +1 -1
  145. package/dist/email/templates/subscription-confirmed.d.ts +2 -2
  146. package/dist/email/templates/subscription-confirmed.d.ts.map +1 -1
  147. package/dist/email/templates/subscription-confirmed.js +13 -28
  148. package/dist/email/templates/subscription-confirmed.js.map +1 -1
  149. package/dist/email/templates/trial-expiry.d.ts +2 -2
  150. package/dist/email/templates/trial-expiry.d.ts.map +1 -1
  151. package/dist/email/templates/trial-expiry.js +12 -36
  152. package/dist/email/templates/trial-expiry.js.map +1 -1
  153. package/dist/email/templates/trial-warning.d.ts +2 -2
  154. package/dist/email/templates/trial-warning.d.ts.map +1 -1
  155. package/dist/email/templates/trial-warning.js +15 -32
  156. package/dist/email/templates/trial-warning.js.map +1 -1
  157. package/dist/email/templates/verify-email.d.ts +2 -2
  158. package/dist/email/templates/verify-email.d.ts.map +1 -1
  159. package/dist/email/templates/verify-email.js +10 -22
  160. package/dist/email/templates/verify-email.js.map +1 -1
  161. package/dist/email/templates/welcome.d.ts +2 -2
  162. package/dist/email/templates/welcome.d.ts.map +1 -1
  163. package/dist/email/templates/welcome.js +13 -20
  164. package/dist/email/templates/welcome.js.map +1 -1
  165. package/dist/email/templates/workspace-invitation.d.ts +2 -2
  166. package/dist/email/templates/workspace-invitation.d.ts.map +1 -1
  167. package/dist/email/templates/workspace-invitation.js +12 -26
  168. package/dist/email/templates/workspace-invitation.js.map +1 -1
  169. package/dist/env.d.ts +5 -10
  170. package/dist/env.d.ts.map +1 -1
  171. package/dist/env.js +41 -31
  172. package/dist/env.js.map +1 -1
  173. package/dist/identity/audit.d.ts +11 -24
  174. package/dist/identity/audit.d.ts.map +1 -1
  175. package/dist/identity/audit.js +13 -27
  176. package/dist/identity/audit.js.map +1 -1
  177. package/dist/identity/errors.d.ts +4 -12
  178. package/dist/identity/errors.d.ts.map +1 -1
  179. package/dist/identity/errors.js +2 -8
  180. package/dist/identity/errors.js.map +1 -1
  181. package/dist/identity/index.d.ts +5 -13
  182. package/dist/identity/index.d.ts.map +1 -1
  183. package/dist/identity/index.js +4 -12
  184. package/dist/identity/index.js.map +1 -1
  185. package/dist/identity/service.d.ts +13 -47
  186. package/dist/identity/service.d.ts.map +1 -1
  187. package/dist/identity/service.js +31 -78
  188. package/dist/identity/service.js.map +1 -1
  189. package/dist/identity/types.d.ts +1 -4
  190. package/dist/identity/types.d.ts.map +1 -1
  191. package/dist/identity/types.js +0 -3
  192. package/dist/identity/types.js.map +1 -1
  193. package/dist/index.d.ts +1 -2
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +3 -10
  196. package/dist/index.js.map +1 -1
  197. package/dist/logger.d.ts +7 -18
  198. package/dist/logger.d.ts.map +1 -1
  199. package/dist/logger.js +45 -49
  200. package/dist/logger.js.map +1 -1
  201. package/dist/money.d.ts +95 -0
  202. package/dist/money.d.ts.map +1 -0
  203. package/dist/money.js +208 -0
  204. package/dist/money.js.map +1 -0
  205. package/dist/notifications/index.d.ts +9 -43
  206. package/dist/notifications/index.d.ts.map +1 -1
  207. package/dist/notifications/index.js +9 -49
  208. package/dist/notifications/index.js.map +1 -1
  209. package/dist/notifications/triggers.d.ts +9 -32
  210. package/dist/notifications/triggers.d.ts.map +1 -1
  211. package/dist/notifications/triggers.js +21 -58
  212. package/dist/notifications/triggers.js.map +1 -1
  213. package/dist/notifications/types.d.ts +1 -10
  214. package/dist/notifications/types.d.ts.map +1 -1
  215. package/dist/notifications/types.js +0 -9
  216. package/dist/notifications/types.js.map +1 -1
  217. package/dist/prompt.d.ts +38 -0
  218. package/dist/prompt.d.ts.map +1 -0
  219. package/dist/prompt.js +118 -0
  220. package/dist/prompt.js.map +1 -0
  221. package/dist/registry.d.ts +32 -0
  222. package/dist/registry.d.ts.map +1 -0
  223. package/dist/registry.js +60 -0
  224. package/dist/registry.js.map +1 -0
  225. package/dist/request-context.d.ts +49 -0
  226. package/dist/request-context.d.ts.map +1 -0
  227. package/dist/request-context.js +100 -0
  228. package/dist/request-context.js.map +1 -0
  229. package/dist/storage/index.d.ts +65 -0
  230. package/dist/storage/index.d.ts.map +1 -0
  231. package/dist/storage/index.js +109 -0
  232. package/dist/storage/index.js.map +1 -0
  233. package/package.json +74 -24
  234. package/src/attachments/errors.ts +18 -0
  235. package/src/attachments/index.ts +22 -0
  236. package/src/attachments/service.ts +178 -0
  237. package/src/attachments/types.ts +6 -0
  238. package/src/conversations/errors.ts +45 -0
  239. package/src/conversations/index.ts +39 -0
  240. package/src/conversations/service.ts +594 -0
  241. package/src/conversations/types.ts +15 -0
  242. package/src/db/client.ts +91 -0
  243. package/src/db/index.ts +3 -0
  244. package/src/db/migrations/0000_baseline.sql +652 -0
  245. package/src/db/migrations/0001_reconcile_chain_built_databases.sql +53 -0
  246. package/src/db/migrations/0002_webhook_claim_lease.sql +1 -0
  247. package/src/db/migrations/README.md +74 -36
  248. package/src/db/migrations/legacy-chain.json +197 -0
  249. package/src/db/migrations/meta/0000_snapshot.json +4182 -157
  250. package/src/db/migrations/meta/0002_snapshot.json +2478 -368
  251. package/src/db/migrations/meta/_journal.json +6 -279
  252. package/src/db/schema/agents.ts +57 -0
  253. package/src/db/schema/ai.ts +174 -0
  254. package/src/db/schema/auth.ts +183 -0
  255. package/src/db/schema/billing.ts +209 -0
  256. package/src/db/schema/feature-flags.ts +20 -0
  257. package/src/db/schema/identity.ts +250 -0
  258. package/src/db/schema/index.ts +12 -0
  259. package/src/db/schema/notifications.ts +31 -0
  260. package/src/db/schema/usage.ts +269 -0
  261. package/src/db/validate.ts +63 -0
  262. package/src/db/workspace-queries.ts +64 -0
  263. package/src/documents/classifier.ts +61 -0
  264. package/src/documents/errors.ts +44 -0
  265. package/src/documents/index.ts +24 -0
  266. package/src/documents/service.ts +256 -0
  267. package/src/documents/types.ts +24 -0
  268. package/src/email/brand.ts +24 -0
  269. package/src/email/index.ts +19 -0
  270. package/src/email/provider.ts +278 -0
  271. package/src/email/send.ts +169 -0
  272. package/src/email/senders.ts +292 -0
  273. package/src/email/templates/base-layout.tsx +145 -0
  274. package/src/email/templates/index.ts +28 -0
  275. package/src/email/templates/password-reset.tsx +72 -0
  276. package/src/email/templates/payment-failed.tsx +77 -0
  277. package/src/email/templates/quota-warning.tsx +118 -0
  278. package/src/email/templates/subscription-confirmed.tsx +91 -0
  279. package/src/email/templates/trial-expiry.tsx +124 -0
  280. package/src/email/templates/trial-warning.tsx +104 -0
  281. package/src/email/templates/verify-email.tsx +72 -0
  282. package/src/email/templates/welcome.tsx +64 -0
  283. package/src/email/templates/workspace-invitation.tsx +105 -0
  284. package/src/env.ts +180 -0
  285. package/src/identity/audit.ts +65 -0
  286. package/src/identity/errors.ts +44 -0
  287. package/src/identity/index.ts +26 -0
  288. package/src/identity/service.ts +202 -0
  289. package/src/identity/types.ts +28 -0
  290. package/src/index.ts +4 -0
  291. package/src/logger.ts +198 -0
  292. package/src/money.ts +270 -0
  293. package/src/notifications/index.ts +108 -0
  294. package/src/notifications/triggers.ts +158 -0
  295. package/src/notifications/types.ts +18 -0
  296. package/src/prompt.ts +142 -0
  297. package/src/registry.ts +75 -0
  298. package/src/request-context.ts +137 -0
  299. package/src/storage/index.ts +153 -0
  300. package/dist/db/schema/rag.d.ts +0 -171
  301. package/dist/db/schema/rag.d.ts.map +0 -1
  302. package/dist/db/schema/rag.js +0 -42
  303. package/dist/db/schema/rag.js.map +0 -1
  304. package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
  305. package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
  306. package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
  307. package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
  308. package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
  309. package/src/db/migrations/0005_careful_switch.sql +0 -8
  310. package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
  311. package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
  312. package/src/db/migrations/0008_powerful_scream.sql +0 -39
  313. package/src/db/migrations/0009_sad_ink.sql +0 -1
  314. package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
  315. package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
  316. package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
  317. package/src/db/migrations/0012_user_profiles.sql +0 -30
  318. package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
  319. package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
  320. package/src/db/migrations/0015_new_v1_tables.sql +0 -149
  321. package/src/db/migrations/0016_document_types.sql +0 -30
  322. package/src/db/migrations/0017_document_metadata.sql +0 -2
  323. package/src/db/migrations/0018_identity_graph.sql +0 -200
  324. package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
  325. package/src/db/migrations/0020_pending_extractions.sql +0 -35
  326. package/src/db/migrations/0021_rag_documents.sql +0 -39
  327. package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
  328. package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
  329. package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
  330. package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
  331. package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
  332. package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
  333. package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
  334. package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
  335. package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
  336. package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
  337. package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
  338. package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
  339. package/src/db/migrations/0034_rate_limit_count.sql +0 -9
  340. package/src/db/migrations/0035_credit_reservations.sql +0 -24
  341. package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
  342. package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
  343. package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
  344. package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
  345. package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
  346. package/src/db/migrations/meta/0001_snapshot.json +0 -631
  347. package/src/db/migrations/meta/0003_snapshot.json +0 -2488
  348. package/src/db/migrations/meta/0004_snapshot.json +0 -2500
  349. package/src/db/migrations/meta/0005_snapshot.json +0 -2548
  350. package/src/db/migrations/meta/0006_snapshot.json +0 -2650
  351. package/src/db/migrations/meta/0007_snapshot.json +0 -2657
  352. package/src/db/migrations/meta/0008_snapshot.json +0 -2719
  353. package/src/db/migrations/meta/0009_snapshot.json +0 -2726
  354. package/src/db/migrations/meta/0010_snapshot.json +0 -2739
  355. package/src/db/migrations/meta/0011_snapshot.json +0 -3886
package/dist/money.js ADDED
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Money, in one unit, with the currency attached. Imports nothing:
3
+ * `@intelligo-dev/executions/pricing` is a zero-import leaf that client
4
+ * bundles reach, and it needs these types.
5
+ *
6
+ * **Micros, not minor units.** A chat turn on a cheap model costs a
7
+ * fraction of a cent; rounding it to whole cents overcharges by more than a
8
+ * third on every request.
9
+ *
10
+ * **Currency on the amount, not in a global.** A bare `number` lets one
11
+ * unit be sold as another; here the currency travels with the amount and
12
+ * `add` refuses to mix two.
13
+ */
14
+ /** Thrown for every misuse in this module, so callers can catch one type. */
15
+ export class MoneyError extends Error {
16
+ constructor(code, message) {
17
+ super(message);
18
+ this.code = code;
19
+ this.name = "MoneyError";
20
+ }
21
+ }
22
+ const MICROS_PER_UNIT = 1000000;
23
+ /**
24
+ * Currencies whose minor unit is not the usual hundredth; everything else
25
+ * is 2. Getting this wrong charges ¥100,000 instead of ¥1,000, because
26
+ * Stripe takes zero-decimal currencies in whole units.
27
+ */
28
+ const MINOR_EXPONENT = {
29
+ BIF: 0,
30
+ CLP: 0,
31
+ DJF: 0,
32
+ GNF: 0,
33
+ ISK: 0,
34
+ JPY: 0,
35
+ KMF: 0,
36
+ KRW: 0,
37
+ MGA: 0,
38
+ MNT: 0,
39
+ PYG: 0,
40
+ RWF: 0,
41
+ UGX: 0,
42
+ UYI: 0,
43
+ VND: 0,
44
+ VUV: 0,
45
+ XAF: 0,
46
+ XOF: 0,
47
+ XPF: 0,
48
+ BHD: 3,
49
+ IQD: 3,
50
+ JOD: 3,
51
+ KWD: 3,
52
+ LYD: 3,
53
+ OMR: 3,
54
+ TND: 3,
55
+ };
56
+ /**
57
+ * Validates and normalises an ISO-4217 code. Shape only: a list would go
58
+ * stale and block a deployment selling in a code it does not know.
59
+ * `minorExponent` gives an unknown code its default.
60
+ */
61
+ export function currency(code) {
62
+ const upper = code.toUpperCase();
63
+ if (!/^[A-Z]{3}$/.test(upper)) {
64
+ throw new MoneyError("invalid_currency", `"${code}" is not an ISO-4217 alphabetic code (three letters).`);
65
+ }
66
+ return upper;
67
+ }
68
+ /**
69
+ * An integer count of micros, up to `Number.MAX_SAFE_INTEGER` (about 9
70
+ * billion major units) — low enough to catch a value in the wrong unit.
71
+ */
72
+ export function micros(value) {
73
+ if (!Number.isInteger(value)) {
74
+ throw new MoneyError("not_an_integer", `Micros must be a whole number; received ${value}. Convert with fromMajor/fromMinor rather than multiplying by hand.`);
75
+ }
76
+ if (!Number.isSafeInteger(value)) {
77
+ throw new MoneyError("out_of_range", `${value} micros exceeds the safe integer range.`);
78
+ }
79
+ return value;
80
+ }
81
+ export function money(amount, code) {
82
+ return { amount: micros(amount), currency: currency(code) };
83
+ }
84
+ /** How many decimal places this currency's minor unit has. */
85
+ export function minorExponent(code) {
86
+ return MINOR_EXPONENT[code] ?? 2;
87
+ }
88
+ /** `12.34` USD → `12_340_000` micros. */
89
+ export function fromMajor(value, code) {
90
+ return {
91
+ amount: micros(Math.round(value * MICROS_PER_UNIT)),
92
+ currency: currency(code),
93
+ };
94
+ }
95
+ /** `1234` cents → `12_340_000` micros. */
96
+ export function fromMinor(value, code) {
97
+ const c = currency(code);
98
+ const scale = MICROS_PER_UNIT / 10 ** minorExponent(c);
99
+ return { amount: micros(Math.round(value * scale)), currency: c };
100
+ }
101
+ /**
102
+ * The integer a payment provider wants: whole units for a zero-decimal
103
+ * currency, hundredths for most, thousandths for a few.
104
+ *
105
+ * Rounds up. A fraction of a minor unit is money the deployment has
106
+ * already spent, and rounding it away means eating the difference on
107
+ * every transaction.
108
+ */
109
+ export function toMinor(value) {
110
+ const scale = MICROS_PER_UNIT / 10 ** minorExponent(value.currency);
111
+ return Math.ceil(value.amount / scale);
112
+ }
113
+ /** The amount as a plain decimal number, for display and for charts. */
114
+ export function toMajor(value) {
115
+ return value.amount / MICROS_PER_UNIT;
116
+ }
117
+ export const zero = (code) => ({
118
+ amount: 0,
119
+ currency: currency(code),
120
+ });
121
+ function sameCurrency(a, b, op) {
122
+ if (a.currency !== b.currency) {
123
+ throw new MoneyError("currency_mismatch", `Cannot ${op} ${a.currency} and ${b.currency}. Convert one first — an exchange rate is a decision, not a coercion.`);
124
+ }
125
+ }
126
+ export function add(a, b) {
127
+ sameCurrency(a, b, "add");
128
+ return { amount: micros(a.amount + b.amount), currency: a.currency };
129
+ }
130
+ export function subtract(a, b) {
131
+ sameCurrency(a, b, "subtract");
132
+ return { amount: micros(a.amount - b.amount), currency: a.currency };
133
+ }
134
+ /** Scale by a plain factor — a margin multiplier, a percentage, a count. */
135
+ export function multiply(value, factor) {
136
+ if (!Number.isFinite(factor)) {
137
+ throw new MoneyError("invalid_factor", `Factor must be finite.`);
138
+ }
139
+ return {
140
+ amount: micros(Math.ceil(value.amount * factor)),
141
+ currency: value.currency,
142
+ };
143
+ }
144
+ export function compare(a, b) {
145
+ sameCurrency(a, b, "compare");
146
+ return a.amount === b.amount ? 0 : a.amount < b.amount ? -1 : 1;
147
+ }
148
+ export const isZero = (value) => value.amount === 0;
149
+ export const isNegative = (value) => value.amount < 0;
150
+ /**
151
+ * Convert at an explicit rate, expressed in micros so the rate itself
152
+ * carries no float error: `3_450_000_000` is 3450.0.
153
+ *
154
+ * There is no ambient rate and no default. A framework that guesses an
155
+ * exchange rate is inventing money.
156
+ */
157
+ export function convert(value, to, rateMicros) {
158
+ const target = currency(to);
159
+ if (!Number.isInteger(rateMicros) || rateMicros <= 0) {
160
+ throw new MoneyError("invalid_rate", `Rate must be a positive integer number of micros; received ${rateMicros}.`);
161
+ }
162
+ if (target === value.currency) {
163
+ if (rateMicros !== MICROS_PER_UNIT) {
164
+ throw new MoneyError("invalid_rate", `Converting ${value.currency} to itself at ${rateMicros / MICROS_PER_UNIT} is not a conversion.`);
165
+ }
166
+ return value;
167
+ }
168
+ return {
169
+ amount: micros(Math.ceil((value.amount * rateMicros) / MICROS_PER_UNIT)),
170
+ currency: target,
171
+ };
172
+ }
173
+ /** Two significant digits is enough to read a sub-cent amount by. */
174
+ const SIGNIFICANT_DIGITS = 2;
175
+ /**
176
+ * How many decimals an amount needs to be legible.
177
+ *
178
+ * The currency's own minor unit, except when that would render a real
179
+ * charge as nothing: one chat turn costs a fraction of a cent, and a
180
+ * usage page that says every request cost `$0.00` is worse than one
181
+ * that says `$0.0048`. Below the minor unit the amount is shown to two
182
+ * significant digits, capped at the six decimals micros can hold.
183
+ */
184
+ export function displayFractionDigits(value) {
185
+ const digits = minorExponent(value.currency);
186
+ const major = Math.abs(toMajor(value));
187
+ // Zero, and anything that still rounds to a visible minor unit, reads
188
+ // the way the currency is normally written.
189
+ if (major === 0 || major >= 10 ** -digits / 2)
190
+ return digits;
191
+ const leadingZeros = Math.floor(-Math.log10(major));
192
+ return Math.min(6, leadingZeros + SIGNIFICANT_DIGITS);
193
+ }
194
+ /**
195
+ * Formats for a human, in their locale. `Intl` owns the symbol, its
196
+ * position and the separators.
197
+ */
198
+ export function formatMoney(value, locale, options = {}) {
199
+ const digits = displayFractionDigits(value);
200
+ return new Intl.NumberFormat(locale, {
201
+ style: "currency",
202
+ currency: value.currency,
203
+ minimumFractionDigits: digits,
204
+ maximumFractionDigits: digits,
205
+ ...options,
206
+ }).format(toMajor(value));
207
+ }
208
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,11 @@
1
1
  /**
2
- * Notifications Module
3
- *
4
- * CRUD operations for user notifications. These are used by server actions
5
- * in the consumer application to power the notification bell, list, and
6
- * mark-as-read functionality.
7
- *
8
- * Notifications are user-scoped (not workspace-scoped) so a user can see
9
- * all their notifications across workspaces.
10
- */
11
- import type { CreateNotificationParams } from "./types";
12
- export type { NotificationType, CreateNotificationParams } from "./types";
13
- export { triggerQuotaNotification, triggerTrialNotification, triggerPaymentFailedNotification, triggerTeamMemberJoinedNotification, } from "./triggers";
14
- /**
15
- * Create a new notification for a user
16
- *
17
- * Serializes metadata to JSON string if provided.
18
- * Returns the created notification.
2
+ * User notifications. User-scoped, not workspace-scoped, so a user sees
3
+ * their notifications from every workspace.
19
4
  */
5
+ import type { CreateNotificationParams } from "./types.js";
6
+ export type { NotificationType, CreateNotificationParams } from "./types.js";
7
+ export { triggerQuotaNotification, triggerTrialNotification, triggerPaymentFailedNotification, triggerTeamMemberJoinedNotification, } from "./triggers.js";
8
+ /** Creates a notification; `metadata` is stored as a JSON string. */
20
9
  export declare function createNotification(params: CreateNotificationParams): Promise<{
21
10
  id: string;
22
11
  createdAt: Date;
@@ -28,12 +17,7 @@ export declare function createNotification(params: CreateNotificationParams): Pr
28
17
  message: string;
29
18
  isRead: boolean;
30
19
  } | undefined>;
31
- /**
32
- * Get unread notifications for a user
33
- *
34
- * Returns notifications where isRead is false, ordered by newest first.
35
- * Parses metadata JSON string back to object.
36
- */
20
+ /** The user's unread notifications, newest first. */
37
21
  export declare function getUnreadNotifications(userId: string, limit?: number): Promise<({
38
22
  id: string;
39
23
  userId: string;
@@ -47,12 +31,7 @@ export declare function getUnreadNotifications(userId: string, limit?: number):
47
31
  } & {
48
32
  metadata: Record<string, unknown> | null;
49
33
  })[]>;
50
- /**
51
- * Get all notifications for a user (read and unread)
52
- *
53
- * Returns notifications ordered by newest first.
54
- * Parses metadata JSON string back to object.
55
- */
34
+ /** All of the user's notifications, newest first. */
56
35
  export declare function getNotifications(userId: string, limit?: number): Promise<({
57
36
  id: string;
58
37
  userId: string;
@@ -66,21 +45,8 @@ export declare function getNotifications(userId: string, limit?: number): Promis
66
45
  } & {
67
46
  metadata: Record<string, unknown> | null;
68
47
  })[]>;
69
- /**
70
- * Get count of unread notifications for a user
71
- *
72
- * Used for the notification bell badge number.
73
- */
74
48
  export declare function getNotificationCount(userId: string): Promise<number>;
75
- /**
76
- * Mark a single notification as read
77
- *
78
- * Security: requires both notificationId and userId to ensure
79
- * users can only mark their own notifications.
80
- */
49
+ /** Filters on userId as well, so users can only mark their own. */
81
50
  export declare function markAsRead(notificationId: string, userId: string): Promise<void>;
82
- /**
83
- * Mark all unread notifications as read for a user
84
- */
85
51
  export declare function markAllAsRead(userId: string): Promise<void>;
86
52
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAGxD,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAG1E,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,mCAAmC,GACpC,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB;;;;;;;;;;eAcxE;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW;;;;;;;;;;;cAoFD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;MAxEhD;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW;;;;;;;;;;;cAgEtD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;MAvDhD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAUtE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,iBAOjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAExD,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE1E,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,mCAAmC,GACpC,MAAM,YAAY,CAAC;AAEpB,qEAAqE;AACrE,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB;;;;;;;;;;eAcxE;AAED,qDAAqD;AACrD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW;;;;;;;;;;;cA6DD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;MAjDhD;AAED,qDAAqD;AACrD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW;;;;;;;;;;;cA8CtD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;MArChD;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;AAED,mEAAmE;AACnE,wBAAsB,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAUtE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,iBAOjD"}
@@ -1,24 +1,12 @@
1
1
  /**
2
- * Notifications Module
3
- *
4
- * CRUD operations for user notifications. These are used by server actions
5
- * in the consumer application to power the notification bell, list, and
6
- * mark-as-read functionality.
7
- *
8
- * Notifications are user-scoped (not workspace-scoped) so a user can see
9
- * all their notifications across workspaces.
2
+ * User notifications. User-scoped, not workspace-scoped, so a user sees
3
+ * their notifications from every workspace.
10
4
  */
11
- import { db } from "../db";
12
- import { notifications } from "../db/schema";
5
+ import { db } from "../db/index.js";
6
+ import { notifications } from "../db/schema/index.js";
13
7
  import { eq, and, desc, count } from "drizzle-orm";
14
- // Re-export trigger functions
15
- export { triggerQuotaNotification, triggerTrialNotification, triggerPaymentFailedNotification, triggerTeamMemberJoinedNotification, } from "./triggers";
16
- /**
17
- * Create a new notification for a user
18
- *
19
- * Serializes metadata to JSON string if provided.
20
- * Returns the created notification.
21
- */
8
+ export { triggerQuotaNotification, triggerTrialNotification, triggerPaymentFailedNotification, triggerTeamMemberJoinedNotification, } from "./triggers.js";
9
+ /** Creates a notification; `metadata` is stored as a JSON string. */
22
10
  export async function createNotification(params) {
23
11
  const [notification] = await db
24
12
  .insert(notifications)
@@ -33,12 +21,7 @@ export async function createNotification(params) {
33
21
  .returning();
34
22
  return notification;
35
23
  }
36
- /**
37
- * Get unread notifications for a user
38
- *
39
- * Returns notifications where isRead is false, ordered by newest first.
40
- * Parses metadata JSON string back to object.
41
- */
24
+ /** The user's unread notifications, newest first. */
42
25
  export async function getUnreadNotifications(userId, limit = 20) {
43
26
  const rows = await db
44
27
  .select()
@@ -48,12 +31,7 @@ export async function getUnreadNotifications(userId, limit = 20) {
48
31
  .limit(limit);
49
32
  return rows.map(parseMetadata);
50
33
  }
51
- /**
52
- * Get all notifications for a user (read and unread)
53
- *
54
- * Returns notifications ordered by newest first.
55
- * Parses metadata JSON string back to object.
56
- */
34
+ /** All of the user's notifications, newest first. */
57
35
  export async function getNotifications(userId, limit = 50) {
58
36
  const rows = await db
59
37
  .select()
@@ -63,11 +41,6 @@ export async function getNotifications(userId, limit = 50) {
63
41
  .limit(limit);
64
42
  return rows.map(parseMetadata);
65
43
  }
66
- /**
67
- * Get count of unread notifications for a user
68
- *
69
- * Used for the notification bell badge number.
70
- */
71
44
  export async function getNotificationCount(userId) {
72
45
  const [result] = await db
73
46
  .select({ count: count() })
@@ -75,32 +48,19 @@ export async function getNotificationCount(userId) {
75
48
  .where(and(eq(notifications.userId, userId), eq(notifications.isRead, false)));
76
49
  return result?.count ?? 0;
77
50
  }
78
- /**
79
- * Mark a single notification as read
80
- *
81
- * Security: requires both notificationId and userId to ensure
82
- * users can only mark their own notifications.
83
- */
51
+ /** Filters on userId as well, so users can only mark their own. */
84
52
  export async function markAsRead(notificationId, userId) {
85
53
  await db
86
54
  .update(notifications)
87
55
  .set({ isRead: true })
88
56
  .where(and(eq(notifications.id, notificationId), eq(notifications.userId, userId)));
89
57
  }
90
- /**
91
- * Mark all unread notifications as read for a user
92
- */
93
58
  export async function markAllAsRead(userId) {
94
59
  await db
95
60
  .update(notifications)
96
61
  .set({ isRead: true })
97
62
  .where(and(eq(notifications.userId, userId), eq(notifications.isRead, false)));
98
63
  }
99
- /**
100
- * Parse metadata JSON string back to object
101
- *
102
- * Returns notification with metadata as parsed object (or null if no metadata).
103
- */
104
64
  function parseMetadata(notification) {
105
65
  return {
106
66
  ...notification,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,12 @@
1
1
  /**
2
- * Notification Trigger Functions
3
- *
4
- * These functions create BOTH in-app notifications (via createNotification)
5
- * AND send emails (via email senders). They are the integration points that
6
- * connect application events to the notification + email infrastructure.
7
- *
8
- * Design:
9
- * - In-app notifications are awaited (fast DB inserts)
10
- * - Email sends are fire-and-forget (non-blocking, errors logged)
11
- * - These do NOT handle deduplication -- that's handled by notification_history
12
- * table from Phase 12's checkNotificationTriggers()
13
- *
14
- * Usage:
15
- * - Quota/trial triggers are called by Phase 12 notification system
16
- * - Payment failed trigger is called by billing email triggers
17
- * - Team member joined trigger is called by server actions
2
+ * Each trigger creates an in-app notification (awaited) and sends an email
3
+ * (fire-and-forget, errors logged). Deduplication is the caller's job.
18
4
  */
5
+ import { type Money } from "../money.js";
19
6
  /**
20
- * Trigger a quota warning or exceeded notification.
21
- * Creates an in-app notification and sends an email.
7
+ * The plan allowance is money, not tokens: `used` and `allowance` are
8
+ * amounts in the deployment's billing currency, and the copy prints
9
+ * them as such.
22
10
  */
23
11
  export declare function triggerQuotaNotification(params: {
24
12
  userId: string;
@@ -26,14 +14,10 @@ export declare function triggerQuotaNotification(params: {
26
14
  workspaceId: string;
27
15
  workspaceName: string;
28
16
  percentageUsed: number;
29
- tokensUsed: number;
30
- tokensLimit: number;
17
+ used: Money;
18
+ allowance: Money;
31
19
  isExceeded: boolean;
32
20
  }): Promise<void>;
33
- /**
34
- * Trigger a trial credits warning or depleted notification.
35
- * Creates an in-app notification and sends an email.
36
- */
37
21
  export declare function triggerTrialNotification(params: {
38
22
  userId: string;
39
23
  userEmail: string;
@@ -44,10 +28,6 @@ export declare function triggerTrialNotification(params: {
44
28
  percentageRemaining: number;
45
29
  isDepleted: boolean;
46
30
  }): Promise<void>;
47
- /**
48
- * Trigger a payment failed notification.
49
- * Creates an in-app notification and sends an email.
50
- */
51
31
  export declare function triggerPaymentFailedNotification(params: {
52
32
  userId: string;
53
33
  userEmail: string;
@@ -55,10 +35,7 @@ export declare function triggerPaymentFailedNotification(params: {
55
35
  workspaceName: string;
56
36
  amount: string;
57
37
  }): Promise<void>;
58
- /**
59
- * Trigger a team member joined notification.
60
- * Creates an in-app notification ONLY (no email for this event).
61
- */
38
+ /** In-app only: this event sends no email. */
62
39
  export declare function triggerTeamMemberJoinedNotification(params: {
63
40
  userId: string;
64
41
  workspaceId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../../src/notifications/triggers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAaH;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAMD;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChB;AAMD;;;GAGG;AACH,wBAAsB,gCAAgC,CAAC,MAAM,EAAE;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhB;AAMD;;;GAGG;AACH,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAahB"}
1
+ {"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../../src/notifications/triggers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAKnD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAED,wBAAsB,gCAAgC,CAAC,MAAM,EAAE;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhB;AAED,8CAA8C;AAC9C,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhB"}
@@ -1,69 +1,49 @@
1
1
  /**
2
- * Notification Trigger Functions
3
- *
4
- * These functions create BOTH in-app notifications (via createNotification)
5
- * AND send emails (via email senders). They are the integration points that
6
- * connect application events to the notification + email infrastructure.
7
- *
8
- * Design:
9
- * - In-app notifications are awaited (fast DB inserts)
10
- * - Email sends are fire-and-forget (non-blocking, errors logged)
11
- * - These do NOT handle deduplication -- that's handled by notification_history
12
- * table from Phase 12's checkNotificationTriggers()
13
- *
14
- * Usage:
15
- * - Quota/trial triggers are called by Phase 12 notification system
16
- * - Payment failed trigger is called by billing email triggers
17
- * - Team member joined trigger is called by server actions
2
+ * Each trigger creates an in-app notification (awaited) and sends an email
3
+ * (fire-and-forget, errors logged). Deduplication is the caller's job.
18
4
  */
19
- import { createNotification } from "./index";
20
- import { sendQuotaWarningEmail, sendTrialWarningEmail, sendPaymentFailedEmail, } from "../email/senders";
21
- // ---------------------------------------------------------------------------
22
- // Quota Notifications (QUOTA-08, QUOTA-09)
23
- // ---------------------------------------------------------------------------
5
+ import { createNotification } from "./index.js";
6
+ import { sendQuotaWarningEmail, sendTrialWarningEmail, sendPaymentFailedEmail, } from "../email/senders.js";
7
+ import { formatMoney } from "../money.js";
8
+ /** The locale the framework's own notification and email copy is written in. */
9
+ const COPY_LOCALE = "en";
24
10
  /**
25
- * Trigger a quota warning or exceeded notification.
26
- * Creates an in-app notification and sends an email.
11
+ * The plan allowance is money, not tokens: `used` and `allowance` are
12
+ * amounts in the deployment's billing currency, and the copy prints
13
+ * them as such.
27
14
  */
28
15
  export async function triggerQuotaNotification(params) {
29
16
  const upgradeUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
30
- // Create in-app notification (awaited -- fast DB insert)
17
+ const used = formatMoney(params.used, COPY_LOCALE);
18
+ const allowance = formatMoney(params.allowance, COPY_LOCALE);
31
19
  await createNotification({
32
20
  userId: params.userId,
33
21
  workspaceId: params.workspaceId,
34
22
  type: params.isExceeded ? "quota_warning_100" : "quota_warning_80",
35
- title: params.isExceeded ? "Quota Exceeded" : "Quota Warning",
23
+ title: params.isExceeded ? "Allowance Used Up" : "Allowance Warning",
36
24
  message: params.isExceeded
37
- ? `Your workspace "${params.workspaceName}" has used all ${params.tokensLimit.toLocaleString()} tokens this month. Upgrade your plan for more tokens.`
38
- : `Your workspace "${params.workspaceName}" has used ${params.percentageUsed}% of its monthly token quota.`,
25
+ ? `Your workspace "${params.workspaceName}" has used all of its ${allowance} monthly allowance. Upgrade your plan for more.`
26
+ : `Your workspace "${params.workspaceName}" has used ${used} of its ${allowance} monthly allowance (${params.percentageUsed}%).`,
39
27
  metadata: {
40
28
  workspaceName: params.workspaceName,
41
29
  percentageUsed: params.percentageUsed,
42
- tokensUsed: params.tokensUsed,
43
- tokensLimit: params.tokensLimit,
30
+ usedMicros: params.used.amount,
31
+ allowanceMicros: params.allowance.amount,
32
+ currency: params.allowance.currency,
44
33
  },
45
34
  });
46
- // Send email (fire-and-forget -- non-blocking)
47
35
  sendQuotaWarningEmail({
48
36
  to: params.userEmail,
49
37
  workspaceName: params.workspaceName,
50
38
  percentageUsed: params.percentageUsed,
51
- tokensUsed: params.tokensUsed,
52
- tokensLimit: params.tokensLimit,
39
+ used: params.used,
40
+ allowance: params.allowance,
53
41
  upgradeUrl,
54
42
  isExceeded: params.isExceeded,
55
43
  }).catch((err) => console.error("[Email] Failed to send quota warning:", err));
56
44
  }
57
- // ---------------------------------------------------------------------------
58
- // Trial Notifications (TRIAL-04, TRIAL-05)
59
- // ---------------------------------------------------------------------------
60
- /**
61
- * Trigger a trial credits warning or depleted notification.
62
- * Creates an in-app notification and sends an email.
63
- */
64
45
  export async function triggerTrialNotification(params) {
65
46
  const upgradeUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
66
- // Create in-app notification (awaited -- fast DB insert)
67
47
  await createNotification({
68
48
  userId: params.userId,
69
49
  workspaceId: params.workspaceId,
@@ -81,7 +61,6 @@ export async function triggerTrialNotification(params) {
81
61
  percentageRemaining: params.percentageRemaining,
82
62
  },
83
63
  });
84
- // Send email (fire-and-forget -- non-blocking)
85
64
  sendTrialWarningEmail({
86
65
  to: params.userEmail,
87
66
  workspaceName: params.workspaceName,
@@ -92,16 +71,8 @@ export async function triggerTrialNotification(params) {
92
71
  isDepleted: params.isDepleted,
93
72
  }).catch((err) => console.error("[Email] Failed to send trial warning:", err));
94
73
  }
95
- // ---------------------------------------------------------------------------
96
- // Payment Failed Notification
97
- // ---------------------------------------------------------------------------
98
- /**
99
- * Trigger a payment failed notification.
100
- * Creates an in-app notification and sends an email.
101
- */
102
74
  export async function triggerPaymentFailedNotification(params) {
103
75
  const updatePaymentUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
104
- // Create in-app notification (awaited -- fast DB insert)
105
76
  await createNotification({
106
77
  userId: params.userId,
107
78
  workspaceId: params.workspaceId,
@@ -113,7 +84,6 @@ export async function triggerPaymentFailedNotification(params) {
113
84
  amount: params.amount,
114
85
  },
115
86
  });
116
- // Send email (fire-and-forget -- non-blocking)
117
87
  sendPaymentFailedEmail({
118
88
  to: params.userEmail,
119
89
  workspaceName: params.workspaceName,
@@ -121,15 +91,8 @@ export async function triggerPaymentFailedNotification(params) {
121
91
  updatePaymentUrl,
122
92
  }).catch((err) => console.error("[Email] Failed to send payment failed:", err));
123
93
  }
124
- // ---------------------------------------------------------------------------
125
- // Team Member Joined Notification
126
- // ---------------------------------------------------------------------------
127
- /**
128
- * Trigger a team member joined notification.
129
- * Creates an in-app notification ONLY (no email for this event).
130
- */
94
+ /** In-app only: this event sends no email. */
131
95
  export async function triggerTeamMemberJoinedNotification(params) {
132
- // Create in-app notification only (no email for team member joined events)
133
96
  await createNotification({
134
97
  userId: params.userId,
135
98
  workspaceId: params.workspaceId,