@topthink/chat 1.0.3 → 1.0.5
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/es/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"react";import{useCallback as r,useState as t,
|
|
1
|
+
import*as e from"react";import{useCallback as r,useState as t,useImperativeHandle as o,memo as n,useRef as i,Fragment as s,useEffect as a}from"react";import{useImmer as l,request as c,isRequestError as d,Lightbox as m,styled as h,Clipboard as p,css as u,formatSize as g,Tooltip as f,useAsync as b,isImageUrl as v,getAbsoluteUrl as x}from"@topthink/components";import{jsx as y,jsxs as k,Fragment as w}from"react/jsx-runtime";import j from"react-markdown";import"katex/dist/katex.min.css";import N from"remark-math";import z from"remark-breaks";import M from"remark-gfm";import E from"rehype-katex";import $ from"rehype-highlight";import{Spinner as q}from"react-bootstrap";import*as C from"path";import F from"path";import P from"react-textarea-autosize";function R(e){let{url:n,transformRequest:i,onboarding:s,onSuccess:a,ref:m,...h}=e;const p=r((e=>{const r=[];if(s){let e=s.questions.filter((e=>!!e.trim()));if(e.length>3){const r=[...e];let t=e.length-3;for(;t--;){let e=Math.floor(Math.random()*r.length);r.splice(e,1)}e=r}r.push({chunks:[{content:[s.prologue,...e.map((e=>`[${e}](#!question)`))].join("\n"),tools:[]}]})}return e?r.concat(e.messages):r}),[s]),[u,g]=l((()=>p(h.conversation))),[f,b]=t(!1),[v,x]=t(h.conversation?.id),y=r((async function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(e||r.length>0){b(!0),g((t=>{t.push({query:e,files:r,chunks:[],loading:!0})}));let t=0,o="";try{await c({method:"post",url:n,data:{query:e,files:r,conversation:v},transformRequest:i,onDownloadProgress:e=>{const r=e.target,{responseText:n}=r;for(;t<e.loaded;){const e=n.substring(t,++t);if(o+=e,"\n"===e){const e=o.match(/^data:(?<data>.*)/);if(e){const r=e.groups.data.trim();if("[DONE]"!=r)try{const e=JSON.parse(r);e.conversation?x(e.conversation):g((r=>{const t=r[r.length-1];if(t.chunks)if(e.chunks){const r=e.chunks.index;if(t.chunks[r]||(t.chunks[r]={content:"",tools:[]}),e.chunks.error)t.chunks[r].error=e.chunks.error;else if(e.chunks.tools){const o=e.chunks.tools.index;"response"in e.chunks.tools?(t.chunks[r].tools[o].response=e.chunks.tools.response,t.chunks[r].tools[o].error=e.chunks.tools.error):"content"in e.chunks.tools?t.chunks[r].tools[o].content=e.chunks.tools.content:t.chunks[r].tools[o]={name:e.chunks.tools.name,title:e.chunks.tools.title,arguments:e.chunks.tools.arguments}}else e.chunks.content&&(t.chunks[r].content+=e.chunks.content)}else e.stats&&(t.stats=e.stats)}))}catch(e){console.error(e)}else g((e=>{e[e.length-1].loading=!1}))}o=""}}}})}catch(e){let r="未知错误";d(e)&&(r=401==e.response?.status?"未授权或授权已过期,请刷新页面后重试":"string"==typeof e.errors?e.errors:Object.values(e.errors).join("\n")),g((e=>{const t=e[e.length-1];t.chunks&&(0===t.chunks.length?t.chunks=[{content:`[${r}]`,tools:[]}]:t.chunks[t.chunks.length-1].content=`[${r}]`),t.loading=!1}))}b(!1),a?.()}}),[i,v]),k=r((e=>{f||(x(e?.id),g(p(e)))}),[f,p]);return o(m,(()=>({reset:k,send:y}))),{messages:u,loading:f,send:y,reset:k}}const T=m.Image,_=n((e=>{let{content:r,components:t}=e;return y(A,{remarkPlugins:[[N,{singleDollarTextMath:!1}],M,z],rehypePlugins:[E,[$,{detect:!1,ignoreMissing:!0}]],components:{pre:e=>{let{children:r}=e;const t=i(null);return k(O,{ref:t,children:[y(D,{tooltip:!1,content:()=>{const e=t.current?.getElementsByTagName("code");return e?.[0]?.innerText||""}}),r]})},a:e=>{let{node:r,href:t,...o}=e;const n=t?.startsWith("http")?"_blank":"_self";return y("a",{...o,href:t,target:n})},img:e=>{let{node:r,...t}=e;return y(T,{...t})},...t},children:r})})),D=h(p)`
|
|
2
2
|
position: absolute;
|
|
3
3
|
right: 10px;
|
|
4
4
|
top: 1em;
|
|
@@ -100,7 +100,6 @@ import*as e from"react";import{useCallback as r,useState as t,useEffect as o,use
|
|
|
100
100
|
background-color: #e1e1e1;
|
|
101
101
|
word-break: break-all;
|
|
102
102
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
|
103
|
-
white-space: pre;
|
|
104
103
|
line-height: 1.3;
|
|
105
104
|
color: inherit;
|
|
106
105
|
font-size: inherit;
|
|
@@ -324,7 +323,7 @@ import*as e from"react";import{useCallback as r,useState as t,useEffect as o,use
|
|
|
324
323
|
max-height: 100%;
|
|
325
324
|
max-width: 100%;
|
|
326
325
|
}
|
|
327
|
-
`;function I(e){let{tool:r,showProcess:o}=e;const[n,i]=t(!1);let
|
|
326
|
+
`;function I(e){let{tool:r,showProcess:o}=e;const[n,i]=t(!1);let a=null;r.content&&("string"==typeof r.content?a=y(_,{content:r.content}):"image"===r.content.type&&(a=y(B,{src:r.content.image})));const l="response"in r;return k(s,{children:["all"==o&&y("div",{className:"mb-2",children:k("div",n&&l?{className:"shadow-sm rounded bg-white fs-7",children:[k("div",{onClick:()=>i(!1),role:"button",className:"d-flex align-items-center p-1 px-2 gap-2",children:[r.error?y("i",{className:"bi bi-x-circle-fill text-danger"}):y("i",{className:"bi bi-check-circle-fill text-success"}),y("span",{className:"text-muted",children:"已使用"}),y("span",{children:r.title}),y("i",{className:"bi bi-caret-up-fill text-muted"})]}),k("div",{className:"border-top p-2 d-flex flex-column gap-2",children:[k("div",{className:"border rounded bg-light",children:[y("div",{className:"d-flex align-items-center p-1 px-2 fs-7 gap-2",children:y("span",{className:"text-muted",children:"参数"})}),y("div",{className:"border-top p-2 overflow-hidden",children:r.arguments})]}),k("div",{className:"border rounded bg-light",children:[y("div",{className:"d-flex align-items-center p-1 px-2 fs-7 gap-2",children:y("span",{className:"text-muted",children:"响应"})}),y(L,{className:"border-top p-2 overflow-hidden",children:r.response||"None"})]})]})]}:{onClick:()=>i(l),role:"button",className:"d-inline-flex align-items-center shadow-sm rounded bg-white p-1 px-2 fs-7 gap-2",children:[l?r.error?y("i",{className:"bi bi-x-circle-fill text-danger"}):y("i",{className:"bi bi-check-circle-fill text-success"}):y(q,{animation:"border",variant:"primary",size:"sm"}),y("span",{className:"text-muted",children:l?"已使用":"正在使用"}),y("span",{children:r.title}),l&&y("i",{className:"bi bi-caret-down-fill text-muted"})]})}),a]})}const L=h.div`
|
|
328
327
|
white-space: pre-wrap;
|
|
329
328
|
`;var H,K,X;function J(){return J=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},J.apply(this,arguments)}const W=r=>e.createElement("svg",J({xmlns:"http://www.w3.org/2000/svg",width:20,height:10,fill:"#fff",viewBox:"0 0 120 30"},r),H||(H=e.createElement("circle",{cx:15,cy:15,r:15,fill:"#3c60ff"},e.createElement("animate",{attributeName:"r",begin:"0s",calcMode:"linear",dur:"0.8s",from:15,repeatCount:"indefinite",to:15,values:"15;9;15"}),e.createElement("animate",{attributeName:"fill-opacity",begin:"0s",calcMode:"linear",dur:"0.8s",from:1,repeatCount:"indefinite",to:1,values:"1;.5;1"}))),K||(K=e.createElement("circle",{cx:60,cy:15,r:9,fill:"#3c60ff",fillOpacity:.3},e.createElement("animate",{attributeName:"r",begin:"0s",calcMode:"linear",dur:"0.8s",from:9,repeatCount:"indefinite",to:9,values:"9;15;9"}),e.createElement("animate",{attributeName:"fill-opacity",begin:"0s",calcMode:"linear",dur:"0.8s",from:.5,repeatCount:"indefinite",to:.5,values:".5;1;.5"}))),X||(X=e.createElement("circle",{cx:105,cy:15,r:15,fill:"#3c60ff"},e.createElement("animate",{attributeName:"r",begin:"0s",calcMode:"linear",dur:"0.8s",from:15,repeatCount:"indefinite",to:15,values:"15;9;15"}),e.createElement("animate",{attributeName:"fill-opacity",begin:"0s",calcMode:"linear",dur:"0.8s",from:1,repeatCount:"indefinite",to:1,values:"1;.5;1"}))));const G=function(e){let{ext:r}=e;const{result:t}=b((async e=>(await function(e){switch(e){case"../../images/file/docx.svg":return import("./docx-nWXnlyT_.js");case"../../images/file/jpg.svg":return import("./jpg-6tBxSzWk.js");case"../../images/file/md.svg":return import("./md-GZ3HJPcw.js");case"../../images/file/pdf.svg":return import("./pdf-pVX1_E6T.js");case"../../images/file/png.svg":return import("./png-u0o1NMqQ.js");case"../../images/file/pptx.svg":return import("./pptx-Hprz0cON.js");case"../../images/file/txt.svg":return import("./txt-eHeCpvNO.js");case"../../images/file/xlsx.svg":return import("./xlsx-uOft-SV2.js");default:return new Promise((function(r,t){("function"==typeof queueMicrotask?queueMicrotask:setTimeout)(t.bind(null,new Error("Unknown variable dynamic import: "+e)))}))}}(`../../images/file/${e}.svg`)).default),[r]);return t?y("img",{width:30,height:30,src:t}):null};function Q(e){let{className:r,name:t,size:o,loading:n,error:i,onRemove:s}=e;const a=F.extname(t).substring(1),l=k(ee,{className:r,$error:!!i,children:[k(Z,{children:[y(G,{ext:a}),n&&y(q,{variant:"primary"})]}),k(Y,{children:[y("h4",{children:t}),y("p",{children:g(o,1)})]}),s&&y(V,{onClick:e=>{e.preventDefault(),s()},children:y("i",{className:"bi bi-trash3"})})]});return i?y(f,{placement:"top",tooltip:i,children:l}):l}const V=h.div`
|
|
330
329
|
width: 1.75rem;
|
|
@@ -392,7 +391,7 @@ import*as e from"react";import{useCallback as r,useState as t,useEffect as o,use
|
|
|
392
391
|
${e=>e.$error&&u`
|
|
393
392
|
border-color: var(--bs-danger) !important;
|
|
394
393
|
`}
|
|
395
|
-
`,re=
|
|
394
|
+
`,re=n((e=>{let{bot:r,user:t,message:o,showProcess:n="none"}=e;const{query:i,files:a=[],chunks:l}=o;return k(w,{children:[(i||a.length>0)&&k(le,{$reverse:!0,children:[t&&y(se,{children:y("img",{src:t.avatar})}),k(ae,{children:[i&&y(_,{content:i}),a.length>0&&a.map(((e,r)=>{let{name:t,size:o,path:n}=e;return v(n)?y(B,{src:x(`/uploads/${n}`)},r):y(te,{children:y(Q,{name:t,size:o})},r)}))]})]}),l&&k(le,{children:[y(se,{children:y("img",{src:r.avatar})}),k(ae,{children:[o.query&&y(ne,{children:y(p,{placement:"top",content:l.reduce((function(e,r){return e+r.content+"\n"+r.tools.reduce(((e,r)=>r.content&&"string"==typeof r.content?e+r.content+"\n":e),"")}),""),as:oe})}),y(ie,{children:["stats","all"].includes(n)&&o.stats&&k(w,{children:[k("span",{children:["耗时 ",o.stats.latency/1e3," 秒"]}),k("span",{children:["花费 Token ",o.stats.usage]})]})}),l.length>0&&l.map(((e,r)=>k(s,{children:[e.content&&y(_,{content:e.content}),e.tools.map(((e,r)=>y(I,{tool:e,showProcess:n},r))),e.error&&y(_,{content:`[${e.error}]`})]},r))),o.loading&&y(W,{})]})]})]})})),te=h.div`
|
|
396
395
|
width: 100%;
|
|
397
396
|
margin-bottom: .5rem;
|
|
398
397
|
margin-top: .5rem;
|
|
@@ -505,7 +504,7 @@ import*as e from"react";import{useCallback as r,useState as t,useEffect as o,use
|
|
|
505
504
|
}
|
|
506
505
|
}
|
|
507
506
|
`};
|
|
508
|
-
`,ce=[".txt",".md",".pdf",".docx",".xlsx",".pptx",".png",".jpg"];function de(e){let{chat:
|
|
507
|
+
`,ce=[".txt",".md",".pdf",".docx",".xlsx",".pptx",".png",".jpg"];function de(e){let{chat:o,fileTypes:n,scrollRef:s,onMessages:m,minRows:h,toolbar:p}=e;const u=i(null),g=i(null),[b,v]=t(""),[x,w]=l([]),[j,N]=t(!1),z=n&&n.length>0?n:ce,{loading:M,messages:E,send:$}=R({...o,onSuccess(){requestAnimationFrame((()=>{u.current?.focus()})),o.onSuccess?.()}});a((()=>{m(E)}),[E]),a((()=>{const e=s.current;if(e&&$){const r=e=>{e.target instanceof HTMLAnchorElement&&"#!question"===e.target.hash&&(e.preventDefault(),$(e.target.text))};return e.addEventListener("click",r),()=>{e.removeEventListener("click",r)}}}),[s,$]);const q=r((e=>{let{target:r}=e;if(r.files){const e=Array.from(r.files).filter((e=>!!z.includes(C.extname(e.name))&&(!(e.size>20971520)&&e))).slice(0,6-x.length);w((r=>{r.push(...e.map((e=>({file:e}))))})),e.forEach((async e=>{try{const r=new FormData;r.set("file",e);const t=await c({method:"POST",url:`${o.url}/upload`,transformRequest:o.transformRequest,data:r});w((r=>{const o=r.find((r=>r.file===e));o&&(o.path=t.path)}))}catch(r){const t=d(r)?r.message:"unknown error";w((r=>{const o=r.find((r=>r.file===e));o&&(o.error=t)}))}}))}r.value=""}),[x,z]),F=x.flatMap((e=>{let{file:r,path:t}=e;return t?[{name:r.name,size:r.size,path:t}]:[]})),T=()=>{(b||F.length>0)&&($(b,F),v(""),w([]))};return k(fe,{children:[p,k(ge,{$focused:j,children:[x.length>0&&y(he,{children:x.map(((e,r)=>{let{file:t,error:o,path:n}=e;const i=void 0===o&&void 0===n;return y(me,{name:t.name,size:t.size,error:o,loading:i,onRemove:()=>{w((e=>{const r=e.findIndex((e=>e.file===t));-1!==r&&e.splice(r,1)}))}},r)}))}),k(ue,{children:[y(P,{disabled:M,ref:u,placeholder:"请输入你的问题, Enter+Shift换行, Enter发送",minRows:h,maxRows:5,value:b,onChange:e=>v(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),T())},onFocus:()=>N(!0),onBlur:()=>N(!1)}),n&&y(f,{tooltip:"可上传不超过6个小于20MB的文件",placement:"top",children:k(pe,{disabled:x.length>=6,onClick:()=>g.current?.click(),children:[y("input",{onChange:q,multiple:!0,accept:z.join(","),ref:g,type:"file",hidden:!0}),y("i",{className:"bi bi-file-earmark-arrow-up"})]})}),y(pe,{className:"text-primary",disabled:!b&&0===F.length,onClick:e=>{e.preventDefault(),T()},children:y("i",{className:"bi bi-send-fill"})})]})]})]})}const me=h(Q)`
|
|
509
508
|
width: calc((100% - .75rem) / 2);
|
|
510
509
|
`,he=h.div`
|
|
511
510
|
display: flex;
|
|
@@ -554,19 +553,20 @@ import*as e from"react";import{useCallback as r,useState as t,useEffect as o,use
|
|
|
554
553
|
}
|
|
555
554
|
`,ge=h.div`
|
|
556
555
|
background: #FFF;
|
|
557
|
-
margin: 0 1rem 1rem;
|
|
558
556
|
border: var(--bs-border-width) var(--bs-border-style) ${e=>e.$focused?"var(--bs-primary)":"var(--bs-border-color)"};
|
|
559
557
|
border-radius: var(--bs-border-radius-lg);
|
|
560
558
|
box-shadow: 0.125rem 0.25rem 0.5rem rgba(0, 0, 0, 0.1);
|
|
561
|
-
|
|
559
|
+
`,fe=h.div`
|
|
560
|
+
margin: 0 1rem 1rem;
|
|
561
|
+
`;function be(e){let{className:o,bot:n,user:s,input:l,showProcess:c,...d}=e;const[h,p]=t(d.messages||[]),u=i(null),g=r((()=>{const e=u.current;e&&requestAnimationFrame((()=>e.scrollTo(0,e.scrollHeight)))}),[]);return a((()=>{g()})),y(xe,{className:o,children:k(m,{children:[y(ve,{ref:u,children:h.map(((e,r)=>y(re,{message:e,showProcess:c,bot:n,user:s},r)))}),l&&y(de,{onMessages:p,scrollRef:u,...l})]})})}const ve=h.div`
|
|
562
562
|
display: flex;
|
|
563
563
|
flex-direction: column;
|
|
564
564
|
flex: 1;
|
|
565
565
|
overflow-y: auto;
|
|
566
566
|
padding: 0 1rem;
|
|
567
|
-
margin-bottom:
|
|
568
|
-
`,
|
|
567
|
+
margin-bottom: .5rem;
|
|
568
|
+
`,xe=h.div`
|
|
569
569
|
display: flex;
|
|
570
570
|
flex-direction: column;
|
|
571
571
|
height: 100%;
|
|
572
|
-
`;export{
|
|
572
|
+
`;export{be as MessageBox,R as useChat};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topthink/chat",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prebuild": "rimraf es types",
|
|
6
6
|
"build": "rollup -c --environment NODE_ENV:production",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@babel/runtime": "^7.11.2",
|
|
20
|
-
"@topthink/components": "^1.0.
|
|
20
|
+
"@topthink/components": "^1.0.81",
|
|
21
21
|
"katex": "^0.16.9",
|
|
22
22
|
"react-markdown": "^8.0.7",
|
|
23
23
|
"react-textarea-autosize": "^8.5.3",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
},
|
|
56
56
|
"author": "yunwuxin <tzzhangyajun@qq.com> (https://github.com/yunwuxin)",
|
|
57
57
|
"license": "MIT",
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "d33659dcc5e1fbbab462c6c4f82d5311829ff33d"
|
|
59
59
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { Message, ShowProcess } from '../../types';
|
|
3
3
|
import { ChatOptions } from '../../hooks/use-chat';
|
|
4
4
|
interface Props {
|
|
@@ -17,6 +17,7 @@ interface Props {
|
|
|
17
17
|
fileTypes?: string[];
|
|
18
18
|
minRows?: number;
|
|
19
19
|
chat: ChatOptions;
|
|
20
|
+
toolbar?: ReactNode;
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
export default function MessageBox({ className, bot, user, input, showProcess, ...props }: Props): JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MutableRefObject } from 'react';
|
|
1
|
+
import { MutableRefObject, ReactNode } from 'react';
|
|
2
2
|
import { Message } from '../../types';
|
|
3
3
|
import { ChatOptions } from '../../hooks/use-chat';
|
|
4
4
|
interface Props {
|
|
@@ -7,6 +7,7 @@ interface Props {
|
|
|
7
7
|
minRows?: number;
|
|
8
8
|
scrollRef: MutableRefObject<HTMLDivElement | null>;
|
|
9
9
|
onMessages: (messages: Message[]) => void;
|
|
10
|
+
toolbar?: ReactNode;
|
|
10
11
|
}
|
|
11
|
-
export default function ({ chat, fileTypes, scrollRef, onMessages, minRows }: Props): JSX.Element;
|
|
12
|
+
export default function ({ chat, fileTypes, scrollRef, onMessages, minRows, toolbar }: Props): JSX.Element;
|
|
12
13
|
export {};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { MutableRefObject } from 'react';
|
|
2
2
|
import { Chat, Message } from '../types';
|
|
3
3
|
import { RequestConfig } from '@topthink/components';
|
|
4
|
+
interface Conversation {
|
|
5
|
+
id: string;
|
|
6
|
+
messages: Message[];
|
|
7
|
+
}
|
|
4
8
|
export interface ChatOptions {
|
|
5
9
|
url: string;
|
|
6
10
|
transformRequest?: Exclude<RequestConfig, string>['transformRequest'];
|
|
@@ -9,15 +13,13 @@ export interface ChatOptions {
|
|
|
9
13
|
prologue: string;
|
|
10
14
|
questions: string[];
|
|
11
15
|
};
|
|
12
|
-
conversation?:
|
|
13
|
-
id: string;
|
|
14
|
-
messages: Message[];
|
|
15
|
-
};
|
|
16
|
+
conversation?: Conversation;
|
|
16
17
|
ref?: MutableRefObject<Chat | null>;
|
|
17
18
|
}
|
|
18
19
|
export default function useChat({ url, transformRequest, onboarding, onSuccess, ref, ...props }: ChatOptions): {
|
|
19
20
|
messages: Message[];
|
|
20
21
|
loading: boolean;
|
|
21
22
|
send: (query: string, files?: Message['files']) => Promise<void>;
|
|
22
|
-
reset: () => void;
|
|
23
|
+
reset: (conversation?: Conversation) => void;
|
|
23
24
|
};
|
|
25
|
+
export {};
|