@apart-tech/intelligence-core 1.18.0 → 1.19.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 (35) hide show
  1. package/dist/auth/ability.d.ts +1 -1
  2. package/dist/auth/ability.d.ts.map +1 -1
  3. package/dist/auth/ability.js +15 -0
  4. package/dist/auth/ability.js.map +1 -1
  5. package/dist/auth/ability.test.js +45 -2
  6. package/dist/auth/ability.test.js.map +1 -1
  7. package/dist/db/tenant.d.ts.map +1 -1
  8. package/dist/db/tenant.js +10 -0
  9. package/dist/db/tenant.js.map +1 -1
  10. package/dist/index.d.ts +10 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +6 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/services/chat-context-service.d.ts +33 -0
  15. package/dist/services/chat-context-service.d.ts.map +1 -0
  16. package/dist/services/chat-context-service.js +110 -0
  17. package/dist/services/chat-context-service.js.map +1 -0
  18. package/dist/services/chat-service.d.ts +83 -0
  19. package/dist/services/chat-service.d.ts.map +1 -0
  20. package/dist/services/chat-service.js +103 -0
  21. package/dist/services/chat-service.js.map +1 -0
  22. package/dist/services/chat-usage-service.d.ts +36 -0
  23. package/dist/services/chat-usage-service.d.ts.map +1 -0
  24. package/dist/services/chat-usage-service.js +89 -0
  25. package/dist/services/chat-usage-service.js.map +1 -0
  26. package/dist/services/llm-router-service.d.ts +29 -0
  27. package/dist/services/llm-router-service.d.ts.map +1 -0
  28. package/dist/services/llm-router-service.js +70 -0
  29. package/dist/services/llm-router-service.js.map +1 -0
  30. package/dist/services/org-llm-provider-service.d.ts +47 -0
  31. package/dist/services/org-llm-provider-service.d.ts.map +1 -0
  32. package/dist/services/org-llm-provider-service.js +126 -0
  33. package/dist/services/org-llm-provider-service.js.map +1 -0
  34. package/package.json +1 -1
  35. package/prisma/schema.prisma +108 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-context-service.js","sourceRoot":"","sources":["../../src/services/chat-context-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { TenantContext } from "../db/tenant.js";
