k2-im 0.1.21 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import {a as a$1}from'./chunk-WOT6VMZA.js';import {parse,isInteger,isSafeNumber}from'lossless-json';import Oe from'axios';function st(t){return {cryptMd5:t.crypt_md5,generateSign:t.generate_sign,encryptAes:t.encrypt_aes,decryptAes:t.decrypt_aes}}var j={};a$1(j,{__wbg_get_67b2ba62fc30de12:()=>Kt,__wbg_get_b9b93047fe3cf45b:()=>Xt,__wbg_length_e2d2a49132c1b256:()=>Qt,__wbg_ownKeys_3930041068756f1f:()=>Zt,__wbg_set_wasm:()=>K,__wbindgen_debug_string:()=>te,__wbindgen_init_externref_table:()=>ee,__wbindgen_is_object:()=>re,__wbindgen_string_get:()=>ne,__wbindgen_string_new:()=>oe,__wbindgen_throw:()=>se,crypt_md5:()=>Vt,decrypt_aes:()=>Gt,encrypt_aes:()=>Yt,generate_sign:()=>Jt});var a;function K(t){a=t;}function $t(t){let e=a.__externref_table_alloc();return a.__wbindgen_export_2.set(e,t),e}function it(t,e){try{return t.apply(this,e)}catch(r){let n=$t(r);a.__wbindgen_exn_store(n);}}function G(t){let e=typeof t;if(e=="number"||e=="boolean"||t==null)return `${t}`;if(e=="string")return `"${t}"`;if(e=="symbol"){let o=t.description;return o==null?"Symbol":`Symbol(${o})`}if(e=="function"){let o=t.name;return typeof o=="string"&&o.length>0?`Function(${o})`:"Function"}if(Array.isArray(t)){let o=t.length,s="[";o>0&&(s+=G(t[0]));for(let i=1;i<o;i++)s+=`, ${G(t[i])}`;return s+="]",s}let r=/\[object ([^\]]+)\]/.exec(toString.call(t)),n;if(r&&r.length>1)n=r[1];else return toString.call(t);if(n=="Object")try{return `Object(${JSON.stringify(t)})`}catch{return "Object"}return t instanceof Error?`${t.name}: ${t.message}
2
+ ${t.stack}`:n}var m=0,L=null;function O(){return (L===null||L.byteLength===0)&&(L=new Uint8Array(a.memory.buffer)),L}var Ft=typeof TextEncoder>"u"?(0, module.require)("util").TextEncoder:TextEncoder,v=new Ft("utf-8"),qt=typeof v.encodeInto=="function"?function(t,e){return v.encodeInto(t,e)}:function(t,e){let r=v.encode(t);return e.set(r),{read:t.length,written:r.length}};function E(t,e,r){if(r===void 0){let u=v.encode(t),c=e(u.length,1)>>>0;return O().subarray(c,c+u.length).set(u),m=u.length,c}let n=t.length,o=e(n,1)>>>0,s=O(),i=0;for(;i<n;i++){let u=t.charCodeAt(i);if(u>127)break;s[o+i]=u;}if(i!==n){i!==0&&(t=t.slice(i)),o=r(o,n,n=i+t.length*3,1)>>>0;let u=O().subarray(o+i,o+n),c=qt(t,u);i+=c.written,o=r(o,n,i,1)>>>0;}return m=i,o}var I=null;function N(){return (I===null||I.buffer.detached===true||I.buffer.detached===void 0&&I.buffer!==a.memory.buffer)&&(I=new DataView(a.memory.buffer)),I}function at(t){return t==null}var Wt=typeof TextDecoder>"u"?(0, module.require)("util").TextDecoder:TextDecoder,ct=new Wt("utf-8",{ignoreBOM:true,fatal:true});ct.decode();function H(t,e){return t=t>>>0,ct.decode(O().subarray(t,t+e))}function Vt(t){let e,r;try{let n=E(t,a.__wbindgen_malloc,a.__wbindgen_realloc),o=m,s=a.crypt_md5(n,o);return e=s[0],r=s[1],H(s[0],s[1])}finally{a.__wbindgen_free(e,r,1);}}function zt(t){let e=a.__wbindgen_export_2.get(t);return a.__externref_table_dealloc(t),e}function Jt(t,e,r,n){let o,s;try{let i=E(t,a.__wbindgen_malloc,a.__wbindgen_realloc),u=m,c=E(e,a.__wbindgen_malloc,a.__wbindgen_realloc),f=m,l=at(n)?0:E(n,a.__wbindgen_malloc,a.__wbindgen_realloc),p=m,d=a.generate_sign(i,u,c,f,r,l,p),b=d[0],g=d[1];if(d[3])throw b=0,g=0,zt(d[2]);return o=b,s=g,H(b,g)}finally{a.__wbindgen_free(o,s,1);}}function ut(t,e){let r=e(t.length*1,1)>>>0;return O().set(t,r/1),m=t.length,r}function lt(t,e){return t=t>>>0,O().subarray(t/1,t/1+e)}function Yt(t){let e=ut(t,a.__wbindgen_malloc),r=m,n=a.encrypt_aes(e,r),o=lt(n[0],n[1]).slice();return a.__wbindgen_free(n[0],n[1]*1,1),o}function Gt(t){let e=ut(t,a.__wbindgen_malloc),r=m,n=a.decrypt_aes(e,r),o=lt(n[0],n[1]).slice();return a.__wbindgen_free(n[0],n[1]*1,1),o}function Kt(){return it((t,e)=>Reflect.get(t,e),arguments)}function Xt(t,e){return t[e>>>0]}function Qt(t){return t.length}function Zt(){return it(t=>Reflect.ownKeys(t),arguments)}function te(t,e){let r=G(e),n=E(r,a.__wbindgen_malloc,a.__wbindgen_realloc),o=m;N().setInt32(t+4,o,true),N().setInt32(t+0,n,true);}function ee(){let t=a.__wbindgen_export_2,e=t.grow(4);t.set(0,void 0),t.set(e+0,void 0),t.set(e+1,null),t.set(e+2,true),t.set(e+3,false);}function re(t){let e=t;return typeof e=="object"&&e!==null}function ne(t,e){let r=e,n=typeof r=="string"?r:void 0,o=at(n)?0:E(n,a.__wbindgen_malloc,a.__wbindgen_realloc),s=m;N().setInt32(t+4,s,true),N().setInt32(t+0,o,true);}function oe(t,e){return H(t,e)}function se(t,e){throw new Error(H(t,e))}var pt=null,$=null;async function ie(){let t=await fetch(new URL("./vendor/crypto/index_bg.wasm",import.meta.url));if(!t.ok)throw new Error(`crypto wasm \u52A0\u8F7D\u5931\u8D25\uFF1AHTTP ${t.status}`);let e={"./index_bg.js":j},r;if(typeof WebAssembly.instantiateStreaming=="function")try{r=await WebAssembly.instantiateStreaming(t.clone(),e);}catch{r=await WebAssembly.instantiate(await t.arrayBuffer(),e);}else r=await WebAssembly.instantiate(await t.arrayBuffer(),e);return K(r.instance.exports),r.instance.exports.__wbindgen_start(),st(j)}async function X(){return $||($=ie().catch(t=>{throw $=null,t})),pt=await $,pt}await X();var ft="b097f885e9577cdb04d9faf91aa08329";function ae(t){return Object.keys(t).sort((r,n)=>r.localeCompare(n,void 0,{numeric:true})).map(r=>r+t[r]).join("")}function dt(t,e){let r=ae(e);return t.cryptMd5(ft+r+ft).toUpperCase()}var gt="123456789";var mt={core:"/api/h5",wallet:"/api/h5",bi:"/bi/h5",im:""};function pe(t){return isInteger(t)?isSafeNumber(t)?Number.parseInt(t,10):t:Number.parseFloat(t)}function F(t){return parse(t,void 0,{parseNumber:pe})}var bt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function _t(t){return t?t instanceof Headers?Object.fromEntries(t.entries()):Array.isArray(t)?Object.fromEntries(t):{...t}:{}}function yt(t){return t?t instanceof Headers?Object.fromEntries(t.entries()):Object.fromEntries(Object.entries(t).map(([e,r])=>[e,Array.isArray(r)?r.join(", "):String(r)])):{}}function Pt(t,e){let r=e.toLowerCase();return Object.entries(t).find(([o])=>o.toLowerCase()===r)?.[1]??null}function M(t,e=2){return t.toString().padStart(e,"0")}function wt(t){return `${t.getFullYear()}-${M(t.getMonth()+1)}-${M(t.getDate())} ${M(t.getHours())}:${M(t.getMinutes())}:${M(t.getSeconds())}`}function de(t){if(t!=null)return typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"||typeof t=="bigint"?String(t):t&&typeof t=="object"?JSON.stringify(t):String(t)}function Tt(t){let e={};for(let[r,n]of Object.entries(t)){let o=de(n);o!==void 0&&(e[r]=o);}return e}function At(t=16){let e="";for(let r=0;r<t;r+=1){let n=Math.floor(Math.random()*bt.length);e+=bt.charAt(n);}return e}function Rt(t){let e={deviceBrand:"web",deviceInfo:"web",deviceNumber:"",deviceToken:"web"},r=t||(typeof navigator<"u"?navigator.userAgent:"");if(!r)return e;let n=r.match(/(Chrome|Firefox|Safari|Edg)\/([\d.]+)/i);return n?{deviceBrand:"web",deviceInfo:`${n[1]}/${n[2]}`,deviceNumber:n[2]??"",deviceToken:"web"}:{...e,deviceInfo:r}}function ht(t){let e=String(t||"").trim().toLowerCase();return e==="cn"||e.startsWith("zh-cn")?"cn":e==="tc"||e.startsWith("zh-tw")||e.startsWith("zh-hk")?"tc":e==="vn"||e.startsWith("vi")?"vn":e==="th"||e.startsWith("th")?"th":e==="en"||e.startsWith("en")?"en":"cn"}function h(t,e){return {baseUrl:e?.baseUrl??"",prefix:e?.prefix??mt[t]}}function ge(t){return t.replace(/^\/+|\/+$/g,"")}function xt(t,e,r){let n=t.replace(/\/+$/g,""),o=ge(e),s=r.startsWith("/")?r:`/${r}`,i=o?`/${o}`:"";return `${n}${i}${s}`}function Ct(t,e){let r=new URLSearchParams(Object.entries(e).map(([u,c])=>[u,String(c)])).toString();if(!r)return t;let n=t.indexOf("#"),o=n>=0?t.slice(0,n):t,s=n>=0?t.slice(n):"",i=o.includes("?")?o.endsWith("?")||o.endsWith("&")?"":"&":"?";return `${o}${i}${r}${s}`}function Q(t){return !!t&&t.toLowerCase().includes("application/json")}function Z(t){return !!t&&t.toLowerCase().startsWith("text/")}function k(t){return t==null?new Uint8Array:typeof t=="string"?new TextEncoder().encode(t):t instanceof ArrayBuffer?new Uint8Array(t):ArrayBuffer.isView(t)?new Uint8Array(t.buffer,t.byteOffset,t.byteLength):new TextEncoder().encode(JSON.stringify(t))}function q(t){return typeof t=="string"?t:new TextDecoder().decode(k(t))}function It(t){return typeof FormData<"u"&&t instanceof FormData}var Pe=new Set(["content-etag","token","req-id"]);function St(t){let e=t.rawBody,r=e!==null&&typeof e=="object"&&"code"in e?e.code:void 0;return {transportStatus:t.transportStatus,...t.httpStatus===void 0?{}:{httpStatus:t.httpStatus},...typeof r=="number"&&Number.isFinite(r)?{businessCode:r}:{}}}function we(t){return Number.isInteger(t)&&t>=400&&t<=599?t:502}function Te(t,e){return {code:t.status,msg:t.statusText,data:null,time:Math.floor(e/1e3)}}function Ae(t,e){return {code:502,msg:t instanceof Error?t.message:String(t),data:null,time:Math.floor(e/1e3)}}function Re(t){if(!t||typeof t!="object")return false;let e=t;return Number.isFinite(e.code)&&"data"in e}function Et(t,e,r,n){if(Q(r))return F(q(e.data));if(Z(r))return q(e.data);let o=k(e.data),s=n?t.crypto.decryptAes(o):o,i=new TextDecoder().decode(s);return F(i)}async function Dt(t,e,r){if(!t.onDebugRecord)return;let n={...e.meta,response:e.response,...r?{error:{name:r instanceof Error?r.name:void 0,message:r instanceof Error?r.message:String(r)}}:{}};try{await t.onDebugRecord(n);}catch{}}function he(t,e,r,n,o){if(r.customUrl)return t;let s=h(n,e.config.targets[n]),i=r.baseUrl??s.baseUrl;return xt(i,o,t)}function xe(t,e){let r=new AbortController,n=setTimeout(()=>r.abort(),t),o=()=>r.abort();return e&&(e.aborted?r.abort():e.addEventListener("abort",o,{once:true})),{signal:r.signal,dispose:()=>{clearTimeout(n),e?.removeEventListener("abort",o);}}}async function Ce(t,e,r,n,o,s,i){let u=yt(e.headers),c=Pt(u,"content-type");if(e.status<200||e.status>=300){let l;if(n)l=void 0;else try{l=Et(t,e,c,r);}catch{l=void 0;}return {response:Re(l)?l:Te(e,i),meta:{...o,transportStatus:"http_error",httpStatus:e.status,contentType:c,responseHeaders:u,...l!==void 0?{rawBody:l}:{},timings:{totalMs:i-s,upstreamMs:i-s}}}}let f=Date.now();if(n){let l=k(e.data),p=Date.now();return {response:{code:e.status,data:l,time:Math.floor(p/1e3)},meta:{...o,transportStatus:"success",httpStatus:e.status,contentType:c,responseHeaders:u,rawBody:l,timings:{totalMs:p-s,upstreamMs:i-s,parseMs:p-f}}}}try{if(Q(c)){let T=Et(t,e,c,!1),_=Date.now();return {response:T,meta:{...o,transportStatus:"success",httpStatus:e.status,contentType:c,responseHeaders:u,rawBody:T,timings:{totalMs:_-s,upstreamMs:i-s,parseMs:_-f}}}}if(Z(c)){let T=q(e.data),_=Date.now();return {response:{code:e.status,msg:e.statusText,data:T,time:Math.floor(_/1e3)},meta:{...o,transportStatus:"success",httpStatus:e.status,contentType:c,responseHeaders:u,rawBody:T,timings:{totalMs:_-s,upstreamMs:i-s,parseMs:_-f}}}}let l=k(e.data),p=Date.now(),d=r?t.crypto.decryptAes(l):l,b=Date.now(),g=new TextDecoder().decode(d),D=F(g),B=Date.now();return {response:D,meta:{...o,transportStatus:"success",httpStatus:e.status,contentType:c,responseHeaders:u,rawBody:D,timings:{totalMs:B-s,upstreamMs:i-s,parseMs:B-f,...r?{decryptMs:b-p}:{}}}}}catch(l){let p=Date.now();return {response:{code:we(e.status),msg:l instanceof Error?l.message:String(l),data:null,time:Math.floor(p/1e3)},meta:{...o,transportStatus:"invalid_response",httpStatus:e.status,contentType:c,responseHeaders:u,timings:{totalMs:p-s,upstreamMs:i-s,parseMs:p-f}}}}}function Ie(t){return async function(r,n={}){let o=t.now??(()=>new Date),s=t.randomNonce??(()=>gt),i=t.randomRequestId??(()=>`req-${crypto.randomUUID().replaceAll("-","")}`),u=t.randomETag??(()=>At()),c=(n.method??"POST").toUpperCase(),f=n.target??"core",l=h(f,t.config.targets[f]),p=n.prefix??l.prefix??"",d=n.body!=null,b=Tt(n.data??{}),g=r==="/v1/feedback"&&p==="/bi/h5",D=g?false:n.encrypt??!d,B=g?false:n.sign??!d,T=o(),_=u(),tt=i(),Ut=n.token??await t.getToken?.()??"",Lt=ht(n.locale??t.getLocale?.()),S=t.getBrowserInfo?.()??Rt(n.userAgent),W={app_id:"5",os_type:"4",app_version:t.config.appVersion,sign_method:"md5",timestamp:wt(T),nonce:s()},y={...W,...b},V=W,et=b,x=y;!g&&B&&(y.sign=t.crypto.generateSign("api",t.config.envType,y,_),W.sign=y.sign);let vt={app_version:t.config.appVersion,"X-ENC-VERSION":t.config.appVersion,"X-APP-TYPE":"h5","Client-type":"2","Content-ETag":_,"brand-id":t.config.brandId,"channel-id":n.channelId||t.config.channelId,device_brand:S.deviceBrand,device_info:S.deviceInfo,device_number:S.deviceNumber,device_token:S.deviceToken,lang:Lt,"mch-id":t.config.merchantId,"req-id":tt,token:Ut},Nt=_t(n.headers),Ht=Object.fromEntries(Object.entries(Nt).filter(([A])=>!Pe.has(A.toLowerCase()))),z=r,C,P={...vt,...Ht};if(d)C=n.body??void 0,V=null,et=n.data??null,x=n.data??null;else if(g){let A=String(T.getTime()),w={"app-id":"1","app-version":t.config.appVersion,"sys-type":"h5","sys-version":S.deviceNumber,time:A};V=w,P={...P,...w,sign:dt(t.crypto,w),"Content-Type":"application/json"},C=JSON.stringify(b),x=b;}else c==="GET"?(z=Ct(z,y),x=y):D?(C=t.crypto.encryptAes(new TextEncoder().encode(JSON.stringify(y))),P["Content-Type"]=P["Content-Type"]||"application/octet-stream",x=y):(C=JSON.stringify(y),P["Content-Type"]=P["Content-Type"]||"application/json",x=y);It(C)&&delete P["Content-Type"];let J=he(z,t,n,f,p),Y=Date.now(),rt=n.timeoutMs??6e4,nt=xe(rt,n.signal),ot={requestId:tt,eTag:_,method:c,upstreamUrl:J,requestHeaders:P,requestCommonParams:V,requestBusinessParams:et,requestParams:x},U;try{let A=await t.transport({url:J,method:c,headers:P,body:C,signal:nt.signal,timeoutMs:rt,onUploadProgress:n.onUploadProgress}),w=Date.now(),R=await Ce(t,A,D&&!g,n.responseMode==="raw",ot,Y,w);return n.onResponse&&(U=St(R.meta),R.observation=U),await Dt(t,R),!n.skipBusinessResponseHandler&&t.onBusinessResponse&&await t.onBusinessResponse(R.response,{request:{path:r,method:c,target:f,url:J},options:n}),R}catch(A){let w=Date.now(),R={response:Ae(A,w),...U===void 0?{}:{observation:U},meta:{...ot,transportStatus:"network_error",timings:{totalMs:w-Y,upstreamMs:w-Y}}};return await Dt(t,R,A),R}finally{nt.dispose();}}}function Mt(t){let e=Ie(t);return async function(n,o={}){let s=await e(n,o);return await o.onResponse?.(s.observation??St(s.meta)),s.response}}function kt(t={}){let e={core:h("core",{baseUrl:t.coreBaseUrl||"",...t.targets?.core}),wallet:h("wallet",{baseUrl:t.walletBaseUrl||"",...t.targets?.wallet}),bi:h("bi",{baseUrl:t.biBaseUrl||"",...t.targets?.bi}),im:h("im",{baseUrl:t.imBaseUrl||"",...t.targets?.im})};return {appVersion:t.appVersion||"",brandId:t.brandId||"",merchantId:t.merchantId||"",channelId:t.channelId||"",envType:t.envType||"prod",targets:e}}function Bt(t={}){let e=t.axios??Oe.create();return async r=>{let n=await e.request({url:r.url,method:r.method,headers:r.headers,data:r.body,signal:r.signal,timeout:r.timeoutMs,onUploadProgress:r.onUploadProgress?o=>{let s=typeof o.progress=="number"?o.progress:typeof o.total=="number"&&o.total>0?o.loaded/o.total:void 0;r.onUploadProgress?.({loaded:o.loaded,...typeof o.total=="number"?{total:o.total}:{},...typeof s=="number"?{progress:s}:{},event:o});}:void 0,responseType:"arraybuffer",transformResponse:o=>o,validateStatus:()=>true});return {status:n.status,statusText:n.statusText,headers:n.headers,data:n.data}}}async function Xe(t={}){let e=await X(),r=kt(t.config);return Mt({...t,config:r,crypto:e,transport:t.transport??Bt()})}export{Xe as createBrowserApiProtocolClient};
package/dist/browser.d.ts CHANGED
@@ -86,6 +86,20 @@ interface ApiProtocolUploadProgress {
86
86
  /** 底层 transport 的原始进度事件,供调试或特殊场景读取。 */
87
87
  event?: unknown;
88
88
  }
89
+ /**
90
+ * 单次请求完成后的安全状态信息,供调用方识别 HTTP 与业务失败。
91
+ *
92
+ * 不包含请求头、URL、凭据或响应正文;HTTP 状态与后端业务码分别保留,避免把网络
93
+ * 失败合成的 502 或纯 HTTP 403 当成服务端业务码。原始响应仍通过请求返回值交付。
94
+ */
95
+ interface ApiProtocolResponseObservation {
96
+ /** 请求结果所属层;成功收到业务错误信封仍属于 `success`。 */
97
+ transportStatus: 'success' | 'http_error' | 'network_error' | 'invalid_response';
98
+ /** 服务端真实 HTTP 状态;未收到响应时不存在。 */
99
+ httpStatus?: number;
100
+ /** 仅在真实响应正文是协议信封时提供其 code;不包含客户端合成的错误码。 */
101
+ businessCode?: number;
102
+ }
89
103
  /**
90
104
  * 单次协议请求的可覆盖项。
91
105
  *
@@ -128,6 +142,13 @@ interface ApiProtocolRequestOptions {
128
142
  signal?: AbortSignal;
129
143
  /** 上传进度回调;默认浏览器客户端的 axios transport 支持该能力。 */
130
144
  onUploadProgress?: (progress: ApiProtocolUploadProgress) => void;
145
+ /**
146
+ * 请求完成后调用一次,只提供安全状态字段。回调异常会使请求显式失败,不会转换成网络错误。
147
+ * 调用方如需检查当前账号是否仍有效,可先保存这些字段,在请求返回后决定是否处理。
148
+ */
149
+ onResponse?: (observation: ApiProtocolResponseObservation) => void | Promise<void>;
150
+ /** 跳过客户端注入的全局业务处理器,默认 false;由调用方接管当前请求的业务副作用。 */
151
+ skipBusinessResponseHandler?: boolean;
131
152
  /**
132
153
  * 响应解析模式。
133
154
  * - `'json'`(默认):按 content-type 走 JSON / 文本 / AES-JSON 解析,返回业务响应对象。
package/dist/browser.js CHANGED
@@ -1 +1 @@
1
- export{A as createLazyBrowserApiProtocolClient}from'./chunk-YAM4YHKF.js';import'./chunk-A2BLOVZ5.js';import'./chunk-WOT6VMZA.js';
1
+ export{A as createLazyBrowserApiProtocolClient}from'./chunk-MO2EU56Q.js';import'./chunk-W5SQGPRQ.js';import'./chunk-WOT6VMZA.js';
@@ -2478,6 +2478,20 @@ interface ApiProtocolUploadProgress {
2478
2478
  /** 底层 transport 的原始进度事件,供调试或特殊场景读取。 */
2479
2479
  event?: unknown;
2480
2480
  }
