@apart-tech/intelligence-core 1.15.2 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/index.d.ts +4 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/services/__tests__/search-service.test.js +3 -3
  6. package/dist/services/__tests__/search-service.test.js.map +1 -1
  7. package/dist/services/billing-event-service.d.ts +22 -0
  8. package/dist/services/billing-event-service.d.ts.map +1 -0
  9. package/dist/services/billing-event-service.js +30 -0
  10. package/dist/services/billing-event-service.js.map +1 -0
  11. package/dist/services/document-service.d.ts +3 -1
  12. package/dist/services/document-service.d.ts.map +1 -1
  13. package/dist/services/document-service.js +7 -1
  14. package/dist/services/document-service.js.map +1 -1
  15. package/dist/services/quota-service.d.ts +43 -0
  16. package/dist/services/quota-service.d.ts.map +1 -0
  17. package/dist/services/quota-service.js +148 -0
  18. package/dist/services/quota-service.js.map +1 -0
  19. package/dist/services/quota-service.test.d.ts +2 -0
  20. package/dist/services/quota-service.test.d.ts.map +1 -0
  21. package/dist/services/quota-service.test.js +165 -0
  22. package/dist/services/quota-service.test.js.map +1 -0
  23. package/dist/services/search-service.d.ts +7 -0
  24. package/dist/services/search-service.d.ts.map +1 -1
  25. package/dist/services/search-service.js +68 -23
  26. package/dist/services/search-service.js.map +1 -1
  27. package/dist/services/search-service.test.d.ts +2 -0
  28. package/dist/services/search-service.test.d.ts.map +1 -0
  29. package/dist/services/search-service.test.js +65 -0
  30. package/dist/services/search-service.test.js.map +1 -0
  31. package/dist/services/usage-service.d.ts +49 -2
  32. package/dist/services/usage-service.d.ts.map +1 -1
  33. package/dist/services/usage-service.js +109 -19
  34. package/dist/services/usage-service.js.map +1 -1
  35. package/dist/services/usage-service.test.d.ts +2 -0
  36. package/dist/services/usage-service.test.d.ts.map +1 -0
  37. package/dist/services/usage-service.test.js +191 -0
  38. package/dist/services/usage-service.test.js.map +1 -0
  39. package/package.json +1 -1
  40. package/prisma/schema.prisma +90 -5
