@pmate/chat-sdk 0.1.9 → 0.1.11

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.
Files changed (49) hide show
  1. package/dist/assets/ChatInput.stories-BABdkDrt.js +1545 -0
  2. package/dist/assets/Color-AVL7NMMY-D33umUzR.js +1 -0
  3. package/dist/assets/DocsRenderer-PQXLIZUC-BUYhEk48.js +1243 -0
  4. package/dist/assets/client-De2ACSn_.js +9 -0
  5. package/dist/assets/iframe-DVJDoCiO.js +1071 -0
  6. package/dist/assets/iframe-q28pAgAa.css +1 -0
  7. package/dist/assets/index-CkuJGuix.js +1 -0
  8. package/dist/assets/preload-helper-PPVm8Dsz.js +1 -0
  9. package/dist/assets/react-18-DfLUnvSL.js +1 -0
  10. package/dist/favicon-wrapper.svg +46 -0
  11. package/dist/favicon.svg +1 -0
  12. package/dist/iframe.html +687 -0
  13. package/dist/index.html +148 -0
  14. package/dist/index.json +1 -0
  15. package/dist/nunito-sans-bold-italic.woff2 +0 -0
  16. package/dist/nunito-sans-bold.woff2 +0 -0
  17. package/dist/nunito-sans-italic.woff2 +0 -0
  18. package/dist/nunito-sans-regular.woff2 +0 -0
  19. package/dist/project.json +1 -0
  20. package/dist/sb-addons/docs-1/manager-bundle.js +151 -0
  21. package/dist/sb-addons/docs-1/manager-bundle.js.LEGAL.txt +0 -0
  22. package/dist/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +971 -0
  23. package/dist/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
  24. package/dist/sb-common-assets/favicon-wrapper.svg +46 -0
  25. package/dist/sb-common-assets/favicon.svg +1 -0
  26. package/dist/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  27. package/dist/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  28. package/dist/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  29. package/dist/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  30. package/dist/sb-manager/globals-module-info.js +799 -0
  31. package/dist/sb-manager/globals-runtime.js +69791 -0
  32. package/dist/sb-manager/globals.js +34 -0
  33. package/dist/sb-manager/runtime.js +13198 -0
  34. package/dist/vite-inject-mocker-entry.js +2 -0
  35. package/lib/components/ChatInputDesktop.js +1 -0
  36. package/lib/components/ChatInputMobile.js +23 -21
  37. package/lib/components/HoldToTalkButton.js +4 -0
  38. package/lib/components/WaveformFeedback.js +0 -1
  39. package/lib/hooks/useVoiceInputController.js +25 -6
  40. package/lib/index.d.ts +1 -0
  41. package/lib/index.js +1 -0
  42. package/lib/runtime/botAuth.d.ts +1 -1
  43. package/lib/runtime/botAuth.js +0 -3
  44. package/lib/runtime/index.d.ts +1 -0
  45. package/lib/runtime/index.js +1 -0
  46. package/lib/runtime/readerClient.d.ts +97 -0
  47. package/lib/runtime/readerClient.js +91 -0
  48. package/lib/types/voice.d.ts +4 -0
  49. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ import{_ as me}from"./assets/preload-helper-PPVm8Dsz.js";class se{registryByUrl=new Map;registryById=new Map;clear(){this.registryByUrl.clear(),this.registryById.clear()}keys(){return this.registryByUrl.keys()}add(e){this.registryByUrl.set(e.url,e),this.registryById.set(e.id,e)}register(e,t,r,i,s){const a=typeof e=="object"?e.type:e;if(typeof e=="object"){const o=e;if(o instanceof q||o instanceof O||o instanceof F||o instanceof C)throw new TypeError(`[vitest] Cannot register a mock that is already defined. Expected a JSON representation from \`MockedModule.toJSON\`, instead got "${o.type}". Use "registry.add()" to update a mock instead.`);if(o.type==="automock"){const l=q.fromJSON(o);return this.add(l),l}else if(o.type==="autospy"){const l=O.fromJSON(o);return this.add(l),l}else if(o.type==="redirect"){const l=C.fromJSON(o);return this.add(l),l}else throw o.type==="manual"?new Error("Cannot set serialized manual mock. Define a factory function manually with `ManualMockedModule.fromJSON()`."):new Error(`Unknown mock type: ${o.type}`)}if(typeof t!="string")throw new TypeError("[vitest] Mocks require a raw string.");if(typeof i!="string")throw new TypeError("[vitest] Mocks require a url string.");if(typeof r!="string")throw new TypeError("[vitest] Mocks require an id string.");if(a==="manual"){if(typeof s!="function")throw new TypeError("[vitest] Manual mocks require a factory function.");const o=new F(t,r,i,s);return this.add(o),o}else if(a==="automock"||a==="autospy"){const o=a==="automock"?new q(t,r,i):new O(t,r,i);return this.add(o),o}else if(a==="redirect"){if(typeof s!="string")throw new TypeError("[vitest] Redirect mocks require a redirect string.");const o=new C(t,r,i,s);return this.add(o),o}else throw new Error(`[vitest] Unknown mock type: ${a}`)}delete(e){this.registryByUrl.delete(e)}get(e){return this.registryByUrl.get(e)}getById(e){return this.registryById.get(e)}has(e){return this.registryByUrl.has(e)}}class q{type="automock";constructor(e,t,r){this.raw=e,this.id=t,this.url=r}static fromJSON(e){return new O(e.raw,e.id,e.url)}toJSON(){return{type:this.type,url:this.url,raw:this.raw,id:this.id}}}class O{type="autospy";constructor(e,t,r){this.raw=e,this.id=t,this.url=r}static fromJSON(e){return new O(e.raw,e.id,e.url)}toJSON(){return{type:this.type,url:this.url,id:this.id,raw:this.raw}}}class C{type="redirect";constructor(e,t,r,i){this.raw=e,this.id=t,this.url=r,this.redirect=i}static fromJSON(e){return new C(e.raw,e.id,e.url,e.redirect)}toJSON(){return{type:this.type,url:this.url,raw:this.raw,id:this.id,redirect:this.redirect}}}class F{cache;type="manual";constructor(e,t,r,i){this.raw=e,this.id=t,this.url=r,this.factory=i}async resolve(){if(this.cache)return this.cache;let e;try{e=await this.factory()}catch(t){const r=new Error('[vitest] There was an error when mocking a module. If you are using "vi.mock" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock');throw r.cause=t,r}if(e===null||typeof e!="object"||Array.isArray(e))throw new TypeError(`[vitest] vi.mock("${this.raw}", factory?: () => unknown) is not returning an object. Did you mean to return an object with a "default" key?`);return this.cache=e}static fromJSON(e,t){return new F(e.raw,e.id,e.url,t)}toJSON(){return{type:this.type,url:this.url,id:this.id,raw:this.raw}}}function ye(n,e,t={}){const r=new Array,i=new ge,s=(l,d,h)=>{try{return l[d]=h,!0}catch{return!1}},a=(l,d)=>{const h=D(l),g=h==="Module"||!!l.__esModule;for(const{key:w,descriptor:b}of K(l,g,n.globalConstructors)){if(!g&&b.get){try{Object.defineProperty(d,w,b)}catch{}continue}if(ve(w,h))continue;const y=l[w],c=i.getId(y);if(c!==void 0){r.push(()=>s(d,w,i.getMockedValue(c)));continue}const u=D(y);if(Array.isArray(y)){s(d,w,[]);continue}const x=u.includes("Function")&&typeof y=="function";if((!x||y._isMockFunction)&&u!=="Object"&&u!=="Module"){s(d,w,y);continue}if(s(d,w,x?y:{})){if(x){let _=function(){if(this instanceof d[w])for(const{key:I,descriptor:R}of K(this,!1,n.globalConstructors)){if(R.get)continue;const N=this[I];if(D(N).includes("Function")&&typeof N=="function"){const L=this[I],f=M(this,I).mockImplementation(L),$=f.mockReset;f.mockRestore=f.mockReset=()=>($.call(f),f.mockImplementation(L),f)}}};if(!n.spyOn)throw new Error("[@vitest/mocker] `spyOn` is not defined. This is a Vitest error. Please open a new issue with reproduction.");const M=n.spyOn,P=M(d,w);if(n.type==="automock"){P.mockImplementation(_);const I=P.mockReset;P.mockRestore=P.mockReset=()=>(I.call(P),P.mockImplementation(_),P)}Object.defineProperty(d[w],"length",{value:0})}i.track(y,d[w]),a(y,d[w])}}},o=t;a(e,o);for(const l of r)l();return o}class ge{idMap=new Map;mockedValueMap=new Map;getId(e){return this.idMap.get(e)}getMockedValue(e){return this.mockedValueMap.get(e)}track(e,t){const r=this.idMap.size;return this.idMap.set(e,r),this.mockedValueMap.set(r,t),r}}function D(n){return Object.prototype.toString.apply(n).slice(8,-1)}function ve(n,e){return e.includes("Function")&&typeof n=="string"&&["arguments","callee","caller","length","name"].includes(n)}function K(n,e,t){const{Map:r,Object:i,Function:s,RegExp:a,Array:o}=t,l=new r;let d=n;do{if(d===i.prototype||d===s.prototype||d===a.prototype)break;we(d,h=>{const g=i.getOwnPropertyDescriptor(d,h);g&&l.set(h,{key:h,descriptor:g})})}while(d=i.getPrototypeOf(d));if(e&&!l.has("default")&&"default"in n){const h=i.getOwnPropertyDescriptor(n,"default");h&&l.set("default",{key:"default",descriptor:h})}return o.from(l.values())}function we(n,e){const t=typeof e=="function"?e:r=>e.add(r);Object.getOwnPropertyNames(n).forEach(t),Object.getOwnPropertySymbols(n).forEach(t)}const ke=/^[A-Za-z]:\//;function ce(n=""){return n&&n.replace(/\\/g,"/").replace(ke,e=>e.toUpperCase())}const Se=/^[/\\]{2}/,_e=/^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/,Ee=/^[A-Za-z]:$/,be=/.(\.[^./]+|\.)$/,Ie=function(n){if(n.length===0)return".";n=ce(n);const e=n.match(Se),t=H(n),r=n[n.length-1]==="/";return n=Te(n,!t),n.length===0?t?"/":r?"./":".":(r&&(n+="/"),Ee.test(n)&&(n+="/"),e?t?`//${n}`:`//./${n}`:t&&!H(n)?`/${n}`:n)},xe=function(...n){let e="";for(const t of n)if(t)if(e.length>0){const r=e[e.length-1]==="/",i=t[0]==="/";r&&i?e+=t.slice(1):e+=r||i?t:`/${t}`}else e+=t;return Ie(e)};function Te(n,e){let t="",r=0,i=-1,s=0,a=null;for(let o=0;o<=n.length;++o){if(o<n.length)a=n[o];else{if(a==="/")break;a="/"}if(a==="/"){if(!(i===o-1||s===1))if(s===2){if(t.length<2||r!==2||t[t.length-1]!=="."||t[t.length-2]!=="."){if(t.length>2){const l=t.lastIndexOf("/");l===-1?(t="",r=0):(t=t.slice(0,l),r=t.length-1-t.lastIndexOf("/")),i=o,s=0;continue}else if(t.length>0){t="",r=0,i=o,s=0;continue}}e&&(t+=t.length>0?"/..":"..",r=2)}else t.length>0?t+=`/${n.slice(i+1,o)}`:t=n.slice(i+1,o),r=o-i-1;i=o,s=0}else a==="."&&s!==-1?++s:s=-1}return t}const H=function(n){return _e.test(n)},$e=function(n){if(n==="..")return"";const e=be.exec(ce(n));return e&&e[1]||""};var Pe={reset:[0,0],bold:[1,22,"\x1B[22m\x1B[1m"],dim:[2,22,"\x1B[22m\x1B[2m"],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29],black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},Me=Object.entries(Pe);function j(n){return String(n)}j.open="";j.close="";function Re(n=!1){let e=typeof process<"u"?process:void 0,t=e?.env||{},r=e?.argv||[];return!("NO_COLOR"in t||r.includes("--no-color"))&&("FORCE_COLOR"in t||r.includes("--color")||e?.platform==="win32"||n&&t.TERM!=="dumb"||"CI"in t)||typeof window<"u"&&!!window.chrome}function Ae(n=!1){let e=Re(n),t=(a,o,l,d)=>{let h="",g=0;do h+=a.substring(g,d)+l,g=d+o.length,d=a.indexOf(o,g);while(~d);return h+a.substring(g)},r=(a,o,l=a)=>{let d=h=>{let g=String(h),w=g.indexOf(o,a.length);return~w?a+t(g,o,l,w)+o:a+g+o};return d.open=a,d.close=o,d},i={isColorSupported:e},s=a=>`\x1B[${a}m`;for(let[a,o]of Me)i[a]=e?r(s(o[0]),s(o[1]),o[2]):j;return i}Ae();function ae(n,e){return e.forEach(function(t){t&&typeof t!="string"&&!Array.isArray(t)&&Object.keys(t).forEach(function(r){if(r!=="default"&&!(r in n)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(n,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}})}),Object.freeze(n)}function le(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var U={exports:{}},k={};var Z;function Oe(){if(Z)return k;Z=1;var n=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),a=Symbol.for("react.context"),o=Symbol.for("react.forward_ref"),l=Symbol.for("react.suspense"),d=Symbol.for("react.suspense_list"),h=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),w=Symbol.for("react.view_transition"),b=Symbol.for("react.client.reference");function y(c){if(typeof c=="object"&&c!==null){var u=c.$$typeof;switch(u){case n:switch(c=c.type,c){case t:case i:case r:case l:case d:case w:return c;default:switch(c=c&&c.$$typeof,c){case a:case o:case g:case h:return c;case s:return c;default:return u}}case e:return u}}}return k.ContextConsumer=s,k.ContextProvider=a,k.Element=n,k.ForwardRef=o,k.Fragment=t,k.Lazy=g,k.Memo=h,k.Portal=e,k.Profiler=i,k.StrictMode=r,k.Suspense=l,k.SuspenseList=d,k.isContextConsumer=function(c){return y(c)===s},k.isContextProvider=function(c){return y(c)===a},k.isElement=function(c){return typeof c=="object"&&c!==null&&c.$$typeof===n},k.isForwardRef=function(c){return y(c)===o},k.isFragment=function(c){return y(c)===t},k.isLazy=function(c){return y(c)===g},k.isMemo=function(c){return y(c)===h},k.isPortal=function(c){return y(c)===e},k.isProfiler=function(c){return y(c)===i},k.isStrictMode=function(c){return y(c)===r},k.isSuspense=function(c){return y(c)===l},k.isSuspenseList=function(c){return y(c)===d},k.isValidElementType=function(c){return typeof c=="string"||typeof c=="function"||c===t||c===i||c===r||c===l||c===d||typeof c=="object"&&c!==null&&(c.$$typeof===g||c.$$typeof===h||c.$$typeof===a||c.$$typeof===s||c.$$typeof===o||c.$$typeof===b||c.getModuleId!==void 0)},k.typeOf=y,k}var G;function Ce(){return G||(G=1,U.exports=Oe()),U.exports}var ue=Ce(),Ne=le(ue),Le=ae({__proto__:null,default:Ne},[ue]),z={exports:{}},v={};var Q;function Je(){if(Q)return v;Q=1;var n=Symbol.for("react.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.provider"),a=Symbol.for("react.context"),o=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),h=Symbol.for("react.suspense_list"),g=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),b=Symbol.for("react.offscreen"),y;y=Symbol.for("react.module.reference");function c(u){if(typeof u=="object"&&u!==null){var x=u.$$typeof;switch(x){case n:switch(u=u.type,u){case t:case i:case r:case d:case h:return u;default:switch(u=u&&u.$$typeof,u){case o:case a:case l:case w:case g:case s:return u;default:return x}}case e:return x}}}return v.ContextConsumer=a,v.ContextProvider=s,v.Element=n,v.ForwardRef=l,v.Fragment=t,v.Lazy=w,v.Memo=g,v.Portal=e,v.Profiler=i,v.StrictMode=r,v.Suspense=d,v.SuspenseList=h,v.isAsyncMode=function(){return!1},v.isConcurrentMode=function(){return!1},v.isContextConsumer=function(u){return c(u)===a},v.isContextProvider=function(u){return c(u)===s},v.isElement=function(u){return typeof u=="object"&&u!==null&&u.$$typeof===n},v.isForwardRef=function(u){return c(u)===l},v.isFragment=function(u){return c(u)===t},v.isLazy=function(u){return c(u)===w},v.isMemo=function(u){return c(u)===g},v.isPortal=function(u){return c(u)===e},v.isProfiler=function(u){return c(u)===i},v.isStrictMode=function(u){return c(u)===r},v.isSuspense=function(u){return c(u)===d},v.isSuspenseList=function(u){return c(u)===h},v.isValidElementType=function(u){return typeof u=="string"||typeof u=="function"||u===t||u===i||u===r||u===d||u===h||u===b||typeof u=="object"&&u!==null&&(u.$$typeof===w||u.$$typeof===g||u.$$typeof===s||u.$$typeof===a||u.$$typeof===l||u.$$typeof===y||u.getModuleId!==void 0)},v.typeOf=c,v}var ee;function Be(){return ee||(ee=1,z.exports=Je()),z.exports}var fe=Be(),Xe=le(fe),qe=ae({__proto__:null,default:Xe},[fe]);const Fe=["isAsyncMode","isConcurrentMode","isContextConsumer","isContextProvider","isElement","isForwardRef","isFragment","isLazy","isMemo","isPortal","isProfiler","isStrictMode","isSuspense","isSuspenseList","isValidElementType"];Object.fromEntries(Fe.map(n=>[n,e=>qe[n](e)||Le[n](e)]));let De=()=>"Promise{…}";try{const{getPromiseDetails:n,kPending:e,kRejected:t}=process.binding("util");Array.isArray(n(Promise.resolve()))&&(De=(r,i)=>{const[s,a]=n(r);return s===e?"Promise{<pending>}":`Promise${s===t?"!":""}{${i.inspect(a,i)}}`})}catch{}function Ue(n){const{message:e="$$stack trace error",stackTraceLimit:t=1}=n||{},r=Error.stackTraceLimit,i=Error.prepareStackTrace;Error.stackTraceLimit=t,Error.prepareStackTrace=o=>o.stack;const a=new Error(e).stack||"";return Error.prepareStackTrace=i,Error.stackTraceLimit=r,a}var V,te;function ze(){if(te)return V;te=1;var n,e,t,r,i,s,a,o,l,d,h,g,w,b,y,c,u,x,M;return w=/\/(?![*\/])(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\\]).|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/uy,g=/--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y,n=/(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/uy,y=/(['"])(?:(?!\1)[^\\\n\r]|\\(?:\r\n|[^]))*(\1)?/y,h=/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[oO][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*)n?|0n|[1-9](?:_?\d)*n|(?:(?:0(?!\d)|0\d*[89]\d*|[1-9](?:_?\d)*)(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?|0[0-7]+/y,c=/[`}](?:[^`\\$]|\\[^]|\$(?!\{))*(`|\$\{)?/y,M=/[\t\v\f\ufeff\p{Zs}]+/uy,o=/\r?\n|[\r\u2028\u2029]/y,l=/\/\*(?:[^*]|\*(?!\/))*(\*\/)?/y,b=/\/\/.*/y,t=/[<>.:={}]|\/(?![\/*])/y,e=/[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}-]*/uy,r=/(['"])(?:(?!\1)[^])*(\1)?/y,i=/[^<>{}]+/y,x=/^(?:[\/+-]|\.{3}|\?(?:InterpolationIn(?:JSX|Template)|NoLineTerminatorHere|NonExpressionParenEnd|UnaryIncDec))?$|[{}([,;<>=*%&|^!~?:]$/,u=/^(?:=>|[;\]){}]|else|\?(?:NoLineTerminatorHere|NonExpressionParenEnd))?$/,s=/^(?:await|case|default|delete|do|else|instanceof|new|return|throw|typeof|void|yield)$/,a=/^(?:return|throw|yield)$/,d=RegExp(o.source),V=function*(_,{jsx:P=!1}={}){var I,R,N,p,m,L,f,$,Y,T,J,S,B,E;for({length:L}=_,p=0,m="",E=[{tag:"JS"}],I=[],J=0,S=!1;p<L;){switch($=E[E.length-1],$.tag){case"JS":case"JSNonExpressionParen":case"InterpolationInTemplate":case"InterpolationInJSX":if(_[p]==="/"&&(x.test(m)||s.test(m))&&(w.lastIndex=p,f=w.exec(_))){p=w.lastIndex,m=f[0],S=!0,yield{type:"RegularExpressionLiteral",value:f[0],closed:f[1]!==void 0&&f[1]!=="\\"};continue}if(g.lastIndex=p,f=g.exec(_)){switch(B=f[0],Y=g.lastIndex,T=B,B){case"(":m==="?NonExpressionParenKeyword"&&E.push({tag:"JSNonExpressionParen",nesting:J}),J++,S=!1;break;case")":J--,S=!0,$.tag==="JSNonExpressionParen"&&J===$.nesting&&(E.pop(),T="?NonExpressionParenEnd",S=!1);break;case"{":g.lastIndex=0,N=!u.test(m)&&(x.test(m)||s.test(m)),I.push(N),S=!1;break;case"}":switch($.tag){case"InterpolationInTemplate":if(I.length===$.nesting){c.lastIndex=p,f=c.exec(_),p=c.lastIndex,m=f[0],f[1]==="${"?(m="?InterpolationInTemplate",S=!1,yield{type:"TemplateMiddle",value:f[0]}):(E.pop(),S=!0,yield{type:"TemplateTail",value:f[0],closed:f[1]==="`"});continue}break;case"InterpolationInJSX":if(I.length===$.nesting){E.pop(),p+=1,m="}",yield{type:"JSXPunctuator",value:"}"};continue}}S=I.pop(),T=S?"?ExpressionBraceEnd":"}";break;case"]":S=!0;break;case"++":case"--":T=S?"?PostfixIncDec":"?UnaryIncDec";break;case"<":if(P&&(x.test(m)||s.test(m))){E.push({tag:"JSXTag"}),p+=1,m="<",yield{type:"JSXPunctuator",value:B};continue}S=!1;break;default:S=!1}p=Y,m=T,yield{type:"Punctuator",value:B};continue}if(n.lastIndex=p,f=n.exec(_)){switch(p=n.lastIndex,T=f[0],f[0]){case"for":case"if":case"while":case"with":m!=="."&&m!=="?."&&(T="?NonExpressionParenKeyword")}m=T,S=!s.test(f[0]),yield{type:f[1]==="#"?"PrivateIdentifier":"IdentifierName",value:f[0]};continue}if(y.lastIndex=p,f=y.exec(_)){p=y.lastIndex,m=f[0],S=!0,yield{type:"StringLiteral",value:f[0],closed:f[2]!==void 0};continue}if(h.lastIndex=p,f=h.exec(_)){p=h.lastIndex,m=f[0],S=!0,yield{type:"NumericLiteral",value:f[0]};continue}if(c.lastIndex=p,f=c.exec(_)){p=c.lastIndex,m=f[0],f[1]==="${"?(m="?InterpolationInTemplate",E.push({tag:"InterpolationInTemplate",nesting:I.length}),S=!1,yield{type:"TemplateHead",value:f[0]}):(S=!0,yield{type:"NoSubstitutionTemplate",value:f[0],closed:f[1]==="`"});continue}break;case"JSXTag":case"JSXTagEnd":if(t.lastIndex=p,f=t.exec(_)){switch(p=t.lastIndex,T=f[0],f[0]){case"<":E.push({tag:"JSXTag"});break;case">":E.pop(),m==="/"||$.tag==="JSXTagEnd"?(T="?JSX",S=!0):E.push({tag:"JSXChildren"});break;case"{":E.push({tag:"InterpolationInJSX",nesting:I.length}),T="?InterpolationInJSX",S=!1;break;case"/":m==="<"&&(E.pop(),E[E.length-1].tag==="JSXChildren"&&E.pop(),E.push({tag:"JSXTagEnd"}))}m=T,yield{type:"JSXPunctuator",value:f[0]};continue}if(e.lastIndex=p,f=e.exec(_)){p=e.lastIndex,m=f[0],yield{type:"JSXIdentifier",value:f[0]};continue}if(r.lastIndex=p,f=r.exec(_)){p=r.lastIndex,m=f[0],yield{type:"JSXString",value:f[0],closed:f[2]!==void 0};continue}break;case"JSXChildren":if(i.lastIndex=p,f=i.exec(_)){p=i.lastIndex,m=f[0],yield{type:"JSXText",value:f[0]};continue}switch(_[p]){case"<":E.push({tag:"JSXTag"}),p++,m="<",yield{type:"JSXPunctuator",value:"<"};continue;case"{":E.push({tag:"InterpolationInJSX",nesting:I.length}),p++,m="?InterpolationInJSX",S=!1,yield{type:"JSXPunctuator",value:"{"};continue}}if(M.lastIndex=p,f=M.exec(_)){p=M.lastIndex,yield{type:"WhiteSpace",value:f[0]};continue}if(o.lastIndex=p,f=o.exec(_)){p=o.lastIndex,S=!1,a.test(m)&&(m="?NoLineTerminatorHere"),yield{type:"LineTerminatorSequence",value:f[0]};continue}if(l.lastIndex=p,f=l.exec(_)){p=l.lastIndex,d.test(f[0])&&(S=!1,a.test(m)&&(m="?NoLineTerminatorHere")),yield{type:"MultiLineComment",value:f[0],closed:f[1]!==void 0};continue}if(b.lastIndex=p,f=b.exec(_)){p=b.lastIndex,S=!1,yield{type:"SingleLineComment",value:f[0]};continue}R=String.fromCodePoint(_.codePointAt(p)),p+=R.length,m=R,S=!1,yield{type:$.tag.startsWith("JSX")?"JSXInvalid":"Invalid",value:R}}},V}ze();var de={keyword:["break","case","catch","continue","debugger","default","do","else","finally","for","function","if","return","switch","throw","try","var","const","while","with","new","this","super","class","extends","export","import","null","true","false","in","instanceof","typeof","void","delete"],strict:["implements","interface","let","package","private","protected","public","static","yield"]};new Set(de.keyword);new Set(de.strict);const re="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Ve=new Uint8Array(64),We=new Uint8Array(128);for(let n=0;n<re.length;n++){const e=re.charCodeAt(n);Ve[n]=e,We[e]=n}var ne;(function(n){n[n.Empty=1]="Empty",n[n.Hash=2]="Hash",n[n.Query=3]="Query",n[n.RelativePath=4]="RelativePath",n[n.AbsolutePath=5]="AbsolutePath",n[n.SchemeRelative=6]="SchemeRelative",n[n.Absolute=7]="Absolute"})(ne||(ne={}));const je=/^[A-Za-z]:\//;function Ye(n=""){return n&&n.replace(/\\/g,"/").replace(je,e=>e.toUpperCase())}const Ke=/^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;function He(){return typeof process<"u"&&typeof process.cwd=="function"?process.cwd().replace(/\\/g,"/"):"/"}const Ze=function(...n){n=n.map(r=>Ye(r));let e="",t=!1;for(let r=n.length-1;r>=-1&&!t;r--){const i=r>=0?n[r]:He();!i||i.length===0||(e=`${i}/${e}`,t=ie(i))}return e=Ge(e,!t),t&&!ie(e)?`/${e}`:e.length>0?e:"."};function Ge(n,e){let t="",r=0,i=-1,s=0,a=null;for(let o=0;o<=n.length;++o){if(o<n.length)a=n[o];else{if(a==="/")break;a="/"}if(a==="/"){if(!(i===o-1||s===1))if(s===2){if(t.length<2||r!==2||t[t.length-1]!=="."||t[t.length-2]!=="."){if(t.length>2){const l=t.lastIndexOf("/");l===-1?(t="",r=0):(t=t.slice(0,l),r=t.length-1-t.lastIndexOf("/")),i=o,s=0;continue}else if(t.length>0){t="",r=0,i=o,s=0;continue}}e&&(t+=t.length>0?"/..":"..",r=2)}else t.length>0?t+=`/${n.slice(i+1,o)}`:t=n.slice(i+1,o),r=o-i-1;i=o,s=0}else a==="."&&s!==-1?++s:s=-1}return t}const ie=function(n){return Ke.test(n)},pe=/^\s*at .*(?:\S:\d+|\(native\))/m,Qe=/^(?:eval@)?(?:\[native code\])?$/;function he(n){if(!n.includes(":"))return[n];const t=/(.+?)(?::(\d+))?(?::(\d+))?$/.exec(n.replace(/^\(|\)$/g,""));if(!t)return[n];let r=t[1];if(r.startsWith("async ")&&(r=r.slice(6)),r.startsWith("http:")||r.startsWith("https:")){const i=new URL(r);i.searchParams.delete("import"),i.searchParams.delete("browserv"),r=i.pathname+i.hash+i.search}if(r.startsWith("/@fs/")){const i=/^\/@fs\/[a-zA-Z]:\//.test(r);r=r.slice(i?5:4)}return[r,t[2]||void 0,t[3]||void 0]}function et(n){let e=n.trim();if(Qe.test(e)||(e.includes(" > eval")&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),!e.includes("@")&&!e.includes(":")))return null;const t=/((.*".+"[^@]*)?[^@]*)(@)/,r=e.match(t),i=r&&r[1]?r[1]:void 0,[s,a,o]=he(e.replace(t,""));return!s||!a||!o?null:{file:s,method:i||"",line:Number.parseInt(a),column:Number.parseInt(o)}}function tt(n){const e=n.trim();return pe.test(e)?rt(e):et(e)}function rt(n){let e=n.trim();if(!pe.test(e))return null;e.includes("(eval ")&&(e=e.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(,.*$)/g,""));let t=e.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/^.*?\s+/,"");const r=t.match(/ (\(.+\)$)/);t=r?t.replace(r[0],""):t;const[i,s,a]=he(r?r[1]:t);let o=r&&t||"",l=i&&["eval","<anonymous>"].includes(i)?void 0:i;return!l||!s||!a?null:(o.startsWith("async ")&&(o=o.slice(6)),l.startsWith("file://")&&(l=l.slice(7)),l=l.startsWith("node:")||l.startsWith("internal:")?l:Ze(l),o&&(o=o.replace(/__vite_ssr_import_\d+__\./g,"")),{method:o,file:l,line:Number.parseInt(s),column:Number.parseInt(a)})}function nt(n){const e=n?.globalThisKey||"__vitest_mocker__";function t(){return typeof globalThis[e]<"u"?globalThis[e]:new Proxy({},{get(r,i){throw new Error(`Vitest mocker was not initialized in this environment. vi.${String(i)}() is forbidden.`)}})}return{hoisted(r){if(typeof r!="function")throw new TypeError(`vi.hoisted() expects a function, but received a ${typeof r}`);return r()},mock(r,i){if(typeof r!="string")throw new TypeError(`vi.mock() expects a string path, but received a ${typeof r}`);const s=A("mock");t().queueMock(r,s,typeof i=="function"?()=>i(()=>t().importActual(r,s)):i)},unmock(r){if(typeof r!="string")throw new TypeError(`vi.unmock() expects a string path, but received a ${typeof r}`);t().queueUnmock(r,A("unmock"))},doMock(r,i){if(typeof r!="string")throw new TypeError(`vi.doMock() expects a string path, but received a ${typeof r}`);const s=A("doMock");t().queueMock(r,s,typeof i=="function"?()=>i(()=>t().importActual(r,s)):i)},doUnmock(r){if(typeof r!="string")throw new TypeError(`vi.doUnmock() expects a string path, but received a ${typeof r}`);t().queueUnmock(r,A("doUnmock"))},async importActual(r){return t().importActual(r,A("importActual"))},async importMock(r){return t().importMock(r,A("importMock"))}}}function A(n){const t=Ue({stackTraceLimit:5}).split(`
