luxlabs 1.0.21 → 1.0.24
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/README.md +16 -21
- package/commands/ab-tests.js +14 -11
- package/commands/agents.js +11 -11
- package/commands/data.js +19 -17
- package/commands/deploy.js +145 -82
- package/commands/flows.js +152 -133
- package/commands/interface/init.js +36 -35
- package/commands/interface.js +135 -10
- package/commands/knowledge.js +3 -3
- package/commands/list.js +6 -24
- package/commands/login.js +31 -26
- package/commands/logout.js +13 -4
- package/commands/logs.js +17 -66
- package/commands/project.js +74 -47
- package/commands/secrets.js +1 -1
- package/commands/servers.js +9 -113
- package/commands/storage.js +1 -1
- package/commands/tools.js +4 -4
- package/commands/validate-data-lux.js +5 -2
- package/commands/voice-agents.js +22 -18
- package/lib/config.js +235 -83
- package/lib/helpers.js +6 -4
- package/lux.js +4 -94
- package/package.json +6 -1
- package/templates/interface-boilerplate/components/auth/sign-in-form.tsx +41 -34
- package/templates/interface-boilerplate/components/auth/sign-up-form.tsx +41 -34
- package/templates/interface-boilerplate/components/providers/posthog-provider.tsx +41 -26
- package/templates/interface-boilerplate/gitignore.template +4 -0
- package/templates/interface-boilerplate/lib/auth.config.ts +3 -2
- package/templates/interface-boilerplate/lib/knowledge.ts +2 -2
- package/templates/interface-boilerplate/middleware.ts +14 -3
- package/templates/interface-boilerplate/next-env.d.ts +6 -0
- package/templates/interface-boilerplate/package-lock.json +432 -8
- package/commands/dev.js +0 -578
- package/commands/init.js +0 -126
- package/commands/link.js +0 -127
- package/commands/up.js +0 -211
package/commands/flows.js
CHANGED
|
@@ -27,6 +27,34 @@ const {
|
|
|
27
27
|
// Webhook helper functions
|
|
28
28
|
const WEBHOOK_WORKER_URL = 'https://webhook-trigger-worker.jason-a5d.workers.dev';
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a flow name-or-id to the actual flow ID.
|
|
32
|
+
* Supports case-insensitive partial matching against both flow ID and name.
|
|
33
|
+
*/
|
|
34
|
+
function resolveFlowId(nameOrId) {
|
|
35
|
+
if (!nameOrId) return null;
|
|
36
|
+
|
|
37
|
+
const localFlows = listLocalFlows();
|
|
38
|
+
if (localFlows.length === 0) return nameOrId; // Fall through to let caller handle not-found
|
|
39
|
+
|
|
40
|
+
const search = nameOrId.toLowerCase();
|
|
41
|
+
|
|
42
|
+
// 1. Exact match on ID
|
|
43
|
+
const exact = localFlows.find(f => f.id === nameOrId);
|
|
44
|
+
if (exact) return exact.id;
|
|
45
|
+
|
|
46
|
+
// 2. Case-insensitive partial match on ID
|
|
47
|
+
const idMatch = localFlows.find(f => f.id.toLowerCase().includes(search));
|
|
48
|
+
if (idMatch) return idMatch.id;
|
|
49
|
+
|
|
50
|
+
// 3. Case-insensitive partial match on name
|
|
51
|
+
const nameMatch = localFlows.find(f => f.name && f.name.toLowerCase().includes(search));
|
|
52
|
+
if (nameMatch) return nameMatch.id;
|
|
53
|
+
|
|
54
|
+
// No match found — return the original input so the caller can show a proper error
|
|
55
|
+
return nameOrId;
|
|
56
|
+
}
|
|
57
|
+
|
|
30
58
|
/**
|
|
31
59
|
* Get webhook token for a workflow
|
|
32
60
|
*/
|
|
@@ -78,7 +106,7 @@ async function handleFlows(args) {
|
|
|
78
106
|
// Check authentication
|
|
79
107
|
if (!isAuthenticated()) {
|
|
80
108
|
console.log(
|
|
81
|
-
chalk.red('
|
|
109
|
+
chalk.red('Not authenticated. Run'),
|
|
82
110
|
chalk.white('lux login'),
|
|
83
111
|
chalk.red('first.')
|
|
84
112
|
);
|
|
@@ -93,20 +121,28 @@ ${chalk.bold('Usage:')} lux flows <command> [args]
|
|
|
93
121
|
|
|
94
122
|
${chalk.bold('Commands:')}
|
|
95
123
|
list List all flows (from local storage)
|
|
96
|
-
get <id>
|
|
97
|
-
status <id>
|
|
124
|
+
get <name-or-id> Get flow details with config
|
|
125
|
+
status <name-or-id> Show sync status for a flow
|
|
98
126
|
create <name> [desc] [--publish] Create flow (use --publish to publish immediately)
|
|
99
|
-
|
|
100
|
-
save <id> <config-file> Save draft config from file (local)
|
|
127
|
+
save <name-or-id> <config-file> Save draft config from file (local)
|
|
101
128
|
sync Sync published flows from cloud
|
|
102
|
-
publish <id>
|
|
103
|
-
delete <id>
|
|
104
|
-
diff <id>
|
|
129
|
+
publish <name-or-id> Publish flow to cloud
|
|
130
|
+
delete <name-or-id> Delete a local flow
|
|
131
|
+
diff <name-or-id> Show local vs published differences
|
|
132
|
+
|
|
133
|
+
${chalk.bold('Webhook Commands:')}
|
|
134
|
+
webhook-url <name-or-id> Get webhook URL and status
|
|
135
|
+
webhook-listen <name-or-id> Start listening session for webhook capture
|
|
136
|
+
webhook-poll <name-or-id> Check for captured webhook payload
|
|
137
|
+
webhook-accept <name-or-id> Accept webhook format and save variables
|
|
138
|
+
webhook-decline <name-or-id> Decline webhook and reset session
|
|
105
139
|
|
|
106
|
-
${chalk.bold('Execution
|
|
107
|
-
executions <
|
|
108
|
-
execution <
|
|
109
|
-
node <
|
|
140
|
+
${chalk.bold('Execution Commands:')}
|
|
141
|
+
executions <name-or-id> [--limit N] List recent executions
|
|
142
|
+
execution <name-or-id> <exec-id> Get execution details
|
|
143
|
+
node <name-or-id> <exec-id> <node-id> Get node execution details
|
|
144
|
+
test <name-or-id> [--data <json>] Test a flow with sample data
|
|
145
|
+
last <name-or-id> Show the last execution result
|
|
110
146
|
|
|
111
147
|
${chalk.bold('Sync Status:')}
|
|
112
148
|
draft - Never published, local only
|
|
@@ -114,47 +150,30 @@ ${chalk.bold('Sync Status:')}
|
|
|
114
150
|
dirty - Has local changes since publish
|
|
115
151
|
conflict - Local changes + cloud has newer version
|
|
116
152
|
|
|
117
|
-
${chalk.bold('Webhook Commands:')}
|
|
118
|
-
webhook-url <id> Get webhook URL and status
|
|
119
|
-
webhook-listen <id> Start listening session for webhook capture
|
|
120
|
-
webhook-poll <id> Check for captured webhook payload
|
|
121
|
-
webhook-accept <id> Accept webhook format and save variables
|
|
122
|
-
webhook-decline <id> Decline webhook and reset session
|
|
123
|
-
|
|
124
|
-
${chalk.bold('Execution Commands:')}
|
|
125
|
-
executions <id> List recent executions for a flow
|
|
126
|
-
execution <id> <exec-id> Get details of a specific execution
|
|
127
|
-
test <id> [--data] Test a flow with sample data
|
|
128
|
-
last <id> Show the last execution result
|
|
129
|
-
|
|
130
153
|
${chalk.bold('Examples:')}
|
|
131
154
|
lux flows list
|
|
132
|
-
lux flows get
|
|
133
|
-
lux flows status
|
|
155
|
+
lux flows get "My Flow"
|
|
156
|
+
lux flows status my-flow
|
|
134
157
|
lux flows create "My Flow" "Description"
|
|
135
|
-
lux flows create "My Flow" --publish
|
|
136
|
-
lux flows
|
|
137
|
-
lux flows save flow_123 ./config.json
|
|
158
|
+
lux flows create "My Flow" --publish
|
|
159
|
+
lux flows save my-flow ./config.json
|
|
138
160
|
lux flows sync
|
|
139
|
-
lux flows publish
|
|
140
|
-
lux flows diff
|
|
161
|
+
lux flows publish my-flow
|
|
162
|
+
lux flows diff my-flow
|
|
141
163
|
|
|
142
|
-
${chalk.bold('Execution
|
|
143
|
-
lux flows executions my-flow
|
|
144
|
-
lux flows executions my-flow
|
|
145
|
-
lux flows execution my-flow
|
|
146
|
-
lux flows node my-flow
|
|
164
|
+
${chalk.bold('Execution:')}
|
|
165
|
+
lux flows executions my-flow
|
|
166
|
+
lux flows executions my-flow --limit 50
|
|
167
|
+
lux flows execution my-flow exec_abc123
|
|
168
|
+
lux flows node my-flow exec_abc123 node-1
|
|
169
|
+
lux flows last my-flow
|
|
170
|
+
lux flows test my-flow --data '{"name":"test"}'
|
|
147
171
|
|
|
148
172
|
${chalk.bold('Webhook:')}
|
|
149
|
-
lux flows webhook-url
|
|
150
|
-
lux flows webhook-listen
|
|
151
|
-
lux flows webhook-poll
|
|
152
|
-
lux flows webhook-accept
|
|
153
|
-
|
|
154
|
-
${chalk.bold('Execution debugging:')}
|
|
155
|
-
lux flows executions my-flow # List recent executions
|
|
156
|
-
lux flows last my-flow # Show last execution result
|
|
157
|
-
lux flows test my-flow --data '{"name":"test"}' # Test with data
|
|
173
|
+
lux flows webhook-url my-flow
|
|
174
|
+
lux flows webhook-listen my-flow
|
|
175
|
+
lux flows webhook-poll my-flow
|
|
176
|
+
lux flows webhook-accept my-flow
|
|
158
177
|
`);
|
|
159
178
|
process.exit(0);
|
|
160
179
|
}
|
|
@@ -203,12 +222,12 @@ ${chalk.bold('Examples:')}
|
|
|
203
222
|
}
|
|
204
223
|
|
|
205
224
|
case 'status': {
|
|
206
|
-
requireArgs(args.slice(1), 1, 'lux flows status <id>');
|
|
207
|
-
const flowId = args[1];
|
|
225
|
+
requireArgs(args.slice(1), 1, 'lux flows status <name-or-id>');
|
|
226
|
+
const flowId = resolveFlowId(args[1]);
|
|
208
227
|
|
|
209
228
|
const flow = loadLocalFlow(flowId);
|
|
210
229
|
if (!flow) {
|
|
211
|
-
error(`Flow not found locally: ${
|
|
230
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
212
231
|
break;
|
|
213
232
|
}
|
|
214
233
|
|
|
@@ -231,7 +250,7 @@ ${chalk.bold('Examples:')}
|
|
|
231
250
|
conflict: chalk.red,
|
|
232
251
|
};
|
|
233
252
|
|
|
234
|
-
console.log(`\
|
|
253
|
+
console.log(`\nFlow: ${flow.name}`);
|
|
235
254
|
console.log(` ID: ${flowId}`);
|
|
236
255
|
console.log(` Sync Status: ${statusColors[syncStatus](syncStatus)}`);
|
|
237
256
|
console.log(` Local Version: ${flow.localVersion || 1}`);
|
|
@@ -243,10 +262,10 @@ ${chalk.bold('Examples:')}
|
|
|
243
262
|
console.log(` Edges: ${flow.edges?.length || 0}`);
|
|
244
263
|
|
|
245
264
|
if (syncStatus === 'conflict') {
|
|
246
|
-
console.log(chalk.red('\
|
|
265
|
+
console.log(chalk.red('\nThis flow has conflicts with the cloud version.'));
|
|
247
266
|
console.log(chalk.gray(' Use the Lux Studio app to resolve conflicts.\n'));
|
|
248
267
|
} else if (syncStatus === 'dirty') {
|
|
249
|
-
console.log(chalk.yellow('\
|
|
268
|
+
console.log(chalk.yellow('\nThis flow has unpublished local changes.'));
|
|
250
269
|
console.log(chalk.gray(' Run "lux flows publish ' + flowId + '" to publish.\n'));
|
|
251
270
|
}
|
|
252
271
|
break;
|
|
@@ -363,17 +382,17 @@ ${chalk.bold('Examples:')}
|
|
|
363
382
|
}
|
|
364
383
|
|
|
365
384
|
case 'delete': {
|
|
366
|
-
requireArgs(args.slice(1), 1, 'lux flows delete <id>');
|
|
367
|
-
const flowId = args[1];
|
|
385
|
+
requireArgs(args.slice(1), 1, 'lux flows delete <name-or-id>');
|
|
386
|
+
const flowId = resolveFlowId(args[1]);
|
|
368
387
|
|
|
369
388
|
const flow = loadLocalFlow(flowId);
|
|
370
389
|
if (!flow) {
|
|
371
|
-
error(`Flow not found locally: ${
|
|
390
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
372
391
|
break;
|
|
373
392
|
}
|
|
374
393
|
|
|
375
394
|
if (flow.publishedVersion) {
|
|
376
|
-
console.log(chalk.yellow(`\
|
|
395
|
+
console.log(chalk.yellow(`\nWarning: "${flow.name}" has been published.`));
|
|
377
396
|
console.log(chalk.gray(' This only deletes the local copy. The published version remains in the cloud.\n'));
|
|
378
397
|
}
|
|
379
398
|
|
|
@@ -383,8 +402,8 @@ ${chalk.bold('Examples:')}
|
|
|
383
402
|
}
|
|
384
403
|
|
|
385
404
|
case 'get': {
|
|
386
|
-
requireArgs(args.slice(1), 1, 'lux flows get <id>');
|
|
387
|
-
const flowId = args[1];
|
|
405
|
+
requireArgs(args.slice(1), 1, 'lux flows get <name-or-id>');
|
|
406
|
+
const flowId = resolveFlowId(args[1]);
|
|
388
407
|
|
|
389
408
|
info(`Loading flow: ${flowId}`);
|
|
390
409
|
const { data } = await axios.get(
|
|
@@ -398,14 +417,14 @@ ${chalk.bold('Examples:')}
|
|
|
398
417
|
|
|
399
418
|
const workflow = data.workflow;
|
|
400
419
|
|
|
401
|
-
console.log(`\
|
|
402
|
-
console.log(
|
|
403
|
-
console.log(
|
|
404
|
-
console.log(
|
|
405
|
-
console.log(
|
|
420
|
+
console.log(`\nName: ${workflow.name}`);
|
|
421
|
+
console.log(`Status: ${workflow.status}`);
|
|
422
|
+
console.log(`Version: ${workflow.version}`);
|
|
423
|
+
console.log(`Created: ${workflow.created_at}`);
|
|
424
|
+
console.log(`Updated: ${workflow.updated_at}`);
|
|
406
425
|
|
|
407
426
|
if (workflow.config) {
|
|
408
|
-
console.log(`\
|
|
427
|
+
console.log(`\nCurrent Config:\n`);
|
|
409
428
|
console.log(formatJson(workflow.config));
|
|
410
429
|
}
|
|
411
430
|
|
|
@@ -540,14 +559,14 @@ ${chalk.bold('Examples:')}
|
|
|
540
559
|
}
|
|
541
560
|
|
|
542
561
|
case 'save': {
|
|
543
|
-
requireArgs(args.slice(1), 2, 'lux flows save <id> <config-file>');
|
|
544
|
-
const flowId = args[1];
|
|
562
|
+
requireArgs(args.slice(1), 2, 'lux flows save <name-or-id> <config-file>');
|
|
563
|
+
const flowId = resolveFlowId(args[1]);
|
|
545
564
|
const configFile = args[2];
|
|
546
565
|
|
|
547
566
|
// Load existing local flow
|
|
548
567
|
const existingFlow = loadLocalFlow(flowId);
|
|
549
568
|
if (!existingFlow) {
|
|
550
|
-
error(`Flow not found locally: ${
|
|
569
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
551
570
|
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
552
571
|
break;
|
|
553
572
|
}
|
|
@@ -586,13 +605,13 @@ ${chalk.bold('Examples:')}
|
|
|
586
605
|
}
|
|
587
606
|
|
|
588
607
|
case 'publish': {
|
|
589
|
-
requireArgs(args.slice(1), 1, 'lux flows publish <id>');
|
|
590
|
-
const flowId = args[1];
|
|
608
|
+
requireArgs(args.slice(1), 1, 'lux flows publish <name-or-id>');
|
|
609
|
+
const flowId = resolveFlowId(args[1]);
|
|
591
610
|
|
|
592
611
|
// Load local flow
|
|
593
612
|
const localFlow = loadLocalFlow(flowId);
|
|
594
613
|
if (!localFlow) {
|
|
595
|
-
error(`Flow not found locally: ${
|
|
614
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
596
615
|
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
597
616
|
break;
|
|
598
617
|
}
|
|
@@ -657,13 +676,13 @@ ${chalk.bold('Examples:')}
|
|
|
657
676
|
}
|
|
658
677
|
|
|
659
678
|
case 'diff': {
|
|
660
|
-
requireArgs(args.slice(1), 1, 'lux flows diff <id>');
|
|
661
|
-
const flowId = args[1];
|
|
679
|
+
requireArgs(args.slice(1), 1, 'lux flows diff <name-or-id>');
|
|
680
|
+
const flowId = resolveFlowId(args[1]);
|
|
662
681
|
|
|
663
682
|
// Load local flow
|
|
664
683
|
const localFlow = loadLocalFlow(flowId);
|
|
665
684
|
if (!localFlow) {
|
|
666
|
-
error(`Flow not found locally: ${
|
|
685
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
667
686
|
break;
|
|
668
687
|
}
|
|
669
688
|
|
|
@@ -676,7 +695,7 @@ ${chalk.bold('Examples:')}
|
|
|
676
695
|
|
|
677
696
|
// Check if never published
|
|
678
697
|
if (!localFlow.publishedVersion) {
|
|
679
|
-
console.log('\
|
|
698
|
+
console.log('\nNEW FLOW (not yet published)\n');
|
|
680
699
|
console.log(` Name: ${localFlow.name}`);
|
|
681
700
|
console.log(` Local Version: ${localFlow.localVersion || 1}`);
|
|
682
701
|
console.log(` Nodes: ${localConfig.nodes.length}`);
|
|
@@ -687,7 +706,7 @@ ${chalk.bold('Examples:')}
|
|
|
687
706
|
|
|
688
707
|
// Check for conflicts
|
|
689
708
|
if (localFlow.cloudData) {
|
|
690
|
-
console.log('\
|
|
709
|
+
console.log('\nCONFLICT DETECTED\n');
|
|
691
710
|
console.log('Local version:');
|
|
692
711
|
console.log(` Version: ${localFlow.localVersion}`);
|
|
693
712
|
console.log(` Nodes: ${localConfig.nodes.length}`);
|
|
@@ -708,7 +727,7 @@ ${chalk.bold('Examples:')}
|
|
|
708
727
|
success('No changes - local matches published version');
|
|
709
728
|
console.log(` Published Version: ${localFlow.publishedVersion}`);
|
|
710
729
|
} else {
|
|
711
|
-
console.log('\
|
|
730
|
+
console.log('\nLOCAL CHANGES (unpublished)\n');
|
|
712
731
|
console.log(` Local Version: ${localFlow.localVersion}`);
|
|
713
732
|
console.log(` Published Version: ${localFlow.publishedVersion}`);
|
|
714
733
|
console.log(` Nodes: ${localConfig.nodes.length}`);
|
|
@@ -719,26 +738,26 @@ ${chalk.bold('Examples:')}
|
|
|
719
738
|
}
|
|
720
739
|
|
|
721
740
|
case 'webhook-url': {
|
|
722
|
-
requireArgs(args.slice(1), 1, 'lux flows webhook-url <
|
|
723
|
-
const flowId = args[1];
|
|
741
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-url <name-or-id>');
|
|
742
|
+
const flowId = resolveFlowId(args[1]);
|
|
724
743
|
|
|
725
744
|
info(`Getting webhook URL for: ${flowId}`);
|
|
726
745
|
const tokenData = await getWebhookToken(flowId);
|
|
727
746
|
|
|
728
|
-
console.log(`\
|
|
729
|
-
console.log(
|
|
730
|
-
console.log(` Format Confirmed: ${tokenData.formatConfirmed ? '
|
|
731
|
-
console.log(` Webhook Trigger Enabled: ${tokenData.webhookTrigger ? '
|
|
747
|
+
console.log(`\nWebhook URL:\n${tokenData.webhookUrl}\n`);
|
|
748
|
+
console.log(`Status:`);
|
|
749
|
+
console.log(` Format Confirmed: ${tokenData.formatConfirmed ? 'Yes' : 'No'}`);
|
|
750
|
+
console.log(` Webhook Trigger Enabled: ${tokenData.webhookTrigger ? 'Yes' : 'No'}\n`);
|
|
732
751
|
|
|
733
752
|
if (!tokenData.formatConfirmed) {
|
|
734
|
-
console.log(chalk.yellow('
|
|
753
|
+
console.log(chalk.yellow('Run "lux flows webhook-listen" to capture a sample webhook'));
|
|
735
754
|
}
|
|
736
755
|
break;
|
|
737
756
|
}
|
|
738
757
|
|
|
739
758
|
case 'webhook-listen': {
|
|
740
|
-
requireArgs(args.slice(1), 1, 'lux flows webhook-listen <
|
|
741
|
-
const flowId = args[1];
|
|
759
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-listen <name-or-id>');
|
|
760
|
+
const flowId = resolveFlowId(args[1]);
|
|
742
761
|
|
|
743
762
|
info(`Starting webhook listening session for: ${flowId}`);
|
|
744
763
|
const tokenData = await getWebhookToken(flowId);
|
|
@@ -747,7 +766,7 @@ ${chalk.bold('Examples:')}
|
|
|
747
766
|
await axios.post(`${WEBHOOK_WORKER_URL}/listening/start/${tokenData.token}`);
|
|
748
767
|
|
|
749
768
|
success('Listening session started!');
|
|
750
|
-
console.log(`\
|
|
769
|
+
console.log(`\nNow listening for webhooks at:\n${tokenData.webhookUrl}\n`);
|
|
751
770
|
console.log('Session expires in 5 minutes.');
|
|
752
771
|
console.log(`\nSend a webhook request to the URL above, then run:`);
|
|
753
772
|
console.log(chalk.white(` lux flows webhook-poll ${flowId}\n`));
|
|
@@ -755,8 +774,8 @@ ${chalk.bold('Examples:')}
|
|
|
755
774
|
}
|
|
756
775
|
|
|
757
776
|
case 'webhook-poll': {
|
|
758
|
-
requireArgs(args.slice(1), 1, 'lux flows webhook-poll <
|
|
759
|
-
const flowId = args[1];
|
|
777
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-poll <name-or-id>');
|
|
778
|
+
const flowId = resolveFlowId(args[1]);
|
|
760
779
|
|
|
761
780
|
const tokenData = await getWebhookToken(flowId);
|
|
762
781
|
const pollData = await getCapturedPayload(tokenData.token);
|
|
@@ -767,8 +786,8 @@ ${chalk.bold('Examples:')}
|
|
|
767
786
|
}
|
|
768
787
|
|
|
769
788
|
case 'webhook-accept': {
|
|
770
|
-
requireArgs(args.slice(1), 1, 'lux flows webhook-accept <
|
|
771
|
-
const flowId = args[1];
|
|
789
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-accept <name-or-id>');
|
|
790
|
+
const flowId = resolveFlowId(args[1]);
|
|
772
791
|
|
|
773
792
|
info(`Accepting webhook format for: ${flowId}`);
|
|
774
793
|
|
|
@@ -835,13 +854,13 @@ ${chalk.bold('Examples:')}
|
|
|
835
854
|
}
|
|
836
855
|
|
|
837
856
|
success('Webhook format updated!');
|
|
838
|
-
console.log(`\
|
|
839
|
-
console.log(
|
|
857
|
+
console.log(`\nCaptured schema with ${Object.keys(schema).length} parameters`);
|
|
858
|
+
console.log(`Schema saved to database`);
|
|
840
859
|
if (!alreadyConfirmed) {
|
|
841
|
-
console.log(
|
|
842
|
-
console.log(
|
|
860
|
+
console.log(`Worker accepted format`);
|
|
861
|
+
console.log(`Format confirmed`);
|
|
843
862
|
} else {
|
|
844
|
-
console.log(
|
|
863
|
+
console.log(`Schema updated (already confirmed)`);
|
|
845
864
|
}
|
|
846
865
|
console.log('');
|
|
847
866
|
|
|
@@ -855,8 +874,8 @@ ${chalk.bold('Examples:')}
|
|
|
855
874
|
}
|
|
856
875
|
|
|
857
876
|
case 'webhook-decline': {
|
|
858
|
-
requireArgs(args.slice(1), 1, 'lux flows webhook-decline <
|
|
859
|
-
const flowId = args[1];
|
|
877
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-decline <name-or-id>');
|
|
878
|
+
const flowId = resolveFlowId(args[1]);
|
|
860
879
|
|
|
861
880
|
info(`Declining webhook format for: ${flowId}`);
|
|
862
881
|
const tokenData = await getWebhookToken(flowId);
|
|
@@ -872,8 +891,8 @@ ${chalk.bold('Examples:')}
|
|
|
872
891
|
await axios.delete(`${WEBHOOK_WORKER_URL}/listening/decline/${tokenData.token}`);
|
|
873
892
|
|
|
874
893
|
success('Webhook format declined!');
|
|
875
|
-
console.log('\
|
|
876
|
-
console.log('
|
|
894
|
+
console.log('\nSchema cleared from database');
|
|
895
|
+
console.log('Listening session has been reset');
|
|
877
896
|
console.log(`\nRun "lux flows webhook-listen ${flowId}" to try again.\n`);
|
|
878
897
|
break;
|
|
879
898
|
}
|
|
@@ -881,8 +900,8 @@ ${chalk.bold('Examples:')}
|
|
|
881
900
|
// ============ EXECUTION HISTORY COMMANDS ============
|
|
882
901
|
|
|
883
902
|
case 'executions': {
|
|
884
|
-
requireArgs(args.slice(1), 1, 'lux flows executions <
|
|
885
|
-
const flowId = args[1];
|
|
903
|
+
requireArgs(args.slice(1), 1, 'lux flows executions <name-or-id> [--limit N]');
|
|
904
|
+
const flowId = resolveFlowId(args[1]);
|
|
886
905
|
|
|
887
906
|
// Parse --limit flag
|
|
888
907
|
const limitIndex = args.indexOf('--limit');
|
|
@@ -924,7 +943,7 @@ ${chalk.bold('Examples:')}
|
|
|
924
943
|
const flow = loadLocalFlow(flowId);
|
|
925
944
|
const flowName = flow?.name || flowId;
|
|
926
945
|
|
|
927
|
-
console.log(`\
|
|
946
|
+
console.log(`\nExecution History for "${flowName}" (${executions.length})\n`);
|
|
928
947
|
|
|
929
948
|
// Status colors
|
|
930
949
|
const statusColors = {
|
|
@@ -963,8 +982,8 @@ ${chalk.bold('Examples:')}
|
|
|
963
982
|
}
|
|
964
983
|
|
|
965
984
|
case 'execution': {
|
|
966
|
-
requireArgs(args.slice(1), 2, 'lux flows execution <
|
|
967
|
-
const flowId = args[1];
|
|
985
|
+
requireArgs(args.slice(1), 2, 'lux flows execution <name-or-id> <execution-id>');
|
|
986
|
+
const flowId = resolveFlowId(args[1]);
|
|
968
987
|
const executionId = args[2];
|
|
969
988
|
const jsonOutput = args.includes('--json');
|
|
970
989
|
|
|
@@ -1009,7 +1028,7 @@ ${chalk.bold('Examples:')}
|
|
|
1009
1028
|
};
|
|
1010
1029
|
const statusColor = statusColors[exec.status] || chalk.white;
|
|
1011
1030
|
|
|
1012
|
-
console.log(`\
|
|
1031
|
+
console.log(`\nExecution Details\n`);
|
|
1013
1032
|
console.log(` ID: ${exec.id}`);
|
|
1014
1033
|
console.log(` Flow: ${flowName}`);
|
|
1015
1034
|
console.log(` Status: ${statusColor(exec.status)}`);
|
|
@@ -1021,28 +1040,28 @@ ${chalk.bold('Examples:')}
|
|
|
1021
1040
|
console.log(` Test Run: ${exec.isTest ? chalk.yellow('Yes') : 'No'}`);
|
|
1022
1041
|
|
|
1023
1042
|
if (exec.error) {
|
|
1024
|
-
console.log(`\n${chalk.red('
|
|
1043
|
+
console.log(`\n${chalk.red('Error:')}`);
|
|
1025
1044
|
console.log(` ${exec.error}`);
|
|
1026
1045
|
}
|
|
1027
1046
|
|
|
1028
1047
|
// Show input data
|
|
1029
1048
|
if (exec.inputData && Object.keys(exec.inputData).length > 0) {
|
|
1030
|
-
console.log(`\n${chalk.cyan('
|
|
1049
|
+
console.log(`\n${chalk.cyan('Input Data:')}`);
|
|
1031
1050
|
console.log(formatJson(exec.inputData));
|
|
1032
1051
|
}
|
|
1033
1052
|
|
|
1034
1053
|
// Show output data
|
|
1035
1054
|
if (exec.outputData && Object.keys(exec.outputData).length > 0) {
|
|
1036
|
-
console.log(`\n${chalk.cyan('
|
|
1055
|
+
console.log(`\n${chalk.cyan('Output Data:')}`);
|
|
1037
1056
|
console.log(formatJson(exec.outputData));
|
|
1038
1057
|
} else if (exec.output) {
|
|
1039
|
-
console.log(`\n${chalk.cyan('
|
|
1058
|
+
console.log(`\n${chalk.cyan('Output:')}`);
|
|
1040
1059
|
console.log(formatJson(exec.output));
|
|
1041
1060
|
}
|
|
1042
1061
|
|
|
1043
1062
|
// Show node executions summary
|
|
1044
1063
|
if (exec.nodeExecutions && exec.nodeExecutions.length > 0) {
|
|
1045
|
-
console.log(`\n${chalk.cyan('
|
|
1064
|
+
console.log(`\n${chalk.cyan('Node Executions:')} (${exec.nodeExecutions.length} nodes)\n`);
|
|
1046
1065
|
|
|
1047
1066
|
const nodeFormatted = exec.nodeExecutions.map((node) => {
|
|
1048
1067
|
const nodeStatus = node.status || 'unknown';
|
|
@@ -1054,7 +1073,7 @@ ${chalk.bold('Examples:')}
|
|
|
1054
1073
|
type: node.nodeType || '-',
|
|
1055
1074
|
status: nodeStatusColor(nodeStatus),
|
|
1056
1075
|
duration: nodeDuration,
|
|
1057
|
-
error: node.error ? chalk.red('
|
|
1076
|
+
error: node.error ? chalk.red('err') : '',
|
|
1058
1077
|
};
|
|
1059
1078
|
});
|
|
1060
1079
|
|
|
@@ -1067,8 +1086,8 @@ ${chalk.bold('Examples:')}
|
|
|
1067
1086
|
}
|
|
1068
1087
|
|
|
1069
1088
|
case 'node': {
|
|
1070
|
-
requireArgs(args.slice(1), 3, 'lux flows node <
|
|
1071
|
-
const flowId = args[1];
|
|
1089
|
+
requireArgs(args.slice(1), 3, 'lux flows node <name-or-id> <execution-id> <node-id>');
|
|
1090
|
+
const flowId = resolveFlowId(args[1]);
|
|
1072
1091
|
const executionId = args[2];
|
|
1073
1092
|
const nodeId = args[3];
|
|
1074
1093
|
const jsonOutput = args.includes('--json');
|
|
@@ -1124,7 +1143,7 @@ ${chalk.bold('Examples:')}
|
|
|
1124
1143
|
};
|
|
1125
1144
|
const statusColor = statusColors[nodeExec.status] || chalk.white;
|
|
1126
1145
|
|
|
1127
|
-
console.log(`\
|
|
1146
|
+
console.log(`\nNode Execution Details\n`);
|
|
1128
1147
|
console.log(` Node ID: ${nodeExec.nodeId || nodeExec.id}`);
|
|
1129
1148
|
console.log(` Type: ${nodeExec.nodeType || '-'}`);
|
|
1130
1149
|
console.log(` Label: ${nodeExec.label || '-'}`);
|
|
@@ -1134,31 +1153,31 @@ ${chalk.bold('Examples:')}
|
|
|
1134
1153
|
console.log(` Completed: ${nodeExec.completedAt ? new Date(nodeExec.completedAt).toLocaleString() : '-'}`);
|
|
1135
1154
|
|
|
1136
1155
|
if (nodeExec.error) {
|
|
1137
|
-
console.log(`\n${chalk.red('
|
|
1156
|
+
console.log(`\n${chalk.red('Error:')}`);
|
|
1138
1157
|
console.log(` ${nodeExec.error}`);
|
|
1139
1158
|
}
|
|
1140
1159
|
|
|
1141
1160
|
// Show node config
|
|
1142
1161
|
if (nodeExec.config && Object.keys(nodeExec.config).length > 0) {
|
|
1143
|
-
console.log(`\n${chalk.cyan('
|
|
1162
|
+
console.log(`\n${chalk.cyan('Node Config:')}`);
|
|
1144
1163
|
console.log(formatJson(nodeExec.config));
|
|
1145
1164
|
}
|
|
1146
1165
|
|
|
1147
1166
|
// Show input
|
|
1148
1167
|
if (nodeExec.input !== undefined) {
|
|
1149
|
-
console.log(`\n${chalk.cyan('
|
|
1168
|
+
console.log(`\n${chalk.cyan('Input:')}`);
|
|
1150
1169
|
console.log(formatJson(nodeExec.input));
|
|
1151
1170
|
}
|
|
1152
1171
|
|
|
1153
1172
|
// Show output
|
|
1154
1173
|
if (nodeExec.output !== undefined) {
|
|
1155
|
-
console.log(`\n${chalk.cyan('
|
|
1174
|
+
console.log(`\n${chalk.cyan('Output:')}`);
|
|
1156
1175
|
console.log(formatJson(nodeExec.output));
|
|
1157
1176
|
}
|
|
1158
1177
|
|
|
1159
1178
|
// Show raw data if nothing else
|
|
1160
1179
|
if (!nodeExec.input && !nodeExec.output && !nodeExec.config) {
|
|
1161
|
-
console.log(`\n${chalk.cyan('
|
|
1180
|
+
console.log(`\n${chalk.cyan('Raw Node Data:')}`);
|
|
1162
1181
|
console.log(formatJson(nodeExec));
|
|
1163
1182
|
}
|
|
1164
1183
|
|
|
@@ -1167,8 +1186,8 @@ ${chalk.bold('Examples:')}
|
|
|
1167
1186
|
}
|
|
1168
1187
|
|
|
1169
1188
|
case 'last': {
|
|
1170
|
-
requireArgs(args.slice(1), 1, 'lux flows last <
|
|
1171
|
-
const flowId = args[1];
|
|
1189
|
+
requireArgs(args.slice(1), 1, 'lux flows last <name-or-id>');
|
|
1190
|
+
const flowId = resolveFlowId(args[1]);
|
|
1172
1191
|
const jsonOutput = args.includes('--json');
|
|
1173
1192
|
|
|
1174
1193
|
const projectId = getProjectId();
|
|
@@ -1217,9 +1236,9 @@ ${chalk.bold('Examples:')}
|
|
|
1217
1236
|
const flow = loadLocalFlow(flowId);
|
|
1218
1237
|
const flowName = flow?.name || flowId;
|
|
1219
1238
|
|
|
1220
|
-
const status = exec.status === 'completed' ? chalk.green('
|
|
1221
|
-
exec.status === 'failed' ? chalk.red('
|
|
1222
|
-
chalk.yellow(
|
|
1239
|
+
const status = exec.status === 'completed' ? chalk.green('Success') :
|
|
1240
|
+
exec.status === 'failed' ? chalk.red('Failed') :
|
|
1241
|
+
chalk.yellow(exec.status);
|
|
1223
1242
|
const timestamp = new Date(exec.startedAt).toLocaleString();
|
|
1224
1243
|
const duration = exec.duration ? `${(exec.duration / 1000).toFixed(1)}s` : '-';
|
|
1225
1244
|
|
|
@@ -1232,9 +1251,9 @@ ${chalk.bold('Examples:')}
|
|
|
1232
1251
|
if (exec.nodeExecutions && exec.nodeExecutions.length > 0) {
|
|
1233
1252
|
console.log(`\n Node Results:`);
|
|
1234
1253
|
exec.nodeExecutions.forEach((node, i) => {
|
|
1235
|
-
const nodeStatus = node.status === 'completed' ? chalk.green('
|
|
1236
|
-
node.status === 'failed' ? chalk.red('
|
|
1237
|
-
chalk.yellow('
|
|
1254
|
+
const nodeStatus = node.status === 'completed' ? chalk.green('ok') :
|
|
1255
|
+
node.status === 'failed' ? chalk.red('fail') :
|
|
1256
|
+
chalk.yellow('...');
|
|
1238
1257
|
const nodeDuration = node.duration ? `${node.duration}ms` : '-';
|
|
1239
1258
|
let outputPreview = '';
|
|
1240
1259
|
if (node.output) {
|
|
@@ -1263,8 +1282,8 @@ ${chalk.bold('Examples:')}
|
|
|
1263
1282
|
}
|
|
1264
1283
|
|
|
1265
1284
|
case 'test': {
|
|
1266
|
-
requireArgs(args.slice(1), 1, 'lux flows test <
|
|
1267
|
-
const flowId = args[1];
|
|
1285
|
+
requireArgs(args.slice(1), 1, 'lux flows test <name-or-id> [--data <json>] [--data-file <path>]');
|
|
1286
|
+
const flowId = resolveFlowId(args[1]);
|
|
1268
1287
|
const jsonOutput = args.includes('--json');
|
|
1269
1288
|
|
|
1270
1289
|
// Parse --data or --data-file arguments
|
|
@@ -1288,7 +1307,7 @@ ${chalk.bold('Examples:')}
|
|
|
1288
1307
|
// Load flow from local storage
|
|
1289
1308
|
const flowData = loadLocalFlow(flowId);
|
|
1290
1309
|
if (!flowData) {
|
|
1291
|
-
error(`Flow not found locally: ${
|
|
1310
|
+
error(`Flow not found locally: ${args[1]}`);
|
|
1292
1311
|
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
1293
1312
|
break;
|
|
1294
1313
|
}
|
|
@@ -1329,9 +1348,9 @@ ${chalk.bold('Examples:')}
|
|
|
1329
1348
|
|
|
1330
1349
|
if (result.nodeExecutions && result.nodeExecutions.length > 0) {
|
|
1331
1350
|
result.nodeExecutions.forEach((node) => {
|
|
1332
|
-
const nodeStatus = node.status === 'completed' ? chalk.green('
|
|
1333
|
-
node.status === 'failed' ? chalk.red('
|
|
1334
|
-
chalk.yellow('
|
|
1351
|
+
const nodeStatus = node.status === 'completed' ? chalk.green('ok') :
|
|
1352
|
+
node.status === 'failed' ? chalk.red('fail') :
|
|
1353
|
+
chalk.yellow('...');
|
|
1335
1354
|
const nodeDuration = node.duration ? `${node.duration}ms` : '-';
|
|
1336
1355
|
let outputPreview = '';
|
|
1337
1356
|
if (node.output) {
|