2481
+ /**
2482
+ * 单次请求完成后的安全状态信息,供调用方识别 HTTP 与业务失败。
2483
+ *
2484
+ * 不包含请求头、URL、凭据或响应正文;HTTP 状态与后端业务码分别保留,避免把网络
2485
+ * 失败合成的 502 或纯 HTTP 403 当成服务端业务码。原始响应仍通过请求返回值交付。
2486
+ */
2487
+ interface ApiProtocolResponseObservation {
2488
+ /** 请求结果所属层;成功收到业务错误信封仍属于 `success`。 */
2489
+ transportStatus: 'success' | 'http_error' | 'network_error' | 'invalid_response';
2490
+ /** 服务端真实 HTTP 状态;未收到响应时不存在。 */
2491
+ httpStatus?: number;
2492
+ /** 仅在真实响应正文是协议信封时提供其 code;不包含客户端合成的错误码。 */
2493
+ businessCode?: number;
2494
+ }
2481
2495
  /**
2482
2496
  * 单次协议请求的可覆盖项。
2483
2497
  *
@@ -2520,6 +2534,13 @@ interface ApiProtocolRequestOptions {
2520
2534
  signal?: AbortSignal;
2521
2535
  /** 上传进度回调;默认浏览器客户端的 axios transport 支持该能力。 */