2
+ `),r=t.findIndex(s=>s.includes(` at Object.${n}`)||s.includes(`${n}@`)),i=tt(t[r+1]);return i?.file||""}const{now:oe}=Date;class it{registry=new se;queue=new Set;mockedIds=new Set;constructor(e,t,r,i){this.interceptor=e,this.rpc=t,this.spyOn=r,this.config=i}async prepare(){this.queue.size&&await Promise.all([...this.queue.values()])}async resolveFactoryModule(e){const t=this.registry.get(e);if(!t||t.type!=="manual")throw new Error(`Mock ${e} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);return await t.resolve()}getFactoryModule(e){const t=this.registry.get(e);if(!t||t.type!=="manual")throw new Error(`Mock ${e} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);if(!t.cache)throw new Error(`Mock ${e} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction.`);return t.cache}async invalidate(){const e=Array.from(this.mockedIds);e.length&&(await this.rpc.invalidate(e),await this.interceptor.invalidate(),this.registry.clear())}async importActual(e,t){const r=await this.rpc.resolveId(e,t);if(r==null)throw new Error(`[vitest] Cannot resolve "${e}" imported from "${t}"`);const i=$e(r.id),s=new URL(r.url,location.href),a=`_vitest_original&ext${i}`,o=`${s.pathname}${s.search?`${s.search}&${a}`:`?${a}`}${s.hash}`;return this.wrapDynamicImport(()=>import(o)).then(l=>{if(!r.optimized||typeof l.default>"u")return l;const d=l.default;return d?.__esModule?d:{...typeof d=="object"&&!Array.isArray(d)||typeof d=="function"?d:{},default:d}})}async importMock(e,t){await this.prepare();const{resolvedId:r,resolvedUrl:i,redirectUrl:s}=await this.rpc.resolveMock(e,t,{mock:"auto"}),a=this.resolveMockPath(X(i));let o=this.registry.get(a);if(!o)if(s){const l=new URL(this.resolveMockPath(X(s)),location.href).toString();o=new C(e,r,a,l)}else o=new q(e,r,a);if(o.type==="manual")return await o.resolve();if(o.type==="automock"||o.type==="autospy"){const l=new URL(`/@id/${r}`,location.href),d=l.search?`${l.search}&t=${oe()}`:`?t=${oe()}`,h=await me(()=>import(`${l.pathname}${d}&mock=${o.type}${l.hash}`),[],import.meta.url);return this.mockObject(h,o.type)}return import(o.redirect)}mockObject(e,t="automock"){return ye({globalConstructors:{Object,Function,Array,Map,RegExp},spyOn:this.spyOn,type:t},e)}queueMock(e,t,r){const i=this.rpc.resolveMock(e,t,{mock:typeof r=="function"?"factory":r?.spy?"spy":"auto"}).then(async({redirectUrl:s,resolvedId:a,resolvedUrl:o,needsInterop:l,mockType:d})=>{const h=this.resolveMockPath(X(o));this.mockedIds.add(a);const g=typeof r=="function"?async()=>{const y=await r();return l?{default:y}:y}:void 0,w=typeof s=="string"?new URL(this.resolveMockPath(X(s)),location.href).toString():null;let b;d==="manual"?b=this.registry.register("manual",e,a,h,g):d==="autospy"?b=this.registry.register("autospy",e,a,h):d==="redirect"?b=this.registry.register("redirect",e,a,h,w):b=this.registry.register("automock",e,a,h),await this.interceptor.register(b)}).finally(()=>{this.queue.delete(i)});this.queue.add(i)}queueUnmock(e,t){const r=this.rpc.resolveId(e,t).then(async i=>{if(!i)return;const s=this.resolveMockPath(X(i.url));this.mockedIds.add(i.id),this.registry.delete(s),await this.interceptor.delete(s)}).finally(()=>{this.queue.delete(r)});this.queue.add(r)}wrapDynamicImport(e){return typeof e=="function"?new Promise((r,i)=>{this.prepare().finally(()=>{e().then(r,i)})}):e}resolveMockPath(e){const t=this.config,r=xe("/@fs/",t.root);return e.startsWith(t.root)?e.slice(t.root.length):e.startsWith(r)?e.slice(r.length):e}}const ot=/(\?|&)v=\w{8}/;function X(n){return n.replace(ot,"")}class st{mocks=new se;constructor(){}async register(e){this.mocks.add(e)}async delete(e){this.mocks.delete(e)}async invalidate(){this.mocks.clear()}}const W=n=>{switch(n){case"resolveId":return Promise.resolve({id:"",url:"",optimized:!1});case"resolveMock":return Promise.resolve({mockType:"dummy",resolvedId:"",resolvedUrl:"",redirectUrl:"",needsInterop:!1});case"invalidate":return Promise.resolve()}};class ct extends it{queueMock(){}}function at(n){const e=new ct(n("__vitest_mocker__"),{resolveId(t,r){return W("resolveId")},resolveMock(t,r,i){return W("resolveMock")},async invalidate(t){return W("invalidate")}},(...t)=>globalThis.__STORYBOOK_MODULE_TEST__.spyOn(...t),{root:""});return globalThis.__vitest_mocker__=e,nt({globalThisKey:"__vitest_mocker__"})}globalThis.__STORYBOOK_MOCKER__=at(()=>new st);
@@ -30,6 +30,7 @@ function DesktopInner(props) {
30
30
  const fileInputRef = useRef(null);
31
31
  const voice = useVoiceInputController({
32
32
  ...props.voice,
33
+ onVoiceTranscript: props.voice?.onVoiceTranscript,
33
34
  onVoiceSend: async (blob) => {
34
35
  await props.voice?.onVoiceSend?.(blob);
35
36
  await props.onSend?.({
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { Provider, createStore } from "jotai";
4
4
  import { useEffect, useRef, useState } from "react";
@@ -35,6 +35,7 @@ function MobileInner(props) {
35
35
  const fileInputRef = useRef(null);
36
36
  const voice = useVoiceInputController({
37
37
  ...props.voice,
38
+ onVoiceTranscript: props.voice?.onVoiceTranscript,
38
39
  onVoiceSend: async (blob) => {
39
40
  await props.onSend?.({
40
41
  text: "",
@@ -313,7 +314,7 @@ function MobileInner(props) {
313
314
  gridTemplateColumns: "30px minmax(0, 1fr) 30px 30px",
314
315
  gap: 4,
315
316
  alignItems: "center",
316
- padding: "0 0 env(safe-area-inset-bottom, 0px)",
317
+ padding: 0,
317
318
  }, children: [_jsx(EmojiPicker, { open: isEmojiOpen, isMobile: true, anchorRef: emojiAnchorRef, onSelect: insertEmoji, onClose: () => setIsEmojiOpen(false) }), _jsx("button", { type: "button", "aria-label": state.mode === "voice" ? "切换到文字输入" : "切换到语音输入", disabled: props.disabled || props.enableVoice === false, onClick: () => {
318
319
  const next = state.mode === "voice" ? "text" : "voice";
319
320
  state.setMode(next);
@@ -325,6 +326,7 @@ function MobileInner(props) {
325
326
  : tokens.color.iconDefault,
326
327
  opacity: props.disabled ? 0.45 : 1,
327
328
  }, children: state.mode === "voice" ? (_jsx(KeyboardOutlineIcon, { size: 27 })) : (_jsx(MicOutlineIcon, { size: 24, strokeWidth: 2 })) }), _jsx(InputSurface, { tokens: tokens, status: state.status, styleOverride: {
329
+ gridColumn: state.mode === "voice" ? "2 / 5" : undefined,
328
330
  borderRadius: tokens.radius.inputSurface,
329
331
  background: state.status === "error"
330
332
  ? tokens.color.surfaceInputError
@@ -342,8 +344,8 @@ function MobileInner(props) {
342
344
  minHeight: 48,
343
345
  display: "flex",
344
346
  alignItems: "center",
345
- padding: state.mode === "voice" ? "0" : "0 12px",
346
- }, children: state.mode === "voice" ? (_jsx("div", { style: { minHeight: 48 }, children: _jsx(HoldToTalkButton, { tokens: tokens, active: isRecordingOverlayVisible, disabled: props.disabled, text: "\u6309\u4F4F \u8BF4\u8BDD", activeText: "\u677E\u5F00 \u53D1\u9001", onPressStart: () => {
347
+ padding: state.mode === "voice" ? 0 : "0 12px",
348
+ }, children: state.mode === "voice" ? (_jsx("div", { style: { minHeight: 48, width: "100%" }, children: _jsx(HoldToTalkButton, { tokens: tokens, active: isRecordingOverlayVisible, disabled: props.disabled, text: "\u6309\u4F4F \u8BF4\u8BDD", activeText: "\u677E\u5F00 \u53D1\u9001", onPressStart: () => {
347
349
  setRecordingChoice("send");
348
350
  voice.startRecording();
349
351
  }, onPressMove: (event) => {
@@ -386,23 +388,23 @@ function MobileInner(props) {
386
388
  fontSize: tokens.typography.inputText.size,
387
389
  lineHeight: `${tokens.typography.inputText.lineHeight}px`,
388
390
  caretColor: tokens.color.brandPrimary,
389
- } })) }), _jsx(EmojiTrigger, { ref: emojiAnchorRef, "data-icon-size": 24, onClick: () => {
390
- setIsMoreOpen(false);
391
- setIsEmojiOpen((prev) => !prev);
392
- }, style: {
393
- ...sideActionStyle,
394
- width: 30,
395
- height: 30,
396
- } }), _jsx(MoreTrigger, { "data-icon-size": 24, onClick: () => {
397
- setIsEmojiOpen(false);
398
- setIsMoreOpen((prev) => !prev);
399
- }, disabled: props.disabled, style: {
400
- ...sideActionStyle,
401
- color: isMoreOpen ? tokens.color.iconActive : tokens.color.iconDefault,
402
- width: 30,
403
- height: 30,
404
- opacity: props.disabled ? 0.4 : 1,
405
- } })] }), _jsx(StatusHint, { tokens: tokens, text: state.status === "recording" || state.status === "transcribing" ? undefined : statusText, tone: state.status === "error" ? "error" : "secondary" })] }));
391
+ } })) }), state.mode === "voice" ? null : (_jsxs(_Fragment, { children: [_jsx(EmojiTrigger, { ref: emojiAnchorRef, "data-icon-size": 24, onClick: () => {
392
+ setIsMoreOpen(false);
393
+ setIsEmojiOpen((prev) => !prev);
394
+ }, style: {
395
+ ...sideActionStyle,
396
+ width: 30,
397
+ height: 30,
398
+ } }), _jsx(MoreTrigger, { "data-icon-size": 24, onClick: () => {
399
+ setIsEmojiOpen(false);
400
+ setIsMoreOpen((prev) => !prev);
401
+ }, disabled: props.disabled, style: {
402
+ ...sideActionStyle,
403
+ color: isMoreOpen ? tokens.color.iconActive : tokens.color.iconDefault,
404
+ width: 30,
405
+ height: 30,
406
+ opacity: props.disabled ? 0.4 : 1,
407
+ } })] }))] }), _jsx(StatusHint, { tokens: tokens, text: state.status === "recording" || state.status === "transcribing" ? undefined : statusText, tone: state.status === "error" ? "error" : "secondary" })] }));
406
408
  }
407
409
  export function ChatInputMobile(props) {
408
410
  const stateKey = JSON.stringify({
@@ -24,6 +24,10 @@ export function HoldToTalkButton({ tokens, active, disabled, text = "按住 说
24
24
  boxShadow: "none",
25
25
  padding: "0 16px",
26
26
  minHeight: 48,
27
+ height: "100%",
28
+ display: "flex",
29
+ alignItems: "center",
30
+ justifyContent: "center",
27
31
  fontFamily: tokens.typography.familyBase,
28
32
  fontSize: tokens.typography.voiceHoldToTalk.size,
29
33
  lineHeight: `${tokens.typography.voiceHoldToTalk.lineHeight}px`,
@@ -8,7 +8,6 @@ export function WaveformFeedback({ levels, tokens, compact = false, }) {
8
8
  justifyContent: "center",
9
9
  gap: compact ? 2 : 3,
10
10
  minHeight: compact ? 24 : 30,
11
- filter: compact ? "blur(0.15px)" : "blur(0.1px)",
12
11
  }, children: normalizedLevels.map((level, index) => {
13
12
  const distanceFromCenter = Math.abs(index - (normalizedLevels.length - 1) / 2);
14
13
  const centerWeight = 1 - distanceFromCenter / ((normalizedLevels.length + 1) / 2);
@@ -36,13 +36,15 @@ export function useVoiceInputController(config) {
36
36
  setDurationMs(0);
37
37
  if (stopActionRef.current === "transcribe") {
38
38
  setStatus("transcribing");
39
- void transcribeBlob(blob);
39
+ void transcribeBlob(blob, "transcribe");
40
40
  return;
41
41
  }
42
- setTranscript("");
43
- setStatus(modeRef.current === "voice" ? "voice-mode-ready" : "idle");
44
- setError(null);
45
- void configRef.current?.onVoiceSend?.(blob);
42
+ if (configRef.current?.asrClient || configRef.current?.simulatedTranscript) {
43
+ setStatus("transcribing");
44
+ void transcribeBlob(blob, "send");
45
+ return;
46
+ }
47
+ finishVoiceSend(blob);
46
48
  });
47
49
  const unsubAbort = manager.on(MicEvents.Abort, () => {
48
50
  setLevels(DEFAULT_WAVEFORM);
@@ -67,7 +69,7 @@ export function useVoiceInputController(config) {
67
69
  managerRef.current = null;
68
70
  };
69
71
  }, []);
70
- async function transcribeBlob(blob) {
72
+ async function transcribeBlob(blob, action) {
71
73
  try {
72
74
  const transcribeTimeoutMs = configRef.current?.transcribeTimeoutMs ?? DEFAULT_TRANSCRIBE_TIMEOUT_MS;
73
75
  const nextTranscript = configRef.current?.asrClient
@@ -80,6 +82,17 @@ export function useVoiceInputController(config) {
80
82
  setError("No speech was recognized.");
81
83
  return;
82
84
  }
85
+ if (action === "send") {
86
+ setTranscript("");
87
+ setDurationMs(0);
88
+ setStatus(modeRef.current === "voice" ? "voice-mode-ready" : "idle");
89
+ setError(null);
90
+ await configRef.current?.onVoiceTranscript?.(nextTranscript, {
91
+ blob,
92
+ action,
93
+ });
94
+ return;
95
+ }
83
96
  setTranscript(nextTranscript);
84
97
  setText(insertTranscriptText(textRef.current, nextTranscript));
85
98
  setDurationMs(0);
@@ -91,6 +104,12 @@ export function useVoiceInputController(config) {
91
104
  setError(error instanceof Error ? error.message : String(error));
92
105
  }
93
106
  }
107
+ function finishVoiceSend(blob) {
108
+ setTranscript("");
109
+ setStatus(modeRef.current === "voice" ? "voice-mode-ready" : "idle");
110
+ setError(null);
111
+ void configRef.current?.onVoiceSend?.(blob);
112
+ }
94
113
  function beginVoiceMode() {
95
114
  setMode("voice");
96
115
  setStatus("voice-mode-ready");
package/lib/index.d.ts CHANGED
@@ -19,6 +19,7 @@ export * from "./services/authTokenResolver";
19
19
  export * from "./runtime/botAuth";
20
20
  export * from "./runtime/botKey";
21
21
  export * from "./runtime/chatClient";
22
+ export * from "./runtime/readerClient";
22
23
  export * from "./runtime/thread";
23
24
  export * from "./tokens/defaultTokens";
24
25
  export * from "./tokens/chatInputThemes";
package/lib/index.js CHANGED
@@ -19,6 +19,7 @@ export * from "./services/authTokenResolver";
19
19
  export * from "./runtime/botAuth";
20
20
  export * from "./runtime/botKey";
21
21
  export * from "./runtime/chatClient";
22
+ export * from "./runtime/readerClient";
22
23
  export * from "./runtime/thread";
23
24
  export * from "./tokens/defaultTokens";
24
25
  export * from "./tokens/chatInputThemes";
@@ -1,4 +1,4 @@
1
- import { type PmateBotKeyFile } from "./botKey.js";
1
+ import type { PmateBotKeyFile } from "./botKey.js";
2
2
  export type BotLoginChallenge = {
3
3
  id: string;
4
4
  app: string;
@@ -1,13 +1,10 @@
1
- import { botCredentialId } from "./botKey.js";
2
1
  const DEFAULT_AUTH_API_BASE_URL = "https://auth-api-v2.pmate.chat";
3
2
  export async function loginPmateBot(input) {
4
3
  const fetcher = input.fetchImpl ?? fetch;
5
4
  const baseUrl = (input.authBaseUrl ?? DEFAULT_AUTH_API_BASE_URL).replace(/\/+$/, "");
6
- const credentialId = botCredentialId(input.botKey);
7
5
  const challenge = await post(fetcher, baseUrl, "/accounts/bots/session/challenge", {
8
6
  app: input.botKey.app,
9
7
  name: input.botKey.name,
10
- credentialId,
11
8
  });
12
9
  const signature = await signBotChallenge(challenge, input.botKey.privateKey);
13
10
  return post(fetcher, baseUrl, "/accounts/bots/session", {
@@ -2,4 +2,5 @@ export * from "./botAuth.js";
2
2
  export * from "./botKey.js";
3
3
  export * from "./chatClient.js";
4
4
  export * from "./protocol.js";
5
+ export * from "./readerClient.js";
5
6
  export * from "./thread.js";
@@ -2,4 +2,5 @@ export * from "./botAuth.js";
2
2
  export * from "./botKey.js";
3
3
  export * from "./chatClient.js";
4
4
  export * from "./protocol.js";
5
+ export * from "./readerClient.js";
5
6
  export * from "./thread.js";
@@ -0,0 +1,97 @@
1
+ export type ChatReaderClientOptions = {
2
+ baseUrl?: string;
3
+ appId: string;
4
+ chainId?: string;
5
+ socialChainId?: string;
6
+ fetchImpl?: typeof fetch;
7
+ };
8
+ export type ChatReaderEnvelope<T> = {
9
+ success?: boolean;
10
+ data?: T;
11
+ message?: string;
12
+ };
13
+ export type ChatReaderMessage = {
14
+ hash: string;
15
+ t: number;
16
+ from: string;
17
+ to: string;
18
+ opcode: number;
19
+ kind: number;
20
+ body: unknown;
21
+ recipients?: string[];
22
+ };
23
+ export type ChatReaderThread = {
24
+ threadHash: string;
25
+ type: "dm" | "group";
26
+ associatedId: string;
27
+ lastUpdateAt: number;
28
+ name: string;
29
+ avatar: string;
30
+ lastMessage: ChatReaderMessage;
31
+ total: number;
32
+ unread: number;
33
+ };
34
+ export type ChatReaderContact = {
35
+ id?: string;
36
+ accountId?: string;
37
+ peerId?: string;
38
+ type?: "dm" | "group" | "user";
39
+ name?: string;
40
+ nickName?: string;
41
+ title?: string;
42
+ avatar?: string;
43
+ relationship?: string;
44
+ threadId?: string;
45
+ updatedAt?: number;
46
+ members?: string[];
47
+ };
48
+ export type ChatReaderSocialMessage = {
49
+ appId: string;
50
+ threadId: string;
51
+ threadKind: "dm" | "group";
52
+ messageId: string;
53
+ from: string;
54
+ to: string;
55
+ recipients?: string[];
56
+ body: unknown;
57
+ clientCreatedAt?: number;
58
+ serverCreatedAt: number;
59
+ };
60
+ export type ChatReaderMessagePage = {
61
+ page: number;
62
+ totalPage: number;
63
+ pageSize: number;
64
+ data: ChatReaderMessage[];
65
+ };
66
+ export type ChatReaderUnread = {
67
+ appId: string;
68
+ accountId: string;
69
+ threadId: string;
70
+ unreadCount: number;
71
+ };
72
+ export declare class ChatReaderClient {
73
+ private readonly options;
74
+ private readonly baseUrl;
75
+ private readonly chainId;
76
+ private readonly socialChainId;
77
+ private readonly fetchImpl;
78
+ constructor(options: ChatReaderClientOptions);
79
+ listThreads(userId: string): Promise<ChatReaderThread[]>;
80
+ getThread(userId: string, threadHash: string): Promise<ChatReaderThread | null>;
81
+ listSocialContacts(accountId: string): Promise<ChatReaderContact[]>;
82
+ listSocialUnread(accountId: string): Promise<ChatReaderUnread[]>;
83
+ listSocialMessages(threadId: string): Promise<ChatReaderSocialMessage[]>;
84
+ listThreadMessages(input: {
85
+ userId: string;
86
+ threadHash: string;
87
+ page?: number;
88
+ }): Promise<ChatReaderMessagePage | null>;
89
+ markRead(input: {
90
+ userId: string;
91
+ threadHash: string;
92
+ hashes: string[];
93
+ }): Promise<unknown>;
94
+ private indexerRequest;
95
+ private request;
96
+ }
97
+ export declare function createChatReaderClient(options: ChatReaderClientOptions): ChatReaderClient;
@@ -0,0 +1,91 @@
1
+ const DEFAULT_INDEXER_URL = "https://indexer.pmate.chat";
2
+ const DEFAULT_CHAIN_ID = "pmate";
3
+ const DEFAULT_SOCIAL_CHAIN_ID = "social";
4
+ export class ChatReaderClient {
5
+ options;
6
+ baseUrl;
7
+ chainId;
8
+ socialChainId;
9
+ fetchImpl;
10
+ constructor(options) {
11
+ this.options = options;
12
+ this.baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_INDEXER_URL);
13
+ this.chainId = options.chainId ?? DEFAULT_CHAIN_ID;
14
+ this.socialChainId = options.socialChainId ?? DEFAULT_SOCIAL_CHAIN_ID;
15
+ this.fetchImpl = options.fetchImpl ?? fetch;
16
+ }
17
+ async listThreads(userId) {
18
+ return this.indexerRequest("thread", "threads", { user: userId });
19
+ }
20
+ async getThread(userId, threadHash) {
21
+ return this.indexerRequest("thread", "thread", { user: userId, threadHash });
22
+ }
23
+ async listSocialContacts(accountId) {
24
+ return this.indexerRequest("social_indexer", "contacts", {
25
+ appId: this.options.appId,
26
+ accountId,
27
+ }, undefined, { chainId: this.socialChainId });
28
+ }
29
+ async listSocialUnread(accountId) {
30
+ return this.indexerRequest("social_indexer", "unread", {
31
+ appId: this.options.appId,
32
+ accountId,
33
+ }, undefined, { chainId: this.socialChainId });
34
+ }
35
+ async listSocialMessages(threadId) {
36
+ return this.indexerRequest("social_indexer", "messages", {
37
+ appId: this.options.appId,
38
+ threadId,
39
+ }, undefined, { chainId: this.socialChainId });
40
+ }
41
+ async listThreadMessages(input) {
42
+ return this.indexerRequest("thread", "messages", {
43
+ user: input.userId,
44
+ threadHash: input.threadHash,
45
+ ...(input.page !== undefined ? { page: String(input.page) } : {}),
46
+ });
47
+ }
48
+ async markRead(input) {
49
+ return this.indexerRequest("thread", "read", {
50
+ user: input.userId,
51
+ threadHash: input.threadHash,
52
+ hashes: JSON.stringify(input.hashes),
53
+ }, {
54
+ method: "POST",
55
+ });
56
+ }
57
+ async indexerRequest(indexer, action, query, init, options) {
58
+ const method = init?.method ?? "GET";
59
+ const chainId = options?.chainId ?? this.chainId;
60
+ const path = `/${encodeURIComponent(chainId)}/${encodeURIComponent(indexer)}/${encodeURIComponent(action)}`;
61
+ if (method.toUpperCase() === "POST") {
62
+ return this.request(path, {
63
+ ...init,
64
+ method,
65
+ body: JSON.stringify(query),
66
+ });
67
+ }
68
+ const search = new URLSearchParams(query);
69
+ return this.request(`${path}?${search.toString()}`, init);
70
+ }
71
+ async request(path, init) {
72
+ const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
73
+ ...init,
74
+ headers: {
75
+ "content-type": "application/json",
76
+ ...(init?.headers ?? {}),
77
+ },
78
+ });
79
+ const json = (await response.json().catch(() => ({})));
80
+ if (!response.ok || json.success === false) {
81
+ throw new Error(json.message || `chat-rest ${response.status}`);
82
+ }
83
+ return (json.data ?? json);
84
+ }
85
+ }
86
+ export function createChatReaderClient(options) {
87
+ return new ChatReaderClient(options);
88
+ }
89
+ function normalizeBaseUrl(baseUrl) {
90
+ return baseUrl.replace(/\/+$/, "");
91
+ }
@@ -15,4 +15,8 @@ export type ChatVoiceConfig = {
15
15
  simulatedTranscript?: string;
16
16
  shortRecordingMessage?: string;
17
17
  onVoiceSend?: (blob: Blob) => Promise<void> | void;
18
+ onVoiceTranscript?: (text: string, context: {
19
+ blob: Blob;
20
+ action: "send" | "transcribe";
21
+ }) => Promise<void> | void;
18
22
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/chat-sdk",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Cross-platform PMate chat input components, voice input primitives, and ASR helpers",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",