@chatman-media/conversation-engine 1.3.1 → 1.4.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.
- package/dist/contact-resolver.test.d.ts +2 -0
- package/dist/contact-resolver.test.d.ts.map +1 -0
- package/dist/conversation-resolver.test.d.ts +2 -0
- package/dist/conversation-resolver.test.d.ts.map +1 -0
- package/dist/dal/experiments.integration.test.d.ts +2 -0
- package/dist/dal/experiments.integration.test.d.ts.map +1 -0
- package/dist/dal/leads.d.ts +12 -2
- package/dist/dal/leads.d.ts.map +1 -1
- package/dist/dal/notifications.integration.test.d.ts +2 -0
- package/dist/dal/notifications.integration.test.d.ts.map +1 -0
- package/dist/dal/outbound.integration.test.d.ts +2 -0
- package/dist/dal/outbound.integration.test.d.ts.map +1 -0
- package/dist/index.js +16 -7
- package/dist/outbound-dispatch.test.d.ts +2 -0
- package/dist/outbound-dispatch.test.d.ts.map +1 -0
- package/dist/stage-classifier.integration.test.d.ts +2 -0
- package/dist/stage-classifier.integration.test.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-resolver.test.d.ts","sourceRoot":"","sources":["../src/contact-resolver.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-resolver.test.d.ts","sourceRoot":"","sources":["../src/conversation-resolver.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiments.integration.test.d.ts","sourceRoot":"","sources":["../../src/dal/experiments.integration.test.ts"],"names":[],"mappings":""}
|
package/dist/dal/leads.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export interface LeadRow {
|
|
|
4
4
|
tenantId: number;
|
|
5
5
|
userId: number;
|
|
6
6
|
state: string;
|
|
7
|
+
/** Тип запроса (concierge): exchange | transfer | … . NULL для одно-воронных вертикалей. */
|
|
8
|
+
requestType: string | null;
|
|
7
9
|
assignedAdminId?: number | null;
|
|
8
10
|
intakeJson: string | null;
|
|
9
11
|
visaDocsJson: string | null;
|
|
@@ -20,17 +22,25 @@ export interface LeadRow {
|
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* Leads repo. Schema-колонка user_id хранит contact.id (см. ConversationsRepo
|
|
23
|
-
* docstring о legacy-имени). UNIQUE(user_id)
|
|
24
|
-
*
|
|
25
|
+
* docstring о legacy-имени). UNIQUE(user_id) снят в migration 0032 — concierge
|
|
26
|
+
* держит несколько лидов на контакт (по одному на request_type). Для одно-
|
|
27
|
+
* воронных вертикалей лид по-прежнему один (гарантия на уровне приложения),
|
|
28
|
+
* поэтому find-методы детерминированы (самый свежий по updated_at).
|
|
25
29
|
*/
|
|
26
30
|
export declare class LeadsRepo {
|
|
27
31
|
private readonly ctx;
|
|
28
32
|
constructor(ctx: RepoCtx);
|
|
29
33
|
byId(id: number): Promise<LeadRow | null>;
|
|
34
|
+
/** Самый свежий лид контакта. Для одно-воронных вертикалей он единственный. */
|
|
30
35
|
findByContactId(contactId: number): Promise<LeadRow | null>;
|
|
36
|
+
/** Все лиды контакта (concierge: N запросов на гостя), свежие первыми. */
|
|
37
|
+
findAllByContact(contactId: number): Promise<LeadRow[]>;
|
|
38
|
+
/** Самый свежий лид контакта заданного request_type (concierge). */
|
|
39
|
+
findByContactAndType(contactId: number, requestType: string): Promise<LeadRow | null>;
|
|
31
40
|
create(opts: {
|
|
32
41
|
contactId: number;
|
|
33
42
|
state: string;
|
|
43
|
+
requestType?: string | null;
|
|
34
44
|
nowEpoch: number;
|
|
35
45
|
}): Promise<LeadRow>;
|
|
36
46
|
updateState(leadId: number, newState: string, nowEpoch: number): Promise<void>;
|
package/dist/dal/leads.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"leads.d.ts","sourceRoot":"","sources":["../../src/dal/leads.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"leads.d.ts","sourceRoot":"","sources":["../../src/dal/leads.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,OAAO;IAEnC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQ/C,+EAA+E;IACzE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAYjE,0EAA0E;IACpE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAW7D,oEAAoE;IAC9D,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAgBpB,MAAM,CAAC,IAAI,EAAE;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBd,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.integration.test.d.ts","sourceRoot":"","sources":["../../src/dal/notifications.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound.integration.test.d.ts","sourceRoot":"","sources":["../../src/dal/outbound.integration.test.ts"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -429,7 +429,7 @@ function parseAllocation(allocationJson) {
|
|
|
429
429
|
}
|
|
430
430
|
// src/dal/leads.ts
|
|
431
431
|
import { leads as leadsTable } from "@chatman-media/storage";
|
|
432
|
-
import { and as and5, eq as eq5 } from "drizzle-orm";
|
|
432
|
+
import { and as and5, desc as desc2, eq as eq5 } from "drizzle-orm";
|
|
433
433
|
|
|
434
434
|
class LeadsRepo {
|
|
435
435
|
ctx;
|
|
@@ -441,7 +441,15 @@ class LeadsRepo {
|
|
|
441
441
|
return row ?? null;
|
|
442
442
|
}
|
|
443
443
|
async findByContactId(contactId) {
|
|
444
|
-
const [row] = await this.ctx.db.select().from(leadsTable).where(and5(eq5(leadsTable.tenantId, this.ctx.tenantId), eq5(leadsTable.userId, contactId)));
|
|
444
|
+
const [row] = await this.ctx.db.select().from(leadsTable).where(and5(eq5(leadsTable.tenantId, this.ctx.tenantId), eq5(leadsTable.userId, contactId))).orderBy(desc2(leadsTable.updatedAt)).limit(1);
|
|
445
|
+
return row ?? null;
|
|
446
|
+
}
|
|
447
|
+
async findAllByContact(contactId) {
|
|
448
|
+
const rows = await this.ctx.db.select().from(leadsTable).where(and5(eq5(leadsTable.tenantId, this.ctx.tenantId), eq5(leadsTable.userId, contactId))).orderBy(desc2(leadsTable.updatedAt));
|
|
449
|
+
return rows;
|
|
450
|
+
}
|
|
451
|
+
async findByContactAndType(contactId, requestType) {
|
|
452
|
+
const [row] = await this.ctx.db.select().from(leadsTable).where(and5(eq5(leadsTable.tenantId, this.ctx.tenantId), eq5(leadsTable.userId, contactId), eq5(leadsTable.requestType, requestType))).orderBy(desc2(leadsTable.updatedAt)).limit(1);
|
|
445
453
|
return row ?? null;
|
|
446
454
|
}
|
|
447
455
|
async create(opts) {
|
|
@@ -449,6 +457,7 @@ class LeadsRepo {
|
|
|
449
457
|
tenantId: this.ctx.tenantId,
|
|
450
458
|
userId: opts.contactId,
|
|
451
459
|
state: opts.state,
|
|
460
|
+
requestType: opts.requestType ?? null,
|
|
452
461
|
createdAt: opts.nowEpoch,
|
|
453
462
|
updatedAt: opts.nowEpoch
|
|
454
463
|
}).returning();
|
|
@@ -462,7 +471,7 @@ class LeadsRepo {
|
|
|
462
471
|
}
|
|
463
472
|
// src/dal/messages.ts
|
|
464
473
|
import { messages as messagesTable } from "@chatman-media/storage";
|
|
465
|
-
import { and as and6, desc as
|
|
474
|
+
import { and as and6, desc as desc3, eq as eq6, isNull, sql as sql3 } from "drizzle-orm";
|
|
466
475
|
|
|
467
476
|
class MessagesRepo {
|
|
468
477
|
ctx;
|
|
@@ -493,7 +502,7 @@ class MessagesRepo {
|
|
|
493
502
|
return row ?? null;
|
|
494
503
|
}
|
|
495
504
|
async recent(conversationId, limit) {
|
|
496
|
-
const rows = await this.ctx.db.select().from(messagesTable).where(and6(eq6(messagesTable.tenantId, this.ctx.tenantId), eq6(messagesTable.conversationId, conversationId), isNull(messagesTable.deletedAt), sql3`role <> 'system'`)).orderBy(
|
|
505
|
+
const rows = await this.ctx.db.select().from(messagesTable).where(and6(eq6(messagesTable.tenantId, this.ctx.tenantId), eq6(messagesTable.conversationId, conversationId), isNull(messagesTable.deletedAt), sql3`role <> 'system'`)).orderBy(desc3(messagesTable.createdAt)).limit(limit);
|
|
497
506
|
return rows.reverse();
|
|
498
507
|
}
|
|
499
508
|
async countByConversation(conversationId) {
|
|
@@ -693,7 +702,7 @@ class StylesRepo {
|
|
|
693
702
|
}
|
|
694
703
|
}
|
|
695
704
|
// src/dal/notifications.ts
|
|
696
|
-
import { and as and10, desc as
|
|
705
|
+
import { and as and10, desc as desc4, eq as eq10, gte, inArray, isNull as isNull2, sql as sql7 } from "drizzle-orm";
|
|
697
706
|
import { admins, adminNotifications, notificationRules, operatorSettings, notificationTemplates, notificationGroupTokens } from "@chatman-media/storage";
|
|
698
707
|
|
|
699
708
|
class NotificationsRepo {
|
|
@@ -846,11 +855,11 @@ class NotificationsRepo {
|
|
|
846
855
|
await this.db.update(adminNotifications).set({ deliveredAt }).where(eq10(adminNotifications.id, id));
|
|
847
856
|
}
|
|
848
857
|
async findRecentByDedup(tenantId, dedupKey, sinceEpoch) {
|
|
849
|
-
const rows = await this.db.select().from(adminNotifications).where(and10(eq10(adminNotifications.tenantId, tenantId), eq10(adminNotifications.dedupKey, dedupKey), gte(adminNotifications.createdAt, sinceEpoch))).orderBy(
|
|
858
|
+
const rows = await this.db.select().from(adminNotifications).where(and10(eq10(adminNotifications.tenantId, tenantId), eq10(adminNotifications.dedupKey, dedupKey), gte(adminNotifications.createdAt, sinceEpoch))).orderBy(desc4(adminNotifications.createdAt)).limit(1);
|
|
850
859
|
return rows[0];
|
|
851
860
|
}
|
|
852
861
|
async listRecentNotifications(tenantId, adminId, limit = 10) {
|
|
853
|
-
return this.db.select().from(adminNotifications).where(and10(eq10(adminNotifications.tenantId, tenantId), eq10(adminNotifications.adminId, adminId))).orderBy(
|
|
862
|
+
return this.db.select().from(adminNotifications).where(and10(eq10(adminNotifications.tenantId, tenantId), eq10(adminNotifications.adminId, adminId))).orderBy(desc4(adminNotifications.createdAt)).limit(limit);
|
|
854
863
|
}
|
|
855
864
|
async listPendingDigest(tenantId, adminId) {
|
|
856
865
|
return this.db.select().from(adminNotifications).where(and10(eq10(adminNotifications.tenantId, tenantId), eq10(adminNotifications.adminId, adminId), isNull2(adminNotifications.deliveredAt), isNull2(adminNotifications.digestBatchId))).orderBy(adminNotifications.createdAt);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-dispatch.test.d.ts","sourceRoot":"","sources":["../src/outbound-dispatch.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-classifier.integration.test.d.ts","sourceRoot":"","sources":["../src/stage-classifier.integration.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatman-media/conversation-engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Channel-agnostic pipeline обработки inbound сообщений: contact-resolve → conversation lookup → mode routing → AI-reply / queued / human → outbound. Сердце data plane.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|