2522
2536
  onUploadProgress?: (progress: ApiProtocolUploadProgress) => void;
2537
+ /**
2538
+ * 请求完成后调用一次,只提供安全状态字段。回调异常会使请求显式失败,不会转换成网络错误。
2539
+ * 调用方如需检查当前账号是否仍有效,可先保存这些字段,在请求返回后决定是否处理。
2540
+ */
2541
+ onResponse?: (observation: ApiProtocolResponseObservation) => void | Promise<void>;
2542
+ /** 跳过客户端注入的全局业务处理器,默认 false;由调用方接管当前请求的业务副作用。 */
2543
+ skipBusinessResponseHandler?: boolean;
2523
2544
  /**
2524
2545
  * 响应解析模式。
2525
2546
  * - `'json'`(默认):按 content-type 走 JSON / 文本 / AES-JSON 解析,返回业务响应对象。
@@ -4426,6 +4447,17 @@ interface ConversationOpenOptions {
4426
4447
  * 后续 read 事件或新消息不会移动分隔线。
4427
4448
  */
4428
4449
  initialPosition?: ConversationInitialPosition;
4450
+ /**
4451
+ * 初始历史加载方式,默认 `blocking`。
4452
+ *
4453
+ * @remarks 两种模式都在句柄交付前把初始窗口和 `entryUnread` 定稿,交付后不会再因本次初始化替换窗口或补填未读锚点,
4454
+ * 因此交付的快照 `loading` 已经结束。区别只在失败处理:`blocking` 下初始历史失败会拒绝 `openConversation`;
4455
+ * `local-first` 先读出本地最新页,之后的远端补齐失败不再拒绝打开,而是保留失败时的当前连续窗口、把失败写入
4456
+ * `error`(`operation` 为 `history.initial`),并把 `first-unread` 的 `entryUnread` 降级为 `unavailable`,
4457
+ * 由调用方用 `history` 动作重试。窗口可能已经定位在历史锚点,`hasNewer` 仍按实际边界返回。
4458
+ * 两种模式下首屏窗口的本地读取失败都拒绝打开,并保留原始异常。
4459
+ */
4460
+ initialLoad?: 'blocking' | 'local-first';
4429
4461
  }
