diff --git a/README.md b/README.md index 7cd8942..ff1ebf4 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,101 @@ -
-
+
+
+ Nền tảng tự động hóa Pull Request, CI/CD và tài liệu vận hành dành cho đội kỹ thuật hiện đại. +
-View your app in AI Studio: https://ai.studio/apps/a18fb367-cc88-4c45-ad81-3a3786f4f2ce ++ Tổng quan · + Tính năng · + Kiến trúc · + Chạy cục bộ · + Vercel +
-## Run Locally +--- -**Prerequisites:** Node.js +## ✨ Tổng quan +**GitBot** là giao diện quản trị giúp nhóm phát triển theo dõi toàn bộ vòng đời Pull Request trong một workspace thống nhất: review diff, bình luận theo dòng, quan sát pipeline, đọc wiki nội bộ và kiểm tra readiness trước khi deploy. -1. Install dependencies: - `npm install` -2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key -3. Run the app: - `npm run dev` +Thiết kế dự án tập trung vào ba nguyên tắc: + +- **Tối giản:** thông tin quan trọng được ưu tiên, ít nhiễu thị giác. +- **Hiện đại:** dark UI cho app vận hành, wiki sáng sạch theo phong cách documentation hub. +- **Thực dụng:** mọi màn hình đều phục vụ trực tiếp cho review, CI/CD, bảo mật và rollout. + +## 🚀 Tính năng chính + +| Khu vực | Mô tả | +| --- | --- | +| Wiki | Trang giới thiệu tài liệu, mục lục, hướng dẫn CI/CD và checklist release. | +| Dashboard | KPI repository, PR, pipeline, diff stats và tín hiệu hệ thống. | +| Code Review | Xem diff, chọn file, gửi bình luận theo ngữ cảnh PR. | +| Pipeline | Theo dõi stage lint/test/build/deploy và trạng thái workflow. | +| Mobile Simulator | Kiểm tra trải nghiệm GitBot trên khung di động mô phỏng. | +| Command Palette | Điều hướng nhanh bằng `⌘K` / `Ctrl K`. | + +## 🧭 Kiến trúc + +```mermaid +flowchart LR + GitHub[GitHub Webhook] --> API[GitBot API] + API --> Runner[GitBot Runner] + API --> DB[(PostgreSQL)] + Runner --> CI[CI/CD Jobs] + API --> UI[React Workspace] + UI --> Wiki[Wiki & Dashboard] +``` + +## 🧩 Logo + +Logo GitBot sử dụng biểu tượng robot kết hợp nhánh Git để thể hiện vai trò trợ lý tự động hóa kỹ thuật. Bảng màu xanh `sky` và `emerald` đồng bộ với giao diện sản phẩm, gợi cảm giác đáng tin cậy, realtime và thân thiện với developer. + +- File logo: [`public/gitbot-logo.svg`](public/gitbot-logo.svg) +- Có thể dùng trực tiếp cho GitHub README, header web app, favicon hoặc tài liệu nội bộ. + +## 🛠 Chạy cục bộ + +```bash +npm install +npm run dev +``` + +Ứng dụng mặc định chạy tại: + +```txt +http://localhost:3000 +``` + +## 📦 Build production + +```bash +npm run build +npm run start +``` + +## ▲ Triển khai Vercel + +Dự án đã chuẩn bị UI và build Vite phù hợp cho triển khai production. Khi môi trường có quyền registry và token Vercel, có thể deploy bằng: + +```bash +npx vercel --prod --yes +``` + +## 📚 Tài liệu trong app + +Mở ứng dụng và chọn tab **Wiki** để xem trang giới thiệu tài liệu được thiết kế riêng cho GitBot, bao gồm: + +1. Tổng quan dự án. +2. Bắt đầu nhanh. +3. Cấu hình `.gitbot-ci.yml` mẫu. +4. Quy ước review và release. +5. Checklist triển khai Vercel. + +## 📄 License + +Apache-2.0 diff --git a/gitbot/frontend/.next/app-build-manifest.json b/gitbot/frontend/.next/app-build-manifest.json new file mode 100644 index 0000000..1b3b57d --- /dev/null +++ b/gitbot/frontend/.next/app-build-manifest.json @@ -0,0 +1,3 @@ +{ + "pages": {} +} \ No newline at end of file diff --git a/gitbot/frontend/.next/build-manifest.json b/gitbot/frontend/.next/build-manifest.json new file mode 100644 index 0000000..b4ca5a8 --- /dev/null +++ b/gitbot/frontend/.next/build-manifest.json @@ -0,0 +1,17 @@ +{ + "polyfillFiles": [ + "static/chunks/polyfills.js" + ], + "devFiles": [], + "ampDevFiles": [], + "lowPriorityFiles": [ + "static/development/_buildManifest.js", + "static/development/_ssgManifest.js" + ], + "rootMainFiles": [], + "rootMainFilesTree": {}, + "pages": { + "/_app": [] + }, + "ampFirstPages": [] +} \ No newline at end of file diff --git a/gitbot/frontend/.next/cache/config.json b/gitbot/frontend/.next/cache/config.json new file mode 100644 index 0000000..adb0498 --- /dev/null +++ b/gitbot/frontend/.next/cache/config.json @@ -0,0 +1,7 @@ +{ + "telemetry": { + "notifiedAt": "1780419628126", + "anonymousId": "e7099743ac30723305ab7580aff2ba7889abefe13da55e52568592b84f34a454", + "salt": "ef9ed5909cda44dbc6e286701b02cfd1" + } +} \ No newline at end of file diff --git a/gitbot/frontend/.next/cache/next-devtools-config.json b/gitbot/frontend/.next/cache/next-devtools-config.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/gitbot/frontend/.next/cache/next-devtools-config.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/gitbot/frontend/.next/cache/webpack/client-development/0.pack.gz b/gitbot/frontend/.next/cache/webpack/client-development/0.pack.gz new file mode 100644 index 0000000..0828856 Binary files /dev/null and b/gitbot/frontend/.next/cache/webpack/client-development/0.pack.gz differ diff --git a/gitbot/frontend/.next/cache/webpack/client-development/index.pack.gz b/gitbot/frontend/.next/cache/webpack/client-development/index.pack.gz new file mode 100644 index 0000000..2c4e3a2 Binary files /dev/null and b/gitbot/frontend/.next/cache/webpack/client-development/index.pack.gz differ diff --git a/gitbot/frontend/.next/package.json b/gitbot/frontend/.next/package.json new file mode 100644 index 0000000..7156107 --- /dev/null +++ b/gitbot/frontend/.next/package.json @@ -0,0 +1 @@ +{"type": "commonjs"} \ No newline at end of file diff --git a/gitbot/frontend/.next/prerender-manifest.json b/gitbot/frontend/.next/prerender-manifest.json new file mode 100644 index 0000000..5f047bd --- /dev/null +++ b/gitbot/frontend/.next/prerender-manifest.json @@ -0,0 +1,11 @@ +{ + "version": 4, + "routes": {}, + "dynamicRoutes": {}, + "notFoundRoutes": [], + "preview": { + "previewModeId": "f9d7bfd052347c73e26ce4431647d6a5", + "previewModeSigningKey": "8abcf7940b0bde95158cc373ae80d66a55f6637655d312f3fe1e12faba40722d", + "previewModeEncryptionKey": "b0da285720eed0e4ca0a86942878b1b88e75c16cad5a0130524342bb03f7bb7f" + } +} \ No newline at end of file diff --git a/gitbot/frontend/.next/react-loadable-manifest.json b/gitbot/frontend/.next/react-loadable-manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/gitbot/frontend/.next/react-loadable-manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/gitbot/frontend/.next/routes-manifest.json b/gitbot/frontend/.next/routes-manifest.json new file mode 100644 index 0000000..8263120 --- /dev/null +++ b/gitbot/frontend/.next/routes-manifest.json @@ -0,0 +1 @@ +{"version":3,"caseSensitive":false,"basePath":"","rewrites":{"beforeFiles":[],"afterFiles":[],"fallback":[]},"redirects":[{"source":"/:path+/","destination":"/:path+","permanent":true,"internal":true,"regex":"^(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))\\/$"}],"headers":[]} \ No newline at end of file diff --git a/gitbot/frontend/.next/server/app-paths-manifest.json b/gitbot/frontend/.next/server/app-paths-manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/gitbot/frontend/.next/server/app-paths-manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/gitbot/frontend/.next/server/interception-route-rewrite-manifest.js b/gitbot/frontend/.next/server/interception-route-rewrite-manifest.js new file mode 100644 index 0000000..82d3ab1 --- /dev/null +++ b/gitbot/frontend/.next/server/interception-route-rewrite-manifest.js @@ -0,0 +1 @@ +self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]" \ No newline at end of file diff --git a/gitbot/frontend/.next/server/middleware-build-manifest.js b/gitbot/frontend/.next/server/middleware-build-manifest.js new file mode 100644 index 0000000..161dbe3 --- /dev/null +++ b/gitbot/frontend/.next/server/middleware-build-manifest.js @@ -0,0 +1,19 @@ +globalThis.__BUILD_MANIFEST = { + "polyfillFiles": [ + "static/chunks/polyfills.js" + ], + "devFiles": [], + "ampDevFiles": [], + "lowPriorityFiles": [], + "rootMainFiles": [], + "rootMainFilesTree": {}, + "pages": { + "/_app": [] + }, + "ampFirstPages": [] +}; +globalThis.__BUILD_MANIFEST.lowPriorityFiles = [ +"/static/" + process.env.__NEXT_BUILD_ID + "/_buildManifest.js", +,"/static/" + process.env.__NEXT_BUILD_ID + "/_ssgManifest.js", + +]; \ No newline at end of file diff --git a/gitbot/frontend/.next/server/middleware-manifest.json b/gitbot/frontend/.next/server/middleware-manifest.json new file mode 100644 index 0000000..33872a3 --- /dev/null +++ b/gitbot/frontend/.next/server/middleware-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 3, + "middleware": {}, + "functions": {}, + "sortedMiddleware": [] +} \ No newline at end of file diff --git a/gitbot/frontend/.next/server/middleware-react-loadable-manifest.js b/gitbot/frontend/.next/server/middleware-react-loadable-manifest.js new file mode 100644 index 0000000..ca34f09 --- /dev/null +++ b/gitbot/frontend/.next/server/middleware-react-loadable-manifest.js @@ -0,0 +1 @@ +self.__REACT_LOADABLE_MANIFEST="{}" \ No newline at end of file diff --git a/gitbot/frontend/.next/server/next-font-manifest.js b/gitbot/frontend/.next/server/next-font-manifest.js new file mode 100644 index 0000000..5cc97eb --- /dev/null +++ b/gitbot/frontend/.next/server/next-font-manifest.js @@ -0,0 +1 @@ +self.__NEXT_FONT_MANIFEST="{\"pages\":{},\"app\":{},\"appUsingSizeAdjust\":false,\"pagesUsingSizeAdjust\":false}" \ No newline at end of file diff --git a/gitbot/frontend/.next/server/next-font-manifest.json b/gitbot/frontend/.next/server/next-font-manifest.json new file mode 100644 index 0000000..25f78e7 --- /dev/null +++ b/gitbot/frontend/.next/server/next-font-manifest.json @@ -0,0 +1 @@ +{"pages":{},"app":{},"appUsingSizeAdjust":false,"pagesUsingSizeAdjust":false} \ No newline at end of file diff --git a/gitbot/frontend/.next/server/pages-manifest.json b/gitbot/frontend/.next/server/pages-manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/gitbot/frontend/.next/server/pages-manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/gitbot/frontend/.next/server/server-reference-manifest.js b/gitbot/frontend/.next/server/server-reference-manifest.js new file mode 100644 index 0000000..cc0af96 --- /dev/null +++ b/gitbot/frontend/.next/server/server-reference-manifest.js @@ -0,0 +1 @@ +self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY\"\n}" \ No newline at end of file diff --git a/gitbot/frontend/.next/server/server-reference-manifest.json b/gitbot/frontend/.next/server/server-reference-manifest.json new file mode 100644 index 0000000..5eb572e --- /dev/null +++ b/gitbot/frontend/.next/server/server-reference-manifest.json @@ -0,0 +1,5 @@ +{ + "node": {}, + "edge": {}, + "encryptionKey": "0nCAvMbN/z64a9O4AmkkByLQJ3dwpKAZQRw4vuCnmvM=" +} \ No newline at end of file diff --git a/gitbot/frontend/.next/static/chunks/polyfills.js b/gitbot/frontend/.next/static/chunks/polyfills.js new file mode 100644 index 0000000..ab422b9 --- /dev/null +++ b/gitbot/frontend/.next/static/chunks/polyfills.js @@ -0,0 +1 @@ +!function(){var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t){var e={exports:{}};return t(e,e.exports),e.exports}var r,n,o=function(t){return t&&t.Math===Math&&t},i=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof t&&t)||o("object"==typeof t&&t)||function(){return this}()||Function("return this")(),a=function(t){try{return!!t()}catch(t){return!0}},u=!a(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]}),s=!a(function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}),c=Function.prototype.call,f=s?c.bind(c):function(){return c.apply(c,arguments)},l={}.propertyIsEnumerable,h=Object.getOwnPropertyDescriptor,p=h&&!l.call({1:2},1)?function(t){var e=h(this,t);return!!e&&e.enumerable}:l,v={f:p},d=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},g=Function.prototype,y=g.call,m=s&&g.bind.bind(y,y),b=s?m:function(t){return function(){return y.apply(t,arguments)}},w=b({}.toString),S=b("".slice),E=function(t){return S(w(t),8,-1)},O=Object,x=b("".split),R=a(function(){return!O("z").propertyIsEnumerable(0)})?function(t){return"String"===E(t)?x(t,""):O(t)}:O,P=function(t){return null==t},A=TypeError,j=function(t){if(P(t))throw new A("Can't call method on "+t);return t},k=function(t){return R(j(t))},I="object"==typeof document&&document.all,T=void 0===I&&void 0!==I?function(t){return"function"==typeof t||t===I}:function(t){return"function"==typeof t},M=function(t){return"object"==typeof t?null!==t:T(t)},L=function(t,e){return arguments.length<2?T(r=i[t])?r:void 0:i[t]&&i[t][e];var r},U=b({}.isPrototypeOf),N=i.navigator,C=N&&N.userAgent,_=C?String(C):"",F=i.process,B=i.Deno,D=F&&F.versions||B&&B.version,z=D&&D.v8;z&&(n=(r=z.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!n&&_&&(!(r=_.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=_.match(/Chrome\/(\d+)/))&&(n=+r[1]);var W=n,q=i.String,H=!!Object.getOwnPropertySymbols&&!a(function(){var t=Symbol("symbol detection");return!q(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&W&&W<41}),$=H&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,K=Object,G=$?function(t){return"symbol"==typeof t}:function(t){var e=L("Symbol");return T(e)&&U(e.prototype,K(t))},V=String,Y=function(t){try{return V(t)}catch(t){return"Object"}},X=TypeError,J=function(t){if(T(t))return t;throw new X(Y(t)+" is not a function")},Q=function(t,e){var r=t[e];return P(r)?void 0:J(r)},Z=TypeError,tt=Object.defineProperty,et=function(t,e){try{tt(i,t,{value:e,configurable:!0,writable:!0})}catch(r){i[t]=e}return e},rt=e(function(t){var e="__core-js_shared__",r=t.exports=i[e]||et(e,{});(r.versions||(r.versions=[])).push({version:"3.38.1",mode:"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.38.1/LICENSE",source:"https://github.com/zloirock/core-js"})}),nt=function(t,e){return rt[t]||(rt[t]=e||{})},ot=Object,it=function(t){return ot(j(t))},at=b({}.hasOwnProperty),ut=Object.hasOwn||function(t,e){return at(it(t),e)},st=0,ct=Math.random(),ft=b(1..toString),lt=function(t){return"Symbol("+(void 0===t?"":t)+")_"+ft(++st+ct,36)},ht=i.Symbol,pt=nt("wks"),vt=$?ht.for||ht:ht&&ht.withoutSetter||lt,dt=function(t){return ut(pt,t)||(pt[t]=H&&ut(ht,t)?ht[t]:vt("Symbol."+t)),pt[t]},gt=TypeError,yt=dt("toPrimitive"),mt=function(t,e){if(!M(t)||G(t))return t;var r,n=Q(t,yt);if(n){if(void 0===e&&(e="default"),r=f(n,t,e),!M(r)||G(r))return r;throw new gt("Can't convert object to primitive value")}return void 0===e&&(e="number"),function(t,e){var r,n;if("string"===e&&T(r=t.toString)&&!M(n=f(r,t)))return n;if(T(r=t.valueOf)&&!M(n=f(r,t)))return n;if("string"!==e&&T(r=t.toString)&&!M(n=f(r,t)))return n;throw new Z("Can't convert object to primitive value")}(t,e)},bt=function(t){var e=mt(t,"string");return G(e)?e:e+""},wt=i.document,St=M(wt)&&M(wt.createElement),Et=function(t){return St?wt.createElement(t):{}},Ot=!u&&!a(function(){return 7!==Object.defineProperty(Et("div"),"a",{get:function(){return 7}}).a}),xt=Object.getOwnPropertyDescriptor,Rt={f:u?xt:function(t,e){if(t=k(t),e=bt(e),Ot)try{return xt(t,e)}catch(t){}if(ut(t,e))return d(!f(v.f,t,e),t[e])}},Pt=u&&a(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype}),At=String,jt=TypeError,kt=function(t){if(M(t))return t;throw new jt(At(t)+" is not an object")},It=TypeError,Tt=Object.defineProperty,Mt=Object.getOwnPropertyDescriptor,Lt="enumerable",Ut="configurable",Nt="writable",Ct={f:u?Pt?function(t,e,r){if(kt(t),e=bt(e),kt(r),"function"==typeof t&&"prototype"===e&&"value"in r&&Nt in r&&!r[Nt]){var n=Mt(t,e);n&&n[Nt]&&(t[e]=r.value,r={configurable:Ut in r?r[Ut]:n[Ut],enumerable:Lt in r?r[Lt]:n[Lt],writable:!1})}return Tt(t,e,r)}:Tt:function(t,e,r){if(kt(t),e=bt(e),kt(r),Ot)try{return Tt(t,e,r)}catch(t){}if("get"in r||"set"in r)throw new It("Accessors not supported");return"value"in r&&(t[e]=r.value),t}},_t=u?function(t,e,r){return Ct.f(t,e,d(1,r))}:function(t,e,r){return t[e]=r,t},Ft=Function.prototype,Bt=u&&Object.getOwnPropertyDescriptor,Dt=ut(Ft,"name"),zt={EXISTS:Dt,PROPER:Dt&&"something"===function(){}.name,CONFIGURABLE:Dt&&(!u||u&&Bt(Ft,"name").configurable)},Wt=b(Function.toString);T(rt.inspectSource)||(rt.inspectSource=function(t){return Wt(t)});var qt,Ht,$t,Kt=rt.inspectSource,Gt=i.WeakMap,Vt=T(Gt)&&/native code/.test(String(Gt)),Yt=nt("keys"),Xt=function(t){return Yt[t]||(Yt[t]=lt(t))},Jt={},Qt="Object already initialized",Zt=i.TypeError;if(Vt||rt.state){var te=rt.state||(rt.state=new(0,i.WeakMap));te.get=te.get,te.has=te.has,te.set=te.set,qt=function(t,e){if(te.has(t))throw new Zt(Qt);return e.facade=t,te.set(t,e),e},Ht=function(t){return te.get(t)||{}},$t=function(t){return te.has(t)}}else{var ee=Xt("state");Jt[ee]=!0,qt=function(t,e){if(ut(t,ee))throw new Zt(Qt);return e.facade=t,_t(t,ee,e),e},Ht=function(t){return ut(t,ee)?t[ee]:{}},$t=function(t){return ut(t,ee)}}var re,ne={set:qt,get:Ht,has:$t,enforce:function(t){return $t(t)?Ht(t):qt(t,{})},getterFor:function(t){return function(e){var r;if(!M(e)||(r=Ht(e)).type!==t)throw new Zt("Incompatible receiver, "+t+" required");return r}}},oe=e(function(t){var e=zt.CONFIGURABLE,r=ne.enforce,n=ne.get,o=String,i=Object.defineProperty,s=b("".slice),c=b("".replace),f=b([].join),l=u&&!a(function(){return 8!==i(function(){},"length",{value:8}).length}),h=String(String).split("String"),p=t.exports=function(t,n,a){"Symbol("===s(o(n),0,7)&&(n="["+c(o(n),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),a&&a.getter&&(n="get "+n),a&&a.setter&&(n="set "+n),(!ut(t,"name")||e&&t.name!==n)&&(u?i(t,"name",{value:n,configurable:!0}):t.name=n),l&&a&&ut(a,"arity")&&t.length!==a.arity&&i(t,"length",{value:a.arity});try{a&&ut(a,"constructor")&&a.constructor?u&&i(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var p=r(t);return ut(p,"source")||(p.source=f(h,"string"==typeof n?n:"")),t};Function.prototype.toString=p(function(){return T(this)&&n(this).source||Kt(this)},"toString")}),ie=function(t,e,r,n){n||(n={});var o=n.enumerable,i=void 0!==n.name?n.name:e;if(T(r)&&oe(r,i,n),n.global)o?t[e]=r:et(e,r);else{try{n.unsafe?t[e]&&(o=!0):delete t[e]}catch(t){}o?t[e]=r:Ct.f(t,e,{value:r,enumerable:!1,configurable:!n.nonConfigurable,writable:!n.nonWritable})}return t},ae=Math.ceil,ue=Math.floor,se=Math.trunc||function(t){var e=+t;return(e>0?ue:ae)(e)},ce=function(t){var e=+t;return e!=e||0===e?0:se(e)},fe=Math.max,le=Math.min,he=function(t,e){var r=ce(t);return r<0?fe(r+e,0):le(r,e)},pe=Math.min,ve=function(t){var e=ce(t);return e>0?pe(e,9007199254740991):0},de=function(t){return ve(t.length)},ge=function(t){return function(e,r,n){var o=k(e),i=de(o);if(0===i)return!t&&-1;var a,u=he(n,i);if(t&&r!=r){for(;i>u;)if((a=o[u++])!=a)return!0}else for(;i>u;u++)if((t||u in o)&&o[u]===r)return t||u||0;return!t&&-1}},ye={includes:ge(!0),indexOf:ge(!1)},me=ye.indexOf,be=b([].push),we=function(t,e){var r,n=k(t),o=0,i=[];for(r in n)!ut(Jt,r)&&ut(n,r)&&be(i,r);for(;e.length>o;)ut(n,r=e[o++])&&(~me(i,r)||be(i,r));return i},Se=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Ee=Se.concat("length","prototype"),Oe={f:Object.getOwnPropertyNames||function(t){return we(t,Ee)}},xe={f:Object.getOwnPropertySymbols},Re=b([].concat),Pe=L("Reflect","ownKeys")||function(t){var e=Oe.f(kt(t)),r=xe.f;return r?Re(e,r(t)):e},Ae=function(t,e,r){for(var n=Pe(e),o=Ct.f,i=Rt.f,a=0;a