newo 2.0.6 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +338 -224
  2. package/README.md +257 -0
  3. package/dist/api.d.ts +23 -1
  4. package/dist/api.js +114 -0
  5. package/dist/auth.js +4 -0
  6. package/dist/cli/commands/create-agent.d.ts +3 -0
  7. package/dist/cli/commands/create-agent.js +75 -0
  8. package/dist/cli/commands/create-attribute.d.ts +3 -0
  9. package/dist/cli/commands/create-attribute.js +63 -0
  10. package/dist/cli/commands/create-event.d.ts +3 -0
  11. package/dist/cli/commands/create-event.js +66 -0
  12. package/dist/cli/commands/create-flow.d.ts +3 -0
  13. package/dist/cli/commands/create-flow.js +100 -0
  14. package/dist/cli/commands/create-parameter.d.ts +3 -0
  15. package/dist/cli/commands/create-parameter.js +47 -0
  16. package/dist/cli/commands/create-persona.d.ts +3 -0
  17. package/dist/cli/commands/create-persona.js +43 -0
  18. package/dist/cli/commands/create-project.d.ts +3 -0
  19. package/dist/cli/commands/create-project.js +55 -0
  20. package/dist/cli/commands/create-skill.d.ts +3 -0
  21. package/dist/cli/commands/create-skill.js +115 -0
  22. package/dist/cli/commands/create-state.d.ts +3 -0
  23. package/dist/cli/commands/create-state.js +58 -0
  24. package/dist/cli/commands/delete-agent.d.ts +3 -0
  25. package/dist/cli/commands/delete-agent.js +70 -0
  26. package/dist/cli/commands/delete-flow.d.ts +3 -0
  27. package/dist/cli/commands/delete-flow.js +83 -0
  28. package/dist/cli/commands/delete-skill.d.ts +3 -0
  29. package/dist/cli/commands/delete-skill.js +87 -0
  30. package/dist/cli/commands/help.js +114 -22
  31. package/dist/cli/commands/push.js +4 -3
  32. package/dist/cli/commands/sandbox.d.ts +14 -0
  33. package/dist/cli/commands/sandbox.js +306 -0
  34. package/dist/cli.js +57 -0
  35. package/dist/sandbox/chat.d.ts +40 -0
  36. package/dist/sandbox/chat.js +280 -0
  37. package/dist/sync/push.d.ts +1 -1
  38. package/dist/sync/push.js +372 -4
  39. package/dist/sync/status.js +178 -1
  40. package/dist/types.d.ts +181 -1
  41. package/package.json +6 -3
  42. package/src/api.ts +172 -1
  43. package/src/auth.ts +7 -2
  44. package/src/cli/commands/create-agent.ts +96 -0
  45. package/src/cli/commands/create-attribute.ts +75 -0
  46. package/src/cli/commands/create-event.ts +79 -0
  47. package/src/cli/commands/create-flow.ts +124 -0
  48. package/src/cli/commands/create-parameter.ts +59 -0
  49. package/src/cli/commands/create-persona.ts +54 -0
  50. package/src/cli/commands/create-project.ts +66 -0
  51. package/src/cli/commands/create-skill.ts +144 -0
  52. package/src/cli/commands/create-state.ts +71 -0
  53. package/src/cli/commands/delete-agent.ts +90 -0
  54. package/src/cli/commands/delete-flow.ts +105 -0
  55. package/src/cli/commands/delete-skill.ts +110 -0
  56. package/src/cli/commands/help.ts +114 -22
  57. package/src/cli/commands/push.ts +5 -3
  58. package/src/cli/commands/sandbox.ts +365 -0
  59. package/src/cli.ts +71 -0
  60. package/src/sandbox/chat.ts +339 -0
  61. package/src/sync/push.ts +413 -5
  62. package/src/sync/status.ts +183 -1
  63. package/src/types.ts +220 -2
