newo 1.9.0 → 1.9.2

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/CHANGELOG.md CHANGED
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.2] - 2025-09-16
9
+
10
+ ### Fixed
11
+ - **Pagination Safety**: Prevent infinite loops and hanging during conversation processing
12
+ - Added max pages limit (50 pages = 5000 acts per persona) to prevent infinite pagination
13
+ - Improved persona filtering for voice actors to avoid unnecessary API calls
14
+ - Better error handling and verbose logging for debugging conversation processing
15
+ - Graceful handling of personas without voice actors (adds with empty acts array)
16
+
17
+ ### Enhanced
18
+ - **Performance Optimization**: Faster conversation processing with early exits
19
+ - Skip personas without newo_voice actors immediately
20
+ - Clear verbose logging for pagination progress
21
+ - Optimized control flow to prevent hanging during large conversation extraction
22
+
23
+ ## [1.9.1] - 2025-09-16
24
+
25
+ ### Fixed
26
+ - **Clean Chat History Implementation**: Remove conversations acts API fallback entirely
27
+ - Eliminates all 403 "Invalid token or account_id field missing" errors
28
+ - Uses only `/api/v1/chat/history` endpoint which works with current API keys
29
+ - Removed unused `getConversationActs()` function and related types
30
+ - Clean implementation without permission-dependent fallbacks
31
+
32
+ ### Removed
33
+ - **Obsolete Code Cleanup**: Remove unused conversation acts API components
34
+ - `getConversationActs()` function (unused after chat history integration)
35
+ - `ConversationActsParams` and `ConversationActsResponse` interfaces
36
+ - Fallback logic that caused 403 errors for personas without proper permissions
37
+
8
38
  ## [1.9.0] - 2025-09-16
9
39
 
10
40
  ### Added
package/dist/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type AxiosInstance } from 'axios';
2
- import type { ProjectMeta, Agent, Skill, FlowEvent, FlowState, AkbImportArticle, CustomerProfile, CustomerAttribute, CustomerAttributesResponse, UserPersonaResponse, UserPersona, ConversationActsResponse, ConversationActsParams, ChatHistoryParams, ChatHistoryResponse } from './types.js';
2
+ import type { ProjectMeta, Agent, Skill, FlowEvent, FlowState, AkbImportArticle, CustomerProfile, CustomerAttribute, CustomerAttributesResponse, UserPersonaResponse, UserPersona, ChatHistoryParams, ChatHistoryResponse } from './types.js';
3
3
  export declare function makeClient(verbose?: boolean, token?: string): Promise<AxiosInstance>;
4
4
  export declare function listProjects(client: AxiosInstance): Promise<ProjectMeta[]>;
5
5
  export declare function listAgents(client: AxiosInstance, projectId: string): Promise<Agent[]>;
@@ -19,6 +19,5 @@ export declare function getAccount(client: AxiosInstance): Promise<{
19
19
  id: string;
20
20
  [key: string]: any;
21
21
  }>;
22
- export declare function getConversationActs(client: AxiosInstance, params: ConversationActsParams): Promise<ConversationActsResponse>;
23
22
  export declare function getChatHistory(client: AxiosInstance, params: ChatHistoryParams): Promise<ChatHistoryResponse>;
24
23
  //# sourceMappingURL=api.d.ts.map
package/dist/api.js CHANGED
@@ -136,26 +136,6 @@ export async function getAccount(client) {
136
136
  const response = await client.get('/api/v1/account');
137
137
  return response.data;
138
138
  }
