plugin-build-guide-block 1.1.7 → 1.1.9
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.
|
@@ -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_build_guide_block_client_v2=self.webpackChunkplugin_build_guide_block_client_v2||[]).push([["376"],{571:function(e,t,r){r.d(t,{UserGuideManager:function(){return v}});var n=r(155),a=r.n(n),l=r(59),u=r(375),i=r(485),c=r(953);function o(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,u){try{var i=e[l](u),c=i.value}catch(e){r(e);return}i.done?t(c):Promise.resolve(c).then(n,a)}function d(e){return function(){var t=this,r=arguments;return new Promise(function(n,a){var l=e.apply(t,r);function u(e){s(l,n,a,u,i,"next",e)}function i(e){s(l,n,a,u,i,"throw",e)}u(void 0)})}}function m(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=[],u=!0,i=!1;try{for(a=a.call(e);!(u=(r=a.next()).done)&&(l.push(r.value),!t||l.length!==t);u=!0);}catch(e){i=!0,n=e}finally{try{u||null==a.return||a.return()}finally{if(i)throw n}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return o(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 o(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:[]},u=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),i=Object.defineProperty;return i(u,"next",{value:c(0)}),i(u,"throw",{value:c(1)}),i(u,"return",{value:c(2)}),"function"==typeof Symbol&&i(u,Symbol.iterator,{value:function(){return this}}),u;function c(i){return function(c){var o=[i,c];if(r)throw TypeError("Generator is already executing.");for(;u&&(u=0,o[0]&&(l=0)),l;)try{if(r=1,n&&(a=2&o[0]?n.return:o[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,o[1])).done)return a;switch(n=0,a&&(o=[2&o[0],a.value]),o[0]){case 0:case 1:a=o;break;case 4:return l.label++,{value:o[1],done:!1};case 5:l.label++,n=o[1],o=[0];continue;case 7:o=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===o[0]||2===o[0])){l=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]<a[3])){l.label=o[1];break}if(6===o[0]&&l.label<a[1]){l.label=a[1],a=o;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(o);break}a[2]&&l.ops.pop(),l.trys.pop();continue}o=t.call(e,l)}catch(e){o=[6,e],n=0}finally{r=a=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}}}var f={draft:"default",building:"blue",completed:"success",error:"error"},h=[{label:"HTML",value:"html"},{label:"Markdown",value:"markdown"}],b=function(e){var t=Number(e);return Number.isFinite(t)?Math.max(1,Math.min(12,Math.round(t))):5},v=function(){var e=(0,c.useTranslation)().t,t=(0,i.useApp)().apiClient,r=l.App.useApp(),o=r.message,s=r.modal,v=m(l.Form.useForm(),1)[0],y=l.Form.useWatch("llmService",v),S=m((0,n.useState)([]),2),g=S[0],E=S[1],C=m((0,n.useState)(!1),2),w=C[0],k=C[1],F=m((0,n.useState)(!1),2),B=F[0],I=F[1],T=m((0,n.useState)(null),2),x=T[0],A=T[1],P=m((0,n.useState)(!1),2),G=P[0],M=P[1],_=m((0,n.useState)([]),2),O=_[0],D=_[1],j=m((0,n.useState)([]),2),q=j[0],L=j[1],V=m((0,n.useState)(null),2),N=V[0],U=V[1],R=(0,n.useRef)(null),H=(0,n.useCallback)(function(){return d(function(){var e,r;return p(this,function(n){switch(n.label){case 0:k(!0),n.label=1;case 1:return n.trys.push([1,,3,4]),[4,t.resource("aiBuildGuideSpaces").list({appends:["documents"],sort:["-createdAt"],paginate:!1})];case 2:return E((null==(r=n.sent())||null==(e=r.data)?void 0:e.data)||[]),[3,4];case 3:return k(!1),[7];case 4:return[2]}})})()},[t]);(0,n.useEffect)(function(){H()},[H]),(0,n.useEffect)(function(){return function(){R.current&&clearTimeout(R.current)}},[]);var K=(0,n.useCallback)(function(){return d(function(){var e,r;return p(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,t.resource("ai").listLLMServices()];case 1:return D(((null==(r=n.sent())||null==(e=r.data)?void 0:e.data)||[]).map(function(e){return{label:e.title||e.name,value:e.name}})),[3,3];case 2:return n.sent(),D([]),[3,3];case 3:return[2]}})})()},[t]),W=(0,n.useCallback)(function(e){return d(function(){var r,n;return p(this,function(a){switch(a.label){case 0:if(!e)return L([]),[2];a.label=1;case 1:return a.trys.push([1,3,,4]),[4,t.resource("ai").listModels({llmService:e})];case 2:return L(((null==(n=a.sent())||null==(r=n.data)?void 0:r.data)||[]).map(function(e){return{label:e.id||e.name,value:e.id||e.name}})),[3,4];case 3:return a.sent(),L([]),[3,4];case 4:return[2]}})})()},[t]);(0,n.useEffect)(function(){W(y)},[y,W]);var Y=function(e){A(e.id),v.resetFields(),v.setFieldsValue({title:e.title,llmService:e.llmService,model:e.model,outputFormat:e.outputFormat||"html",targetChapterCount:b(e.targetChapterCount),chapterGuidance:e.chapterGuidance,systemPrompt:e.systemPrompt}),K(),W(e.llmService),I(!0)},$=(0,n.useCallback)(function(){R.current&&(clearTimeout(R.current),R.current=null),U(null)},[]),z=[{title:e("Title"),dataIndex:"title"},{title:e("Status"),dataIndex:"status",render:function(e){return e?a().createElement(l.Tag,{color:f[e]||"default"},String(e).toUpperCase()):null}},{title:e("Build Phase"),dataIndex:"buildPhase"},{title:e("Chapters"),dataIndex:"pageCount"},{title:e("Actions"),key:"actions",render:function(r,n){return a().createElement(l.Space,{split:"|"},a().createElement(l.Button,{type:"link",icon:a().createElement(u.PlayCircleOutlined,null),loading:N===n.id,disabled:"building"===n.status,onClick:function(){return d(function(){var r,a,l,u,i,c,s;return p(this,function(m){switch(m.label){case 0:U(n.id),m.label=1;case 1:return m.trys.push([1,3,,4]),[4,t.resource("aiBuildGuideSpaces").build({filterByTk:n.id})];case 2:return m.sent(),o.success(e("Build started")),r=Date.now(),a=!1,l=function(){return d(function(){var u,i,c,s,d;return p(this,function(m){switch(m.label){case 0:return m.trys.push([0,4,,6]),[4,t.resource("aiBuildGuideSpaces").get({filterByTk:n.id})];case 1:if("building"===(s=null==(c=m.sent())||null==(i=c.data)||null==(u=i.data)?void 0:u.status))return[3,3];return $(),[4,H()];case 2:return m.sent(),"completed"===s?o.success(e("Build completed")):"error"===s&&o.error(e("Build failed")),[2];case 3:return(d=Date.now()-r)>=3e5&&!a&&(a=!0,o.info(e("Build is still running"))),R.current=setTimeout(l,d>=3e5?1e4:3e3),[3,6];case 4:return m.sent(),$(),[4,H()];case 5:return m.sent(),[3,6];case 6:return[2]}})})()},R.current=setTimeout(l,3e3),[3,4];case 3:return u=m.sent(),o.error((null==u||null==(s=u.response)||null==(c=s.data)||null==(i=c.error)?void 0:i.message)||e("Build failed")),U(null),[3,4];case 4:return[2]}})})()}},e("Build")),a().createElement("a",{onClick:function(){return Y(n)}},e("Edit")),a().createElement("a",{onClick:function(){return s.confirm({title:e("Delete"),content:e("Are you sure you want to delete this space?"),onOk:function(){return d(function(){return p(this,function(r){switch(r.label){case 0:return[4,t.resource("aiBuildGuideSpaces").destroy({filterByTk:n.id})];case 1:return r.sent(),o.success(e("Deleted")),[4,H()];case 2:return r.sent(),[2]}})})()}})}},e("Delete")))}}];return a().createElement("div",null,a().createElement(l.Space,{style:{marginBottom:16}},a().createElement(l.Button,{type:"primary",icon:a().createElement(u.PlusOutlined,null),onClick:function(){A(null),v.resetFields(),v.setFieldsValue({outputFormat:"html",targetChapterCount:5,systemPrompt:"You are an expert technical writer. Generate a comprehensive user guide based on the provided documents."}),K(),I(!0)}},e("Create space")),a().createElement(l.Button,{onClick:H},e("Refresh"))),a().createElement(l.Table,{rowKey:"id",loading:w,dataSource:g,columns:z}),a().createElement(l.Drawer,{title:x?e("Edit space"):e("Create space"),open:B,onClose:function(){return I(!1)},width:640,footer:a().createElement(l.Space,{style:{float:"right"}},a().createElement(l.Button,{onClick:function(){return I(!1)}},e("Cancel")),a().createElement(l.Button,{type:"primary",loading:G,onClick:function(){return d(function(){var r,n,a,l,u;return p(this,function(i){switch(i.label){case 0:return[4,v.validateFields()];case 1:(r=i.sent()).targetChapterCount=b(r.targetChapterCount),M(!0),i.label=2;case 2:if(i.trys.push([2,8,9,10]),!x)return[3,4];return[4,t.resource("aiBuildGuideSpaces").update({filterByTk:x,values:r})];case 3:return i.sent(),[3,6];case 4:return[4,t.resource("aiBuildGuideSpaces").create({values:r})];case 5:i.sent(),i.label=6;case 6:return o.success(e("Saved successfully")),I(!1),[4,H()];case 7:return i.sent(),[3,10];case 8:if(null==(n=i.sent())?void 0:n.errorFields)return[2];return o.error((null==n||null==(u=n.response)||null==(l=u.data)||null==(a=l.error)?void 0:a.message)||e("Save failed")),[3,10];case 9:return M(!1),[7];case 10:return[2]}})})()}},e("Submit")))},a().createElement(l.Form,{form:v,layout:"vertical",onValuesChange:function(e){"llmService"in e&&v.setFieldValue("model",void 0)}},a().createElement(l.Form.Item,{name:"title",label:e("Title"),rules:[{required:!0}]},a().createElement(l.Input,null)),a().createElement(l.Form.Item,{name:"llmService",label:e("LLM Service"),rules:[{required:!0}]},a().createElement(l.Select,{options:O,onFocus:K,showSearch:!0,optionFilterProp:"label"})),a().createElement(l.Form.Item,{name:"model",label:e("Model"),rules:[{required:!0}]},a().createElement(l.Select,{options:q,disabled:!y,showSearch:!0,optionFilterProp:"label"})),a().createElement(l.Form.Item,{name:"outputFormat",label:e("Output format"),rules:[{required:!0}]},a().createElement(l.Select,{options:h})),a().createElement(l.Form.Item,{name:"targetChapterCount",label:e("Target chapters"),rules:[{required:!0}]},a().createElement(l.InputNumber,{min:1,max:12,precision:0,style:{width:"100%"}})),a().createElement(l.Form.Item,{name:"chapterGuidance",label:e("Chapter guidance")},a().createElement(l.Input.TextArea,{rows:3,placeholder:e("Describe how the guide should be split into chapters")})),a().createElement(l.Form.Item,{name:"systemPrompt",label:e("System Prompt")},a().createElement(l.Input.TextArea,{rows:4})))))}}}]);
|
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("react-i18next"),require("@nocobase/client-v2"),require("
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react-i18next"),require("@nocobase/client-v2"),require("react"),require("antd"),require("@ant-design/icons")):"function"==typeof define&&define.amd?define("plugin-build-guide-block/client-v2",["react-i18next","@nocobase/client-v2","react","antd","@ant-design/icons"],t):"object"==typeof exports?exports["plugin-build-guide-block/client-v2"]=t(require("react-i18next"),require("@nocobase/client-v2"),require("react"),require("antd"),require("@ant-design/icons")):e["plugin-build-guide-block/client-v2"]=t(e["react-i18next"],e["@nocobase/client-v2"],e.react,e.antd,e["@ant-design/icons"])}(self,function(e,t,n,r,o){return function(){"use strict";var i,u,c,a={375:function(e){e.exports=o},485:function(e){e.exports=t},59:function(e){e.exports=r},155:function(e){e.exports=n},953:function(t){t.exports=e}},l={};function f(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={exports:{}};return a[e](n,n.exports,f),n.exports}f.m=a,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+".bea427a4cf8864b4.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)},p={},f.l=function(e,t,n,r){if(p[e])return void p[e].push(t);if(void 0!==n)for(var o,i,u=document.getElementsByTagName("script"),c=0;c<u.length;c++){var a=u[c];if(a.getAttribute("src")==e||a.getAttribute("data-rspack")=="plugin-build-guide-block/client-v2:"+n){o=a;break}}o||(i=!0,(o=document.createElement("script")).timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.setAttribute("data-rspack","plugin-build-guide-block/client-v2:"+n),o.src=e),p[e]=[t];var l=function(t,n){o.onerror=o.onload=null,clearTimeout(s);var r=p[e];if(delete p[e],o.parentNode&&o.parentNode.removeChild(o),r&&r.forEach(function(e){return e(n)}),t)return t(n)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),i&&document.head.appendChild(o)},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&&(s=f.g.location+"");var p,s,d=f.g.document;if(!s&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(s=d.currentScript.src),!s)){var b=d.getElementsByTagName("script");if(b.length)for(var v=b.length-1;v>-1&&(!s||!/^http(s?):/.test(s));)s=b[v--].src}if(!s)throw Error("Automatic publicPath is not supported in this browser");f.p=s.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),i={889:0},f.f.j=function(e,t){var n=f.o(i,e)?i[e]:void 0;if(0!==n)if(n)t.push(n[2]);else{var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=f.p+f.u(e),u=Error();f.l(o,function(t){if(f.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}},u=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],a=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)f.o(u,n)&&(f.m[n]=u[n]);c&&c(f)}for(e&&e(t);a<o.length;a++)r=o[a],f.o(i,r)&&i[r]&&i[r][0](),i[r]=0},(c=self.webpackChunkplugin_build_guide_block_client_v2=self.webpackChunkplugin_build_guide_block_client_v2||[]).forEach(u.bind(null,0)),c.push=u.bind(null,c.push.bind(c));var g={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src&&(e=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/")),!e){var n=window.__webpack_public_path__||"";n&&("/"!==n.charAt(n.length-1)&&(n+="/"),e=n+"static/plugins/plugin-build-guide-block/dist/client-v2/")}if(!e){var r=window.__nocobase_modern_client_prefix__||"v",o="/"+(r=String(r).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var i=window.location.pathname||"/",u=i.indexOf(o);e=u>=0?i.slice(0,u+1):"/"}e&&(e=e.replace(RegExp("/"+r+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/plugin-build-guide-block/dist/client-v2/"}f.p=e}(),!function(){f.r(g),f.d(g,{default:function(){return c}});var e=f(485);function t(e,t,n,r,o,i,u){try{var c=e[i](u),a=c.value}catch(e){n(e);return}c.done?t(a):Promise.resolve(a).then(r,o)}function n(e,t,r){return(n=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)}f(155);function r(e){return(r=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 i(e){var t="function"==typeof Map?new Map:void 0;return(i=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,i)}function i(){return n(e,arguments,r(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),o(i,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 n;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=r(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||[],r(this).constructor):e.apply(this,t))}return i.prototype=Object.create(e&&e.prototype,{constructor:{value:i,writable:!0,configurable:!0}}),e&&o(i,e),n=[{key:"load",value:function(){var e;return(e=function(){return function(e,t){var n,r,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},u=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),c=Object.defineProperty;return c(u,"next",{value:a(0)}),c(u,"throw",{value:a(1)}),c(u,"return",{value:a(2)}),"function"==typeof Symbol&&c(u,Symbol.iterator,{value:function(){return this}}),u;function a(c){return function(a){var l=[c,a];if(n)throw TypeError("Generator is already executing.");for(;u&&(u=0,l[0]&&(i=0)),i;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,r=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(e){return this.pluginSettingsManager.addMenuItem({key:"ai-build-guide",title:this.t("Build Guide Block"),icon:"ReadOutlined",aclSnippet:"pm.ai-build-guide"}),this.pluginSettingsManager.addPageTabItem({menuKey:"ai-build-guide",key:"index",title:this.t("Build Guide Block"),componentLoader:function(){return f.e("376").then(f.bind(f,571)).then(function(e){return{default:e.UserGuideManager}})}}),[2]})},function(){var n=this,r=arguments;return new Promise(function(o,i){var u=e.apply(n,r);function c(e){t(u,o,i,c,a,"next",e)}function a(e){t(u,o,i,c,a,"throw",e)}c(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,n),i}(i(e.Plugin))}(),g}()});
|
package/dist/externalVersion.js
CHANGED
|
@@ -14,9 +14,9 @@ module.exports = {
|
|
|
14
14
|
"antd": "5.24.2",
|
|
15
15
|
"react-i18next": "11.18.6",
|
|
16
16
|
"@ant-design/icons": "5.6.1",
|
|
17
|
-
"@formily/core": "2.3.7",
|
|
18
17
|
"@nocobase/client-v2": "2.1.6",
|
|
19
18
|
"@nocobase/server": "2.1.6",
|
|
19
|
+
"@formily/core": "2.3.7",
|
|
20
20
|
"@nocobase/flow-engine": "2.1.6",
|
|
21
21
|
"@nocobase/actions": "2.1.6",
|
|
22
22
|
"@nocobase/database": "2.1.6",
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"displayName.zh-CN": "构建指南区块",
|
|
6
6
|
"description": "Generate user guides, tutorials and help books from documents using AI, then render the result as a block (HTML or Markdown).",
|
|
7
7
|
"description.vi-VN": "Tạo hướng dẫn người dùng, tutorial và help book từ tài liệu bằng AI, hiển thị kết quả dưới dạng block (HTML hoặc Markdown).",
|
|
8
|
-
"version": "1.1.
|
|
8
|
+
"version": "1.1.9",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"ai",
|
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
useDataBlockRequest,
|
|
7
|
-
useDataBlockResource,
|
|
8
|
-
useDestroyActionProps,
|
|
9
|
-
useTableBlockProps,
|
|
10
|
-
} from '@nocobase/client';
|
|
11
|
-
import { createForm } from '@formily/core';
|
|
12
|
-
import { useForm } from '@formily/react';
|
|
13
|
-
import { App } from 'antd';
|
|
14
|
-
import { useTranslation } from 'react-i18next';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { App, Button, Drawer, Form, Input, InputNumber, Select, Space, Table, Tag } from 'antd';
|
|
3
|
+
import { PlayCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
|
4
|
+
import { useApp } from '@nocobase/client-v2';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
15
6
|
import {
|
|
16
7
|
DEFAULT_TARGET_CHAPTER_COUNT,
|
|
17
8
|
MAX_TARGET_CHAPTER_COUNT,
|
|
18
9
|
MIN_TARGET_CHAPTER_COUNT,
|
|
19
|
-
spacesSchema,
|
|
20
10
|
} from './schemas/spacesSchema';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
|
|
12
|
+
const POLL_INTERVAL_MS = 3000;
|
|
13
|
+
const STILL_RUNNING_AFTER_MS = 5 * 60 * 1000;
|
|
14
|
+
const SLOW_POLL_INTERVAL_MS = 10000;
|
|
15
|
+
|
|
16
|
+
const STATUS_COLORS: Record<string, string> = {
|
|
17
|
+
draft: 'default',
|
|
18
|
+
building: 'blue',
|
|
19
|
+
completed: 'success',
|
|
20
|
+
error: 'error',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const OUTPUT_FORMAT_OPTIONS = [
|
|
24
|
+
{ label: 'HTML', value: 'html' },
|
|
25
|
+
{ label: 'Markdown', value: 'markdown' },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
interface SpaceRecord {
|
|
29
|
+
id: number;
|
|
30
|
+
title?: string;
|
|
31
|
+
status?: string;
|
|
32
|
+
buildPhase?: string;
|
|
33
|
+
pageCount?: number;
|
|
34
|
+
buildLog?: string;
|
|
35
|
+
llmService?: string;
|
|
36
|
+
model?: string;
|
|
37
|
+
outputFormat?: string;
|
|
38
|
+
targetChapterCount?: number;
|
|
39
|
+
chapterGuidance?: string;
|
|
40
|
+
systemPrompt?: string;
|
|
41
|
+
generatedHtml?: string;
|
|
42
|
+
generatedMarkdown?: string;
|
|
43
|
+
documents?: any[];
|
|
44
|
+
}
|
|
25
45
|
|
|
26
46
|
const normalizeTargetChapterCount = (value: unknown) => {
|
|
27
47
|
const count = Number(value);
|
|
@@ -31,127 +51,276 @@ const normalizeTargetChapterCount = (value: unknown) => {
|
|
|
31
51
|
|
|
32
52
|
export const UserGuideManager = () => {
|
|
33
53
|
const { t } = useTranslation();
|
|
54
|
+
const api = useApp().apiClient;
|
|
55
|
+
const { message, modal } = App.useApp();
|
|
56
|
+
const [form] = Form.useForm();
|
|
57
|
+
const selectedService = Form.useWatch('llmService', form);
|
|
58
|
+
|
|
59
|
+
const [data, setData] = useState<SpaceRecord[]>([]);
|
|
60
|
+
const [loading, setLoading] = useState(false);
|
|
61
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
62
|
+
const [editingId, setEditingId] = useState<number | null>(null);
|
|
63
|
+
const [submitting, setSubmitting] = useState(false);
|
|
64
|
+
const [serviceOptions, setServiceOptions] = useState<{ label: string; value: string }[]>([]);
|
|
65
|
+
const [modelOptions, setModelOptions] = useState<{ label: string; value: string }[]>([]);
|
|
66
|
+
const [buildingId, setBuildingId] = useState<number | null>(null);
|
|
67
|
+
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
68
|
+
|
|
69
|
+
const loadList = useCallback(async () => {
|
|
70
|
+
setLoading(true);
|
|
71
|
+
try {
|
|
72
|
+
const res = await api.resource('aiBuildGuideSpaces').list({
|
|
73
|
+
appends: ['documents'],
|
|
74
|
+
sort: ['-createdAt'],
|
|
75
|
+
paginate: false,
|
|
76
|
+
});
|
|
77
|
+
setData(res?.data?.data || []);
|
|
78
|
+
} finally {
|
|
79
|
+
setLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}, [api]);
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
loadList();
|
|
85
|
+
}, [loadList]);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
return () => {
|
|
89
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
90
|
+
};
|
|
91
|
+
}, []);
|
|
92
|
+
|
|
93
|
+
const loadServices = useCallback(async () => {
|
|
94
|
+
try {
|
|
95
|
+
const res = await api.resource('ai').listLLMServices();
|
|
96
|
+
const list = res?.data?.data || [];
|
|
97
|
+
setServiceOptions(list.map((s: any) => ({ label: s.title || s.name, value: s.name })));
|
|
98
|
+
} catch {
|
|
99
|
+
setServiceOptions([]);
|
|
100
|
+
}
|
|
101
|
+
}, [api]);
|
|
102
|
+
|
|
103
|
+
const loadModels = useCallback(
|
|
104
|
+
async (service?: string) => {
|
|
105
|
+
if (!service) {
|
|
106
|
+
setModelOptions([]);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const res = await api.resource('ai').listModels({ llmService: service });
|
|
111
|
+
const list = res?.data?.data || [];
|
|
112
|
+
setModelOptions(list.map((m: any) => ({ label: m.id || m.name, value: m.id || m.name })));
|
|
113
|
+
} catch {
|
|
114
|
+
setModelOptions([]);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
[api],
|
|
118
|
+
);
|
|
34
119
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
loadModels(selectedService);
|
|
122
|
+
}, [selectedService, loadModels]);
|
|
123
|
+
|
|
124
|
+
const openCreate = () => {
|
|
125
|
+
setEditingId(null);
|
|
126
|
+
form.resetFields();
|
|
127
|
+
form.setFieldsValue({
|
|
128
|
+
outputFormat: 'html',
|
|
129
|
+
targetChapterCount: DEFAULT_TARGET_CHAPTER_COUNT,
|
|
130
|
+
systemPrompt:
|
|
131
|
+
'You are an expert technical writer. Generate a comprehensive user guide based on the provided documents.',
|
|
132
|
+
});
|
|
133
|
+
loadServices();
|
|
134
|
+
setDrawerOpen(true);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const openEdit = (record: SpaceRecord) => {
|
|
138
|
+
setEditingId(record.id);
|
|
139
|
+
form.resetFields();
|
|
140
|
+
form.setFieldsValue({
|
|
141
|
+
title: record.title,
|
|
142
|
+
llmService: record.llmService,
|
|
143
|
+
model: record.model,
|
|
144
|
+
outputFormat: record.outputFormat || 'html',
|
|
145
|
+
targetChapterCount: normalizeTargetChapterCount(record.targetChapterCount),
|
|
146
|
+
chapterGuidance: record.chapterGuidance,
|
|
147
|
+
systemPrompt: record.systemPrompt,
|
|
148
|
+
});
|
|
149
|
+
loadServices();
|
|
150
|
+
loadModels(record.llmService);
|
|
151
|
+
setDrawerOpen(true);
|
|
46
152
|
};
|
|
47
153
|
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
154
|
+
const handleSubmit = async () => {
|
|
155
|
+
const values = await form.validateFields();
|
|
156
|
+
values.targetChapterCount = normalizeTargetChapterCount(values.targetChapterCount);
|
|
157
|
+
setSubmitting(true);
|
|
158
|
+
try {
|
|
159
|
+
if (editingId) {
|
|
160
|
+
await api.resource('aiBuildGuideSpaces').update({ filterByTk: editingId, values });
|
|
161
|
+
} else {
|
|
162
|
+
await api.resource('aiBuildGuideSpaces').create({ values });
|
|
163
|
+
}
|
|
164
|
+
message.success(t('Saved successfully'));
|
|
165
|
+
setDrawerOpen(false);
|
|
166
|
+
await loadList();
|
|
167
|
+
} catch (err: any) {
|
|
168
|
+
if (err?.errorFields) return;
|
|
169
|
+
message.error(err?.response?.data?.error?.message || t('Save failed'));
|
|
170
|
+
} finally {
|
|
171
|
+
setSubmitting(false);
|
|
172
|
+
}
|
|
61
173
|
};
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const normalizeValues = (values: any) => {
|
|
74
|
-
const { documents, ...rest } = values;
|
|
75
|
-
rest.targetChapterCount = normalizeTargetChapterCount(rest.targetChapterCount);
|
|
76
|
-
if (Array.isArray(documents)) {
|
|
77
|
-
rest.documents = documents.map((doc: any) => (typeof doc === 'object' && doc?.id ? { id: doc.id } : doc));
|
|
174
|
+
|
|
175
|
+
const handleDelete = async (record: SpaceRecord) => {
|
|
176
|
+
await api.resource('aiBuildGuideSpaces').destroy({ filterByTk: record.id });
|
|
177
|
+
message.success(t('Deleted'));
|
|
178
|
+
await loadList();
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const stopPolling = useCallback(() => {
|
|
182
|
+
if (timerRef.current) {
|
|
183
|
+
clearTimeout(timerRef.current);
|
|
184
|
+
timerRef.current = null;
|
|
78
185
|
}
|
|
79
|
-
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
186
|
+
setBuildingId(null);
|
|
187
|
+
}, []);
|
|
188
|
+
|
|
189
|
+
const handleBuild = async (record: SpaceRecord) => {
|
|
190
|
+
setBuildingId(record.id);
|
|
191
|
+
try {
|
|
192
|
+
await api.resource('aiBuildGuideSpaces').build({ filterByTk: record.id });
|
|
193
|
+
message.success(t('Build started'));
|
|
194
|
+
const startedAt = Date.now();
|
|
195
|
+
let stillRunningNotified = false;
|
|
196
|
+
const poll = async () => {
|
|
197
|
+
try {
|
|
198
|
+
const res = await api.resource('aiBuildGuideSpaces').get({ filterByTk: record.id });
|
|
199
|
+
const status = res?.data?.data?.status;
|
|
200
|
+
if (status !== 'building') {
|
|
201
|
+
stopPolling();
|
|
202
|
+
await loadList();
|
|
203
|
+
if (status === 'completed') message.success(t('Build completed'));
|
|
204
|
+
else if (status === 'error') message.error(t('Build failed'));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const elapsed = Date.now() - startedAt;
|
|
208
|
+
if (elapsed >= STILL_RUNNING_AFTER_MS && !stillRunningNotified) {
|
|
209
|
+
stillRunningNotified = true;
|
|
210
|
+
message.info(t('Build is still running'));
|
|
211
|
+
}
|
|
212
|
+
const next = elapsed >= STILL_RUNNING_AFTER_MS ? SLOW_POLL_INTERVAL_MS : POLL_INTERVAL_MS;
|
|
213
|
+
timerRef.current = setTimeout(poll, next);
|
|
214
|
+
} catch {
|
|
215
|
+
stopPolling();
|
|
216
|
+
await loadList();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
timerRef.current = setTimeout(poll, POLL_INTERVAL_MS);
|
|
220
|
+
} catch (err: any) {
|
|
221
|
+
message.error(err?.response?.data?.error?.message || t('Build failed'));
|
|
222
|
+
setBuildingId(null);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const columns = [
|
|
227
|
+
{ title: t('Title'), dataIndex: 'title' },
|
|
228
|
+
{
|
|
229
|
+
title: t('Status'),
|
|
230
|
+
dataIndex: 'status',
|
|
231
|
+
render: (v: string) => (v ? <Tag color={STATUS_COLORS[v] || 'default'}>{String(v).toUpperCase()}</Tag> : null),
|
|
232
|
+
},
|
|
233
|
+
{ title: t('Build Phase'), dataIndex: 'buildPhase' },
|
|
234
|
+
{ title: t('Chapters'), dataIndex: 'pageCount' },
|
|
235
|
+
{
|
|
236
|
+
title: t('Actions'),
|
|
237
|
+
key: 'actions',
|
|
238
|
+
render: (_: unknown, record: SpaceRecord) => (
|
|
239
|
+
<Space split="|">
|
|
240
|
+
<Button
|
|
241
|
+
type="link"
|
|
242
|
+
icon={<PlayCircleOutlined />}
|
|
243
|
+
loading={buildingId === record.id}
|
|
244
|
+
disabled={record.status === 'building'}
|
|
245
|
+
onClick={() => handleBuild(record)}
|
|
246
|
+
>
|
|
247
|
+
{t('Build')}
|
|
248
|
+
</Button>
|
|
249
|
+
<a onClick={() => openEdit(record)}>{t('Edit')}</a>
|
|
250
|
+
<a
|
|
251
|
+
onClick={() =>
|
|
252
|
+
modal.confirm({
|
|
253
|
+
title: t('Delete'),
|
|
254
|
+
content: t('Are you sure you want to delete this space?'),
|
|
255
|
+
onOk: () => handleDelete(record),
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
>
|
|
259
|
+
{t('Delete')}
|
|
260
|
+
</a>
|
|
261
|
+
</Space>
|
|
262
|
+
),
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
<div>
|
|
268
|
+
<Space style={{ marginBottom: 16 }}>
|
|
269
|
+
<Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
|
|
270
|
+
{t('Create space')}
|
|
271
|
+
</Button>
|
|
272
|
+
<Button onClick={loadList}>{t('Refresh')}</Button>
|
|
273
|
+
</Space>
|
|
274
|
+
<Table rowKey="id" loading={loading} dataSource={data} columns={columns} />
|
|
275
|
+
<Drawer
|
|
276
|
+
title={editingId ? t('Edit space') : t('Create space')}
|
|
277
|
+
open={drawerOpen}
|
|
278
|
+
onClose={() => setDrawerOpen(false)}
|
|
279
|
+
width={640}
|
|
280
|
+
footer={
|
|
281
|
+
<Space style={{ float: 'right' }}>
|
|
282
|
+
<Button onClick={() => setDrawerOpen(false)}>{t('Cancel')}</Button>
|
|
283
|
+
<Button type="primary" loading={submitting} onClick={handleSubmit}>
|
|
284
|
+
{t('Submit')}
|
|
285
|
+
</Button>
|
|
286
|
+
</Space>
|
|
287
|
+
}
|
|
288
|
+
>
|
|
289
|
+
<Form
|
|
290
|
+
form={form}
|
|
291
|
+
layout="vertical"
|
|
292
|
+
onValuesChange={(changed) => {
|
|
293
|
+
if ('llmService' in changed) form.setFieldValue('model', undefined);
|
|
294
|
+
}}
|
|
295
|
+
>
|
|
296
|
+
<Form.Item name="title" label={t('Title')} rules={[{ required: true }]}>
|
|
297
|
+
<Input />
|
|
298
|
+
</Form.Item>
|
|
299
|
+
<Form.Item name="llmService" label={t('LLM Service')} rules={[{ required: true }]}>
|
|
300
|
+
<Select options={serviceOptions} onFocus={loadServices} showSearch optionFilterProp="label" />
|
|
301
|
+
</Form.Item>
|
|
302
|
+
<Form.Item name="model" label={t('Model')} rules={[{ required: true }]}>
|
|
303
|
+
<Select options={modelOptions} disabled={!selectedService} showSearch optionFilterProp="label" />
|
|
304
|
+
</Form.Item>
|
|
305
|
+
<Form.Item name="outputFormat" label={t('Output format')} rules={[{ required: true }]}>
|
|
306
|
+
<Select options={OUTPUT_FORMAT_OPTIONS} />
|
|
307
|
+
</Form.Item>
|
|
308
|
+
<Form.Item name="targetChapterCount" label={t('Target chapters')} rules={[{ required: true }]}>
|
|
309
|
+
<InputNumber
|
|
310
|
+
min={MIN_TARGET_CHAPTER_COUNT}
|
|
311
|
+
max={MAX_TARGET_CHAPTER_COUNT}
|
|
312
|
+
precision={0}
|
|
313
|
+
style={{ width: '100%' }}
|
|
314
|
+
/>
|
|
315
|
+
</Form.Item>
|
|
316
|
+
<Form.Item name="chapterGuidance" label={t('Chapter guidance')}>
|
|
317
|
+
<Input.TextArea rows={3} placeholder={t('Describe how the guide should be split into chapters')} />
|
|
318
|
+
</Form.Item>
|
|
319
|
+
<Form.Item name="systemPrompt" label={t('System Prompt')}>
|
|
320
|
+
<Input.TextArea rows={4} />
|
|
321
|
+
</Form.Item>
|
|
322
|
+
</Form>
|
|
323
|
+
</Drawer>
|
|
324
|
+
</div>
|
|
325
|
+
);
|
|
326
|
+
};
|