@adminforth/bulk-ai-flow 1.26.4 → 1.26.6
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 +38 -18
- package/dist/custom/VisionAction.vue +38 -18
- package/dist/index.d.ts +1 -0
- package/dist/index.js +21 -2
- package/index.ts +21 -3
- package/package.json +3 -3
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 129,
|
|
17
|
+
sent 130,637 bytes received 191 bytes 261,656.00 bytes/sec
|
|
18
|
+
total size is 129,924 speedup is 0.99
|
package/custom/VisionAction.vue
CHANGED
|
@@ -482,7 +482,7 @@ const generationModeButtons = computed(() => {
|
|
|
482
482
|
return arrayToReturn;
|
|
483
483
|
});
|
|
484
484
|
|
|
485
|
-
async function regenerateRecord({ recordId }) {
|
|
485
|
+
async function regenerateRecord({ recordId }: { recordId: string }) {
|
|
486
486
|
|
|
487
487
|
const promises = [];
|
|
488
488
|
|
|
@@ -610,7 +610,8 @@ async function getListOfIds() {
|
|
|
610
610
|
|
|
611
611
|
|
|
612
612
|
async function runAiActions() {
|
|
613
|
-
|
|
613
|
+
const { ok, sessionIds } = await checkRateLimits();
|
|
614
|
+
if (!ok || !sessionIds) {
|
|
614
615
|
confirmDialog.value.close();
|
|
615
616
|
return;
|
|
616
617
|
}
|
|
@@ -625,7 +626,7 @@ async function runAiActions() {
|
|
|
625
626
|
tableRef.value?.refresh();
|
|
626
627
|
const limit = pLimit(props.meta.concurrencyLimit || 10);
|
|
627
628
|
const tasks = recordIds.value
|
|
628
|
-
.map(id => limit(() => processOneRecord(String(id))));
|
|
629
|
+
.map(id => limit(() => processOneRecord(String(id), sessionIds)));
|
|
629
630
|
await Promise.all(tasks);
|
|
630
631
|
showGenerationFailureSummary();
|
|
631
632
|
isActiveGeneration.value = false;
|
|
@@ -825,7 +826,7 @@ function createEmptyRecord(recordId: string | number): RecordState {
|
|
|
825
826
|
};
|
|
826
827
|
}
|
|
827
828
|
|
|
828
|
-
async function processOneRecord(recordId: string) {
|
|
829
|
+
async function processOneRecord(recordId: string, sessionIds: string[]) {
|
|
829
830
|
if (!checkIfDialogOpen()) {
|
|
830
831
|
return;
|
|
831
832
|
}
|
|
@@ -898,7 +899,7 @@ async function processOneRecord(recordId: string) {
|
|
|
898
899
|
actions.push('analyze_no_images');
|
|
899
900
|
}
|
|
900
901
|
|
|
901
|
-
const results = await Promise.allSettled(actions.map(actionType => runActionForRecord(record, actionType)));
|
|
902
|
+
const results = await Promise.allSettled(actions.map(actionType => runActionForRecord(record, actionType, sessionIds)));
|
|
902
903
|
if (!checkIfDialogOpen()) {
|
|
903
904
|
return;
|
|
904
905
|
}
|
|
@@ -908,17 +909,22 @@ async function processOneRecord(recordId: string) {
|
|
|
908
909
|
touchRecords();
|
|
909
910
|
}
|
|
910
911
|
|
|
911
|
-
async function checkRateLimits() {
|
|
912
|
+
async function checkRateLimits(actions?: GenerationAction[]): Promise<{ ok: boolean; sessionIds?: string[] }> {
|
|
913
|
+
let sessionIds: string[] = [];
|
|
912
914
|
isCheckingRateLimits.value = true;
|
|
913
915
|
const actionsToCheck: GenerationAction[] = [];
|
|
914
|
-
if (
|
|
915
|
-
actionsToCheck.push(
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
916
|
+
if (actions) {
|
|
917
|
+
actionsToCheck.push(...actions);
|
|
918
|
+
} else {
|
|
919
|
+
if (props.meta.isImageGeneration) {
|
|
920
|
+
actionsToCheck.push('generate_images');
|
|
921
|
+
}
|
|
922
|
+
if (props.meta.isFieldsForAnalizeFromImages) {
|
|
923
|
+
actionsToCheck.push('analyze');
|
|
924
|
+
}
|
|
925
|
+
if (props.meta.isFieldsForAnalizePlain) {
|
|
926
|
+
actionsToCheck.push('analyze_no_images');
|
|
927
|
+
}
|
|
922
928
|
}
|
|
923
929
|
for (const actionType of actionsToCheck) {
|
|
924
930
|
try {
|
|
@@ -933,8 +939,9 @@ async function checkRateLimits() {
|
|
|
933
939
|
variant: 'danger',
|
|
934
940
|
timeout: 'unlimited',
|
|
935
941
|
});
|
|
936
|
-
return false;
|
|
942
|
+
return { ok: false };
|
|
937
943
|
}
|
|
944
|
+
sessionIds.push(rateLimitRes.sessionId);
|
|
938
945
|
} catch (e) {
|
|
939
946
|
adminforth.alert({
|
|
940
947
|
message: t(`Error checking rate limit for "${getActionLabel(actionType)}" action.`),
|
|
@@ -942,14 +949,14 @@ async function checkRateLimits() {
|
|
|
942
949
|
timeout: 'unlimited',
|
|
943
950
|
});
|
|
944
951
|
isCheckingRateLimits.value = false;
|
|
945
|
-
return false;
|
|
952
|
+
return { ok: false };
|
|
946
953
|
}
|
|
947
954
|
}
|
|
948
955
|
isCheckingRateLimits.value = false;
|
|
949
|
-
return true;
|
|
956
|
+
return { ok: true, sessionIds };
|
|
950
957
|
}
|
|
951
958
|
|
|
952
|
-
async function runActionForRecord(record: RecordState, actionType: GenerationAction, forceFilterFilledFields?: boolean) {
|
|
959
|
+
async function runActionForRecord(record: RecordState, actionType: GenerationAction, sessionIds: string[], forceFilterFilledFields?: boolean) {
|
|
953
960
|
if (!checkIfDialogOpen()) {
|
|
954
961
|
return;
|
|
955
962
|
}
|
|
@@ -982,6 +989,7 @@ async function runActionForRecord(record: RecordState, actionType: GenerationAct
|
|
|
982
989
|
recordId: record.id,
|
|
983
990
|
...(customPrompt !== undefined ? { customPrompt: JSON.stringify(customPrompt) } : {}),
|
|
984
991
|
filterFilledFields: forceFilterFilledFields !== undefined ? forceFilterFilledFields: !overwriteExistingValues.value,
|
|
992
|
+
sessionIds
|
|
985
993
|
},
|
|
986
994
|
silentError: true,
|
|
987
995
|
});
|
|
@@ -1438,6 +1446,10 @@ async function uploadImage(imgBlob, id, fieldName) {
|
|
|
1438
1446
|
}
|
|
1439
1447
|
|
|
1440
1448
|
async function regenerateImages({ recordId }: { recordId: any }) {
|
|
1449
|
+
const {ok, sessionIds} = await checkRateLimits(['generate_images']);
|
|
1450
|
+
if (!ok || !sessionIds) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1441
1453
|
if (coreStore.isInternetError) {
|
|
1442
1454
|
adminforth.alert({
|
|
1443
1455
|
message: t('Cannot regenerate images while internet connection is lost. Please check your connection and try again.'),
|
|
@@ -1458,6 +1470,7 @@ async function regenerateImages({ recordId }: { recordId: any }) {
|
|
|
1458
1470
|
await runActionForRecord(
|
|
1459
1471
|
record,
|
|
1460
1472
|
'generate_images',
|
|
1473
|
+
sessionIds,
|
|
1461
1474
|
false
|
|
1462
1475
|
);
|
|
1463
1476
|
|
|
@@ -1616,6 +1629,12 @@ async function regenerateCell(recordInfo: any) {
|
|
|
1616
1629
|
});
|
|
1617
1630
|
return;
|
|
1618
1631
|
}
|
|
1632
|
+
|
|
1633
|
+
const {ok, sessionIds} = await checkRateLimits(['analyze_no_images', 'analyze']);
|
|
1634
|
+
if (!ok || !sessionIds) {
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1619
1638
|
const record = recordsById.get(String(recordInfo.recordId));
|
|
1620
1639
|
if (!record) {
|
|
1621
1640
|
return;
|
|
@@ -1658,6 +1677,7 @@ async function regenerateCell(recordInfo: any) {
|
|
|
1658
1677
|
action: actionType,
|
|
1659
1678
|
actionType: "regenerate_cell",
|
|
1660
1679
|
prompt: generationPromptsForField[recordInfo.fieldName] || null,
|
|
1680
|
+
sessionIds
|
|
1661
1681
|
},
|
|
1662
1682
|
silentError: true,
|
|
1663
1683
|
});
|
|
@@ -482,7 +482,7 @@ const generationModeButtons = computed(() => {
|
|
|
482
482
|
return arrayToReturn;
|
|
483
483
|
});
|
|
484
484
|
|
|
485
|
-
async function regenerateRecord({ recordId }) {
|
|
485
|
+
async function regenerateRecord({ recordId }: { recordId: string }) {
|
|
486
486
|
|
|
487
487
|
const promises = [];
|
|
488
488
|
|
|
@@ -610,7 +610,8 @@ async function getListOfIds() {
|
|
|
610
610
|
|
|
611
611
|
|
|
612
612
|
async function runAiActions() {
|
|
613
|
-
|
|
613
|
+
const { ok, sessionIds } = await checkRateLimits();
|
|
614
|
+
if (!ok || !sessionIds) {
|
|
614
615
|
confirmDialog.value.close();
|
|
615
616
|
return;
|
|
616
617
|
}
|
|
@@ -625,7 +626,7 @@ async function runAiActions() {
|
|
|
625
626
|
tableRef.value?.refresh();
|
|
626
627
|
const limit = pLimit(props.meta.concurrencyLimit || 10);
|
|
627
628
|
const tasks = recordIds.value
|
|
628
|
-
.map(id => limit(() => processOneRecord(String(id))));
|
|
629
|
+
.map(id => limit(() => processOneRecord(String(id), sessionIds)));
|
|
629
630
|
await Promise.all(tasks);
|
|
630
631
|
showGenerationFailureSummary();
|
|
631
632
|
isActiveGeneration.value = false;
|
|
@@ -825,7 +826,7 @@ function createEmptyRecord(recordId: string | number): RecordState {
|
|
|
825
826
|
};
|
|
826
827
|
}
|
|
827
828
|
|
|
828
|
-
async function processOneRecord(recordId: string) {
|
|
829
|
+
async function processOneRecord(recordId: string, sessionIds: string[]) {
|
|
829
830
|
if (!checkIfDialogOpen()) {
|
|
830
831
|
return;
|
|
831
832
|
}
|
|
@@ -898,7 +899,7 @@ async function processOneRecord(recordId: string) {
|
|
|
898
899
|
actions.push('analyze_no_images');
|
|
899
900
|
}
|
|
900
901
|
|
|
901
|
-
const results = await Promise.allSettled(actions.map(actionType => runActionForRecord(record, actionType)));
|
|
902
|
+
const results = await Promise.allSettled(actions.map(actionType => runActionForRecord(record, actionType, sessionIds)));
|
|
902
903
|
if (!checkIfDialogOpen()) {
|
|
903
904
|
return;
|
|
904
905
|
}
|
|
@@ -908,17 +909,22 @@ async function processOneRecord(recordId: string) {
|
|
|
908
909
|
touchRecords();
|
|
909
910
|
}
|
|
910
911
|
|
|
911
|
-
async function checkRateLimits() {
|
|
912
|
+
async function checkRateLimits(actions?: GenerationAction[]): Promise<{ ok: boolean; sessionIds?: string[] }> {
|
|
913
|
+
let sessionIds: string[] = [];
|
|
912
914
|
isCheckingRateLimits.value = true;
|
|
913
915
|
const actionsToCheck: GenerationAction[] = [];
|
|
914
|
-
if (
|
|
915
|
-
actionsToCheck.push(
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
916
|
+
if (actions) {
|
|
917
|
+
actionsToCheck.push(...actions);
|
|
918
|
+
} else {
|
|
919
|
+
if (props.meta.isImageGeneration) {
|
|
920
|
+
actionsToCheck.push('generate_images');
|
|
921
|
+
}
|
|
922
|
+
if (props.meta.isFieldsForAnalizeFromImages) {
|
|
923
|
+
actionsToCheck.push('analyze');
|
|
924
|
+
}
|
|
925
|
+
if (props.meta.isFieldsForAnalizePlain) {
|
|
926
|
+
actionsToCheck.push('analyze_no_images');
|
|
927
|
+
}
|
|
922
928
|
}
|
|
923
929
|
for (const actionType of actionsToCheck) {
|
|
924
930
|
try {
|
|
@@ -933,8 +939,9 @@ async function checkRateLimits() {
|
|
|
933
939
|
variant: 'danger',
|
|
934
940
|
timeout: 'unlimited',
|
|
935
941
|
});
|
|
936
|
-
return false;
|
|
942
|
+
return { ok: false };
|
|
937
943
|
}
|
|
944
|
+
sessionIds.push(rateLimitRes.sessionId);
|
|
938
945
|
} catch (e) {
|
|
939
946
|
adminforth.alert({
|
|
940
947
|
message: t(`Error checking rate limit for "${getActionLabel(actionType)}" action.`),
|
|
@@ -942,14 +949,14 @@ async function checkRateLimits() {
|
|
|
942
949
|
timeout: 'unlimited',
|
|
943
950
|
});
|
|
944
951
|
isCheckingRateLimits.value = false;
|
|
945
|
-
return false;
|
|
952
|
+
return { ok: false };
|
|
946
953
|
}
|
|
947
954
|
}
|
|
948
955
|
isCheckingRateLimits.value = false;
|
|
949
|
-
return true;
|
|
956
|
+
return { ok: true, sessionIds };
|
|
950
957
|
}
|
|
951
958
|
|
|
952
|
-
async function runActionForRecord(record: RecordState, actionType: GenerationAction, forceFilterFilledFields?: boolean) {
|
|
959
|
+
async function runActionForRecord(record: RecordState, actionType: GenerationAction, sessionIds: string[], forceFilterFilledFields?: boolean) {
|
|
953
960
|
if (!checkIfDialogOpen()) {
|
|
954
961
|
return;
|
|
955
962
|
}
|
|
@@ -982,6 +989,7 @@ async function runActionForRecord(record: RecordState, actionType: GenerationAct
|
|
|
982
989
|
recordId: record.id,
|
|
983
990
|
...(customPrompt !== undefined ? { customPrompt: JSON.stringify(customPrompt) } : {}),
|
|
984
991
|
filterFilledFields: forceFilterFilledFields !== undefined ? forceFilterFilledFields: !overwriteExistingValues.value,
|
|
992
|
+
sessionIds
|
|
985
993
|
},
|
|
986
994
|
silentError: true,
|
|
987
995
|
});
|
|
@@ -1438,6 +1446,10 @@ async function uploadImage(imgBlob, id, fieldName) {
|
|
|
1438
1446
|
}
|
|
1439
1447
|
|
|
1440
1448
|
async function regenerateImages({ recordId }: { recordId: any }) {
|
|
1449
|
+
const {ok, sessionIds} = await checkRateLimits(['generate_images']);
|
|
1450
|
+
if (!ok || !sessionIds) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1441
1453
|
if (coreStore.isInternetError) {
|
|
1442
1454
|
adminforth.alert({
|
|
1443
1455
|
message: t('Cannot regenerate images while internet connection is lost. Please check your connection and try again.'),
|
|
@@ -1458,6 +1470,7 @@ async function regenerateImages({ recordId }: { recordId: any }) {
|
|
|
1458
1470
|
await runActionForRecord(
|
|
1459
1471
|
record,
|
|
1460
1472
|
'generate_images',
|
|
1473
|
+
sessionIds,
|
|
1461
1474
|
false
|
|
1462
1475
|
);
|
|
1463
1476
|
|
|
@@ -1616,6 +1629,12 @@ async function regenerateCell(recordInfo: any) {
|
|
|
1616
1629
|
});
|
|
1617
1630
|
return;
|
|
1618
1631
|
}
|
|
1632
|
+
|
|
1633
|
+
const {ok, sessionIds} = await checkRateLimits(['analyze_no_images', 'analyze']);
|
|
1634
|
+
if (!ok || !sessionIds) {
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1619
1638
|
const record = recordsById.get(String(recordInfo.recordId));
|
|
1620
1639
|
if (!record) {
|
|
1621
1640
|
return;
|
|
@@ -1658,6 +1677,7 @@ async function regenerateCell(recordInfo: any) {
|
|
|
1658
1677
|
action: actionType,
|
|
1659
1678
|
actionType: "regenerate_cell",
|
|
1660
1679
|
prompt: generationPromptsForField[recordInfo.fieldName] || null,
|
|
1680
|
+
sessionIds
|
|
1661
1681
|
},
|
|
1662
1682
|
silentError: true,
|
|
1663
1683
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
8
8
|
totalCalls: number;
|
|
9
9
|
totalDuration: number;
|
|
10
10
|
rateLimiters: Record<string, RateLimiter>;
|
|
11
|
+
sessionIds: Set<string>;
|
|
11
12
|
constructor(options: PluginOptions);
|
|
12
13
|
private compileTemplates;
|
|
13
14
|
private compileOutputFieldsTemplates;
|
package/dist/index.js
CHANGED
|
@@ -18,10 +18,13 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
18
18
|
constructor(options) {
|
|
19
19
|
super(options, import.meta.url);
|
|
20
20
|
this.rateLimiters = {};
|
|
21
|
+
this.sessionIds = new Set();
|
|
21
22
|
this.options = options;
|
|
22
23
|
// for calculating average time
|
|
23
24
|
this.totalCalls = 0;
|
|
24
25
|
this.totalDuration = 0;
|
|
26
|
+
// for rate limiting
|
|
27
|
+
this.sessionIds = new Set();
|
|
25
28
|
}
|
|
26
29
|
// Compile Handlebars templates in outputFields using record fields as context
|
|
27
30
|
compileTemplates(source, record, valueSelector) {
|
|
@@ -945,7 +948,20 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
945
948
|
method: 'POST',
|
|
946
949
|
path: `/plugin/${this.pluginInstanceId}/create-job`,
|
|
947
950
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
|
|
948
|
-
const { actionType, recordId, customPrompt, filterFilledFields } = body;
|
|
951
|
+
const { actionType, recordId, customPrompt, filterFilledFields, sessionIds } = body;
|
|
952
|
+
if (this.options.rateLimits) {
|
|
953
|
+
if (sessionIds && sessionIds.length > 0) {
|
|
954
|
+
for (const sessionId of sessionIds) {
|
|
955
|
+
if (!this.sessionIds.has(sessionId)) {
|
|
956
|
+
return { ok: false, error: "Invalid session id" };
|
|
957
|
+
}
|
|
958
|
+
this.sessionIds.delete(sessionId);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
else {
|
|
962
|
+
return { ok: false, error: "Missing session ids" };
|
|
963
|
+
}
|
|
964
|
+
}
|
|
949
965
|
const jobId = randomUUID();
|
|
950
966
|
jobs.set(jobId, { status: "in_progress" });
|
|
951
967
|
if (!actionType) {
|
|
@@ -1026,6 +1042,8 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
1026
1042
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
|
|
1027
1043
|
var _b, _c, _d;
|
|
1028
1044
|
const actionType = body.actionType;
|
|
1045
|
+
const sessionId = randomUUID();
|
|
1046
|
+
this.sessionIds.add(sessionId);
|
|
1029
1047
|
if (actionType === 'analyze' && ((_b = this.options.rateLimits) === null || _b === void 0 ? void 0 : _b.fillFieldsFromImages)) {
|
|
1030
1048
|
if (yield this.checkRateLimit("fillFieldsFromImages", this.options.rateLimits.fillFieldsFromImages, headers)) {
|
|
1031
1049
|
return { ok: false, error: "Rate limit exceeded for image analyze" };
|
|
@@ -1041,7 +1059,8 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
1041
1059
|
return { ok: false, error: "Rate limit exceeded for image generation" };
|
|
1042
1060
|
}
|
|
1043
1061
|
}
|
|
1044
|
-
|
|
1062
|
+
setTimeout(() => this.sessionIds.delete(sessionId), 300000);
|
|
1063
|
+
return { ok: true, sessionId };
|
|
1045
1064
|
})
|
|
1046
1065
|
});
|
|
1047
1066
|
server.endpoint({
|
package/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
13
13
|
totalCalls: number;
|
|
14
14
|
totalDuration: number;
|
|
15
15
|
rateLimiters: Record<string, RateLimiter> = {};
|
|
16
|
+
sessionIds: Set<string> = new Set();
|
|
16
17
|
|
|
17
18
|
constructor(options: PluginOptions) {
|
|
18
19
|
super(options, import.meta.url);
|
|
@@ -21,6 +22,9 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
21
22
|
// for calculating average time
|
|
22
23
|
this.totalCalls = 0;
|
|
23
24
|
this.totalDuration = 0;
|
|
25
|
+
|
|
26
|
+
// for rate limiting
|
|
27
|
+
this.sessionIds = new Set();
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
// Compile Handlebars templates in outputFields using record fields as context
|
|
@@ -970,7 +974,19 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
970
974
|
method: 'POST',
|
|
971
975
|
path: `/plugin/${this.pluginInstanceId}/create-job`,
|
|
972
976
|
handler: async ({ body, adminUser, headers }) => {
|
|
973
|
-
const { actionType, recordId, customPrompt, filterFilledFields } = body;
|
|
977
|
+
const { actionType, recordId, customPrompt, filterFilledFields, sessionIds } = body;
|
|
978
|
+
if (this.options.rateLimits) {
|
|
979
|
+
if (sessionIds && sessionIds.length > 0) {
|
|
980
|
+
for (const sessionId of sessionIds) {
|
|
981
|
+
if (!this.sessionIds.has(sessionId)) {
|
|
982
|
+
return { ok: false, error: "Invalid session id" };
|
|
983
|
+
}
|
|
984
|
+
this.sessionIds.delete(sessionId);
|
|
985
|
+
}
|
|
986
|
+
} else {
|
|
987
|
+
return { ok: false, error: "Missing session ids" };
|
|
988
|
+
}
|
|
989
|
+
}
|
|
974
990
|
const jobId = randomUUID();
|
|
975
991
|
jobs.set(jobId, { status: "in_progress" });
|
|
976
992
|
if (!actionType) {
|
|
@@ -1056,6 +1072,8 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
1056
1072
|
path: `/plugin/${this.pluginInstanceId}/update-rate-limits`,
|
|
1057
1073
|
handler: async ({ body, adminUser, headers }) => {
|
|
1058
1074
|
const actionType = body.actionType;
|
|
1075
|
+
const sessionId = randomUUID();
|
|
1076
|
+
this.sessionIds.add(sessionId);
|
|
1059
1077
|
if (actionType === 'analyze' && this.options.rateLimits?.fillFieldsFromImages) {
|
|
1060
1078
|
if (await this.checkRateLimit("fillFieldsFromImages" ,this.options.rateLimits.fillFieldsFromImages, headers)) {
|
|
1061
1079
|
return {ok: false, error: "Rate limit exceeded for image analyze" };
|
|
@@ -1071,8 +1089,8 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
|
|
|
1071
1089
|
return {ok: false, error: "Rate limit exceeded for image generation" };
|
|
1072
1090
|
}
|
|
1073
1091
|
}
|
|
1074
|
-
|
|
1075
|
-
return { ok: true };
|
|
1092
|
+
setTimeout(() => this.sessionIds.delete(sessionId), 300_000);
|
|
1093
|
+
return { ok: true, sessionId };
|
|
1076
1094
|
}
|
|
1077
1095
|
});
|
|
1078
1096
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/bulk-ai-flow",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.6",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"description": "Bulk AI workflow plugin for AdminForth for batch field generation and image processing",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "latest",
|
|
28
|
-
"adminforth": "^3.1.
|
|
28
|
+
"adminforth": "^3.1.0",
|
|
29
29
|
"semantic-release": "^24.2.1",
|
|
30
30
|
"semantic-release-slack-bot": "^4.0.2",
|
|
31
31
|
"typescript": "^5.7.3"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"handlebars": "^4.7.8"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"adminforth": "^3.1.
|
|
38
|
+
"adminforth": "^3.1.0"
|
|
39
39
|
},
|
|
40
40
|
"release": {
|
|
41
41
|
"plugins": [
|