4430
4462
  /**
4431
4463
  * 产品会话的连续窗口快照;协议 cursor、窗口 id 与 generation 始终保持在 SDK 内部。
@@ -5318,6 +5350,39 @@ interface ImMembershipJoinResult {
5318
5350
  outcome: 'joined' | 'waiting';
5319
5351
  }
5320
5352
 
5353
+ /**
5354
+ * SDK 自管 Core JSON / CM HTTP 请求的失败事实,交由宿主决定是否触发全局处理。
5355
+ *
5356
+ * 不包含 URL、响应正文、服务端文案或凭据。`httpStatus` 与 `businessCode` 分别来自 HTTP
5357
+ * 响应和真实业务响应体;网络失败没有 HTTP 状态,合成的 502 不会冒充业务码。
5358
+ * S3、Giphy 和宿主自己发出的请求不属于这两个服务,不会被当作账号认证失败上报。
5359
+ */
5360
+ interface ImRequestError {
5361
+ /** 返回错误的服务;宿主不能把 CM 成员权限错误等同于 Core 账号失效。 */
5362
+ readonly service: 'core' | 'cm';
5363
+ /** 失败发生在哪一层;同时有 HTTP 和业务失败时,优先标为 `http`。 */
5364
+ readonly kind: 'http' | 'business' | 'network' | 'invalid-response';
5365
+ /** 实际 HTTP 状态;没有收到响应时不存在。 */
5366
+ readonly httpStatus?: number;
5367
+ /** Core 返回的真实业务码;CM protobuf 请求不提供该字段。 */
5368
+ readonly businessCode?: number;
5369
+ }
5370
+ /**
5371
+ * 宿主的全局请求错误入口;SDK 不依据返回值重试、登出或改变原调用的结果。
5372
+ *
5373
+ * 每个失败请求通知一次,重复提示策略由宿主现有全局处理器负责。调用前 SDK 会核对账号、
5374
+ * 实际发送凭据及运行时是否仍有效;异步处理器应在第一次 await 前完成需要当前登录态的决策。
5375
+ * 回调抛错或拒绝只进入 SDK 诊断,不会替换请求本身的失败。不会等待回调中的登录/退出操作,
5376
+ * 避免宿主退出流程等待当前请求时互相阻塞。
5377
+ *
5378
+ * @example
5379
+ * ```ts
5380
+ * const onRequestError: ImRequestErrorHandler = issue => appErrors.handleImRequest(issue)
5381
+ * const client = createImClient({ authProvider, endpointProvider, cache, onRequestError })
5382
+ * ```
5383
+ */
5384
+ type ImRequestErrorHandler = (issue: ImRequestError) => void | Promise<void>;
5385
+
5321
5386
  /**
5322
5387
  * 当前账号本地会话与消息的分场景产品搜索运行时。
5323
5388
  *
@@ -5586,6 +5651,8 @@ interface ImClientAdapters {
5586
5651
  * ```
5587
5652
  */