@@ -0,0 +1,165 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { QuotaService, QuotaError } from "./quota-service.js";
3
+ import { UsageService } from "./usage-service.js";
4
+ const ORG_ID = "org-1";
5
+ function makeMockUsageService(overrides) {
6
+ const defaults = {
7
+ plan: "free",
8
+ nodes: 10,
9
+ apiCalls: 0,
10
+ members: 1,
11
+ ocrPages: 0,
12
+ storageBytes: 0,
13
+ agentRuns: 0,
14
+ ...overrides,
15
+ };
16
+ return {
17
+ getUsage: vi.fn(async () => ({
18
+ plan: defaults.plan,
19
+ limits: UsageService.getPlanLimits(defaults.plan),
20
+ usage: {
21
+ nodes: defaults.nodes,
22
+ apiCalls: defaults.apiCalls,
23
+ members: defaults.members,
24
+ ocrPages: defaults.ocrPages,
25
+ storageBytes: defaults.storageBytes,
26
+ agentRuns: defaults.agentRuns,
27
+ },
28
+ stripeCustomerId: null,
29
+ stripeSubscriptionId: null,
30
+ currentPeriodEnd: null,
31
+ })),
32
+ getStorageUsed: vi.fn(async () => defaults.storageBytes),
33
+ };
34
+ }
35
+ function makeMockDb(opts) {
36
+ return {
37
+ quotaOverride: {
38
+ findFirst: vi.fn(async ({ where }) => {
39
+ const match = opts?.overrides?.find((o) => o.resource === where.resource);
40
+ if (match) {
41
+ return { overrideLimit: match.overrideLimit, expiresAt: match.expiresAt };
42
+ }
43
+ return null;
44
+ }),
45
+ },
46
+ membership: {
47
+ count: vi.fn(async () => opts?.memberCount ?? 1),
48
+ },
49
+ };
50
+ }
51
+ describe("QuotaService", () => {
52
+ describe("free tier", () => {
53
+ it("allows OCR within budget", async () => {
54
+ const usage = makeMockUsageService({ ocrPages: 10 });
55
+ const db = makeMockDb();
56
+ const svc = new QuotaService(db, usage);
57
+ // 10 existing + 5 = 15, limit is 25
58
+ await expect(svc.checkOcrQuota(ORG_ID, 5)).resolves.toBeUndefined();
59
+ });
60
+ it("blocks OCR over budget", async () => {
61
+ const usage = makeMockUsageService({ ocrPages: 20 });
62
+ const db = makeMockDb();
63
+ const svc = new QuotaService(db, usage);
64
+ // 20 existing + 10 = 30, limit is 25
65
+ await expect(svc.checkOcrQuota(ORG_ID, 10)).rejects.toThrow(QuotaError);
66
+ });
67
+ it("blocks agent runs on free tier (limit is 0)", async () => {
68
+ const usage = makeMockUsageService({ agentRuns: 0 });
69
+ const db = makeMockDb();
70
+ const svc = new QuotaService(db, usage);
71
+ // 0 >= 0 → blocked
72
+ await expect(svc.checkAgentRunQuota(ORG_ID)).rejects.toThrow(QuotaError);
73
+ });
74
+ it("allows storage within budget", async () => {
75
+ const usage = makeMockUsageService({ storageBytes: 500_000_000 });
76
+ const db = makeMockDb();
77
+ const svc = new QuotaService(db, usage);
78
+ // 500MB + 100MB < 1GB
79
+ await expect(svc.checkStorageQuota(ORG_ID, 100_000_000)).resolves.toBeUndefined();
80
+ });
81
+ it("blocks storage over budget", async () => {
82
+ const usage = makeMockUsageService({ storageBytes: 1_000_000_000 });
83
+ const db = makeMockDb();
84
+ const svc = new QuotaService(db, usage);
85
+ // 1GB + 100MB > 1GB
86
+ await expect(svc.checkStorageQuota(ORG_ID, 100_000_000)).rejects.toThrow(QuotaError);
87
+ });
88
+ it("enforces file size limit for free tier (10 MB)", async () => {
89
+ const usage = makeMockUsageService();
90
+ const db = makeMockDb();
91
+ const svc = new QuotaService(db, usage);
92
+ await expect(svc.checkFileSizeLimit(ORG_ID, 11_000_000)).rejects.toThrow(QuotaError);
93
+ await expect(svc.checkFileSizeLimit(ORG_ID, 5_000_000)).resolves.toBeUndefined();
94
+ });
95
+ it("enforces page per document limit (20)", async () => {
96
+ const usage = makeMockUsageService();
97
+ const db = makeMockDb();
98
+ const svc = new QuotaService(db, usage);
99
+ await expect(svc.checkPagePerDocumentLimit(ORG_ID, 25)).rejects.toThrow(QuotaError);
100
+ await expect(svc.checkPagePerDocumentLimit(ORG_ID, 15)).resolves.toBeUndefined();
101
+ });
102
+ });
103
+ describe("pro tier", () => {
104
+ it("allows agent runs on pro tier", async () => {
105
+ const usage = makeMockUsageService({ plan: "pro", agentRuns: 10, members: 3 });
106
+ const db = makeMockDb({ memberCount: 3 });
107
+ const svc = new QuotaService(db, usage);
108
+ // 10 < 50 * 3 = 150
109
+ await expect(svc.checkAgentRunQuota(ORG_ID)).resolves.toBeUndefined();
110
+ });
111
+ it("scales OCR limit by seats", async () => {
112
+ const usage = makeMockUsageService({ plan: "pro", ocrPages: 900, members: 2 });
113
+ const db = makeMockDb({ memberCount: 2 });
114
+ const svc = new QuotaService(db, usage);
115
+ // 900 + 200 = 1100 > 500 * 2 = 1000
116
+ await expect(svc.checkOcrQuota(ORG_ID, 200)).rejects.toThrow(QuotaError);
117
+ // 900 + 50 = 950 < 1000
118
+ await expect(svc.checkOcrQuota(ORG_ID, 50)).resolves.toBeUndefined();
119
+ });
120
+ });
121
+ describe("quota overrides", () => {
122
+ it("uses override instead of plan limit", async () => {
123
+ const usage = makeMockUsageService({ ocrPages: 30 });
124
+ const db = makeMockDb({
125
+ overrides: [
126
+ { resource: "ocr_pages", overrideLimit: 100, expiresAt: null },
127
+ ],
128
+ });
129
+ const svc = new QuotaService(db, usage);
130
+ // Override is 100, usage is 30, adding 60 = 90 < 100
131
+ await expect(svc.checkOcrQuota(ORG_ID, 60)).resolves.toBeUndefined();
132
+ });
133
+ it("override allows agent runs on free tier", async () => {
134
+ const usage = makeMockUsageService({ agentRuns: 0 });
135
+ const db = makeMockDb({
136
+ overrides: [
137
+ { resource: "agent_runs", overrideLimit: 10, expiresAt: null },
138
+ ],
139
+ });
140
+ const svc = new QuotaService(db, usage);
141
+ // Override gives 10 agent runs, usage is 0
142
+ await expect(svc.checkAgentRunQuota(ORG_ID)).resolves.toBeUndefined();
143
+ });
144
+ });
145
+ describe("QuotaError", () => {
146
+ it("contains resource, current, limit, plan fields", async () => {
147
+ const usage = makeMockUsageService({ ocrPages: 30 });
148
+ const db = makeMockDb();
149
+ const svc = new QuotaService(db, usage);
150
+ try {
151
+ await svc.checkOcrQuota(ORG_ID, 10);
152
+ expect.unreachable();
153
+ }
154
+ catch (err) {
155
+ expect(err).toBeInstanceOf(QuotaError);
156
+ const qErr = err;
157
+ expect(qErr.resource).toBe("ocr_pages");
158
+ expect(qErr.current).toBe(30);
159
+ expect(qErr.limit).toBe(25);
160
+ expect(qErr.plan).toBe("free");
161
+ }
162
+ });
163
+ });
164
+ });
165
+ //# sourceMappingURL=quota-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-service.test.js","sourceRoot":"","sources":["../../src/services/quota-service.test.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,11 @@ import type { SearchOptions, SearchResult, EmbeddingProvider, ApartConfig } from
3
3
  import { type TenantContext } from "../db/tenant.js";
