@webority/mobile-chat 0.16.4 → 0.16.6
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/lib/commonjs/components/ChatMessage.js +1 -1
- package/lib/commonjs/useChat.js +1 -1
- package/lib/module/components/ChatMessage.js +1 -1
- package/lib/module/useChat.js +1 -1
- package/lib/typescript/commonjs/components/ChatMessage.d.ts +3 -1
- package/lib/typescript/module/components/ChatMessage.d.ts +3 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_markdownParse=require("../markdownParse.js"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");const inlineText=e=>e.map(e=>"text"===e.type||"code"===e.type?e.text:inlineText(e.children)).join(""),spokenText=e=>(0,_markdownParse.parseBlocks)(e).map(e=>{switch(e.type){case"paragraph":return inlineText((0,_markdownParse.parseInline)(e.lines.join(" ")));case"heading":return inlineText((0,_markdownParse.parseInline)(e.text));case"list":return e.items.map(e=>inlineText((0,_markdownParse.parseInline)(e))).join(". ");case"table":return[e.header,...e.rows].map(e=>e.join(", ")).join(". ");case"code":return e.text;default:return""}}).filter(Boolean).join("\n");function ChatMessageView({turn:e,onRate:t,resolveLink:i,onLinkPress:s,confirmAction:n,onViewTicket:r,renderReply:a,labels:o,testID:l="chat-message"}){const m=(0,_labels.mergeLabels)(o),u=(0,_mobileUi.useTheme)(),c=e.streaming&&!e.answer,x=(0,_react.useMemo)(()=>e.streaming?e.answer:spokenText(e.answer),[e.streaming,e.answer]),_=(0,_react.useMemo)(()=>({you:m.you}),[m.you]);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:u.spacing.sm},testID:l,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:_,testID:`${l}-question`}),c?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:m.assistant,text:x,streaming:e.streaming,testID:`${l}-answer`,children:a?a(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:i,onLinkPress:s})}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"error",accessibilityLiveRegion:"polite",children:e.error.message}),n&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:n,onViewTicket:r,labels:o},e.token)),t&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(i,s)=>t(e.id,i,s),labels:o})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
|
package/lib/commonjs/useChat.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useChat=void 0;var _react=require("react");const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const r of e??[]){if("User"===r.role){t.push(emptyTurn(r.publicId,r.content));continue}const e=t[t.length-1],n={answer:r.content,actions:parseActions(r.actionsJson),messageId:r.publicId,rating:r.rating??null,ratingNote:r.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,n):t.push({...emptyTurn(r.publicId,""),...n})}return t},useChat=({client:e,pageContext:t})=>{const[r,n]=(0,_react.useState)([]),[s
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useChat=void 0;var _react=require("react");const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const r of e??[]){if("User"===r.role){t.push(emptyTurn(r.publicId,r.content));continue}const e=t[t.length-1],n={answer:r.content,actions:parseActions(r.actionsJson),messageId:r.publicId,rating:r.rating??null,ratingNote:r.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,n):t.push({...emptyTurn(r.publicId,""),...n})}return t},useChat=({client:e,pageContext:t})=>{const[r,n]=(0,_react.useState)([]),[a,s]=(0,_react.useState)(null),[c,u]=(0,_react.useState)(null),[o,l]=(0,_react.useState)(!1),[i,g]=(0,_react.useState)(null),d=(0,_react.useRef)(null),m=(0,_react.useRef)(0),f=(0,_react.useRef)(0),p=(0,_react.useRef)(t);p.current=t;const y=(0,_react.useRef)(null);y.current=a;const _=(0,_react.useRef)(r);_.current=r;const w=(0,_react.useRef)(new Map),C=(0,_react.useRef)(0),b=(0,_react.useRef)(!1),h=(0,_react.useCallback)(()=>{const e=w.current;0!==e.size&&(w.current=new Map,n(t=>t.map(t=>e.has(t.id)?{...t,answer:t.answer+(e.get(t.id)??"")}:t)))},[]),I=(0,_react.useCallback)((e,t)=>{w.current.set(e,(w.current.get(e)??"")+t),b.current||(b.current=!0,C.current=requestAnimationFrame(()=>{b.current=!1,h()}))},[h]),v=(0,_react.useCallback)(()=>{cancelAnimationFrame(C.current),b.current=!1,w.current=new Map},[]),A=(0,_react.useCallback)(()=>{m.current+=1,d.current?.abort(),d.current=null,v()},[v]);(0,_react.useEffect)(()=>A,[A]);const k=(0,_react.useCallback)((e,t)=>{n(r=>r.map(r=>r.id===e?{...r,..."function"==typeof t?t(r):t}:r))},[]),R=(0,_react.useCallback)(async t=>{const r="string"==typeof t?t.trim():"";if(!r||d.current)return;const a=m.current,c=new AbortController;d.current=c,f.current+=1;const o=`turn-${f.current}`;n(e=>[...e,{...emptyTurn(o,r),streaming:!0}]);const live=()=>a===m.current&&!c.signal.aborted;try{const t=await e.sendMessage({message:r,conversationId:y.current,pageContext:p.current},{signal:c.signal,onEvent:(e,t)=>{if(!live())return;const r=t;"delta"===e?I(o,r?.text??""):"reset"===e?(w.current.delete(o),k(o,{answer:""})):(h(),"actions"===e&&k(o,{actions:Array.isArray(r?.actions)?r.actions:[]}))}});if(!live())return;h(),k(o,{answer:t.reply,messageId:t.messageId??null,streaming:!1}),y.current=t.conversationId,s(t.conversationId),u(t.messagesLeftToday??null)}catch(e){if(!live())return;const t=toError(e);w.current.delete(o),k(o,{answer:"",actions:[],streaming:!1,error:t}),"daily_limit"===t.code&&u(0),"conversation_not_found"===t.code&&(y.current=null,s(null))}finally{d.current===c&&(d.current=null)}},[e,k,h,I]),E=(0,_react.useCallback)(async t=>{A();const r=m.current;n([]),s(null),g(null),l(!0);try{const a=await e.getConversation(t);if(r!==m.current)return;n(turnsFromConversation(a.messages)),s(a.publicId)}catch(e){if(r!==m.current)return;g(toError(e))}finally{r===m.current&&l(!1)}},[A,e]),N=(0,_react.useCallback)(()=>{A(),n([]),s(null),g(null),l(!1)},[A]),S=(0,_react.useCallback)(()=>{A(),n([]),s(null),u(null),g(null),l(!1)},[A]),T=(0,_react.useCallback)(async()=>{const t=m.current,r=await e.getAllowance();t===m.current&&u(r?.messagesLeftToday??null)},[e]),x=(0,_react.useCallback)(async(t,r,n)=>{const a=_.current.find(e=>e.id===t),s=y.current;if(!a?.messageId||!s)throw new Error("Only a stored reply can be rated.");const c={rating:a.rating,ratingNote:a.ratingNote},u="string"==typeof n&&n.trim()?n.trim():null;k(t,{rating:r,ratingNote:u});try{await e.rateMessage(s,a.messageId,{rating:r,note:u})}catch(e){throw k(t,c),e}},[e,k]);return{turns:r,conversationId:a,messagesLeftToday:c,streaming:r.some(e=>e.streaming),loading:o,loadError:i,submit:R,openConversation:E,newConversation:N,rate:x,refreshAllowance:T,reset:S}};exports.useChat=useChat;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{parseBlocks,parseInline}from"../markdownParse.js";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const inlineText=e=>e.map(e=>"text"===e.type||"code"===e.type?e.text:inlineText(e.children)).join(""),spokenText=e=>parseBlocks(e).map(e=>{switch(e.type){case"paragraph":return inlineText(parseInline(e.lines.join(" ")));case"heading":return inlineText(parseInline(e.text));case"list":return e.items.map(e=>inlineText(parseInline(e))).join(". ");case"table":return[e.header,...e.rows].map(e=>e.join(", ")).join(". ");case"code":return e.text;default:return""}}).filter(Boolean).join("\n");
|
|
1
|
+
"use strict";import{MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{parseBlocks,parseInline}from"../markdownParse.js";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const inlineText=e=>e.map(e=>"text"===e.type||"code"===e.type?e.text:inlineText(e.children)).join(""),spokenText=e=>parseBlocks(e).map(e=>{switch(e.type){case"paragraph":return inlineText(parseInline(e.lines.join(" ")));case"heading":return inlineText(parseInline(e.text));case"list":return e.items.map(e=>inlineText(parseInline(e))).join(". ");case"table":return[e.header,...e.rows].map(e=>e.join(", ")).join(". ");case"code":return e.text;default:return""}}).filter(Boolean).join("\n");function ChatMessageView({turn:e,onRate:s,resolveLink:t,onLinkPress:n,confirmAction:i,onViewTicket:r,renderReply:a,labels:o,testID:l="chat-message"}){const m=mergeLabels(o),c=useTheme(),p=e.streaming&&!e.answer,g=useMemo(()=>e.streaming?e.answer:spokenText(e.answer),[e.streaming,e.answer]),u=useMemo(()=>({you:m.you}),[m.you]);return _jsxs(View,{style:{gap:c.spacing.sm},testID:l,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:u,testID:`${l}-question`}),p?_jsx(TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:m.assistant,text:g,streaming:e.streaming,testID:`${l}-answer`,children:a?a(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:t,onLinkPress:n})}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"error",accessibilityLiveRegion:"polite",children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:i,onViewTicket:r,labels:o},e.token)),s&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,n)=>s(e.id,t,n),labels:o})]})}export const ChatMessage=memo(ChatMessageView);
|
package/lib/module/useChat.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useCallback,useEffect,useRef,useState}from"react";const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const n of e??[]){if("User"===n.role){t.push(emptyTurn(n.publicId,n.content));continue}const e=t[t.length-1],r={answer:n.content,actions:parseActions(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,r):t.push({...emptyTurn(n.publicId,""),...r})}return t};export const useChat=({client:e,pageContext:t})=>{const[n,r]=useState([]),[s,a]=useState(null),[
|
|
1
|
+
"use strict";import{useCallback,useEffect,useRef,useState}from"react";const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const n of e??[]){if("User"===n.role){t.push(emptyTurn(n.publicId,n.content));continue}const e=t[t.length-1],r={answer:n.content,actions:parseActions(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,r):t.push({...emptyTurn(n.publicId,""),...r})}return t};export const useChat=({client:e,pageContext:t})=>{const[n,r]=useState([]),[s,a]=useState(null),[u,c]=useState(null),[o,l]=useState(!1),[i,g]=useState(null),m=useRef(null),d=useRef(0),f=useRef(0),p=useRef(t);p.current=t;const y=useRef(null);y.current=s;const w=useRef(n);w.current=n;const b=useRef(new Map),C=useRef(0),I=useRef(!1),A=useCallback(()=>{const e=b.current;0!==e.size&&(b.current=new Map,r(t=>t.map(t=>e.has(t.id)?{...t,answer:t.answer+(e.get(t.id)??"")}:t)))},[]),k=useCallback((e,t)=>{b.current.set(e,(b.current.get(e)??"")+t),I.current||(I.current=!0,C.current=requestAnimationFrame(()=>{I.current=!1,A()}))},[A]),h=useCallback(()=>{cancelAnimationFrame(C.current),I.current=!1,b.current=new Map},[]),v=useCallback(()=>{d.current+=1,m.current?.abort(),m.current=null,h()},[h]);useEffect(()=>v,[v]);const R=useCallback((e,t)=>{r(n=>n.map(n=>n.id===e?{...n,..."function"==typeof t?t(n):t}:n))},[]),E=useCallback(async t=>{const n="string"==typeof t?t.trim():"";if(!n||m.current)return;const s=d.current,u=new AbortController;m.current=u,f.current+=1;const o=`turn-${f.current}`;r(e=>[...e,{...emptyTurn(o,n),streaming:!0}]);const live=()=>s===d.current&&!u.signal.aborted;try{const t=await e.sendMessage({message:n,conversationId:y.current,pageContext:p.current},{signal:u.signal,onEvent:(e,t)=>{if(!live())return;const n=t;"delta"===e?k(o,n?.text??""):"reset"===e?(b.current.delete(o),R(o,{answer:""})):(A(),"actions"===e&&R(o,{actions:Array.isArray(n?.actions)?n.actions:[]}))}});if(!live())return;A(),R(o,{answer:t.reply,messageId:t.messageId??null,streaming:!1}),y.current=t.conversationId,a(t.conversationId),c(t.messagesLeftToday??null)}catch(e){if(!live())return;const t=toError(e);b.current.delete(o),R(o,{answer:"",actions:[],streaming:!1,error:t}),"daily_limit"===t.code&&c(0),"conversation_not_found"===t.code&&(y.current=null,a(null))}finally{m.current===u&&(m.current=null)}},[e,R,A,k]),S=useCallback(async t=>{v();const n=d.current;r([]),a(null),g(null),l(!0);try{const s=await e.getConversation(t);if(n!==d.current)return;r(turnsFromConversation(s.messages)),a(s.publicId)}catch(e){if(n!==d.current)return;g(toError(e))}finally{n===d.current&&l(!1)}},[v,e]),N=useCallback(()=>{v(),r([]),a(null),g(null),l(!1)},[v]),T=useCallback(()=>{v(),r([]),a(null),c(null),g(null),l(!1)},[v]),M=useCallback(async()=>{const t=d.current,n=await e.getAllowance();t===d.current&&c(n?.messagesLeftToday??null)},[e]),x=useCallback(async(t,n,r)=>{const s=w.current.find(e=>e.id===t),a=y.current;if(!s?.messageId||!a)throw new Error("Only a stored reply can be rated.");const u={rating:s.rating,ratingNote:s.ratingNote},c="string"==typeof r&&r.trim()?r.trim():null;R(t,{rating:n,ratingNote:c});try{await e.rateMessage(a,s.messageId,{rating:n,note:c})}catch(e){throw R(t,u),e}},[e,R]);return{turns:n,conversationId:s,messagesLeftToday:u,streaming:n.some(e=>e.streaming),loading:o,loadError:i,submit:E,openConversation:S,newConversation:N,rate:x,refreshAllowance:M,reset:T}};
|
|
@@ -32,5 +32,7 @@ export interface ChatMessageProps<T = string> extends ChatReplyProps<T> {
|
|
|
32
32
|
* leading side. The answer is announced once, when it finishes arriving. Support actions show
|
|
33
33
|
* under the answer, and the rating once the reply is stored.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
declare function ChatMessageView<T = string>({ turn, onRate, resolveLink, onLinkPress, confirmAction, onViewTicket, renderReply, labels: labelOverrides, testID }: ChatMessageProps<T>): React.ReactElement;
|
|
36
|
+
export declare const ChatMessage: typeof ChatMessageView;
|
|
37
|
+
export {};
|
|
36
38
|
//# sourceMappingURL=ChatMessage.d.ts.map
|
|
@@ -32,5 +32,7 @@ export interface ChatMessageProps<T = string> extends ChatReplyProps<T> {
|
|
|
32
32
|
* leading side. The answer is announced once, when it finishes arriving. Support actions show
|
|
33
33
|
* under the answer, and the rating once the reply is stored.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
declare function ChatMessageView<T = string>({ turn, onRate, resolveLink, onLinkPress, confirmAction, onViewTicket, renderReply, labels: labelOverrides, testID }: ChatMessageProps<T>): React.ReactElement;
|
|
36
|
+
export declare const ChatMessage: typeof ChatMessageView;
|
|
37
|
+
export {};
|
|
36
38
|
//# sourceMappingURL=ChatMessage.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/mobile-chat",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.6",
|
|
4
4
|
"description": "AI assistant chat for Webority React Native apps: a streaming chat client, a store-agnostic chat hook, and the chat screen, thread, composer, past chats, reply rating and support action cards, built on @webority/mobile-ui.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@webority/mobile-
|
|
85
|
-
"@webority/mobile-
|
|
84
|
+
"@webority/mobile-core": "0.16.6",
|
|
85
|
+
"@webority/mobile-ui": "0.16.6"
|
|
86
86
|
},
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "bob build && node ../../scripts/minify-lib.mjs",
|