5588
5653
  interface ImClientOptions {
5654
+ /** HTTP/业务失败交给宿主全局处理;SDK 不自动登出,详见 ImRequestErrorHandler。 */
5655
+ onRequestError?: ImRequestErrorHandler;
5589
5656
  authProvider: ImAuthProvider;
5590
5657
  endpointProvider: ImEndpointProvider;
5591
5658
  /** 所有 SDK 自管本地数据与协调名称的宿主前缀;创建 client 时同步校验。 */
@@ -6207,6 +6274,8 @@ interface ChatRuntimeHostDeps {
6207
6274
  } | null;
6208
6275
  /** 返回 core JSON 部署配置;未提供 core client 时由 SDK 内部协议工厂创建等价 client。 */
6209
6276
  getCoreApi?: () => ImCoreApiOptions | undefined;
6277
+ /** HTTP/业务错误交回宿主的全局处理器;Chat Kit 不依据状态码作登录决策。 */
6278
+ onRequestError?: ImRequestErrorHandler;
6210
6279
  /** 当前宿主的客户端类型编号,随登录请求上报,PC Web 默认使用自己的固定类型。 */
6211
6280
  clientType: number;
6212
6281
  /** 获取当前环境的媒体上传下载配置;未启用媒体能力时返回 `undefined`。 */
@@ -6740,22 +6809,24 @@ declare function getImChatKitContext(pinia: Pinia): ImChatKitContext;
6740
6809
  /** 释放指定 Pinia 下全部 IM Store 和 Runtime;未安装时不执行任何操作。 */
6741
6810
  declare function disposeImChatKit(pinia: Pinia): void;
6742
6811
 
6743
- type ProductConversationRef$5 = ConversationRef<ProductHandleConversationType>;
6812
+ type ProductConversationRef$6 = ConversationRef<ProductHandleConversationType>;
6744
6813
  /** 宿主可据此决定反馈的安全错误;底层 cause/details 只允许进入统一诊断。 */
6745
6814
  type ImConversationActivationError = Readonly<Omit<ImSdkErrorShape, 'cause' | 'details'>>;
6746
6815
  /**
6747
6816
  * 共享会话激活的稳定结果。
6748
6817
  *
6749
- * 成功后宿主才提交路由/面板选择;`stale` 表示该意图已被更新点击、切账号或 Context dispose 取代。
6818
+ * 成功表示已绑定首屏窗口和未读入口已定稿的目标句柄;首屏补齐错误及后续分页状态从 Thread Store 读取。
6819
+ * 等待激活期间的页面外壳和加载提示由宿主展示。
6820
+ * `stale` 表示该意图已被更新点击、切账号或 Context dispose 取代。
6750
6821
  */
6751
6822
  type ImConversationActivationResult = Readonly<{
6752
6823
  ok: true;
6753
6824
  status: 'opened';
6754
- conversation: ProductConversationRef$5;
6825
+ conversation: ProductConversationRef$6;
6755
6826
  } | {
6756
6827
  ok: false;
6757
6828
  reason: 'draft-save-failed' | 'open-failed';
6758
- conversation: ProductConversationRef$5;
6829
+ conversation: ProductConversationRef$6;
6759
6830
  error: ImConversationActivationError;
6760
6831
  } | {
6761
6832
  ok: false;
@@ -6764,29 +6835,32 @@ type ImConversationActivationResult = Readonly<{
6764
6835
  }>;
6765
6836
  /** 按单个 Pinia 串联 Composer 与 Thread Store 的无 UI coordinator。 */
6766
6837
  interface ImConversationActivationCoordinator {
6767
- activate: (conversation: ConversationRef) => Promise<ImConversationActivationResult>;
6838
+ /** signal 取消本次在途激活;保留已显示线程,不影响之后开始的激活。 */
6839
+ activate: (conversation: ConversationRef, options?: {
6840
+ signal?: AbortSignal;
6841
+ }) => Promise<ImConversationActivationResult>;
6768
6842
  }
6769
6843
  /**
6770
6844
  * 取得当前 Vue setup 或显式 Pinia 的会话激活 coordinator。
6771
6845
  *
6772
6846
  * coordinator 没有响应式产品状态;每个 Pinia 只持有 operation epoch,用于在草稿 flush 和 Thread open
6773
- * 之间判定新点击、账号 generation 变化与 dispose。调用方不得根据 Thread 中间态提前提交宿主选择。
6847
+ * 之间判定新点击、账号 generation 变化与 dispose。宿主可先展示目标页,但只有 exact handle 成功后才能展示线程内容。
6774
6848
  */
6775
6849
  declare function useImConversationActivationCoordinator(pinia?: Pinia): ImConversationActivationCoordinator;
6776
6850
 
6777
- type ProductConversationRef$4 = ConversationRef<ProductConversationListType>;
6851
+ type ProductConversationRef$5 = ConversationRef<ProductConversationListType>;
6778
6852
  /** 删除失败时提供给宿主映射反馈的安全错误,不暴露底层 cause/details。 */
6779
6853
  type ImConversationDeletionError = Readonly<Omit<ImSdkErrorShape, 'cause' | 'details'>>;
6780
6854
  /** local-only 删除的稳定结果;成功只代表 SDK 已同步提交当前内存删除,不代表 durable 存储已完成。 */
6781
6855
  type ImConversationDeletionResult = Readonly<{
6782
6856
  ok: true;
6783
6857
  status: 'deleted';
6784
- conversation: ProductConversationRef$4;
6858
+ conversation: ProductConversationRef$5;
6785
6859
  activeConversationCleared: boolean;
6786
6860
  } | {
6787
6861
  ok: false;
6788
6862
  reason: 'delete-failed';
6789
- conversation: ProductConversationRef$4;
6863
+ conversation: ProductConversationRef$5;
6790
6864
  error: ImConversationDeletionError;
6791
6865
  } | {
6792
6866
  ok: false;
@@ -6805,7 +6879,7 @@ interface ImConversationDeletionCoordinator {
6805
6879
  */
6806
6880
  declare function useImConversationDeletionCoordinator(pinia?: Pinia): ImConversationDeletionCoordinator;
6807
6881
 
6808
- type ProductConversationRef$3 = ConversationRef<ProductConversationListType>;
6882
+ type ProductConversationRef$4 = ConversationRef<ProductConversationListType>;
6809
6883
  type ImConversationListMutationOperation = 'set-pinned' | 'set-muted' | 'mark-read' | 'mark-unread' | 'delete-local';
6810
6884
  /** 会话列表动作失败时返回给宿主的安全错误;底层 cause/details 不跨出共享 Store。 */
6811
6885
  type ImConversationListActionError = Readonly<Omit<ImSdkErrorShape, 'cause' | 'details'>>;
@@ -6832,11 +6906,11 @@ interface ImConversationListStore {
6832
6906
  start: () => void;
6833
6907
  reset: () => void;
6834
6908
  refresh: () => Promise<ImConversationListRefreshResult>;
6835
- setPinned: (ref: ProductConversationRef$3, pinned: boolean) => ImConversationListMutationResult;
6836
- setMuted: (ref: ProductConversationRef$3, muted: boolean) => Promise<ImConversationListMutationResult>;
6837
- markRead: (ref: ProductConversationRef$3) => Promise<ImConversationListMutationResult>;
6838
- markUnread: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6839
- deleteLocal: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6909
+ setPinned: (ref: ProductConversationRef$4, pinned: boolean) => ImConversationListMutationResult;
6910
+ setMuted: (ref: ProductConversationRef$4, muted: boolean) => Promise<ImConversationListMutationResult>;
6911
+ markRead: (ref: ProductConversationRef$4) => Promise<ImConversationListMutationResult>;
6912
+ markUnread: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6913
+ deleteLocal: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6840
6914
  dispose: () => void;
6841
6915
  }
6842
6916
  /**
@@ -6848,17 +6922,17 @@ interface ImConversationListStore {
6848
6922
  type ImConversationListMutationResult = Readonly<{
6849
6923
  ok: true;
6850
6924
  operation: ImConversationListMutationOperation;
6851
- conversation: ProductConversationRef$3;
6925
+ conversation: ProductConversationRef$4;
6852
6926
  } | {
6853
6927
  ok: false;
6854
6928
  operation: ImConversationListMutationOperation;
6855
6929
  reason: 'stale';
6856
- conversation: ProductConversationRef$3;
6930
+ conversation: ProductConversationRef$4;
6857
6931
  } | {
6858
6932
  ok: false;
6859
6933
  operation: ImConversationListMutationOperation;
6860
6934
  reason: 'failed';
6861
- conversation: ProductConversationRef$3;
6935
+ conversation: ProductConversationRef$4;
6862
6936
  error: ImConversationListActionError;
6863
6937
  }>;
6864
6938
  declare function defineImConversationListStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-conversation-list", Pick<{
@@ -6869,11 +6943,11 @@ declare function defineImConversationListStore(pinia: Pinia): pinia.StoreDefinit
6869
6943
  start: () => void;
6870
6944
  reset: () => void;
6871
6945
  refresh: () => Promise<ImConversationListRefreshResult>;
6872
- setPinned: (ref: ProductConversationRef$3, pinned: boolean) => ImConversationListMutationResult;
6873
- setMuted: (ref: ProductConversationRef$3, muted: boolean) => Promise<ImConversationListMutationResult>;
6874
- markRead: (ref: ProductConversationRef$3) => Promise<ImConversationListMutationResult>;
6875
- markUnread: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6876
- deleteLocal: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6946
+ setPinned: (ref: ProductConversationRef$4, pinned: boolean) => ImConversationListMutationResult;
6947
+ setMuted: (ref: ProductConversationRef$4, muted: boolean) => Promise<ImConversationListMutationResult>;
6948
+ markRead: (ref: ProductConversationRef$4) => Promise<ImConversationListMutationResult>;
6949
+ markUnread: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6950
+ deleteLocal: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6877
6951
  dispose: () => void;
6878
6952
  }, any>, Pick<{
6879
6953
  items: any;
@@ -6883,11 +6957,11 @@ declare function defineImConversationListStore(pinia: Pinia): pinia.StoreDefinit
6883
6957
  start: () => void;
6884
6958
  reset: () => void;
6885
6959
  refresh: () => Promise<ImConversationListRefreshResult>;
6886
- setPinned: (ref: ProductConversationRef$3, pinned: boolean) => ImConversationListMutationResult;
6887
- setMuted: (ref: ProductConversationRef$3, muted: boolean) => Promise<ImConversationListMutationResult>;
6888
- markRead: (ref: ProductConversationRef$3) => Promise<ImConversationListMutationResult>;
6889
- markUnread: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6890
- deleteLocal: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6960
+ setPinned: (ref: ProductConversationRef$4, pinned: boolean) => ImConversationListMutationResult;
6961
+ setMuted: (ref: ProductConversationRef$4, muted: boolean) => Promise<ImConversationListMutationResult>;
6962
+ markRead: (ref: ProductConversationRef$4) => Promise<ImConversationListMutationResult>;
6963
+ markUnread: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6964
+ deleteLocal: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6891
6965
  dispose: () => void;
6892
6966
  }, any>, Pick<{
6893
6967
  items: any;
@@ -6897,11 +6971,11 @@ declare function defineImConversationListStore(pinia: Pinia): pinia.StoreDefinit
6897
6971
  start: () => void;
6898
6972
  reset: () => void;
6899
6973
  refresh: () => Promise<ImConversationListRefreshResult>;
6900
- setPinned: (ref: ProductConversationRef$3, pinned: boolean) => ImConversationListMutationResult;
6901
- setMuted: (ref: ProductConversationRef$3, muted: boolean) => Promise<ImConversationListMutationResult>;
6902
- markRead: (ref: ProductConversationRef$3) => Promise<ImConversationListMutationResult>;
6903
- markUnread: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6904
- deleteLocal: (ref: ProductConversationRef$3) => ImConversationListMutationResult;
6974
+ setPinned: (ref: ProductConversationRef$4, pinned: boolean) => ImConversationListMutationResult;
6975
+ setMuted: (ref: ProductConversationRef$4, muted: boolean) => Promise<ImConversationListMutationResult>;
6976
+ markRead: (ref: ProductConversationRef$4) => Promise<ImConversationListMutationResult>;
6977
+ markUnread: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6978
+ deleteLocal: (ref: ProductConversationRef$4) => ImConversationListMutationResult;
6905
6979
  dispose: () => void;
6906
6980
  }, any>>;
6907
6981
  type InternalImConversationListStore = ReturnType<ReturnType<typeof defineImConversationListStore>>;
@@ -7061,7 +7135,7 @@ type ImExpressionStore = Store<'k2-im-expression', ImExpressionStoreState, ImExp
7061
7135
  */
7062
7136
  declare function useImExpressionStore(pinia?: Pinia): ImExpressionStore;
7063
7137
 
7064
- type ProductConversationRef$2 = ConversationRef<ProductHandleConversationType>;
7138
+ type ProductConversationRef$3 = ConversationRef<ProductHandleConversationType>;
7065
7139
  /** 返回最新页失败时给宿主的安全错误;底层 cause/details 只进入统一诊断。 */
7066
7140
  type ImHistoryReturnError = Readonly<Omit<ImSdkErrorShape, 'cause' | 'details'>>;
7067
7141
  /** 历史窗口发送后的稳定结算;宿主只在 `applied` 时执行自己的 DOM 滚动。 */
@@ -7069,10 +7143,10 @@ type ImHistoryReturnResult = Readonly<{
7069
7143
  status: 'not-needed';
7070
7144
  } | {
7071
7145
  status: 'applied' | 'stale';
7072
- conversation: ProductConversationRef$2;
7146
+ conversation: ProductConversationRef$3;
7073
7147
  } | {
7074
7148
  status: 'failed';
7075
- conversation: ProductConversationRef$2;
7149
+ conversation: ProductConversationRef$3;
7076
7150
  error: ImHistoryReturnError;
7077
7151
  }>;
7078
7152
  /** 保留原发送动作的返回值,并把独立的历史窗口结算交给宿主消费。 */
@@ -7092,33 +7166,6 @@ interface ImHistoryReturnAfterSendCoordinator {
7092
7166
  */
7093
7167
  declare function useImHistoryReturnAfterSendCoordinator(pinia?: Pinia): ImHistoryReturnAfterSendCoordinator;
7094
7168
 
7095
- /**
7096
- * 为页面展示当前账号的媒体上传/下载进度,并提供取消、重试和重新选择原文件入口。
7097
- *
7098
- * 【状态从哪里来】
7099
- * Store 订阅 SDK 的完整媒体任务列表,向页面提供任务、当前线程每条消息的上传百分比、是否还在排队等
7100
- * 上传槽位、是否正在完成最后处理以及稳定错误。传输、任务状态、消息状态、取消和重试都由 SDK 维护;Store 不模拟进度,也不
7101
- * 创建第二套上传队列。
7102
- *
7103
- * 【提供的能力】
7104
- * - `start` / `reset`:开始监听当前 SDK Client,或切账号时退订并清空旧任务。
7105
- * - `cancel` / `retry`:按 SDK 给出的任务 ID 取消或重试。
7106
- * - `cancelUpload`:根据当前会话类型、会话 ID 和消息 ID 找到唯一上传任务后取消。
7107
- * - `cancelDownload`:按消息身份取消在途下载;合集要带项下标,因为一条合集的每一项是独立任务。
7108
- * 与 `cancelUpload` 不同,它定位任务时不看当前会话——切会话正是关闭预览的路径之一。
7109
- * 取消是任务级的,同一下载的所有等待方都会一起收到取消,只有唯一消费者才该调它。
7110
- * - `requestReplacement` / `takeReplacementRequest`:视频或文件刷新后失去本地源时,生成一次重新选择请求;
7111
- * 宿主取走意图后自行打开平台文件选择器,File 本身不会写入 Store。
7112
- *
7113
- * 【安全、并发与资源边界】
7114
- * 页面任务会删除 SDK 错误中的底层原因和详情,只保留错误码、分类和是否可重试。File、Blob、本地地址、
7115
- * 播放器、中止控制器、传输能力、Client 和订阅函数都不能进入 `$state`。Store 同时核对当前 Client、
7116
- * 账号版本号和绑定序号;旧账号任务或旧操作晚返回时只得到 `stale`,不会更新新页面。
7117
- *
7118
- * 【明确不负责】
7119
- * 文件选择、预览、录音权限、播放器、Blob URL 生命周期、toast 和页面布局属于浏览器或宿主平台能力。
7120
- */
7121
-
7122
7169
  /** 页面可保存和判断的媒体错误;底层响应、异常对象和详情只进入统一诊断,不进入 Pinia。 */
7123
7170
  type ImMediaStoreError = Readonly<Omit<ImSdkErrorShape, 'cause' | 'details'>>;
7124
7171
  /** 页面可展示的只读媒体任务;不含文件字节、本地地址、密钥、中止控制器或传输对象。 */
@@ -7150,8 +7197,67 @@ type ImMediaOperationResult = Readonly<{
7150
7197
  * 宿主既有的 `downloadProgress[message.id]` 读法不受影响。
7151
7198
  */
7152
7199
  declare function imMediaDownloadKey(messageId: string, itemIndex?: number): string;
7200
+ declare function defineImMediaStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-media", Pick<{
7201
+ tasks: any;
7202
+ error: any;
7203
+ uploadProgress: any;
7204
+ downloadTasks: any;
7205
+ downloadProgress: any;
7206
+ uploadWaiting: any;
7207
+ uploadFinalizing: any;
7208
+ replacementRequest: any;
7209
+ start: () => void;
7210
+ reset: () => void;
7211
+ cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7212
+ retry: (taskId: string) => Promise<ImMediaOperationResult>;
7213
+ cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7214
+ cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7215
+ requestReplacement: (message: ImMessageView) => boolean;
7216
+ takeReplacementRequest: () => ImMediaReplacementRequest | null;
7217
+ clearReplacementRequest: () => void;
7218
+ dispose: () => void;
7219
+ }, any>, Pick<{
7220
+ tasks: any;
7221
+ error: any;
7222
+ uploadProgress: any;
7223
+ downloadTasks: any;
7224
+ downloadProgress: any;
7225
+ uploadWaiting: any;
7226
+ uploadFinalizing: any;
7227
+ replacementRequest: any;
7228
+ start: () => void;
7229
+ reset: () => void;
7230
+ cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7231
+ retry: (taskId: string) => Promise<ImMediaOperationResult>;
7232
+ cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7233
+ cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7234
+ requestReplacement: (message: ImMessageView) => boolean;
7235
+ takeReplacementRequest: () => ImMediaReplacementRequest | null;
7236
+ clearReplacementRequest: () => void;
7237
+ dispose: () => void;
7238
+ }, any>, Pick<{
7239
+ tasks: any;
7240
+ error: any;
7241
+ uploadProgress: any;
7242
+ downloadTasks: any;
7243
+ downloadProgress: any;
7244
+ uploadWaiting: any;
7245
+ uploadFinalizing: any;
7246
+ replacementRequest: any;
7247
+ start: () => void;
7248
+ reset: () => void;
7249
+ cancel: (taskId: string) => Promise<ImMediaOperationResult>;
7250
+ retry: (taskId: string) => Promise<ImMediaOperationResult>;
7251
+ cancelUpload: (messageId: string) => Promise<ImMediaOperationResult>;
7252
+ cancelDownload: (messageId: string, itemIndex?: number) => Promise<ImMediaOperationResult>;
7253
+ requestReplacement: (message: ImMessageView) => boolean;
7254
+ takeReplacementRequest: () => ImMediaReplacementRequest | null;
7255
+ clearReplacementRequest: () => void;
7256
+ dispose: () => void;
7257
+ }, any>>;
7258
+ type ImMediaStore = ReturnType<ReturnType<typeof defineImMediaStore>>;
7153
7259
  /** 取得当前 Vue setup 或显式 Pinia 的媒体任务 Store;不会隐式创建 Runtime。 */
7154
- declare function useImMediaStore(pinia?: Pinia): any;
7260
+ declare function useImMediaStore(pinia?: Pinia): ImMediaStore;
7155
7261
 
7156
7262
  /**
7157
7263
  * 执行“把当前会话中的一条或多条消息转发到若干目标会话”。
@@ -8351,30 +8457,20 @@ type ImReactionStore = Store<'k2-im-reaction', ImReactionStoreState, Record<stri
8351
8457
  declare function useImReactionStore(pinia?: Pinia): ImReactionStore;
8352
8458
 
8353
8459
  /**
8354
- * 为当前聊天线程提供关键词搜索、分类媒体浏览、结果续页和跳转到原消息。
8355
- *
8356
- * 【对外状态】
8357
- * Store 暴露关键词、全部/文件/图片/视频/语音分类、结果列表、搜索状态、是否还有下一页、正在定位的
8358
- * 消息 ID、短暂高亮 ID 与稳定错误。SDK 仍维护搜索索引、消息历史窗口和真实分页位置,Pinia 只保存
8359
- * 当前搜索面板需要展示的状态。
8360
- *
8361
- * 【提供的能力】
8362
- * - `search`:更新关键词,用户停止输入 250ms 后执行,避免每个按键都发请求。
8363
- * - `setCategory`:切换消息、文件、图片、视频或语音产品入口。
8364
- * - `loadMore`:使用闭包中不可解析的分页凭证继续同一次查询。
8365
- * - `locate`:让当前线程加载目标消息附近的历史并发布定位 ID;宿主完成实际滚动后,高亮 ID 再保留 2 秒。
8366
- * - `clearLocation` / `reset`:结束定位或作废当前查询生命周期;`reset({ preserveLocation: true })` 可在关闭搜索面板时保留刚写入的高亮。
8460
+ * 读取当前会话的消息搜索结果和分类媒体列表。
8367
8461
  *
8368
- * 【并发与身份隔离】
8369
- * 分页凭证、定时器、会话句柄、请求序号和账号版本号全部留在闭包。切查询、分类、会话、账号或
8370
- * 销毁 Store 会把等待/在途任务结算为 `stale`;同 ID 的单聊、普通群和社群始终按类型 + ID 隔离。旧任务
8371
- * 不能关闭新任务的 loading,也不能覆盖新结果、错误或高亮。
8462
+ * 全部消息按关键词搜索;文件既可按名称搜索也可浏览;图片、视频和语音按分类浏览。单聊、普通群和
8463
+ * 社群会调用各自的 SDK 搜索能力。分页位置由 SDK 封装成 `ImPageToken`,调用方只能原样传回续页,
8464
+ * 不能解析或修改其中的账号、会话和查询条件。
8372
8465
  *
8373
- * 【明确不负责】
8374
- * Store 不访问滚动容器,不决定搜索面板、空态和反馈文案。宿主监听 `highlightMessageId` 后完成实际
8375
- * DOM 居中/高亮;分页凭证、协议续页位置与底层响应不会暴露给宿主。
8466
+ * 防抖、当前查询状态、切账号/切会话后的旧结果丢弃由 Search Store 负责。本 Service 只取一批结果,
8467
+ * 并在底层出现稀疏空页时有限地向后查找,避免页面误显示“没有结果”。
8376
8468
  */
8377
8469
 
8470
+ /** 搜索面板可选择的业务分类:全部/文本走关键词;文件可空词浏览;图/音/视频按类型浏览。 */
8471
+ type ConversationSearchCategory = 'all' | 'text' | 'image' | 'video' | 'file' | 'voice';
8472
+
8473
+ type ProductConversationRef$2 = ConversationRef<ProductHandleConversationType>;
8378
8474
  type SearchOperation = 'search' | 'load-more' | 'locate';
8379
8475
  /** 搜索、续页或定位结果;宿主只按操作和原因决定反馈,不解析 SDK 底层异常。 */
8380
8476
  type ImSearchOperationResult = Readonly<{
@@ -8386,8 +8482,67 @@ type ImSearchOperationResult = Readonly<{
8386
8482
  reason: 'not-ready' | 'no-condition' | 'busy' | 'exhausted' | 'stale' | 'failed';
8387
8483
  error?: ImSdkErrorShape;
8388
8484
  }>;
8485
+ declare function defineImSearchStore(pinia: Pinia): pinia.StoreDefinition<"k2-im-search", Pick<{
8486
+ keyword: any;
8487
+ results: any;
8488
+ searching: any;
8489
+ hasMore: any;
8490
+ category: any;
8491
+ locatingMessageId: any;
8492
+ highlightMessageId: any;
8493
+ error: any;
8494
+ search: (nextKeyword: string) => Promise<ImSearchOperationResult>;
8495
+ setCategory: (nextCategory: ConversationSearchCategory) => Promise<ImSearchOperationResult>;
8496
+ loadMore: () => Promise<ImSearchOperationResult>;
8497
+ locate: (ref: ProductConversationRef$2, messageId: string) => Promise<ImSearchOperationResult>;
8498
+ completeLocation: (messageId: string) => boolean;
8499
+ clearLocation: () => void;
8500
+ reset: (options?: {
8501
+ preserveLocation?: boolean;
8502
+ }) => void;
8503
+ dispose: () => void;
8504
+ }, any>, Pick<{
8505
+ keyword: any;
8506
+ results: any;
8507
+ searching: any;
8508
+ hasMore: any;
8509
+ category: any;
8510
+ locatingMessageId: any;
8511
+ highlightMessageId: any;
8512
+ error: any;
8513
+ search: (nextKeyword: string) => Promise<ImSearchOperationResult>;
8514
+ setCategory: (nextCategory: ConversationSearchCategory) => Promise<ImSearchOperationResult>;
8515
+ loadMore: () => Promise<ImSearchOperationResult>;
8516
+ locate: (ref: ProductConversationRef$2, messageId: string) => Promise<ImSearchOperationResult>;
8517
+ completeLocation: (messageId: string) => boolean;
8518
+ clearLocation: () => void;
8519
+ reset: (options?: {
8520
+ preserveLocation?: boolean;
8521
+ }) => void;
8522
+ dispose: () => void;
8523
+ }, any>, Pick<{
8524
+ keyword: any;
8525
+ results: any;
8526
+ searching: any;
8527
+ hasMore: any;
8528
+ category: any;
8529
+ locatingMessageId: any;
8530
+ highlightMessageId: any;
8531
+ error: any;
8532
+ search: (nextKeyword: string) => Promise<ImSearchOperationResult>;
8533
+ setCategory: (nextCategory: ConversationSearchCategory) => Promise<ImSearchOperationResult>;
8534
+ loadMore: () => Promise<ImSearchOperationResult>;
8535
+ locate: (ref: ProductConversationRef$2, messageId: string) => Promise<ImSearchOperationResult>;
8536
+ completeLocation: (messageId: string) => boolean;
8537
+ clearLocation: () => void;
8538
+ reset: (options?: {
8539
+ preserveLocation?: boolean;
8540
+ }) => void;
8541
+ dispose: () => void;
8542
+ }, any>>;
8543
+ type ImSearchStore = ReturnType<ReturnType<typeof defineImSearchStore>>;
8389
8544
  /** 取得当前 Vue setup 或显式 Pinia 的搜索 Store;不同宿主实例不会共享查询或定位状态。 */
8390
- declare function useImSearchStore(pinia?: Pinia): any;
8545
+ declare function useImSearchStore(pinia?: Pinia): ImSearchStore;
8391
8546
 
8392
8547
  /**
8393
8548
  * 为 PC/H5 提供同一套会话收藏列表和已收藏标记。
@@ -8652,4 +8807,4 @@ type MessageNotificationDecision = {
8652
8807
  declare function resolveMessageNotificationDecision(input: MessageNotificationInput): MessageNotificationDecision;
8653
8808
 
8654
8809
  export { applicationKey, createAndInstallImChatKit, createImChatKitContext, disposeImChatKit, ensureImChatKitSelfProfile, getImChatKitContext, imMediaDownloadKey, installImChatKit, resolveMessageNotificationDecision, useImApplicationsStore, useImCapabilitiesStore, useImComposerStore, useImConversationActivationCoordinator, useImConversationDeletionCoordinator, useImConversationListStore, useImExpressionStore, useImHistoryReturnAfterSendCoordinator, useImMediaStore, useImMessageOperationsStore, useImProfileDirectoryStore, useImQuotedMessageStore, useImReactionStore, useImSearchStore, useImSessionFavoritesStore, useImSessionStore, useImThreadPagingStore, useImThreadReturnToLatestCoordinator, useImThreadStore };
8655
- export type { ApplyImSessionInput, ChatRuntimeFactories, ChatRuntimeHostDeps, ImApplicationDomainCounts, ImApplicationReviewOperation, ImApplicationReviewResult, ImApplicationsReloadResult, ImApplicationsStoreError, ImCapabilitiesStore, ImChannelManagementMemberTarget, ImChannelMemberManagementOperation, ImChannelMemberManagementResult, ImChannelMemberManagementResultFor, ImChannelProfileActionResult, ImChannelProfileActionResultFor, ImChannelProfileOperation, ImChatKitContext, ImChatKitInstallation, ImComposerStore, ImComposerStoreActions, ImComposerStoreState, ImComposerSubmitResult, ImConversationActivationCoordinator, ImConversationActivationError, ImConversationActivationResult, ImConversationDeletionCoordinator, ImConversationDeletionError, ImConversationDeletionResult, ImConversationListActionError, ImConversationListMutationOperation, ImConversationListMutationResult, ImConversationListRefreshResult, ImConversationListStore, ImDirectContactActionResult, ImDirectContactActionResultFor, ImDirectContactOperation, ImDirectoryState, ImEmojiPanelRecentEntry, ImEmojiRecentEntry, ImExpressionLoadStatus, ImExpressionOperation, ImExpressionOperationResult, ImExpressionRecentPersistencePort, ImExpressionRecentPersistenceSnapshot, ImExpressionRecentViewItem, ImExpressionResetOptions, ImExpressionSendResult, ImExpressionStore, ImExpressionStoreActions, ImExpressionStoreError, ImExpressionStoreGetters, ImExpressionStoreState, ImForwardPreparationResult, ImGameRecentEntry, ImGroupMemberManagementOperation, ImGroupMemberManagementResult, ImGroupMemberManagementResultFor, ImGroupProfileActionResult, ImGroupProfileActionResultFor, ImGroupProfileOperation, ImHistoryReturnAfterSendCoordinator, ImHistoryReturnError, ImHistoryReturnExecution, ImHistoryReturnResult, ImMediaOperationResult, ImMediaReplacementRequest, ImMediaStoreError, ImMediaTaskPresentation, ImMembershipJoinActionResult, ImMembershipJoinOperation, ImMessageOperationsStore, ImMessageOperationsStoreActions, ImMessageOperationsStoreState, ImMessageSelectionResult, ImPersistedEmojiPanelRecentEntry, ImPersistedEmojiRecentEntry, ImPersistedExpressionAssetRecentEntry, ImPersistedGameRecentEntry, ImProfileAccessDestination, ImProfileAccessResult, ImProfileDirectoryResult, ImQuotedMessageState, ImQuotedMessageStore, ImQuotedMessageStoreActions, ImQuotedMessageStoreState, ImReactionOperationResult, ImReactionStore, ImReactionStoreActions, ImReactionStoreError, ImReactionStoreState, ImSearchOperationResult, ImSessionFavoritesReloadResult, ImSessionFavoritesStoreError, ImSessionFavoritesWriteResult, ImSessionPhase, ImSessionStore, ImThreadPagingActions, ImThreadPagingState, ImThreadPagingStore, ImThreadReturnToLatestCoordinator, ImThreadStore, ImThreadStoreActions, ImThreadStoreState };
8810
+ export type { ApplyImSessionInput, ChatRuntimeFactories, ChatRuntimeHostDeps, ImApplicationDomainCounts, ImApplicationReviewOperation, ImApplicationReviewResult, ImApplicationsReloadResult, ImApplicationsStoreError, ImCapabilitiesStore, ImChannelManagementMemberTarget, ImChannelMemberManagementOperation, ImChannelMemberManagementResult, ImChannelMemberManagementResultFor, ImChannelProfileActionResult, ImChannelProfileActionResultFor, ImChannelProfileOperation, ImChatKitContext, ImChatKitInstallation, ImComposerStore, ImComposerStoreActions, ImComposerStoreState, ImComposerSubmitResult, ImConversationActivationCoordinator, ImConversationActivationError, ImConversationActivationResult, ImConversationDeletionCoordinator, ImConversationDeletionError, ImConversationDeletionResult, ImConversationListActionError, ImConversationListMutationOperation, ImConversationListMutationResult, ImConversationListRefreshResult, ImConversationListStore, ImDirectContactActionResult, ImDirectContactActionResultFor, ImDirectContactOperation, ImDirectoryState, ImEmojiPanelRecentEntry, ImEmojiRecentEntry, ImExpressionLoadStatus, ImExpressionOperation, ImExpressionOperationResult, ImExpressionRecentPersistencePort, ImExpressionRecentPersistenceSnapshot, ImExpressionRecentViewItem, ImExpressionResetOptions, ImExpressionSendResult, ImExpressionStore, ImExpressionStoreActions, ImExpressionStoreError, ImExpressionStoreGetters, ImExpressionStoreState, ImForwardPreparationResult, ImGameRecentEntry, ImGroupMemberManagementOperation, ImGroupMemberManagementResult, ImGroupMemberManagementResultFor, ImGroupProfileActionResult, ImGroupProfileActionResultFor, ImGroupProfileOperation, ImHistoryReturnAfterSendCoordinator, ImHistoryReturnError, ImHistoryReturnExecution, ImHistoryReturnResult, ImMediaOperationResult, ImMediaReplacementRequest, ImMediaStore, ImMediaStoreError, ImMediaTaskPresentation, ImMembershipJoinActionResult, ImMembershipJoinOperation, ImMessageOperationsStore, ImMessageOperationsStoreActions, ImMessageOperationsStoreState, ImMessageSelectionResult, ImPersistedEmojiPanelRecentEntry, ImPersistedEmojiRecentEntry, ImPersistedExpressionAssetRecentEntry, ImPersistedGameRecentEntry, ImProfileAccessDestination, ImProfileAccessResult, ImProfileDirectoryResult, ImQuotedMessageState, ImQuotedMessageStore, ImQuotedMessageStoreActions, ImQuotedMessageStoreState, ImReactionOperationResult, ImReactionStore, ImReactionStoreActions, ImReactionStoreError, ImReactionStoreState, ImSearchOperationResult, ImSearchStore, ImSessionFavoritesReloadResult, ImSessionFavoritesStoreError, ImSessionFavoritesWriteResult, ImSessionPhase, ImSessionStore, ImThreadPagingActions, ImThreadPagingState, ImThreadPagingStore, ImThreadReturnToLatestCoordinator, ImThreadStore, ImThreadStoreActions, ImThreadStoreState };