newo 1.9.1 → 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 +15 -0
- package/dist/sync.js +80 -51
- package/package.json +1 -1
- package/src/sync.ts +51 -22
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ 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
|
+
|
|
8
23
|
## [1.9.1] - 2025-09-16
|
|
9
24
|
|
|
10
25
|
### Fixed
|
package/dist/sync.js
CHANGED
|
@@ -1057,68 +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
|
-
|
|
1061
|
-
|
|
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
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
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
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
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
1143
|
console.log(` ⚠️ Chat history failed for ${persona.name}: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
|
|
1118
|
-
// No fallback - only use chat history API
|
|
1119
1144
|
hasMoreActs = false;
|
|
1120
1145
|
}
|
|
1121
1146
|
}
|
|
1147
|
+
if (actPage > maxPages) {
|
|
1148
|
+
if (verbose)
|
|
1149
|
+
console.log(` ⚠️ ${persona.name}: Reached max pages limit (${maxPages}), stopping pagination`);
|
|
1150
|
+
}
|
|
1122
1151
|
// Sort acts by datetime ascending (chronological order)
|
|
1123
1152
|
allActs.sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime());
|
|
1124
1153
|
// Process acts into simplified format - exclude redundant fields
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newo",
|
|
3
|
-
"version": "1.9.
|
|
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/sync.ts
CHANGED
|
@@ -1234,24 +1234,41 @@ export async function pullConversations(
|
|
|
1234
1234
|
const actsPerPage = 100; // Higher limit for acts
|
|
1235
1235
|
let hasMoreActs = true;
|
|
1236
1236
|
|
|
1237
|
-
|
|
1238
|
-
|
|
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) {
|
|
1239
1261
|
try {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
if (
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
per: actsPerPage
|
|
1251
|
-
};
|
|
1252
|
-
|
|
1253
|
-
const chatResponse = await getChatHistory(client, chatHistoryParams);
|
|
1254
|
-
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) {
|
|
1255
1272
|
// Convert chat history format to acts format - create minimal ConversationAct objects
|
|
1256
1273
|
const convertedActs: ConversationAct[] = chatResponse.items.map((item: any) => ({
|
|
1257
1274
|
id: item.id || `chat_${Math.random()}`,
|
|
@@ -1288,20 +1305,32 @@ export async function pullConversations(
|
|
|
1288
1305
|
console.log(` 👤 ${persona.name}: Chat History - ${convertedActs.length} messages (${allActs.length} total)`);
|
|
1289
1306
|
}
|
|
1290
1307
|
|
|
1308
|
+
// Check if we should continue paginating
|
|
1309
|
+
const hasMetadata = chatResponse.metadata?.total !== undefined;
|
|
1310
|
+
const currentTotal = chatResponse.metadata?.total || 0;
|
|
1311
|
+
|
|
1291
1312
|
hasMoreActs = chatResponse.items.length === actsPerPage &&
|
|
1292
|
-
|
|
1293
|
-
allActs.length <
|
|
1313
|
+
hasMetadata &&
|
|
1314
|
+
allActs.length < currentTotal;
|
|
1315
|
+
|
|
1294
1316
|
actPage++;
|
|
1295
|
-
|
|
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`);
|
|
1296
1323
|
}
|
|
1297
|
-
}
|
|
1298
1324
|
} catch (chatError) {
|
|
1299
1325
|
if (verbose) console.log(` ⚠️ Chat history failed for ${persona.name}: ${chatError instanceof Error ? chatError.message : String(chatError)}`);
|
|
1300
|
-
// No fallback - only use chat history API
|
|
1301
1326
|
hasMoreActs = false;
|
|
1302
1327
|
}
|
|
1303
1328
|
}
|
|
1304
1329
|
|
|
1330
|
+
if (actPage > maxPages) {
|
|
1331
|
+
if (verbose) console.log(` ⚠️ ${persona.name}: Reached max pages limit (${maxPages}), stopping pagination`);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1305
1334
|
// Sort acts by datetime ascending (chronological order)
|
|
1306
1335
|
allActs.sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime());
|
|
1307
1336
|
|