plugin-ai-api 1.0.23 → 1.0.25
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/dist/client/757.56952e321dc399b7.js +10 -0
- package/dist/client/902.e74518750f1e4201.js +10 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/757.db678ca1aa6c422c.js +10 -0
- package/dist/client-v2/902.c7c00a565085438a.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/externalVersion.js +8 -8
- package/dist/locale/en-US.json +4 -0
- package/dist/locale/vi-VN.json +4 -0
- package/dist/locale/zh-CN.json +4 -0
- package/dist/server/billing.js +6 -1
- package/dist/server/collections/ai-api-config.js +6 -0
- package/dist/server/collections/ai-api-usage-records.js +1 -0
- package/dist/server/collections/ai-api-user-quota-policies.js +2 -1
- package/dist/server/migrations/20260813000000-add-prompt-cache-tokens.js +69 -0
- package/dist/server/plugin.js +10 -0
- package/dist/server/resource/ai-api-config.js +5 -0
- package/dist/server/resource/ai-api-usage-monitor.js +3 -1
- package/dist/server/routes/chat-completions.js +110 -19
- package/dist/server/routes/completions.js +59 -24
- package/dist/server/services/file-processor.js +262 -0
- package/dist/server/usage.js +33 -3
- package/dist/server/utils/direct-llm-context.js +319 -0
- package/dist/server/utils/openai-format.js +21 -2
- package/dist/server/validation.js +3 -0
- package/dist/swagger.js +42 -3
- package/package.json +1 -1
- package/src/client-v2/pages/UsagePage.tsx +9 -0
- package/src/client-v2/pages/UserQuotasPage.tsx +18 -0
- package/src/locale/en-US.json +4 -0
- package/src/locale/vi-VN.json +4 -0
- package/src/locale/zh-CN.json +4 -0
- package/src/server/__tests__/direct-llm-context.test.ts +206 -0
- package/src/server/__tests__/openai-format.test.ts +12 -2
- package/src/server/__tests__/request-body.test.ts +45 -2
- package/src/server/__tests__/usage-route.test.ts +173 -9
- package/src/server/__tests__/usage.test.ts +19 -0
- package/src/server/__tests__/validation.test.ts +36 -0
- package/src/server/billing.ts +6 -1
- package/src/server/collections/ai-api-config.ts +8 -0
- package/src/server/collections/ai-api-role-permissions.ts +41 -41
- package/src/server/collections/ai-api-usage-records.ts +1 -0
- package/src/server/collections/ai-api-user-quota-policies.ts +1 -0
- package/src/server/index.ts +10 -10
- package/src/server/middleware/rate-limit.ts +70 -70
- package/src/server/migrations/20260813000000-add-prompt-cache-tokens.ts +46 -0
- package/src/server/plugin.ts +20 -0
- package/src/server/resource/ai-api-config.ts +5 -0
- package/src/server/resource/ai-api-usage-monitor.ts +3 -0
- package/src/server/routes/chat-completions.ts +157 -22
- package/src/server/routes/completions.ts +61 -23
- package/src/server/services/__tests__/file-processor.test.ts +184 -0
- package/src/server/services/file-processor.ts +323 -0
- package/src/server/usage.ts +47 -1
- package/src/server/utils/direct-llm-context.ts +394 -0
- package/src/server/utils/openai-format.ts +25 -2
- package/src/server/utils/rate-limiter.ts +83 -83
- package/src/server/utils/resolve-service.ts +82 -82
- package/src/server/validation.ts +3 -0
- package/src/swagger.ts +45 -3
- package/dist/client/757.a01403fb7a1bea01.js +0 -10
- package/dist/client/902.92e1daaf1ab16ebf.js +0 -10
- package/dist/client-v2/757.a117ce1cf7119cea.js +0 -10
- package/dist/client-v2/902.9054d990ddc223ac.js +0 -10
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Context } from '@nocobase/actions';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Resolve an LLM service by name or title.
|
|
14
|
-
*/
|
|
15
|
-
export async function resolveLlmService(ctx: Context, serviceKey: string) {
|
|
16
|
-
const repo = ctx.db.getRepository('llmServices');
|
|
17
|
-
|
|
18
|
-
let service = await repo.findOne({ filter: { name: serviceKey } });
|
|
19
|
-
if (!service) {
|
|
20
|
-
service = await repo.findOne({ filter: { title: serviceKey } });
|
|
21
|
-
}
|
|
22
|
-
return service;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Resolve a model string to a service + modelId.
|
|
27
|
-
*
|
|
28
|
-
* Strategy (priority order):
|
|
29
|
-
* 1. Try splitting at each "/" position and match the left part against DB (name or title).
|
|
30
|
-
* This handles cases like "Custom LLM (OpenAI Compatible)/qwen/qwen3.6-plus-preview:free"
|
|
31
|
-
* 2. If no service match, use the defaultLlmService from config and treat the ENTIRE
|
|
32
|
-
* model string as the modelId. This allows clients to send just "qwen/qwen3.6-plus-preview:free"
|
|
33
|
-
* or "gpt-4o" without knowing the service name.
|
|
34
|
-
*/
|
|
35
|
-
export async function resolveModelString(
|
|
36
|
-
ctx: Context,
|
|
37
|
-
modelString: string,
|
|
38
|
-
): Promise<{ service: any; modelId: string } | null> {
|
|
39
|
-
const repo = ctx.db.getRepository('llmServices');
|
|
40
|
-
|
|
41
|
-
// ─── Strategy 1: Try splitting at "/" positions ───
|
|
42
|
-
const slashPositions: number[] = [];
|
|
43
|
-
for (let i = 0; i < modelString.length; i++) {
|
|
44
|
-
if (modelString[i] === '/') {
|
|
45
|
-
slashPositions.push(i);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (slashPositions.length > 0) {
|
|
50
|
-
for (const pos of slashPositions) {
|
|
51
|
-
const serviceKey = modelString.substring(0, pos);
|
|
52
|
-
const modelId = modelString.substring(pos + 1);
|
|
53
|
-
if (!serviceKey || !modelId) continue;
|
|
54
|
-
|
|
55
|
-
let service = await repo.findOne({ filter: { name: serviceKey } });
|
|
56
|
-
if (!service) {
|
|
57
|
-
service = await repo.findOne({ filter: { title: serviceKey } });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (service) {
|
|
61
|
-
return { service, modelId };
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ─── Strategy 2: Use default LLM service from config ───
|
|
67
|
-
const config = await ctx.db.getRepository('aiApiConfig').findOne();
|
|
68
|
-
if (config?.defaultLlmService) {
|
|
69
|
-
const service = await repo.findOne({ filter: { name: config.defaultLlmService } });
|
|
70
|
-
if (service) {
|
|
71
|
-
return { service, modelId: modelString };
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ─── Strategy 3: If only one service enabled, use it ───
|
|
76
|
-
const enabledServices = await repo.find({ filter: { enabled: true } });
|
|
77
|
-
if (enabledServices.length === 1) {
|
|
78
|
-
return { service: enabledServices[0], modelId: modelString };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Context } from '@nocobase/actions';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolve an LLM service by name or title.
|
|
14
|
+
*/
|
|
15
|
+
export async function resolveLlmService(ctx: Context, serviceKey: string) {
|
|
16
|
+
const repo = ctx.db.getRepository('llmServices');
|
|
17
|
+
|
|
18
|
+
let service = await repo.findOne({ filter: { name: serviceKey } });
|
|
19
|
+
if (!service) {
|
|
20
|
+
service = await repo.findOne({ filter: { title: serviceKey } });
|
|
21
|
+
}
|
|
22
|
+
return service;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a model string to a service + modelId.
|
|
27
|
+
*
|
|
28
|
+
* Strategy (priority order):
|
|
29
|
+
* 1. Try splitting at each "/" position and match the left part against DB (name or title).
|
|
30
|
+
* This handles cases like "Custom LLM (OpenAI Compatible)/qwen/qwen3.6-plus-preview:free"
|
|
31
|
+
* 2. If no service match, use the defaultLlmService from config and treat the ENTIRE
|
|
32
|
+
* model string as the modelId. This allows clients to send just "qwen/qwen3.6-plus-preview:free"
|
|
33
|
+
* or "gpt-4o" without knowing the service name.
|
|
34
|
+
*/
|
|
35
|
+
export async function resolveModelString(
|
|
36
|
+
ctx: Context,
|
|
37
|
+
modelString: string,
|
|
38
|
+
): Promise<{ service: any; modelId: string } | null> {
|
|
39
|
+
const repo = ctx.db.getRepository('llmServices');
|
|
40
|
+
|
|
41
|
+
// ─── Strategy 1: Try splitting at "/" positions ───
|
|
42
|
+
const slashPositions: number[] = [];
|
|
43
|
+
for (let i = 0; i < modelString.length; i++) {
|
|
44
|
+
if (modelString[i] === '/') {
|
|
45
|
+
slashPositions.push(i);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (slashPositions.length > 0) {
|
|
50
|
+
for (const pos of slashPositions) {
|
|
51
|
+
const serviceKey = modelString.substring(0, pos);
|
|
52
|
+
const modelId = modelString.substring(pos + 1);
|
|
53
|
+
if (!serviceKey || !modelId) continue;
|
|
54
|
+
|
|
55
|
+
let service = await repo.findOne({ filter: { name: serviceKey } });
|
|
56
|
+
if (!service) {
|
|
57
|
+
service = await repo.findOne({ filter: { title: serviceKey } });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (service) {
|
|
61
|
+
return { service, modelId };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── Strategy 2: Use default LLM service from config ───
|
|
67
|
+
const config = await ctx.db.getRepository('aiApiConfig').findOne();
|
|
68
|
+
if (config?.defaultLlmService) {
|
|
69
|
+
const service = await repo.findOne({ filter: { name: config.defaultLlmService } });
|
|
70
|
+
if (service) {
|
|
71
|
+
return { service, modelId: modelString };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ─── Strategy 3: If only one service enabled, use it ───
|
|
76
|
+
const enabledServices = await repo.find({ filter: { enabled: true } });
|
|
77
|
+
if (enabledServices.length === 1) {
|
|
78
|
+
return { service: enabledServices[0], modelId: modelString };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return null;
|
|
82
|
+
}
|
package/src/server/validation.ts
CHANGED
|
@@ -76,6 +76,9 @@ export function validateQuotaPolicy(model: Model): void {
|
|
|
76
76
|
if (!['allow', 'use_reserved'].includes(String(model.get('missingUsageBehavior')))) {
|
|
77
77
|
throw new Error('missingUsageBehavior must be allow or use_reserved.');
|
|
78
78
|
}
|
|
79
|
+
if (!['reject', 'truncate'].includes(String(model.get('contextOverflowBehavior') ?? 'reject'))) {
|
|
80
|
+
throw new Error('contextOverflowBehavior must be reject or truncate.');
|
|
81
|
+
}
|
|
79
82
|
try {
|
|
80
83
|
dayjs().tz(String(model.get('timezone') || 'UTC'));
|
|
81
84
|
} catch {
|
package/src/swagger.ts
CHANGED
|
@@ -273,6 +273,13 @@ export default {
|
|
|
273
273
|
'Max request body size in megabytes. Requests above this return 413. ' +
|
|
274
274
|
'The gateway buffers each body in memory, so values above 100 are rejected.',
|
|
275
275
|
},
|
|
276
|
+
pdfRenderPagesAsImages: {
|
|
277
|
+
type: 'boolean',
|
|
278
|
+
default: false,
|
|
279
|
+
description:
|
|
280
|
+
'When true, PDF file/file_url blocks are rendered to per-page PNG images and sent as image_url blocks. ' +
|
|
281
|
+
'Requires a registered PdfToImageRenderer. When false or no renderer is available, PDFs are forwarded as file blocks.',
|
|
282
|
+
},
|
|
276
283
|
},
|
|
277
284
|
},
|
|
278
285
|
ModelObject: {
|
|
@@ -287,10 +294,10 @@ export default {
|
|
|
287
294
|
ContentBlock: {
|
|
288
295
|
type: 'object',
|
|
289
296
|
description:
|
|
290
|
-
'A multimodal content block.
|
|
291
|
-
'
|
|
297
|
+
'A multimodal content block. text, image_url, file and file_url blocks are forwarded; ' +
|
|
298
|
+
'file and file_url blocks are first run through the configurable file processor service.',
|
|
292
299
|
properties: {
|
|
293
|
-
type: { type: 'string', enum: ['text', 'image_url'] },
|
|
300
|
+
type: { type: 'string', enum: ['text', 'image_url', 'file', 'file_url'] },
|
|
294
301
|
text: { type: 'string' },
|
|
295
302
|
image_url: {
|
|
296
303
|
type: 'object',
|
|
@@ -304,6 +311,35 @@ export default {
|
|
|
304
311
|
},
|
|
305
312
|
required: ['url'],
|
|
306
313
|
},
|
|
314
|
+
file: {
|
|
315
|
+
type: 'object',
|
|
316
|
+
properties: {
|
|
317
|
+
file_data: {
|
|
318
|
+
type: 'string',
|
|
319
|
+
description: 'A base64 data URL, e.g. data:application/pdf;base64,JVBERi0...',
|
|
320
|
+
example: 'data:application/pdf;base64,JVBERi0...',
|
|
321
|
+
},
|
|
322
|
+
filename: { type: 'string' },
|
|
323
|
+
mime_type: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
description: 'MIME type of the file, e.g. application/pdf',
|
|
326
|
+
example: 'application/pdf',
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
required: ['file_data'],
|
|
330
|
+
},
|
|
331
|
+
file_url: {
|
|
332
|
+
type: 'object',
|
|
333
|
+
properties: {
|
|
334
|
+
url: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
description:
|
|
337
|
+
'An http(s) URL pointing to a file. The gateway downloads the file and converts it to a file block.',
|
|
338
|
+
example: 'https://example.com/document.pdf',
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
required: ['url'],
|
|
342
|
+
},
|
|
307
343
|
},
|
|
308
344
|
required: ['type'],
|
|
309
345
|
},
|
|
@@ -366,6 +402,12 @@ export default {
|
|
|
366
402
|
prompt_tokens: { type: 'integer' },
|
|
367
403
|
completion_tokens: { type: 'integer' },
|
|
368
404
|
total_tokens: { type: 'integer' },
|
|
405
|
+
prompt_tokens_details: {
|
|
406
|
+
type: 'object',
|
|
407
|
+
properties: {
|
|
408
|
+
cached_tokens: { type: 'integer' },
|
|
409
|
+
},
|
|
410
|
+
},
|
|
369
411
|
},
|
|
370
412
|
},
|
|
371
413
|
},
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";(self.webpackChunkplugin_ai_api=self.webpackChunkplugin_ai_api||[]).push([["757"],{364:function(e,t,r){r.r(t),r.d(t,{default:function(){return y}});var n=r(155),a=r.n(n),l=r(59),o=r(185),s=r.n(o),u=r(694),i=r(650),c=r(630);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function m(e,t,r,n,a,l,o){try{var s=e[l](o),u=s.value}catch(e){r(e);return}s.done?t(u):Promise.resolve(u).then(n,a)}function f(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,a=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var l=[],o=!0,s=!1;try{for(a=a.call(e);!(o=(r=a.next()).done)&&(l.push(r.value),!t||l.length!==t);o=!0);}catch(e){s=!0,n=e}finally{try{o||null==a.return||a.return()}finally{if(s)throw n}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return d(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var v=function(){return[s()().subtract(29,"day").startOf("day"),s()().endOf("day")]},p={requestCount:0,inputTokens:0,outputTokens:0,totalTokens:0,costsByCurrency:[]};function y(){var e=(0,u.useFlowContext)(),t=(0,i.k)(),r=f(l.Form.useForm(),1)[0],o=f((0,n.useState)([]),2),s=o[0],d=o[1],y=f((0,n.useState)(p),2),h=y[0],S=y[1],b=f((0,n.useState)([]),2),g=b[0],k=b[1],I=f((0,n.useState)(!1),2),E=I[0],w=I[1],C=(0,n.useCallback)(function(t){var n;return(n=function(){var n,a,o,s,u,i,m,y,h,b,g;return function(e,t){var r,n,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),s=Object.defineProperty;return s(o,"next",{value:u(0)}),s(o,"throw",{value:u(1)}),s(o,"return",{value:u(2)}),"function"==typeof Symbol&&s(o,Symbol.iterator,{value:function(){return this}}),o;function u(s){return function(u){var i=[s,u];if(r)throw TypeError("Generator is already executing.");for(;o&&(o=0,i[0]&&(l=0)),l;)try{if(r=1,n&&(a=2&i[0]?n.return:i[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,i[1])).done)return a;switch(n=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return l.label++,{value:i[1],done:!1};case 5:l.label++,n=i[1],i=[0];continue;case 7:i=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===i[0]||2===i[0])){l=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]<a[3])){l.label=i[1];break}if(6===i[0]&&l.label<a[1]){l.label=a[1],a=i;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(i);break}a[2]&&l.ops.pop(),l.trys.pop();continue}i=t.call(e,l)}catch(e){i=[6,e],n=0}finally{r=a=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}}}(this,function(k){switch(k.label){case 0:s=(o=f(null!=(n=(a=null!=t?t:r.getFieldsValue()).range)?n:v(),2))[0],u=o[1],i=[{startedAt:{$gte:s.toISOString(),$lte:u.toISOString()}}],void 0!==a.userId&&i.push({userId:a.userId}),a.resolvedService&&i.push({resolvedService:a.resolvedService}),a.resolvedModel&&i.push({resolvedModel:a.resolvedModel}),a.status&&i.push({status:a.status}),m={start:s.toISOString(),end:u.toISOString(),userId:a.userId,resolvedService:a.resolvedService,resolvedModel:a.resolvedModel,status:a.status},w(!0),k.label=1;case 1:return k.trys.push([1,3,4,5]),[4,Promise.all([e.api.request({url:"aiApiUsageRecords:list",method:"get",params:{pageSize:100,sort:"-startedAt",filter:{$and:i}}}),e.api.request({url:"aiApiUsageMonitor:summary",method:"get",params:m})])];case 2:return h=(y=f.apply(void 0,[k.sent(),2]))[0],b=y[1],d((0,c.m)(h,[])),S((0,c.m)(b,p)),[3,5];case 3:return g=k.sent(),l.message.error((0,c.g)(g)),[3,5];case 4:return w(!1),[7];case 5:return[2]}})},function(){var e=this,t=arguments;return new Promise(function(r,a){var l=n.apply(e,t);function o(e){m(l,r,a,o,s,"next",e)}function s(e){m(l,r,a,o,s,"throw",e)}o(void 0)})})()},[e.api,r]);(0,n.useEffect)(function(){var t=v();r.setFieldsValue({range:t}),C({range:t}),e.api.request({url:"ai:listLLMServices",method:"get"}).then(function(e){return k((0,c.m)(e,[]))}).catch(function(e){return l.message.error((0,c.g)(e))})},[e.api,r,C]);var x=h.costsByCurrency.length?h.costsByCurrency.map(function(e){return"".concat(e.totalCost," ").concat(e.currency)}).join(" + "):"0",T=[{title:t("Started at"),dataIndex:"startedAt",key:"startedAt",width:180},{title:t("User"),dataIndex:"userId",key:"userId",width:90},{title:t("Requested model"),dataIndex:"model",key:"model",width:170},{title:t("Resolved service"),dataIndex:"resolvedService",key:"resolvedService",width:170},{title:t("Resolved model"),dataIndex:"resolvedModel",key:"resolvedModel",width:170},{title:t("Input tokens"),dataIndex:"inputTokens",key:"inputTokens",width:110},{title:t("Output tokens"),dataIndex:"outputTokens",key:"outputTokens",width:110},{title:t("Total tokens"),dataIndex:"totalTokens",key:"totalTokens",width:110},{title:t("Cost"),key:"cost",width:130,render:function(e,t){var r;return null==t.estimatedCost?"-":"".concat(t.estimatedCost," ").concat(null!=(r=t.currency)?r:"")}},{title:t("Cost status"),dataIndex:"costStatus",key:"costStatus",width:130,render:function(e){return e?a().createElement(l.Tag,null,e):"-"}},{title:t("Status"),dataIndex:"status",key:"status",width:100},{title:t("Request ID"),dataIndex:"requestId",key:"requestId",width:240}];return a().createElement(l.Space,{direction:"vertical",size:16,style:{width:"100%"}},a().createElement(l.Card,{title:t("Usage filters"),size:"small"},a().createElement(l.Form,{form:r,layout:"inline",onFinish:function(e){return C(e)}},a().createElement(l.Form.Item,{name:"range",label:t("Time range"),rules:[{required:!0}]},a().createElement(l.DatePicker.RangePicker,{showTime:!0})),a().createElement(l.Form.Item,{name:"userId",label:t("User ID")},a().createElement(l.InputNumber,{min:1,style:{width:110}})),a().createElement(l.Form.Item,{name:"resolvedService",label:t("Resolved service")},a().createElement(l.Select,{allowClear:!0,showSearch:!0,optionFilterProp:"label",style:{width:190},options:g.map(function(e){return{label:e.title||e.name,value:e.name}})})),a().createElement(l.Form.Item,{name:"resolvedModel",label:t("Resolved model")},a().createElement(l.Input,{allowClear:!0,style:{width:180}})),a().createElement(l.Form.Item,{name:"status",label:t("Status")},a().createElement(l.Select,{allowClear:!0,style:{width:130},options:[{label:t("Succeeded"),value:"succeeded"},{label:t("Failed"),value:"failed"},{label:t("Started"),value:"started"}]})),a().createElement(l.Form.Item,null,a().createElement(l.Space,null,a().createElement(l.Button,{type:"primary",htmlType:"submit",loading:E},t("Apply filters")),a().createElement(l.Button,{onClick:function(){var e=v();r.setFieldsValue({range:e,userId:void 0,resolvedService:void 0,resolvedModel:void 0,status:void 0}),C({range:e})}},t("Reset")))))),a().createElement(l.Row,{gutter:[16,16]},a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Requests"),value:h.requestCount}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Input tokens"),value:h.inputTokens}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Output tokens"),value:h.outputTokens}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Total tokens"),value:h.totalTokens}))),a().createElement(l.Col,{xs:24},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Total cost"),value:x})))),a().createElement(l.Card,{title:t("Usage records"),extra:a().createElement(l.Button,{onClick:function(){return C()}},t("Refresh"))},a().createElement(l.Table,{rowKey:"id",columns:T,dataSource:s,loading:E,scroll:{x:1600}})))}},650:function(e,t,r){r.d(t,{k:function(){return l}});var n=r(694),a=JSON.parse('{"UU":"plugin-ai-api"}');function l(){var e=(0,n.useFlowEngine)();return function(t){return e.context.t(t,{ns:[a.UU,"client"]})}}},630:function(e,t,r){function n(e,t){var r,n;return e&&(void 0===e?"undefined":e&&"u">typeof Symbol&&e.constructor===Symbol?"symbol":typeof e)=="object"?null!=(r=null==(n=e.data)?void 0:n.data)?r:t:t}function a(e){var t;return(null!=(t=Error)&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t)?e.message:String(e)}r.d(t,{g:function(){return a},m:function(){return n}})}}]);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";(self.webpackChunkplugin_ai_api=self.webpackChunkplugin_ai_api||[]).push([["902"],{77:function(e,t,r){r.r(t),r.d(t,{default:function(){return f}});var n=r(155),a=r.n(n),l=r(59),i=r(694),o=r(650),u=r(630);function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function s(e,t,r,n,a,l,i){try{var o=e[l](i),u=o.value}catch(e){r(e);return}o.done?t(u):Promise.resolve(u).then(n,a)}function m(e){return function(){var t=this,r=arguments;return new Promise(function(n,a){var l=e.apply(t,r);function i(e){s(l,n,a,i,o,"next",e)}function o(e){s(l,n,a,i,o,"throw",e)}i(void 0)})}}function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,a=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var l=[],i=!0,o=!1;try{for(a=a.call(e);!(i=(r=a.next()).done)&&(l.push(r.value),!t||l.length!==t);i=!0);}catch(e){o=!0,n=e}finally{try{i||null==a.return||a.return()}finally{if(o)throw n}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e,t){var r,n,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),o=Object.defineProperty;return o(i,"next",{value:u(0)}),o(i,"throw",{value:u(1)}),o(i,"return",{value:u(2)}),"function"==typeof Symbol&&o(i,Symbol.iterator,{value:function(){return this}}),i;function u(o){return function(u){var c=[o,u];if(r)throw TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(l=0)),l;)try{if(r=1,n&&(a=2&c[0]?n.return:c[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,c[1])).done)return a;switch(n=0,a&&(c=[2&c[0],a.value]),c[0]){case 0:case 1:a=c;break;case 4:return l.label++,{value:c[1],done:!1};case 5:l.label++,n=c[1],c=[0];continue;case 7:c=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===c[0]||2===c[0])){l=0;continue}if(3===c[0]&&(!a||c[1]>a[0]&&c[1]<a[3])){l.label=c[1];break}if(6===c[0]&&l.label<a[1]){l.label=a[1],a=c;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(c);break}a[2]&&l.ops.pop(),l.trys.pop();continue}c=t.call(e,l)}catch(e){c=[6,e],n=0}finally{r=a=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}}function f(){var e=(0,i.useFlowContext)(),t=(0,o.k)(),r=d(l.Form.useForm(),1)[0],c=d((0,n.useState)([]),2),s=c[0],f=c[1],y=d((0,n.useState)([]),2),b=y[0],h=y[1],v=d((0,n.useState)(!1),2),g=v[0],E=v[1],w=d((0,n.useState)(!1),2),S=w[0],k=w[1],I=d((0,n.useState)(),2),U=I[0],q=I[1],F=d((0,n.useState)(!1),2),T=F[0],x=F[1],C=(0,n.useCallback)(function(){return m(function(){var t,r,n,a;return p(this,function(i){switch(i.label){case 0:E(!0),i.label=1;case 1:return i.trys.push([1,3,4,5]),[4,Promise.all([e.api.request({url:"aiApiUserQuotaPolicies:list",method:"get",params:{pageSize:200,appends:["user"],sort:"-updatedAt"}}),e.api.request({url:"users:list",method:"get",params:{pageSize:200}})])];case 2:return r=(t=d.apply(void 0,[i.sent(),2]))[0],n=t[1],f((0,u.m)(r,[])),h((0,u.m)(n,[])),[3,5];case 3:return a=i.sent(),l.message.error((0,u.g)(a)),[3,5];case 4:return E(!1),[7];case 5:return[2]}})})()},[e.api]);(0,n.useEffect)(function(){C()},[C]);var A=function(e){q(e),r.setFieldsValue(e),x(!0)},P=function(e){var t;return(null==e?void 0:e.nickname)||(null==e?void 0:e.username)||(null==e?void 0:e.email)||String(null!=(t=null==e?void 0:e.id)?t:"")},j=[{title:t("User"),key:"user",width:180,render:function(e,t){return P(t.user)||String(t.userId)}},{title:t("Period"),dataIndex:"periodType",key:"periodType",width:100},{title:t("Request limit"),dataIndex:"requestLimit",key:"requestLimit",width:130,render:function(e){return null!=e?e:t("Unlimited")}},{title:t("Token limit"),dataIndex:"totalTokenLimit",key:"totalTokenLimit",width:130,render:function(e){return null!=e?e:t("Unlimited")}},{title:t("Cost limit"),dataIndex:"costLimit",key:"costLimit",width:120,render:function(e,r){return null==e?t("Unlimited"):"".concat(e," ").concat(r.currency)}},{title:t("Timezone"),dataIndex:"timezone",key:"timezone",width:140},{title:t("Status"),dataIndex:"enabled",key:"enabled",width:100,render:function(e){return a().createElement(l.Tag,{color:e?"green":"default"},e?t("Enabled"):t("Disabled"))}},{title:t("Actions"),key:"actions",width:150,fixed:"right",render:function(r,n){return a().createElement(l.Space,{size:0},a().createElement(l.Button,{type:"link",onClick:function(){return A(n)}},t("Edit")),a().createElement(l.Popconfirm,{title:t("Delete this quota?"),onConfirm:function(){return m(function(){var r;return p(this,function(a){switch(a.label){case 0:return a.trys.push([0,3,,4]),[4,e.api.request({url:"aiApiUserQuotaPolicies:destroy/".concat(n.id),method:"post"})];case 1:return a.sent(),l.message.success(t("Deleted successfully")),[4,C()];case 2:return a.sent(),[3,4];case 3:return r=a.sent(),l.message.error((0,u.g)(r)),[3,4];case 4:return[2]}})})()}},a().createElement(l.Button,{type:"link",danger:!0},t("Delete"))))}}];return a().createElement(l.Card,{title:t("User quotas"),extra:a().createElement(l.Button,{type:"primary",onClick:function(){q(void 0),r.setFieldsValue({enabled:!0,periodType:"monthly",timezone:"UTC",currency:"USD",rejectUnpricedModel:!0,missingUsageBehavior:"use_reserved"}),x(!0)}},t("Add quota"))},a().createElement(l.Table,{rowKey:"id",columns:j,dataSource:s,loading:g,scroll:{x:1100}}),a().createElement(l.Modal,{title:U?t("Edit quota"):t("Add quota"),open:T,onCancel:function(){return x(!1)},onOk:function(){return m(function(){var n,a;return p(this,function(i){switch(i.label){case 0:return[4,r.validateFields()];case 1:n=i.sent(),k(!0),i.label=2;case 2:return i.trys.push([2,5,6,7]),[4,e.api.request({url:U?"aiApiUserQuotaPolicies:update/".concat(U.id):"aiApiUserQuotaPolicies:create",method:"post",data:n})];case 3:return i.sent(),l.message.success(t("Saved successfully")),x(!1),[4,C()];case 4:return i.sent(),[3,7];case 5:return a=i.sent(),l.message.error((0,u.g)(a)),[3,7];case 6:return k(!1),[7];case 7:return[2]}})})()},confirmLoading:S,destroyOnClose:!0},a().createElement(l.Form,{form:r,layout:"vertical",preserve:!1},a().createElement(l.Form.Item,{name:"userId",label:t("User"),rules:[{required:!0}]},a().createElement(l.Select,{disabled:!!U,showSearch:!0,optionFilterProp:"label",options:b.map(function(e){return{label:P(e),value:e.id}})})),a().createElement(l.Form.Item,{name:"periodType",label:t("Period"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Daily"),value:"daily"},{label:t("Monthly"),value:"monthly"}]})),a().createElement(l.Form.Item,{name:"timezone",label:t("Timezone"),rules:[{required:!0}]},a().createElement(l.Input,{placeholder:"UTC"})),a().createElement(l.Form.Item,{name:"requestLimit",label:t("Request limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"totalTokenLimit",label:t("Token limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"costLimit",label:t("Cost limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"currency",label:t("Currency"),rules:[{required:!0}]},a().createElement(l.Input,null)),a().createElement(l.Form.Item,{name:"rejectUnpricedModel",label:t("Reject unpriced models"),valuePropName:"checked"},a().createElement(l.Switch,null)),a().createElement(l.Form.Item,{name:"missingUsageBehavior",label:t("Missing usage behavior"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Use reserved estimate"),value:"use_reserved"},{label:t("Allow without token charge"),value:"allow"}]})),a().createElement(l.Form.Item,{name:"enabled",label:t("Enabled"),valuePropName:"checked"},a().createElement(l.Switch,null)))))}},650:function(e,t,r){r.d(t,{k:function(){return l}});var n=r(694),a=JSON.parse('{"UU":"plugin-ai-api"}');function l(){var e=(0,n.useFlowEngine)();return function(t){return e.context.t(t,{ns:[a.UU,"client"]})}}},630:function(e,t,r){function n(e,t){var r,n;return e&&(void 0===e?"undefined":e&&"u">typeof Symbol&&e.constructor===Symbol?"symbol":typeof e)=="object"?null!=(r=null==(n=e.data)?void 0:n.data)?r:t:t}function a(e){var t;return(null!=(t=Error)&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t)?e.message:String(e)}r.d(t,{g:function(){return a},m:function(){return n}})}}]);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";(self.webpackChunkplugin_ai_api_client_v2=self.webpackChunkplugin_ai_api_client_v2||[]).push([["757"],{364:function(e,t,r){r.r(t),r.d(t,{default:function(){return y}});var n=r(155),a=r.n(n),l=r(59),o=r(185),s=r.n(o),u=r(694),i=r(650),c=r(630);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function m(e,t,r,n,a,l,o){try{var s=e[l](o),u=s.value}catch(e){r(e);return}s.done?t(u):Promise.resolve(u).then(n,a)}function f(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,a=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var l=[],o=!0,s=!1;try{for(a=a.call(e);!(o=(r=a.next()).done)&&(l.push(r.value),!t||l.length!==t);o=!0);}catch(e){s=!0,n=e}finally{try{o||null==a.return||a.return()}finally{if(s)throw n}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return d(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var v=function(){return[s()().subtract(29,"day").startOf("day"),s()().endOf("day")]},p={requestCount:0,inputTokens:0,outputTokens:0,totalTokens:0,costsByCurrency:[]};function y(){var e=(0,u.useFlowContext)(),t=(0,i.k)(),r=f(l.Form.useForm(),1)[0],o=f((0,n.useState)([]),2),s=o[0],d=o[1],y=f((0,n.useState)(p),2),h=y[0],S=y[1],b=f((0,n.useState)([]),2),g=b[0],k=b[1],I=f((0,n.useState)(!1),2),E=I[0],w=I[1],C=(0,n.useCallback)(function(t){var n;return(n=function(){var n,a,o,s,u,i,m,y,h,b,g;return function(e,t){var r,n,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),s=Object.defineProperty;return s(o,"next",{value:u(0)}),s(o,"throw",{value:u(1)}),s(o,"return",{value:u(2)}),"function"==typeof Symbol&&s(o,Symbol.iterator,{value:function(){return this}}),o;function u(s){return function(u){var i=[s,u];if(r)throw TypeError("Generator is already executing.");for(;o&&(o=0,i[0]&&(l=0)),l;)try{if(r=1,n&&(a=2&i[0]?n.return:i[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,i[1])).done)return a;switch(n=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return l.label++,{value:i[1],done:!1};case 5:l.label++,n=i[1],i=[0];continue;case 7:i=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===i[0]||2===i[0])){l=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]<a[3])){l.label=i[1];break}if(6===i[0]&&l.label<a[1]){l.label=a[1],a=i;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(i);break}a[2]&&l.ops.pop(),l.trys.pop();continue}i=t.call(e,l)}catch(e){i=[6,e],n=0}finally{r=a=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}}}(this,function(k){switch(k.label){case 0:s=(o=f(null!=(n=(a=null!=t?t:r.getFieldsValue()).range)?n:v(),2))[0],u=o[1],i=[{startedAt:{$gte:s.toISOString(),$lte:u.toISOString()}}],void 0!==a.userId&&i.push({userId:a.userId}),a.resolvedService&&i.push({resolvedService:a.resolvedService}),a.resolvedModel&&i.push({resolvedModel:a.resolvedModel}),a.status&&i.push({status:a.status}),m={start:s.toISOString(),end:u.toISOString(),userId:a.userId,resolvedService:a.resolvedService,resolvedModel:a.resolvedModel,status:a.status},w(!0),k.label=1;case 1:return k.trys.push([1,3,4,5]),[4,Promise.all([e.api.request({url:"aiApiUsageRecords:list",method:"get",params:{pageSize:100,sort:"-startedAt",filter:{$and:i}}}),e.api.request({url:"aiApiUsageMonitor:summary",method:"get",params:m})])];case 2:return h=(y=f.apply(void 0,[k.sent(),2]))[0],b=y[1],d((0,c.m)(h,[])),S((0,c.m)(b,p)),[3,5];case 3:return g=k.sent(),l.message.error((0,c.g)(g)),[3,5];case 4:return w(!1),[7];case 5:return[2]}})},function(){var e=this,t=arguments;return new Promise(function(r,a){var l=n.apply(e,t);function o(e){m(l,r,a,o,s,"next",e)}function s(e){m(l,r,a,o,s,"throw",e)}o(void 0)})})()},[e.api,r]);(0,n.useEffect)(function(){var t=v();r.setFieldsValue({range:t}),C({range:t}),e.api.request({url:"ai:listLLMServices",method:"get"}).then(function(e){return k((0,c.m)(e,[]))}).catch(function(e){return l.message.error((0,c.g)(e))})},[e.api,r,C]);var x=h.costsByCurrency.length?h.costsByCurrency.map(function(e){return"".concat(e.totalCost," ").concat(e.currency)}).join(" + "):"0",T=[{title:t("Started at"),dataIndex:"startedAt",key:"startedAt",width:180},{title:t("User"),dataIndex:"userId",key:"userId",width:90},{title:t("Requested model"),dataIndex:"model",key:"model",width:170},{title:t("Resolved service"),dataIndex:"resolvedService",key:"resolvedService",width:170},{title:t("Resolved model"),dataIndex:"resolvedModel",key:"resolvedModel",width:170},{title:t("Input tokens"),dataIndex:"inputTokens",key:"inputTokens",width:110},{title:t("Output tokens"),dataIndex:"outputTokens",key:"outputTokens",width:110},{title:t("Total tokens"),dataIndex:"totalTokens",key:"totalTokens",width:110},{title:t("Cost"),key:"cost",width:130,render:function(e,t){var r;return null==t.estimatedCost?"-":"".concat(t.estimatedCost," ").concat(null!=(r=t.currency)?r:"")}},{title:t("Cost status"),dataIndex:"costStatus",key:"costStatus",width:130,render:function(e){return e?a().createElement(l.Tag,null,e):"-"}},{title:t("Status"),dataIndex:"status",key:"status",width:100},{title:t("Request ID"),dataIndex:"requestId",key:"requestId",width:240}];return a().createElement(l.Space,{direction:"vertical",size:16,style:{width:"100%"}},a().createElement(l.Card,{title:t("Usage filters"),size:"small"},a().createElement(l.Form,{form:r,layout:"inline",onFinish:function(e){return C(e)}},a().createElement(l.Form.Item,{name:"range",label:t("Time range"),rules:[{required:!0}]},a().createElement(l.DatePicker.RangePicker,{showTime:!0})),a().createElement(l.Form.Item,{name:"userId",label:t("User ID")},a().createElement(l.InputNumber,{min:1,style:{width:110}})),a().createElement(l.Form.Item,{name:"resolvedService",label:t("Resolved service")},a().createElement(l.Select,{allowClear:!0,showSearch:!0,optionFilterProp:"label",style:{width:190},options:g.map(function(e){return{label:e.title||e.name,value:e.name}})})),a().createElement(l.Form.Item,{name:"resolvedModel",label:t("Resolved model")},a().createElement(l.Input,{allowClear:!0,style:{width:180}})),a().createElement(l.Form.Item,{name:"status",label:t("Status")},a().createElement(l.Select,{allowClear:!0,style:{width:130},options:[{label:t("Succeeded"),value:"succeeded"},{label:t("Failed"),value:"failed"},{label:t("Started"),value:"started"}]})),a().createElement(l.Form.Item,null,a().createElement(l.Space,null,a().createElement(l.Button,{type:"primary",htmlType:"submit",loading:E},t("Apply filters")),a().createElement(l.Button,{onClick:function(){var e=v();r.setFieldsValue({range:e,userId:void 0,resolvedService:void 0,resolvedModel:void 0,status:void 0}),C({range:e})}},t("Reset")))))),a().createElement(l.Row,{gutter:[16,16]},a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Requests"),value:h.requestCount}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Input tokens"),value:h.inputTokens}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Output tokens"),value:h.outputTokens}))),a().createElement(l.Col,{xs:24,sm:12,lg:6},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Total tokens"),value:h.totalTokens}))),a().createElement(l.Col,{xs:24},a().createElement(l.Card,{size:"small"},a().createElement(l.Statistic,{title:t("Total cost"),value:x})))),a().createElement(l.Card,{title:t("Usage records"),extra:a().createElement(l.Button,{onClick:function(){return C()}},t("Refresh"))},a().createElement(l.Table,{rowKey:"id",columns:T,dataSource:s,loading:E,scroll:{x:1600}})))}},650:function(e,t,r){r.d(t,{k:function(){return l}});var n=r(694),a=JSON.parse('{"UU":"plugin-ai-api"}');function l(){var e=(0,n.useFlowEngine)();return function(t){return e.context.t(t,{ns:[a.UU,"client"]})}}},630:function(e,t,r){function n(e,t){var r,n;return e&&(void 0===e?"undefined":e&&"u">typeof Symbol&&e.constructor===Symbol?"symbol":typeof e)=="object"?null!=(r=null==(n=e.data)?void 0:n.data)?r:t:t}function a(e){var t;return(null!=(t=Error)&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t)?e.message:String(e)}r.d(t,{g:function(){return a},m:function(){return n}})}}]);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";(self.webpackChunkplugin_ai_api_client_v2=self.webpackChunkplugin_ai_api_client_v2||[]).push([["902"],{77:function(e,t,r){r.r(t),r.d(t,{default:function(){return f}});var n=r(155),a=r.n(n),l=r(59),i=r(694),o=r(650),u=r(630);function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function s(e,t,r,n,a,l,i){try{var o=e[l](i),u=o.value}catch(e){r(e);return}o.done?t(u):Promise.resolve(u).then(n,a)}function m(e){return function(){var t=this,r=arguments;return new Promise(function(n,a){var l=e.apply(t,r);function i(e){s(l,n,a,i,o,"next",e)}function o(e){s(l,n,a,i,o,"throw",e)}i(void 0)})}}function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,a=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var l=[],i=!0,o=!1;try{for(a=a.call(e);!(i=(r=a.next()).done)&&(l.push(r.value),!t||l.length!==t);i=!0);}catch(e){o=!0,n=e}finally{try{i||null==a.return||a.return()}finally{if(o)throw n}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e,t){var r,n,a,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),o=Object.defineProperty;return o(i,"next",{value:u(0)}),o(i,"throw",{value:u(1)}),o(i,"return",{value:u(2)}),"function"==typeof Symbol&&o(i,Symbol.iterator,{value:function(){return this}}),i;function u(o){return function(u){var c=[o,u];if(r)throw TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(l=0)),l;)try{if(r=1,n&&(a=2&c[0]?n.return:c[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,c[1])).done)return a;switch(n=0,a&&(c=[2&c[0],a.value]),c[0]){case 0:case 1:a=c;break;case 4:return l.label++,{value:c[1],done:!1};case 5:l.label++,n=c[1],c=[0];continue;case 7:c=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===c[0]||2===c[0])){l=0;continue}if(3===c[0]&&(!a||c[1]>a[0]&&c[1]<a[3])){l.label=c[1];break}if(6===c[0]&&l.label<a[1]){l.label=a[1],a=c;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(c);break}a[2]&&l.ops.pop(),l.trys.pop();continue}c=t.call(e,l)}catch(e){c=[6,e],n=0}finally{r=a=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}}function f(){var e=(0,i.useFlowContext)(),t=(0,o.k)(),r=d(l.Form.useForm(),1)[0],c=d((0,n.useState)([]),2),s=c[0],f=c[1],y=d((0,n.useState)([]),2),b=y[0],h=y[1],v=d((0,n.useState)(!1),2),g=v[0],E=v[1],w=d((0,n.useState)(!1),2),S=w[0],k=w[1],I=d((0,n.useState)(),2),U=I[0],q=I[1],F=d((0,n.useState)(!1),2),T=F[0],x=F[1],C=(0,n.useCallback)(function(){return m(function(){var t,r,n,a;return p(this,function(i){switch(i.label){case 0:E(!0),i.label=1;case 1:return i.trys.push([1,3,4,5]),[4,Promise.all([e.api.request({url:"aiApiUserQuotaPolicies:list",method:"get",params:{pageSize:200,appends:["user"],sort:"-updatedAt"}}),e.api.request({url:"users:list",method:"get",params:{pageSize:200}})])];case 2:return r=(t=d.apply(void 0,[i.sent(),2]))[0],n=t[1],f((0,u.m)(r,[])),h((0,u.m)(n,[])),[3,5];case 3:return a=i.sent(),l.message.error((0,u.g)(a)),[3,5];case 4:return E(!1),[7];case 5:return[2]}})})()},[e.api]);(0,n.useEffect)(function(){C()},[C]);var A=function(e){q(e),r.setFieldsValue(e),x(!0)},P=function(e){var t;return(null==e?void 0:e.nickname)||(null==e?void 0:e.username)||(null==e?void 0:e.email)||String(null!=(t=null==e?void 0:e.id)?t:"")},j=[{title:t("User"),key:"user",width:180,render:function(e,t){return P(t.user)||String(t.userId)}},{title:t("Period"),dataIndex:"periodType",key:"periodType",width:100},{title:t("Request limit"),dataIndex:"requestLimit",key:"requestLimit",width:130,render:function(e){return null!=e?e:t("Unlimited")}},{title:t("Token limit"),dataIndex:"totalTokenLimit",key:"totalTokenLimit",width:130,render:function(e){return null!=e?e:t("Unlimited")}},{title:t("Cost limit"),dataIndex:"costLimit",key:"costLimit",width:120,render:function(e,r){return null==e?t("Unlimited"):"".concat(e," ").concat(r.currency)}},{title:t("Timezone"),dataIndex:"timezone",key:"timezone",width:140},{title:t("Status"),dataIndex:"enabled",key:"enabled",width:100,render:function(e){return a().createElement(l.Tag,{color:e?"green":"default"},e?t("Enabled"):t("Disabled"))}},{title:t("Actions"),key:"actions",width:150,fixed:"right",render:function(r,n){return a().createElement(l.Space,{size:0},a().createElement(l.Button,{type:"link",onClick:function(){return A(n)}},t("Edit")),a().createElement(l.Popconfirm,{title:t("Delete this quota?"),onConfirm:function(){return m(function(){var r;return p(this,function(a){switch(a.label){case 0:return a.trys.push([0,3,,4]),[4,e.api.request({url:"aiApiUserQuotaPolicies:destroy/".concat(n.id),method:"post"})];case 1:return a.sent(),l.message.success(t("Deleted successfully")),[4,C()];case 2:return a.sent(),[3,4];case 3:return r=a.sent(),l.message.error((0,u.g)(r)),[3,4];case 4:return[2]}})})()}},a().createElement(l.Button,{type:"link",danger:!0},t("Delete"))))}}];return a().createElement(l.Card,{title:t("User quotas"),extra:a().createElement(l.Button,{type:"primary",onClick:function(){q(void 0),r.setFieldsValue({enabled:!0,periodType:"monthly",timezone:"UTC",currency:"USD",rejectUnpricedModel:!0,missingUsageBehavior:"use_reserved"}),x(!0)}},t("Add quota"))},a().createElement(l.Table,{rowKey:"id",columns:j,dataSource:s,loading:g,scroll:{x:1100}}),a().createElement(l.Modal,{title:U?t("Edit quota"):t("Add quota"),open:T,onCancel:function(){return x(!1)},onOk:function(){return m(function(){var n,a;return p(this,function(i){switch(i.label){case 0:return[4,r.validateFields()];case 1:n=i.sent(),k(!0),i.label=2;case 2:return i.trys.push([2,5,6,7]),[4,e.api.request({url:U?"aiApiUserQuotaPolicies:update/".concat(U.id):"aiApiUserQuotaPolicies:create",method:"post",data:n})];case 3:return i.sent(),l.message.success(t("Saved successfully")),x(!1),[4,C()];case 4:return i.sent(),[3,7];case 5:return a=i.sent(),l.message.error((0,u.g)(a)),[3,7];case 6:return k(!1),[7];case 7:return[2]}})})()},confirmLoading:S,destroyOnClose:!0},a().createElement(l.Form,{form:r,layout:"vertical",preserve:!1},a().createElement(l.Form.Item,{name:"userId",label:t("User"),rules:[{required:!0}]},a().createElement(l.Select,{disabled:!!U,showSearch:!0,optionFilterProp:"label",options:b.map(function(e){return{label:P(e),value:e.id}})})),a().createElement(l.Form.Item,{name:"periodType",label:t("Period"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Daily"),value:"daily"},{label:t("Monthly"),value:"monthly"}]})),a().createElement(l.Form.Item,{name:"timezone",label:t("Timezone"),rules:[{required:!0}]},a().createElement(l.Input,{placeholder:"UTC"})),a().createElement(l.Form.Item,{name:"requestLimit",label:t("Request limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"totalTokenLimit",label:t("Token limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"costLimit",label:t("Cost limit")},a().createElement(l.InputNumber,{min:0,stringMode:!0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"currency",label:t("Currency"),rules:[{required:!0}]},a().createElement(l.Input,null)),a().createElement(l.Form.Item,{name:"rejectUnpricedModel",label:t("Reject unpriced models"),valuePropName:"checked"},a().createElement(l.Switch,null)),a().createElement(l.Form.Item,{name:"missingUsageBehavior",label:t("Missing usage behavior"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Use reserved estimate"),value:"use_reserved"},{label:t("Allow without token charge"),value:"allow"}]})),a().createElement(l.Form.Item,{name:"enabled",label:t("Enabled"),valuePropName:"checked"},a().createElement(l.Switch,null)))))}},650:function(e,t,r){r.d(t,{k:function(){return l}});var n=r(694),a=JSON.parse('{"UU":"plugin-ai-api"}');function l(){var e=(0,n.useFlowEngine)();return function(t){return e.context.t(t,{ns:[a.UU,"client"]})}}},630:function(e,t,r){function n(e,t){var r,n;return e&&(void 0===e?"undefined":e&&"u">typeof Symbol&&e.constructor===Symbol?"symbol":typeof e)=="object"?null!=(r=null==(n=e.data)?void 0:n.data)?r:t:t}function a(e){var t;return(null!=(t=Error)&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t)?e.message:String(e)}r.d(t,{g:function(){return a},m:function(){return n}})}}]);
|