luxlabs 1.0.18 → 1.0.19
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/commands/{workflows.js → flows.js} +131 -131
- package/lux.js +6 -6
- package/package.json +2 -2
|
@@ -74,7 +74,7 @@ async function saveWorkflowDraft(workflowId, config) {
|
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
async function
|
|
77
|
+
async function handleFlows(args) {
|
|
78
78
|
// Check authentication
|
|
79
79
|
if (!isAuthenticated()) {
|
|
80
80
|
console.log(
|
|
@@ -89,18 +89,18 @@ async function handleWorkflows(args) {
|
|
|
89
89
|
|
|
90
90
|
if (!command) {
|
|
91
91
|
console.log(`
|
|
92
|
-
${chalk.bold('Usage:')} lux
|
|
92
|
+
${chalk.bold('Usage:')} lux flows <command> [args]
|
|
93
93
|
|
|
94
94
|
${chalk.bold('Commands:')}
|
|
95
|
-
list List all
|
|
96
|
-
get <id> Get
|
|
97
|
-
status <id> Show sync status for a
|
|
98
|
-
create <name> [desc] [--publish] Create
|
|
99
|
-
init <name> [desc] [--publish] Initialize
|
|
95
|
+
list List all flows (from local storage)
|
|
96
|
+
get <id> Get flow details with config
|
|
97
|
+
status <id> Show sync status for a flow
|
|
98
|
+
create <name> [desc] [--publish] Create flow (use --publish to publish immediately)
|
|
99
|
+
init <name> [desc] [--publish] Initialize flow (alias for create)
|
|
100
100
|
save <id> <config-file> Save draft config from file (local)
|
|
101
|
-
sync Sync published
|
|
102
|
-
publish <id> Publish
|
|
103
|
-
delete <id> Delete a local
|
|
101
|
+
sync Sync published flows from cloud
|
|
102
|
+
publish <id> Publish flow to cloud
|
|
103
|
+
delete <id> Delete a local flow
|
|
104
104
|
diff <id> Show local vs published differences
|
|
105
105
|
|
|
106
106
|
${chalk.bold('Execution History:')}
|
|
@@ -128,33 +128,33 @@ ${chalk.bold('Execution Commands:')}
|
|
|
128
128
|
last <id> Show the last execution result
|
|
129
129
|
|
|
130
130
|
${chalk.bold('Examples:')}
|
|
131
|
-
lux
|
|
132
|
-
lux
|
|
133
|
-
lux
|
|
134
|
-
lux
|
|
135
|
-
lux
|
|
136
|
-
lux
|
|
137
|
-
lux
|
|
138
|
-
lux
|
|
139
|
-
lux
|
|
140
|
-
lux
|
|
131
|
+
lux flows list
|
|
132
|
+
lux flows get flow_123
|
|
133
|
+
lux flows status flow_123
|
|
134
|
+
lux flows create "My Flow" "Description"
|
|
135
|
+
lux flows create "My Flow" --publish # Create and publish immediately
|
|
136
|
+
lux flows init "My Flow" --publish
|
|
137
|
+
lux flows save flow_123 ./config.json
|
|
138
|
+
lux flows sync
|
|
139
|
+
lux flows publish flow_123
|
|
140
|
+
lux flows diff flow_123
|
|
141
141
|
|
|
142
142
|
${chalk.bold('Execution history:')}
|
|
143
|
-
lux
|
|
144
|
-
lux
|
|
145
|
-
lux
|
|
146
|
-
lux
|
|
143
|
+
lux flows executions my-flow-id
|
|
144
|
+
lux flows executions my-flow-id --limit 50
|
|
145
|
+
lux flows execution my-flow-id exec_abc123
|
|
146
|
+
lux flows node my-flow-id exec_abc123 node-1
|
|
147
147
|
|
|
148
|
-
${chalk.bold('Webhook
|
|
149
|
-
lux
|
|
150
|
-
lux
|
|
151
|
-
lux
|
|
152
|
-
lux
|
|
148
|
+
${chalk.bold('Webhook:')}
|
|
149
|
+
lux flows webhook-url flow_123
|
|
150
|
+
lux flows webhook-listen flow_123
|
|
151
|
+
lux flows webhook-poll flow_123
|
|
152
|
+
lux flows webhook-accept flow_123
|
|
153
153
|
|
|
154
154
|
${chalk.bold('Execution debugging:')}
|
|
155
|
-
lux
|
|
156
|
-
lux
|
|
157
|
-
lux
|
|
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
|
|
158
158
|
`);
|
|
159
159
|
process.exit(0);
|
|
160
160
|
}
|
|
@@ -165,14 +165,14 @@ ${chalk.bold('Examples:')}
|
|
|
165
165
|
try {
|
|
166
166
|
switch (command) {
|
|
167
167
|
case 'list': {
|
|
168
|
-
info('Loading
|
|
168
|
+
info('Loading flows from local storage...');
|
|
169
169
|
const localFlows = listLocalFlows();
|
|
170
170
|
|
|
171
171
|
if (localFlows.length === 0) {
|
|
172
|
-
console.log('\n(No local
|
|
173
|
-
console.log(chalk.gray('Run "lux
|
|
172
|
+
console.log('\n(No local flows found)');
|
|
173
|
+
console.log(chalk.gray('Run "lux flows sync" to sync from cloud, or "lux flows create" to create one.\n'));
|
|
174
174
|
} else {
|
|
175
|
-
console.log(`\nFound ${localFlows.length}
|
|
175
|
+
console.log(`\nFound ${localFlows.length} flow(s):\n`);
|
|
176
176
|
|
|
177
177
|
// Color-code sync status
|
|
178
178
|
const statusColors = {
|
|
@@ -203,12 +203,12 @@ ${chalk.bold('Examples:')}
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
case 'status': {
|
|
206
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
207
|
-
const
|
|
206
|
+
requireArgs(args.slice(1), 1, 'lux flows status <id>');
|
|
207
|
+
const flowId = args[1];
|
|
208
208
|
|
|
209
|
-
const flow = loadLocalFlow(
|
|
209
|
+
const flow = loadLocalFlow(flowId);
|
|
210
210
|
if (!flow) {
|
|
211
|
-
error(`
|
|
211
|
+
error(`Flow not found locally: ${flowId}`);
|
|
212
212
|
break;
|
|
213
213
|
}
|
|
214
214
|
|
|
@@ -231,8 +231,8 @@ ${chalk.bold('Examples:')}
|
|
|
231
231
|
conflict: chalk.red,
|
|
232
232
|
};
|
|
233
233
|
|
|
234
|
-
console.log(`\n📝
|
|
235
|
-
console.log(` ID: ${
|
|
234
|
+
console.log(`\n📝 Flow: ${flow.name}`);
|
|
235
|
+
console.log(` ID: ${flowId}`);
|
|
236
236
|
console.log(` Sync Status: ${statusColors[syncStatus](syncStatus)}`);
|
|
237
237
|
console.log(` Local Version: ${flow.localVersion || 1}`);
|
|
238
238
|
console.log(` Published Version: ${flow.publishedVersion || '(never published)'}`);
|
|
@@ -243,17 +243,17 @@ ${chalk.bold('Examples:')}
|
|
|
243
243
|
console.log(` Edges: ${flow.edges?.length || 0}`);
|
|
244
244
|
|
|
245
245
|
if (syncStatus === 'conflict') {
|
|
246
|
-
console.log(chalk.red('\n⚠️ This
|
|
246
|
+
console.log(chalk.red('\n⚠️ This flow has conflicts with the cloud version.'));
|
|
247
247
|
console.log(chalk.gray(' Use the Lux Studio app to resolve conflicts.\n'));
|
|
248
248
|
} else if (syncStatus === 'dirty') {
|
|
249
|
-
console.log(chalk.yellow('\n📤 This
|
|
250
|
-
console.log(chalk.gray(' Run "lux
|
|
249
|
+
console.log(chalk.yellow('\n📤 This flow has unpublished local changes.'));
|
|
250
|
+
console.log(chalk.gray(' Run "lux flows publish ' + flowId + '" to publish.\n'));
|
|
251
251
|
}
|
|
252
252
|
break;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
case 'sync': {
|
|
256
|
-
info('Syncing
|
|
256
|
+
info('Syncing flows from cloud...');
|
|
257
257
|
|
|
258
258
|
const { data } = await axios.get(`${apiUrl}/api/workflows?include_config=true`, {
|
|
259
259
|
headers: getAuthHeaders(),
|
|
@@ -357,18 +357,18 @@ ${chalk.bold('Examples:')}
|
|
|
357
357
|
console.log(` New from cloud: ${newFromCloud}`);
|
|
358
358
|
if (conflicts > 0) {
|
|
359
359
|
console.log(chalk.red(` Conflicts: ${conflicts}`));
|
|
360
|
-
console.log(chalk.gray('\n Use "lux
|
|
360
|
+
console.log(chalk.gray('\n Use "lux flows list" to see flows with conflicts.'));
|
|
361
361
|
}
|
|
362
362
|
break;
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
case 'delete': {
|
|
366
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
367
|
-
const
|
|
366
|
+
requireArgs(args.slice(1), 1, 'lux flows delete <id>');
|
|
367
|
+
const flowId = args[1];
|
|
368
368
|
|
|
369
|
-
const flow = loadLocalFlow(
|
|
369
|
+
const flow = loadLocalFlow(flowId);
|
|
370
370
|
if (!flow) {
|
|
371
|
-
error(`
|
|
371
|
+
error(`Flow not found locally: ${flowId}`);
|
|
372
372
|
break;
|
|
373
373
|
}
|
|
374
374
|
|
|
@@ -377,23 +377,23 @@ ${chalk.bold('Examples:')}
|
|
|
377
377
|
console.log(chalk.gray(' This only deletes the local copy. The published version remains in the cloud.\n'));
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
-
deleteLocalFlow(
|
|
381
|
-
success(`Deleted local
|
|
380
|
+
deleteLocalFlow(flowId);
|
|
381
|
+
success(`Deleted local flow: ${flow.name}`);
|
|
382
382
|
break;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
case 'get': {
|
|
386
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
387
|
-
const
|
|
386
|
+
requireArgs(args.slice(1), 1, 'lux flows get <id>');
|
|
387
|
+
const flowId = args[1];
|
|
388
388
|
|
|
389
|
-
info(`Loading
|
|
389
|
+
info(`Loading flow: ${flowId}`);
|
|
390
390
|
const { data } = await axios.get(
|
|
391
|
-
`${apiUrl}/api/workflows/${
|
|
391
|
+
`${apiUrl}/api/workflows/${flowId}`,
|
|
392
392
|
{ headers: getAuthHeaders() }
|
|
393
393
|
);
|
|
394
394
|
|
|
395
395
|
if (!data.workflow) {
|
|
396
|
-
error(`
|
|
396
|
+
error(`Flow not found: ${flowId}`);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
const workflow = data.workflow;
|
|
@@ -421,7 +421,7 @@ ${chalk.bold('Examples:')}
|
|
|
421
421
|
args.splice(publishFlagIndex, 1); // Remove flag from args
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
424
|
+
requireArgs(args.slice(1), 1, 'lux flows create <name> [description] [--publish]');
|
|
425
425
|
const name = args[1];
|
|
426
426
|
const description = args[2] || '';
|
|
427
427
|
|
|
@@ -454,15 +454,15 @@ ${chalk.bold('Examples:')}
|
|
|
454
454
|
updatedAt: now,
|
|
455
455
|
};
|
|
456
456
|
|
|
457
|
-
info(`Creating local
|
|
457
|
+
info(`Creating local flow: ${name}`);
|
|
458
458
|
|
|
459
459
|
if (saveLocalFlow(flowId, newFlow)) {
|
|
460
|
-
success(`
|
|
460
|
+
success(`Flow created locally!`);
|
|
461
461
|
console.log(` ID: ${flowId}`);
|
|
462
462
|
|
|
463
463
|
// If --publish flag was provided, publish immediately
|
|
464
464
|
if (shouldPublish) {
|
|
465
|
-
info(`Publishing
|
|
465
|
+
info(`Publishing flow to cloud...`);
|
|
466
466
|
|
|
467
467
|
try {
|
|
468
468
|
const publishConfig = {
|
|
@@ -485,7 +485,7 @@ ${chalk.bold('Examples:')}
|
|
|
485
485
|
|
|
486
486
|
const cloudId = createResponse.data.workflow?.id || createResponse.data.workflow?.workflow_id;
|
|
487
487
|
if (!cloudId) {
|
|
488
|
-
throw new Error('No
|
|
488
|
+
throw new Error('No flow ID returned from cloud');
|
|
489
489
|
}
|
|
490
490
|
|
|
491
491
|
info(`Created in cloud with ID: ${cloudId}`);
|
|
@@ -518,41 +518,41 @@ ${chalk.bold('Examples:')}
|
|
|
518
518
|
};
|
|
519
519
|
saveLocalFlow(flowId, updatedFlow);
|
|
520
520
|
|
|
521
|
-
success('
|
|
521
|
+
success('Flow published!');
|
|
522
522
|
console.log(` Cloud ID: ${cloudId}`);
|
|
523
523
|
console.log(` Status: ${chalk.green('published')}`);
|
|
524
524
|
console.log(` Version: ${newVersion}`);
|
|
525
525
|
} catch (publishError) {
|
|
526
526
|
error(`Failed to publish: ${publishError.response?.data?.error || publishError.message}`);
|
|
527
527
|
console.log(` Status: ${chalk.gray('draft')}`);
|
|
528
|
-
console.log(chalk.gray(`\nRun "lux
|
|
528
|
+
console.log(chalk.gray(`\nRun "lux flows publish ${flowId}" to try again.`));
|
|
529
529
|
}
|
|
530
530
|
} else {
|
|
531
531
|
console.log(` Status: ${chalk.gray('draft')}`);
|
|
532
|
-
console.log(chalk.gray(`\n This
|
|
532
|
+
console.log(chalk.gray(`\n This flow is local only. Run "lux flows publish ${flowId}" to publish to cloud.`));
|
|
533
533
|
}
|
|
534
534
|
} else {
|
|
535
|
-
error('Failed to create
|
|
535
|
+
error('Failed to create flow. Make sure you are authenticated.');
|
|
536
536
|
}
|
|
537
537
|
break;
|
|
538
538
|
}
|
|
539
539
|
|
|
540
540
|
case 'save': {
|
|
541
|
-
requireArgs(args.slice(1), 2, 'lux
|
|
542
|
-
const
|
|
541
|
+
requireArgs(args.slice(1), 2, 'lux flows save <id> <config-file>');
|
|
542
|
+
const flowId = args[1];
|
|
543
543
|
const configFile = args[2];
|
|
544
544
|
|
|
545
545
|
// Load existing local flow
|
|
546
|
-
const existingFlow = loadLocalFlow(
|
|
546
|
+
const existingFlow = loadLocalFlow(flowId);
|
|
547
547
|
if (!existingFlow) {
|
|
548
|
-
error(`
|
|
549
|
-
console.log(chalk.gray('Run "lux
|
|
548
|
+
error(`Flow not found locally: ${flowId}`);
|
|
549
|
+
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
550
550
|
break;
|
|
551
551
|
}
|
|
552
552
|
|
|
553
553
|
info(`Reading config from: ${configFile}`);
|
|
554
554
|
const configJson = readFile(configFile);
|
|
555
|
-
const config = parseJson(configJson, '
|
|
555
|
+
const config = parseJson(configJson, 'flow config');
|
|
556
556
|
|
|
557
557
|
// Update local flow with new config
|
|
558
558
|
const updatedFlow = {
|
|
@@ -563,9 +563,9 @@ ${chalk.bold('Examples:')}
|
|
|
563
563
|
updatedAt: new Date().toISOString(),
|
|
564
564
|
};
|
|
565
565
|
|
|
566
|
-
info(`Saving to local storage: ${
|
|
567
|
-
if (saveLocalFlow(
|
|
568
|
-
success('
|
|
566
|
+
info(`Saving to local storage: ${flowId}`);
|
|
567
|
+
if (saveLocalFlow(flowId, updatedFlow)) {
|
|
568
|
+
success('Flow saved locally!');
|
|
569
569
|
console.log(` Local Version: ${updatedFlow.localVersion}`);
|
|
570
570
|
|
|
571
571
|
// Show sync status
|
|
@@ -576,22 +576,22 @@ ${chalk.bold('Examples:')}
|
|
|
576
576
|
console.log(` Status: ${chalk.yellow('dirty')} (has unpublished changes)`);
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
-
console.log(chalk.gray(`\nRun "lux
|
|
579
|
+
console.log(chalk.gray(`\nRun "lux flows publish ${flowId}" to publish to cloud.`));
|
|
580
580
|
} else {
|
|
581
|
-
error('Failed to save
|
|
581
|
+
error('Failed to save flow locally.');
|
|
582
582
|
}
|
|
583
583
|
break;
|
|
584
584
|
}
|
|
585
585
|
|
|
586
586
|
case 'publish': {
|
|
587
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
588
|
-
const
|
|
587
|
+
requireArgs(args.slice(1), 1, 'lux flows publish <id>');
|
|
588
|
+
const flowId = args[1];
|
|
589
589
|
|
|
590
590
|
// Load local flow
|
|
591
|
-
const localFlow = loadLocalFlow(
|
|
591
|
+
const localFlow = loadLocalFlow(flowId);
|
|
592
592
|
if (!localFlow) {
|
|
593
|
-
error(`
|
|
594
|
-
console.log(chalk.gray('Run "lux
|
|
593
|
+
error(`Flow not found locally: ${flowId}`);
|
|
594
|
+
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
595
595
|
break;
|
|
596
596
|
}
|
|
597
597
|
|
|
@@ -599,12 +599,12 @@ ${chalk.bold('Examples:')}
|
|
|
599
599
|
if (localFlow.cloudVersion && localFlow.publishedVersion &&
|
|
600
600
|
localFlow.cloudVersion > localFlow.publishedVersion &&
|
|
601
601
|
localFlow.localVersion > localFlow.publishedVersion) {
|
|
602
|
-
error('Cannot publish:
|
|
602
|
+
error('Cannot publish: flow has conflicts with cloud version.');
|
|
603
603
|
console.log(chalk.gray('Resolve conflicts in Lux Studio first.'));
|
|
604
604
|
break;
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
info(`Publishing
|
|
607
|
+
info(`Publishing flow: ${flowId}`);
|
|
608
608
|
|
|
609
609
|
// Publish directly to cloud with config in request body
|
|
610
610
|
const publishConfig = {
|
|
@@ -615,7 +615,7 @@ ${chalk.bold('Examples:')}
|
|
|
615
615
|
};
|
|
616
616
|
|
|
617
617
|
const { data } = await axios.post(
|
|
618
|
-
`${apiUrl}/api/workflows/${
|
|
618
|
+
`${apiUrl}/api/workflows/${flowId}/publish`,
|
|
619
619
|
{
|
|
620
620
|
name: localFlow.name,
|
|
621
621
|
description: localFlow.description,
|
|
@@ -643,9 +643,9 @@ ${chalk.bold('Examples:')}
|
|
|
643
643
|
cloudPublishedAt: now,
|
|
644
644
|
cloudStatus: 'published',
|
|
645
645
|
};
|
|
646
|
-
saveLocalFlow(
|
|
646
|
+
saveLocalFlow(flowId, updatedFlow);
|
|
647
647
|
|
|
648
|
-
success('
|
|
648
|
+
success('Flow published!');
|
|
649
649
|
console.log(` Name: ${localFlow.name}`);
|
|
650
650
|
console.log(` Version: ${newVersion}`);
|
|
651
651
|
console.log(` Status: ${chalk.green('synced')}`);
|
|
@@ -653,17 +653,17 @@ ${chalk.bold('Examples:')}
|
|
|
653
653
|
}
|
|
654
654
|
|
|
655
655
|
case 'diff': {
|
|
656
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
657
|
-
const
|
|
656
|
+
requireArgs(args.slice(1), 1, 'lux flows diff <id>');
|
|
657
|
+
const flowId = args[1];
|
|
658
658
|
|
|
659
659
|
// Load local flow
|
|
660
|
-
const localFlow = loadLocalFlow(
|
|
660
|
+
const localFlow = loadLocalFlow(flowId);
|
|
661
661
|
if (!localFlow) {
|
|
662
|
-
error(`
|
|
662
|
+
error(`Flow not found locally: ${flowId}`);
|
|
663
663
|
break;
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
info(`Comparing local vs published for: ${
|
|
666
|
+
info(`Comparing local vs published for: ${flowId}`);
|
|
667
667
|
|
|
668
668
|
const localConfig = {
|
|
669
669
|
nodes: localFlow.nodes || [],
|
|
@@ -672,12 +672,12 @@ ${chalk.bold('Examples:')}
|
|
|
672
672
|
|
|
673
673
|
// Check if never published
|
|
674
674
|
if (!localFlow.publishedVersion) {
|
|
675
|
-
console.log('\n📝 NEW
|
|
675
|
+
console.log('\n📝 NEW FLOW (not yet published)\n');
|
|
676
676
|
console.log(` Name: ${localFlow.name}`);
|
|
677
677
|
console.log(` Local Version: ${localFlow.localVersion || 1}`);
|
|
678
678
|
console.log(` Nodes: ${localConfig.nodes.length}`);
|
|
679
679
|
console.log(` Edges: ${localConfig.edges.length}`);
|
|
680
|
-
console.log(chalk.gray(`\nRun "lux
|
|
680
|
+
console.log(chalk.gray(`\nRun "lux flows publish ${flowId}" to publish.\n`));
|
|
681
681
|
break;
|
|
682
682
|
}
|
|
683
683
|
|
|
@@ -709,17 +709,17 @@ ${chalk.bold('Examples:')}
|
|
|
709
709
|
console.log(` Published Version: ${localFlow.publishedVersion}`);
|
|
710
710
|
console.log(` Nodes: ${localConfig.nodes.length}`);
|
|
711
711
|
console.log(` Edges: ${localConfig.edges.length}`);
|
|
712
|
-
console.log(chalk.gray(`\nRun "lux
|
|
712
|
+
console.log(chalk.gray(`\nRun "lux flows publish ${flowId}" to publish changes.\n`));
|
|
713
713
|
}
|
|
714
714
|
break;
|
|
715
715
|
}
|
|
716
716
|
|
|
717
717
|
case 'webhook-url': {
|
|
718
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
719
|
-
const
|
|
718
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-url <flow-id>');
|
|
719
|
+
const flowId = args[1];
|
|
720
720
|
|
|
721
|
-
info(`Getting webhook URL for: ${
|
|
722
|
-
const tokenData = await getWebhookToken(
|
|
721
|
+
info(`Getting webhook URL for: ${flowId}`);
|
|
722
|
+
const tokenData = await getWebhookToken(flowId);
|
|
723
723
|
|
|
724
724
|
console.log(`\n📍 Webhook URL:\n${tokenData.webhookUrl}\n`);
|
|
725
725
|
console.log(`📊 Status:`);
|
|
@@ -727,17 +727,17 @@ ${chalk.bold('Examples:')}
|
|
|
727
727
|
console.log(` Webhook Trigger Enabled: ${tokenData.webhookTrigger ? '✅ Yes' : '❌ No'}\n`);
|
|
728
728
|
|
|
729
729
|
if (!tokenData.formatConfirmed) {
|
|
730
|
-
console.log(chalk.yellow('ℹ️ Run "lux
|
|
730
|
+
console.log(chalk.yellow('ℹ️ Run "lux flows webhook-listen" to capture a sample webhook'));
|
|
731
731
|
}
|
|
732
732
|
break;
|
|
733
733
|
}
|
|
734
734
|
|
|
735
735
|
case 'webhook-listen': {
|
|
736
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
737
|
-
const
|
|
736
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-listen <flow-id>');
|
|
737
|
+
const flowId = args[1];
|
|
738
738
|
|
|
739
|
-
info(`Starting webhook listening session for: ${
|
|
740
|
-
const tokenData = await getWebhookToken(
|
|
739
|
+
info(`Starting webhook listening session for: ${flowId}`);
|
|
740
|
+
const tokenData = await getWebhookToken(flowId);
|
|
741
741
|
|
|
742
742
|
// Start listening session
|
|
743
743
|
await axios.post(`${WEBHOOK_WORKER_URL}/listening/start/${tokenData.token}`);
|
|
@@ -746,15 +746,15 @@ ${chalk.bold('Examples:')}
|
|
|
746
746
|
console.log(`\n📡 Now listening for webhooks at:\n${tokenData.webhookUrl}\n`);
|
|
747
747
|
console.log('Session expires in 5 minutes.');
|
|
748
748
|
console.log(`\nSend a webhook request to the URL above, then run:`);
|
|
749
|
-
console.log(chalk.white(` lux
|
|
749
|
+
console.log(chalk.white(` lux flows webhook-poll ${flowId}\n`));
|
|
750
750
|
break;
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
case 'webhook-poll': {
|
|
754
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
755
|
-
const
|
|
754
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-poll <flow-id>');
|
|
755
|
+
const flowId = args[1];
|
|
756
756
|
|
|
757
|
-
const tokenData = await getWebhookToken(
|
|
757
|
+
const tokenData = await getWebhookToken(flowId);
|
|
758
758
|
const pollData = await getCapturedPayload(tokenData.token);
|
|
759
759
|
|
|
760
760
|
// Return raw JSON response
|
|
@@ -763,20 +763,20 @@ ${chalk.bold('Examples:')}
|
|
|
763
763
|
}
|
|
764
764
|
|
|
765
765
|
case 'webhook-accept': {
|
|
766
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
767
|
-
const
|
|
766
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-accept <flow-id>');
|
|
767
|
+
const flowId = args[1];
|
|
768
768
|
|
|
769
|
-
info(`Accepting webhook format for: ${
|
|
769
|
+
info(`Accepting webhook format for: ${flowId}`);
|
|
770
770
|
|
|
771
771
|
// Step 1: Get webhook token
|
|
772
|
-
const tokenData = await getWebhookToken(
|
|
772
|
+
const tokenData = await getWebhookToken(flowId);
|
|
773
773
|
|
|
774
774
|
// Step 2: Poll for captured payload
|
|
775
775
|
const pollData = await getCapturedPayload(tokenData.token);
|
|
776
776
|
|
|
777
777
|
// Check if payload was captured
|
|
778
778
|
if (pollData.waiting || !pollData.payload) {
|
|
779
|
-
error('No webhook captured. Run "lux
|
|
779
|
+
error('No webhook captured. Run "lux flows webhook-listen" first and send a test webhook.');
|
|
780
780
|
break;
|
|
781
781
|
}
|
|
782
782
|
|
|
@@ -851,11 +851,11 @@ ${chalk.bold('Examples:')}
|
|
|
851
851
|
}
|
|
852
852
|
|
|
853
853
|
case 'webhook-decline': {
|
|
854
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
855
|
-
const
|
|
854
|
+
requireArgs(args.slice(1), 1, 'lux flows webhook-decline <flow-id>');
|
|
855
|
+
const flowId = args[1];
|
|
856
856
|
|
|
857
|
-
info(`Declining webhook format for: ${
|
|
858
|
-
const tokenData = await getWebhookToken(
|
|
857
|
+
info(`Declining webhook format for: ${flowId}`);
|
|
858
|
+
const tokenData = await getWebhookToken(flowId);
|
|
859
859
|
|
|
860
860
|
// Clear webhook schema from database
|
|
861
861
|
info('Clearing webhook schema...');
|
|
@@ -870,14 +870,14 @@ ${chalk.bold('Examples:')}
|
|
|
870
870
|
success('Webhook format declined!');
|
|
871
871
|
console.log('\n✅ Schema cleared from database');
|
|
872
872
|
console.log('✅ Listening session has been reset');
|
|
873
|
-
console.log(`\nRun "lux
|
|
873
|
+
console.log(`\nRun "lux flows webhook-listen ${flowId}" to try again.\n`);
|
|
874
874
|
break;
|
|
875
875
|
}
|
|
876
876
|
|
|
877
877
|
// ============ EXECUTION HISTORY COMMANDS ============
|
|
878
878
|
|
|
879
879
|
case 'executions': {
|
|
880
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
880
|
+
requireArgs(args.slice(1), 1, 'lux flows executions <flow-id> [--limit N]');
|
|
881
881
|
const flowId = args[1];
|
|
882
882
|
|
|
883
883
|
// Parse --limit flag
|
|
@@ -912,7 +912,7 @@ ${chalk.bold('Examples:')}
|
|
|
912
912
|
|
|
913
913
|
if (executions.length === 0) {
|
|
914
914
|
console.log('\n(No executions found for this flow)');
|
|
915
|
-
console.log(chalk.gray('Run the flow from the interface or use "lux
|
|
915
|
+
console.log(chalk.gray('Run the flow from the interface or use "lux flows test" to create an execution.\n'));
|
|
916
916
|
break;
|
|
917
917
|
}
|
|
918
918
|
|
|
@@ -954,12 +954,12 @@ ${chalk.bold('Examples:')}
|
|
|
954
954
|
console.log(chalk.dim(`Use --limit N to see more.\n`));
|
|
955
955
|
}
|
|
956
956
|
|
|
957
|
-
console.log(chalk.gray(`\nTo see full details: lux
|
|
957
|
+
console.log(chalk.gray(`\nTo see full details: lux flows execution ${flowId} <execution-id>\n`));
|
|
958
958
|
break;
|
|
959
959
|
}
|
|
960
960
|
|
|
961
961
|
case 'execution': {
|
|
962
|
-
requireArgs(args.slice(1), 2, 'lux
|
|
962
|
+
requireArgs(args.slice(1), 2, 'lux flows execution <flow-id> <execution-id>');
|
|
963
963
|
const flowId = args[1];
|
|
964
964
|
const executionId = args[2];
|
|
965
965
|
const jsonOutput = args.includes('--json');
|
|
@@ -1056,14 +1056,14 @@ ${chalk.bold('Examples:')}
|
|
|
1056
1056
|
|
|
1057
1057
|
formatTable(nodeFormatted);
|
|
1058
1058
|
|
|
1059
|
-
console.log(chalk.gray(`\nTo see node details: lux
|
|
1059
|
+
console.log(chalk.gray(`\nTo see node details: lux flows node ${flowId} ${executionId} <node-id>\n`));
|
|
1060
1060
|
}
|
|
1061
1061
|
|
|
1062
1062
|
break;
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
1065
|
case 'node': {
|
|
1066
|
-
requireArgs(args.slice(1), 3, 'lux
|
|
1066
|
+
requireArgs(args.slice(1), 3, 'lux flows node <flow-id> <execution-id> <node-id>');
|
|
1067
1067
|
const flowId = args[1];
|
|
1068
1068
|
const executionId = args[2];
|
|
1069
1069
|
const nodeId = args[3];
|
|
@@ -1163,7 +1163,7 @@ ${chalk.bold('Examples:')}
|
|
|
1163
1163
|
}
|
|
1164
1164
|
|
|
1165
1165
|
case 'last': {
|
|
1166
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
1166
|
+
requireArgs(args.slice(1), 1, 'lux flows last <flow-id>');
|
|
1167
1167
|
const flowId = args[1];
|
|
1168
1168
|
const jsonOutput = args.includes('--json');
|
|
1169
1169
|
|
|
@@ -1188,7 +1188,7 @@ ${chalk.bold('Examples:')}
|
|
|
1188
1188
|
const executions = listData.executions || [];
|
|
1189
1189
|
if (executions.length === 0) {
|
|
1190
1190
|
console.log('\n(No executions found for this flow)');
|
|
1191
|
-
console.log(chalk.gray('Run the flow from the interface or use "lux
|
|
1191
|
+
console.log(chalk.gray('Run the flow from the interface or use "lux flows test" to create an execution.\n'));
|
|
1192
1192
|
break;
|
|
1193
1193
|
}
|
|
1194
1194
|
|
|
@@ -1259,7 +1259,7 @@ ${chalk.bold('Examples:')}
|
|
|
1259
1259
|
}
|
|
1260
1260
|
|
|
1261
1261
|
case 'test': {
|
|
1262
|
-
requireArgs(args.slice(1), 1, 'lux
|
|
1262
|
+
requireArgs(args.slice(1), 1, 'lux flows test <flow-id> [--data <json>] [--data-file <path>]');
|
|
1263
1263
|
const flowId = args[1];
|
|
1264
1264
|
const jsonOutput = args.includes('--json');
|
|
1265
1265
|
|
|
@@ -1285,7 +1285,7 @@ ${chalk.bold('Examples:')}
|
|
|
1285
1285
|
const flowData = loadLocalFlow(flowId);
|
|
1286
1286
|
if (!flowData) {
|
|
1287
1287
|
error(`Flow not found locally: ${flowId}`);
|
|
1288
|
-
console.log(chalk.gray('Run "lux
|
|
1288
|
+
console.log(chalk.gray('Run "lux flows sync" to sync from cloud first.'));
|
|
1289
1289
|
break;
|
|
1290
1290
|
}
|
|
1291
1291
|
|
|
@@ -1363,7 +1363,7 @@ ${chalk.bold('Examples:')}
|
|
|
1363
1363
|
|
|
1364
1364
|
default:
|
|
1365
1365
|
error(
|
|
1366
|
-
`Unknown command: ${command}\n\nRun 'lux
|
|
1366
|
+
`Unknown command: ${command}\n\nRun 'lux flows' to see available commands`
|
|
1367
1367
|
);
|
|
1368
1368
|
}
|
|
1369
1369
|
} catch (err) {
|
|
@@ -1373,4 +1373,4 @@ ${chalk.bold('Examples:')}
|
|
|
1373
1373
|
}
|
|
1374
1374
|
}
|
|
1375
1375
|
|
|
1376
|
-
module.exports = {
|
|
1376
|
+
module.exports = { handleFlows };
|
package/lux.js
CHANGED
|
@@ -11,7 +11,7 @@ const { dev } = require('./commands/dev');
|
|
|
11
11
|
const { handleInterface } = require('./commands/interface');
|
|
12
12
|
const { handleData } = require('./commands/data');
|
|
13
13
|
const { handleStorage } = require('./commands/storage');
|
|
14
|
-
const {
|
|
14
|
+
const { handleFlows } = require('./commands/flows');
|
|
15
15
|
const { handleSecrets } = require('./commands/secrets');
|
|
16
16
|
const { handleAgents } = require('./commands/agents');
|
|
17
17
|
const { handleKnowledge } = require('./commands/knowledge');
|
|
@@ -96,14 +96,14 @@ program
|
|
|
96
96
|
handleStorage(subcommand ? [subcommand, ...(args || [])] : []);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
//
|
|
99
|
+
// Flows commands (with short alias 'f')
|
|
100
100
|
program
|
|
101
|
-
.command('
|
|
102
|
-
.
|
|
103
|
-
.description('
|
|
101
|
+
.command('flows [subcommand] [args...]')
|
|
102
|
+
.alias('f')
|
|
103
|
+
.description('Flow management (list, get, create/init, save, publish, diff)')
|
|
104
104
|
.allowUnknownOption()
|
|
105
105
|
.action((subcommand, args) => {
|
|
106
|
-
|
|
106
|
+
handleFlows(subcommand ? [subcommand, ...(args || [])] : []);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
// Secrets commands
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "luxlabs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "CLI tool for Lux - Upload and deploy interfaces from your terminal",
|
|
5
5
|
"author": "Jason Henkel <jason@uselux.ai>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"deploy",
|
|
25
25
|
"interfaces",
|
|
26
26
|
"ai",
|
|
27
|
-
"
|
|
27
|
+
"flows",
|
|
28
28
|
"agents"
|
|
29
29
|
],
|
|
30
30
|
"repository": {
|