4
4
  import type { PiiEncryptionService } from "./pii-encryption-service.js";
5
5
  import type { PiiEncryptionOptions } from "./pii-encryption-service.js";
6
+ interface TimedResult<T> {
7
+ result: T;
8
+ ms: number;
9
+ }
10
+ export declare function timeBranch<T>(promise: Promise<T>): Promise<TimedResult<T>>;
6
11
  export declare class SearchService {
7
12
  private db;
8
13
  private embeddings;
@@ -33,6 +38,7 @@ export declare class SearchService {
33
38
  private trigramSearch;
34
39
  private stripQueryPii;
35
40
  private logPiiQuery;
41
+ private logSearchMetrics;
36
42
  /**
37
43
  * Generalized reciprocal rank fusion over N ranked lists.
38
44
  * Each list carries its own weight. Results appearing in multiple
@@ -41,4 +47,5 @@ export declare class SearchService {
41
47
  */
42
48
  private reciprocalRankFusion;
43
49
  }
50
+ export {};
44
51
  //# sourceMappingURL=search-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-service.d.ts","sourceRoot":"","sources":["../../src/services/search-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EAIZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAoBxE,qBAAa,aAAa;IAItB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,UAAU,CAAC;IARrB,OAAO,CAAC,SAAS,CAAgB;gBAGvB,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,WAAW,EAC3B,SAAS,CAAC,EAAE,aAAa,EACjB,aAAa,CAAC,EAAE,oBAAoB,YAAA,EACpC,UAAU,CAAC,EAAE,oBAAoB,YAAA;IAKrC,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA0C7D,OAAO,CAAC,iBAAiB;IAMzB;;;OAGG;YACW,mBAAmB;YA2DnB,cAAc;YA6Cd,aAAa;IAwC3B;;;;OAIG;YACW,eAAe;IA4D7B;;;OAGG;YACW,aAAa;IAmD3B,OAAO,CAAC,aAAa;YAWP,WAAW;IAoBzB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CA2C7B"}
1
+ {"version":3,"file":"search-service.d.ts","sourceRoot":"","sources":["../../src/services/search-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EAIZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAoBxE,UAAU,WAAW,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAIhF;AAED,qBAAa,aAAa;IAItB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,UAAU,CAAC;IARrB,OAAO,CAAC,SAAS,CAAgB;gBAGvB,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,WAAW,EAC3B,SAAS,CAAC,EAAE,aAAa,EACjB,aAAa,CAAC,EAAE,oBAAoB,YAAA,EACpC,UAAU,CAAC,EAAE,oBAAoB,YAAA;IAKrC,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA6D7D,OAAO,CAAC,iBAAiB;IAMzB;;;OAGG;YACW,mBAAmB;YA0DnB,cAAc;YA4Cd,aAAa;IAwC3B;;;;OAIG;YACW,eAAe;IAqE7B;;;OAGG;YACW,aAAa;IAmD3B,OAAO,CAAC,aAAa;YAWP,WAAW;YAoBX,gBAAgB;IA4B9B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CA2C7B"}
@@ -11,6 +11,11 @@ const NODE_COLUMNS_PREFIXED = Prisma.sql `n.id, n.type, n.title, n.content, n.me
11
11
  const MIN_FUZZY_QUERY_LENGTH = 3;
12
12
  // Maximum number of terms in a split-term ILIKE query to prevent query explosion.
13
13
  const MAX_ILIKE_TERMS = 10;
14
+ export async function timeBranch(promise) {
15
+ const start = performance.now();
16
+ const result = await promise;
17
+ return { result, ms: performance.now() - start };
18
+ }
14
19
  export class SearchService {
15
20
  db;
16
21
  embeddings;
@@ -38,26 +43,41 @@ export class SearchService {
38
43
  if (piiTypes.length > 0) {
39
44
  this.logPiiQuery(options.query, piiTypes, "search").catch(() => { });
40
45
  }
41
- // Run all search branches in parallel using stripped query
42
- // Chunk semantic search + fallback node semantic search run together
43
- const [chunkSemanticResults, nodeFallbackResults, keywordResults, substringResults, trigramResults] = await Promise.all([
44
- this.chunkSemanticSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters),
45
- this.semanticSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters),
46
- this.keywordSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters),
47
- this.substringSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters),
48
- this.trigramSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters),
46
+ // Embed query once for both semantic branches
47
+ const queryEmbedding = await this.embeddings.embed(strippedQuery, { inputType: "query" });
48
+ // Run all search branches in parallel using stripped query, with timing
49
+ const searchStart = performance.now();
50
+ const [chunkSemantic, nodeFallback, keyword, substring, trigram] = await Promise.all([
51
+ timeBranch(this.chunkSemanticSearch(queryEmbedding, limit, statuses, options.types, options.domainIds, options.tagFilters)),
52
+ timeBranch(this.semanticSearch(queryEmbedding, limit, statuses, options.types, options.domainIds, options.tagFilters)),
53
+ timeBranch(this.keywordSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters)),
54
+ timeBranch(this.substringSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters)),
55
+ timeBranch(this.trigramSearch(strippedQuery, limit, statuses, options.types, options.domainIds, options.tagFilters)),
49
56
  ]);
50
57
  // Merge chunk results with node-level fallback (for unchunked nodes)
51
- const chunkNodeIds = new Set(chunkSemanticResults.map((r) => r.node.id));
52
- const fallbackOnly = nodeFallbackResults.filter((r) => !chunkNodeIds.has(r.node.id));
53
- const semanticResults = [...chunkSemanticResults, ...fallbackOnly];
58
+ const chunkNodeIds = new Set(chunkSemantic.result.map((r) => r.node.id));
59
+ const fallbackOnly = nodeFallback.result.filter((r) => !chunkNodeIds.has(r.node.id));
60
+ const semanticResults = [...chunkSemantic.result, ...fallbackOnly];
54
61
  // N-branch reciprocal rank fusion
55
- return this.reciprocalRankFusion([
62
+ const merged = this.reciprocalRankFusion([
56
63
  { results: semanticResults, weight: this.config.search.semanticWeight },
57
- { results: keywordResults, weight: this.config.search.keywordWeight },
58
- { results: substringResults, weight: this.config.search.substringWeight },
59
- { results: trigramResults, weight: this.config.search.trigramWeight },
64
+ { results: keyword.result, weight: this.config.search.keywordWeight },
65
+ { results: substring.result, weight: this.config.search.substringWeight },
66
+ { results: trigram.result, weight: this.config.search.trigramWeight },
60
67
  ], limit);
68
+ const totalMs = performance.now() - searchStart;
69
+ // Fire-and-forget metrics log
70
+ this.logSearchMetrics({
71
+ query: strippedQuery,
72
+ chunkSemanticMs: chunkSemantic.ms,
73
+ nodeSemanticMs: nodeFallback.ms,
74
+ keywordMs: keyword.ms,
75
+ substringMs: substring.ms,
76
+ trigramMs: trigram.ms,
77
+ totalMs,
78
+ resultCount: merged.length,
79
+ }).catch(() => { });
80
+ return merged;
61
81
  }
62
82
  buildTagCondition(tagFilters) {
63
83
  if (!tagFilters || tagFilters.length === 0)
@@ -69,8 +89,7 @@ export class SearchService {
69
89
  * Chunk-level semantic search: finds the best-matching chunk per node,
70
90
  * returns the parent node with snippet from the best chunk.
71
91
  */
72
- async chunkSemanticSearch(query, limit, statuses, types, domainIds, tagFilters) {
73
- const queryEmbedding = await this.embeddings.embed(query, { inputType: "query" });
92
+ async chunkSemanticSearch(queryEmbedding, limit, statuses, types, domainIds, tagFilters) {
74
93
  const embeddingStr = `[${queryEmbedding.join(",")}]`;
75
94
  const typeCondition = types?.length
76
95
  ? Prisma.sql `n.type = ANY(${types}::text[])`
@@ -111,8 +130,7 @@ export class SearchService {
111
130
  snippetChunkIndex: row.chunk_index,
112
131
  }));
113
132
  }
114
- async semanticSearch(query, limit, statuses, types, domainIds, tagFilters) {
115
- const queryEmbedding = await this.embeddings.embed(query, { inputType: "query" });
133
+ async semanticSearch(queryEmbedding, limit, statuses, types, domainIds, tagFilters) {
116
134
  const embeddingStr = `[${queryEmbedding.join(",")}]`;
117
135
  const typeCondition = types?.length
118
136
  ? Prisma.sql `type = ANY(${types}::text[])`
@@ -189,15 +207,24 @@ export class SearchService {
189
207
  : Prisma.sql `TRUE`;
190
208
  const orgCondition = tenantWhere(this.tenantCtx);
191
209
  const tagCondition = this.buildTagCondition(tagFilters);
192
- // Build per-term conditions: each term must appear in title or content
193
- // (also checking with dots removed for punctuation-agnostic matching)
210
+ // Build per-term conditions: each term must appear in title or content.
211
+ // Normalize the search term (strip dots) instead of applying functions to columns,
212
+ // so that GIN trigram indexes on bare columns can be used.
194
213
  const termConditions = terms.map((term) => {
195
214
  const pattern = `%${term}%`;
215
+ const stripped = term.replace(/\./g, "");
216
+ if (stripped !== term && stripped.length > 0) {
217
+ const strippedPattern = `%${stripped}%`;
218
+ return Prisma.sql `(
219
+ title ILIKE ${pattern}
220
+ OR content ILIKE ${pattern}
221
+ OR title ILIKE ${strippedPattern}
222
+ OR content ILIKE ${strippedPattern}
223
+ )`;
224
+ }
196
225
  return Prisma.sql `(
197
226
  title ILIKE ${pattern}
198
227
  OR content ILIKE ${pattern}
199
- OR replace(title, '.', '') ILIKE ${pattern}
200
- OR replace(content, '.', '') ILIKE ${pattern}
201
228
  )`;
202
229
  });
203
230
  // Join all term conditions with AND
@@ -288,6 +315,24 @@ export class SearchService {
288
315
  )
289
316
  `;
290
317
  }
318
+ async logSearchMetrics(params) {
319
+ const queryHash = createHash("sha256").update(params.query).digest("hex");
320
+ await this.db.$executeRaw `
321
+ INSERT INTO search_metrics (id, organization_id, query_hash, chunk_semantic_ms, node_semantic_ms, keyword_ms, substring_ms, trigram_ms, total_ms, result_count)
322
+ VALUES (
323
+ gen_random_uuid(),
324
+ ${this.tenantCtx.organizationId}::uuid,
325
+ ${queryHash},
326
+ ${params.chunkSemanticMs},
327
+ ${params.nodeSemanticMs},
328
+ ${params.keywordMs},
329
+ ${params.substringMs},
330
+ ${params.trigramMs},
331
+ ${params.totalMs},
332
+ ${params.resultCount}
333
+ )
334
+ `;
335
+ }
291
336
  /**
292
337
  * Generalized reciprocal rank fusion over N ranked lists.
293
338
  * Each list carries its own weight. Results appearing in multiple
@@ -1 +1 @@
1
- {"version":3,"file":"search-service.js","sourceRoot":"","sources":["../../src/services/search-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-service.js","sourceRoot":"","sources":["../../src/services/search-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-service.test.d.ts","sourceRoot":"","sources":["../../src/services/search-service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { timeBranch } from "./search-service.js";
3
+ describe("timeBranch", () => {
4
+ it("returns the result and positive ms", async () => {
5
+ const { result, ms } = await timeBranch(Promise.resolve(42));
6
+ expect(result).toBe(42);
7
+ expect(ms).toBeGreaterThanOrEqual(0);
8
+ });
9
+ it("propagates errors from the wrapped promise", async () => {
10
+ await expect(timeBranch(Promise.reject(new Error("boom")))).rejects.toThrow("boom");
11
+ });
12
+ it("measures elapsed time", async () => {
13
+ const delay = (ms) => new Promise((r) => setTimeout(r, ms));
14
+ const { ms } = await timeBranch(delay(50));
15
+ // Allow for timer imprecision; should be at least 30ms
16
+ expect(ms).toBeGreaterThanOrEqual(30);
17
+ });
18
+ });
19
+ describe("SearchService.logSearchMetrics", () => {
20
+ it("calls $executeRaw with correct column shape", async () => {
21
+ // We test logSearchMetrics indirectly by constructing a SearchService
22
+ // and calling search() with a mock db. The fire-and-forget INSERT
23
+ // is the only raw query that writes to search_metrics.
24
+ const executeRaw = vi.fn().mockResolvedValue(1);
25
+ // Minimal mock to verify the INSERT statement shape
26
+ const mockDb = {
27
+ $executeRaw: executeRaw,
28
+ $queryRaw: vi.fn().mockResolvedValue([]),
29
+ };
30
+ // Import SearchService and construct with mocks
31
+ const { SearchService } = await import("./search-service.js");
32
+ const mockEmbeddings = {
33
+ embed: vi.fn().mockResolvedValue([0.1, 0.2, 0.3]),
34
+ };
35
+ const mockConfig = {
36
+ search: {
37
+ defaultLimit: 10,
38
+ includeDrafts: false,
39
+ semanticWeight: 1,
40
+ keywordWeight: 0.7,
41
+ substringWeight: 0.5,
42
+ trigramWeight: 0.3,
43
+ trigramThreshold: 0.3,
44
+ },
45
+ };
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ const service = new SearchService(mockDb, mockEmbeddings, mockConfig, { organizationId: "org-123" });
48
+ await service.search({ query: "test query" });
49
+ // Wait for the fire-and-forget logSearchMetrics to settle
50
+ await new Promise((r) => setTimeout(r, 50));
51
+ // The INSERT into search_metrics should have been called via $executeRaw
52
+ // (logPiiQuery also uses $executeRaw but only when PII is detected)
53
+ const searchMetricsCalls = executeRaw.mock.calls.filter((call) => {
54
+ // Tagged template calls have the first arg as TemplateStringsArray
55
+ const tmpl = call[0];
56
+ if (tmpl && typeof tmpl === "object" && "raw" in tmpl) {
57
+ const raw = tmpl.raw.join("");
58
+ return raw.includes("search_metrics");
59
+ }
60
+ return false;
61
+ });
62
+ expect(searchMetricsCalls.length).toBe(1);
63
+ });
64
+ });
65
+ //# sourceMappingURL=search-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-service.test.js","sourceRoot":"","sources":["../../src/services/search-service.test.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,13 @@ export interface PlanLimits {
3
3
  maxNodes: number;
4
4
  maxApiCallsPerMonth: number;
5
5
  maxMembers: number;
6
+ maxOcrPagesPerMonth: number;
7
+ maxStorageBytes: number;
8
+ maxAgentRunsPerMonth: number;
9
+ maxFileSizeBytes: number;
10
+ maxPagesPerDocument: number;
6
11
  }
12
+ export type UsageMetric = "nodes" | "apiCalls" | "members" | "ocrPages" | "storageBytes" | "agentRuns";
7
13
  export interface UsageSnapshot {
8
14
  plan: string;
9
15
  limits: PlanLimits;
@@ -11,6 +17,9 @@ export interface UsageSnapshot {
11
17
  nodes: number;
12
18
  apiCalls: number;
13
19
  members: number;
20
+ ocrPages: number;
21
+ storageBytes: number;
22
+ agentRuns: number;
14
23
  };
15
24
  stripeCustomerId: string | null;
16
25
  stripeSubscriptionId: string | null;
@@ -26,6 +35,10 @@ export interface UsageSnapshot {
26
35
  export declare class UsageService {
27
36
  private db;
28
37
  constructor(db: PrismaClient);
38
+ /**
39
+ * Get the base plan limits for a given plan name.
40
+ */
41
+ static getPlanLimits(plan: string): PlanLimits;
29
42
  /**
30
43
  * Get the full usage snapshot for an organization.
31
44
  */
@@ -35,11 +48,45 @@ export declare class UsageService {
35
48
  * Uses upsert to create or increment atomically.
36
49
  */
37
50
  incrementApiCalls(organizationId: string, count?: number): Promise<void>;
51
+ /**
52
+ * Increment the OCR pages counter for the current month.
53
+ */
54
+ incrementOcrPages(organizationId: string, count?: number): Promise<void>;
55
+ /**
56
+ * Increment the agent runs counter for the current month.
57
+ */
58
+ incrementAgentRuns(organizationId: string, count?: number): Promise<void>;
59
+ /**
60
+ * Get OCR pages used in the current period.
61
+ */
62
+ getOcrPagesUsed(organizationId: string): Promise<number>;
63
+ /**
64
+ * Get agent runs used in the current period.
65
+ */
66
+ getAgentRunsUsed(organizationId: string): Promise<number>;
67
+ /**
68
+ * Get total storage used by an org, computed as SUM(fileSizeBytes) from documents.
69
+ */
70
+ getStorageUsed(organizationId: string): Promise<number>;
71
+ /**
72
+ * Get usage history for a metric over the last N months.
73
+ */
74
+ getUsageHistory(organizationId: string, metric: string, months?: number): Promise<{
75
+ periodStart: Date;
76
+ count: number;
77
+ }[]>;
38
78
  /**
39
79
  * Check whether an organization has exceeded a specific limit.
40
80
  */
41
- isOverLimit(organizationId: string, metric: "nodes" | "apiCalls" | "members"): Promise<boolean>;
42
- private getApiCallCount;
81
+ isOverLimit(organizationId: string, metric: UsageMetric): Promise<boolean>;
82
+ /**
83
+ * Generic metric increment — upsert a usage_records row for the current period.
84
+ */
85
+ private incrementMetric;
86
+ /**
87
+ * Get the count for a metric in the current period.
88
+ */
89
+ private getMetricCount;
43
90
  /**
44
91
  * First day of the current month at midnight UTC.
45
92
  */
@@ -1 +1 @@
1
- {"version":3,"file":"usage-service.d.ts","sourceRoot":"","sources":["../../src/services/usage-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAeD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,gBAAgB,EAAE,IAAI,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAEpC;;OAEG;IACG,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA4B9D;;;OAGG;IACG,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjF;;OAEG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YAcvF,eAAe;IAiB7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAI3B"}
1
+ {"version":3,"file":"usage-service.d.ts","sourceRoot":"","sources":["../../src/services/usage-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAyBD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,cAAc,GAAG,WAAW,CAAC;AAEvG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,gBAAgB,EAAE,IAAI,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAEpC;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAI9C;;OAEG;IACG,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkC9D;;;OAGG;IACG,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjF;;OAEG;IACG,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjF;;OAEG;IACG,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF;;OAEG;IACG,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9D;;OAEG;IACG,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/D;;OAEG;IACG,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ7D;;OAEG;IACG,eAAe,CACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAU,GACjB,OAAO,CAAC;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAmBlD;;OAEG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBhF;;OAEG;YACW,eAAe;IAwB7B;;OAEG;YACW,cAAc;IAiB5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAI3B"}