139
- export async function getConversationActs(client, params) {
140
- const queryParams = {
141
- user_persona_id: params.user_persona_id,
142
- page: params.page || 1,
143
- per: params.per || 50
144
- };
145
- // Only add optional parameters if explicitly provided
146
- if (params.turn_type)
147
- queryParams.turn_type = params.turn_type;
148
- if (params.connectors)
149
- queryParams.connectors = params.connectors;
150
- if (params.from_date)
151
- queryParams.from_date = params.from_date;
152
- if (params.to_date)
153
- queryParams.to_date = params.to_date;
154
- const response = await client.get('/api/v1/bff/conversations/acts', {
155
- params: queryParams
156
- });
157
- return response.data;
158
- }
159
139
  export async function getChatHistory(client, params) {
160
140
  const queryParams = {
161
141
  user_actor_id: params.user_actor_id,
package/dist/sync.js CHANGED
@@ -1,4 +1,4 @@
1
- import { listProjects, listAgents, listFlowSkills, updateSkill, listFlowEvents, listFlowStates, getProjectMeta, getCustomerAttributes, updateCustomerAttribute, listUserPersonas, getConversationActs, getChatHistory } from './api.js';
1
+ import { listProjects, listAgents, listFlowSkills, updateSkill, listFlowEvents, listFlowStates, getProjectMeta, getCustomerAttributes, updateCustomerAttribute, listUserPersonas, getChatHistory } from './api.js';
2
2
  import { ensureState, skillPath, skillScriptPath, writeFileSafe, readIfExists, mapPath, projectMetadataPath, agentMetadataPath, flowMetadataPath, skillMetadataPath, flowsYamlPath, customerAttributesPath, customerAttributesMapPath, customerAttributesBackupPath } from './fsutil.js';
3
3
  import fs from 'fs-extra';
4
4
  import { sha256, loadHashes, saveHashes } from './hash.js';
@@ -1057,90 +1057,97 @@ export async function pullConversations(client, customer, options = {}, verbose
1057
1057
  let actPage = 1;
1058
1058
  const actsPerPage = 100; // Higher limit for acts
1059
1059
  let hasMoreActs = true;
1060
- while (hasMoreActs) {
1061
- // First try the chat history API as alternative
1060
+ // Get user actor IDs from persona actors first
1061
+ const userActors = persona.actors.filter(actor => actor.integration_idn === 'newo_voice' &&
1062
+ actor.connector_idn === 'newo_voice_connector');
1063
+ if (userActors.length === 0) {
1064
+ if (verbose)
1065
+ console.log(` 👤 ${persona.name}: No voice actors found, skipping`);
1066
+ // No voice actors, can't get chat history - add persona with empty acts
1067
+ processedPersonas.push({
1068
+ id: persona.id,
1069
+ name: persona.name,
1070
+ phone,
1071
+ act_count: persona.act_count,
1072
+ acts: []
1073
+ });
1074
+ if (verbose)
1075
+ console.log(` ✓ Processed ${persona.name}: 0 acts (no voice actors)`);
1076
+ return; // Return from the concurrency function
1077
+ }
1078
+ // Safety mechanism to prevent infinite loops
1079
+ const maxPages = 50; // Limit to 50 pages (5000 acts max per persona)
1080
+ while (hasMoreActs && actPage <= maxPages) {
1062
1081
  try {
1063
- // Get user actor IDs from persona actors
1064
- const userActors = persona.actors.filter(actor => actor.integration_idn === 'newo_voice' &&
1065
- actor.connector_idn === 'newo_voice_connector');
1066
- if (userActors.length > 0) {
1067
- const chatHistoryParams = {
1082
+ const chatHistoryParams = {
1083
+ user_actor_id: userActors[0].id,
1084
+ page: actPage,
1085
+ per: actsPerPage
1086
+ };
1087
+ if (verbose)
1088
+ console.log(` 📄 ${persona.name}: Fetching page ${actPage}...`);
1089
+ const chatResponse = await getChatHistory(client, chatHistoryParams);
1090
+ if (chatResponse.items && chatResponse.items.length > 0) {
1091
+ // Convert chat history format to acts format - create minimal ConversationAct objects
1092
+ const convertedActs = chatResponse.items.map((item) => ({
1093
+ id: item.id || `chat_${Math.random()}`,
1094
+ command_act_id: null,
1095
+ external_event_id: item.external_event_id || 'chat_history',
1096
+ arguments: [],
1097
+ reference_idn: (item.is_agent === true) ? 'agent_message' : 'user_message',
1098
+ runtime_context_id: item.runtime_context_id || 'chat_history',
1099
+ source_text: item.payload?.text || item.message || item.content || item.text || '',
1100
+ original_text: item.payload?.text || item.message || item.content || item.text || '',
1101
+ datetime: item.datetime || item.created_at || item.timestamp || new Date().toISOString(),
1068
1102
  user_actor_id: userActors[0].id,
1069
- page: actPage,
1070
- per: actsPerPage
1071
- };
1072
- const chatResponse = await getChatHistory(client, chatHistoryParams);
1073
- if (chatResponse.items && chatResponse.items.length > 0) {
1074
- // Convert chat history format to acts format - create minimal ConversationAct objects
1075
- const convertedActs = chatResponse.items.map((item) => ({
1076
- id: item.id || `chat_${Math.random()}`,
1077
- command_act_id: null,
1078
- external_event_id: item.external_event_id || 'chat_history',
1079
- arguments: [],
1080
- reference_idn: (item.is_agent === true) ? 'agent_message' : 'user_message',
1081
- runtime_context_id: item.runtime_context_id || 'chat_history',
1082
- source_text: item.payload?.text || item.message || item.content || item.text || '',
1083
- original_text: item.payload?.text || item.message || item.content || item.text || '',
1084
- datetime: item.datetime || item.created_at || item.timestamp || new Date().toISOString(),
1085
- user_actor_id: userActors[0].id,
1086
- agent_actor_id: null,
1087
- user_persona_id: persona.id,
1088
- user_persona_name: persona.name,
1089
- agent_persona_id: item.agent_persona_id || 'unknown',
1090
- external_id: item.external_id || null,
1091
- integration_idn: 'newo_voice',
1092
- connector_idn: 'newo_voice_connector',
1093
- to_integration_idn: null,
1094
- to_connector_idn: null,
1095
- is_agent: Boolean(item.is_agent === true),
1096
- project_idn: null,
1097
- flow_idn: item.flow_idn || 'unknown',
1098
- skill_idn: item.skill_idn || 'unknown',
1099
- session_id: item.session_id || 'unknown',
1100
- recordings: item.recordings || [],
1101
- contact_information: item.contact_information || null
1102
- }));
1103
- allActs.push(...convertedActs);
1104
- if (verbose && convertedActs.length > 0) {
1105
- console.log(` 👤 ${persona.name}: Chat History - ${convertedActs.length} messages (${allActs.length} total)`);
1106
- }
1107
- hasMoreActs = chatResponse.items.length === actsPerPage &&
1108
- chatResponse.metadata?.total !== undefined &&
1109
- allActs.length < chatResponse.metadata.total;
1110
- actPage++;
1111
- continue; // Skip the original acts API call
1103
+ agent_actor_id: null,
1104
+ user_persona_id: persona.id,
1105
+ user_persona_name: persona.name,
1106
+ agent_persona_id: item.agent_persona_id || 'unknown',
1107
+ external_id: item.external_id || null,
1108
+ integration_idn: 'newo_voice',
1109
+ connector_idn: 'newo_voice_connector',
1110
+ to_integration_idn: null,
1111
+ to_connector_idn: null,
1112
+ is_agent: Boolean(item.is_agent === true),
1113
+ project_idn: null,
1114
+ flow_idn: item.flow_idn || 'unknown',
1115
+ skill_idn: item.skill_idn || 'unknown',
1116
+ session_id: item.session_id || 'unknown',
1117
+ recordings: item.recordings || [],
1118
+ contact_information: item.contact_information || null
1119
+ }));
1120
+ allActs.push(...convertedActs);
1121
+ if (verbose && convertedActs.length > 0) {
1122
+ console.log(` 👤 ${persona.name}: Chat History - ${convertedActs.length} messages (${allActs.length} total)`);
1112
1123
  }
1124
+ // Check if we should continue paginating
1125
+ const hasMetadata = chatResponse.metadata?.total !== undefined;
1126
+ const currentTotal = chatResponse.metadata?.total || 0;
1127
+ hasMoreActs = chatResponse.items.length === actsPerPage &&
1128
+ hasMetadata &&
1129
+ allActs.length < currentTotal;
1130
+ actPage++;
1131
+ if (verbose)
1132
+ console.log(` 📊 ${persona.name}: Page ${actPage - 1} done, ${allActs.length}/${currentTotal} total acts`);
1133
+ }
1134
+ else {
1135
+ // No more items
1136
+ hasMoreActs = false;
1137
+ if (verbose)
1138
+ console.log(` 📊 ${persona.name}: No more chat history items`);
1113
1139
  }
1114
1140
  }
1115
1141
  catch (chatError) {
1116
1142
  if (verbose)
1117
- console.log(` ⚠️ Chat history failed for ${persona.name}, trying acts API: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
1118
- }
1119
- // Fallback to original acts API
1120
- const actsParams = {
1121
- user_persona_id: persona.id,
1122
- page: actPage,
1123
- per: actsPerPage,
1124
- turn_type: 'messages',
1125
- connectors: options.connectors?.join(',') || 'newo_voice/*',
1126
- ...(options.fromDate && { from_date: options.fromDate }),
1127
- ...(options.toDate && { to_date: options.toDate })
1128
- };
1129
- const actsResponse = await getConversationActs(client, actsParams);
1130
- allActs.push(...actsResponse.items);
1131
- if (verbose && actsResponse.items.length > 0) {
1132
- console.log(` 👤 ${persona.name}: Page ${actPage} - ${actsResponse.items.length} acts (${allActs.length}/${actsResponse.metadata.total} total)`);
1133
- }
1134
- hasMoreActs = actsResponse.items.length === actsPerPage && allActs.length < actsResponse.metadata.total;
1135
- actPage++;
1136
- // Apply per-persona act limit if specified
1137
- if (options.maxActsPerPersona && allActs.length >= options.maxActsPerPersona) {
1138
- allActs.splice(options.maxActsPerPersona);
1143
+ console.log(` ⚠️ Chat history failed for ${persona.name}: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
1139
1144
  hasMoreActs = false;
1140
- if (verbose)
1141
- console.log(` ⚠️ Limited to ${options.maxActsPerPersona} acts for ${persona.name}`);
1142
1145
  }
1143
1146
  }
1147
+ if (actPage > maxPages) {
1148
+ if (verbose)
1149
+ console.log(` ⚠️ ${persona.name}: Reached max pages limit (${maxPages}), stopping pagination`);
1150
+ }
1144
1151
  // Sort acts by datetime ascending (chronological order)
1145
1152
  allActs.sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime());
1146
1153
  // Process acts into simplified format - exclude redundant fields
package/dist/types.d.ts CHANGED
@@ -337,23 +337,6 @@ export interface UserPersonaResponse {
337
337
  readonly total: number;
338
338
  };
339
339
  }
340
- export interface ConversationActsResponse {
341
- readonly items: readonly ConversationAct[];
342
- readonly metadata: {
343
- readonly page: number;
344
- readonly per: number;
345
- readonly total: number;
346
- };
347
- }
348
- export interface ConversationActsParams {
349
- readonly turn_type?: string;
350
- readonly connectors?: string;
351
- readonly user_persona_id: string;
352
- readonly page?: number;
353
- readonly per?: number;
354
- readonly from_date?: string;
355
- readonly to_date?: string;
356
- }
357
340
  export interface ChatHistoryParams {
358
341
  readonly user_actor_id: string;
359
342
  readonly agent_actor_id?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newo",
3
- "version": "1.9.0",
3
+ "version": "1.9.2",
4
4
  "description": "NEWO CLI: comprehensive sync for AI Agent skills, customer attributes, conversations, and metadata between NEWO platform and local files. Multi-customer workspaces, conversation history extraction, complete change tracking, Git-first workflows.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.ts CHANGED
@@ -13,8 +13,6 @@ import type {
13
13
  CustomerAttributesResponse,
14
14
  UserPersonaResponse,
15
15
  UserPersona,
16
- ConversationActsResponse,
17
- ConversationActsParams,
18
16
  ChatHistoryParams,
19
17
  ChatHistoryResponse
20
18
  } from './types.js';
@@ -179,24 +177,6 @@ export async function getAccount(client: AxiosInstance): Promise<{ id: string; [
179
177
  return response.data;
180
178
  }
181
179
 
182
- export async function getConversationActs(client: AxiosInstance, params: ConversationActsParams): Promise<ConversationActsResponse> {
183
- const queryParams: Record<string, any> = {
184
- user_persona_id: params.user_persona_id,
185
- page: params.page || 1,
186
- per: params.per || 50
187
- };
188
-
189
- // Only add optional parameters if explicitly provided
190
- if (params.turn_type) queryParams.turn_type = params.turn_type;
191
- if (params.connectors) queryParams.connectors = params.connectors;
192
- if (params.from_date) queryParams.from_date = params.from_date;
193
- if (params.to_date) queryParams.to_date = params.to_date;
194
-
195
- const response = await client.get<ConversationActsResponse>('/api/v1/bff/conversations/acts', {
196
- params: queryParams
197
- });
198
- return response.data;
199
- }
200
180
 
201
181
  export async function getChatHistory(client: AxiosInstance, params: ChatHistoryParams): Promise<ChatHistoryResponse> {
202
182
  const queryParams: Record<string, any> = {
package/src/sync.ts CHANGED
@@ -9,7 +9,6 @@ import {
9
9
  getCustomerAttributes,
10
10
  updateCustomerAttribute,
11
11
  listUserPersonas,
12
- getConversationActs,
13
12
  getChatHistory
14
13
  } from './api.js';
15
14
  import {
@@ -1235,24 +1234,41 @@ export async function pullConversations(
1235
1234
  const actsPerPage = 100; // Higher limit for acts
1236
1235
  let hasMoreActs = true;
1237
1236
 
1238
- while (hasMoreActs) {
1239
- // First try the chat history API as alternative
1237
+ // Get user actor IDs from persona actors first
1238
+ const userActors = persona.actors.filter(actor =>
1239
+ actor.integration_idn === 'newo_voice' &&
1240
+ actor.connector_idn === 'newo_voice_connector'
1241
+ );
1242
+
1243
+ if (userActors.length === 0) {
1244
+ if (verbose) console.log(` 👤 ${persona.name}: No voice actors found, skipping`);
1245
+ // No voice actors, can't get chat history - add persona with empty acts
1246
+ processedPersonas.push({
1247
+ id: persona.id,
1248
+ name: persona.name,
1249
+ phone,
1250
+ act_count: persona.act_count,
1251
+ acts: []
1252
+ });
1253
+ if (verbose) console.log(` ✓ Processed ${persona.name}: 0 acts (no voice actors)`);
1254
+ return; // Return from the concurrency function
1255
+ }
1256
+
1257
+ // Safety mechanism to prevent infinite loops
1258
+ const maxPages = 50; // Limit to 50 pages (5000 acts max per persona)
1259
+
1260
+ while (hasMoreActs && actPage <= maxPages) {
1240
1261
  try {
1241
- // Get user actor IDs from persona actors
1242
- const userActors = persona.actors.filter(actor =>
1243
- actor.integration_idn === 'newo_voice' &&
1244
- actor.connector_idn === 'newo_voice_connector'
1245
- );
1246
-
1247
- if (userActors.length > 0) {
1248
- const chatHistoryParams = {
1249
- user_actor_id: userActors[0]!.id,
1250
- page: actPage,
1251
- per: actsPerPage
1252
- };
1253
-
1254
- const chatResponse = await getChatHistory(client, chatHistoryParams);
1255
- if (chatResponse.items && chatResponse.items.length > 0) {
1262
+ const chatHistoryParams = {
1263
+ user_actor_id: userActors[0]!.id,
1264
+ page: actPage,
1265
+ per: actsPerPage
1266
+ };
1267
+
1268
+ if (verbose) console.log(` 📄 ${persona.name}: Fetching page ${actPage}...`);
1269
+ const chatResponse = await getChatHistory(client, chatHistoryParams);
1270
+
1271
+ if (chatResponse.items && chatResponse.items.length > 0) {
1256
1272
  // Convert chat history format to acts format - create minimal ConversationAct objects
1257
1273
  const convertedActs: ConversationAct[] = chatResponse.items.map((item: any) => ({
1258
1274
  id: item.id || `chat_${Math.random()}`,
@@ -1289,46 +1305,32 @@ export async function pullConversations(
1289
1305
  console.log(` 👤 ${persona.name}: Chat History - ${convertedActs.length} messages (${allActs.length} total)`);
1290
1306
  }
1291
1307
 
1308
+ // Check if we should continue paginating
1309
+ const hasMetadata = chatResponse.metadata?.total !== undefined;
1310
+ const currentTotal = chatResponse.metadata?.total || 0;
1311
+
1292
1312
  hasMoreActs = chatResponse.items.length === actsPerPage &&
1293
- chatResponse.metadata?.total !== undefined &&
1294
- allActs.length < chatResponse.metadata.total;
1313
+ hasMetadata &&
1314
+ allActs.length < currentTotal;
1315
+
1295
1316
  actPage++;
1296
- continue; // Skip the original acts API call
1317
+
1318
+ if (verbose) console.log(` 📊 ${persona.name}: Page ${actPage - 1} done, ${allActs.length}/${currentTotal} total acts`);
1319
+ } else {
1320
+ // No more items
1321
+ hasMoreActs = false;
1322
+ if (verbose) console.log(` 📊 ${persona.name}: No more chat history items`);
1297
1323
  }
1298
- }
1299
1324
  } catch (chatError) {
1300
- if (verbose) console.log(` ⚠️ Chat history failed for ${persona.name}, trying acts API: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
1301
- }
1302
-
1303
- // Fallback to original acts API
1304
- const actsParams = {
1305
- user_persona_id: persona.id,
1306
- page: actPage,
1307
- per: actsPerPage,
1308
- turn_type: 'messages',
1309
- connectors: options.connectors?.join(',') || 'newo_voice/*',
1310
- ...(options.fromDate && { from_date: options.fromDate }),
1311
- ...(options.toDate && { to_date: options.toDate })
1312
- };
1313
-
1314
- const actsResponse = await getConversationActs(client, actsParams);
1315
- allActs.push(...actsResponse.items);
1316
-
1317
- if (verbose && actsResponse.items.length > 0) {
1318
- console.log(` 👤 ${persona.name}: Page ${actPage} - ${actsResponse.items.length} acts (${allActs.length}/${actsResponse.metadata.total} total)`);
1319
- }
1320
-
1321
- hasMoreActs = actsResponse.items.length === actsPerPage && allActs.length < actsResponse.metadata.total;
1322
- actPage++;
1323
-
1324
- // Apply per-persona act limit if specified
1325
- if (options.maxActsPerPersona && allActs.length >= options.maxActsPerPersona) {
1326
- allActs.splice(options.maxActsPerPersona);
1325
+ if (verbose) console.log(` ⚠️ Chat history failed for ${persona.name}: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
1327
1326
  hasMoreActs = false;
1328
- if (verbose) console.log(` ⚠️ Limited to ${options.maxActsPerPersona} acts for ${persona.name}`);
1329
1327
  }
1330
1328
  }
1331
1329
 
1330
+ if (actPage > maxPages) {
1331
+ if (verbose) console.log(` ⚠️ ${persona.name}: Reached max pages limit (${maxPages}), stopping pagination`);
1332
+ }
1333
+
1332
1334
  // Sort acts by datetime ascending (chronological order)
1333
1335
  allActs.sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime());
1334
1336
 
package/src/types.ts CHANGED
@@ -399,24 +399,6 @@ export interface UserPersonaResponse {
399
399
  };
400
400
  }
401
401
 
402
- export interface ConversationActsResponse {
403
- readonly items: readonly ConversationAct[];
404
- readonly metadata: {
405
- readonly page: number;
406
- readonly per: number;
407
- readonly total: number;
408
- };
409
- }
410
-
411
- export interface ConversationActsParams {
412
- readonly turn_type?: string;
413
- readonly connectors?: string;
414
- readonly user_persona_id: string;
415
- readonly page?: number;
416
- readonly per?: number;
417
- readonly from_date?: string;
418
- readonly to_date?: string;
419
- }
420
402
 
421
403
  export interface ChatHistoryParams {
422
404
  readonly user_actor_id: string;