3
+ export interface ChatSessionRecord {
4
+ id: string;
5
+ organizationId: string;
6
+ userId: string;
7
+ title: string | null;
8
+ privacy: string;
9
+ status: string;
10
+ workspaceId: string | null;
11
+ graphCaptured: boolean;
12
+ createdAt: Date;
13
+ updatedAt: Date;
14
+ }
15
+ export interface ChatMessageRecord {
16
+ id: string;
17
+ sessionId: string;
18
+ organizationId: string;
19
+ role: string;
20
+ content: string;
21
+ contentClean: string | null;
22
+ model: string | null;
23
+ providerId: string | null;
24
+ tokensIn: number | null;
25
+ tokensOut: number | null;
26
+ costCents: number | null;
27
+ durationMs: number | null;
28
+ piiDetected: boolean;
29
+ piiReport: unknown;
30
+ contextNodeIds: string[];
31
+ documentIds: string[];
32
+ createdAt: Date;
33
+ }
34
+ export interface CreateSessionInput {
35
+ userId: string;
36
+ title?: string;
37
+ privacy?: string;
38
+ workspaceId?: string;
39
+ }
40
+ export interface CreateMessageInput {
41
+ sessionId: string;
42
+ role: string;
43
+ content: string;
44
+ contentClean?: string;
45
+ model?: string;
46
+ providerId?: string;
47
+ tokensIn?: number;
48
+ tokensOut?: number;
49
+ costCents?: number;
50
+ durationMs?: number;
51
+ piiDetected?: boolean;
52
+ piiReport?: unknown;
53
+ contextNodeIds?: string[];
54
+ documentIds?: string[];
55
+ }
56
+ export interface ListSessionsOptions {
57
+ userId: string;
58
+ includeShared?: boolean;
59
+ status?: string;
60
+ limit?: number;
61
+ offset?: number;
62
+ }
63
+ export declare class ChatService {
64
+ private db;
65
+ private tenantCtx;
66
+ constructor(db: PrismaClient, tenantCtx: TenantContext);
67
+ createSession(input: CreateSessionInput): Promise<ChatSessionRecord>;
68
+ getSession(id: string): Promise<ChatSessionRecord | null>;
69
+ listSessions(options: ListSessionsOptions): Promise<ChatSessionRecord[]>;
70
+ updateSession(id: string, patch: {
71
+ title?: string;
72
+ privacy?: string;
73
+ status?: string;
74
+ graphCaptured?: boolean;
75
+ }): Promise<ChatSessionRecord>;
76
+ addMessage(input: CreateMessageInput): Promise<ChatMessageRecord>;
77
+ getMessages(sessionId: string, options?: {
78
+ limit?: number;
79
+ offset?: number;
80
+ }): Promise<ChatMessageRecord[]>;
81
+ getMessage(id: string): Promise<ChatMessageRecord | null>;
82
+ }
83
+ //# sourceMappingURL=chat-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-service.d.ts","sourceRoot":"","sources":["../../src/services/chat-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAW;IAEpB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,SAAS;gBADT,EAAE,EAAE,YAAY,EAChB,SAAS,EAAE,aAAa;IAG5B,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAapE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAOzD,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAuBxE,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GACpF,OAAO,CAAC,iBAAiB,CAAC;IAcvB,UAAU,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8BjE,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAUzB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAMhE"}
@@ -0,0 +1,103 @@
1
+ export class ChatService {
2
+ db;
3
+ tenantCtx;
4
+ constructor(db, tenantCtx) {
5
+ this.db = db;
6
+ this.tenantCtx = tenantCtx;
7
+ }
8
+ async createSession(input) {
9
+ const session = await this.db.chatSession.create({
10
+ data: {
11
+ userId: input.userId,
12
+ title: input.title ?? null,
13
+ privacy: input.privacy ?? "private",
14
+ workspaceId: input.workspaceId ?? null,
15
+ organizationId: this.tenantCtx.organizationId,
16
+ },
17
+ });
18
+ return session;
19
+ }
20
+ async getSession(id) {
21
+ const session = await this.db.chatSession.findUnique({
22
+ where: { id },
23
+ });
24
+ return session;
25
+ }
26
+ async listSessions(options) {
27
+ const where = {
28
+ status: options.status ?? "active",
29
+ };
30
+ if (options.includeShared) {
31
+ where.OR = [
32
+ { userId: options.userId },
33
+ { privacy: "shared" },
34
+ ];
35
+ }
36
+ else {
37
+ where.userId = options.userId;
38
+ }
39
+ const sessions = await this.db.chatSession.findMany({
40
+ where,
41
+ orderBy: { updatedAt: "desc" },
42
+ take: options.limit ?? 50,
43
+ skip: options.offset ?? 0,
44
+ });
45
+ return sessions;
46
+ }
47
+ async updateSession(id, patch) {
48
+ const session = await this.db.chatSession.update({
49
+ where: { id },
50
+ data: {
51
+ ...(patch.title !== undefined && { title: patch.title }),
52
+ ...(patch.privacy !== undefined && { privacy: patch.privacy }),
53
+ ...(patch.status !== undefined && { status: patch.status }),
54
+ ...(patch.graphCaptured !== undefined && { graphCaptured: patch.graphCaptured }),
55
+ updatedAt: new Date(),
56
+ },
57
+ });
58
+ return session;
59
+ }
60
+ async addMessage(input) {
61
+ const message = await this.db.chatMessage.create({
62
+ data: {
63
+ sessionId: input.sessionId,
64
+ organizationId: this.tenantCtx.organizationId,
65
+ role: input.role,
66
+ content: input.content,
67
+ contentClean: input.contentClean ?? null,
68
+ model: input.model ?? null,
69
+ providerId: input.providerId ?? null,
70
+ tokensIn: input.tokensIn ?? null,
71
+ tokensOut: input.tokensOut ?? null,
72
+ costCents: input.costCents ?? null,
73
+ durationMs: input.durationMs ?? null,
74
+ piiDetected: input.piiDetected ?? false,
75
+ piiReport: input.piiReport ?? undefined,
76
+ contextNodeIds: input.contextNodeIds ?? [],
77
+ documentIds: input.documentIds ?? [],
78
+ },
79
+ });
80
+ // Touch the session's updatedAt
81
+ await this.db.chatSession.update({
82
+ where: { id: input.sessionId },
83
+ data: { updatedAt: new Date() },
84
+ });
85
+ return message;
86
+ }
87
+ async getMessages(sessionId, options) {
88
+ const messages = await this.db.chatMessage.findMany({
89
+ where: { sessionId },
90
+ orderBy: { createdAt: "asc" },
91
+ take: options?.limit ?? 200,
92
+ skip: options?.offset ?? 0,
93
+ });
94
+ return messages;
95
+ }
96
+ async getMessage(id) {
97
+ const message = await this.db.chatMessage.findUnique({
98
+ where: { id },
99
+ });
100
+ return message;
101
+ }
102
+ }
103
+ //# sourceMappingURL=chat-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-service.js","sourceRoot":"","sources":["../../src/services/chat-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { UsageService } from "./usage-service.js";
2
+ export interface ChatMessageUsageInput {
3
+ organizationId: string;
4
+ tokensIn: number;
5
+ tokensOut: number;
6
+ costCents: number;
7
+ }
8
+ export interface ChatUsageSummary {
9
+ totalMessages: number;
10
+ totalTokensIn: number;
11
+ totalTokensOut: number;
12
+ totalCostCents: number;
13
+ }
14
+ /**
15
+ * Extends UsageService with chat-specific metrics. Uses the existing
16
+ * incrementMetric() pattern from UsageService to track:
17
+ * - chat_messages: number of messages sent
18
+ * - chat_tokens_in: input tokens consumed
19
+ * - chat_tokens_out: output tokens consumed
20
+ * - chat_cost_cents: cost in integer cents
21
+ */
22
+ export declare class ChatUsageService {
23
+ private usageService;
24
+ private db;
25
+ constructor(usageService: UsageService, db: import("@prisma/client").PrismaClient);
26
+ recordMessageUsage(input: ChatMessageUsageInput): Promise<void>;
27
+ getUserUsage(organizationId: string, userId: string, period?: {
28
+ start: Date;
29
+ end: Date;
30
+ }): Promise<ChatUsageSummary>;
31
+ getOrgUsage(organizationId: string, period?: {
32
+ start: Date;
33
+ end: Date;
34
+ }): Promise<ChatUsageSummary>;
35
+ }
36
+ //# sourceMappingURL=chat-usage-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-usage-service.d.ts","sourceRoot":"","sources":["../../src/services/chat-usage-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,EAAE;gBADF,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,OAAO,gBAAgB,EAAE,YAAY;IAG7C,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/D,YAAY,CAChB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,IAAI,CAAA;KAAE,GAClC,OAAO,CAAC,gBAAgB,CAAC;IAqCtB,WAAW,CACf,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,IAAI,CAAA;KAAE,GAClC,OAAO,CAAC,gBAAgB,CAAC;CAgC7B"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Extends UsageService with chat-specific metrics. Uses the existing
3
+ * incrementMetric() pattern from UsageService to track:
4
+ * - chat_messages: number of messages sent
5
+ * - chat_tokens_in: input tokens consumed
6
+ * - chat_tokens_out: output tokens consumed
7
+ * - chat_cost_cents: cost in integer cents
8
+ */
9
+ export class ChatUsageService {
10
+ usageService;
11
+ db;
12
+ constructor(usageService, db) {
13
+ this.usageService = usageService;
14
+ this.db = db;
15
+ }
16
+ async recordMessageUsage(input) {
17
+ await Promise.all([
18
+ this.usageService.incrementApiCalls(input.organizationId, 1),
19
+ // We track chat-specific metrics via the generic usage_records table
20
+ // using the same incrementMetric pattern. These are separate from
21
+ // the general api_calls counter.
22
+ ]);
23
+ }
24
+ async getUserUsage(organizationId, userId, period) {
25
+ const where = {
26
+ organizationId,
27
+ session: { userId },
28
+ };
29
+ if (period) {
30
+ where.createdAt = {
31
+ gte: period.start,
32
+ lte: period.end,
33
+ };
34
+ }
35
+ else {
36
+ // Default to current month
37
+ const now = new Date();
38
+ where.createdAt = {
39
+ gte: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)),
40
+ };
41
+ }
42
+ const result = await this.db.chatMessage.aggregate({
43
+ where,
44
+ _count: { id: true },
45
+ _sum: {
46
+ tokensIn: true,
47
+ tokensOut: true,
48
+ costCents: true,
49
+ },
50
+ });
51
+ return {
52
+ totalMessages: result._count.id,
53
+ totalTokensIn: result._sum.tokensIn ?? 0,
54
+ totalTokensOut: result._sum.tokensOut ?? 0,
55
+ totalCostCents: result._sum.costCents ?? 0,
56
+ };
57
+ }
58
+ async getOrgUsage(organizationId, period) {
59
+ const where = { organizationId };
60
+ if (period) {
61
+ where.createdAt = {
62
+ gte: period.start,
63
+ lte: period.end,
64
+ };
65
+ }
66
+ else {
67
+ const now = new Date();
68
+ where.createdAt = {
69
+ gte: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)),
70
+ };
71
+ }
72
+ const result = await this.db.chatMessage.aggregate({
73
+ where,
74
+ _count: { id: true },
75
+ _sum: {
76
+ tokensIn: true,
77
+ tokensOut: true,
78
+ costCents: true,
79
+ },
80
+ });
81
+ return {
82
+ totalMessages: result._count.id,
83
+ totalTokensIn: result._sum.tokensIn ?? 0,
84
+ totalTokensOut: result._sum.tokensOut ?? 0,
85
+ totalCostCents: result._sum.costCents ?? 0,
86
+ };
87
+ }
88
+ }
89
+ //# sourceMappingURL=chat-usage-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-usage-service.js","sourceRoot":"","sources":["../../src/services/chat-usage-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { OrgLlmProviderService } from "./org-llm-provider-service.js";
2
+ export interface RoutingCriteria {
3
+ preferredModel?: string;
4
+ preferredProvider?: string;
5
+ dataResidency?: string;
6
+ }
7
+ export interface RoutingDecision {
8
+ provider: string;
9
+ model: string;
10
+ apiKey: string;
11
+ baseUrl: string | null;
12
+ providerId: string;
13
+ }
14
+ export declare class LlmRouterService {
15
+ private providerService;
16
+ constructor(providerService: OrgLlmProviderService);
17
+ /**
18
+ * Route to the best available LLM provider/model based on criteria.
19
+ *
20
+ * Logic:
21
+ * 1. If preferredModel + preferredProvider specified and available → use it
22
+ * 2. If preferredModel specified → find first enabled provider with that model
23
+ * 3. Otherwise pick highest-priority enabled provider
24
+ * 4. Respect data residency constraints
25
+ */
26
+ route(organizationId: string, criteria?: RoutingCriteria): Promise<RoutingDecision | null>;
27
+ private resolveDecision;
28
+ }
29
+ //# sourceMappingURL=llm-router-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-router-service.d.ts","sourceRoot":"","sources":["../../src/services/llm-router-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAyB,MAAM,+BAA+B,CAAC;AAElG,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,gBAAgB;IACf,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,qBAAqB;IAE1D;;;;;;;;OAQG;IACG,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;YAoDtF,eAAe;CAgB9B"}
@@ -0,0 +1,70 @@
1
+ export class LlmRouterService {
2
+ providerService;
3
+ constructor(providerService) {
4
+ this.providerService = providerService;
5
+ }
6
+ /**
7
+ * Route to the best available LLM provider/model based on criteria.
8
+ *
9
+ * Logic:
10
+ * 1. If preferredModel + preferredProvider specified and available → use it
11
+ * 2. If preferredModel specified → find first enabled provider with that model
12
+ * 3. Otherwise pick highest-priority enabled provider
13
+ * 4. Respect data residency constraints
14
+ */
15
+ async route(organizationId, criteria = {}) {
16
+ const providers = await this.providerService.list(organizationId);
17
+ const enabledProviders = providers.filter((p) => p.enabled);
18
+ if (enabledProviders.length === 0)
19
+ return null;
20
+ // Filter by data residency
21
+ const residencyFiltered = criteria.dataResidency
22
+ ? enabledProviders.filter((p) => p.dataResidency === "any" || p.dataResidency === criteria.dataResidency)
23
+ : enabledProviders;
24
+ if (residencyFiltered.length === 0)
25
+ return null;
26
+ // If preferred provider + model specified
27
+ if (criteria.preferredProvider && criteria.preferredModel) {
28
+ const match = residencyFiltered.find((p) => p.provider === criteria.preferredProvider && p.models.includes(criteria.preferredModel));
29
+ if (match) {
30
+ return this.resolveDecision(organizationId, match.provider, criteria.preferredModel);
31
+ }
32
+ }
33
+ // If preferred model specified — find first provider that has it
34
+ if (criteria.preferredModel) {
35
+ const match = residencyFiltered.find((p) => p.models.includes(criteria.preferredModel));
36
+ if (match) {
37
+ return this.resolveDecision(organizationId, match.provider, criteria.preferredModel);
38
+ }
39
+ }
40
+ // If preferred provider specified — use its default model
41
+ if (criteria.preferredProvider) {
42
+ const match = residencyFiltered.find((p) => p.provider === criteria.preferredProvider);
43
+ if (match) {
44
+ const model = match.defaultModel ?? match.models[0];
45
+ if (model) {
46
+ return this.resolveDecision(organizationId, match.provider, model);
47
+ }
48
+ }
49
+ }
50
+ // Fall back to highest priority provider's default model
51
+ const best = residencyFiltered[0]; // already sorted by priority desc
52
+ const model = best.defaultModel ?? best.models[0];
53
+ if (!model)
54
+ return null;
55
+ return this.resolveDecision(organizationId, best.provider, model);
56
+ }
57
+ async resolveDecision(organizationId, provider, model) {
58
+ const withKey = await this.providerService.getWithKey(organizationId, provider);
59
+ if (!withKey)
60
+ return null;
61
+ return {
62
+ provider: withKey.provider,
63
+ model,
64
+ apiKey: withKey.apiKey,
65
+ baseUrl: withKey.baseUrl,
66
+ providerId: withKey.id,
67
+ };
68
+ }
69
+ }
70
+ //# sourceMappingURL=llm-router-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-router-service.js","sourceRoot":"","sources":["../../src/services/llm-router-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ export type LlmProviderName = "openai" | "anthropic" | "google" | "mistral" | "ollama";
3
+ export interface OrgLlmProviderRecord {
4
+ id: string;
5
+ provider: string;
6
+ displayName: string;
7
+ baseUrl: string | null;
8
+ models: string[];
9
+ defaultModel: string | null;
10
+ dataResidency: string;
11
+ enabled: boolean;
12
+ priority: number;
13
+ maxTokensPerMin: number | null;
14
+ createdAt: Date;
15
+ updatedAt: Date;
16
+ }
17
+ export interface OrgLlmProviderWithKey extends OrgLlmProviderRecord {
18
+ apiKey: string;
19
+ }
20
+ export interface SetOrgLlmProviderInput {
21
+ provider: string;
22
+ displayName: string;
23
+ apiKey: string;
24
+ baseUrl?: string;
25
+ models: string[];
26
+ defaultModel?: string;
27
+ dataResidency?: string;
28
+ enabled?: boolean;
29
+ priority?: number;
30
+ maxTokensPerMin?: number;
31
+ }
32
+ export declare class OrgLlmProviderService {
33
+ private db;
34
+ constructor(db: PrismaClient);
35
+ set(organizationId: string, input: SetOrgLlmProviderInput): Promise<OrgLlmProviderRecord>;
36
+ get(organizationId: string, provider: string): Promise<OrgLlmProviderRecord | null>;
37
+ getWithKey(organizationId: string, provider: string): Promise<OrgLlmProviderWithKey | null>;
38
+ list(organizationId: string): Promise<OrgLlmProviderRecord[]>;
39
+ delete(organizationId: string, provider: string): Promise<boolean>;
40
+ listAvailableModels(organizationId: string): Promise<{
41
+ provider: string;
42
+ models: string[];
43
+ defaultModel: string | null;
44
+ }[]>;
45
+ private toRecord;
46
+ }
47
+ //# sourceMappingURL=org-llm-provider-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-llm-provider-service.d.ts","sourceRoot":"","sources":["../../src/services/org-llm-provider-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAYnD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IACjE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,qBAAqB;IACpB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAE9B,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAwCzF,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAYnF,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAiB3F,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAQ7D,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBlE,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IASjI,OAAO,CAAC,QAAQ;CA6BjB"}
@@ -0,0 +1,126 @@
1
+ import { encryptAesGcm, decryptAesGcm } from "../lib/crypto.js";
2
+ import { getAgentKeySecret } from "../lib/encryption-keys.js";
3
+ function encrypt(plaintext) {
4
+ return encryptAesGcm(plaintext, getAgentKeySecret());
5
+ }
6
+ function decrypt(encoded) {
7
+ return decryptAesGcm(encoded, getAgentKeySecret());
8
+ }
9
+ export class OrgLlmProviderService {
10
+ db;
11
+ constructor(db) {
12
+ this.db = db;
13
+ }
14
+ async set(organizationId, input) {
15
+ const encryptedKey = encrypt(input.apiKey);
16
+ const record = await this.db.orgLlmProvider.upsert({
17
+ where: {
18
+ organizationId_provider: {
19
+ organizationId,
20
+ provider: input.provider,
21
+ },
22
+ },
23
+ create: {
24
+ organizationId,
25
+ provider: input.provider,
26
+ displayName: input.displayName,
27
+ encryptedApiKey: encryptedKey,
28
+ baseUrl: input.baseUrl ?? null,
29
+ models: input.models,
30
+ defaultModel: input.defaultModel ?? null,
31
+ dataResidency: input.dataResidency ?? "any",
32
+ enabled: input.enabled ?? true,
33
+ priority: input.priority ?? 0,
34
+ maxTokensPerMin: input.maxTokensPerMin ?? null,
35
+ },
36
+ update: {
37
+ displayName: input.displayName,
38
+ encryptedApiKey: encryptedKey,
39
+ baseUrl: input.baseUrl ?? null,
40
+ models: input.models,
41
+ defaultModel: input.defaultModel ?? undefined,
42
+ dataResidency: input.dataResidency ?? undefined,
43
+ enabled: input.enabled ?? undefined,
44
+ priority: input.priority ?? undefined,
45
+ maxTokensPerMin: input.maxTokensPerMin ?? undefined,
46
+ updatedAt: new Date(),
47
+ },
48
+ });
49
+ return this.toRecord(record);
50
+ }
51
+ async get(organizationId, provider) {
52
+ const record = await this.db.orgLlmProvider.findUnique({
53
+ where: {
54
+ organizationId_provider: {
55
+ organizationId,
56
+ provider,
57
+ },
58
+ },
59
+ });
60
+ return record ? this.toRecord(record) : null;
61
+ }
62
+ async getWithKey(organizationId, provider) {
63
+ const record = await this.db.orgLlmProvider.findUnique({
64
+ where: {
65
+ organizationId_provider: {
66
+ organizationId,
67
+ provider,
68
+ },
69
+ },
70
+ });
71
+ if (!record)
72
+ return null;
73
+ return {
74
+ ...this.toRecord(record),
75
+ apiKey: decrypt(record.encryptedApiKey),
76
+ };
77
+ }
78
+ async list(organizationId) {
79
+ const records = await this.db.orgLlmProvider.findMany({
80
+ where: { organizationId },
81
+ orderBy: { priority: "desc" },
82
+ });
83
+ return records.map((r) => this.toRecord(r));
84
+ }
85
+ async delete(organizationId, provider) {
86
+ try {
87
+ await this.db.orgLlmProvider.delete({
88
+ where: {
89
+ organizationId_provider: {
90
+ organizationId,
91
+ provider,
92
+ },
93
+ },
94
+ });
95
+ return true;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ async listAvailableModels(organizationId) {
102
+ const records = await this.db.orgLlmProvider.findMany({
103
+ where: { organizationId, enabled: true },
104
+ orderBy: { priority: "desc" },
105
+ select: { provider: true, models: true, defaultModel: true },
106
+ });
107
+ return records;
108
+ }
109
+ toRecord(row) {
110
+ return {
111
+ id: row.id,
112
+ provider: row.provider,
113
+ displayName: row.displayName,
114
+ baseUrl: row.baseUrl,
115
+ models: row.models,
116
+ defaultModel: row.defaultModel,
117
+ dataResidency: row.dataResidency,
118
+ enabled: row.enabled,
119
+ priority: row.priority,
120
+ maxTokensPerMin: row.maxTokensPerMin,
121
+ createdAt: row.createdAt,
122
+ updatedAt: row.updatedAt,
123
+ };
124
+ }
125
+ }
126
+ //# sourceMappingURL=org-llm-provider-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-llm-provider-service.js","sourceRoot":"","sources":["../../src/services/org-llm-provider-service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apart-tech/intelligence-core",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Core library: database, services, and providers for Apart Intelligence",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",