@intelligo-dev/core 1.0.0-beta.14 → 1.0.0-beta.15

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.
@@ -29,6 +29,13 @@
29
29
  "when": 1790179158533,
30
30
  "tag": "0003_local_payments",
31
31
  "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "7",
36
+ "when": 1790259860351,
37
+ "tag": "0004_usage_subjects",
38
+ "breakpoints": true
32
39
  }
33
40
  ]
34
41
  }
@@ -27,10 +27,12 @@ export const usageRecords = pgTable(
27
27
  workspaceId: text("workspace_id")
28
28
  .notNull()
29
29
  .references(() => organization.id, { onDelete: "cascade" }),
30
- userId: text("user_id")
31
- .notNull()
32
- .references(() => users.id, { onDelete: "cascade" }),
33
- type: text("type").notNull(), // "ai_tokens", "api_call"
30
+ /** Null for work no signed-in user started: a job, an anonymous request. */
31
+ userId: text("user_id").references(() => users.id, {
32
+ onDelete: "cascade",
33
+ }),
34
+ /** "ai_tokens", "fixed_charge", or "credit" (a refund or goodwill credit, negative). */
35
+ type: text("type").notNull(),
34
36
  model: text("model"), // "gpt-4o", "gpt-4o-mini"
35
37
  agent: text("agent"), // the product's agent slug
36
38
  inputTokens: integer("input_tokens").notNull().default(0),
@@ -155,7 +157,8 @@ export const trialCredits = pgTable(
155
157
  );
156
158
 
157
159
  /**
158
- * One row per (workspace, endpoint, minute bucket). Each request upserts the
160
+ * One row per (subject, endpoint, bucket); a window other than a minute
161
+ * is part of the endpoint key (`export@86400s`). Each request upserts the
159
162
  * row and atomically increments `count`, so N concurrent requests observe
160
163
  * 1..N and exactly `limit` are admitted. Old buckets are deleted by the
161
164
  * billing-maintenance job.
@@ -164,13 +167,18 @@ export const rateLimitEntries = pgTable(
164
167
  "rate_limit_entries",
165
168
  {
166
169
  id: text("id").primaryKey(),
167
- workspaceId: text("workspace_id")
168
- .notNull()
169
- .references(() => organization.id, { onDelete: "cascade" }),
170
+ /**
171
+ * Who is counted: a workspace id, or any key the caller chose (a
172
+ * hashed IP). Not a foreign key, so a subject need not be a
173
+ * workspace; rows expire with their window either way.
174
+ */
175
+ workspaceId: text("workspace_id").notNull(),
170
176
  endpoint: text("endpoint").notNull().default("chat"),
171
177
  requestedAt: timestamp("requested_at").notNull().defaultNow(),
172
- /** Floored minute bucket for unique constraint enforcement */
178
+ /** The start of the window this row counts, floored to its length. */
173
179
  minuteBucket: timestamp("minute_bucket").notNull(),
180
+ /** The window's length, for cleanup: a row expires when its window has closed. */
181
+ windowSeconds: integer("window_seconds").notNull().default(60),
174
182
  /** Requests observed in this bucket — incremented via upsert */
175
183
  count: integer("count").notNull().default(1),
176
184
  },
package/src/env.ts CHANGED
@@ -76,6 +76,7 @@ export function validateEnv(): {
76
76
  } {
77
77
  const errors: string[] = [];
78
78
  const warnings: string[] = [];
79
+ const unsetOptional: string[] = [];
79
80
 
80
81
  for (const envVar of ENV_VARS) {
81
82
  let value = process.env[envVar.name];
@@ -97,9 +98,7 @@ export function validateEnv(): {
97
98
  `Missing required env var: ${envVar.name} — ${envVar.description}`
98
99
  );
99
100
  } else {
100
- warnings.push(
101
- `Missing optional env var: ${envVar.name} — ${envVar.description}`
102
- );
101
+ unsetOptional.push(envVar.name);
103
102
  }
104
103
  continue;
105
104
  }
@@ -113,6 +112,14 @@ export function validateEnv(): {
113
112
  }
114
113
  }
115
114
 
115
+ // One line for all of them: each is a feature left off, which is the
116
+ // point of its being optional, not a fault to repeat on every boot.
117
+ if (unsetOptional.length > 0) {
118
+ warnings.push(
119
+ `Optional env vars not set, their features stay off: ${unsetOptional.join(", ")}`
120
+ );
121
+ }
122
+
116
123
  // Resend rejects a send without a sender on a verified domain, and the
117
124
  // framework has no domain of its own to fall back on. Loops takes the
118
125
  // sender from each template, so only Resend is checked.