@adminforth/bulk-ai-flow 1.24.3 → 1.24.4
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/build.log +2 -2
- package/custom/VisionAction.vue +55 -20
- package/dist/custom/VisionAction.vue +55 -20
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -14,5 +14,5 @@ custom/package.json
|
|
|
14
14
|
custom/pnpm-lock.yaml
|
|
15
15
|
custom/tsconfig.json
|
|
16
16
|
|
|
17
|
-
sent
|
|
18
|
-
total size is
|
|
17
|
+
sent 112,987 bytes received 191 bytes 226,356.00 bytes/sec
|
|
18
|
+
total size is 112,273 speedup is 0.99
|
package/custom/VisionAction.vue
CHANGED
|
@@ -197,6 +197,7 @@ const props = defineProps<{
|
|
|
197
197
|
}>();
|
|
198
198
|
|
|
199
199
|
type RecordStatus = 'pending' | 'processing' | 'completed' | 'failed';
|
|
200
|
+
type GenerationAction = 'analyze' | 'analyze_no_images' | 'generate_images';
|
|
200
201
|
|
|
201
202
|
type RecordState = {
|
|
202
203
|
id: string | number;
|
|
@@ -256,6 +257,11 @@ const startedRecordCount = ref(0);
|
|
|
256
257
|
const isCheckingRateLimits = ref(false);
|
|
257
258
|
let startGate = Promise.resolve();
|
|
258
259
|
const tableRef = ref<any>(null);
|
|
260
|
+
const generationFailureGroups = new Map<string, {
|
|
261
|
+
actionType: GenerationAction;
|
|
262
|
+
error: string;
|
|
263
|
+
recordIds: Set<string>;
|
|
264
|
+
}>();
|
|
259
265
|
const processedCount = computed(() => {
|
|
260
266
|
recordsVersion.value;
|
|
261
267
|
return Array.from(recordsById.values()).filter(record => record.status === 'completed' || record.status === 'failed').length;
|
|
@@ -398,12 +404,14 @@ async function runAiActions() {
|
|
|
398
404
|
isActiveGeneration.value = true;
|
|
399
405
|
completedRecordIds.value = new Set();
|
|
400
406
|
startedRecordCount.value = 0;
|
|
407
|
+
generationFailureGroups.clear();
|
|
401
408
|
await nextTick();
|
|
402
409
|
tableRef.value?.refresh();
|
|
403
410
|
const limit = pLimit(props.meta.concurrencyLimit || 10);
|
|
404
411
|
const tasks = recordIds.value
|
|
405
412
|
.map(id => limit(() => processOneRecord(String(id))));
|
|
406
413
|
await Promise.all(tasks);
|
|
414
|
+
showGenerationFailureSummary();
|
|
407
415
|
isActiveGeneration.value = false;
|
|
408
416
|
}
|
|
409
417
|
|
|
@@ -431,6 +439,39 @@ function resetGlobalState() {
|
|
|
431
439
|
recordIds.value = [];
|
|
432
440
|
recordsById.clear();
|
|
433
441
|
uncheckedRecordIds.clear();
|
|
442
|
+
generationFailureGroups.clear();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function getActionLabel(actionType: GenerationAction) {
|
|
446
|
+
return actionType.replace('_', ' ');
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function registerGenerationFailure(record: RecordState, actionType: GenerationAction, error: string) {
|
|
450
|
+
const key = `${actionType}:${error}`;
|
|
451
|
+
let group = generationFailureGroups.get(key);
|
|
452
|
+
if (!group) {
|
|
453
|
+
group = {
|
|
454
|
+
actionType,
|
|
455
|
+
error,
|
|
456
|
+
recordIds: new Set(),
|
|
457
|
+
};
|
|
458
|
+
generationFailureGroups.set(key, group);
|
|
459
|
+
}
|
|
460
|
+
group.recordIds.add(String(record.id));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function showGenerationFailureSummary() {
|
|
464
|
+
for (const group of generationFailureGroups.values()) {
|
|
465
|
+
const failedCount = group.recordIds.size;
|
|
466
|
+
const firstRecordId = Array.from(group.recordIds)[0];
|
|
467
|
+
adminforth.alert({
|
|
468
|
+
message: t(
|
|
469
|
+
`Generation action "${getActionLabel(group.actionType)}" failed for ${failedCount} record(s). First failed record: ${firstRecordId}. Error: ${group.error}`,
|
|
470
|
+
),
|
|
471
|
+
variant: 'danger',
|
|
472
|
+
timeout: 'unlimited',
|
|
473
|
+
});
|
|
474
|
+
}
|
|
434
475
|
}
|
|
435
476
|
|
|
436
477
|
function getOrCreateRecord(recordId: string | number): RecordState {
|
|
@@ -622,7 +663,7 @@ async function processOneRecord(recordId: string) {
|
|
|
622
663
|
}
|
|
623
664
|
}
|
|
624
665
|
|
|
625
|
-
const actions:
|
|
666
|
+
const actions: GenerationAction[] = [];
|
|
626
667
|
if (props.meta.isImageGeneration) {
|
|
627
668
|
actions.push('generate_images');
|
|
628
669
|
}
|
|
@@ -645,7 +686,7 @@ async function processOneRecord(recordId: string) {
|
|
|
645
686
|
|
|
646
687
|
async function checkRateLimits() {
|
|
647
688
|
isCheckingRateLimits.value = true;
|
|
648
|
-
const actionsToCheck:
|
|
689
|
+
const actionsToCheck: GenerationAction[] = [];
|
|
649
690
|
if (props.meta.isImageGeneration) {
|
|
650
691
|
actionsToCheck.push('generate_images');
|
|
651
692
|
}
|
|
@@ -664,7 +705,7 @@ async function checkRateLimits() {
|
|
|
664
705
|
});
|
|
665
706
|
if (rateLimitRes?.error || rateLimitRes?.ok === false) {
|
|
666
707
|
adminforth.alert({
|
|
667
|
-
message: t(`Rate limit exceeded for "${actionType
|
|
708
|
+
message: t(`Rate limit exceeded for "${getActionLabel(actionType)}" action. Please try again later.`),
|
|
668
709
|
variant: 'danger',
|
|
669
710
|
timeout: 'unlimited',
|
|
670
711
|
});
|
|
@@ -672,7 +713,7 @@ async function checkRateLimits() {
|
|
|
672
713
|
}
|
|
673
714
|
} catch (e) {
|
|
674
715
|
adminforth.alert({
|
|
675
|
-
message: t(`Error checking rate limit for "${actionType
|
|
716
|
+
message: t(`Error checking rate limit for "${getActionLabel(actionType)}" action.`),
|
|
676
717
|
variant: 'danger',
|
|
677
718
|
timeout: 'unlimited',
|
|
678
719
|
});
|
|
@@ -684,7 +725,7 @@ async function checkRateLimits() {
|
|
|
684
725
|
return true;
|
|
685
726
|
}
|
|
686
727
|
|
|
687
|
-
async function runActionForRecord(record: RecordState, actionType:
|
|
728
|
+
async function runActionForRecord(record: RecordState, actionType: GenerationAction) {
|
|
688
729
|
if (!checkIfDialogOpen()) {
|
|
689
730
|
return;
|
|
690
731
|
}
|
|
@@ -722,6 +763,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
722
763
|
});
|
|
723
764
|
} catch (e) {
|
|
724
765
|
record.aiStatus[responseFlag] = true;
|
|
766
|
+
registerGenerationFailure(record, actionType, e instanceof Error ? e.message : String(e));
|
|
725
767
|
throw e;
|
|
726
768
|
}
|
|
727
769
|
|
|
@@ -731,11 +773,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
731
773
|
|
|
732
774
|
if (createJobResponse?.error || !createJobResponse?.jobId) {
|
|
733
775
|
record.aiStatus[responseFlag] = true;
|
|
734
|
-
|
|
735
|
-
message: t(`Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`),
|
|
736
|
-
variant: 'danger',
|
|
737
|
-
timeout: 'unlimited',
|
|
738
|
-
});
|
|
776
|
+
registerGenerationFailure(record, actionType, createJobResponse?.error || `Failed to ${getActionLabel(actionType)}. Please, try to re-run the action.`);
|
|
739
777
|
throw new Error(createJobResponse?.error || 'Failed to create job');
|
|
740
778
|
}
|
|
741
779
|
|
|
@@ -745,7 +783,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
745
783
|
async function pollJob(
|
|
746
784
|
record: RecordState,
|
|
747
785
|
jobId: string,
|
|
748
|
-
actionType:
|
|
786
|
+
actionType: GenerationAction,
|
|
749
787
|
responseFlag: keyof RecordState['aiStatus']
|
|
750
788
|
) {
|
|
751
789
|
let isInProgress = true;
|
|
@@ -762,6 +800,7 @@ async function pollJob(
|
|
|
762
800
|
}
|
|
763
801
|
if (jobResponse?.error) {
|
|
764
802
|
record.aiStatus[responseFlag] = true;
|
|
803
|
+
registerGenerationFailure(record, actionType, jobResponse.error);
|
|
765
804
|
throw new Error(jobResponse.error);
|
|
766
805
|
}
|
|
767
806
|
const jobStatus = jobResponse?.job?.status;
|
|
@@ -783,7 +822,7 @@ async function pollJob(
|
|
|
783
822
|
}
|
|
784
823
|
}
|
|
785
824
|
|
|
786
|
-
function applyJobResult(record: RecordState, job: any, actionType:
|
|
825
|
+
function applyJobResult(record: RecordState, job: any, actionType: GenerationAction) {
|
|
787
826
|
if (actionType === 'generate_images') {
|
|
788
827
|
for (const fieldName of props.meta.outputImageFields || []) {
|
|
789
828
|
const resultValue = job?.result?.[fieldName];
|
|
@@ -805,12 +844,8 @@ function applyJobResult(record: RecordState, job: any, actionType: 'analyze' | '
|
|
|
805
844
|
touchRecords();
|
|
806
845
|
}
|
|
807
846
|
|
|
808
|
-
function applyJobFailure(record: RecordState, job: any, actionType:
|
|
809
|
-
|
|
810
|
-
message: t(`Generation action "${actionType.replace('_', ' ')}" failed for record: ${record.id}. Error: ${job?.error || 'Unknown error'}`),
|
|
811
|
-
variant: 'danger',
|
|
812
|
-
timeout: 'unlimited',
|
|
813
|
-
});
|
|
847
|
+
function applyJobFailure(record: RecordState, job: any, actionType: GenerationAction) {
|
|
848
|
+
registerGenerationFailure(record, actionType, job?.error || 'Unknown error');
|
|
814
849
|
if (actionType === 'generate_images') {
|
|
815
850
|
record.imageGenerationFailed = true;
|
|
816
851
|
record.imageGenerationErrorMessage = job?.error || 'Unknown error';
|
|
@@ -826,7 +861,7 @@ function applyJobFailure(record: RecordState, job: any, actionType: 'analyze' |
|
|
|
826
861
|
touchRecords();
|
|
827
862
|
}
|
|
828
863
|
|
|
829
|
-
async function waitForRefresh(actionType:
|
|
864
|
+
async function waitForRefresh(actionType: GenerationAction) {
|
|
830
865
|
if (actionType === 'generate_images') {
|
|
831
866
|
await new Promise(resolve => setTimeout(resolve, props.meta.refreshRates?.generateImages));
|
|
832
867
|
} else if (actionType === 'analyze') {
|
|
@@ -1532,4 +1567,4 @@ async function saveCurrentGenerated() {
|
|
|
1532
1567
|
props.updateList();
|
|
1533
1568
|
}
|
|
1534
1569
|
|
|
1535
|
-
</script>
|
|
1570
|
+
</script>
|
|
@@ -197,6 +197,7 @@ const props = defineProps<{
|
|
|
197
197
|
}>();
|
|
198
198
|
|
|
199
199
|
type RecordStatus = 'pending' | 'processing' | 'completed' | 'failed';
|
|
200
|
+
type GenerationAction = 'analyze' | 'analyze_no_images' | 'generate_images';
|
|
200
201
|
|
|
201
202
|
type RecordState = {
|
|
202
203
|
id: string | number;
|
|
@@ -256,6 +257,11 @@ const startedRecordCount = ref(0);
|
|
|
256
257
|
const isCheckingRateLimits = ref(false);
|
|
257
258
|
let startGate = Promise.resolve();
|
|
258
259
|
const tableRef = ref<any>(null);
|
|
260
|
+
const generationFailureGroups = new Map<string, {
|
|
261
|
+
actionType: GenerationAction;
|
|
262
|
+
error: string;
|
|
263
|
+
recordIds: Set<string>;
|
|
264
|
+
}>();
|
|
259
265
|
const processedCount = computed(() => {
|
|
260
266
|
recordsVersion.value;
|
|
261
267
|
return Array.from(recordsById.values()).filter(record => record.status === 'completed' || record.status === 'failed').length;
|
|
@@ -398,12 +404,14 @@ async function runAiActions() {
|
|
|
398
404
|
isActiveGeneration.value = true;
|
|
399
405
|
completedRecordIds.value = new Set();
|
|
400
406
|
startedRecordCount.value = 0;
|
|
407
|
+
generationFailureGroups.clear();
|
|
401
408
|
await nextTick();
|
|
402
409
|
tableRef.value?.refresh();
|
|
403
410
|
const limit = pLimit(props.meta.concurrencyLimit || 10);
|
|
404
411
|
const tasks = recordIds.value
|
|
405
412
|
.map(id => limit(() => processOneRecord(String(id))));
|
|
406
413
|
await Promise.all(tasks);
|
|
414
|
+
showGenerationFailureSummary();
|
|
407
415
|
isActiveGeneration.value = false;
|
|
408
416
|
}
|
|
409
417
|
|
|
@@ -431,6 +439,39 @@ function resetGlobalState() {
|
|
|
431
439
|
recordIds.value = [];
|
|
432
440
|
recordsById.clear();
|
|
433
441
|
uncheckedRecordIds.clear();
|
|
442
|
+
generationFailureGroups.clear();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function getActionLabel(actionType: GenerationAction) {
|
|
446
|
+
return actionType.replace('_', ' ');
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function registerGenerationFailure(record: RecordState, actionType: GenerationAction, error: string) {
|
|
450
|
+
const key = `${actionType}:${error}`;
|
|
451
|
+
let group = generationFailureGroups.get(key);
|
|
452
|
+
if (!group) {
|
|
453
|
+
group = {
|
|
454
|
+
actionType,
|
|
455
|
+
error,
|
|
456
|
+
recordIds: new Set(),
|
|
457
|
+
};
|
|
458
|
+
generationFailureGroups.set(key, group);
|
|
459
|
+
}
|
|
460
|
+
group.recordIds.add(String(record.id));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function showGenerationFailureSummary() {
|
|
464
|
+
for (const group of generationFailureGroups.values()) {
|
|
465
|
+
const failedCount = group.recordIds.size;
|
|
466
|
+
const firstRecordId = Array.from(group.recordIds)[0];
|
|
467
|
+
adminforth.alert({
|
|
468
|
+
message: t(
|
|
469
|
+
`Generation action "${getActionLabel(group.actionType)}" failed for ${failedCount} record(s). First failed record: ${firstRecordId}. Error: ${group.error}`,
|
|
470
|
+
),
|
|
471
|
+
variant: 'danger',
|
|
472
|
+
timeout: 'unlimited',
|
|
473
|
+
});
|
|
474
|
+
}
|
|
434
475
|
}
|
|
435
476
|
|
|
436
477
|
function getOrCreateRecord(recordId: string | number): RecordState {
|
|
@@ -622,7 +663,7 @@ async function processOneRecord(recordId: string) {
|
|
|
622
663
|
}
|
|
623
664
|
}
|
|
624
665
|
|
|
625
|
-
const actions:
|
|
666
|
+
const actions: GenerationAction[] = [];
|
|
626
667
|
if (props.meta.isImageGeneration) {
|
|
627
668
|
actions.push('generate_images');
|
|
628
669
|
}
|
|
@@ -645,7 +686,7 @@ async function processOneRecord(recordId: string) {
|
|
|
645
686
|
|
|
646
687
|
async function checkRateLimits() {
|
|
647
688
|
isCheckingRateLimits.value = true;
|
|
648
|
-
const actionsToCheck:
|
|
689
|
+
const actionsToCheck: GenerationAction[] = [];
|
|
649
690
|
if (props.meta.isImageGeneration) {
|
|
650
691
|
actionsToCheck.push('generate_images');
|
|
651
692
|
}
|
|
@@ -664,7 +705,7 @@ async function checkRateLimits() {
|
|
|
664
705
|
});
|
|
665
706
|
if (rateLimitRes?.error || rateLimitRes?.ok === false) {
|
|
666
707
|
adminforth.alert({
|
|
667
|
-
message: t(`Rate limit exceeded for "${actionType
|
|
708
|
+
message: t(`Rate limit exceeded for "${getActionLabel(actionType)}" action. Please try again later.`),
|
|
668
709
|
variant: 'danger',
|
|
669
710
|
timeout: 'unlimited',
|
|
670
711
|
});
|
|
@@ -672,7 +713,7 @@ async function checkRateLimits() {
|
|
|
672
713
|
}
|
|
673
714
|
} catch (e) {
|
|
674
715
|
adminforth.alert({
|
|
675
|
-
message: t(`Error checking rate limit for "${actionType
|
|
716
|
+
message: t(`Error checking rate limit for "${getActionLabel(actionType)}" action.`),
|
|
676
717
|
variant: 'danger',
|
|
677
718
|
timeout: 'unlimited',
|
|
678
719
|
});
|
|
@@ -684,7 +725,7 @@ async function checkRateLimits() {
|
|
|
684
725
|
return true;
|
|
685
726
|
}
|
|
686
727
|
|
|
687
|
-
async function runActionForRecord(record: RecordState, actionType:
|
|
728
|
+
async function runActionForRecord(record: RecordState, actionType: GenerationAction) {
|
|
688
729
|
if (!checkIfDialogOpen()) {
|
|
689
730
|
return;
|
|
690
731
|
}
|
|
@@ -722,6 +763,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
722
763
|
});
|
|
723
764
|
} catch (e) {
|
|
724
765
|
record.aiStatus[responseFlag] = true;
|
|
766
|
+
registerGenerationFailure(record, actionType, e instanceof Error ? e.message : String(e));
|
|
725
767
|
throw e;
|
|
726
768
|
}
|
|
727
769
|
|
|
@@ -731,11 +773,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
731
773
|
|
|
732
774
|
if (createJobResponse?.error || !createJobResponse?.jobId) {
|
|
733
775
|
record.aiStatus[responseFlag] = true;
|
|
734
|
-
|
|
735
|
-
message: t(`Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`),
|
|
736
|
-
variant: 'danger',
|
|
737
|
-
timeout: 'unlimited',
|
|
738
|
-
});
|
|
776
|
+
registerGenerationFailure(record, actionType, createJobResponse?.error || `Failed to ${getActionLabel(actionType)}. Please, try to re-run the action.`);
|
|
739
777
|
throw new Error(createJobResponse?.error || 'Failed to create job');
|
|
740
778
|
}
|
|
741
779
|
|
|
@@ -745,7 +783,7 @@ async function runActionForRecord(record: RecordState, actionType: 'analyze' | '
|
|
|
745
783
|
async function pollJob(
|
|
746
784
|
record: RecordState,
|
|
747
785
|
jobId: string,
|
|
748
|
-
actionType:
|
|
786
|
+
actionType: GenerationAction,
|
|
749
787
|
responseFlag: keyof RecordState['aiStatus']
|
|
750
788
|
) {
|
|
751
789
|
let isInProgress = true;
|
|
@@ -762,6 +800,7 @@ async function pollJob(
|
|
|
762
800
|
}
|
|
763
801
|
if (jobResponse?.error) {
|
|
764
802
|
record.aiStatus[responseFlag] = true;
|
|
803
|
+
registerGenerationFailure(record, actionType, jobResponse.error);
|
|
765
804
|
throw new Error(jobResponse.error);
|
|
766
805
|
}
|
|
767
806
|
const jobStatus = jobResponse?.job?.status;
|
|
@@ -783,7 +822,7 @@ async function pollJob(
|
|
|
783
822
|
}
|
|
784
823
|
}
|
|
785
824
|
|
|
786
|
-
function applyJobResult(record: RecordState, job: any, actionType:
|
|
825
|
+
function applyJobResult(record: RecordState, job: any, actionType: GenerationAction) {
|
|
787
826
|
if (actionType === 'generate_images') {
|
|
788
827
|
for (const fieldName of props.meta.outputImageFields || []) {
|
|
789
828
|
const resultValue = job?.result?.[fieldName];
|
|
@@ -805,12 +844,8 @@ function applyJobResult(record: RecordState, job: any, actionType: 'analyze' | '
|
|
|
805
844
|
touchRecords();
|
|
806
845
|
}
|
|
807
846
|
|
|
808
|
-
function applyJobFailure(record: RecordState, job: any, actionType:
|
|
809
|
-
|
|
810
|
-
message: t(`Generation action "${actionType.replace('_', ' ')}" failed for record: ${record.id}. Error: ${job?.error || 'Unknown error'}`),
|
|
811
|
-
variant: 'danger',
|
|
812
|
-
timeout: 'unlimited',
|
|
813
|
-
});
|
|
847
|
+
function applyJobFailure(record: RecordState, job: any, actionType: GenerationAction) {
|
|
848
|
+
registerGenerationFailure(record, actionType, job?.error || 'Unknown error');
|
|
814
849
|
if (actionType === 'generate_images') {
|
|
815
850
|
record.imageGenerationFailed = true;
|
|
816
851
|
record.imageGenerationErrorMessage = job?.error || 'Unknown error';
|
|
@@ -826,7 +861,7 @@ function applyJobFailure(record: RecordState, job: any, actionType: 'analyze' |
|
|
|
826
861
|
touchRecords();
|
|
827
862
|
}
|
|
828
863
|
|
|
829
|
-
async function waitForRefresh(actionType:
|
|
864
|
+
async function waitForRefresh(actionType: GenerationAction) {
|
|
830
865
|
if (actionType === 'generate_images') {
|
|
831
866
|
await new Promise(resolve => setTimeout(resolve, props.meta.refreshRates?.generateImages));
|
|
832
867
|
} else if (actionType === 'analyze') {
|
|
@@ -1532,4 +1567,4 @@ async function saveCurrentGenerated() {
|
|
|
1532
1567
|
props.updateList();
|
|
1533
1568
|
}
|
|
1534
1569
|
|
|
1535
|
-
</script>
|
|
1570
|
+
</script>
|