@recombine-ai/platform 0.2.6-test.8 → 0.2.6-test.9
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/build/analytics.d.ts +18 -20
- package/build/analytics.d.ts.map +1 -1
- package/build/analytics.js +56 -42
- package/build/interfaces/platform.d.ts +24 -5
- package/build/interfaces/platform.d.ts.map +1 -1
- package/build/interfaces/platform.js +17 -2
- package/build/postgres-analytics-query.d.ts +2 -2
- package/build/postgres-analytics-query.d.ts.map +1 -1
- package/build/postgres-analytics-query.js +9 -1
- package/build/postgres-analytics.d.ts +6 -7
- package/build/postgres-analytics.d.ts.map +1 -1
- package/build/postgres-analytics.js +13 -21
- package/package.json +1 -1
package/build/analytics.d.ts
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export type
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
export type AnalyticsFieldType = 'boolean' | 'json' | 'number' | 'string';
|
|
2
|
+
export type AnalyticsScalar = boolean | number | string;
|
|
3
|
+
export type AnalyticsFieldType = 'boolean' | 'number' | 'string';
|
|
6
4
|
export interface AnalyticsFieldDefinition<T> {
|
|
7
5
|
readonly type: AnalyticsFieldType;
|
|
8
6
|
readonly schema: z.ZodType<T>;
|
|
9
7
|
}
|
|
10
|
-
export interface AnalyticsField<T> extends AnalyticsFieldDefinition<T> {
|
|
11
|
-
readonly agentId: string;
|
|
12
|
-
readonly key: string;
|
|
13
|
-
}
|
|
14
8
|
export type AnalyticsFieldDefinitions = Readonly<Record<string, AnalyticsFieldDefinition<unknown>>>;
|
|
15
|
-
export type RegisteredAnalyticsFields<TFields extends AnalyticsFieldDefinitions> = {
|
|
16
|
-
readonly [TKey in keyof TFields]: AnalyticsField<AnalyticsValue<TFields[TKey]>>;
|
|
17
|
-
};
|
|
18
9
|
export type AnalyticsValue<TField extends AnalyticsFieldDefinition<unknown>> = TField extends AnalyticsFieldDefinition<infer TValue> ? TValue : never;
|
|
10
|
+
type AnalyticsFieldName<TFields extends AnalyticsFieldDefinitions> = Extract<keyof TFields, string>;
|
|
19
11
|
export interface ConversationAnalyticsSummary {
|
|
20
12
|
conversationId: string;
|
|
21
13
|
agentId: string;
|
|
22
14
|
channel: string;
|
|
23
15
|
startedAt: Date;
|
|
24
16
|
}
|
|
25
|
-
export interface
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
export interface AnalyticsStore {
|
|
18
|
+
set(conversationId: string, agentId: string, fieldName: string, value: AnalyticsScalar): Promise<void>;
|
|
19
|
+
clear(conversationId: string, agentId: string, fieldName: string): Promise<void>;
|
|
20
|
+
get(conversationId: string, agentId: string, fieldName: string): Promise<unknown | undefined>;
|
|
21
|
+
getSummary(conversationId: string, agentId: string): Promise<ConversationAnalyticsSummary | undefined>;
|
|
22
|
+
}
|
|
23
|
+
export interface AgentAnalytics<TFields extends AnalyticsFieldDefinitions> {
|
|
24
|
+
set<TName extends AnalyticsFieldName<TFields>>(conversationId: string, fieldName: TName, value: AnalyticsValue<TFields[TName]>): Promise<void>;
|
|
25
|
+
clear<TName extends AnalyticsFieldName<TFields>>(conversationId: string, fieldName: TName): Promise<void>;
|
|
26
|
+
get<TName extends AnalyticsFieldName<TFields>>(conversationId: string, fieldName: TName): Promise<AnalyticsValue<TFields[TName]> | undefined>;
|
|
30
27
|
getSummary(conversationId: string): Promise<ConversationAnalyticsSummary | undefined>;
|
|
31
28
|
}
|
|
32
29
|
export declare const analyticsField: {
|
|
@@ -34,9 +31,10 @@ export declare const analyticsField: {
|
|
|
34
31
|
number(): AnalyticsFieldDefinition<number>;
|
|
35
32
|
string(): AnalyticsFieldDefinition<string>;
|
|
36
33
|
enum<const TValues extends readonly [string, ...string[]]>(values: TValues): AnalyticsFieldDefinition<TValues[number]>;
|
|
37
|
-
json<T extends AnalyticsJsonValue>(schema: z.ZodType<T>): AnalyticsFieldDefinition<T>;
|
|
38
34
|
};
|
|
39
|
-
export declare function
|
|
40
|
-
export declare function
|
|
41
|
-
export declare function
|
|
35
|
+
export declare function validateAgentAnalytics(agentId: string, fields: AnalyticsFieldDefinitions): void;
|
|
36
|
+
export declare function createAgentAnalytics<TFields extends AnalyticsFieldDefinitions>(store: AnalyticsStore, agentId: string, fields: TFields): AgentAnalytics<TFields>;
|
|
37
|
+
export declare function createInMemoryAnalytics(summaries?: ConversationAnalyticsSummary[]): AnalyticsStore;
|
|
38
|
+
export declare function assertAnalyticsScalar(value: unknown): asserts value is AnalyticsScalar;
|
|
39
|
+
export {};
|
|
42
40
|
//# sourceMappingURL=analytics.d.ts.map
|
package/build/analytics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"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"}
|
package/build/analytics.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.analyticsField = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.validateAgentAnalytics = validateAgentAnalytics;
|
|
5
|
+
exports.createAgentAnalytics = createAgentAnalytics;
|
|
5
6
|
exports.createInMemoryAnalytics = createInMemoryAnalytics;
|
|
6
|
-
exports.
|
|
7
|
+
exports.assertAnalyticsScalar = assertAnalyticsScalar;
|
|
7
8
|
const zod_1 = require("zod");
|
|
8
9
|
function defineField(type, schema) {
|
|
9
10
|
return Object.freeze({ type, schema });
|
|
@@ -21,80 +22,93 @@ exports.analyticsField = {
|
|
|
21
22
|
enum(values) {
|
|
22
23
|
return defineField('string', zod_1.z.enum(values));
|
|
23
24
|
},
|
|
24
|
-
json(schema) {
|
|
25
|
-
return defineField('json', schema);
|
|
26
|
-
},
|
|
27
25
|
};
|
|
28
|
-
function
|
|
26
|
+
function validateAgentAnalytics(agentId, fields) {
|
|
29
27
|
if (agentId.trim() === '') {
|
|
30
28
|
throw new Error('Analytics agent ID must not be empty');
|
|
31
29
|
}
|
|
32
|
-
const
|
|
33
|
-
if (!/^[A-Za-z0-9_.:-]{1,128}$/.test(
|
|
30
|
+
for (const [fieldName, definition] of Object.entries(fields)) {
|
|
31
|
+
if (!/^[A-Za-z0-9_.:-]{1,128}$/.test(fieldName)) {
|
|
34
32
|
throw new Error('Analytics field name contains unsupported characters');
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
if (!['boolean', 'number', 'string'].includes(definition.type)) {
|
|
35
|
+
throw new Error(`Analytics field '${fieldName}' has an unsupported type`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function createAgentAnalytics(store, agentId, fields) {
|
|
40
|
+
validateAgentAnalytics(agentId, fields);
|
|
41
|
+
const getDefinition = (fieldName) => {
|
|
42
|
+
const definition = fields[fieldName];
|
|
43
|
+
if (!definition) {
|
|
44
|
+
throw new Error(`Analytics field '${fieldName}' is not declared for agent '${agentId}'`);
|
|
45
|
+
}
|
|
46
|
+
return definition;
|
|
47
|
+
};
|
|
48
|
+
const parseValue = (fieldName, value) => getDefinition(fieldName).schema.parse(value);
|
|
49
|
+
return {
|
|
50
|
+
async set(conversationId, fieldName, value) {
|
|
51
|
+
const parsed = parseValue(fieldName, value);
|
|
52
|
+
assertAnalyticsScalar(parsed);
|
|
53
|
+
await store.set(conversationId, agentId, fieldName, parsed);
|
|
54
|
+
},
|
|
55
|
+
async clear(conversationId, fieldName) {
|
|
56
|
+
getDefinition(fieldName);
|
|
57
|
+
await store.clear(conversationId, agentId, fieldName);
|
|
58
|
+
},
|
|
59
|
+
async get(conversationId, fieldName) {
|
|
60
|
+
getDefinition(fieldName);
|
|
61
|
+
const value = await store.get(conversationId, agentId, fieldName);
|
|
62
|
+
return value === undefined ? undefined : parseValue(fieldName, value);
|
|
63
|
+
},
|
|
64
|
+
getSummary(conversationId) {
|
|
65
|
+
return store.getSummary(conversationId, agentId);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
39
68
|
}
|
|
40
69
|
function createInMemoryAnalytics(summaries = []) {
|
|
41
70
|
const conversations = new Map();
|
|
42
71
|
const conversationAgents = new Map(summaries.map((summary) => [summary.conversationId, summary.agentId]));
|
|
43
72
|
const summariesById = new Map(summaries.map((summary) => [summary.conversationId, structuredClone(summary)]));
|
|
44
73
|
return {
|
|
45
|
-
|
|
46
|
-
async set(conversationId, field, value) {
|
|
74
|
+
async set(conversationId, agentId, fieldName, value) {
|
|
47
75
|
const existingAgentId = conversationAgents.get(conversationId);
|
|
48
|
-
if (existingAgentId !== undefined && existingAgentId !==
|
|
76
|
+
if (existingAgentId !== undefined && existingAgentId !== agentId) {
|
|
49
77
|
throw new Error(`Conversation '${conversationId}' belongs to another agent`);
|
|
50
78
|
}
|
|
51
|
-
|
|
52
|
-
assertAnalyticsJsonValue(parsed);
|
|
79
|
+
assertAnalyticsScalar(value);
|
|
53
80
|
const values = conversations.get(conversationId) ?? new Map();
|
|
54
|
-
values.set(
|
|
81
|
+
values.set(fieldName, value);
|
|
55
82
|
conversations.set(conversationId, values);
|
|
56
|
-
conversationAgents.set(conversationId,
|
|
83
|
+
conversationAgents.set(conversationId, agentId);
|
|
57
84
|
},
|
|
58
|
-
async clear(conversationId,
|
|
59
|
-
if (conversationAgents.get(conversationId) !==
|
|
85
|
+
async clear(conversationId, agentId, fieldName) {
|
|
86
|
+
if (conversationAgents.get(conversationId) !== agentId) {
|
|
60
87
|
return;
|
|
61
88
|
}
|
|
62
89
|
const values = conversations.get(conversationId);
|
|
63
|
-
values?.delete(
|
|
90
|
+
values?.delete(fieldName);
|
|
64
91
|
if (values?.size === 0) {
|
|
65
92
|
conversations.delete(conversationId);
|
|
66
93
|
}
|
|
67
94
|
},
|
|
68
|
-
async get(conversationId,
|
|
69
|
-
if (conversationAgents.get(conversationId) !==
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
const values = conversations.get(conversationId);
|
|
73
|
-
if (!values?.has(field.key)) {
|
|
95
|
+
async get(conversationId, agentId, fieldName) {
|
|
96
|
+
if (conversationAgents.get(conversationId) !== agentId) {
|
|
74
97
|
return undefined;
|
|
75
98
|
}
|
|
76
|
-
return
|
|
99
|
+
return conversations.get(conversationId)?.get(fieldName);
|
|
77
100
|
},
|
|
78
|
-
async getSummary(conversationId) {
|
|
101
|
+
async getSummary(conversationId, agentId) {
|
|
79
102
|
const summary = summariesById.get(conversationId);
|
|
80
|
-
return summary ? structuredClone(summary) : undefined;
|
|
103
|
+
return summary?.agentId === agentId ? structuredClone(summary) : undefined;
|
|
81
104
|
},
|
|
82
105
|
};
|
|
83
106
|
}
|
|
84
|
-
function
|
|
85
|
-
if (value ===
|
|
86
|
-
typeof value === 'boolean' ||
|
|
107
|
+
function assertAnalyticsScalar(value) {
|
|
108
|
+
if (typeof value === 'boolean' ||
|
|
87
109
|
typeof value === 'string' ||
|
|
88
110
|
(typeof value === 'number' && Number.isFinite(value))) {
|
|
89
111
|
return;
|
|
90
112
|
}
|
|
91
|
-
|
|
92
|
-
value.forEach(assertAnalyticsJsonValue);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {
|
|
96
|
-
Object.values(value).forEach(assertAnalyticsJsonValue);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
throw new Error('Analytics value must be valid JSON');
|
|
113
|
+
throw new Error('Analytics value must be a boolean, finite number, or string');
|
|
100
114
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReadableStream } from 'node:stream/web';
|
|
2
2
|
import { AIEngine, AIStreamEngine, LlmAdapter, LlmStreamAdapter, Logger, Message, PromptFS, ResponseChunk } from '@recombine-ai/engine';
|
|
3
|
-
import {
|
|
3
|
+
import { AgentAnalytics, AnalyticsFieldDefinitions, AnalyticsStore } from '../analytics';
|
|
4
4
|
import { ContextCache } from '../context-cache';
|
|
5
5
|
import { TimeoutManager } from '../timeouts-manager';
|
|
6
6
|
import { IRcVoice } from './rc-voice';
|
|
@@ -18,24 +18,43 @@ export interface Platform<TContext extends {}, TModels extends IModels, TRcVoice
|
|
|
18
18
|
models: TModels['models'];
|
|
19
19
|
streamingModels: TModels['streamingModels'];
|
|
20
20
|
contextCache: TContextCache;
|
|
21
|
-
analytics:
|
|
21
|
+
analytics: AnalyticsStore;
|
|
22
22
|
}
|
|
23
23
|
export interface CallInfo {
|
|
24
24
|
callId: string;
|
|
25
25
|
phoneNumber?: string;
|
|
26
26
|
headers: Record<string, unknown>;
|
|
27
27
|
}
|
|
28
|
+
export type VoiceSettings = Record<string, string | number | boolean | number[]>;
|
|
28
29
|
export interface VoiceAgent {
|
|
29
30
|
onCallStart: (call: CallInfo) => Promise<{
|
|
30
31
|
initialMessage: string;
|
|
31
|
-
initialSettings?:
|
|
32
|
+
initialSettings?: VoiceSettings;
|
|
32
33
|
}>;
|
|
33
34
|
onCallReady: (call: CallInfo) => Promise<void>;
|
|
34
35
|
streamResponse: (messages: Message[], call: CallInfo) => Promise<ReadableStream<ResponseChunk>>;
|
|
35
|
-
onCallEnd: (call: CallInfo) => Promise<void>;
|
|
36
|
+
onCallEnd: (call: CallInfo, completedConversation?: Message[]) => Promise<void>;
|
|
36
37
|
onAgentSpeechDone: (messages: Message[], call: CallInfo) => Promise<void>;
|
|
37
38
|
onServiceStartup: () => Promise<void>;
|
|
38
39
|
onFatalError: (callId: string, err: any) => Promise<void>;
|
|
39
40
|
}
|
|
40
|
-
export
|
|
41
|
+
export type AgentPlatform<TPlatform extends {
|
|
42
|
+
analytics: AnalyticsStore;
|
|
43
|
+
}, TFields extends AnalyticsFieldDefinitions> = Omit<TPlatform, 'analytics'> & {
|
|
44
|
+
analytics: AgentAnalytics<TFields>;
|
|
45
|
+
};
|
|
46
|
+
type ComposedPlatform<TContext extends object, TModels extends IModels> = Platform<TContext, TModels, unknown, unknown, unknown>;
|
|
47
|
+
export interface AgentDefinition<TFields extends AnalyticsFieldDefinitions> {
|
|
48
|
+
readonly agentId: string;
|
|
49
|
+
readonly analytics: Readonly<TFields>;
|
|
50
|
+
}
|
|
51
|
+
export interface AgentDeclaration<TContext extends object, TServices, TModels extends IModels, TFields extends AnalyticsFieldDefinitions, TPlatform extends ComposedPlatform<TContext, TModels> = Platform<TContext, TModels>> extends AgentDefinition<TFields> {
|
|
52
|
+
create: (platform: AgentPlatform<TPlatform, TFields>, services: TServices) => VoiceAgent;
|
|
53
|
+
}
|
|
54
|
+
export interface AgentCreator<TContext extends object, TServices, TModels extends IModels, TFields extends AnalyticsFieldDefinitions, TPlatform extends ComposedPlatform<TContext, TModels> = Platform<TContext, TModels>> {
|
|
55
|
+
(platform: TPlatform, services: TServices): VoiceAgent;
|
|
56
|
+
readonly definition: AgentDefinition<TFields>;
|
|
57
|
+
}
|
|
58
|
+
export declare function createAgent<TContext extends object, TServices, TModels extends IModels, const TFields extends AnalyticsFieldDefinitions, TPlatform extends ComposedPlatform<TContext, TModels> = Platform<TContext, TModels>>(declaration: AgentDeclaration<TContext, TServices, TModels, TFields, TPlatform>): AgentCreator<TContext, TServices, TModels, TFields, TPlatform>;
|
|
59
|
+
export {};
|
|
41
60
|
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/interfaces/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EACH,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,EAChB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/interfaces/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAgent = createAgent;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const analytics_1 = require("../analytics");
|
|
5
|
+
function createAgent(declaration) {
|
|
6
|
+
const { agentId, create } = declaration;
|
|
7
|
+
const analytics = Object.freeze({ ...declaration.analytics });
|
|
8
|
+
(0, analytics_1.validateAgentAnalytics)(agentId, analytics);
|
|
9
|
+
const creator = (platform, services) => {
|
|
10
|
+
const agentPlatform = {
|
|
11
|
+
...platform,
|
|
12
|
+
analytics: (0, analytics_1.createAgentAnalytics)(platform.analytics, agentId, analytics),
|
|
13
|
+
};
|
|
14
|
+
return create(agentPlatform, services);
|
|
15
|
+
};
|
|
16
|
+
const definition = Object.freeze({ agentId, analytics });
|
|
17
|
+
return Object.defineProperty(creator, 'definition', {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
value: definition,
|
|
20
|
+
});
|
|
6
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PoolConfig, QueryResult } from 'pg';
|
|
2
|
-
import {
|
|
2
|
+
import { AnalyticsScalar } from './analytics';
|
|
3
3
|
export type AnalyticsFilterScalar = boolean | number | string;
|
|
4
4
|
export type AnalyticsFilterValueType = 'boolean' | 'number' | 'string';
|
|
5
5
|
export type AnalyticsFilterOperator = 'eq' | 'exists' | 'gt' | 'gte' | 'in' | 'lt' | 'lte';
|
|
@@ -31,7 +31,7 @@ export interface TelescopeConversation {
|
|
|
31
31
|
audioUrl?: string;
|
|
32
32
|
createdAt: number;
|
|
33
33
|
endedAt?: number;
|
|
34
|
-
analytics: Record<string,
|
|
34
|
+
analytics: Record<string, AnalyticsScalar>;
|
|
35
35
|
}
|
|
36
36
|
export interface TelescopeConversationPage {
|
|
37
37
|
limit: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-analytics-query.d.ts","sourceRoot":"","sources":["../src/postgres-analytics-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAElD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"postgres-analytics-query.d.ts","sourceRoot":"","sources":["../src/postgres-analytics-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -301,9 +301,17 @@ function conversationRowToJson(row) {
|
|
|
301
301
|
audioUrl: row.recording_url || undefined,
|
|
302
302
|
createdAt: new Date(row.started_at).getTime(),
|
|
303
303
|
endedAt: row.ended_at ? new Date(row.ended_at).getTime() : undefined,
|
|
304
|
-
analytics: row.analytics
|
|
304
|
+
analytics: analyticsScalars(row.analytics),
|
|
305
305
|
};
|
|
306
306
|
}
|
|
307
|
+
function analyticsScalars(values) {
|
|
308
|
+
return Object.fromEntries(Object.entries(values ?? {}).filter((entry) => {
|
|
309
|
+
const value = entry[1];
|
|
310
|
+
return (typeof value === 'boolean' ||
|
|
311
|
+
typeof value === 'string' ||
|
|
312
|
+
(typeof value === 'number' && Number.isFinite(value)));
|
|
313
|
+
}));
|
|
314
|
+
}
|
|
307
315
|
function analyticsFieldRowsToJson(rows) {
|
|
308
316
|
const fields = new Map();
|
|
309
317
|
for (const row of rows) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Pool, PoolConfig, QueryResult } from 'pg';
|
|
2
|
-
import {
|
|
2
|
+
import { AnalyticsScalar, AnalyticsStore, ConversationAnalyticsSummary } from './analytics';
|
|
3
3
|
import { PostgresAnalyticsQueryService } from './postgres-analytics-query';
|
|
4
4
|
export interface ConversationRecord {
|
|
5
5
|
conversationId: string;
|
|
@@ -18,14 +18,13 @@ export interface PhoneCallRecord {
|
|
|
18
18
|
interface Queryable {
|
|
19
19
|
query<TResult extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: unknown[]): Promise<QueryResult<TResult>>;
|
|
20
20
|
}
|
|
21
|
-
export declare class PostgresAnalytics implements
|
|
21
|
+
export declare class PostgresAnalytics implements AnalyticsStore {
|
|
22
22
|
private readonly database;
|
|
23
23
|
constructor(database: Queryable);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
getSummary(conversationId: string): Promise<ConversationAnalyticsSummary | undefined>;
|
|
24
|
+
set(conversationId: string, agentId: string, fieldName: string, value: AnalyticsScalar): Promise<void>;
|
|
25
|
+
clear(conversationId: string, agentId: string, fieldName: string): Promise<void>;
|
|
26
|
+
get(conversationId: string, agentId: string, fieldName: string): Promise<unknown | undefined>;
|
|
27
|
+
getSummary(conversationId: string, agentId: string): Promise<ConversationAnalyticsSummary | undefined>;
|
|
29
28
|
}
|
|
30
29
|
export declare class PostgresConversationRepository {
|
|
31
30
|
private readonly pool;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-analytics.d.ts","sourceRoot":"","sources":["../src/postgres-analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAE9D,OAAO,EACH,
|
|
1
|
+
{"version":3,"file":"postgres-analytics.d.ts","sourceRoot":"","sources":["../src/postgres-analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAE9D,OAAO,EACH,eAAe,EACf,cAAc,EACd,4BAA4B,EAE/B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAA;AAI1E,MAAM,WAAW,kBAAkB;IAC/B,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;IACf,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,eAAe,CAAC,EAAE,MAAM,CAAA;CAC3B;AAID,MAAM,WAAW,eAAe;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAID,UAAU,SAAS;IACf,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAA;CACnC;AAaD,qBAAa,iBAAkB,YAAW,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,SAAS;IAE1C,GAAG,CACL,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC;IAeV,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAchF,GAAG,CACL,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAezB,UAAU,CACZ,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GAChB,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC;CAqBvD;AAgBD,qBAAa,8BAA8B;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEjC,gBAAgB,CAClB,YAAY,EAAE,kBAAkB,EAChC,SAAS,CAAC,EAAE,eAAe,GAC5B,OAAO,CAAC,IAAI,CAAC;YAmBF,kBAAkB;YA4ClB,eAAe;CA0BhC;AAsED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDxE;AA6BD,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,iBAAiB,CAAA;IAC5B,aAAa,EAAE,8BAA8B,CAAA;IAC7C,OAAO,EAAE,6BAA6B,CAAA;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAID,wBAAsB,+BAA+B,CACjD,MAAM,EAAE,UAAU,GACnB,OAAO,CAAC,yBAAyB,CAAC,CAgBpC"}
|
|
@@ -11,48 +11,40 @@ class PostgresAnalytics {
|
|
|
11
11
|
constructor(database) {
|
|
12
12
|
this.database = database;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
async set(conversationId, field, value) {
|
|
18
|
-
const parsed = field.schema.parse(value);
|
|
19
|
-
(0, analytics_1.assertAnalyticsJsonValue)(parsed);
|
|
20
|
-
const serialized = JSON.stringify(parsed);
|
|
21
|
-
if (serialized === undefined) {
|
|
22
|
-
throw new Error(`Analytics value for '${field.key}' is not valid JSON`);
|
|
23
|
-
}
|
|
14
|
+
async set(conversationId, agentId, fieldName, value) {
|
|
15
|
+
(0, analytics_1.assertAnalyticsScalar)(value);
|
|
16
|
+
const serialized = JSON.stringify(value);
|
|
24
17
|
const result = await this.database.query(`UPDATE conversations
|
|
25
18
|
SET analytics = jsonb_set(analytics, ARRAY[$3::text], $4::jsonb, true),
|
|
26
19
|
updated_at = now()
|
|
27
20
|
WHERE conversation_id = $1
|
|
28
|
-
AND agent_id = $2`, [conversationId,
|
|
29
|
-
assertConversationBelongsToAgent(result.rowCount, conversationId,
|
|
21
|
+
AND agent_id = $2`, [conversationId, agentId, fieldName, serialized]);
|
|
22
|
+
assertConversationBelongsToAgent(result.rowCount, conversationId, agentId);
|
|
30
23
|
}
|
|
31
|
-
async clear(conversationId,
|
|
24
|
+
async clear(conversationId, agentId, fieldName) {
|
|
32
25
|
const result = await this.database.query(`UPDATE conversations
|
|
33
26
|
SET analytics = analytics - $3::text,
|
|
34
27
|
updated_at = now()
|
|
35
28
|
WHERE conversation_id = $1
|
|
36
|
-
AND agent_id = $2`, [conversationId,
|
|
37
|
-
assertConversationBelongsToAgent(result.rowCount, conversationId,
|
|
29
|
+
AND agent_id = $2`, [conversationId, agentId, fieldName]);
|
|
30
|
+
assertConversationBelongsToAgent(result.rowCount, conversationId, agentId);
|
|
38
31
|
}
|
|
39
|
-
async get(conversationId,
|
|
32
|
+
async get(conversationId, agentId, fieldName) {
|
|
40
33
|
const result = await this.database.query(`SELECT analytics ? $3::text AS present,
|
|
41
34
|
analytics -> $3::text AS value
|
|
42
35
|
FROM conversations
|
|
43
36
|
WHERE conversation_id = $1
|
|
44
|
-
AND agent_id = $2`, [conversationId,
|
|
37
|
+
AND agent_id = $2`, [conversationId, agentId, fieldName]);
|
|
45
38
|
if (result.rows.length === 0 || !result.rows[0].present) {
|
|
46
39
|
return undefined;
|
|
47
40
|
}
|
|
48
|
-
return
|
|
41
|
+
return result.rows[0].value;
|
|
49
42
|
}
|
|
50
|
-
async getSummary(conversationId) {
|
|
43
|
+
async getSummary(conversationId, agentId) {
|
|
51
44
|
const result = await this.database.query(`SELECT conversation_id, agent_id, channel, started_at
|
|
52
45
|
FROM conversations
|
|
53
46
|
WHERE conversation_id = $1
|
|
54
|
-
AND agent_id
|
|
55
|
-
AND btrim(agent_id) <> ''`, [conversationId]);
|
|
47
|
+
AND agent_id = $2`, [conversationId, agentId]);
|
|
56
48
|
const row = result.rows[0];
|
|
57
49
|
if (!row) {
|
|
58
50
|
return undefined;
|