@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.
@@ -1,32 +1,29 @@
1
1
  import { z } from 'zod';
2
- export type AnalyticsJsonValue = boolean | number | string | null | AnalyticsJsonValue[] | {
3
- [key: string]: AnalyticsJsonValue;
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 Analytics {
26
- registerAgent<TFields extends AnalyticsFieldDefinitions>(agentId: string, fields: TFields): RegisteredAnalyticsFields<TFields>;
27
- set<TValue>(conversationId: string, field: AnalyticsField<TValue>, value: TValue): Promise<void>;
28
- clear(conversationId: string, field: AnalyticsField<unknown>): Promise<void>;
29
- get<TValue>(conversationId: string, field: AnalyticsField<TValue>): Promise<TValue | undefined>;
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 registerAnalyticsFields<TFields extends AnalyticsFieldDefinitions>(agentId: string, fields: TFields): RegisteredAnalyticsFields<TFields>;
40
- export declare function createInMemoryAnalytics(summaries?: ConversationAnalyticsSummary[]): Analytics;
41
- export declare function assertAnalyticsJsonValue(value: unknown): asserts value is AnalyticsJsonValue;
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
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AACvD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAIhE,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;CAChC;AAED,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAInG,MAAM,MAAM,cAAc,CAAC,MAAM,SAAS,wBAAwB,CAAC,OAAO,CAAC,IACvE,MAAM,SAAS,wBAAwB,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAA;AAE1E,KAAK,kBAAkB,CAAC,OAAO,SAAS,yBAAyB,IAAI,OAAO,CAAC,MAAM,OAAO,EAAE,MAAM,CAAC,CAAA;AAEnG,MAAM,WAAW,4BAA4B;IACzC,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAClB;AAMD,MAAM,WAAW,cAAc;IAC3B,GAAG,CACC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChF,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAA;IAC7F,UAAU,CACN,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GAChB,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC,CAAA;CACvD;AAMD,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,yBAAyB;IACrE,GAAG,CAAC,KAAK,SAAS,kBAAkB,CAAC,OAAO,CAAC,EACzC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,KAAK,EAChB,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,KAAK,CAAC,KAAK,SAAS,kBAAkB,CAAC,OAAO,CAAC,EAC3C,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,KAAK,GACjB,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,GAAG,CAAC,KAAK,SAAS,kBAAkB,CAAC,OAAO,CAAC,EACzC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,KAAK,GACjB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IACtD,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC,CAAA;CACxF;AAWD,eAAO,MAAM,cAAc;eACZ,wBAAwB,CAAC,OAAO,CAAC;cAGlC,wBAAwB,CAAC,MAAM,CAAC;cAGhC,wBAAwB,CAAC,MAAM,CAAC;eAG/B,OAAO,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,UAC7C,OAAO,GAChB,wBAAwB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;CAG/C,CAAA;AAID,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAa/F;AASD,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,yBAAyB,EAC1E,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GAChB,cAAc,CAAC,OAAO,CAAC,CAsCzB;AAID,wBAAgB,uBAAuB,CACnC,SAAS,GAAE,4BAA4B,EAAO,GAC/C,cAAc,CA2ChB;AAID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,eAAe,CAStF"}
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.analyticsField = void 0;
4
- exports.registerAnalyticsFields = registerAnalyticsFields;
4
+ exports.validateAgentAnalytics = validateAgentAnalytics;
5
+ exports.createAgentAnalytics = createAgentAnalytics;
5
6
  exports.createInMemoryAnalytics = createInMemoryAnalytics;
6
- exports.assertAnalyticsJsonValue = assertAnalyticsJsonValue;
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 registerAnalyticsFields(agentId, fields) {
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 registered = Object.fromEntries(Object.entries(fields).map(([key, definition]) => {
33
- if (!/^[A-Za-z0-9_.:-]{1,128}$/.test(key)) {
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
- return [key, Object.freeze({ ...definition, agentId, key })];
37
- }));
38
- return Object.freeze(registered);
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
- registerAgent: registerAnalyticsFields,
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 !== field.agentId) {
76
+ if (existingAgentId !== undefined && existingAgentId !== agentId) {
49
77
  throw new Error(`Conversation '${conversationId}' belongs to another agent`);
50
78
  }
51
- const parsed = field.schema.parse(value);
52
- assertAnalyticsJsonValue(parsed);
79
+ assertAnalyticsScalar(value);
53
80
  const values = conversations.get(conversationId) ?? new Map();
54
- values.set(field.key, structuredClone(parsed));
81
+ values.set(fieldName, value);
55
82
  conversations.set(conversationId, values);
56
- conversationAgents.set(conversationId, field.agentId);
83
+ conversationAgents.set(conversationId, agentId);
57
84
  },
58
- async clear(conversationId, field) {
59
- if (conversationAgents.get(conversationId) !== field.agentId) {
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(field.key);
90
+ values?.delete(fieldName);
64
91
  if (values?.size === 0) {
65
92
  conversations.delete(conversationId);
66
93
  }
67
94
  },
68
- async get(conversationId, field) {
69
- if (conversationAgents.get(conversationId) !== field.agentId) {
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 field.schema.parse(structuredClone(values.get(field.key)));
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 assertAnalyticsJsonValue(value) {
85
- if (value === null ||
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
- if (Array.isArray(value)) {
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 { Analytics } from '../analytics';
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: 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?: Record<string, string | number>;
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 declare function createAgent<TContext extends {}, TServices, TModels extends IModels>(creator: (platform: Platform<TContext, TModels>, services: TServices) => VoiceAgent): (platform: Platform<TContext, TModels>, services: TServices) => VoiceAgent;
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;AAI7B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,MAAM,WAAW,OAAO;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAClC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CACpD;AAID,MAAM,WAAW,QAAQ,CACrB,QAAQ,SAAS,EAAE,EACnB,OAAO,SAAS,OAAO,EACvB,QAAQ,GAAG,QAAQ,EACnB,eAAe,GAAG,cAAc,EAChC,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC;IAGtC,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IAElC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAEtB,EAAE,EAAE,QAAQ,CAAA;IAEZ,OAAO,EAAE,QAAQ,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,eAAe,CAAA;IAE/B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IACzB,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAE3C,YAAY,EAAE,aAAa,CAAA;IAK3B,SAAS,EAAE,SAAS,CAAA;CACvB;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,UAAU;IACvB,WAAW,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;QACrC,cAAc,EAAE,MAAM,CAAA;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;KACpD,CAAC,CAAA;IACF,WAAW,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,cAAc,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAA;IAC/F,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,iBAAiB,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzE,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D;AAED,wBAAgB,WAAW,CAAC,QAAQ,SAAS,EAAE,EAAE,SAAS,EAAE,OAAO,SAAS,OAAO,EAC/E,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,KAAK,UAAU,cAA/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,SAAS,KAAK,UAAU,CAGtF"}
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
- function createAgent(creator) {
5
- return creator;
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 { AnalyticsJsonValue } from './analytics';
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, AnalyticsJsonValue>;
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":"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"}
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 { Analytics, AnalyticsField, AnalyticsFieldDefinitions, ConversationAnalyticsSummary, RegisteredAnalyticsFields } from './analytics';
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 Analytics {
21
+ export declare class PostgresAnalytics implements AnalyticsStore {
22
22
  private readonly database;
23
23
  constructor(database: Queryable);
24
- registerAgent<TFields extends AnalyticsFieldDefinitions>(agentId: string, fields: TFields): RegisteredAnalyticsFields<TFields>;
25
- set<TValue>(conversationId: string, field: AnalyticsField<TValue>, value: TValue): Promise<void>;
26
- clear(conversationId: string, field: AnalyticsField<unknown>): Promise<void>;
27
- get<TValue>(conversationId: string, field: AnalyticsField<TValue>): Promise<TValue | undefined>;
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,SAAS,EACT,cAAc,EACd,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EAG5B,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,SAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,SAAS;IAEhD,aAAa,CAAC,OAAO,SAAS,yBAAyB,EACnD,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GAChB,yBAAyB,CAAC,OAAO,CAAC;IAI/B,GAAG,CAAC,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,EAC7B,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAqBV,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5E,GAAG,CAAC,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,GAC9B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAiBxB,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC;CAsB9F;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"}
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
- registerAgent(agentId, fields) {
15
- return (0, analytics_1.registerAnalyticsFields)(agentId, fields);
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, field.agentId, field.key, serialized]);
29
- assertConversationBelongsToAgent(result.rowCount, conversationId, field.agentId);
21
+ AND agent_id = $2`, [conversationId, agentId, fieldName, serialized]);
22
+ assertConversationBelongsToAgent(result.rowCount, conversationId, agentId);
30
23
  }
31
- async clear(conversationId, field) {
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, field.agentId, field.key]);
37
- assertConversationBelongsToAgent(result.rowCount, conversationId, field.agentId);
29
+ AND agent_id = $2`, [conversationId, agentId, fieldName]);
30
+ assertConversationBelongsToAgent(result.rowCount, conversationId, agentId);
38
31
  }
39
- async get(conversationId, field) {
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, field.agentId, field.key]);
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 field.schema.parse(result.rows[0].value);
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 IS NOT NULL
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recombine-ai/platform",
3
- "version": "0.2.6-test.8",
3
+ "version": "0.2.6-test.9",
4
4
  "description": "Recombine AI: voice agent platform",
5
5
  "license": "EULA",
6
6
  "author": "recombine.ai",