@@ -0,0 +1,365 @@
1
+ /**
2
+ * Sandbox Chat Command Handler
3
+ * Supports both single-command and interactive modes
4
+ */
5
+
6
+ import type { MultiCustomerConfig, CliArgs } from '../../types.js';
7
+ import { makeClient } from '../../api.js';
8
+ import { getValidAccessToken } from '../../auth.js';
9
+ import { selectSingleCustomer } from '../customer-selection.js';
10
+ import { getChatHistory } from '../../api.js';
11
+ import {
12
+ findSandboxConnector,
13
+ createChatSession,
14
+ sendMessage,
15
+ pollForResponse,
16
+ extractAgentMessages,
17
+ formatDebugInfo
18
+ } from '../../sandbox/chat.js';
19
+
20
+ /**
21
+ * Handle sandbox command
22
+ * Usage:
23
+ * npx newo sandbox "Hello" --customer <idn> # Single message mode
24
+ * npx newo sandbox --actor <actor_id> "Follow up" # Continue existing chat
25
+ * npx newo sandbox --interactive # Interactive mode (TBD)
26
+ */
27
+ export async function handleSandboxCommand(
28
+ customerConfig: MultiCustomerConfig,
29
+ args: CliArgs,
30
+ verbose: boolean
31
+ ): Promise<void> {
32
+ const quiet: boolean = Boolean(args.quiet || args.q);
33
+
34
+ // Save original console functions
35
+ const originalConsoleLog = console.log;
36
+ const originalConsoleError = console.error;
37
+ const originalConsoleWarn = console.warn;
38
+
39
+ // In quiet mode, set environment variable to suppress auth logging AND suppress console
40
+ if (quiet) {
41
+ process.env.NEWO_QUIET_MODE = 'true';
42
+ console.log = () => {};
43
+ console.error = () => {};
44
+ console.warn = () => {};
45
+ }
46
+
47
+ try {
48
+ // Select customer
49
+ const customerArg = args.customer as string | undefined;
50
+ const result = selectSingleCustomer(customerConfig, customerArg);
51
+
52
+ if (!result.selectedCustomer) {
53
+ if (!quiet) {
54
+ console.error = originalConsoleError;
55
+ console.error('āŒ No customer selected');
56
+ }
57
+ process.exit(1);
58
+ }
59
+
60
+ // Get access token and create client (quiet mode already suppressing logs)
61
+ const token = await getValidAccessToken(result.selectedCustomer);
62
+ const client = await makeClient(quiet ? false : verbose, token);
63
+
64
+ // Restore console for our own output
65
+ if (quiet) {
66
+ console.log = originalConsoleLog;
67
+ console.error = originalConsoleError;
68
+ console.warn = originalConsoleWarn;
69
+ }
70
+
71
+ // Check for interactive mode
72
+ const interactive = args.interactive || args.i;
73
+ if (interactive) {
74
+ if (!quiet) {
75
+ console.log('āŒ Interactive mode not yet implemented');
76
+ console.log(' Use single-command mode: npx newo sandbox "your message"');
77
+ }
78
+ process.exit(1);
79
+ }
80
+
81
+ // Check if continuing existing chat
82
+ const actorId = args.actor as string | undefined;
83
+
84
+ // Extract message from arguments (position depends on whether --actor is used)
85
+ const messageArg = args._[1];
86
+ if (!messageArg) {
87
+ if (!quiet) {
88
+ console.log('āŒ Message is required');
89
+ console.log('Usage: npx newo sandbox "your message" [--actor <id>]');
90
+ console.log(' or: npx newo sandbox --actor <id> "your message"');
91
+ }
92
+ process.exit(1);
93
+ }
94
+
95
+ // Convert to string (minimist may parse numbers)
96
+ const message = String(messageArg);
97
+ if (message.trim() === '') {
98
+ if (!quiet) console.log('āŒ Message cannot be empty');
99
+ process.exit(1);
100
+ }
101
+
102
+ if (actorId) {
103
+ // Continue existing chat
104
+ await continueExistingChat(client, actorId, message, verbose, quiet, originalConsoleLog, originalConsoleError, originalConsoleWarn);
105
+ } else {
106
+ // Start new chat
107
+ await startNewChat(client, message, verbose, quiet, originalConsoleLog, originalConsoleError, originalConsoleWarn);
108
+ }
109
+
110
+ } catch (error: any) {
111
+ // Restore console for error reporting
112
+ if (quiet) {
113
+ console.error = originalConsoleError;
114
+ console.log = originalConsoleLog;
115
+ console.warn = originalConsoleWarn;
116
+ }
117
+
118
+ console.error('āŒ Sandbox chat error:', error.message);
119
+ if (verbose && error.response?.data) {
120
+ console.error(' Response data:', JSON.stringify(error.response.data, null, 2));
121
+ }
122
+ process.exit(1);
123
+ } finally {
124
+ // Always restore console functions and clear quiet mode flag
125
+ if (quiet) {
126
+ console.log = originalConsoleLog;
127
+ console.error = originalConsoleError;
128
+ console.warn = originalConsoleWarn;
129
+ delete process.env.NEWO_QUIET_MODE;
130
+ }
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Start a new sandbox chat and send a message
136
+ */
137
+ async function startNewChat(
138
+ client: any,
139
+ message: string,
140
+ verbose: boolean,
141
+ quiet: boolean = false,
142
+ originalConsoleLog: typeof console.log = console.log,
143
+ _originalConsoleError: typeof console.error = console.error,
144
+ _originalConsoleWarn: typeof console.warn = console.warn
145
+ ): Promise<void> {
146
+ if (!quiet) console.log('šŸ”§ Starting new sandbox chat...\n');
147
+
148
+ // Find sandbox connector
149
+ const connector = await findSandboxConnector(client, quiet ? false : verbose);
150
+ if (!connector) {
151
+ if (!quiet) {
152
+ console.error('āŒ No running sandbox connector found');
153
+ console.error(' Please ensure you have a sandbox connector configured in your NEWO project');
154
+ }
155
+ process.exit(1);
156
+ }
157
+
158
+ // Create chat session
159
+ const session = await createChatSession(client, connector, quiet ? false : verbose);
160
+
161
+ if (!quiet) {
162
+ console.log(`\nšŸ“‹ Chat Session Created:`);
163
+ console.log(` Chat ID (actor_id): ${session.user_actor_id}`);
164
+ console.log(` Persona ID: ${session.user_persona_id}`);
165
+ console.log(` Connector: ${session.connector_idn}`);
166
+ console.log(` External ID: ${session.external_id}\n`);
167
+ console.log(`šŸ“¤ You: ${message}\n`);
168
+ } else {
169
+ // In quiet mode, output Chat ID FIRST to stdout
170
+ originalConsoleLog(`CHAT_ID:${session.user_actor_id}`);
171
+ originalConsoleLog(`You: ${message}`);
172
+ }
173
+
174
+ const sentAt = await sendMessage(client, session, message, quiet ? false : verbose);
175
+
176
+ // Poll for response
177
+ const { acts, agentPersonaId } = await pollForResponse(client, session, sentAt, quiet ? false : verbose);
178
+
179
+ if (acts.length === 0) {
180
+ if (!quiet) {
181
+ console.log('ā±ļø No response received within timeout period');
182
+ console.log(` You can continue this chat with: npx newo sandbox --actor ${session.user_actor_id} "your message"`);
183
+ }
184
+ return;
185
+ }
186
+
187
+ // Update session with agent_persona_id
188
+ session.agent_persona_id = agentPersonaId;
189
+
190
+ // Extract agent messages - show only the MOST RECENT one
191
+ const agentMessages = extractAgentMessages(acts);
192
+
193
+ if (agentMessages.length > 0) {
194
+ // Show only the latest agent message (messages are in reverse chronological order from API)
195
+ const latestAgentMessage = agentMessages[0];
196
+ if (latestAgentMessage) {
197
+ if (quiet) {
198
+ // Quiet mode: ONLY message content
199
+ originalConsoleLog(`Agent: ${latestAgentMessage.source_text || latestAgentMessage.original_text}`);
200
+ } else {
201
+ // Normal mode: full output
202
+ console.log('šŸ¤– Agent:');
203
+ console.log(` ${latestAgentMessage.source_text || latestAgentMessage.original_text}`);
204
+ console.log('');
205
+
206
+ if (verbose && agentMessages.length > 1) {
207
+ console.log(`ā„¹ļø Note: Received ${agentMessages.length} agent messages, showing latest only\n`);
208
+ }
209
+ }
210
+ }
211
+ }
212
+
213
+ // In quiet mode, skip all debug output and continuation info completely
214
+ if (quiet) {
215
+ return; // Exit early, showing only messages
216
+ }
217
+
218
+ // Display debug information (skip in quiet mode)
219
+ if (!quiet) {
220
+ if (verbose) {
221
+ console.log('\nšŸ“Š Debug Information:');
222
+ console.log(formatDebugInfo(acts));
223
+ console.log('');
224
+ } else {
225
+ // Show condensed debug info for single-command mode
226
+ console.log('šŸ“Š Debug Summary:');
227
+ const agentActs = acts.filter(a => a.is_agent);
228
+ if (agentActs.length > 0) {
229
+ const lastAct = agentActs[agentActs.length - 1];
230
+ if (lastAct) {
231
+ console.log(` Flow: ${lastAct.flow_idn || 'N/A'}`);
232
+ console.log(` Skill: ${lastAct.skill_idn || 'N/A'}`);
233
+ console.log(` Session: ${lastAct.session_id}`);
234
+ }
235
+ console.log(` Acts Processed: ${acts.length} (${agentActs.length} agent, ${acts.length - agentActs.length} system)`);
236
+ }
237
+ console.log('');
238
+ }
239
+
240
+ // Show continuation info
241
+ console.log(`šŸ’” To continue this conversation:`);
242
+ console.log(` npx newo sandbox --actor ${session.user_actor_id} "your next message"`);
243
+ console.log('');
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Continue an existing sandbox chat
249
+ */
250
+ async function continueExistingChat(
251
+ client: any,
252
+ actorId: string,
253
+ message: string,
254
+ verbose: boolean,
255
+ quiet: boolean = false,
256
+ originalConsoleLog: typeof console.log = console.log,
257
+ _originalConsoleError: typeof console.error = console.error,
258
+ _originalConsoleWarn: typeof console.warn = console.warn
259
+ ): Promise<void> {
260
+ if (!quiet) {
261
+ console.log(`šŸ’¬ Continuing chat...`);
262
+ console.log(` Chat ID: ${actorId}\n`);
263
+ }
264
+
265
+ // First, get current chat history to find the last message ID
266
+ const historyResponse = await getChatHistory(client, {
267
+ user_actor_id: actorId,
268
+ page: 1,
269
+ per: 100
270
+ });
271
+
272
+ // Get the last message ID
273
+ let lastMessageId: string | null = null;
274
+ if (historyResponse.items && historyResponse.items.length > 0) {
275
+ const lastItem = historyResponse.items[0];
276
+ if (lastItem && 'id' in lastItem) {
277
+ lastMessageId = lastItem.id as string;
278
+ }
279
+ }
280
+
281
+ if (verbose && lastMessageId && !quiet) {
282
+ console.log(`šŸ“Œ Last message ID: ${lastMessageId}`);
283
+ }
284
+
285
+ // Create a temporary session for the existing chat
286
+ const session: any = {
287
+ user_actor_id: actorId,
288
+ user_persona_id: 'unknown', // Not needed for continuation
289
+ agent_persona_id: null,
290
+ connector_idn: 'sandbox',
291
+ session_id: null,
292
+ external_id: 'continuation'
293
+ };
294
+
295
+ // Send message (use original console in quiet mode)
296
+ if (quiet) {
297
+ originalConsoleLog(`You: ${message}`);
298
+ } else {
299
+ console.log(`šŸ“¤ You: ${message}\n`);
300
+ }
301
+ const sentAt = await sendMessage(client, session, message, quiet ? false : verbose);
302
+
303
+ // Poll for response using timestamp-based filtering
304
+ const { acts } = await pollForResponse(client, session, sentAt, quiet ? false : verbose);
305
+
306
+ if (acts.length === 0) {
307
+ if (!quiet) {
308
+ console.log('ā±ļø No response received within timeout period');
309
+ console.log(` You can continue this chat with: npx newo sandbox --actor ${actorId} "your message"`);
310
+ }
311
+ return;
312
+ }
313
+
314
+ // Extract agent messages - show only the MOST RECENT one
315
+ const agentMessages = extractAgentMessages(acts);
316
+
317
+ if (agentMessages.length > 0) {
318
+ // Show only the latest agent message (messages are in reverse chronological order from API)
319
+ const latestAgentMessage = agentMessages[0];
320
+ if (latestAgentMessage) {
321
+ if (quiet) {
322
+ // Quiet mode: ONLY message content
323
+ originalConsoleLog(`Agent: ${latestAgentMessage.source_text || latestAgentMessage.original_text}`);
324
+ return; // Exit immediately, no debug output
325
+ } else {
326
+ // Normal mode: full output
327
+ console.log('šŸ¤– Agent:');
328
+ console.log(` ${latestAgentMessage.source_text || latestAgentMessage.original_text}`);
329
+ console.log('');
330
+
331
+ if (verbose && agentMessages.length > 1) {
332
+ console.log(`ā„¹ļø Note: Received ${agentMessages.length} agent messages, showing latest only\n`);
333
+ }
334
+ }
335
+ }
336
+ }
337
+
338
+ // Display debug information (skip in quiet mode)
339
+ if (!quiet) {
340
+ if (verbose) {
341
+ console.log('\nšŸ“Š Debug Information:');
342
+ console.log(formatDebugInfo(acts));
343
+ console.log('');
344
+ } else {
345
+ // Show condensed debug info
346
+ console.log('šŸ“Š Debug Summary:');
347
+ const agentActs = acts.filter(a => a.is_agent);
348
+ if (agentActs.length > 0) {
349
+ const lastAct = agentActs[agentActs.length - 1];
350
+ if (lastAct) {
351
+ console.log(` Flow: ${lastAct.flow_idn || 'N/A'}`);
352
+ console.log(` Skill: ${lastAct.skill_idn || 'N/A'}`);
353
+ console.log(` Session: ${lastAct.session_id}`);
354
+ }
355
+ console.log(` Acts Processed: ${acts.length} (${agentActs.length} agent, ${acts.length - agentActs.length} user)`);
356
+ }
357
+ console.log('');
358
+ }
359
+
360
+ // Show continuation info
361
+ console.log(`šŸ’” To continue this conversation:`);
362
+ console.log(` npx newo sandbox --actor ${actorId} "your next message"`);
363
+ console.log('');
364
+ }
365
+ }
package/src/cli.ts CHANGED
@@ -16,6 +16,19 @@ import { handlePullAttributesCommand } from './cli/commands/pull-attributes.js';
16
16
  import { handleImportAkbCommand } from './cli/commands/import-akb.js';
17
17
  import { handleHelpCommand } from './cli/commands/help.js';
18
18
  import { handleListCustomersCommand } from './cli/commands/list-customers.js';
19
+ import { handleCreateAgentCommand } from './cli/commands/create-agent.js';
20
+ import { handleDeleteAgentCommand } from './cli/commands/delete-agent.js';
21
+ import { handleCreateFlowCommand } from './cli/commands/create-flow.js';
22
+ import { handleDeleteFlowCommand } from './cli/commands/delete-flow.js';
23
+ import { handleCreateSkillCommand } from './cli/commands/create-skill.js';
24
+ import { handleDeleteSkillCommand } from './cli/commands/delete-skill.js';
25
+ import { handleCreateProjectCommand } from './cli/commands/create-project.js';
26
+ import { handleCreateEventCommand } from './cli/commands/create-event.js';
27
+ import { handleCreateStateCommand } from './cli/commands/create-state.js';
28
+ import { handleCreateParameterCommand } from './cli/commands/create-parameter.js';
29
+ import { handleCreatePersonaCommand } from './cli/commands/create-persona.js';
30
+ import { handleCreateAttributeCommand } from './cli/commands/create-attribute.js';
31
+ import { handleSandboxCommand } from './cli/commands/sandbox.js';
19
32
  import type { CliArgs, NewoApiError } from './types.js';
20
33
 
21
34
  dotenv.config();
@@ -32,6 +45,12 @@ async function main(): Promise<void> {
32
45
  const args = minimist(process.argv.slice(2)) as CliArgs;
33
46
  const cmd = args._[0];
34
47
  const verbose = Boolean(args.verbose || args.v);
48
+ const quiet = Boolean(args.quiet || args.q);
49
+
50
+ // Set quiet mode flag EARLY to suppress auth logging
51
+ if (quiet) {
52
+ process.env.NEWO_QUIET_MODE = 'true';
53
+ }
35
54
 
36
55
  if (verbose) console.log(`šŸ” Command parsed: "${cmd}"`);
37
56
 
@@ -75,6 +94,10 @@ async function main(): Promise<void> {
75
94
  await handleConversationsCommand(customerConfig, args, verbose);
76
95
  break;
77
96
 
97
+ case 'sandbox':
98
+ await handleSandboxCommand(customerConfig, args, verbose);
99
+ break;
100
+
78
101
  case 'meta':
79
102
  await handleMetaCommand(customerConfig, args, verbose);
80
103
  break;
@@ -87,6 +110,54 @@ async function main(): Promise<void> {
87
110
  await handleImportAkbCommand(customerConfig, args, verbose);
88
111
  break;
89
112
 
113
+ case 'create-agent':
114
+ await handleCreateAgentCommand(customerConfig, args, verbose);
115
+ break;
116
+
117
+ case 'delete-agent':
118
+ await handleDeleteAgentCommand(customerConfig, args, verbose);
119
+ break;
120
+
121
+ case 'create-flow':
122
+ await handleCreateFlowCommand(customerConfig, args, verbose);
123
+ break;
124
+
125
+ case 'delete-flow':
126
+ await handleDeleteFlowCommand(customerConfig, args, verbose);
127
+ break;
128
+
129
+ case 'create-skill':
130
+ await handleCreateSkillCommand(customerConfig, args, verbose);
131
+ break;
132
+
133
+ case 'delete-skill':
134
+ await handleDeleteSkillCommand(customerConfig, args, verbose);
135
+ break;
136
+
137
+ case 'create-project':
138
+ await handleCreateProjectCommand(customerConfig, args, verbose);
139
+ break;
140
+
141
+ case 'create-event':
142
+ await handleCreateEventCommand(customerConfig, args, verbose);
143
+ break;
144
+
145
+ case 'create-state':
146
+ await handleCreateStateCommand(customerConfig, args, verbose);
147
+ break;
148
+
149
+ case 'create-parameter':
150
+ await handleCreateParameterCommand(customerConfig, args, verbose);
151
+ break;
152
+
153
+ case 'create-persona':
154
+ await handleCreatePersonaCommand(customerConfig, args, verbose);
155
+ break;
156
+
157
+ case 'create-attribute':
158
+ await handleCreateAttributeCommand(customerConfig, args, verbose);
159
+ break;
160
+
90
161
  default:
91
162
  console.error('Unknown command:', cmd);
92
163
  console.error('Run "newo --help" for usage information');