plugin-ai-api 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/902.e74518750f1e4201.js +10 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/902.c7c00a565085438a.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/locale/en-US.json +3 -0
- package/dist/locale/vi-VN.json +3 -0
- package/dist/locale/zh-CN.json +3 -0
- package/dist/server/collections/ai-api-user-quota-policies.js +2 -1
- package/dist/server/routes/chat-completions.js +24 -12
- package/dist/server/routes/completions.js +27 -14
- package/dist/server/utils/direct-llm-context.js +184 -0
- package/dist/server/validation.js +3 -0
- package/package.json +1 -1
- package/src/client-v2/pages/UserQuotasPage.tsx +18 -0
- package/src/locale/en-US.json +3 -0
- package/src/locale/vi-VN.json +3 -0
- package/src/locale/zh-CN.json +3 -0
- package/src/server/__tests__/direct-llm-context.test.ts +125 -0
- package/src/server/__tests__/usage-route.test.ts +53 -6
- package/src/server/__tests__/validation.test.ts +36 -0
- package/src/server/collections/ai-api-user-quota-policies.ts +1 -0
- package/src/server/routes/chat-completions.ts +26 -14
- package/src/server/routes/completions.ts +28 -16
- package/src/server/utils/direct-llm-context.ts +216 -0
- package/src/server/validation.ts +3 -0
- package/dist/client/902.92e1daaf1ab16ebf.js +0 -10
- package/dist/client-v2/902.9054d990ddc223ac.js +0 -10
|
@@ -0,0 +1,10 @@
|
|
|
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 p}});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 f(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 p(){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],p=c[1],y=d((0,n.useState)([]),2),h=y[0],b=y[1],v=d((0,n.useState)(!1),2),g=v[0],w=v[1],E=d((0,n.useState)(!1),2),S=E[0],k=E[1],I=d((0,n.useState)(),2),x=I[0],U=I[1],q=d((0,n.useState)(!1),2),F=q[0],T=q[1],C=(0,n.useCallback)(function(){return m(function(){var t,r,n,a;return f(this,function(i){switch(i.label){case 0:w(!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],p((0,u.m)(r,[])),b((0,u.m)(n,[])),[3,5];case 3:return a=i.sent(),l.message.error((0,u.g)(a)),[3,5];case 4:return w(!1),[7];case 5:return[2]}})})()},[e.api]);(0,n.useEffect)(function(){C()},[C]);var A=function(e){U(e),r.setFieldsValue(e),T(!0)},j=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:"")},P=[{title:t("User"),key:"user",width:180,render:function(e,t){return j(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("Context overflow behavior"),dataIndex:"contextOverflowBehavior",key:"contextOverflowBehavior",width:150,render:function(e){return"truncate"===e?t("Truncate oldest conversation turns"):t("Reject request")}},{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 f(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(){U(void 0),r.setFieldsValue({enabled:!0,periodType:"monthly",timezone:"UTC",currency:"USD",rejectUnpricedModel:!0,missingUsageBehavior:"use_reserved",contextOverflowBehavior:"reject"}),T(!0)}},t("Add quota"))},a().createElement(l.Table,{rowKey:"id",columns:P,dataSource:s,loading:g,scroll:{x:1100}}),a().createElement(l.Modal,{title:x?t("Edit quota"):t("Add quota"),open:F,onCancel:function(){return T(!1)},onOk:function(){return m(function(){var n,a;return f(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:x?"aiApiUserQuotaPolicies:update/".concat(x.id):"aiApiUserQuotaPolicies:create",method:"post",data:n})];case 3:return i.sent(),l.message.success(t("Saved successfully")),T(!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:!!x,showSearch:!0,optionFilterProp:"label",options:h.map(function(e){return{label:j(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:"contextOverflowBehavior",label:t("Context overflow behavior"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Reject request"),value:"reject"},{label:t("Truncate oldest conversation turns"),value:"truncate"}]})),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}})}}]);
|
package/dist/client/index.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/client"),require("@nocobase/plugin-acl/client"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("plugin-ai-api",["@nocobase/client-v2","dayjs","react","antd","@nocobase/client","@nocobase/plugin-acl/client","@nocobase/flow-engine"],t):"object"==typeof exports?exports["plugin-ai-api"]=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/client"),require("@nocobase/plugin-acl/client"),require("@nocobase/flow-engine")):e["plugin-ai-api"]=t(e["@nocobase/client-v2"],e.dayjs,e.react,e.antd,e["@nocobase/client"],e["@nocobase/plugin-acl/client"],e["@nocobase/flow-engine"])}(self,function(e,t,n,r,i,o,a){return function(){"use strict";var u,c,l,p={342:function(e){e.exports=i},485:function(t){t.exports=e},694:function(e){e.exports=a},79:function(e){e.exports=o},59:function(e){e.exports=r},185:function(e){e.exports=t},155:function(e){e.exports=n}},s={};function f(e){var t=s[e];if(void 0!==t)return t.exports;var n=s[e]={exports:{}};return p[e](n,n.exports,f),n.exports}f.m=p,f.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(t,{a:t}),t},f.d=function(e,t){for(var n in t)f.o(t,n)&&!f.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},f.f={},f.e=function(e){return Promise.all(Object.keys(f.f).reduce(function(t,n){return f.f[n](e,t),t},[]))},f.u=function(e){return""+e+"."+({123:"e6fe04c856ce6417",286:"01c0e3c5fff3cccb",302:"fc3a3491b4ec2dfd",562:"17a0a299d2e5152c",757:"a01403fb7a1bea01",902:"92e1daaf1ab16ebf",97:"72979a11a067a7c9"})[e]+".js"},f.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),f.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},d={},f.l=function(e,t,n,r){if(d[e])return void d[e].push(t);if(void 0!==n)for(var i,o,a=document.getElementsByTagName("script"),u=0;u<a.length;u++){var c=a[u];if(c.getAttribute("src")==e||c.getAttribute("data-rspack")=="plugin-ai-api:"+n){i=c;break}}i||(o=!0,(i=document.createElement("script")).timeout=120,f.nc&&i.setAttribute("nonce",f.nc),i.setAttribute("data-rspack","plugin-ai-api:"+n),i.src=e),d[e]=[t];var l=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var r=d[e];if(delete d[e],i.parentNode&&i.parentNode.removeChild(i),r&&r.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(l.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=l.bind(null,i.onerror),i.onload=l.bind(null,i.onload),o&&document.head.appendChild(i)},f.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.g.importScripts&&(b=f.g.location+"");var d,b,g=f.g.document;if(!b&&g&&(g.currentScript&&"SCRIPT"===g.currentScript.tagName.toUpperCase()&&(b=g.currentScript.src),!b)){var h=g.getElementsByTagName("script");if(h.length)for(var y=h.length-1;y>-1&&(!b||!/^http(s?):/.test(b));)b=h[y--].src}if(!b)throw Error("Automatic publicPath is not supported in this browser");f.p=b.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),u={889:0},f.f.j=function(e,t){var n=f.o(u,e)?u[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=u[e]=[t,r]});t.push(n[2]=r);var i=f.p+f.u(e),o=Error();f.l(i,function(t){if(f.o(u,e)&&(0!==(n=u[e])&&(u[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;o.message="Loading chunk "+e+" failed.\n("+r+": "+i+")",o.name="ChunkLoadError",o.type=r,o.request=i,n[1](o)}},"chunk-"+e,e)}},c=function(e,t){var n,r,i=t[0],o=t[1],a=t[2],c=0;if(i.some(function(e){return 0!==u[e]})){for(n in o)f.o(o,n)&&(f.m[n]=o[n]);a&&a(f)}for(e&&e(t);c<i.length;c++)r=i[c],f.o(u,r)&&u[r]&&u[r][0](),u[r]=0},(l=self.webpackChunkplugin_ai_api=self.webpackChunkplugin_ai_api||[]).forEach(c.bind(null,0)),l.push=c.bind(null,l.push.bind(l));var v={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var n=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");n.indexOf("/static/plugins/plugin-ai-api/dist/client/")>=0&&(e=n.replace(/\/[^\/]+$/,"/"))}if(!e){var r=window.__webpack_public_path__||"";r&&("/"!==r.charAt(r.length-1)&&(r+="/"),e=r+"static/plugins/plugin-ai-api/dist/client/")}if(!e){var i=window.__nocobase_modern_client_prefix__||"v",o="/"+(i=String(i).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var a=window.location.pathname||"/",u=a.indexOf(o);e=u>=0?a.slice(0,u+1):"/"}e&&(e=e.replace(RegExp("/"+i+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/plugin-ai-api/dist/client/"}f.p=e}(),!function(){f.r(v),f.d(v,{default:function(){return _}});var e=f(342),t=f(79),n=f.n(t),r="pm.plugin-ai-api.configuration",i=f(155),o=f.n(i);function a(e,t,n,r,i,o,a){try{var u=e[o](a),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,i)}function u(e,t,n){return(u=s()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&l(i,n.prototype),i}).apply(null,arguments)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function p(e){var t="function"==typeof Map?new Map:void 0;return(p=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return u(e,arguments,c(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),l(n,e)})(e)}function s(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(s=function(){return!!e})()}var d=o().lazy(function(){return f.e("302").then(f.bind(f,581))}),b=o().lazy(function(){return f.e("97").then(f.bind(f,760))}),g=o().lazy(function(){return f.e("562").then(f.bind(f,641))}),h=o().lazy(function(){return f.e("123").then(f.bind(f,46))}),y=o().lazy(function(){return f.e("902").then(f.bind(f,77))}),m=o().lazy(function(){return f.e("757").then(f.bind(f,364))}),w=(0,e.lazy)(function(){return f.e("286").then(f.bind(f,421))},"AiApiRolePermissions").AiApiRolePermissions,_=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function i(){var e,t;if(!(this instanceof i))throw TypeError("Cannot call a class as a function");return e=i,t=arguments,e=c(e),function(e,t){var n;if(t&&("object"==((n=t)&&"u">typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,s()?Reflect.construct(e,t||[],c(this).constructor):e.apply(this,t))}return i.prototype=Object.create(e&&e.prototype,{constructor:{value:i,writable:!0,configurable:!0}}),e&&l(i,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(o=0)),o;)try{if(n=1,r&&(i=2&l[0]?r.return:l[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,l[1])).done)return i;switch(r=0,i&&(l=[2&l[0],i.value]),l[0]){case 0:case 1:i=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,r=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===l[0]||2===l[0])){o=0;continue}if(3===l[0]&&(!i||l[1]>i[0]&&l[1]<i[3])){o.label=l[1];break}if(6===l[0]&&o.label<i[1]){o.label=i[1],i=l;break}if(i&&o.label<i[2]){o.label=i[2],o.ops.push(l);break}i[2]&&o.ops.pop(),o.trys.pop();continue}l=t.call(e,o)}catch(e){l=[6,e],r=0}finally{n=i=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return this.app.pluginSettingsManager.add("ai-api",{icon:"ApiOutlined",title:this.t("AI API Gateway"),aclSnippet:r}),this.app.pluginSettingsManager.add("ai-api.config",{title:this.t("Configuration"),Component:d,aclSnippet:r,sort:1}),this.app.pluginSettingsManager.add("ai-api.model-pricing",{title:this.t("Model pricing"),Component:b,aclSnippet:r,sort:2}),this.app.pluginSettingsManager.add("ai-api.model-metadata",{title:this.t("Model metadata"),Component:g,aclSnippet:r,sort:3}),this.app.pluginSettingsManager.add("ai-api.user-permissions",{title:this.t("User LLM permissions"),Component:h,aclSnippet:"pm.plugin-ai-api.user-permissions",sort:4}),this.app.pluginSettingsManager.add("ai-api.user-quotas",{title:this.t("User quotas"),Component:y,aclSnippet:r,sort:5}),this.app.pluginSettingsManager.add("ai-api.usage",{title:this.t("Usage"),Component:m,aclSnippet:r,sort:6}),(null==(e=this.app.pm.get(n()))?void 0:e.settingsUI)&&e.settingsUI.addPermissionsTab(function(e){var t=e.t,n=e.TabLayout,r=e.activeRole;return{key:"aiApi",label:t("AI API",{ns:["plugin-ai-api","client"]}),sort:25,children:o().createElement(n,null,o().createElement(w,{role:r}))}}),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,i){var o=e.apply(t,n);function u(e){a(o,r,i,u,c,"next",e)}function c(e){a(o,r,i,u,c,"throw",e)}u(void 0)})}).call(this)}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(i.prototype,t),i}(p(e.Plugin))}(),v}()});
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/client"),require("@nocobase/plugin-acl/client"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("plugin-ai-api",["@nocobase/client-v2","dayjs","react","antd","@nocobase/client","@nocobase/plugin-acl/client","@nocobase/flow-engine"],t):"object"==typeof exports?exports["plugin-ai-api"]=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/client"),require("@nocobase/plugin-acl/client"),require("@nocobase/flow-engine")):e["plugin-ai-api"]=t(e["@nocobase/client-v2"],e.dayjs,e.react,e.antd,e["@nocobase/client"],e["@nocobase/plugin-acl/client"],e["@nocobase/flow-engine"])}(self,function(e,t,n,r,i,o,a){return function(){"use strict";var u,c,l,p={342:function(e){e.exports=i},485:function(t){t.exports=e},694:function(e){e.exports=a},79:function(e){e.exports=o},59:function(e){e.exports=r},185:function(e){e.exports=t},155:function(e){e.exports=n}},s={};function f(e){var t=s[e];if(void 0!==t)return t.exports;var n=s[e]={exports:{}};return p[e](n,n.exports,f),n.exports}f.m=p,f.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(t,{a:t}),t},f.d=function(e,t){for(var n in t)f.o(t,n)&&!f.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},f.f={},f.e=function(e){return Promise.all(Object.keys(f.f).reduce(function(t,n){return f.f[n](e,t),t},[]))},f.u=function(e){return""+e+"."+({123:"e6fe04c856ce6417",286:"01c0e3c5fff3cccb",302:"fc3a3491b4ec2dfd",562:"17a0a299d2e5152c",757:"a01403fb7a1bea01",902:"e74518750f1e4201",97:"72979a11a067a7c9"})[e]+".js"},f.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),f.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},d={},f.l=function(e,t,n,r){if(d[e])return void d[e].push(t);if(void 0!==n)for(var i,o,a=document.getElementsByTagName("script"),u=0;u<a.length;u++){var c=a[u];if(c.getAttribute("src")==e||c.getAttribute("data-rspack")=="plugin-ai-api:"+n){i=c;break}}i||(o=!0,(i=document.createElement("script")).timeout=120,f.nc&&i.setAttribute("nonce",f.nc),i.setAttribute("data-rspack","plugin-ai-api:"+n),i.src=e),d[e]=[t];var l=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var r=d[e];if(delete d[e],i.parentNode&&i.parentNode.removeChild(i),r&&r.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(l.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=l.bind(null,i.onerror),i.onload=l.bind(null,i.onload),o&&document.head.appendChild(i)},f.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.g.importScripts&&(b=f.g.location+"");var d,b,g=f.g.document;if(!b&&g&&(g.currentScript&&"SCRIPT"===g.currentScript.tagName.toUpperCase()&&(b=g.currentScript.src),!b)){var h=g.getElementsByTagName("script");if(h.length)for(var y=h.length-1;y>-1&&(!b||!/^http(s?):/.test(b));)b=h[y--].src}if(!b)throw Error("Automatic publicPath is not supported in this browser");f.p=b.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),u={889:0},f.f.j=function(e,t){var n=f.o(u,e)?u[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=u[e]=[t,r]});t.push(n[2]=r);var i=f.p+f.u(e),o=Error();f.l(i,function(t){if(f.o(u,e)&&(0!==(n=u[e])&&(u[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;o.message="Loading chunk "+e+" failed.\n("+r+": "+i+")",o.name="ChunkLoadError",o.type=r,o.request=i,n[1](o)}},"chunk-"+e,e)}},c=function(e,t){var n,r,i=t[0],o=t[1],a=t[2],c=0;if(i.some(function(e){return 0!==u[e]})){for(n in o)f.o(o,n)&&(f.m[n]=o[n]);a&&a(f)}for(e&&e(t);c<i.length;c++)r=i[c],f.o(u,r)&&u[r]&&u[r][0](),u[r]=0},(l=self.webpackChunkplugin_ai_api=self.webpackChunkplugin_ai_api||[]).forEach(c.bind(null,0)),l.push=c.bind(null,l.push.bind(l));var v={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var n=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");n.indexOf("/static/plugins/plugin-ai-api/dist/client/")>=0&&(e=n.replace(/\/[^\/]+$/,"/"))}if(!e){var r=window.__webpack_public_path__||"";r&&("/"!==r.charAt(r.length-1)&&(r+="/"),e=r+"static/plugins/plugin-ai-api/dist/client/")}if(!e){var i=window.__nocobase_modern_client_prefix__||"v",o="/"+(i=String(i).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var a=window.location.pathname||"/",u=a.indexOf(o);e=u>=0?a.slice(0,u+1):"/"}e&&(e=e.replace(RegExp("/"+i+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/plugin-ai-api/dist/client/"}f.p=e}(),!function(){f.r(v),f.d(v,{default:function(){return _}});var e=f(342),t=f(79),n=f.n(t),r="pm.plugin-ai-api.configuration",i=f(155),o=f.n(i);function a(e,t,n,r,i,o,a){try{var u=e[o](a),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,i)}function u(e,t,n){return(u=s()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&l(i,n.prototype),i}).apply(null,arguments)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function p(e){var t="function"==typeof Map?new Map:void 0;return(p=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return u(e,arguments,c(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),l(n,e)})(e)}function s(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(s=function(){return!!e})()}var d=o().lazy(function(){return f.e("302").then(f.bind(f,581))}),b=o().lazy(function(){return f.e("97").then(f.bind(f,760))}),g=o().lazy(function(){return f.e("562").then(f.bind(f,641))}),h=o().lazy(function(){return f.e("123").then(f.bind(f,46))}),y=o().lazy(function(){return f.e("902").then(f.bind(f,77))}),m=o().lazy(function(){return f.e("757").then(f.bind(f,364))}),w=(0,e.lazy)(function(){return f.e("286").then(f.bind(f,421))},"AiApiRolePermissions").AiApiRolePermissions,_=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function i(){var e,t;if(!(this instanceof i))throw TypeError("Cannot call a class as a function");return e=i,t=arguments,e=c(e),function(e,t){var n;if(t&&("object"==((n=t)&&"u">typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,s()?Reflect.construct(e,t||[],c(this).constructor):e.apply(this,t))}return i.prototype=Object.create(e&&e.prototype,{constructor:{value:i,writable:!0,configurable:!0}}),e&&l(i,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(o=0)),o;)try{if(n=1,r&&(i=2&l[0]?r.return:l[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,l[1])).done)return i;switch(r=0,i&&(l=[2&l[0],i.value]),l[0]){case 0:case 1:i=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,r=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===l[0]||2===l[0])){o=0;continue}if(3===l[0]&&(!i||l[1]>i[0]&&l[1]<i[3])){o.label=l[1];break}if(6===l[0]&&o.label<i[1]){o.label=i[1],i=l;break}if(i&&o.label<i[2]){o.label=i[2],o.ops.push(l);break}i[2]&&o.ops.pop(),o.trys.pop();continue}l=t.call(e,o)}catch(e){l=[6,e],r=0}finally{n=i=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return this.app.pluginSettingsManager.add("ai-api",{icon:"ApiOutlined",title:this.t("AI API Gateway"),aclSnippet:r}),this.app.pluginSettingsManager.add("ai-api.config",{title:this.t("Configuration"),Component:d,aclSnippet:r,sort:1}),this.app.pluginSettingsManager.add("ai-api.model-pricing",{title:this.t("Model pricing"),Component:b,aclSnippet:r,sort:2}),this.app.pluginSettingsManager.add("ai-api.model-metadata",{title:this.t("Model metadata"),Component:g,aclSnippet:r,sort:3}),this.app.pluginSettingsManager.add("ai-api.user-permissions",{title:this.t("User LLM permissions"),Component:h,aclSnippet:"pm.plugin-ai-api.user-permissions",sort:4}),this.app.pluginSettingsManager.add("ai-api.user-quotas",{title:this.t("User quotas"),Component:y,aclSnippet:r,sort:5}),this.app.pluginSettingsManager.add("ai-api.usage",{title:this.t("Usage"),Component:m,aclSnippet:r,sort:6}),(null==(e=this.app.pm.get(n()))?void 0:e.settingsUI)&&e.settingsUI.addPermissionsTab(function(e){var t=e.t,n=e.TabLayout,r=e.activeRole;return{key:"aiApi",label:t("AI API",{ns:["plugin-ai-api","client"]}),sort:25,children:o().createElement(n,null,o().createElement(w,{role:r}))}}),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,i){var o=e.apply(t,n);function u(e){a(o,r,i,u,c,"next",e)}function c(e){a(o,r,i,u,c,"throw",e)}u(void 0)})}).call(this)}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(i.prototype,t),i}(p(e.Plugin))}(),v}()});
|
|
@@ -0,0 +1,10 @@
|
|
|
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 p}});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 f(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 p(){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],p=c[1],y=d((0,n.useState)([]),2),h=y[0],v=y[1],b=d((0,n.useState)(!1),2),g=b[0],w=b[1],E=d((0,n.useState)(!1),2),S=E[0],k=E[1],I=d((0,n.useState)(),2),x=I[0],U=I[1],q=d((0,n.useState)(!1),2),F=q[0],T=q[1],C=(0,n.useCallback)(function(){return m(function(){var t,r,n,a;return f(this,function(i){switch(i.label){case 0:w(!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],p((0,u.m)(r,[])),v((0,u.m)(n,[])),[3,5];case 3:return a=i.sent(),l.message.error((0,u.g)(a)),[3,5];case 4:return w(!1),[7];case 5:return[2]}})})()},[e.api]);(0,n.useEffect)(function(){C()},[C]);var A=function(e){U(e),r.setFieldsValue(e),T(!0)},j=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:"")},P=[{title:t("User"),key:"user",width:180,render:function(e,t){return j(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("Context overflow behavior"),dataIndex:"contextOverflowBehavior",key:"contextOverflowBehavior",width:150,render:function(e){return"truncate"===e?t("Truncate oldest conversation turns"):t("Reject request")}},{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 f(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(){U(void 0),r.setFieldsValue({enabled:!0,periodType:"monthly",timezone:"UTC",currency:"USD",rejectUnpricedModel:!0,missingUsageBehavior:"use_reserved",contextOverflowBehavior:"reject"}),T(!0)}},t("Add quota"))},a().createElement(l.Table,{rowKey:"id",columns:P,dataSource:s,loading:g,scroll:{x:1100}}),a().createElement(l.Modal,{title:x?t("Edit quota"):t("Add quota"),open:F,onCancel:function(){return T(!1)},onOk:function(){return m(function(){var n,a;return f(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:x?"aiApiUserQuotaPolicies:update/".concat(x.id):"aiApiUserQuotaPolicies:create",method:"post",data:n})];case 3:return i.sent(),l.message.success(t("Saved successfully")),T(!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:!!x,showSearch:!0,optionFilterProp:"label",options:h.map(function(e){return{label:j(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:"contextOverflowBehavior",label:t("Context overflow behavior"),rules:[{required:!0}]},a().createElement(l.Select,{options:[{label:t("Reject request"),value:"reject"},{label:t("Truncate oldest conversation turns"),value:"truncate"}]})),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}})}}]);
|
package/dist/client-v2/index.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("plugin-ai-api/client-v2",["@nocobase/client-v2","dayjs","react","antd","@nocobase/flow-engine"],t):"object"==typeof exports?exports["plugin-ai-api/client-v2"]=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/flow-engine")):e["plugin-ai-api/client-v2"]=t(e["@nocobase/client-v2"],e.dayjs,e.react,e.antd,e["@nocobase/flow-engine"])}(self,function(e,t,n,r,i){return function(){"use strict";var o,a,u,c={485:function(t){t.exports=e},694:function(e){e.exports=i},59:function(e){e.exports=r},185:function(e){e.exports=t},155:function(e){e.exports=n}},l={};function p(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={exports:{}};return c[e](n,n.exports,p),n.exports}p.m=c,p.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(t,{a:t}),t},p.d=function(e,t){for(var n in t)p.o(t,n)&&!p.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},p.f={},p.e=function(e){return Promise.all(Object.keys(p.f).reduce(function(t,n){return p.f[n](e,t),t},[]))},p.u=function(e){return""+e+"."+({123:"05f1f649923f93eb",302:"d27fe4ea9b0b3bf5",562:"fb2948ee6402de95",757:"a117ce1cf7119cea",902:"
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("plugin-ai-api/client-v2",["@nocobase/client-v2","dayjs","react","antd","@nocobase/flow-engine"],t):"object"==typeof exports?exports["plugin-ai-api/client-v2"]=t(require("@nocobase/client-v2"),require("dayjs"),require("react"),require("antd"),require("@nocobase/flow-engine")):e["plugin-ai-api/client-v2"]=t(e["@nocobase/client-v2"],e.dayjs,e.react,e.antd,e["@nocobase/flow-engine"])}(self,function(e,t,n,r,i){return function(){"use strict";var o,a,u,c={485:function(t){t.exports=e},694:function(e){e.exports=i},59:function(e){e.exports=r},185:function(e){e.exports=t},155:function(e){e.exports=n}},l={};function p(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={exports:{}};return c[e](n,n.exports,p),n.exports}p.m=c,p.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(t,{a:t}),t},p.d=function(e,t){for(var n in t)p.o(t,n)&&!p.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},p.f={},p.e=function(e){return Promise.all(Object.keys(p.f).reduce(function(t,n){return p.f[n](e,t),t},[]))},p.u=function(e){return""+e+"."+({123:"05f1f649923f93eb",302:"d27fe4ea9b0b3bf5",562:"fb2948ee6402de95",757:"a117ce1cf7119cea",902:"c7c00a565085438a",952:"94100128b7757f56",97:"29c663318eebbd57"})[e]+".js"},p.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),p.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s={},p.l=function(e,t,n,r){if(s[e])return void s[e].push(t);if(void 0!==n)for(var i,o,a=document.getElementsByTagName("script"),u=0;u<a.length;u++){var c=a[u];if(c.getAttribute("src")==e||c.getAttribute("data-rspack")=="plugin-ai-api/client-v2:"+n){i=c;break}}i||(o=!0,(i=document.createElement("script")).timeout=120,p.nc&&i.setAttribute("nonce",p.nc),i.setAttribute("data-rspack","plugin-ai-api/client-v2:"+n),i.src=e),s[e]=[t];var l=function(t,n){i.onerror=i.onload=null,clearTimeout(f);var r=s[e];if(delete s[e],i.parentNode&&i.parentNode.removeChild(i),r&&r.forEach(function(e){return e(n)}),t)return t(n)},f=setTimeout(l.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=l.bind(null,i.onerror),i.onload=l.bind(null,i.onload),o&&document.head.appendChild(i)},p.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},p.g.importScripts&&(f=p.g.location+"");var s,f,d=p.g.document;if(!f&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(f=d.currentScript.src),!f)){var b=d.getElementsByTagName("script");if(b.length)for(var g=b.length-1;g>-1&&(!f||!/^http(s?):/.test(f));)f=b[g--].src}if(!f)throw Error("Automatic publicPath is not supported in this browser");p.p=f.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),o={889:0},p.f.j=function(e,t){var n=p.o(o,e)?o[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=o[e]=[t,r]});t.push(n[2]=r);var i=p.p+p.u(e),a=Error();p.l(i,function(t){if(p.o(o,e)&&(0!==(n=o[e])&&(o[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;a.message="Loading chunk "+e+" failed.\n("+r+": "+i+")",a.name="ChunkLoadError",a.type=r,a.request=i,n[1](a)}},"chunk-"+e,e)}},a=function(e,t){var n,r,i=t[0],a=t[1],u=t[2],c=0;if(i.some(function(e){return 0!==o[e]})){for(n in a)p.o(a,n)&&(p.m[n]=a[n]);u&&u(p)}for(e&&e(t);c<i.length;c++)r=i[c],p.o(o,r)&&o[r]&&o[r][0](),o[r]=0},(u=self.webpackChunkplugin_ai_api_client_v2=self.webpackChunkplugin_ai_api_client_v2||[]).forEach(a.bind(null,0)),u.push=a.bind(null,u.push.bind(u));var h={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var n=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");n.indexOf("/static/plugins/plugin-ai-api/dist/client-v2/")>=0&&(e=n.replace(/\/[^\/]+$/,"/"))}if(!e){var r=window.__webpack_public_path__||"";r&&("/"!==r.charAt(r.length-1)&&(r+="/"),e=r+"static/plugins/plugin-ai-api/dist/client-v2/")}if(!e){var i=window.__nocobase_modern_client_prefix__||"v",o="/"+(i=String(i).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var a=window.location.pathname||"/",u=a.indexOf(o);e=u>=0?a.slice(0,u+1):"/"}e&&(e=e.replace(RegExp("/"+i+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/plugin-ai-api/dist/client-v2/"}p.p=e}(),!function(){p.r(h),p.d(h,{default:function(){return c}}),p(155);var e=p(485),t="pm.plugin-ai-api.configuration";function n(e,t,n,r,i,o,a){try{var u=e[o](a),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,i)}function r(e,t,n){return(r=u()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&o(i,n.prototype),i}).apply(null,arguments)}function i(e){return(i=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function o(e,t){return(o=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function a(e){var t="function"==typeof Map?new Map:void 0;return(a=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return r(e,arguments,i(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),o(n,e)})(e)}function u(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(u=function(){return!!e})()}var c=function(e){var r;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function a(){var e,t;if(!(this instanceof a))throw TypeError("Cannot call a class as a function");return e=a,t=arguments,e=i(e),function(e,t){var n;if(t&&("object"==((n=t)&&"u">typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,u()?Reflect.construct(e,t||[],i(this).constructor):e.apply(this,t))}return a.prototype=Object.create(e&&e.prototype,{constructor:{value:a,writable:!0,configurable:!0}}),e&&o(a,e),r=[{key:"load",value:function(){var e;return(e=function(){var e,n,r;return function(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(o=0)),o;)try{if(n=1,r&&(i=2&l[0]?r.return:l[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,l[1])).done)return i;switch(r=0,i&&(l=[2&l[0],i.value]),l[0]){case 0:case 1:i=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,r=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===l[0]||2===l[0])){o=0;continue}if(3===l[0]&&(!i||l[1]>i[0]&&l[1]<i[3])){o.label=l[1];break}if(6===l[0]&&o.label<i[1]){o.label=i[1],i=l;break}if(i&&o.label<i[2]){o.label=i[2],o.ops.push(l);break}i[2]&&o.ops.pop(),o.trys.pop();continue}l=t.call(e,o)}catch(e){l=[6,e],r=0}finally{n=i=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(i){return this.pluginSettingsManager.addMenuItem({key:"ai-api",title:this.t("AI API Gateway"),icon:"ApiOutlined",aclSnippet:t}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"index",title:this.t("Configuration"),aclSnippet:t,sort:1,componentLoader:function(){return p.e("302").then(p.bind(p,581))}}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"model-pricing",title:this.t("Model pricing"),aclSnippet:t,sort:2,componentLoader:function(){return p.e("97").then(p.bind(p,760))}}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"model-metadata",title:this.t("Model metadata"),aclSnippet:t,sort:3,componentLoader:function(){return p.e("562").then(p.bind(p,641))}}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"user-permissions",title:this.t("User LLM permissions"),aclSnippet:"pm.plugin-ai-api.user-permissions",sort:4,componentLoader:function(){return p.e("123").then(p.bind(p,46))}}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"user-quotas",title:this.t("User quotas"),aclSnippet:t,sort:5,componentLoader:function(){return p.e("902").then(p.bind(p,77))}}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-api",key:"usage",title:this.t("Usage"),aclSnippet:t,sort:6,componentLoader:function(){return p.e("757").then(p.bind(p,364))}}),null==(r=this.app.pm.get("@nocobase/plugin-acl"))||null==(n=r.settingsUI)||null==(e=n.addPermissionsTab)||e.call(n,{key:"aiApi",label:this.t("AI API"),sort:25,componentLoader:function(){return p.e("952").then(p.bind(p,699))}}),[2]})},function(){var t=this,r=arguments;return new Promise(function(i,o){var a=e.apply(t,r);function u(e){n(a,i,o,u,c,"next",e)}function c(e){n(a,i,o,u,c,"throw",e)}u(void 0)})}).call(this)}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(a.prototype,r),a}(a(e.Plugin))}(),h}()});
|
package/dist/locale/en-US.json
CHANGED
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
"Missing usage behavior": "Missing usage behavior",
|
|
54
54
|
"Use reserved estimate": "Use reserved estimate",
|
|
55
55
|
"Allow without token charge": "Allow without token charge",
|
|
56
|
+
"Context overflow behavior": "Context overflow behavior",
|
|
57
|
+
"Reject request": "Reject request",
|
|
58
|
+
"Truncate oldest conversation turns": "Truncate oldest conversation turns",
|
|
56
59
|
"Started at": "Started at",
|
|
57
60
|
"Requested model": "Requested model",
|
|
58
61
|
"Resolved service": "Resolved service",
|
package/dist/locale/vi-VN.json
CHANGED
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
"Missing usage behavior": "Xử lý khi thiếu token usage",
|
|
54
54
|
"Use reserved estimate": "Dùng số liệu giữ chỗ để ước tính",
|
|
55
55
|
"Allow without token charge": "Cho phép và không tính token",
|
|
56
|
+
"Context overflow behavior": "Xử lý khi vượt context",
|
|
57
|
+
"Reject request": "Từ chối request",
|
|
58
|
+
"Truncate oldest conversation turns": "Cắt các lượt hội thoại cũ nhất",
|
|
56
59
|
"Started at": "Bắt đầu lúc",
|
|
57
60
|
"Requested model": "Model được yêu cầu",
|
|
58
61
|
"Resolved service": "Service đã resolve",
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
"Missing usage behavior": "缺少用量时的行为",
|
|
54
54
|
"Use reserved estimate": "使用预留估算",
|
|
55
55
|
"Allow without token charge": "允许且不计令牌",
|
|
56
|
+
"Context overflow behavior": "上下文超限处理",
|
|
57
|
+
"Reject request": "拒绝请求",
|
|
58
|
+
"Truncate oldest conversation turns": "截断最早的对话轮次",
|
|
56
59
|
"Started at": "开始时间",
|
|
57
60
|
"Requested model": "请求模型",
|
|
58
61
|
"Resolved service": "解析后的服务",
|
|
@@ -51,7 +51,8 @@ var ai_api_user_quota_policies_default = (0, import_database.defineCollection)({
|
|
|
51
51
|
{ name: "costLimit", type: "decimal", precision: 20, scale: 8, allowNull: true },
|
|
52
52
|
{ name: "currency", type: "string", allowNull: false, defaultValue: "USD" },
|
|
53
53
|
{ name: "rejectUnpricedModel", type: "boolean", defaultValue: true },
|
|
54
|
-
{ name: "missingUsageBehavior", type: "string", allowNull: false, defaultValue: "use_reserved" }
|
|
54
|
+
{ name: "missingUsageBehavior", type: "string", allowNull: false, defaultValue: "use_reserved" },
|
|
55
|
+
{ name: "contextOverflowBehavior", type: "string", allowNull: false, defaultValue: "reject" }
|
|
55
56
|
],
|
|
56
57
|
indexes: [
|
|
57
58
|
{
|
|
@@ -41,8 +41,10 @@ var import_role_permission = require("../middleware/role-permission");
|
|
|
41
41
|
var import_user_permissions = require("../utils/user-permissions");
|
|
42
42
|
var import_usage = require("../usage");
|
|
43
43
|
var import_billing = require("../billing");
|
|
44
|
+
var import_direct_llm_context = require("../utils/direct-llm-context");
|
|
44
45
|
var import_app_observability = require("../utils/app-observability");
|
|
45
46
|
async function handleChatCompletions(ctx, plugin) {
|
|
47
|
+
var _a;
|
|
46
48
|
const body = ctx.request.body;
|
|
47
49
|
if (!(body == null ? void 0 : body.model)) {
|
|
48
50
|
ctx.status = 400;
|
|
@@ -126,7 +128,6 @@ async function handleChatCompletions(ctx, plugin) {
|
|
|
126
128
|
ctx.body = (0, import_openai_format.toOpenAIError)(500, `Provider '${service.provider}' not registered`, "server_error");
|
|
127
129
|
return;
|
|
128
130
|
}
|
|
129
|
-
await (0, import_billing.prepareLlmBilling)(ctx, resolved);
|
|
130
131
|
const providerRequestParameters = getProviderRequestParameters(body);
|
|
131
132
|
if (stream) {
|
|
132
133
|
const streamOptions = isRecord(body.stream_options) ? body.stream_options : {};
|
|
@@ -146,12 +147,6 @@ async function handleChatCompletions(ctx, plugin) {
|
|
|
146
147
|
if (body.frequency_penalty !== void 0) modelOptions.frequencyPenalty = body.frequency_penalty;
|
|
147
148
|
if (body.presence_penalty !== void 0) modelOptions.presencePenalty = body.presence_penalty;
|
|
148
149
|
if (body.stop !== void 0) modelOptions.stop = body.stop;
|
|
149
|
-
const Provider = providerMeta.provider;
|
|
150
|
-
const provider = new Provider({
|
|
151
|
-
app: ctx.app,
|
|
152
|
-
serviceOptions: service.options,
|
|
153
|
-
modelOptions
|
|
154
|
-
});
|
|
155
150
|
let systemPrompt = "";
|
|
156
151
|
if (config == null ? void 0 : config.defaultAiEmployee) {
|
|
157
152
|
if (!(0, import_role_permission.checkEmployeeAccess)(ctx, config.defaultAiEmployee)) {
|
|
@@ -171,11 +166,27 @@ async function handleChatCompletions(ctx, plugin) {
|
|
|
171
166
|
systemPrompt = employee.about || employee.defaultPrompt || "";
|
|
172
167
|
}
|
|
173
168
|
}
|
|
174
|
-
|
|
169
|
+
let messages = [...body.messages];
|
|
175
170
|
const hasSystemMessage = messages.some((m) => m.role === "system");
|
|
176
171
|
if (systemPrompt && !hasSystemMessage) {
|
|
177
172
|
messages.unshift({ role: "system", content: systemPrompt });
|
|
178
173
|
}
|
|
174
|
+
const preparedContext = await (0, import_direct_llm_context.prepareDirectLlmContext)(ctx, {
|
|
175
|
+
serviceName: service.name,
|
|
176
|
+
modelId,
|
|
177
|
+
messages,
|
|
178
|
+
tools: body.tools,
|
|
179
|
+
maxCompletionTokens: body.max_completion_tokens,
|
|
180
|
+
maxTokens: body.max_tokens
|
|
181
|
+
});
|
|
182
|
+
messages = preparedContext.messages;
|
|
183
|
+
await (0, import_billing.prepareLlmBilling)(ctx, resolved);
|
|
184
|
+
const Provider = providerMeta.provider;
|
|
185
|
+
const provider = new Provider({
|
|
186
|
+
app: ctx.app,
|
|
187
|
+
serviceOptions: service.options,
|
|
188
|
+
modelOptions
|
|
189
|
+
});
|
|
179
190
|
const langchainMessages = messages.map((msg) => {
|
|
180
191
|
const role = msg.role === "assistant" ? "ai" : msg.role;
|
|
181
192
|
const content = normalizeMessageContent(msg.content);
|
|
@@ -218,15 +229,16 @@ async function handleChatCompletions(ctx, plugin) {
|
|
|
218
229
|
}
|
|
219
230
|
} catch (err) {
|
|
220
231
|
ctx.log.error("AI API chat completions error:", err);
|
|
221
|
-
if (!ctx.res.headersSent) {
|
|
232
|
+
if (!((_a = ctx.res) == null ? void 0 : _a.headersSent)) {
|
|
222
233
|
const isQuotaError = err instanceof import_billing.AiApiQuotaError;
|
|
223
|
-
|
|
234
|
+
const isContextError = err instanceof import_direct_llm_context.DirectLlmContextError;
|
|
235
|
+
ctx.status = isQuotaError ? 429 : isContextError ? 400 : 500;
|
|
224
236
|
if (isQuotaError) ctx.set("X-RateLimit-Reason", err.code);
|
|
225
237
|
ctx.body = (0, import_openai_format.toOpenAIError)(
|
|
226
238
|
ctx.status,
|
|
227
239
|
getErrorMessage(err, "Internal server error"),
|
|
228
|
-
isQuotaError ? "quota_error" : "server_error",
|
|
229
|
-
isQuotaError ? err.code : void 0
|
|
240
|
+
isQuotaError ? "quota_error" : isContextError ? "invalid_request_error" : "server_error",
|
|
241
|
+
isQuotaError || isContextError ? err.code : void 0
|
|
230
242
|
);
|
|
231
243
|
}
|
|
232
244
|
}
|
|
@@ -35,8 +35,10 @@ var import_user_permissions = require("../utils/user-permissions");
|
|
|
35
35
|
var import_streaming = require("../utils/streaming");
|
|
36
36
|
var import_usage = require("../usage");
|
|
37
37
|
var import_billing = require("../billing");
|
|
38
|
+
var import_direct_llm_context = require("../utils/direct-llm-context");
|
|
38
39
|
var import_app_observability = require("../utils/app-observability");
|
|
39
40
|
async function handleCompletions(ctx, plugin) {
|
|
41
|
+
var _a;
|
|
40
42
|
const body = ctx.request.body;
|
|
41
43
|
if (!(body == null ? void 0 : body.model)) {
|
|
42
44
|
ctx.status = 400;
|
|
@@ -98,7 +100,6 @@ async function handleCompletions(ctx, plugin) {
|
|
|
98
100
|
ctx.body = (0, import_openai_format.toOpenAIError)(500, `Provider '${service.provider}' not registered`, "server_error");
|
|
99
101
|
return;
|
|
100
102
|
}
|
|
101
|
-
await (0, import_billing.prepareLlmBilling)(ctx, resolved);
|
|
102
103
|
const modelOptions = {
|
|
103
104
|
model: modelId,
|
|
104
105
|
llmService: service.name
|
|
@@ -107,14 +108,8 @@ async function handleCompletions(ctx, plugin) {
|
|
|
107
108
|
if (body.top_p !== void 0) modelOptions.topP = body.top_p;
|
|
108
109
|
if (body.max_tokens !== void 0) modelOptions.maxTokens = body.max_tokens;
|
|
109
110
|
if (body.stop !== void 0) modelOptions.stop = body.stop;
|
|
110
|
-
const Provider = providerMeta.provider;
|
|
111
|
-
const provider = new Provider({
|
|
112
|
-
app: ctx.app,
|
|
113
|
-
serviceOptions: service.options,
|
|
114
|
-
modelOptions
|
|
115
|
-
});
|
|
116
111
|
const prompt = typeof body.prompt === "string" ? body.prompt : Array.isArray(body.prompt) ? body.prompt.join("\n") : String(body.prompt);
|
|
117
|
-
const
|
|
112
|
+
const messages = [];
|
|
118
113
|
if (config == null ? void 0 : config.defaultAiEmployee) {
|
|
119
114
|
const employee = await ctx.db.getRepository("aiEmployees").findOne({
|
|
120
115
|
filter: { username: config.defaultAiEmployee }
|
|
@@ -122,11 +117,28 @@ async function handleCompletions(ctx, plugin) {
|
|
|
122
117
|
if (employee) {
|
|
123
118
|
const systemPrompt = employee.about || employee.defaultPrompt || "";
|
|
124
119
|
if (systemPrompt) {
|
|
125
|
-
|
|
120
|
+
messages.push({ role: "system", content: systemPrompt });
|
|
126
121
|
}
|
|
127
122
|
}
|
|
128
123
|
}
|
|
129
|
-
|
|
124
|
+
messages.push({ role: "user", content: prompt });
|
|
125
|
+
const preparedContext = await (0, import_direct_llm_context.prepareDirectLlmContext)(ctx, {
|
|
126
|
+
serviceName: service.name,
|
|
127
|
+
modelId,
|
|
128
|
+
messages,
|
|
129
|
+
maxTokens: body.max_tokens
|
|
130
|
+
});
|
|
131
|
+
await (0, import_billing.prepareLlmBilling)(ctx, resolved);
|
|
132
|
+
const Provider = providerMeta.provider;
|
|
133
|
+
const provider = new Provider({
|
|
134
|
+
app: ctx.app,
|
|
135
|
+
serviceOptions: service.options,
|
|
136
|
+
modelOptions
|
|
137
|
+
});
|
|
138
|
+
const langchainMessages = preparedContext.messages.map((message) => [
|
|
139
|
+
message.role === "user" ? "human" : message.role,
|
|
140
|
+
String(message.content ?? "")
|
|
141
|
+
]);
|
|
130
142
|
const completionId = (0, import_openai_format.generateCompletionId)().replace("chatcmpl-", "cmpl-");
|
|
131
143
|
const chatModel = provider.createModel();
|
|
132
144
|
(0, import_billing.markLlmProviderAttempted)(ctx);
|
|
@@ -144,15 +156,16 @@ async function handleCompletions(ctx, plugin) {
|
|
|
144
156
|
}
|
|
145
157
|
} catch (err) {
|
|
146
158
|
ctx.log.error("AI API completions error:", err);
|
|
147
|
-
if (!ctx.res.headersSent) {
|
|
159
|
+
if (!((_a = ctx.res) == null ? void 0 : _a.headersSent)) {
|
|
148
160
|
const isQuotaError = err instanceof import_billing.AiApiQuotaError;
|
|
149
|
-
|
|
161
|
+
const isContextError = err instanceof import_direct_llm_context.DirectLlmContextError;
|
|
162
|
+
ctx.status = isQuotaError ? 429 : isContextError ? 400 : 500;
|
|
150
163
|
if (isQuotaError) ctx.set("X-RateLimit-Reason", err.code);
|
|
151
164
|
ctx.body = (0, import_openai_format.toOpenAIError)(
|
|
152
165
|
ctx.status,
|
|
153
166
|
getErrorMessage(err, "Internal server error"),
|
|
154
|
-
isQuotaError ? "quota_error" : "server_error",
|
|
155
|
-
isQuotaError ? err.code : void 0
|
|
167
|
+
isQuotaError ? "quota_error" : isContextError ? "invalid_request_error" : "server_error",
|
|
168
|
+
isQuotaError || isContextError ? err.code : void 0
|
|
156
169
|
);
|
|
157
170
|
}
|
|
158
171
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var direct_llm_context_exports = {};
|
|
28
|
+
__export(direct_llm_context_exports, {
|
|
29
|
+
DirectLlmContextError: () => DirectLlmContextError,
|
|
30
|
+
prepareDirectLlmContext: () => prepareDirectLlmContext
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(direct_llm_context_exports);
|
|
33
|
+
class DirectLlmContextError extends Error {
|
|
34
|
+
constructor(code, message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.code = code;
|
|
37
|
+
this.name = "DirectLlmContextError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getValue(record, key) {
|
|
41
|
+
var _a;
|
|
42
|
+
return ((_a = record == null ? void 0 : record.get) == null ? void 0 : _a.call(record, key)) ?? (record == null ? void 0 : record[key]);
|
|
43
|
+
}
|
|
44
|
+
function positiveInteger(value) {
|
|
45
|
+
const parsed = Number(value);
|
|
46
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
47
|
+
}
|
|
48
|
+
function hasImageContent(value) {
|
|
49
|
+
return Array.isArray(value) && value.some(
|
|
50
|
+
(block) => typeof block === "object" && block !== null && block.type === "image_url"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function estimateValueTokens(value) {
|
|
54
|
+
if (value === void 0) return 0;
|
|
55
|
+
return Math.ceil(Buffer.byteLength(JSON.stringify(value), "utf8") / 3);
|
|
56
|
+
}
|
|
57
|
+
function estimateMessagesTokens(messages) {
|
|
58
|
+
return messages.reduce((total, message) => total + estimateValueTokens(message) + 4, 0);
|
|
59
|
+
}
|
|
60
|
+
function containsUnsupportedContent(messages) {
|
|
61
|
+
return messages.some((message) => hasImageContent(message.content));
|
|
62
|
+
}
|
|
63
|
+
function isInstruction(message) {
|
|
64
|
+
return message.role === "system" || message.role === "developer";
|
|
65
|
+
}
|
|
66
|
+
function splitTurns(messages) {
|
|
67
|
+
const fixed = [];
|
|
68
|
+
const turns = [];
|
|
69
|
+
let currentTurn;
|
|
70
|
+
for (const message of messages) {
|
|
71
|
+
if (isInstruction(message)) {
|
|
72
|
+
fixed.push(message);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (message.role === "user" || !currentTurn) {
|
|
76
|
+
currentTurn = [message];
|
|
77
|
+
turns.push(currentTurn);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
currentTurn.push(message);
|
|
81
|
+
}
|
|
82
|
+
return { fixed, turns };
|
|
83
|
+
}
|
|
84
|
+
function messagesWithTurns(messages, turns) {
|
|
85
|
+
const retainedMessages = new Set(turns.flat());
|
|
86
|
+
return messages.filter((message) => isInstruction(message) || retainedMessages.has(message));
|
|
87
|
+
}
|
|
88
|
+
async function loadModelMetadata(ctx, serviceName, modelId) {
|
|
89
|
+
const row = await ctx.db.getRepository("aiApiModelMetadata").findOne({
|
|
90
|
+
filter: { llmService: serviceName, model: modelId, enabled: true }
|
|
91
|
+
});
|
|
92
|
+
const contextWindow = positiveInteger(getValue(row, "contextWindow"));
|
|
93
|
+
const maxCompletionTokens = positiveInteger(getValue(row, "maxCompletionTokens"));
|
|
94
|
+
if (!contextWindow || !maxCompletionTokens) {
|
|
95
|
+
throw new DirectLlmContextError(
|
|
96
|
+
"model_context_metadata_not_configured",
|
|
97
|
+
`Context metadata is not configured for '${serviceName}/${modelId}'. Configure context window and max completion tokens.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return { contextWindow, maxCompletionTokens };
|
|
101
|
+
}
|
|
102
|
+
async function resolveOverflowBehavior(ctx) {
|
|
103
|
+
var _a;
|
|
104
|
+
const userId = (_a = ctx.state.currentUser) == null ? void 0 : _a.id;
|
|
105
|
+
if (userId === null || userId === void 0) return "reject";
|
|
106
|
+
const policy = await ctx.db.getRepository("aiApiUserQuotaPolicies").findOne({
|
|
107
|
+
filter: { userId, enabled: true }
|
|
108
|
+
});
|
|
109
|
+
return getValue(policy, "contextOverflowBehavior") === "truncate" ? "truncate" : "reject";
|
|
110
|
+
}
|
|
111
|
+
function resolveReservedOutputTokens(options, metadata) {
|
|
112
|
+
const requested = positiveInteger(options.maxCompletionTokens ?? options.maxTokens);
|
|
113
|
+
if (requested && requested > metadata.maxCompletionTokens) {
|
|
114
|
+
throw new DirectLlmContextError(
|
|
115
|
+
"max_completion_tokens_exceeds_model_limit",
|
|
116
|
+
`Requested max completion tokens (${requested}) exceeds the model limit (${metadata.maxCompletionTokens}).`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
return requested ?? metadata.maxCompletionTokens;
|
|
120
|
+
}
|
|
121
|
+
async function prepareDirectLlmContext(ctx, options) {
|
|
122
|
+
if (containsUnsupportedContent(options.messages)) {
|
|
123
|
+
throw new DirectLlmContextError(
|
|
124
|
+
"context_estimation_unsupported",
|
|
125
|
+
"Context enforcement does not support image_url content without a model-specific vision token estimator."
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const [metadata, behavior] = await Promise.all([
|
|
129
|
+
loadModelMetadata(ctx, options.serviceName, options.modelId),
|
|
130
|
+
resolveOverflowBehavior(ctx)
|
|
131
|
+
]);
|
|
132
|
+
const reservedOutputTokens = resolveReservedOutputTokens(options, metadata);
|
|
133
|
+
const inputTokenBudget = metadata.contextWindow - reservedOutputTokens;
|
|
134
|
+
if (inputTokenBudget <= 0) {
|
|
135
|
+
throw new DirectLlmContextError(
|
|
136
|
+
"context_length_exceeded",
|
|
137
|
+
`The model context window (${metadata.contextWindow}) leaves no input capacity after reserving ${reservedOutputTokens} output tokens.`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const fixedOverheadTokens = estimateValueTokens(options.tools) + (options.tools === void 0 ? 0 : 4);
|
|
141
|
+
const originalEstimate = estimateMessagesTokens(options.messages) + fixedOverheadTokens;
|
|
142
|
+
if (originalEstimate <= inputTokenBudget) {
|
|
143
|
+
return {
|
|
144
|
+
messages: options.messages,
|
|
145
|
+
estimatedInputTokens: originalEstimate,
|
|
146
|
+
inputTokenBudget,
|
|
147
|
+
reservedOutputTokens,
|
|
148
|
+
truncated: false
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (behavior === "reject") {
|
|
152
|
+
throw new DirectLlmContextError(
|
|
153
|
+
"context_length_exceeded",
|
|
154
|
+
`Estimated input tokens (${originalEstimate}) exceed the allowed input budget (${inputTokenBudget}).`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const { turns } = splitTurns(options.messages);
|
|
158
|
+
let remainingTurns = turns;
|
|
159
|
+
let messages = messagesWithTurns(options.messages, remainingTurns);
|
|
160
|
+
let estimatedInputTokens = estimateMessagesTokens(messages) + fixedOverheadTokens;
|
|
161
|
+
while (remainingTurns.length > 1 && estimatedInputTokens > inputTokenBudget) {
|
|
162
|
+
remainingTurns = remainingTurns.slice(1);
|
|
163
|
+
messages = messagesWithTurns(options.messages, remainingTurns);
|
|
164
|
+
estimatedInputTokens = estimateMessagesTokens(messages) + fixedOverheadTokens;
|
|
165
|
+
}
|
|
166
|
+
if (estimatedInputTokens > inputTokenBudget) {
|
|
167
|
+
throw new DirectLlmContextError(
|
|
168
|
+
"context_length_exceeded",
|
|
169
|
+
`The fixed instructions, tools, and newest conversation turn require ${estimatedInputTokens} input tokens, exceeding the allowed budget (${inputTokenBudget}).`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
messages,
|
|
174
|
+
estimatedInputTokens,
|
|
175
|
+
inputTokenBudget,
|
|
176
|
+
reservedOutputTokens,
|
|
177
|
+
truncated: messages.length !== options.messages.length
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
181
|
+
0 && (module.exports = {
|
|
182
|
+
DirectLlmContextError,
|
|
183
|
+
prepareDirectLlmContext
|
|
184
|
+
});
|
|
@@ -101,6 +101,9 @@ function validateQuotaPolicy(model) {
|
|
|
101
101
|
if (!["allow", "use_reserved"].includes(String(model.get("missingUsageBehavior")))) {
|
|
102
102
|
throw new Error("missingUsageBehavior must be allow or use_reserved.");
|
|
103
103
|
}
|
|
104
|
+
if (!["reject", "truncate"].includes(String(model.get("contextOverflowBehavior") ?? "reject"))) {
|
|
105
|
+
throw new Error("contextOverflowBehavior must be reject or truncate.");
|
|
106
|
+
}
|
|
104
107
|
try {
|
|
105
108
|
(0, import_dayjs.default)().tz(String(model.get("timezone") || "UTC"));
|
|
106
109
|
} catch {
|